diff --git a/src/error.js b/src/error.js index 82db93f..b921d7c 100644 --- a/src/error.js +++ b/src/error.js @@ -1,13 +1,6 @@ 'use strict' -const isPlainObject = value => { - if (!value || typeof value !== 'object' || value.toString() !== '[object Object]') { - return false - } - - const prototype = Object.getPrototypeOf(value) - return prototype === null || prototype === Object.prototype -} +const { isPlainObject } = require('./util') class OpenKeyError extends Error { constructor (props) { @@ -29,15 +22,15 @@ const errors = [ ['METADATA_NOT_FLAT_OBJECT', () => 'The metadata must be a flat object.'], ['METADATA_INVALID', key => `The metadata field '${key}' can't be an object.`] ].reduce((acc, [code, message]) => { - acc[code] = (...input) => new OpenKeyError({ code, message: message(...input) }) + acc[code] = args => new OpenKeyError({ code, message: message.apply(null, args()) }) return acc }, {}) -const assert = (condition, code, ...opts) => { +const assert = (condition, code, args = () => []) => { return ( condition || (() => { - throw errors[code].apply(null, opts) + throw errors[code](args) })() ) } @@ -46,7 +39,7 @@ const assertMetadata = metadata => { if (metadata) { assert(isPlainObject(metadata), 'METADATA_NOT_FLAT_OBJECT') Object.keys(metadata).forEach(key => { - assert(!isPlainObject(metadata[key]), 'METADATA_INVALID', key) + assert(!isPlainObject(metadata[key]), 'METADATA_INVALID', () => [key]) if (metadata[key] === undefined) delete metadata[key] }) return Object.keys(metadata).length ? metadata : undefined diff --git a/src/keys.js b/src/keys.js index 584c989..c3e752a 100644 --- a/src/keys.js +++ b/src/keys.js @@ -41,7 +41,7 @@ module.exports = ({ serialize, deserialize, plans, redis, prefix } = {}) => { */ const retrieve = async (value, { throwError = false } = {}) => { const key = await redis.get(prefixKey(value)) - if (throwError) assert(key !== null, 'KEY_NOT_EXIST', value) + if (throwError) assert(key !== null, 'KEY_NOT_EXIST', () => [value]) else if (key === null) return null return Object.assign({ value }, deserialize(key)) } @@ -55,7 +55,7 @@ module.exports = ({ serialize, deserialize, plans, redis, prefix } = {}) => { */ const del = async value => { const isDeleted = (await redis.del(prefixKey(value))) === 1 - assert(isDeleted, 'KEY_NOT_EXIST', value) + assert(isDeleted, 'KEY_NOT_EXIST', () => [value]) return isDeleted } diff --git a/src/plans.js b/src/plans.js index 1f05e66..d5e9795 100644 --- a/src/plans.js +++ b/src/plans.js @@ -31,7 +31,7 @@ module.exports = ({ serialize, deserialize, redis, keys, prefix } = {}) => { if (metadata) plan.metadata = metadata plan.createdAt = plan.updatedAt = Date.now() const isCreated = (await redis.set(prefixKey(opts.id), serialize(plan), 'NX')) === 'OK' - assert(isCreated, 'PLAN_ALREADY_EXIST', opts.id) + assert(isCreated, 'PLAN_ALREADY_EXIST', () => [opts.id]) return Object.assign({ id: opts.id }, plan) } @@ -47,7 +47,7 @@ module.exports = ({ serialize, deserialize, redis, keys, prefix } = {}) => { */ const retrieve = async (id, { throwError = false } = {}) => { const plan = await redis.get(prefixKey(id)) - if (throwError) assert(plan !== null, 'PLAN_NOT_EXIST', id) + if (throwError) assert(plan !== null, 'PLAN_NOT_EXIST', () => [id]) else if (plan === null) return null return Object.assign({ id }, deserialize(plan)) } @@ -63,10 +63,9 @@ module.exports = ({ serialize, deserialize, redis, keys, prefix } = {}) => { const del = async id => { const allKeys = await keys().list() const key = allKeys.find(key => key.plan === id) - // TODO: try to improve this - assert(key === undefined, 'KEY_IS_ASSOCIATED', id, key?.value) + assert(key === undefined, 'KEY_IS_ASSOCIATED', () => [id, key.value]) const isDeleted = (await redis.del(prefixKey(id))) === 1 - assert(isDeleted, 'PLAN_NOT_EXIST', id) + assert(isDeleted, 'PLAN_NOT_EXIST', () => [id]) return isDeleted } diff --git a/src/stats.js b/src/stats.js index ef0db9e..11b9402 100644 --- a/src/stats.js +++ b/src/stats.js @@ -3,17 +3,11 @@ const { promisify } = require('util') const stream = require('stream') -const { Transform } = stream +const { formatYYYMMDDDate } = require('./util') +const { Transform } = stream const pipeline = promisify(stream.pipeline) -const formatYYYMMDDDate = (now = new Date()) => { - const year = now.getFullYear() - const month = String(now.getMonth() + 1).padStart(2, '0') - const day = String(now.getDate()).padStart(2, '0') - return `${year}-${month}-${day}` -} - /** * 90 days in milliseconds */ diff --git a/src/util.js b/src/util.js index a33fead..ed22daa 100644 --- a/src/util.js +++ b/src/util.js @@ -20,26 +20,11 @@ const pick = (obj, keys) => { return result } -/** - * Assert a condition, or throw an error if the condition is falsy. - * @param {*} value - The value to assert. - * @param {string} message - The error message. - */ -const assert = (value, message) => - value || - (() => { - throw new TypeError(message()) - })() - -const assertMetadata = metadata => { - if (metadata) { - assert(isPlainObject(metadata), () => 'The metadata must be a flat object.') - Object.keys(metadata).forEach(key => { - assert(!isPlainObject(metadata[key]), () => `The metadata field '${key}' can't be an object.`) - if (metadata[key] === undefined) delete metadata[key] - }) - return Object.keys(metadata).length ? metadata : undefined - } +const formatYYYMMDDDate = (now = new Date()) => { + const year = now.getFullYear() + const month = String(now.getMonth() + 1).padStart(2, '0') + const day = String(now.getDate()).padStart(2, '0') + return `${year}-${month}-${day}` } const isPlainObject = value => { @@ -52,8 +37,8 @@ const isPlainObject = value => { } module.exports = { - assert, - assertMetadata, + formatYYYMMDDDate, + isPlainObject, pick, uid }