@restura/core 0.1.0-alpha.13 → 0.1.0-alpha.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/dist/index.d.mts +41 -23
- package/dist/index.d.ts +41 -23
- package/dist/index.js +170 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +168 -32
- 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 pg4 from "pg";
|
|
220
220
|
import * as prettier3 from "prettier";
|
|
221
221
|
|
|
222
222
|
// src/restura/sql/SqlUtils.ts
|
|
@@ -748,7 +748,7 @@ var joinDataSchema = z3.object({
|
|
|
748
748
|
var requestDataSchema = z3.object({
|
|
749
749
|
name: z3.string(),
|
|
750
750
|
required: z3.boolean(),
|
|
751
|
-
isNullable: z3.boolean().optional()
|
|
751
|
+
isNullable: z3.boolean().optional(),
|
|
752
752
|
validator: z3.array(validatorDataSchema)
|
|
753
753
|
}).strict();
|
|
754
754
|
var responseDataSchema = z3.object({
|
|
@@ -834,6 +834,12 @@ var postgresColumnDateTypesSchema = z3.enum([
|
|
|
834
834
|
"INTERVAL"
|
|
835
835
|
// time span
|
|
836
836
|
]);
|
|
837
|
+
var postgresColumnJsonTypesSchema = z3.enum([
|
|
838
|
+
"JSON",
|
|
839
|
+
// stores JSON data as raw text
|
|
840
|
+
"JSONB"
|
|
841
|
+
// stores JSON data in a binary format, optimized for query performance
|
|
842
|
+
]);
|
|
837
843
|
var mariaDbColumnNumericTypesSchema = z3.enum([
|
|
838
844
|
"BOOLEAN",
|
|
839
845
|
// 1-byte A synonym for "TINYINT(1)". Supported from version 1.2.0 onwards.
|
|
@@ -896,6 +902,7 @@ var columnDataSchema = z3.object({
|
|
|
896
902
|
postgresColumnNumericTypesSchema,
|
|
897
903
|
postgresColumnStringTypesSchema,
|
|
898
904
|
postgresColumnDateTypesSchema,
|
|
905
|
+
postgresColumnJsonTypesSchema,
|
|
899
906
|
mariaDbColumnNumericTypesSchema,
|
|
900
907
|
mariaDbColumnStringTypesSchema,
|
|
901
908
|
mariaDbColumnDateTypesSchema
|
|
@@ -1203,9 +1210,14 @@ function convertTable(table) {
|
|
|
1203
1210
|
|
|
1204
1211
|
// src/restura/sql/PsqlEngine.ts
|
|
1205
1212
|
import { ObjectUtils as ObjectUtils4 } from "@redskytech/core-utils";
|
|
1213
|
+
import getDiff from "@wmfs/pg-diff-sync";
|
|
1214
|
+
import pgInfo from "@wmfs/pg-info";
|
|
1215
|
+
import pg2 from "pg";
|
|
1206
1216
|
|
|
1207
1217
|
// src/restura/sql/PsqlPool.ts
|
|
1208
1218
|
import pg from "pg";
|
|
1219
|
+
|
|
1220
|
+
// src/restura/sql/PsqlConnection.ts
|
|
1209
1221
|
import format3 from "pg-format";
|
|
1210
1222
|
|
|
1211
1223
|
// src/restura/sql/PsqlUtils.ts
|
|
@@ -1255,25 +1267,16 @@ function SQL(strings, ...values) {
|
|
|
1255
1267
|
return query;
|
|
1256
1268
|
}
|
|
1257
1269
|
|
|
1258
|
-
// src/restura/sql/
|
|
1259
|
-
var
|
|
1260
|
-
|
|
1261
|
-
constructor(poolConfig) {
|
|
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
|
-
});
|
|
1270
|
+
// src/restura/sql/PsqlConnection.ts
|
|
1271
|
+
var PsqlConnection = class {
|
|
1272
|
+
constructor() {
|
|
1270
1273
|
}
|
|
1271
1274
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1272
1275
|
async queryOne(query, options, requesterDetails) {
|
|
1273
1276
|
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1274
1277
|
this.logSqlStatement(formattedQuery, options, requesterDetails);
|
|
1275
1278
|
try {
|
|
1276
|
-
const response = await this.
|
|
1279
|
+
const response = await this.query(formattedQuery, options);
|
|
1277
1280
|
if (response.rows.length === 0) throw new RsError("NOT_FOUND", "No results found");
|
|
1278
1281
|
else if (response.rows.length > 1) throw new RsError("DUPLICATE", "More than one result found");
|
|
1279
1282
|
return response.rows[0];
|
|
@@ -1290,10 +1293,8 @@ var PsqlPool = class {
|
|
|
1290
1293
|
async runQuery(query, options, requesterDetails) {
|
|
1291
1294
|
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1292
1295
|
this.logSqlStatement(formattedQuery, options, requesterDetails);
|
|
1293
|
-
const queryUpdated = query.replace(/[\t\n]/g, " ");
|
|
1294
|
-
console.log(queryUpdated, options);
|
|
1295
1296
|
try {
|
|
1296
|
-
const response = await this.
|
|
1297
|
+
const response = await this.query(formattedQuery, options);
|
|
1297
1298
|
return response.rows;
|
|
1298
1299
|
} catch (error) {
|
|
1299
1300
|
console.error(error, query, options);
|
|
@@ -1325,6 +1326,25 @@ var PsqlPool = class {
|
|
|
1325
1326
|
}
|
|
1326
1327
|
};
|
|
1327
1328
|
|
|
1329
|
+
// src/restura/sql/PsqlPool.ts
|
|
1330
|
+
var { Pool } = pg;
|
|
1331
|
+
var PsqlPool = class extends PsqlConnection {
|
|
1332
|
+
constructor(poolConfig) {
|
|
1333
|
+
super();
|
|
1334
|
+
this.poolConfig = poolConfig;
|
|
1335
|
+
this.pool = new Pool(poolConfig);
|
|
1336
|
+
this.queryOne("SELECT NOW();", [], { isSystemUser: true, role: "", host: "localhost", ipAddress: "" }).then(() => {
|
|
1337
|
+
logger.info("Connected to PostgreSQL database");
|
|
1338
|
+
}).catch((error) => {
|
|
1339
|
+
logger.error("Error connecting to database", error);
|
|
1340
|
+
process.exit(1);
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
async query(query, values) {
|
|
1344
|
+
return this.pool.query(query, values);
|
|
1345
|
+
}
|
|
1346
|
+
};
|
|
1347
|
+
|
|
1328
1348
|
// src/restura/sql/SqlEngine.ts
|
|
1329
1349
|
import { ObjectUtils as ObjectUtils3 } from "@redskytech/core-utils";
|
|
1330
1350
|
var SqlEngine = class {
|
|
@@ -1489,9 +1509,9 @@ expressionList =
|
|
|
1489
1509
|
|
|
1490
1510
|
expression =
|
|
1491
1511
|
negate:negate?"(" "column:" column:column ","? value:value? ","? type:type? ")"
|
|
1492
|
-
{return \`\${negate? "
|
|
1512
|
+
{return \`\${negate? " NOT " : ""}(\${type? type(column, value) : \`\${column} = \${format.literal(value)}\`})\`;}
|
|
1493
1513
|
/
|
|
1494
|
-
negate:negate?"("expression:expressionList")" { return \`\${negate? "
|
|
1514
|
+
negate:negate?"("expression:expressionList")" { return \`\${negate? " NOT " : ""}(\${expression})\`; }
|
|
1495
1515
|
|
|
1496
1516
|
negate = "!"
|
|
1497
1517
|
|
|
@@ -1526,9 +1546,7 @@ var filterPsqlParser = peg.generate(filterSqlGrammar, {
|
|
|
1526
1546
|
var filterPsqlParser_default = filterPsqlParser;
|
|
1527
1547
|
|
|
1528
1548
|
// src/restura/sql/PsqlEngine.ts
|
|
1529
|
-
|
|
1530
|
-
import pgInfo from "@wmfs/pg-info";
|
|
1531
|
-
var { Client } = "pg";
|
|
1549
|
+
var { Client } = pg2;
|
|
1532
1550
|
var systemUser = {
|
|
1533
1551
|
role: "",
|
|
1534
1552
|
host: "",
|
|
@@ -1576,7 +1594,7 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
1576
1594
|
}
|
|
1577
1595
|
if (column.isNullable) columnSql += " NULL";
|
|
1578
1596
|
else columnSql += " NOT NULL";
|
|
1579
|
-
if (column.default) columnSql += ` DEFAULT
|
|
1597
|
+
if (column.default) columnSql += ` DEFAULT ${column.default}`;
|
|
1580
1598
|
tableColumns.push(columnSql);
|
|
1581
1599
|
}
|
|
1582
1600
|
sql += tableColumns.join(", \n");
|
|
@@ -1663,15 +1681,12 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
1663
1681
|
await originalClient.connect();
|
|
1664
1682
|
await scratchClient.connect();
|
|
1665
1683
|
const info1 = await pgInfo({
|
|
1666
|
-
client: originalClient
|
|
1667
|
-
schema: "public"
|
|
1684
|
+
client: originalClient
|
|
1668
1685
|
});
|
|
1669
1686
|
const info2 = await pgInfo({
|
|
1670
|
-
client: scratchClient
|
|
1671
|
-
schema: "public"
|
|
1687
|
+
client: scratchClient
|
|
1672
1688
|
});
|
|
1673
1689
|
const diff = getDiff(info1, info2);
|
|
1674
|
-
console.log("Schema differences:", diff);
|
|
1675
1690
|
await originalClient.end();
|
|
1676
1691
|
await scratchClient.end();
|
|
1677
1692
|
return diff.join("\n");
|
|
@@ -1948,16 +1963,135 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
1948
1963
|
return whereClause;
|
|
1949
1964
|
}
|
|
1950
1965
|
};
|
|
1951
|
-
|
|
1966
|
+
function schemaToPsqlType(column, tableName) {
|
|
1952
1967
|
if (column.hasAutoIncrement) return "BIGSERIAL";
|
|
1953
1968
|
if (column.type === "ENUM") return `"${tableName}_${column.name}_enum"`;
|
|
1954
1969
|
if (column.type === "DATETIME") return "TIMESTAMPTZ";
|
|
1955
1970
|
if (column.type === "MEDIUMINT") return "INT";
|
|
1956
1971
|
return column.type;
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
// src/restura/sql/PsqlTransaction.ts
|
|
1975
|
+
import pg3 from "pg";
|
|
1976
|
+
var { Client: Client2 } = pg3;
|
|
1977
|
+
var PsqlTransaction = class extends PsqlConnection {
|
|
1978
|
+
constructor(clientConfig) {
|
|
1979
|
+
super();
|
|
1980
|
+
this.clientConfig = clientConfig;
|
|
1981
|
+
this.client = new Client2(clientConfig);
|
|
1982
|
+
this.beginTransactionPromise = this.beginTransaction();
|
|
1983
|
+
}
|
|
1984
|
+
async beginTransaction() {
|
|
1985
|
+
return this.query("BEGIN");
|
|
1986
|
+
}
|
|
1987
|
+
async rollback() {
|
|
1988
|
+
return this.query("ROLLBACK");
|
|
1989
|
+
}
|
|
1990
|
+
async commit() {
|
|
1991
|
+
return this.query("COMMIT");
|
|
1992
|
+
}
|
|
1993
|
+
async release() {
|
|
1994
|
+
return this.client.end();
|
|
1995
|
+
}
|
|
1996
|
+
async query(query, values) {
|
|
1997
|
+
await this.client.connect();
|
|
1998
|
+
await this.beginTransactionPromise;
|
|
1999
|
+
return this.client.query(query, values);
|
|
2000
|
+
}
|
|
2001
|
+
};
|
|
2002
|
+
|
|
2003
|
+
// src/restura/compareSchema.ts
|
|
2004
|
+
import cloneDeep from "lodash.clonedeep";
|
|
2005
|
+
var CompareSchema = class {
|
|
2006
|
+
async diffSchema(newSchema, latestSchema, psqlEngine) {
|
|
2007
|
+
const endPoints = this.diffEndPoints(newSchema.endpoints[0].routes, latestSchema.endpoints[0].routes);
|
|
2008
|
+
const globalParams = this.diffStringArray(newSchema.globalParams, latestSchema.globalParams);
|
|
2009
|
+
const roles = this.diffStringArray(newSchema.roles, latestSchema.roles);
|
|
2010
|
+
let commands = "";
|
|
2011
|
+
if (JSON.stringify(newSchema.database) !== JSON.stringify(latestSchema.database))
|
|
2012
|
+
commands = await psqlEngine.diffDatabaseToSchema(newSchema);
|
|
2013
|
+
const customTypes = newSchema.customTypes !== latestSchema.customTypes;
|
|
2014
|
+
const schemaPreview = { endPoints, globalParams, roles, commands, customTypes };
|
|
2015
|
+
return schemaPreview;
|
|
2016
|
+
}
|
|
2017
|
+
diffStringArray(newArray, originalArray) {
|
|
2018
|
+
const stringsDiff = [];
|
|
2019
|
+
const originalClone = new Set(originalArray);
|
|
2020
|
+
newArray.forEach((item) => {
|
|
2021
|
+
const originalIndex = originalClone.has(item);
|
|
2022
|
+
if (!originalIndex) {
|
|
2023
|
+
stringsDiff.push({
|
|
2024
|
+
name: item,
|
|
2025
|
+
changeType: "NEW"
|
|
2026
|
+
});
|
|
2027
|
+
} else {
|
|
2028
|
+
originalClone.delete(item);
|
|
2029
|
+
}
|
|
2030
|
+
});
|
|
2031
|
+
originalClone.forEach((item) => {
|
|
2032
|
+
stringsDiff.push({
|
|
2033
|
+
name: item,
|
|
2034
|
+
changeType: "DELETED"
|
|
2035
|
+
});
|
|
2036
|
+
});
|
|
2037
|
+
return stringsDiff;
|
|
2038
|
+
}
|
|
2039
|
+
diffEndPoints(newEndPoints, originalEndpoints) {
|
|
2040
|
+
const originalClone = cloneDeep(originalEndpoints);
|
|
2041
|
+
const diffObj = [];
|
|
2042
|
+
newEndPoints.forEach((endPoint) => {
|
|
2043
|
+
const { path: path4, method } = endPoint;
|
|
2044
|
+
const endPointIndex = originalClone.findIndex((original) => {
|
|
2045
|
+
return original.path === endPoint.path && original.method === endPoint.method;
|
|
2046
|
+
});
|
|
2047
|
+
if (endPointIndex === -1) {
|
|
2048
|
+
diffObj.push({
|
|
2049
|
+
name: `${method} ${path4}`,
|
|
2050
|
+
changeType: "NEW"
|
|
2051
|
+
});
|
|
2052
|
+
} else {
|
|
2053
|
+
const original = originalClone.findIndex((original2) => {
|
|
2054
|
+
return this.compareEndPoints(endPoint, original2);
|
|
2055
|
+
});
|
|
2056
|
+
if (original === -1) {
|
|
2057
|
+
diffObj.push({
|
|
2058
|
+
name: `${method} ${path4}`,
|
|
2059
|
+
changeType: "MODIFIED"
|
|
2060
|
+
});
|
|
2061
|
+
}
|
|
2062
|
+
originalClone.splice(endPointIndex, 1);
|
|
2063
|
+
}
|
|
2064
|
+
});
|
|
2065
|
+
originalClone.forEach((original) => {
|
|
2066
|
+
const { path: path4, method } = original;
|
|
2067
|
+
diffObj.push({
|
|
2068
|
+
name: `${method} ${path4}`,
|
|
2069
|
+
changeType: "DELETED"
|
|
2070
|
+
});
|
|
2071
|
+
});
|
|
2072
|
+
return diffObj;
|
|
2073
|
+
}
|
|
2074
|
+
compareEndPoints(endPoint1, endPoint2) {
|
|
2075
|
+
return JSON.stringify(endPoint1) === JSON.stringify(endPoint2);
|
|
2076
|
+
}
|
|
1957
2077
|
};
|
|
2078
|
+
__decorateClass([
|
|
2079
|
+
boundMethod
|
|
2080
|
+
], CompareSchema.prototype, "diffSchema", 1);
|
|
2081
|
+
__decorateClass([
|
|
2082
|
+
boundMethod
|
|
2083
|
+
], CompareSchema.prototype, "diffStringArray", 1);
|
|
2084
|
+
__decorateClass([
|
|
2085
|
+
boundMethod
|
|
2086
|
+
], CompareSchema.prototype, "diffEndPoints", 1);
|
|
2087
|
+
__decorateClass([
|
|
2088
|
+
boundMethod
|
|
2089
|
+
], CompareSchema.prototype, "compareEndPoints", 1);
|
|
2090
|
+
var compareSchema = new CompareSchema();
|
|
2091
|
+
var compareSchema_default = compareSchema;
|
|
1958
2092
|
|
|
1959
2093
|
// src/restura/restura.ts
|
|
1960
|
-
var { types } =
|
|
2094
|
+
var { types } = pg4;
|
|
1961
2095
|
var ResturaEngine = class {
|
|
1962
2096
|
constructor() {
|
|
1963
2097
|
this.publicEndpoints = {
|
|
@@ -2161,7 +2295,7 @@ var ResturaEngine = class {
|
|
|
2161
2295
|
}
|
|
2162
2296
|
async previewCreateSchema(req, res) {
|
|
2163
2297
|
try {
|
|
2164
|
-
const schemaDiff =
|
|
2298
|
+
const schemaDiff = await compareSchema_default.diffSchema(req.data, this.schema, this.psqlEngine);
|
|
2165
2299
|
res.send({ data: schemaDiff });
|
|
2166
2300
|
} catch (err) {
|
|
2167
2301
|
res.status(400).send(err);
|
|
@@ -2334,7 +2468,9 @@ setupPgReturnTypes();
|
|
|
2334
2468
|
var restura = new ResturaEngine();
|
|
2335
2469
|
export {
|
|
2336
2470
|
HtmlStatusCodes,
|
|
2471
|
+
PsqlConnection,
|
|
2337
2472
|
PsqlPool,
|
|
2473
|
+
PsqlTransaction,
|
|
2338
2474
|
RsError,
|
|
2339
2475
|
SQL,
|
|
2340
2476
|
escapeColumnName,
|