@restura/core 0.1.0-alpha.20 → 0.1.0-alpha.22

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 CHANGED
@@ -3,6 +3,7 @@ import * as express from 'express';
3
3
  import { z } from 'zod';
4
4
  import { QueryResultRow, QueryConfigValues, QueryResult, PoolConfig, Pool, ClientConfig, Client } from 'pg';
5
5
  import { IncomingHttpHeaders } from 'http2';
6
+ import { UUID } from 'crypto';
6
7
 
7
8
  declare const logger: winston.Logger;
8
9
 
@@ -2364,6 +2365,7 @@ interface AsyncExpressApplication {
2364
2365
  }
2365
2366
 
2366
2367
  declare abstract class PsqlConnection {
2368
+ readonly instanceId: UUID;
2367
2369
  protected constructor();
2368
2370
  protected abstract query<R extends QueryResultRow = QueryResultRow, T extends Array<unknown> = unknown[]>(query: string, values?: QueryConfigValues<T>): Promise<QueryResult<R>>;
2369
2371
  queryOne<T>(query: string, options: any[], requesterDetails: RequesterDetails): Promise<T>;
@@ -2543,11 +2545,11 @@ type EventType = 'DATABASE_ROW_DELETE' | 'DATABASE_ROW_INSERT' | 'DATABASE_COLUM
2543
2545
  type MutationType = 'INSERT' | 'UPDATE' | 'DELETE';
2544
2546
  interface SqlMutationData {
2545
2547
  mutationType: MutationType;
2546
- requesterDetails: RequesterDetails;
2548
+ queryMetadata: QueryMetadata;
2547
2549
  }
2548
2550
  interface DatabaseActionData {
2549
2551
  tableName: string;
2550
- requesterDetails: RequesterDetails;
2552
+ queryMetadata: QueryMetadata;
2551
2553
  }
2552
2554
  interface ActionRowInsertData<T = DynamicObject> extends DatabaseActionData {
2553
2555
  insertId: number;
@@ -2570,6 +2572,7 @@ interface ActionRowDeleteFilter {
2570
2572
  }
2571
2573
  interface ActionColumnChangeFilter {
2572
2574
  tableName: string;
2575
+ columns: string[];
2573
2576
  }
2574
2577
  type TriggerResult = {
2575
2578
  table: string;
@@ -2579,6 +2582,9 @@ type TriggerResult = {
2579
2582
  previousRecord: DynamicObject;
2580
2583
  requesterId: number;
2581
2584
  };
2585
+ type QueryMetadata = RequesterDetails & {
2586
+ connectionInstanceId: UUID;
2587
+ };
2582
2588
  declare class EventManager {
2583
2589
  private actionHandlers;
2584
2590
  addRowInsertHandler(onInsert: (data: ActionRowInsertData<unknown>) => Promise<void>, filter?: ActionRowInsertFilter): void;
@@ -2592,4 +2598,4 @@ declare class EventManager {
2592
2598
  }
2593
2599
  declare const eventManager: EventManager;
2594
2600
 
2595
- export { type ActionColumnChangeData, type ActionColumnChangeFilter, type ActionRowDeleteData, type ActionRowDeleteFilter, type ActionRowInsertData, type ActionRowInsertFilter, type ApiMethod, type AsyncExpressApplication, type AuthenticateHandler, type AuthenticationUserDetails, type ConjunctionTypes, type DatabaseActionData, type DynamicObject, type ErrorCode, type EventType, HtmlStatusCodes, type LoginDetails, type MatchTypes, type MutationType, type PageQuery, PsqlConnection, PsqlEngine, PsqlPool, PsqlTransaction, type RequesterDetails, type ResponseType, type ResponseTypeMap, RsError, type RsErrorData, type RsErrorInternalData, type RsHeaders, type RsPagedResponseData, type RsRequest, type RsResponse, type RsResponseData, type RsRouteHandler, SQL, type SchemaChangeValue, type SchemaPreview, type SqlMutationData, type StandardOrderTypes, type TriggerResult, type ValidAuthenticationCallback, type ValidatorString, escapeColumnName, eventManager, insertObjectQuery, isValueNumber, logger, questionMarksToOrderedParams, restura, updateObjectQuery };
2601
+ export { type ActionColumnChangeData, type ActionColumnChangeFilter, type ActionRowDeleteData, type ActionRowDeleteFilter, type ActionRowInsertData, type ActionRowInsertFilter, type ApiMethod, type AsyncExpressApplication, type AuthenticateHandler, type AuthenticationUserDetails, type ConjunctionTypes, type DatabaseActionData, type DynamicObject, type ErrorCode, type EventType, HtmlStatusCodes, type LoginDetails, type MatchTypes, type MutationType, type PageQuery, PsqlConnection, PsqlEngine, PsqlPool, PsqlTransaction, type QueryMetadata, type RequesterDetails, type ResponseType, type ResponseTypeMap, RsError, type RsErrorData, type RsErrorInternalData, type RsHeaders, type RsPagedResponseData, type RsRequest, type RsResponse, type RsResponseData, type RsRouteHandler, SQL, type SchemaChangeValue, type SchemaPreview, type SqlMutationData, type StandardOrderTypes, type TriggerResult, type ValidAuthenticationCallback, type ValidatorString, escapeColumnName, eventManager, insertObjectQuery, isValueNumber, logger, questionMarksToOrderedParams, restura, updateObjectQuery };
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import * as express from 'express';
3
3
  import { z } from 'zod';
4
4
  import { QueryResultRow, QueryConfigValues, QueryResult, PoolConfig, Pool, ClientConfig, Client } from 'pg';
5
5
  import { IncomingHttpHeaders } from 'http2';
6
+ import { UUID } from 'crypto';
6
7
 
7
8
  declare const logger: winston.Logger;
8
9
 
@@ -2364,6 +2365,7 @@ interface AsyncExpressApplication {
2364
2365
  }
2365
2366
 
2366
2367
  declare abstract class PsqlConnection {
2368
+ readonly instanceId: UUID;
2367
2369
  protected constructor();
2368
2370
  protected abstract query<R extends QueryResultRow = QueryResultRow, T extends Array<unknown> = unknown[]>(query: string, values?: QueryConfigValues<T>): Promise<QueryResult<R>>;
2369
2371
  queryOne<T>(query: string, options: any[], requesterDetails: RequesterDetails): Promise<T>;
@@ -2543,11 +2545,11 @@ type EventType = 'DATABASE_ROW_DELETE' | 'DATABASE_ROW_INSERT' | 'DATABASE_COLUM
2543
2545
  type MutationType = 'INSERT' | 'UPDATE' | 'DELETE';
2544
2546
  interface SqlMutationData {
2545
2547
  mutationType: MutationType;
2546
- requesterDetails: RequesterDetails;
2548
+ queryMetadata: QueryMetadata;
2547
2549
  }
2548
2550
  interface DatabaseActionData {
2549
2551
  tableName: string;
2550
- requesterDetails: RequesterDetails;
2552
+ queryMetadata: QueryMetadata;
2551
2553
  }
2552
2554
  interface ActionRowInsertData<T = DynamicObject> extends DatabaseActionData {
2553
2555
  insertId: number;
@@ -2570,6 +2572,7 @@ interface ActionRowDeleteFilter {
2570
2572
  }
2571
2573
  interface ActionColumnChangeFilter {
2572
2574
  tableName: string;
2575
+ columns: string[];
2573
2576
  }
2574
2577
  type TriggerResult = {
2575
2578
  table: string;
@@ -2579,6 +2582,9 @@ type TriggerResult = {
2579
2582
  previousRecord: DynamicObject;
2580
2583
  requesterId: number;
2581
2584
  };
2585
+ type QueryMetadata = RequesterDetails & {
2586
+ connectionInstanceId: UUID;
2587
+ };
2582
2588
  declare class EventManager {
2583
2589
  private actionHandlers;
2584
2590
  addRowInsertHandler(onInsert: (data: ActionRowInsertData<unknown>) => Promise<void>, filter?: ActionRowInsertFilter): void;
@@ -2592,4 +2598,4 @@ declare class EventManager {
2592
2598
  }
2593
2599
  declare const eventManager: EventManager;
2594
2600
 
2595
- export { type ActionColumnChangeData, type ActionColumnChangeFilter, type ActionRowDeleteData, type ActionRowDeleteFilter, type ActionRowInsertData, type ActionRowInsertFilter, type ApiMethod, type AsyncExpressApplication, type AuthenticateHandler, type AuthenticationUserDetails, type ConjunctionTypes, type DatabaseActionData, type DynamicObject, type ErrorCode, type EventType, HtmlStatusCodes, type LoginDetails, type MatchTypes, type MutationType, type PageQuery, PsqlConnection, PsqlEngine, PsqlPool, PsqlTransaction, type RequesterDetails, type ResponseType, type ResponseTypeMap, RsError, type RsErrorData, type RsErrorInternalData, type RsHeaders, type RsPagedResponseData, type RsRequest, type RsResponse, type RsResponseData, type RsRouteHandler, SQL, type SchemaChangeValue, type SchemaPreview, type SqlMutationData, type StandardOrderTypes, type TriggerResult, type ValidAuthenticationCallback, type ValidatorString, escapeColumnName, eventManager, insertObjectQuery, isValueNumber, logger, questionMarksToOrderedParams, restura, updateObjectQuery };
2601
+ export { type ActionColumnChangeData, type ActionColumnChangeFilter, type ActionRowDeleteData, type ActionRowDeleteFilter, type ActionRowInsertData, type ActionRowInsertFilter, type ApiMethod, type AsyncExpressApplication, type AuthenticateHandler, type AuthenticationUserDetails, type ConjunctionTypes, type DatabaseActionData, type DynamicObject, type ErrorCode, type EventType, HtmlStatusCodes, type LoginDetails, type MatchTypes, type MutationType, type PageQuery, PsqlConnection, PsqlEngine, PsqlPool, PsqlTransaction, type QueryMetadata, type RequesterDetails, type ResponseType, type ResponseTypeMap, RsError, type RsErrorData, type RsErrorInternalData, type RsHeaders, type RsPagedResponseData, type RsRequest, type RsResponse, type RsResponseData, type RsRouteHandler, SQL, type SchemaChangeValue, type SchemaPreview, type SqlMutationData, type StandardOrderTypes, type TriggerResult, type ValidAuthenticationCallback, type ValidatorString, escapeColumnName, eventManager, insertObjectQuery, isValueNumber, logger, questionMarksToOrderedParams, restura, updateObjectQuery };
package/dist/index.js CHANGED
@@ -263,7 +263,7 @@ function boundMethod(target, key, descriptor) {
263
263
  var import_body_parser = __toESM(require("body-parser"));
264
264
  var import_compression = __toESM(require("compression"));
265
265
  var import_cookie_parser = __toESM(require("cookie-parser"));
266
- var import_crypto = require("crypto");
266
+ var import_crypto2 = require("crypto");
267
267
  var express = __toESM(require("express"));
268
268
  var import_fs4 = __toESM(require("fs"));
269
269
  var import_path5 = __toESM(require("path"));
@@ -757,6 +757,8 @@ function addApiResponseFunctions(req, res, next) {
757
757
  function authenticateUser(applicationAuthenticateHandler) {
758
758
  return (req, res, next) => {
759
759
  applicationAuthenticateHandler(req, res, (userDetails) => {
760
+ req.requesterDetails.host = req.hostname;
761
+ req.requesterDetails.ipAddress = req.ip || "";
760
762
  req.requesterDetails = __spreadValues(__spreadValues({}, req.requesterDetails), userDetails);
761
763
  next();
762
764
  });
@@ -1329,14 +1331,17 @@ function SQL(strings, ...values) {
1329
1331
  }
1330
1332
 
1331
1333
  // src/restura/sql/PsqlConnection.ts
1334
+ var import_crypto = __toESM(require("crypto"));
1332
1335
  var PsqlConnection = class {
1333
1336
  constructor() {
1337
+ this.instanceId = import_crypto.default.randomUUID();
1334
1338
  }
1335
1339
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1336
1340
  async queryOne(query, options, requesterDetails) {
1337
1341
  const formattedQuery = questionMarksToOrderedParams(query);
1338
- this.logSqlStatement(formattedQuery, options, requesterDetails);
1339
- const queryMetadata = `--QUERY_METADATA(${JSON.stringify(requesterDetails)})
1342
+ const meta = __spreadValues({ connectionInstanceId: this.instanceId }, requesterDetails);
1343
+ this.logSqlStatement(formattedQuery, options, meta);
1344
+ const queryMetadata = `--QUERY_METADATA(${JSON.stringify(meta)})
1340
1345
  `;
1341
1346
  try {
1342
1347
  const response = await this.query(queryMetadata + formattedQuery, options);
@@ -1355,8 +1360,9 @@ var PsqlConnection = class {
1355
1360
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1356
1361
  async runQuery(query, options, requesterDetails) {
1357
1362
  const formattedQuery = questionMarksToOrderedParams(query);
1358
- this.logSqlStatement(formattedQuery, options, requesterDetails);
1359
- const queryMetadata = `--QUERY_METADATA(${JSON.stringify(requesterDetails)})
1363
+ const meta = __spreadValues({ connectionInstanceId: this.instanceId }, requesterDetails);
1364
+ this.logSqlStatement(formattedQuery, options, meta);
1365
+ const queryMetadata = `--QUERY_METADATA(${JSON.stringify(meta)})
1360
1366
  `;
1361
1367
  try {
1362
1368
  const response = await this.query(queryMetadata + formattedQuery, options);
@@ -1369,7 +1375,7 @@ var PsqlConnection = class {
1369
1375
  throw new RsError("DATABASE_ERROR", `${error.message}`);
1370
1376
  }
1371
1377
  }
1372
- logSqlStatement(query, options, requesterDetails, prefix = "") {
1378
+ logSqlStatement(query, options, queryMetadata, prefix = "") {
1373
1379
  if (logger.level !== "silly") return;
1374
1380
  let sqlStatement = "";
1375
1381
  if (options.length === 0) {
@@ -1383,9 +1389,9 @@ var PsqlConnection = class {
1383
1389
  });
1384
1390
  }
1385
1391
  let initiator = "Anonymous";
1386
- if ("userId" in requesterDetails && requesterDetails.userId)
1387
- initiator = `User Id (${requesterDetails.userId.toString()})`;
1388
- if ("isSystemUser" in requesterDetails && requesterDetails.isSystemUser) initiator = "SYSTEM";
1392
+ if ("userId" in queryMetadata && queryMetadata.userId)
1393
+ initiator = `User Id (${queryMetadata.userId.toString()})`;
1394
+ if ("isSystemUser" in queryMetadata && queryMetadata.isSystemUser) initiator = "SYSTEM";
1389
1395
  logger.silly(`${prefix}query by ${initiator}, Query ->
1390
1396
  ${sqlStatement}`);
1391
1397
  }
@@ -1567,13 +1573,15 @@ var filterSqlGrammar = `
1567
1573
 
1568
1574
  start = expressionList
1569
1575
 
1576
+ _ = [ \\t\\r\\n]* // Matches spaces, tabs, and line breaks
1577
+
1570
1578
  expressionList =
1571
- leftExpression:expression operator:operator rightExpression:expressionList
1579
+ leftExpression:expression _ operator:operator _ rightExpression:expressionList
1572
1580
  { return \`\${leftExpression} \${operator} \${rightExpression}\`;}
1573
1581
  / expression
1574
1582
 
1575
1583
  expression =
1576
- negate:negate?"(" "column:" column:column ","? value:value? ","? type:type? ")"
1584
+ negate:negate? _ "(" _ "column" _ ":" column:column _ ","? _ value:value? ","? _ type:type? _ ")"_
1577
1585
  {return \`\${negate? " NOT " : ""}(\${type? type(column, value) : \`\${column} = \${format.literal(value)}\`})\`;}
1578
1586
  /
1579
1587
  negate:negate?"("expression:expressionList")" { return \`\${negate? " NOT " : ""}(\${expression})\`; }
@@ -1588,9 +1596,9 @@ column = left:text "." right:text { return \`\${quoteSqlIdentity(left)}.\${quot
1588
1596
  text:text { return quoteSqlIdentity(text); }
1589
1597
 
1590
1598
 
1591
- text = text:[a-z0-9-_:@]i+ { return text.join("");}
1599
+ text = text:[a-z0-9 \\t\\r\\n\\-_:@]i+ { return text.join(""); }
1592
1600
 
1593
- type = "type:" type:typeString { return type; }
1601
+ type = "type" _ ":" _ type:typeString { return type; }
1594
1602
  typeString = text:"startsWith" { return function(column, value) { return \`\${column} ILIKE '\${format.literal(value).slice(1,-1)}%'\`; } } /
1595
1603
  text:"endsWith" { return function(column, value) { return \`\${column} ILIKE '%\${format.literal(value).slice(1,-1)}'\`; } } /
1596
1604
  text:"contains" { return function(column, value) { return \`\${column} ILIKE '%\${format.literal(value).slice(1,-1)}%'\`; } } /
@@ -1600,8 +1608,9 @@ typeString = text:"startsWith" { return function(column, value) { return \`\${co
1600
1608
  text:"lessThanEqual" { return function(column, value) { return \`\${column} <= '\${format.literal(value).slice(1,-1)}'\`; } } /
1601
1609
  text:"lessThan" { return function(column, value) { return \`\${column} < '\${format.literal(value).slice(1,-1)}'\`; } } /
1602
1610
  text:"isNull" { return function(column, value) { return \`isNull(\${column})\`; } }
1603
-
1604
- value = "value:" value:text { return value; }
1611
+
1612
+ value = "value" _ ":" value:text { return value; }
1613
+
1605
1614
 
1606
1615
  `;
1607
1616
  var filterPsqlParser = import_pegjs.default.generate(filterSqlGrammar, {
@@ -1656,9 +1665,9 @@ var EventManager = class {
1656
1665
  tableName: triggerResult.table,
1657
1666
  insertId: triggerResult.record.id,
1658
1667
  insertObject: triggerResult.record,
1659
- requesterDetails: data.requesterDetails
1668
+ queryMetadata: data.queryMetadata
1660
1669
  };
1661
- callback(insertData, data.requesterDetails);
1670
+ callback(insertData, data.queryMetadata);
1662
1671
  },
1663
1672
  { concurrency: 10 }
1664
1673
  );
@@ -1671,9 +1680,9 @@ var EventManager = class {
1671
1680
  const deleteData = {
1672
1681
  tableName: triggerResult.table,
1673
1682
  deletedRow: triggerResult.previousRecord,
1674
- requesterDetails: data.requesterDetails
1683
+ queryMetadata: data.queryMetadata
1675
1684
  };
1676
- callback(deleteData, data.requesterDetails);
1685
+ callback(deleteData, data.queryMetadata);
1677
1686
  },
1678
1687
  { concurrency: 10 }
1679
1688
  );
@@ -1688,9 +1697,9 @@ var EventManager = class {
1688
1697
  rowId: triggerResult.record.id,
1689
1698
  newData: triggerResult.record,
1690
1699
  oldData: triggerResult.previousRecord,
1691
- requesterDetails: data.requesterDetails
1700
+ queryMetadata: data.queryMetadata
1692
1701
  };
1693
- callback(columnChangeData, data.requesterDetails);
1702
+ callback(columnChangeData, data.queryMetadata);
1694
1703
  },
1695
1704
  { concurrency: 10 }
1696
1705
  );
@@ -1705,6 +1714,13 @@ var EventManager = class {
1705
1714
  case "DATABASE_COLUMN_UPDATE":
1706
1715
  const filterColumnChange = filter;
1707
1716
  if (filterColumnChange.tableName !== filter.tableName) return false;
1717
+ if (!filterColumnChange.columns.some((item) => {
1718
+ const updatedColumns = Object.keys(
1719
+ changedValues(triggerResult.record, triggerResult.previousRecord)
1720
+ );
1721
+ return updatedColumns.includes(item);
1722
+ }))
1723
+ return false;
1708
1724
  break;
1709
1725
  }
1710
1726
  }
@@ -1713,6 +1729,22 @@ var EventManager = class {
1713
1729
  };
1714
1730
  var eventManager = new EventManager();
1715
1731
  var eventManager_default = eventManager;
1732
+ function changedValues(record, previousRecord) {
1733
+ const changed = {};
1734
+ for (const i in previousRecord) {
1735
+ if (previousRecord[i] !== record[i]) {
1736
+ if (typeof previousRecord[i] === "object" && typeof record[i] === "object") {
1737
+ const nestedChanged = changedValues(record[i], previousRecord[i]);
1738
+ if (Object.keys(nestedChanged).length > 0) {
1739
+ changed[i] = record[i];
1740
+ }
1741
+ } else {
1742
+ changed[i] = record[i];
1743
+ }
1744
+ }
1745
+ }
1746
+ return changed;
1747
+ }
1716
1748
 
1717
1749
  // src/restura/sql/PsqlEngine.ts
1718
1750
  var { Client } = import_pg2.default;
@@ -1759,12 +1791,15 @@ var PsqlEngine = class extends SqlEngine {
1759
1791
  }
1760
1792
  async handleTrigger(payload, mutationType) {
1761
1793
  const findRequesterDetailsRegex = /^--QUERY_METADATA\(\{.*\}\)/;
1762
- let requesterDetails = {};
1763
1794
  const match = payload.query.match(findRequesterDetailsRegex);
1764
1795
  if (match) {
1765
1796
  const jsonString = match[0].slice(match[0].indexOf("{"), match[0].lastIndexOf("}") + 1);
1766
- requesterDetails = import_core_utils5.ObjectUtils.safeParse(jsonString);
1767
- await eventManager_default.fireActionFromDbTrigger({ requesterDetails, mutationType }, payload);
1797
+ const queryMetadata = import_core_utils5.ObjectUtils.safeParse(jsonString);
1798
+ const triggerFromThisInstance = queryMetadata.connectionInstanceId === this.psqlConnectionPool.instanceId;
1799
+ if (!triggerFromThisInstance) {
1800
+ return;
1801
+ }
1802
+ await eventManager_default.fireActionFromDbTrigger({ queryMetadata, mutationType }, payload);
1768
1803
  }
1769
1804
  }
1770
1805
  async createDatabaseFromSchema(schema, connection) {
@@ -1774,7 +1809,6 @@ var PsqlEngine = class extends SqlEngine {
1774
1809
  }
1775
1810
  generateDatabaseSchemaFromSchema(schema) {
1776
1811
  const sqlStatements = [];
1777
- const enums = [];
1778
1812
  const indexes = [];
1779
1813
  const triggers = [];
1780
1814
  for (const table of schema.database) {
@@ -1786,10 +1820,7 @@ var PsqlEngine = class extends SqlEngine {
1786
1820
  const tableColumns = [];
1787
1821
  for (const column of table.columns) {
1788
1822
  let columnSql = "";
1789
- if (column.type === "ENUM") {
1790
- enums.push(`CREATE TYPE ${schemaToPsqlType(column, table.name)} AS ENUM (${column.value});`);
1791
- }
1792
- columnSql += ` "${column.name}" ${schemaToPsqlType(column, table.name)}`;
1823
+ columnSql += ` "${column.name}" ${schemaToPsqlType(column)}`;
1793
1824
  let value = column.value;
1794
1825
  if (column.type === "JSON") value = "";
1795
1826
  if (column.type === "JSONB") value = "";
@@ -1808,6 +1839,9 @@ var PsqlEngine = class extends SqlEngine {
1808
1839
  if (column.isNullable) columnSql += " NULL";
1809
1840
  else columnSql += " NOT NULL";
1810
1841
  if (column.default) columnSql += ` DEFAULT ${column.default}`;
1842
+ if (value && column.type === "ENUM") {
1843
+ columnSql += ` CHECK ("${column.name}" IN (${value}))`;
1844
+ }
1811
1845
  tableColumns.push(columnSql);
1812
1846
  }
1813
1847
  sql += tableColumns.join(", \n");
@@ -1850,16 +1884,18 @@ var PsqlEngine = class extends SqlEngine {
1850
1884
  }
1851
1885
  sqlStatements.push(indexes.join("\n"));
1852
1886
  sqlStatements.push(triggers.join("\n"));
1853
- return enums.join("\n") + "\n" + sqlStatements.join("\n\n");
1887
+ return sqlStatements.join("\n\n");
1854
1888
  }
1855
1889
  async getScratchPool() {
1856
- const response = await this.psqlConnectionPool.runQuery(
1857
- `SELECT * FROM pg_database
1858
- WHERE datname = '${this.psqlConnectionPool.poolConfig.database}_scratch'`,
1890
+ var _a2, _b;
1891
+ const scratchDbExists = await this.psqlConnectionPool.runQuery(
1892
+ `SELECT *
1893
+ FROM pg_database
1894
+ WHERE datname = '${this.psqlConnectionPool.poolConfig.database}_scratch';`,
1859
1895
  [],
1860
1896
  systemUser
1861
1897
  );
1862
- if (response.length === 0) {
1898
+ if (scratchDbExists.length === 0) {
1863
1899
  await this.psqlConnectionPool.runQuery(
1864
1900
  `CREATE DATABASE ${this.psqlConnectionPool.poolConfig.database}_scratch;`,
1865
1901
  [],
@@ -1876,12 +1912,27 @@ var PsqlEngine = class extends SqlEngine {
1876
1912
  idleTimeoutMillis: this.psqlConnectionPool.poolConfig.idleTimeoutMillis,
1877
1913
  connectionTimeoutMillis: this.psqlConnectionPool.poolConfig.connectionTimeoutMillis
1878
1914
  });
1879
- await scratchPool.runQuery(`drop schema public cascade;`, [], systemUser);
1915
+ await scratchPool.runQuery(`DROP SCHEMA public CASCADE;`, [], systemUser);
1880
1916
  await scratchPool.runQuery(
1881
- `create schema public authorization ${this.psqlConnectionPool.poolConfig.user};`,
1917
+ `CREATE SCHEMA public AUTHORIZATION ${this.psqlConnectionPool.poolConfig.user};`,
1918
+ [],
1919
+ systemUser
1920
+ );
1921
+ const schemaComment = await this.psqlConnectionPool.runQuery(
1922
+ `SELECT pg_description.description
1923
+ FROM pg_description
1924
+ JOIN pg_namespace ON pg_namespace.oid = pg_description.objoid
1925
+ WHERE pg_namespace.nspname = 'public';`,
1882
1926
  [],
1883
1927
  systemUser
1884
1928
  );
1929
+ if ((_a2 = schemaComment[0]) == null ? void 0 : _a2.description) {
1930
+ await scratchPool.runQuery(
1931
+ `COMMENT ON SCHEMA public IS '${(_b = schemaComment[0]) == null ? void 0 : _b.description}';`,
1932
+ [],
1933
+ systemUser
1934
+ );
1935
+ }
1885
1936
  return scratchPool;
1886
1937
  }
1887
1938
  async diffDatabaseToSchema(schema) {
@@ -2251,9 +2302,9 @@ __decorateClass([
2251
2302
  __decorateClass([
2252
2303
  boundMethod
2253
2304
  ], PsqlEngine.prototype, "createInsertTriggers", 1);
2254
- function schemaToPsqlType(column, tableName) {
2305
+ function schemaToPsqlType(column) {
2255
2306
  if (column.hasAutoIncrement) return "BIGSERIAL";
2256
- if (column.type === "ENUM") return `"${tableName}_${column.name}_enum"`;
2307
+ if (column.type === "ENUM") return `TEXT`;
2257
2308
  if (column.type === "DATETIME") return "TIMESTAMPTZ";
2258
2309
  if (column.type === "MEDIUMINT") return "INT";
2259
2310
  return column.type;
@@ -2727,7 +2778,7 @@ var ResturaEngine = class {
2727
2778
  printWidth: 120,
2728
2779
  singleQuote: true
2729
2780
  }));
2730
- return (0, import_crypto.createHash)("sha256").update(schemaPrettyStr).digest("hex");
2781
+ return (0, import_crypto2.createHash)("sha256").update(schemaPrettyStr).digest("hex");
2731
2782
  }
2732
2783
  async storeFileSystemSchema() {
2733
2784
  const schemaPrettyStr = await prettier3.format(JSON.stringify(this.schema), __spreadValues({
@@ -2796,7 +2847,7 @@ __decorateClass([
2796
2847
  __decorateClass([
2797
2848
  boundMethod
2798
2849
  ], ResturaEngine.prototype, "runCustomRouteLogic", 1);
2799
- var setupPgReturnTypes = () => {
2850
+ function setupPgReturnTypes() {
2800
2851
  const TIMESTAMPTZ_OID = 1184;
2801
2852
  types.setTypeParser(TIMESTAMPTZ_OID, (val) => {
2802
2853
  return val === null ? null : new Date(val).toISOString();
@@ -2805,7 +2856,7 @@ var setupPgReturnTypes = () => {
2805
2856
  types.setTypeParser(BIGINT_OID, (val) => {
2806
2857
  return val === null ? null : Number(val);
2807
2858
  });
2808
- };
2859
+ }
2809
2860
  setupPgReturnTypes();
2810
2861
  var restura = new ResturaEngine();
2811
2862