@restura/core 0.1.0-alpha.10 → 0.1.0-alpha.12
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 +60 -42
- package/dist/index.d.ts +60 -42
- package/dist/index.js +289 -88
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +287 -86
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -258,7 +258,7 @@ var import_crypto = require("crypto");
|
|
|
258
258
|
var express = __toESM(require("express"));
|
|
259
259
|
var import_fs3 = __toESM(require("fs"));
|
|
260
260
|
var import_path3 = __toESM(require("path"));
|
|
261
|
-
var
|
|
261
|
+
var import_pg3 = __toESM(require("pg"));
|
|
262
262
|
var prettier3 = __toESM(require("prettier"));
|
|
263
263
|
|
|
264
264
|
// src/restura/sql/SqlUtils.ts
|
|
@@ -536,7 +536,7 @@ var ApiTree = class _ApiTree {
|
|
|
536
536
|
break;
|
|
537
537
|
}
|
|
538
538
|
}
|
|
539
|
-
return `'${p.name}'${p.required ? "" : "?"}:${requestType}`;
|
|
539
|
+
return `'${p.name}'${p.required ? "" : "?"}:${requestType}${p.isNullable ? " | null" : ""}`;
|
|
540
540
|
}).join(";\n")}${import_core_utils.ObjectUtils.isArrayWithData(route.request) ? ";" : ""}
|
|
541
541
|
`;
|
|
542
542
|
modelString += `}`;
|
|
@@ -560,18 +560,18 @@ var ApiTree = class _ApiTree {
|
|
|
560
560
|
return nested;
|
|
561
561
|
}
|
|
562
562
|
getNameAndType(p) {
|
|
563
|
-
let responseType = "any",
|
|
563
|
+
let responseType = "any", isNullable = false, array = false;
|
|
564
564
|
if (p.selector) {
|
|
565
|
-
({ responseType,
|
|
565
|
+
({ responseType, isNullable } = this.getTypeFromTable(p.selector, p.name));
|
|
566
566
|
} else if (p.subquery) {
|
|
567
567
|
responseType = this.getFields(p.subquery.properties);
|
|
568
568
|
array = true;
|
|
569
569
|
}
|
|
570
|
-
return `${p.name}${
|
|
570
|
+
return `${p.name}:${responseType}${array ? "[]" : ""}${isNullable ? " | null" : ""}`;
|
|
571
571
|
}
|
|
572
572
|
getTypeFromTable(selector, name) {
|
|
573
573
|
const path4 = selector.split(".");
|
|
574
|
-
if (path4.length === 0 || path4.length > 2 || path4[0] === "") return { responseType: "any",
|
|
574
|
+
if (path4.length === 0 || path4.length > 2 || path4[0] === "") return { responseType: "any", isNullable: false };
|
|
575
575
|
let tableName = path4.length == 2 ? path4[0] : name;
|
|
576
576
|
const columnName = path4.length == 2 ? path4[1] : path4[0];
|
|
577
577
|
let table = this.database.find((t) => t.name == tableName);
|
|
@@ -581,10 +581,10 @@ var ApiTree = class _ApiTree {
|
|
|
581
581
|
table = this.database.find((t) => t.name == tableName);
|
|
582
582
|
}
|
|
583
583
|
const column = table == null ? void 0 : table.columns.find((c) => c.name == columnName);
|
|
584
|
-
if (!table || !column) return { responseType: "any",
|
|
584
|
+
if (!table || !column) return { responseType: "any", isNullable: false };
|
|
585
585
|
return {
|
|
586
586
|
responseType: SqlUtils.convertDatabaseTypeToTypescript(column.type, column.value),
|
|
587
|
-
|
|
587
|
+
isNullable: column.roles.length > 0 || column.isNullable
|
|
588
588
|
};
|
|
589
589
|
}
|
|
590
590
|
};
|
|
@@ -790,6 +790,7 @@ var joinDataSchema = import_zod3.z.object({
|
|
|
790
790
|
var requestDataSchema = import_zod3.z.object({
|
|
791
791
|
name: import_zod3.z.string(),
|
|
792
792
|
required: import_zod3.z.boolean(),
|
|
793
|
+
isNullable: import_zod3.z.boolean().optional().default(false),
|
|
793
794
|
validator: import_zod3.z.array(validatorDataSchema)
|
|
794
795
|
}).strict();
|
|
795
796
|
var responseDataSchema = import_zod3.z.object({
|
|
@@ -1065,6 +1066,7 @@ function validateRequestParams(req, routeData, validationSchema) {
|
|
|
1065
1066
|
});
|
|
1066
1067
|
}
|
|
1067
1068
|
function validateRequestSingleParam(requestValue, requestParam) {
|
|
1069
|
+
if (requestParam.isNullable && requestValue === null) return;
|
|
1068
1070
|
requestParam.validator.forEach((validator) => {
|
|
1069
1071
|
switch (validator.type) {
|
|
1070
1072
|
case "TYPE_CHECK":
|
|
@@ -1244,6 +1246,10 @@ function convertTable(table) {
|
|
|
1244
1246
|
// src/restura/sql/PsqlEngine.ts
|
|
1245
1247
|
var import_core_utils5 = require("@redskytech/core-utils");
|
|
1246
1248
|
|
|
1249
|
+
// src/restura/sql/PsqlPool.ts
|
|
1250
|
+
var import_pg = __toESM(require("pg"));
|
|
1251
|
+
var import_pg_format2 = __toESM(require("pg-format"));
|
|
1252
|
+
|
|
1247
1253
|
// src/restura/sql/PsqlUtils.ts
|
|
1248
1254
|
var import_pg_format = __toESM(require("pg-format"));
|
|
1249
1255
|
function escapeColumnName(columnName) {
|
|
@@ -1279,7 +1285,9 @@ function isValueNumber2(value) {
|
|
|
1279
1285
|
function SQL(strings, ...values) {
|
|
1280
1286
|
let query = strings[0];
|
|
1281
1287
|
values.forEach((value, index) => {
|
|
1282
|
-
if (
|
|
1288
|
+
if (typeof value === "boolean") {
|
|
1289
|
+
query += value;
|
|
1290
|
+
} else if (typeof value === "number") {
|
|
1283
1291
|
query += value;
|
|
1284
1292
|
} else {
|
|
1285
1293
|
query += import_pg_format.default.literal(value);
|
|
@@ -1289,6 +1297,76 @@ function SQL(strings, ...values) {
|
|
|
1289
1297
|
return query;
|
|
1290
1298
|
}
|
|
1291
1299
|
|
|
1300
|
+
// src/restura/sql/PsqlPool.ts
|
|
1301
|
+
var { Pool } = import_pg.default;
|
|
1302
|
+
var PsqlPool = class {
|
|
1303
|
+
constructor(poolConfig) {
|
|
1304
|
+
this.poolConfig = poolConfig;
|
|
1305
|
+
this.pool = new Pool(poolConfig);
|
|
1306
|
+
this.queryOne("SELECT NOW();", [], { isSystemUser: true, role: "", host: "localhost", ipAddress: "" }).then(() => {
|
|
1307
|
+
logger.info("Connected to PostgreSQL database");
|
|
1308
|
+
}).catch((error) => {
|
|
1309
|
+
logger.error("Error connecting to database", error);
|
|
1310
|
+
process.exit(1);
|
|
1311
|
+
});
|
|
1312
|
+
}
|
|
1313
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1314
|
+
async queryOne(query, options, requesterDetails) {
|
|
1315
|
+
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1316
|
+
this.logSqlStatement(formattedQuery, options, requesterDetails);
|
|
1317
|
+
try {
|
|
1318
|
+
const response = await this.pool.query(formattedQuery, options);
|
|
1319
|
+
if (response.rows.length === 0) throw new RsError("NOT_FOUND", "No results found");
|
|
1320
|
+
else if (response.rows.length > 1) throw new RsError("DUPLICATE", "More than one result found");
|
|
1321
|
+
return response.rows[0];
|
|
1322
|
+
} catch (error) {
|
|
1323
|
+
console.error(error, query, options);
|
|
1324
|
+
if (RsError.isRsError(error)) throw error;
|
|
1325
|
+
if ((error == null ? void 0 : error.routine) === "_bt_check_unique") {
|
|
1326
|
+
throw new RsError("DUPLICATE", error.message);
|
|
1327
|
+
}
|
|
1328
|
+
throw new RsError("DATABASE_ERROR", `${error.message}`);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1332
|
+
async runQuery(query, options, requesterDetails) {
|
|
1333
|
+
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1334
|
+
this.logSqlStatement(formattedQuery, options, requesterDetails);
|
|
1335
|
+
const queryUpdated = query.replace(/[\t\n]/g, " ");
|
|
1336
|
+
console.log(queryUpdated, options);
|
|
1337
|
+
try {
|
|
1338
|
+
const response = await this.pool.query(formattedQuery, options);
|
|
1339
|
+
return response.rows;
|
|
1340
|
+
} catch (error) {
|
|
1341
|
+
console.error(error, query, options);
|
|
1342
|
+
if ((error == null ? void 0 : error.routine) === "_bt_check_unique") {
|
|
1343
|
+
throw new RsError("DUPLICATE", error.message);
|
|
1344
|
+
}
|
|
1345
|
+
throw new RsError("DATABASE_ERROR", `${error.message}`);
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
logSqlStatement(query, options, requesterDetails, prefix = "") {
|
|
1349
|
+
if (logger.level !== "silly") return;
|
|
1350
|
+
let sqlStatement = "";
|
|
1351
|
+
if (options.length === 0) {
|
|
1352
|
+
sqlStatement = query;
|
|
1353
|
+
} else {
|
|
1354
|
+
let stringIndex = 0;
|
|
1355
|
+
sqlStatement = query.replace(/\$\d+/g, () => {
|
|
1356
|
+
const value = options[stringIndex++];
|
|
1357
|
+
if (typeof value === "number") return value.toString();
|
|
1358
|
+
return import_pg_format2.default.literal(value);
|
|
1359
|
+
});
|
|
1360
|
+
}
|
|
1361
|
+
let initiator = "Anonymous";
|
|
1362
|
+
if ("userId" in requesterDetails && requesterDetails.userId)
|
|
1363
|
+
initiator = `User Id (${requesterDetails.userId.toString()})`;
|
|
1364
|
+
if ("isSystemUser" in requesterDetails && requesterDetails.isSystemUser) initiator = "SYSTEM";
|
|
1365
|
+
logger.silly(`${prefix}query by ${initiator}, Query ->
|
|
1366
|
+
${sqlStatement}`);
|
|
1367
|
+
}
|
|
1368
|
+
};
|
|
1369
|
+
|
|
1292
1370
|
// src/restura/sql/SqlEngine.ts
|
|
1293
1371
|
var import_core_utils4 = require("@redskytech/core-utils");
|
|
1294
1372
|
var SqlEngine = class {
|
|
@@ -1393,6 +1471,57 @@ var SqlEngine = class {
|
|
|
1393
1471
|
// src/restura/sql/filterPsqlParser.ts
|
|
1394
1472
|
var import_pegjs = __toESM(require("pegjs"));
|
|
1395
1473
|
var filterSqlGrammar = `
|
|
1474
|
+
{
|
|
1475
|
+
// ported from pg-format but intentionally will add double quotes to every column
|
|
1476
|
+
function quoteSqlIdentity(value) {
|
|
1477
|
+
if (value === undefined || value === null) {
|
|
1478
|
+
throw new Error('SQL identifier cannot be null or undefined');
|
|
1479
|
+
} else if (value === false) {
|
|
1480
|
+
return '"f"';
|
|
1481
|
+
} else if (value === true) {
|
|
1482
|
+
return '"t"';
|
|
1483
|
+
} else if (value instanceof Date) {
|
|
1484
|
+
// return '"' + formatDate(value.toISOString()) + '"';
|
|
1485
|
+
} else if (value instanceof Buffer) {
|
|
1486
|
+
throw new Error('SQL identifier cannot be a buffer');
|
|
1487
|
+
} else if (Array.isArray(value) === true) {
|
|
1488
|
+
var temp = [];
|
|
1489
|
+
for (var i = 0; i < value.length; i++) {
|
|
1490
|
+
if (Array.isArray(value[i]) === true) {
|
|
1491
|
+
throw new Error('Nested array to grouped list conversion is not supported for SQL identifier');
|
|
1492
|
+
} else {
|
|
1493
|
+
// temp.push(quoteIdent(value[i]));
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
return temp.toString();
|
|
1497
|
+
} else if (value === Object(value)) {
|
|
1498
|
+
throw new Error('SQL identifier cannot be an object');
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
var ident = value.toString().slice(0); // create copy
|
|
1502
|
+
|
|
1503
|
+
// do not quote a valid, unquoted identifier
|
|
1504
|
+
// if (/^[a-z_][a-z0-9_$]*$/.test(ident) === true && isReserved(ident) === false) {
|
|
1505
|
+
// return ident;
|
|
1506
|
+
// }
|
|
1507
|
+
|
|
1508
|
+
var quoted = '"';
|
|
1509
|
+
|
|
1510
|
+
for (var i = 0; i < ident.length; i++) {
|
|
1511
|
+
var c = ident[i];
|
|
1512
|
+
if (c === '"') {
|
|
1513
|
+
quoted += c + c;
|
|
1514
|
+
} else {
|
|
1515
|
+
quoted += c;
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
quoted += '"';
|
|
1520
|
+
|
|
1521
|
+
return quoted;
|
|
1522
|
+
};
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1396
1525
|
start = expressionList
|
|
1397
1526
|
|
|
1398
1527
|
expressionList =
|
|
@@ -1411,9 +1540,9 @@ negate = "!"
|
|
|
1411
1540
|
operator = "and"i / "or"i
|
|
1412
1541
|
|
|
1413
1542
|
|
|
1414
|
-
column = left:text "." right:text { return \`\${
|
|
1543
|
+
column = left:text "." right:text { return \`\${quoteSqlIdentity(left)}.\${quoteSqlIdentity(right)}\`; }
|
|
1415
1544
|
/
|
|
1416
|
-
text:text { return
|
|
1545
|
+
text:text { return quoteSqlIdentity(text); }
|
|
1417
1546
|
|
|
1418
1547
|
|
|
1419
1548
|
text = text:[a-z0-9-_:@]i+ { return text.join("");}
|
|
@@ -1439,18 +1568,155 @@ var filterPsqlParser = import_pegjs.default.generate(filterSqlGrammar, {
|
|
|
1439
1568
|
var filterPsqlParser_default = filterPsqlParser;
|
|
1440
1569
|
|
|
1441
1570
|
// src/restura/sql/PsqlEngine.ts
|
|
1571
|
+
var import_pg_diff_sync = __toESM(require("@wmfs/pg-diff-sync"));
|
|
1572
|
+
var import_pg_info = __toESM(require("@wmfs/pg-info"));
|
|
1573
|
+
var import_pg2 = require("pg");
|
|
1574
|
+
var systemUser = {
|
|
1575
|
+
role: "",
|
|
1576
|
+
host: "",
|
|
1577
|
+
ipAddress: "",
|
|
1578
|
+
isSystemUser: true
|
|
1579
|
+
};
|
|
1442
1580
|
var PsqlEngine = class extends SqlEngine {
|
|
1443
1581
|
constructor(psqlConnectionPool) {
|
|
1444
1582
|
super();
|
|
1445
1583
|
this.psqlConnectionPool = psqlConnectionPool;
|
|
1446
1584
|
}
|
|
1447
|
-
async
|
|
1448
|
-
|
|
1449
|
-
|
|
1585
|
+
async createDatabaseFromSchema(schema, connection) {
|
|
1586
|
+
const sqlFullStatement = this.generateDatabaseSchemaFromSchema(schema);
|
|
1587
|
+
await connection.runQuery(sqlFullStatement, [], systemUser);
|
|
1588
|
+
return sqlFullStatement;
|
|
1450
1589
|
}
|
|
1451
1590
|
generateDatabaseSchemaFromSchema(schema) {
|
|
1452
|
-
|
|
1453
|
-
|
|
1591
|
+
const sqlStatements = [];
|
|
1592
|
+
const enums = [];
|
|
1593
|
+
const indexes = [];
|
|
1594
|
+
for (const table of schema.database) {
|
|
1595
|
+
let sql = `CREATE TABLE "${table.name}"
|
|
1596
|
+
( `;
|
|
1597
|
+
const tableColumns = [];
|
|
1598
|
+
for (const column of table.columns) {
|
|
1599
|
+
let columnSql = "";
|
|
1600
|
+
if (column.type === "ENUM") {
|
|
1601
|
+
enums.push(`CREATE TYPE ${schemaToPsqlType(column, table.name)} AS ENUM (${column.value});`);
|
|
1602
|
+
}
|
|
1603
|
+
columnSql += ` "${column.name}" ${schemaToPsqlType(column, table.name)}`;
|
|
1604
|
+
let value = column.value;
|
|
1605
|
+
if (column.type === "JSON") value = "";
|
|
1606
|
+
if (column.type === "JSONB") value = "";
|
|
1607
|
+
if (column.type === "DECIMAL" && value) {
|
|
1608
|
+
value = value.replace("-", ",").replace(/['"]/g, "");
|
|
1609
|
+
}
|
|
1610
|
+
if (value && column.type !== "ENUM") {
|
|
1611
|
+
columnSql += `(${value})`;
|
|
1612
|
+
} else if (column.length) columnSql += `(${column.length})`;
|
|
1613
|
+
if (column.isPrimary) {
|
|
1614
|
+
columnSql += " PRIMARY KEY ";
|
|
1615
|
+
}
|
|
1616
|
+
if (column.isUnique) {
|
|
1617
|
+
columnSql += ` CONSTRAINT "${table.name}_${column.name}_unique_index" UNIQUE `;
|
|
1618
|
+
}
|
|
1619
|
+
if (column.isNullable) columnSql += " NULL";
|
|
1620
|
+
else columnSql += " NOT NULL";
|
|
1621
|
+
if (column.default) columnSql += ` DEFAULT '${column.default}'`;
|
|
1622
|
+
tableColumns.push(columnSql);
|
|
1623
|
+
}
|
|
1624
|
+
sql += tableColumns.join(", \n");
|
|
1625
|
+
for (const index of table.indexes) {
|
|
1626
|
+
if (!index.isPrimaryKey) {
|
|
1627
|
+
let unique = " ";
|
|
1628
|
+
if (index.isUnique) unique = "UNIQUE ";
|
|
1629
|
+
indexes.push(
|
|
1630
|
+
` CREATE ${unique}INDEX "${index.name}" ON "${table.name}" (${index.columns.map((item) => {
|
|
1631
|
+
return `"${item}" ${index.order}`;
|
|
1632
|
+
}).join(", ")})`
|
|
1633
|
+
);
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
sql += "\n);";
|
|
1637
|
+
sqlStatements.push(sql);
|
|
1638
|
+
}
|
|
1639
|
+
for (const table of schema.database) {
|
|
1640
|
+
if (!table.foreignKeys.length) continue;
|
|
1641
|
+
const sql = `ALTER TABLE "${table.name}" `;
|
|
1642
|
+
const constraints = [];
|
|
1643
|
+
for (const foreignKey of table.foreignKeys) {
|
|
1644
|
+
let constraint = ` ADD CONSTRAINT "${foreignKey.name}"
|
|
1645
|
+
FOREIGN KEY ("${foreignKey.column}") REFERENCES "${foreignKey.refTable}" ("${foreignKey.refColumn}")`;
|
|
1646
|
+
constraint += ` ON DELETE ${foreignKey.onDelete}`;
|
|
1647
|
+
constraint += ` ON UPDATE ${foreignKey.onUpdate}`;
|
|
1648
|
+
constraints.push(constraint);
|
|
1649
|
+
}
|
|
1650
|
+
sqlStatements.push(sql + constraints.join(",\n") + ";");
|
|
1651
|
+
}
|
|
1652
|
+
for (const table of schema.database) {
|
|
1653
|
+
if (!table.checkConstraints.length) continue;
|
|
1654
|
+
const sql = `ALTER TABLE "${table.name}" `;
|
|
1655
|
+
const constraints = [];
|
|
1656
|
+
for (const check of table.checkConstraints) {
|
|
1657
|
+
const constraint = `ADD CONSTRAINT "${check.name}" CHECK (${check.check})`;
|
|
1658
|
+
constraints.push(constraint);
|
|
1659
|
+
}
|
|
1660
|
+
sqlStatements.push(sql + constraints.join(",\n") + ";");
|
|
1661
|
+
}
|
|
1662
|
+
sqlStatements.push(indexes.join(";\n"));
|
|
1663
|
+
return enums.join("\n") + "\n" + sqlStatements.join("\n\n");
|
|
1664
|
+
}
|
|
1665
|
+
async getScratchPool() {
|
|
1666
|
+
await this.psqlConnectionPool.runQuery(
|
|
1667
|
+
`DROP DATABASE IF EXISTS ${this.psqlConnectionPool.poolConfig.database}_scratch`,
|
|
1668
|
+
[],
|
|
1669
|
+
systemUser
|
|
1670
|
+
);
|
|
1671
|
+
await this.psqlConnectionPool.runQuery(
|
|
1672
|
+
`CREATE DATABASE ${this.psqlConnectionPool.poolConfig.database}_scratch;`,
|
|
1673
|
+
[],
|
|
1674
|
+
systemUser
|
|
1675
|
+
);
|
|
1676
|
+
const scratchPool = new PsqlPool({
|
|
1677
|
+
host: this.psqlConnectionPool.poolConfig.host,
|
|
1678
|
+
port: this.psqlConnectionPool.poolConfig.port,
|
|
1679
|
+
user: this.psqlConnectionPool.poolConfig.user,
|
|
1680
|
+
database: this.psqlConnectionPool.poolConfig.database + "_scratch",
|
|
1681
|
+
password: this.psqlConnectionPool.poolConfig.password,
|
|
1682
|
+
max: this.psqlConnectionPool.poolConfig.max,
|
|
1683
|
+
idleTimeoutMillis: this.psqlConnectionPool.poolConfig.idleTimeoutMillis,
|
|
1684
|
+
connectionTimeoutMillis: this.psqlConnectionPool.poolConfig.connectionTimeoutMillis
|
|
1685
|
+
});
|
|
1686
|
+
return scratchPool;
|
|
1687
|
+
}
|
|
1688
|
+
async diffDatabaseToSchema(schema) {
|
|
1689
|
+
const scratchPool = await this.getScratchPool();
|
|
1690
|
+
await this.createDatabaseFromSchema(schema, scratchPool);
|
|
1691
|
+
const originalClient = new import_pg2.Client({
|
|
1692
|
+
database: this.psqlConnectionPool.poolConfig.database,
|
|
1693
|
+
user: this.psqlConnectionPool.poolConfig.user,
|
|
1694
|
+
password: this.psqlConnectionPool.poolConfig.password,
|
|
1695
|
+
host: this.psqlConnectionPool.poolConfig.host,
|
|
1696
|
+
port: this.psqlConnectionPool.poolConfig.port
|
|
1697
|
+
});
|
|
1698
|
+
const scratchClient = new import_pg2.Client({
|
|
1699
|
+
database: this.psqlConnectionPool.poolConfig.database + "_scratch",
|
|
1700
|
+
user: this.psqlConnectionPool.poolConfig.user,
|
|
1701
|
+
password: this.psqlConnectionPool.poolConfig.password,
|
|
1702
|
+
host: this.psqlConnectionPool.poolConfig.host,
|
|
1703
|
+
port: this.psqlConnectionPool.poolConfig.port
|
|
1704
|
+
});
|
|
1705
|
+
await originalClient.connect();
|
|
1706
|
+
await scratchClient.connect();
|
|
1707
|
+
const info1 = await (0, import_pg_info.default)({
|
|
1708
|
+
client: originalClient,
|
|
1709
|
+
schema: "public"
|
|
1710
|
+
});
|
|
1711
|
+
const info2 = await (0, import_pg_info.default)({
|
|
1712
|
+
client: scratchClient,
|
|
1713
|
+
schema: "public"
|
|
1714
|
+
});
|
|
1715
|
+
const diff = (0, import_pg_diff_sync.default)(info1, info2);
|
|
1716
|
+
console.log("Schema differences:", diff);
|
|
1717
|
+
await originalClient.end();
|
|
1718
|
+
await scratchClient.end();
|
|
1719
|
+
return diff.join("\n");
|
|
1454
1720
|
}
|
|
1455
1721
|
createNestedSelect(req, schema, item, routeData, userRole, sqlParams) {
|
|
1456
1722
|
if (!item.subquery) return "";
|
|
@@ -1726,81 +1992,16 @@ ${sqlStatement};`,
|
|
|
1726
1992
|
return whereClause;
|
|
1727
1993
|
}
|
|
1728
1994
|
};
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
constructor(poolConfig) {
|
|
1736
|
-
this.poolConfig = poolConfig;
|
|
1737
|
-
this.pool = new Pool(poolConfig);
|
|
1738
|
-
this.queryOne("SELECT NOW();", [], { isSystemUser: true, role: "", host: "localhost", ipAddress: "" }).then(() => {
|
|
1739
|
-
logger.info("Connected to PostgreSQL database");
|
|
1740
|
-
}).catch((error) => {
|
|
1741
|
-
logger.error("Error connecting to database", error);
|
|
1742
|
-
process.exit(1);
|
|
1743
|
-
});
|
|
1744
|
-
}
|
|
1745
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1746
|
-
async queryOne(query, options, requesterDetails) {
|
|
1747
|
-
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1748
|
-
this.logSqlStatement(formattedQuery, options, requesterDetails);
|
|
1749
|
-
try {
|
|
1750
|
-
const response = await this.pool.query(formattedQuery, options);
|
|
1751
|
-
if (response.rows.length === 0) throw new RsError("NOT_FOUND", "No results found");
|
|
1752
|
-
else if (response.rows.length > 1) throw new RsError("DUPLICATE", "More than one result found");
|
|
1753
|
-
return response.rows[0];
|
|
1754
|
-
} catch (error) {
|
|
1755
|
-
console.error(error, query, options);
|
|
1756
|
-
if (RsError.isRsError(error)) throw error;
|
|
1757
|
-
if ((error == null ? void 0 : error.routine) === "_bt_check_unique") {
|
|
1758
|
-
throw new RsError("DUPLICATE", error.message);
|
|
1759
|
-
}
|
|
1760
|
-
throw new RsError("DATABASE_ERROR", `${error.message}`);
|
|
1761
|
-
}
|
|
1762
|
-
}
|
|
1763
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1764
|
-
async runQuery(query, options, requesterDetails) {
|
|
1765
|
-
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1766
|
-
this.logSqlStatement(formattedQuery, options, requesterDetails);
|
|
1767
|
-
const queryUpdated = query.replace(/[\t\n]/g, " ");
|
|
1768
|
-
console.log(queryUpdated, options);
|
|
1769
|
-
try {
|
|
1770
|
-
const response = await this.pool.query(formattedQuery, options);
|
|
1771
|
-
return response.rows;
|
|
1772
|
-
} catch (error) {
|
|
1773
|
-
console.error(error, query, options);
|
|
1774
|
-
if ((error == null ? void 0 : error.routine) === "_bt_check_unique") {
|
|
1775
|
-
throw new RsError("DUPLICATE", error.message);
|
|
1776
|
-
}
|
|
1777
|
-
throw new RsError("DATABASE_ERROR", `${error.message}`);
|
|
1778
|
-
}
|
|
1779
|
-
}
|
|
1780
|
-
logSqlStatement(query, options, requesterDetails, prefix = "") {
|
|
1781
|
-
if (logger.level !== "silly") return;
|
|
1782
|
-
let sqlStatement = "";
|
|
1783
|
-
if (options.length === 0) {
|
|
1784
|
-
sqlStatement = query;
|
|
1785
|
-
} else {
|
|
1786
|
-
let stringIndex = 0;
|
|
1787
|
-
sqlStatement = query.replace(/\$\d+/g, () => {
|
|
1788
|
-
const value = options[stringIndex++];
|
|
1789
|
-
if (typeof value === "number") return value.toString();
|
|
1790
|
-
return import_pg_format2.default.literal(value);
|
|
1791
|
-
});
|
|
1792
|
-
}
|
|
1793
|
-
let initiator = "Anonymous";
|
|
1794
|
-
if ("userId" in requesterDetails && requesterDetails.userId)
|
|
1795
|
-
initiator = `User Id (${requesterDetails.userId.toString()})`;
|
|
1796
|
-
if ("isSystemUser" in requesterDetails && requesterDetails.isSystemUser) initiator = "SYSTEM";
|
|
1797
|
-
logger.silly(`${prefix}query by ${initiator}, Query ->
|
|
1798
|
-
${sqlStatement}`);
|
|
1799
|
-
}
|
|
1995
|
+
var schemaToPsqlType = (column, tableName) => {
|
|
1996
|
+
if (column.hasAutoIncrement) return "BIGSERIAL";
|
|
1997
|
+
if (column.type === "ENUM") return `"${tableName}_${column.name}_enum"`;
|
|
1998
|
+
if (column.type === "DATETIME") return "TIMESTAMPTZ";
|
|
1999
|
+
if (column.type === "MEDIUMINT") return "INT";
|
|
2000
|
+
return column.type;
|
|
1800
2001
|
};
|
|
1801
2002
|
|
|
1802
2003
|
// src/restura/restura.ts
|
|
1803
|
-
var { types } =
|
|
2004
|
+
var { types } = import_pg3.default;
|
|
1804
2005
|
var ResturaEngine = class {
|
|
1805
2006
|
constructor() {
|
|
1806
2007
|
this.publicEndpoints = {
|