@dataramen/cli 0.0.2

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/bin/run.js ADDED
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ const { execSync } = require("node:child_process");
3
+ const path = require("node:path");
4
+ const yargs = require("yargs");
5
+ const yargsHelpers = require("yargs/helpers");
6
+ const os = require('node:os');
7
+ const fs = require("fs-extra");
8
+
9
+ const processName = "@odemian/dataramen-cli";
10
+
11
+ const homeDir = os.homedir();
12
+ const filesPath = path.join(homeDir, ".odemian", ".runtime", "server");
13
+
14
+ yargs()
15
+ .command("start", 'Default command, start/restart the server', () => {
16
+ const hasPm2 = checkPm2();
17
+ if (!hasPm2) {
18
+ installPm2();
19
+ }
20
+
21
+ start();
22
+ })
23
+ .command("logs", 'Listen for logs', () => {
24
+ execSync(`pm2 logs ${processName}`, {
25
+ stdio: "inherit",
26
+ });
27
+ })
28
+ .command("stop", 'Stop the server', () => {
29
+ execSync(`pm2 stop ${processName}`, {
30
+ stdio: "inherit",
31
+ })
32
+ })
33
+ .parse(yargsHelpers.hideBin(process.argv));
34
+
35
+ function checkPm2 () {
36
+ try {
37
+ execSync(`pm2 -v`, {
38
+ stdio: "inherit"
39
+ });
40
+
41
+ return true;
42
+ } catch (e) {
43
+ console.error("Library does not exist");
44
+ return false;
45
+ }
46
+ }
47
+
48
+ function installPm2 () {
49
+ console.log("Install Pm2");
50
+ execSync(`npm i -g pm2`, {
51
+ stdio: "inherit"
52
+ });
53
+ }
54
+
55
+ function stopExisting () {
56
+ try {
57
+ execSync(`pm2 stop "${processName}"`);
58
+ } catch (e) {}
59
+ }
60
+
61
+ function installServer () {
62
+ console.log("Installing Server");
63
+ // copy code
64
+ fs.copySync(path.join(__dirname, '..', 'dist', "code"), path.join(filesPath, "code"));
65
+ // copy default env (do not override existing .env)
66
+ fs.copySync(path.join(__dirname, '..', 'dist', "env", ".env.default"), path.join(filesPath, "env", ".env.default"));
67
+ // copy package.json
68
+ fs.copySync(path.join(__dirname, '..', 'dist', "package.json"), path.join(filesPath, "package.json"));
69
+
70
+ execSync(`npm i --omit=dev`, {
71
+ stdio: "inherit",
72
+ cwd: filesPath,
73
+ });
74
+ console.log("Server installed");
75
+ }
76
+
77
+ function start () {
78
+ stopExisting();
79
+
80
+ try {
81
+ installServer();
82
+ console.log("Starting server");
83
+ const pkg = fs.readJsonSync(path.join(filesPath, "package.json"));
84
+ execSync(`pm2 start "${pkg.main}" --name "${processName}" --no-autorestart`, {
85
+ stdio: "inherit",
86
+ cwd: filesPath,
87
+ });
88
+ console.log(`Server is running`);
89
+ } catch (e) {
90
+ console.error(`Failed to start local server`, e);
91
+ }
92
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";var tt=Object.create;var ae=Object.defineProperty;var rt=Object.getOwnPropertyDescriptor;var at=Object.getOwnPropertyNames;var st=Object.getPrototypeOf,ot=Object.prototype.hasOwnProperty;var H=(a,e)=>()=>(e||a((e={exports:{}}).exports,e),e.exports);var nt=(a,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of at(e))!ot.call(a,s)&&s!==t&&ae(a,s,{get:()=>e[s],enumerable:!(r=rt(e,s))||r.enumerable});return a};var A=(a,e,t)=>(t=a!=null?tt(st(a)):{},nt(e||!a||!a.__esModule?ae(t,"default",{value:a,enumerable:!0}):t,a));var De=H(_e=>{"use strict";Object.defineProperty(_e,"__esModule",{value:!0})});var Oe=H(O=>{"use strict";Object.defineProperty(O,"__esModule",{value:!0});O.SQLManipulator=O.SQLBuilder=O.SQLParser=void 0;var j=class{constructor(e="mysql"){this.dialect=e}parse(e){let r=e.trim().replace(/;$/,"").replace(/\s+/g," "),s=r.toUpperCase(),o;if(s.startsWith("SELECT"))o=this.parseSelect(r);else if(s.startsWith("INSERT"))o=this.parseInsert(r);else if(s.startsWith("UPDATE"))o=this.parseUpdate(r);else if(s.startsWith("DELETE"))o=this.parseDelete(r);else throw new Error("Unsupported SQL statement type");return o.parameters=this.extractParameters(r),o}extractParameters(e){let t=/:(\w+)/g,r=[],s;for(;(s=t.exec(e))!==null;){let o=s[1];r.includes(o)||r.push(o)}return r}parseSelect(e){let t={type:"SELECT"},{cleanedSQL:r,subqueries:s}=this.extractSubqueries(e),o=r.match(/SELECT\s+(.*?)\s+FROM/i);if(o){let m=o[1].trim();t.columns=m==="*"?["*"]:this.parseColumns(m)}let n=r.match(/FROM\s+([^\s]+)(?:\s|$)/i);if(n&&(t.table=n[1]),!t.table){let m=r.match(/FROM\s+([^\s]+)(?:\s+(?:AS\s+)?([^\s]+))?(?:\s+(?:WHERE|JOIN|INNER|LEFT|RIGHT|FULL|GROUP|ORDER|LIMIT|OFFSET|HAVING)|$)/i);m&&(t.table=m[1])}t.joins=this.parseJoins(r);let u=r.match(/WHERE\s+(.*?)(?:\s+GROUP\s+BY|\s+ORDER\s+BY|\s+LIMIT|\s+OFFSET|$)/i);u&&(t.where=this.restoreSubqueries(u[1].trim(),s));let i=r.match(/ORDER\s+BY\s+(.*?)(?:\s+LIMIT|\s+OFFSET|$)/i);i&&(t.orderBy=this.parseOrderBy(i[1]));let d=r.match(/GROUP\s+BY\s+(.*?)(?:\s+HAVING|\s+ORDER\s+BY|\s+LIMIT|\s+OFFSET|$)/i);d&&(t.groupBy=this.parseColumns(d[1]));let l=r.match(/HAVING\s+(.*?)(?:\s+ORDER\s+BY|\s+LIMIT|\s+OFFSET|$)/i);l&&(t.having=this.restoreSubqueries(l[1].trim(),s));let T=r.match(/LIMIT\s+(\d+)/i);T&&(t.limit=parseInt(T[1]));let p=r.match(/OFFSET\s+(\d+)/i);return p&&(t.offset=parseInt(p[1])),t}parseColumns(e){let t=[],r="",s=!1,o="",n=0;for(let u=0;u<e.length;u++){let i=e[u];!s&&(i==='"'||i==="'")?(s=!0,o=i,r+=i):s&&i===o?u+1<e.length&&e[u+1]===o?(r+=i+i,u++):(s=!1,o="",r+=i):!s&&i==="("?(n++,r+=i):!s&&i===")"?(n--,r+=i):!s&&i===","&&n===0?(t.push(r.trim()),r=""):r+=i}return r.trim()&&t.push(r.trim()),t}extractSubqueries(e){let t=new Map,r=e,s=0,o=/\(([^()]*(?:SELECT|INSERT|UPDATE|DELETE)[^()]*(?:\([^()]*\)[^()]*)*)\)/gi,n=!0;for(;n;)n=!1,r=r.replace(o,(u,i)=>{if(/\b(SELECT|INSERT|UPDATE|DELETE)\b/i.test(i)){let d=`__SUBQUERY_${s}__`;return t.set(d,u),s++,n=!0,d}return u});return{cleanedSQL:r,subqueries:t}}restoreSubqueries(e,t){let r=e;return t.forEach((s,o)=>{r=r.replace(new RegExp(o,"g"),s)}),r}parseJoins(e){let t=[],r=/((?:INNER|LEFT|RIGHT|FULL)?\s*JOIN)\s+(\w+(?:\s+\w+)?)\s+ON\s+(.*?)(?=\s+(?:INNER|LEFT|RIGHT|FULL)?\s*JOIN|\s+WHERE|\s+GROUP\s+BY|\s+ORDER\s+BY|\s+LIMIT|\s+OFFSET|$)/gi,s;for(;(s=r.exec(e))!==null;){let o=s[1].trim().toUpperCase(),n=s[2].trim(),u=s[3].trim(),i=n.split(/\s+/),d=i[0],l=i.length>1?i[1]:void 0,T;o.includes("LEFT")?T="LEFT":o.includes("RIGHT")?T="RIGHT":o.includes("FULL")?T="FULL":T="INNER",t.push({type:T,table:d,alias:l,on:u})}return t.length>0?t:[]}parseInsert(e){let t={type:"INSERT"},r=e.match(/INSERT\s+INTO\s+(\w+)\s*\(([^)]+(?:\([^)]*\)[^)]*)*)\)\s*VALUES\s*\((.+)\)\s*;?$/i);return r&&(t.table=r[1],t.columns=this.parseColumns(r[2]),t.values=this.parseColumns(r[3])),t}parseUpdate(e){let t={type:"UPDATE"},r=e.match(/UPDATE\s+(\w+)\s+SET\s+(.*?)(?:\s+WHERE|$)/i);r&&(t.table=r[1],t.set=this.parseSetClause(r[2]));let s=e.match(/WHERE\s+(.*?)$/i);return s&&(t.where=s[1].trim()),t}parseDelete(e){let t={type:"DELETE"},r=e.match(/DELETE\s+FROM\s+(\w+)(?:\s+WHERE\s+(.*?))?$/i);return r&&(t.table=r[1],r[2]&&(t.where=r[2].trim())),t}parseOrderBy(e){return e.split(",").map(r=>{let s=r.trim().split(" "),o=s.pop();return o==="DESC"||o==="desc"?{column:s.join(" "),direction:"DESC"}:o==="ASC"||o==="asc"?{column:s.join(" "),direction:"ASC"}:{column:s.join(" ")+" "+o,direction:"ASC"}})}parseSetClause(e){let t={};return this.parseColumns(e).forEach(s=>{let o=s.indexOf("=");if(o>0){let n=s.substring(0,o).trim(),u=s.substring(o+1).trim();t[n]=u}}),t}};O.SQLParser=j;var F=class{constructor(e,t="mysql"){this.parsed={...e},this.dialect=t}build(){switch(this.parsed.type){case"SELECT":return this.buildSelect();case"INSERT":return this.buildInsert();case"UPDATE":return this.buildUpdate();case"DELETE":return this.buildDelete();default:throw new Error("Unsupported SQL type")}}buildSelect(){let e="SELECT ";if(this.parsed.columns&&this.parsed.columns.length>0?e+=this.parsed.columns.join(", "):e+="*",this.parsed.table&&(e+=` FROM ${this.parsed.table}`),this.parsed.joins&&this.parsed.joins.length>0&&this.parsed.joins.forEach(t=>{e+=` ${t.type} JOIN ${t.table} ON ${t.on}`}),this.parsed.where&&(e+=` WHERE ${this.parsed.where}`),this.parsed.groupBy&&this.parsed.groupBy.length>0&&(e+=` GROUP BY ${this.parsed.groupBy.join(", ")}`),this.parsed.having&&(e+=` HAVING ${this.parsed.having}`),this.parsed.orderBy&&this.parsed.orderBy.length>0){let t=this.parsed.orderBy.reduce((s,o)=>(s[o.column]=o.direction,s),{}),r=Object.entries(t).map(([s,o])=>`${s} ${o}`);e+=` ORDER BY ${r.join(", ")}`}return this.parsed.limit!==void 0&&(e+=` LIMIT ${this.parsed.limit}`),this.parsed.offset!==void 0&&(this.dialect==="mysql"?e+=` OFFSET ${this.parsed.offset}`:e+=` OFFSET ${this.parsed.offset}`),e}buildInsert(){if(!this.parsed.table||!this.parsed.columns||!this.parsed.values)throw new Error("Invalid INSERT statement data");let e=this.parsed.columns.join(", "),t=this.parsed.values.join(", ");return`INSERT INTO ${this.parsed.table} (${e}) VALUES (${t})`}buildUpdate(){if(!this.parsed.table||!this.parsed.set)throw new Error("Invalid UPDATE statement data");let e=Object.entries(this.parsed.set).map(([r,s])=>`${r} = ${s}`),t=`UPDATE ${this.parsed.table} SET ${e.join(", ")}`;return this.parsed.where&&(t+=` WHERE ${this.parsed.where}`),t}buildDelete(){if(!this.parsed.table)throw new Error("Invalid DELETE statement data");let e=`DELETE FROM ${this.parsed.table}`;return this.parsed.where&&(e+=` WHERE ${this.parsed.where}`),e}};O.SQLBuilder=F;var te=class{constructor(e,t="mysql"){this.dialect=t,this.parser=new j(t),this.parsed=this.parser.parse(e),this.parameters={}}setParameter(e,t){return this.parameters[e]=t,this}setParameters(e){return this.parameters={...this.parameters,...e},this}getParameter(e){return this.parameters[e]}getParameters(){return{...this.parameters}}clearParameters(){return this.parameters={},this}getRequiredParameters(){return this.parsed.parameters||[]}getMissingParameters(){let e=this.getRequiredParameters(),t=Object.keys(this.parameters);return e.filter(r=>!t.includes(r))}addWhereWithParam(e,t,r,s="AND"){let o=this.buildWhereConditionWithParam(e,t,r);return this.parsed.where?this.parsed.where+=` ${s} ${o}`:this.parsed.where=o,this.parsed.parameters||(this.parsed.parameters=[]),this.parsed.parameters.includes(r)||this.parsed.parameters.push(r),this}addWhere(e){let t=this.buildWhereCondition(e);if(this.parsed.where){let r=e.connector||"AND";this.parsed.where+=` ${r} ${t}`}else this.parsed.where=t;return this}addWhereRaw(e,t="AND"){return this.parsed.where?this.parsed.where+=` ${t} ${e}`:this.parsed.where=e,this}clearWhere(){return this.parsed.where=void 0,this}addOrderBy(...e){return this.parsed.orderBy||(this.parsed.orderBy=[]),this.parsed.orderBy.push(...e),this}clearOrderBy(){return this.parsed.orderBy=void 0,this}setLimit(e){return this.parsed.limit=e,this}setOffset(e){return this.parsed.offset=e,this}addGroupBy(e){this.parsed.groupBy||(this.parsed.groupBy=[]);let t=this.parsed.groupBy.findIndex(r=>r===e);return t>-1?this.parsed.groupBy[t]=e:this.parsed.groupBy.push(e),this}setHaving(e){return this.parsed.having=e,this}addJoin(...e){if(this.parsed.type!=="SELECT")throw new Error("JOIN operations are only supported for SELECT queries");return this.parsed.joins||(this.parsed.joins=[]),this.parsed.joins.push(...e),this}selectColumns(e){if(this.parsed.type!=="SELECT")throw new Error("Column selection is only supported for SELECT queries");return this.parsed.columns=e,this}toSQL(e=!1,t=!1){let s=new F(this.parsed,this.dialect).build();return e&&(s=this.substituteParameters(s)),t&&(s+=";"),s}toParameterizedSQL(e=!1){let r=new F(this.parsed,this.dialect).build();return e?r+";":r}toExecutableSQL(e=!1){return this.toSQL(!0,e)}substituteParameters(e){let t=e;return Object.entries(this.parameters).forEach(([r,s])=>{let o=new RegExp(`:${r}\\b`,"g"),n=this.formatParameterValue(s);t=t.replace(o,n)}),t}formatParameterValue(e){return e==null?"NULL":typeof e=="string"?e:typeof e=="boolean"?this.dialect==="postgres"?e?"TRUE":"FALSE":e?"1":"0":Array.isArray(e)?`(${e.map(r=>this.formatParameterValue(r)).join(", ")})`:e instanceof Date?`'${e.toISOString().slice(0,19).replace("T"," ")}'`:String(e)}buildWhereConditionWithParam(e,t,r){switch(t){case"IS NULL":case"IS NOT NULL":return`${e} ${t}`;case"IN":case"NOT IN":return`${e} ${t} :${r}`;default:return`${e} ${t} :${r}`}}getParsed(){return{...this.parsed}}buildWhereCondition(e){let{column:t,operator:r,value:s}=e;switch(r){case"IS NULL":case"IS NOT NULL":return`${t} ${r}`;case"IN":case"NOT IN":let o=s?.map(i=>typeof i=="string"?`'${i}'`:i).join(", ");return`${t} ${r} (${o})`;default:let n=s?.[0],u=typeof n=="string"?`'${n}'`:n;return`${t} ${r} ${u}`}}};O.SQLManipulator=te});var re=H(N=>{"use strict";var Rt=N&&N.__createBinding||(Object.create?function(a,e,t,r){r===void 0&&(r=t);var s=Object.getOwnPropertyDescriptor(e,t);(!s||("get"in s?!e.__esModule:s.writable||s.configurable))&&(s={enumerable:!0,get:function(){return e[t]}}),Object.defineProperty(a,r,s)}:function(a,e,t,r){r===void 0&&(r=t),a[r]=e[t]}),Ne=N&&N.__exportStar||function(a,e){for(var t in a)t!=="default"&&!Object.prototype.hasOwnProperty.call(e,t)&&Rt(e,a,t)};Object.defineProperty(N,"__esModule",{value:!0});Ne(De(),N);Ne(Oe(),N)});var $=require("dotenv"),Q=require("node:path"),se=require("node:fs"),it=(()=>{try{let a=(0,se.readFileSync)((0,Q.join)(__dirname,"..","package.json"),"utf8");return JSON.parse(a)}catch{return{version:"0.0.0"}}})();(0,$.config)({path:[(0,Q.join)(__dirname,"..","env",".env"),(0,Q.join)(__dirname,"..","env",".env.default")]});(0,$.populate)(process.env,{SERVER_VERSION:it.version});var Ke=A(require("fastify")),Ze=A(require("@fastify/cors"));var c=class extends Error{constructor(t,r){super(r);this.status=t;this.message=r}};var me=require("typeorm");var oe=require("typeorm"),Y=new oe.EntitySchema({name:"DatabaseInspection",tableName:"db_inspection",columns:{id:{type:String,unique:!0,primary:!0,generated:"uuid"},tableName:{nullable:!0,type:String},columns:{type:"json",nullable:!0},createdAt:{type:"datetime",default:"CURRENT_TIMESTAMP"},updatedAt:{type:"datetime",default:"CURRENT_TIMESTAMP"}},relations:{datasource:{target:()=>"DataSource",type:"many-to-one",joinTable:!1,cascade:!0}}});var ne=require("typeorm"),G=new ne.EntitySchema({name:"Team",tableName:"teams",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},createdAt:{type:"datetime",default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:"datetime",default:()=>"CURRENT_TIMESTAMP"}},relations:{users:{type:"many-to-many",target:()=>"User",inverseSide:"teams"},workbooks:{type:"one-to-many",target:()=>"Workbook",inverseSide:"team"},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"team"},datasources:{type:"one-to-many",target:()=>"DataSource",inverseSide:"team"}}});var ie=require("typeorm"),V=new ie.EntitySchema({name:"User",tableName:"users",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},createdAt:{type:"datetime",default:"CURRENT_TIMESTAMP"},updatedAt:{type:"datetime",default:"CURRENT_TIMESTAMP"}},relations:{teams:{type:"many-to-many",target:()=>"Team",inverseSide:"users",joinTable:!0},settings:{type:"one-to-one",target:()=>"UserSettings",inverseSide:"user",joinColumn:!0},currentTeam:{type:"many-to-one",target:()=>"Team",joinColumn:!0}}});var ce=require("typeorm"),z=new ce.EntitySchema({name:"UserSettings",tableName:"user_settings",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},openAiToken:{type:String,nullable:!0},model:{type:String,default:"gpt-3.5-turbo"},createdAt:{type:"datetime",default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:"datetime",default:()=>"CURRENT_TIMESTAMP"}},relations:{user:{type:"one-to-one",target:()=>"User",inverseSide:"settings",joinColumn:!0}}});var ue=require("typeorm"),J=new ue.EntitySchema({name:"Workbook",tableName:"workbooks",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},path:{type:"uuid",generated:"uuid"},isTrash:{type:"boolean",default:!1},createdAt:{type:"datetime",default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:"datetime",default:()=>"CURRENT_TIMESTAMP",onUpdate:"CURRENT_TIMESTAMP"}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"workbooks",joinColumn:!0}}});var de=require("typeorm"),K=new de.EntitySchema({name:"DataSource",tableName:"data_sources",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},dbUrl:{type:String},dbPort:{type:Number,nullable:!0},dbUser:{type:String},dbPassword:{type:String,nullable:!0},dbType:{type:String},createdAt:{type:"datetime",default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:"datetime",default:()=>"CURRENT_TIMESTAMP"},name:{type:String},description:{type:String,nullable:!0},dbDatabase:{type:String},dbSchema:{type:String,nullable:!0},lastInspected:{type:"datetime",nullable:!0,default:()=>null},status:{type:String,nullable:!0}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"datasources",joinColumn:!0},inspections:{type:"one-to-many",target:()=>"DatabaseInspection",inverseSide:"datasource"},queries:{type:"one-to-many",target:()=>"Query",inverseSide:"dataSource"},owner:{type:"many-to-one",target:()=>"User",joinColumn:!0}}});var le=A(require("os"));var pe=require("typeorm"),Z=new pe.EntitySchema({name:"Query",tableName:"query",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},path:{type:"uuid",generated:"uuid"},isTrash:{type:Boolean,default:!1,nullable:!0},createdAt:{type:"datetime",default:()=>"CURRENT_TIMESTAMP"},updatedAt:{type:"datetime",default:()=>"CURRENT_TIMESTAMP",onUpdate:"CURRENT_TIMESTAMP"}},relations:{team:{type:"many-to-one",target:()=>"Team",inverseSide:"workbooks",joinColumn:!0},dataSource:{type:"many-to-one",target:()=>"DataSource",inverseSide:"queries",joinColumn:!0}}});function ct(){let a=process.env.TYPEORM_DATABASE;if(!a)throw new Error("Bad value for TYPEORM_DATABASE. Please check your config!");return a.startsWith("<home>")&&(a=a.replace("<home>",le.default.homedir())),a}var w=new me.DataSource({type:process.env.TYPEORM_CONNECTION,database:ct(),synchronize:process.env.TYPEORM_SYNCHRONIZE==="true",host:process.env.TYPEORM_HOST,username:process.env.TYPEORM_USERNAME,password:process.env.TYPEORM_PASSWORD,port:process.env.TYPEORM_PORT?parseInt(process.env.TYPEORM_PORT):void 0,logging:process.env.TYPEORM_LOGGING==="true",entities:[Y,K,G,V,z,J,Z]}),fe=async()=>{if(!w.isInitialized)return w.initialize();throw new Error("Already initialized")},P=w.getRepository(Y),g=w.getRepository(K),k=w.getRepository(G),I=w.getRepository(V),_=w.getRepository(z),b=w.getRepository(J),S=w.getRepository(Z);var x=A(require("node:fs/promises")),X=require("node:path"),ye=A(require("node:os")),ut=ye.default.homedir(),ee=(0,X.join)(ut,".odemian",".runtime","files"),he=a=>(0,X.join)(ee,a),B=async a=>x.default.readFile(he(a),{encoding:"utf8"}),v=async(a,e)=>x.default.writeFile(he(a),e,{encoding:"utf8"});var ge=async()=>{await dt()||await x.default.mkdir(ee,{recursive:!0})};async function dt(){try{return(await x.default.lstat(ee)).isDirectory()}catch{return!1}}var h=a=>(e,t,r)=>{a(e),r()};var Te=h(a=>{a.post("/workbook",async e=>({data:""}))});var f=(a,e)=>{let t=a.body;return e&&e(t),t},M=(a,e)=>{let t=a.query;return e&&e(t),t},y=(a,e)=>{let t=a.params;return e&&e(t),t};var D=a=>a.headers["phoenix-user-id"];var we=a=>{if(!a.dbUrl)throw new c(400,"url is required");if(!a.dbUser)throw new c(400,"user is required");if(!a.dbType)throw new c(400,"type is required");if(!a.name)throw new c(400,"name is required");if(!a.dbDatabase)throw new c(400,"database is required")};var Se=A(require("mysql2/promise"));var mt=({dbDatabase:a,dbPassword:e,dbUser:t,dbUrl:r})=>Se.default.createConnection({host:r,user:t,database:a,password:e}),lt=async a=>{let e=`
2
+ SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION
3
+ FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
4
+ WHERE CONSTRAINT_NAME = 'PRIMARY'
5
+ ORDER BY TABLE_NAME, ORDINAL_POSITION;
6
+ `,[t]=await a.execute(e),r={};return t.forEach(s=>{let o=s.TABLE_NAME,n=s.COLUMN_NAME;r[o]||(r[o]=[]),r[o].push(n)}),r},ft=async a=>{let e=`
7
+ SELECT
8
+ TABLE_NAME AS table_name,
9
+ COLUMN_NAME AS field,
10
+ REFERENCED_TABLE_NAME AS referenced_table,
11
+ REFERENCED_COLUMN_NAME AS referenced_field
12
+ FROM
13
+ information_schema.KEY_COLUMN_USAGE
14
+ WHERE
15
+ REFERENCED_TABLE_NAME IS NOT NULL
16
+ AND CONSTRAINT_SCHEMA = DATABASE();
17
+ `,[t]=await a.execute(e),r={};return Array.isArray(t)&&t.forEach(s=>{r[s.table_name]||(r[s.table_name]={}),r[s.table_name][s.field]={refTable:s.referenced_table,refField:s.referenced_field}}),r},yt=async(a,e)=>{let r=(await e.query("SHOW TABLES"))[0],s=await ft(e),o=await lt(e),n=r.map(async u=>{let i=Object.values(u)[0],d=`select COLUMN_NAME, DATA_TYPE from information_schema.columns where table_schema = '${a.dbDatabase}' and table_name = '${i}'`,[l]=await e.query(d),T=s[i];return{columns:l.map(p=>({name:p.COLUMN_NAME,type:p.DATA_TYPE,isPrimary:o[i]?.includes(p.COLUMN_NAME),ref:T?.[p.COLUMN_NAME]?{table:T[p.COLUMN_NAME].refTable,field:T[p.COLUMN_NAME].refField}:void 0})).sort((p,m)=>p.isPrimary&&m.isPrimary?p.name.localeCompare(m.name):p.isPrimary?-1:1),createdAt:new Date,tableName:i,updatedAt:new Date}});return Promise.all(n)},Ee=async(a,e,t)=>{try{console.log(`[MYSQL CONN] Query: ${a}`);let[r,s]=await e.query({sql:a,rowsAsArray:!0}),o=r?.constructor?.name;if(o==="ResultSetHeader"){let n=r;if(n.affectedRows>3&&t.allowBulkUpdate!==!0)throw new Error("[MYSQL CONN] Bulk update performed without permission.");return{columns:[{column:"affectedRows",alias:"Affected rows",full:"affectedRows"}],rows:[[n.affectedRows]],query:a}}else if(o==="Array"){let n=r;return{columns:s?.map(u=>({column:u.orgName||u.name,table:u.orgTable,alias:u.name,full:u.orgTable?u.orgTable+"."+u.orgName:u.name}))||[],rows:n,query:a}}throw new Error(`[MYSQL CONN] Unknown result type: ${o}`)}catch(r){throw console.error(r),r instanceof c?r:new c(400,r.message)}},ht=async(a,e)=>{await a.beginTransaction();try{let t=await e();return await a.commit(),console.log("[MYSQL CONN] Commit"),t}catch(t){throw await a.rollback(),console.warn(t.message),console.log("[MYSQL CONN] Rollback"),t}},be=async a=>{let e=await mt(a),t=!1;return{dbType:"mysql",dataSource:a,inspectSchema:()=>yt(a,e),executeQuery:(r,s)=>s.type==="SELECT"?Ee(r,e,s):ht(e,()=>Ee(r,e,s)),checkConnection:async()=>e.ping(),isClosed:()=>t,close:async()=>{if(!t)return t=!0,e.destroy()}}};var Ie=A(require("pg"));var gt=async({dbDatabase:a,dbPassword:e,dbUser:t,dbUrl:r,dbPort:s})=>{let o=new Ie.default.Client({host:r,user:t,database:a,password:e,port:s,query_timeout:1e4});return await o.connect(),o},Tt=async a=>{let t=await a.query(`
18
+ SELECT
19
+ kcu.table_name,
20
+ kcu.column_name,
21
+ kcu.ordinal_position
22
+ FROM
23
+ information_schema.table_constraints tc
24
+ JOIN information_schema.key_column_usage kcu
25
+ ON tc.constraint_name = kcu.constraint_name
26
+ AND tc.table_schema = kcu.table_schema
27
+ WHERE
28
+ tc.constraint_type = 'PRIMARY KEY'
29
+ ORDER BY
30
+ kcu.table_name, kcu.ordinal_position;
31
+ `),r={};return t.rows.forEach(s=>{let o=s.table_name,n=s.column_name;r[o]||(r[o]=[]),r[o].push(n)}),r},wt=async a=>{let t=await a.query(`
32
+ SELECT
33
+ tc.table_name AS table_name,
34
+ kcu.column_name AS field,
35
+ ccu.table_name AS referenced_table,
36
+ ccu.column_name AS referenced_field
37
+ FROM
38
+ information_schema.table_constraints AS tc
39
+ JOIN information_schema.key_column_usage AS kcu
40
+ ON tc.constraint_name = kcu.constraint_name
41
+ AND tc.table_schema = kcu.table_schema
42
+ JOIN information_schema.constraint_column_usage AS ccu
43
+ ON ccu.constraint_name = tc.constraint_name
44
+ AND ccu.table_schema = tc.table_schema
45
+ WHERE tc.constraint_type = 'FOREIGN KEY';
46
+ `),r={};return t.rows.forEach(s=>{r[s.table_name]||(r[s.table_name]={}),r[s.table_name][s.field]={refTable:s.referenced_table,refField:s.referenced_field}}),r},Et=async(a,e)=>{let t=`SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = '${a.dbSchema}'`,s=(await e.query(t)).rows,o=await wt(e),n=await Tt(e),u=s.map(async i=>{let d=Object.values(i)[0],l=`
47
+ SELECT column_name, data_type
48
+ FROM information_schema.columns
49
+ WHERE
50
+ table_name = '${d}' and
51
+ table_schema = '${a.dbSchema}'
52
+ `,{rows:T}=await e.query(l),p=o[d];return{columns:T.map(m=>({name:m.column_name,type:m.data_type,isPrimary:n[d]?.includes(m.column_name),ref:p?.[m.column_name]?{table:p[m.column_name].refTable,field:p[m.column_name].refField}:void 0})).sort((m,E)=>m.isPrimary&&E.isPrimary?m.name.localeCompare(E.name):m.isPrimary?-1:1),createdAt:new Date,tableName:d,updatedAt:new Date}});return Promise.all(u)},St=async(a,e)=>{let t=`select relname, attname, concat(pg_class.oid, '-', attnum) as row_key
53
+ from pg_attribute
54
+ left join pg_class on pg_attribute.attrelid = pg_class.oid
55
+ where
56
+ concat(pg_class.oid, '-', attnum) IN (${a.join(", ")})
57
+ limit 25;`;return(await e.query(t)).rows.reduce((s,o)=>(s[o.row_key]={table:o.relname,column:o.attname},s),{})},Re=async(a,e,t)=>{try{console.log(`[PG CONN] Query: ${a}`);let{rows:r,fields:s,command:o,rowCount:n}=await e.query({text:a,rowMode:"array"});if(o==="UPDATE"||o==="INSERT"||o==="DELETE"){if(n!=null&&n>3&&t.allowBulkUpdate!==!0)throw new Error("[PG CONN] Bulk update performed without permission.");return{columns:[{column:"affectedRows",alias:"Affected rows",full:"affectedRows"}],rows:[[n]],query:a}}if(o==="SELECT"){let u=s.map(d=>`'${d.tableID}-${d.columnID}'`),i=await St(u,e);return{columns:s.map(d=>{let l=i[`${d.tableID}-${d.columnID}`];return{column:l?.column||d.name,alias:d.name,table:l?.table||"",full:l?l.table+"."+l.column:d.name}}),rows:r,query:a}}throw new Error(`[PG CONN] Unsupported command: ${o}`)}catch(r){throw r instanceof c?r:new c(400,r.message)}},bt=async(a,e)=>{await a.query("BEGIN");try{let t=await e();return await a.query("COMMIT"),console.log("[PG CONN] Commit"),t}catch(t){throw await a.query("ROLLBACK"),console.log("[PG CONN] Rollback"),t}},Ce=async a=>{let e=await gt(a),t=!1,r=!1,s=async o=>(r||await e.query(`SET search_path TO ${a.dbSchema}`),o());return{dbType:"postgres",dataSource:a,inspectSchema:()=>Et(a,e),executeQuery:(o,n)=>s(()=>n.type==="SELECT"?Re(o,e,n):bt(e,()=>Re(o,e,n))),checkConnection:async()=>{},isClosed:()=>t,close:async()=>{if(!t)return t=!0,e.end()}}};var q=async(a,e)=>{try{let t;if(a.dbType==="mysql")t=await be(a);else if(a.dbType==="postgres")t=await Ce(a);else throw new c(500,`Connection manager for ${a.dbType} not found`);return e.__connections?e.__connections.push(t):e.__connections=[t],t}catch(t){throw console.error(t),t instanceof c?t:t?.code==="ECONNREFUSED"?new c(500,"Failed to connect to the database"):new c(500,t.message)}};var Ae=h(a=>{a.get("/:id",async e=>{let{id:t}=y(e),r=await g.findOne({where:{id:t}});if(!r)throw new c(404,"Data source not found");return{data:r}}),a.get("/",async e=>{let{teamId:t}=M(e);return{data:await g.find({where:{team:{id:t}},order:{createdAt:"DESC"}})}}),a.post("/",async(e,t)=>{let{teamId:r,ownerId:s,...o}=f(e,we),n=g.create({...o,team:{id:r},owner:{id:s}}),u=await q(n,e);try{await u.checkConnection()}catch{throw new c(400,"Cannot connect to the database, please check datasource configuration")}return{data:await g.save(n)}}),a.put("/:id",async(e,t)=>{let{id:r}=y(e),s=f(e),o=await g.findOneBy({id:r});if(!o)throw new c(404,"Data source not found");let n=g.merge(o,s);return await g.save(n),{data:n}}),a.delete("/:id",async(e,t)=>w.transaction(async()=>{let{id:r}=y(e);await Promise.all([P.delete({datasource:{id:r}}),S.delete({dataSource:{id:r}})]),await g.delete({id:r})})),a.post("/:id/inspect",async(e,t)=>{let{id:r}=y(e),s=await g.findOneBy({id:r});if(!s)throw new Error("Data source not found");s.status="INSPECTING",await g.save(s);let n=await(await q(s,e)).inspectSchema();await P.delete({datasource:{id:r}}),await P.insert(n.sort().map(u=>P.create({tableName:u.tableName,columns:u.columns,datasource:{id:r}}))),s.status="READY",s.lastInspected=new Date,await g.save(s)}),a.get("/:id/inspections",async(e,t)=>{let{id:r}=y(e);return{data:await P.find({where:{datasource:{id:r}}})}})});var Pe=h(a=>{a.get("/team/:teamId/files",async(e,t)=>{let{teamId:r}=y(e),s={where:{team:{id:r}},order:{name:"ASC"},select:{id:!0,name:!0,updatedAt:!0}},[o=[],n=[],u=[]]=await Promise.all([g.find(s),b.find({...s,where:{...s.where,isTrash:!1}}),S.find({...s,where:{...s.where,isTrash:!1}})]);return{data:[...o.map(i=>({...i,type:"dataSource"})),...n.map(i=>({...i,type:"workbook"})),...u.map(i=>({...i,type:"query"}))]}}),a.get("/team/:teamId/trash",async e=>{let{teamId:t}=y(e);return{data:await w.query(`
58
+ select id, name, updatedAt
59
+ from workbooks
60
+ where teamId = '${t}' AND (isTrash = true OR isTrash IS NULL)
61
+ order by name asc
62
+ limit 100;
63
+ `)}})});function W(a,e=void 0){try{if(a){let t=a.split("&"),r={};for(let s of t){let o=s.split(":");r[o[0]]=o[1]}return r}}catch{}return e}var ke=A(re()),Me=h(a=>{a.get("/",async e=>{let{dataSourceId:t,teamId:r,limit:s,orderBy:o}=M(e);if(!t&&!r)throw new c(400,"Either dsId or teamId is required");let n={isTrash:!1};return t&&(n.dataSource={id:t}),r&&(n.team={id:r}),{data:await S.find({where:n,take:s,order:W(o,{createdAt:"DESC"})})}}),a.get("/:id",async e=>{let{id:t}=y(e),r=await S.findOne({where:{id:t},select:{dataSource:{id:!0}},relations:{dataSource:!0}});return r?{data:r}:{status:404,data:"Query not found"}}),a.post("/",async e=>{let t=f(e),r=await g.findOne({where:{id:t.dataSourceId},relations:{team:!0}});return{data:await S.save(S.create({name:t.name,isTrash:!1,team:{id:r?.team.id},dataSource:{id:t.dataSourceId}}))}}),a.patch("/:id",async e=>{let{id:t}=y(e),r=f(e);if(!(await S.update(t,r)).affected)throw new c(404,"Workbook not found");return{data:await S.findOneBy({id:t})}}),a.delete("/:id",async e=>w.transaction(async()=>{let{id:t}=y(e);if(!(await S.delete({id:t})).affected)return{status:404,data:"Workbook not found"}})),a.get("/:id/content",async e=>{let{id:t}=y(e),r=await S.findOneBy({id:t});if(!r)throw new c(404,"Workbook not found");try{let s=await B(r?.path);if(s)return{data:s}}catch{}return{data:""}}),a.patch("/:id/content",async e=>{let{id:t}=y(e),r=f(e);if(new ke.SQLManipulator(r.content).getParsed().type!=="SELECT")throw new c(400,"Query can only be of type SELECT");let o=await S.findOneBy({id:t});if(!o?.path)throw new c(404,"Workbook not found");await v(o?.path,r.content),await S.update(o.id,{updatedAt:new Date})})});var xe=A(re()),Fe=require("typeorm");function qe(a,e,t){return`${a.replace(/;\s*$/,"").trim()} LIMIT ${e} OFFSET ${t}`}function Ue(a,e){return a.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g,(t,r)=>{if(!(r in e))throw new Error(`Missing value for SQL variable: ${r}`);return String(e[r])})}function Le(a){let t=a.replace(/--.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"").trim().match(/^\s*(\(?\s*)*([a-zA-Z]+)/);if(!t)throw new c(400,"Failed to detect query type");return t[2].toUpperCase()}function It(a){return a||20}function Ct(a){return a||0}function At(a){return a.includes(" ")&&!a.startsWith("'")?`\`${a}\``:a}var Qe=async(a,{sql:e,variables:t,datasourceId:r,filters:s,joins:o,orderBy:n,size:u,page:i,columns:d,groupBy:l})=>{let T=await g.findOneBy({id:r}),p=[],m=[];if(!T)throw new c(404,"Data source not found");let E=new xe.SQLManipulator(e,T.dbType);if(t&&E.setParameters(t),E.getParsed().type==="SELECT"){E.setLimit(u||20),E.setOffset(u*i),s?.forEach(R=>{E.addWhere(R)}),o&&E.addJoin(...o),n&&E.addOrderBy(...n.map(R=>({...R,column:At(R.column)}))),d&&d.length>0&&E.selectColumns(d),l&&l.length>0&&l.forEach(R=>E.addGroupBy(R));let L=E.getParsed();L.table&&p.push(L.table),L.joins&&L.joins.length>0&&L.joins.forEach(R=>{p.push(R.table)});let Xe=await P.find({where:{tableName:(0,Fe.In)(p),datasource:{id:r}}});for(let R of Xe)if(R.columns)for(let et of R.columns)m.push({column:et.name,table:R.tableName||""})}return{...await(await q(T,a)).executeQuery(E.toExecutableSQL(),{type:E.getParsed().type,allowBulkUpdate:!1}),tables:p,allColumns:m}},$e=async(a,{sql:e,variables:t,datasourceId:r,size:s,page:o})=>{let n=await g.findOneBy({id:r});if(!n)throw new c(404,"Data source not found");let u=Le(e),i=e;if(u==="SELECT"){if(i.match(/LIMIT|OFFSET/ig))throw new c(400,"Queries are automatically paginated, do not use LIMIT and/or OFFSET");let l=It(s);i=qe(i,l,l*Ct(o))}return t&&(i=Ue(i,t)),(await q(n,a)).executeQuery(i,{type:u,allowBulkUpdate:!1})};var Be=h(a=>{a.post("/sql",async e=>{let t=f(e);return{data:await Qe(e,t)}}),a.post("/raw",async e=>{let t=f(e);return{data:await $e(e,t)}})});var ve=require("node:child_process"),We=h(a=>{a.get("/",async(e,t)=>({data:{active:!0,version:process.env.SERVER_VERSION}})),a.get("/logs",async()=>{(0,ve.spawn)(`echo "${process.env.SERVER_VERSION}"`)})});var je=h(a=>{a.get("/",async(e,t)=>{let r=D(e);return{data:await k.find({where:{users:{id:r}}})}}),a.post("/",async(e,t)=>w.transaction(async()=>{let r=D(e),s=f(e),o=I.create();o.id=r;let n=k.create(s);return n.users=[o],await k.save(n),{data:n}}))});var He=async a=>({email:"local@localhost",sub:"local"});async function Ye(){let a=k.create({name:"Personal"}),e=await I.save(I.create({}));return a.users=[e],await k.save(a),await I.update(e.id,{currentTeam:{id:a.id}}),I.findOne({where:{},relations:{currentTeam:!0}})}var Ge=h(a=>{a.post("/register",async(e,t)=>{let r=await He(e);if(!r?.email||!r?.sub)throw new c(400,"Invalid token");return{data:await Ye()}}),a.get("/",async(e,t)=>{let r=await I.findOne({where:{},relations:{currentTeam:!0}});return r?{data:r}:{data:await Ye()}}),a.put("/",async(e,t)=>{let r=D(e),s=f(e);if(!(await I.update(r,s)).affected)throw new c(404,"User not found");return{data:I.findOneBy({id:r})}}),a.put("/team",async(e,t)=>{let r=D(e),s=f(e);return await I.update(r,{currentTeam:{id:s.teamId}}),{data:await I.findOne({where:{id:r},relations:{currentTeam:!0}})}})});var Pt="********************************************",Ve=a=>a.slice(0,4)+Pt+a.slice(a.length-4);function _t(a){let e=_.create(a);return a.openAiToken&&(e.openAiToken=Ve(a.openAiToken)),e}var ze=h(a=>{a.get("/",async e=>{let t=D(e),r=await _.findOneBy({user:{id:t}});return r||(r=await _.save(_.create({user:{id:t},model:"gpt-4o"}))),{data:_t(r)}}),a.patch("/",async e=>{let{settings:t}=f(e);if(!t.id)throw new c(400,"Settings id is required!");if(!(await _.update(t.id,t)).affected)throw new c(404,"You do not own these settings!");return{data:await _.findOneBy({id:t.id})}})});var Je=h(a=>{a.get("/",async e=>{let{dsId:t,teamId:r,limit:s,orderBy:o}=M(e);if(!t&&!r)throw new c(400,"Either dsId or teamId is required");return{data:await b.find({where:{team:{id:r},isTrash:!1},take:s,order:W(o,{createdAt:"DESC"})})}}),a.get("/:id",async e=>{let{id:t}=y(e),r=await b.findOneBy({id:t});return r?{data:r}:{status:404,data:"Workbook not found"}}),a.post("/",async e=>{let t=f(e);return{data:await b.save(b.create({name:t.name,isTrash:!1,team:{id:t.teamId}}))}}),a.patch("/:id",async e=>{let{id:t}=y(e),r=f(e);if(!(await b.update(t,r)).affected)throw new c(404,"Workbook not found");return{data:await b.findOneBy({id:t})}}),a.delete("/:id",async e=>{let{id:t}=y(e);if(!(await b.delete({id:t})).affected)return{status:404,data:"Workbook not found"}}),a.get("/:id/content",async e=>{let{id:t}=y(e),r=await b.findOneBy({id:t});if(!r)throw new c(404,"Workbook not found");try{let s=await B(r?.path);if(s)return{data:s}}catch{}return{data:""}}),a.patch("/:id/content",async e=>{let{id:t}=y(e),r=f(e),s=await b.findOneBy({id:t});if(!s?.path)throw new c(404,"Workbook not found");await v(s?.path,r.content),await b.update(s.id,{updatedAt:new Date})})});var U=(0,Ke.default)(),Dt=process.env.PORT?parseInt(process.env.PORT):4466;function C(a,e){U.register(a,{prefix:e}),console.log("Registered "+e)}async function Ot(){await ge(),C(Te,"/api/chat"),C(Ae,"/api/data-sources"),C(Pe,"/api/project"),C(Me,"/api/queries"),C(Be,"/api/runner"),C(We,"/api/status"),C(je,"/api/teams"),C(Ge,"/api/users"),C(ze,"/api/user-settings"),C(Je,"/api/workbooks"),U.register(Ze.default,{origin:"*",methods:"*"}),U.addHook("onResponse",async a=>{a.__connections&&a.__connections.forEach(e=>{e.close()})}),U.setErrorHandler((a,e,t)=>{if(a instanceof c){console.error(a),t.status(a.status).send({error:a.message});return}else console.error(a),t.status(500).send({error:"Internal Server Error"})}),await U.after(),await fe(),U.listen({port:Dt,host:"0.0.0.0"},(a,e)=>{a&&(console.error(a),process.exit(1)),console.log(`Server listening at ${e}`)})}Ot();
@@ -0,0 +1,5 @@
1
+ PORT=4466
2
+
3
+ TYPEORM_CONNECTION=sqlite
4
+ TYPEORM_DATABASE=<home>/.odemian/.runtime/db.sqlite3
5
+ TYPEORM_SYNCHRONIZE=true
@@ -0,0 +1 @@
1
+ {"name":"@odemian/sql-local-server-proxy","version":"0.0.30","license":"MIT","main":"code/proxy.js","dependencies":{"@fastify/cors":"^11.0.1","dotenv":"^16.5.0","fast-glob":"^3.3.3","fastify":"^5.3.2","mysql2":"^3.14.1","pg":"^8.15.6","sqlite3":"^5.1.7","typeorm":"^0.3.23"}}
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@dataramen/cli",
3
+ "version": "0.0.2",
4
+ "license": "MIT",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "dataramen-cli": "bin/run.js"
8
+ },
9
+ "scripts": {
10
+ "build": "node build.js"
11
+ },
12
+ "dependencies": {
13
+ "yargs": "^18.0.0",
14
+ "fs-extra": "^11.3.0"
15
+ },
16
+ "files": [
17
+ "dist/"
18
+ ]
19
+ }