@restura/core 0.1.0-alpha.11 → 0.1.0-alpha.13
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.js +288 -91
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +288 -91
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
package/dist/index.mjs
CHANGED
|
@@ -1204,6 +1204,10 @@ function convertTable(table) {
|
|
|
1204
1204
|
// src/restura/sql/PsqlEngine.ts
|
|
1205
1205
|
import { ObjectUtils as ObjectUtils4 } from "@redskytech/core-utils";
|
|
1206
1206
|
|
|
1207
|
+
// src/restura/sql/PsqlPool.ts
|
|
1208
|
+
import pg from "pg";
|
|
1209
|
+
import format3 from "pg-format";
|
|
1210
|
+
|
|
1207
1211
|
// src/restura/sql/PsqlUtils.ts
|
|
1208
1212
|
import format2 from "pg-format";
|
|
1209
1213
|
function escapeColumnName(columnName) {
|
|
@@ -1239,7 +1243,9 @@ function isValueNumber2(value) {
|
|
|
1239
1243
|
function SQL(strings, ...values) {
|
|
1240
1244
|
let query = strings[0];
|
|
1241
1245
|
values.forEach((value, index) => {
|
|
1242
|
-
if (
|
|
1246
|
+
if (typeof value === "boolean") {
|
|
1247
|
+
query += value;
|
|
1248
|
+
} else if (typeof value === "number") {
|
|
1243
1249
|
query += value;
|
|
1244
1250
|
} else {
|
|
1245
1251
|
query += format2.literal(value);
|
|
@@ -1249,6 +1255,76 @@ function SQL(strings, ...values) {
|
|
|
1249
1255
|
return query;
|
|
1250
1256
|
}
|
|
1251
1257
|
|
|
1258
|
+
// src/restura/sql/PsqlPool.ts
|
|
1259
|
+
var { Pool } = pg;
|
|
1260
|
+
var PsqlPool = class {
|
|
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
|
+
}
|
|
1271
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1272
|
+
async queryOne(query, options, requesterDetails) {
|
|
1273
|
+
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1274
|
+
this.logSqlStatement(formattedQuery, options, requesterDetails);
|
|
1275
|
+
try {
|
|
1276
|
+
const response = await this.pool.query(formattedQuery, options);
|
|
1277
|
+
if (response.rows.length === 0) throw new RsError("NOT_FOUND", "No results found");
|
|
1278
|
+
else if (response.rows.length > 1) throw new RsError("DUPLICATE", "More than one result found");
|
|
1279
|
+
return response.rows[0];
|
|
1280
|
+
} catch (error) {
|
|
1281
|
+
console.error(error, query, options);
|
|
1282
|
+
if (RsError.isRsError(error)) throw error;
|
|
1283
|
+
if ((error == null ? void 0 : error.routine) === "_bt_check_unique") {
|
|
1284
|
+
throw new RsError("DUPLICATE", error.message);
|
|
1285
|
+
}
|
|
1286
|
+
throw new RsError("DATABASE_ERROR", `${error.message}`);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1290
|
+
async runQuery(query, options, requesterDetails) {
|
|
1291
|
+
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1292
|
+
this.logSqlStatement(formattedQuery, options, requesterDetails);
|
|
1293
|
+
const queryUpdated = query.replace(/[\t\n]/g, " ");
|
|
1294
|
+
console.log(queryUpdated, options);
|
|
1295
|
+
try {
|
|
1296
|
+
const response = await this.pool.query(formattedQuery, options);
|
|
1297
|
+
return response.rows;
|
|
1298
|
+
} catch (error) {
|
|
1299
|
+
console.error(error, query, options);
|
|
1300
|
+
if ((error == null ? void 0 : error.routine) === "_bt_check_unique") {
|
|
1301
|
+
throw new RsError("DUPLICATE", error.message);
|
|
1302
|
+
}
|
|
1303
|
+
throw new RsError("DATABASE_ERROR", `${error.message}`);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
logSqlStatement(query, options, requesterDetails, prefix = "") {
|
|
1307
|
+
if (logger.level !== "silly") return;
|
|
1308
|
+
let sqlStatement = "";
|
|
1309
|
+
if (options.length === 0) {
|
|
1310
|
+
sqlStatement = query;
|
|
1311
|
+
} else {
|
|
1312
|
+
let stringIndex = 0;
|
|
1313
|
+
sqlStatement = query.replace(/\$\d+/g, () => {
|
|
1314
|
+
const value = options[stringIndex++];
|
|
1315
|
+
if (typeof value === "number") return value.toString();
|
|
1316
|
+
return format3.literal(value);
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
let initiator = "Anonymous";
|
|
1320
|
+
if ("userId" in requesterDetails && requesterDetails.userId)
|
|
1321
|
+
initiator = `User Id (${requesterDetails.userId.toString()})`;
|
|
1322
|
+
if ("isSystemUser" in requesterDetails && requesterDetails.isSystemUser) initiator = "SYSTEM";
|
|
1323
|
+
logger.silly(`${prefix}query by ${initiator}, Query ->
|
|
1324
|
+
${sqlStatement}`);
|
|
1325
|
+
}
|
|
1326
|
+
};
|
|
1327
|
+
|
|
1252
1328
|
// src/restura/sql/SqlEngine.ts
|
|
1253
1329
|
import { ObjectUtils as ObjectUtils3 } from "@redskytech/core-utils";
|
|
1254
1330
|
var SqlEngine = class {
|
|
@@ -1353,6 +1429,57 @@ var SqlEngine = class {
|
|
|
1353
1429
|
// src/restura/sql/filterPsqlParser.ts
|
|
1354
1430
|
import peg from "pegjs";
|
|
1355
1431
|
var filterSqlGrammar = `
|
|
1432
|
+
{
|
|
1433
|
+
// ported from pg-format but intentionally will add double quotes to every column
|
|
1434
|
+
function quoteSqlIdentity(value) {
|
|
1435
|
+
if (value === undefined || value === null) {
|
|
1436
|
+
throw new Error('SQL identifier cannot be null or undefined');
|
|
1437
|
+
} else if (value === false) {
|
|
1438
|
+
return '"f"';
|
|
1439
|
+
} else if (value === true) {
|
|
1440
|
+
return '"t"';
|
|
1441
|
+
} else if (value instanceof Date) {
|
|
1442
|
+
// return '"' + formatDate(value.toISOString()) + '"';
|
|
1443
|
+
} else if (value instanceof Buffer) {
|
|
1444
|
+
throw new Error('SQL identifier cannot be a buffer');
|
|
1445
|
+
} else if (Array.isArray(value) === true) {
|
|
1446
|
+
var temp = [];
|
|
1447
|
+
for (var i = 0; i < value.length; i++) {
|
|
1448
|
+
if (Array.isArray(value[i]) === true) {
|
|
1449
|
+
throw new Error('Nested array to grouped list conversion is not supported for SQL identifier');
|
|
1450
|
+
} else {
|
|
1451
|
+
// temp.push(quoteIdent(value[i]));
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
return temp.toString();
|
|
1455
|
+
} else if (value === Object(value)) {
|
|
1456
|
+
throw new Error('SQL identifier cannot be an object');
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
var ident = value.toString().slice(0); // create copy
|
|
1460
|
+
|
|
1461
|
+
// do not quote a valid, unquoted identifier
|
|
1462
|
+
// if (/^[a-z_][a-z0-9_$]*$/.test(ident) === true && isReserved(ident) === false) {
|
|
1463
|
+
// return ident;
|
|
1464
|
+
// }
|
|
1465
|
+
|
|
1466
|
+
var quoted = '"';
|
|
1467
|
+
|
|
1468
|
+
for (var i = 0; i < ident.length; i++) {
|
|
1469
|
+
var c = ident[i];
|
|
1470
|
+
if (c === '"') {
|
|
1471
|
+
quoted += c + c;
|
|
1472
|
+
} else {
|
|
1473
|
+
quoted += c;
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
quoted += '"';
|
|
1478
|
+
|
|
1479
|
+
return quoted;
|
|
1480
|
+
};
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1356
1483
|
start = expressionList
|
|
1357
1484
|
|
|
1358
1485
|
expressionList =
|
|
@@ -1371,9 +1498,9 @@ negate = "!"
|
|
|
1371
1498
|
operator = "and"i / "or"i
|
|
1372
1499
|
|
|
1373
1500
|
|
|
1374
|
-
column = left:text "." right:text { return \`\${
|
|
1501
|
+
column = left:text "." right:text { return \`\${quoteSqlIdentity(left)}.\${quoteSqlIdentity(right)}\`; }
|
|
1375
1502
|
/
|
|
1376
|
-
text:text { return
|
|
1503
|
+
text:text { return quoteSqlIdentity(text); }
|
|
1377
1504
|
|
|
1378
1505
|
|
|
1379
1506
|
text = text:[a-z0-9-_:@]i+ { return text.join("");}
|
|
@@ -1399,18 +1526,155 @@ var filterPsqlParser = peg.generate(filterSqlGrammar, {
|
|
|
1399
1526
|
var filterPsqlParser_default = filterPsqlParser;
|
|
1400
1527
|
|
|
1401
1528
|
// src/restura/sql/PsqlEngine.ts
|
|
1529
|
+
import getDiff from "@wmfs/pg-diff-sync";
|
|
1530
|
+
import pgInfo from "@wmfs/pg-info";
|
|
1531
|
+
var { Client } = "pg";
|
|
1532
|
+
var systemUser = {
|
|
1533
|
+
role: "",
|
|
1534
|
+
host: "",
|
|
1535
|
+
ipAddress: "",
|
|
1536
|
+
isSystemUser: true
|
|
1537
|
+
};
|
|
1402
1538
|
var PsqlEngine = class extends SqlEngine {
|
|
1403
1539
|
constructor(psqlConnectionPool) {
|
|
1404
1540
|
super();
|
|
1405
1541
|
this.psqlConnectionPool = psqlConnectionPool;
|
|
1406
1542
|
}
|
|
1407
|
-
async
|
|
1408
|
-
|
|
1409
|
-
|
|
1543
|
+
async createDatabaseFromSchema(schema, connection) {
|
|
1544
|
+
const sqlFullStatement = this.generateDatabaseSchemaFromSchema(schema);
|
|
1545
|
+
await connection.runQuery(sqlFullStatement, [], systemUser);
|
|
1546
|
+
return sqlFullStatement;
|
|
1410
1547
|
}
|
|
1411
1548
|
generateDatabaseSchemaFromSchema(schema) {
|
|
1412
|
-
|
|
1413
|
-
|
|
1549
|
+
const sqlStatements = [];
|
|
1550
|
+
const enums = [];
|
|
1551
|
+
const indexes = [];
|
|
1552
|
+
for (const table of schema.database) {
|
|
1553
|
+
let sql = `CREATE TABLE "${table.name}"
|
|
1554
|
+
( `;
|
|
1555
|
+
const tableColumns = [];
|
|
1556
|
+
for (const column of table.columns) {
|
|
1557
|
+
let columnSql = "";
|
|
1558
|
+
if (column.type === "ENUM") {
|
|
1559
|
+
enums.push(`CREATE TYPE ${schemaToPsqlType(column, table.name)} AS ENUM (${column.value});`);
|
|
1560
|
+
}
|
|
1561
|
+
columnSql += ` "${column.name}" ${schemaToPsqlType(column, table.name)}`;
|
|
1562
|
+
let value = column.value;
|
|
1563
|
+
if (column.type === "JSON") value = "";
|
|
1564
|
+
if (column.type === "JSONB") value = "";
|
|
1565
|
+
if (column.type === "DECIMAL" && value) {
|
|
1566
|
+
value = value.replace("-", ",").replace(/['"]/g, "");
|
|
1567
|
+
}
|
|
1568
|
+
if (value && column.type !== "ENUM") {
|
|
1569
|
+
columnSql += `(${value})`;
|
|
1570
|
+
} else if (column.length) columnSql += `(${column.length})`;
|
|
1571
|
+
if (column.isPrimary) {
|
|
1572
|
+
columnSql += " PRIMARY KEY ";
|
|
1573
|
+
}
|
|
1574
|
+
if (column.isUnique) {
|
|
1575
|
+
columnSql += ` CONSTRAINT "${table.name}_${column.name}_unique_index" UNIQUE `;
|
|
1576
|
+
}
|
|
1577
|
+
if (column.isNullable) columnSql += " NULL";
|
|
1578
|
+
else columnSql += " NOT NULL";
|
|
1579
|
+
if (column.default) columnSql += ` DEFAULT '${column.default}'`;
|
|
1580
|
+
tableColumns.push(columnSql);
|
|
1581
|
+
}
|
|
1582
|
+
sql += tableColumns.join(", \n");
|
|
1583
|
+
for (const index of table.indexes) {
|
|
1584
|
+
if (!index.isPrimaryKey) {
|
|
1585
|
+
let unique = " ";
|
|
1586
|
+
if (index.isUnique) unique = "UNIQUE ";
|
|
1587
|
+
indexes.push(
|
|
1588
|
+
` CREATE ${unique}INDEX "${index.name}" ON "${table.name}" (${index.columns.map((item) => {
|
|
1589
|
+
return `"${item}" ${index.order}`;
|
|
1590
|
+
}).join(", ")})`
|
|
1591
|
+
);
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
sql += "\n);";
|
|
1595
|
+
sqlStatements.push(sql);
|
|
1596
|
+
}
|
|
1597
|
+
for (const table of schema.database) {
|
|
1598
|
+
if (!table.foreignKeys.length) continue;
|
|
1599
|
+
const sql = `ALTER TABLE "${table.name}" `;
|
|
1600
|
+
const constraints = [];
|
|
1601
|
+
for (const foreignKey of table.foreignKeys) {
|
|
1602
|
+
let constraint = ` ADD CONSTRAINT "${foreignKey.name}"
|
|
1603
|
+
FOREIGN KEY ("${foreignKey.column}") REFERENCES "${foreignKey.refTable}" ("${foreignKey.refColumn}")`;
|
|
1604
|
+
constraint += ` ON DELETE ${foreignKey.onDelete}`;
|
|
1605
|
+
constraint += ` ON UPDATE ${foreignKey.onUpdate}`;
|
|
1606
|
+
constraints.push(constraint);
|
|
1607
|
+
}
|
|
1608
|
+
sqlStatements.push(sql + constraints.join(",\n") + ";");
|
|
1609
|
+
}
|
|
1610
|
+
for (const table of schema.database) {
|
|
1611
|
+
if (!table.checkConstraints.length) continue;
|
|
1612
|
+
const sql = `ALTER TABLE "${table.name}" `;
|
|
1613
|
+
const constraints = [];
|
|
1614
|
+
for (const check of table.checkConstraints) {
|
|
1615
|
+
const constraint = `ADD CONSTRAINT "${check.name}" CHECK (${check.check})`;
|
|
1616
|
+
constraints.push(constraint);
|
|
1617
|
+
}
|
|
1618
|
+
sqlStatements.push(sql + constraints.join(",\n") + ";");
|
|
1619
|
+
}
|
|
1620
|
+
sqlStatements.push(indexes.join(";\n"));
|
|
1621
|
+
return enums.join("\n") + "\n" + sqlStatements.join("\n\n");
|
|
1622
|
+
}
|
|
1623
|
+
async getScratchPool() {
|
|
1624
|
+
await this.psqlConnectionPool.runQuery(
|
|
1625
|
+
`DROP DATABASE IF EXISTS ${this.psqlConnectionPool.poolConfig.database}_scratch`,
|
|
1626
|
+
[],
|
|
1627
|
+
systemUser
|
|
1628
|
+
);
|
|
1629
|
+
await this.psqlConnectionPool.runQuery(
|
|
1630
|
+
`CREATE DATABASE ${this.psqlConnectionPool.poolConfig.database}_scratch;`,
|
|
1631
|
+
[],
|
|
1632
|
+
systemUser
|
|
1633
|
+
);
|
|
1634
|
+
const scratchPool = new PsqlPool({
|
|
1635
|
+
host: this.psqlConnectionPool.poolConfig.host,
|
|
1636
|
+
port: this.psqlConnectionPool.poolConfig.port,
|
|
1637
|
+
user: this.psqlConnectionPool.poolConfig.user,
|
|
1638
|
+
database: this.psqlConnectionPool.poolConfig.database + "_scratch",
|
|
1639
|
+
password: this.psqlConnectionPool.poolConfig.password,
|
|
1640
|
+
max: this.psqlConnectionPool.poolConfig.max,
|
|
1641
|
+
idleTimeoutMillis: this.psqlConnectionPool.poolConfig.idleTimeoutMillis,
|
|
1642
|
+
connectionTimeoutMillis: this.psqlConnectionPool.poolConfig.connectionTimeoutMillis
|
|
1643
|
+
});
|
|
1644
|
+
return scratchPool;
|
|
1645
|
+
}
|
|
1646
|
+
async diffDatabaseToSchema(schema) {
|
|
1647
|
+
const scratchPool = await this.getScratchPool();
|
|
1648
|
+
await this.createDatabaseFromSchema(schema, scratchPool);
|
|
1649
|
+
const originalClient = new Client({
|
|
1650
|
+
database: this.psqlConnectionPool.poolConfig.database,
|
|
1651
|
+
user: this.psqlConnectionPool.poolConfig.user,
|
|
1652
|
+
password: this.psqlConnectionPool.poolConfig.password,
|
|
1653
|
+
host: this.psqlConnectionPool.poolConfig.host,
|
|
1654
|
+
port: this.psqlConnectionPool.poolConfig.port
|
|
1655
|
+
});
|
|
1656
|
+
const scratchClient = new Client({
|
|
1657
|
+
database: this.psqlConnectionPool.poolConfig.database + "_scratch",
|
|
1658
|
+
user: this.psqlConnectionPool.poolConfig.user,
|
|
1659
|
+
password: this.psqlConnectionPool.poolConfig.password,
|
|
1660
|
+
host: this.psqlConnectionPool.poolConfig.host,
|
|
1661
|
+
port: this.psqlConnectionPool.poolConfig.port
|
|
1662
|
+
});
|
|
1663
|
+
await originalClient.connect();
|
|
1664
|
+
await scratchClient.connect();
|
|
1665
|
+
const info1 = await pgInfo({
|
|
1666
|
+
client: originalClient,
|
|
1667
|
+
schema: "public"
|
|
1668
|
+
});
|
|
1669
|
+
const info2 = await pgInfo({
|
|
1670
|
+
client: scratchClient,
|
|
1671
|
+
schema: "public"
|
|
1672
|
+
});
|
|
1673
|
+
const diff = getDiff(info1, info2);
|
|
1674
|
+
console.log("Schema differences:", diff);
|
|
1675
|
+
await originalClient.end();
|
|
1676
|
+
await scratchClient.end();
|
|
1677
|
+
return diff.join("\n");
|
|
1414
1678
|
}
|
|
1415
1679
|
createNestedSelect(req, schema, item, routeData, userRole, sqlParams) {
|
|
1416
1680
|
if (!item.subquery) return "";
|
|
@@ -1521,22 +1785,20 @@ var PsqlEngine = class extends SqlEngine {
|
|
|
1521
1785
|
);
|
|
1522
1786
|
} else if (routeData.type === "PAGED") {
|
|
1523
1787
|
const data = req.data;
|
|
1524
|
-
const
|
|
1525
|
-
`${selectStatement}${sqlStatement}${groupByOrderByStatement} LIMIT
|
|
1526
|
-
|
|
1527
|
-
[
|
|
1528
|
-
...sqlParams,
|
|
1529
|
-
data.perPage || DEFAULT_PAGED_PER_PAGE_NUMBER,
|
|
1530
|
-
(data.page - 1) * data.perPage || DEFAULT_PAGED_PAGE_NUMBER,
|
|
1531
|
-
...sqlParams
|
|
1532
|
-
],
|
|
1788
|
+
const pagePromise = this.psqlConnectionPool.runQuery(
|
|
1789
|
+
`${selectStatement}${sqlStatement}${groupByOrderByStatement}` + SQL`LIMIT ${data.perPage || DEFAULT_PAGED_PER_PAGE_NUMBER} OFFSET ${(data.page - 1) * data.perPage || DEFAULT_PAGED_PAGE_NUMBER};`,
|
|
1790
|
+
sqlParams,
|
|
1533
1791
|
req.requesterDetails
|
|
1534
1792
|
);
|
|
1793
|
+
const totalQuery = `SELECT COUNT(${routeData.groupBy ? `DISTINCT ${routeData.groupBy.tableName}.${routeData.groupBy.columnName}` : "*"}) AS total
|
|
1794
|
+
${sqlStatement};`;
|
|
1795
|
+
const totalPromise = await this.psqlConnectionPool.runQuery(totalQuery, sqlParams, req.requesterDetails);
|
|
1796
|
+
const [pageResults, totalResponse] = await Promise.all([pagePromise, totalPromise]);
|
|
1535
1797
|
let total = 0;
|
|
1536
|
-
if (ObjectUtils4.isArrayWithData(
|
|
1537
|
-
total =
|
|
1798
|
+
if (ObjectUtils4.isArrayWithData(totalResponse)) {
|
|
1799
|
+
total = totalResponse[0].total;
|
|
1538
1800
|
}
|
|
1539
|
-
return { data: pageResults
|
|
1801
|
+
return { data: pageResults, total };
|
|
1540
1802
|
} else {
|
|
1541
1803
|
throw new RsError("UNKNOWN_ERROR", "Unknown route type.");
|
|
1542
1804
|
}
|
|
@@ -1686,77 +1948,12 @@ ${sqlStatement};`,
|
|
|
1686
1948
|
return whereClause;
|
|
1687
1949
|
}
|
|
1688
1950
|
};
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
constructor(poolConfig) {
|
|
1696
|
-
this.poolConfig = poolConfig;
|
|
1697
|
-
this.pool = new Pool(poolConfig);
|
|
1698
|
-
this.queryOne("SELECT NOW();", [], { isSystemUser: true, role: "", host: "localhost", ipAddress: "" }).then(() => {
|
|
1699
|
-
logger.info("Connected to PostgreSQL database");
|
|
1700
|
-
}).catch((error) => {
|
|
1701
|
-
logger.error("Error connecting to database", error);
|
|
1702
|
-
process.exit(1);
|
|
1703
|
-
});
|
|
1704
|
-
}
|
|
1705
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1706
|
-
async queryOne(query, options, requesterDetails) {
|
|
1707
|
-
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1708
|
-
this.logSqlStatement(formattedQuery, options, requesterDetails);
|
|
1709
|
-
try {
|
|
1710
|
-
const response = await this.pool.query(formattedQuery, options);
|
|
1711
|
-
if (response.rows.length === 0) throw new RsError("NOT_FOUND", "No results found");
|
|
1712
|
-
else if (response.rows.length > 1) throw new RsError("DUPLICATE", "More than one result found");
|
|
1713
|
-
return response.rows[0];
|
|
1714
|
-
} catch (error) {
|
|
1715
|
-
console.error(error, query, options);
|
|
1716
|
-
if (RsError.isRsError(error)) throw error;
|
|
1717
|
-
if ((error == null ? void 0 : error.routine) === "_bt_check_unique") {
|
|
1718
|
-
throw new RsError("DUPLICATE", error.message);
|
|
1719
|
-
}
|
|
1720
|
-
throw new RsError("DATABASE_ERROR", `${error.message}`);
|
|
1721
|
-
}
|
|
1722
|
-
}
|
|
1723
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1724
|
-
async runQuery(query, options, requesterDetails) {
|
|
1725
|
-
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1726
|
-
this.logSqlStatement(formattedQuery, options, requesterDetails);
|
|
1727
|
-
const queryUpdated = query.replace(/[\t\n]/g, " ");
|
|
1728
|
-
console.log(queryUpdated, options);
|
|
1729
|
-
try {
|
|
1730
|
-
const response = await this.pool.query(formattedQuery, options);
|
|
1731
|
-
return response.rows;
|
|
1732
|
-
} catch (error) {
|
|
1733
|
-
console.error(error, query, options);
|
|
1734
|
-
if ((error == null ? void 0 : error.routine) === "_bt_check_unique") {
|
|
1735
|
-
throw new RsError("DUPLICATE", error.message);
|
|
1736
|
-
}
|
|
1737
|
-
throw new RsError("DATABASE_ERROR", `${error.message}`);
|
|
1738
|
-
}
|
|
1739
|
-
}
|
|
1740
|
-
logSqlStatement(query, options, requesterDetails, prefix = "") {
|
|
1741
|
-
if (logger.level !== "silly") return;
|
|
1742
|
-
let sqlStatement = "";
|
|
1743
|
-
if (options.length === 0) {
|
|
1744
|
-
sqlStatement = query;
|
|
1745
|
-
} else {
|
|
1746
|
-
let stringIndex = 0;
|
|
1747
|
-
sqlStatement = query.replace(/\$\d+/g, () => {
|
|
1748
|
-
const value = options[stringIndex++];
|
|
1749
|
-
if (typeof value === "number") return value.toString();
|
|
1750
|
-
return format3.literal(value);
|
|
1751
|
-
});
|
|
1752
|
-
}
|
|
1753
|
-
let initiator = "Anonymous";
|
|
1754
|
-
if ("userId" in requesterDetails && requesterDetails.userId)
|
|
1755
|
-
initiator = `User Id (${requesterDetails.userId.toString()})`;
|
|
1756
|
-
if ("isSystemUser" in requesterDetails && requesterDetails.isSystemUser) initiator = "SYSTEM";
|
|
1757
|
-
logger.silly(`${prefix}query by ${initiator}, Query ->
|
|
1758
|
-
${sqlStatement}`);
|
|
1759
|
-
}
|
|
1951
|
+
var schemaToPsqlType = (column, tableName) => {
|
|
1952
|
+
if (column.hasAutoIncrement) return "BIGSERIAL";
|
|
1953
|
+
if (column.type === "ENUM") return `"${tableName}_${column.name}_enum"`;
|
|
1954
|
+
if (column.type === "DATETIME") return "TIMESTAMPTZ";
|
|
1955
|
+
if (column.type === "MEDIUMINT") return "INT";
|
|
1956
|
+
return column.type;
|
|
1760
1957
|
};
|
|
1761
1958
|
|
|
1762
1959
|
// src/restura/restura.ts
|