feathers-utils 7.0.0 → 7.0.1
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/README.md +3 -4
- package/dist/index.cjs +28 -42
- package/dist/index.d.cts +27 -28
- package/dist/index.d.mts +27 -28
- package/dist/index.d.ts +27 -28
- package/dist/index.mjs +28 -42
- package/package.json +19 -22
- package/src/filters/array.ts +11 -13
- package/src/filters/index.ts +2 -2
- package/src/filters/object.ts +11 -11
- package/src/hooks/checkMulti.ts +98 -82
- package/src/hooks/createRelated.ts +22 -23
- package/src/hooks/forEach.ts +32 -32
- package/src/hooks/from-client-for-server/common.ts +1 -1
- package/src/hooks/from-client-for-server/index.ts +2 -2
- package/src/hooks/from-client-for-server/paramsForServer.ts +32 -32
- package/src/hooks/from-client-for-server/paramsFromClient.ts +25 -25
- package/src/hooks/index.ts +9 -9
- package/src/hooks/onDelete.ts +32 -32
- package/src/hooks/parseFields.ts +13 -13
- package/src/hooks/removeRelated.ts +20 -20
- package/src/hooks/runPerItem.ts +17 -18
- package/src/hooks/setData.ts +295 -264
- package/src/index.ts +6 -6
- package/src/mixins/debounce-mixin/DebouncedStore.ts +29 -29
- package/src/mixins/debounce-mixin/debounceMixin.ts +17 -17
- package/src/mixins/debounce-mixin/index.ts +3 -3
- package/src/mixins/debounce-mixin/types.ts +9 -9
- package/src/mixins/debounce-mixin/utils.ts +3 -3
- package/src/mixins/index.ts +1 -1
- package/src/types.ts +3 -5
- package/src/typesInternal.ts +14 -14
- package/src/utility-types/index.ts +48 -48
- package/src/utils/_utils.internal.ts +5 -5
- package/src/utils/defineHooks.ts +8 -8
- package/src/utils/deflattenQuery.ts +31 -31
- package/src/utils/filterQuery.ts +58 -58
- package/src/utils/flattenQuery.ts +54 -54
- package/src/utils/getItemsIsArray.ts +148 -149
- package/src/utils/getPaginate.ts +31 -31
- package/src/utils/index.ts +17 -17
- package/src/utils/isMulti.ts +48 -40
- package/src/utils/isPaginated.ts +30 -30
- package/src/utils/markHookForSkip.ts +177 -178
- package/src/utils/mergeQuery/index.ts +3 -3
- package/src/utils/mergeQuery/mergeArrays.ts +67 -67
- package/src/utils/mergeQuery/mergeQuery.ts +211 -211
- package/src/utils/mergeQuery/types.ts +12 -12
- package/src/utils/mergeQuery/utils.ts +224 -224
- package/src/utils/optimizeBatchPatch.ts +42 -42
- package/src/utils/pushSet.ts +57 -57
- package/src/utils/setQueryKeySafely.ts +68 -68
- package/src/utils/setResultEmpty.ts +125 -123
- package/src/utils/shouldSkip.ts +72 -72
- package/src/utils/toJSON.ts +4 -4
- package/src/utils/validateQueryProperty.ts +10 -10
- package/src/hooks/makeSequelizeQuery.ts_ +0 -90
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { HookContext } from
|
|
2
|
-
import { FROM_CLIENT_FOR_SERVER_DEFAULT_KEY } from
|
|
1
|
+
import type { HookContext } from '@feathersjs/feathers'
|
|
2
|
+
import { FROM_CLIENT_FOR_SERVER_DEFAULT_KEY } from './common.js'
|
|
3
3
|
|
|
4
4
|
export function defineParamsFromClient(keyToHide: string) {
|
|
5
5
|
return function paramsFromClient(
|
|
@@ -8,9 +8,9 @@ export function defineParamsFromClient(keyToHide: string) {
|
|
|
8
8
|
return (context: HookContext): HookContext => {
|
|
9
9
|
if (
|
|
10
10
|
!context.params?.query?.[keyToHide] ||
|
|
11
|
-
typeof context.params.query[keyToHide] !==
|
|
11
|
+
typeof context.params.query[keyToHide] !== 'object'
|
|
12
12
|
) {
|
|
13
|
-
return context
|
|
13
|
+
return context
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
const params = {
|
|
@@ -21,40 +21,40 @@ export function defineParamsFromClient(keyToHide: string) {
|
|
|
21
21
|
...context.params.query[keyToHide],
|
|
22
22
|
},
|
|
23
23
|
},
|
|
24
|
-
}
|
|
24
|
+
}
|
|
25
25
|
|
|
26
|
-
const client = params.query[keyToHide]
|
|
26
|
+
const client = params.query[keyToHide]
|
|
27
27
|
|
|
28
28
|
whitelist.forEach((key) => {
|
|
29
29
|
if (key in client) {
|
|
30
|
-
params[key] = client[key]
|
|
31
|
-
delete client[key]
|
|
30
|
+
params[key] = client[key]
|
|
31
|
+
delete client[key]
|
|
32
32
|
}
|
|
33
|
-
})
|
|
33
|
+
})
|
|
34
34
|
|
|
35
35
|
if (Object.keys(client).length === 0) {
|
|
36
|
-
delete params.query[keyToHide]
|
|
36
|
+
delete params.query[keyToHide]
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
context.params = params
|
|
39
|
+
context.params = params
|
|
40
40
|
|
|
41
|
-
return context
|
|
42
|
-
}
|
|
43
|
-
}
|
|
41
|
+
return context
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export const paramsFromClient = defineParamsFromClient(
|
|
47
47
|
FROM_CLIENT_FOR_SERVER_DEFAULT_KEY,
|
|
48
|
-
)
|
|
48
|
+
)
|
|
49
49
|
|
|
50
50
|
if (import.meta.vitest) {
|
|
51
|
-
const { it, expect } = import.meta.vitest
|
|
51
|
+
const { it, expect } = import.meta.vitest
|
|
52
52
|
|
|
53
|
-
it(
|
|
53
|
+
it('should move params to query._$client', () => {
|
|
54
54
|
expect(
|
|
55
55
|
paramsFromClient(
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
'a',
|
|
57
|
+
'b',
|
|
58
58
|
)({
|
|
59
59
|
params: {
|
|
60
60
|
query: {
|
|
@@ -74,12 +74,12 @@ if (import.meta.vitest) {
|
|
|
74
74
|
c: 3,
|
|
75
75
|
},
|
|
76
76
|
},
|
|
77
|
-
})
|
|
78
|
-
})
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
79
|
|
|
80
|
-
it(
|
|
80
|
+
it('should move params to query._$client and leave remaining', () => {
|
|
81
81
|
expect(
|
|
82
|
-
paramsFromClient(
|
|
82
|
+
paramsFromClient('a')({
|
|
83
83
|
params: {
|
|
84
84
|
query: {
|
|
85
85
|
_$client: {
|
|
@@ -100,6 +100,6 @@ if (import.meta.vitest) {
|
|
|
100
100
|
c: 3,
|
|
101
101
|
},
|
|
102
102
|
},
|
|
103
|
-
})
|
|
104
|
-
})
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
105
|
}
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
6
|
-
export * from
|
|
7
|
-
export * from
|
|
8
|
-
export * from
|
|
9
|
-
export * from
|
|
1
|
+
export * from './checkMulti.js'
|
|
2
|
+
export * from './createRelated.js'
|
|
3
|
+
export * from './forEach.js'
|
|
4
|
+
export * from './onDelete.js'
|
|
5
|
+
export * from './parseFields.js'
|
|
6
|
+
export * from './removeRelated.js'
|
|
7
|
+
export * from './runPerItem.js'
|
|
8
|
+
export * from './setData.js'
|
|
9
|
+
export * from './from-client-for-server/index.js'
|
package/src/hooks/onDelete.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import type { HookContext } from
|
|
2
|
-
import { checkContext } from
|
|
3
|
-
import { getItemsIsArray, shouldSkip } from
|
|
4
|
-
import type { KeyOf, MaybeArray } from
|
|
1
|
+
import type { HookContext } from '@feathersjs/feathers'
|
|
2
|
+
import { checkContext } from 'feathers-hooks-common'
|
|
3
|
+
import { getItemsIsArray, shouldSkip } from '../utils/index.js'
|
|
4
|
+
import type { KeyOf, MaybeArray } from '../typesInternal.js'
|
|
5
5
|
|
|
6
|
-
export type OnDeleteAction =
|
|
6
|
+
export type OnDeleteAction = 'cascade' | 'set null'
|
|
7
7
|
|
|
8
8
|
export interface OnDeleteOptions<Path extends string = string> {
|
|
9
|
-
service: Path
|
|
10
|
-
keyThere: string
|
|
11
|
-
keyHere: string
|
|
12
|
-
onDelete: OnDeleteAction
|
|
13
|
-
blocking?: boolean
|
|
9
|
+
service: Path
|
|
10
|
+
keyThere: string
|
|
11
|
+
keyHere: string
|
|
12
|
+
onDelete: OnDeleteAction
|
|
13
|
+
blocking?: boolean
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -21,25 +21,25 @@ export function onDelete<
|
|
|
21
21
|
H extends HookContext = HookContext,
|
|
22
22
|
>(options: MaybeArray<OnDeleteOptions<KeyOf<S>>>) {
|
|
23
23
|
return async (context: H) => {
|
|
24
|
-
if (shouldSkip(
|
|
25
|
-
return context
|
|
24
|
+
if (shouldSkip('onDelete', context)) {
|
|
25
|
+
return context
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
checkContext(context,
|
|
28
|
+
checkContext(context, 'after', 'remove', 'onDelete')
|
|
29
29
|
|
|
30
|
-
const { items } = getItemsIsArray(context)
|
|
30
|
+
const { items } = getItemsIsArray(context)
|
|
31
31
|
|
|
32
|
-
const entries = Array.isArray(options) ? options : [options]
|
|
32
|
+
const entries = Array.isArray(options) ? options : [options]
|
|
33
33
|
|
|
34
|
-
const promises: Promise<any>[] = []
|
|
34
|
+
const promises: Promise<any>[] = []
|
|
35
35
|
|
|
36
36
|
entries.forEach(
|
|
37
37
|
async ({ keyHere, keyThere, onDelete, service, blocking }) => {
|
|
38
|
-
let ids = items.map((x) => x[keyHere]).filter((x) => !!x)
|
|
39
|
-
ids = [...new Set(ids)]
|
|
38
|
+
let ids = items.map((x) => x[keyHere]).filter((x) => !!x)
|
|
39
|
+
ids = [...new Set(ids)]
|
|
40
40
|
|
|
41
41
|
if (!ids || ids.length <= 0) {
|
|
42
|
-
return context
|
|
42
|
+
return context
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
const params = {
|
|
@@ -49,29 +49,29 @@ export function onDelete<
|
|
|
49
49
|
},
|
|
50
50
|
},
|
|
51
51
|
paginate: false,
|
|
52
|
-
}
|
|
52
|
+
}
|
|
53
53
|
|
|
54
|
-
let promise: Promise<any> | undefined = undefined
|
|
54
|
+
let promise: Promise<any> | undefined = undefined
|
|
55
55
|
|
|
56
|
-
if (onDelete ===
|
|
57
|
-
promise = context.app.service(service as string).remove(null, params)
|
|
58
|
-
} else if (onDelete ===
|
|
59
|
-
const data = { [keyThere]: null }
|
|
56
|
+
if (onDelete === 'cascade') {
|
|
57
|
+
promise = context.app.service(service as string).remove(null, params)
|
|
58
|
+
} else if (onDelete === 'set null') {
|
|
59
|
+
const data = { [keyThere]: null }
|
|
60
60
|
promise = context.app
|
|
61
61
|
.service(service as string)
|
|
62
|
-
.patch(null, data, params)
|
|
62
|
+
.patch(null, data, params)
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
if (blocking) {
|
|
66
|
-
promises.push(promise)
|
|
65
|
+
if (blocking && promise) {
|
|
66
|
+
promises.push(promise)
|
|
67
67
|
}
|
|
68
68
|
},
|
|
69
|
-
)
|
|
69
|
+
)
|
|
70
70
|
|
|
71
71
|
if (promises.length) {
|
|
72
|
-
await Promise.all(promises)
|
|
72
|
+
await Promise.all(promises)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
return context
|
|
76
|
-
}
|
|
75
|
+
return context
|
|
76
|
+
}
|
|
77
77
|
}
|
package/src/hooks/parseFields.ts
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import type { HookContext } from
|
|
2
|
-
import { getItemsIsArray } from
|
|
1
|
+
import type { HookContext } from '@feathersjs/feathers'
|
|
2
|
+
import { getItemsIsArray } from '../utils/getItemsIsArray.js'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Parse fields to date or number
|
|
6
6
|
* skips undefined fields
|
|
7
7
|
*/
|
|
8
8
|
export const parseFields =
|
|
9
|
-
(type:
|
|
9
|
+
(type: 'date' | 'number', options: { fields: string[] }) =>
|
|
10
10
|
(context: HookContext) => {
|
|
11
|
-
const { items } = getItemsIsArray(context)
|
|
11
|
+
const { items } = getItemsIsArray(context)
|
|
12
12
|
|
|
13
13
|
items.forEach((item) => {
|
|
14
14
|
options.fields.forEach((field) => {
|
|
15
15
|
// ignore undefined fields
|
|
16
16
|
if (!(field in item)) {
|
|
17
|
-
return
|
|
17
|
+
return
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
if (type ===
|
|
21
|
-
item[field] = new Date(item[field])
|
|
22
|
-
} else if (type ===
|
|
23
|
-
item[field] = Number(item[field])
|
|
20
|
+
if (type === 'date') {
|
|
21
|
+
item[field] = new Date(item[field])
|
|
22
|
+
} else if (type === 'number') {
|
|
23
|
+
item[field] = Number(item[field])
|
|
24
24
|
}
|
|
25
|
-
})
|
|
26
|
-
})
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
27
|
|
|
28
|
-
return context
|
|
29
|
-
}
|
|
28
|
+
return context
|
|
29
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { HookContext, Params, Query } from
|
|
2
|
-
import { checkContext } from
|
|
3
|
-
import { getItemsIsArray, shouldSkip } from
|
|
1
|
+
import type { HookContext, Params, Query } from '@feathersjs/feathers'
|
|
2
|
+
import { checkContext } from 'feathers-hooks-common'
|
|
3
|
+
import { getItemsIsArray, shouldSkip } from '../utils/index.js'
|
|
4
4
|
|
|
5
5
|
export interface RemoveRelatedOptions<S = Record<string, any>> {
|
|
6
|
-
service: keyof S
|
|
7
|
-
keyThere: string
|
|
8
|
-
keyHere: string
|
|
9
|
-
blocking?: boolean
|
|
6
|
+
service: keyof S
|
|
7
|
+
keyThere: string
|
|
8
|
+
keyHere: string
|
|
9
|
+
blocking?: boolean
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -20,26 +20,26 @@ export function removeRelated<
|
|
|
20
20
|
>({
|
|
21
21
|
service,
|
|
22
22
|
keyThere,
|
|
23
|
-
keyHere =
|
|
23
|
+
keyHere = 'id',
|
|
24
24
|
blocking = true,
|
|
25
25
|
}: RemoveRelatedOptions<S>) {
|
|
26
26
|
if (!service || !keyThere) {
|
|
27
|
-
throw "initialize hook 'removeRelated' completely!"
|
|
27
|
+
throw "initialize hook 'removeRelated' completely!"
|
|
28
28
|
}
|
|
29
29
|
return async (context: H) => {
|
|
30
|
-
if (shouldSkip(
|
|
31
|
-
return context
|
|
30
|
+
if (shouldSkip('removeRelated', context)) {
|
|
31
|
+
return context
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
checkContext(context,
|
|
34
|
+
checkContext(context, 'after', 'remove', 'removeRelated')
|
|
35
35
|
|
|
36
|
-
const { items } = getItemsIsArray(context)
|
|
36
|
+
const { items } = getItemsIsArray(context)
|
|
37
37
|
|
|
38
|
-
let ids = items.map((x) => x[keyHere]).filter((x) => !!x)
|
|
39
|
-
ids = [...new Set(ids)]
|
|
38
|
+
let ids = items.map((x) => x[keyHere]).filter((x) => !!x)
|
|
39
|
+
ids = [...new Set(ids)]
|
|
40
40
|
|
|
41
41
|
if (!ids || ids.length <= 0) {
|
|
42
|
-
return context
|
|
42
|
+
return context
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// feathers does not accept `paginate: false` for remove, but some adapters need it to work properly
|
|
@@ -52,12 +52,12 @@ export function removeRelated<
|
|
|
52
52
|
},
|
|
53
53
|
},
|
|
54
54
|
paginate: false,
|
|
55
|
-
} as Params<Query>)
|
|
55
|
+
} as Params<Query>)
|
|
56
56
|
|
|
57
57
|
if (blocking) {
|
|
58
|
-
await promise
|
|
58
|
+
await promise
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
return context
|
|
62
|
-
}
|
|
61
|
+
return context
|
|
62
|
+
}
|
|
63
63
|
}
|
package/src/hooks/runPerItem.ts
CHANGED
|
@@ -1,47 +1,46 @@
|
|
|
1
|
-
import { shouldSkip, getItemsIsArray } from
|
|
1
|
+
import { shouldSkip, getItemsIsArray } from '../utils/index.js'
|
|
2
2
|
|
|
3
|
-
import type { HookContext } from
|
|
4
|
-
import type { Promisable } from
|
|
3
|
+
import type { HookContext } from '@feathersjs/feathers'
|
|
4
|
+
import type { Promisable } from '../typesInternal.js'
|
|
5
5
|
|
|
6
6
|
export interface HookRunPerItemOptions {
|
|
7
|
-
wait?: boolean
|
|
7
|
+
wait?: boolean
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
const makeOptions = (
|
|
11
11
|
options?: HookRunPerItemOptions,
|
|
12
12
|
): Required<HookRunPerItemOptions> => {
|
|
13
|
-
options = options || {}
|
|
13
|
+
options = options || {}
|
|
14
14
|
return {
|
|
15
15
|
wait: true,
|
|
16
16
|
...options,
|
|
17
|
-
}
|
|
18
|
-
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* hook to run a hook for each item in the context
|
|
22
22
|
* uses `context.result` if it is existent. otherwise uses context.data
|
|
23
23
|
*/
|
|
24
24
|
export const runPerItem = <H extends HookContext = HookContext, T = any>(
|
|
25
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
25
|
actionPerItem: (item: T, context: H) => Promisable<any>,
|
|
27
26
|
_options?: HookRunPerItemOptions,
|
|
28
27
|
) => {
|
|
29
|
-
const options = makeOptions(_options)
|
|
28
|
+
const options = makeOptions(_options)
|
|
30
29
|
return async (context: H) => {
|
|
31
|
-
if (shouldSkip(
|
|
32
|
-
return context
|
|
30
|
+
if (shouldSkip('runForItems', context)) {
|
|
31
|
+
return context
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
const { items } = getItemsIsArray(context)
|
|
34
|
+
const { items } = getItemsIsArray(context)
|
|
36
35
|
|
|
37
36
|
const promises = items.map(async (item: T) => {
|
|
38
|
-
await actionPerItem(item, context)
|
|
39
|
-
})
|
|
37
|
+
await actionPerItem(item, context)
|
|
38
|
+
})
|
|
40
39
|
|
|
41
40
|
if (options.wait) {
|
|
42
|
-
await Promise.all(promises)
|
|
41
|
+
await Promise.all(promises)
|
|
43
42
|
}
|
|
44
43
|
|
|
45
|
-
return context
|
|
46
|
-
}
|
|
47
|
-
}
|
|
44
|
+
return context
|
|
45
|
+
}
|
|
46
|
+
}
|