diff --git a/lib/mutation.mjs b/lib/mutation.mjs index 43ea381..da46e91 100644 --- a/lib/mutation.mjs +++ b/lib/mutation.mjs @@ -104,6 +104,9 @@ function prepareContext (context, unwrapOptions) { commitMode: mutentOptions.commitMode !== undefined ? parseCommitMode(mutentOptions.commitMode) : context.commitMode, + handlers: context.handlers.concat( + normalizeMutators(mutentOptions.handlers) + ), hooks: mergeHooks(context.hooks, normalizeHooks(mutentOptions.hooks)), intent, multiple: isMultiple(intent, argument), @@ -121,12 +124,23 @@ function prepareContext (context, unwrapOptions) { } } -async function * iterateMethod (context, mutators) { - const { adapter, argument, intent, multiple, options } = context - - const iterable = context.mutators.concat(mutators).reduce( - (accumulator, mutator) => mutator(accumulator, context), - iterateEntities(iterateContext(context), context) +async function * iterateMethod (ctx, mutators) { + const { adapter, argument, intent, multiple, options } = ctx + + const chain = [ + // Plugins' mutators + ...ctx.mutators, + // Local chain mutators + ...mutators, + // Internal end/safe mutator + mutatorClose, + // Plugins' handlers (end mutators) + ...ctx.handlers + ] + + const iterable = chain.reduce( + (acc, mutator) => mutator(acc, ctx), + iterateEntities(iterateContext(ctx), ctx) ) let count = 0 diff --git a/lib/mutation.spec.mjs b/lib/mutation.spec.mjs index 2d1031d..552dc42 100644 --- a/lib/mutation.spec.mjs +++ b/lib/mutation.spec.mjs @@ -9,6 +9,7 @@ function buildMutation (intent, argument, context = {}) { adapter: {}, argument, commitMode: 'AUTO', + handlers: [], intent, mutators: [], writeMode: 'AUTO', diff --git a/lib/store.mjs b/lib/store.mjs index 516ffd7..04a443d 100644 --- a/lib/store.mjs +++ b/lib/store.mjs @@ -13,6 +13,7 @@ export class Store { const { adapter, commitMode, + handlers, hooks, mutators, plugins, @@ -27,13 +28,21 @@ export class Store { // Save (valid) defaults this.adapter = adapter this.commitMode = 'AUTO' + this.handlers = [] this.hooks = normalizeHooks() this.mutators = [] this.writeMode = 'AUTO' this.writeSize = 16 // Parse and save submitted options - this.register({ commitMode, hooks, mutators, writeMode, writeSize }) + this.register({ + commitMode, + handlers, + hooks, + mutators, + writeMode, + writeSize + }) // Register plugins if (Array.isArray(plugins)) { @@ -50,6 +59,7 @@ export class Store { register (plugin) { const { commitMode, + handlers, hooks, mutators, writeMode, @@ -59,6 +69,9 @@ export class Store { if (commitMode !== undefined) { this.commitMode = parseCommitMode(commitMode) } + if (handlers !== undefined) { + this.handlers = this.handlers.concat(normalizeMutators(handlers)) + } if (hooks !== undefined) { this.hooks = mergeHooks(this.hooks, normalizeHooks(hooks)) } @@ -92,6 +105,7 @@ export class Store { adapter: this.adapter, argument, commitMode: this.commitMode, + handlers: this.handlers, hooks: this.hooks, intent, mutators: this.mutators, diff --git a/mutent.spec.mjs b/mutent.spec.mjs index ff491f3..a65d949 100644 --- a/mutent.spec.mjs +++ b/mutent.spec.mjs @@ -778,3 +778,24 @@ test('bulkEntities over bulk', async t => { 'SECOND_UPDATE' ]) }) + +test('store handlers', async t => { + t.plan(3) + + const store = new Store({ + adapter: {}, + handlers: [ + async function * (iterable, ctx) { + t.like(ctx, { multiple: false }) + try { + yield * iterable + } catch (err) { + t.like(err, { code: 'EMUT_PARTIAL_ADAPTER' }) + } + } + ] + }) + + const result = await store.create('Oh no').unwrap() + t.is(result, null) +})