diff --git a/packages/keyv-mongo/src/index.js b/packages/keyv-mongo/src/index.js
index ff808d2..5a1e63b 100644
--- a/packages/keyv-mongo/src/index.js
+++ b/packages/keyv-mongo/src/index.js
@@ -20,7 +20,8 @@ class KeyvMongo extends EventEmitter {
this.options = Object.assign(
{
url: 'mongodb://127.0.0.1:27017',
- collection: 'keyv'
+ collection: 'keyv',
+ emitErrors: true
},
url,
options
@@ -40,7 +41,7 @@ class KeyvMongo extends EventEmitter {
this.options.mongoOptions
)
} catch (error) {
- this.emit('error', error)
+ if (this.options.emitErrors) this.emit('error', error)
}
this.mongo = {}
@@ -76,13 +77,17 @@ class KeyvMongo extends EventEmitter {
}
if (!listeningEvents) {
- this.client.on('error', error => this.emit('error', error))
- listeningEvents = true
+ if (this.options.emitErrors) {
+ this.client.on('error', error => this.emit('error', error))
+ listeningEvents = true
+ }
}
resolve(this.store)
})
- .catch(error => this.emit('error', error))
+ .catch(error => {
+ if (this.options.emitErrors) this.emit('error', error)
+ })
})
}
diff --git a/packages/keyv-redis/src/index.js b/packages/keyv-redis/src/index.js
index 0e09c8f..ae752f7 100644
--- a/packages/keyv-redis/src/index.js
+++ b/packages/keyv-redis/src/index.js
@@ -5,7 +5,7 @@ const pEvent = require('p-event')
const Redis = require('ioredis')
class KeyvRedis extends EventEmitter {
- constructor (uri, options) {
+ constructor (uri, { emitErrors = true, ...options }) {
super()
if (uri instanceof Redis) {
@@ -19,7 +19,9 @@ class KeyvRedis extends EventEmitter {
this.redis = new Redis(options.uri, options)
}
- this.redis.on('error', error => this.emit('error', error))
+ if (emitErrors) {
+ this.redis.on('error', error => this.emit('error', error))
+ }
}
async get (key) {
diff --git a/packages/keyv-sql/src/index.js b/packages/keyv-sql/src/index.js
index 0f13091..2020283 100644
--- a/packages/keyv-sql/src/index.js
+++ b/packages/keyv-sql/src/index.js
@@ -6,33 +6,45 @@ class KeyvSql extends EventEmitter {
super()
this.ttlSupport = false
- this.options = Object.assign({
- table: 'keyv',
- keySize: 255,
- iterationLimit: 10
- }, options)
-
- const createTable = this.options.dialect === 'mysql' ? `CREATE TABLE IF NOT EXISTS \`${this.options.table}\` (\`key\` VARCHAR(${this.options.keySize}) PRIMARY KEY, \`value\` TEXT)` : `CREATE TABLE IF NOT EXISTS "${this.options.table}" ("key" VARCHAR(${this.options.keySize}) PRIMARY KEY, "value" TEXT)`
-
- const connected = this.options.connect()
+ this.options = Object.assign(
+ {
+ table: 'keyv',
+ keySize: 255,
+ iterationLimit: 10
+ },
+ options
+ )
+
+ const createTable =
+ this.options.dialect === 'mysql'
+ ? `CREATE TABLE IF NOT EXISTS \`${this.options.table}\` (\`key\` VARCHAR(${this.options.keySize}) PRIMARY KEY, \`value\` TEXT)`
+ : `CREATE TABLE IF NOT EXISTS "${this.options.table}" ("key" VARCHAR(${this.options.keySize}) PRIMARY KEY, "value" TEXT)`
+
+ const connected = this.options
+ .connect()
.then(query => query(createTable).then(() => query))
- .catch(error => this.emit('error', error))
+ .catch(error => {
+ if (this.options.emitErrors && typeof this.store.on === 'function') {
+ this.emit('error', error)
+ }
+ })
- this.query = sqlString => connected
- .then(query => query(sqlString))
+ this.query = sqlString => connected.then(query => query(sqlString))
}
get (key) {
- const select = this.options.dialect === 'mysql' ? `SELECT \`${this.options.table}\`.* FROM \`${this.options.table}\` WHERE (\`${this.options.table}\`.\`key\` = '${key}')` : `SELECT "${this.options.table}".* FROM "${this.options.table}" WHERE ("${this.options.table}"."key" = '${key}')`
- return this.query(select)
- .then(rows => {
- const row = rows[0]
- if (row === undefined) {
- return undefined
- }
+ const select =
+ this.options.dialect === 'mysql'
+ ? `SELECT \`${this.options.table}\`.* FROM \`${this.options.table}\` WHERE (\`${this.options.table}\`.\`key\` = '${key}')`
+ : `SELECT "${this.options.table}".* FROM "${this.options.table}" WHERE ("${this.options.table}"."key" = '${key}')`
+ return this.query(select).then(rows => {
+ const row = rows[0]
+ if (row === undefined) {
+ return undefined
+ }
- return row.value
- })
+ return row.value
+ })
}
set (key, value) {
@@ -40,39 +52,61 @@ class KeyvSql extends EventEmitter {
value = value.replace(/\\/g, '\\\\')
}
- const upsert = this.options.dialect === 'postgres'
- ? `INSERT INTO "${this.options.table}" ("key", "value") VALUES ('${key}', '${value}') ON CONFLICT ("key") DO UPDATE SET "value" = EXCLUDED."value"`
- : (this.options.dialect === 'mysql'
- ? `REPLACE INTO \`${this.options.table}\` (\`key\`, \`value\`) VALUES ('${key}', '${value}')`
- : `REPLACE INTO "${this.options.table}" ("key", "value") VALUES ('${key}', '${value}')`)
+ const upsert =
+ this.options.dialect === 'postgres'
+ ? `INSERT INTO "${this.options.table}" ("key", "value") VALUES ('${key}', '${value}') ON CONFLICT ("key") DO UPDATE SET "value" = EXCLUDED."value"`
+ : this.options.dialect === 'mysql'
+ ? `REPLACE INTO \`${this.options.table}\` (\`key\`, \`value\`) VALUES ('${key}', '${value}')`
+ : `REPLACE INTO "${this.options.table}" ("key", "value") VALUES ('${key}', '${value}')`
return this.query(upsert)
}
delete (key) {
- const select = this.options.dialect === 'mysql' ? `SELECT \`${this.options.table}\`.* FROM \`${this.options.table}\` WHERE (\`${this.options.table}\`.\`key\` = '${key}')` : `SELECT "${this.options.table}".* FROM "${this.options.table}" WHERE ("${this.options.table}"."key" = '${key}')`
- const del = this.options.dialect === 'mysql' ? `DELETE FROM \`${this.options.table}\` WHERE (\`${this.options.table}\`.\`key\` = '${key}')` : `DELETE FROM "${this.options.table}" WHERE ("${this.options.table}"."key" = '${key}')`
- return this.query(select)
- .then(rows => {
- const row = rows[0]
- if (row === undefined) {
- return false
- }
+ const select =
+ this.options.dialect === 'mysql'
+ ? `SELECT \`${this.options.table}\`.* FROM \`${this.options.table}\` WHERE (\`${this.options.table}\`.\`key\` = '${key}')`
+ : `SELECT "${this.options.table}".* FROM "${this.options.table}" WHERE ("${this.options.table}"."key" = '${key}')`
+ const del =
+ this.options.dialect === 'mysql'
+ ? `DELETE FROM \`${this.options.table}\` WHERE (\`${this.options.table}\`.\`key\` = '${key}')`
+ : `DELETE FROM "${this.options.table}" WHERE ("${this.options.table}"."key" = '${key}')`
+ return this.query(select).then(rows => {
+ const row = rows[0]
+ if (row === undefined) {
+ return false
+ }
- return this.query(del)
- .then(() => true)
- })
+ return this.query(del).then(() => true)
+ })
}
clear () {
- const del = this.options.dialect === 'mysql' ? `DELETE FROM \`${this.options.table}\` WHERE (\`${this.options.table}\`.\`key\` LIKE '${this.namespace ? this.namespace + ':' : ''}%')` : `DELETE FROM "${this.options.table}" WHERE ("${this.options.table}"."key" LIKE '${this.namespace ? this.namespace + ':' : ''}%')`
- return this.query(del)
- .then(() => undefined)
+ const del =
+ this.options.dialect === 'mysql'
+ ? `DELETE FROM \`${this.options.table}\` WHERE (\`${
+ this.options.table
+ }\`.\`key\` LIKE '${this.namespace ? this.namespace + ':' : ''}%')`
+ : `DELETE FROM "${this.options.table}" WHERE ("${
+ this.options.table
+ }"."key" LIKE '${this.namespace ? this.namespace + ':' : ''}%')`
+ return this.query(del).then(() => undefined)
}
async * iterator () {
const limit = Number.parseInt(this.options.iterationLimit, 10)
- const selectChunk = this.options.dialect === 'mysql' ? `SELECT * FROM \`${this.options.table}\` WHERE (\`${this.options.table}\`.\`key\` LIKE '${this.namespace ? this.namespace + ':' : ''}%') LIMIT ${limit} OFFSET ` : `SELECT * FROM "${this.options.table}" WHERE ("${this.options.table}"."key" LIKE '${this.namespace ? this.namespace + ':' : ''}%') LIMIT ${limit} OFFSET `
+ const selectChunk =
+ this.options.dialect === 'mysql'
+ ? `SELECT * FROM \`${this.options.table}\` WHERE (\`${
+ this.options.table
+ }\`.\`key\` LIKE '${
+ this.namespace ? this.namespace + ':' : ''
+ }%') LIMIT ${limit} OFFSET `
+ : `SELECT * FROM "${this.options.table}" WHERE ("${
+ this.options.table
+ }"."key" LIKE '${
+ this.namespace ? this.namespace + ':' : ''
+ }%') LIMIT ${limit} OFFSET `
async function * iterate (offset, query) {
const entries = await query(selectChunk + offset)
diff --git a/packages/keyv/README.md b/packages/keyv/README.md
index 6f57838..c46527c 100644
--- a/packages/keyv/README.md
+++ b/packages/keyv/README.md
@@ -232,6 +232,13 @@ Default: `JSONB.parse`
A custom deserialization function.
+#### options.emitErrors
+
+Type: `Boolean`
+Default: `true`
+
+When it's `true`, errors on `options.store` will be emitted at keyv level.
+
#### options.store
Type: `Storage adapter instance`
diff --git a/packages/keyv/src/index.js b/packages/keyv/src/index.js
index 0e69d72..f5956c2 100644
--- a/packages/keyv/src/index.js
+++ b/packages/keyv/src/index.js
@@ -4,22 +4,22 @@ const EventEmitter = require('events')
const JSONB = require('json-buffer')
class Keyv extends EventEmitter {
- constructor (options) {
+ constructor ({ emitErrors = true, ...options }) {
super()
this.options = Object.assign(
{
namespace: 'keyv',
serialize: JSONB.stringify,
- deserialize: JSONB.parse
+ deserialize: JSONB.parse,
+ emitErrors: true
},
options
)
this.store = this.options.store || new Map()
-
this.store.namespace = this.options.namespace
- if (typeof this.store.on === 'function') {
+ if (emitErrors) {
this.store.on('error', error => this.emit('error', error))
}
diff --git a/packages/keyv/test/keyv.js b/packages/keyv/test/keyv.js
index ea66037..37f3843 100644
--- a/packages/keyv/test/keyv.js
+++ b/packages/keyv/test/keyv.js
@@ -157,5 +157,19 @@ test.serial('An empty namespace stores the key as-is', async t => {
t.is([...store.keys()][0], 42)
})
+test('emit errors by default', async t => {
+ const store = new Keyv()
+ const keyv = new Keyv({ store, namespace: '' })
+ await keyv.set(42, 'foo')
+ t.is(store.listenerCount('error'), 1)
+})
+
+test('disable emit errors', async t => {
+ const store = new Keyv({ emitErrors: false })
+ const keyv = new Keyv({ store, emitErrors: false, namespace: '' })
+ await keyv.set(42, 'foo')
+ t.is(keyv.listenerCount('error'), 0)
+})
+
const store = () => new Map()
keyvTestSuite(test, Keyv, store)