pgterra 0.2.11 → 0.2.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.
Files changed (2) hide show
  1. package/dist/index.js +411 -493
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -17322,19 +17322,19 @@ var require_utils = __commonJS((exports, module) => {
17322
17322
  ret += " BC";
17323
17323
  return ret;
17324
17324
  }
17325
- function normalizeQueryConfig(config, values, callback) {
17326
- config = typeof config === "string" ? { text: config } : config;
17325
+ function normalizeQueryConfig(config6, values, callback) {
17326
+ config6 = typeof config6 === "string" ? { text: config6 } : config6;
17327
17327
  if (values) {
17328
17328
  if (typeof values === "function") {
17329
- config.callback = values;
17329
+ config6.callback = values;
17330
17330
  } else {
17331
- config.values = values;
17331
+ config6.values = values;
17332
17332
  }
17333
17333
  }
17334
17334
  if (callback) {
17335
- config.callback = callback;
17335
+ config6.callback = callback;
17336
17336
  }
17337
- return config;
17337
+ return config6;
17338
17338
  }
17339
17339
  var escapeIdentifier = function(str) {
17340
17340
  return '"' + str.replace(/"/g, '""') + '"';
@@ -17775,10 +17775,10 @@ var require_type_overrides = __commonJS((exports, module) => {
17775
17775
  var require_pg_connection_string = __commonJS((exports, module) => {
17776
17776
  function parse2(str, options = {}) {
17777
17777
  if (str.charAt(0) === "/") {
17778
- const config2 = str.split(" ");
17779
- return { host: config2[0], database: config2[1] };
17778
+ const config7 = str.split(" ");
17779
+ return { host: config7[0], database: config7[1] };
17780
17780
  }
17781
- const config = {};
17781
+ const config6 = {};
17782
17782
  let result;
17783
17783
  let dummyHost = false;
17784
17784
  if (/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) {
@@ -17791,72 +17791,72 @@ var require_pg_connection_string = __commonJS((exports, module) => {
17791
17791
  dummyHost = true;
17792
17792
  }
17793
17793
  for (const entry of result.searchParams.entries()) {
17794
- config[entry[0]] = entry[1];
17794
+ config6[entry[0]] = entry[1];
17795
17795
  }
17796
- config.user = config.user || decodeURIComponent(result.username);
17797
- config.password = config.password || decodeURIComponent(result.password);
17796
+ config6.user = config6.user || decodeURIComponent(result.username);
17797
+ config6.password = config6.password || decodeURIComponent(result.password);
17798
17798
  if (result.protocol == "socket:") {
17799
- config.host = decodeURI(result.pathname);
17800
- config.database = result.searchParams.get("db");
17801
- config.client_encoding = result.searchParams.get("encoding");
17802
- return config;
17799
+ config6.host = decodeURI(result.pathname);
17800
+ config6.database = result.searchParams.get("db");
17801
+ config6.client_encoding = result.searchParams.get("encoding");
17802
+ return config6;
17803
17803
  }
17804
17804
  const hostname = dummyHost ? "" : result.hostname;
17805
- if (!config.host) {
17806
- config.host = decodeURIComponent(hostname);
17805
+ if (!config6.host) {
17806
+ config6.host = decodeURIComponent(hostname);
17807
17807
  } else if (hostname && /^%2f/i.test(hostname)) {
17808
17808
  result.pathname = hostname + result.pathname;
17809
17809
  }
17810
- if (!config.port) {
17811
- config.port = result.port;
17810
+ if (!config6.port) {
17811
+ config6.port = result.port;
17812
17812
  }
17813
17813
  const pathname = result.pathname.slice(1) || null;
17814
- config.database = pathname ? decodeURI(pathname) : null;
17815
- if (config.ssl === "true" || config.ssl === "1") {
17816
- config.ssl = true;
17814
+ config6.database = pathname ? decodeURI(pathname) : null;
17815
+ if (config6.ssl === "true" || config6.ssl === "1") {
17816
+ config6.ssl = true;
17817
17817
  }
17818
- if (config.ssl === "0") {
17819
- config.ssl = false;
17818
+ if (config6.ssl === "0") {
17819
+ config6.ssl = false;
17820
17820
  }
17821
- if (config.sslcert || config.sslkey || config.sslrootcert || config.sslmode) {
17822
- config.ssl = {};
17821
+ if (config6.sslcert || config6.sslkey || config6.sslrootcert || config6.sslmode) {
17822
+ config6.ssl = {};
17823
17823
  }
17824
- const fs = config.sslcert || config.sslkey || config.sslrootcert ? __require("fs") : null;
17825
- if (config.sslcert) {
17826
- config.ssl.cert = fs.readFileSync(config.sslcert).toString();
17824
+ const fs = config6.sslcert || config6.sslkey || config6.sslrootcert ? __require("fs") : null;
17825
+ if (config6.sslcert) {
17826
+ config6.ssl.cert = fs.readFileSync(config6.sslcert).toString();
17827
17827
  }
17828
- if (config.sslkey) {
17829
- config.ssl.key = fs.readFileSync(config.sslkey).toString();
17828
+ if (config6.sslkey) {
17829
+ config6.ssl.key = fs.readFileSync(config6.sslkey).toString();
17830
17830
  }
17831
- if (config.sslrootcert) {
17832
- config.ssl.ca = fs.readFileSync(config.sslrootcert).toString();
17831
+ if (config6.sslrootcert) {
17832
+ config6.ssl.ca = fs.readFileSync(config6.sslrootcert).toString();
17833
17833
  }
17834
- if (options.useLibpqCompat && config.uselibpqcompat) {
17834
+ if (options.useLibpqCompat && config6.uselibpqcompat) {
17835
17835
  throw new Error("Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.");
17836
17836
  }
17837
- if (config.uselibpqcompat === "true" || options.useLibpqCompat) {
17838
- switch (config.sslmode) {
17837
+ if (config6.uselibpqcompat === "true" || options.useLibpqCompat) {
17838
+ switch (config6.sslmode) {
17839
17839
  case "disable": {
17840
- config.ssl = false;
17840
+ config6.ssl = false;
17841
17841
  break;
17842
17842
  }
17843
17843
  case "prefer": {
17844
- config.ssl.rejectUnauthorized = false;
17844
+ config6.ssl.rejectUnauthorized = false;
17845
17845
  break;
17846
17846
  }
17847
17847
  case "require": {
17848
- if (config.sslrootcert) {
17849
- config.ssl.checkServerIdentity = function() {};
17848
+ if (config6.sslrootcert) {
17849
+ config6.ssl.checkServerIdentity = function() {};
17850
17850
  } else {
17851
- config.ssl.rejectUnauthorized = false;
17851
+ config6.ssl.rejectUnauthorized = false;
17852
17852
  }
17853
17853
  break;
17854
17854
  }
17855
17855
  case "verify-ca": {
17856
- if (!config.ssl.ca) {
17856
+ if (!config6.ssl.ca) {
17857
17857
  throw new Error("SECURITY WARNING: Using sslmode=verify-ca requires specifying a CA with sslrootcert. If a public CA is used, verify-ca allows connections to a server that somebody else may have registered with the CA, making you vulnerable to Man-in-the-Middle attacks. Either specify a custom CA certificate with sslrootcert parameter or use sslmode=verify-full for proper security.");
17858
17858
  }
17859
- config.ssl.checkServerIdentity = function() {};
17859
+ config6.ssl.checkServerIdentity = function() {};
17860
17860
  break;
17861
17861
  }
17862
17862
  case "verify-full": {
@@ -17864,9 +17864,9 @@ var require_pg_connection_string = __commonJS((exports, module) => {
17864
17864
  }
17865
17865
  }
17866
17866
  } else {
17867
- switch (config.sslmode) {
17867
+ switch (config6.sslmode) {
17868
17868
  case "disable": {
17869
- config.ssl = false;
17869
+ config6.ssl = false;
17870
17870
  break;
17871
17871
  }
17872
17872
  case "prefer":
@@ -17876,12 +17876,12 @@ var require_pg_connection_string = __commonJS((exports, module) => {
17876
17876
  break;
17877
17877
  }
17878
17878
  case "no-verify": {
17879
- config.ssl.rejectUnauthorized = false;
17879
+ config6.ssl.rejectUnauthorized = false;
17880
17880
  break;
17881
17881
  }
17882
17882
  }
17883
17883
  }
17884
- return config;
17884
+ return config6;
17885
17885
  }
17886
17886
  function toConnectionOptions(sslConfig) {
17887
17887
  const connectionOptions = Object.entries(sslConfig).reduce((c, [key, value]) => {
@@ -17892,8 +17892,8 @@ var require_pg_connection_string = __commonJS((exports, module) => {
17892
17892
  }, {});
17893
17893
  return connectionOptions;
17894
17894
  }
17895
- function toClientConfig(config) {
17896
- const poolConfig = Object.entries(config).reduce((c, [key, value]) => {
17895
+ function toClientConfig(config6) {
17896
+ const poolConfig = Object.entries(config6).reduce((c, [key, value]) => {
17897
17897
  if (key === "ssl") {
17898
17898
  const sslConfig = value;
17899
17899
  if (typeof sslConfig === "boolean") {
@@ -17933,13 +17933,13 @@ var require_connection_parameters = __commonJS((exports, module) => {
17933
17933
  var dns = __require("dns");
17934
17934
  var defaults = require_defaults();
17935
17935
  var parse2 = require_pg_connection_string().parse;
17936
- var val = function(key, config, envVar) {
17936
+ var val = function(key, config6, envVar) {
17937
17937
  if (envVar === undefined) {
17938
17938
  envVar = process.env["PG" + key.toUpperCase()];
17939
17939
  } else if (envVar === false) {} else {
17940
17940
  envVar = process.env[envVar];
17941
17941
  }
17942
- return config[key] || envVar || defaults[key];
17942
+ return config6[key] || envVar || defaults[key];
17943
17943
  };
17944
17944
  var readSSLConfigFromEnvironment = function() {
17945
17945
  switch (process.env.PGSSLMODE) {
@@ -17958,35 +17958,35 @@ var require_connection_parameters = __commonJS((exports, module) => {
17958
17958
  var quoteParamValue = function(value) {
17959
17959
  return "'" + ("" + value).replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'";
17960
17960
  };
17961
- var add = function(params, config, paramName) {
17962
- const value = config[paramName];
17961
+ var add = function(params, config6, paramName) {
17962
+ const value = config6[paramName];
17963
17963
  if (value !== undefined && value !== null) {
17964
17964
  params.push(paramName + "=" + quoteParamValue(value));
17965
17965
  }
17966
17966
  };
17967
17967
 
17968
17968
  class ConnectionParameters {
17969
- constructor(config) {
17970
- config = typeof config === "string" ? parse2(config) : config || {};
17971
- if (config.connectionString) {
17972
- config = Object.assign({}, config, parse2(config.connectionString));
17969
+ constructor(config6) {
17970
+ config6 = typeof config6 === "string" ? parse2(config6) : config6 || {};
17971
+ if (config6.connectionString) {
17972
+ config6 = Object.assign({}, config6, parse2(config6.connectionString));
17973
17973
  }
17974
- this.user = val("user", config);
17975
- this.database = val("database", config);
17974
+ this.user = val("user", config6);
17975
+ this.database = val("database", config6);
17976
17976
  if (this.database === undefined) {
17977
17977
  this.database = this.user;
17978
17978
  }
17979
- this.port = parseInt(val("port", config), 10);
17980
- this.host = val("host", config);
17979
+ this.port = parseInt(val("port", config6), 10);
17980
+ this.host = val("host", config6);
17981
17981
  Object.defineProperty(this, "password", {
17982
17982
  configurable: true,
17983
17983
  enumerable: false,
17984
17984
  writable: true,
17985
- value: val("password", config)
17985
+ value: val("password", config6)
17986
17986
  });
17987
- this.binary = val("binary", config);
17988
- this.options = val("options", config);
17989
- this.ssl = typeof config.ssl === "undefined" ? readSSLConfigFromEnvironment() : config.ssl;
17987
+ this.binary = val("binary", config6);
17988
+ this.options = val("options", config6);
17989
+ this.ssl = typeof config6.ssl === "undefined" ? readSSLConfigFromEnvironment() : config6.ssl;
17990
17990
  if (typeof this.ssl === "string") {
17991
17991
  if (this.ssl === "true") {
17992
17992
  this.ssl = true;
@@ -18000,27 +18000,27 @@ var require_connection_parameters = __commonJS((exports, module) => {
18000
18000
  enumerable: false
18001
18001
  });
18002
18002
  }
18003
- this.client_encoding = val("client_encoding", config);
18004
- this.replication = val("replication", config);
18003
+ this.client_encoding = val("client_encoding", config6);
18004
+ this.replication = val("replication", config6);
18005
18005
  this.isDomainSocket = !(this.host || "").indexOf("/");
18006
- this.application_name = val("application_name", config, "PGAPPNAME");
18007
- this.fallback_application_name = val("fallback_application_name", config, false);
18008
- this.statement_timeout = val("statement_timeout", config, false);
18009
- this.lock_timeout = val("lock_timeout", config, false);
18010
- this.idle_in_transaction_session_timeout = val("idle_in_transaction_session_timeout", config, false);
18011
- this.query_timeout = val("query_timeout", config, false);
18012
- if (config.connectionTimeoutMillis === undefined) {
18006
+ this.application_name = val("application_name", config6, "PGAPPNAME");
18007
+ this.fallback_application_name = val("fallback_application_name", config6, false);
18008
+ this.statement_timeout = val("statement_timeout", config6, false);
18009
+ this.lock_timeout = val("lock_timeout", config6, false);
18010
+ this.idle_in_transaction_session_timeout = val("idle_in_transaction_session_timeout", config6, false);
18011
+ this.query_timeout = val("query_timeout", config6, false);
18012
+ if (config6.connectionTimeoutMillis === undefined) {
18013
18013
  this.connect_timeout = process.env.PGCONNECT_TIMEOUT || 0;
18014
18014
  } else {
18015
- this.connect_timeout = Math.floor(config.connectionTimeoutMillis / 1000);
18015
+ this.connect_timeout = Math.floor(config6.connectionTimeoutMillis / 1000);
18016
18016
  }
18017
- if (config.keepAlive === false) {
18017
+ if (config6.keepAlive === false) {
18018
18018
  this.keepalives = 0;
18019
- } else if (config.keepAlive === true) {
18019
+ } else if (config6.keepAlive === true) {
18020
18020
  this.keepalives = 1;
18021
18021
  }
18022
- if (typeof config.keepAliveInitialDelayMillis === "number") {
18023
- this.keepalives_idle = Math.floor(config.keepAliveInitialDelayMillis / 1000);
18022
+ if (typeof config6.keepAliveInitialDelayMillis === "number") {
18023
+ this.keepalives_idle = Math.floor(config6.keepAliveInitialDelayMillis / 1000);
18024
18024
  }
18025
18025
  }
18026
18026
  getLibpqConnectionString(cb) {
@@ -18158,21 +18158,21 @@ var require_query = __commonJS((exports, module) => {
18158
18158
  var utils = require_utils();
18159
18159
 
18160
18160
  class Query extends EventEmitter {
18161
- constructor(config, values, callback) {
18161
+ constructor(config6, values, callback) {
18162
18162
  super();
18163
- config = utils.normalizeQueryConfig(config, values, callback);
18164
- this.text = config.text;
18165
- this.values = config.values;
18166
- this.rows = config.rows;
18167
- this.types = config.types;
18168
- this.name = config.name;
18169
- this.queryMode = config.queryMode;
18170
- this.binary = config.binary;
18171
- this.portal = config.portal || "";
18172
- this.callback = config.callback;
18173
- this._rowMode = config.rowMode;
18174
- if (process.domain && config.callback) {
18175
- this.callback = process.domain.bind(config.callback);
18163
+ config6 = utils.normalizeQueryConfig(config6, values, callback);
18164
+ this.text = config6.text;
18165
+ this.values = config6.values;
18166
+ this.rows = config6.rows;
18167
+ this.types = config6.types;
18168
+ this.name = config6.name;
18169
+ this.queryMode = config6.queryMode;
18170
+ this.binary = config6.binary;
18171
+ this.portal = config6.portal || "";
18172
+ this.callback = config6.callback;
18173
+ this._rowMode = config6.rowMode;
18174
+ if (process.domain && config6.callback) {
18175
+ this.callback = process.domain.bind(config6.callback);
18176
18176
  }
18177
18177
  this._result = new Result(this._rowMode, this.types);
18178
18178
  this._results = this._result;
@@ -18661,27 +18661,27 @@ var require_serializer = __commonJS((exports) => {
18661
18661
  }
18662
18662
  }
18663
18663
  };
18664
- var bind = (config = {}) => {
18665
- const portal = config.portal || "";
18666
- const statement = config.statement || "";
18667
- const binary = config.binary || false;
18668
- const values = config.values || emptyArray;
18664
+ var bind = (config6 = {}) => {
18665
+ const portal = config6.portal || "";
18666
+ const statement = config6.statement || "";
18667
+ const binary = config6.binary || false;
18668
+ const values = config6.values || emptyArray;
18669
18669
  const len = values.length;
18670
18670
  writer.addCString(portal).addCString(statement);
18671
18671
  writer.addInt16(len);
18672
- writeValues(values, config.valueMapper);
18672
+ writeValues(values, config6.valueMapper);
18673
18673
  writer.addInt16(len);
18674
18674
  writer.add(paramWriter.flush());
18675
18675
  writer.addInt16(binary ? 1 : 0);
18676
18676
  return writer.flush(66);
18677
18677
  };
18678
18678
  var emptyExecute = Buffer.from([69, 0, 0, 0, 9, 0, 0, 0, 0, 0]);
18679
- var execute = (config) => {
18680
- if (!config || !config.portal && !config.rows) {
18679
+ var execute = (config6) => {
18680
+ if (!config6 || !config6.portal && !config6.rows) {
18681
18681
  return emptyExecute;
18682
18682
  }
18683
- const portal = config.portal || "";
18684
- const rows = config.rows || 0;
18683
+ const portal = config6.portal || "";
18684
+ const rows = config6.rows || 0;
18685
18685
  const portalLength = Buffer.byteLength(portal);
18686
18686
  const len = 4 + portalLength + 1 + 4;
18687
18687
  const buff = Buffer.allocUnsafe(1 + len);
@@ -19337,18 +19337,18 @@ var require_connection = __commonJS((exports, module) => {
19337
19337
  var endBuffer = serialize.end();
19338
19338
 
19339
19339
  class Connection extends EventEmitter {
19340
- constructor(config) {
19340
+ constructor(config6) {
19341
19341
  super();
19342
- config = config || {};
19343
- this.stream = config.stream || getStream(config.ssl);
19342
+ config6 = config6 || {};
19343
+ this.stream = config6.stream || getStream(config6.ssl);
19344
19344
  if (typeof this.stream === "function") {
19345
- this.stream = this.stream(config);
19345
+ this.stream = this.stream(config6);
19346
19346
  }
19347
- this._keepAlive = config.keepAlive;
19348
- this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis;
19347
+ this._keepAlive = config6.keepAlive;
19348
+ this._keepAliveInitialDelayMillis = config6.keepAliveInitialDelayMillis;
19349
19349
  this.lastBuffer = false;
19350
19350
  this.parsedStatements = {};
19351
- this.ssl = config.ssl || false;
19351
+ this.ssl = config6.ssl || false;
19352
19352
  this._ending = false;
19353
19353
  this._emitMessage = false;
19354
19354
  const self = this;
@@ -19429,8 +19429,8 @@ var require_connection = __commonJS((exports, module) => {
19429
19429
  requestSsl() {
19430
19430
  this.stream.write(serialize.requestSsl());
19431
19431
  }
19432
- startup(config) {
19433
- this.stream.write(serialize.startup(config));
19432
+ startup(config6) {
19433
+ this.stream.write(serialize.startup(config6));
19434
19434
  }
19435
19435
  cancel(processID, secretKey) {
19436
19436
  this._send(serialize.cancel(processID, secretKey));
@@ -19456,11 +19456,11 @@ var require_connection = __commonJS((exports, module) => {
19456
19456
  parse(query) {
19457
19457
  this._send(serialize.parse(query));
19458
19458
  }
19459
- bind(config) {
19460
- this._send(serialize.bind(config));
19459
+ bind(config6) {
19460
+ this._send(serialize.bind(config6));
19461
19461
  }
19462
- execute(config) {
19463
- this._send(serialize.execute(config));
19462
+ execute(config6) {
19463
+ this._send(serialize.execute(config6));
19464
19464
  }
19465
19465
  flush() {
19466
19466
  if (this.stream.writable) {
@@ -19800,9 +19800,9 @@ var require_client = __commonJS((exports, module) => {
19800
19800
  var crypto = require_utils2();
19801
19801
 
19802
19802
  class Client extends EventEmitter {
19803
- constructor(config) {
19803
+ constructor(config6) {
19804
19804
  super();
19805
- this.connectionParameters = new ConnectionParameters(config);
19805
+ this.connectionParameters = new ConnectionParameters(config6);
19806
19806
  this.user = this.connectionParameters.user;
19807
19807
  this.database = this.connectionParameters.database;
19808
19808
  this.port = this.connectionParameters.port;
@@ -19814,7 +19814,7 @@ var require_client = __commonJS((exports, module) => {
19814
19814
  value: this.connectionParameters.password
19815
19815
  });
19816
19816
  this.replication = this.connectionParameters.replication;
19817
- const c = config || {};
19817
+ const c = config6 || {};
19818
19818
  this._Promise = c.Promise || global.Promise;
19819
19819
  this._types = new TypeOverrides(c.types);
19820
19820
  this._ending = false;
@@ -20194,23 +20194,23 @@ var require_client = __commonJS((exports, module) => {
20194
20194
  }
20195
20195
  }
20196
20196
  }
20197
- query(config, values, callback) {
20197
+ query(config6, values, callback) {
20198
20198
  let query;
20199
20199
  let result;
20200
20200
  let readTimeout;
20201
20201
  let readTimeoutTimer;
20202
20202
  let queryCallback;
20203
- if (config === null || config === undefined) {
20203
+ if (config6 === null || config6 === undefined) {
20204
20204
  throw new TypeError("Client was passed a null or undefined query");
20205
- } else if (typeof config.submit === "function") {
20206
- readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
20207
- result = query = config;
20205
+ } else if (typeof config6.submit === "function") {
20206
+ readTimeout = config6.query_timeout || this.connectionParameters.query_timeout;
20207
+ result = query = config6;
20208
20208
  if (typeof values === "function") {
20209
20209
  query.callback = query.callback || values;
20210
20210
  }
20211
20211
  } else {
20212
- readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
20213
- query = new Query(config, values, callback);
20212
+ readTimeout = config6.query_timeout || this.connectionParameters.query_timeout;
20213
+ query = new Query(config6, values, callback);
20214
20214
  if (!query.callback) {
20215
20215
  result = new this._Promise((resolve, reject) => {
20216
20216
  query.callback = (err, res) => err ? reject(err) : resolve(res);
@@ -20679,16 +20679,16 @@ var require_query2 = __commonJS((exports, module) => {
20679
20679
  var EventEmitter = __require("events").EventEmitter;
20680
20680
  var util = __require("util");
20681
20681
  var utils = require_utils();
20682
- var NativeQuery = module.exports = function(config, values, callback) {
20682
+ var NativeQuery = module.exports = function(config6, values, callback) {
20683
20683
  EventEmitter.call(this);
20684
- config = utils.normalizeQueryConfig(config, values, callback);
20685
- this.text = config.text;
20686
- this.values = config.values;
20687
- this.name = config.name;
20688
- this.queryMode = config.queryMode;
20689
- this.callback = config.callback;
20684
+ config6 = utils.normalizeQueryConfig(config6, values, callback);
20685
+ this.text = config6.text;
20686
+ this.values = config6.values;
20687
+ this.name = config6.name;
20688
+ this.queryMode = config6.queryMode;
20689
+ this.callback = config6.callback;
20690
20690
  this.state = "new";
20691
- this._arrayMode = config.rowMode === "array";
20691
+ this._arrayMode = config6.rowMode === "array";
20692
20692
  this._emitRowEvents = false;
20693
20693
  this.on("newListener", function(event) {
20694
20694
  if (event === "row")
@@ -20823,11 +20823,11 @@ var require_client2 = __commonJS((exports, module) => {
20823
20823
  var util = __require("util");
20824
20824
  var ConnectionParameters = require_connection_parameters();
20825
20825
  var NativeQuery = require_query2();
20826
- var Client = module.exports = function(config) {
20826
+ var Client = module.exports = function(config6) {
20827
20827
  EventEmitter.call(this);
20828
- config = config || {};
20829
- this._Promise = config.Promise || global.Promise;
20830
- this._types = new TypeOverrides(config.types);
20828
+ config6 = config6 || {};
20829
+ this._Promise = config6.Promise || global.Promise;
20830
+ this._types = new TypeOverrides(config6.types);
20831
20831
  this.native = new Native({
20832
20832
  types: this._types
20833
20833
  });
@@ -20836,9 +20836,9 @@ var require_client2 = __commonJS((exports, module) => {
20836
20836
  this._connecting = false;
20837
20837
  this._connected = false;
20838
20838
  this._queryable = true;
20839
- const cp = this.connectionParameters = new ConnectionParameters(config);
20840
- if (config.nativeConnectionString)
20841
- cp.nativeConnectionString = config.nativeConnectionString;
20839
+ const cp = this.connectionParameters = new ConnectionParameters(config6);
20840
+ if (config6.nativeConnectionString)
20841
+ cp.nativeConnectionString = config6.nativeConnectionString;
20842
20842
  this.user = cp.user;
20843
20843
  Object.defineProperty(this, "password", {
20844
20844
  configurable: true,
@@ -20917,23 +20917,23 @@ var require_client2 = __commonJS((exports, module) => {
20917
20917
  });
20918
20918
  });
20919
20919
  };
20920
- Client.prototype.query = function(config, values, callback) {
20920
+ Client.prototype.query = function(config6, values, callback) {
20921
20921
  let query;
20922
20922
  let result;
20923
20923
  let readTimeout;
20924
20924
  let readTimeoutTimer;
20925
20925
  let queryCallback;
20926
- if (config === null || config === undefined) {
20926
+ if (config6 === null || config6 === undefined) {
20927
20927
  throw new TypeError("Client was passed a null or undefined query");
20928
- } else if (typeof config.submit === "function") {
20929
- readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
20930
- result = query = config;
20928
+ } else if (typeof config6.submit === "function") {
20929
+ readTimeout = config6.query_timeout || this.connectionParameters.query_timeout;
20930
+ result = query = config6;
20931
20931
  if (typeof values === "function") {
20932
- config.callback = values;
20932
+ config6.callback = values;
20933
20933
  }
20934
20934
  } else {
20935
- readTimeout = config.query_timeout || this.connectionParameters.query_timeout;
20936
- query = new NativeQuery(config, values, callback);
20935
+ readTimeout = config6.query_timeout || this.connectionParameters.query_timeout;
20936
+ query = new NativeQuery(config6, values, callback);
20937
20937
  if (!query.callback) {
20938
20938
  let resolveOut, rejectOut;
20939
20939
  result = new this._Promise((resolve, reject) => {
@@ -21475,6 +21475,7 @@ function parseCreateIndex(stmt) {
21475
21475
  const schema = stmt.relation?.schemaname || undefined;
21476
21476
  const indexParams = stmt.indexParams || [];
21477
21477
  const columns = [];
21478
+ let opclasses;
21478
21479
  let expression;
21479
21480
  if (indexParams.length === 1 && indexParams[0].IndexElem?.expr) {
21480
21481
  expression = import_pgsql_parser3.deparseSync([indexParams[0].IndexElem.expr]).trim();
@@ -21484,6 +21485,14 @@ function parseCreateIndex(stmt) {
21484
21485
  const colName = param.IndexElem.name;
21485
21486
  if (colName) {
21486
21487
  columns.push(colName);
21488
+ if (param.IndexElem.opclass && param.IndexElem.opclass.length > 0) {
21489
+ const opclassName = param.IndexElem.opclass.map((node) => node.String?.sval).filter(Boolean).join(".");
21490
+ if (opclassName) {
21491
+ if (!opclasses)
21492
+ opclasses = {};
21493
+ opclasses[colName] = opclassName;
21494
+ }
21495
+ }
21487
21496
  } else if (param.IndexElem.expr) {
21488
21497
  expression = import_pgsql_parser3.deparseSync([param.IndexElem.expr]).trim();
21489
21498
  break;
@@ -21553,6 +21562,7 @@ function parseCreateIndex(stmt) {
21553
21562
  tableName,
21554
21563
  schema,
21555
21564
  columns,
21565
+ opclasses,
21556
21566
  type,
21557
21567
  unique,
21558
21568
  concurrent,
@@ -22846,6 +22856,22 @@ class DatabaseInspector {
22846
22856
  -- Expression index - no simple column names
22847
22857
  ARRAY[]::text[]
22848
22858
  END as column_names,
22859
+ -- Get operator class names for each column (non-default only)
22860
+ CASE
22861
+ WHEN ix.indexprs IS NULL THEN
22862
+ ARRAY(
22863
+ SELECT
22864
+ CASE
22865
+ WHEN opc.opcdefault THEN NULL
22866
+ ELSE opc.opcname
22867
+ END
22868
+ FROM unnest(ix.indclass) WITH ORDINALITY AS u(opcoid, ord)
22869
+ JOIN pg_opclass opc ON opc.oid = u.opcoid
22870
+ ORDER BY u.ord
22871
+ )
22872
+ ELSE
22873
+ ARRAY[]::text[]
22874
+ END as opclass_names,
22849
22875
  CASE
22850
22876
  WHEN ix.indpred IS NOT NULL THEN
22851
22877
  regexp_replace(
@@ -22874,19 +22900,32 @@ class DatabaseInspector {
22874
22900
  )
22875
22901
  ORDER BY i.indexname
22876
22902
  `, [tableName, tableSchema]);
22877
- return result.rows.map((row) => ({
22878
- name: row.index_name,
22879
- tableName: row.table_name,
22880
- schema: row.table_schema,
22881
- columns: row.column_names || [],
22882
- type: this.mapPostgreSQLIndexType(row.access_method),
22883
- unique: row.is_unique,
22884
- concurrent: false,
22885
- where: row.where_clause || undefined,
22886
- expression: row.has_expressions ? row.expression_def : undefined,
22887
- storageParameters: this.parseStorageOptions(row.storage_options),
22888
- tablespace: row.tablespace_name || undefined
22889
- }));
22903
+ return result.rows.map((row) => {
22904
+ const columns = row.column_names || [];
22905
+ const opclassNames = row.opclass_names || [];
22906
+ let opclasses;
22907
+ for (let i = 0;i < columns.length; i++) {
22908
+ if (opclassNames[i]) {
22909
+ if (!opclasses)
22910
+ opclasses = {};
22911
+ opclasses[columns[i]] = opclassNames[i];
22912
+ }
22913
+ }
22914
+ return {
22915
+ name: row.index_name,
22916
+ tableName: row.table_name,
22917
+ schema: row.table_schema,
22918
+ columns,
22919
+ opclasses,
22920
+ type: this.mapPostgreSQLIndexType(row.access_method),
22921
+ unique: row.is_unique,
22922
+ concurrent: false,
22923
+ where: row.where_clause || undefined,
22924
+ expression: row.has_expressions ? row.expression_def : undefined,
22925
+ storageParameters: this.parseStorageOptions(row.storage_options),
22926
+ tablespace: row.tablespace_name || undefined
22927
+ };
22928
+ });
22890
22929
  }
22891
22930
  parseStorageOptions(reloptions) {
22892
22931
  if (!reloptions || !Array.isArray(reloptions) || reloptions.length === 0) {
@@ -23688,6 +23727,30 @@ function normalizeDefault(value) {
23688
23727
  normalized = normalized.replace(/::[a-z_]+(\s+[a-z_]+)*(\([^)]*\))?$/i, "");
23689
23728
  return normalized.trim();
23690
23729
  }
23730
+ function normalizeExpression(expr) {
23731
+ let normalized = expr.replace(/\s+/g, " ").trim().replace(/::[a-z_]+(\([^)]*\))?/gi, "").replace(/\(([a-z_][a-z0-9_]*)\)/gi, "$1");
23732
+ while (/^\(.*\)$/.test(normalized)) {
23733
+ const inner = normalized.slice(1, -1);
23734
+ let depth = 0;
23735
+ let balanced = true;
23736
+ for (const char of inner) {
23737
+ if (char === "(")
23738
+ depth++;
23739
+ if (char === ")")
23740
+ depth--;
23741
+ if (depth < 0) {
23742
+ balanced = false;
23743
+ break;
23744
+ }
23745
+ }
23746
+ if (balanced && depth === 0) {
23747
+ normalized = inner.trim();
23748
+ } else {
23749
+ break;
23750
+ }
23751
+ }
23752
+ return normalized.replace(/\s+/g, " ").trim();
23753
+ }
23691
23754
  function columnsAreDifferent(desired, current) {
23692
23755
  const normalizedDesiredType = normalizeType(desired.type);
23693
23756
  const normalizedCurrentType = normalizeType(current.type);
@@ -23718,7 +23781,7 @@ function columnsAreDifferent(desired, current) {
23718
23781
  if (!desired.generated || !current.generated) {
23719
23782
  return true;
23720
23783
  }
23721
- if (desired.generated.always !== current.generated.always || desired.generated.stored !== current.generated.stored || desired.generated.expression !== current.generated.expression) {
23784
+ if (desired.generated.always !== current.generated.always || desired.generated.stored !== current.generated.stored || normalizeExpression(desired.generated.expression) !== normalizeExpression(current.generated.expression)) {
23722
23785
  return true;
23723
23786
  }
23724
23787
  }
@@ -24073,94 +24136,10 @@ class DependencyResolver {
24073
24136
  return this.topologicalSort(true);
24074
24137
  }
24075
24138
  topologicalSortCreation() {
24076
- const inDegree = new Map;
24077
- for (const tableName of this.nodes.keys()) {
24078
- inDegree.set(tableName, 0);
24079
- }
24080
- for (const [tableName, node] of this.nodes) {
24081
- for (const dependency of node.dependencies) {
24082
- inDegree.set(tableName, (inDegree.get(tableName) || 0) + 1);
24083
- }
24084
- }
24085
- const result = [];
24086
- const queue = [];
24087
- for (const [tableName, degree] of inDegree) {
24088
- if (degree === 0) {
24089
- queue.push(tableName);
24090
- }
24091
- }
24092
- while (queue.length > 0) {
24093
- const current = queue.shift();
24094
- result.push(current);
24095
- const currentNode = this.nodes.get(current);
24096
- if (currentNode) {
24097
- for (const dependent of currentNode.dependents) {
24098
- const newDegree = (inDegree.get(dependent) || 0) - 1;
24099
- inDegree.set(dependent, newDegree);
24100
- if (newDegree === 0) {
24101
- queue.push(dependent);
24102
- }
24103
- }
24104
- }
24105
- }
24106
- if (result.length !== this.nodes.size) {
24107
- const cycles = this.getCircularDependencies();
24108
- if (cycles.length > 0) {
24109
- const cycleDescriptions = cycles.map((cycle) => cycle.join(" → ")).join(`
24110
- `);
24111
- throw new Error(`Circular dependency detected. Cannot resolve table creation order.
24112
- ` + `Detected cycles:
24113
- ${cycleDescriptions}
24114
- ` + `Tables involved in cycles cannot be created because they reference each other.`);
24115
- }
24116
- throw new Error(`Cannot resolve table creation order. ` + `Processed ${result.length} out of ${this.nodes.size} tables.`);
24117
- }
24118
- return result;
24139
+ return this.topologicalSortCore(this.nodes, false, "creation");
24119
24140
  }
24120
24141
  topologicalSortDeletion() {
24121
- const inDegree = new Map;
24122
- for (const tableName of this.nodes.keys()) {
24123
- inDegree.set(tableName, 0);
24124
- }
24125
- for (const [tableName, node] of this.nodes) {
24126
- for (const dependent of node.dependents) {
24127
- inDegree.set(tableName, (inDegree.get(tableName) || 0) + 1);
24128
- }
24129
- }
24130
- const result = [];
24131
- const queue = [];
24132
- for (const [tableName, degree] of inDegree) {
24133
- if (degree === 0) {
24134
- queue.push(tableName);
24135
- }
24136
- }
24137
- while (queue.length > 0) {
24138
- const current = queue.shift();
24139
- result.push(current);
24140
- const currentNode = this.nodes.get(current);
24141
- if (currentNode) {
24142
- for (const dependency of currentNode.dependencies) {
24143
- const newDegree = (inDegree.get(dependency) || 0) - 1;
24144
- inDegree.set(dependency, newDegree);
24145
- if (newDegree === 0) {
24146
- queue.push(dependency);
24147
- }
24148
- }
24149
- }
24150
- }
24151
- if (result.length !== this.nodes.size) {
24152
- const cycles = this.getCircularDependencies();
24153
- if (cycles.length > 0) {
24154
- const cycleDescriptions = cycles.map((cycle) => cycle.join(" → ")).join(`
24155
- `);
24156
- throw new Error(`Circular dependency detected. Cannot resolve table deletion order.
24157
- ` + `Detected cycles:
24158
- ${cycleDescriptions}
24159
- ` + `Tables involved in cycles cannot be deleted in a valid order.`);
24160
- }
24161
- throw new Error(`Cannot resolve table deletion order. ` + `Processed ${result.length} out of ${this.nodes.size} tables.`);
24162
- }
24163
- return result;
24142
+ return this.topologicalSortCore(this.nodes, true, "deletion");
24164
24143
  }
24165
24144
  topologicalSort(reverse) {
24166
24145
  return reverse ? this.topologicalSortDeletion() : this.topologicalSortCreation();
@@ -24250,7 +24229,7 @@ class DependencyResolver {
24250
24229
  }
24251
24230
  }
24252
24231
  }
24253
- const order = this.topologicalSortWithNodes(modifiedNodes, false);
24232
+ const order = this.topologicalSortCore(modifiedNodes, false);
24254
24233
  return {
24255
24234
  order,
24256
24235
  foreignKeysToDefer
@@ -24299,13 +24278,13 @@ class DependencyResolver {
24299
24278
  }
24300
24279
  }
24301
24280
  }
24302
- const order = this.topologicalSortWithNodes(modifiedNodes, true);
24281
+ const order = this.topologicalSortCore(modifiedNodes, true);
24303
24282
  return {
24304
24283
  order,
24305
24284
  foreignKeysToDefer: foreignKeysToDrop
24306
24285
  };
24307
24286
  }
24308
- topologicalSortWithNodes(nodes, reverse) {
24287
+ topologicalSortCore(nodes, reverse, mode = "internal") {
24309
24288
  const inDegree = new Map;
24310
24289
  for (const tableName of nodes.keys()) {
24311
24290
  inDegree.set(tableName, 0);
@@ -24346,7 +24325,21 @@ class DependencyResolver {
24346
24325
  }
24347
24326
  }
24348
24327
  if (result.length !== nodes.size) {
24349
- throw new Error(`Internal error: topological sort failed even after removing cycle-forming edges. ` + `Processed ${result.length} out of ${nodes.size} tables.`);
24328
+ if (mode === "internal") {
24329
+ throw new Error(`Internal error: topological sort failed even after removing cycle-forming edges. ` + `Processed ${result.length} out of ${nodes.size} tables.`);
24330
+ }
24331
+ const cycles = this.getCircularDependencies();
24332
+ if (cycles.length > 0) {
24333
+ const cycleDescriptions = cycles.map((cycle) => cycle.join(" → ")).join(`
24334
+ `);
24335
+ const orderType2 = mode === "creation" ? "creation" : "deletion";
24336
+ throw new Error(`Circular dependency detected. Cannot resolve table ${orderType2} order.
24337
+ ` + `Detected cycles:
24338
+ ${cycleDescriptions}
24339
+ ` + `Tables involved in cycles cannot be ${mode === "creation" ? "created because they reference each other" : "deleted in a valid order"}.`);
24340
+ }
24341
+ const orderType = mode === "creation" ? "creation" : "deletion";
24342
+ throw new Error(`Cannot resolve table ${orderType} order. ` + `Processed ${result.length} out of ${nodes.size} tables.`);
24350
24343
  }
24351
24344
  return result;
24352
24345
  }
@@ -24489,7 +24482,7 @@ class SchemaDiffer {
24489
24482
  }
24490
24483
  generateColumnModificationStatements(tableName, desiredColumn, currentColumn) {
24491
24484
  const statements = [];
24492
- const generatedChanging = (desiredColumn.generated || currentColumn.generated) && (!desiredColumn.generated || !currentColumn.generated || desiredColumn.generated.expression !== currentColumn.generated.expression || desiredColumn.generated.always !== currentColumn.generated.always || desiredColumn.generated.stored !== currentColumn.generated.stored);
24485
+ const generatedChanging = (desiredColumn.generated || currentColumn.generated) && (!desiredColumn.generated || !currentColumn.generated || normalizeExpression(desiredColumn.generated.expression) !== normalizeExpression(currentColumn.generated.expression) || desiredColumn.generated.always !== currentColumn.generated.always || desiredColumn.generated.stored !== currentColumn.generated.stored);
24493
24486
  if (generatedChanging) {
24494
24487
  const dropSql = new SQLBuilder().p("ALTER TABLE").p(tableName).p("DROP COLUMN").ident(desiredColumn.name).p(";").build();
24495
24488
  statements.push(dropSql);
@@ -24694,6 +24687,16 @@ class SchemaDiffer {
24694
24687
  return false;
24695
24688
  if (index1.tablespace !== index2.tablespace)
24696
24689
  return false;
24690
+ const opclasses1 = index1.opclasses || {};
24691
+ const opclasses2 = index2.opclasses || {};
24692
+ const opKeys1 = Object.keys(opclasses1);
24693
+ const opKeys2 = Object.keys(opclasses2);
24694
+ if (opKeys1.length !== opKeys2.length)
24695
+ return false;
24696
+ for (const key of opKeys1) {
24697
+ if (opclasses1[key] !== opclasses2[key])
24698
+ return false;
24699
+ }
24697
24700
  const params1 = index1.storageParameters || {};
24698
24701
  const params2 = index2.storageParameters || {};
24699
24702
  const keys1 = Object.keys(params1);
@@ -24739,7 +24742,11 @@ class SchemaDiffer {
24739
24742
  if (index.expression) {
24740
24743
  builder.p(`(${index.expression})`);
24741
24744
  } else {
24742
- const quotedColumns = index.columns.map((col) => `"${col.replace(/"/g, '""')}"`).join(", ");
24745
+ const quotedColumns = index.columns.map((col) => {
24746
+ const quoted = `"${col.replace(/"/g, '""')}"`;
24747
+ const opclass = index.opclasses?.[col];
24748
+ return opclass ? `${quoted} ${opclass}` : quoted;
24749
+ }).join(", ");
24743
24750
  builder.p(`(${quotedColumns})`);
24744
24751
  }
24745
24752
  if (index.where) {
@@ -24769,9 +24776,9 @@ class SchemaDiffer {
24769
24776
  }
24770
24777
  generateCheckConstraintStatements(tableName, desiredConstraints, currentConstraints) {
24771
24778
  const statements = [];
24772
- const normalizeExpression = (expr) => expr.replace(/\s+/g, " ").trim();
24773
- const currentMap = new Map(currentConstraints.map((c) => [normalizeExpression(c.expression), c]));
24774
- const desiredMap = new Map(desiredConstraints.map((c) => [normalizeExpression(c.expression), c]));
24779
+ const normalizeExpression2 = (expr) => expr.replace(/\s+/g, " ").trim();
24780
+ const currentMap = new Map(currentConstraints.map((c) => [normalizeExpression2(c.expression), c]));
24781
+ const desiredMap = new Map(desiredConstraints.map((c) => [normalizeExpression2(c.expression), c]));
24775
24782
  for (const [key, constraint] of currentMap) {
24776
24783
  if (!desiredMap.has(key)) {
24777
24784
  if (constraint.name) {
@@ -24892,7 +24899,7 @@ class SchemaDiffer {
24892
24899
  return alterations;
24893
24900
  }
24894
24901
  collectColumnModificationAlterations(desiredColumn, currentColumn, alterations) {
24895
- const generatedChanging = (desiredColumn.generated || currentColumn.generated) && (!desiredColumn.generated || !currentColumn.generated || desiredColumn.generated.expression !== currentColumn.generated.expression || desiredColumn.generated.always !== currentColumn.generated.always || desiredColumn.generated.stored !== currentColumn.generated.stored);
24902
+ const generatedChanging = (desiredColumn.generated || currentColumn.generated) && (!desiredColumn.generated || !currentColumn.generated || normalizeExpression(desiredColumn.generated.expression) !== normalizeExpression(currentColumn.generated.expression) || desiredColumn.generated.always !== currentColumn.generated.always || desiredColumn.generated.stored !== currentColumn.generated.stored);
24896
24903
  if (generatedChanging) {
24897
24904
  alterations.push({ type: "drop_column", columnName: desiredColumn.name });
24898
24905
  alterations.push({ type: "add_column", column: desiredColumn });
@@ -24950,9 +24957,9 @@ class SchemaDiffer {
24950
24957
  }
24951
24958
  }
24952
24959
  collectCheckConstraintAlterations(desiredConstraints, currentConstraints, alterations) {
24953
- const normalizeExpression = (expr) => expr.replace(/\s+/g, " ").trim();
24954
- const currentMap = new Map(currentConstraints.map((c) => [normalizeExpression(c.expression), c]));
24955
- const desiredMap = new Map(desiredConstraints.map((c) => [normalizeExpression(c.expression), c]));
24960
+ const normalizeExpression2 = (expr) => expr.replace(/\s+/g, " ").trim();
24961
+ const currentMap = new Map(currentConstraints.map((c) => [normalizeExpression2(c.expression), c]));
24962
+ const desiredMap = new Map(desiredConstraints.map((c) => [normalizeExpression2(c.expression), c]));
24956
24963
  for (const [key, constraint] of currentMap) {
24957
24964
  if (!desiredMap.has(key) && constraint.name) {
24958
24965
  alterations.push({
@@ -25189,27 +25196,32 @@ class MigrationExecutor {
25189
25196
  spinner.stopAndPersist({ symbol: "✔", text: `Applied concurrent change (${elapsed}s)` });
25190
25197
  } catch (error2) {
25191
25198
  spinner.stopAndPersist({ symbol: "✗", text: "Failed to apply concurrent change" });
25192
- throw error2;
25199
+ if (error2 && typeof error2 === "object" && "code" in error2) {
25200
+ const pgError = error2;
25201
+ throw new MigrationError(pgError.message || "Concurrent statement failed", statement, {
25202
+ code: pgError.code,
25203
+ detail: pgError.detail,
25204
+ hint: pgError.hint,
25205
+ position: pgError.position
25206
+ });
25207
+ }
25208
+ throw new MigrationError(error2 instanceof Error ? error2.message : String(error2), statement);
25193
25209
  }
25194
25210
  }
25195
25211
  }
25196
25212
  } catch (error2) {
25213
+ if (error2 instanceof MigrationError) {
25214
+ throw error2;
25215
+ }
25197
25216
  if (error2 && typeof error2 === "object" && "code" in error2) {
25198
25217
  const pgError = error2;
25199
- let failedStatement;
25200
- if (pgError.message) {
25201
- failedStatement = undefined;
25202
- }
25203
- throw new MigrationError(pgError.message || "Database migration failed", failedStatement, {
25218
+ throw new MigrationError(pgError.message || "Database migration failed", undefined, {
25204
25219
  code: pgError.code,
25205
25220
  detail: pgError.detail,
25206
25221
  hint: pgError.hint,
25207
25222
  position: pgError.position
25208
25223
  });
25209
25224
  }
25210
- if (error2 instanceof MigrationError) {
25211
- throw error2;
25212
- }
25213
25225
  throw new MigrationError(error2 instanceof Error ? error2.message : String(error2));
25214
25226
  }
25215
25227
  }
@@ -25279,18 +25291,13 @@ class EnumHandler {
25279
25291
  }
25280
25292
  return { transactional, concurrent };
25281
25293
  }
25282
- async generateRemovalStatements(desiredEnums, currentEnums, client, schemas) {
25294
+ generateRemovalStatements(desiredEnums, currentEnums) {
25283
25295
  const statements = [];
25284
25296
  const desiredEnumNames = new Set(desiredEnums.map((e) => e.name));
25285
25297
  for (const currentEnum of currentEnums) {
25286
25298
  if (!desiredEnumNames.has(currentEnum.name)) {
25287
- const isUsed = await this.isTypeUsed(currentEnum.name, client, schemas);
25288
- if (!isUsed) {
25289
- statements.push(generateDropTypeSQL(currentEnum.name, currentEnum.schema));
25290
- Logger.info(`Dropping unused ENUM type '${currentEnum.name}'`);
25291
- } else {
25292
- Logger.warning(`ENUM type '${currentEnum.name}' is not in schema but is still referenced by table columns. ` + `Cannot auto-drop. Remove column references first.`);
25293
- }
25299
+ statements.push(generateDropTypeSQL(currentEnum.name, currentEnum.schema));
25300
+ Logger.info(`Dropping ENUM type '${currentEnum.name}'`);
25294
25301
  }
25295
25302
  }
25296
25303
  return statements;
@@ -25328,14 +25335,6 @@ class EnumHandler {
25328
25335
  }
25329
25336
  return statements;
25330
25337
  }
25331
- async isTypeUsed(enumName, client, schemas) {
25332
- const result = await client.query(`
25333
- SELECT COUNT(*) as usage_count
25334
- FROM information_schema.columns
25335
- WHERE udt_name = $1 AND table_schema = ANY($2::text[])
25336
- `, [enumName, schemas]);
25337
- return parseInt(result.rows[0].usage_count) > 0;
25338
- }
25339
25338
  }
25340
25339
  // src/core/schema/handlers/extension-handler.ts
25341
25340
  class ExtensionHandler {
@@ -25380,72 +25379,77 @@ class ExtensionHandler {
25380
25379
  return builder.build() + ";";
25381
25380
  }
25382
25381
  }
25383
- // src/core/schema/handlers/function-handler.ts
25384
- class FunctionHandler {
25385
- generateStatements(desiredFunctions, currentFunctions) {
25386
- const statements = [];
25387
- const currentFunctionMap = new Map(currentFunctions.map((f) => [f.name, f]));
25388
- const desiredFunctionNames = new Set(desiredFunctions.map((f) => f.name));
25389
- for (const currentFunc of currentFunctions) {
25390
- if (!desiredFunctionNames.has(currentFunc.name)) {
25391
- statements.push(generateDropFunctionSQL(currentFunc));
25392
- Logger.info(`Dropping function '${currentFunc.name}'`);
25393
- }
25394
- }
25395
- for (const desiredFunc of desiredFunctions) {
25396
- const currentFunc = currentFunctionMap.get(desiredFunc.name);
25397
- if (!currentFunc) {
25398
- statements.push(generateCreateFunctionSQL(desiredFunc));
25399
- Logger.info(`Creating function '${desiredFunc.name}'`);
25382
+ // src/core/schema/handlers/base-handler.ts
25383
+ function generateStatements(desired, current, config) {
25384
+ const statements = [];
25385
+ const currentMap = new Map(current.map((obj) => [config.getKey(obj), obj]));
25386
+ const desiredKeys = new Set(desired.map((obj) => config.getKey(obj)));
25387
+ const getLogName = config.getLogName ?? config.getKey;
25388
+ for (const curr of current) {
25389
+ const shouldManage = config.shouldManage?.(curr) ?? true;
25390
+ if (!desiredKeys.has(config.getKey(curr)) && shouldManage) {
25391
+ statements.push(config.generateDrop(curr));
25392
+ Logger.info(`Dropping ${config.name} '${getLogName(curr)}'`);
25393
+ }
25394
+ }
25395
+ for (const des of desired) {
25396
+ const key = config.getKey(des);
25397
+ const curr = currentMap.get(key);
25398
+ const shouldManage = config.shouldManage?.(curr ?? des) ?? true;
25399
+ if (!shouldManage) {
25400
+ Logger.info(`${config.name} '${getLogName(des)}' is owned by a table column, skipping`);
25401
+ continue;
25402
+ }
25403
+ if (!curr) {
25404
+ statements.push(config.generateCreate(des));
25405
+ Logger.info(`Creating ${config.name} '${getLogName(des)}'`);
25406
+ } else if (config.needsUpdate(des, curr)) {
25407
+ if (config.generateUpdate) {
25408
+ statements.push(config.generateUpdate(des));
25400
25409
  } else {
25401
- if (this.needsUpdate(desiredFunc, currentFunc)) {
25402
- statements.push(generateDropFunctionSQL(currentFunc));
25403
- statements.push(generateCreateFunctionSQL(desiredFunc));
25404
- Logger.info(`Updating function '${desiredFunc.name}'`);
25405
- } else {
25406
- Logger.info(`Function '${desiredFunc.name}' is up to date, skipping`);
25407
- }
25410
+ statements.push(config.generateDrop(curr));
25411
+ statements.push(config.generateCreate(des));
25408
25412
  }
25413
+ Logger.info(`Updating ${config.name} '${getLogName(des)}'`);
25414
+ } else {
25415
+ Logger.info(`${config.name} '${getLogName(des)}' is up to date, skipping`);
25409
25416
  }
25410
- return statements;
25411
25417
  }
25412
- needsUpdate(desired, current) {
25413
- const normalizeBody = (body) => body.replace(/\s+/g, " ").trim();
25414
- return normalizeBody(desired.body) !== normalizeBody(current.body) || desired.returnType !== current.returnType || desired.language !== current.language || desired.volatility !== current.volatility;
25418
+ return statements;
25419
+ }
25420
+
25421
+ // src/core/schema/handlers/function-handler.ts
25422
+ function normalizeBody(body) {
25423
+ return body.replace(/\s+/g, " ").trim();
25424
+ }
25425
+ var config = {
25426
+ name: "function",
25427
+ getKey: (f) => f.name,
25428
+ generateDrop: generateDropFunctionSQL,
25429
+ generateCreate: generateCreateFunctionSQL,
25430
+ needsUpdate: (desired, current) => normalizeBody(desired.body) !== normalizeBody(current.body) || desired.returnType !== current.returnType || desired.language !== current.language || desired.volatility !== current.volatility
25431
+ };
25432
+
25433
+ class FunctionHandler {
25434
+ generateStatements(desiredFunctions, currentFunctions) {
25435
+ return generateStatements(desiredFunctions, currentFunctions, config);
25415
25436
  }
25416
25437
  }
25417
25438
  // src/core/schema/handlers/procedure-handler.ts
25439
+ function normalizeBody2(body) {
25440
+ return body.replace(/\s+/g, " ").trim();
25441
+ }
25442
+ var config2 = {
25443
+ name: "procedure",
25444
+ getKey: (p) => p.name,
25445
+ generateDrop: generateDropProcedureSQL,
25446
+ generateCreate: generateCreateProcedureSQL,
25447
+ needsUpdate: (desired, current) => normalizeBody2(desired.body) !== normalizeBody2(current.body) || desired.language !== current.language
25448
+ };
25449
+
25418
25450
  class ProcedureHandler {
25419
25451
  generateStatements(desiredProcedures, currentProcedures) {
25420
- const statements = [];
25421
- const currentProcedureMap = new Map(currentProcedures.map((p) => [p.name, p]));
25422
- const desiredProcedureNames = new Set(desiredProcedures.map((p) => p.name));
25423
- for (const currentProc of currentProcedures) {
25424
- if (!desiredProcedureNames.has(currentProc.name)) {
25425
- statements.push(generateDropProcedureSQL(currentProc));
25426
- Logger.info(`Dropping procedure '${currentProc.name}'`);
25427
- }
25428
- }
25429
- for (const desiredProc of desiredProcedures) {
25430
- const currentProc = currentProcedureMap.get(desiredProc.name);
25431
- if (!currentProc) {
25432
- statements.push(generateCreateProcedureSQL(desiredProc));
25433
- Logger.info(`Creating procedure '${desiredProc.name}'`);
25434
- } else {
25435
- if (this.needsUpdate(desiredProc, currentProc)) {
25436
- statements.push(generateDropProcedureSQL(currentProc));
25437
- statements.push(generateCreateProcedureSQL(desiredProc));
25438
- Logger.info(`Updating procedure '${desiredProc.name}'`);
25439
- } else {
25440
- Logger.info(`Procedure '${desiredProc.name}' is up to date, skipping`);
25441
- }
25442
- }
25443
- }
25444
- return statements;
25445
- }
25446
- needsUpdate(desired, current) {
25447
- const normalizeBody = (body) => body.replace(/\s+/g, " ").trim();
25448
- return normalizeBody(desired.body) !== normalizeBody(current.body) || desired.language !== current.language;
25452
+ return generateStatements(desiredProcedures, currentProcedures, config2);
25449
25453
  }
25450
25454
  }
25451
25455
  // src/core/schema/handlers/schema-handler.ts
@@ -25473,123 +25477,51 @@ class SchemaHandler {
25473
25477
  }
25474
25478
  }
25475
25479
  // src/core/schema/handlers/sequence-handler.ts
25480
+ var config3 = {
25481
+ name: "sequence",
25482
+ getKey: (s) => s.name,
25483
+ generateDrop: (s) => generateDropSequenceSQL(s.name),
25484
+ generateCreate: generateCreateSequenceSQL,
25485
+ shouldManage: (s) => !s.ownedBy,
25486
+ needsUpdate: (desired, current) => desired.increment !== current.increment || desired.minValue !== current.minValue || desired.maxValue !== current.maxValue || desired.start !== current.start || desired.cache !== current.cache || desired.cycle !== current.cycle
25487
+ };
25488
+
25476
25489
  class SequenceHandler {
25477
25490
  generateStatements(desiredSequences, currentSequences) {
25478
- const statements = [];
25479
- const currentSequenceMap = new Map(currentSequences.map((s) => [s.name, s]));
25480
- const desiredSequenceNames = new Set(desiredSequences.map((s) => s.name));
25481
- for (const currentSeq of currentSequences) {
25482
- if (!desiredSequenceNames.has(currentSeq.name) && !currentSeq.ownedBy) {
25483
- statements.push(generateDropSequenceSQL(currentSeq.name));
25484
- Logger.info(`Dropping sequence '${currentSeq.name}'`);
25485
- }
25486
- }
25487
- for (const desiredSeq of desiredSequences) {
25488
- const currentSeq = currentSequenceMap.get(desiredSeq.name);
25489
- if (!currentSeq) {
25490
- statements.push(generateCreateSequenceSQL(desiredSeq));
25491
- Logger.info(`Creating sequence '${desiredSeq.name}'`);
25492
- } else if (!currentSeq.ownedBy) {
25493
- if (this.needsUpdate(desiredSeq, currentSeq)) {
25494
- statements.push(generateDropSequenceSQL(currentSeq.name));
25495
- statements.push(generateCreateSequenceSQL(desiredSeq));
25496
- Logger.info(`Updating sequence '${desiredSeq.name}'`);
25497
- } else {
25498
- Logger.info(`Sequence '${desiredSeq.name}' is up to date, skipping`);
25499
- }
25500
- } else {
25501
- Logger.info(`Sequence '${desiredSeq.name}' is owned by a table column, skipping`);
25502
- }
25503
- }
25504
- return statements;
25505
- }
25506
- needsUpdate(desired, current) {
25507
- return desired.increment !== current.increment || desired.minValue !== current.minValue || desired.maxValue !== current.maxValue || desired.start !== current.start || desired.cache !== current.cache || desired.cycle !== current.cycle;
25491
+ return generateStatements(desiredSequences, currentSequences, config3);
25508
25492
  }
25509
25493
  }
25510
25494
  // src/core/schema/handlers/trigger-handler.ts
25495
+ var config4 = {
25496
+ name: "trigger",
25497
+ getKey: (t) => `${t.tableName}.${t.name}`,
25498
+ getLogName: (t) => `${t.name}' on '${t.tableName}`,
25499
+ generateDrop: generateDropTriggerSQL,
25500
+ generateCreate: generateCreateTriggerSQL,
25501
+ needsUpdate: (desired, current) => desired.timing !== current.timing || desired.forEach !== current.forEach || desired.functionName !== current.functionName || JSON.stringify(desired.events) !== JSON.stringify(current.events)
25502
+ };
25503
+
25511
25504
  class TriggerHandler {
25512
25505
  generateStatements(desiredTriggers, currentTriggers) {
25513
- const statements = [];
25514
- const currentTriggerMap = new Map(currentTriggers.map((t) => [`${t.tableName}.${t.name}`, t]));
25515
- const desiredTriggerKeys = new Set(desiredTriggers.map((t) => `${t.tableName}.${t.name}`));
25516
- for (const currentTrig of currentTriggers) {
25517
- const key = `${currentTrig.tableName}.${currentTrig.name}`;
25518
- if (!desiredTriggerKeys.has(key)) {
25519
- statements.push(generateDropTriggerSQL(currentTrig));
25520
- Logger.info(`Dropping trigger '${currentTrig.name}' on '${currentTrig.tableName}'`);
25521
- }
25522
- }
25523
- for (const desiredTrig of desiredTriggers) {
25524
- const key = `${desiredTrig.tableName}.${desiredTrig.name}`;
25525
- const currentTrig = currentTriggerMap.get(key);
25526
- if (!currentTrig) {
25527
- statements.push(generateCreateTriggerSQL(desiredTrig));
25528
- Logger.info(`Creating trigger '${desiredTrig.name}' on '${desiredTrig.tableName}'`);
25529
- } else {
25530
- if (this.needsUpdate(desiredTrig, currentTrig)) {
25531
- statements.push(generateDropTriggerSQL(currentTrig));
25532
- statements.push(generateCreateTriggerSQL(desiredTrig));
25533
- Logger.info(`Updating trigger '${desiredTrig.name}' on '${desiredTrig.tableName}'`);
25534
- } else {
25535
- Logger.info(`Trigger '${desiredTrig.name}' is up to date, skipping`);
25536
- }
25537
- }
25538
- }
25539
- return statements;
25540
- }
25541
- needsUpdate(desired, current) {
25542
- return desired.timing !== current.timing || desired.forEach !== current.forEach || desired.functionName !== current.functionName || JSON.stringify(desired.events) !== JSON.stringify(current.events);
25506
+ return generateStatements(desiredTriggers, currentTriggers, config4);
25543
25507
  }
25544
25508
  }
25545
25509
  // src/core/schema/handlers/view-handler.ts
25510
+ function normalizeDefinition(def) {
25511
+ return def.replace(/\s+/g, " ").trim();
25512
+ }
25513
+ var config5 = {
25514
+ name: "view",
25515
+ getKey: (v) => v.name,
25516
+ generateDrop: (v) => generateDropViewSQL(v.name, v.materialized),
25517
+ generateCreate: generateCreateViewSQL,
25518
+ generateUpdate: generateCreateOrReplaceViewSQL,
25519
+ needsUpdate: (desired, current) => desired.materialized !== current.materialized || normalizeDefinition(desired.definition) !== normalizeDefinition(current.definition) || desired.checkOption !== current.checkOption || desired.securityBarrier !== current.securityBarrier
25520
+ };
25521
+
25546
25522
  class ViewHandler {
25547
25523
  generateStatements(desiredViews, currentViews) {
25548
- const statements = [];
25549
- const currentViewMap = new Map(currentViews.map((v) => [v.name, v]));
25550
- const desiredViewNames = new Set(desiredViews.map((v) => v.name));
25551
- for (const currentView of currentViews) {
25552
- if (!desiredViewNames.has(currentView.name)) {
25553
- statements.push(generateDropViewSQL(currentView.name, currentView.materialized));
25554
- Logger.info(`Dropping view '${currentView.name}'`);
25555
- }
25556
- }
25557
- for (const desiredView of desiredViews) {
25558
- const currentView = currentViewMap.get(desiredView.name);
25559
- if (!currentView) {
25560
- statements.push(generateCreateViewSQL(desiredView));
25561
- Logger.info(`Creating view '${desiredView.name}'`);
25562
- } else {
25563
- if (this.needsUpdate(desiredView, currentView)) {
25564
- statements.push(generateCreateOrReplaceViewSQL(desiredView));
25565
- Logger.info(`Updating view '${desiredView.name}'`);
25566
- } else {
25567
- Logger.info(`View '${desiredView.name}' is up to date, skipping`);
25568
- }
25569
- }
25570
- }
25571
- return statements;
25572
- }
25573
- needsUpdate(desired, current) {
25574
- if (desired.materialized !== current.materialized) {
25575
- return true;
25576
- }
25577
- const normalizeDefinition = (def) => def.replace(/\s+/g, " ").trim();
25578
- const normalizedDesired = normalizeDefinition(desired.definition);
25579
- const normalizedCurrent = normalizeDefinition(current.definition);
25580
- if (normalizedDesired !== normalizedCurrent) {
25581
- Logger.info(`View '${desired.name}' needs update:`);
25582
- Logger.info(` Desired: ${normalizedDesired.substring(0, 100)}...`);
25583
- Logger.info(` Current: ${normalizedCurrent.substring(0, 100)}...`);
25584
- return true;
25585
- }
25586
- if (desired.checkOption !== current.checkOption) {
25587
- return true;
25588
- }
25589
- if (desired.securityBarrier !== current.securityBarrier) {
25590
- return true;
25591
- }
25592
- return false;
25524
+ return generateStatements(desiredViews, currentViews, config5);
25593
25525
  }
25594
25526
  }
25595
25527
  // src/core/schema/service.ts
@@ -25741,15 +25673,25 @@ class SchemaService {
25741
25673
  return;
25742
25674
  }
25743
25675
  }
25744
- await this.executeStatements(client, sequenceStatements, autoApprove);
25745
- await this.executor.executePlan(client, plan, autoApprove);
25746
- await this.executeEnumRemovals(client, desiredEnums, currentEnums, schemas);
25747
- await this.executeStatements(client, functionStatements, autoApprove);
25748
- await this.executeStatements(client, procedureStatements, autoApprove);
25749
- await this.executeStatements(client, viewStatements, autoApprove);
25750
- await this.executeStatements(client, triggerStatements, autoApprove);
25751
- await this.executeStatements(client, commentStatements, autoApprove);
25752
- await this.executeStatements(client, extensionDropStatements, autoApprove);
25676
+ const enumRemovalStatements = this.enumHandler.generateRemovalStatements(desiredEnums, currentEnums);
25677
+ const combinedPlan = {
25678
+ transactional: [
25679
+ ...sequenceStatements,
25680
+ ...plan.transactional,
25681
+ ...plan.deferred,
25682
+ ...enumRemovalStatements,
25683
+ ...functionStatements,
25684
+ ...procedureStatements,
25685
+ ...viewStatements,
25686
+ ...triggerStatements,
25687
+ ...commentStatements,
25688
+ ...extensionDropStatements
25689
+ ],
25690
+ concurrent: plan.concurrent,
25691
+ deferred: [],
25692
+ hasChanges: true
25693
+ };
25694
+ await this.executor.executePlan(client, combinedPlan, autoApprove);
25753
25695
  } finally {
25754
25696
  if (lockOptions && !dryRun) {
25755
25697
  await this.databaseService.releaseAdvisoryLock(client, lockOptions.lockName);
@@ -25782,32 +25724,6 @@ class SchemaService {
25782
25724
  return await this.parser.parseSchemaFile(input);
25783
25725
  }
25784
25726
  }
25785
- async executeStatements(client, statements, autoApprove) {
25786
- if (statements.length === 0)
25787
- return;
25788
- await this.executor.executePlan(client, {
25789
- transactional: statements,
25790
- concurrent: [],
25791
- deferred: [],
25792
- hasChanges: true
25793
- }, autoApprove);
25794
- }
25795
- async executeEnumRemovals(client, desiredEnums, currentEnums, schemas) {
25796
- const statements = await this.enumHandler.generateRemovalStatements(desiredEnums, currentEnums, client, schemas);
25797
- for (const statement of statements) {
25798
- try {
25799
- await client.query(statement);
25800
- } catch (error2) {
25801
- if (error2.code === "2BP01") {
25802
- const match = statement.match(/DROP TYPE\s+(?:"?(\w+)"?\.)?"?(\w+)"?/i);
25803
- const typeName = match ? match[1] ? `${match[1]}.${match[2]}` : match[2] : "unknown";
25804
- Logger.warning(`Could not drop ENUM '${typeName}': now in use (concurrent change). Will retry next migration.`);
25805
- } else {
25806
- throw error2;
25807
- }
25808
- }
25809
- }
25810
- }
25811
25727
  validateSchemaReferences(managedSchemas, tables, enums, views, functions, procedures, triggers, sequences) {
25812
25728
  const errors = [];
25813
25729
  const checkSchema = (objType, objName, objSchema) => {
@@ -25852,8 +25768,8 @@ var defaults = import_lib.default.defaults;
25852
25768
  // src/core/database/client.ts
25853
25769
  class DatabaseService {
25854
25770
  config;
25855
- constructor(config) {
25856
- this.config = config;
25771
+ constructor(config6) {
25772
+ this.config = config6;
25857
25773
  }
25858
25774
  async createClient() {
25859
25775
  const client = new Client(this.config);
@@ -25906,6 +25822,7 @@ class DatabaseService {
25906
25822
  const timeoutMs = options.lockTimeout;
25907
25823
  const lockKeyResult = await client.query("SELECT hashtext($1)::bigint as lock_key", [options.lockName]);
25908
25824
  const lockKey = lockKeyResult.rows[0].lock_key;
25825
+ let delay = 100;
25909
25826
  while (true) {
25910
25827
  const result = await client.query("SELECT pg_try_advisory_lock($1) as acquired", [lockKey]);
25911
25828
  if (result.rows[0].acquired) {
@@ -25915,7 +25832,8 @@ class DatabaseService {
25915
25832
  if (elapsed >= timeoutMs) {
25916
25833
  throw new MigrationError(`Failed to acquire advisory lock '${options.lockName}' within ${timeoutMs / 1000}s. Another migration may be in progress. Please wait and try again.`);
25917
25834
  }
25918
- await new Promise((resolve) => setTimeout(resolve, 100));
25835
+ await new Promise((resolve) => setTimeout(resolve, delay));
25836
+ delay = Math.min(delay * 2, 5000);
25919
25837
  }
25920
25838
  }
25921
25839
  async releaseAdvisoryLock(client, lockName) {
@@ -25930,8 +25848,8 @@ class DatabaseService {
25930
25848
  }
25931
25849
 
25932
25850
  // src/cli/commands/apply.ts
25933
- async function applyCommand(options, config) {
25934
- const databaseService = new DatabaseService(config);
25851
+ async function applyCommand(options, config6) {
25852
+ const databaseService = new DatabaseService(config6);
25935
25853
  const schemaService = new SchemaService(databaseService);
25936
25854
  const lockTimeout = parseInt(options.lockTimeout, 10);
25937
25855
  if (isNaN(lockTimeout) || lockTimeout <= 0) {
@@ -25946,7 +25864,7 @@ async function applyCommand(options, config) {
25946
25864
  // package.json
25947
25865
  var package_default = {
25948
25866
  name: "pgterra",
25949
- version: "0.2.11",
25867
+ version: "0.2.13",
25950
25868
  description: "Declarative schema management for Postgres",
25951
25869
  keywords: [
25952
25870
  "postgres",
@@ -26042,8 +25960,8 @@ async function runCLI() {
26042
25960
  const program2 = new Command;
26043
25961
  program2.name("pgterra").description("Declarative schema management for Postgres").version(package_default.version, "-v, --version");
26044
25962
  program2.command("apply").description("Apply schema changes to database").requiredOption("-f, --file <file>", "Schema file path").option("-u, --url <url>", "Database connection string (overrides DATABASE_URL)").option("-s, --schema <schema>", "Database schema to manage (can be specified multiple times, defaults to 'public')", collectSchemas, []).option("--auto-approve", "Skip confirmation prompt").option("--dry-run", "Show migration plan without executing changes").option("--lock-name <name>", "Advisory lock name to prevent concurrent migrations", "pgterra_migrate_execute").option("--lock-timeout <seconds>", "Maximum time to wait for advisory lock in seconds", "10").action(async (options) => {
26045
- const config = loadConfig(options.url);
26046
- await applyCommand(options, config);
25963
+ const config6 = loadConfig(options.url);
25964
+ await applyCommand(options, config6);
26047
25965
  });
26048
25966
  await program2.parseAsync();
26049
25967
  }