@dataramen/cli 0.0.9 → 0.0.10
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/README.md +67 -0
- package/dist/code/api/chat/router.js +55 -0
- package/dist/code/api/dataSources/router.js +147 -0
- package/dist/code/api/dataSources/types.js +2 -0
- package/dist/code/api/dataSources/validators.js +22 -0
- package/dist/code/api/project/router.js +100 -0
- package/dist/code/api/queries/router.js +122 -0
- package/dist/code/api/runner/router.js +22 -0
- package/dist/code/api/status/router.js +17 -0
- package/dist/code/api/teams/router.js +35 -0
- package/dist/code/api/userSettings/router.js +54 -0
- package/dist/code/api/users/router.js +91 -0
- package/dist/code/api/workbooks/router.js +123 -0
- package/dist/code/api/workbooks/types.js +2 -0
- package/dist/code/env.js +25 -0
- package/dist/code/index.js +86 -0
- package/dist/code/proxy.js +8 -8
- package/dist/code/repository/db.js +58 -0
- package/dist/code/repository/tables/databaseInspection.js +40 -0
- package/dist/code/repository/tables/datasource.js +86 -0
- package/dist/code/repository/tables/query.js +50 -0
- package/dist/code/repository/tables/teams.js +48 -0
- package/dist/code/repository/tables/userSettings.js +39 -0
- package/dist/code/repository/tables/users.js +42 -0
- package/dist/code/repository/tables/workbook.js +43 -0
- package/dist/code/services/connectorManager/index.js +38 -0
- package/dist/code/services/connectorManager/types.js +2 -0
- package/dist/code/services/files/index.js +44 -0
- package/dist/code/services/mysqlConnector/index.js +180 -0
- package/dist/code/services/oauthClient/oauth2Client.js +10 -0
- package/dist/code/services/openai/index.js +20 -0
- package/dist/code/services/openai/types.js +2 -0
- package/dist/code/services/pgConnector/index.js +220 -0
- package/dist/code/services/userSqlPromptRunner/index.js +207 -0
- package/dist/code/types/connectors.js +2 -0
- package/dist/code/utils/createRouter.js +10 -0
- package/dist/code/utils/httpError.js +13 -0
- package/dist/code/utils/prompts.js +11 -0
- package/dist/code/utils/queryUtils.js +18 -0
- package/dist/code/utils/rawSql.js +32 -0
- package/dist/code/utils/request.js +35 -0
- package/dist/code/utils/token.js +8 -0
- package/dist/package.json +1 -1
- package/package.json +21 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const createRouter_1 = require("../../utils/createRouter");
|
|
4
|
+
const request_1 = require("../../utils/request");
|
|
5
|
+
const httpError_1 = require("../../utils/httpError");
|
|
6
|
+
const oauth2Client_1 = require("../../services/oauthClient/oauth2Client");
|
|
7
|
+
const db_1 = require("../../repository/db");
|
|
8
|
+
async function createUser() {
|
|
9
|
+
const team = db_1.TeamRepository.create({
|
|
10
|
+
name: "Personal",
|
|
11
|
+
});
|
|
12
|
+
const user = await db_1.UserRepository.save(db_1.UserRepository.create({}));
|
|
13
|
+
team.users = [user];
|
|
14
|
+
await db_1.TeamRepository.save(team);
|
|
15
|
+
await db_1.UserRepository.update(user.id, {
|
|
16
|
+
currentTeam: {
|
|
17
|
+
id: team.id,
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
return db_1.UserRepository.findOne({
|
|
21
|
+
where: {},
|
|
22
|
+
relations: {
|
|
23
|
+
currentTeam: true,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
exports.default = (0, createRouter_1.createRouter)((instance) => {
|
|
28
|
+
instance.post("/register", async (request, reply) => {
|
|
29
|
+
const userInfo = await (0, oauth2Client_1.getTokenInfoFromRequest)(request);
|
|
30
|
+
if (!userInfo?.email || !userInfo?.sub) {
|
|
31
|
+
throw new httpError_1.HttpError(400, "Invalid token");
|
|
32
|
+
}
|
|
33
|
+
const user = await createUser();
|
|
34
|
+
return {
|
|
35
|
+
data: user,
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
// get user
|
|
39
|
+
instance.get("/", async (request, reply) => {
|
|
40
|
+
const user = await db_1.UserRepository.findOne({
|
|
41
|
+
where: {}, // select first user
|
|
42
|
+
relations: {
|
|
43
|
+
currentTeam: true,
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
if (!user) {
|
|
47
|
+
const user = await createUser();
|
|
48
|
+
return {
|
|
49
|
+
data: user,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
data: user,
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
// update user
|
|
57
|
+
instance.put("/", async (request, reply) => {
|
|
58
|
+
const userId = (0, request_1.getRequestUserId)(request);
|
|
59
|
+
const payload = (0, request_1.getRequestPayload)(request);
|
|
60
|
+
const result = await db_1.UserRepository.update(userId, payload);
|
|
61
|
+
if (!result.affected) {
|
|
62
|
+
throw new httpError_1.HttpError(404, "User not found");
|
|
63
|
+
}
|
|
64
|
+
const user = db_1.UserRepository.findOneBy({
|
|
65
|
+
id: userId,
|
|
66
|
+
});
|
|
67
|
+
return {
|
|
68
|
+
data: user,
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
instance.put('/team', async (request, reply) => {
|
|
72
|
+
const userId = (0, request_1.getRequestUserId)(request);
|
|
73
|
+
const payload = (0, request_1.getRequestPayload)(request);
|
|
74
|
+
await db_1.UserRepository.update(userId, {
|
|
75
|
+
currentTeam: {
|
|
76
|
+
id: payload.teamId,
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
const user = await db_1.UserRepository.findOne({
|
|
80
|
+
where: {
|
|
81
|
+
id: userId,
|
|
82
|
+
},
|
|
83
|
+
relations: {
|
|
84
|
+
currentTeam: true,
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
return {
|
|
88
|
+
data: user,
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const createRouter_1 = require("../../utils/createRouter");
|
|
4
|
+
const request_1 = require("../../utils/request");
|
|
5
|
+
const queryUtils_1 = require("../../utils/queryUtils");
|
|
6
|
+
const httpError_1 = require("../../utils/httpError");
|
|
7
|
+
const db_1 = require("../../repository/db");
|
|
8
|
+
const files_1 = require("../../services/files");
|
|
9
|
+
exports.default = (0, createRouter_1.createRouter)((instance) => {
|
|
10
|
+
instance.get("/", async (request) => {
|
|
11
|
+
const { dsId, teamId, limit, orderBy } = (0, request_1.getRequestQuery)(request);
|
|
12
|
+
if (!dsId && !teamId) {
|
|
13
|
+
throw new httpError_1.HttpError(400, "Either dsId or teamId is required");
|
|
14
|
+
}
|
|
15
|
+
const workbooks = await db_1.WorkbookRepository.find({
|
|
16
|
+
where: {
|
|
17
|
+
team: {
|
|
18
|
+
id: teamId,
|
|
19
|
+
},
|
|
20
|
+
isTrash: false,
|
|
21
|
+
},
|
|
22
|
+
take: limit,
|
|
23
|
+
order: (0, queryUtils_1.parseOrderQueryParam)(orderBy, {
|
|
24
|
+
createdAt: "DESC",
|
|
25
|
+
})
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
data: workbooks,
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
instance.get("/:id", async (request) => {
|
|
32
|
+
const { id } = (0, request_1.getRequestParams)(request);
|
|
33
|
+
const workbook = await db_1.WorkbookRepository.findOneBy({
|
|
34
|
+
id,
|
|
35
|
+
});
|
|
36
|
+
if (!workbook) {
|
|
37
|
+
return {
|
|
38
|
+
status: 404,
|
|
39
|
+
data: "Workbook not found",
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
data: workbook,
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
instance.post("/", async (request) => {
|
|
47
|
+
const payload = (0, request_1.getRequestPayload)(request);
|
|
48
|
+
const workbook = await db_1.WorkbookRepository.save(db_1.WorkbookRepository.create({
|
|
49
|
+
name: payload.name,
|
|
50
|
+
isTrash: false,
|
|
51
|
+
team: {
|
|
52
|
+
id: payload.teamId,
|
|
53
|
+
}
|
|
54
|
+
}));
|
|
55
|
+
return {
|
|
56
|
+
data: workbook,
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
// update workbook
|
|
60
|
+
instance.patch("/:id", async (request) => {
|
|
61
|
+
const { id } = (0, request_1.getRequestParams)(request);
|
|
62
|
+
const payload = (0, request_1.getRequestPayload)(request);
|
|
63
|
+
const result = await db_1.WorkbookRepository.update(id, payload);
|
|
64
|
+
if (!result.affected) {
|
|
65
|
+
throw new httpError_1.HttpError(404, "Workbook not found");
|
|
66
|
+
}
|
|
67
|
+
const workbook = await db_1.WorkbookRepository.findOneBy({
|
|
68
|
+
id,
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
data: workbook,
|
|
72
|
+
};
|
|
73
|
+
});
|
|
74
|
+
// delete workbook
|
|
75
|
+
instance.delete("/:id", async (request) => {
|
|
76
|
+
const { id } = (0, request_1.getRequestParams)(request);
|
|
77
|
+
// todo: delete file
|
|
78
|
+
const result = await db_1.WorkbookRepository.delete({
|
|
79
|
+
id
|
|
80
|
+
});
|
|
81
|
+
if (!result.affected) {
|
|
82
|
+
return {
|
|
83
|
+
status: 404,
|
|
84
|
+
data: "Workbook not found",
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
instance.get("/:id/content", async (request) => {
|
|
89
|
+
const { id } = (0, request_1.getRequestParams)(request);
|
|
90
|
+
const workbook = await db_1.WorkbookRepository.findOneBy({
|
|
91
|
+
id,
|
|
92
|
+
});
|
|
93
|
+
if (!workbook) {
|
|
94
|
+
throw new httpError_1.HttpError(404, "Workbook not found");
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const file = await (0, files_1.getFile)(workbook?.path);
|
|
98
|
+
if (file) {
|
|
99
|
+
return {
|
|
100
|
+
data: file,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (e) { }
|
|
105
|
+
return {
|
|
106
|
+
data: "",
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
instance.patch("/:id/content", async (request) => {
|
|
110
|
+
const { id } = (0, request_1.getRequestParams)(request);
|
|
111
|
+
const body = (0, request_1.getRequestPayload)(request);
|
|
112
|
+
const workbook = await db_1.WorkbookRepository.findOneBy({
|
|
113
|
+
id,
|
|
114
|
+
});
|
|
115
|
+
if (!workbook?.path) {
|
|
116
|
+
throw new httpError_1.HttpError(404, "Workbook not found");
|
|
117
|
+
}
|
|
118
|
+
await (0, files_1.storeFile)(workbook?.path, body.content);
|
|
119
|
+
await db_1.WorkbookRepository.update(workbook.id, {
|
|
120
|
+
updatedAt: new Date()
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
package/dist/code/env.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const dotenv_1 = require("dotenv");
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const packageJson = (() => {
|
|
7
|
+
try {
|
|
8
|
+
const file = (0, node_fs_1.readFileSync)((0, node_path_1.join)(__dirname, "..", "package.json"), "utf8");
|
|
9
|
+
return JSON.parse(file);
|
|
10
|
+
}
|
|
11
|
+
catch (e) {
|
|
12
|
+
return {
|
|
13
|
+
version: "0.0.0",
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
})();
|
|
17
|
+
(0, dotenv_1.config)({
|
|
18
|
+
path: [
|
|
19
|
+
(0, node_path_1.join)(__dirname, "..", "env", ".env"),
|
|
20
|
+
(0, node_path_1.join)(__dirname, "..", "env", ".env.default"),
|
|
21
|
+
],
|
|
22
|
+
});
|
|
23
|
+
(0, dotenv_1.populate)(process.env, {
|
|
24
|
+
SERVER_VERSION: packageJson.version,
|
|
25
|
+
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
require("./env");
|
|
7
|
+
const fastify_1 = __importDefault(require("fastify"));
|
|
8
|
+
const cors_1 = __importDefault(require("@fastify/cors"));
|
|
9
|
+
const httpError_1 = require("./utils/httpError");
|
|
10
|
+
const db_1 = require("./repository/db");
|
|
11
|
+
const files_1 = require("./services/files");
|
|
12
|
+
const router_1 = __importDefault(require("./api/chat/router"));
|
|
13
|
+
const router_2 = __importDefault(require("./api/dataSources/router"));
|
|
14
|
+
const router_3 = __importDefault(require("./api/project/router"));
|
|
15
|
+
const router_4 = __importDefault(require("./api/queries/router"));
|
|
16
|
+
const router_5 = __importDefault(require("./api/runner/router"));
|
|
17
|
+
const router_6 = __importDefault(require("./api/status/router"));
|
|
18
|
+
const router_7 = __importDefault(require("./api/teams/router"));
|
|
19
|
+
const router_8 = __importDefault(require("./api/users/router"));
|
|
20
|
+
const router_9 = __importDefault(require("./api/userSettings/router"));
|
|
21
|
+
const router_10 = __importDefault(require("./api/workbooks/router"));
|
|
22
|
+
const server = (0, fastify_1.default)();
|
|
23
|
+
const PORT = process.env.PORT ? parseInt(process.env.PORT) : 4466;
|
|
24
|
+
function registerRouter(fn, prefix) {
|
|
25
|
+
server.register(fn, { prefix });
|
|
26
|
+
console.log("Registered " + prefix);
|
|
27
|
+
}
|
|
28
|
+
async function initialize() {
|
|
29
|
+
await (0, files_1.setupProjectFolders)(); // creates .dataramen/files
|
|
30
|
+
// const routers = glob.sync("./api/**/router.js", {
|
|
31
|
+
// cwd: __dirname,
|
|
32
|
+
// });
|
|
33
|
+
//
|
|
34
|
+
// routers.forEach((file) => {
|
|
35
|
+
// const apiName = file.split("/")[2];
|
|
36
|
+
// const prefix = "/api/" + folderNameToSnakeCase(apiName);
|
|
37
|
+
// server.register(require(file), { prefix });
|
|
38
|
+
// console.log(`${prefix} -> ${apiName} controller `);
|
|
39
|
+
// });
|
|
40
|
+
registerRouter(router_1.default, `/api/chat`);
|
|
41
|
+
registerRouter(router_2.default, `/api/data-sources`);
|
|
42
|
+
registerRouter(router_3.default, `/api/project`);
|
|
43
|
+
registerRouter(router_4.default, `/api/queries`);
|
|
44
|
+
registerRouter(router_5.default, `/api/runner`);
|
|
45
|
+
registerRouter(router_6.default, `/api/status`);
|
|
46
|
+
registerRouter(router_7.default, `/api/teams`);
|
|
47
|
+
registerRouter(router_8.default, `/api/users`);
|
|
48
|
+
registerRouter(router_9.default, `/api/user-settings`);
|
|
49
|
+
registerRouter(router_10.default, `/api/workbooks`);
|
|
50
|
+
server.register(cors_1.default, {
|
|
51
|
+
origin: "*",
|
|
52
|
+
methods: "*",
|
|
53
|
+
});
|
|
54
|
+
server.addHook("onResponse", async (request) => {
|
|
55
|
+
if (request.__connections) {
|
|
56
|
+
request.__connections.forEach((connection) => {
|
|
57
|
+
connection.close();
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
server.setErrorHandler((error, request, reply) => {
|
|
62
|
+
if (error instanceof httpError_1.HttpError) {
|
|
63
|
+
console.error(error);
|
|
64
|
+
reply.status(error.status).send({
|
|
65
|
+
error: error.message,
|
|
66
|
+
});
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.error(error);
|
|
71
|
+
reply.status(500).send({
|
|
72
|
+
error: "Internal Server Error",
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
await server.after();
|
|
77
|
+
await (0, db_1.init)();
|
|
78
|
+
server.listen({ port: PORT, host: '0.0.0.0' }, (err, address) => {
|
|
79
|
+
if (err) {
|
|
80
|
+
console.error(err);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
console.log(`Server listening at ${address}`);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
initialize();
|
package/dist/code/proxy.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"use strict";var rt=Object.create;var ee=Object.defineProperty;var at=Object.getOwnPropertyDescriptor;var st=Object.getOwnPropertyNames;var ot=Object.getPrototypeOf,nt=Object.prototype.hasOwnProperty;var W=(a,e)=>()=>(e||a((e={exports:{}}).exports,e),e.exports);var it=(a,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of st(e))!nt.call(a,s)&&s!==t&&ee(a,s,{get:()=>e[s],enumerable:!(r=at(e,s))||r.enumerable});return a};var P=(a,e,t)=>(t=a!=null?rt(ot(a)):{},it(e||!a||!a.__esModule?ee(t,"default",{value:a,enumerable:!0}):t,a));var De=W(_e=>{"use strict";Object.defineProperty(_e,"__esModule",{value:!0})});var ke=W(D=>{"use strict";Object.defineProperty(D,"__esModule",{value:!0});D.SQLManipulator=D.SQLBuilder=D.SQLParser=void 0;var v=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 p=o[1].trim();t.columns=p==="*"?["*"]:this.parseColumns(p)}let n=r.match(/FROM\s+([^\s]+)(?:\s|$)/i);if(n&&(t.table=n[1]),!t.table){let p=r.match(/FROM\s+([^\s]+)(?:\s+(?:AS\s+)?([^\s]+))?(?:\s+(?:WHERE|JOIN|INNER|LEFT|RIGHT|FULL|GROUP|ORDER|LIMIT|OFFSET|HAVING)|$)/i);p&&(t.table=p[1])}t.joins=this.parseJoins(r);let c=r.match(/WHERE\s+(.*?)(?:\s+GROUP\s+BY|\s+ORDER\s+BY|\s+LIMIT|\s+OFFSET|$)/i);c&&(t.where=this.restoreSubqueries(c[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 m=r.match(/OFFSET\s+(\d+)/i);return m&&(t.offset=parseInt(m[1])),t}parseColumns(e){let t=[],r="",s=!1,o="",n=0;for(let c=0;c<e.length;c++){let i=e[c];!s&&(i==='"'||i==="'")?(s=!0,o=i,r+=i):s&&i===o?c+1<e.length&&e[c+1]===o?(r+=i+i,c++):(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,(c,i)=>{if(/\b(SELECT|INSERT|UPDATE|DELETE)\b/i.test(i)){let d=`__SUBQUERY_${s}__`;return t.set(d,c),s++,n=!0,d}return c});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(),c=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:c})}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(),c=s.substring(o+1).trim();t[n]=c}}),t}};D.SQLParser=v;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}};D.SQLBuilder=F;var X=class{constructor(e="mysql",t){this.dialect=e,this.parser=new v(e),this.parsed=t==="SELECT"?{type:"SELECT"}:this.parser.parse(t),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}setTable(e){return this.parsed.table=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],c=typeof n=="string"?`'${n}'`:n;return`${t} ${r} ${c}`}}};D.SQLManipulator=X});var Me=W(k=>{"use strict";var It=k&&k.__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]}),qe=k&&k.__exportStar||function(a,e){for(var t in a)t!=="default"&&!Object.prototype.hasOwnProperty.call(e,t)&&It(e,a,t)};Object.defineProperty(k,"__esModule",{value:!0});qe(De(),k);qe(ke(),k)});var $=require("dotenv"),Q=require("node:path"),te=require("node:fs"),ct=(()=>{try{let a=(0,te.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:ct.version});var Ze=P(require("fastify")),Xe=P(require("@fastify/cors"));var u=class extends Error{constructor(t,r){super(r);this.status=t;this.message=r}};var ue=require("typeorm");var re=require("typeorm"),j=new re.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 ae=require("typeorm"),H=new ae.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 se=require("typeorm"),Y=new se.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 oe=require("typeorm"),G=new oe.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 ne=require("typeorm"),V=new ne.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 ie=require("typeorm"),z=new ie.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 de=P(require("os"));var ce=require("typeorm"),K=new ce.EntitySchema({name:"Query",tableName:"query",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},opts:{type:"json",default:"{}"},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 ut(){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>",de.default.homedir())),a}var E=new ue.DataSource({type:process.env.TYPEORM_CONNECTION,database:ut(),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:[j,z,H,Y,G,V,K]}),me=async()=>{if(!E.isInitialized)return E.initialize();throw new Error("Already initialized")},C=E.getRepository(j),g=E.getRepository(z),q=E.getRepository(H),R=E.getRepository(Y),O=E.getRepository(G),S=E.getRepository(V),I=E.getRepository(K);var x=P(require("node:fs/promises")),J=require("node:path"),pe=P(require("node:os")),dt=pe.default.homedir(),Z=(0,J.join)(dt,".dataramen",".runtime","files"),le=a=>(0,J.join)(Z,a),fe=async a=>x.default.readFile(le(a),{encoding:"utf8"}),ye=async(a,e)=>x.default.writeFile(le(a),e,{encoding:"utf8"});var he=async()=>{await mt()||await x.default.mkdir(Z,{recursive:!0})};async function mt(){try{return(await x.default.lstat(Z)).isDirectory()}catch{return!1}}var f=a=>(e,t,r)=>{a(e),r()};var ge=f(a=>{a.post("/workbook",async e=>({data:""}))});var y=(a,e)=>{let t=a.body;return e&&e(t),t},N=(a,e)=>{let t=a.query;return e&&e(t),t},h=(a,e)=>{let t=a.params;return e&&e(t),t};var _=a=>a.headers["phoenix-user-id"];var Te=a=>{if(!a.dbUrl)throw new u(400,"url is required");if(!a.dbUser)throw new u(400,"user is required");if(!a.dbType)throw new u(400,"type is required");if(!a.name)throw new u(400,"name is required");if(!a.dbDatabase)throw new u(400,"database is required")};var we=P(require("mysql2/promise"));var lt=({dbDatabase:a,dbPassword:e,dbUser:t,dbUrl:r})=>we.default.createConnection({host:r,user:t,database:a,password:e}),ft=async a=>{let e=`
|
|
1
|
+
"use strict";var ot=Object.create;var te=Object.defineProperty;var nt=Object.getOwnPropertyDescriptor;var it=Object.getOwnPropertyNames;var ct=Object.getPrototypeOf,ut=Object.prototype.hasOwnProperty;var Q=(a,e)=>()=>(e||a((e={exports:{}}).exports,e),e.exports);var dt=(a,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of it(e))!ut.call(a,s)&&s!==t&&te(a,s,{get:()=>e[s],enumerable:!(r=nt(e,s))||r.enumerable});return a};var P=(a,e,t)=>(t=a!=null?ot(ct(a)):{},dt(e||!a||!a.__esModule?te(t,"default",{value:a,enumerable:!0}):t,a));var ke=Q(De=>{"use strict";Object.defineProperty(De,"__esModule",{value:!0})});var qe=Q(W=>{"use strict";Object.defineProperty(W,"__esModule",{value:!0});W.isString=void 0;var Ot=a=>typeof a=="string";W.isString=Ot});var Le=Q(D=>{"use strict";Object.defineProperty(D,"__esModule",{value:!0});D.SQLManipulator=D.SQLBuilder=D.SQLParser=void 0;var Me=qe(),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 p=o[1].trim();t.columns=p==="*"?["*"]:this.parseColumns(p)}let n=r.match(/FROM\s+([^\s]+)(?:\s|$)/i);if(n&&(t.table=n[1]),!t.table){let p=r.match(/FROM\s+([^\s]+)(?:\s+(?:AS\s+)?([^\s]+))?(?:\s+(?:WHERE|JOIN|INNER|LEFT|RIGHT|FULL|GROUP|ORDER|LIMIT|OFFSET|HAVING)|$)/i);p&&(t.table=p[1])}t.joins=this.parseJoins(r);let i=r.match(/WHERE\s+(.*?)(?:\s+GROUP\s+BY|\s+ORDER\s+BY|\s+LIMIT|\s+OFFSET|$)/i);i&&(t.where=this.restoreSubqueries(i[1].trim(),s));let c=r.match(/ORDER\s+BY\s+(.*?)(?:\s+LIMIT|\s+OFFSET|$)/i);c&&(t.orderBy=this.parseOrderBy(c[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 m=r.match(/OFFSET\s+(\d+)/i);return m&&(t.offset=parseInt(m[1])),t}parseColumns(e){let t=[],r="",s=!1,o="",n=0;for(let i=0;i<e.length;i++){let c=e[i];!s&&(c==='"'||c==="'")?(s=!0,o=c,r+=c):s&&c===o?i+1<e.length&&e[i+1]===o?(r+=c+c,i++):(s=!1,o="",r+=c):!s&&c==="("?(n++,r+=c):!s&&c===")"?(n--,r+=c):!s&&c===","&&n===0?(t.push(r.trim()),r=""):r+=c}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,(i,c)=>{if(/\b(SELECT|INSERT|UPDATE|DELETE)\b/i.test(c)){let d=`__SUBQUERY_${s}__`;return t.set(d,i),s++,n=!0,d}return i});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(),i=s[3].trim(),c=n.split(/\s+/),d=c[0],l=c.length>1?c[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:i})}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(),i=s.substring(o+1).trim();t[n]=i}}),t}};D.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}};D.SQLBuilder=F;var ee=class{constructor(e="mysql",t){this.dialect=e,this.parser=new j(e),this.parsed=t==="SELECT"?{type:"SELECT"}:this.parser.parse(t),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}setTable(e){return this.parsed.table=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(c=>(0,Me.isString)(c)?`'${c}'`:c).join(", ");return`${t} ${r} (${o})`;default:let n=s?.[0],i;return(0,Me.isString)(n?.value)&&n?.isColumn!==!0?i=`'${n?.value}'`:i=n?.value,`${t} ${r} ${i}`}}};D.SQLManipulator=ee});var xe=Q(k=>{"use strict";var Pt=k&&k.__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]}),Ue=k&&k.__exportStar||function(a,e){for(var t in a)t!=="default"&&!Object.prototype.hasOwnProperty.call(e,t)&&Pt(e,a,t)};Object.defineProperty(k,"__esModule",{value:!0});Ue(ke(),k);Ue(Le(),k)});var v=require("dotenv"),$=require("node:path"),re=require("node:fs"),mt=(()=>{try{let a=(0,re.readFileSync)((0,$.join)(__dirname,"..","package.json"),"utf8");return JSON.parse(a)}catch{return{version:"0.0.0"}}})();(0,v.config)({path:[(0,$.join)(__dirname,"..","env",".env"),(0,$.join)(__dirname,"..","env",".env.default")]});(0,v.populate)(process.env,{SERVER_VERSION:mt.version});var tt=P(require("fastify")),rt=P(require("@fastify/cors"));var u=class extends Error{constructor(t,r){super(r);this.status=t;this.message=r}};var de=require("typeorm");var ae=require("typeorm"),H=new ae.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 se=require("typeorm"),Y=new se.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 oe=require("typeorm"),G=new oe.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 ne=require("typeorm"),V=new ne.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 ie=require("typeorm"),z=new ie.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 ce=require("typeorm"),K=new ce.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 me=P(require("os"));var ue=require("typeorm"),J=new ue.EntitySchema({name:"Query",tableName:"query",columns:{id:{type:"uuid",primary:!0,generated:"uuid"},name:{type:String},opts:{type:"json",default:"{}"},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 pt(){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>",me.default.homedir())),a}var E=new de.DataSource({type:process.env.TYPEORM_CONNECTION,database:pt(),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:[H,K,Y,G,V,z,J]}),pe=async()=>{if(!E.isInitialized)return E.initialize();throw new Error("Already initialized")},C=E.getRepository(H),g=E.getRepository(K),q=E.getRepository(Y),R=E.getRepository(G),O=E.getRepository(V),S=E.getRepository(z),I=E.getRepository(J);var x=P(require("node:fs/promises")),Z=require("node:path"),le=P(require("node:os")),lt=le.default.homedir(),X=(0,Z.join)(lt,".dataramen",".runtime","files"),fe=a=>(0,Z.join)(X,a),ye=async a=>x.default.readFile(fe(a),{encoding:"utf8"}),he=async(a,e)=>x.default.writeFile(fe(a),e,{encoding:"utf8"});var ge=async()=>{await ft()||await x.default.mkdir(X,{recursive:!0})};async function ft(){try{return(await x.default.lstat(X)).isDirectory()}catch{return!1}}var f=a=>(e,t,r)=>{a(e),r()};var Te=f(a=>{a.post("/workbook",async e=>({data:""}))});var y=(a,e)=>{let t=a.body;return e&&e(t),t},_=(a,e)=>{let t=a.query;return e&&e(t),t},h=(a,e)=>{let t=a.params;return e&&e(t),t};var N=a=>a.headers["phoenix-user-id"];var Ee=a=>{if(!a.dbUrl)throw new u(400,"url is required");if(!a.dbUser)throw new u(400,"user is required");if(!a.dbType)throw new u(400,"type is required");if(!a.name)throw new u(400,"name is required");if(!a.dbDatabase)throw new u(400,"database is required")};var Se=P(require("mysql2/promise"));var ht=({dbDatabase:a,dbPassword:e,dbUser:t,dbUrl:r})=>Se.default.createConnection({host:r,user:t,database:a,password:e}),gt=async a=>{let e=`
|
|
2
2
|
SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION
|
|
3
3
|
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
|
4
4
|
WHERE CONSTRAINT_NAME = 'PRIMARY'
|
|
5
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},
|
|
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},Tt=async a=>{let e=`
|
|
7
7
|
SELECT
|
|
8
8
|
TABLE_NAME AS table_name,
|
|
9
9
|
COLUMN_NAME AS field,
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
WHERE
|
|
15
15
|
REFERENCED_TABLE_NAME IS NOT NULL
|
|
16
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},
|
|
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},Et=async(a,e)=>{let r=(await e.query("SHOW TABLES"))[0],s=await Tt(e),o=await gt(e),n=r.map(async i=>{let c=Object.values(i)[0],d=`select COLUMN_NAME, DATA_TYPE from information_schema.columns where table_schema = '${a.dbDatabase}' and table_name = '${c}'`,[l]=await e.query(d),T=s[c];return{columns:l.map(m=>({name:m.COLUMN_NAME,type:m.DATA_TYPE,isPrimary:o[c]?.includes(m.COLUMN_NAME),ref:T?.[m.COLUMN_NAME]?{table:T[m.COLUMN_NAME].refTable,field:T[m.COLUMN_NAME].refField}:void 0})).sort((m,p)=>m.isPrimary&&p.isPrimary?m.name.localeCompare(p.name):m.isPrimary?-1:1),createdAt:new Date,tableName:c,updatedAt:new Date}});return Promise.all(n)},we=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(i=>({column:i.orgName||i.name,table:i.orgTable,alias:i.name,full:i.orgTable?i.orgTable+"."+i.orgName:i.name}))||[],rows:n,query:a}}throw new Error(`[MYSQL CONN] Unknown result type: ${o}`)}catch(r){throw console.error(r),r instanceof u?r:new u(400,r.message)}},wt=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 ht(a),t=!1;return{dbType:"mysql",dataSource:a,inspectSchema:()=>Et(a,e),executeQuery:(r,s)=>s.type==="SELECT"?we(r,e,s):wt(e,()=>we(r,e,s)),checkConnection:async()=>e.ping(),isClosed:()=>t,close:async()=>{if(!t)return t=!0,e.destroy()}}};var Ie=P(require("pg"));var St=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},bt=async a=>{let t=await a.query(`
|
|
18
18
|
SELECT
|
|
19
19
|
kcu.table_name,
|
|
20
20
|
kcu.column_name,
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
tc.constraint_type = 'PRIMARY KEY'
|
|
29
29
|
ORDER BY
|
|
30
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},
|
|
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},Rt=async a=>{let t=await a.query(`
|
|
32
32
|
SELECT
|
|
33
33
|
tc.table_name AS table_name,
|
|
34
34
|
kcu.column_name AS field,
|
|
@@ -43,21 +43,21 @@
|
|
|
43
43
|
ON ccu.constraint_name = tc.constraint_name
|
|
44
44
|
AND ccu.table_schema = tc.table_schema
|
|
45
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},
|
|
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},It=async(a,e)=>{let t=`SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = '${a.dbSchema}'`,s=(await e.query(t)).rows,o=await Rt(e),n=await bt(e),i=s.map(async c=>{let d=Object.values(c)[0],l=`
|
|
47
47
|
SELECT column_name, data_type
|
|
48
48
|
FROM information_schema.columns
|
|
49
49
|
WHERE
|
|
50
50
|
table_name = '${d}' and
|
|
51
51
|
table_schema = '${a.dbSchema}'
|
|
52
|
-
`,{rows:T}=await e.query(l),m=o[d];return{columns:T.map(p=>({name:p.column_name,type:p.data_type,isPrimary:n[d]?.includes(p.column_name),ref:m?.[p.column_name]?{table:m[p.column_name].refTable,field:m[p.column_name].refField}:void 0})).sort((p,w)=>p.isPrimary&&w.isPrimary?p.name.localeCompare(w.name):p.isPrimary?-1:1),createdAt:new Date,tableName:d,updatedAt:new Date}});return Promise.all(
|
|
52
|
+
`,{rows:T}=await e.query(l),m=o[d];return{columns:T.map(p=>({name:p.column_name,type:p.data_type,isPrimary:n[d]?.includes(p.column_name),ref:m?.[p.column_name]?{table:m[p.column_name].refTable,field:m[p.column_name].refField}:void 0})).sort((p,w)=>p.isPrimary&&w.isPrimary?p.name.localeCompare(w.name):p.isPrimary?-1:1),createdAt:new Date,tableName:d,updatedAt:new Date}});return Promise.all(i)},Ct=async(a,e)=>{let t=`select relname, attname, concat(pg_class.oid, '-', attnum) as row_key
|
|
53
53
|
from pg_attribute
|
|
54
54
|
left join pg_class on pg_attribute.attrelid = pg_class.oid
|
|
55
55
|
where
|
|
56
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),{})},
|
|
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 i=s.map(d=>`'${d.tableID}-${d.columnID}'`),c=await Ct(i,e);return{columns:s.map(d=>{let l=c[`${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 u?r:new u(400,r.message)}},At=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 St(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:()=>It(a,e),executeQuery:(o,n)=>s(()=>n.type==="SELECT"?Re(o,e,n):At(e,()=>Re(o,e,n))),checkConnection:async()=>{},isClosed:()=>t,close:async()=>{if(!t)return t=!0,e.end()}}};var M=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 u(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 u?t:t?.code==="ECONNREFUSED"?new u(500,"Failed to connect to the database"):new u(500,t.message)}};var Ae=f(a=>{a.get("/:id",async e=>{let{id:t}=h(e),r=await g.findOne({where:{id:t}});if(!r)throw new u(404,"Data source not found");return{data:r}}),a.get("/",async e=>{let{teamId:t}=_(e);return{data:await g.find({where:{team:{id:t}},order:{createdAt:"DESC"}})}}),a.post("/",async(e,t)=>{let{teamId:r,ownerId:s,...o}=y(e,Ee),n=g.create({...o,team:{id:r},owner:{id:s}}),i=await M(n,e);try{await i.checkConnection()}catch{throw new u(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}=h(e),s=y(e),o=await g.findOneBy({id:r});if(!o)throw new u(404,"Data source not found");let n=g.merge(o,s);return await g.save(n),{data:n}}),a.delete("/:id",async(e,t)=>E.transaction(async()=>{let{id:r}=h(e);await Promise.all([C.delete({datasource:{id:r}}),I.delete({dataSource:{id:r}})]),await g.delete({id:r})})),a.post("/:id/inspect",async(e,t)=>{let{id:r}=h(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 M(s,e)).inspectSchema();await C.delete({datasource:{id:r}}),await C.insert(n.sort().map(i=>C.create({tableName:i.tableName,columns:i.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}=h(e);return{data:await C.find({where:{datasource:{id:r}}})}})});var Oe=require("typeorm"),Pe=f(a=>{a.get("/team/:teamId/files",async(e,t)=>{let{teamId:r}=h(e),s={where:{team:{id:r}},order:{name:"ASC"},select:{id:!0,name:!0,updatedAt:!0}},[o=[],n=[],i=[]]=await Promise.all([g.find(s),S.find({...s,where:{...s.where,isTrash:!1}}),I.find({...s,where:{...s.where,isTrash:!1}})]);return{data:[...o.map(c=>({...c,type:"dataSource"})),...n.map(c=>({...c,type:"workbook"})),...i.map(c=>({...c,type:"query"}))]}}),a.get("/team/:teamId/trash",async e=>{let{teamId:t}=h(e);return{data:await E.query(`
|
|
58
58
|
select id, name, updatedAt
|
|
59
59
|
from workbooks
|
|
60
60
|
where teamId = '${t}' AND (isTrash = true OR isTrash IS NULL)
|
|
61
61
|
order by name asc
|
|
62
62
|
limit 100;
|
|
63
|
-
`)}}),a.get("/team/:teamId/tables",async e=>{let{teamId:t}=h(e),{search:r,size:s}=
|
|
63
|
+
`)}}),a.get("/team/:teamId/tables",async e=>{let{teamId:t}=h(e),{search:r,size:s}=_(e);return{data:(await C.find({where:{tableName:(0,Oe.Like)(`%${r}%`),datasource:{team:{id:t}}},relations:{datasource:!0},select:{id:!0,tableName:!0,datasource:{name:!0,id:!0}},order:{tableName:"ASC"},take:parseInt(s)||20})).map(n=>({name:n.tableName,id:n.id,dataSourceName:n.datasource?.name||"--",dataSourceId:n.datasource?.id||"--"}))}})});function B(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 _e=require("typeorm"),Ne=f(a=>{a.get("/",async e=>{let{dataSourceId:t,teamId:r,limit:s,orderBy:o,name:n}=_(e);if(!t&&!r)throw new u(400,"Either dsId or teamId is required");let i={isTrash:!1};return t&&(i.dataSource={id:t}),r&&(i.team={id:r}),n&&(i.name=(0,_e.Like)(`%${n}%`)),{data:await I.find({where:i,take:s,order:B(o,{createdAt:"DESC"})})}}),a.get("/:id",async e=>{let{id:t}=h(e),r=await I.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=y(e),r=await g.findOne({where:{id:t.dataSourceId},relations:{team:!0}});return{data:await I.save(I.create({name:t.name,isTrash:!1,opts:t.opts,team:{id:r?.team.id},dataSource:{id:t.dataSourceId}}))}}),a.patch("/:id",async e=>{let{id:t}=h(e),r=y(e);if(!(await I.update(t,r)).affected)throw new u(404,"Workbook not found");return{data:await I.findOneBy({id:t})}}),a.delete("/:id",async e=>E.transaction(async()=>{let{id:t}=h(e);if(!(await I.delete({id:t})).affected)return{status:404,data:"Workbook not found"}}))});var ve=P(xe()),Be=require("typeorm");function Fe(a,e,t){return`${a.replace(/;\s*$/,"").trim()} LIMIT ${e} OFFSET ${t}`}function Qe(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 $e(a){let t=a.replace(/--.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,"").trim().match(/^\s*(\(?\s*)*([a-zA-Z]+)/);if(!t)throw new u(400,"Failed to detect query type");return t[2].toUpperCase()}function _t(a){return a||20}function Nt(a){return a||0}function Dt(a){return a.includes(" ")&&!a.startsWith("'")?`\`${a}\``:a}var We=async(a,{table:e,variables:t,datasourceId:r,filters:s,joins:o,orderBy:n,size:i,page:c,columns:d,groupBy:l})=>{let T=await g.findOneBy({id:r}),m=[],p=[];if(!T)throw new u(404,"Data source not found");let w=new ve.SQLManipulator(T.dbType,"SELECT");if(w.setTable(e),t&&w.setParameters(t),w.getParsed().type!=="SELECT")throw new u(400,"Only SELECT queries are allowed in this endpoint");w.setLimit(i||20),w.setOffset(i*c),s?.forEach(b=>{w.addWhere(kt(b))}),o&&w.addJoin(...o),n&&w.addOrderBy(...n.map(b=>({...b,column:Dt(b.column)}))),d&&d.length>0&&w.selectColumns(d),l&&l.length>0&&l.forEach(b=>w.addGroupBy(b));let U=w.getParsed();U.table&&m.push(U.table),U.joins&&U.joins.length>0&&U.joins.forEach(b=>{m.push(b.table)});let at=await C.find({where:{tableName:(0,Be.In)(m),datasource:{id:r}}});for(let b of at)if(b.columns)for(let st of b.columns)p.push({column:st.name,table:b.tableName||""});return{...await(await M(T,a)).executeQuery(w.toExecutableSQL(),{type:w.getParsed().type,allowBulkUpdate:!1}),tables:m,allColumns:p}},je=async(a,{sql:e,variables:t,datasourceId:r,size:s,page:o})=>{let n=await g.findOneBy({id:r});if(!n)throw new u(404,"Data source not found");let i=$e(e),c=e;if(i==="SELECT"){if(c.match(/LIMIT|OFFSET/ig))throw new u(400,"Queries are automatically paginated, do not use LIMIT and/or OFFSET");let l=_t(s);c=Fe(c,l,l*Nt(o))}return t&&(c=Qe(c,t)),(await M(n,a)).executeQuery(c,{type:i,allowBulkUpdate:!1})};function kt(a){let e={...a};switch(e.operator){case"IS NULL":case"IS NOT NULL":e.value=void 0;break;case"LIKE":case"ILIKE":case"NOT LIKE":case"NOT ILIKE":e.value=e.value?.map(t=>({isColumn:t?.isColumn,value:`%${t?.value}%`}));break}return e}var He=f(a=>{a.post("/sql",async e=>{let t=y(e);return{data:await We(e,t)}}),a.post("/raw",async e=>{let t=y(e);return{data:await je(e,t)}})});var Ye=require("node:child_process"),Ge=f(a=>{a.get("/",async(e,t)=>({data:{active:!0,version:process.env.SERVER_VERSION}})),a.get("/logs",async()=>{(0,Ye.spawn)(`echo "${process.env.SERVER_VERSION}"`)})});var Ve=f(a=>{a.get("/",async(e,t)=>{let r=N(e);return{data:await q.find({where:{users:{id:r}}})}}),a.post("/",async(e,t)=>E.transaction(async()=>{let r=N(e),s=y(e),o=R.create();o.id=r;let n=q.create(s);return n.users=[o],await q.save(n),{data:n}}))});var ze=async a=>({email:"local@localhost",sub:"local"});async function Ke(){let a=q.create({name:"Personal"}),e=await R.save(R.create({}));return a.users=[e],await q.save(a),await R.update(e.id,{currentTeam:{id:a.id}}),R.findOne({where:{},relations:{currentTeam:!0}})}var Je=f(a=>{a.post("/register",async(e,t)=>{let r=await ze(e);if(!r?.email||!r?.sub)throw new u(400,"Invalid token");return{data:await Ke()}}),a.get("/",async(e,t)=>{let r=await R.findOne({where:{},relations:{currentTeam:!0}});return r?{data:r}:{data:await Ke()}}),a.put("/",async(e,t)=>{let r=N(e),s=y(e);if(!(await R.update(r,s)).affected)throw new u(404,"User not found");return{data:R.findOneBy({id:r})}}),a.put("/team",async(e,t)=>{let r=N(e),s=y(e);return await R.update(r,{currentTeam:{id:s.teamId}}),{data:await R.findOne({where:{id:r},relations:{currentTeam:!0}})}})});var qt="********************************************",Ze=a=>a.slice(0,4)+qt+a.slice(a.length-4);function Mt(a){let e=O.create(a);return a.openAiToken&&(e.openAiToken=Ze(a.openAiToken)),e}var Xe=f(a=>{a.get("/",async e=>{let t=N(e),r=await O.findOneBy({user:{id:t}});return r||(r=await O.save(O.create({user:{id:t},model:"gpt-4o"}))),{data:Mt(r)}}),a.patch("/",async e=>{let{settings:t}=y(e);if(!t.id)throw new u(400,"Settings id is required!");if(!(await O.update(t.id,t)).affected)throw new u(404,"You do not own these settings!");return{data:await O.findOneBy({id:t.id})}})});var et=f(a=>{a.get("/",async e=>{let{dsId:t,teamId:r,limit:s,orderBy:o}=_(e);if(!t&&!r)throw new u(400,"Either dsId or teamId is required");return{data:await S.find({where:{team:{id:r},isTrash:!1},take:s,order:B(o,{createdAt:"DESC"})})}}),a.get("/:id",async e=>{let{id:t}=h(e),r=await S.findOneBy({id:t});return r?{data:r}:{status:404,data:"Workbook not found"}}),a.post("/",async e=>{let t=y(e);return{data:await S.save(S.create({name:t.name,isTrash:!1,team:{id:t.teamId}}))}}),a.patch("/:id",async e=>{let{id:t}=h(e),r=y(e);if(!(await S.update(t,r)).affected)throw new u(404,"Workbook not found");return{data:await S.findOneBy({id:t})}}),a.delete("/:id",async e=>{let{id:t}=h(e);if(!(await S.delete({id:t})).affected)return{status:404,data:"Workbook not found"}}),a.get("/:id/content",async e=>{let{id:t}=h(e),r=await S.findOneBy({id:t});if(!r)throw new u(404,"Workbook not found");try{let s=await ye(r?.path);if(s)return{data:s}}catch{}return{data:""}}),a.patch("/:id/content",async e=>{let{id:t}=h(e),r=y(e),s=await S.findOneBy({id:t});if(!s?.path)throw new u(404,"Workbook not found");await he(s?.path,r.content),await S.update(s.id,{updatedAt:new Date})})});var L=(0,tt.default)(),Lt=process.env.PORT?parseInt(process.env.PORT):4466;function A(a,e){L.register(a,{prefix:e}),console.log("Registered "+e)}async function Ut(){await ge(),A(Te,"/api/chat"),A(Ae,"/api/data-sources"),A(Pe,"/api/project"),A(Ne,"/api/queries"),A(He,"/api/runner"),A(Ge,"/api/status"),A(Ve,"/api/teams"),A(Je,"/api/users"),A(Xe,"/api/user-settings"),A(et,"/api/workbooks"),L.register(rt.default,{origin:"*",methods:"*"}),L.addHook("onResponse",async a=>{a.__connections&&a.__connections.forEach(e=>{e.close()})}),L.setErrorHandler((a,e,t)=>{if(a instanceof u){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 L.after(),await pe(),L.listen({port:Lt,host:"0.0.0.0"},(a,e)=>{a&&(console.error(a),process.exit(1)),console.log(`Server listening at ${e}`)})}Ut();
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.QueriesRepository = exports.WorkbookRepository = exports.UserSettingsRepository = exports.UserRepository = exports.TeamRepository = exports.DataSourceRepository = exports.DatabaseInspectionRepository = exports.init = exports.AppDataSource = void 0;
|
|
7
|
+
const typeorm_1 = require("typeorm");
|
|
8
|
+
const databaseInspection_1 = require("./tables/databaseInspection");
|
|
9
|
+
const teams_1 = require("./tables/teams");
|
|
10
|
+
const users_1 = require("./tables/users");
|
|
11
|
+
const userSettings_1 = require("./tables/userSettings");
|
|
12
|
+
const workbook_1 = require("./tables/workbook");
|
|
13
|
+
const datasource_1 = require("./tables/datasource");
|
|
14
|
+
const os_1 = __importDefault(require("os"));
|
|
15
|
+
const query_1 = require("./tables/query");
|
|
16
|
+
function getDatabaseValue() {
|
|
17
|
+
let value = process.env.TYPEORM_DATABASE;
|
|
18
|
+
if (!value) {
|
|
19
|
+
throw new Error("Bad value for TYPEORM_DATABASE. Please check your config!");
|
|
20
|
+
}
|
|
21
|
+
if (value.startsWith("<home>")) {
|
|
22
|
+
value = value.replace("<home>", os_1.default.homedir());
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
exports.AppDataSource = new typeorm_1.DataSource({
|
|
27
|
+
type: process.env.TYPEORM_CONNECTION,
|
|
28
|
+
database: getDatabaseValue(),
|
|
29
|
+
synchronize: process.env.TYPEORM_SYNCHRONIZE === 'true',
|
|
30
|
+
host: process.env.TYPEORM_HOST,
|
|
31
|
+
username: process.env.TYPEORM_USERNAME,
|
|
32
|
+
password: process.env.TYPEORM_PASSWORD,
|
|
33
|
+
port: process.env.TYPEORM_PORT ? parseInt(process.env.TYPEORM_PORT) : undefined,
|
|
34
|
+
logging: process.env.TYPEORM_LOGGING === 'true',
|
|
35
|
+
entities: [
|
|
36
|
+
databaseInspection_1.DatabaseInspection,
|
|
37
|
+
datasource_1.DataSource,
|
|
38
|
+
teams_1.Team,
|
|
39
|
+
users_1.User,
|
|
40
|
+
userSettings_1.UserSettings,
|
|
41
|
+
workbook_1.Workbook,
|
|
42
|
+
query_1.Query,
|
|
43
|
+
],
|
|
44
|
+
});
|
|
45
|
+
const init = async () => {
|
|
46
|
+
if (!exports.AppDataSource.isInitialized) {
|
|
47
|
+
return exports.AppDataSource.initialize();
|
|
48
|
+
}
|
|
49
|
+
throw new Error("Already initialized");
|
|
50
|
+
};
|
|
51
|
+
exports.init = init;
|
|
52
|
+
exports.DatabaseInspectionRepository = exports.AppDataSource.getRepository(databaseInspection_1.DatabaseInspection);
|
|
53
|
+
exports.DataSourceRepository = exports.AppDataSource.getRepository(datasource_1.DataSource);
|
|
54
|
+
exports.TeamRepository = exports.AppDataSource.getRepository(teams_1.Team);
|
|
55
|
+
exports.UserRepository = exports.AppDataSource.getRepository(users_1.User);
|
|
56
|
+
exports.UserSettingsRepository = exports.AppDataSource.getRepository(userSettings_1.UserSettings);
|
|
57
|
+
exports.WorkbookRepository = exports.AppDataSource.getRepository(workbook_1.Workbook);
|
|
58
|
+
exports.QueriesRepository = exports.AppDataSource.getRepository(query_1.Query);
|