Skip to content

Tags: olivierwilkinson/prisma-nested-middleware

Tags

v4.0.0

Toggle v4.0.0's commit message
feat: avoid multiple types of select calls

Currently there are two scenarios when a select action type is found:
- When an include has a select within it
- When a select has a relation in it

This means that there is a situation where it is not possible to reason
about what to do with a select because the two scenarios look the same
based on the available information; both have the include action as the
parent.

BREAKING CHANGE: remove the calls for include selects

Middleware that relied on calls with the "select" action for select
objects within an include will no longer be able to use that call.
Instead use the parent "include" action to modify the selected fields,
or use the "select" action for the relation within that select object.

v3.0.3

Toggle v3.0.3's commit message
fix: groupBy not included in NestedAction type

Prisma client does not include groupBy in the Prisma.PrismaAction types.
This appears to be an omission because middleware is called with the
action set to 'groupBy'.

Include it in NestedAction types while we wait for it to be added to
Prisma.PrismaAction.

v3.0.2

Toggle v3.0.2's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
fix: error parsing invalid logical where arrays (#22)

When extracting nested actions in logical where arrays we can encounter
an error if the array contains null or undefined. This is because we try
to access a property on those values.

Use optional chaining to ensure that the value is defined before trying
to access a property in logical where arrays.

v3.0.1

Toggle v3.0.1's commit message
fix: queries that use Json NullTypes

Prisma NullTypes are used as the null value for Json fields. When using
a NullType in a query the instance of the NullType must remain the same
or Prisma is unable to parse the value correctly, replacing it with
undefined.

Lodash cloneDeep causes these NullTypes to be new instances and so
params that use them have unexpected undefined values, causing errors.

When the Prisma client has NullTypes, which is true for v4, clone params
but pass through the instances of Prisma.JsonNull, Prisma.DbNull and
Prisma.AnyNull so that they are not replaced with undefined.

Prisma client v3 uses strings for these null types so cloneDeep works as
is in that case.

v3.0.0

Toggle v3.0.0's commit message
feat: new scope, actions and full concurrency

- move parent params into the scope object

There are other fields that are only relevant when handling a nested
action so move the parent params into the scope object under the
"parentParams" field to make room for them.

- add a new "where" action

The "where" action calls the middleware function for each relation
found in where objects.

In order to make the args have a consistent format the modifiers that
can be found after a relation such as "some" or "every" have been moved
to the scope object.

Also add the logical operators that needed to be traversed to find the
relation to the scope object, these can be either "OR", "NOT" or "AND".
Since these operators can be chained the "logicalOperators" field in
scope is an array.

- improve speed of async middleware

The current recursive strategy for resolving nested middleware has a
major drawback that each layer of async middleware needs to be resolved
one after the other, this can make async middleware extremely slow.

Instead recurse through the params object to find all the nested params
that the middleware function needs to be called with and then execute
the middleware for all params at once.

Once all the updated params have been resolved execute the root next
function and then synchronously parse the result to find all the slices
necessary for "include" and "select" actions.

Once all the slices of the result have been found we can resolve the
nested middleware next functions and await their updated results in
parallel.

The final result object can then be updated synchronously as well.

- Add "connect" and "disconnect" to the list of available actions

- Support converting a single nested action to multiple actions

Since multiple nested actions can be found at the same level of a params
object it is possible to convert a single nested action into multiple
actions by setting the resulting params into the corresponding fields
based off their action type.

This is done by passing an array of NestedParams objects to the next
function.

- fix merging nested boolean actions

When merging a nested boolean action, for example a delete true action,
the params do not support arrays of operations. Instead of merging into
an array of operations set the value of the operation to the new value.

Process calls that change the action last when building params, this
allows changes of action to overwrite the default args when the target
action is defined before the changed action.

- include relations in both directions in scope

Some middleware needs to make use of the relation from the current model
to the parent model, for example to find the foreign key that references
the parent.

- add relation from model to parent

relations are now stored on the scope object under "relations". The
relations object has "to" and "from" keys for the relation to the model
and from the model back to the parent respectively.

- update README for new features and try to better explain how to write
  middleware using createNestedMiddleware

- fix count query without args

- add smoke tests

BREAKING CHANGE: scope is no longer the parent params and relation has
been moved to live inside of the scope object.

v2.3.0

Toggle v2.3.0's commit message
feat: include relation in NestedParams

For certain middleware it is necessary to reference the relation for
that nested action. For example instead of deleting a toOne relation a
soft delete middleware may decide instead to unlink the relation and
update it to have a deleted mark which would require both the isList and
the foreign key information stored on the relation.

v2.2.0

Toggle v2.2.0's commit message
feat: support changing nested params action

Currently modifications to the params of nested actions has been limited
to the args field in order to prevent breaking params. The reason
changing the action in nested params can cause unexpected behaviour is
that the new action may already exist, causing the old args to be
overwritten by the new args. Changing two different actions to be the
same action would also cause args to be lost.

When combining the updated params from nested middleware with the
original params there are a few scenarios we need to handle:
- if the action does not already exist set the args
- if the action exists but and is an operation array push the args
- if the action exists but is not an operation array turn it into one
  and make the previous args the first operation and the new args the
  second
- if the action is createMany operation arrays are not supported and so
  the args.data arrays must be combined instead.

For nested reads the above problems go away since a select cannot be
found at the same level as an include, instead of merging we can set and
delete the original action.

Supporting changing actions also introduces a new problem: Since the
passed middleware function for each action at a particular level is
processed in parallel the order the actions are defined on the params
object matters. If the middleware processes action A before action B
then if action B is changed to be action A the new operations added
will not be processed by the middleware.

Since it is only possible to know if an action has been changed when the
params have been passed to next the execution strategy of nested
middleware needs to change. Update the middleware execution to wait for
params to be passed to next and then execute middleware with the updated
params again if the action has changed. This recursive execution ensures
every operation is processed regardless of the order of nested actions.

v2.1.0

Toggle v2.1.0's commit message
feat: call middleware for all lists of operations

Similarly to nested update, create or delete operations it is possible
to pass an array of operations to nested upsert, updateMany and
deleteMany actions. Since createMany operations can be flattened to a
single data array they cannot be passed as an array.

For update, create and delete actions we already call the passed
middleware function for each operation in the array if passed,
unfortunately other actions that support passing an array of operations
were omitted.

On closer inspection the Prisma nested write API is such that the only
time an action is passed as an array is when it is an operation list.
Due to this it's possible to change the logic to simply check for
whether the action is an array in order to determine if the middleware
function should be called for each operation in the array.

This is not a breaking change due to the fact that middleware already
needs to handle the non-list case along with any lists. The new
behaviour will cause list operations to be handled by the non-list
logic.

v2.0.0

Toggle v2.0.0's commit message
feat: put nested create args in data field

Currently middleware that modifies nested creates must modify args
directly rather than the data object that is found in root create
operations. Having two different scenarios for root and nested
create operations makes middleware difficult to write intuitively.

Move nested create operation args into a data object so that they can
be modified in the same way as when handling a root create operation.

BREAKING CHANGE: nested creates params.args have new format

Middleware that currently check for the existence of params.scope and
then modify args are broken by this change. Middleware must now modify
args.data for all create operations regardless of whether they are
nested or not.

v1.2.0

Toggle v1.2.0's commit message
feat: call middleware for writes in nested lists

In a prisma query it is possible to provide multiple create, update or
delete operations within a query as a list. To avoid nested middleware
needing to handle these nested lists manually call the middleware
function for each write within the list. This means that nested lists of
write operations can be handled in the same way as when they are not in
a list.

This is not a breaking change due to the fact that middleware would need
to handle the non-list case along with any lists. The new behaviour will
cause list operations to be handled by the non-list logic.