@alinex/datastore
Version:
Read, work and write data structures from and to differents locations and formats.
121 lines • 4.33 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.modified = exports.save = exports.load = void 0;
const util_1 = require("util");
const debug_1 = require("debug");
const flat = require("flat");
const moment = require("moment");
const async_1 = require("@alinex/async");
let pg = require('pg');
try {
// if pg-native is installed, use it
require.resolve('pg-native');
pg = pg.native;
console.log('Using native pg!');
}
catch (e) { }
const debug = debug_1.default('datastore:protocol:psql');
const debugDetails = debug_1.default('datastore:details');
// postgres://user:pass@example.com:5432/dbname/schema.table#WHERE ...
// postgres://user:pass@example.com:5432/dbname#SELECT * FROM ...
function cast(value) {
if (value === '')
return null;
if (value === 'false')
return false;
if (value === 'true')
return true;
// string -> number
const n = Number(value);
if (!isNaN(n))
return n;
// string -> date
const d = moment(value);
if (d.isValid())
return d.toDate();
return value;
}
function toObject(arr, recordFormat) {
let res = recordFormat ? [] : {};
// console.log(res);
arr.forEach(row => {
if (recordFormat) {
res.push(flat.unflatten(row));
}
else {
const val = Object.values(row);
res[val[0]] = cast(val[1]);
}
});
return recordFormat ? res : flat.unflatten(res);
}
const load = function (parsedUri, options = {}) {
if (!parsedUri.pathname)
return Promise.reject(`No pathname given in ${parsedUri.href}`);
options.format = 'json';
debug(`loading ${parsedUri.protocol}//${parsedUri.username}@${parsedUri.host}${parsedUri.pathname}`);
// @ts-ignore
const defaultFallback = moment.createFromInputFallback;
// @ts-ignore
moment.createFromInputFallback = function (config) {
config._d = new Date(NaN);
};
const conn = `${parsedUri.protocol}//${parsedUri.username}:${parsedUri.password}@${parsedUri.host}${parsedUri.pathname}`;
const sql = decodeURI(parsedUri.hash.substring(1));
// debug(`conn ${conn}`);
debug(`query ${sql}`);
let client;
return (
// connect to database
async_1.default
.retry(() => {
client = new pg.Client({
connectionString: conn
});
return client.connect().catch((e) => {
debug(`WARN: ${e.message}`);
client.end();
return Promise.reject(e);
});
})
// query data
.then(() => options.search && client.query(`SET search_path TO ${options.search}`))
.then(() => client.query(sql))
.catch((e) => {
client.end();
console.error(e);
// @ts-ignore
moment.createFromInputFallback = defaultFallback;
return Promise.reject(e);
})
// process results
.then((res) => {
debugDetails(`postgres rows ${util_1.inspect(res.rowCount)}`);
debugDetails(`postgres result ${util_1.inspect(res.rows)}`);
const recordFormat = options.records || res.rows.length && Object.keys(res.rows[0]).length > 2;
return Promise.resolve(toObject(res.rows, recordFormat));
})
// end connection and return data
.then((data) => {
client.end();
// @ts-ignore
moment.createFromInputFallback = defaultFallback;
return Promise.resolve([Buffer.from(JSON.stringify(data)), {}]);
}));
};
exports.load = load;
const save = (function (parsedUri, buffer, options) {
if (!parsedUri.pathname)
return Promise.reject(`No pathname given in ${parsedUri.href}`);
debug(`storing to ${parsedUri.protocol}//${parsedUri.username}@${parsedUri.host}${parsedUri.pathname}`);
return Promise.reject(new Error('Save not implemented here!'));
});
exports.save = save;
const modified = async function (parsedUri, options) {
if (!parsedUri.pathname)
return Promise.reject(`No pathname given in ${parsedUri.href}`);
debug(`last modification check ${parsedUri.protocol}//${parsedUri.username}@${parsedUri.host}${parsedUri.pathname}`);
return Promise.resolve(new Date()); // always use current date
};
exports.modified = modified;
//# sourceMappingURL=postgres.js.map