db-crud-api 0.2.2 → 0.3.1

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/lib/mysql.js ADDED
@@ -0,0 +1,278 @@
1
+ 'use strict';
2
+
3
+ import sql from 'mysql2/promise';
4
+
5
+ const pools = {};
6
+
7
+ // Common
8
+ function stringifyValue(fieldName, value, tSchema) {
9
+ if (value == undefined) { return 'null' }
10
+ if (typeof value !== 'string' || value.trimStart().charAt(0) !== '\`') {
11
+ if (tSchema.table.fields && tSchema.table.fields[fieldName] && tSchema.table.fields[fieldName].type) {
12
+ if (tSchema.table.fields[fieldName].type == 'datetime') {
13
+ if (typeof value == 'datetime' || typeof value == 'object') return `\'${value.toISOString().slice(0, 19).replace('T', ' ')}\'`;
14
+ if (typeof value == 'string' && value.trimStart().charAt(0) !== '\'' && value.trimStart().charAt(0) !== '\"') return `\'${value}\'`;
15
+ return value;
16
+ }
17
+ if (tSchema.table.fields[fieldName].type == 'boolean' && typeof value == 'boolean') return `\'${value}\'`;
18
+ if (tSchema.table.fields[fieldName].type == 'string' && value.trimStart().charAt(0) !== '\'' && value.trimStart().charAt(0) !== '\"') return `\'${value}\'`;
19
+ if (tSchema.table.fields[fieldName].type == 'uuid' && value.trimStart().charAt(0) !== '\'' && value.trimStart().charAt(0) !== '\"') return `\'${value}\'`;
20
+ }
21
+ else {
22
+ // if (typeof value == 'datetime') return `\'${value.toISOString().slice(0, 19).replace('T', ' ')}\'`;
23
+ if (typeof value == 'boolean') return `\'${value}\'`;
24
+ if (typeof value == 'string' && value.trimStart().charAt(0) !== '\'' && value.trimStart().charAt(0) !== '\"') return `\'${value}\'`;
25
+ }
26
+ }
27
+ return value;
28
+ }
29
+
30
+ // Create config object for pool
31
+ export function prepareConnection(tSchema) {
32
+ return {
33
+ id: `${tSchema.server.realName}-${tSchema.database.realName}-${tSchema.server.user}`,
34
+ host: ((tSchema.server.instance && tSchema.server.instance != 'DEFAULT') ? (tSchema.server.realName + '\\' + tSchema.server.instance) : tSchema.server.realName) ?? 'localhost',
35
+ port: tSchema.server.port,
36
+ user: tSchema.server.user,
37
+ password: tSchema.server.password,
38
+ database: tSchema.database.realName,
39
+ ssl : {
40
+ rejectUnauthorized: false
41
+ },
42
+ multipleStatements: true,
43
+ connectionLimit: tSchema.server.connectionLimit
44
+ };
45
+ };
46
+
47
+ // Close connection
48
+ export async function closeConnection(connection) {
49
+ let pool = pools[connection.id];
50
+ if (pool) {
51
+ pool.releaseConnection();
52
+ connection.end();
53
+ pools[connection.id] = undefined; // remove pool from pools
54
+ }
55
+ }
56
+
57
+ // Close all connections
58
+ export async function closeAllConnections() {
59
+ for (let poolId in pools) {
60
+ if (!pools.hasOwnProperty(poolId)) continue;
61
+ let pool = pools[poolId];
62
+ if (pool) {
63
+ pool.end();
64
+ pool = undefined; // remove pool from pools
65
+ }
66
+ }
67
+ }
68
+
69
+ // Query
70
+ export async function query(connection, dbOpes) {
71
+
72
+ // Prepare pool
73
+ let pool = pools[connection.id]; // Try to get an existing pool
74
+ if (!pool) {
75
+ pool = new sql.createPool(connection); // Create new pool
76
+ pools[connection.id] = pool; // add new pool to pools
77
+ }
78
+
79
+ // Prepare sql statement
80
+ let sqlString = '';
81
+ // if exists, input params will be added to request
82
+ if (Array.isArray(dbOpes)) dbOpes.forEach((dbOpe, index) => { sqlString += ToSql(dbOpe, pool); });
83
+ else sqlString += ToSql(dbOpes, pool);
84
+
85
+ // Run query
86
+ let sqlresult = undefined;
87
+ let sqlconn = undefined;
88
+ try {
89
+ sqlconn = await pool.getConnection();
90
+ sqlresult = await sqlconn.query(sqlString);
91
+ }
92
+ catch(err) { throw(err); } // using original error
93
+ finally { if (sqlconn) sqlconn.release(); }
94
+
95
+ // Return single object if there is only 1 row
96
+ if (sqlresult[0].length === 0) return;
97
+ if (sqlresult[0].length === 1) return sqlresult[0][0];
98
+ else return sqlresult[0];
99
+ }
100
+
101
+ // Normalize field name
102
+ //function toFieldName(s) {
103
+ // if ( s.trimStart().charAt(0) === '\`' ) return s;
104
+ // else return `\`${s}\``;
105
+ //}
106
+
107
+ // Compose fully qualified table name
108
+ function fullyQualifiedTableName(tSchema) {
109
+ return (tSchema.database.realName + '.' + tSchema.table.realName);
110
+ }
111
+
112
+ // Parse oprations object to sql string
113
+ function ToSql(dbOpe, sqlRequest) {
114
+ if (dbOpe.get) return getToSql(dbOpe, sqlRequest);
115
+ if (dbOpe.patch) return patchToSql(dbOpe, sqlRequest);
116
+ if (dbOpe.put) return putToSql(dbOpe, sqlRequest);
117
+ if (dbOpe.delete) return deleteToSql(dbOpe, sqlRequest);
118
+ if (dbOpe.execute) return executeToSql(dbOpe, sqlRequest);
119
+ if (dbOpe.begin) return beginToSql(dbOpe, sqlRequest);
120
+ if (dbOpe.commit) return commitToSql(dbOpe, sqlRequest);
121
+ if (dbOpe.passthrough) return passthroughToSql(dbOpe, sqlRequest);
122
+ }
123
+
124
+ // Parse operation object to sql string without any trasformation.
125
+ function passthroughToSql(dbOpe, sqlRequest) {
126
+
127
+ let result = "";
128
+
129
+ if (dbOpe.passthrough.command) {
130
+ result += dbOpe.passthrough.command;
131
+ }
132
+ else { throw new Error('command is missing.'); }
133
+
134
+ if (dbOpe.passthrough.params) addParams(dbOpe.passthrough.params, sqlRequest);
135
+
136
+ return result;
137
+ }
138
+
139
+ // Parse get operation object to sql string
140
+ function getToSql(dbOpe, sqlRequest) {
141
+ let _first = true;
142
+
143
+ let result = 'select '
144
+
145
+ if ((dbOpe.get.fields) && (Object.keys(dbOpe.get.fields).length > 0)) {
146
+ if (Array.isArray(dbOpe.get.fields)) result += dbOpe.get.fields.join(', ');
147
+ else result += dbOpe.get.fields;
148
+ }
149
+ else { throw new Error('fields is missing.'); }
150
+
151
+ result += ' from ' + fullyQualifiedTableName(dbOpe.get.schema);
152
+
153
+ if ((dbOpe.get.filters) && (Object.keys(dbOpe.get.filters).length > 0)) {
154
+ if (Array.isArray(dbOpe.get.filters)) result += ' where ' + dbOpe.get.filters.join(' ');
155
+ else result += ' where ' + dbOpe.get.filters;
156
+ }
157
+
158
+ if ((dbOpe.get.groups) && (Object.keys(dbOpe.get.groups).length > 0)) {
159
+ if (Array.isArray(dbOpe.get.groups)) result += ' group by ' + dbOpe.get.groups.join(', ');
160
+ else result += ' group by ' + dbOpe.get.groups;
161
+ }
162
+
163
+ if ((dbOpe.get.groupsFilters) && (Object.keys(dbOpe.get.groupsFilters).length > 0)) {
164
+ if (Array.isArray(dbOpe.get.groupsFilters)) result += ' having ' + dbOpe.get.groupsFilters.join(' ');
165
+ else result += ' having ' + dbOpe.get.groupsFilters;
166
+ }
167
+
168
+ if ((dbOpe.get.orderBy) && (Object.keys(dbOpe.get.orderBy).length > 0)) {
169
+ if (Array.isArray(dbOpe.get.orderBy)) result += ' order by ' + dbOpe.get.orderBy.join(', ');
170
+ else result += ' order by ' + dbOpe.get.orderBy;
171
+ }
172
+
173
+ if ((dbOpe.get.options) && (Object.keys(dbOpe.get.options).length > 0)) {
174
+ if (Array.isArray(dbOpe.get.options)) result += ' ' + dbOpe.get.options.join(' ');
175
+ else result += ' ' + dbOpe.get.options;
176
+ }
177
+
178
+ if (dbOpe.get.params) addParams(dbOpe.get.params, sqlRequest);
179
+
180
+ result += ';'
181
+
182
+ return result;
183
+ }
184
+
185
+ // Parse patch operation object to sql string
186
+ function patchToSql(dbOpe, sqlRequest) {
187
+ let result = 'update ' + fullyQualifiedTableName(dbOpe.patch.schema);
188
+
189
+ if (dbOpe.patch.sets) { result += ' set ' + Object.entries(dbOpe.patch.sets).map(e => { return e[0] + '=' + stringifyValue(e[0], e[1], dbOpe.patch.schema) }).join(', '); }
190
+ else { throw new Error('sets is missing.'); }
191
+
192
+ if ((dbOpe.patch.filters) && (Object.keys(dbOpe.patch.filters).length > 0)) {
193
+ if (Array.isArray(dbOpe.patch.filters)) result += ' where ' + dbOpe.patch.filters.join(' ');
194
+ else result += ' where ' + dbOpe.patch.filters;
195
+ }
196
+
197
+ if (dbOpe.patch.params) addParams(dbOpe.patch.params, sqlRequest);
198
+
199
+ result += ';'
200
+
201
+ return result;
202
+ }
203
+
204
+ // Parse put (add) operation object to sql string
205
+ function putToSql(dbOpe, sqlRequest) {
206
+ let result = 'insert into ' + fullyQualifiedTableName(dbOpe.put.schema);
207
+
208
+ if ((dbOpe.put.sets) && (Object.keys(dbOpe.put.sets).length > 0)) {
209
+ let result_f = ' ('; let result_v = ' values (';
210
+ let _first = true;
211
+ for (const [key, value] of Object.entries(dbOpe.put.sets)) {
212
+ if (!_first) { result_f += ', '; result_v += ', '; } else { _first = false }
213
+ if (key || value) { result_f += key; result_v += stringifyValue(key, value, dbOpe.put.schema); }
214
+ }
215
+ result_f += ')'; result_v += ')';
216
+ result += result_f + result_v;
217
+ }
218
+ else { throw new Error('sets is missing.'); }
219
+
220
+ if (dbOpe.put.params) addParams(dbOpe.put.params, sqlRequest);
221
+
222
+ result += ';'
223
+
224
+ return result;
225
+ }
226
+
227
+ // Parse delete operation object to sql string
228
+ function deleteToSql(dbOpe, sqlRequest) {
229
+ let result = 'delete from ' + fullyQualifiedTableName(dbOpe.delete.schema);
230
+
231
+ if ((dbOpe.delete.filters) && (Object.keys(dbOpe.delete.filters).length > 0)) {
232
+ if (Array.isArray(dbOpe.delete.filters)) result += ' where ' + dbOpe.delete.filters.join(' ');
233
+ else result += ' where ' + dbOpe.delete.filters;
234
+ }
235
+
236
+ if (dbOpe.delete.params) addParams(dbOpe.delete.params, sqlRequest);
237
+
238
+ result += ';'
239
+
240
+ return result;
241
+ }
242
+
243
+ // Parse execute operation object to sql string
244
+ function executeToSql(dbOpe, sqlRequest) {
245
+ let result = "CALL ";
246
+
247
+ if (dbOpe.execute.schema.procedure) {
248
+ result += dbOpe.execute.schema.procedure.command;
249
+ if (dbOpe.execute.arguments) { result += ('(' + dbOpe.execute.arguments) + ')'; }
250
+ }
251
+ else { throw new Error('missing procedure/function name.'); }
252
+
253
+ if (dbOpe.execute.params) addParams(dbOpe.execute.params, sqlRequest);
254
+
255
+ result += ';'
256
+
257
+ return result;
258
+ }
259
+
260
+ // Parse begin operation object to sql string
261
+ function beginToSql(dbOpe, sqlRequest) {
262
+ return "START TRANSACTION; ";
263
+ }
264
+
265
+ // Parse commit operation object to sql string
266
+ function commitToSql(dbOpe, sqlRequest) {
267
+ return " COMMIT;";
268
+ }
269
+
270
+ // Add input parameters to pool.request
271
+ function addParams(params, sqlRequest) {
272
+ if (params) {
273
+ for (const [key, value] of Object.entries(params)) {
274
+ sqlRequest.input(key, value)
275
+ }
276
+ }
277
+ return;
278
+ }
package/lib/schema.js CHANGED
@@ -1,4 +1,4 @@
1
- export default {
2
- servers: {
3
- }
1
+ export default {
2
+ servers: {
3
+ }
4
4
  }
package/package.json CHANGED
@@ -1,17 +1,22 @@
1
- {
2
- "name": "db-crud-api",
3
- "version": "0.2.2",
4
- "type": "module",
5
- "description": "CRUD api for database tables",
6
- "main": "index.js",
7
- "scripts": {
8
- "test": "echo \"Error: no test specified\" && exit 1"
9
- },
10
- "author": "FF",
11
- "license": "MIT",
12
- "dependencies": {
13
- "mssql": "^11.0.1",
14
- "uuid": "^11.0.3"
15
- },
16
- "keywords":["db","crud","api"]
17
- }
1
+ {
2
+ "name": "db-crud-api",
3
+ "version": "0.3.1",
4
+ "type": "module",
5
+ "description": "CRUD api for database tables",
6
+ "main": "index.js",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 1"
9
+ },
10
+ "author": "FF",
11
+ "license": "MIT",
12
+ "dependencies": {
13
+ "mssql": "^11.0.1",
14
+ "mysql2": "^3.12.0",
15
+ "uuid": "^11.0.3"
16
+ },
17
+ "keywords": [
18
+ "db",
19
+ "crud",
20
+ "api"
21
+ ]
22
+ }