libpiggy
Version:
Use a PostgreSQL database like a JSON document store.
94 lines (77 loc) • 1.92 kB
JavaScript
import defaultsDeep from 'lodash/defaultsDeep';
import isString from 'lodash/isString';
import isNumber from 'lodash/isNumber';
import createClient from './create-client';
import get from './get';
import set from './set';
const getText = function ({table, existingKey, columnNames}) {
return `UPDATE "${table}" SET ("${columnNames.val}", "${columnNames.updatedAt}") = ($1, current_timestamp) WHERE "${columnNames.key}" = '${existingKey}';`;
};
const getVal = function ({existingVal, newVal, merge}) {
let val = {};
if (merge && existingVal) {
val = defaultsDeep({}, newVal, existingVal);
} else {
val = newVal;
}
return val;
};
const upsert = async function ({
store,
client,
table,
key,
not,
val: newVal,
options,
generateKeyFn
}, globals) {
let clientCreated = false;
try {
if (!client) {
client = await createClient(options, globals);
clientCreated = true;
}
const {columnNames} = store.settings;
const {merge} = options || {};
let existing;
if (key) {
existing = await get({store, client, table, key, not, options});
}
if (!existing || !existing.key) {
let newKey;
if (isString(key) || isNumber(key)) {
newKey = key;
}
return set({
store,
client,
table,
key: newKey,
val: newVal,
options,
generateKeyFn
});
}
const existingKey = existing.key;
const existingVal = existing.val;
const text = getText({table, existingKey, columnNames});
const val = getVal({existingVal, newVal, merge});
const values = [val];
await client.query({text, values});
return get({
store,
client,
table,
key: existingKey,
options
});
} catch (error) {
throw error;
} finally {
if (clientCreated && client) {
client.close();
}
}
};
export default upsert;