feathers-utils 10.0.0 → 10.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{hooks-DPFxxjBu.mjs → hooks-yFJ5FmU5.mjs} +115 -99
- package/dist/hooks-yFJ5FmU5.mjs.map +1 -0
- package/dist/hooks.d.mts +98 -29
- package/dist/hooks.mjs +4 -4
- package/dist/{index-CNrzxmWo.d.mts → index-CgAuzxiv.d.mts} +49 -4
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +7 -7
- package/dist/{internal.utils-BWQ25nOd.mjs → internal.utils-3BrB8lRY.mjs} +8 -2
- package/dist/internal.utils-3BrB8lRY.mjs.map +1 -0
- package/dist/{mutate-result.util-CCBWix-G.mjs → mutate-result.util-B6FOkwrd.mjs} +73 -11
- package/dist/mutate-result.util-B6FOkwrd.mjs.map +1 -0
- package/dist/{predicates-CT08opkD.mjs → predicates-BC8p_YLo.mjs} +27 -24
- package/dist/predicates-BC8p_YLo.mjs.map +1 -0
- package/dist/predicates.d.mts +2 -2
- package/dist/predicates.mjs +1 -1
- package/dist/{resolve-Cx9osy8O.mjs → resolve-ClHfNFlm.mjs} +3 -3
- package/dist/resolve-ClHfNFlm.mjs.map +1 -0
- package/dist/resolvers.mjs +1 -1
- package/dist/{transform-result.hook-BUwLePT2.d.mts → transform-result.hook-C8-4Lezj.d.mts} +8 -5
- package/dist/{transform-result.hook-CevWK5TA.mjs → transform-result.hook-CanJtTPV.mjs} +13 -12
- package/dist/transform-result.hook-CanJtTPV.mjs.map +1 -0
- package/dist/transformers.d.mts +1 -1
- package/dist/transformers.mjs +8 -4
- package/dist/transformers.mjs.map +1 -1
- package/dist/{unless.hook-BYWO9hzO.d.mts → unless.hook-BX0mOvdN.d.mts} +6 -3
- package/dist/{utils-1I_iPZkV.mjs → utils-BrvpblXB.mjs} +38 -19
- package/dist/utils-BrvpblXB.mjs.map +1 -0
- package/dist/utils.d.mts +2 -2
- package/dist/utils.mjs +4 -4
- package/package.json +1 -1
- package/src/common/clone.ts +9 -7
- package/src/hooks/cache/cache-utils.ts +5 -18
- package/src/hooks/cache/cache.hook.ts +37 -16
- package/src/hooks/check-multi/check-multi.hook.ts +5 -2
- package/src/hooks/check-required/check-required.hook.ts +6 -1
- package/src/hooks/create-related/create-related.hook.ts +2 -2
- package/src/hooks/debug/debug.hook.ts +1 -1
- package/src/hooks/disable-pagination/disable-pagination.hook.ts +7 -4
- package/src/hooks/disallow/disallow.hook.ts +10 -3
- package/src/hooks/on-delete/on-delete.hook.ts +61 -41
- package/src/hooks/params-for-server/params-for-server.hook.ts +16 -5
- package/src/hooks/params-from-client/params-from-client.hook.ts +10 -6
- package/src/hooks/rate-limit/rate-limit.hook.ts +2 -2
- package/src/hooks/set-data/set-data.hook.ts +8 -7
- package/src/hooks/set-field/set-field.hook.ts +42 -17
- package/src/hooks/set-result/set-result.hook.ts +16 -3
- package/src/hooks/set-slug/set-slug.hook.ts +8 -6
- package/src/hooks/skippable/skippable.hook.ts +17 -12
- package/src/hooks/soft-delete/soft-delete.hook.ts +4 -5
- package/src/hooks/stashable/stashable.hook.ts +9 -8
- package/src/hooks/throw-if/throw-if.hook.ts +2 -2
- package/src/hooks/transform-data/transform-data.hook.ts +2 -4
- package/src/hooks/transform-query/transform-query.hook.ts +6 -5
- package/src/hooks/transform-result/transform-result.hook.ts +6 -9
- package/src/hooks/traverse/traverse.hook.ts +30 -10
- package/src/internal.utils.ts +6 -1
- package/src/predicates/and/and.predicate.ts +5 -5
- package/src/predicates/is-context/is-context.predicate.ts +1 -1
- package/src/predicates/or/or.predicate.ts +6 -8
- package/src/resolvers/resolve-result/resolve-result.ts +4 -1
- package/src/transformers/parse-date/parse-date.transformer.ts +6 -1
- package/src/utils/chunk-find/chunk-find.util.ts +7 -0
- package/src/utils/combine/combine.util.ts +8 -15
- package/src/utils/get-paginate/get-paginate.util.ts +1 -3
- package/src/utils/index.ts +2 -0
- package/src/utils/iterate-find/iterate-find.util.ts +8 -0
- package/src/utils/mutate-data/mutate-data.util.ts +21 -4
- package/src/utils/mutate-result/mutate-result.util.ts +4 -10
- package/src/utils/patch-batch/patch-batch.util.ts +32 -14
- package/src/utils/replace-data/replace-data.util.ts +26 -0
- package/src/utils/replace-result/replace-result.util.ts +60 -0
- package/src/utils/sort-query-properties/sort-query-properties.util.ts +15 -8
- package/src/utils/walk-query/walk-query.util.ts +2 -2
- package/dist/hooks-DPFxxjBu.mjs.map +0 -1
- package/dist/internal.utils-BWQ25nOd.mjs.map +0 -1
- package/dist/mutate-result.util-CCBWix-G.mjs.map +0 -1
- package/dist/predicates-CT08opkD.mjs.map +0 -1
- package/dist/resolve-Cx9osy8O.mjs.map +0 -1
- package/dist/transform-result.hook-CevWK5TA.mjs.map +0 -1
- package/dist/utils-1I_iPZkV.mjs.map +0 -1
|
@@ -28,8 +28,12 @@ export const disallow = <H extends HookContext = HookContext>(
|
|
|
28
28
|
transports?: MaybeArray<TransportName>,
|
|
29
29
|
) => {
|
|
30
30
|
const transportsArr = toArray(transports)
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
function hook(context: H): void
|
|
32
|
+
function hook(context: H, next: NextFunction): Promise<void>
|
|
33
|
+
function hook(context: H, next?: NextFunction): void | Promise<void> {
|
|
34
|
+
// No transports (undefined) or an empty list means "block completely".
|
|
35
|
+
// Fail closed for a guard hook rather than throwing a confusing internal error.
|
|
36
|
+
if (!transports || transportsArr.length === 0) {
|
|
33
37
|
throw new MethodNotAllowed('Method not allowed')
|
|
34
38
|
}
|
|
35
39
|
|
|
@@ -39,6 +43,9 @@ export const disallow = <H extends HookContext = HookContext>(
|
|
|
39
43
|
)
|
|
40
44
|
}
|
|
41
45
|
|
|
42
|
-
if (next) return next()
|
|
46
|
+
if (next) return next()
|
|
47
|
+
|
|
48
|
+
return
|
|
43
49
|
}
|
|
50
|
+
return hook
|
|
44
51
|
}
|
|
@@ -43,6 +43,12 @@ export interface OnDeleteOptions<
|
|
|
43
43
|
* @default false
|
|
44
44
|
*/
|
|
45
45
|
blocking?: boolean
|
|
46
|
+
/**
|
|
47
|
+
* Called when a non-blocking (`blocking: false`) related-service call rejects.
|
|
48
|
+
* Without this, fire-and-forget rejections are swallowed (but never leak as an
|
|
49
|
+
* unhandled rejection). In `blocking` mode the error is thrown to the caller instead.
|
|
50
|
+
*/
|
|
51
|
+
onError?: (error: any, context: H) => void
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
/**
|
|
@@ -72,7 +78,7 @@ export const onDelete = <H extends HookContext = HookContext>(
|
|
|
72
78
|
) => {
|
|
73
79
|
const optionsMulti = Array.isArray(options) ? options : [options]
|
|
74
80
|
|
|
75
|
-
return async (context: H, next?: NextFunction) => {
|
|
81
|
+
return async (context: H, next?: NextFunction): Promise<void> => {
|
|
76
82
|
checkContext(context, {
|
|
77
83
|
type: ['after', 'around'],
|
|
78
84
|
method: 'remove',
|
|
@@ -89,46 +95,60 @@ export const onDelete = <H extends HookContext = HookContext>(
|
|
|
89
95
|
return
|
|
90
96
|
}
|
|
91
97
|
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
98
|
+
const blockingPromises: Promise<any>[] = []
|
|
99
|
+
|
|
100
|
+
for (const {
|
|
101
|
+
keyHere,
|
|
102
|
+
keyThere,
|
|
103
|
+
onDelete,
|
|
104
|
+
service,
|
|
105
|
+
blocking,
|
|
106
|
+
query,
|
|
107
|
+
onError,
|
|
108
|
+
} of optionsMulti) {
|
|
109
|
+
let ids = result.map((x) => x[keyHere]).filter((x) => !!x)
|
|
110
|
+
ids = [...new Set(ids)]
|
|
111
|
+
|
|
112
|
+
if (!ids || ids.length <= 0) {
|
|
113
|
+
continue
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const params = {
|
|
117
|
+
query: {
|
|
118
|
+
...query,
|
|
119
|
+
...(ids.length === 1
|
|
120
|
+
? { [keyThere]: ids[0] }
|
|
121
|
+
: { [keyThere]: { $in: ids } }),
|
|
122
|
+
},
|
|
123
|
+
paginate: false,
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let promise: Promise<any> | undefined = undefined
|
|
127
|
+
|
|
128
|
+
if (onDelete === 'cascade') {
|
|
129
|
+
promise = context.app.service(service as string).remove(null, params)
|
|
130
|
+
} else if (onDelete === 'set null') {
|
|
131
|
+
const data = { [keyThere]: null }
|
|
132
|
+
promise = context.app
|
|
133
|
+
.service(service as string)
|
|
134
|
+
.patch(null, data, params)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!promise) {
|
|
138
|
+
continue
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (blocking) {
|
|
142
|
+
blockingPromises.push(promise)
|
|
143
|
+
} else {
|
|
144
|
+
// fire-and-forget: always attach a catch so a rejection never becomes
|
|
145
|
+
// an unhandled promise rejection. Surface it via `onError` if provided.
|
|
146
|
+
promise.catch((error) => onError?.(error, context))
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (blockingPromises.length) {
|
|
151
|
+
await Promise.all(blockingPromises)
|
|
132
152
|
}
|
|
133
153
|
|
|
134
154
|
return
|
|
@@ -35,7 +35,15 @@ export const paramsForServer = (
|
|
|
35
35
|
|
|
36
36
|
const { keyToHide = FROM_CLIENT_FOR_SERVER_DEFAULT_KEY } = options || {}
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
function hook<H extends HookContext>(context: H): void
|
|
39
|
+
function hook<H extends HookContext>(
|
|
40
|
+
context: H,
|
|
41
|
+
next: NextFunction,
|
|
42
|
+
): Promise<void>
|
|
43
|
+
function hook<H extends HookContext>(
|
|
44
|
+
context: H,
|
|
45
|
+
next?: NextFunction,
|
|
46
|
+
): void | Promise<void> {
|
|
39
47
|
// clone params on demand
|
|
40
48
|
let clonedParams: any
|
|
41
49
|
|
|
@@ -56,6 +64,10 @@ export const paramsForServer = (
|
|
|
56
64
|
|
|
57
65
|
if (!clonedParams.query[keyToHide]) {
|
|
58
66
|
clonedParams.query[keyToHide] = {}
|
|
67
|
+
} else {
|
|
68
|
+
// The shallow query copy still aliases a pre-existing key object;
|
|
69
|
+
// clone it so we don't mutate the caller's original params.
|
|
70
|
+
clonedParams.query[keyToHide] = { ...clonedParams.query[keyToHide] }
|
|
59
71
|
}
|
|
60
72
|
|
|
61
73
|
clonedParams.query[keyToHide][key] = clonedParams[key]
|
|
@@ -67,10 +79,9 @@ export const paramsForServer = (
|
|
|
67
79
|
context.params = clonedParams
|
|
68
80
|
}
|
|
69
81
|
|
|
70
|
-
if (next)
|
|
71
|
-
return next()
|
|
72
|
-
}
|
|
82
|
+
if (next) return next()
|
|
73
83
|
|
|
74
|
-
return
|
|
84
|
+
return
|
|
75
85
|
}
|
|
86
|
+
return hook
|
|
76
87
|
}
|
|
@@ -33,13 +33,18 @@ export const paramsFromClient = (
|
|
|
33
33
|
) => {
|
|
34
34
|
const whitelistArr = toArray(whitelist)
|
|
35
35
|
const { keyToHide = FROM_CLIENT_FOR_SERVER_DEFAULT_KEY } = options || {}
|
|
36
|
-
|
|
36
|
+
function hook(context: HookContext): void
|
|
37
|
+
function hook(context: HookContext, next: NextFunction): Promise<void>
|
|
38
|
+
function hook(
|
|
39
|
+
context: HookContext,
|
|
40
|
+
next?: NextFunction,
|
|
41
|
+
): void | Promise<void> {
|
|
37
42
|
if (
|
|
38
43
|
!context.params?.query?.[keyToHide] ||
|
|
39
44
|
typeof context.params.query[keyToHide] !== 'object'
|
|
40
45
|
) {
|
|
41
46
|
if (next) return next()
|
|
42
|
-
return
|
|
47
|
+
return
|
|
43
48
|
}
|
|
44
49
|
|
|
45
50
|
const params = {
|
|
@@ -67,10 +72,9 @@ export const paramsFromClient = (
|
|
|
67
72
|
|
|
68
73
|
context.params = params
|
|
69
74
|
|
|
70
|
-
if (next)
|
|
71
|
-
return next()
|
|
72
|
-
}
|
|
75
|
+
if (next) return next()
|
|
73
76
|
|
|
74
|
-
return
|
|
77
|
+
return
|
|
75
78
|
}
|
|
79
|
+
return hook
|
|
76
80
|
}
|
|
@@ -37,7 +37,7 @@ export const rateLimit = <H extends HookContext = HookContext>(
|
|
|
37
37
|
const key = options?.key ?? ((context: HookContext) => context.path)
|
|
38
38
|
const points = options?.points ?? (() => 1)
|
|
39
39
|
|
|
40
|
-
return async (context: H, next?: NextFunction) => {
|
|
40
|
+
return async (context: H, next?: NextFunction): Promise<void> => {
|
|
41
41
|
checkContext(context, { type: ['before', 'around'], label: 'rateLimit' })
|
|
42
42
|
|
|
43
43
|
const resolvedKey = await key(context)
|
|
@@ -53,6 +53,6 @@ export const rateLimit = <H extends HookContext = HookContext>(
|
|
|
53
53
|
})
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
if (next)
|
|
56
|
+
if (next) await next()
|
|
57
57
|
}
|
|
58
58
|
}
|
|
@@ -68,7 +68,9 @@ export function setData<H extends HookContext = HookContext>(
|
|
|
68
68
|
) {
|
|
69
69
|
const { allowUndefined = false, overwrite = true } = options ?? {}
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
function hook(context: H): void
|
|
72
|
+
function hook(context: H, next: NextFunction): Promise<void>
|
|
73
|
+
function hook(context: H, next?: NextFunction): void | Promise<void> {
|
|
72
74
|
const { data } = getDataIsArray(context)
|
|
73
75
|
|
|
74
76
|
const contextJson = contextToJson(context)
|
|
@@ -76,7 +78,7 @@ export function setData<H extends HookContext = HookContext>(
|
|
|
76
78
|
if (!_has(contextJson, from)) {
|
|
77
79
|
if (!context.params?.provider || allowUndefined === true) {
|
|
78
80
|
if (next) return next()
|
|
79
|
-
return
|
|
81
|
+
return
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
if (
|
|
@@ -84,7 +86,7 @@ export function setData<H extends HookContext = HookContext>(
|
|
|
84
86
|
data.every((item: Record<string, unknown>) => _has(item, to))
|
|
85
87
|
) {
|
|
86
88
|
if (next) return next()
|
|
87
|
-
return
|
|
89
|
+
return
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
throw options?.error
|
|
@@ -107,10 +109,9 @@ export function setData<H extends HookContext = HookContext>(
|
|
|
107
109
|
_set(item, to, val)
|
|
108
110
|
}
|
|
109
111
|
|
|
110
|
-
if (next)
|
|
111
|
-
return next()
|
|
112
|
-
}
|
|
112
|
+
if (next) return next()
|
|
113
113
|
|
|
114
|
-
return
|
|
114
|
+
return
|
|
115
115
|
}
|
|
116
|
+
return hook
|
|
116
117
|
}
|
|
@@ -6,9 +6,23 @@ import type { FeathersError } from '@feathersjs/errors'
|
|
|
6
6
|
import { Forbidden } from '@feathersjs/errors'
|
|
7
7
|
import type { HookContext, NextFunction } from '@feathersjs/feathers'
|
|
8
8
|
|
|
9
|
-
export interface SetFieldOptions {
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
export interface SetFieldOptions<H extends HookContext = HookContext> {
|
|
10
|
+
/**
|
|
11
|
+
* The target path(s) to set. Pass an array to write the same value to several
|
|
12
|
+
* paths (e.g. multiple query keys).
|
|
13
|
+
*
|
|
14
|
+
* @example 'params.query.userId'
|
|
15
|
+
* @example ['params.query.userId', 'params.query.ownerId']
|
|
16
|
+
*/
|
|
17
|
+
as: string | string[]
|
|
18
|
+
/**
|
|
19
|
+
* The source of the value: a `dot.notation` path on the context, or a function
|
|
20
|
+
* that derives the value from the context.
|
|
21
|
+
*
|
|
22
|
+
* @example 'params.user.id'
|
|
23
|
+
* @example (context) => context.params.user?.id
|
|
24
|
+
*/
|
|
25
|
+
from: string | ((context: H) => unknown)
|
|
12
26
|
/**
|
|
13
27
|
* If set to `true`, allows the field to be undefined.
|
|
14
28
|
* If the field is not available and this is `true`, the hook will not throw an error.
|
|
@@ -23,7 +37,10 @@ export interface SetFieldOptions {
|
|
|
23
37
|
*
|
|
24
38
|
* If not provided, throws a `Forbidden` error with a message indicating the missing field.
|
|
25
39
|
*/
|
|
26
|
-
error?: (
|
|
40
|
+
error?: (
|
|
41
|
+
context: H,
|
|
42
|
+
from: string | ((context: H) => unknown),
|
|
43
|
+
) => FeathersError
|
|
27
44
|
}
|
|
28
45
|
|
|
29
46
|
/**
|
|
@@ -42,34 +59,42 @@ export interface SetFieldOptions {
|
|
|
42
59
|
*
|
|
43
60
|
* @see https://utils.feathersjs.com/hooks/set-field.html
|
|
44
61
|
*/
|
|
45
|
-
export const setField =
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
62
|
+
export const setField = <H extends HookContext = HookContext>({
|
|
63
|
+
as,
|
|
64
|
+
from,
|
|
65
|
+
allowUndefined = false,
|
|
66
|
+
error,
|
|
67
|
+
}: SetFieldOptions<H>) => {
|
|
68
|
+
const targets = Array.isArray(as) ? as : [as]
|
|
69
|
+
|
|
70
|
+
function hook(context: H): void
|
|
71
|
+
function hook(context: H, next: NextFunction): Promise<void>
|
|
72
|
+
function hook(context: H, next?: NextFunction): void | Promise<void> {
|
|
53
73
|
const { params } = context
|
|
54
74
|
|
|
55
75
|
checkContext(context, { type: ['before', 'around'], label: 'setField' })
|
|
56
76
|
|
|
57
|
-
const value =
|
|
77
|
+
const value =
|
|
78
|
+
typeof from === 'function' ? from(context) : _get(context, from)
|
|
58
79
|
|
|
59
80
|
if (value === undefined) {
|
|
60
81
|
if (!params.provider || allowUndefined) {
|
|
61
82
|
if (next) return next()
|
|
62
|
-
return
|
|
83
|
+
return
|
|
63
84
|
}
|
|
64
85
|
|
|
65
86
|
throw error
|
|
66
87
|
? error(context, from)
|
|
67
|
-
: new Forbidden(`Expected field ${
|
|
88
|
+
: new Forbidden(`Expected field ${targets.join(', ')} not available`)
|
|
68
89
|
}
|
|
69
90
|
|
|
70
|
-
|
|
91
|
+
for (const target of targets) {
|
|
92
|
+
_setWith(context, target, value, _clone)
|
|
93
|
+
}
|
|
71
94
|
|
|
72
95
|
if (next) return next()
|
|
73
96
|
|
|
74
|
-
return
|
|
97
|
+
return
|
|
75
98
|
}
|
|
99
|
+
return hook
|
|
100
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import _get from 'lodash/get.js'
|
|
2
2
|
import _set from 'lodash/set.js'
|
|
3
3
|
import _has from 'lodash/has.js'
|
|
4
|
+
import { copy } from 'fast-copy'
|
|
4
5
|
|
|
5
6
|
import type { FeathersError } from '@feathersjs/errors'
|
|
6
7
|
import { Forbidden } from '@feathersjs/errors'
|
|
@@ -110,6 +111,12 @@ export function setResult<H extends HookContext = HookContext>(
|
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
const fn = (context: H) => {
|
|
114
|
+
// Seed context.dispatch from result so the dispatch branch mutates (and
|
|
115
|
+
// persists to) a real object instead of a throwaway copy. Mirrors mutateResult.
|
|
116
|
+
if (!!options?.dispatch && !context.dispatch) {
|
|
117
|
+
context.dispatch = copy(context.result)
|
|
118
|
+
}
|
|
119
|
+
|
|
113
120
|
if (options?.dispatch === 'both') {
|
|
114
121
|
forResultOrDispatch(context, true)
|
|
115
122
|
return forResultOrDispatch(context, false)
|
|
@@ -118,11 +125,17 @@ export function setResult<H extends HookContext = HookContext>(
|
|
|
118
125
|
return forResultOrDispatch(context, !!options?.dispatch)
|
|
119
126
|
}
|
|
120
127
|
|
|
121
|
-
|
|
128
|
+
function hook(context: H): void
|
|
129
|
+
function hook(context: H, next: NextFunction): Promise<void>
|
|
130
|
+
function hook(context: H, next?: NextFunction): void | Promise<void> {
|
|
122
131
|
if (next) {
|
|
123
|
-
return next().then(() =>
|
|
132
|
+
return next().then(() => {
|
|
133
|
+
fn(context)
|
|
134
|
+
})
|
|
124
135
|
}
|
|
125
136
|
|
|
126
|
-
|
|
137
|
+
fn(context)
|
|
138
|
+
return
|
|
127
139
|
}
|
|
140
|
+
return hook
|
|
128
141
|
}
|
|
@@ -21,20 +21,22 @@ export const setSlug = <H extends HookContext = HookContext>(
|
|
|
21
21
|
slug: string,
|
|
22
22
|
fieldName?: string,
|
|
23
23
|
) => {
|
|
24
|
-
|
|
25
|
-
fieldName
|
|
26
|
-
}
|
|
24
|
+
const targetField: string =
|
|
25
|
+
typeof fieldName === 'string' ? fieldName : `query.${slug}`
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
function hook(context: H): void
|
|
28
|
+
function hook(context: H, next: NextFunction): Promise<void>
|
|
29
|
+
function hook(context: H, next?: NextFunction): void | Promise<void> {
|
|
29
30
|
if (context.params && context.params.provider === 'rest') {
|
|
30
31
|
const value = context.params.route[slug]
|
|
31
32
|
if (typeof value === 'string' && value[0] !== ':') {
|
|
32
|
-
_set(context.params,
|
|
33
|
+
_set(context.params, targetField, value)
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
if (next) return next()
|
|
37
38
|
|
|
38
|
-
return
|
|
39
|
+
return
|
|
39
40
|
}
|
|
41
|
+
return hook
|
|
40
42
|
}
|
|
@@ -15,26 +15,31 @@ import type { HookFunction, PredicateFn } from '../../types.js'
|
|
|
15
15
|
*
|
|
16
16
|
* @see https://utils.feathersjs.com/hooks/skippable.html
|
|
17
17
|
*/
|
|
18
|
-
export const skippable =
|
|
19
|
-
<H
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
)
|
|
23
|
-
(context: H, next
|
|
18
|
+
export const skippable = <H extends HookContext = HookContext>(
|
|
19
|
+
innerHook: HookFunction<H>,
|
|
20
|
+
predicate: PredicateFn<H>,
|
|
21
|
+
) => {
|
|
22
|
+
function hook(context: H): H | void | Promise<H | void>
|
|
23
|
+
function hook(context: H, next: NextFunction): Promise<void>
|
|
24
|
+
function hook(context: H, next?: NextFunction): H | void | Promise<H | void> {
|
|
24
25
|
const skip = predicate(context)
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
if (
|
|
27
|
+
const skipOrRun = (shouldSkip: boolean): H | void | Promise<H | void> => {
|
|
28
|
+
if (shouldSkip) {
|
|
28
29
|
if (next) return next()
|
|
29
|
-
return
|
|
30
|
-
} else {
|
|
31
|
-
return hook(context, next)
|
|
30
|
+
return
|
|
32
31
|
}
|
|
32
|
+
if (next) return innerHook(context, next) as Promise<void>
|
|
33
|
+
// before/after mode: return the inner hook's result so an async hook is
|
|
34
|
+
// awaited and a returned/modified context is propagated to the pipeline.
|
|
35
|
+
return innerHook(context)
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
if (!skip || typeof skip === 'boolean') {
|
|
36
39
|
return skipOrRun(skip)
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
return skip.then(skipOrRun)
|
|
42
|
+
return skip.then(skipOrRun) as Promise<void>
|
|
40
43
|
}
|
|
44
|
+
return hook
|
|
45
|
+
}
|
|
@@ -65,13 +65,14 @@ export const softDelete = <H extends HookContext = HookContext>(
|
|
|
65
65
|
)
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
return async (context: H, next?: NextFunction) => {
|
|
68
|
+
return async (context: H, next?: NextFunction): Promise<void> => {
|
|
69
69
|
checkContext(context, { type: ['before', 'around'], label: 'softDelete' })
|
|
70
70
|
|
|
71
71
|
const { disableSoftDeleteKey = 'disableSoftDelete' } = options
|
|
72
72
|
|
|
73
73
|
if (context.params[disableSoftDeleteKey]) {
|
|
74
|
-
|
|
74
|
+
await early(context, next)
|
|
75
|
+
return
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
const { deletedQuery, removeData } = options
|
|
@@ -105,10 +106,8 @@ export const softDelete = <H extends HookContext = HookContext>(
|
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
if (next) {
|
|
108
|
-
|
|
109
|
+
await next()
|
|
109
110
|
}
|
|
110
|
-
|
|
111
|
-
return context
|
|
112
111
|
}
|
|
113
112
|
}
|
|
114
113
|
|
|
@@ -44,17 +44,16 @@ const defaultStashFunc = (context: HookContext) => {
|
|
|
44
44
|
*/
|
|
45
45
|
export function stashable<H extends HookContext = HookContext>(
|
|
46
46
|
options?: StashableOptions,
|
|
47
|
-
)
|
|
48
|
-
(context: H, next: NextFunction): Promise<void>
|
|
49
|
-
(context: H): H
|
|
50
|
-
} {
|
|
47
|
+
) {
|
|
51
48
|
const propName = options?.propName ?? 'stashed'
|
|
52
49
|
const stashFunc = options?.stashFunc ?? defaultStashFunc
|
|
53
50
|
|
|
54
|
-
|
|
51
|
+
function hook(context: H): void
|
|
52
|
+
function hook(context: H, next: NextFunction): Promise<void>
|
|
53
|
+
function hook(context: H, next?: NextFunction): void | Promise<void> {
|
|
55
54
|
if (context.params._stashable) {
|
|
56
55
|
if (next) return next()
|
|
57
|
-
return
|
|
56
|
+
return
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
checkContext(context, {
|
|
@@ -68,6 +67,8 @@ export function stashable<H extends HookContext = HookContext>(
|
|
|
68
67
|
context.params[propName] = () => promise
|
|
69
68
|
|
|
70
69
|
if (next) return next()
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
return hook
|
|
73
74
|
}
|
|
@@ -32,7 +32,7 @@ export const throwIf = <H extends HookContext = HookContext>(
|
|
|
32
32
|
predicate: PredicateFn,
|
|
33
33
|
options?: ThrowIfOptions,
|
|
34
34
|
) => {
|
|
35
|
-
return async (context: H, next?: NextFunction) => {
|
|
35
|
+
return async (context: H, next?: NextFunction): Promise<void> => {
|
|
36
36
|
const result = await predicate(context)
|
|
37
37
|
|
|
38
38
|
if (result) {
|
|
@@ -42,7 +42,7 @@ export const throwIf = <H extends HookContext = HookContext>(
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
if (next) {
|
|
45
|
-
|
|
45
|
+
await next()
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -29,12 +29,10 @@ export const transformData =
|
|
|
29
29
|
<H extends HookContext = HookContext, D = Data<H>>(
|
|
30
30
|
transformer: TransformerInputFn<D, H>,
|
|
31
31
|
) =>
|
|
32
|
-
async (context: H, next?: NextFunction) => {
|
|
32
|
+
async (context: H, next?: NextFunction): Promise<void> => {
|
|
33
33
|
await mutateData(context, transformer)
|
|
34
34
|
|
|
35
35
|
if (next) {
|
|
36
|
-
|
|
36
|
+
await next()
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
return context
|
|
40
38
|
}
|
|
@@ -23,16 +23,17 @@ export const transformQuery = <
|
|
|
23
23
|
>(
|
|
24
24
|
transformer: TransformerFn<Q, H>,
|
|
25
25
|
) => {
|
|
26
|
-
|
|
26
|
+
function hook(context: H): void
|
|
27
|
+
function hook(context: H, next: NextFunction): Promise<void>
|
|
28
|
+
function hook(context: H, next?: NextFunction): void | Promise<void> {
|
|
27
29
|
context.params.query = transformer(context.params.query ?? {}, {
|
|
28
30
|
context,
|
|
29
31
|
i: 0,
|
|
30
32
|
})
|
|
31
33
|
|
|
32
|
-
if (next)
|
|
33
|
-
return next().then(() => context)
|
|
34
|
-
}
|
|
34
|
+
if (next) return next()
|
|
35
35
|
|
|
36
|
-
return
|
|
36
|
+
return
|
|
37
37
|
}
|
|
38
|
+
return hook
|
|
38
39
|
}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import type { HookContext, NextFunction } from '@feathersjs/feathers'
|
|
2
2
|
import { mutateResult } from '../../utils/mutate-result/mutate-result.util.js'
|
|
3
|
-
import type {
|
|
4
|
-
DispatchOption,
|
|
5
|
-
HookFunction,
|
|
6
|
-
TransformerInputFn,
|
|
7
|
-
} from '../../types.js'
|
|
3
|
+
import type { DispatchOption, TransformerInputFn } from '../../types.js'
|
|
8
4
|
import type { ResultSingleHookContext } from '../../utility-types/hook-context.js'
|
|
9
5
|
import type { AnyFallback } from '../../internal.utils.js'
|
|
10
6
|
|
|
@@ -37,9 +33,10 @@ export const transformResult =
|
|
|
37
33
|
<H extends HookContext = HookContext, R = Result<H>>(
|
|
38
34
|
transformer: TransformerInputFn<R, H>,
|
|
39
35
|
options?: TransformResultOptions,
|
|
40
|
-
)
|
|
41
|
-
(context: H, next?: NextFunction) =>
|
|
42
|
-
mutateResult(context, transformer, {
|
|
36
|
+
) =>
|
|
37
|
+
async (context: H, next?: NextFunction): Promise<void> => {
|
|
38
|
+
await mutateResult(context, transformer, {
|
|
43
39
|
next,
|
|
44
40
|
dispatch: options?.dispatch,
|
|
45
|
-
})
|
|
41
|
+
})
|
|
42
|
+
}
|