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

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
@@ -1,7 +1,7 @@
1
1
  import winston from 'winston';
2
2
  import * as express from 'express';
3
3
  import { z } from 'zod';
4
- import { PoolConfig, Pool } from 'pg';
4
+ import pg, { QueryResultRow, QueryConfigValues, QueryResult, PoolConfig, Pool, ClientConfig, Client } from 'pg';
5
5
  import { IncomingHttpHeaders } from 'http2';
6
6
 
7
7
  declare const logger: winston.Logger;
@@ -1391,15 +1391,33 @@ interface AsyncExpressApplication {
1391
1391
  delete: (url: string, handler: RsRouteHandler, nextFunction?: RsRouteHandler) => Promise<void> | void;
1392
1392
  }
1393
1393
 
1394
- declare class PsqlPool {
1395
- poolConfig: PoolConfig;
1396
- pool: Pool;
1397
- constructor(poolConfig: PoolConfig);
1394
+ declare abstract class PsqlConnection {
1395
+ constructor();
1396
+ protected abstract query<R extends QueryResultRow = any>(query: string, values?: QueryConfigValues<any>): Promise<QueryResult<R>>;
1398
1397
  queryOne(query: string, options: any[], requesterDetails: RequesterDetails): Promise<any>;
1399
1398
  runQuery(query: string, options: any[], requesterDetails: RequesterDetails): Promise<any[]>;
1400
1399
  private logSqlStatement;
1401
1400
  }
1402
1401
 
1402
+ declare class PsqlPool extends PsqlConnection {
1403
+ poolConfig: PoolConfig;
1404
+ pool: Pool;
1405
+ constructor(poolConfig: PoolConfig);
1406
+ protected query<R extends QueryResultRow = any>(query: string, values?: QueryConfigValues<any>): Promise<QueryResult<R>>;
1407
+ }
1408
+
1409
+ declare class PsqlTransaction extends PsqlConnection {
1410
+ clientConfig: ClientConfig;
1411
+ client: Client;
1412
+ private beginTransactionPromise;
1413
+ constructor(clientConfig: ClientConfig);
1414
+ private beginTransaction;
1415
+ rollback(): Promise<pg.QueryResult<any>>;
1416
+ commit(): Promise<pg.QueryResult<any>>;
1417
+ release(): Promise<void>;
1418
+ protected query<R extends QueryResultRow = any>(query: string, values?: QueryConfigValues<any>): Promise<QueryResult<R>>;
1419
+ }
1420
+
1403
1421
  declare class ResturaEngine {
1404
1422
  resturaConfig: ResturaConfigSchema;
1405
1423
  private resturaRouter;
@@ -1498,4 +1516,4 @@ declare function updateObjectQuery(table: string, obj: DynamicObject, whereState
1498
1516
  declare function isValueNumber(value: unknown): value is number;
1499
1517
  declare function SQL(strings: any, ...values: any): any;
1500
1518
 
1501
- export { type ApiMethod, type AsyncExpressApplication, type AuthenticateHandler, type AuthenticationUserDetails, type ConjunctionTypes, type DynamicObject, type ErrorCode, HtmlStatusCodes, type LoginDetails, type MatchTypes, type PageQuery, PsqlPool, 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 StandardOrderTypes, type ValidAuthenticationCallback, type ValidatorString, escapeColumnName, insertObjectQuery, isValueNumber, logger, questionMarksToOrderedParams, restura, updateObjectQuery };
1519
+ export { type ApiMethod, type AsyncExpressApplication, type AuthenticateHandler, type AuthenticationUserDetails, type ConjunctionTypes, type DynamicObject, type ErrorCode, HtmlStatusCodes, type LoginDetails, type MatchTypes, type PageQuery, PsqlConnection, 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 StandardOrderTypes, type ValidAuthenticationCallback, type ValidatorString, escapeColumnName, insertObjectQuery, isValueNumber, logger, questionMarksToOrderedParams, restura, updateObjectQuery };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import winston from 'winston';
2
2
  import * as express from 'express';
3
3
  import { z } from 'zod';
4
- import { PoolConfig, Pool } from 'pg';
4
+ import pg, { QueryResultRow, QueryConfigValues, QueryResult, PoolConfig, Pool, ClientConfig, Client } from 'pg';
5
5
  import { IncomingHttpHeaders } from 'http2';
6
6
 
7
7
  declare const logger: winston.Logger;
@@ -1391,15 +1391,33 @@ interface AsyncExpressApplication {
1391
1391
  delete: (url: string, handler: RsRouteHandler, nextFunction?: RsRouteHandler) => Promise<void> | void;
1392
1392
  }
1393
1393
 
1394
- declare class PsqlPool {
1395
- poolConfig: PoolConfig;
1396
- pool: Pool;
1397
- constructor(poolConfig: PoolConfig);
1394
+ declare abstract class PsqlConnection {
1395
+ constructor();
1396
+ protected abstract query<R extends QueryResultRow = any>(query: string, values?: QueryConfigValues<any>): Promise<QueryResult<R>>;
1398
1397
  queryOne(query: string, options: any[], requesterDetails: RequesterDetails): Promise<any>;
1399
1398
  runQuery(query: string, options: any[], requesterDetails: RequesterDetails): Promise<any[]>;
1400
1399
  private logSqlStatement;
1401
1400
  }
1402
1401
 
1402
+ declare class PsqlPool extends PsqlConnection {
1403
+ poolConfig: PoolConfig;
1404
+ pool: Pool;
1405
+ constructor(poolConfig: PoolConfig);
1406
+ protected query<R extends QueryResultRow = any>(query: string, values?: QueryConfigValues<any>): Promise<QueryResult<R>>;
1407
+ }
1408
+
1409
+ declare class PsqlTransaction extends PsqlConnection {
1410
+ clientConfig: ClientConfig;
1411
+ client: Client;
1412
+ private beginTransactionPromise;
1413
+ constructor(clientConfig: ClientConfig);
1414
+ private beginTransaction;
1415
+ rollback(): Promise<pg.QueryResult<any>>;
1416
+ commit(): Promise<pg.QueryResult<any>>;
1417
+ release(): Promise<void>;
1418
+ protected query<R extends QueryResultRow = any>(query: string, values?: QueryConfigValues<any>): Promise<QueryResult<R>>;
1419
+ }
1420
+
1403
1421
  declare class ResturaEngine {
1404
1422
  resturaConfig: ResturaConfigSchema;
1405
1423
  private resturaRouter;
@@ -1498,4 +1516,4 @@ declare function updateObjectQuery(table: string, obj: DynamicObject, whereState
1498
1516
  declare function isValueNumber(value: unknown): value is number;
1499
1517
  declare function SQL(strings: any, ...values: any): any;
1500
1518
 
1501
- export { type ApiMethod, type AsyncExpressApplication, type AuthenticateHandler, type AuthenticationUserDetails, type ConjunctionTypes, type DynamicObject, type ErrorCode, HtmlStatusCodes, type LoginDetails, type MatchTypes, type PageQuery, PsqlPool, 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 StandardOrderTypes, type ValidAuthenticationCallback, type ValidatorString, escapeColumnName, insertObjectQuery, isValueNumber, logger, questionMarksToOrderedParams, restura, updateObjectQuery };
1519
+ export { type ApiMethod, type AsyncExpressApplication, type AuthenticateHandler, type AuthenticationUserDetails, type ConjunctionTypes, type DynamicObject, type ErrorCode, HtmlStatusCodes, type LoginDetails, type MatchTypes, type PageQuery, PsqlConnection, 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 StandardOrderTypes, type ValidAuthenticationCallback, type ValidatorString, escapeColumnName, insertObjectQuery, isValueNumber, logger, questionMarksToOrderedParams, restura, updateObjectQuery };
package/dist/index.js CHANGED
@@ -68,7 +68,9 @@ var __decorateClass = (decorators, target, key, kind) => {
68
68
  var src_exports = {};
69
69
  __export(src_exports, {
70
70
  HtmlStatusCodes: () => HtmlStatusCodes,
71
+ PsqlConnection: () => PsqlConnection,
71
72
  PsqlPool: () => PsqlPool,
73
+ PsqlTransaction: () => PsqlTransaction,
72
74
  RsError: () => RsError,
73
75
  SQL: () => SQL,
74
76
  escapeColumnName: () => escapeColumnName,
@@ -258,7 +260,7 @@ var import_crypto = require("crypto");
258
260
  var express = __toESM(require("express"));
259
261
  var import_fs3 = __toESM(require("fs"));
260
262
  var import_path3 = __toESM(require("path"));
261
- var import_pg2 = __toESM(require("pg"));
263
+ var import_pg3 = __toESM(require("pg"));
262
264
  var prettier3 = __toESM(require("prettier"));
263
265
 
264
266
  // src/restura/sql/SqlUtils.ts
@@ -1248,7 +1250,6 @@ var import_core_utils5 = require("@redskytech/core-utils");
1248
1250
 
1249
1251
  // src/restura/sql/PsqlPool.ts
1250
1252
  var import_pg = __toESM(require("pg"));
1251
- var import_pg_format2 = __toESM(require("pg-format"));
1252
1253
 
1253
1254
  // src/restura/sql/PsqlUtils.ts
1254
1255
  var import_pg_format = __toESM(require("pg-format"));
@@ -1297,25 +1298,17 @@ function SQL(strings, ...values) {
1297
1298
  return query;
1298
1299
  }
1299
1300
 
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
- });
1301
+ // src/restura/sql/PsqlConnection.ts
1302
+ var import_pg_format2 = __toESM(require("pg-format"));
1303
+ var PsqlConnection = class {
1304
+ constructor() {
1312
1305
  }
1313
1306
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1314
1307
  async queryOne(query, options, requesterDetails) {
1315
1308
  const formattedQuery = questionMarksToOrderedParams(query);
1316
1309
  this.logSqlStatement(formattedQuery, options, requesterDetails);
1317
1310
  try {
1318
- const response = await this.pool.query(formattedQuery, options);
1311
+ const response = await this.query(formattedQuery, options);
1319
1312
  if (response.rows.length === 0) throw new RsError("NOT_FOUND", "No results found");
1320
1313
  else if (response.rows.length > 1) throw new RsError("DUPLICATE", "More than one result found");
1321
1314
  return response.rows[0];
@@ -1332,10 +1325,8 @@ var PsqlPool = class {
1332
1325
  async runQuery(query, options, requesterDetails) {
1333
1326
  const formattedQuery = questionMarksToOrderedParams(query);
1334
1327
  this.logSqlStatement(formattedQuery, options, requesterDetails);
1335
- const queryUpdated = query.replace(/[\t\n]/g, " ");
1336
- console.log(queryUpdated, options);
1337
1328
  try {
1338
- const response = await this.pool.query(formattedQuery, options);
1329
+ const response = await this.query(formattedQuery, options);
1339
1330
  return response.rows;
1340
1331
  } catch (error) {
1341
1332
  console.error(error, query, options);
@@ -1367,6 +1358,25 @@ var PsqlPool = class {
1367
1358
  }
1368
1359
  };
1369
1360
 
1361
+ // src/restura/sql/PsqlPool.ts
1362
+ var { Pool } = import_pg.default;
1363
+ var PsqlPool = class extends PsqlConnection {
1364
+ constructor(poolConfig) {
1365
+ super();
1366
+ this.poolConfig = poolConfig;
1367
+ this.pool = new Pool(poolConfig);
1368
+ this.queryOne("SELECT NOW();", [], { isSystemUser: true, role: "", host: "localhost", ipAddress: "" }).then(() => {
1369
+ logger.info("Connected to PostgreSQL database");
1370
+ }).catch((error) => {
1371
+ logger.error("Error connecting to database", error);
1372
+ process.exit(1);
1373
+ });
1374
+ }
1375
+ async query(query, values) {
1376
+ return this.pool.query(query, values);
1377
+ }
1378
+ };
1379
+
1370
1380
  // src/restura/sql/SqlEngine.ts
1371
1381
  var import_core_utils4 = require("@redskytech/core-utils");
1372
1382
  var SqlEngine = class {
@@ -1531,9 +1541,9 @@ expressionList =
1531
1541
 
1532
1542
  expression =
1533
1543
  negate:negate?"(" "column:" column:column ","? value:value? ","? type:type? ")"
1534
- {return \`\${negate? "!" : ""}(\${type? type(column, value) : \`\${column} = \${format.literal(value)}\`})\`;}
1544
+ {return \`\${negate? " NOT " : ""}(\${type? type(column, value) : \`\${column} = \${format.literal(value)}\`})\`;}
1535
1545
  /
1536
- negate:negate?"("expression:expressionList")" { return \`\${negate? "!" : ""}(\${expression})\`; }
1546
+ negate:negate?"("expression:expressionList")" { return \`\${negate? " NOT " : ""}(\${expression})\`; }
1537
1547
 
1538
1548
  negate = "!"
1539
1549
 
@@ -1713,7 +1723,6 @@ var PsqlEngine = class extends SqlEngine {
1713
1723
  schema: "public"
1714
1724
  });
1715
1725
  const diff = (0, import_pg_diff_sync.default)(info1, info2);
1716
- console.log("Schema differences:", diff);
1717
1726
  await originalClient.end();
1718
1727
  await scratchClient.end();
1719
1728
  return diff.join("\n");
@@ -1998,8 +2007,127 @@ var schemaToPsqlType = (column, tableName) => {
1998
2007
  return column.type;
1999
2008
  };
2000
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
+ };
2038
+
2039
+ // src/restura/compareSchema.ts
2040
+ var import_lodash = __toESM(require("lodash.clonedeep"));
2041
+ var CompareSchema = class {
2042
+ 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);
2046
+ let commands = "";
2047
+ if (JSON.stringify(newSchema.database) !== JSON.stringify(latestSchema.database))
2048
+ commands = await psqlEngine.diffDatabaseToSchema(newSchema);
2049
+ let customTypes = newSchema.customTypes !== latestSchema.customTypes;
2050
+ const schemaPreview = { endPoints, globalParams, roles, commands, customTypes };
2051
+ return schemaPreview;
2052
+ }
2053
+ diffStringArray(newArray, originalArray) {
2054
+ let stringsDiff = [];
2055
+ let originalClone = new Set(originalArray);
2056
+ newArray.forEach((item) => {
2057
+ let originalIndex = originalClone.has(item);
2058
+ if (!originalIndex) {
2059
+ stringsDiff.push({
2060
+ name: item,
2061
+ changeType: "NEW"
2062
+ });
2063
+ } else {
2064
+ originalClone.delete(item);
2065
+ }
2066
+ });
2067
+ originalClone.forEach((item) => {
2068
+ stringsDiff.push({
2069
+ name: item,
2070
+ changeType: "DELETED"
2071
+ });
2072
+ });
2073
+ return stringsDiff;
2074
+ }
2075
+ diffEndPoints(newEndPoints, originalEndpoints) {
2076
+ let originalClone = (0, import_lodash.default)(originalEndpoints);
2077
+ let diffObj = [];
2078
+ newEndPoints.forEach((endPoint) => {
2079
+ let { path: path4, method } = endPoint;
2080
+ let endPointIndex = originalClone.findIndex((original) => {
2081
+ return original.path === endPoint.path && original.method === endPoint.method;
2082
+ });
2083
+ if (endPointIndex === -1) {
2084
+ diffObj.push({
2085
+ name: `${method} ${path4}`,
2086
+ changeType: "NEW"
2087
+ });
2088
+ } else {
2089
+ let original = originalClone.findIndex((original2) => {
2090
+ return this.compareEndPoints(endPoint, original2);
2091
+ });
2092
+ if (original === -1) {
2093
+ diffObj.push({
2094
+ name: `${method} ${path4}`,
2095
+ changeType: "MODIFIED"
2096
+ });
2097
+ }
2098
+ originalClone.splice(endPointIndex, 1);
2099
+ }
2100
+ });
2101
+ originalClone.forEach((original) => {
2102
+ let { path: path4, method } = original;
2103
+ diffObj.push({
2104
+ name: `${method} ${path4}`,
2105
+ changeType: "DELETED"
2106
+ });
2107
+ });
2108
+ return diffObj;
2109
+ }
2110
+ compareEndPoints(endPoint1, endPoint2) {
2111
+ return JSON.stringify(endPoint1) === JSON.stringify(endPoint2);
2112
+ }
2113
+ };
2114
+ __decorateClass([
2115
+ boundMethod
2116
+ ], CompareSchema.prototype, "diffSchema", 1);
2117
+ __decorateClass([
2118
+ boundMethod
2119
+ ], CompareSchema.prototype, "diffStringArray", 1);
2120
+ __decorateClass([
2121
+ boundMethod
2122
+ ], CompareSchema.prototype, "diffEndPoints", 1);
2123
+ __decorateClass([
2124
+ boundMethod
2125
+ ], CompareSchema.prototype, "compareEndPoints", 1);
2126
+ var compareSchema = new CompareSchema();
2127
+ var compareSchema_default = compareSchema;
2128
+
2001
2129
  // src/restura/restura.ts
2002
- var { types } = import_pg2.default;
2130
+ var { types } = import_pg3.default;
2003
2131
  var ResturaEngine = class {
2004
2132
  constructor() {
2005
2133
  this.publicEndpoints = {
@@ -2203,7 +2331,7 @@ var ResturaEngine = class {
2203
2331
  }
2204
2332
  async previewCreateSchema(req, res) {
2205
2333
  try {
2206
- const schemaDiff = { commands: "", endPoints: [], globalParams: [], roles: [], customTypes: false };
2334
+ const schemaDiff = await compareSchema_default.diffSchema(req.data, this.schema, this.psqlEngine);
2207
2335
  res.send({ data: schemaDiff });
2208
2336
  } catch (err) {
2209
2337
  res.status(400).send(err);
@@ -2377,7 +2505,9 @@ var restura = new ResturaEngine();
2377
2505
  // Annotate the CommonJS export names for ESM import in node:
2378
2506
  0 && (module.exports = {
2379
2507
  HtmlStatusCodes,
2508
+ PsqlConnection,
2380
2509
  PsqlPool,
2510
+ PsqlTransaction,
2381
2511
  RsError,
2382
2512
  SQL,
2383
2513
  escapeColumnName,