@quillsql/node 0.5.9 → 0.6.0

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.
@@ -164,6 +164,7 @@ function convertBigQueryTypeToPostgresOID(type) {
164
164
  FLOAT: 700,
165
165
  TIMESTAMP: 1114,
166
166
  DATE: 1082,
167
+ BOOL: 16,
167
168
  };
168
169
  const postgresType = typeToOidMap[type.toUpperCase()] || "VARCHAR"; // Default to 'text' if the type is not recognized
169
170
  return typeToOidMap[postgresType] || 1043; // Default to OID for 'text' if the type is not recognized
@@ -7,8 +7,10 @@ export declare class CachedConnection {
7
7
  ttl: number;
8
8
  cache: Mapable | null;
9
9
  private config;
10
+ private activeQueries;
11
+ private readonly MAX_ACTIVE_QUERIES;
10
12
  constructor(databaseType: "postgresql" | "snowflake" | "bigquery" | "mysql", config: any, cacheConfig?: Partial<CacheCredentials>);
11
- query(text: string, values?: any[]): Promise<any>;
13
+ query(text: string): Promise<any>;
12
14
  /**
13
15
  * Configures and returns a cache instance or null if none could be created.
14
16
  */
@@ -13,29 +13,23 @@ exports.CachedConnection = void 0;
13
13
  const redis_1 = require("redis");
14
14
  const Error_1 = require("../utils/Error");
15
15
  const DatabaseHelper_1 = require("./DatabaseHelper");
16
- class PgError extends Error {
17
- // Add other properties if needed
18
- constructor(detail, hint, position) {
19
- super();
20
- this.detail = detail;
21
- this.hint = hint;
22
- this.position = position;
23
- }
24
- }
25
16
  /** The TTL for new cache entries (default: 1h) */
26
17
  const DEFAULT_CACHE_TTL = 24 * 60 * 60;
27
18
  class CachedConnection {
28
19
  constructor(databaseType, config, cacheConfig = {}) {
29
20
  var _a;
21
+ this.activeQueries = 0;
22
+ this.MAX_ACTIVE_QUERIES = 0;
30
23
  this.databaseType = databaseType;
31
24
  this.pool = (0, DatabaseHelper_1.connectToDatabase)(databaseType, config);
32
25
  this.config = config;
33
26
  this.ttl = (_a = cacheConfig === null || cacheConfig === void 0 ? void 0 : cacheConfig.ttl) !== null && _a !== void 0 ? _a : DEFAULT_CACHE_TTL;
34
27
  this.cache = this.getCache(cacheConfig);
35
28
  }
36
- query(text, values) {
29
+ query(text) {
37
30
  return __awaiter(this, void 0, void 0, function* () {
38
31
  try {
32
+ this.activeQueries++;
39
33
  this.pool = this.getPool();
40
34
  if (!this.cache) {
41
35
  return yield (0, DatabaseHelper_1.runQueryByDatabase)(this.databaseType, this.pool, text);
@@ -53,16 +47,19 @@ class CachedConnection {
53
47
  }
54
48
  }
55
49
  catch (err) {
56
- if ((0, Error_1.isSuperset)(err, PgError)) {
57
- throw new PgError(err.detail, err.hint, err.position);
50
+ if ((0, Error_1.isSuperset)(err, Error_1.PgError)) {
51
+ throw new Error_1.PgError(err.message, err.detail, err.hint, err.position);
58
52
  }
59
53
  else if (err instanceof Error) {
60
54
  throw new Error(err.message);
61
55
  }
62
56
  }
63
57
  finally {
64
- if (this.databaseType.toLowerCase() === "mysql") {
65
- this.close();
58
+ this.activeQueries--;
59
+ if (this.activeQueries <= this.MAX_ACTIVE_QUERIES) {
60
+ if (this.databaseType.toLowerCase() === "mysql") {
61
+ this.close();
62
+ }
66
63
  }
67
64
  }
68
65
  });
@@ -138,24 +138,31 @@ function formatPostgresConfig(connectionString) {
138
138
  }
139
139
  exports.formatPostgresConfig = formatPostgresConfig;
140
140
  // CURRENTLY UNUSED BUT MAYBE USEFUL IN THE FUTURE
141
- function getSslConfig(client) {
142
- if (!client.useSsl) {
143
- return undefined;
144
- }
145
- if (client.serverCa && client.clientKey && client.clientCert) {
146
- return {
147
- rejectUnauthorized: false,
148
- ca: client.serverCa,
149
- key: client.clientKey,
150
- cert: client.clientCert,
151
- };
152
- }
153
- if (client.serverCa) {
154
- return {
155
- rejectUnauthorized: false,
156
- ca: client.serverCa,
157
- };
158
- }
159
- // if using ssl with no certificates
160
- return { rejectUnauthorized: false };
161
- }
141
+ // function getSslConfig(client: Client):
142
+ // | {
143
+ // rejectUnauthorized: false;
144
+ // ca?: string;
145
+ // key?: string;
146
+ // cert?: string;
147
+ // }
148
+ // | undefined {
149
+ // if (!client.useSsl) {
150
+ // return undefined;
151
+ // }
152
+ // if (client.serverCa && client.clientKey && client.clientCert) {
153
+ // return {
154
+ // rejectUnauthorized: false,
155
+ // ca: client.serverCa,
156
+ // key: client.clientKey,
157
+ // cert: client.clientCert,
158
+ // };
159
+ // }
160
+ // if (client.serverCa) {
161
+ // return {
162
+ // rejectUnauthorized: false,
163
+ // ca: client.serverCa,
164
+ // };
165
+ // }
166
+ // // if using ssl with no certificates
167
+ // return { rejectUnauthorized: false };
168
+ // }
@@ -116,7 +116,7 @@ function connectToSnowflake(config) {
116
116
  exports.connectToSnowflake = connectToSnowflake;
117
117
  function disconnectFromSnowflake(connection) {
118
118
  return __awaiter(this, void 0, void 0, function* () {
119
- connection.destroy((err, conn) => {
119
+ connection.destroy((err) => {
120
120
  if (err) {
121
121
  console.error(`Failed to disconnect from Snowflake: ${err.message}`);
122
122
  }
@@ -126,7 +126,7 @@ function disconnectFromSnowflake(connection) {
126
126
  exports.disconnectFromSnowflake = disconnectFromSnowflake;
127
127
  function getForeignKeysSnowflake(connection, schemaName, tableName, primaryKey) {
128
128
  return __awaiter(this, void 0, void 0, function* () {
129
- let depluralizedTableName = (0, textProcessing_1.depluralize)(tableName);
129
+ const depluralizedTableName = (0, textProcessing_1.depluralize)(tableName);
130
130
  let sql = `SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
131
131
  WHERE TABLE_SCHEMA = '${schemaName}'
132
132
  AND TABLE_NAME = '${schemaName}'
package/dist/index.js CHANGED
@@ -41,10 +41,13 @@ class Quill {
41
41
  this.targetConnection = new CachedConnection_1.CachedConnection(databaseType, credentials, cache || {});
42
42
  }
43
43
  query({ orgId, metadata, }) {
44
- var _a, _b;
44
+ var _a, _b, _c, _d, _e;
45
45
  return __awaiter(this, void 0, void 0, function* () {
46
46
  this.targetConnection.orgId = orgId;
47
47
  let responseMetadata = {};
48
+ if (!metadata.task) {
49
+ return { error: "Missing task.", status: "error", data: {} };
50
+ }
48
51
  try {
49
52
  const preQueryResults = metadata.preQueries
50
53
  ? yield this.runQueries(metadata.preQueries, this.targetConnection.databaseType, metadata.databaseType, metadata.runQueryConfig)
@@ -57,7 +60,11 @@ class Quill {
57
60
  }
58
61
  const response = yield this.postQuill(metadata.task, Object.assign(Object.assign(Object.assign({}, metadata), preQueryResults), { orgId, viewQuery: metadata.preQueries ? metadata.preQueries[0] : undefined }));
59
62
  if (response.error) {
60
- return { status: "error", error: response.error };
63
+ return {
64
+ status: "error",
65
+ error: response.error,
66
+ data: response.metadata || {},
67
+ };
61
68
  }
62
69
  // if there is no metadata object in the response, create one
63
70
  if (response.metadata) {
@@ -92,8 +99,8 @@ class Quill {
92
99
  catch (err) {
93
100
  return {
94
101
  status: "error",
95
- error: err.message,
96
- data: responseMetadata,
102
+ error: (_e = (_d = (_c = err.response) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.error) !== null && _e !== void 0 ? _e : err.message,
103
+ data: responseMetadata || {},
97
104
  };
98
105
  }
99
106
  });
@@ -152,7 +159,9 @@ class Quill {
152
159
  return Object.assign(Object.assign({}, table), { columns: columns, rows: queryResult.rows });
153
160
  }
154
161
  catch (err) {
155
- return Object.assign(Object.assign({}, table), { error: "Error fetching columns" });
162
+ return Object.assign(Object.assign({}, table), { error: err.message
163
+ ? `Error fetching columns: ${err.message}`
164
+ : "Error fetching columns" });
156
165
  }
157
166
  })));
158
167
  results = Object.assign(Object.assign({}, results), { queryResults });
@@ -3,5 +3,6 @@ export declare class PgError extends Error {
3
3
  detail?: string;
4
4
  hint?: string;
5
5
  position?: string;
6
+ constructor(message: string, detail?: string, hint?: string, position?: string, code?: string);
6
7
  }
7
8
  export declare function isSuperset(obj: any, baseClass: any): boolean;
@@ -2,14 +2,23 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isSuperset = exports.PgError = void 0;
4
4
  class PgError extends Error {
5
+ // Add other properties if needed
6
+ constructor(message, detail, hint, position, code) {
7
+ super(message);
8
+ this.code = code;
9
+ this.detail = detail;
10
+ this.hint = hint;
11
+ this.position = position;
12
+ }
5
13
  }
6
14
  exports.PgError = PgError;
7
15
  function isSuperset(obj, baseClass) {
8
- // Get the property names of the base class
9
- const baseProps = Object.getOwnPropertyNames(baseClass.prototype);
16
+ // Get the property names of the base class instance
17
+ const baseInstance = new baseClass();
18
+ const baseProps = Object.keys(baseInstance);
10
19
  // Check if the object has all the properties of the base class
11
20
  for (const prop of baseProps) {
12
- if (!obj.hasOwnProperty(prop)) {
21
+ if (!Object.prototype.hasOwnProperty.call(obj, prop)) {
13
22
  return false;
14
23
  }
15
24
  }
@@ -1,3 +1,9 @@
1
1
  import { CachedConnection } from "../db/CachedConnection";
2
+ export interface TableSchemaInfo {
3
+ fieldType: string;
4
+ name: string;
5
+ displayName: string;
6
+ isVisible: boolean;
7
+ }
2
8
  export declare function removeFields(queryResults: any, fieldsToRemove: string[]): any;
3
9
  export declare function mapQueries(queries: string[], targetConnection: CachedConnection): Promise<any[]>;
@@ -0,0 +1,16 @@
1
+ import globals from "globals";
2
+ import pluginJs from "@eslint/js";
3
+ import tseslint from "typescript-eslint";
4
+
5
+ export default [
6
+ { files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"] },
7
+ { languageOptions: { globals: globals.node } },
8
+ pluginJs.configs.recommended,
9
+ ...tseslint.configs.recommended,
10
+ {
11
+ rules: {
12
+ "@typescript-eslint/no-explicit-any": "off",
13
+ "@typescript-eslint/no-require-imports": "off",
14
+ },
15
+ },
16
+ ];
@@ -0,0 +1,62 @@
1
+ // Write a simple node server to test the SDK
2
+
3
+ import express from "express";
4
+ import cors from "cors";
5
+ import requireQuill from "../../src/index";
6
+
7
+ const app = express();
8
+ const port = 3005;
9
+
10
+ // postgresqlConfigExample {
11
+ // connectionString: process.env.DB_URL,
12
+ // ssl: {
13
+ // rejectUnauthorized: false,
14
+ // },
15
+ // };
16
+
17
+ // bigqueryConfigExample {
18
+ // projectId: process.env.PROJECT_ID,
19
+ // credentials: serviceAccount // You need to make the serviceAccount JSON
20
+ // }
21
+
22
+ // snowflakeConfigExample {
23
+ // account: process.env.ACCOUNT,
24
+ // username: process.env.USERNAME,
25
+ // password: process.env.PASSWORD,
26
+ // warehouse: process.env.WAREHOUSE,
27
+ // database: process.env.DATABASE,
28
+ // }
29
+
30
+ // mysqlConfigExample {
31
+ // host: process.env.HOST,
32
+ // user: process.env.USER,
33
+ // password: process.env.PASSWORD,
34
+ // database: process.env.DATABASE,
35
+ // }
36
+
37
+ app.use(cors());
38
+ app.use(express.json());
39
+
40
+ app.get("/", (req, res) => {
41
+ res.send("Hello World!");
42
+ });
43
+
44
+ const quill = requireQuill({
45
+ privateKey: process.env.MYSQL_PRIVATE_KEY ?? "",
46
+ databaseConnectionString: process.env.MYSQL_DB_URL ?? "",
47
+ databaseConfig: {}, // TODO: Add database config
48
+ databaseType: "mysql",
49
+ });
50
+
51
+ app.post("/quill", async (req, res) => {
52
+ const { orgId, metadata } = req.body;
53
+ const result = await quill.query({
54
+ orgId: orgId ?? metadata.orgId,
55
+ metadata,
56
+ });
57
+ res.send(result);
58
+ });
59
+
60
+ app.listen(port, () => {
61
+ console.log(`Example app listening at http://localhost:${port}`);
62
+ });
@@ -34,15 +34,14 @@ const port = 3001;
34
34
  // }
35
35
 
36
36
  const quill = require("../../src/index")({
37
- privateKey: process.env.PRIVATE_KEY,
38
- databaseConnectionString: process.env.DB_URL,
39
- // databaseConfig: {
40
- // connectionString: process.env.DB_URL,
41
- // ssl: {
42
- // rejectUnauthorized: false,
43
- // },
44
- // },
45
- databaseType: process.env.DB_TYPE,
37
+ privateKey: process.env.PRIVATE_KEY ?? "",
38
+ databaseConnectionString: process.env.DB_URL ?? "",
39
+ databaseConfig: {}, // TODO: Add database config
40
+ databaseType: process.env.DB_TYPE as
41
+ | "postgresql"
42
+ | "snowflake"
43
+ | "bigquery"
44
+ | "mysql",
46
45
  });
47
46
 
48
47
  app.use(cors());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quillsql/node",
3
- "version": "0.5.9",
3
+ "version": "0.6.0",
4
4
  "description": "Quill Server SDK for Node.js",
5
5
  "main": "dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -8,12 +8,18 @@
8
8
  "scripts": {
9
9
  "build": "tsc --outDir dist",
10
10
  "start:dev": "nodemon ./examples/node-server/app.ts",
11
+ "mysql:dev": "nodemon ./examples/mysql-node/app.ts",
11
12
  "integration-tests": "jest '.*\\.ispec\\.ts$'",
12
- "test": "tsc src && jest --detectOpenHandles"
13
+ "test": "tsc src && jest --detectOpenHandles",
14
+ "style-check": "prettier --check \"**/*.{ts,tsx,md}\"",
15
+ "style-fix": "prettier --write \"**/*.{ts,tsx,md}\"",
16
+ "lint-check": "eslint \"**/*.{ts,tsx}\"",
17
+ "lint-fix": "eslint '**/*.{ts,tsx}' --fix"
13
18
  },
14
19
  "author": "lagambino",
15
20
  "license": "ISC",
16
21
  "devDependencies": {
22
+ "@eslint/js": "^9.9.0",
17
23
  "@types/cors": "^2.8.17",
18
24
  "@types/express": "^4.17.21",
19
25
  "@types/jest": "^29.5.11",
@@ -21,11 +27,18 @@
21
27
  "@types/pg": "^8.10.9",
22
28
  "@types/snowflake-sdk": "^1.6.20",
23
29
  "cors": "^2.8.5",
30
+ "eslint": "^9.9.0",
31
+ "eslint-config-prettier": "^9.1.0",
32
+ "eslint-plugin-prettier": "^5.2.1",
33
+ "eslint-plugin-react": "^7.35.0",
24
34
  "express": "^4.18.2",
35
+ "globals": "^15.9.0",
25
36
  "jest": "^29.7.0",
26
37
  "nodemon": "^3.0.2",
38
+ "prettier": "^3.3.3",
27
39
  "ts-node": "^10.9.2",
28
- "typescript": "^5.3.3"
40
+ "typescript": "^5.3.3",
41
+ "typescript-eslint": "^8.1.0"
29
42
  },
30
43
  "dependencies": {
31
44
  "@google-cloud/bigquery": "^7.4.0",