@graphenedata/cli 0.0.1 → 0.0.3

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/dist/cli/cli.js CHANGED
@@ -1,18 +1,1603 @@
1
1
  #!/usr/bin/env node
2
- var Qt=Object.defineProperty;var E=(e,n)=>()=>(e&&(n=e(e=0)),n);var ae=(e,n)=>{for(var t in n)Qt(e,t,{get:n[t],enumerable:!0})};function bt(e,n){let t=n.virtualToMarkdownOffset;return!t||t.length===0?e:e<=0?t[0]??0:e>=t.length?t[t.length-1]:t[e]}function se(e,n){let t=bt(e,n),r=n.contents.split(/\r?\n/),i=0;for(let a=0;a<r.length;a++){let s=r[a],o=i+s.length+1;if(t<o||a===r.length-1){let l=Math.max(0,t-i);return{offset:t,line:a,col:l,lineStart:i,lineText:s}}i=o}return{offset:t,line:1,col:0}}function A(e){e.node&&(e=e.node);let n=e;for(;n.parent;)n=n.parent;return n.tree.fileInfo}function c(e){if(!e)return"";let n=A(e);return(n.virtualContents??n.contents).substring(e.from,e.to)||""}function Fe(e){return Object.fromEntries(Object.entries(e).filter(([n,t])=>t!==void 0))}function R(e,n,t=null){e&&(n(e,t),e.e&&R(e.e,n,e),e.kids&&Object.values(e.kids).forEach(r=>{Array.isArray(r)?r.forEach(i=>R(i,n,e)):R(r,n,e)}))}var Z=E(()=>{});function z(e){let n=A(e).contents;if(!n)return{};let t=e.from,r=n.lastIndexOf(`
3
- `,Math.max(0,t-1))+1,i=r-1,a=n.slice(r,t),s=!/[^\s]/.test(a),o=[];if(s&&i>=0){let p=i;for(;p>=0;){let w=n.lastIndexOf(`
4
- `,Math.max(0,p-1))+1,f=n.slice(w,p).trimEnd().trim();if(f.length===0||!f.startsWith("--"))break;o.push(f),p=w-1}}o.reverse();let l={},m=[];for(let p of o){let w=p.slice(2).trimStart();if(w.startsWith("#")){let C=w.slice(1).trim(),f=C.indexOf("=");if(f>0){let h=C.slice(0,f).trim(),u=C.slice(f+1).trim();h&&(l[h]=u)}continue}w&&m.push(w)}let d=e.to,P=n.indexOf(`
5
- `,d);P===-1&&(P=n.length);let T=n.slice(d,P);if(T.length){let p=T.indexOf("--");if(p>=0){let w=T.slice(0,p);if(/^[\s,]*$/.test(w)){let C=T.slice(p+2).trimStart(),f=/#([A-Za-z0-9_-]+)=([^\s#]+)/g,h=C.replace(f,(u,O,k)=>(O&&(l[O]=String(k)),"")).trim();h&&m.push(h)}}}return m.length&&(l.description=m.join(" ")),l}var De=E(()=>{Z()});import*as Ie from"fs";import wt from"path";function Tt(e){Object.keys(y).forEach(n=>delete y[n]),Object.assign(y,e)}function oe(e){if(y.root)return;let n={};try{let t=Ie.readFileSync(wt.join(e,"package.json"),"utf8");n=JSON.parse(t).graphene||{}}catch{console.warn("No package.json found in current directory")}Tt({...n,dialect:n.dialect||"duckdb",port:process.env.GRAPHENE_PORT||n.port||4e3,root:n.root||process.cwd()})}var y,N=E(()=>{y={dialect:"duckdb"}});import{DUCKDB_DIALECT_FUNCTIONS as ue,GlobalNameSpace as kt,DialectNameSpace as Et,getDialect as xt}from"@graphenedata/malloy";function Ne(e,n){if(!le.has(n)){let r=xt(n);le.set(n,new Et(r))}let t=le.get(n).getEntry(e)||Ct.getEntry(e);return t?.entry?t.entry.overloads:[]}var Ct,le,Ue,Oe=E(()=>{Ct=new kt,le=new Map;Object.assign(ue,{count_if:{takes:{value:"boolean"},returns:{measure:"number"},impl:{function:"COUNT_IF"}},if:{takes:{condition:"boolean",trueValue:{generic:"T"},falseValue:{generic:"T"}},generic:{T:["any"]},returns:{generic:"T"},impl:{function:"IF"}},date_trunc:{takes:{unit:"string",date:"timestamp"},returns:"timestamp",impl:{sql:"DATE_TRUNC(${unit}, ${date})"}},current_date:{takes:{},returns:"date",impl:{function:"CURRENT_DATE"}},current_time:{takes:{},returns:"timestamp",impl:{function:"CURRENT_TIME"}},current_timestamp:{default_precision:{takes:{},returns:"timestamp",impl:{function:"CURRENT_TIMESTAMP"}},precision:{takes:{precision:"number"},returns:"timestamp",impl:{function:"CURRENT_TIMESTAMP"}}},local_timestamp:{default_precision:{takes:{},returns:"timestamp",impl:{function:"LOCALTIMESTAMP"}},precision:{takes:{precision:"number"},returns:"timestamp",impl:{function:"LOCALTIMESTAMP"}}}});Ue={count_if:{...ue.count_if},if:{...ue.if},safe_divide:{takes:{numerator:"number",denominator:"number"},returns:"number",impl:{function:"SAFE_DIVIDE"}},timestamp_diff:{takes:{start:"timestamp",end:"timestamp",unit:{sql_native:"kw"}},returns:"number",impl:{function:"TIMESTAMP_DIFF"}},date_trunc:{takes:{date:"timestamp",unit:{sql_native:"kw"}},returns:"timestamp",impl:{sql:"DATE_TRUNC(${date}, ${unit})"}},current_date:{default_timezone:{takes:{},returns:"date",impl:{function:"CURRENT_DATE"}},timezone:{takes:{timezone:"string"},returns:"date",impl:{function:"CURRENT_DATE"}}},current_time:{default_timezone:{takes:{},returns:"timestamp",impl:{function:"CURRENT_TIME"}},timezone:{takes:{timezone:"string"},returns:"timestamp",impl:{function:"CURRENT_TIME"}}},current_timestamp:{default_timezone:{takes:{},returns:"timestamp",impl:{function:"CURRENT_TIMESTAMP"}},timezone:{takes:{timezone:"string"},returns:"timestamp",impl:{function:"CURRENT_TIMESTAMP"}}},local_timestamp:{takes:{},returns:"timestamp",impl:{function:"CURRENT_DATETIME"}},current_datetime:{default_timezone:{takes:{},returns:"timestamp",impl:{function:"CURRENT_DATETIME"}},timezone:{takes:{timezone:"string"},returns:"timestamp",impl:{function:"CURRENT_DATETIME"}}}}});function Ae(e){let n=new WeakMap,t=r=>{r&&R(r,(i,a)=>{if(n.set(i,a??null),i.node!=="parameter")return;let s=Rt(i,n);s&&(i.type=s)})};for(let r of e.pipeline||[])(r?.filterList||[]).forEach(s=>t(s?.e)),(r?.queryFields||[]).forEach(s=>t(s?.e))}function Rt(e,n){let t=n.get(e)||null;for(;t;){let r=qt(e,t);if(r)return r;t=n.get(t)||null}}function qt(e,n){let t=typeof n.node=="string"?n.node:"";if(St.has(t)){let i=_t(n,e)?.type;if(i)return q(i)}if(t==="in"){let r=n?.kids||{},i=r.e,a=Array.isArray(r.oneOf)?r.oneOf:[];if(a.includes(e)){if(a.length===1){let s=i?.type&&q(i.type);return s&&(e.paramElementType=s),"array"}return i?.type&&q(i.type)||void 0}if(i===e&&a.length){let s=a.find(l=>l!==e),o=s?.type&&q(s.type);if(o)return o}}if(Xt.has(t)||t==="not")return"boolean";if(vt.has(t))return"number";if(t==="function_call"){let r=n?.kids||{},a=(Array.isArray(r.args)?r.args:[]).indexOf(e);if(a>=0){let s=n?.overload,o=s?.params?.[a];if(!o&&s?.params?.length){let m=s.params[s.params.length-1];m?.isVariadic&&(o=m)}let l=typeof o?.type=="string"?q(o.type):void 0;if(l)return l}}if(t==="aggregate"&&n?.e===e){let r=(n?.function||"").toLowerCase();if(r==="sum"||r==="avg"||r==="count")return"number"}if(t==="case"){let r=n?.kids||{};if((Array.isArray(r.caseWhen)?r.caseWhen:[]).includes(e))return"boolean";if(r.caseElse===e)return q(n.type)||void 0;let a=Array.isArray(r.caseThen)?r.caseThen:[];if(a.includes(e))return q(n.type)||void 0;if(r.caseValue===e){let s=a[0];if(s?.type)return q(s.type)}}}function _t(e,n){if(!e?.kids)return;let t=e.kids,r=t.left,i=t.right;if(r===n)return i;if(i===n)return r}function q(e){if(typeof e=="string"&&Ft.has(e)&&e!=="fieldref")return e}function ce(e,n){let t=structuredClone(e),r=t.pipeline[0].filterList||[];for(let i of r)R(i.e,a=>{if(a.node!=="parameter")return;let s=n[a.path[0]];if(s===void 0)throw new Error(`Missing param $${a.path[0]}`);if(s==null)Object.assign(a,{node:"null",type:"string"});else if(a.type=="string")Object.assign(a,{node:"stringLiteral",literal:s});else if(a.type=="number")Object.assign(a,{node:"numberLiteral",literal:s.toString()});else if(a.type=="boolean")Object.assign(a,{node:s?"true":"false"});else throw new Error(`Unsupported param type ${a.type}`)});return t}var St,Xt,vt,Ft,pe=E(()=>{Z();St=new Set(["=","!=","<>",">",">=","<","<=","like","ilike"]),Xt=new Set(["and","or"]),vt=new Set(["unary-"]);Ft=new Set(["string","number","boolean","date","timestamp","json","sql native","error","fieldref","array","record","null"])});import{NodeWeakMap as Dt}from"@lezer/common";import{isExtractUnit as It,isTemporalType as Nt}from"@graphenedata/malloy";function We(e){let n=e.tree.topNode;e.tables=[];let t=n.getChildren("TableStatement").concat(n.getChildren("ViewStatement"));for(let r of t){let i=c(r.getChild("Identifier"));Object.values(x).find(s=>s.tables.find(o=>o.name==i))&&g(r.getChild("Identifier"),`Table "${i}" is already defined`);let a=Ve(i,r.getChild("QueryStatement")?"query_source":"table");a.metadata=z(r);for(let s of r.getChildren("ColumnDef")){let o=c(s.getChild("Identifier"));s.getChild("PrimaryKey")&&(a.primaryKey&&g(s,`Table ${a.name} has multiple primary keys`),a.primaryKey=o);let l=Wt(c(s.getChild("DataType")));l||g(s,`Unsupported data type: ${c(s.getChild("DataType"))}`);let m={name:o,type:l,metadata:z(s)};a.fields.push(m),M.set(m,s)}for(let s of r.getChildren("JoinDef")){let o=s.getChild("Alias")||s.getChild("Identifier"),l={name:c(o)};a.fields.push(l),M.set(l,s)}for(let s of r.getChildren("ComputedDef")){let o={name:c(s.getChild("Alias")),metadata:z(s)};a.fields.push(o),M.set(o,s)}a.fields.reduce((s,o)=>(s[o.name]?g(M.get(o),`Table already has a field called "${o.name}"`):s[o.name]=!0,s),{}),J.set(a,r),e.tables.push(a)}}function Ve(e,n){let t=y.namespace?`${y.namespace}.${e}`:e;return{name:e,type:n,fields:[],connection:y.dialect,dialect:y.dialect,tableName:e,tablePath:t,metadata:{}}}function Ze(e){if(e.type=="query_source")return ge(e);for(let n of e.fields)n.type||me(n,e)}function me(e,n){if(e.type)return;let t=M.get(e);if(de.has(e)&&g(t,"Cycles are not allowed between computed columns"),de.add(e),t.name=="JoinDef"){e=e;let r=H(c(t.getChild("Identifier")),t);if(!r)return g(t,"Unknown table to join");r.type=="query_source"&&ge(r);let i={join_many:"many",join_one:"one"}[c(t.getChild("JoinType"))];if(!i)return g(t,"Unknown join type");Object.assign(e,r,{name:e.name,join:i}),e.onExpression=b(t.getChild("Expression"),{table:n,outputFields:[]})}if(t.name=="ComputedDef"){let r=b(t.getChild("Expression"),{table:n,outputFields:[]}),i=z(t);Object.assign(e,{e:r,metadata:i,type:r.type,isAgg:r.isAgg})}de.delete(e)}function ge(e){if(e.query)return;let n=J.get(e),t=he(n.getChild("QueryStatement"));if(!t)throw new Error("Couldnt find query in QueryStatement");e.fields=t.fields.map(r=>({type:r.type,name:r.name,metadata:r.metadata})),e.query=t.malloyQuery,typeof e.query.structRef=="string"&&(e.query.structRef=H(e.query.structRef,n))}function he(e){let n,t={table:null,outputFields:[]},r=!1,i=[];if(!c(e))return;let a=e.getChild("FromClause")?.getChildren("TablePrimary")||[];if(a.find(u=>u.name=="JoinClause")&&g(a[0],"Query joins not yet supported"),a.length==0&&g(e,"No tables in FROM clause"),a.length>1&&g(a[0],"Multiple tables/joins in FROM clause not yet supported"),a[0].name=="Subquery")n=c(a[0].getChild("Alias"))||"subquery",t.table=Ve(n,"query_source"),J.set(t.table,a[0].getChild("SubqueryExpression")),ge(t.table),i.push(t.table);else{if(n=c(a[0].getChild("Identifier")),t.table=H(n,a[0]),!t.table)return g(a[0],`could not find table "${n}"`);fe.set(a[0],{entityType:"table",table:t.table})}let s=e.getChild("SelectClause")?.getChildren("SelectItem")||[],o=e.getChild("SelectClause")?.getChildren("Kw").find(u=>c(u).toLowerCase()=="distinct");r||=!!o,s.forEach(u=>{if(u.getChild("Wildcard")){let O=u.getChild("Wildcard").getChildren("Identifier"),k=O.map(Q=>c(Q)),$=ze(O,t.table);if(!$)return;$.fields.forEach(Q=>{G(Q)||Q.isAgg||t.outputFields.push({...Q,e:{node:"field",path:[...k,Q.name],type:Q.type}})})}else{let O=b(u.getChild("Expression"),t),k=je(O,t,u.getChild("Alias"));r||=!!O.isAgg;let $={};O.isAgg?t.outputFields.push({type:O.type,name:k,metadata:$,e:O,expressionType:"aggregate",isAgg:!0}):t.outputFields.push({type:O.type,name:k,metadata:$,e:O})}});let l=e.getChild("WhereClause")?.getChild("Expression"),m=e.getChild("HavingClause")?.getChild("Expression"),d=[l,m].flatMap(u=>u?Le(b(u,t)).map(k=>({node:"filterCondition",expressionType:k.isAgg?"aggregate":"scalar",e:k})):[]),P=e.getChild("GroupByClause")?.getChildren("SelectItem")||[];r||=!!P.length,P.forEach(u=>{let O=b(u.getChild("Expression"),t),k=je(O,t,u.getChild("Alias"));if(O.isAgg)return g(u,"Cannot group by aggregate expressions");t.outputFields.find($=>$.name==k)||t.outputFields.unshift({type:O.type,name:k,metadata:{},e:O})});let p=(e.getChild("OrderByClause")?.getChildren("OrderItem")||[]).map(u=>{let O=c(u.getChild("Identifier"))||Number(c(u.getChild("Number"))),k=c(u.getChild("Kw")).toLowerCase()=="desc"?"desc":"asc";return{field:O,dir:k}}),w=e.getChild("LimitClause")?.getChildren("Number")||[],C=w[0]?Number(c(w[0])):void 0;(w[1]?Number(c(w[1])):void 0)&&g(w[1],"OFFSET is not supported yet"),t.outputFields.length==0&&t.table.fields.forEach(u=>{G(u)||u.isAgg||t.outputFields.push({...u,e:{node:"field",path:[u.name],type:u.type}})});let h={fields:t.outputFields,subQuerySources:i,malloyQuery:{type:"query",structRef:n,pipeline:[{type:r?"reduce":"project",queryFields:t.outputFields,filterList:d,outputStruct:null,isRepeated:!1,orderBy:p.length?p:void 0,limit:C}]}};return Ae(h.malloyQuery),h}function b(e,n){if(e.type.isError)return g(e,"Invalid expression",X);switch(e.name){case"Number":return{node:"numberLiteral",literal:c(e),type:"number"};case"Boolean":return{node:c(e).toLowerCase()=="true"?"true":"false",type:"boolean"};case"Null":return{node:"null",type:"string"};case"String":return{node:"stringLiteral",literal:c(e).slice(1,-1),type:"string"};case"Param":return{node:"parameter",path:[c(e).slice(1)],type:"string"};case"Ref":{let t=jt(e,n);if(!t)return X;let r=t.type||"unknown",i={type:r};return(r==="date"||r==="timestamp")&&(i.typeDef={type:r}),n.outputFields.includes(t)&&t.isAgg?{node:"outputField",name:t.name,...i,isAgg:t.isAgg}:{node:"field",path:e.getChildren("Identifier").map(s=>c(s)),...i,isAgg:t.isAgg}}case"ExtractExpression":{let t=b(e.getChild("Expression"),n);if(!Nt(t.type)||!t.typeDef)return g(e,"Expression must be a date or timestamp",X);let r=c(e.getChild("ExtractUnit")).replace(/^['"]|['"]$/g,"").toLowerCase();return It(r)?{node:"extract",type:"number",units:r,e:t,isAgg:!1}:g(e,"Not a valid unit to extract",X)}case"FunctionCall":return Ut(e,n);case"Parenthetical":return b(e.getChild("Expression"),n);case"Count":{let t=e.getChild("Expression");return t?{node:"aggregate",function:"distinct",e:b(t,n),type:"number",isAgg:!0}:{node:"aggregate",function:"count",e:{node:""},type:"number",isAgg:!0}}case"BinaryExpression":{let t=b(e.firstChild,n),r=b(e.lastChild,n);return{node:c(e.firstChild?.nextSibling).toLowerCase(),kids:{left:t,right:r},type:t.type,isAgg:t.isAgg||r.isAgg}}case"NullTestExpression":{let t=e.getChildren("Kw").find(i=>c(i).toLowerCase()=="not")?"is-not-null":"is-null",r=b(e.firstChild,n);return{node:t,type:"boolean",isAgg:r.isAgg,e:r}}case"UnaryExpression":{let t=c(e.firstChild).toLowerCase(),r=b(e.lastChild,n);return t==="not"?{node:"not",e:r,type:"boolean",isAgg:r.isAgg}:t==="-"?{node:"unary-",e:r,type:r.type,isAgg:r.isAgg}:t==="+"?{node:"()",e:r,type:r.type,isAgg:r.isAgg}:g(e,`Unknown unary operator: ${t}`,X)}case"CaseExpression":{let t=e.getChild("Expression"),r=e.getChildren("WhenClause"),i=e.getChild("ElseClause"),a={caseValue:t?b(t,n):void 0,caseElse:i?b(i.getChild("Expression"),n):void 0,caseWhen:r.map(o=>b(o.getChildren("Expression")[0],n)),caseThen:r.map(o=>b(o.getChildren("Expression")[1],n))},s=a.caseThen[0]?.type||"string";return{node:"case",kids:Fe(a),type:s,isAgg:!1}}case"InExpression":{let t=c(e.getChild("Kw")).toLowerCase()=="not",r=b(e.firstChild,n),i=[],a=e.getChild("InValueList");a?i=a.getChildren("Expression").map(o=>b(o,n)):i=[{node:"genericSQLExpr",kids:{args:[]},type:"array"}];let s=r.isAgg||i.some(o=>o.isAgg);return{node:"in",not:t,kids:{e:r,oneOf:i},type:"boolean",isAgg:s}}case"SubqueryExpression":default:return g(e,`Unsupported expression "${e.name}": ${c(e)}`,X)}}function Ut(e,n){let t=c(e.getChild("Identifier")).toLowerCase(),r=e.getChildren("Expression"),i=Ne(t,y.dialect).find(d=>d.params.length==r.length||!!d.params.find(P=>P.isVariadic)),a=r.map((d,P)=>{let T=i?.params[P]?.allowedTypes[0];return T?.type==="sql native"&&T?.rawType==="kw"?{node:"genericSQLExpr",kids:{args:[]},type:"sql native",src:[c(d)],isAgg:!1}:b(d,n)}),s=i?.returnType.type;if(s=="generic"&&(s=a[0]?.type||"string"),s&&!At(s))return g(e,`Unsupported function return type ${s} from function ${t}`,X);let o=new Set;a.forEach(d=>R(d,P=>{P.node=="field"&&o.add(P.path.slice(0,-1).join(".")||n.table.name)}));let l;if(["count","min","max","avg","sum"].includes(t.toLowerCase()))l={node:"aggregate",function:t,e:a[0],type:"number",isAgg:!0};else if(i&&s)l={node:"function_call",type:s,name:t,overload:i,expressionType:i.returnType.expressionType||"scalar",kids:{args:a},isAgg:i.returnType.expressionType=="aggregate"||a.some(d=>d.isAgg)};else return g(e,`Unknown function: ${t}`,X);if(o.size>1&&(l.node=="aggregate"||l.expressionType=="aggregate"))return g(e,"Graphene only supports a single table within aggregates. This one has: "+Array.from(o).join(", "),X);let m=Array.from(o).filter(d=>d!=n.table.name);return m.length>0&&(l.structPath=m[0].split(".")),l}function At(e){return["string","number","boolean","date","timestamp","json","sql native","error","array","record","null","generic"].includes(e)}function jt(e,n){let t=e.getChildren("Identifier"),r=t.pop();if(!r)return g(e,"Missing identifiers in ref",null);let i=c(r),a=n.outputFields.find(l=>l.name==i);if(t.length==0&&a)return a;let s=ze(t,n.table);if(!s)return null;let o=s.fields.find(l=>l.name==i);return o?G(o)?g(r,`${i} is a join, but is used as a column here`,null):(me(o,s),fe.set(r,{entityType:"field",field:o,table:s}),o):g(r,`Could not find "${i}" on ${s.name}`,null)}function ze(e,n){for(let t of e){let r=c(t),i=n.fields.find(a=>a.name==r);if(r!=n.name){if(!i){let a=n.fields.find(o=>G(o)&&o.tableName==r),s=a?`. Did you mean "${a.name}"?`:"";return g(t,`Join "${r}" does not exist on table "${n.name}"${s}`,null)}if(me(i,n),!G(i))return g(t,`"${r}" is not a join on "${n.name}"`,null);if(n=H(i.tableName||"",t),!n)return g(t,"Following valid join but we couldnt find the table",null);fe.set(t,{entityType:"table",table:n})}}return n}function H(e,n){let t=A(n).path;for(let r of Object.values(x))if(r.path.endsWith(".gsql")||r.path==t){let i=r.tables.find(a=>a.name==e);if(i)return i}}function ye(){x={},J=new WeakMap,L=[]}function Me(){L=[]}function je(e,n,t){return t?c(t):e.node=="field"?e.path.join("_"):`col_${n.outputFields.length}`}function g(e,n,t){let r=A(e),i=se(e.from,r),a=se(e.to,r);return L.push({from:i,to:a,message:n,severity:"error",file:r.path}),t}function Ge(e){e.tree.topNode.cursor().iterate(n=>{n.type.isError&&g(n.node,"Syntax error")})}function Le(e){return e.node=="and"?[e.kids.left,e.kids.right].flatMap(Le):[e]}function G(e){return e.type=="table"||e.type=="query_source"}function Wt(e){switch(e.toUpperCase()){case"INT":return"number";case"INT64":return"number";case"TEXT":return"string";case"STRING":return"string";case"VARCHAR":return"string";case"INTEGER":return"number";case"FLOAT":return"number";case"FLOAT64":return"number";case"BOOLEAN":return"boolean";case"DATE":return"date";case"DATETIME":return"timestamp";case"TIME":return"timestamp";case"TIMESTAMP":return"timestamp";case"DECIMAL":return"number";case"DOUBLE":return"number";case"BIGINT":return"number";case"SMALLINT":return"number";case"TINYINT":return"number";case"BYTEINT":return"number";case"BIGDECIMAL":return"number";case"GEOGRAPHY":return"string";default:return null}}var x,L,J,M,fe,de,X,Ye=E(()=>{Z();De();N();Oe();pe();x={},L=[],J=new WeakMap,M=new WeakMap,fe=new Dt;de=new Set;X={node:"error",type:"error"}});var Ke=E(()=>{});function $e(e){let n=e.toLowerCase();return Pn[n]||-1}var Pn,Be=E(()=>{Ke();Pn={select:72,not:31,true:115,false:117,null:111,like:141,in:105,is:109,and:132,or:130,as:19,from:53,inner:59,left:61,right:63,full:65,cross:67,join:69,on:22,where:80,group:83,by:85,order:91,asc:95,desc:97,limit:100,offset:102,table:6,exists:49,primary_key:11}});import{LRParser as Qn}from"@lezer/lr";var bn,ee,Pe=E(()=>{Be();bn={__proto__:null,table:12,primary_key:22,join_one:30,join_many:34,as:38,on:44,not:62,case:72,when:78,then:82,else:88,end:92,exists:98,from:106,inner:118,left:122,right:126,full:130,cross:134,join:138,select:144,distinct:148,where:160,group:166,by:170,having:176,order:182,asc:190,desc:194,limit:200,offset:204,in:210,is:218,null:222,true:230,false:234,count:244,extract:250,or:260,and:264,like:282},ee=Qn.deserialize({version:14,states:"BbQYQPOOOOQO'#C`'#C`OOQO'#Db'#DbOtQPO'#DaOOQO'#Du'#DuO#QQPO'#DtOOQO'#D}'#D}O#XQPO'#D|OOQO'#EQ'#EQO$YQPO'#EPOOQO'#EV'#EVO#XQPO'#EUOOQO'#EY'#EYO$YQPO'#EXOOQO'#Ec'#EcO$_QPO'#EbOOQO'#Fi'#FiO$dQPO'#D`O$qQPO'#C_O$vQPO'#FeQYQPOOQ%hQPO'#FeO%mQPO'#DdO]QPO'#DfO&zQPO'#DeOOQO'#Fv'#FvO(mQPO,59{O*tQPO'#CtO,^QPO'#CtOOQO'#Cz'#CzOOQO'#Cy'#CyO#XQPO'#CxOOQO'#DP'#DPO,fQPO'#DOOOQO'#D^'#D^O,mQPO'#DfOOQO'#Dw'#DwOOQO'#Dz'#DzO.bQPO'#DyOOQO'#Dy'#DyO/_QPO,5:`O|QPO,5:`O0SQPO'#D]OOQO'#En'#EnOOQO'#Er'#ErOOQO'#Et'#EtOOQO'#Eq'#EqOOQO'#Ev'#EvOOQO'#Fy'#FyOOQO'#Ey'#EyO0XQPO'#ExOOQO'#E|'#E|O0^QPO'#E{OOQO'#Fu'#FuO0cQPO'#CtO0hQPO,5:hOOQO'#ES'#ESO|QPO,5:kO1[QPO,5:pO2OQPO,5:sO2WQPO,5:|OOQO-E9g-E9gO2{QPO,58yOOQO,5<P,5<POOQO-E9c-E9cOOQO'#Cn'#CnOOQO'#Cp'#CpOOQO,5:O,5:OO3TQPO,5:OO3YQPO,5:QOOQO,5:P,5:PO3TQPO,5:POOQO'#Dh'#DhOOQO'#Dj'#DjOOQO'#Dl'#DlOOQO'#Dn'#DnOOQO'#Dp'#DpOOQO'#Dr'#DrOtQPO'#DgO(hQPO'#DgOOQO'#Fj'#FjO3_QPO1G/gOOQO,5<R,5<RO4RQPO,5;kO4YQPO,59`OOQO-E9e-E9eOOQO,5:f,5:fOOQO,59d,59dOOQO'#DS'#DSO#XQPO'#DROOQO'#Fh'#FhO7wQPO,59jO8SQPO,59jO8ZQPO,5;lOOQO,5:e,5:eO3TQPO,5:eOOQO'#Eh'#EhO8bQPO,5;RO8gQPO,5;ROOQO'#El'#ElO8oQPO,5;VOOQO'#FR'#FROOQO'#FT'#FTOOQO'#F^'#F^OOQO'#FV'#FVOOQO'#F`'#F`OOQO'#Fa'#FaO#XQPO,59cO#XQPO,59cO#XQPO,59cO#XQPO,59cO#XQPO,59cO8wQPO1G/zO9kQPO1G/zO9kQPO1G/zO]QPO,59wO:`QPO,5;dO:mQPO,5;gO:uQPO1G0VO;jQPO'#E[O<eQPO1G0_OOQO'#Ee'#EeO=YQPO1G0hO=_QPO1G.eO>fQPO1G1jOOQO1G/j1G/jOOQO1G/l1G/lOOQO1G/k1G/kO>kQPO,5:ROtQPO,5:ROOQO-E9h-E9hO?rQPO1G1VOOQO1G1V1G1VP?|QPO'#FgO@RQPO,59mOOQO-E9f-E9fOOQO'#DX'#DXO#XQPO'#DWOOQO'#DZ'#DZOOQO1G/U1G/UO7}QPO1G/UO7wQPO1G/UOOQO1G1W1G1WOOQO1G0P1G0PO,mQPO1G0mO@YQPO1G0mOOQO,5;q,5;qOOQO1G0q1G0qO8rQPO1G0qOB}QPO1G.}OCUQPO1G.}OExQPO1G.}OFSQPO1G.}OOQO1G.}1G.}OOQO,5<V,5<VOF^QPO7+%fOOQO-E9i-E9iOGQQPO7+%fOGuQPO1G/cOGzQPO1G1OOOQO1G1O1G1OOHRQPO1G1OO#XQPO1G1OOOQO'#FO'#FOOHWQPO1G1ROH]QPO7+%qOIPQPO7+%qOOQO'#E^'#E^OOQO'#E`'#E`OOQO,5:v,5:vOJfQPO7+%yOJpQPO7+%yOOQO7+&S7+&SOJwQPO'#CtOOQO'#Cj'#CjOOQO'#Cl'#ClOOQO'#Ci'#CiOKOQPO'#ChO-WQPOOOL_QPO'#FuOLfQPO'#FuOOQO'#Ft'#FtOLmQPO'#CvOOQO'#Fr'#FrOLrQPO'#FfONPQPO7+$PO]QPO7+'UOOQO'#Cq'#CqO#XQPO1G/mONWQPO1G/mO! _QPO7+&qO! fQPO7+&qOOQO7+&q7+&qOOQO'#DU'#DUO#XQPO1G/XO! nQPO,59rOOQO7+$p7+$pO7}QPO7+$pO! uQPO'#EjO!!PQPO7+&XO,mQPO7+&XOOQO7+&]7+&]P|QPO'#FkO!!UQPO<<IQOOQO7+$}7+$}OOQO7+&j7+&jO!!xQPO7+&jO#XQPO7+&mO!#PQPO<<I]OOQO,5<W,5<WO!#sQPO<<IeOOQO-E9j-E9jOOQO'#Cd'#CdO!$kQPO,58}O!%{QPO,59SO3TQPO,59bOOQO,5<Q,5<QOOQO-E9d-E9dOOQO<<Gk<<GkO!&TQPO<<JpO!&YQPO7+%XO#XQPO7+%XO!'`QPO,5<XOOQO<<J]<<J]O!'jQPO<<J]OOQO-E9k-E9kO!'qQPO7+$sOOQO<<H[<<H[O!(OQPO,5;UO!(VQPO,5;UOOQO<<Is<<IsO!(_QPO<<IsOOQO<<JU<<JUO!(dQPO<<JXP2OQPO'#FlOOQO'#Cf'#CfOOQO'#Ce'#CeOOQO1G.i1G.iO!(kQPO1G.nO3TQPO1G.nOOQO1G.|1G.|OOQOAN@[AN@[O!(pQPO<<HsOOQOAN?wAN?wP#XQPO'#FmO!)vQPO1G0pOOQOAN?_AN?_OOQOAN?sAN?sO!)}QPO'#CtO!+bQPO'#CsOOQO7+$Y7+$YO!&OQPO7+$YO!(kQPO,59_O!(kQPO<<GtOOQO1G.y1G.yOOQOAN=`AN=`",stateData:"!+l~O$dOSPOS~OUPO!VQO!jSO!rUO!uWO!zYO!}[O#W^O~OTfO$egO~OTkOomOpnOqnOtpO!RrO!ouO#P!QO#c{O#d!QO#g|O#i}O#k!VO#n!RO#q!TO$esO~O!ltO~P|OTkOomOpnOqnOtpO!RrO#P!QO#c{O#d!QO#g|O#i}O#k!VO#n!RO#q!TO$esO~O!w!YO~O#P!^O~O$b!SX$o!SX$k!SX~P]OT!`O~O$o!aOU$XX!V$XX!j$XX!r$XX!u$XX!z$XX!}$XX#W$XX$b$XX~O$o!aO~OT!dOc!cO!V!WX!]!WX!_!WX!a!WX!c!WX!e!WX!g!WX!j!WX!r!WX!u!WX!z!WX!}!WX#W!WX$b!WX$o!WX$k!WXf!WX~OT!dOc!cO!V!XX!]!XX!_!XX!a!XX!c!XX!e!XX!g!XX!j!XX!r!XX!u!XX!z!XX!}!XX#W!XX$b!XX$o!XX$k!XXf!XX~O!]!jO!_!kO!a!lO!c!mO!e!nO!g!oO~O!V!Ta!j!Ta!r!Ta!u!Ta!z!Ta!}!Ta#W!Ta$b!Ta$o!Ta$k!Ta~P(XO$e!uO$g!tOchXihXohXphXqhX!ohX#]hX#ahX#vhX#xhX#zhX#{hX#|hX#}hX$OhX$PhX$RhX$UhX$VhX~OThX!VhX!jhX!rhX!uhX!zhX!}hX#WhX$bhX$lhX$ohXwhX$khXyhX!OhX!]hX!_hX!ahX!chX!ehX!ghX|hX~P)aOT!vO!o!xO~Ow!zO~P#XO!VQO!jSO!rUO!uWO!zYO!}[O#W^O~P#XOi#[OomOp#]Oq#]O!o#^O#]#SO#a#VO#v#XO#x#YO#z#[O#{#[O#|#[O#}#[O$O#[O$P#[O$R#ZO$U#^O$V#^O~OT!dOc!cO!V!mX!j!mX!r!mX!u!mX!z!mX!}!mX#W!mX$b!mX$l!mX$o!mX$k!mX~P-WO$l#dO!V!ha!j!ha!r!ha!u!ha!z!ha!}!ha#W!ha$b!ha$o!ha$k!ha~O$e#gO~O$e#hO~O$e#iO~OT!vO~O!V!pa!j!pa!r!pa!u!pa!z!pa!}!pa#W!pa$b!pa$o!pa$k!pa~P-WO!V!xa!j!xa!r!xa!u!xa!z!xa!}!xa#W!xa$b!xa$o!xa$k!xa~P-WOT#kO#P#kO~O#Y#mO!V#Ua!j#Ua!r#Ua!u#Ua!z#Ua!}#Ua#W#Ua$b#Ua$o#Ua$k#Ua~Oc!cO$e#oO~OT!dO~O$k#rO~O!V!Ti!j!Ti!r!Ti!u!Ti!z!Ti!}!Ti#W!Ti$b!Ti$o!Ti$k!Ti~P(XO$k#xO~P#XO$g!tOThachaihaohaphaqha!Vha!jha!oha!rha!uha!zha!}ha#Wha#]ha#aha#vha#xha#zha#{ha#|ha#}ha$Oha$Pha$Rha$Uha$Vha$bha$lha$ohawha$khayha!Oha!]ha!_ha!aha!cha!eha!gha|ha_haahatha!Rha#Pha#cha#dha#gha#iha#kha#nha#qha$eha~Ow!zO|#|O!O$OO~Ow!zO~P-WO$k$SO~P-WO$e$UO~O#]#SO$R#ZO~OomO#c{O~O!V!hi!j!hi!r!hi!u!hi!z!hi!}!hi#W!hi$b!hi$o!hi$k!hi~P|O$l$aO!V!hi!j!hi!r!hi!u!hi!z!hi!}!hi#W!hi$b!hi$o!hi$k!hi~O!ltO!o$gO$k$fO~P#XOT$iO#d$iO~O$l$kO!V!si!j!si!r!si!u!si!z!si!}!si#W!si$b!si$o!si$k!si~O#R$mO#T$nO!V#OX!j#OX!r#OX!u#OX!z#OX!}#OX#W#OX$b#OX$l#OX$o#OX$k#OX~O$l$pO!V!{i!j!{i!r!{i!u!{i!z!{i!}!{i#W!{i$b!{i$o!{i$k!{i~O#P$rO~OT$sO_$tOa$uOomOpnOqnOtpO!RrO#P!QO#c{O#d!QO#g|O#i}O#k!VO#n!RO#q!TO$esO~O$e%QO~Of%RO!V!Za!]!Za!_!Za!a!Za!c!Za!e!Za!g!Za!j!Za!r!Za!u!Za!z!Za!}!Za#W!Za$b!Za$o!Za$k!Za~O$k%WO$l%UO~P-WO$g!tO~Oy%XO~P-WO$e%`O~Oi#[OomOp#]Oq#]O!o#^O#]#SO#z#[O#{#[O#|#[O#}#[O$O#[O$P#[O$R#ZO$U#^O$V#^OTkicki!Vki!jki!rki!uki!zki!}ki#Wki#aki#vki$bki$lki$okiwki$kkiyki!Oki!]ki!_ki!aki!cki!eki!gki|ki~O#x#YO~P@_O#xki~P@_O!o#^O$U#^O$V#^OTkickiikioki!Vki!jki!rki!uki!zki!}ki#Wki#]ki#aki#vki#xki#zki#{ki#|ki#}ki$Oki$Pki$Rki$bki$lki$okiwki$kkiyki!Oki!]ki!_ki!aki!cki!eki!gki|ki~Op#]Oq#]O~PC]Opkiqki~PC]O!V!hq!j!hq!r!hq!u!hq!z!hq!}!hq#W!hq$b!hq$o!hq$k!hq~P|O$l%cO!V!hq!j!hq!r!hq!u!hq!z!hq!}!hq#W!hq$b!hq$o!hq$k!hq~O$k%dO~O$k%eO~P-WO$k%eO~O!VQO~O!V!sq!j!sq!r!sq!u!sq!z!sq!}!sq#W!sq$b!sq$o!sq$k!sq~P|O$l%hO!V!sq!j!sq!r!sq!u!sq!z!sq!}!sq#W!sq$b!sq$o!sq$k!sq~O!V!{q!j!{q!r!{q!u!{q!z!{q!}!{q#W!{q$b!{q$o!{q$k!{q~OT#kO#P#kO~PItO$l%jO~PItOT%lO~P)aOT%nO~Oi$iXo$iXp$iXq$iX!o$iX#]$iX#a$iX#v$iX#x$iX#z$iX#{$iX#|$iX#}$iX$O$iX$P$iX$R$iX$U$iX$V$iX~Oc$hX~PKTOc$nX~PKTOc!cO~O$l%pOT$YX_$YXa$YXo$YXp$YXq$YXt$YX!R$YX#P$YX#c$YX#d$YX#g$YX#i$YX#k$YX#n$YX#q$YX$e$YX$k$YX~O$k%rO~P=_Of%RO!V!Zi!]!Zi!_!Zi!a!Zi!c!Zi!e!Zi!g!Zi!j!Zi!r!Zi!u!Zi!z!Zi!}!Zi#W!Zi$b!Zi$o!Zi$k!Zi~O$k%wO~P#XO$k%wO$l%xO~O!Oza~P-WO$l%|O$k#^X~P-WO$k&OO~O!V!hy!j!hy!r!hy!u!hy!z!hy!}!hy#W!hy$b!hy$o!hy$k!hy~P|O$k&QO~P-WO!V!sy!j!sy!r!sy!u!sy!z!sy!}!sy#W!sy$b!sy$o!sy$k!sy~P|OT#kO#P#kO!V!{y!j!{y!r!{y!u!{y!z!{y!}!{y#W!{y$b!{y$o!{y$k!{y~OZ&TOTVa_VaaVaoVapVaqVatVa!RVa#PVa#cVa#dVa#gVa#iVa#kVa#nVa#qVa$eVa$kVa$lVa~Oc!cOf%RO~O$k&ZO~O!V!Zq!]!Zq!_!Zq!a!Zq!c!Zq!e!Zq!g!Zq!j!Zq!r!Zq!u!Zq!z!Zq!}!Zq#W!Zq$b!Zq$o!Zq$k!Zq~P-WO$k$aa$l$aa~P-WO$k&]O~P#XOwuq|uq!Ouq~P-WO$k#^a~P#XO$l&_O$k#^a~O$k&`O~O$k&aO~P-WOT&bO~O!V!Zy!]!Zy!_!Zy!a!Zy!c!Zy!e!Zy!g!Zy!j!Zy!r!Zy!u!Zy!z!Zy!}!Zy#W!Zy$b!Zy$o!Zy$k!Zy~P-WO$k#^i~P#XO$g!tOihXThX_hXahXohXphXqhXthX!RhX#PhX#chX#dhX#ghX#ihX#khX#nhX#qhX$ehX$khX$lhX~Oi&fO~OP$U!op~",goto:"@[$oPPP$p$tPP$x$|%P%SP$x%V%ZP%ZP%_P%q&ZP&g&mP$x'o'o(j)cPPP'o*tP+m+sP+yP+|,SP,WP'o,bP-Z-o-zP.Y.Y._/]/aP/aP/aP/aP/aP/eP-o/lP/wP/}0`P-o0kP-o0vP1RP-o1XP-o1dP1oP1wP1wP-o1zP2VP'o2YP2r.d2xP3]PP4[5TP5TP4[P5|6wP.d7pP8i5|.d8lP9PP9ePPPPPP9zP:d:zPP$p;c;i;o<q<{=Y=`=n=tPPPP>OP>S>W?}PP5|@WTcOdTbOdT$}#o%PR%m$sR&V%mR&U%mT$w#o%PT$v#o%PQ!ffQ!ihQ#RvQ#p!`Q%o$|R&X%nQ!efQ!hhQ#QvQ#q!fQ#s!iQ$T#RQ&Y%oR&e&XQ%S#tQ%u%TQ&W%nR&g&eQ&d&WR&i&g!h!VTVZoqsy!Z!u!{#_#`#a#b#c#d#h#}$U$a$h$k%S%U%Y%`%b%c%g%h%u%x%|&^&_S$z#o%PS&c&W&gR&h&f!h!VTVZoqsy!Z!u!{#_#`#a#b#c#d#h#}$U$a$h$k%S%U%Y%`%b%c%g%h%u%x%|&^&_T$y#o%P!moTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_!lnTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_v#Uv!X![#O#P#w#z$Z$[$e$x%Z%^%f%t%v%z&R&[R$Y#W!mqTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_X!|q!}#O$RX!{q!}#O$RR%Y#zQ$Q!}R%]$RT#}!}$RQ$P!}S%[$Q$RR%{%]!mzTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_SeOdS!ggsQ$d#gQ%_$UQ%s%QR&P%`c`Oadgs#g$U%Q%`bROadgs#g$U%Q%`R%g$jViR!p#uUhR!p#u!m!VTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_T!rj!sT!qj!sS!pj!sR#u!qcTOadgs#g$U%Q%`QyTR$h#hQxTQ#fyQ#j!Z]$`#d$a$k%b%c%hcwTy!Z#d$a$k%b%c%hcVOadgs#g$U%Q%`cXOadgs#g$U%Q%`Q!ZXR!]]cZOadgs#g$U%Q%`c]Oadgs#g$U%Q%`Q#l!]V%i$p%j&SR$o#kc_Oadgs#g$U%Q%`R#n!^v#Tv!X![#O#P#w#z$Z$[$e$x%Z%^%f%t%v%z&R&[R$V#UQ%_$UR&P%`s#Wv!X![#O#P#w#z$e$x%Z%^%f%t%v%z&R&[!l!PTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_Q$X#WR%a$Y!m!QTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_!m!OTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_!h!VTVZoqsy!Z!u!{#_#`#a#b#c#d#h#}$U$a$h$k%S%U%Y%`%b%c%g%h%u%x%|&^&_T$z#o%P!m!STVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_!m!UTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_R$j#is#_v!X![#O#P#w#z$e$x%Z%^%f%t%v%z&R&[u#`v!X![#O#P#w#z$Z$e$x%Z%^%f%t%v%z&R&[w#av!X![#O#P#w#z$Z$[$e$x%Z%^%f%t%v%z&R&[v#[v!X![#O#P#w#z$Z$[$e$x%Z%^%f%t%v%z&R&[R$W#Uy#bv!X![#O#P#w#z$Z$[$]$e$x%Z%^%f%t%v%z&R&[{#cv!X![#O#P#w#z$Z$[$]$^$e$x%Z%^%f%t%v%z&R&[QdOR!bdQ%P#oR%q%PblTy!Z#d$a$k%b%c%h!`!WVZoqs!u!{#_#`#a#b#c#h#o#}$U$h%P%S%U%Y%`%g%u%x%|&W&^&_&f&gT!wl!WQ!}qS#{!}$RR$R#O`aOdgs#g$U%Q%`R!_aQ!sjR#v!sQ#exU$b#e$c$lQ$c#fR$l#jQ$q#lR%k$qQ%V#wS%y%V%}R%}%^T%O#o%PT$|#o%PbvTy!Z#d$a$k%b%c%hQ!XVQ![ZQ!yoQ#OqQ#PsQ#w!uQ#z!{Q$Z#_Q$[#`Q$]#aQ$^#bQ$_#cQ$e#hS$x#o%PQ%Z#}S%^$U%`Q%f$hQ%t%SY%v%U%x%|&^&_Q%z%YQ&R%gR&[%uQjRQ#t!pR%T#uT${#o%P",nodeNames:"\u26A0 Comment Program TableStatement Kw Identifier table ColumnDef DataType PrimaryKey Kw primary_key JoinDef JoinType Kw join_one Kw join_many Kw as Alias Kw on BinaryExpression Ref = ComputedDef BinaryExpression UnaryExpression UnaryOperator Kw not - + CaseExpression Kw case WhenClause Kw when Kw then ElseClause Kw else Kw end ExistsExpression Kw exists QueryStatement FromClause Kw from TableName Subquery SubqueryExpression JoinClause Kw inner Kw left Kw right Kw full Kw cross Kw join SelectClause Kw select Kw distinct SelectItem Wildcard * WhereClause Kw where GroupByClause Kw group Kw by HavingClause Kw having OrderByClause Kw order OrderItem Number Kw asc Kw desc LimitClause Kw limit Kw offset InExpression Kw in InValueList NullTestExpression Kw is Kw null String Boolean Kw true Kw false Null Param Count Kw count ExtractExpression Kw extract ExtractUnit FunctionCall Parenthetical Kw or Kw and ComparisonOp != <> < > <= >= Kw like AddOp MulOp / % ViewStatement",maxTerm:169,nodeProps:[["group",-6,23,56,107,119,123,128,"Expression",-12,24,27,28,34,47,93,103,112,113,118,120,127,"Expression Expression",-2,54,55,"TablePrimary"]],skippedNodes:[0,1],repeatNodeCount:9,tokenData:"*g~RnX^#Ppq#Pqr#trs$Ptu$nuv%`wx%exy%}yz&Sz{&X{|&^|}&c}!O&h!O!P'X!P!Q'^!Q![(m!]!^)W!^!_)]!_!`)r!`!a)w!c!}*U#T#o*U#y#z#P$f$g#P#BY#BZ#P$IS$I_#P$I|$JO#P$JT$JU#P$KV$KW#P&FU&FV#P~#UY$d~X^#Ppq#P#y#z#P$f$g#P#BY#BZ#P$IS$I_#P$I|$JO#P$JT$JU#P$KV$KW#P&FU&FV#P~#wP!_!`#z~$PO#z~~$STOr$Prs$cs;'S$P;'S;=`$h<%lO$P~$hO#d~~$kP;=`<%l$P~$qS!Q![$}!c!}$}#R#S$}#T#o$}~%SS#k~!Q![$}!c!}$}#R#S$}#T#o$}~%eO$V~~%hTOw%ewx$cx;'S%e;'S;=`%w<%lO%e~%zP;=`<%l%e~&SO$e~~&XO$k~~&^O!o~~&cOq~~&hO$l~~&mPp~}!O&p~&uSP~OY&pZ;'S&p;'S;=`'R<%lO&p~'UP;=`<%l&p~'^O$g~~'cP$U~z{'f~'iTOz'fz{'x{;'S'f;'S;=`(g<%lO'f~'{VOz'fz{'x{!P'f!P!Q(b!Q;'S'f;'S;=`(g<%lO'f~(gOP~~(jP;=`<%l'f~(rQ#P~!O!P(x!Q![(m~({P!Q![)O~)TP#P~!Q![)O~)]O$o~~)bQ#|~!_!`)h!`!a)m~)mO$O~~)rO#{~~)wOi~~)|P#}~!_!`*P~*UO$P~~*ZST~!Q![*U!c!}*U#R#S*U#T#o*U",tokenizers:[0],topRules:{Program:[0,2]},specialized:[{term:5,get:(e,n)=>$e(e,n)<<1,external:$e},{term:5,get:e=>bn[e]||-1}],tokenPrec:2599})});function tt(e){let n=e.contents,t=wn(n),r=Tn(n,t),i=[...t,...r].sort((f,h)=>f.start-h.start),a=[],s=[],o=0,l=-1,m=n.length,d=(f,h)=>{let u=h;u<=l&&(u=l+1),u>m&&(u=m),a.push(f),s.push(u),l=u},P=f=>{l=f},T=(f,h)=>{P(f-1);for(let u=f;u<h;u++){let O=n[u];d(O===`
6
- `||O==="\r"?O:" ",u)}},p=(f,h,u)=>{u?.reset!==void 0&&P(u.reset);for(let O=0;O<f.length;O++)d(f[O],h(O))},w=(f,h)=>{P(h-1);for(let u=0;u<f.length;u++){let O=h+u;a.push(f[u]),s.push(O),l=O}};for(let f of i){if(f.start<o)continue;if(T(o,f.start),o=f.start,Cn(f)){let $=f,Q=$.contentStart,I=$.content;$.name?(p(`table ${$.name} as (
7
- `,()=>Q,{reset:Q-1}),w(I,Q),I.endsWith(`
8
- `)||p(`
9
- `,()=>Q+I.length,{reset:Q+I.length-1}),p(`)
10
- `,()=>$.end-1,{reset:$.end-2})):w(I,Q),o=$.end;continue}let h=f,{data:u,attributes:O}=h,k=Qe.some($=>O[$]!==void 0);if(u&&k){p("from ",()=>h.start,{reset:h.start-1}),p(u.value,W=>u.start+W,{reset:u.start-1}),p(" select ",()=>h.start);let $=null;for(let W of Qe){let V=O[W];if(V){if($){let ie=$.start+$.value.length;p(", ",()=>ie)}p(V.value,ie=>V.start+ie,{reset:V.start-1}),$=V}}let Q=$,I=Q?Q.start+Q.value.length:u.start+u.value.length,Pt=Q?Q.start+Q.value.length-1:u.start+u.value.length-1;p(`;
11
- `,W=>W===0?I:h.end,{reset:Pt})}o=h.end}T(o,n.length);let C=a.join("");return e.virtualContents=C,e.virtualToMarkdownOffset=[...s,n.length],ee.parse(C)}function wn(e){let n=[];Je.lastIndex=0;let t;for(;t=Je.exec(e);){let r=t.index??0,i=t[0],a=i.indexOf(`
12
- `);if(a===-1)continue;a+=1;let s=t[3]||"",o=r+a,l=kn(i.slice(0,a));n.push({start:r,end:r+i.length,headerLength:a,contentStart:o,content:s,name:l})}return n}function Tn(e,n){let t=[];He.lastIndex=0;let r;for(;r=He.exec(e);){let i=r.index??0,a=i+r[0].length;if(xn(i,n))continue;let s=En(r[0],i),o={};for(let l of Qe)s[l]&&(o[l]=s[l]);t.push({start:i,end:a,data:s.data||null,attributes:o})}return t}function kn(e){let n=e.trim().split(/\s+/);if(n.length>1)return n[1]}function En(e,n){let t={};et.lastIndex=0;let r;for(;r=et.exec(e);){let i=r[1],a=r[2],s=n+r.index+i.length+2;t[i]={value:a,start:s}}return t}function xn(e,n){return n.some(t=>e>=t.start&&e<t.end)}function Cn(e){return e.content!==void 0}var Qe,Je,He,et,nt=E(()=>{Pe();Qe=["x","y","y2","series","value","category"],Je=/^([ \t]*)(`{3,})g?sql[^\n]*\n([\s\S]*?)^\1\2[ \t]*$/gim,He=/<([A-Z][A-Za-z0-9]*)\s+[^>]*\/>/g,et=/(\w+)="([^"]*)"/g});import{registerDialect as Sn,StandardSQLDialect as Xn,QueryModel as vn,expandBlueprintMap as Rn}from"@graphenedata/malloy";import{readFile as qn}from"node:fs/promises";import{glob as _n}from"glob";import Fn from"node:path";function rt(e){return x[e]}function _(){return L}async function U(e,n){let t=await _n(n?"**/*.{gsql,md}":"**/*.gsql",{cwd:e,ignore:["node_modules/**"]});for await(let r of t){let i=await qn(Fn.join(e,r),"utf-8");it(i,r)}}function it(e,n){return x[n]||={path:n,contents:e,tree:null,tables:[],queries:[]},x[n].contents=e,x[n].tree=null,x[n]}function j(e,n){if(Me(),delete x.input,e&&it(e,"input"),Object.values(x).forEach(t=>{let r=t.path.endsWith(".md")||t.path=="input"&&n=="md";t.tree||=r?tt(t):ee.parse(t.contents),t.tree.fileInfo=t,Ge(t),We(t)}),Object.values(x).flatMap(t=>t.tables).forEach(Ze),e){let t=x.input,r=t.tree.topNode.getChildren("QueryStatement")||[];return t.queries=r.map(he).filter(i=>!!i),t.queries}else return[]}function Y(e,n={}){let t={};Object.values(x).filter(o=>o.path!=="input").flatMap(o=>o.tables).forEach(o=>t[o.name]=o),[...x.input?.tables||[],...e.subQuerySources].forEach(o=>t[o.name]={...o,query:o.query&&ce(o.query,n)});let a=ce(e.malloyQuery,n);return new vn({name:"generated_model",contents:t,queryList:[],dependencies:{},exports:[]}).compileQuery(a).sql}var be,te=E(()=>{Ye();pe();Z();N();Oe();Pe();nt();be=class extends Xn{constructor(){super(),this.name="bigquery"}getDialectFunctions(){return Rn(Ue)}};Sn(new be)});var Ot={};ae(Ot,{BigQueryConnection:()=>Ce});import{BigQuery as Wn,BigQueryDate as Vn,BigQueryTimestamp as Zn}from"@google-cloud/bigquery";var Ce,ct=E(()=>{N();Ce=class{client;constructor(n={}){if(n.projectId||=y.googleProjectId,n.maxRetries||=3,n.userAgent||="Graphene",!n.projectId)throw new Error("googleProjectId must be set in config or provided in service account credentials");this.client=new Wn(n)}async runQuery(n){let[t]=await this.client.createQueryJob({query:n,useLegacySql:!1}),[r]=await t.getQueryResults({maxResults:1e4}),i=t.metadata||(await t.getMetadata())[0],a=Number(i?.statistics?.query?.totalRows??r.length);return r.forEach(s=>{Object.entries(s).forEach(([o,l])=>{l instanceof Zn&&(s[o]=l.value),l instanceof Vn&&(s[o]=l.value)})}),{rows:r,totalRows:a}}}});var pt={};ae(pt,{DuckDBConnection:()=>Se});import{promises as zn}from"fs";import Mn from"path";import{DuckDBTimestampValue as Gn,DuckDBInstance as Ln,DuckDBDateValue as Yn}from"@duckdb/node-api";var Se,dt=E(()=>{N();Se=class{ready;connection=null;constructor(){this.ready=this.initialize()}async initialize(){let t=(await zn.readdir(y.root)).find(a=>a.endsWith(".duckdb"));if(!t)throw new Error("No .duckdb file found in current directory");t=Mn.resolve(y.root,t);let r=await Ln.create(":memory:");this.connection=await r.connect();let i=t.replace(/'/g,"''");await this.connection.run(`attach '${i}' as graphene_cli (READ_ONLY);`),await this.connection.run("use graphene_cli;")}async runQuery(n){return await this.ready,{rows:(await this.connection.runAndReadAll(n)).getRowObjects().map(i=>{let a={};for(let[s,o]of Object.entries(i))if(typeof o=="bigint")a[s]=Number(o);else if(o===null)a[s]=null;else if(o instanceof Gn)a[s]=new Date(Number(o.micros/1000n)).toUTCString();else if(o instanceof Yn)a[s]=o.toString();else{if(typeof o=="object")throw new Error(`Unsupported datatype ${o.constructor?.name}`);a[s]=o}return a})}}}});async function ne(){if(y.dialect==="bigquery"){let e=await Promise.resolve().then(()=>(ct(),Ot));return new e.BigQueryConnection}else if(y.dialect==="duckdb"){let e=await Promise.resolve().then(()=>(dt(),pt));return new e.DuckDBConnection}else throw new Error(`Unsupported dialect: ${y.dialect}`)}var Xe=E(()=>{N()});var mt={};ae(mt,{mockFileMap:()=>qe,serve2:()=>sr});import{createServer as Kn,optimizeDeps as Bn}from"vite";import{svelte as Jn,vitePreprocess as Hn}from"@sveltejs/vite-plugin-svelte";import{visit as er}from"unist-util-visit";import re from"fs-extra";import tr from"crypto";import{mdsvex as nr}from"mdsvex";import F from"path";import{fileURLToPath as rr}from"url";import{WebSocketServer as ir}from"ws";import{spawn as ar}from"child_process";async function sr(){D=y.root,K=F.join(rr(import.meta.url),"../../ui"),await re.ensureDir(F.resolve(D,"node_modules/.graphene")),await re.writeFile(F.resolve(D,`node_modules/.graphene/${process.env.NODE_ENV=="test"?"test":"serve"}.pid`),String(process.pid));let e=await Kn({root:y.root,plugins:[Jn({extensions:[".svelte",".md"],preprocess:[Hn(),nr({extensions:[".md"],remarkPlugins:[cr],layout:F.resolve(K,"layout.svelte")}),pr()]}),lr,or,dr()],server:{port:y.port,fs:{strict:!1},strictPort:!0},optimizeDeps:{},resolve:{alias:{graphene:F.resolve(K,"web.js")}}});return await Bn(e.config),await e.listen(),console.log(`Server running at http://localhost:${y.port}`),e}async function ur(e,n){let t=[];for await(let p of e)t.push(p);let{gsql:r,params:i,hashes:a}=JSON.parse(Buffer.concat(t).toString());n.setHeader("Content-Type","application/json"),await ve;let s=j(r);if(_().length){n.statusCode=400,n.end(JSON.stringify(_()));return}if(s.length>1)throw new Error("Found multiple queries, which could be a parsing error");let o=Y(s[0],i),l=tr.createHash("SHA1").update(o).digest("hex");if(n.setHeader("ETag",l),a.includes(l)&&e.headers["cache-control"]!="no-cache")return n.statusCode=304,n.end();let d=await(await ne()).runQuery(o);if((d.totalRows??d.rows.length)>d.rows.length)throw new Error("Query returns too many rows");let T=s[0].fields.map(p=>({name:p.name,type:p.type}));n.end(JSON.stringify({rows:d.rows,hash:l,fields:T,sql:o}))}async function Or(e,n){let t=[];for await(let l of e)t.push(l);let{mdFile:r,chart:i}=JSON.parse(Buffer.concat(t).toString()),a=Math.random().toString(36).slice(2);n.setHeader("Content-Type","application/json"),Re[a]={response:n};let s="/"+r.replace(/\.md$/,"").replace(/^\//,"");s==="/index"&&(s="/"),s=`http://localhost:${y.port||4e3}${s}`;let o=B.find(l=>l.url===s);if(!o){ar("open",[s]);let l=Date.now()+5e3;for(;Date.now()<l&&!o;)o=B.find(m=>m.url===s),await new Promise(m=>setTimeout(m,100));if(!o)return n.statusCode=500,n.end(JSON.stringify({error:"No browser tab available and failed to open one"}))}o.socket.send(JSON.stringify({type:"view",chart:i,requestId:a}))}async function ft(e,n,t,r){n.setHeader("Content-Type","text/html");let i=r?`
13
- import Page from ${JSON.stringify(t)};
14
- new Page({ target: document.getElementById('app'), props: {} })
15
- `:"",a=await e.transformIndexHtml(t,`<!doctype html>
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __esm = (fn, res) => function __init() {
5
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
+ };
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+
12
+ // ../lang/util.ts
13
+ function markdownOffset(offset2, file) {
14
+ let map = file.virtualToMarkdownOffset;
15
+ if (!map || map.length === 0) return offset2;
16
+ if (offset2 <= 0) return map[0] ?? 0;
17
+ if (offset2 >= map.length) return map[map.length - 1];
18
+ return map[offset2];
19
+ }
20
+ function getPosition(offset2, file) {
21
+ let mdOffset = markdownOffset(offset2, file);
22
+ let lines = file.contents.split(/\r?\n/);
23
+ let acc = 0;
24
+ for (let i = 0; i < lines.length; i++) {
25
+ let lineText = lines[i];
26
+ let nextAcc = acc + lineText.length + 1;
27
+ if (mdOffset < nextAcc || i === lines.length - 1) {
28
+ let col = Math.max(0, mdOffset - acc);
29
+ return { offset: mdOffset, line: i, col, lineStart: acc, lineText };
30
+ }
31
+ acc = nextAcc;
32
+ }
33
+ return { offset: mdOffset, line: 1, col: 0 };
34
+ }
35
+ function getFile(node) {
36
+ if (node.node) node = node.node;
37
+ let top = node;
38
+ while (top.parent) top = top.parent;
39
+ return top.tree.fileInfo;
40
+ }
41
+ function txt(node) {
42
+ if (!node) return "";
43
+ let file = getFile(node);
44
+ let source = file.virtualContents ?? file.contents;
45
+ return source.substring(node.from, node.to) || "";
46
+ }
47
+ function compact(obj) {
48
+ return Object.fromEntries(Object.entries(obj).filter(([_, v]) => v !== void 0));
49
+ }
50
+ function walkExpression(root, fn, parent = null) {
51
+ if (!root) return;
52
+ fn(root, parent);
53
+ if (root.e) walkExpression(root.e, fn, root);
54
+ if (root.kids) {
55
+ Object.values(root.kids).forEach((kid) => {
56
+ if (Array.isArray(kid)) kid.forEach((k) => walkExpression(k, fn, root));
57
+ else walkExpression(kid, fn, root);
58
+ });
59
+ }
60
+ }
61
+ var init_util = __esm({
62
+ "../lang/util.ts"() {
63
+ }
64
+ });
65
+
66
+ // ../lang/metadata.ts
67
+ function extractLeadingMetadata(node) {
68
+ let src = getFile(node).contents;
69
+ if (!src) return {};
70
+ let pos = node.from;
71
+ let currentLineStart = src.lastIndexOf("\n", Math.max(0, pos - 1)) + 1;
72
+ let endOfPrevLine = currentLineStart - 1;
73
+ let beforeOnLine = src.slice(currentLineStart, pos);
74
+ let isFirstTokenOnLine = !/[^\s]/.test(beforeOnLine);
75
+ let commentLines = [];
76
+ if (isFirstTokenOnLine && endOfPrevLine >= 0) {
77
+ let cursor = endOfPrevLine;
78
+ while (cursor >= 0) {
79
+ let startOfLine = src.lastIndexOf("\n", Math.max(0, cursor - 1)) + 1;
80
+ let line = src.slice(startOfLine, cursor).trimEnd();
81
+ let trimmed = line.trim();
82
+ if (trimmed.length === 0) break;
83
+ if (!trimmed.startsWith("--")) break;
84
+ commentLines.push(trimmed);
85
+ cursor = startOfLine - 1;
86
+ }
87
+ }
88
+ commentLines.reverse();
89
+ let metadata = {};
90
+ let descriptionLines = [];
91
+ for (let raw of commentLines) {
92
+ let withoutPrefix = raw.slice(2).trimStart();
93
+ if (withoutPrefix.startsWith("#")) {
94
+ let kv = withoutPrefix.slice(1).trim();
95
+ let eqIdx = kv.indexOf("=");
96
+ if (eqIdx > 0) {
97
+ let key = kv.slice(0, eqIdx).trim();
98
+ let value = kv.slice(eqIdx + 1).trim();
99
+ if (key) metadata[key] = value;
100
+ }
101
+ continue;
102
+ }
103
+ if (withoutPrefix) descriptionLines.push(withoutPrefix);
104
+ }
105
+ let endPos = node.to;
106
+ let endOfLine = src.indexOf("\n", endPos);
107
+ if (endOfLine === -1) endOfLine = src.length;
108
+ let after = src.slice(endPos, endOfLine);
109
+ if (after.length) {
110
+ let commentIdx = after.indexOf("--");
111
+ if (commentIdx >= 0) {
112
+ let between = after.slice(0, commentIdx);
113
+ if (/^[\s,]*$/.test(between)) {
114
+ let trailingText = after.slice(commentIdx + 2).trimStart();
115
+ let inlineKv = /#([A-Za-z0-9_-]+)=([^\s#]+)/g;
116
+ let cleaned = trailingText.replace(inlineKv, (_m, k, v) => {
117
+ if (k) metadata[k] = String(v);
118
+ return "";
119
+ }).trim();
120
+ if (cleaned) descriptionLines.push(cleaned);
121
+ }
122
+ }
123
+ }
124
+ if (descriptionLines.length) metadata.description = descriptionLines.join(" ");
125
+ return metadata;
126
+ }
127
+ var init_metadata = __esm({
128
+ "../lang/metadata.ts"() {
129
+ init_util();
130
+ }
131
+ });
132
+
133
+ // ../lang/config.ts
134
+ import * as fs from "fs";
135
+ import path from "path";
136
+ function setConfig(cfg) {
137
+ Object.keys(config).forEach((key) => delete config[key]);
138
+ Object.assign(config, cfg);
139
+ }
140
+ function loadConfig(dir) {
141
+ if (config.root) return;
142
+ let packageJsonObject = {};
143
+ try {
144
+ let txt2 = fs.readFileSync(path.join(dir, "package.json"), "utf8");
145
+ let all = JSON.parse(txt2);
146
+ packageJsonObject = all.graphene || {};
147
+ } catch {
148
+ console.warn("No package.json found in current directory");
149
+ }
150
+ setConfig({
151
+ ...packageJsonObject,
152
+ dialect: packageJsonObject.dialect || "duckdb",
153
+ port: process.env.GRAPHENE_PORT || packageJsonObject.port || 4e3,
154
+ root: packageJsonObject.root || process.cwd()
155
+ });
156
+ }
157
+ var config;
158
+ var init_config = __esm({
159
+ "../lang/config.ts"() {
160
+ config = { dialect: "duckdb" };
161
+ }
162
+ });
163
+
164
+ // ../lang/functions.ts
165
+ import { DUCKDB_DIALECT_FUNCTIONS, GlobalNameSpace, DialectNameSpace, getDialect } from "@graphenedata/malloy";
166
+ function findOverloads(name, dialect) {
167
+ if (!dialectNamespaces.has(dialect)) {
168
+ let d = getDialect(dialect);
169
+ dialectNamespaces.set(dialect, new DialectNameSpace(d));
170
+ }
171
+ let res = dialectNamespaces.get(dialect).getEntry(name) || globalNamespace.getEntry(name);
172
+ return res?.entry ? res.entry.overloads : [];
173
+ }
174
+ var globalNamespace, dialectNamespaces, BIGQUERY_DIALECT_FUNCTIONS;
175
+ var init_functions = __esm({
176
+ "../lang/functions.ts"() {
177
+ globalNamespace = new GlobalNameSpace();
178
+ dialectNamespaces = /* @__PURE__ */ new Map();
179
+ Object.assign(DUCKDB_DIALECT_FUNCTIONS, {
180
+ "count_if": {
181
+ takes: { "value": "boolean" },
182
+ returns: { measure: "number" },
183
+ impl: { function: "COUNT_IF" }
184
+ },
185
+ "if": {
186
+ takes: { "condition": "boolean", "trueValue": { generic: "T" }, "falseValue": { generic: "T" } },
187
+ generic: { "T": ["any"] },
188
+ returns: { generic: "T" },
189
+ impl: { function: "IF" }
190
+ },
191
+ "date_trunc": {
192
+ takes: { "unit": "string", "date": "timestamp" },
193
+ returns: "timestamp",
194
+ impl: { sql: "DATE_TRUNC(${unit}, ${date})" }
195
+ },
196
+ "current_date": {
197
+ takes: {},
198
+ returns: "date",
199
+ impl: { function: "CURRENT_DATE" }
200
+ },
201
+ "current_time": {
202
+ takes: {},
203
+ returns: "timestamp",
204
+ impl: { function: "CURRENT_TIME" }
205
+ },
206
+ "current_timestamp": {
207
+ default_precision: {
208
+ takes: {},
209
+ returns: "timestamp",
210
+ impl: { function: "CURRENT_TIMESTAMP" }
211
+ },
212
+ precision: {
213
+ takes: { "precision": "number" },
214
+ returns: "timestamp",
215
+ impl: { function: "CURRENT_TIMESTAMP" }
216
+ }
217
+ },
218
+ "local_timestamp": {
219
+ default_precision: {
220
+ takes: {},
221
+ returns: "timestamp",
222
+ impl: { function: "LOCALTIMESTAMP" }
223
+ },
224
+ precision: {
225
+ takes: { "precision": "number" },
226
+ returns: "timestamp",
227
+ impl: { function: "LOCALTIMESTAMP" }
228
+ }
229
+ }
230
+ });
231
+ BIGQUERY_DIALECT_FUNCTIONS = {
232
+ "count_if": { ...DUCKDB_DIALECT_FUNCTIONS["count_if"] },
233
+ "if": { ...DUCKDB_DIALECT_FUNCTIONS["if"] },
234
+ "safe_divide": {
235
+ takes: { "numerator": "number", "denominator": "number" },
236
+ returns: "number",
237
+ impl: { function: "SAFE_DIVIDE" }
238
+ },
239
+ "timestamp_diff": {
240
+ takes: { "start": "timestamp", "end": "timestamp", "unit": { sql_native: "kw" } },
241
+ returns: "number",
242
+ impl: { function: "TIMESTAMP_DIFF" }
243
+ },
244
+ "date_trunc": {
245
+ takes: { "date": "timestamp", "unit": { sql_native: "kw" } },
246
+ returns: "timestamp",
247
+ impl: { sql: "DATE_TRUNC(${date}, ${unit})" }
248
+ },
249
+ "current_date": {
250
+ default_timezone: {
251
+ takes: {},
252
+ returns: "date",
253
+ impl: { function: "CURRENT_DATE" }
254
+ },
255
+ timezone: {
256
+ takes: { "timezone": "string" },
257
+ returns: "date",
258
+ impl: { function: "CURRENT_DATE" }
259
+ }
260
+ },
261
+ "current_time": {
262
+ default_timezone: {
263
+ takes: {},
264
+ returns: "timestamp",
265
+ impl: { function: "CURRENT_TIME" }
266
+ },
267
+ timezone: {
268
+ takes: { "timezone": "string" },
269
+ returns: "timestamp",
270
+ impl: { function: "CURRENT_TIME" }
271
+ }
272
+ },
273
+ "current_timestamp": {
274
+ default_timezone: {
275
+ takes: {},
276
+ returns: "timestamp",
277
+ impl: { function: "CURRENT_TIMESTAMP" }
278
+ },
279
+ timezone: {
280
+ takes: { "timezone": "string" },
281
+ returns: "timestamp",
282
+ impl: { function: "CURRENT_TIMESTAMP" }
283
+ }
284
+ },
285
+ "local_timestamp": {
286
+ takes: {},
287
+ returns: "timestamp",
288
+ impl: { function: "CURRENT_DATETIME" }
289
+ },
290
+ "current_datetime": {
291
+ default_timezone: {
292
+ takes: {},
293
+ returns: "timestamp",
294
+ impl: { function: "CURRENT_DATETIME" }
295
+ },
296
+ timezone: {
297
+ takes: { "timezone": "string" },
298
+ returns: "timestamp",
299
+ impl: { function: "CURRENT_DATETIME" }
300
+ }
301
+ }
302
+ };
303
+ }
304
+ });
305
+
306
+ // ../lang/params.ts
307
+ function inferParamTypes(query) {
308
+ let parentMap = /* @__PURE__ */ new WeakMap();
309
+ let inspect = (expr) => {
310
+ if (!expr) return;
311
+ walkExpression(expr, (node, parent) => {
312
+ parentMap.set(node, parent ?? null);
313
+ if (node.node !== "parameter") return;
314
+ let inferred = inferTypeFromParents(node, parentMap);
315
+ if (inferred) node.type = inferred;
316
+ });
317
+ };
318
+ for (let stage of query.pipeline || []) {
319
+ let filters = stage?.filterList || [];
320
+ filters.forEach((f) => inspect(f?.e));
321
+ let fields = stage?.queryFields || [];
322
+ fields.forEach((field) => inspect(field?.e));
323
+ }
324
+ }
325
+ function inferTypeFromParents(expr, parents) {
326
+ let current = parents.get(expr) || null;
327
+ while (current) {
328
+ let inferred = inferFromImmediateParent(expr, current);
329
+ if (inferred) return inferred;
330
+ current = parents.get(current) || null;
331
+ }
332
+ return void 0;
333
+ }
334
+ function inferFromImmediateParent(expr, parent) {
335
+ let node = typeof parent.node == "string" ? parent.node : "";
336
+ if (COMPARISON_OPS.has(node)) {
337
+ let sibling = getBinarySibling(parent, expr);
338
+ let siblingType = sibling?.type;
339
+ if (siblingType) return sanitizeType(siblingType);
340
+ }
341
+ if (node === "in") {
342
+ let kids = parent?.kids || {};
343
+ let lhs = kids.e;
344
+ let values = Array.isArray(kids.oneOf) ? kids.oneOf : [];
345
+ if (values.includes(expr)) {
346
+ if (values.length === 1) {
347
+ let elementType = lhs?.type && sanitizeType(lhs.type);
348
+ if (elementType) expr.paramElementType = elementType;
349
+ return "array";
350
+ }
351
+ return lhs?.type && sanitizeType(lhs.type) || void 0;
352
+ }
353
+ if (lhs === expr && values.length) {
354
+ let example = values.find((v) => v !== expr);
355
+ let exampleType = example?.type && sanitizeType(example.type);
356
+ if (exampleType) return exampleType;
357
+ }
358
+ }
359
+ if (BOOLEAN_OPS.has(node)) return "boolean";
360
+ if (node === "not") return "boolean";
361
+ if (NUMERIC_UNARY_OPS.has(node)) return "number";
362
+ if (node === "function_call") {
363
+ let kids = parent?.kids || {};
364
+ let args = Array.isArray(kids.args) ? kids.args : [];
365
+ let idx = args.indexOf(expr);
366
+ if (idx >= 0) {
367
+ let overload = parent?.overload;
368
+ let param = overload?.params?.[idx];
369
+ if (!param && overload?.params?.length) {
370
+ let last = overload.params[overload.params.length - 1];
371
+ if (last?.isVariadic) param = last;
372
+ }
373
+ let fromOverload = typeof param?.type == "string" ? sanitizeType(param.type) : void 0;
374
+ if (fromOverload) return fromOverload;
375
+ }
376
+ }
377
+ if (node === "aggregate" && parent?.e === expr) {
378
+ let fn = (parent?.function || "").toLowerCase();
379
+ if (fn === "sum" || fn === "avg") return "number";
380
+ if (fn === "count") return "number";
381
+ }
382
+ if (node === "case") {
383
+ let kids = parent?.kids || {};
384
+ let caseWhen = Array.isArray(kids.caseWhen) ? kids.caseWhen : [];
385
+ if (caseWhen.includes(expr)) return "boolean";
386
+ if (kids.caseElse === expr) return sanitizeType(parent.type) || void 0;
387
+ let caseThen = Array.isArray(kids.caseThen) ? kids.caseThen : [];
388
+ if (caseThen.includes(expr)) return sanitizeType(parent.type) || void 0;
389
+ if (kids.caseValue === expr) {
390
+ let sample = caseThen[0];
391
+ if (sample?.type) return sanitizeType(sample.type);
392
+ }
393
+ }
394
+ return void 0;
395
+ }
396
+ function getBinarySibling(parent, target) {
397
+ if (!parent?.kids) return void 0;
398
+ let kids = parent.kids;
399
+ let left2 = kids.left;
400
+ let right2 = kids.right;
401
+ if (left2 === target) return right2;
402
+ if (right2 === target) return left2;
403
+ return void 0;
404
+ }
405
+ function sanitizeType(value) {
406
+ if (typeof value !== "string") return void 0;
407
+ if (!FIELD_TYPES.has(value)) return void 0;
408
+ if (value === "fieldref") return void 0;
409
+ return value;
410
+ }
411
+ function fillInParams(query, params) {
412
+ let q = structuredClone(query);
413
+ let filters = q.pipeline[0].filterList || [];
414
+ for (let filter of filters) {
415
+ walkExpression(filter.e, (e) => {
416
+ if (e.node !== "parameter") return;
417
+ let value = params[e.path[0]];
418
+ if (value === void 0) throw new Error(`Missing param $${e.path[0]}`);
419
+ else if (value == null) Object.assign(e, { node: "null", type: "string" });
420
+ else if (e.type == "string") Object.assign(e, { node: "stringLiteral", literal: value });
421
+ else if (e.type == "number") Object.assign(e, { node: "numberLiteral", literal: value.toString() });
422
+ else if (e.type == "boolean") Object.assign(e, { node: value ? "true" : "false" });
423
+ else throw new Error(`Unsupported param type ${e.type}`);
424
+ });
425
+ }
426
+ return q;
427
+ }
428
+ var COMPARISON_OPS, BOOLEAN_OPS, NUMERIC_UNARY_OPS, FIELD_TYPES;
429
+ var init_params = __esm({
430
+ "../lang/params.ts"() {
431
+ init_util();
432
+ COMPARISON_OPS = /* @__PURE__ */ new Set(["=", "!=", "<>", ">", ">=", "<", "<=", "like", "ilike"]);
433
+ BOOLEAN_OPS = /* @__PURE__ */ new Set(["and", "or"]);
434
+ NUMERIC_UNARY_OPS = /* @__PURE__ */ new Set(["unary-"]);
435
+ FIELD_TYPES = /* @__PURE__ */ new Set(["string", "number", "boolean", "date", "timestamp", "json", "sql native", "error", "fieldref", "array", "record", "null"]);
436
+ }
437
+ });
438
+
439
+ // ../lang/analyze.ts
440
+ import { NodeWeakMap } from "@lezer/common";
441
+ import { isExtractUnit, isTemporalType } from "@graphenedata/malloy";
442
+ function findTables(fi) {
443
+ let tn = fi.tree.topNode;
444
+ fi.tables = [];
445
+ let nodes = tn.getChildren("TableStatement").concat(tn.getChildren("ViewStatement"));
446
+ for (let syntaxNode of nodes) {
447
+ let name = txt(syntaxNode.getChild("Identifier"));
448
+ if (Object.values(FILE_MAP).find((f) => f.tables.find((t) => t.name == name))) {
449
+ diag(syntaxNode.getChild("Identifier"), `Table "${name}" is already defined`);
450
+ }
451
+ let table2 = makeTable(name, syntaxNode.getChild("QueryStatement") ? "query_source" : "table");
452
+ table2.metadata = extractLeadingMetadata(syntaxNode);
453
+ for (let cn of syntaxNode.getChildren("ColumnDef")) {
454
+ let name2 = txt(cn.getChild("Identifier"));
455
+ if (cn.getChild("PrimaryKey")) {
456
+ if (table2.primaryKey) diag(cn, `Table ${table2.name} has multiple primary keys`);
457
+ table2.primaryKey = name2;
458
+ }
459
+ let type = convertDataType(txt(cn.getChild("DataType")));
460
+ if (!type) diag(cn, `Unsupported data type: ${txt(cn.getChild("DataType"))}`);
461
+ let field = { name: name2, type, metadata: extractLeadingMetadata(cn) };
462
+ table2.fields.push(field);
463
+ FIELD_NODE_MAP.set(field, cn);
464
+ }
465
+ for (let jn of syntaxNode.getChildren("JoinDef")) {
466
+ let nameNode = jn.getChild("Alias") || jn.getChild("Identifier");
467
+ let field = { name: txt(nameNode) };
468
+ table2.fields.push(field);
469
+ FIELD_NODE_MAP.set(field, jn);
470
+ }
471
+ for (let cn of syntaxNode.getChildren("ComputedDef")) {
472
+ let field = { name: txt(cn.getChild("Alias")), metadata: extractLeadingMetadata(cn) };
473
+ table2.fields.push(field);
474
+ FIELD_NODE_MAP.set(field, cn);
475
+ }
476
+ table2.fields.reduce((set, f) => {
477
+ if (!set[f.name]) set[f.name] = true;
478
+ else diag(FIELD_NODE_MAP.get(f), `Table already has a field called "${f.name}"`);
479
+ return set;
480
+ }, {});
481
+ TABLE_NODE_MAP.set(table2, syntaxNode);
482
+ fi.tables.push(table2);
483
+ }
484
+ }
485
+ function makeTable(name, type) {
486
+ let tablePath = config.namespace ? `${config.namespace}.${name}` : name;
487
+ return { name, type, fields: [], connection: config.dialect, dialect: config.dialect, tableName: name, tablePath, metadata: {} };
488
+ }
489
+ function analyzeTable(table2) {
490
+ if (table2.type == "query_source") return analyzeQueryTable(table2);
491
+ for (let f of table2.fields) {
492
+ if (f.type) continue;
493
+ analyzeField(f, table2);
494
+ }
495
+ }
496
+ function analyzeField(field, table2) {
497
+ if (field.type) return;
498
+ let node = FIELD_NODE_MAP.get(field);
499
+ if (analysisQueue.has(field)) {
500
+ diag(node, "Cycles are not allowed between computed columns");
501
+ }
502
+ analysisQueue.add(field);
503
+ if (node.name == "JoinDef") {
504
+ field = field;
505
+ let target = lookupTable(txt(node.getChild("Identifier")), node);
506
+ if (!target) return diag(node, "Unknown table to join");
507
+ if (target.type == "query_source") analyzeQueryTable(target);
508
+ let jt = { "join_many": "many", "join_one": "one" }[txt(node.getChild("JoinType"))];
509
+ if (!jt) return diag(node, "Unknown join type");
510
+ Object.assign(field, target, { name: field.name, join: jt });
511
+ field.onExpression = analyzeExpression(node.getChild("Expression"), { table: table2, outputFields: [] });
512
+ }
513
+ if (node.name == "ComputedDef") {
514
+ let e = analyzeExpression(node.getChild("Expression"), { table: table2, outputFields: [] });
515
+ let metadata = extractLeadingMetadata(node);
516
+ Object.assign(field, { e, metadata, type: e.type, isAgg: e.isAgg });
517
+ }
518
+ analysisQueue.delete(field);
519
+ }
520
+ function analyzeQueryTable(table2) {
521
+ if (table2.query) return;
522
+ let node = TABLE_NODE_MAP.get(table2);
523
+ let query = analyzeQuery(node.getChild("QueryStatement"));
524
+ if (!query) throw new Error("Couldnt find query in QueryStatement");
525
+ table2.fields = query.fields.map((f) => ({ type: f.type, name: f.name, metadata: f.metadata }));
526
+ table2.query = query.malloyQuery;
527
+ if (typeof table2.query.structRef == "string") {
528
+ table2.query.structRef = lookupTable(table2.query.structRef, node);
529
+ }
530
+ }
531
+ function analyzeQuery(queryNode) {
532
+ let structRef;
533
+ let scope = { table: null, outputFields: [] };
534
+ let isAgg = false;
535
+ let subQuerySources = [];
536
+ if (!txt(queryNode)) return;
537
+ let froms = queryNode.getChild("FromClause")?.getChildren("TablePrimary") || [];
538
+ if (froms.find((f) => f.name == "JoinClause")) diag(froms[0], "Query joins not yet supported");
539
+ if (froms.length == 0) diag(queryNode, "No tables in FROM clause");
540
+ if (froms.length > 1) diag(froms[0], "Multiple tables/joins in FROM clause not yet supported");
541
+ if (froms[0].name == "Subquery") {
542
+ structRef = txt(froms[0].getChild("Alias")) || "subquery";
543
+ scope.table = makeTable(structRef, "query_source");
544
+ TABLE_NODE_MAP.set(scope.table, froms[0].getChild("SubqueryExpression"));
545
+ analyzeQueryTable(scope.table);
546
+ subQuerySources.push(scope.table);
547
+ } else {
548
+ structRef = txt(froms[0].getChild("Identifier"));
549
+ scope.table = lookupTable(structRef, froms[0]);
550
+ if (!scope.table) return diag(froms[0], `could not find table "${structRef}"`);
551
+ NODE_ENTITY_MAP.set(froms[0], { entityType: "table", table: scope.table });
552
+ }
553
+ let selects = queryNode.getChild("SelectClause")?.getChildren("SelectItem") || [];
554
+ let isSelectDistinct = queryNode.getChild("SelectClause")?.getChildren("Kw").find((n) => txt(n).toLowerCase() == "distinct");
555
+ isAgg ||= !!isSelectDistinct;
556
+ selects.forEach((s) => {
557
+ if (s.getChild("Wildcard")) {
558
+ let path9 = s.getChild("Wildcard").getChildren("Identifier");
559
+ let pathStrings = path9.map((p) => txt(p));
560
+ let target = followJoins(path9, scope.table);
561
+ if (!target) return;
562
+ target.fields.forEach((f) => {
563
+ if (isJoin(f) || f.isAgg) return;
564
+ scope.outputFields.push({ ...f, e: { node: "field", path: [...pathStrings, f.name], type: f.type } });
565
+ });
566
+ } else {
567
+ let expr = analyzeExpression(s.getChild("Expression"), scope);
568
+ let name = nameExpression(expr, scope, s.getChild("Alias"));
569
+ isAgg ||= !!expr.isAgg;
570
+ let metadata = {};
571
+ if (expr.isAgg) {
572
+ scope.outputFields.push({ type: expr.type, name, metadata, e: expr, expressionType: "aggregate", isAgg: true });
573
+ } else {
574
+ scope.outputFields.push({ type: expr.type, name, metadata, e: expr });
575
+ }
576
+ }
577
+ });
578
+ let where2 = queryNode.getChild("WhereClause")?.getChild("Expression");
579
+ let having = queryNode.getChild("HavingClause")?.getChild("Expression");
580
+ let filterList = [where2, having].flatMap((node) => {
581
+ if (!node) return [];
582
+ let ands = unpackAnds(analyzeExpression(node, scope));
583
+ return ands.map((e) => ({
584
+ node: "filterCondition",
585
+ expressionType: e.isAgg ? "aggregate" : "scalar",
586
+ e
587
+ }));
588
+ });
589
+ let groupBys = queryNode.getChild("GroupByClause")?.getChildren("SelectItem") || [];
590
+ isAgg ||= !!groupBys.length;
591
+ groupBys.forEach((g) => {
592
+ let expr = analyzeExpression(g.getChild("Expression"), scope);
593
+ let name = nameExpression(expr, scope, g.getChild("Alias"));
594
+ if (expr.isAgg) return diag(g, "Cannot group by aggregate expressions");
595
+ if (scope.outputFields.find((f) => f.name == name)) return;
596
+ scope.outputFields.unshift({ type: expr.type, name, metadata: {}, e: expr });
597
+ });
598
+ let orderBys = queryNode.getChild("OrderByClause")?.getChildren("OrderItem") || [];
599
+ let orderByList = orderBys.map((o) => {
600
+ let field = txt(o.getChild("Identifier")) || Number(txt(o.getChild("Number")));
601
+ let dir = txt(o.getChild("Kw")).toLowerCase() == "desc" ? "desc" : "asc";
602
+ return { field, dir };
603
+ });
604
+ let limts = queryNode.getChild("LimitClause")?.getChildren("Number") || [];
605
+ let queryLimit = limts[0] ? Number(txt(limts[0])) : void 0;
606
+ let queryOffset = limts[1] ? Number(txt(limts[1])) : void 0;
607
+ if (queryOffset) diag(limts[1], "OFFSET is not supported yet");
608
+ if (scope.outputFields.length == 0) {
609
+ scope.table.fields.forEach((f) => {
610
+ if (isJoin(f) || f.isAgg) return;
611
+ scope.outputFields.push({ ...f, e: { node: "field", path: [f.name], type: f.type } });
612
+ });
613
+ }
614
+ let q = {
615
+ fields: scope.outputFields,
616
+ subQuerySources,
617
+ malloyQuery: {
618
+ type: "query",
619
+ structRef,
620
+ pipeline: [{
621
+ type: isAgg ? "reduce" : "project",
622
+ queryFields: scope.outputFields,
623
+ filterList,
624
+ outputStruct: null,
625
+ isRepeated: false,
626
+ orderBy: orderByList.length ? orderByList : void 0,
627
+ limit: queryLimit
628
+ }]
629
+ }
630
+ };
631
+ inferParamTypes(q.malloyQuery);
632
+ return q;
633
+ }
634
+ function analyzeExpression(expr, scope) {
635
+ if (expr.type.isError) {
636
+ return diag(expr, "Invalid expression", errExpr);
637
+ }
638
+ switch (expr.name) {
639
+ case "Number":
640
+ return { node: "numberLiteral", literal: txt(expr), type: "number" };
641
+ case "Boolean":
642
+ return { node: txt(expr).toLowerCase() == "true" ? "true" : "false", type: "boolean" };
643
+ case "Null":
644
+ return { node: "null", type: "string" };
645
+ case "String":
646
+ return { node: "stringLiteral", literal: txt(expr).slice(1, -1), type: "string" };
647
+ case "Param":
648
+ return { node: "parameter", path: [txt(expr).slice(1)], type: "string" };
649
+ case "Ref": {
650
+ let field = lookupField(expr, scope);
651
+ if (!field) return errExpr;
652
+ let type = field.type || "unknown";
653
+ let typeInfo = { type };
654
+ if (type === "date" || type === "timestamp") typeInfo.typeDef = { type };
655
+ if (scope.outputFields.includes(field) && field.isAgg) {
656
+ return { node: "outputField", name: field.name, ...typeInfo, isAgg: field.isAgg };
657
+ }
658
+ let path9 = expr.getChildren("Identifier").map((i) => txt(i));
659
+ return { node: "field", path: path9, ...typeInfo, isAgg: field.isAgg };
660
+ }
661
+ case "ExtractExpression": {
662
+ let e = analyzeExpression(expr.getChild("Expression"), scope);
663
+ if (!isTemporalType(e.type) || !e.typeDef) return diag(expr, "Expression must be a date or timestamp", errExpr);
664
+ let units = txt(expr.getChild("ExtractUnit")).replace(/^['"]|['"]$/g, "").toLowerCase();
665
+ if (!isExtractUnit(units)) return diag(expr, "Not a valid unit to extract", errExpr);
666
+ return { node: "extract", type: "number", units, e, isAgg: false };
667
+ }
668
+ case "FunctionCall":
669
+ return analyzeFunctionCall(expr, scope);
670
+ case "Parenthetical":
671
+ return analyzeExpression(expr.getChild("Expression"), scope);
672
+ case "Count": {
673
+ let countExpr = expr.getChild("Expression");
674
+ if (countExpr) {
675
+ let e = analyzeExpression(countExpr, scope);
676
+ return { node: "aggregate", function: "distinct", e, type: "number", isAgg: true };
677
+ } else {
678
+ return { node: "aggregate", function: "count", e: { node: "" }, type: "number", isAgg: true };
679
+ }
680
+ }
681
+ case "BinaryExpression": {
682
+ let left2 = analyzeExpression(expr.firstChild, scope);
683
+ let right2 = analyzeExpression(expr.lastChild, scope);
684
+ let op = txt(expr.firstChild?.nextSibling).toLowerCase();
685
+ return { node: op, kids: { left: left2, right: right2 }, type: left2.type, isAgg: left2.isAgg || right2.isAgg };
686
+ }
687
+ case "NullTestExpression": {
688
+ let node = expr.getChildren("Kw").find((n) => txt(n).toLowerCase() == "not") ? "is-not-null" : "is-null";
689
+ let e = analyzeExpression(expr.firstChild, scope);
690
+ return { node, type: "boolean", isAgg: e.isAgg, e };
691
+ }
692
+ case "UnaryExpression": {
693
+ let opTxt = txt(expr.firstChild).toLowerCase();
694
+ let child = analyzeExpression(expr.lastChild, scope);
695
+ if (opTxt === "not") return { node: "not", e: child, type: "boolean", isAgg: child.isAgg };
696
+ if (opTxt === "-") return { node: "unary-", e: child, type: child.type, isAgg: child.isAgg };
697
+ if (opTxt === "+") return { node: "()", e: child, type: child.type, isAgg: child.isAgg };
698
+ return diag(expr, `Unknown unary operator: ${opTxt}`, errExpr);
699
+ }
700
+ case "CaseExpression": {
701
+ let caseValue = expr.getChild("Expression");
702
+ let whens = expr.getChildren("WhenClause");
703
+ let els = expr.getChild("ElseClause");
704
+ let kids = {
705
+ caseValue: caseValue ? analyzeExpression(caseValue, scope) : void 0,
706
+ caseElse: els ? analyzeExpression(els.getChild("Expression"), scope) : void 0,
707
+ caseWhen: whens.map((w) => analyzeExpression(w.getChildren("Expression")[0], scope)),
708
+ caseThen: whens.map((w) => analyzeExpression(w.getChildren("Expression")[1], scope))
709
+ };
710
+ let thenType = kids.caseThen[0]?.type || "string";
711
+ return { node: "case", kids: compact(kids), type: thenType, isAgg: false };
712
+ }
713
+ case "InExpression": {
714
+ let not2 = txt(expr.getChild("Kw")).toLowerCase() == "not";
715
+ let eNode = analyzeExpression(expr.firstChild, scope);
716
+ let oneOf = [];
717
+ let valueList = expr.getChild("InValueList");
718
+ if (valueList) {
719
+ oneOf = valueList.getChildren("Expression").map((v) => analyzeExpression(v, scope));
720
+ } else {
721
+ oneOf = [{ node: "genericSQLExpr", kids: { args: [] }, type: "array" }];
722
+ }
723
+ let isAgg = eNode.isAgg || oneOf.some((v) => v.isAgg);
724
+ return { node: "in", not: not2, kids: { e: eNode, oneOf }, type: "boolean", isAgg };
725
+ }
726
+ case "SubqueryExpression":
727
+ default:
728
+ return diag(expr, `Unsupported expression "${expr.name}": ${txt(expr)}`, errExpr);
729
+ }
730
+ }
731
+ function analyzeFunctionCall(expr, scope) {
732
+ let name = txt(expr.getChild("Identifier")).toLowerCase();
733
+ let argNodes = expr.getChildren("Expression");
734
+ let overload = findOverloads(name, config.dialect).find((o) => {
735
+ return o.params.length == argNodes.length || !!o.params.find((p) => p.isVariadic);
736
+ });
737
+ let args = argNodes.map((node, idx) => {
738
+ let type2 = overload?.params[idx]?.allowedTypes[0];
739
+ if (type2?.type === "sql native" && type2?.rawType === "kw") {
740
+ return { node: "genericSQLExpr", kids: { args: [] }, type: "sql native", src: [txt(node)], isAgg: false };
741
+ } else {
742
+ return analyzeExpression(node, scope);
743
+ }
744
+ });
745
+ let type = overload?.returnType.type;
746
+ if (type == "generic") type = args[0]?.type || "string";
747
+ if (type && !isSupportedType(type)) {
748
+ return diag(expr, `Unsupported function return type ${type} from function ${name}`, errExpr);
749
+ }
750
+ let structPaths = /* @__PURE__ */ new Set();
751
+ args.forEach((a) => walkExpression(a, (e) => {
752
+ if (e.node != "field") return;
753
+ structPaths.add(e.path.slice(0, -1).join(".") || scope.table.name);
754
+ }));
755
+ let ret;
756
+ if (["count", "min", "max", "avg", "sum"].includes(name.toLowerCase())) {
757
+ ret = { node: "aggregate", function: name, e: args[0], type: "number", isAgg: true };
758
+ } else if (overload && type) {
759
+ ret = {
760
+ node: "function_call",
761
+ type,
762
+ name,
763
+ overload,
764
+ expressionType: overload.returnType.expressionType || "scalar",
765
+ kids: { args },
766
+ isAgg: overload.returnType.expressionType == "aggregate" || args.some((a) => a.isAgg)
767
+ };
768
+ } else {
769
+ return diag(expr, `Unknown function: ${name}`, errExpr);
770
+ }
771
+ if (structPaths.size > 1 && (ret.node == "aggregate" || ret.expressionType == "aggregate")) {
772
+ return diag(expr, "Graphene only supports a single table within aggregates. This one has: " + Array.from(structPaths).join(", "), errExpr);
773
+ }
774
+ let foriegnPaths = Array.from(structPaths).filter((p) => p != scope.table.name);
775
+ if (foriegnPaths.length > 0) ret.structPath = foriegnPaths[0].split(".");
776
+ return ret;
777
+ }
778
+ function isSupportedType(value) {
779
+ let supported = ["string", "number", "boolean", "date", "timestamp", "json", "sql native", "error", "array", "record", "null", "generic"];
780
+ return supported.includes(value);
781
+ }
782
+ function lookupField(expr, scope) {
783
+ let pathNodes = expr.getChildren("Identifier");
784
+ let fieldNode = pathNodes.pop();
785
+ if (!fieldNode) return diag(expr, "Missing identifiers in ref", null);
786
+ let fieldName = txt(fieldNode);
787
+ let outField = scope.outputFields.find((of) => of.name == fieldName);
788
+ if (pathNodes.length == 0 && outField) return outField;
789
+ let table2 = followJoins(pathNodes, scope.table);
790
+ if (!table2) return null;
791
+ let field = table2.fields.find((f) => f.name == fieldName);
792
+ if (!field) return diag(fieldNode, `Could not find "${fieldName}" on ${table2.name}`, null);
793
+ if (isJoin(field)) return diag(fieldNode, `${fieldName} is a join, but is used as a column here`, null);
794
+ analyzeField(field, table2);
795
+ NODE_ENTITY_MAP.set(fieldNode, { entityType: "field", field, table: table2 });
796
+ return field;
797
+ }
798
+ function followJoins(pathNodes, curr) {
799
+ for (let part of pathNodes) {
800
+ let name = txt(part);
801
+ let next = curr.fields.find((f) => f.name == name);
802
+ if (name == curr.name) continue;
803
+ if (!next) {
804
+ let other = curr.fields.find((f) => isJoin(f) && f.tableName == name);
805
+ let dym = other ? `. Did you mean "${other.name}"?` : "";
806
+ return diag(part, `Join "${name}" does not exist on table "${curr.name}"${dym}`, null);
807
+ }
808
+ analyzeField(next, curr);
809
+ if (!isJoin(next)) return diag(part, `"${name}" is not a join on "${curr.name}"`, null);
810
+ curr = lookupTable(next.tableName || "", part);
811
+ if (!curr) return diag(part, "Following valid join but we couldnt find the table", null);
812
+ NODE_ENTITY_MAP.set(part, { entityType: "table", table: curr });
813
+ }
814
+ return curr;
815
+ }
816
+ function lookupTable(name, node) {
817
+ let currentUri = getFile(node).path;
818
+ for (let file of Object.values(FILE_MAP)) {
819
+ if (file.path.endsWith(".gsql") || file.path == currentUri) {
820
+ let match = file.tables.find((t) => t.name == name);
821
+ if (match) return match;
822
+ }
823
+ }
824
+ }
825
+ function clearWorkspace() {
826
+ FILE_MAP = {};
827
+ TABLE_NODE_MAP = /* @__PURE__ */ new WeakMap();
828
+ diagnostics = [];
829
+ }
830
+ function clearDiagnostics() {
831
+ diagnostics = [];
832
+ }
833
+ function nameExpression(expr, scope, aliasNode) {
834
+ if (aliasNode) return txt(aliasNode);
835
+ if (expr.node == "field") return expr.path.join("_");
836
+ return `col_${scope.outputFields.length}`;
837
+ }
838
+ function diag(node, message, defaultReturn) {
839
+ let file = getFile(node);
840
+ let from2 = getPosition(node.from, file);
841
+ let to = getPosition(node.to, file);
842
+ diagnostics.push({ from: from2, to, message, severity: "error", file: file.path });
843
+ return defaultReturn;
844
+ }
845
+ function recordSyntaxErrors(fi) {
846
+ fi.tree.topNode.cursor().iterate((n) => {
847
+ if (n.type.isError) diag(n.node, "Syntax error");
848
+ });
849
+ }
850
+ function unpackAnds(expr) {
851
+ if (expr.node == "and") {
852
+ return [expr.kids.left, expr.kids.right].flatMap(unpackAnds);
853
+ }
854
+ return [expr];
855
+ }
856
+ function isJoin(field) {
857
+ return field.type == "table" || field.type == "query_source";
858
+ }
859
+ function convertDataType(dataType) {
860
+ switch (dataType.toUpperCase()) {
861
+ case "INT":
862
+ return "number";
863
+ case "INT64":
864
+ return "number";
865
+ case "TEXT":
866
+ return "string";
867
+ case "STRING":
868
+ return "string";
869
+ case "VARCHAR":
870
+ return "string";
871
+ case "INTEGER":
872
+ return "number";
873
+ case "FLOAT":
874
+ return "number";
875
+ case "FLOAT64":
876
+ return "number";
877
+ case "BOOLEAN":
878
+ return "boolean";
879
+ case "DATE":
880
+ return "date";
881
+ case "DATETIME":
882
+ return "timestamp";
883
+ case "TIME":
884
+ return "timestamp";
885
+ case "TIMESTAMP":
886
+ return "timestamp";
887
+ case "DECIMAL":
888
+ return "number";
889
+ case "DOUBLE":
890
+ return "number";
891
+ case "BIGINT":
892
+ return "number";
893
+ case "SMALLINT":
894
+ return "number";
895
+ case "TINYINT":
896
+ return "number";
897
+ case "BYTEINT":
898
+ return "number";
899
+ case "BIGDECIMAL":
900
+ return "number";
901
+ case "GEOGRAPHY":
902
+ return "string";
903
+ default:
904
+ return null;
905
+ }
906
+ }
907
+ var FILE_MAP, diagnostics, TABLE_NODE_MAP, FIELD_NODE_MAP, NODE_ENTITY_MAP, analysisQueue, errExpr;
908
+ var init_analyze = __esm({
909
+ "../lang/analyze.ts"() {
910
+ init_util();
911
+ init_metadata();
912
+ init_config();
913
+ init_functions();
914
+ init_params();
915
+ FILE_MAP = {};
916
+ diagnostics = [];
917
+ TABLE_NODE_MAP = /* @__PURE__ */ new WeakMap();
918
+ FIELD_NODE_MAP = /* @__PURE__ */ new WeakMap();
919
+ NODE_ENTITY_MAP = new NodeWeakMap();
920
+ analysisQueue = /* @__PURE__ */ new Set();
921
+ errExpr = { node: "error", type: "error" };
922
+ }
923
+ });
924
+
925
+ // ../lang/parser.terms.js
926
+ var table, primary_key, as, on, not, exists, from, inner, left, right, full, cross, join, select, where, group, by, order, asc, desc, limit, offset, _in, is, _null, _true, _false, or, and, like;
927
+ var init_parser_terms = __esm({
928
+ "../lang/parser.terms.js"() {
929
+ table = 6;
930
+ primary_key = 11;
931
+ as = 19;
932
+ on = 22;
933
+ not = 31;
934
+ exists = 49;
935
+ from = 53;
936
+ inner = 59;
937
+ left = 61;
938
+ right = 63;
939
+ full = 65;
940
+ cross = 67;
941
+ join = 69;
942
+ select = 72;
943
+ where = 80;
944
+ group = 83;
945
+ by = 85;
946
+ order = 91;
947
+ asc = 95;
948
+ desc = 97;
949
+ limit = 100;
950
+ offset = 102;
951
+ _in = 105;
952
+ is = 109;
953
+ _null = 111;
954
+ _true = 115;
955
+ _false = 117;
956
+ or = 130;
957
+ and = 132;
958
+ like = 141;
959
+ }
960
+ });
961
+
962
+ // ../lang/tokens.js
963
+ function specializeIdentifier(value) {
964
+ let lower = value.toLowerCase();
965
+ return keywords[lower] || -1;
966
+ }
967
+ var keywords;
968
+ var init_tokens = __esm({
969
+ "../lang/tokens.js"() {
970
+ init_parser_terms();
971
+ keywords = {
972
+ select,
973
+ not,
974
+ true: _true,
975
+ false: _false,
976
+ null: _null,
977
+ like,
978
+ in: _in,
979
+ is,
980
+ and,
981
+ or,
982
+ as,
983
+ from,
984
+ inner,
985
+ left,
986
+ right,
987
+ full,
988
+ cross,
989
+ join,
990
+ on,
991
+ where,
992
+ group,
993
+ by,
994
+ order,
995
+ asc,
996
+ desc,
997
+ limit,
998
+ offset,
999
+ table,
1000
+ exists,
1001
+ primary_key
1002
+ };
1003
+ }
1004
+ });
1005
+
1006
+ // ../lang/parser.js
1007
+ import { LRParser } from "@lezer/lr";
1008
+ var spec_Identifier, parser;
1009
+ var init_parser = __esm({
1010
+ "../lang/parser.js"() {
1011
+ init_tokens();
1012
+ spec_Identifier = { __proto__: null, table: 12, primary_key: 22, join_one: 30, join_many: 34, as: 38, on: 44, not: 62, case: 72, when: 78, then: 82, else: 88, end: 92, exists: 98, from: 106, inner: 118, left: 122, right: 126, full: 130, cross: 134, join: 138, select: 144, distinct: 148, where: 160, group: 166, by: 170, having: 176, order: 182, asc: 190, desc: 194, limit: 200, offset: 204, in: 210, is: 218, null: 222, true: 230, false: 234, count: 244, extract: 250, or: 260, and: 264, like: 282 };
1013
+ parser = LRParser.deserialize({
1014
+ version: 14,
1015
+ states: "BbQYQPOOOOQO'#C`'#C`OOQO'#Db'#DbOtQPO'#DaOOQO'#Du'#DuO#QQPO'#DtOOQO'#D}'#D}O#XQPO'#D|OOQO'#EQ'#EQO$YQPO'#EPOOQO'#EV'#EVO#XQPO'#EUOOQO'#EY'#EYO$YQPO'#EXOOQO'#Ec'#EcO$_QPO'#EbOOQO'#Fi'#FiO$dQPO'#D`O$qQPO'#C_O$vQPO'#FeQYQPOOQ%hQPO'#FeO%mQPO'#DdO]QPO'#DfO&zQPO'#DeOOQO'#Fv'#FvO(mQPO,59{O*tQPO'#CtO,^QPO'#CtOOQO'#Cz'#CzOOQO'#Cy'#CyO#XQPO'#CxOOQO'#DP'#DPO,fQPO'#DOOOQO'#D^'#D^O,mQPO'#DfOOQO'#Dw'#DwOOQO'#Dz'#DzO.bQPO'#DyOOQO'#Dy'#DyO/_QPO,5:`O|QPO,5:`O0SQPO'#D]OOQO'#En'#EnOOQO'#Er'#ErOOQO'#Et'#EtOOQO'#Eq'#EqOOQO'#Ev'#EvOOQO'#Fy'#FyOOQO'#Ey'#EyO0XQPO'#ExOOQO'#E|'#E|O0^QPO'#E{OOQO'#Fu'#FuO0cQPO'#CtO0hQPO,5:hOOQO'#ES'#ESO|QPO,5:kO1[QPO,5:pO2OQPO,5:sO2WQPO,5:|OOQO-E9g-E9gO2{QPO,58yOOQO,5<P,5<POOQO-E9c-E9cOOQO'#Cn'#CnOOQO'#Cp'#CpOOQO,5:O,5:OO3TQPO,5:OO3YQPO,5:QOOQO,5:P,5:PO3TQPO,5:POOQO'#Dh'#DhOOQO'#Dj'#DjOOQO'#Dl'#DlOOQO'#Dn'#DnOOQO'#Dp'#DpOOQO'#Dr'#DrOtQPO'#DgO(hQPO'#DgOOQO'#Fj'#FjO3_QPO1G/gOOQO,5<R,5<RO4RQPO,5;kO4YQPO,59`OOQO-E9e-E9eOOQO,5:f,5:fOOQO,59d,59dOOQO'#DS'#DSO#XQPO'#DROOQO'#Fh'#FhO7wQPO,59jO8SQPO,59jO8ZQPO,5;lOOQO,5:e,5:eO3TQPO,5:eOOQO'#Eh'#EhO8bQPO,5;RO8gQPO,5;ROOQO'#El'#ElO8oQPO,5;VOOQO'#FR'#FROOQO'#FT'#FTOOQO'#F^'#F^OOQO'#FV'#FVOOQO'#F`'#F`OOQO'#Fa'#FaO#XQPO,59cO#XQPO,59cO#XQPO,59cO#XQPO,59cO#XQPO,59cO8wQPO1G/zO9kQPO1G/zO9kQPO1G/zO]QPO,59wO:`QPO,5;dO:mQPO,5;gO:uQPO1G0VO;jQPO'#E[O<eQPO1G0_OOQO'#Ee'#EeO=YQPO1G0hO=_QPO1G.eO>fQPO1G1jOOQO1G/j1G/jOOQO1G/l1G/lOOQO1G/k1G/kO>kQPO,5:ROtQPO,5:ROOQO-E9h-E9hO?rQPO1G1VOOQO1G1V1G1VP?|QPO'#FgO@RQPO,59mOOQO-E9f-E9fOOQO'#DX'#DXO#XQPO'#DWOOQO'#DZ'#DZOOQO1G/U1G/UO7}QPO1G/UO7wQPO1G/UOOQO1G1W1G1WOOQO1G0P1G0PO,mQPO1G0mO@YQPO1G0mOOQO,5;q,5;qOOQO1G0q1G0qO8rQPO1G0qOB}QPO1G.}OCUQPO1G.}OExQPO1G.}OFSQPO1G.}OOQO1G.}1G.}OOQO,5<V,5<VOF^QPO7+%fOOQO-E9i-E9iOGQQPO7+%fOGuQPO1G/cOGzQPO1G1OOOQO1G1O1G1OOHRQPO1G1OO#XQPO1G1OOOQO'#FO'#FOOHWQPO1G1ROH]QPO7+%qOIPQPO7+%qOOQO'#E^'#E^OOQO'#E`'#E`OOQO,5:v,5:vOJfQPO7+%yOJpQPO7+%yOOQO7+&S7+&SOJwQPO'#CtOOQO'#Cj'#CjOOQO'#Cl'#ClOOQO'#Ci'#CiOKOQPO'#ChO-WQPOOOL_QPO'#FuOLfQPO'#FuOOQO'#Ft'#FtOLmQPO'#CvOOQO'#Fr'#FrOLrQPO'#FfONPQPO7+$PO]QPO7+'UOOQO'#Cq'#CqO#XQPO1G/mONWQPO1G/mO! _QPO7+&qO! fQPO7+&qOOQO7+&q7+&qOOQO'#DU'#DUO#XQPO1G/XO! nQPO,59rOOQO7+$p7+$pO7}QPO7+$pO! uQPO'#EjO!!PQPO7+&XO,mQPO7+&XOOQO7+&]7+&]P|QPO'#FkO!!UQPO<<IQOOQO7+$}7+$}OOQO7+&j7+&jO!!xQPO7+&jO#XQPO7+&mO!#PQPO<<I]OOQO,5<W,5<WO!#sQPO<<IeOOQO-E9j-E9jOOQO'#Cd'#CdO!$kQPO,58}O!%{QPO,59SO3TQPO,59bOOQO,5<Q,5<QOOQO-E9d-E9dOOQO<<Gk<<GkO!&TQPO<<JpO!&YQPO7+%XO#XQPO7+%XO!'`QPO,5<XOOQO<<J]<<J]O!'jQPO<<J]OOQO-E9k-E9kO!'qQPO7+$sOOQO<<H[<<H[O!(OQPO,5;UO!(VQPO,5;UOOQO<<Is<<IsO!(_QPO<<IsOOQO<<JU<<JUO!(dQPO<<JXP2OQPO'#FlOOQO'#Cf'#CfOOQO'#Ce'#CeOOQO1G.i1G.iO!(kQPO1G.nO3TQPO1G.nOOQO1G.|1G.|OOQOAN@[AN@[O!(pQPO<<HsOOQOAN?wAN?wP#XQPO'#FmO!)vQPO1G0pOOQOAN?_AN?_OOQOAN?sAN?sO!)}QPO'#CtO!+bQPO'#CsOOQO7+$Y7+$YO!&OQPO7+$YO!(kQPO,59_O!(kQPO<<GtOOQO1G.y1G.yOOQOAN=`AN=`",
1016
+ stateData: "!+l~O$dOSPOS~OUPO!VQO!jSO!rUO!uWO!zYO!}[O#W^O~OTfO$egO~OTkOomOpnOqnOtpO!RrO!ouO#P!QO#c{O#d!QO#g|O#i}O#k!VO#n!RO#q!TO$esO~O!ltO~P|OTkOomOpnOqnOtpO!RrO#P!QO#c{O#d!QO#g|O#i}O#k!VO#n!RO#q!TO$esO~O!w!YO~O#P!^O~O$b!SX$o!SX$k!SX~P]OT!`O~O$o!aOU$XX!V$XX!j$XX!r$XX!u$XX!z$XX!}$XX#W$XX$b$XX~O$o!aO~OT!dOc!cO!V!WX!]!WX!_!WX!a!WX!c!WX!e!WX!g!WX!j!WX!r!WX!u!WX!z!WX!}!WX#W!WX$b!WX$o!WX$k!WXf!WX~OT!dOc!cO!V!XX!]!XX!_!XX!a!XX!c!XX!e!XX!g!XX!j!XX!r!XX!u!XX!z!XX!}!XX#W!XX$b!XX$o!XX$k!XXf!XX~O!]!jO!_!kO!a!lO!c!mO!e!nO!g!oO~O!V!Ta!j!Ta!r!Ta!u!Ta!z!Ta!}!Ta#W!Ta$b!Ta$o!Ta$k!Ta~P(XO$e!uO$g!tOchXihXohXphXqhX!ohX#]hX#ahX#vhX#xhX#zhX#{hX#|hX#}hX$OhX$PhX$RhX$UhX$VhX~OThX!VhX!jhX!rhX!uhX!zhX!}hX#WhX$bhX$lhX$ohXwhX$khXyhX!OhX!]hX!_hX!ahX!chX!ehX!ghX|hX~P)aOT!vO!o!xO~Ow!zO~P#XO!VQO!jSO!rUO!uWO!zYO!}[O#W^O~P#XOi#[OomOp#]Oq#]O!o#^O#]#SO#a#VO#v#XO#x#YO#z#[O#{#[O#|#[O#}#[O$O#[O$P#[O$R#ZO$U#^O$V#^O~OT!dOc!cO!V!mX!j!mX!r!mX!u!mX!z!mX!}!mX#W!mX$b!mX$l!mX$o!mX$k!mX~P-WO$l#dO!V!ha!j!ha!r!ha!u!ha!z!ha!}!ha#W!ha$b!ha$o!ha$k!ha~O$e#gO~O$e#hO~O$e#iO~OT!vO~O!V!pa!j!pa!r!pa!u!pa!z!pa!}!pa#W!pa$b!pa$o!pa$k!pa~P-WO!V!xa!j!xa!r!xa!u!xa!z!xa!}!xa#W!xa$b!xa$o!xa$k!xa~P-WOT#kO#P#kO~O#Y#mO!V#Ua!j#Ua!r#Ua!u#Ua!z#Ua!}#Ua#W#Ua$b#Ua$o#Ua$k#Ua~Oc!cO$e#oO~OT!dO~O$k#rO~O!V!Ti!j!Ti!r!Ti!u!Ti!z!Ti!}!Ti#W!Ti$b!Ti$o!Ti$k!Ti~P(XO$k#xO~P#XO$g!tOThachaihaohaphaqha!Vha!jha!oha!rha!uha!zha!}ha#Wha#]ha#aha#vha#xha#zha#{ha#|ha#}ha$Oha$Pha$Rha$Uha$Vha$bha$lha$ohawha$khayha!Oha!]ha!_ha!aha!cha!eha!gha|ha_haahatha!Rha#Pha#cha#dha#gha#iha#kha#nha#qha$eha~Ow!zO|#|O!O$OO~Ow!zO~P-WO$k$SO~P-WO$e$UO~O#]#SO$R#ZO~OomO#c{O~O!V!hi!j!hi!r!hi!u!hi!z!hi!}!hi#W!hi$b!hi$o!hi$k!hi~P|O$l$aO!V!hi!j!hi!r!hi!u!hi!z!hi!}!hi#W!hi$b!hi$o!hi$k!hi~O!ltO!o$gO$k$fO~P#XOT$iO#d$iO~O$l$kO!V!si!j!si!r!si!u!si!z!si!}!si#W!si$b!si$o!si$k!si~O#R$mO#T$nO!V#OX!j#OX!r#OX!u#OX!z#OX!}#OX#W#OX$b#OX$l#OX$o#OX$k#OX~O$l$pO!V!{i!j!{i!r!{i!u!{i!z!{i!}!{i#W!{i$b!{i$o!{i$k!{i~O#P$rO~OT$sO_$tOa$uOomOpnOqnOtpO!RrO#P!QO#c{O#d!QO#g|O#i}O#k!VO#n!RO#q!TO$esO~O$e%QO~Of%RO!V!Za!]!Za!_!Za!a!Za!c!Za!e!Za!g!Za!j!Za!r!Za!u!Za!z!Za!}!Za#W!Za$b!Za$o!Za$k!Za~O$k%WO$l%UO~P-WO$g!tO~Oy%XO~P-WO$e%`O~Oi#[OomOp#]Oq#]O!o#^O#]#SO#z#[O#{#[O#|#[O#}#[O$O#[O$P#[O$R#ZO$U#^O$V#^OTkicki!Vki!jki!rki!uki!zki!}ki#Wki#aki#vki$bki$lki$okiwki$kkiyki!Oki!]ki!_ki!aki!cki!eki!gki|ki~O#x#YO~P@_O#xki~P@_O!o#^O$U#^O$V#^OTkickiikioki!Vki!jki!rki!uki!zki!}ki#Wki#]ki#aki#vki#xki#zki#{ki#|ki#}ki$Oki$Pki$Rki$bki$lki$okiwki$kkiyki!Oki!]ki!_ki!aki!cki!eki!gki|ki~Op#]Oq#]O~PC]Opkiqki~PC]O!V!hq!j!hq!r!hq!u!hq!z!hq!}!hq#W!hq$b!hq$o!hq$k!hq~P|O$l%cO!V!hq!j!hq!r!hq!u!hq!z!hq!}!hq#W!hq$b!hq$o!hq$k!hq~O$k%dO~O$k%eO~P-WO$k%eO~O!VQO~O!V!sq!j!sq!r!sq!u!sq!z!sq!}!sq#W!sq$b!sq$o!sq$k!sq~P|O$l%hO!V!sq!j!sq!r!sq!u!sq!z!sq!}!sq#W!sq$b!sq$o!sq$k!sq~O!V!{q!j!{q!r!{q!u!{q!z!{q!}!{q#W!{q$b!{q$o!{q$k!{q~OT#kO#P#kO~PItO$l%jO~PItOT%lO~P)aOT%nO~Oi$iXo$iXp$iXq$iX!o$iX#]$iX#a$iX#v$iX#x$iX#z$iX#{$iX#|$iX#}$iX$O$iX$P$iX$R$iX$U$iX$V$iX~Oc$hX~PKTOc$nX~PKTOc!cO~O$l%pOT$YX_$YXa$YXo$YXp$YXq$YXt$YX!R$YX#P$YX#c$YX#d$YX#g$YX#i$YX#k$YX#n$YX#q$YX$e$YX$k$YX~O$k%rO~P=_Of%RO!V!Zi!]!Zi!_!Zi!a!Zi!c!Zi!e!Zi!g!Zi!j!Zi!r!Zi!u!Zi!z!Zi!}!Zi#W!Zi$b!Zi$o!Zi$k!Zi~O$k%wO~P#XO$k%wO$l%xO~O!Oza~P-WO$l%|O$k#^X~P-WO$k&OO~O!V!hy!j!hy!r!hy!u!hy!z!hy!}!hy#W!hy$b!hy$o!hy$k!hy~P|O$k&QO~P-WO!V!sy!j!sy!r!sy!u!sy!z!sy!}!sy#W!sy$b!sy$o!sy$k!sy~P|OT#kO#P#kO!V!{y!j!{y!r!{y!u!{y!z!{y!}!{y#W!{y$b!{y$o!{y$k!{y~OZ&TOTVa_VaaVaoVapVaqVatVa!RVa#PVa#cVa#dVa#gVa#iVa#kVa#nVa#qVa$eVa$kVa$lVa~Oc!cOf%RO~O$k&ZO~O!V!Zq!]!Zq!_!Zq!a!Zq!c!Zq!e!Zq!g!Zq!j!Zq!r!Zq!u!Zq!z!Zq!}!Zq#W!Zq$b!Zq$o!Zq$k!Zq~P-WO$k$aa$l$aa~P-WO$k&]O~P#XOwuq|uq!Ouq~P-WO$k#^a~P#XO$l&_O$k#^a~O$k&`O~O$k&aO~P-WOT&bO~O!V!Zy!]!Zy!_!Zy!a!Zy!c!Zy!e!Zy!g!Zy!j!Zy!r!Zy!u!Zy!z!Zy!}!Zy#W!Zy$b!Zy$o!Zy$k!Zy~P-WO$k#^i~P#XO$g!tOihXThX_hXahXohXphXqhXthX!RhX#PhX#chX#dhX#ghX#ihX#khX#nhX#qhX$ehX$khX$lhX~Oi&fO~OP$U!op~",
1017
+ goto: "@[$oPPP$p$tPP$x$|%P%SP$x%V%ZP%ZP%_P%q&ZP&g&mP$x'o'o(j)cPPP'o*tP+m+sP+yP+|,SP,WP'o,bP-Z-o-zP.Y.Y._/]/aP/aP/aP/aP/aP/eP-o/lP/wP/}0`P-o0kP-o0vP1RP-o1XP-o1dP1oP1wP1wP-o1zP2VP'o2YP2r.d2xP3]PP4[5TP5TP4[P5|6wP.d7pP8i5|.d8lP9PP9ePPPPPP9zP:d:zPP$p;c;i;o<q<{=Y=`=n=tPPPP>OP>S>W?}PP5|@WTcOdTbOdT$}#o%PR%m$sR&V%mR&U%mT$w#o%PT$v#o%PQ!ffQ!ihQ#RvQ#p!`Q%o$|R&X%nQ!efQ!hhQ#QvQ#q!fQ#s!iQ$T#RQ&Y%oR&e&XQ%S#tQ%u%TQ&W%nR&g&eQ&d&WR&i&g!h!VTVZoqsy!Z!u!{#_#`#a#b#c#d#h#}$U$a$h$k%S%U%Y%`%b%c%g%h%u%x%|&^&_S$z#o%PS&c&W&gR&h&f!h!VTVZoqsy!Z!u!{#_#`#a#b#c#d#h#}$U$a$h$k%S%U%Y%`%b%c%g%h%u%x%|&^&_T$y#o%P!moTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_!lnTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_v#Uv!X![#O#P#w#z$Z$[$e$x%Z%^%f%t%v%z&R&[R$Y#W!mqTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_X!|q!}#O$RX!{q!}#O$RR%Y#zQ$Q!}R%]$RT#}!}$RQ$P!}S%[$Q$RR%{%]!mzTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_SeOdS!ggsQ$d#gQ%_$UQ%s%QR&P%`c`Oadgs#g$U%Q%`bROadgs#g$U%Q%`R%g$jViR!p#uUhR!p#u!m!VTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_T!rj!sT!qj!sS!pj!sR#u!qcTOadgs#g$U%Q%`QyTR$h#hQxTQ#fyQ#j!Z]$`#d$a$k%b%c%hcwTy!Z#d$a$k%b%c%hcVOadgs#g$U%Q%`cXOadgs#g$U%Q%`Q!ZXR!]]cZOadgs#g$U%Q%`c]Oadgs#g$U%Q%`Q#l!]V%i$p%j&SR$o#kc_Oadgs#g$U%Q%`R#n!^v#Tv!X![#O#P#w#z$Z$[$e$x%Z%^%f%t%v%z&R&[R$V#UQ%_$UR&P%`s#Wv!X![#O#P#w#z$e$x%Z%^%f%t%v%z&R&[!l!PTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_Q$X#WR%a$Y!m!QTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_!m!OTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_!h!VTVZoqsy!Z!u!{#_#`#a#b#c#d#h#}$U$a$h$k%S%U%Y%`%b%c%g%h%u%x%|&^&_T$z#o%P!m!STVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_!m!UTVZoqsy!Z!u!{#_#`#a#b#c#d#h#o#}$U$a$h$k%P%S%U%Y%`%b%c%g%h%u%x%|&^&_R$j#is#_v!X![#O#P#w#z$e$x%Z%^%f%t%v%z&R&[u#`v!X![#O#P#w#z$Z$e$x%Z%^%f%t%v%z&R&[w#av!X![#O#P#w#z$Z$[$e$x%Z%^%f%t%v%z&R&[v#[v!X![#O#P#w#z$Z$[$e$x%Z%^%f%t%v%z&R&[R$W#Uy#bv!X![#O#P#w#z$Z$[$]$e$x%Z%^%f%t%v%z&R&[{#cv!X![#O#P#w#z$Z$[$]$^$e$x%Z%^%f%t%v%z&R&[QdOR!bdQ%P#oR%q%PblTy!Z#d$a$k%b%c%h!`!WVZoqs!u!{#_#`#a#b#c#h#o#}$U$h%P%S%U%Y%`%g%u%x%|&W&^&_&f&gT!wl!WQ!}qS#{!}$RR$R#O`aOdgs#g$U%Q%`R!_aQ!sjR#v!sQ#exU$b#e$c$lQ$c#fR$l#jQ$q#lR%k$qQ%V#wS%y%V%}R%}%^T%O#o%PT$|#o%PbvTy!Z#d$a$k%b%c%hQ!XVQ![ZQ!yoQ#OqQ#PsQ#w!uQ#z!{Q$Z#_Q$[#`Q$]#aQ$^#bQ$_#cQ$e#hS$x#o%PQ%Z#}S%^$U%`Q%f$hQ%t%SY%v%U%x%|&^&_Q%z%YQ&R%gR&[%uQjRQ#t!pR%T#uT${#o%P",
1018
+ nodeNames: "\u26A0 Comment Program TableStatement Kw Identifier table ColumnDef DataType PrimaryKey Kw primary_key JoinDef JoinType Kw join_one Kw join_many Kw as Alias Kw on BinaryExpression Ref = ComputedDef BinaryExpression UnaryExpression UnaryOperator Kw not - + CaseExpression Kw case WhenClause Kw when Kw then ElseClause Kw else Kw end ExistsExpression Kw exists QueryStatement FromClause Kw from TableName Subquery SubqueryExpression JoinClause Kw inner Kw left Kw right Kw full Kw cross Kw join SelectClause Kw select Kw distinct SelectItem Wildcard * WhereClause Kw where GroupByClause Kw group Kw by HavingClause Kw having OrderByClause Kw order OrderItem Number Kw asc Kw desc LimitClause Kw limit Kw offset InExpression Kw in InValueList NullTestExpression Kw is Kw null String Boolean Kw true Kw false Null Param Count Kw count ExtractExpression Kw extract ExtractUnit FunctionCall Parenthetical Kw or Kw and ComparisonOp != <> < > <= >= Kw like AddOp MulOp / % ViewStatement",
1019
+ maxTerm: 169,
1020
+ nodeProps: [
1021
+ ["group", -6, 23, 56, 107, 119, 123, 128, "Expression", -12, 24, 27, 28, 34, 47, 93, 103, 112, 113, 118, 120, 127, "Expression Expression", -2, 54, 55, "TablePrimary"]
1022
+ ],
1023
+ skippedNodes: [0, 1],
1024
+ repeatNodeCount: 9,
1025
+ tokenData: "*g~RnX^#Ppq#Pqr#trs$Ptu$nuv%`wx%exy%}yz&Sz{&X{|&^|}&c}!O&h!O!P'X!P!Q'^!Q![(m!]!^)W!^!_)]!_!`)r!`!a)w!c!}*U#T#o*U#y#z#P$f$g#P#BY#BZ#P$IS$I_#P$I|$JO#P$JT$JU#P$KV$KW#P&FU&FV#P~#UY$d~X^#Ppq#P#y#z#P$f$g#P#BY#BZ#P$IS$I_#P$I|$JO#P$JT$JU#P$KV$KW#P&FU&FV#P~#wP!_!`#z~$PO#z~~$STOr$Prs$cs;'S$P;'S;=`$h<%lO$P~$hO#d~~$kP;=`<%l$P~$qS!Q![$}!c!}$}#R#S$}#T#o$}~%SS#k~!Q![$}!c!}$}#R#S$}#T#o$}~%eO$V~~%hTOw%ewx$cx;'S%e;'S;=`%w<%lO%e~%zP;=`<%l%e~&SO$e~~&XO$k~~&^O!o~~&cOq~~&hO$l~~&mPp~}!O&p~&uSP~OY&pZ;'S&p;'S;=`'R<%lO&p~'UP;=`<%l&p~'^O$g~~'cP$U~z{'f~'iTOz'fz{'x{;'S'f;'S;=`(g<%lO'f~'{VOz'fz{'x{!P'f!P!Q(b!Q;'S'f;'S;=`(g<%lO'f~(gOP~~(jP;=`<%l'f~(rQ#P~!O!P(x!Q![(m~({P!Q![)O~)TP#P~!Q![)O~)]O$o~~)bQ#|~!_!`)h!`!a)m~)mO$O~~)rO#{~~)wOi~~)|P#}~!_!`*P~*UO$P~~*ZST~!Q![*U!c!}*U#R#S*U#T#o*U",
1026
+ tokenizers: [0],
1027
+ topRules: { "Program": [0, 2] },
1028
+ specialized: [{ term: 5, get: (value, stack) => specializeIdentifier(value, stack) << 1, external: specializeIdentifier }, { term: 5, get: (value) => spec_Identifier[value] || -1 }],
1029
+ tokenPrec: 2599
1030
+ });
1031
+ }
1032
+ });
1033
+
1034
+ // ../lang/markdown.ts
1035
+ function parseMarkdown(fi) {
1036
+ let source = fi.contents;
1037
+ let fences = collectFences(source);
1038
+ let components = collectComponents(source, fences);
1039
+ let events = [...fences, ...components].sort((a, b) => a.start - b.start);
1040
+ let virtual = [];
1041
+ let mapping = [];
1042
+ let cursor = 0;
1043
+ let lastMapped = -1;
1044
+ let maxOffset = source.length;
1045
+ let push = (ch, target) => {
1046
+ let mapped = target;
1047
+ if (mapped <= lastMapped) mapped = lastMapped + 1;
1048
+ if (mapped > maxOffset) mapped = maxOffset;
1049
+ virtual.push(ch);
1050
+ mapping.push(mapped);
1051
+ lastMapped = mapped;
1052
+ };
1053
+ let resetLast = (value) => {
1054
+ lastMapped = value;
1055
+ };
1056
+ let appendWhitespace = (start, end) => {
1057
+ resetLast(start - 1);
1058
+ for (let i = start; i < end; i++) {
1059
+ let ch = source[i];
1060
+ push(ch === "\n" || ch === "\r" ? ch : " ", i);
1061
+ }
1062
+ };
1063
+ let appendMapped = (text, mapFn, options) => {
1064
+ if (options?.reset !== void 0) resetLast(options.reset);
1065
+ for (let i = 0; i < text.length; i++) {
1066
+ push(text[i], mapFn(i));
1067
+ }
1068
+ };
1069
+ let appendContent = (text, contentStart) => {
1070
+ resetLast(contentStart - 1);
1071
+ for (let i = 0; i < text.length; i++) {
1072
+ let target = contentStart + i;
1073
+ virtual.push(text[i]);
1074
+ mapping.push(target);
1075
+ lastMapped = target;
1076
+ }
1077
+ };
1078
+ for (let event of events) {
1079
+ if (event.start < cursor) continue;
1080
+ appendWhitespace(cursor, event.start);
1081
+ cursor = event.start;
1082
+ if (isFence(event)) {
1083
+ let fence = event;
1084
+ let contentStart = fence.contentStart;
1085
+ let content = fence.content;
1086
+ if (fence.name) {
1087
+ appendMapped(`table ${fence.name} as (
1088
+ `, () => contentStart, { reset: contentStart - 1 });
1089
+ appendContent(content, contentStart);
1090
+ if (!content.endsWith("\n")) appendMapped("\n", () => contentStart + content.length, { reset: contentStart + content.length - 1 });
1091
+ appendMapped(")\n", () => fence.end - 1, { reset: fence.end - 2 });
1092
+ } else {
1093
+ appendContent(content, contentStart);
1094
+ }
1095
+ cursor = fence.end;
1096
+ continue;
1097
+ }
1098
+ let component = event;
1099
+ let { data, attributes } = component;
1100
+ let hasComponentAttribute = COMPONENT_ATTRIBUTE_KEYS.some((key) => attributes[key] !== void 0);
1101
+ if (data && hasComponentAttribute) {
1102
+ appendMapped("from ", () => component.start, { reset: component.start - 1 });
1103
+ appendMapped(data.value, (i) => data.start + i, { reset: data.start - 1 });
1104
+ appendMapped(" select ", () => component.start);
1105
+ let previousAttr = null;
1106
+ for (let key of COMPONENT_ATTRIBUTE_KEYS) {
1107
+ let attribute = attributes[key];
1108
+ if (!attribute) continue;
1109
+ if (previousAttr) {
1110
+ let prevEnd = previousAttr.start + previousAttr.value.length;
1111
+ appendMapped(", ", () => prevEnd);
1112
+ }
1113
+ appendMapped(attribute.value, (i) => attribute.start + i, { reset: attribute.start - 1 });
1114
+ previousAttr = attribute;
1115
+ }
1116
+ let lastAttr = previousAttr;
1117
+ let selectEnd = lastAttr ? lastAttr.start + lastAttr.value.length : data.start + data.value.length;
1118
+ let resetPoint = lastAttr ? lastAttr.start + lastAttr.value.length - 1 : data.start + data.value.length - 1;
1119
+ appendMapped(";\n", (i) => {
1120
+ if (i === 0) return selectEnd;
1121
+ return component.end;
1122
+ }, { reset: resetPoint });
1123
+ }
1124
+ cursor = component.end;
1125
+ }
1126
+ appendWhitespace(cursor, source.length);
1127
+ let doc = virtual.join("");
1128
+ fi.virtualContents = doc;
1129
+ fi.virtualToMarkdownOffset = [...mapping, source.length];
1130
+ return parser.parse(doc);
1131
+ }
1132
+ function collectFences(source) {
1133
+ let matches = [];
1134
+ GSQL_FENCE.lastIndex = 0;
1135
+ let match;
1136
+ while (match = GSQL_FENCE.exec(source)) {
1137
+ let start = match.index ?? 0;
1138
+ let full2 = match[0];
1139
+ let headerLength = full2.indexOf("\n");
1140
+ if (headerLength === -1) continue;
1141
+ headerLength += 1;
1142
+ let content = match[3] || "";
1143
+ let contentStart = start + headerLength;
1144
+ let name = extractFenceName(full2.slice(0, headerLength));
1145
+ matches.push({ start, end: start + full2.length, headerLength, contentStart, content, name });
1146
+ }
1147
+ return matches;
1148
+ }
1149
+ function collectComponents(source, fences) {
1150
+ let matches = [];
1151
+ COMPONENT_TAG.lastIndex = 0;
1152
+ let match;
1153
+ while (match = COMPONENT_TAG.exec(source)) {
1154
+ let start = match.index ?? 0;
1155
+ let end = start + match[0].length;
1156
+ if (isInsideFence(start, fences)) continue;
1157
+ let attrs = extractAttributes(match[0], start);
1158
+ let attributeMatches = {};
1159
+ for (let key of COMPONENT_ATTRIBUTE_KEYS) {
1160
+ if (attrs[key]) attributeMatches[key] = attrs[key];
1161
+ }
1162
+ matches.push({ start, end, data: attrs.data || null, attributes: attributeMatches });
1163
+ }
1164
+ return matches;
1165
+ }
1166
+ function extractFenceName(header) {
1167
+ let parts = header.trim().split(/\s+/);
1168
+ if (parts.length > 1) return parts[1];
1169
+ return void 0;
1170
+ }
1171
+ function extractAttributes(fragment, baseStart) {
1172
+ let attrs = {};
1173
+ ATTRIBUTE.lastIndex = 0;
1174
+ let match;
1175
+ while (match = ATTRIBUTE.exec(fragment)) {
1176
+ let key = match[1];
1177
+ let value = match[2];
1178
+ let valueStart = baseStart + match.index + key.length + 2;
1179
+ attrs[key] = { value, start: valueStart };
1180
+ }
1181
+ return attrs;
1182
+ }
1183
+ function isInsideFence(offset2, fences) {
1184
+ return fences.some((f) => offset2 >= f.start && offset2 < f.end);
1185
+ }
1186
+ function isFence(event) {
1187
+ return event.content !== void 0;
1188
+ }
1189
+ var COMPONENT_ATTRIBUTE_KEYS, GSQL_FENCE, COMPONENT_TAG, ATTRIBUTE;
1190
+ var init_markdown = __esm({
1191
+ "../lang/markdown.ts"() {
1192
+ init_parser();
1193
+ COMPONENT_ATTRIBUTE_KEYS = ["x", "y", "y2", "series", "value", "category"];
1194
+ GSQL_FENCE = /^([ \t]*)(`{3,})g?sql[^\n]*\n([\s\S]*?)^\1\2[ \t]*$/gim;
1195
+ COMPONENT_TAG = /<([A-Z][A-Za-z0-9]*)\s+[^>]*\/>/g;
1196
+ ATTRIBUTE = /(\w+)="([^"]*)"/g;
1197
+ }
1198
+ });
1199
+
1200
+ // ../lang/core.ts
1201
+ import { registerDialect, StandardSQLDialect, QueryModel, expandBlueprintMap } from "@graphenedata/malloy";
1202
+ import { readFile } from "node:fs/promises";
1203
+ import { glob } from "glob";
1204
+ import path2 from "node:path";
1205
+ function getFile2(name) {
1206
+ return FILE_MAP[name];
1207
+ }
1208
+ function getDiagnostics() {
1209
+ return diagnostics;
1210
+ }
1211
+ async function loadWorkspace(dir, includeMd) {
1212
+ let files = await glob(includeMd ? "**/*.{gsql,md}" : "**/*.gsql", { cwd: dir, ignore: ["node_modules/**"] });
1213
+ for await (let file of files) {
1214
+ let contents = await readFile(path2.join(dir, file), "utf-8");
1215
+ updateFile(contents, file);
1216
+ }
1217
+ }
1218
+ function updateFile(contents, path9) {
1219
+ FILE_MAP[path9] ||= { path: path9, contents, tree: null, tables: [], queries: [] };
1220
+ FILE_MAP[path9].contents = contents;
1221
+ FILE_MAP[path9].tree = null;
1222
+ return FILE_MAP[path9];
1223
+ }
1224
+ function analyze(contents, type) {
1225
+ clearDiagnostics();
1226
+ delete FILE_MAP["input"];
1227
+ if (contents) updateFile(contents, "input");
1228
+ Object.values(FILE_MAP).forEach((fi) => {
1229
+ let isMd = fi.path.endsWith(".md") || fi.path == "input" && type == "md";
1230
+ fi.tree ||= isMd ? parseMarkdown(fi) : parser.parse(fi.contents);
1231
+ fi.tree.fileInfo = fi;
1232
+ recordSyntaxErrors(fi);
1233
+ findTables(fi);
1234
+ });
1235
+ Object.values(FILE_MAP).flatMap((f) => f.tables).forEach(analyzeTable);
1236
+ if (contents) {
1237
+ let fi = FILE_MAP["input"];
1238
+ let nodes = fi.tree.topNode.getChildren("QueryStatement") || [];
1239
+ fi.queries = nodes.map(analyzeQuery).filter((q) => !!q);
1240
+ return fi.queries;
1241
+ } else {
1242
+ return [];
1243
+ }
1244
+ }
1245
+ function toSql(query, params = {}) {
1246
+ let contents = {};
1247
+ let gsqlTables = Object.values(FILE_MAP).filter((f) => f.path !== "input").flatMap((f) => f.tables);
1248
+ gsqlTables.forEach((t) => contents[t.name] = t);
1249
+ let inputTables = [...FILE_MAP["input"]?.tables || [], ...query.subQuerySources];
1250
+ inputTables.forEach((t) => contents[t.name] = { ...t, query: t.query && fillInParams(t.query, params) });
1251
+ let malloyQuery = fillInParams(query.malloyQuery, params);
1252
+ let qm = new QueryModel({
1253
+ name: "generated_model",
1254
+ contents,
1255
+ queryList: [],
1256
+ dependencies: {},
1257
+ exports: []
1258
+ });
1259
+ return qm.compileQuery(malloyQuery).sql;
1260
+ }
1261
+ var BigQueryDialect;
1262
+ var init_core = __esm({
1263
+ "../lang/core.ts"() {
1264
+ init_analyze();
1265
+ init_params();
1266
+ init_util();
1267
+ init_config();
1268
+ init_functions();
1269
+ init_parser();
1270
+ init_markdown();
1271
+ BigQueryDialect = class extends StandardSQLDialect {
1272
+ constructor() {
1273
+ super();
1274
+ this.name = "bigquery";
1275
+ }
1276
+ getDialectFunctions() {
1277
+ return expandBlueprintMap(BIGQUERY_DIALECT_FUNCTIONS);
1278
+ }
1279
+ };
1280
+ registerDialect(new BigQueryDialect());
1281
+ }
1282
+ });
1283
+
1284
+ // connections/bigQuery.ts
1285
+ var bigQuery_exports = {};
1286
+ __export(bigQuery_exports, {
1287
+ BigQueryConnection: () => BigQueryConnection
1288
+ });
1289
+ import fs3 from "fs";
1290
+ import path4 from "path";
1291
+ import { BigQuery, BigQueryDate, BigQueryTimestamp } from "@google-cloud/bigquery";
1292
+ var BigQueryConnection;
1293
+ var init_bigQuery = __esm({
1294
+ "connections/bigQuery.ts"() {
1295
+ init_config();
1296
+ BigQueryConnection = class {
1297
+ client;
1298
+ constructor(options = {}) {
1299
+ if (process.env.GOOGLE_CREDENTIALS_CONTENT) {
1300
+ let parsed = JSON.parse(process.env.GOOGLE_CREDENTIALS_CONTENT);
1301
+ let credPath = path4.resolve("./bq.json");
1302
+ fs3.writeFileSync("./bq.json", process.env.GOOGLE_CREDENTIALS_CONTENT.replace(" ", "\n "));
1303
+ process.env.GOOGLE_APPLICATION_CREDENTIALS = credPath;
1304
+ options.projectId = parsed.project_id;
1305
+ }
1306
+ options.projectId ||= config.googleProjectId;
1307
+ options.maxRetries ||= 3;
1308
+ options.userAgent ||= "Graphene";
1309
+ if (!options.projectId) throw new Error("googleProjectId must be set in config or provided in service account credentials");
1310
+ this.client = new BigQuery(options);
1311
+ }
1312
+ async runQuery(sql) {
1313
+ let [job] = await this.client.createQueryJob({ query: sql, useLegacySql: false });
1314
+ let [rows] = await job.getQueryResults({ maxResults: 1e4 });
1315
+ let metadata = job.metadata || (await job.getMetadata())[0];
1316
+ let totalRows = Number(metadata?.statistics?.query?.totalRows ?? rows.length);
1317
+ rows.forEach((r) => {
1318
+ Object.entries(r).forEach(([k, v]) => {
1319
+ if (v instanceof BigQueryTimestamp) r[k] = v.value;
1320
+ if (v instanceof BigQueryDate) r[k] = v.value;
1321
+ });
1322
+ });
1323
+ return { rows, totalRows };
1324
+ }
1325
+ };
1326
+ }
1327
+ });
1328
+
1329
+ // connections/duckdb.ts
1330
+ var duckdb_exports = {};
1331
+ __export(duckdb_exports, {
1332
+ DuckDBConnection: () => DuckDBConnection
1333
+ });
1334
+ import { promises as fs4 } from "fs";
1335
+ import path5 from "path";
1336
+ import { DuckDBTimestampValue, DuckDBInstance, DuckDBDateValue } from "@duckdb/node-api";
1337
+ var DuckDBConnection;
1338
+ var init_duckdb = __esm({
1339
+ "connections/duckdb.ts"() {
1340
+ init_config();
1341
+ DuckDBConnection = class {
1342
+ ready;
1343
+ connection = null;
1344
+ constructor() {
1345
+ this.ready = this.initialize();
1346
+ }
1347
+ async initialize() {
1348
+ let files = await fs4.readdir(config.root);
1349
+ let databasePath = files.find((f) => f.endsWith(".duckdb"));
1350
+ if (!databasePath) throw new Error("No .duckdb file found in current directory");
1351
+ databasePath = path5.resolve(config.root, databasePath);
1352
+ let db = await DuckDBInstance.create(":memory:");
1353
+ this.connection = await db.connect();
1354
+ let escapedPath = databasePath.replace(/'/g, "''");
1355
+ await this.connection.run(`attach '${escapedPath}' as graphene_cli (READ_ONLY);`);
1356
+ await this.connection.run("use graphene_cli;");
1357
+ }
1358
+ async runQuery(sql) {
1359
+ await this.ready;
1360
+ let reader = await this.connection.runAndReadAll(sql);
1361
+ let rows = reader.getRowObjects().map((record) => {
1362
+ let out = {};
1363
+ for (let [k, v] of Object.entries(record)) {
1364
+ if (typeof v === "bigint") out[k] = Number(v);
1365
+ else if (v === null) out[k] = null;
1366
+ else if (v instanceof DuckDBTimestampValue) out[k] = new Date(Number(v.micros / 1000n)).toUTCString();
1367
+ else if (v instanceof DuckDBDateValue) out[k] = v.toString();
1368
+ else if (typeof v === "object") throw new Error(`Unsupported datatype ${v.constructor?.name}`);
1369
+ else out[k] = v;
1370
+ }
1371
+ return out;
1372
+ });
1373
+ return { rows };
1374
+ }
1375
+ };
1376
+ }
1377
+ });
1378
+
1379
+ // connections/index.ts
1380
+ async function getConnection() {
1381
+ if (config.dialect === "bigquery") {
1382
+ let mod = await Promise.resolve().then(() => (init_bigQuery(), bigQuery_exports));
1383
+ return new mod.BigQueryConnection();
1384
+ } else if (config.dialect === "duckdb") {
1385
+ let mod = await Promise.resolve().then(() => (init_duckdb(), duckdb_exports));
1386
+ return new mod.DuckDBConnection();
1387
+ } else {
1388
+ throw new Error(`Unsupported dialect: ${config.dialect}`);
1389
+ }
1390
+ }
1391
+ var init_connections = __esm({
1392
+ "connections/index.ts"() {
1393
+ init_config();
1394
+ }
1395
+ });
1396
+
1397
+ // mdCompile.ts
1398
+ import fs5 from "fs";
1399
+ import path6 from "path";
1400
+ import { visit } from "unist-util-visit";
1401
+ import sanitizeHtml from "sanitize-html";
1402
+ function extractQueries() {
1403
+ function escapeHtml(str) {
1404
+ return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
1405
+ }
1406
+ return function transformer(tree) {
1407
+ visit(tree, "code", (node, index, parent) => {
1408
+ if (index === null) return;
1409
+ let name = typeof node.meta === "string" ? node.meta : "";
1410
+ let code = typeof node.value === "string" ? node.value.trim() : "";
1411
+ parent.children[index] = { type: "html", value: `<GrapheneQuery name="${escapeHtml(name)}" code="${escapeHtml(code)}" />` };
1412
+ });
1413
+ };
1414
+ }
1415
+ function escapeAngles() {
1416
+ return function transformer(tree) {
1417
+ visit(tree, "text", (node) => {
1418
+ if (!node.value || typeof node.value !== "string") return;
1419
+ if (!node.value.includes("<")) return;
1420
+ node.value = node.value.replace(/</g, "&lt;");
1421
+ });
1422
+ };
1423
+ }
1424
+ function sanitizeMarkdown() {
1425
+ return function transformer(tree) {
1426
+ visit(tree, "raw", (node) => {
1427
+ if (typeof node.value !== "string") return;
1428
+ let expanded = node.value.replace(/<(\w+)((?:\s[^<>]*?)?)\s*\/>/gi, (_, name, attrs = "") => {
1429
+ let spacing = attrs;
1430
+ return `<${name}${spacing}></${name}>`;
1431
+ });
1432
+ let sanitized = sanitizeHtml(expanded, {
1433
+ ...sanitizeHtml.defaults,
1434
+ allowedTags: [
1435
+ ...sanitizeHtml.defaults.allowedTags,
1436
+ ...componentNames()
1437
+ ],
1438
+ allowedAttributes: {
1439
+ ...sanitizeHtml.defaults.allowedAttributes,
1440
+ ...Object.fromEntries(componentNames().map((n) => [n, ["*"]]))
1441
+ },
1442
+ parser: {
1443
+ ...sanitizeHtml.defaults.parser || {},
1444
+ lowerCaseAttributeNames: false,
1445
+ lowerCaseTags: false
1446
+ }
1447
+ });
1448
+ node.value = sanitized;
1449
+ });
1450
+ };
1451
+ }
1452
+ function injectComponentImports() {
1453
+ let imp = `const {${componentNames().join(", ")}} = window.$GRAPHENE.components`;
1454
+ return {
1455
+ markup: ({ content, filename }) => {
1456
+ if (!filename.endsWith(".md")) return;
1457
+ if (content.includes("<script>")) {
1458
+ content = content.replace("<script>", `<script>
1459
+ ${imp}`);
1460
+ } else {
1461
+ content = `<script>
1462
+ ${imp}
1463
+ </script>
1464
+ ${content}`;
1465
+ }
1466
+ return { code: content };
1467
+ },
1468
+ style: () => {
1469
+ },
1470
+ script: () => {
1471
+ }
1472
+ };
1473
+ }
1474
+ function componentNames() {
1475
+ if (cachedComponentNames) return cachedComponentNames;
1476
+ let files = fs5.readdirSync(path6.join(import.meta.dirname, "../ui/components"));
1477
+ cachedComponentNames = files.map((f) => path6.basename(f, ".svelte")).filter((f) => !f.startsWith("_"));
1478
+ return cachedComponentNames || [];
1479
+ }
1480
+ var cachedComponentNames;
1481
+ var init_mdCompile = __esm({
1482
+ "mdCompile.ts"() {
1483
+ cachedComponentNames = null;
1484
+ }
1485
+ });
1486
+
1487
+ // serve2.ts
1488
+ var serve2_exports = {};
1489
+ __export(serve2_exports, {
1490
+ mockFileMap: () => mockFileMap,
1491
+ serve2: () => serve2
1492
+ });
1493
+ import { createServer, optimizeDeps } from "vite";
1494
+ import { svelte, vitePreprocess } from "@sveltejs/vite-plugin-svelte";
1495
+ import fs6 from "fs-extra";
1496
+ import crypto from "crypto";
1497
+ import { mdsvex } from "mdsvex";
1498
+ import path7 from "path";
1499
+ import { fileURLToPath as fileURLToPath2 } from "url";
1500
+ import { WebSocketServer } from "ws";
1501
+ import { spawn as spawn2 } from "child_process";
1502
+ async function serve2() {
1503
+ grapheneRoot = config.root;
1504
+ uiRoot = path7.join(fileURLToPath2(import.meta.url), "../../ui");
1505
+ await fs6.ensureDir(path7.resolve(grapheneRoot, "node_modules/.graphene"));
1506
+ await fs6.writeFile(path7.resolve(grapheneRoot, `node_modules/.graphene/${process.env.NODE_ENV == "test" ? "test" : "serve"}.pid`), String(process.pid));
1507
+ let server = await createServer({
1508
+ root: config.root,
1509
+ plugins: [
1510
+ svelte({
1511
+ extensions: [".svelte", ".md"],
1512
+ preprocess: [
1513
+ vitePreprocess(),
1514
+ mdsvex({
1515
+ extensions: [".md"],
1516
+ remarkPlugins: [extractQueries, escapeAngles],
1517
+ rehypePlugins: [sanitizeMarkdown]
1518
+ }),
1519
+ injectComponentImports()
1520
+ ]
1521
+ }),
1522
+ handleRequestPlugin,
1523
+ updateWorkspacePlugin,
1524
+ mockFilesForTests()
1525
+ ],
1526
+ server: {
1527
+ port: config.port,
1528
+ fs: { strict: false },
1529
+ strictPort: true
1530
+ },
1531
+ resolve: {
1532
+ alias: {
1533
+ graphene: path7.resolve(uiRoot, "web.js")
1534
+ }
1535
+ }
1536
+ });
1537
+ await optimizeDeps(server.config);
1538
+ await server.listen();
1539
+ console.log(`Server running at http://localhost:${config.port}`);
1540
+ return server;
1541
+ }
1542
+ async function handleQuery(req, res) {
1543
+ let chunks = [];
1544
+ for await (let chunk of req) chunks.push(chunk);
1545
+ let { gsql, params, hashes } = JSON.parse(Buffer.concat(chunks).toString());
1546
+ res.setHeader("Content-Type", "application/json");
1547
+ await workspaceLoadPromise;
1548
+ let queries = analyze(gsql);
1549
+ if (getDiagnostics().length) {
1550
+ res.statusCode = 400;
1551
+ res.end(JSON.stringify(getDiagnostics()));
1552
+ return;
1553
+ }
1554
+ if (queries.length > 1) throw new Error("Found multiple queries, which could be a parsing error");
1555
+ let sql = toSql(queries[0], params);
1556
+ let hash = crypto.createHash("SHA1").update(sql).digest("hex");
1557
+ res.setHeader("ETag", hash);
1558
+ if (hashes.includes(hash) && req.headers["cache-control"] != "no-cache") {
1559
+ res.statusCode = 304;
1560
+ return res.end();
1561
+ }
1562
+ let connection = await getConnection();
1563
+ let queryResults = await connection.runQuery(sql);
1564
+ let totalRows = queryResults.totalRows ?? queryResults.rows.length;
1565
+ if (totalRows > queryResults.rows.length) throw new Error("Query returns too many rows");
1566
+ let fields = queries[0].fields.map((f) => ({ name: f.name, type: f.type }));
1567
+ res.end(JSON.stringify({ rows: queryResults.rows, hash, fields, sql }));
1568
+ }
1569
+ async function handleView(req, res) {
1570
+ let chunks = [];
1571
+ for await (let chunk of req) chunks.push(chunk);
1572
+ let { mdFile, chart } = JSON.parse(Buffer.concat(chunks).toString());
1573
+ let id = Math.random().toString(36).slice(2);
1574
+ res.setHeader("Content-Type", "application/json");
1575
+ viewRequests[id] = { response: res };
1576
+ let pageUrl = "/" + mdFile.replace(/\.md$/, "").replace(/^\//, "");
1577
+ if (pageUrl === "/index") pageUrl = "/";
1578
+ pageUrl = `http://localhost:${config.port || 4e3}${pageUrl}`;
1579
+ let conn = browserConnections.find((conn2) => conn2.url === pageUrl);
1580
+ if (!conn) {
1581
+ spawn2("open", [pageUrl]);
1582
+ let end = Date.now() + 5e3;
1583
+ while (Date.now() < end && !conn) {
1584
+ conn = browserConnections.find((conn2) => conn2.url === pageUrl);
1585
+ await new Promise((resolve) => setTimeout(resolve, 100));
1586
+ }
1587
+ if (!conn) {
1588
+ res.statusCode = 500;
1589
+ return res.end(JSON.stringify({ error: "No browser tab available and failed to open one" }));
1590
+ }
1591
+ }
1592
+ conn.socket.send(JSON.stringify({ type: "view", chart, requestId: id }));
1593
+ }
1594
+ async function handlePage(server, res, filePath, mount) {
1595
+ res.setHeader("Content-Type", "text/html");
1596
+ let mdMount = mount ? `
1597
+ import Page from ${JSON.stringify(filePath)};
1598
+ new Page({ target: document.getElementById('content'), props: {} })
1599
+ ` : "";
1600
+ let html = await server.transformIndexHtml(filePath, `<!doctype html>
16
1601
  <html lang="en">
17
1602
  <head>
18
1603
  <meta charset="UTF-8" />
@@ -24,20 +1609,350 @@ var Qt=Object.defineProperty;var E=(e,n)=>()=>(e&&(n=e(e=0)),n);var ae=(e,n)=>{f
24
1609
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet">
25
1610
  </head>
26
1611
  <body>
27
- <div id="app"></div>
1612
+ <main>
1613
+ <div id="content"></div>
1614
+ </main>
28
1615
  <script type="module">
29
1616
  // do this first so we can track errors caused by importing the md file
30
1617
  import 'graphene'
31
- // import '${K}/web.js'
32
- console.log('imported graphene')
33
1618
  </script>
34
1619
  <script type="module">
35
- console.log('starting mount')
36
- ${i}
1620
+ ${mdMount}
37
1621
  </script>
38
1622
  </body>
39
- </html>`);return n.end(a)}function cr(){function e(n){return n.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}return function(t){er(t,"code",(r,i,a)=>{i!==null&&(a.children[i]={type:"html",value:`<GrapheneQuery name="${e(r.meta)}" code="${e(r.value.trim())}" />`})})}}function pr(){let t=`const {${re.readdirSync(F.join(K,"components")).map(r=>F.basename(r,".svelte")).filter(r=>!r.startsWith("_")).join(", ")}} = window.$GRAPHENE.components`;return{markup:({content:r,filename:i})=>{if(i.endsWith(".md"))return r=r.replace("<script>",`<script>
40
- ${t}`),{code:r}},style:()=>{},script:()=>{}}}function dr(){return process.env.NODE_ENV!=="test"?null:{name:"mock-files-for-tests",enforce:"pre",resolveId(e){if(qe[e.replace(D,"")])return e+"?mock"},load(e){return e.endsWith("?mock")?qe[e.replace(D,"").replace(/\?mock$/,"")]:null}}}var D,K,ve,or,lr,B,Re,qe,gt=E(()=>{te();Xe();or={name:"updateWorkspace",configureServer:e=>{e.watcher.add("**/*.gsql"),e.watcher.on("change",()=>{ye(),ve=U(D,!1)}),ve=U(D,!1)}},lr={name:"handleRequest",configureServer:e=>{let n=new ir({noServer:!0});e.httpServer.on("upgrade",(t,r,i)=>{t.url?.endsWith("/graphene-ws")&&n.handleUpgrade(t,r,i,a=>{n.emit("connection",a,t)})}),n.on("connection",t=>{t.on("message",r=>{let i=JSON.parse(r.toString());i.type==="register"&&B.push({url:i.url,socket:t}),i.type==="viewResponse"&&(Re[i.requestId].response.end(JSON.stringify(i)),delete Re[i.requestId])}),t.on("close",()=>B=B.filter(r=>r.socket!==t))}),e.middlewares.use(async function(r,i,a){try{let[s]=(r.url||"").split("?");if(s=="/_api/query")return await ur(r,i);if(s=="/graphene/view")return await Or(r,i);if(s=="/__ct")return await ft(e,i,"__ct",!1);(!s||s=="/")&&(s="index");let o=F.join(D,s+".md");await re.exists(o)?await ft(e,i,o,!0):a()}catch(s){console.error(s),i.statusCode=500,i.end(JSON.stringify([{message:s.message,stack:s.stack}]))}})}};B=[],Re={};qe={}});import{Command as fr}from"commander";te();import{styleText as at}from"node:util";import Dn from"cli-table3";import we from"chalk";var st=(e,n)=>{try{return at?at(e,n):n}catch{return n}};function In(e,n){let t=e.split(/\r?\n/),r=0;for(let i=0;i<t.length;i++){let a=t[i],s=r+a.length+1;if(n<s||i===t.length-1){let o=Math.max(0,n-r);return{line:i+1,col:o,lineStart:r,lineText:a}}r=s}return{line:1,col:0,lineStart:0,lineText:t[0]||""}}function Te(e){let n=[];for(let t of e){let r=rt(t.file)?.contents||"",{line:i,col:a,lineStart:s,lineText:o}=In(r,t.from.offset),l=Math.max(a+1,Math.min(o.length,t.to.offset-s)),m=Math.max(1,l-a),d=t.severity==="error"?"red":"yellow",P=`${st(d,t.severity.toUpperCase())}: ${t.file} line ${i}: ${t.message}`,T=" | ",p=`${" ".repeat(a)}${st(d,"^".repeat(m))}`;n.push([P,`${T}${o}`,`${T}${p}`].join(`
41
- `))}n.length&&console.error(n.join(`
42
- `))}function ot(e){if(!e||e.length===0){console.log(we.yellow("No results returned"));return}let n=Object.keys(e[0]),t=new Dn({head:n.map(a=>we.blue(a))}),r=200;e.slice(0,r).forEach(a=>t.push(n.map(s=>a[s]?.toString()||""))),console.log(t.toString()),e.length>r&&console.log(we.yellow(`Displayed first ${r} rows (of ${e.length} total).`))}te();N();import _e from"fs-extra";import ht from"path";import mr from"os";import{spawn as Nn}from"child_process";import{fileURLToPath as Un}from"url";import v from"fs-extra";import Ee from"path";async function lt(){let e=process.cwd(),n=ut(e),t=Ee.join(n,"serve.log");await v.ensureDir(n),await xe(e);let r=v.openSync(t,"w"),i=process.argv[1]||Un(import.meta.url),a=[...process.execArgv,i,"serve","--fg",...process.argv.slice(3)],s=Nn(process.execPath,a,{cwd:e,detached:!0,env:{...process.env},stdio:["ignore",r,r]});if(!s.pid)throw new Error("Failed to start server process");await new Promise((o,l)=>{let m="";v.watchFile(t,{interval:200},(d,P)=>{d.size>P.size&&v.createReadStream(t,{start:0,end:d.size-1}).on("data",p=>{process.stdout.write(p),m=(m+p.toString()).slice(-200),m.includes("Server running at http://localhost:")&&o()})}),s.once("exit",()=>{process.stdout.write(v.readFileSync(t)),l(new Error("Exited before server started"))}),s.once("error",d=>l(d))})}function ut(e){return Ee.join(e,"node_modules",".graphene")}function An(e){return Ee.join(ut(e),process.env.NODE_ENV=="test"?"test.pid":"serve.pid")}async function xe(e){let n=An(e),t=await jn(n);if(!t)return!0;if(!ke(t))return await v.remove(n),!0;try{console.log(`Stopping server (${t})`),process.kill(t,"SIGTERM")}catch(i){return i.code==="ESRCH"}let r=Date.now()+5e3;for(;Date.now()<r&&ke(t);)await new Promise(i=>setTimeout(i,100));return await v.remove(n),!ke(t)}async function jn(e){if(!await v.pathExists(e))return;let n=(await v.readFile(e,"utf8")).trim();if(!n)return;let t=Number.parseInt(n,10);if(!Number.isNaN(t))return t}function ke(e){try{return process.kill(e,0),!0}catch{return!1}}Xe();var S=new fr;S.name("graphene").description("Graphene CLI").version("1.0.0");S.hook("preAction",async()=>{process.env.CLI_DELAY&&await new Promise(e=>setTimeout(e,1e3)),oe(process.cwd())});S.command("compile").description("Translate a query to SQL and print it").argument("[input]",'Path to file, a raw string, or "-" for stdin').action(async e=>{await U(process.cwd(),!1);let n=await yt(e),t=j(n);$t(t)&&console.log(Y(t[0]))});S.command("run").description("Run a query against your database").argument("[input]",'Path to file, a raw string, or "-" for stdin').action(async e=>{await U(process.cwd(),!1);let n=await yt(e),t=j(n);if(!$t(t))return;let r=Y(t[0]),a=await(await ne()).runQuery(r);ot(a.rows)});S.command("serve").description("Run the local server").option("--fg","Run the server in the foreground").action(async e=>{e.fg||process.env.DEBUG?await(await Promise.resolve().then(()=>(gt(),mt))).serve2():(await lt(),process.exit(0))});S.command("stop").description("Stop the local server").action(async()=>{await xe(process.cwd())});S.command("check").description("Check the project for errors").action(async()=>{await U(process.cwd(),!0),j(),_().length&&(Te(_()),process.exit(1)),console.log("No errors found \u{1F48E}")});S.command("view").description("Capture a screenshot of a rendered markdown file").argument("<mdFile>","Markdown file to view (e.g., index.md)").option("-c, --chart <chartName>","Name of specific chart to capture").action(async(e,n)=>{let t=await fetch("http://localhost:4000/graphene/view",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({mdFile:e,chart:n.chart})});if(!t.ok)throw new Error(`View request failed: ${await t.text()}`);let r=await t.json();if(r.errors&&r.errors.length>0&&(console.error("Errors found:"),r.errors.forEach(i=>console.error(JSON.stringify(i)))),r.stillLoading&&console.error("Warning: Queries were still loading when the screenshot was taken"),r.screenshot){let i=`graphene-screenshot-${new Date().toISOString().replace(/[:.]/g,"-")}.png`,a=ht.join(mr.tmpdir(),i),s=r.screenshot.replace(/^data:image\/png;base64,/,"");await _e.writeFile(a,s,"base64"),console.log("Screenshot saved to",a)}});process.env.GRAPHENE_DEBUG&&S.commands.find(n=>n._name==process.argv[2])._actionHandler;S.parse(process.argv);async function yt(e){if(!e||e==="-")return await new Promise(t=>{let r="";process.stdin.setEncoding("utf-8"),process.stdin.on("data",i=>r+=i),process.stdin.on("end",()=>t(r)),process.stdin.resume()});let n=ht.resolve(e);return _e.existsSync(n)?await _e.promises.readFile(n,"utf-8"):e}function $t(e){return _().length&&(Te(_()),process.exit(1)),e.length==0&&(console.warn("No queries found"),process.exit(1)),!0}
1623
+ </html>`);
1624
+ return res.end(html);
1625
+ }
1626
+ function mockFilesForTests() {
1627
+ if (process.env.NODE_ENV !== "test") return null;
1628
+ return {
1629
+ name: "mock-files-for-tests",
1630
+ enforce: "pre",
1631
+ resolveId(id) {
1632
+ if (mockFileMap[id.replace(grapheneRoot, "")]) return id + "?mock";
1633
+ },
1634
+ load(id) {
1635
+ if (!id.endsWith("?mock")) return null;
1636
+ return mockFileMap[id.replace(grapheneRoot, "").replace(/\?mock$/, "")];
1637
+ }
1638
+ };
1639
+ }
1640
+ var grapheneRoot, uiRoot, workspaceLoadPromise, updateWorkspacePlugin, handleRequestPlugin, browserConnections, viewRequests, mockFileMap;
1641
+ var init_serve2 = __esm({
1642
+ "serve2.ts"() {
1643
+ init_core();
1644
+ init_connections();
1645
+ init_mdCompile();
1646
+ updateWorkspacePlugin = {
1647
+ name: "updateWorkspace",
1648
+ configureServer: (s) => {
1649
+ s.watcher.add("**/*.gsql");
1650
+ s.watcher.on("change", () => {
1651
+ clearWorkspace();
1652
+ workspaceLoadPromise = loadWorkspace(grapheneRoot, false);
1653
+ });
1654
+ workspaceLoadPromise = loadWorkspace(grapheneRoot, false);
1655
+ }
1656
+ };
1657
+ handleRequestPlugin = {
1658
+ name: "handleRequest",
1659
+ configureServer: (s) => {
1660
+ let wss = new WebSocketServer({ noServer: true });
1661
+ s.httpServer.on("upgrade", (req, socket, head) => {
1662
+ if (!req.url?.endsWith("/graphene-ws")) return;
1663
+ wss.handleUpgrade(req, socket, head, (ws) => {
1664
+ wss.emit("connection", ws, req);
1665
+ });
1666
+ });
1667
+ wss.on("connection", (socket) => {
1668
+ socket.on("message", (data) => {
1669
+ let message = JSON.parse(data.toString());
1670
+ if (message.type === "register") {
1671
+ browserConnections.push({ url: message.url, socket });
1672
+ }
1673
+ if (message.type === "viewResponse") {
1674
+ viewRequests[message.requestId].response.end(JSON.stringify(message));
1675
+ delete viewRequests[message.requestId];
1676
+ }
1677
+ });
1678
+ socket.on("close", () => browserConnections = browserConnections.filter((conn) => conn.socket !== socket));
1679
+ });
1680
+ s.middlewares.use(async function handleRequest(req, res, next) {
1681
+ try {
1682
+ let [pathName] = (req.url || "").split("?");
1683
+ if (pathName == "/_api/query") return await handleQuery(req, res);
1684
+ if (pathName == "/graphene/view") return await handleView(req, res);
1685
+ if (pathName == "/__ct") return await handlePage(s, res, "__ct", false);
1686
+ if (!pathName || pathName == "/") pathName = "index";
1687
+ let mdPath = path7.join(grapheneRoot, pathName + ".md");
1688
+ if (await fs6.exists(mdPath)) {
1689
+ await handlePage(s, res, mdPath, true);
1690
+ } else {
1691
+ next();
1692
+ }
1693
+ } catch (err) {
1694
+ console.error(err);
1695
+ res.statusCode = 500;
1696
+ res.end(JSON.stringify([{ message: err.message, stack: err.stack }]));
1697
+ }
1698
+ });
1699
+ }
1700
+ };
1701
+ browserConnections = [];
1702
+ viewRequests = {};
1703
+ mockFileMap = {};
1704
+ }
1705
+ });
1706
+
1707
+ // cli.ts
1708
+ import { Command } from "commander";
1709
+
1710
+ // printer.ts
1711
+ init_core();
1712
+ import { styleText as nodeStyleText } from "node:util";
1713
+ import Table from "cli-table3";
1714
+ import chalk from "chalk";
1715
+ var styleText = (style, text) => {
1716
+ try {
1717
+ return nodeStyleText ? nodeStyleText(style, text) : text;
1718
+ } catch {
1719
+ return text;
1720
+ }
1721
+ };
1722
+ function offsetToLineCol(src, offset2) {
1723
+ let lines = src.split(/\r?\n/);
1724
+ let acc = 0;
1725
+ for (let i = 0; i < lines.length; i++) {
1726
+ let lineText = lines[i];
1727
+ let nextAcc = acc + lineText.length + 1;
1728
+ if (offset2 < nextAcc || i === lines.length - 1) {
1729
+ let col = Math.max(0, offset2 - acc);
1730
+ return { line: i + 1, col, lineStart: acc, lineText };
1731
+ }
1732
+ acc = nextAcc;
1733
+ }
1734
+ return { line: 1, col: 0, lineStart: 0, lineText: lines[0] || "" };
1735
+ }
1736
+ function printDiagnostics(diags) {
1737
+ let parts = [];
1738
+ for (let d of diags) {
1739
+ let src = getFile2(d.file)?.contents || "";
1740
+ let { line, col, lineStart, lineText } = offsetToLineCol(src, d.from.offset);
1741
+ let endCol = Math.max(col + 1, Math.min(lineText.length, d.to.offset - lineStart));
1742
+ let caretLen = Math.max(1, endCol - col);
1743
+ let sev = d.severity === "error" ? "red" : "yellow";
1744
+ let header = `${styleText(sev, d.severity.toUpperCase())}: ${d.file} line ${line}: ${d.message}`;
1745
+ let gutter = " | ";
1746
+ let caretLine = `${" ".repeat(col)}${styleText(sev, "^".repeat(caretLen))}`;
1747
+ parts.push([header, `${gutter}${lineText}`, `${gutter}${caretLine}`].join("\n"));
1748
+ }
1749
+ if (parts.length) console.error(parts.join("\n"));
1750
+ }
1751
+ function printTable(rows) {
1752
+ if (!rows || rows.length === 0) {
1753
+ console.log(chalk.yellow("No results returned"));
1754
+ return;
1755
+ }
1756
+ let headers = Object.keys(rows[0]);
1757
+ let table2 = new Table({ head: headers.map((h) => chalk.blue(h)) });
1758
+ let MAX_DISPLAY_ROWS = 200;
1759
+ let displayRows = rows.slice(0, MAX_DISPLAY_ROWS);
1760
+ displayRows.forEach((row) => table2.push(headers.map((h) => row[h]?.toString() || "")));
1761
+ console.log(table2.toString());
1762
+ if (rows.length > MAX_DISPLAY_ROWS) {
1763
+ console.log(chalk.yellow(`Displayed first ${MAX_DISPLAY_ROWS} rows (of ${rows.length} total).`));
1764
+ }
1765
+ }
1766
+
1767
+ // cli.ts
1768
+ init_core();
1769
+ init_config();
1770
+ import fs7 from "fs-extra";
1771
+ import path8 from "path";
1772
+ import os from "os";
1773
+
1774
+ // background.ts
1775
+ import { spawn } from "child_process";
1776
+ import { fileURLToPath } from "url";
1777
+ import fs2 from "fs-extra";
1778
+ import path3 from "path";
1779
+ async function runServeInBackground() {
1780
+ let root = process.cwd();
1781
+ let grapheneCache = getGrapheneCache(root);
1782
+ let logFile = path3.join(grapheneCache, "serve.log");
1783
+ await fs2.ensureDir(grapheneCache);
1784
+ await stopGrapheneIfRunning(root);
1785
+ let log = fs2.openSync(logFile, "w");
1786
+ let entryPoint = process.argv[1] || fileURLToPath(import.meta.url);
1787
+ let childArgs = [...process.execArgv, entryPoint, "serve", "--fg", ...process.argv.slice(3)];
1788
+ let child = spawn(process.execPath, childArgs, {
1789
+ cwd: root,
1790
+ detached: true,
1791
+ env: { ...process.env },
1792
+ stdio: ["ignore", log, log]
1793
+ });
1794
+ if (!child.pid) throw new Error("Failed to start server process");
1795
+ await new Promise((resolve, reject) => {
1796
+ let buffer = "";
1797
+ fs2.watchFile(logFile, { interval: 200 }, (curr, prev) => {
1798
+ if (curr.size > prev.size) {
1799
+ let stream = fs2.createReadStream(logFile, { start: 0, end: curr.size - 1 });
1800
+ stream.on("data", (d) => {
1801
+ process.stdout.write(d);
1802
+ buffer = (buffer + d.toString()).slice(-200);
1803
+ if (buffer.includes("Server running at http://localhost:")) resolve();
1804
+ });
1805
+ }
1806
+ });
1807
+ child.once("exit", () => {
1808
+ process.stdout.write(fs2.readFileSync(logFile));
1809
+ reject(new Error("Exited before server started"));
1810
+ });
1811
+ child.once("error", (e) => reject(e));
1812
+ });
1813
+ }
1814
+ function getGrapheneCache(root) {
1815
+ return path3.join(root, "node_modules", ".graphene");
1816
+ }
1817
+ function getPidFilePath(root) {
1818
+ return path3.join(getGrapheneCache(root), process.env.NODE_ENV == "test" ? "test.pid" : "serve.pid");
1819
+ }
1820
+ async function stopGrapheneIfRunning(root) {
1821
+ let pidFile = getPidFilePath(root);
1822
+ let pid = await readPid(pidFile);
1823
+ if (!pid) return true;
1824
+ if (!isProcessRunning(pid)) {
1825
+ await fs2.remove(pidFile);
1826
+ return true;
1827
+ }
1828
+ try {
1829
+ console.log(`Stopping server (${pid})`);
1830
+ process.kill(pid, "SIGTERM");
1831
+ } catch (err) {
1832
+ if (err.code === "ESRCH") return true;
1833
+ return false;
1834
+ }
1835
+ let end = Date.now() + 5e3;
1836
+ while (Date.now() < end && isProcessRunning(pid)) {
1837
+ await new Promise((resolve) => setTimeout(resolve, 100));
1838
+ }
1839
+ await fs2.remove(pidFile);
1840
+ return !isProcessRunning(pid);
1841
+ }
1842
+ async function readPid(pidFile) {
1843
+ if (!await fs2.pathExists(pidFile)) return void 0;
1844
+ let contents = (await fs2.readFile(pidFile, "utf8")).trim();
1845
+ if (!contents) return void 0;
1846
+ let pid = Number.parseInt(contents, 10);
1847
+ if (Number.isNaN(pid)) return void 0;
1848
+ return pid;
1849
+ }
1850
+ function isProcessRunning(pid) {
1851
+ try {
1852
+ process.kill(pid, 0);
1853
+ return true;
1854
+ } catch {
1855
+ return false;
1856
+ }
1857
+ }
1858
+
1859
+ // cli.ts
1860
+ init_connections();
1861
+ var program = new Command();
1862
+ program.name("graphene").description("Graphene CLI").version("1.0.0");
1863
+ program.hook("preAction", async () => {
1864
+ if (process.env.CLI_DELAY) {
1865
+ await new Promise((r) => setTimeout(r, 1e3));
1866
+ }
1867
+ loadConfig(process.cwd());
1868
+ });
1869
+ program.command("compile").description("Translate a query to SQL and print it").argument("[input]", 'Path to file, a raw string, or "-" for stdin').action(async (input) => {
1870
+ await loadWorkspace(process.cwd(), false);
1871
+ let sql = await readInput(input);
1872
+ let queries = analyze(sql);
1873
+ if (!validQuery(queries)) return;
1874
+ console.log(toSql(queries[0]));
1875
+ });
1876
+ program.command("run").description("Run a query against your database").argument("[input]", 'Path to file, a raw string, or "-" for stdin').action(async (input) => {
1877
+ await loadWorkspace(process.cwd(), false);
1878
+ let gsql = await readInput(input);
1879
+ let queries = analyze(gsql);
1880
+ if (!validQuery(queries)) return;
1881
+ let sql = toSql(queries[0]);
1882
+ let connection = await getConnection();
1883
+ let res = await connection.runQuery(sql);
1884
+ printTable(res.rows);
1885
+ });
1886
+ program.command("serve").description("Run the local server").option("--fg", "Run the server in the foreground").action(async (options) => {
1887
+ if (options.fg || process.env.DEBUG) {
1888
+ let mod = await Promise.resolve().then(() => (init_serve2(), serve2_exports));
1889
+ await mod.serve2();
1890
+ } else {
1891
+ await runServeInBackground();
1892
+ process.exit(0);
1893
+ }
1894
+ });
1895
+ program.command("stop").description("Stop the local server").action(async () => {
1896
+ await stopGrapheneIfRunning(process.cwd());
1897
+ });
1898
+ program.command("check").description("Check the project for errors").action(async () => {
1899
+ await loadWorkspace(process.cwd(), true);
1900
+ analyze();
1901
+ if (getDiagnostics().length) {
1902
+ printDiagnostics(getDiagnostics());
1903
+ process.exit(1);
1904
+ }
1905
+ console.log("No errors found \u{1F48E}");
1906
+ });
1907
+ program.command("view").description("Capture a screenshot of a rendered markdown file").argument("<mdFile>", "Markdown file to view (e.g., index.md)").option("-c, --chart <chartName>", "Name of specific chart to capture").action(async (mdFile, options) => {
1908
+ let response = await fetch("http://localhost:4000/graphene/view", {
1909
+ method: "POST",
1910
+ headers: { "Content-Type": "application/json" },
1911
+ body: JSON.stringify({ mdFile, chart: options.chart })
1912
+ });
1913
+ if (!response.ok) throw new Error(`View request failed: ${await response.text()}`);
1914
+ let result = await response.json();
1915
+ if (result.errors && result.errors.length > 0) {
1916
+ console.error("Errors found:");
1917
+ result.errors.forEach((error) => console.error(JSON.stringify(error)));
1918
+ }
1919
+ if (result.stillLoading) {
1920
+ console.error("Warning: Queries were still loading when the screenshot was taken");
1921
+ }
1922
+ if (result.screenshot) {
1923
+ let filename = `graphene-screenshot-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.png`;
1924
+ let screenshotPath = path8.join(os.tmpdir(), filename);
1925
+ let base64Data = result.screenshot.replace(/^data:image\/png;base64,/, "");
1926
+ await fs7.writeFile(screenshotPath, base64Data, "base64");
1927
+ console.log("Screenshot saved to", screenshotPath);
1928
+ }
1929
+ });
1930
+ program.parse(process.argv);
1931
+ async function readInput(arg) {
1932
+ if (!arg || arg === "-") {
1933
+ return await new Promise((resolve) => {
1934
+ let data = "";
1935
+ process.stdin.setEncoding("utf-8");
1936
+ process.stdin.on("data", (chunk) => data += chunk);
1937
+ process.stdin.on("end", () => resolve(data));
1938
+ process.stdin.resume();
1939
+ });
1940
+ }
1941
+ let absolutePath = path8.resolve(arg);
1942
+ if (fs7.existsSync(absolutePath)) {
1943
+ return await fs7.promises.readFile(absolutePath, "utf-8");
1944
+ }
1945
+ return arg;
1946
+ }
1947
+ function validQuery(queries) {
1948
+ if (getDiagnostics().length) {
1949
+ printDiagnostics(getDiagnostics());
1950
+ process.exit(1);
1951
+ }
1952
+ if (queries.length == 0) {
1953
+ console.warn("No queries found");
1954
+ process.exit(1);
1955
+ }
1956
+ return true;
1957
+ }
43
1958
  //# sourceMappingURL=cli.js.map