229 lines
8.4 KiB
JavaScript
229 lines
8.4 KiB
JavaScript
"use strict";
|
|
/**
|
|
* Helpers to convert the change Payload into native JS types.
|
|
*/
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.httpEndpointURL = exports.toTimestampString = exports.toArray = exports.toJson = exports.toNumber = exports.toBoolean = exports.convertCell = exports.convertColumn = exports.convertChangeData = exports.PostgresTypes = void 0;
|
|
// Adapted from epgsql (src/epgsql_binary.erl), this module licensed under
|
|
// 3-clause BSD found here: https://raw.githubusercontent.com/epgsql/epgsql/devel/LICENSE
|
|
var PostgresTypes;
|
|
(function (PostgresTypes) {
|
|
PostgresTypes["abstime"] = "abstime";
|
|
PostgresTypes["bool"] = "bool";
|
|
PostgresTypes["date"] = "date";
|
|
PostgresTypes["daterange"] = "daterange";
|
|
PostgresTypes["float4"] = "float4";
|
|
PostgresTypes["float8"] = "float8";
|
|
PostgresTypes["int2"] = "int2";
|
|
PostgresTypes["int4"] = "int4";
|
|
PostgresTypes["int4range"] = "int4range";
|
|
PostgresTypes["int8"] = "int8";
|
|
PostgresTypes["int8range"] = "int8range";
|
|
PostgresTypes["json"] = "json";
|
|
PostgresTypes["jsonb"] = "jsonb";
|
|
PostgresTypes["money"] = "money";
|
|
PostgresTypes["numeric"] = "numeric";
|
|
PostgresTypes["oid"] = "oid";
|
|
PostgresTypes["reltime"] = "reltime";
|
|
PostgresTypes["text"] = "text";
|
|
PostgresTypes["time"] = "time";
|
|
PostgresTypes["timestamp"] = "timestamp";
|
|
PostgresTypes["timestamptz"] = "timestamptz";
|
|
PostgresTypes["timetz"] = "timetz";
|
|
PostgresTypes["tsrange"] = "tsrange";
|
|
PostgresTypes["tstzrange"] = "tstzrange";
|
|
})(PostgresTypes || (exports.PostgresTypes = PostgresTypes = {}));
|
|
/**
|
|
* Takes an array of columns and an object of string values then converts each string value
|
|
* to its mapped type.
|
|
*
|
|
* @param {{name: String, type: String}[]} columns
|
|
* @param {Object} record
|
|
* @param {Object} options The map of various options that can be applied to the mapper
|
|
* @param {Array} options.skipTypes The array of types that should not be converted
|
|
*
|
|
* @example convertChangeData([{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {first_name: 'Paul', age:'33'}, {})
|
|
* //=>{ first_name: 'Paul', age: 33 }
|
|
*/
|
|
const convertChangeData = (columns, record, options = {}) => {
|
|
var _a;
|
|
const skipTypes = (_a = options.skipTypes) !== null && _a !== void 0 ? _a : [];
|
|
return Object.keys(record).reduce((acc, rec_key) => {
|
|
acc[rec_key] = (0, exports.convertColumn)(rec_key, columns, record, skipTypes);
|
|
return acc;
|
|
}, {});
|
|
};
|
|
exports.convertChangeData = convertChangeData;
|
|
/**
|
|
* Converts the value of an individual column.
|
|
*
|
|
* @param {String} columnName The column that you want to convert
|
|
* @param {{name: String, type: String}[]} columns All of the columns
|
|
* @param {Object} record The map of string values
|
|
* @param {Array} skipTypes An array of types that should not be converted
|
|
* @return {object} Useless information
|
|
*
|
|
* @example convertColumn('age', [{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {first_name: 'Paul', age: '33'}, [])
|
|
* //=> 33
|
|
* @example convertColumn('age', [{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {first_name: 'Paul', age: '33'}, ['int4'])
|
|
* //=> "33"
|
|
*/
|
|
const convertColumn = (columnName, columns, record, skipTypes) => {
|
|
const column = columns.find((x) => x.name === columnName);
|
|
const colType = column === null || column === void 0 ? void 0 : column.type;
|
|
const value = record[columnName];
|
|
if (colType && !skipTypes.includes(colType)) {
|
|
return (0, exports.convertCell)(colType, value);
|
|
}
|
|
return noop(value);
|
|
};
|
|
exports.convertColumn = convertColumn;
|
|
/**
|
|
* If the value of the cell is `null`, returns null.
|
|
* Otherwise converts the string value to the correct type.
|
|
* @param {String} type A postgres column type
|
|
* @param {String} value The cell value
|
|
*
|
|
* @example convertCell('bool', 't')
|
|
* //=> true
|
|
* @example convertCell('int8', '10')
|
|
* //=> 10
|
|
* @example convertCell('_int4', '{1,2,3,4}')
|
|
* //=> [1,2,3,4]
|
|
*/
|
|
const convertCell = (type, value) => {
|
|
// if data type is an array
|
|
if (type.charAt(0) === '_') {
|
|
const dataType = type.slice(1, type.length);
|
|
return (0, exports.toArray)(value, dataType);
|
|
}
|
|
// If not null, convert to correct type.
|
|
switch (type) {
|
|
case PostgresTypes.bool:
|
|
return (0, exports.toBoolean)(value);
|
|
case PostgresTypes.float4:
|
|
case PostgresTypes.float8:
|
|
case PostgresTypes.int2:
|
|
case PostgresTypes.int4:
|
|
case PostgresTypes.int8:
|
|
case PostgresTypes.numeric:
|
|
case PostgresTypes.oid:
|
|
return (0, exports.toNumber)(value);
|
|
case PostgresTypes.json:
|
|
case PostgresTypes.jsonb:
|
|
return (0, exports.toJson)(value);
|
|
case PostgresTypes.timestamp:
|
|
return (0, exports.toTimestampString)(value); // Format to be consistent with PostgREST
|
|
case PostgresTypes.abstime: // To allow users to cast it based on Timezone
|
|
case PostgresTypes.date: // To allow users to cast it based on Timezone
|
|
case PostgresTypes.daterange:
|
|
case PostgresTypes.int4range:
|
|
case PostgresTypes.int8range:
|
|
case PostgresTypes.money:
|
|
case PostgresTypes.reltime: // To allow users to cast it based on Timezone
|
|
case PostgresTypes.text:
|
|
case PostgresTypes.time: // To allow users to cast it based on Timezone
|
|
case PostgresTypes.timestamptz: // To allow users to cast it based on Timezone
|
|
case PostgresTypes.timetz: // To allow users to cast it based on Timezone
|
|
case PostgresTypes.tsrange:
|
|
case PostgresTypes.tstzrange:
|
|
return noop(value);
|
|
default:
|
|
// Return the value for remaining types
|
|
return noop(value);
|
|
}
|
|
};
|
|
exports.convertCell = convertCell;
|
|
const noop = (value) => {
|
|
return value;
|
|
};
|
|
const toBoolean = (value) => {
|
|
switch (value) {
|
|
case 't':
|
|
return true;
|
|
case 'f':
|
|
return false;
|
|
default:
|
|
return value;
|
|
}
|
|
};
|
|
exports.toBoolean = toBoolean;
|
|
const toNumber = (value) => {
|
|
if (typeof value === 'string') {
|
|
const parsedValue = parseFloat(value);
|
|
if (!Number.isNaN(parsedValue)) {
|
|
return parsedValue;
|
|
}
|
|
}
|
|
return value;
|
|
};
|
|
exports.toNumber = toNumber;
|
|
const toJson = (value) => {
|
|
if (typeof value === 'string') {
|
|
try {
|
|
return JSON.parse(value);
|
|
}
|
|
catch (error) {
|
|
console.log(`JSON parse error: ${error}`);
|
|
return value;
|
|
}
|
|
}
|
|
return value;
|
|
};
|
|
exports.toJson = toJson;
|
|
/**
|
|
* Converts a Postgres Array into a native JS array
|
|
*
|
|
* @example toArray('{}', 'int4')
|
|
* //=> []
|
|
* @example toArray('{"[2021-01-01,2021-12-31)","(2021-01-01,2021-12-32]"}', 'daterange')
|
|
* //=> ['[2021-01-01,2021-12-31)', '(2021-01-01,2021-12-32]']
|
|
* @example toArray([1,2,3,4], 'int4')
|
|
* //=> [1,2,3,4]
|
|
*/
|
|
const toArray = (value, type) => {
|
|
if (typeof value !== 'string') {
|
|
return value;
|
|
}
|
|
const lastIdx = value.length - 1;
|
|
const closeBrace = value[lastIdx];
|
|
const openBrace = value[0];
|
|
// Confirm value is a Postgres array by checking curly brackets
|
|
if (openBrace === '{' && closeBrace === '}') {
|
|
let arr;
|
|
const valTrim = value.slice(1, lastIdx);
|
|
// TODO: find a better solution to separate Postgres array data
|
|
try {
|
|
arr = JSON.parse('[' + valTrim + ']');
|
|
}
|
|
catch (_) {
|
|
// WARNING: splitting on comma does not cover all edge cases
|
|
arr = valTrim ? valTrim.split(',') : [];
|
|
}
|
|
return arr.map((val) => (0, exports.convertCell)(type, val));
|
|
}
|
|
return value;
|
|
};
|
|
exports.toArray = toArray;
|
|
/**
|
|
* Fixes timestamp to be ISO-8601. Swaps the space between the date and time for a 'T'
|
|
* See https://github.com/supabase/supabase/issues/18
|
|
*
|
|
* @example toTimestampString('2019-09-10 00:00:00')
|
|
* //=> '2019-09-10T00:00:00'
|
|
*/
|
|
const toTimestampString = (value) => {
|
|
if (typeof value === 'string') {
|
|
return value.replace(' ', 'T');
|
|
}
|
|
return value;
|
|
};
|
|
exports.toTimestampString = toTimestampString;
|
|
const httpEndpointURL = (socketUrl) => {
|
|
let url = socketUrl;
|
|
url = url.replace(/^ws/i, 'http');
|
|
url = url.replace(/(\/socket\/websocket|\/socket|\/websocket)\/?$/i, '');
|
|
return url.replace(/\/+$/, '');
|
|
};
|
|
exports.httpEndpointURL = httpEndpointURL;
|
|
//# sourceMappingURL=transformers.js.map
|