n8n
Version:
n8n Workflow Automation Tool
260 lines • 9.35 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.toDslColumns = toDslColumns;
exports.isValidColumnName = isValidColumnName;
exports.addColumnQuery = addColumnQuery;
exports.deleteColumnQuery = deleteColumnQuery;
exports.renameColumnQuery = renameColumnQuery;
exports.quoteIdentifier = quoteIdentifier;
exports.extractReturningData = extractReturningData;
exports.extractInsertedIds = extractInsertedIds;
exports.normalizeRows = normalizeRows;
exports.normalizeValueForDatabase = normalizeValueForDatabase;
exports.toSqliteGlobFromPercent = toSqliteGlobFromPercent;
exports.escapeLikeSpecials = escapeLikeSpecials;
exports.toTableName = toTableName;
exports.toTableId = toTableId;
const api_types_1 = require("@n8n/api-types");
const config_1 = require("@n8n/config");
const db_1 = require("@n8n/db");
const di_1 = require("@n8n/di");
const n8n_workflow_1 = require("n8n-workflow");
const not_found_error_1 = require("../../../errors/response-errors/not-found.error");
function toDslColumns(columns) {
return columns.map((col) => {
const name = new db_1.DslColumn(col.name.trim());
switch (col.type) {
case 'number':
return name.double;
case 'boolean':
return name.bool;
case 'string':
return name.text;
case 'date':
return name.timestampTimezone();
default:
return name.text;
}
});
}
function dataTableColumnTypeToSql(type, dbType) {
switch (type) {
case 'string':
return 'TEXT';
case 'number':
switch (dbType) {
case 'postgres':
return 'DOUBLE PRECISION';
case 'mysql':
case 'mariadb':
return 'DOUBLE';
case 'sqlite':
return 'REAL';
default:
return 'DOUBLE';
}
case 'boolean':
return 'BOOLEAN';
case 'date':
if (dbType === 'postgres') {
return 'TIMESTAMP';
}
return 'DATETIME';
default:
throw new not_found_error_1.NotFoundError(`Unsupported field type: ${type}`);
}
}
function columnToWildcardAndType(column, dbType) {
return `${quoteIdentifier(column.name, dbType)} ${dataTableColumnTypeToSql(column.type, dbType)}`;
}
function isValidColumnName(name) {
return api_types_1.dataTableColumnNameSchema.safeParse(name).success;
}
function addColumnQuery(tableName, column, dbType) {
if (!isValidColumnName(column.name)) {
throw new n8n_workflow_1.UnexpectedError(api_types_1.DATA_TABLE_COLUMN_ERROR_MESSAGE);
}
const quotedTableName = quoteIdentifier(tableName, dbType);
return `ALTER TABLE ${quotedTableName} ADD ${columnToWildcardAndType(column, dbType)}`;
}
function deleteColumnQuery(tableName, column, dbType) {
const quotedTableName = quoteIdentifier(tableName, dbType);
return `ALTER TABLE ${quotedTableName} DROP COLUMN ${quoteIdentifier(column, dbType)}`;
}
function renameColumnQuery(tableName, oldColumnName, newColumnName, dbType) {
if (!isValidColumnName(oldColumnName) || !isValidColumnName(newColumnName)) {
throw new n8n_workflow_1.UnexpectedError(api_types_1.DATA_TABLE_COLUMN_ERROR_MESSAGE);
}
const quotedTableName = quoteIdentifier(tableName, dbType);
const quotedOldName = quoteIdentifier(oldColumnName, dbType);
const quotedNewName = quoteIdentifier(newColumnName, dbType);
return `ALTER TABLE ${quotedTableName} RENAME COLUMN ${quotedOldName} TO ${quotedNewName}`;
}
function quoteIdentifier(name, dbType) {
switch (dbType) {
case 'mysql':
case 'mariadb':
return `\`${name}\``;
case 'postgres':
case 'sqlite':
default:
return `"${name}"`;
}
}
const isArrayOf = (data, itemGuard) => Array.isArray(data) && data.every(itemGuard);
const isNumber = (value) => {
return typeof value === 'number' && Number.isFinite(value);
};
const isDate = (value) => {
return value instanceof Date;
};
function hasInsertId(data) {
return typeof data === 'object' && data !== null && 'insertId' in data && isNumber(data.insertId);
}
function hasRowReturnData(data) {
return (typeof data === 'object' &&
data !== null &&
'id' in data &&
isNumber(data.id) &&
'createdAt' in data &&
(isDate(data.createdAt) || typeof data.createdAt === 'string') &&
'updatedAt' in data &&
(isDate(data.updatedAt) || typeof data.updatedAt === 'string'));
}
function hasRowId(data) {
return typeof data === 'object' && data !== null && 'id' in data && isNumber(data.id);
}
function extractReturningData(raw) {
if (!isArrayOf(raw, hasRowReturnData)) {
throw new n8n_workflow_1.UnexpectedError(`Expected INSERT INTO raw to be { id: number; createdAt: string; updatedAt: string }[] on Postgres or MariaDB. Is '${JSON.stringify(raw)}'`);
}
return raw;
}
function extractInsertedIds(raw, dbType) {
switch (dbType) {
case 'postgres':
case 'mariadb': {
if (!isArrayOf(raw, hasRowId)) {
throw new n8n_workflow_1.UnexpectedError(`Expected INSERT INTO raw to be { id: number }[] on Postgres or MariaDB. Is '${JSON.stringify(raw)}'`);
}
return raw.map((r) => r.id);
}
case 'mysql': {
if (!hasInsertId(raw)) {
throw new n8n_workflow_1.UnexpectedError('Expected INSERT INTO raw.insertId: number for MySQL');
}
return [raw.insertId];
}
case 'sqlite':
default: {
if (!isNumber(raw)) {
throw new n8n_workflow_1.UnexpectedError('Expected INSERT INTO raw to be a number for SQLite');
}
return [raw];
}
}
}
function normalizeDate(value) {
if (value instanceof Date)
return value;
if (typeof value === 'string') {
const parsed = new Date(value.endsWith('Z') ? value : value + 'Z');
if (!isNaN(parsed.getTime()))
return parsed;
}
if (typeof value === 'number') {
const parsed = new Date(value);
if (!isNaN(parsed.getTime()))
return parsed;
}
return null;
}
function normalizeRows(rows, columns) {
const typeMap = {
...Object.fromEntries(columns.map((col) => [col.name, col.type])),
...n8n_workflow_1.DATA_TABLE_SYSTEM_COLUMN_TYPE_MAP,
};
return rows.map((row) => {
const { id, createdAt, updatedAt, ...rest } = row;
const normalized = {
...rest,
id,
createdAt: normalizeDate(createdAt) ?? new Date(),
updatedAt: normalizeDate(updatedAt) ?? new Date(),
};
for (const [key, value] of Object.entries(rest)) {
const type = typeMap[key];
if (type === 'boolean') {
if (typeof value === 'boolean') {
normalized[key] = value;
}
else if (value === 1 || value === '1') {
normalized[key] = true;
}
else if (value === 0 || value === '0') {
normalized[key] = false;
}
}
if (type === 'date' && value !== null && value !== undefined) {
normalized[key] = normalizeDate(value) ?? value;
}
}
return normalized;
});
}
function formatDateForDatabase(value, dbType) {
let date;
if (value instanceof Date) {
date = value;
}
else if (typeof value === 'string') {
date = new Date(value);
}
else {
throw new n8n_workflow_1.UnexpectedError(`Expected Date object or ISO date string, got ${typeof value}: ${String(value)}`);
}
if (isNaN(date.getTime())) {
throw new n8n_workflow_1.UnexpectedError(`Invalid date: ${String(value)}`);
}
if (dbType && ['sqlite', 'sqlite-pooled', 'mysql', 'mariadb'].includes(dbType)) {
return date.toISOString().replace('T', ' ').replace('Z', '');
}
return date.toISOString();
}
function normalizeValueForDatabase(value, columnType, dbType) {
if (columnType === 'date' && value !== null) {
return formatDateForDatabase(value, dbType);
}
return value;
}
function toSqliteGlobFromPercent(input) {
const out = [];
for (const ch of String(input ?? '')) {
if (ch === '%')
out.push('*');
else if (ch === '[')
out.push('[[]');
else if (ch === ']')
out.push('[]]');
else if (ch === '*')
out.push('[*]');
else if (ch === '?')
out.push('[?]');
else
out.push(ch);
}
return out.join('');
}
function escapeLikeSpecials(input) {
return input
.replace(/\\/g, '\\\\')
.replace(/_/g, '\\_');
}
function toTableName(dataTableId) {
const { tablePrefix } = di_1.Container.get(config_1.GlobalConfig).database;
return `${tablePrefix}data_table_user_${dataTableId}`;
}
function toTableId(tableName) {
return tableName.replace(/.*data_table_user_/, '');
}
//# sourceMappingURL=sql-utils.js.map