@restura/core 0.1.0-alpha.14 → 0.1.0-alpha.16

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 CHANGED
@@ -68,9 +68,7 @@ var __decorateClass = (decorators, target, key, kind) => {
68
68
  var src_exports = {};
69
69
  __export(src_exports, {
70
70
  HtmlStatusCodes: () => HtmlStatusCodes,
71
- PsqlConnection: () => PsqlConnection,
72
71
  PsqlPool: () => PsqlPool,
73
- PsqlTransaction: () => PsqlTransaction,
74
72
  RsError: () => RsError,
75
73
  SQL: () => SQL,
76
74
  escapeColumnName: () => escapeColumnName,
@@ -792,7 +790,7 @@ var joinDataSchema = import_zod3.z.object({
792
790
  var requestDataSchema = import_zod3.z.object({
793
791
  name: import_zod3.z.string(),
794
792
  required: import_zod3.z.boolean(),
795
- isNullable: import_zod3.z.boolean().optional().default(false),
793
+ isNullable: import_zod3.z.boolean().optional(),
796
794
  validator: import_zod3.z.array(validatorDataSchema)
797
795
  }).strict();
798
796
  var responseDataSchema = import_zod3.z.object({
@@ -878,6 +876,12 @@ var postgresColumnDateTypesSchema = import_zod3.z.enum([
878
876
  "INTERVAL"
879
877
  // time span
880
878
  ]);
879
+ var postgresColumnJsonTypesSchema = import_zod3.z.enum([
880
+ "JSON",
881
+ // stores JSON data as raw text
882
+ "JSONB"
883
+ // stores JSON data in a binary format, optimized for query performance
884
+ ]);
881
885
  var mariaDbColumnNumericTypesSchema = import_zod3.z.enum([
882
886
  "BOOLEAN",
883
887
  // 1-byte A synonym for "TINYINT(1)". Supported from version 1.2.0 onwards.
@@ -940,6 +944,7 @@ var columnDataSchema = import_zod3.z.object({
940
944
  postgresColumnNumericTypesSchema,
941
945
  postgresColumnStringTypesSchema,
942
946
  postgresColumnDateTypesSchema,
947
+ postgresColumnJsonTypesSchema,
943
948
  mariaDbColumnNumericTypesSchema,
944
949
  mariaDbColumnStringTypesSchema,
945
950
  mariaDbColumnDateTypesSchema
@@ -1247,10 +1252,16 @@ function convertTable(table) {
1247
1252
 
1248
1253
  // src/restura/sql/PsqlEngine.ts
1249
1254
  var import_core_utils5 = require("@redskytech/core-utils");
1255
+ var import_pg_diff_sync = __toESM(require("@wmfs/pg-diff-sync"));
1256
+ var import_pg_info = __toESM(require("@wmfs/pg-info"));
1257
+ var import_pg2 = __toESM(require("pg"));
1250
1258
 
1251
1259
  // src/restura/sql/PsqlPool.ts
1252
1260
  var import_pg = __toESM(require("pg"));
1253
1261
 
1262
+ // src/restura/sql/PsqlConnection.ts
1263
+ var import_pg_format2 = __toESM(require("pg-format"));
1264
+
1254
1265
  // src/restura/sql/PsqlUtils.ts
1255
1266
  var import_pg_format = __toESM(require("pg-format"));
1256
1267
  function escapeColumnName(columnName) {
@@ -1266,7 +1277,8 @@ function insertObjectQuery(table, obj) {
1266
1277
  const params = Object.values(obj);
1267
1278
  const columns = keys.map((column) => escapeColumnName(column)).join(", ");
1268
1279
  const values = params.map((value) => SQL`${value}`).join(", ");
1269
- const query = `INSERT INTO "${table}" (${columns})
1280
+ const query = `
1281
+ INSERT INTO "${table}" (${columns})
1270
1282
  VALUES (${values})
1271
1283
  RETURNING *`;
1272
1284
  return query;
@@ -1276,7 +1288,8 @@ function updateObjectQuery(table, obj, whereStatement) {
1276
1288
  for (const i in obj) {
1277
1289
  setArray.push(`${escapeColumnName(i)} = ` + SQL`${obj[i]}`);
1278
1290
  }
1279
- return `UPDATE ${escapeColumnName(table)}
1291
+ return `
1292
+ UPDATE ${escapeColumnName(table)}
1280
1293
  SET ${setArray.join(", ")} ${whereStatement}
1281
1294
  RETURNING *`;
1282
1295
  }
@@ -1299,7 +1312,6 @@ function SQL(strings, ...values) {
1299
1312
  }
1300
1313
 
1301
1314
  // src/restura/sql/PsqlConnection.ts
1302
- var import_pg_format2 = __toESM(require("pg-format"));
1303
1315
  var PsqlConnection = class {
1304
1316
  constructor() {
1305
1317
  }
@@ -1307,8 +1319,10 @@ var PsqlConnection = class {
1307
1319
  async queryOne(query, options, requesterDetails) {
1308
1320
  const formattedQuery = questionMarksToOrderedParams(query);
1309
1321
  this.logSqlStatement(formattedQuery, options, requesterDetails);
1322
+ const queryMetadata = `--QUERY_METADATA(${JSON.stringify(requesterDetails)})
1323
+ `;
1310
1324
  try {
1311
- const response = await this.query(formattedQuery, options);
1325
+ const response = await this.query(queryMetadata + formattedQuery, options);
1312
1326
  if (response.rows.length === 0) throw new RsError("NOT_FOUND", "No results found");
1313
1327
  else if (response.rows.length > 1) throw new RsError("DUPLICATE", "More than one result found");
1314
1328
  return response.rows[0];
@@ -1325,8 +1339,10 @@ var PsqlConnection = class {
1325
1339
  async runQuery(query, options, requesterDetails) {
1326
1340
  const formattedQuery = questionMarksToOrderedParams(query);
1327
1341
  this.logSqlStatement(formattedQuery, options, requesterDetails);
1342
+ const queryMetadata = `--QUERY_METADATA(${JSON.stringify(requesterDetails)})
1343
+ `;
1328
1344
  try {
1329
- const response = await this.query(formattedQuery, options);
1345
+ const response = await this.query(queryMetadata + formattedQuery, options);
1330
1346
  return response.rows;
1331
1347
  } catch (error) {
1332
1348
  console.error(error, query, options);
@@ -1577,10 +1593,112 @@ var filterPsqlParser = import_pegjs.default.generate(filterSqlGrammar, {
1577
1593
  });
1578
1594
  var filterPsqlParser_default = filterPsqlParser;
1579
1595
 
1596
+ // src/restura/eventManager.ts
1597
+ var import_bluebird = __toESM(require("bluebird"));
1598
+ var EventManager = class {
1599
+ constructor() {
1600
+ this.actionHandlers = {
1601
+ DATABASE_ROW_DELETE: [],
1602
+ DATABASE_ROW_INSERT: [],
1603
+ DATABASE_COLUMN_UPDATE: []
1604
+ };
1605
+ }
1606
+ addRowInsertHandler(onInsert, filter) {
1607
+ this.actionHandlers.DATABASE_ROW_INSERT.push({
1608
+ callback: onInsert,
1609
+ filter
1610
+ });
1611
+ }
1612
+ addColumnChangeHandler(onUpdate, filter) {
1613
+ this.actionHandlers.DATABASE_COLUMN_UPDATE.push({
1614
+ callback: onUpdate,
1615
+ filter
1616
+ });
1617
+ }
1618
+ addRowDeleteHandler(onDelete, filter) {
1619
+ this.actionHandlers.DATABASE_ROW_DELETE.push({
1620
+ callback: onDelete,
1621
+ filter
1622
+ });
1623
+ }
1624
+ async fireActionFromDbTrigger(sqlMutationData, result) {
1625
+ if (sqlMutationData.mutationType === "INSERT") {
1626
+ await this.fireInsertActions(sqlMutationData, result);
1627
+ } else if (sqlMutationData.mutationType === "UPDATE") {
1628
+ await this.fireUpdateActions(sqlMutationData, result);
1629
+ } else if (sqlMutationData.mutationType === "DELETE") {
1630
+ await this.fireDeleteActions(sqlMutationData, result);
1631
+ }
1632
+ }
1633
+ async fireInsertActions(data, triggerResult) {
1634
+ await import_bluebird.default.map(
1635
+ this.actionHandlers.DATABASE_ROW_INSERT,
1636
+ ({ callback, filter }) => {
1637
+ if (!this.hasHandlersForEventType("DATABASE_ROW_INSERT", filter, triggerResult)) return;
1638
+ const insertData = {
1639
+ tableName: triggerResult.table,
1640
+ insertId: triggerResult.record.id,
1641
+ insertObject: triggerResult.record,
1642
+ requesterDetails: data.requesterDetails
1643
+ };
1644
+ callback(insertData, data.requesterDetails);
1645
+ },
1646
+ { concurrency: 10 }
1647
+ );
1648
+ }
1649
+ async fireDeleteActions(data, triggerResult) {
1650
+ await import_bluebird.default.map(
1651
+ this.actionHandlers.DATABASE_ROW_DELETE,
1652
+ ({ callback, filter }) => {
1653
+ if (!this.hasHandlersForEventType("DATABASE_ROW_DELETE", filter, triggerResult)) return;
1654
+ const deleteData = {
1655
+ tableName: triggerResult.table,
1656
+ deletedRow: triggerResult.previousRecord,
1657
+ requesterDetails: data.requesterDetails
1658
+ };
1659
+ callback(deleteData, data.requesterDetails);
1660
+ },
1661
+ { concurrency: 10 }
1662
+ );
1663
+ }
1664
+ async fireUpdateActions(data, triggerResult) {
1665
+ await import_bluebird.default.map(
1666
+ this.actionHandlers.DATABASE_COLUMN_UPDATE,
1667
+ ({ callback, filter }) => {
1668
+ if (!this.hasHandlersForEventType("DATABASE_COLUMN_UPDATE", filter, triggerResult)) return;
1669
+ const columnChangeData = {
1670
+ tableName: triggerResult.table,
1671
+ rowId: triggerResult.record.id,
1672
+ newData: triggerResult.record,
1673
+ oldData: triggerResult.previousRecord,
1674
+ requesterDetails: data.requesterDetails
1675
+ };
1676
+ callback(columnChangeData, data.requesterDetails);
1677
+ },
1678
+ { concurrency: 10 }
1679
+ );
1680
+ }
1681
+ hasHandlersForEventType(eventType, filter, triggerResult) {
1682
+ if (filter) {
1683
+ switch (eventType) {
1684
+ case "DATABASE_ROW_INSERT":
1685
+ case "DATABASE_ROW_DELETE":
1686
+ if (filter.tableName && filter.tableName !== triggerResult.table) return false;
1687
+ break;
1688
+ case "DATABASE_COLUMN_UPDATE":
1689
+ const filterColumnChange = filter;
1690
+ if (filterColumnChange.tableName !== filter.tableName) return false;
1691
+ break;
1692
+ }
1693
+ }
1694
+ return true;
1695
+ }
1696
+ };
1697
+ var eventManager = new EventManager();
1698
+ var eventManager_default = eventManager;
1699
+
1580
1700
  // src/restura/sql/PsqlEngine.ts
1581
- var import_pg_diff_sync = __toESM(require("@wmfs/pg-diff-sync"));
1582
- var import_pg_info = __toESM(require("@wmfs/pg-info"));
1583
- var { Client } = "pg";
1701
+ var { Client } = import_pg2.default;
1584
1702
  var systemUser = {
1585
1703
  role: "",
1586
1704
  host: "",
@@ -1588,9 +1706,49 @@ var systemUser = {
1588
1706
  isSystemUser: true
1589
1707
  };
1590
1708
  var PsqlEngine = class extends SqlEngine {
1591
- constructor(psqlConnectionPool) {
1709
+ constructor(psqlConnectionPool, shouldListenForDbTriggers = false) {
1592
1710
  super();
1593
1711
  this.psqlConnectionPool = psqlConnectionPool;
1712
+ if (shouldListenForDbTriggers) {
1713
+ this.setupTriggerListeners = this.listenForDbTriggers();
1714
+ }
1715
+ }
1716
+ async close() {
1717
+ if (this.triggerClient) {
1718
+ await this.triggerClient.end();
1719
+ }
1720
+ }
1721
+ async listenForDbTriggers() {
1722
+ this.triggerClient = new Client({
1723
+ user: this.psqlConnectionPool.poolConfig.user,
1724
+ host: this.psqlConnectionPool.poolConfig.host,
1725
+ database: this.psqlConnectionPool.poolConfig.database,
1726
+ password: this.psqlConnectionPool.poolConfig.password,
1727
+ port: this.psqlConnectionPool.poolConfig.port,
1728
+ connectionTimeoutMillis: 2e3
1729
+ });
1730
+ await this.triggerClient.connect();
1731
+ const promises = [];
1732
+ promises.push(this.triggerClient.query("LISTEN insert"));
1733
+ promises.push(this.triggerClient.query("LISTEN update"));
1734
+ promises.push(this.triggerClient.query("LISTEN delete"));
1735
+ await Promise.all(promises);
1736
+ this.triggerClient.on("notification", async (msg) => {
1737
+ if (msg.channel === "insert" || msg.channel === "update" || msg.channel === "delete") {
1738
+ const payload = JSON.parse(msg.payload);
1739
+ await this.handleTrigger(payload, msg.channel.toUpperCase());
1740
+ }
1741
+ });
1742
+ }
1743
+ async handleTrigger(payload, mutationType) {
1744
+ const findRequesterDetailsRegex = /^--QUERY_METADATA\(\{.*\}\)/;
1745
+ let requesterDetails = {};
1746
+ const match = payload.query.match(findRequesterDetailsRegex);
1747
+ if (match) {
1748
+ const jsonString = match[0].slice(match[0].indexOf("{"), match[0].lastIndexOf("}") + 1);
1749
+ requesterDetails = import_core_utils5.ObjectUtils.safeParse(jsonString);
1750
+ await eventManager_default.fireActionFromDbTrigger({ requesterDetails, mutationType }, payload);
1751
+ }
1594
1752
  }
1595
1753
  async createDatabaseFromSchema(schema, connection) {
1596
1754
  const sqlFullStatement = this.generateDatabaseSchemaFromSchema(schema);
@@ -1601,7 +1759,11 @@ var PsqlEngine = class extends SqlEngine {
1601
1759
  const sqlStatements = [];
1602
1760
  const enums = [];
1603
1761
  const indexes = [];
1762
+ const triggers = [];
1604
1763
  for (const table of schema.database) {
1764
+ triggers.push(this.createInsertTriggers(table.name));
1765
+ triggers.push(this.createUpdateTrigger(table.name));
1766
+ triggers.push(this.createDeleteTrigger(table.name));
1605
1767
  let sql = `CREATE TABLE "${table.name}"
1606
1768
  ( `;
1607
1769
  const tableColumns = [];
@@ -1628,7 +1790,7 @@ var PsqlEngine = class extends SqlEngine {
1628
1790
  }
1629
1791
  if (column.isNullable) columnSql += " NULL";
1630
1792
  else columnSql += " NOT NULL";
1631
- if (column.default) columnSql += ` DEFAULT '${column.default}'`;
1793
+ if (column.default) columnSql += ` DEFAULT ${column.default}`;
1632
1794
  tableColumns.push(columnSql);
1633
1795
  }
1634
1796
  sql += tableColumns.join(", \n");
@@ -1639,7 +1801,7 @@ var PsqlEngine = class extends SqlEngine {
1639
1801
  indexes.push(
1640
1802
  ` CREATE ${unique}INDEX "${index.name}" ON "${table.name}" (${index.columns.map((item) => {
1641
1803
  return `"${item}" ${index.order}`;
1642
- }).join(", ")})`
1804
+ }).join(", ")});`
1643
1805
  );
1644
1806
  }
1645
1807
  }
@@ -1669,7 +1831,8 @@ var PsqlEngine = class extends SqlEngine {
1669
1831
  }
1670
1832
  sqlStatements.push(sql + constraints.join(",\n") + ";");
1671
1833
  }
1672
- sqlStatements.push(indexes.join(";\n"));
1834
+ sqlStatements.push(indexes.join("\n"));
1835
+ sqlStatements.push(triggers.join("\n"));
1673
1836
  return enums.join("\n") + "\n" + sqlStatements.join("\n\n");
1674
1837
  }
1675
1838
  async getScratchPool() {
@@ -1715,12 +1878,10 @@ var PsqlEngine = class extends SqlEngine {
1715
1878
  await originalClient.connect();
1716
1879
  await scratchClient.connect();
1717
1880
  const info1 = await (0, import_pg_info.default)({
1718
- client: originalClient,
1719
- schema: "public"
1881
+ client: originalClient
1720
1882
  });
1721
1883
  const info2 = await (0, import_pg_info.default)({
1722
- client: scratchClient,
1723
- schema: "public"
1884
+ client: scratchClient
1724
1885
  });
1725
1886
  const diff = (0, import_pg_diff_sync.default)(info1, info2);
1726
1887
  await originalClient.end();
@@ -1739,8 +1900,7 @@ var PsqlEngine = class extends SqlEngine {
1739
1900
  )) {
1740
1901
  return "'[]'";
1741
1902
  }
1742
- return `COALESCE((
1743
- SELECT JSON_AGG(JSON_BUILD_OBJECT(
1903
+ return `COALESCE((SELECT JSON_AGG(JSON_BUILD_OBJECT(
1744
1904
  ${item.subquery.properties.map((nestedItem) => {
1745
1905
  if (!this.doesRoleHavePermissionToColumn(req.requesterDetails.role, schema, nestedItem, [
1746
1906
  ...routeData.joins,
@@ -1749,7 +1909,7 @@ var PsqlEngine = class extends SqlEngine {
1749
1909
  return;
1750
1910
  }
1751
1911
  if (nestedItem.subquery) {
1752
- return `"${nestedItem.name}", ${this.createNestedSelect(
1912
+ return `'${nestedItem.name}', ${this.createNestedSelect(
1753
1913
  // recursion
1754
1914
  req,
1755
1915
  schema,
@@ -1760,7 +1920,7 @@ var PsqlEngine = class extends SqlEngine {
1760
1920
  )}`;
1761
1921
  }
1762
1922
  return `'${nestedItem.name}', ${escapeColumnName(nestedItem.selector)}`;
1763
- }).filter(Boolean).join(",")}
1923
+ }).filter(Boolean).join(", ")}
1764
1924
  ))
1765
1925
  FROM
1766
1926
  "${item.subquery.table}"
@@ -1888,10 +2048,12 @@ var PsqlEngine = class extends SqlEngine {
1888
2048
  req.requesterDetails.role,
1889
2049
  sqlParams
1890
2050
  );
1891
- let deleteStatement = `DELETE
1892
- FROM "${routeData.table}" ${joinStatement}`;
1893
- deleteStatement += this.generateWhereClause(req, routeData.where, routeData, sqlParams);
1894
- deleteStatement += ";";
2051
+ const whereClause = this.generateWhereClause(req, routeData.where, routeData, sqlParams);
2052
+ if (whereClause.replace(/\s/g, "") === "") {
2053
+ throw new RsError("DELETE_FORBIDDEN", "Deletes need a where clause");
2054
+ }
2055
+ const deleteStatement = `
2056
+ DELETE FROM "${routeData.table}" ${joinStatement} ${whereClause}`;
1895
2057
  await this.psqlConnectionPool.runQuery(deleteStatement, sqlParams, req.requesterDetails);
1896
2058
  return true;
1897
2059
  }
@@ -1954,17 +2116,17 @@ var PsqlEngine = class extends SqlEngine {
1954
2116
  );
1955
2117
  let operator = item.operator;
1956
2118
  if (operator === "LIKE") {
1957
- sqlParams[sqlParams.length - 1] = `%${sqlParams[sqlParams.length - 1]}%`;
2119
+ item.value = `%${item.value}%`;
1958
2120
  } else if (operator === "STARTS WITH") {
1959
2121
  operator = "LIKE";
1960
- sqlParams[sqlParams.length - 1] = `${sqlParams[sqlParams.length - 1]}%`;
2122
+ item.value = `${item.value}%`;
1961
2123
  } else if (operator === "ENDS WITH") {
1962
2124
  operator = "LIKE";
1963
- sqlParams[sqlParams.length - 1] = `%${sqlParams[sqlParams.length - 1]}`;
2125
+ item.value = `%${item.value}`;
1964
2126
  }
1965
2127
  const replacedValue = this.replaceParamKeywords(item.value, routeData, req, sqlParams);
1966
2128
  const escapedValue = SQL`${replacedValue}`;
1967
- whereClause += ` ${item.conjunction || ""} "${item.tableName}"."${item.columnName}" ${operator} ${["IN", "NOT IN"].includes(operator) ? `(${escapedValue})` : escapedValue}
2129
+ whereClause += ` ${item.conjunction || ""} "${item.tableName}"."${item.columnName}" ${operator.replace("LIKE", "ILIKE")} ${["IN", "NOT IN"].includes(operator) ? `(${escapedValue})` : escapedValue}
1968
2130
  `;
1969
2131
  });
1970
2132
  const data = req.data;
@@ -1998,63 +2160,94 @@ var PsqlEngine = class extends SqlEngine {
1998
2160
  }
1999
2161
  return whereClause;
2000
2162
  }
2163
+ createUpdateTrigger(tableName) {
2164
+ return `
2165
+ CREATE OR REPLACE FUNCTION notify_${tableName}_update()
2166
+ RETURNS TRIGGER AS $$
2167
+ BEGIN
2168
+ PERFORM pg_notify('update', JSON_BUILD_OBJECT('table', '${tableName}', 'query', current_query(), 'record', NEW, 'previousRecord', OLD)::text);
2169
+ RETURN NEW;
2170
+ END;
2171
+ $$ LANGUAGE plpgsql;
2172
+
2173
+ CREATE OR REPLACE TRIGGER ${tableName}_update
2174
+ AFTER UPDATE ON "${tableName}"
2175
+ FOR EACH ROW
2176
+ EXECUTE FUNCTION notify_${tableName}_update();
2177
+ `;
2178
+ }
2179
+ createDeleteTrigger(tableName) {
2180
+ return `
2181
+ CREATE OR REPLACE FUNCTION notify_${tableName}_delete()
2182
+ RETURNS TRIGGER AS $$
2183
+ BEGIN
2184
+ PERFORM pg_notify('delete', JSON_BUILD_OBJECT('table', '${tableName}', 'query', current_query(), 'record', NEW, 'previousRecord', OLD)::text);
2185
+ RETURN NEW;
2186
+ END;
2187
+ $$ LANGUAGE plpgsql;
2188
+
2189
+ CREATE OR REPLACE TRIGGER "${tableName}_delete"
2190
+ AFTER DELETE ON "${tableName}"
2191
+ FOR EACH ROW
2192
+ EXECUTE FUNCTION notify_${tableName}_delete();
2193
+ `;
2194
+ }
2195
+ createInsertTriggers(tableName) {
2196
+ return `
2197
+ CREATE OR REPLACE FUNCTION notify_${tableName}_insert()
2198
+ RETURNS TRIGGER AS $$
2199
+ BEGIN
2200
+ PERFORM pg_notify('insert', JSON_BUILD_OBJECT('table', '${tableName}', 'query', current_query(), 'record', NEW, 'previousRecord', OLD)::text);
2201
+ RETURN NEW;
2202
+ END;
2203
+ $$ LANGUAGE plpgsql;
2204
+
2205
+ CREATE TRIGGER "${tableName}_insert"
2206
+ AFTER INSERT ON "${tableName}"
2207
+ FOR EACH ROW
2208
+ EXECUTE FUNCTION notify_${tableName}_insert();
2209
+ `;
2210
+ }
2001
2211
  };
2002
- var schemaToPsqlType = (column, tableName) => {
2212
+ __decorateClass([
2213
+ boundMethod
2214
+ ], PsqlEngine.prototype, "handleTrigger", 1);
2215
+ __decorateClass([
2216
+ boundMethod
2217
+ ], PsqlEngine.prototype, "createUpdateTrigger", 1);
2218
+ __decorateClass([
2219
+ boundMethod
2220
+ ], PsqlEngine.prototype, "createDeleteTrigger", 1);
2221
+ __decorateClass([
2222
+ boundMethod
2223
+ ], PsqlEngine.prototype, "createInsertTriggers", 1);
2224
+ function schemaToPsqlType(column, tableName) {
2003
2225
  if (column.hasAutoIncrement) return "BIGSERIAL";
2004
2226
  if (column.type === "ENUM") return `"${tableName}_${column.name}_enum"`;
2005
2227
  if (column.type === "DATETIME") return "TIMESTAMPTZ";
2006
2228
  if (column.type === "MEDIUMINT") return "INT";
2007
2229
  return column.type;
2008
- };
2009
-
2010
- // src/restura/sql/PsqlTransaction.ts
2011
- var import_pg2 = __toESM(require("pg"));
2012
- var { Client: Client2 } = import_pg2.default;
2013
- var PsqlTransaction = class extends PsqlConnection {
2014
- constructor(clientConfig) {
2015
- super();
2016
- this.clientConfig = clientConfig;
2017
- this.client = new Client2(clientConfig);
2018
- this.beginTransactionPromise = this.beginTransaction();
2019
- }
2020
- async beginTransaction() {
2021
- return this.query("BEGIN");
2022
- }
2023
- async rollback() {
2024
- return this.query("ROLLBACK");
2025
- }
2026
- async commit() {
2027
- return this.query("COMMIT");
2028
- }
2029
- async release() {
2030
- return this.client.end();
2031
- }
2032
- async query(query, values) {
2033
- await this.client.connect();
2034
- await this.beginTransactionPromise;
2035
- return this.client.query(query, values);
2036
- }
2037
- };
2230
+ }
2038
2231
 
2039
2232
  // src/restura/compareSchema.ts
2040
2233
  var import_lodash = __toESM(require("lodash.clonedeep"));
2041
2234
  var CompareSchema = class {
2042
2235
  async diffSchema(newSchema, latestSchema, psqlEngine) {
2043
- let endPoints = this.diffEndPoints(newSchema.endpoints[0].routes, latestSchema.endpoints[0].routes);
2044
- let globalParams = this.diffStringArray(newSchema.globalParams, latestSchema.globalParams);
2045
- let roles = this.diffStringArray(newSchema.roles, latestSchema.roles);
2236
+ const endPoints = this.diffEndPoints(newSchema.endpoints[0].routes, latestSchema.endpoints[0].routes);
2237
+ const globalParams = this.diffStringArray(newSchema.globalParams, latestSchema.globalParams);
2238
+ const roles = this.diffStringArray(newSchema.roles, latestSchema.roles);
2046
2239
  let commands = "";
2047
2240
  if (JSON.stringify(newSchema.database) !== JSON.stringify(latestSchema.database))
2048
2241
  commands = await psqlEngine.diffDatabaseToSchema(newSchema);
2049
- let customTypes = newSchema.customTypes !== latestSchema.customTypes;
2242
+ const customTypes = newSchema.customTypes !== latestSchema.customTypes;
2050
2243
  const schemaPreview = { endPoints, globalParams, roles, commands, customTypes };
2051
2244
  return schemaPreview;
2052
2245
  }
2053
2246
  diffStringArray(newArray, originalArray) {
2054
- let stringsDiff = [];
2055
- let originalClone = new Set(originalArray);
2247
+ const stringsDiff = [];
2248
+ const originalClone = new Set(originalArray);
2056
2249
  newArray.forEach((item) => {
2057
- let originalIndex = originalClone.has(item);
2250
+ const originalIndex = originalClone.has(item);
2058
2251
  if (!originalIndex) {
2059
2252
  stringsDiff.push({
2060
2253
  name: item,
@@ -2073,11 +2266,11 @@ var CompareSchema = class {
2073
2266
  return stringsDiff;
2074
2267
  }
2075
2268
  diffEndPoints(newEndPoints, originalEndpoints) {
2076
- let originalClone = (0, import_lodash.default)(originalEndpoints);
2077
- let diffObj = [];
2269
+ const originalClone = (0, import_lodash.default)(originalEndpoints);
2270
+ const diffObj = [];
2078
2271
  newEndPoints.forEach((endPoint) => {
2079
- let { path: path4, method } = endPoint;
2080
- let endPointIndex = originalClone.findIndex((original) => {
2272
+ const { path: path4, method } = endPoint;
2273
+ const endPointIndex = originalClone.findIndex((original) => {
2081
2274
  return original.path === endPoint.path && original.method === endPoint.method;
2082
2275
  });
2083
2276
  if (endPointIndex === -1) {
@@ -2086,7 +2279,7 @@ var CompareSchema = class {
2086
2279
  changeType: "NEW"
2087
2280
  });
2088
2281
  } else {
2089
- let original = originalClone.findIndex((original2) => {
2282
+ const original = originalClone.findIndex((original2) => {
2090
2283
  return this.compareEndPoints(endPoint, original2);
2091
2284
  });
2092
2285
  if (original === -1) {
@@ -2099,7 +2292,7 @@ var CompareSchema = class {
2099
2292
  }
2100
2293
  });
2101
2294
  originalClone.forEach((original) => {
2102
- let { path: path4, method } = original;
2295
+ const { path: path4, method } = original;
2103
2296
  diffObj.push({
2104
2297
  name: `${method} ${path4}`,
2105
2298
  changeType: "DELETED"
@@ -2502,12 +2695,14 @@ var setupPgReturnTypes = () => {
2502
2695
  };
2503
2696
  setupPgReturnTypes();
2504
2697
  var restura = new ResturaEngine();
2698
+
2699
+ // src/restura/sql/PsqlTransaction.ts
2700
+ var import_pg4 = __toESM(require("pg"));
2701
+ var { Client: Client2 } = import_pg4.default;
2505
2702
  // Annotate the CommonJS export names for ESM import in node:
2506
2703
  0 && (module.exports = {
2507
2704
  HtmlStatusCodes,
2508
- PsqlConnection,
2509
2705
  PsqlPool,
2510
- PsqlTransaction,
2511
2706
  RsError,
2512
2707
  SQL,
2513
2708
  escapeColumnName,