"use strict";

function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.fetchSchemaJson = void 0;
var _pg = require("pg");
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return exports; }; var exports = {}, Op = Object.prototype, hasOwn = Op.hasOwnProperty, defineProperty = Object.defineProperty || function (obj, key, desc) { obj[key] = desc.value; }, $Symbol = "function" == typeof Symbol ? Symbol : {}, iteratorSymbol = $Symbol.iterator || "@@iterator", asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator", toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; function define(obj, key, value) { return Object.defineProperty(obj, key, { value: value, enumerable: !0, configurable: !0, writable: !0 }), obj[key]; } try { define({}, ""); } catch (err) { define = function define(obj, key, value) { return obj[key] = value; }; } function wrap(innerFn, outerFn, self, tryLocsList) { var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator, generator = Object.create(protoGenerator.prototype), context = new Context(tryLocsList || []); return defineProperty(generator, "_invoke", { value: makeInvokeMethod(innerFn, self, context) }), generator; } function tryCatch(fn, obj, arg) { try { return { type: "normal", arg: fn.call(obj, arg) }; } catch (err) { return { type: "throw", arg: err }; } } exports.wrap = wrap; var ContinueSentinel = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var IteratorPrototype = {}; define(IteratorPrototype, iteratorSymbol, function () { return this; }); var getProto = Object.getPrototypeOf, NativeIteratorPrototype = getProto && getProto(getProto(values([]))); NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype); var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype); function defineIteratorMethods(prototype) { ["next", "throw", "return"].forEach(function (method) { define(prototype, method, function (arg) { return this._invoke(method, arg); }); }); } function AsyncIterator(generator, PromiseImpl) { function invoke(method, arg, resolve, reject) { var record = tryCatch(generator[method], generator, arg); if ("throw" !== record.type) { var result = record.arg, value = result.value; return value && "object" == _typeof(value) && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) { invoke("next", value, resolve, reject); }, function (err) { invoke("throw", err, resolve, reject); }) : PromiseImpl.resolve(value).then(function (unwrapped) { result.value = unwrapped, resolve(result); }, function (error) { return invoke("throw", error, resolve, reject); }); } reject(record.arg); } var previousPromise; defineProperty(this, "_invoke", { value: function value(method, arg) { function callInvokeWithMethodAndArg() { return new PromiseImpl(function (resolve, reject) { invoke(method, arg, resolve, reject); }); } return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(innerFn, self, context) { var state = "suspendedStart"; return function (method, arg) { if ("executing" === state) throw new Error("Generator is already running"); if ("completed" === state) { if ("throw" === method) throw arg; return doneResult(); } for (context.method = method, context.arg = arg;;) { var delegate = context.delegate; if (delegate) { var delegateResult = maybeInvokeDelegate(delegate, context); if (delegateResult) { if (delegateResult === ContinueSentinel) continue; return delegateResult; } } if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) { if ("suspendedStart" === state) throw state = "completed", context.arg; context.dispatchException(context.arg); } else "return" === context.method && context.abrupt("return", context.arg); state = "executing"; var record = tryCatch(innerFn, self, context); if ("normal" === record.type) { if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue; return { value: record.arg, done: context.done }; } "throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg); } }; } function maybeInvokeDelegate(delegate, context) { var methodName = context.method, method = delegate.iterator[methodName]; if (undefined === method) return context.delegate = null, "throw" === methodName && delegate.iterator["return"] && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method) || "return" !== methodName && (context.method = "throw", context.arg = new TypeError("The iterator does not provide a '" + methodName + "' method")), ContinueSentinel; var record = tryCatch(method, delegate.iterator, context.arg); if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel; var info = record.arg; return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel); } function pushTryEntry(locs) { var entry = { tryLoc: locs[0] }; 1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry); } function resetTryEntry(entry) { var record = entry.completion || {}; record.type = "normal", delete record.arg, entry.completion = record; } function Context(tryLocsList) { this.tryEntries = [{ tryLoc: "root" }], tryLocsList.forEach(pushTryEntry, this), this.reset(!0); } function values(iterable) { if (iterable) { var iteratorMethod = iterable[iteratorSymbol]; if (iteratorMethod) return iteratorMethod.call(iterable); if ("function" == typeof iterable.next) return iterable; if (!isNaN(iterable.length)) { var i = -1, next = function next() { for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next; return next.value = undefined, next.done = !0, next; }; return next.next = next; } } return { next: doneResult }; } function doneResult() { return { value: undefined, done: !0 }; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, defineProperty(Gp, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), defineProperty(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) { var ctor = "function" == typeof genFun && genFun.constructor; return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name)); }, exports.mark = function (genFun) { return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun; }, exports.awrap = function (arg) { return { __await: arg }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () { return this; }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) { void 0 === PromiseImpl && (PromiseImpl = Promise); var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl); return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) { return result.done ? result.value : iter.next(); }); }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () { return this; }), define(Gp, "toString", function () { return "[object Generator]"; }), exports.keys = function (val) { var object = Object(val), keys = []; for (var key in object) keys.push(key); return keys.reverse(), function next() { for (; keys.length;) { var key = keys.pop(); if (key in object) return next.value = key, next.done = !1, next; } return next.done = !0, next; }; }, exports.values = values, Context.prototype = { constructor: Context, reset: function reset(skipTempReset) { if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined); }, stop: function stop() { this.done = !0; var rootRecord = this.tryEntries[0].completion; if ("throw" === rootRecord.type) throw rootRecord.arg; return this.rval; }, dispatchException: function dispatchException(exception) { if (this.done) throw exception; var context = this; function handle(loc, caught) { return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught; } for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i], record = entry.completion; if ("root" === entry.tryLoc) return handle("end"); if (entry.tryLoc <= this.prev) { var hasCatch = hasOwn.call(entry, "catchLoc"), hasFinally = hasOwn.call(entry, "finallyLoc"); if (hasCatch && hasFinally) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } else if (hasCatch) { if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0); } else { if (!hasFinally) throw new Error("try statement without catch or finally"); if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc); } } } }, abrupt: function abrupt(type, arg) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) { var finallyEntry = entry; break; } } finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null); var record = finallyEntry ? finallyEntry.completion : {}; return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record); }, complete: function complete(record, afterLoc) { if ("throw" === record.type) throw record.arg; return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel; }, finish: function finish(finallyLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel; } }, "catch": function _catch(tryLoc) { for (var i = this.tryEntries.length - 1; i >= 0; --i) { var entry = this.tryEntries[i]; if (entry.tryLoc === tryLoc) { var record = entry.completion; if ("throw" === record.type) { var thrown = record.arg; resetTryEntry(entry); } return thrown; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(iterable, resultName, nextLoc) { return this.delegate = { iterator: values(iterable), resultName: resultName, nextLoc: nextLoc }, "next" === this.method && (this.arg = undefined), ContinueSentinel; } }, exports; }
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } /* eslint-disable camelcase */
var getValidatedClient = /*#__PURE__*/function () {
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(connection) {
    var client;
    return _regeneratorRuntime().wrap(function _callee$(_context) {
      while (1) switch (_context.prev = _context.next) {
        case 0:
          client = new _pg.Client(connection);
          _context.prev = 1;
          _context.next = 4;
          return client.connect();
        case 4:
          _context.next = 6;
          return client.query('SELECT 1');
        case 6:
          return _context.abrupt("return", client);
        case 9:
          _context.prev = 9;
          _context.t0 = _context["catch"](1);
          // Log the error and handle it as per your application's requirement
          console.error('PostgreSQL connection error:', _context.t0);

          // Ensure to close the client in case of failure
          _context.next = 14;
          return client.end();
        case 14:
          throw _context.t0;
        case 15:
        case "end":
          return _context.stop();
      }
    }, _callee, null, [[1, 9]]);
  }));
  return function getValidatedClient(_x) {
    return _ref.apply(this, arguments);
  };
}();
var convertQueryBoolean = function convertQueryBoolean(val) {
  return val === 'YES';
};
var getFieldType = function getFieldType(data_type, udt_name, character_maximum_length, numeric_precision, numeric_scale) {
  if (data_type === 'ARRAY') {
    return "".concat(udt_name.slice(1, udt_name.length), "[]");
  }
  if (character_maximum_length) {
    return "".concat(udt_name, "(").concat(character_maximum_length, ")");
  }
  if (numeric_precision && numeric_scale) {
    return "".concat(udt_name, "(").concat(numeric_precision, ",").concat(numeric_scale, ")");
  }
  return udt_name;
};
var getDbdefault = function getDbdefault(data_type, column_default, default_type) {
  if (data_type === 'ARRAY') {
    var values = column_default.slice(6, -1).split(',').map(function (value) {
      return value.split('::')[0];
    });
    return {
      type: default_type,
      value: "ARRAY[".concat(values.join(', '), "]")
    };
  }
  if (default_type === 'string') {
    var defaultValues = column_default.split('::')[0];
    var isJson = data_type === 'json' || data_type === 'jsonb';
    var type = isJson ? 'expression' : 'string';
    return {
      type: type,
      value: defaultValues.slice(1, -1)
    };
  }
  return {
    type: default_type,
    value: column_default
  };
};
var generateField = function generateField(row) {
  var column_name = row.column_name,
    data_type = row.data_type,
    character_maximum_length = row.character_maximum_length,
    numeric_precision = row.numeric_precision,
    numeric_scale = row.numeric_scale,
    udt_schema = row.udt_schema,
    udt_name = row.udt_name,
    identity_increment = row.identity_increment,
    is_nullable = row.is_nullable,
    column_default = row.column_default,
    default_type = row.default_type,
    column_comment = row.column_comment;
  var dbdefault = column_default && default_type !== 'increment' ? getDbdefault(data_type, column_default, default_type) : null;
  var fieldType = data_type === 'USER-DEFINED' ? {
    type_name: udt_name,
    schemaName: udt_schema
  } : {
    type_name: getFieldType(data_type, udt_name, character_maximum_length, numeric_precision, numeric_scale),
    schemaname: null
  };
  return {
    name: column_name,
    type: fieldType,
    dbdefault: dbdefault,
    not_null: !convertQueryBoolean(is_nullable),
    increment: !!identity_increment || default_type === 'increment',
    note: column_comment ? {
      value: column_comment
    } : {
      value: ''
    }
  };
};
var generateTablesAndFields = /*#__PURE__*/function () {
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(client) {
    var fields, tablesAndFieldsSql, tablesAndFieldsResult, tables;
    return _regeneratorRuntime().wrap(function _callee2$(_context2) {
      while (1) switch (_context2.prev = _context2.next) {
        case 0:
          fields = {};
          tablesAndFieldsSql = "\n    WITH comments AS (\n      SELECT\n        pc.relname AS table_name,\n        pn.nspname AS table_schema,\n        pa.attname AS column_name,\n        pd.description\n      FROM\n        pg_description pd\n      JOIN\n        pg_class pc ON pd.objoid = pc.oid\n      JOIN\n        pg_namespace pn ON pc.relnamespace = pn.oid\n      LEFT JOIN\n        pg_attribute pa ON pd.objoid = pa.attrelid AND pd.objsubid = pa.attnum\n      WHERE\n        pc.relkind = 'r'\n        AND pn.nspname NOT IN ('pg_catalog', 'information_schema')\n    )\n    SELECT\n      t.table_schema,\n      t.table_name,\n      c.column_name,\n      c.data_type,\n      c.character_maximum_length,\n      c.numeric_precision,\n      c.numeric_scale,\n      c.udt_schema,\n      c.udt_name,\n      c.identity_increment,\n      c.is_nullable,\n      c.column_default,\n      CASE\n        WHEN c.column_default IS NULL THEN NULL\n        WHEN c.column_default LIKE 'nextval(%' THEN 'increment'\n        WHEN c.column_default LIKE '''%' THEN 'string'\n        WHEN c.column_default = 'true' OR c.column_default = 'false' THEN 'boolean'\n        WHEN c.column_default ~ '^-?[0-9]+(.[0-9]+)?$' THEN 'number'\n        ELSE 'expression'\n      END AS default_type,\n      (SELECT description FROM comments WHERE table_name = t.table_name AND table_schema = t.table_schema AND column_name IS NULL) AS table_comment,\n      (SELECT description FROM comments WHERE table_name = t.table_name AND table_schema = t.table_schema AND column_name = c.column_name) AS column_comment\n    FROM\n      information_schema.columns c\n    JOIN\n      information_schema.tables t ON c.table_name = t.table_name AND c.table_schema = t.table_schema\n    WHERE\n      t.table_type = 'BASE TABLE'\n      AND t.table_schema NOT IN ('pg_catalog', 'information_schema')\n    ORDER BY\n      t.table_schema,\n      t.table_name,\n      c.ordinal_position\n    ;\n  ";
          _context2.next = 4;
          return client.query(tablesAndFieldsSql);
        case 4:
          tablesAndFieldsResult = _context2.sent;
          tables = tablesAndFieldsResult.rows.reduce(function (acc, row) {
            var table_schema = row.table_schema,
              table_name = row.table_name,
              table_comment = row.table_comment;
            var key = "".concat(table_schema, ".").concat(table_name);
            if (!acc[key]) {
              acc[key] = {
                name: table_name,
                schemaName: table_schema,
                note: table_comment ? {
                  value: table_comment
                } : {
                  value: ''
                }
              };
            }
            if (!fields[key]) fields[key] = [];
            var field = generateField(row);
            fields[key].push(field);
            return acc;
          }, {});
          return _context2.abrupt("return", {
            tables: Object.values(tables),
            fields: fields
          });
        case 7:
        case "end":
          return _context2.stop();
      }
    }, _callee2);
  }));
  return function generateTablesAndFields(_x2) {
    return _ref2.apply(this, arguments);
  };
}();
var generateRawRefs = /*#__PURE__*/function () {
  var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(client) {
    var refs, refsListSql, refsQueryResult;
    return _regeneratorRuntime().wrap(function _callee3$(_context3) {
      while (1) switch (_context3.prev = _context3.next) {
        case 0:
          refs = [];
          refsListSql = "\n    SELECT\n      tc.table_schema,\n      tc.table_name,\n      tc.constraint_name as fk_constraint_name,\n      STRING_AGG(DISTINCT kcu.column_name, ',') AS column_names,\n      ccu.table_schema AS foreign_table_schema,\n      ccu.table_name AS foreign_table_name,\n      STRING_AGG(DISTINCT ccu.column_name, ',') AS foreign_column_names,\n      tc.constraint_type,\n      rc.delete_rule AS on_delete,\n      rc.update_rule AS on_update\n    FROM information_schema.table_constraints AS tc\n    JOIN information_schema.key_column_usage AS kcu\n      ON tc.constraint_name = kcu.constraint_name\n      AND tc.table_schema = kcu.table_schema\n    JOIN information_schema.constraint_column_usage AS ccu\n      ON ccu.constraint_name = tc.constraint_name\n    JOIN information_schema.referential_constraints AS rc\n      ON tc.constraint_name = rc.constraint_name\n      AND tc.table_schema = rc.constraint_schema\n    WHERE tc.constraint_type = 'FOREIGN KEY'\n      AND tc.table_schema NOT IN ('pg_catalog', 'information_schema')\n    GROUP BY\n      tc.table_schema,\n      tc.table_name,\n      tc.constraint_name,\n      ccu.table_schema,\n      ccu.table_name,\n      tc.constraint_type,\n      rc.delete_rule,\n      rc.update_rule\n    ORDER BY\n      tc.table_schema,\n      tc.table_name;\n  ";
          _context3.next = 4;
          return client.query(refsListSql);
        case 4:
          refsQueryResult = _context3.sent;
          refsQueryResult.rows.forEach(function (refRow) {
            var table_schema = refRow.table_schema,
              fk_constraint_name = refRow.fk_constraint_name,
              table_name = refRow.table_name,
              column_names = refRow.column_names,
              foreign_table_schema = refRow.foreign_table_schema,
              foreign_table_name = refRow.foreign_table_name,
              foreign_column_names = refRow.foreign_column_names,
              on_delete = refRow.on_delete,
              on_update = refRow.on_update;
            var ep1 = {
              tableName: table_name,
              schemaName: table_schema,
              fieldNames: column_names.split(','),
              relation: '*'
            };
            var ep2 = {
              tableName: foreign_table_name,
              schemaName: foreign_table_schema,
              fieldNames: foreign_column_names.split(','),
              relation: '1'
            };
            refs.push({
              name: fk_constraint_name,
              endpoints: [ep1, ep2],
              onDelete: on_delete === 'NO ACTION' ? null : on_delete,
              onUpdate: on_update === 'NO ACTION' ? null : on_update
            });
          });
          return _context3.abrupt("return", refs);
        case 7:
        case "end":
          return _context3.stop();
      }
    }, _callee3);
  }));
  return function generateRawRefs(_x3) {
    return _ref3.apply(this, arguments);
  };
}();
var generateIndexes = /*#__PURE__*/function () {
  var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(client) {
    var indexListSql, indexListResult, _indexListResult$rows, outOfLineConstraints, inlineConstraints, indexes, tableConstraints;
    return _regeneratorRuntime().wrap(function _callee4$(_context4) {
      while (1) switch (_context4.prev = _context4.next) {
        case 0:
          // const tableConstraints = {};
          indexListSql = "\n    WITH user_tables AS (\n      SELECT\n        schemaname AS tableschema,\n        tablename\n      FROM pg_tables\n      WHERE schemaname NOT IN ('pg_catalog', 'information_schema')  -- Exclude system schemas\n        AND tablename NOT LIKE 'pg_%'  -- Exclude PostgreSQL system tables\n        AND tablename NOT LIKE 'sql_%'  -- Exclude SQL standard tables\n    ),\n    index_info AS (\n      SELECT\n        t.relname AS table_name,\n        i.relname AS index_name,\n        ix.indisunique AS is_unique,\n        ix.indisprimary AS is_primary,\n        am.amname AS index_type,\n        array_to_string(array_agg(a.attname ORDER BY x.n), ', ') AS columns,\n        pg_get_expr(ix.indexprs, ix.indrelid) AS expressions,\n        CASE\n          WHEN ix.indisprimary THEN 'PRIMARY KEY'\n          WHEN ix.indisunique THEN 'UNIQUE'\n          ELSE NULL\n        END AS constraint_type\n      FROM\n        pg_class t\n        JOIN pg_index ix ON t.oid = ix.indrelid\n        JOIN pg_class i ON i.oid = ix.indexrelid\n        LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)\n        JOIN pg_am am ON i.relam = am.oid\n        LEFT JOIN generate_subscripts(ix.indkey, 1) AS x(n) ON a.attnum = ix.indkey[x.n]\n      WHERE\n        t.relkind = 'r'\n        AND t.relname NOT LIKE 'pg_%'\n        AND t.relname NOT LIKE 'sql_%'\n      GROUP BY\n        t.relname, i.relname, ix.indisunique, ix.indisprimary, am.amname, ix.indexprs, ix.indrelid\n    )\n    SELECT\n      ut.tableschema AS table_schema,\n      ut.tablename AS table_name,\n      ii.index_name,\n      ii.is_unique,\n      ii.is_primary,\n      ii.index_type,\n      ii.columns,\n      ii.expressions,\n      ii.constraint_type  -- Added constraint type\n    FROM\n      user_tables ut\n    LEFT JOIN\n      index_info ii ON ut.tablename = ii.table_name\n    WHERE ii.columns IS NOT NULL\n    ORDER BY\n      ut.tablename,\n      ii.constraint_type,\n      ii.index_name\n    ;\n  ";
          _context4.next = 3;
          return client.query(indexListSql);
        case 3:
          indexListResult = _context4.sent;
          _indexListResult$rows = indexListResult.rows.reduce(function (acc, row) {
            var constraint_type = row.constraint_type,
              columns = row.columns;
            if (columns === 'null' || columns.trim() === '') return acc;
            var isSingleColumn = columns.split(',').length === 1;
            var isInlineConstraint = isSingleColumn && (constraint_type === 'PRIMARY KEY' || constraint_type === 'UNIQUE');
            if (isInlineConstraint) {
              acc.inlineConstraints.push(row);
            } else {
              acc.outOfLineConstraints.push(row);
            }
            return acc;
          }, {
            outOfLineConstraints: [],
            inlineConstraints: []
          }), outOfLineConstraints = _indexListResult$rows.outOfLineConstraints, inlineConstraints = _indexListResult$rows.inlineConstraints;
          indexes = outOfLineConstraints.reduce(function (acc, indexRow) {
            var table_schema = indexRow.table_schema,
              table_name = indexRow.table_name,
              index_name = indexRow.index_name,
              index_type = indexRow.index_type,
              columns = indexRow.columns,
              expressions = indexRow.expressions;
            var indexColumns = columns.split(',').map(function (column) {
              return {
                type: 'column',
                value: column.trim()
              };
            });
            var indexExpressions = expressions ? expressions.split(',').map(function (expression) {
              return {
                type: 'expression',
                value: expression
              };
            }) : [];
            var index = {
              name: index_name,
              type: index_type,
              columns: [].concat(_toConsumableArray(indexColumns), _toConsumableArray(indexExpressions))
            };
            var key = "".concat(table_schema, ".").concat(table_name);
            if (acc[key]) {
              acc[key].push(index);
            } else {
              acc[key] = [index];
            }
            return acc;
          }, {});
          tableConstraints = inlineConstraints.reduce(function (acc, row) {
            var table_schema = row.table_schema,
              table_name = row.table_name,
              columns = row.columns,
              constraint_type = row.constraint_type;
            var key = "".concat(table_schema, ".").concat(table_name);
            if (!acc[key]) acc[key] = {};
            var columnNames = columns.split(',').map(function (column) {
              return column.trim();
            });
            columnNames.forEach(function (columnName) {
              if (!acc[key][columnName]) acc[key][columnName] = {};
              if (constraint_type === 'PRIMARY KEY') {
                acc[key][columnName].pk = true;
              }
              if (constraint_type === 'UNIQUE' && !acc[key][columnName].pk) {
                acc[key][columnName].unique = true;
              }
            });
            return acc;
          }, {});
          return _context4.abrupt("return", {
            indexes: indexes,
            tableConstraints: tableConstraints
          });
        case 8:
        case "end":
          return _context4.stop();
      }
    }, _callee4);
  }));
  return function generateIndexes(_x4) {
    return _ref4.apply(this, arguments);
  };
}();
var generateRawEnums = /*#__PURE__*/function () {
  var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(client) {
    var enumListSql, enumListResult, enums;
    return _regeneratorRuntime().wrap(function _callee5$(_context5) {
      while (1) switch (_context5.prev = _context5.next) {
        case 0:
          enumListSql = "\n    SELECT\n      n.nspname AS schema_name,\n      t.typname AS enum_type,\n      e.enumlabel AS enum_value,\n      e.enumsortorder AS sort_order\n    FROM\n      pg_enum e\n    JOIN\n      pg_type t ON e.enumtypid = t.oid\n    JOIN\n      pg_namespace n ON t.typnamespace = n.oid\n    ORDER BY\n      schema_name,\n      enum_type,\n      sort_order;\n    ;\n  ";
          _context5.next = 3;
          return client.query(enumListSql);
        case 3:
          enumListResult = _context5.sent;
          enums = enumListResult.rows.reduce(function (acc, row) {
            var schema_name = row.schema_name,
              enum_type = row.enum_type,
              enum_value = row.enum_value;
            if (!acc[enum_type]) {
              acc[enum_type] = {
                name: enum_type,
                schemaName: schema_name,
                values: []
              };
            }
            acc[enum_type].values.push({
              name: enum_value
            });
            return acc;
          }, {});
          return _context5.abrupt("return", Object.values(enums));
        case 6:
        case "end":
          return _context5.stop();
      }
    }, _callee5);
  }));
  return function generateRawEnums(_x5) {
    return _ref5.apply(this, arguments);
  };
}();
var fetchSchemaJson = /*#__PURE__*/function () {
  var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(connection) {
    var client, tablesAndFieldsRes, indexesRes, refsRes, enumsRes, res, _res$, tables, fields, _res$2, indexes, tableConstraints, refs, enums;
    return _regeneratorRuntime().wrap(function _callee6$(_context6) {
      while (1) switch (_context6.prev = _context6.next) {
        case 0:
          _context6.next = 2;
          return getValidatedClient(connection);
        case 2:
          client = _context6.sent;
          tablesAndFieldsRes = generateTablesAndFields(client);
          indexesRes = generateIndexes(client);
          refsRes = generateRawRefs(client);
          enumsRes = generateRawEnums(client);
          _context6.next = 9;
          return Promise.all([tablesAndFieldsRes, indexesRes, refsRes, enumsRes]);
        case 9:
          res = _context6.sent;
          client.end();
          _res$ = res[0], tables = _res$.tables, fields = _res$.fields;
          _res$2 = res[1], indexes = _res$2.indexes, tableConstraints = _res$2.tableConstraints;
          refs = res[2];
          enums = res[3];
          return _context6.abrupt("return", {
            tables: tables,
            fields: fields,
            refs: refs,
            enums: enums,
            indexes: indexes,
            tableConstraints: tableConstraints
          });
        case 16:
        case "end":
          return _context6.stop();
      }
    }, _callee6);
  }));
  return function fetchSchemaJson(_x6) {
    return _ref6.apply(this, arguments);
  };
}();
exports.fetchSchemaJson = fetchSchemaJson;