@heyhru/business-dms-approval 0.9.1 → 0.11.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.
- package/dist/approvals.model.d.ts.map +1 -1
- package/dist/index.js +41 -5
- package/dist/index.mjs +41 -5
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approvals.model.d.ts","sourceRoot":"","sources":["../src/approvals.model.ts"],"names":[],"mappings":"AAGA,UAAU,eAAe;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgBD,wBAAsB,cAAc,CAAC,OAAO,CAAC,EAAE,eAAe,mBAO7D;AAED,wBAAsB,aAAa,CAAC,OAAO,CAAC,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"approvals.model.d.ts","sourceRoot":"","sources":["../src/approvals.model.ts"],"names":[],"mappings":"AAGA,UAAU,eAAe;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgBD,wBAAsB,cAAc,CAAC,OAAO,CAAC,EAAE,eAAe,mBAO7D;AAED,wBAAsB,aAAa,CAAC,OAAO,CAAC,EAAE,eAAe,sCAW5D;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,gDAEzC;AAED,UAAU,oBAAoB;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,cAAc,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,OAAe,EAAE,EAAE,oBAAoB,gDAEnH;AAED,wBAAgB,YAAY,CAC1B,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,GAAG,IAAI,gDAG5B;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM;;GAEtC;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;;GAE1E"}
|
package/dist/index.js
CHANGED
|
@@ -85,9 +85,11 @@ async function countApprovals(filters) {
|
|
|
85
85
|
return Number(row?.["total"] ?? 0);
|
|
86
86
|
}
|
|
87
87
|
async function listApprovals(filters) {
|
|
88
|
-
let query = `SELECT a.*, u.username AS submitter_name
|
|
88
|
+
let query = `SELECT a.*, u.username AS submitter_name,
|
|
89
|
+
ds.name AS data_source_name, ds.type AS data_source_type
|
|
89
90
|
FROM approvals a
|
|
90
91
|
LEFT JOIN users u ON u.id = a.submitted_by
|
|
92
|
+
LEFT JOIN data_sources ds ON ds.id = a.data_source_id
|
|
91
93
|
WHERE 1=1`;
|
|
92
94
|
const { where, params } = buildWhereParams(filters);
|
|
93
95
|
query += where + " ORDER BY a.created_at DESC LIMIT ? OFFSET ?";
|
|
@@ -190,6 +192,31 @@ function approvalExecute(encryptionKey) {
|
|
|
190
192
|
}
|
|
191
193
|
};
|
|
192
194
|
}
|
|
195
|
+
function splitStatements(sql) {
|
|
196
|
+
const statements = [];
|
|
197
|
+
let current = "";
|
|
198
|
+
let inSingle = false;
|
|
199
|
+
let inDouble = false;
|
|
200
|
+
for (let i = 0; i < sql.length; i++) {
|
|
201
|
+
const ch = sql[i];
|
|
202
|
+
const prev = sql[i - 1];
|
|
203
|
+
if (ch === "'" && !inDouble && prev !== "\\") {
|
|
204
|
+
inSingle = !inSingle;
|
|
205
|
+
} else if (ch === '"' && !inSingle && prev !== "\\") {
|
|
206
|
+
inDouble = !inDouble;
|
|
207
|
+
}
|
|
208
|
+
if (ch === ";" && !inSingle && !inDouble) {
|
|
209
|
+
const trimmed2 = current.trim();
|
|
210
|
+
if (trimmed2) statements.push(trimmed2);
|
|
211
|
+
current = "";
|
|
212
|
+
} else {
|
|
213
|
+
current += ch;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const trimmed = current.trim();
|
|
217
|
+
if (trimmed) statements.push(trimmed);
|
|
218
|
+
return statements;
|
|
219
|
+
}
|
|
193
220
|
async function doExecuteApproval({ id, userId, ip, encryptionKey }, log) {
|
|
194
221
|
const approval = await getApprovalById(id);
|
|
195
222
|
if (!approval || !["approved", "execute_failed"].includes(approval["status"])) {
|
|
@@ -205,15 +232,24 @@ async function doExecuteApproval({ id, userId, ip, encryptionKey }, log) {
|
|
|
205
232
|
return (0, import_business_dms_datasource.getPool)({ ...ds, database: ds.database ?? "" });
|
|
206
233
|
})();
|
|
207
234
|
if (!pool) throw new Error("Data source not found");
|
|
208
|
-
const
|
|
209
|
-
const
|
|
235
|
+
const sqlText = approval["sql_text"];
|
|
236
|
+
const statements = splitStatements(sqlText);
|
|
237
|
+
let result;
|
|
238
|
+
if (statements.length <= 1) {
|
|
239
|
+
const rows = await pool.execute(sqlText);
|
|
240
|
+
result = `${rows.length} rows affected`;
|
|
241
|
+
} else {
|
|
242
|
+
const results = await pool.executeInTransaction(statements);
|
|
243
|
+
const details = results.map((r) => `${r.rowCount} rows`).join(", ");
|
|
244
|
+
result = `${statements.length} statements executed (${details})`;
|
|
245
|
+
}
|
|
210
246
|
await setExecuteResult(id, "executed", result);
|
|
211
|
-
log.info("Approval executed (id=%s, user=%s)", id, userId);
|
|
247
|
+
log.info("Approval executed (id=%s, user=%s, stmts=%d)", id, userId, statements.length);
|
|
212
248
|
await (0, import_business_dms_audit.writeAuditLog)({
|
|
213
249
|
userId,
|
|
214
250
|
dataSourceId,
|
|
215
251
|
action: "DML_EXECUTE",
|
|
216
|
-
sqlText
|
|
252
|
+
sqlText,
|
|
217
253
|
resultSummary: result,
|
|
218
254
|
ipAddress: ip
|
|
219
255
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -51,9 +51,11 @@ async function countApprovals(filters) {
|
|
|
51
51
|
return Number(row?.["total"] ?? 0);
|
|
52
52
|
}
|
|
53
53
|
async function listApprovals(filters) {
|
|
54
|
-
let query = `SELECT a.*, u.username AS submitter_name
|
|
54
|
+
let query = `SELECT a.*, u.username AS submitter_name,
|
|
55
|
+
ds.name AS data_source_name, ds.type AS data_source_type
|
|
55
56
|
FROM approvals a
|
|
56
57
|
LEFT JOIN users u ON u.id = a.submitted_by
|
|
58
|
+
LEFT JOIN data_sources ds ON ds.id = a.data_source_id
|
|
57
59
|
WHERE 1=1`;
|
|
58
60
|
const { where, params } = buildWhereParams(filters);
|
|
59
61
|
query += where + " ORDER BY a.created_at DESC LIMIT ? OFFSET ?";
|
|
@@ -156,6 +158,31 @@ function approvalExecute(encryptionKey) {
|
|
|
156
158
|
}
|
|
157
159
|
};
|
|
158
160
|
}
|
|
161
|
+
function splitStatements(sql) {
|
|
162
|
+
const statements = [];
|
|
163
|
+
let current = "";
|
|
164
|
+
let inSingle = false;
|
|
165
|
+
let inDouble = false;
|
|
166
|
+
for (let i = 0; i < sql.length; i++) {
|
|
167
|
+
const ch = sql[i];
|
|
168
|
+
const prev = sql[i - 1];
|
|
169
|
+
if (ch === "'" && !inDouble && prev !== "\\") {
|
|
170
|
+
inSingle = !inSingle;
|
|
171
|
+
} else if (ch === '"' && !inSingle && prev !== "\\") {
|
|
172
|
+
inDouble = !inDouble;
|
|
173
|
+
}
|
|
174
|
+
if (ch === ";" && !inSingle && !inDouble) {
|
|
175
|
+
const trimmed2 = current.trim();
|
|
176
|
+
if (trimmed2) statements.push(trimmed2);
|
|
177
|
+
current = "";
|
|
178
|
+
} else {
|
|
179
|
+
current += ch;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const trimmed = current.trim();
|
|
183
|
+
if (trimmed) statements.push(trimmed);
|
|
184
|
+
return statements;
|
|
185
|
+
}
|
|
159
186
|
async function doExecuteApproval({ id, userId, ip, encryptionKey }, log) {
|
|
160
187
|
const approval = await getApprovalById(id);
|
|
161
188
|
if (!approval || !["approved", "execute_failed"].includes(approval["status"])) {
|
|
@@ -171,15 +198,24 @@ async function doExecuteApproval({ id, userId, ip, encryptionKey }, log) {
|
|
|
171
198
|
return getPool({ ...ds, database: ds.database ?? "" });
|
|
172
199
|
})();
|
|
173
200
|
if (!pool) throw new Error("Data source not found");
|
|
174
|
-
const
|
|
175
|
-
const
|
|
201
|
+
const sqlText = approval["sql_text"];
|
|
202
|
+
const statements = splitStatements(sqlText);
|
|
203
|
+
let result;
|
|
204
|
+
if (statements.length <= 1) {
|
|
205
|
+
const rows = await pool.execute(sqlText);
|
|
206
|
+
result = `${rows.length} rows affected`;
|
|
207
|
+
} else {
|
|
208
|
+
const results = await pool.executeInTransaction(statements);
|
|
209
|
+
const details = results.map((r) => `${r.rowCount} rows`).join(", ");
|
|
210
|
+
result = `${statements.length} statements executed (${details})`;
|
|
211
|
+
}
|
|
176
212
|
await setExecuteResult(id, "executed", result);
|
|
177
|
-
log.info("Approval executed (id=%s, user=%s)", id, userId);
|
|
213
|
+
log.info("Approval executed (id=%s, user=%s, stmts=%d)", id, userId, statements.length);
|
|
178
214
|
await writeAuditLog({
|
|
179
215
|
userId,
|
|
180
216
|
dataSourceId,
|
|
181
217
|
action: "DML_EXECUTE",
|
|
182
|
-
sqlText
|
|
218
|
+
sqlText,
|
|
183
219
|
resultSummary: result,
|
|
184
220
|
ipAddress: ip
|
|
185
221
|
});
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.11.0",
|
|
7
7
|
"description": "DMS approval workflow domain logic: service, model, sql",
|
|
8
8
|
"main": "./dist/index.js",
|
|
9
9
|
"module": "./dist/index.mjs",
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
"clean": "rm -rf dist"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@heyhru/business-dms-audit": "0.6.
|
|
30
|
-
"@heyhru/business-dms-datasource": "0.8.
|
|
31
|
-
"@heyhru/server-plugin-pg": "0.
|
|
29
|
+
"@heyhru/business-dms-audit": "0.6.3",
|
|
30
|
+
"@heyhru/business-dms-datasource": "0.8.3",
|
|
31
|
+
"@heyhru/server-plugin-pg": "0.8.0",
|
|
32
32
|
"fastify": "^5.8.4"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
@@ -36,5 +36,5 @@
|
|
|
36
36
|
"typescript": "^6.0.2",
|
|
37
37
|
"vitest": "^4.1.4"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "643229b8735627837110392818e8b737a218e32b"
|
|
40
40
|
}
|