"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.execute = execute;
exports.sql = sql;
exports.findValue = findValue;
exports.insert = insert;
exports.insertMany = insertMany;
exports.upsert = upsert;
exports.upsertIf = upsertIf;
exports.upsertMany = upsertMany;
exports.describeTable = describeTable;
exports.insertTable = insertTable;
exports.modifyTable = modifyTable;
Object.defineProperty(exports, "alterState", {
enumerable: true,
get: function get() {
return _languageCommon.alterState;
}
});
Object.defineProperty(exports, "fn", {
enumerable: true,
get: function get() {
return _languageCommon.fn;
}
});
Object.defineProperty(exports, "combine", {
enumerable: true,
get: function get() {
return _languageCommon.combine;
}
});
Object.defineProperty(exports, "dataPath", {
enumerable: true,
get: function get() {
return _languageCommon.dataPath;
}
});
Object.defineProperty(exports, "dataValue", {
enumerable: true,
get: function get() {
return _languageCommon.dataValue;
}
});
Object.defineProperty(exports, "each", {
enumerable: true,
get: function get() {
return _languageCommon.each;
}
});
Object.defineProperty(exports, "field", {
enumerable: true,
get: function get() {
return _languageCommon.field;
}
});
Object.defineProperty(exports, "fields", {
enumerable: true,
get: function get() {
return _languageCommon.fields;
}
});
Object.defineProperty(exports, "http", {
enumerable: true,
get: function get() {
return _languageCommon.http;
}
});
Object.defineProperty(exports, "lastReferenceValue", {
enumerable: true,
get: function get() {
return _languageCommon.lastReferenceValue;
}
});
Object.defineProperty(exports, "merge", {
enumerable: true,
get: function get() {
return _languageCommon.merge;
}
});
Object.defineProperty(exports, "sourceValue", {
enumerable: true,
get: function get() {
return _languageCommon.sourceValue;
}
});
var _languageCommon = require("@openfn/language-common");
var _url = require("url");
var _tedious = require("tedious");
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
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 ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
/**
* Creates a connection.
* @example
* createConnection(state)
* @function
* @param {State} state - Runtime state.
* @returns {State}
*/
function createConnection(state) {
var _state$configuration = state.configuration,
server = _state$configuration.server,
userName = _state$configuration.userName,
password = _state$configuration.password,
database = _state$configuration.database;
if (!server) {
throw new Error('server missing from configuration.');
}
var config = {
authentication: {
options: {
userName: userName,
password: password
},
type: 'default'
},
server: server,
options: {
database: database,
encrypt: true,
rowCollectionOnRequestCompletion: true
}
};
var connection = new _tedious.Connection(config); // Attempt to connect and execute queries if connection goes through
return new Promise(function (resolve, reject) {
connection.on('connect', function (err) {
if (err) {
console.error(err.message);
reject(err);
} else {
resolve(_objectSpread(_objectSpread({}, state), {}, {
connection: connection
}));
}
});
});
}
/**
* Execute a sequence of operations.
* Wraps `language-common/execute`, and prepends initial state for mssql.
* @example
* execute(
* create('foo'),
* delete('bar')
* )(state)
* @constructor
* @param {Operations} operations - Operations to be performed.
* @returns {Operation}
*/
function execute() {
for (var _len = arguments.length, operations = new Array(_len), _key = 0; _key < _len; _key++) {
operations[_key] = arguments[_key];
}
var initialState = {
references: [],
data: null,
queries: []
};
return function (state) {
return _languageCommon.execute.apply(void 0, [createConnection].concat(operations, [cleanupState]))(_objectSpread(_objectSpread({}, initialState), state))["catch"](function (e) {
console.error(e);
console.error('Unhandled error in the operations. Exiting process.');
process.exit(1);
});
};
}
/**
* Removes unserializable keys from the state.
* @example
* cleanupState(state)
* @function
* @param {State} state
* @returns {State}
*/
function cleanupState(state) {
if (state.connection) {
state.connection.close();
}
delete state.connection;
return state;
}
/**
* Sets the returned rows from a query as the first item in the state.references
* array, leaving state.data unchanged between operations.
* @function
* @param {State} state
* @param {array} rows - the array of rows returned from the sql query
* @returns {State}
*/
function addRowsToRefs(state, rows) {
return _objectSpread(_objectSpread({}, state), {}, {
references: [rows].concat(_toConsumableArray(state.references))
});
}
/**
* Returns a flatten object of the rows (array of arrays) with rowCount.
* @function
* @param {State} state
* @param {array} rows - the array of rows returned from the sql query
* @returns {State}
*/
function flattenRows(state, rows) {
var obj = [];
rows.forEach(function (row) {
return obj.push({
column_name: row[0].value
});
});
var data = {
rowCount: rows.length,
rows: obj
};
return _objectSpread(_objectSpread({}, state), {}, {
response: {
body: data
}
});
}
function composeNextState(state, rows) {
var obj = {};
rows.forEach(function (row) {
row.forEach(function (col) {
obj[col.metadata.colName] = col.value;
});
});
return _objectSpread(_objectSpread({}, state), {}, {
response: {
body: obj
}
});
}
function queryHandler(state, query, callback, options) {
var connection = state.connection;
return new Promise(function (resolve, reject) {
if (options) {
if (options.writeSql) {
console.log('Adding prepared SQL to state.queries array.');
state.queries.push(query);
}
if (options.execute === false) {
console.log('Not executing query; options.execute === false');
resolve(state);
return state;
}
}
var request = new _tedious.Request(query, function (err, rowCount, rows) {
if (err) {
console.error(err.message);
throw err;
} else {
console.log("Finished: ".concat(rowCount, " row(s)."));
resolve(callback(state, rows));
}
});
connection.execSql(request);
});
}
/**
* Execute an SQL statement
* @public
* @example
* execute(
* sql(sqlQuery)
* )(state)
* @constructor
* @param {object} params - Payload data for the message
* @returns {Operation}
*/
function sql(params) {
return function (state) {
var connection = state.connection;
try {
var _expandReferences = (0, _languageCommon.expandReferences)(params)(state),
query = _expandReferences.query,
options = _expandReferences.options;
console.log("Preparing to execute sql statement: ".concat(query));
return queryHandler(state, query, composeNextState, options);
} catch (e) {
connection.close();
throw e;
}
};
}
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
function handleValues(sqlString, nullString) {
var sql = sqlString;
if (nullString == false) {
return sqlString;
} else if (Array.isArray(nullString)) {
nullString.forEach(function (ns) {
var re = new RegExp(escapeRegExp(ns), 'g');
sql = sql.replace(re, 'NULL');
});
return sql;
} else if (_typeof(nullString) === 'object') {
throw 'setNull must be a string or an array of strings.';
}
var re = new RegExp(escapeRegExp(nullString), 'g');
return sqlString.replace(re, 'NULL');
}
function handleOptions(options) {
if (options && options.setNull === false) {
return false;
}
return options && options.setNull || "'undefined'";
}
function escapeQuote(stringExp) {
if (_typeof(stringExp) === 'object' && stringExp !== null) {
return Object.values(stringExp).map(function (x) {
return escapeQuote(x);
});
} else if (typeof stringExp !== 'string') {
return stringExp;
}
return stringExp.replace(/\'/g, "''");
}
/**
* Fetch a uuid key given a condition
* @public
* @example
* findValue({
* uuid: 'id',
* relation: 'users',
* where: { first_name: 'Mama%', last_name: 'Cisse'},
* operator: { first_name: 'like', last_name: '='}
* })
* @constructor
* @param {object} filter - A filter object with the lookup table, a uuid and the condition
* @returns {Operation}
*/
function findValue(filter) {
return function (state) {
var connection = state.connection;
var uuid = filter.uuid,
relation = filter.relation,
where = filter.where,
operator = filter.operator;
var whereData = (0, _languageCommon.expandReferences)(where)(state);
var operatorData = (0, _languageCommon.expandReferences)(operator)(state);
var conditionsArray = [];
for (var key in whereData) {
conditionsArray.push("".concat(key, " ").concat(operatorData ? operatorData[key] : '=', " '").concat(whereData[key], "'"));
}
var condition = conditionsArray.length > 0 ? "where ".concat(conditionsArray.join(' and ')) : ''; // In a near future the 'and' can live in the filter.
try {
var body = "select ".concat(uuid, " from ").concat(relation, " ").concat(condition);
console.log('Preparing to execute sql statement');
var returnValue = null;
return new Promise(function (resolve, reject) {
console.log("Executing query: ".concat(body));
var request = new _tedious.Request(body, function (err, rowCount, rows) {
if (err) {
console.error(err.message);
throw err;
} else {
if (rows.length > 0) {
returnValue = rows[0][0].value;
}
if (returnValue === null) resolve(undefined);
resolve(returnValue);
}
});
connection.execSql(request);
});
} catch (e) {
connection.close();
throw e;
}
};
}
/**
* Insert a record
* @public
* @example
* execute(
* insert(table, record, {setNull: ["'undefined'", "''"], logValues: false})
* )(state)
* @constructor
* @param {string} table - The target table
* @param {object} record - Payload data for the record as a JS object
* @param {object} options - Optional options argument
* @returns {Operation}
*/
function insert(table, record, options) {
return function (state) {
var connection = state.connection;
try {
var recordData = (0, _languageCommon.expandReferences)(record)(state);
var columns = Object.keys(recordData).sort();
var values = columns.map(function (key) {
return escapeQuote(recordData[key]);
}).join("', '");
var query = handleValues("INSERT INTO ".concat(table, " (").concat(columns.join(', '), ") VALUES ('").concat(values, "');"), handleOptions(options));
var safeQuery = "INSERT INTO ".concat(table, " (").concat(columns.join(', '), ") VALUES [--REDACTED--]];");
return new Promise(function (resolve, reject) {
var queryToLog = options && options.logValues ? query : safeQuery;
console.log("Executing insert via: ".concat(queryToLog));
resolve(queryHandler(state, query, addRowsToRefs, options));
});
} catch (e) {
connection.close();
throw e;
}
};
}
/**
* Insert many records, using the keys of the first as the column template
* @public
* @example
* execute(
* insertMany(table, records, { setNull: false, writeSql: true, logValues: false })
* )(state)
* @constructor
* @param {string} table - The target table
* @param {function} records - A function that takes state and returns an array of records
* @param {object} options - Optional options argument
* @returns {Operation}
*/
function insertMany(table, records, options) {
return function (state) {
var connection = state.connection;
try {
var recordData = (0, _languageCommon.expandReferences)(records)(state); // Note: we select the keys of the FIRST object as the canonical template.
var columns = Object.keys(recordData[0]);
var valueSets = recordData.map(function (x) {
return "('".concat(escapeQuote(Object.values(x)).join("', '"), "')");
});
var query = handleValues("INSERT INTO ".concat(table, " (").concat(columns.join(', '), ") VALUES ").concat(valueSets.join(', '), ";"), handleOptions(options));
var safeQuery = "INSERT INTO ".concat(table, " (").concat(columns.join(', '), ") VALUES [--REDACTED--]];");
return new Promise(function (resolve, reject) {
var queryToLog = options && options.logValues ? query : safeQuery;
console.log("Executing insertMany via: ".concat(queryToLog));
resolve(queryHandler(state, query, addRowsToRefs, options));
});
} catch (e) {
connection.close();
throw e;
}
};
}
/**
* Insert or update a record using SQL MERGE
* @public
* @example
* execute(
* upsert(table, uuid, record, { setNull: "'undefined'", logValues: false})
* )(state)
* execute(
* upsert(table, [uuid1, uuid2], record, { setNull: "'undefined'", logValues: false})
* )(state)
* @constructor
* @param {string} table - The target table
* @param {string} uuid - The uuid column to determine a matching/existing record
* @param {object} record - Payload data for the record as a JS object
* @param {object} options - Optional options argument
* @returns {Operation}
*/
function upsert(table, uuid, record, options) {
return function (state) {
var connection = state.connection;
try {
var recordData = (0, _languageCommon.expandReferences)(record)(state);
var columns = Object.keys(recordData).sort();
var selectValues = columns.map(function (key) {
return "'".concat(escapeQuote(recordData[key]), "' AS ").concat(key);
}).join(', ');
var updateValues = columns.map(function (key) {
return "[Target].".concat(key, "='").concat(escapeQuote(recordData[key]), "'");
}).join(', ');
var insertColumns = columns.join(', ');
var insertValues = columns.map(function (key) {
return "[Source].".concat(key);
}).join(', ');
var constraint = [];
if (Array.isArray(uuid)) {
uuid.forEach(function (key) {
constraint.push("[Target].".concat(key, " = [Source].").concat(key));
});
} else {
constraint.push("[Target].".concat(uuid, " = [Source].").concat(uuid));
}
var query = handleValues("MERGE ".concat(table, " AS [Target]\n USING (SELECT ").concat(selectValues, ") AS [Source] \n ON ").concat(constraint.join(' AND '), "\n WHEN MATCHED THEN\n UPDATE SET ").concat(updateValues, " \n WHEN NOT MATCHED THEN\n INSERT (").concat(insertColumns, ") VALUES (").concat(insertValues, ");"), handleOptions(options));
var safeQuery = "MERGE ".concat(table, " AS [Target]\n USING (SELECT [--REDACTED--]) \n ON [Target].[--VALUE--] = [Source].[--VALUE--]\n WHEN MATCHED THEN\n UPDATE SET [--REDACTED--] \n WHEN NOT MATCHED THEN\n INSERT (").concat(insertColumns, ") VALUES [--REDACTED--];");
return new Promise(function (resolve, reject) {
var queryToLog = options && options.logValues ? query : safeQuery;
console.log("Executing upsert via: ".concat(queryToLog));
resolve(queryHandler(state, query, addRowsToRefs, options));
});
} catch (e) {
connection.close();
throw e;
}
};
}
/**
* Insert or update a record based on a logical condition using ON CONFLICT UPDATE
* @public
* @example
* upsertIf(
* dataValue('name'),
* 'users', // the DB table
* 'uuid', // a DB column with a unique constraint
* { name: 'Elodie', id: 7 },
* { writeSql:true, execute: true, logValues: false }
* )
* @constructor
* @param {string} logical - a data to check existing value for.
* @param {string} table - The target table
* @param {string} uuid - The uuid column to determine a matching/existing record
* @param {object} record - Payload data for the record as a JS object or function
* @param {object} options - Optional options argument
* @returns {Operation}
*/
function upsertIf(logical, table, uuid, record, options) {
return function (state) {
var connection = state.connection;
try {
var recordData = (0, _languageCommon.expandReferences)(record)(state);
var columns = Object.keys(recordData).sort();
var logicalData = (0, _languageCommon.expandReferences)(logical)(state);
return new Promise(function (resolve, reject) {
if (!logicalData) {
console.log("Skipping upsert for ".concat(uuid, "."));
resolve(state);
return state;
}
var selectValues = columns.map(function (key) {
return "'".concat(escapeQuote(recordData[key]), "' AS ").concat(key);
}).join(', ');
var updateValues = columns.map(function (key) {
return "[Target].".concat(key, "='").concat(escapeQuote(recordData[key]), "'");
}).join(', ');
var insertColumns = columns.join(', ');
var insertValues = columns.map(function (key) {
return "[Source].".concat(key);
}).join(', ');
var constraint = [];
if (Array.isArray(uuid)) {
uuid.forEach(function (key) {
constraint.push("[Target].".concat(key, " = [Source].").concat(key));
});
} else {
constraint.push("[Target].".concat(uuid, " = [Source].").concat(uuid));
}
var query = handleValues("MERGE ".concat(table, " AS [Target]\n USING (SELECT ").concat(selectValues, ") AS [Source] \n ON ").concat(constraint.join(' AND '), "\n WHEN MATCHED THEN\n UPDATE SET ").concat(updateValues, " \n WHEN NOT MATCHED THEN\n INSERT (").concat(insertColumns, ") VALUES (").concat(insertValues, ");"), handleOptions(options));
var safeQuery = "MERGE ".concat(table, " AS [Target]\n USING (SELECT [--REDACTED--]) \n ON [Target].[--VALUE--] = [Source].[--VALUE--]\n WHEN MATCHED THEN\n UPDATE SET [--REDACTED--] \n WHEN NOT MATCHED THEN\n INSERT (").concat(insertColumns, ") VALUES [--REDACTED--];");
var queryToLog = options && options.logValues ? query : safeQuery;
console.log("Executing upsertIf via: ".concat(queryToLog));
resolve(queryHandler(state, query, addRowsToRefs, options));
});
} catch (e) {
connection.close();
throw e;
}
};
}
/**
* Insert or update multiple records using ON CONFLICT UPDATE and excluded
* @public
* @example
* upsertMany(
* 'users', 'email', records, { logValues: false }
* )
* upsertMany(
* 'users', ['email', 'phone'], records, { logValues: false }
* )
* @constructor
* @param {string} table - The target table
* @param {string} uuid - The uuid column to determine a matching/existing record
* @param {function} records - A function that takes state and returns an array of records
* @param {object} options - Optional options argument
* @returns {Operation}
*/
function upsertMany(table, uuid, records, options) {
return function (state) {
var connection = state.connection;
try {
var recordData = (0, _languageCommon.expandReferences)(records)(state);
return new Promise(function (resolve, reject) {
if (!recordData || recordData.length === 0) {
console.log('No records provided; skipping upsert.');
resolve(state);
} // Note: we select the keys of the FIRST object as the canonical template.
var columns = Object.keys(recordData[0]);
var valueSets = recordData.map(function (x) {
return "('".concat(escapeQuote(Object.values(x)).join("', '"), "')");
});
var insertColumns = columns.join(', ');
var insertValues = columns.map(function (key) {
return "[Source].".concat(key);
}).join(', ');
var updateValues = columns.map(function (key) {
return "[Target].".concat(key, "=[Source].").concat(key);
}).join(', ');
var constraint = [];
if (Array.isArray(uuid)) {
uuid.forEach(function (key) {
constraint.push("[Target].".concat(key, " = [Source].").concat(key));
});
} else {
constraint.push("[Target].".concat(uuid, " = [Source].").concat(uuid));
}
var query = handleValues("MERGE ".concat(table, " AS [Target]\n USING (VALUES ").concat(valueSets.join(', '), ") AS [Source] (").concat(insertColumns, ")\n ON ").concat(constraint.join(' AND '), "\n WHEN MATCHED THEN\n UPDATE SET ").concat(updateValues, "\n WHEN NOT MATCHED THEN\n INSERT (").concat(insertColumns, ") VALUES (").concat(insertValues, ");"), handleOptions(options));
var safeQuery = "MERGE ".concat(table, " AS [Target]\n USING (VALUES [--REDACTED--]) AS [SOURCE] (").concat(insertColumns, ")\n ON [Target].[--VALUE--] = [Source].[--VALUE--]\n WHEN MATCHED THEN\n UPDATE SET [--REDACTED--] \n WHEN NOT MATCHED THEN\n INSERT (").concat(insertColumns, ") VALUES [--REDACTED--];");
var queryToLog = options && options.logValues ? query : safeQuery;
console.log("Executing upsertMany via: ".concat(queryToLog));
resolve(queryHandler(state, query, addRowsToRefs, options));
});
} catch (e) {
connection.close();
throw e;
}
};
}
/**
* List the columns of a table in a database.
* @public
* @example
* describeTable('clinic_visits')
* @constructor
* @param {string} tableName - The name of the table to describe
* @param {object} options - Optional options argument
* @returns {Operation}
*/
function describeTable(tableName, options) {
return function (state) {
var connection = state.connection;
var name = (0, _languageCommon.expandReferences)(tableName)(state);
try {
var query = "SELECT column_name\n FROM information_schema.columns \n WHERE table_name = '".concat(name, "'\n ORDER BY ordinal_position");
console.log('Preparing to describe table via:', query);
return queryHandler(state, query, flattenRows, options);
} catch (e) {
connection.close();
throw e;
}
};
}
/**
* Create a table in database when given an array of columns and a table_name.
* @public
* @example
* insertTable('table_name', state => state.data.map(
* column => ({
* name: column.name,
* type: column.type,
* required: true, // optional
* unique: false, // optional - to be set to true for unique constraint
* })
* ));
* @constructor
* @param {string} tableName - The name of the table to create
* @param {array} columns - An array of form columns
* @param {object} options - Optional options argument
* @returns {Operation}
*/
function insertTable(tableName, columns, options) {
return function (state) {
var connection = state.connection;
try {
var data = (0, _languageCommon.expandReferences)(columns)(state);
return new Promise(function (resolve, reject) {
if (!data || data.length === 0) {
console.log('No columns provided; skipping table creation.');
resolve(state);
return state;
}
var structureData = data.map(function (x) {
return "".concat(x.name, " ").concat(x.type, " ").concat(x.hasOwnProperty('default') ? x.type.includes('varchar') || x.type.includes('text') ? "DEFAULT '".concat(x["default"], "'") : "DEFAULT ".concat(x["default"]) : '', " ").concat(x.unique ? 'UNIQUE' : '', " ").concat(x.identity ? 'PRIMARY KEY IDENTITY (1,1)' : '', " ").concat(x.required ? 'NOT NULL' : '');
}).join(', ');
var query = "CREATE TABLE ".concat(tableName, " (\n ").concat(structureData, "\n );");
console.log('Preparing to create table via:', query);
resolve(queryHandler(state, query, flattenRows, options));
});
} catch (e) {
connection.close();
throw e;
}
};
}
/**
* Alter an existing table in the database.
* @public
* @example
* modifyTable('table_name', state => state.data.map(
* newColumn => ({
* name: newColumn.name,
* type: newColumn.type,
* required: true, // optional
* unique: false, // optional - to be set to true for unique constraint
* })
* ));
* @constructor
* @param {string} tableName - The name of the table to alter
* @param {array} columns - An array of form columns
* @param {object} options - Optional options argument
* @returns {Operation}
*/
function modifyTable(tableName, columns, options) {
return function (state) {
var connection = state.connection;
try {
var data = (0, _languageCommon.expandReferences)(columns)(state);
return new Promise(function (resolve, reject) {
if (!data || data.length === 0) {
console.log('No columns provided; skipping table modification.');
resolve(state);
return state;
}
var structureData = data.map(function (x) {
return "".concat(x.name, " ").concat(x.type, " ").concat(x.hasOwnProperty('default') ? x.type.includes('varchar') || x.type.includes('text') ? "DEFAULT '".concat(x["default"], "'") : "DEFAULT ".concat(x["default"]) : '', " ").concat(x.unique ? 'UNIQUE' : '', " ").concat(x.identity ? 'IDENTITY (1,1)' : '', " ").concat(x.required ? 'NOT NULL' : '');
}).join(', ');
var query = "ALTER TABLE ".concat(tableName, " ADD ").concat(structureData, ";");
console.log('Preparing to modify table via:', query);
resolve(queryHandler(state, query, flattenRows, options));
});
} catch (e) {
connection.close();
throw e;
}
};
}