db-crud-api 0.3.13 → 0.3.15
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/CHANGELOG.md +9 -0
- package/README.md +99 -99
- package/index.js +19 -10
- package/lib/api-factory.js +30 -30
- package/lib/db-operations.js +427 -427
- package/lib/log.js +12 -0
- package/lib/mssql.js +11 -3
- package/lib/mysql.js +11 -3
- package/lib/schema.js +9 -3
- package/package.json +1 -1
- package/deploy +0 -5
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
# db-crud-api 💡
|
|
2
|
-
CRUD api for database tables.
|
|
3
|
-
|
|
4
|
-
## Installation
|
|
5
|
-
npm install db-crud-api
|
|
6
|
-
|
|
7
|
-
# Usage
|
|
8
|
-
```javascript
|
|
9
|
-
import dbCrudApi from "db-crud-api";
|
|
10
|
-
const apiFactory = dbCrudApi(mySchema);
|
|
11
|
-
|
|
12
|
-
const mySchema = {
|
|
13
|
-
servers: {
|
|
14
|
-
server1: {
|
|
15
|
-
realName: "server1.mydomain.com",
|
|
16
|
-
type: "ms-sql",
|
|
17
|
-
instance: "DEFAULT",
|
|
18
|
-
user: "User1",
|
|
19
|
-
password: "mypassword",
|
|
20
|
-
options: {
|
|
21
|
-
appName: "myAppName",
|
|
22
|
-
...
|
|
23
|
-
},
|
|
24
|
-
databases: {
|
|
25
|
-
db1: {
|
|
26
|
-
realName: "db_orders",
|
|
27
|
-
tables: {
|
|
28
|
-
table1: {
|
|
29
|
-
realName: "tb_orders_head",
|
|
30
|
-
idField: "Id",
|
|
31
|
-
autoId: true,
|
|
32
|
-
fields: {
|
|
33
|
-
Id: { realName: "OrderId", type: "uuid", lengh: undefined, canBeNull: false, description: "Unique Id", defaultValue: undefined },
|
|
34
|
-
CustomerId: { type: "string", lengh: undefined, canBeNull: false, description: "Customer Id", defaultValue: undefined },
|
|
35
|
-
...
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
table2: {
|
|
39
|
-
realName: "tb_orders_detail",
|
|
40
|
-
idField: "Id",
|
|
41
|
-
autoId: true,
|
|
42
|
-
fields: {
|
|
43
|
-
Id: { realName: "OrderId", type: "uuid", lengh: undefined, canBeNull: false, description: "Unique Id", defaultValue: undefined },
|
|
44
|
-
OrderId: { type: "uuid", lengh: undefined, canBeNull: false, description: "Order Id", defaultValue: undefined },
|
|
45
|
-
RowSeq: { type: "numeric", lengh: undefined, canBeNull: false, description: "Row sequence", defaultValue: undefined },
|
|
46
|
-
...
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
...
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
...
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
...
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const apiOrder = apiFactory.newROApi("server1.db1.table1"); // Read Only api
|
|
60
|
-
const apiOrderDetail = apiFactory.newFullApi("table2"); // full CRUD api
|
|
61
|
-
const apiExecuteSP = apiFactory.newExecuteApi("db1.my_storeproc"); // execute my_storeproc
|
|
62
|
-
|
|
63
|
-
console.log(await apiFactory.testConnection()); // optional
|
|
64
|
-
|
|
65
|
-
console.log(await apiOrder.getById("xxxxx-xxxxx-xxxxxxxxxxxx-xxxxxx"));
|
|
66
|
-
console.log(await apiOrder.getById("xxxxx-xxxxx-xxxxxxxxxxxx-xxxxxx", {get: {fields: ["Id", "OrderNumber", "OrderTotal"]}}));
|
|
67
|
-
console.log(await apiOrder.getByFilter({get: {filters: ["OrderType in ('P', 'A')", "and", "OrderDate > '2022-12-01'"]}})); // get filterd rows
|
|
68
|
-
console.log(await apiOrder.getByFilter()); // this get all rows
|
|
69
|
-
console.log(await apiOrderDetail.patchById({patch: {sets: {ItemRef: "2024-TX-0001", ItemDate: "2024-01-31"}}}, "xxxxx-xxxxx-xxxxxxxxxxxx-xxxxxx")); // change some fields
|
|
70
|
-
console.log(await apiOrderDetail.patchByFilter({patch: {sets: {LastUpdate: "2023-04-30"}, filters: ["OrderId: 'xxxxx-xxxxx-xxxxxxxxxxxx-xxxxxx'"]}})); // change by filter
|
|
71
|
-
console.log(await apiOrderDetail.deleteById("xxxxx-xxxxx-xxxxxxxxxxxx-xxxxxx")); // delete row by Id
|
|
72
|
-
console.log(await apiOrderDetail.deleteByFilter({delete: {filters: ["ItemType in ('X', 'W')", "and", "ItemDate > '2022-12-01'"]}})); // delete filterd rows
|
|
73
|
-
console.log(await apiExecuteSP.execute()); // execute procedure with no argument
|
|
74
|
-
console.log(await apiExecuteSP.execute({execute: {arguments: "@Company, @OrderNumber", params: {Company: "XXX", OrderNumber: "12345"}}})); // execute procedure with arguments and params
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
License
|
|
78
|
-
-------
|
|
79
|
-
|
|
80
|
-
MIT License
|
|
81
|
-
|
|
82
|
-
Copyright (c) 2022
|
|
83
|
-
|
|
84
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
85
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
86
|
-
in the Software without restriction, including without limitation the rights
|
|
87
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
88
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
89
|
-
furnished to do so, subject to the following conditions:
|
|
90
|
-
|
|
91
|
-
The above copyright notice and this permission notice shall be included in all
|
|
92
|
-
copies or substantial portions of the Software.
|
|
93
|
-
|
|
94
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
95
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
96
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
97
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
98
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
99
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1
|
+
# db-crud-api 💡
|
|
2
|
+
CRUD api for database tables.
|
|
3
|
+
|
|
4
|
+
## Installation
|
|
5
|
+
npm install db-crud-api
|
|
6
|
+
|
|
7
|
+
# Usage
|
|
8
|
+
```javascript
|
|
9
|
+
import dbCrudApi from "db-crud-api";
|
|
10
|
+
const apiFactory = dbCrudApi(mySchema);
|
|
11
|
+
|
|
12
|
+
const mySchema = {
|
|
13
|
+
servers: {
|
|
14
|
+
server1: {
|
|
15
|
+
realName: "server1.mydomain.com",
|
|
16
|
+
type: "ms-sql",
|
|
17
|
+
instance: "DEFAULT",
|
|
18
|
+
user: "User1",
|
|
19
|
+
password: "mypassword",
|
|
20
|
+
options: {
|
|
21
|
+
appName: "myAppName",
|
|
22
|
+
...
|
|
23
|
+
},
|
|
24
|
+
databases: {
|
|
25
|
+
db1: {
|
|
26
|
+
realName: "db_orders",
|
|
27
|
+
tables: {
|
|
28
|
+
table1: {
|
|
29
|
+
realName: "tb_orders_head",
|
|
30
|
+
idField: "Id",
|
|
31
|
+
autoId: true,
|
|
32
|
+
fields: {
|
|
33
|
+
Id: { realName: "OrderId", type: "uuid", lengh: undefined, canBeNull: false, description: "Unique Id", defaultValue: undefined },
|
|
34
|
+
CustomerId: { type: "string", lengh: undefined, canBeNull: false, description: "Customer Id", defaultValue: undefined },
|
|
35
|
+
...
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
table2: {
|
|
39
|
+
realName: "tb_orders_detail",
|
|
40
|
+
idField: "Id",
|
|
41
|
+
autoId: true,
|
|
42
|
+
fields: {
|
|
43
|
+
Id: { realName: "OrderId", type: "uuid", lengh: undefined, canBeNull: false, description: "Unique Id", defaultValue: undefined },
|
|
44
|
+
OrderId: { type: "uuid", lengh: undefined, canBeNull: false, description: "Order Id", defaultValue: undefined },
|
|
45
|
+
RowSeq: { type: "numeric", lengh: undefined, canBeNull: false, description: "Row sequence", defaultValue: undefined },
|
|
46
|
+
...
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
...
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
...
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
...
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const apiOrder = apiFactory.newROApi("server1.db1.table1"); // Read Only api
|
|
60
|
+
const apiOrderDetail = apiFactory.newFullApi("table2"); // full CRUD api
|
|
61
|
+
const apiExecuteSP = apiFactory.newExecuteApi("db1.my_storeproc"); // execute my_storeproc
|
|
62
|
+
|
|
63
|
+
console.log(await apiFactory.testConnection()); // optional
|
|
64
|
+
|
|
65
|
+
console.log(await apiOrder.getById("xxxxx-xxxxx-xxxxxxxxxxxx-xxxxxx"));
|
|
66
|
+
console.log(await apiOrder.getById("xxxxx-xxxxx-xxxxxxxxxxxx-xxxxxx", {get: {fields: ["Id", "OrderNumber", "OrderTotal"]}}));
|
|
67
|
+
console.log(await apiOrder.getByFilter({get: {filters: ["OrderType in ('P', 'A')", "and", "OrderDate > '2022-12-01'"]}})); // get filterd rows
|
|
68
|
+
console.log(await apiOrder.getByFilter()); // this get all rows
|
|
69
|
+
console.log(await apiOrderDetail.patchById({patch: {sets: {ItemRef: "2024-TX-0001", ItemDate: "2024-01-31"}}}, "xxxxx-xxxxx-xxxxxxxxxxxx-xxxxxx")); // change some fields
|
|
70
|
+
console.log(await apiOrderDetail.patchByFilter({patch: {sets: {LastUpdate: "2023-04-30"}, filters: ["OrderId: 'xxxxx-xxxxx-xxxxxxxxxxxx-xxxxxx'"]}})); // change by filter
|
|
71
|
+
console.log(await apiOrderDetail.deleteById("xxxxx-xxxxx-xxxxxxxxxxxx-xxxxxx")); // delete row by Id
|
|
72
|
+
console.log(await apiOrderDetail.deleteByFilter({delete: {filters: ["ItemType in ('X', 'W')", "and", "ItemDate > '2022-12-01'"]}})); // delete filterd rows
|
|
73
|
+
console.log(await apiExecuteSP.execute()); // execute procedure with no argument
|
|
74
|
+
console.log(await apiExecuteSP.execute({execute: {arguments: "@Company, @OrderNumber", params: {Company: "XXX", OrderNumber: "12345"}}})); // execute procedure with arguments and params
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
License
|
|
78
|
+
-------
|
|
79
|
+
|
|
80
|
+
MIT License
|
|
81
|
+
|
|
82
|
+
Copyright (c) 2022
|
|
83
|
+
|
|
84
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
85
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
86
|
+
in the Software without restriction, including without limitation the rights
|
|
87
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
88
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
89
|
+
furnished to do so, subject to the following conditions:
|
|
90
|
+
|
|
91
|
+
The above copyright notice and this permission notice shall be included in all
|
|
92
|
+
copies or substantial portions of the Software.
|
|
93
|
+
|
|
94
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
95
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
96
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
97
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
98
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
99
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
100
100
|
SOFTWARE.
|
package/index.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import schema from "./lib/schema.js";
|
|
4
|
-
import * as apiFactory from "./lib/api-factory.js";
|
|
5
|
-
|
|
6
|
-
export default function(customSchema) {
|
|
7
|
-
if (customSchema && customSchema.servers) {
|
|
8
|
-
schema.servers = customSchema.servers;
|
|
9
|
-
}
|
|
10
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import schema from "./lib/schema.js";
|
|
4
|
+
import * as apiFactory from "./lib/api-factory.js";
|
|
5
|
+
|
|
6
|
+
export default function(customSchema, config) {
|
|
7
|
+
if (customSchema && customSchema.servers) {
|
|
8
|
+
schema.servers = customSchema.servers;
|
|
9
|
+
}
|
|
10
|
+
if (config) {
|
|
11
|
+
if (config.log) {
|
|
12
|
+
if (config.log.level) {
|
|
13
|
+
if (typeof(config.log.level) === 'number') { schema.config.log.level = config.log.level }
|
|
14
|
+
else if (typeof(config.log.level) === 'string' && Number.parseInt(config.log.level) != NaN) { schema.config.log.level = Number.parseInt(config.log.level) }
|
|
15
|
+
}
|
|
16
|
+
if (config.log.callback && typeof(config.log.callback) === 'function') { schema.config.log.callback = config.log.callback }
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return apiFactory;
|
|
11
20
|
}
|
package/lib/api-factory.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import * as dbOpe from "./db-operations.js"
|
|
4
|
-
import apiFull from "./api-full.js"
|
|
5
|
-
import apiRO from "./api-ro.js"
|
|
6
|
-
import apiExecute from "./api-execute.js"
|
|
7
|
-
import apiBatch from "./api-batch.js"
|
|
8
|
-
|
|
9
|
-
export function newFullApi(tablePath) {
|
|
10
|
-
return new apiFull(tablePath);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function newROApi(tablePath) {
|
|
14
|
-
return new apiRO(tablePath);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function newExecuteApi(procPath) {
|
|
18
|
-
return new apiExecute(procPath);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function newBatchApi(useTransaction) {
|
|
22
|
-
return new apiBatch(useTransaction);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function closeAllDbConnections() {
|
|
26
|
-
return dbOpe.closeAllConnections();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function testDbConnection() {
|
|
30
|
-
return dbOpe.testConnection();
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import * as dbOpe from "./db-operations.js"
|
|
4
|
+
import apiFull from "./api-full.js"
|
|
5
|
+
import apiRO from "./api-ro.js"
|
|
6
|
+
import apiExecute from "./api-execute.js"
|
|
7
|
+
import apiBatch from "./api-batch.js"
|
|
8
|
+
|
|
9
|
+
export function newFullApi(tablePath) {
|
|
10
|
+
return new apiFull(tablePath);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function newROApi(tablePath) {
|
|
14
|
+
return new apiRO(tablePath);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function newExecuteApi(procPath) {
|
|
18
|
+
return new apiExecute(procPath);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function newBatchApi(useTransaction) {
|
|
22
|
+
return new apiBatch(useTransaction);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function closeAllDbConnections() {
|
|
26
|
+
return dbOpe.closeAllConnections();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function testDbConnection() {
|
|
30
|
+
return dbOpe.testConnection();
|
|
31
31
|
}
|
package/lib/db-operations.js
CHANGED
|
@@ -1,427 +1,427 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// import modules
|
|
4
|
-
import schema from './schema.js'
|
|
5
|
-
import * as mssql from './mssql.js';
|
|
6
|
-
import * as mysql from './mysql.js';
|
|
7
|
-
|
|
8
|
-
// Common
|
|
9
|
-
const defautlFields = ['*'];
|
|
10
|
-
export const serverType = Object.freeze({ mssql: 'ms-sql', mysql: 'my-sql', mongodb: 'mongo-db' });
|
|
11
|
-
export const objectType = Object.freeze({ table: 'T', procedure: 'P' });
|
|
12
|
-
|
|
13
|
-
// Exported functions
|
|
14
|
-
export function idField(tSchema) {
|
|
15
|
-
return tSchema.table?.idField ?? 'id';
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function autoId(tSchema) {
|
|
19
|
-
return tSchema.table?.autoId;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export async function runQuery(dbOpes) {
|
|
23
|
-
|
|
24
|
-
// all connections must have same id
|
|
25
|
-
const _connection = Array.isArray(dbOpes) ? dbOpes[0].connection : dbOpes.connection;
|
|
26
|
-
if (Array.isArray(dbOpes)) {
|
|
27
|
-
for (let i = 1; i < dbOpes.length; i++) {
|
|
28
|
-
if (dbOpes[i].connection?.id !== _connection.id) throw new TypeError('runQuery: for multiple operations, connection must be the same');
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// MSSQL
|
|
33
|
-
if (_connection.serverType === serverType.mssql) {
|
|
34
|
-
return await mssql.query(_connection, dbOpes);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// MySQL
|
|
38
|
-
else if (_connection.serverType === serverType.mysql) {
|
|
39
|
-
return await mysql.query(_connection, dbOpes);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// server type not supported
|
|
43
|
-
else throw new TypeError('server type not supported');
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function prepareConnection(schema) {
|
|
48
|
-
// MySQL
|
|
49
|
-
if (schema.server.type === serverType.mysql) {
|
|
50
|
-
const _return = mysql.prepareConnection(schema);
|
|
51
|
-
_return.serverType = serverType.mysql; // append 'serverType' to connection
|
|
52
|
-
return _return;
|
|
53
|
-
}
|
|
54
|
-
// MSSQL is also the default
|
|
55
|
-
if (!schema.server.type || schema.server.type === serverType.mssql) {
|
|
56
|
-
const _return = mssql.prepareConnection(schema);
|
|
57
|
-
_return.serverType = serverType.mssql; // append 'serverType' to connection
|
|
58
|
-
return _return;
|
|
59
|
-
}
|
|
60
|
-
throw new TypeError('server type not supported');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function closeConnection(connection) {
|
|
64
|
-
// MSSQL
|
|
65
|
-
if (connection.serverType === serverType.mssql) { return mssql.closeConnection(connection); }
|
|
66
|
-
// MySQL
|
|
67
|
-
if (connection.serverType === serverType.mysql) { return mysql.closeConnection(connection); }
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export function closeAllConnections() {
|
|
71
|
-
// MSSQL
|
|
72
|
-
mssql.closeAllConnections();
|
|
73
|
-
// MySQL
|
|
74
|
-
mysql.closeAllConnections();
|
|
75
|
-
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function testConnection() {
|
|
80
|
-
const _connection = prepareConnection(prepareSchema("test", objectType.procedure));
|
|
81
|
-
// MSSQL
|
|
82
|
-
if (_connection.serverType === serverType.mssql) { return mssql.testConnection(_connection); }
|
|
83
|
-
// MySQL
|
|
84
|
-
if (_connection.serverType === serverType.mysql) { return mysql.testConnection(_connection); }
|
|
85
|
-
// server type not supported
|
|
86
|
-
throw new TypeError('server type not supported');
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function toStringValue(value) {
|
|
90
|
-
if (!value) return 'null';
|
|
91
|
-
if (value.trimStart().charAt(0) === '\'') return value;
|
|
92
|
-
return `\'${value}\'`;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function prepareSchema(obj, objType) {
|
|
96
|
-
// objType = 'objectType.' (Table or StoreProcedure)
|
|
97
|
-
// obj = 'systemName.dbName.objName' or 'dbName.objName' or 'objName' or 'systemNme..objName'
|
|
98
|
-
|
|
99
|
-
if (obj == undefined || typeof obj !== 'string') throw new TypeError('prepareSchema: wrong obj');
|
|
100
|
-
if (objType !== undefined && objType !== objectType.table && objType !== objectType.procedure) throw new TypeError(`prepareSchema: wrong objType, must be ${objectType.join(', ')}`);
|
|
101
|
-
const objPath = obj.trimStart().split(' ')[0];
|
|
102
|
-
|
|
103
|
-
// split objPath to serverName,dbName,objName
|
|
104
|
-
let serverName = undefined;
|
|
105
|
-
let dbName = undefined;
|
|
106
|
-
let objName = undefined;
|
|
107
|
-
const objPathArray = objPath.split('.');
|
|
108
|
-
if (objPathArray.length > 2) {
|
|
109
|
-
serverName = objPathArray[0]
|
|
110
|
-
dbName = objPathArray[1]
|
|
111
|
-
objName = objPathArray[2]
|
|
112
|
-
}
|
|
113
|
-
else if (objPathArray.length > 1) {
|
|
114
|
-
dbName = objPathArray[0]
|
|
115
|
-
objName = objPathArray[1]
|
|
116
|
-
}
|
|
117
|
-
else if (objPathArray.length > 0) {
|
|
118
|
-
objName = objPathArray[0]
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// server
|
|
122
|
-
if (!serverName || serverName.length == 0) {
|
|
123
|
-
if (!schema.servers || !Object.keys(schema.servers)[0]) throw new TypeError('missing default server in dbSchema');
|
|
124
|
-
serverName = Object.keys(schema.servers)[0];
|
|
125
|
-
}
|
|
126
|
-
else { // add server to schema
|
|
127
|
-
if (!schema.servers) { schema.servers = {} };
|
|
128
|
-
if (!schema.servers[serverName]) { schema.servers[serverName] = {} };
|
|
129
|
-
}
|
|
130
|
-
if (!schema.servers[serverName].realName) { schema.servers[serverName].realName = serverName } // add realName
|
|
131
|
-
|
|
132
|
-
// database
|
|
133
|
-
if (!dbName || dbName.length == 0) {
|
|
134
|
-
if (!schema.servers[serverName].databases || !Object.keys(schema.servers[serverName].databases)[0]) throw new TypeError('missing default database in dbSchema');
|
|
135
|
-
dbName = Object.keys(schema.servers[serverName].databases)[0];
|
|
136
|
-
}
|
|
137
|
-
else { // add db to schema
|
|
138
|
-
if (!schema.servers[serverName].databases) { schema.servers[serverName].databases = {} };
|
|
139
|
-
if (!schema.servers[serverName].databases[dbName]) { schema.servers[serverName].databases[dbName] = {} };
|
|
140
|
-
}
|
|
141
|
-
if (!schema.servers[serverName].databases[dbName].realName) { schema.servers[serverName].databases[dbName].realName = dbName } // add realName
|
|
142
|
-
|
|
143
|
-
// table
|
|
144
|
-
if (objType === objectType.table || objType == undefined) {
|
|
145
|
-
if (!objName || objName.length == 0) {
|
|
146
|
-
if (!schema.servers[serverName].databases[dbName] || !Object.keys(schema.servers[serverName].databases[dbName].tables)[0]) throw new TypeError('missing default table in dbSchema');
|
|
147
|
-
objName = Object.keys(schema.servers[serverName].databases[dbName].tables)[0];
|
|
148
|
-
}
|
|
149
|
-
else { // add table to schema
|
|
150
|
-
if (!schema.servers[serverName].databases[dbName].tables) { schema.servers[serverName].databases[dbName].tables = {} };
|
|
151
|
-
if (!schema.servers[serverName].databases[dbName].tables[objName]) { schema.servers[serverName].databases[dbName].tables[objName] = {} }
|
|
152
|
-
}
|
|
153
|
-
if (!schema.servers[serverName].databases[dbName].tables[objName].realName) { schema.servers[serverName].databases[dbName].tables[objName].realName = objName } // add realName
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// store procedure
|
|
157
|
-
if (objType === objectType.procedure) {
|
|
158
|
-
if (!objName || objName.length == 0) {
|
|
159
|
-
if (!schema.servers[serverName].databases[dbName] || !Object.keys(schema.servers[serverName].databases[dbName].procedures)[0]) throw new TypeError('missing default procedure in dbSchema');
|
|
160
|
-
objName = Object.keys(schema.servers[serverName].databases[dbName].procedures)[0];
|
|
161
|
-
}
|
|
162
|
-
else { // add storeprocedure to schema
|
|
163
|
-
if (!schema.servers[serverName].databases[dbName].procedures) { schema.servers[serverName].databases[dbName].procedures = {} };
|
|
164
|
-
if (!schema.servers[serverName].databases[dbName].procedures[objName]) { schema.servers[serverName].databases[dbName].procedures[objName] = {command: obj} }
|
|
165
|
-
}
|
|
166
|
-
if (!schema.servers[serverName].databases[dbName].procedures[objName].realName) { schema.servers[serverName].databases[dbName].procedures[objName].realName = objName } // add realName
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// return Schema
|
|
170
|
-
return {
|
|
171
|
-
table: (objType == undefined || objType === objectType.table) ? schema.servers[serverName].databases[dbName].tables[objName] : undefined,
|
|
172
|
-
procedure: (objType === objectType.procedure) ? schema.servers[serverName].databases[dbName].procedures[objName] : undefined,
|
|
173
|
-
database: schema.servers[serverName].databases[dbName],
|
|
174
|
-
server: schema.servers[serverName]
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
export function prepareRun(tSchema, connection, reqOpe) {
|
|
180
|
-
const _reqOpe = [];
|
|
181
|
-
const _result = [];
|
|
182
|
-
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
183
|
-
else _reqOpe.push(reqOpe);
|
|
184
|
-
_reqOpe.forEach(function (_ope) {
|
|
185
|
-
if (_ope?.get) _result.push(prepareGet(tSchema, connection, _ope));
|
|
186
|
-
else if (_ope?.patch) _result.push(preparePatch(tSchema, connection, _ope));
|
|
187
|
-
else if (_ope?.put) _result.push(preparePut(tSchema, connection, _ope));
|
|
188
|
-
else if (_ope?.delete) _result.push(prepareDelete(tSchema, connection, _ope));
|
|
189
|
-
else if (_ope?.execute) _result.push(prepareExecute(connection, _ope));
|
|
190
|
-
else if (_ope?.begin) _result.push(prepareBegin(connection, _ope));
|
|
191
|
-
else if (_ope?.commit) _result.push(prepareCommit(connection, _ope));
|
|
192
|
-
else if (_ope?.rollback) _result.push(prepareRollback(connection, _ope));
|
|
193
|
-
else if (_ope?.passthrough) _result.push(preparePassthrough(connection, _ope));
|
|
194
|
-
else throw new Error('Request sintax error, missing property get/patch/put/delete/...');
|
|
195
|
-
});
|
|
196
|
-
if (_result.length > 1) return _result;
|
|
197
|
-
if (_result.length = 1) return _result[0];
|
|
198
|
-
return undefined;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
export function prepareRunById(tSchema, connection, reqOpe, idValue) {
|
|
202
|
-
if (reqOpe?.get) return prepareGetById(tSchema, connection, reqOpe, idValue);
|
|
203
|
-
if (reqOpe?.patch) return preparePatchById(tSchema, connection, reqOpe, idValue);
|
|
204
|
-
if (reqOpe?.put) return preparePutById(tSchema, connection, reqOpe, idValue);
|
|
205
|
-
if (reqOpe?.delete) return prepareDeleteById(tSchema, connection, reqOpe, idValue);
|
|
206
|
-
else throw new Error('Request sintax error, missing property get/patch/put/delete...');
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export function prepareGet(tSchema, connection, reqOpe) {
|
|
210
|
-
const _reqOpe = [];
|
|
211
|
-
const _result = [];
|
|
212
|
-
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
213
|
-
else _reqOpe.push(reqOpe);
|
|
214
|
-
_reqOpe.forEach(function (_ope) {
|
|
215
|
-
_result.push({
|
|
216
|
-
get: {
|
|
217
|
-
schema: tSchema,
|
|
218
|
-
options: _ope?.get?.options,
|
|
219
|
-
fields: _ope?.get?.fields ?? defautlFields,
|
|
220
|
-
filters: _ope?.get?.filters,
|
|
221
|
-
groups: _ope?.get?.groups,
|
|
222
|
-
groupsFilters: _ope?.get?.groupsFilters,
|
|
223
|
-
orderBy: _ope?.get?.orderBy,
|
|
224
|
-
params: _ope?.get?.params
|
|
225
|
-
},
|
|
226
|
-
connection: connection
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
if (_result.length > 1) return _result;
|
|
230
|
-
if (_result.length = 1) return _result[0];
|
|
231
|
-
return undefined;
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
export function prepareGetById(tSchema, connection, reqOpe, idValue) {
|
|
235
|
-
const _filters = [idField(tSchema) + ' = ' + toStringValue(idValue)];
|
|
236
|
-
if (reqOpe?.get?.filters && reqOpe?.get?.filters.length > 0) {
|
|
237
|
-
_filters.push('and');
|
|
238
|
-
Array.isArray(reqOpe.get.filters) ? _filters.push(...reqOpe.get.filters) : _filters.push(reqOpe.get.filters);
|
|
239
|
-
}
|
|
240
|
-
return {
|
|
241
|
-
get: {
|
|
242
|
-
schema: tSchema,
|
|
243
|
-
options: reqOpe?.get?.options,
|
|
244
|
-
fields: reqOpe?.get?.fields ?? defautlFields,
|
|
245
|
-
filters: _filters
|
|
246
|
-
},
|
|
247
|
-
connection: connection
|
|
248
|
-
}
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
export function preparePatch(tSchema, connection, reqOpe) {
|
|
252
|
-
const _reqOpe = [];
|
|
253
|
-
const _result = [];
|
|
254
|
-
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
255
|
-
else _reqOpe.push(reqOpe);
|
|
256
|
-
_reqOpe.forEach(function (_ope) {
|
|
257
|
-
if (_ope?.patch) {
|
|
258
|
-
if (!_ope.patch.sets) throw new Error('Request sintax error, missing "patch.sets" property.')
|
|
259
|
-
_result.push({
|
|
260
|
-
patch: {
|
|
261
|
-
schema: tSchema,
|
|
262
|
-
sets: _ope.patch.sets,
|
|
263
|
-
filters: _ope.patch.filters,
|
|
264
|
-
params: _ope.patch.params
|
|
265
|
-
},
|
|
266
|
-
connection: connection
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
else throw new Error('Request sintax error, missing "patch" property.');
|
|
270
|
-
});
|
|
271
|
-
if (_result.length > 1) return _result;
|
|
272
|
-
if (_result.length = 1) return _result[0];
|
|
273
|
-
return undefined;
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
export function preparePatchById(tSchema, connection, reqOpe, idValue) {
|
|
277
|
-
if (!reqOpe?.patch) throw new Error('Request sintax error, missing "patch" property.')
|
|
278
|
-
if (!reqOpe.patch.sets) throw new Error('Missing "patch.sets" in operation.')
|
|
279
|
-
const _filters = [idField(tSchema) + ' = ' + toStringValue(idValue)];
|
|
280
|
-
if (reqOpe?.patch?.filters && reqOpe?.patch?.filters.length > 0) {
|
|
281
|
-
_filters.push('and');
|
|
282
|
-
Array.isArray(reqOpe.patch.filters) ? _filters.push(...reqOpe.patch.filters) : _filters.push(reqOpe.patch.filters);
|
|
283
|
-
}
|
|
284
|
-
return {
|
|
285
|
-
patch: {
|
|
286
|
-
schema: tSchema,
|
|
287
|
-
sets: reqOpe.patch.sets,
|
|
288
|
-
filters: _filters
|
|
289
|
-
},
|
|
290
|
-
connection: connection
|
|
291
|
-
}
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
export function preparePut(tSchema, connection, reqOpe) {
|
|
295
|
-
const _reqOpe = [];
|
|
296
|
-
const _result = [];
|
|
297
|
-
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
298
|
-
else _reqOpe.push(reqOpe);
|
|
299
|
-
_reqOpe.forEach(function (_ope) {
|
|
300
|
-
if (_ope?.put) {
|
|
301
|
-
if (!_ope.put.sets) throw new Error('Request sintax error, missing "put.sets" property.')
|
|
302
|
-
_result.push({
|
|
303
|
-
put: {
|
|
304
|
-
schema: tSchema,
|
|
305
|
-
sets: _ope.put.sets,
|
|
306
|
-
params: _ope.put.params
|
|
307
|
-
},
|
|
308
|
-
connection: connection
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
else throw new Error('Request sintax error, missing "put" property.');
|
|
312
|
-
});
|
|
313
|
-
if (_result.length > 1) return _result;
|
|
314
|
-
if (_result.length = 1) return _result[0];
|
|
315
|
-
return undefined;
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
export function preparePutById(tSchema, connection, reqOpe, idValue) {
|
|
319
|
-
if (!reqOpe?.put) throw new Error('Request sintax error, missing "put" property.')
|
|
320
|
-
if (!reqOpe.put.sets) throw new Error('Missing "put.sets" in operation.')
|
|
321
|
-
reqOpe.put.sets[idField(tSchema)] = idValue;
|
|
322
|
-
return {
|
|
323
|
-
put: {
|
|
324
|
-
schema: tSchema,
|
|
325
|
-
sets: reqOpe.put.sets,
|
|
326
|
-
params: reqOpe.put.params
|
|
327
|
-
},
|
|
328
|
-
connection: connection
|
|
329
|
-
}
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
export function prepareDelete(tSchema, connection, reqOpe) {
|
|
333
|
-
const _reqOpe = [];
|
|
334
|
-
const _result = [];
|
|
335
|
-
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
336
|
-
else _reqOpe.push(reqOpe);
|
|
337
|
-
_reqOpe.forEach(function (_ope) {
|
|
338
|
-
if (_ope?.delete) {
|
|
339
|
-
_result.push({
|
|
340
|
-
delete: {
|
|
341
|
-
schema: tSchema,
|
|
342
|
-
filters: _ope.delete.filters,
|
|
343
|
-
params: _ope.delete.params
|
|
344
|
-
},
|
|
345
|
-
connection: connection
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
else throw new Error('Request sintax error, missing "delete" property.');
|
|
349
|
-
});
|
|
350
|
-
if (_result.length > 1) return _result;
|
|
351
|
-
if (_result.length = 1) return _result[0];
|
|
352
|
-
return undefined;
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
export function prepareDeleteById(tSchema, connection, idValue) {
|
|
356
|
-
return {
|
|
357
|
-
delete: {
|
|
358
|
-
schema: tSchema,
|
|
359
|
-
filters: [idField(tSchema) + ' = ' + toStringValue(idValue)]
|
|
360
|
-
},
|
|
361
|
-
connection: connection
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
|
-
|
|
365
|
-
export function prepareExecute(pSchema, connection, reqOpe) {
|
|
366
|
-
const _reqOpe = [];
|
|
367
|
-
const _result = [];
|
|
368
|
-
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
369
|
-
else _reqOpe.push(reqOpe);
|
|
370
|
-
_reqOpe.forEach(function (_ope) {
|
|
371
|
-
_result.push({
|
|
372
|
-
execute: {
|
|
373
|
-
schema: pSchema,
|
|
374
|
-
arguments: _ope.execute?.arguments,
|
|
375
|
-
params: _ope.execute?.params
|
|
376
|
-
},
|
|
377
|
-
connection: connection
|
|
378
|
-
});
|
|
379
|
-
});
|
|
380
|
-
if (_result.length > 1) return _result;
|
|
381
|
-
if (_result.length = 1) return _result[0];
|
|
382
|
-
return undefined;
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
export function preparePassthrough(connection, reqOpe) {
|
|
386
|
-
const _reqOpe = [];
|
|
387
|
-
const _result = [];
|
|
388
|
-
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
389
|
-
else _reqOpe.push(reqOpe);
|
|
390
|
-
_reqOpe.forEach(function (_ope) {
|
|
391
|
-
if (_ope?.passthrough) {
|
|
392
|
-
if (!_ope.passthrough.command) throw new Error('Request sintax error, missing "passthrough.command" property.')
|
|
393
|
-
_result.push({
|
|
394
|
-
passthrough: {
|
|
395
|
-
command: _ope.passthrough.command,
|
|
396
|
-
params: _ope.passthrough.params
|
|
397
|
-
},
|
|
398
|
-
connection: connection
|
|
399
|
-
});
|
|
400
|
-
}
|
|
401
|
-
else throw new Error('Request sintax error, missing "passthrough" property.');
|
|
402
|
-
});
|
|
403
|
-
if (_result.length > 1) return _result;
|
|
404
|
-
if (_result.length = 1) return _result[0];
|
|
405
|
-
return undefined;
|
|
406
|
-
};
|
|
407
|
-
|
|
408
|
-
export function prepareBegin(connection, reqOpe) {
|
|
409
|
-
return {
|
|
410
|
-
begin: {},
|
|
411
|
-
connection: connection
|
|
412
|
-
}
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
export function prepareCommit(connection, reqOpe) {
|
|
416
|
-
return {
|
|
417
|
-
commit: {},
|
|
418
|
-
connection: connection
|
|
419
|
-
}
|
|
420
|
-
};
|
|
421
|
-
|
|
422
|
-
export function prepareRollback(connection, reqOpe) {
|
|
423
|
-
return {
|
|
424
|
-
rollback: {},
|
|
425
|
-
connection: connection
|
|
426
|
-
}
|
|
427
|
-
};
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// import modules
|
|
4
|
+
import schema from './schema.js'
|
|
5
|
+
import * as mssql from './mssql.js';
|
|
6
|
+
import * as mysql from './mysql.js';
|
|
7
|
+
|
|
8
|
+
// Common
|
|
9
|
+
const defautlFields = ['*'];
|
|
10
|
+
export const serverType = Object.freeze({ mssql: 'ms-sql', mysql: 'my-sql', mongodb: 'mongo-db' });
|
|
11
|
+
export const objectType = Object.freeze({ table: 'T', procedure: 'P' });
|
|
12
|
+
|
|
13
|
+
// Exported functions
|
|
14
|
+
export function idField(tSchema) {
|
|
15
|
+
return tSchema.table?.idField ?? 'id';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function autoId(tSchema) {
|
|
19
|
+
return tSchema.table?.autoId;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function runQuery(dbOpes) {
|
|
23
|
+
|
|
24
|
+
// all connections must have same id
|
|
25
|
+
const _connection = Array.isArray(dbOpes) ? dbOpes[0].connection : dbOpes.connection;
|
|
26
|
+
if (Array.isArray(dbOpes)) {
|
|
27
|
+
for (let i = 1; i < dbOpes.length; i++) {
|
|
28
|
+
if (dbOpes[i].connection?.id !== _connection.id) throw new TypeError('runQuery: for multiple operations, connection must be the same');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// MSSQL
|
|
33
|
+
if (_connection.serverType === serverType.mssql) {
|
|
34
|
+
return await mssql.query(_connection, dbOpes);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// MySQL
|
|
38
|
+
else if (_connection.serverType === serverType.mysql) {
|
|
39
|
+
return await mysql.query(_connection, dbOpes);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// server type not supported
|
|
43
|
+
else throw new TypeError('server type not supported');
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function prepareConnection(schema) {
|
|
48
|
+
// MySQL
|
|
49
|
+
if (schema.server.type === serverType.mysql) {
|
|
50
|
+
const _return = mysql.prepareConnection(schema);
|
|
51
|
+
_return.serverType = serverType.mysql; // append 'serverType' to connection
|
|
52
|
+
return _return;
|
|
53
|
+
}
|
|
54
|
+
// MSSQL is also the default
|
|
55
|
+
if (!schema.server.type || schema.server.type === serverType.mssql) {
|
|
56
|
+
const _return = mssql.prepareConnection(schema);
|
|
57
|
+
_return.serverType = serverType.mssql; // append 'serverType' to connection
|
|
58
|
+
return _return;
|
|
59
|
+
}
|
|
60
|
+
throw new TypeError('server type not supported');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function closeConnection(connection) {
|
|
64
|
+
// MSSQL
|
|
65
|
+
if (connection.serverType === serverType.mssql) { return mssql.closeConnection(connection); }
|
|
66
|
+
// MySQL
|
|
67
|
+
if (connection.serverType === serverType.mysql) { return mysql.closeConnection(connection); }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function closeAllConnections() {
|
|
71
|
+
// MSSQL
|
|
72
|
+
mssql.closeAllConnections();
|
|
73
|
+
// MySQL
|
|
74
|
+
mysql.closeAllConnections();
|
|
75
|
+
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function testConnection() {
|
|
80
|
+
const _connection = prepareConnection(prepareSchema("test", objectType.procedure));
|
|
81
|
+
// MSSQL
|
|
82
|
+
if (_connection.serverType === serverType.mssql) { return mssql.testConnection(_connection); }
|
|
83
|
+
// MySQL
|
|
84
|
+
if (_connection.serverType === serverType.mysql) { return mysql.testConnection(_connection); }
|
|
85
|
+
// server type not supported
|
|
86
|
+
throw new TypeError('server type not supported');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function toStringValue(value) {
|
|
90
|
+
if (!value) return 'null';
|
|
91
|
+
if (value.trimStart().charAt(0) === '\'') return value;
|
|
92
|
+
return `\'${value}\'`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function prepareSchema(obj, objType) {
|
|
96
|
+
// objType = 'objectType.' (Table or StoreProcedure)
|
|
97
|
+
// obj = 'systemName.dbName.objName' or 'dbName.objName' or 'objName' or 'systemNme..objName'
|
|
98
|
+
|
|
99
|
+
if (obj == undefined || typeof obj !== 'string') throw new TypeError('prepareSchema: wrong obj');
|
|
100
|
+
if (objType !== undefined && objType !== objectType.table && objType !== objectType.procedure) throw new TypeError(`prepareSchema: wrong objType, must be ${objectType.join(', ')}`);
|
|
101
|
+
const objPath = obj.trimStart().split(' ')[0];
|
|
102
|
+
|
|
103
|
+
// split objPath to serverName,dbName,objName
|
|
104
|
+
let serverName = undefined;
|
|
105
|
+
let dbName = undefined;
|
|
106
|
+
let objName = undefined;
|
|
107
|
+
const objPathArray = objPath.split('.');
|
|
108
|
+
if (objPathArray.length > 2) {
|
|
109
|
+
serverName = objPathArray[0]
|
|
110
|
+
dbName = objPathArray[1]
|
|
111
|
+
objName = objPathArray[2]
|
|
112
|
+
}
|
|
113
|
+
else if (objPathArray.length > 1) {
|
|
114
|
+
dbName = objPathArray[0]
|
|
115
|
+
objName = objPathArray[1]
|
|
116
|
+
}
|
|
117
|
+
else if (objPathArray.length > 0) {
|
|
118
|
+
objName = objPathArray[0]
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// server
|
|
122
|
+
if (!serverName || serverName.length == 0) {
|
|
123
|
+
if (!schema.servers || !Object.keys(schema.servers)[0]) throw new TypeError('missing default server in dbSchema');
|
|
124
|
+
serverName = Object.keys(schema.servers)[0];
|
|
125
|
+
}
|
|
126
|
+
else { // add server to schema
|
|
127
|
+
if (!schema.servers) { schema.servers = {} };
|
|
128
|
+
if (!schema.servers[serverName]) { schema.servers[serverName] = {} };
|
|
129
|
+
}
|
|
130
|
+
if (!schema.servers[serverName].realName) { schema.servers[serverName].realName = serverName } // add realName
|
|
131
|
+
|
|
132
|
+
// database
|
|
133
|
+
if (!dbName || dbName.length == 0) {
|
|
134
|
+
if (!schema.servers[serverName].databases || !Object.keys(schema.servers[serverName].databases)[0]) throw new TypeError('missing default database in dbSchema');
|
|
135
|
+
dbName = Object.keys(schema.servers[serverName].databases)[0];
|
|
136
|
+
}
|
|
137
|
+
else { // add db to schema
|
|
138
|
+
if (!schema.servers[serverName].databases) { schema.servers[serverName].databases = {} };
|
|
139
|
+
if (!schema.servers[serverName].databases[dbName]) { schema.servers[serverName].databases[dbName] = {} };
|
|
140
|
+
}
|
|
141
|
+
if (!schema.servers[serverName].databases[dbName].realName) { schema.servers[serverName].databases[dbName].realName = dbName } // add realName
|
|
142
|
+
|
|
143
|
+
// table
|
|
144
|
+
if (objType === objectType.table || objType == undefined) {
|
|
145
|
+
if (!objName || objName.length == 0) {
|
|
146
|
+
if (!schema.servers[serverName].databases[dbName] || !Object.keys(schema.servers[serverName].databases[dbName].tables)[0]) throw new TypeError('missing default table in dbSchema');
|
|
147
|
+
objName = Object.keys(schema.servers[serverName].databases[dbName].tables)[0];
|
|
148
|
+
}
|
|
149
|
+
else { // add table to schema
|
|
150
|
+
if (!schema.servers[serverName].databases[dbName].tables) { schema.servers[serverName].databases[dbName].tables = {} };
|
|
151
|
+
if (!schema.servers[serverName].databases[dbName].tables[objName]) { schema.servers[serverName].databases[dbName].tables[objName] = {} }
|
|
152
|
+
}
|
|
153
|
+
if (!schema.servers[serverName].databases[dbName].tables[objName].realName) { schema.servers[serverName].databases[dbName].tables[objName].realName = objName } // add realName
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// store procedure
|
|
157
|
+
if (objType === objectType.procedure) {
|
|
158
|
+
if (!objName || objName.length == 0) {
|
|
159
|
+
if (!schema.servers[serverName].databases[dbName] || !Object.keys(schema.servers[serverName].databases[dbName].procedures)[0]) throw new TypeError('missing default procedure in dbSchema');
|
|
160
|
+
objName = Object.keys(schema.servers[serverName].databases[dbName].procedures)[0];
|
|
161
|
+
}
|
|
162
|
+
else { // add storeprocedure to schema
|
|
163
|
+
if (!schema.servers[serverName].databases[dbName].procedures) { schema.servers[serverName].databases[dbName].procedures = {} };
|
|
164
|
+
if (!schema.servers[serverName].databases[dbName].procedures[objName]) { schema.servers[serverName].databases[dbName].procedures[objName] = {command: obj} }
|
|
165
|
+
}
|
|
166
|
+
if (!schema.servers[serverName].databases[dbName].procedures[objName].realName) { schema.servers[serverName].databases[dbName].procedures[objName].realName = objName } // add realName
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// return Schema
|
|
170
|
+
return {
|
|
171
|
+
table: (objType == undefined || objType === objectType.table) ? schema.servers[serverName].databases[dbName].tables[objName] : undefined,
|
|
172
|
+
procedure: (objType === objectType.procedure) ? schema.servers[serverName].databases[dbName].procedures[objName] : undefined,
|
|
173
|
+
database: schema.servers[serverName].databases[dbName],
|
|
174
|
+
server: schema.servers[serverName]
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function prepareRun(tSchema, connection, reqOpe) {
|
|
180
|
+
const _reqOpe = [];
|
|
181
|
+
const _result = [];
|
|
182
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
183
|
+
else _reqOpe.push(reqOpe);
|
|
184
|
+
_reqOpe.forEach(function (_ope) {
|
|
185
|
+
if (_ope?.get) _result.push(prepareGet(tSchema, connection, _ope));
|
|
186
|
+
else if (_ope?.patch) _result.push(preparePatch(tSchema, connection, _ope));
|
|
187
|
+
else if (_ope?.put) _result.push(preparePut(tSchema, connection, _ope));
|
|
188
|
+
else if (_ope?.delete) _result.push(prepareDelete(tSchema, connection, _ope));
|
|
189
|
+
else if (_ope?.execute) _result.push(prepareExecute(connection, _ope));
|
|
190
|
+
else if (_ope?.begin) _result.push(prepareBegin(connection, _ope));
|
|
191
|
+
else if (_ope?.commit) _result.push(prepareCommit(connection, _ope));
|
|
192
|
+
else if (_ope?.rollback) _result.push(prepareRollback(connection, _ope));
|
|
193
|
+
else if (_ope?.passthrough) _result.push(preparePassthrough(connection, _ope));
|
|
194
|
+
else throw new Error('Request sintax error, missing property get/patch/put/delete/...');
|
|
195
|
+
});
|
|
196
|
+
if (_result.length > 1) return _result;
|
|
197
|
+
if (_result.length = 1) return _result[0];
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function prepareRunById(tSchema, connection, reqOpe, idValue) {
|
|
202
|
+
if (reqOpe?.get) return prepareGetById(tSchema, connection, reqOpe, idValue);
|
|
203
|
+
if (reqOpe?.patch) return preparePatchById(tSchema, connection, reqOpe, idValue);
|
|
204
|
+
if (reqOpe?.put) return preparePutById(tSchema, connection, reqOpe, idValue);
|
|
205
|
+
if (reqOpe?.delete) return prepareDeleteById(tSchema, connection, reqOpe, idValue);
|
|
206
|
+
else throw new Error('Request sintax error, missing property get/patch/put/delete...');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function prepareGet(tSchema, connection, reqOpe) {
|
|
210
|
+
const _reqOpe = [];
|
|
211
|
+
const _result = [];
|
|
212
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
213
|
+
else _reqOpe.push(reqOpe);
|
|
214
|
+
_reqOpe.forEach(function (_ope) {
|
|
215
|
+
_result.push({
|
|
216
|
+
get: {
|
|
217
|
+
schema: tSchema,
|
|
218
|
+
options: _ope?.get?.options,
|
|
219
|
+
fields: _ope?.get?.fields ?? defautlFields,
|
|
220
|
+
filters: _ope?.get?.filters,
|
|
221
|
+
groups: _ope?.get?.groups,
|
|
222
|
+
groupsFilters: _ope?.get?.groupsFilters,
|
|
223
|
+
orderBy: _ope?.get?.orderBy,
|
|
224
|
+
params: _ope?.get?.params
|
|
225
|
+
},
|
|
226
|
+
connection: connection
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
if (_result.length > 1) return _result;
|
|
230
|
+
if (_result.length = 1) return _result[0];
|
|
231
|
+
return undefined;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
export function prepareGetById(tSchema, connection, reqOpe, idValue) {
|
|
235
|
+
const _filters = [idField(tSchema) + ' = ' + toStringValue(idValue)];
|
|
236
|
+
if (reqOpe?.get?.filters && reqOpe?.get?.filters.length > 0) {
|
|
237
|
+
_filters.push('and');
|
|
238
|
+
Array.isArray(reqOpe.get.filters) ? _filters.push(...reqOpe.get.filters) : _filters.push(reqOpe.get.filters);
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
get: {
|
|
242
|
+
schema: tSchema,
|
|
243
|
+
options: reqOpe?.get?.options,
|
|
244
|
+
fields: reqOpe?.get?.fields ?? defautlFields,
|
|
245
|
+
filters: _filters
|
|
246
|
+
},
|
|
247
|
+
connection: connection
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
export function preparePatch(tSchema, connection, reqOpe) {
|
|
252
|
+
const _reqOpe = [];
|
|
253
|
+
const _result = [];
|
|
254
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
255
|
+
else _reqOpe.push(reqOpe);
|
|
256
|
+
_reqOpe.forEach(function (_ope) {
|
|
257
|
+
if (_ope?.patch) {
|
|
258
|
+
if (!_ope.patch.sets) throw new Error('Request sintax error, missing "patch.sets" property.')
|
|
259
|
+
_result.push({
|
|
260
|
+
patch: {
|
|
261
|
+
schema: tSchema,
|
|
262
|
+
sets: _ope.patch.sets,
|
|
263
|
+
filters: _ope.patch.filters,
|
|
264
|
+
params: _ope.patch.params
|
|
265
|
+
},
|
|
266
|
+
connection: connection
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
else throw new Error('Request sintax error, missing "patch" property.');
|
|
270
|
+
});
|
|
271
|
+
if (_result.length > 1) return _result;
|
|
272
|
+
if (_result.length = 1) return _result[0];
|
|
273
|
+
return undefined;
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
export function preparePatchById(tSchema, connection, reqOpe, idValue) {
|
|
277
|
+
if (!reqOpe?.patch) throw new Error('Request sintax error, missing "patch" property.')
|
|
278
|
+
if (!reqOpe.patch.sets) throw new Error('Missing "patch.sets" in operation.')
|
|
279
|
+
const _filters = [idField(tSchema) + ' = ' + toStringValue(idValue)];
|
|
280
|
+
if (reqOpe?.patch?.filters && reqOpe?.patch?.filters.length > 0) {
|
|
281
|
+
_filters.push('and');
|
|
282
|
+
Array.isArray(reqOpe.patch.filters) ? _filters.push(...reqOpe.patch.filters) : _filters.push(reqOpe.patch.filters);
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
patch: {
|
|
286
|
+
schema: tSchema,
|
|
287
|
+
sets: reqOpe.patch.sets,
|
|
288
|
+
filters: _filters
|
|
289
|
+
},
|
|
290
|
+
connection: connection
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
export function preparePut(tSchema, connection, reqOpe) {
|
|
295
|
+
const _reqOpe = [];
|
|
296
|
+
const _result = [];
|
|
297
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
298
|
+
else _reqOpe.push(reqOpe);
|
|
299
|
+
_reqOpe.forEach(function (_ope) {
|
|
300
|
+
if (_ope?.put) {
|
|
301
|
+
if (!_ope.put.sets) throw new Error('Request sintax error, missing "put.sets" property.')
|
|
302
|
+
_result.push({
|
|
303
|
+
put: {
|
|
304
|
+
schema: tSchema,
|
|
305
|
+
sets: _ope.put.sets,
|
|
306
|
+
params: _ope.put.params
|
|
307
|
+
},
|
|
308
|
+
connection: connection
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
else throw new Error('Request sintax error, missing "put" property.');
|
|
312
|
+
});
|
|
313
|
+
if (_result.length > 1) return _result;
|
|
314
|
+
if (_result.length = 1) return _result[0];
|
|
315
|
+
return undefined;
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
export function preparePutById(tSchema, connection, reqOpe, idValue) {
|
|
319
|
+
if (!reqOpe?.put) throw new Error('Request sintax error, missing "put" property.')
|
|
320
|
+
if (!reqOpe.put.sets) throw new Error('Missing "put.sets" in operation.')
|
|
321
|
+
reqOpe.put.sets[idField(tSchema)] = idValue;
|
|
322
|
+
return {
|
|
323
|
+
put: {
|
|
324
|
+
schema: tSchema,
|
|
325
|
+
sets: reqOpe.put.sets,
|
|
326
|
+
params: reqOpe.put.params
|
|
327
|
+
},
|
|
328
|
+
connection: connection
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
export function prepareDelete(tSchema, connection, reqOpe) {
|
|
333
|
+
const _reqOpe = [];
|
|
334
|
+
const _result = [];
|
|
335
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
336
|
+
else _reqOpe.push(reqOpe);
|
|
337
|
+
_reqOpe.forEach(function (_ope) {
|
|
338
|
+
if (_ope?.delete) {
|
|
339
|
+
_result.push({
|
|
340
|
+
delete: {
|
|
341
|
+
schema: tSchema,
|
|
342
|
+
filters: _ope.delete.filters,
|
|
343
|
+
params: _ope.delete.params
|
|
344
|
+
},
|
|
345
|
+
connection: connection
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
else throw new Error('Request sintax error, missing "delete" property.');
|
|
349
|
+
});
|
|
350
|
+
if (_result.length > 1) return _result;
|
|
351
|
+
if (_result.length = 1) return _result[0];
|
|
352
|
+
return undefined;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
export function prepareDeleteById(tSchema, connection, idValue) {
|
|
356
|
+
return {
|
|
357
|
+
delete: {
|
|
358
|
+
schema: tSchema,
|
|
359
|
+
filters: [idField(tSchema) + ' = ' + toStringValue(idValue)]
|
|
360
|
+
},
|
|
361
|
+
connection: connection
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
export function prepareExecute(pSchema, connection, reqOpe) {
|
|
366
|
+
const _reqOpe = [];
|
|
367
|
+
const _result = [];
|
|
368
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
369
|
+
else _reqOpe.push(reqOpe);
|
|
370
|
+
_reqOpe.forEach(function (_ope) {
|
|
371
|
+
_result.push({
|
|
372
|
+
execute: {
|
|
373
|
+
schema: pSchema,
|
|
374
|
+
arguments: _ope.execute?.arguments,
|
|
375
|
+
params: _ope.execute?.params
|
|
376
|
+
},
|
|
377
|
+
connection: connection
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
if (_result.length > 1) return _result;
|
|
381
|
+
if (_result.length = 1) return _result[0];
|
|
382
|
+
return undefined;
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
export function preparePassthrough(connection, reqOpe) {
|
|
386
|
+
const _reqOpe = [];
|
|
387
|
+
const _result = [];
|
|
388
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
389
|
+
else _reqOpe.push(reqOpe);
|
|
390
|
+
_reqOpe.forEach(function (_ope) {
|
|
391
|
+
if (_ope?.passthrough) {
|
|
392
|
+
if (!_ope.passthrough.command) throw new Error('Request sintax error, missing "passthrough.command" property.')
|
|
393
|
+
_result.push({
|
|
394
|
+
passthrough: {
|
|
395
|
+
command: _ope.passthrough.command,
|
|
396
|
+
params: _ope.passthrough.params
|
|
397
|
+
},
|
|
398
|
+
connection: connection
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
else throw new Error('Request sintax error, missing "passthrough" property.');
|
|
402
|
+
});
|
|
403
|
+
if (_result.length > 1) return _result;
|
|
404
|
+
if (_result.length = 1) return _result[0];
|
|
405
|
+
return undefined;
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
export function prepareBegin(connection, reqOpe) {
|
|
409
|
+
return {
|
|
410
|
+
begin: {},
|
|
411
|
+
connection: connection
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
export function prepareCommit(connection, reqOpe) {
|
|
416
|
+
return {
|
|
417
|
+
commit: {},
|
|
418
|
+
connection: connection
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
export function prepareRollback(connection, reqOpe) {
|
|
423
|
+
return {
|
|
424
|
+
rollback: {},
|
|
425
|
+
connection: connection
|
|
426
|
+
}
|
|
427
|
+
};
|
package/lib/log.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import schema from './schema.js';
|
|
4
|
+
|
|
5
|
+
export default function log(msg, level = 1) {
|
|
6
|
+
if (schema.config.log.level >= level && schema.config.log.callback) {
|
|
7
|
+
try {
|
|
8
|
+
schema.config.log.callback({level: level, text: msg})
|
|
9
|
+
}
|
|
10
|
+
catch {}
|
|
11
|
+
}
|
|
12
|
+
};
|
package/lib/mssql.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
import sql from 'mssql';
|
|
4
|
+
import log from './log.js'
|
|
4
5
|
|
|
5
6
|
// Regex
|
|
6
7
|
const _match_LIMIT_n = /\bLIMIT\b +\d+/ig
|
|
@@ -111,14 +112,21 @@ export async function query(connection, dbOpes) {
|
|
|
111
112
|
|
|
112
113
|
sqlString = normalizeSpecialName(sqlString);
|
|
113
114
|
|
|
115
|
+
// Log
|
|
116
|
+
log(sqlString, 50);
|
|
117
|
+
log(JSON.stringify(dbOpes), 60);
|
|
118
|
+
|
|
114
119
|
// Run query
|
|
115
120
|
const sqlresult = await sqlRequest.query(sqlString);
|
|
116
121
|
|
|
117
|
-
//
|
|
122
|
+
// Log
|
|
123
|
+
log(`Query result: ${sqlresult.recordset ? sqlresult.recordset.length : 0} rows.`, 50);
|
|
124
|
+
|
|
125
|
+
// normalize return object
|
|
118
126
|
if (sqlresult.recordset == undefined) return;
|
|
119
127
|
if (sqlresult.recordset.length === 0) return;
|
|
120
|
-
|
|
121
|
-
|
|
128
|
+
|
|
129
|
+
return sqlresult.recordset;
|
|
122
130
|
}
|
|
123
131
|
|
|
124
132
|
// Normalize SpecialName
|
package/lib/mysql.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
import sql from 'mysql2/promise';
|
|
4
|
+
import log from './log.js'
|
|
4
5
|
|
|
5
6
|
// Regex
|
|
6
7
|
const _match_LIMIT_n = /\bLIMIT\b +\d+/ig
|
|
@@ -102,6 +103,10 @@ export async function query(connection, dbOpes) {
|
|
|
102
103
|
|
|
103
104
|
sqlString = normalizeSpecialName(sqlString);
|
|
104
105
|
|
|
106
|
+
// Log
|
|
107
|
+
log(JSON.stringify(dbOpes), 60);
|
|
108
|
+
log(sqlString, 50);
|
|
109
|
+
|
|
105
110
|
// Run query
|
|
106
111
|
let sqlresult = undefined;
|
|
107
112
|
let sqlconn = undefined;
|
|
@@ -112,12 +117,15 @@ export async function query(connection, dbOpes) {
|
|
|
112
117
|
catch (err) { throw (err); } // using original error
|
|
113
118
|
finally { if (sqlconn) sqlconn.release(); }
|
|
114
119
|
|
|
115
|
-
//
|
|
120
|
+
// Log
|
|
121
|
+
log(`Query result: ${(sqlresult && sqlresult.length > 0) ? sqlresult[0].length : 0} rows.`, 50);
|
|
122
|
+
|
|
123
|
+
// normalize return object
|
|
116
124
|
if (sqlresult == undefined) return;
|
|
117
125
|
if (sqlresult.length === 0) return;
|
|
118
126
|
if (sqlresult[0].length === 0) return;
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
|
|
128
|
+
return sqlresult[0];
|
|
121
129
|
}
|
|
122
130
|
|
|
123
131
|
// Normalize SpecialName
|
package/lib/schema.js
CHANGED
package/package.json
CHANGED