@restura/core 0.1.0-alpha.12 → 0.1.0-alpha.14
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/index.d.mts +24 -6
- package/dist/index.d.ts +24 -6
- package/dist/index.js +164 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +162 -36
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
package/dist/index.mjs
CHANGED
|
@@ -216,7 +216,7 @@ import { createHash } from "crypto";
|
|
|
216
216
|
import * as express from "express";
|
|
217
217
|
import fs3 from "fs";
|
|
218
218
|
import path3 from "path";
|
|
219
|
-
import
|
|
219
|
+
import pg3 from "pg";
|
|
220
220
|
import * as prettier3 from "prettier";
|
|
221
221
|
|
|
222
222
|
// src/restura/sql/SqlUtils.ts
|
|
@@ -1206,7 +1206,6 @@ import { ObjectUtils as ObjectUtils4 } from "@redskytech/core-utils";
|
|
|
1206
1206
|
|
|
1207
1207
|
// src/restura/sql/PsqlPool.ts
|
|
1208
1208
|
import pg from "pg";
|
|
1209
|
-
import format3 from "pg-format";
|
|
1210
1209
|
|
|
1211
1210
|
// src/restura/sql/PsqlUtils.ts
|
|
1212
1211
|
import format2 from "pg-format";
|
|
@@ -1255,25 +1254,17 @@ function SQL(strings, ...values) {
|
|
|
1255
1254
|
return query;
|
|
1256
1255
|
}
|
|
1257
1256
|
|
|
1258
|
-
// src/restura/sql/
|
|
1259
|
-
|
|
1260
|
-
var
|
|
1261
|
-
constructor(
|
|
1262
|
-
this.poolConfig = poolConfig;
|
|
1263
|
-
this.pool = new Pool(poolConfig);
|
|
1264
|
-
this.queryOne("SELECT NOW();", [], { isSystemUser: true, role: "", host: "localhost", ipAddress: "" }).then(() => {
|
|
1265
|
-
logger.info("Connected to PostgreSQL database");
|
|
1266
|
-
}).catch((error) => {
|
|
1267
|
-
logger.error("Error connecting to database", error);
|
|
1268
|
-
process.exit(1);
|
|
1269
|
-
});
|
|
1257
|
+
// src/restura/sql/PsqlConnection.ts
|
|
1258
|
+
import format3 from "pg-format";
|
|
1259
|
+
var PsqlConnection = class {
|
|
1260
|
+
constructor() {
|
|
1270
1261
|
}
|
|
1271
1262
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1272
1263
|
async queryOne(query, options, requesterDetails) {
|
|
1273
1264
|
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1274
1265
|
this.logSqlStatement(formattedQuery, options, requesterDetails);
|
|
1275
1266
|
try {
|
|
1276
|
-
const response = await this.
|
|
1267
|
+
const response = await this.query(formattedQuery, options);
|
|
1277
1268
|
if (response.rows.length === 0) throw new RsError("NOT_FOUND", "No results found");
|
|
1278
1269
|
else if (response.rows.length > 1) throw new RsError("DUPLICATE", "More than one result found");
|
|
1279
1270
|
return response.rows[0];
|
|
@@ -1290,10 +1281,8 @@ var PsqlPool = class {
|
|
|
1290
1281
|
async runQuery(query, options, requesterDetails) {
|
|
1291
1282
|
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1292
1283
|
this.logSqlStatement(formattedQuery, options, requesterDetails);
|
|
1293
|
-
const queryUpdated = query.replace(/[\t\n]/g, " ");
|
|
1294
|
-
console.log(queryUpdated, options);
|
|
1295
1284
|
try {
|
|
1296
|
-
const response = await this.
|
|
1285
|
+
const response = await this.query(formattedQuery, options);
|
|
1297
1286
|
return response.rows;
|
|
1298
1287
|
} catch (error) {
|
|
1299
1288
|
console.error(error, query, options);
|
|
@@ -1325,6 +1314,25 @@ var PsqlPool = class {
|
|
|
1325
1314
|
}
|
|
1326
1315
|
};
|
|
1327
1316
|
|
|
1317
|
+
// src/restura/sql/PsqlPool.ts
|
|
1318
|
+
var { Pool } = pg;
|
|
1319
|
+
var PsqlPool = class extends PsqlConnection {
|
|
1320
|
+
constructor(poolConfig) {
|
|
1321
|
+
super();
|
|
1322
|
+
this.poolConfig = poolConfig;
|
|
1323
|
+
this.pool = new Pool(poolConfig);
|
|
1324
|
+
this.queryOne("SELECT NOW();", [], { isSystemUser: true, role: "", host: "localhost", ipAddress: "" }).then(() => {
|
|
1325
|
+
logger.info("Connected to PostgreSQL database");
|
|
1326
|
+
}).catch((error) => {
|
|
1327
|
+
logger.error("Error connecting to database", error);
|
|
1328
|
+
process.exit(1);
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
async query(query, values) {
|
|
1332
|
+
return this.pool.query(query, values);
|
|
1333
|
+
}
|
|
1334
|
+
};
|
|
1335
|
+
|
|
1328
1336
|
// src/restura/sql/SqlEngine.ts
|
|
1329
1337
|
import { ObjectUtils as ObjectUtils3 } from "@redskytech/core-utils";
|
|
1330
1338
|
var SqlEngine = class {
|
|
@@ -1489,9 +1497,9 @@ expressionList =
|
|
|
1489
1497
|
|
|
1490
1498
|
expression =
|
|
1491
1499
|
negate:negate?"(" "column:" column:column ","? value:value? ","? type:type? ")"
|
|
1492
|
-
{return \`\${negate? "
|
|
1500
|
+
{return \`\${negate? " NOT " : ""}(\${type? type(column, value) : \`\${column} = \${format.literal(value)}\`})\`;}
|
|
1493
1501
|
/
|
|
1494
|
-
negate:negate?"("expression:expressionList")" { return \`\${negate? "
|
|
1502
|
+
negate:negate?"("expression:expressionList")" { return \`\${negate? " NOT " : ""}(\${expression})\`; }
|
|
1495
1503
|
|
|
1496
1504
|
negate = "!"
|
|
1497
1505
|
|
|
@@ -1528,7 +1536,7 @@ var filterPsqlParser_default = filterPsqlParser;
|
|
|
1528
1536
|
// src/restura/sql/PsqlEngine.ts
|
|
1529
1537
|
import getDiff from "@wmfs/pg-diff-sync";
|
|
1530
1538
|
import pgInfo from "@wmfs/pg-info";
|
|
1531
|
-
|
|
1539
|
+
var { Client } = "pg";
|
|
1532
1540
|
var systemUser = {
|
|
1533
1541
|
role: "",
|
|
1534
1542
|
host: "",
|
|
@@ -1671,7 +1679,6 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
1671
1679
|
schema: "public"
|
|
1672
1680
|
});
|
|
1673
1681
|
const diff = getDiff(info1, info2);
|
|
1674
|
-
console.log("Schema differences:", diff);
|
|
1675
1682
|
await originalClient.end();
|
|
1676
1683
|
await scratchClient.end();
|
|
1677
1684
|
return diff.join("\n");
|
|
@@ -1785,22 +1792,20 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
1785
1792
|
);
|
|
1786
1793
|
} else if (routeData.type === "PAGED") {
|
|
1787
1794
|
const data = req.data;
|
|
1788
|
-
const
|
|
1789
|
-
`${selectStatement}${sqlStatement}${groupByOrderByStatement} LIMIT
|
|
1790
|
-
|
|
1791
|
-
[
|
|
1792
|
-
...sqlParams,
|
|
1793
|
-
data.perPage || DEFAULT_PAGED_PER_PAGE_NUMBER,
|
|
1794
|
-
(data.page - 1) * data.perPage || DEFAULT_PAGED_PAGE_NUMBER,
|
|
1795
|
-
...sqlParams
|
|
1796
|
-
],
|
|
1795
|
+
const pagePromise = this.psqlConnectionPool.runQuery(
|
|
1796
|
+
`${selectStatement}${sqlStatement}${groupByOrderByStatement}` + SQL`LIMIT ${data.perPage || DEFAULT_PAGED_PER_PAGE_NUMBER} OFFSET ${(data.page - 1) * data.perPage || DEFAULT_PAGED_PAGE_NUMBER};`,
|
|
1797
|
+
sqlParams,
|
|
1797
1798
|
req.requesterDetails
|
|
1798
1799
|
);
|
|
1800
|
+
const totalQuery = `SELECT COUNT(${routeData.groupBy ? `DISTINCT ${routeData.groupBy.tableName}.${routeData.groupBy.columnName}` : "*"}) AS total
|
|
1801
|
+
${sqlStatement};`;
|
|
1802
|
+
const totalPromise = await this.psqlConnectionPool.runQuery(totalQuery, sqlParams, req.requesterDetails);
|
|
1803
|
+
const [pageResults, totalResponse] = await Promise.all([pagePromise, totalPromise]);
|
|
1799
1804
|
let total = 0;
|
|
1800
|
-
if (ObjectUtils4.isArrayWithData(
|
|
1801
|
-
total =
|
|
1805
|
+
if (ObjectUtils4.isArrayWithData(totalResponse)) {
|
|
1806
|
+
total = totalResponse[0].total;
|
|
1802
1807
|
}
|
|
1803
|
-
return { data: pageResults
|
|
1808
|
+
return { data: pageResults, total };
|
|
1804
1809
|
} else {
|
|
1805
1810
|
throw new RsError("UNKNOWN_ERROR", "Unknown route type.");
|
|
1806
1811
|
}
|
|
@@ -1958,8 +1963,127 @@ var schemaToPsqlType = (column, tableName) => {
|
|
|
1958
1963
|
return column.type;
|
|
1959
1964
|
};
|
|
1960
1965
|
|
|
1966
|
+
// src/restura/sql/PsqlTransaction.ts
|
|
1967
|
+
import pg2 from "pg";
|
|
1968
|
+
var { Client: Client2 } = pg2;
|
|
1969
|
+
var PsqlTransaction = class extends PsqlConnection {
|
|
1970
|
+
constructor(clientConfig) {
|
|
1971
|
+
super();
|
|
1972
|
+
this.clientConfig = clientConfig;
|
|
1973
|
+
this.client = new Client2(clientConfig);
|
|
1974
|
+
this.beginTransactionPromise = this.beginTransaction();
|
|
1975
|
+
}
|
|
1976
|
+
async beginTransaction() {
|
|
1977
|
+
return this.query("BEGIN");
|
|
1978
|
+
}
|
|
1979
|
+
async rollback() {
|
|
1980
|
+
return this.query("ROLLBACK");
|
|
1981
|
+
}
|
|
1982
|
+
async commit() {
|
|
1983
|
+
return this.query("COMMIT");
|
|
1984
|
+
}
|
|
1985
|
+
async release() {
|
|
1986
|
+
return this.client.end();
|
|
1987
|
+
}
|
|
1988
|
+
async query(query, values) {
|
|
1989
|
+
await this.client.connect();
|
|
1990
|
+
await this.beginTransactionPromise;
|
|
1991
|
+
return this.client.query(query, values);
|
|
1992
|
+
}
|
|
1993
|
+
};
|
|
1994
|
+
|
|
1995
|
+
// src/restura/compareSchema.ts
|
|
1996
|
+
import cloneDeep from "lodash.clonedeep";
|
|
1997
|
+
var CompareSchema = class {
|
|
1998
|
+
async diffSchema(newSchema, latestSchema, psqlEngine) {
|
|
1999
|
+
let endPoints = this.diffEndPoints(newSchema.endpoints[0].routes, latestSchema.endpoints[0].routes);
|
|
2000
|
+
let globalParams = this.diffStringArray(newSchema.globalParams, latestSchema.globalParams);
|
|
2001
|
+
let roles = this.diffStringArray(newSchema.roles, latestSchema.roles);
|
|
2002
|
+
let commands = "";
|
|
2003
|
+
if (JSON.stringify(newSchema.database) !== JSON.stringify(latestSchema.database))
|
|
2004
|
+
commands = await psqlEngine.diffDatabaseToSchema(newSchema);
|
|
2005
|
+
let customTypes = newSchema.customTypes !== latestSchema.customTypes;
|
|
2006
|
+
const schemaPreview = { endPoints, globalParams, roles, commands, customTypes };
|
|
2007
|
+
return schemaPreview;
|
|
2008
|
+
}
|
|
2009
|
+
diffStringArray(newArray, originalArray) {
|
|
2010
|
+
let stringsDiff = [];
|
|
2011
|
+
let originalClone = new Set(originalArray);
|
|
2012
|
+
newArray.forEach((item) => {
|
|
2013
|
+
let originalIndex = originalClone.has(item);
|
|
2014
|
+
if (!originalIndex) {
|
|
2015
|
+
stringsDiff.push({
|
|
2016
|
+
name: item,
|
|
2017
|
+
changeType: "NEW"
|
|
2018
|
+
});
|
|
2019
|
+
} else {
|
|
2020
|
+
originalClone.delete(item);
|
|
2021
|
+
}
|
|
2022
|
+
});
|
|
2023
|
+
originalClone.forEach((item) => {
|
|
2024
|
+
stringsDiff.push({
|
|
2025
|
+
name: item,
|
|
2026
|
+
changeType: "DELETED"
|
|
2027
|
+
});
|
|
2028
|
+
});
|
|
2029
|
+
return stringsDiff;
|
|
2030
|
+
}
|
|
2031
|
+
diffEndPoints(newEndPoints, originalEndpoints) {
|
|
2032
|
+
let originalClone = cloneDeep(originalEndpoints);
|
|
2033
|
+
let diffObj = [];
|
|
2034
|
+
newEndPoints.forEach((endPoint) => {
|
|
2035
|
+
let { path: path4, method } = endPoint;
|
|
2036
|
+
let endPointIndex = originalClone.findIndex((original) => {
|
|
2037
|
+
return original.path === endPoint.path && original.method === endPoint.method;
|
|
2038
|
+
});
|
|
2039
|
+
if (endPointIndex === -1) {
|
|
2040
|
+
diffObj.push({
|
|
2041
|
+
name: `${method} ${path4}`,
|
|
2042
|
+
changeType: "NEW"
|
|
2043
|
+
});
|
|
2044
|
+
} else {
|
|
2045
|
+
let original = originalClone.findIndex((original2) => {
|
|
2046
|
+
return this.compareEndPoints(endPoint, original2);
|
|
2047
|
+
});
|
|
2048
|
+
if (original === -1) {
|
|
2049
|
+
diffObj.push({
|
|
2050
|
+
name: `${method} ${path4}`,
|
|
2051
|
+
changeType: "MODIFIED"
|
|
2052
|
+
});
|
|
2053
|
+
}
|
|
2054
|
+
originalClone.splice(endPointIndex, 1);
|
|
2055
|
+
}
|
|
2056
|
+
});
|
|
2057
|
+
originalClone.forEach((original) => {
|
|
2058
|
+
let { path: path4, method } = original;
|
|
2059
|
+
diffObj.push({
|
|
2060
|
+
name: `${method} ${path4}`,
|
|
2061
|
+
changeType: "DELETED"
|
|
2062
|
+
});
|
|
2063
|
+
});
|
|
2064
|
+
return diffObj;
|
|
2065
|
+
}
|
|
2066
|
+
compareEndPoints(endPoint1, endPoint2) {
|
|
2067
|
+
return JSON.stringify(endPoint1) === JSON.stringify(endPoint2);
|
|
2068
|
+
}
|
|
2069
|
+
};
|
|
2070
|
+
__decorateClass([
|
|
2071
|
+
boundMethod
|
|
2072
|
+
], CompareSchema.prototype, "diffSchema", 1);
|
|
2073
|
+
__decorateClass([
|
|
2074
|
+
boundMethod
|
|
2075
|
+
], CompareSchema.prototype, "diffStringArray", 1);
|
|
2076
|
+
__decorateClass([
|
|
2077
|
+
boundMethod
|
|
2078
|
+
], CompareSchema.prototype, "diffEndPoints", 1);
|
|
2079
|
+
__decorateClass([
|
|
2080
|
+
boundMethod
|
|
2081
|
+
], CompareSchema.prototype, "compareEndPoints", 1);
|
|
2082
|
+
var compareSchema = new CompareSchema();
|
|
2083
|
+
var compareSchema_default = compareSchema;
|
|
2084
|
+
|
|
1961
2085
|
// src/restura/restura.ts
|
|
1962
|
-
var { types } =
|
|
2086
|
+
var { types } = pg3;
|
|
1963
2087
|
var ResturaEngine = class {
|
|
1964
2088
|
constructor() {
|
|
1965
2089
|
this.publicEndpoints = {
|
|
@@ -2163,7 +2287,7 @@ var ResturaEngine = class {
|
|
|
2163
2287
|
}
|
|
2164
2288
|
async previewCreateSchema(req, res) {
|
|
2165
2289
|
try {
|
|
2166
|
-
const schemaDiff =
|
|
2290
|
+
const schemaDiff = await compareSchema_default.diffSchema(req.data, this.schema, this.psqlEngine);
|
|
2167
2291
|
res.send({ data: schemaDiff });
|
|
2168
2292
|
} catch (err) {
|
|
2169
2293
|
res.status(400).send(err);
|
|
@@ -2336,7 +2460,9 @@ setupPgReturnTypes();
|
|
|
2336
2460
|
var restura = new ResturaEngine();
|
|
2337
2461
|
export {
|
|
2338
2462
|
HtmlStatusCodes,
|
|
2463
|
+
PsqlConnection,
|
|
2339
2464
|
PsqlPool,
|
|
2465
|
+
PsqlTransaction,
|
|
2340
2466
|
RsError,
|
|
2341
2467
|
SQL,
|
|
2342
2468
|
escapeColumnName,
|