8000 fix(schema): Ensure that resolveResult and resolveExternal are run as around hooks by daffl · Pull Request #3032 · feathersjs/feathers · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/api/schema/resolvers.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ app.service('users').hooks({

<BlockQuote type="warning" label="important">

In order to get the safe data from resolved associations **all services** involved need the `schemaHooks.resolveExternal` (or `resolveAll`) hook registered even if it does not need a resolver (`schemaHooks.resolveExternal()`).
In order to get the safe data from resolved associations **all services** involved need the `schemaHooks.resolveExternal` hook registered even if it does not need a resolver (`schemaHooks.resolveExternal()`).

`schemaHooks.resolveExternal` should be registered first when used as an `around` hook or last when used as an `after` hook so that it gets the final result data.

Expand Down
50 changes: 27 additions & 23 deletions packages/schema/src/hooks/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,28 +81,30 @@ export const resolveData =
export const resolveResult = <H extends HookContext>(...resolvers: Resolver<any, H>[]) => {
const virtualProperties = new Set(resolvers.reduce((acc, current) => acc.concat(current.virtualNames), []))

return async (context: H, next?: NextFunction) => {
if (typeof next === 'function') {
const { $resolve, $select: select, ...query } = context.params?.query || {}
const $select = Array.isArray(select) ? select.filter((name) => !virtualProperties.has(name)) : select
const resolve = {
originalContext: context,
...context.params.resolve,
properties: $resolve || select
}
return async (context: H, next: NextFunction) => {
if (typeof next !== 'function') {
throw new Error('The resolveResult hook must be used as an around hook')
}

context.params = {
...context.params,
resolve,
query: {
...query,
...($select ? { $select } : {})
}
}
const { $resolve, $select: select, ...query } = context.params?.query || {}
const $select = Array.isArray(select) ? select.filter((name) => !virtualProperties.has(name)) : select
const resolve = {
originalContext: context,
...context.params.resolve,
properties: $resolve || select
}

await next()
context.params = {
...context.params,
resolve,
query: {
...query,
...($select ? { $select } : {})
}
}

await next()

const ctx = getContext(context)
const status = context.params.resolve
const { isPaginated, data } = getResult(context)
Expand Down Expand Up @@ -148,13 +150,15 @@ export const setDispatch = (current: any, dispatch: any) => {
return dispatch
}

export const resolveDispatch =
export const resolveExternal =
<H extends HookContext>(...resolvers: Resolver<any, H>[]) =>
async (context: H, next?: NextFunction) => {
if (typeof next === 'function') {
await next()
async (context: H, next: NextFunction) => {
if (typeof next !== 'function') {
throw new Error('The resolveExternal hook must be used as an around hook')
}

await next()

const ctx = getContext(context)
const existingDispatch = getDispatch(context.result)

Expand Down Expand Up @@ -188,7 +192,7 @@ export const resolveDispatch =
}
}

export const resolveExternal = resolveDispatch
export const resolveDispatch = resolveExternal

type ResolveAllSettings<H extends HookContext> = {
data?: {
Expand Down
0