feathers-utils 3.0.2 → 3.1.0
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/index.cjs +60 -8
- package/dist/index.d.cts +269 -0
- package/dist/index.d.mts +269 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.mjs +60 -9
- package/package.json +23 -27
- package/src/filters/array.ts +1 -1
- package/src/filters/object.ts +1 -1
- package/src/hooks/createRelated.ts +3 -3
- package/src/hooks/forEach.ts +10 -8
- package/src/hooks/index.ts +0 -1
- package/src/hooks/onDelete.ts +2 -2
- package/src/hooks/parseFields.ts +20 -18
- package/src/hooks/removeRelated.ts +1 -1
- package/src/hooks/runPerItem.ts +2 -2
- package/src/hooks/setData.ts +5 -3
- package/src/mixins/debounce-mixin/DebouncedStore.ts +2 -2
- package/src/mixins/debounce-mixin/debounceMixin.ts +4 -4
- package/src/types.ts +1 -1
- package/src/typesInternal.ts +10 -4
- package/src/utility-types/index.ts +88 -42
- package/src/utils/getItemsIsArray.ts +12 -15
- package/src/utils/getPaginate.ts +1 -1
- package/src/utils/index.ts +1 -0
- package/src/utils/isMulti.ts +1 -1
- package/src/utils/isPaginated.ts +1 -1
- package/src/utils/markHookForSkip.ts +1 -1
- package/src/utils/mergeQuery/mergeArrays.ts +2 -2
- package/src/utils/mergeQuery/mergeQuery.ts +1 -1
- package/src/utils/mergeQuery/types.ts +1 -1
- package/src/utils/mergeQuery/utils.ts +11 -11
- package/src/utils/pushSet.ts +1 -1
- package/src/utils/setQueryKeySafely.ts +64 -0
- package/src/utils/setResultEmpty.ts +1 -1
- package/src/utils/shouldSkip.ts +1 -1
- package/src/utils/validateQueryProperty.ts +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _feathersjs_feathers from '@feathersjs/feathers';
|
|
2
|
-
import { HookContext, Application, Id, Query } from '@feathersjs/feathers';
|
|
2
|
+
import { HookContext, Application, Id, Query, Params } from '@feathersjs/feathers';
|
|
3
3
|
import { HookContext as HookContext$1, Application as Application$1 } from '@feathersjs/feathers/lib';
|
|
4
4
|
import { PropertyPath, DebouncedFunc } from 'lodash';
|
|
5
5
|
import { AdapterBase, FilterQueryOptions as FilterQueryOptions$1, PaginationOptions } from '@feathersjs/adapter-commons';
|
|
@@ -211,6 +211,11 @@ declare const validateQueryProperty: (query: any, operators?: string[]) => Query
|
|
|
211
211
|
|
|
212
212
|
declare const toJSON: (context: HookContext) => HookContext<_feathersjs_feathers.Application<any, any>, any>;
|
|
213
213
|
|
|
214
|
+
type SetQueryKeySafelyOptions = {
|
|
215
|
+
mutate?: boolean;
|
|
216
|
+
};
|
|
217
|
+
declare const setQueryKeySafely: (params: Params, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => Params<_feathersjs_feathers.Query>;
|
|
218
|
+
|
|
214
219
|
declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions$1) => any; };
|
|
215
220
|
|
|
216
221
|
declare const filterObject: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions$1) => any; };
|
|
@@ -261,4 +266,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
|
|
|
261
266
|
type InferDataFromPath<App extends Application, Path extends string, Method extends "create" | "update" | "patch"> = Method extends "create" ? InferCreateDataFromPath<App, Path> : Method extends "update" ? InferUpdateDataFromPath<App, Path> : Method extends "patch" ? InferPatchDataFromPath<App, Path> : never;
|
|
262
267
|
type InferResultFromPath<App extends Application, Path extends string, Method extends "get" | "find" | "create" | "update" | "patch" | "remove"> = Method extends "get" ? InferGetResultFromPath<App, Path> : Method extends "find" ? InferFindResultFromPath<App, Path> : Method extends "create" ? InferCreateResultFromPath<App, Path> : Method extends "update" ? InferUpdateResultFromPath<App, Path> : Method extends "patch" ? InferPatchResultFromPath<App, Path> : Method extends "remove" ? InferRemoveResultFromPath<App, Path> : never;
|
|
263
268
|
|
|
264
|
-
export { ActionOnEmptyIntersect, CreateRelatedOptions, DebouncedFunctionApp, DebouncedService, DebouncedStore, DebouncedStoreOptions, FilterQueryOptions, FirstLast, GetItemsIsArrayOptions, GetItemsIsArrayResult, GetService, Handle, HookForEachOptions, HookRunPerItemOptions, HookSetDataOptions, InferCreateData, InferCreateDataFromPath, InferCreateDataSingle, InferCreateDataSingleFromPath, InferCreateResult, InferCreateResultFromPath, InferCreateResultSingle, InferCreateResultSingleFromPath, InferDataFromPath, InferFindResult, InferFindResultFromPath, InferGetResult, InferGetResultFromPath, InferPatchData, InferPatchDataFromPath, InferPatchResult, InferPatchResultFromPath, InferRemoveResult, InferRemoveResultFromPath, InferResultFromPath, InferUpdateData, InferUpdateDataFromPath, InferUpdateResult, InferUpdateResultFromPath, InitDebounceMixinOptions, MergeQueryOptions, OnDeleteAction, OnDeleteOptions, Predicate, PredicateWithContext, PushSetOptions, RemoveRelatedOptions, ShouldSkipOptions, checkMulti, createRelated, debounceMixin, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, parseFields, pushSet, removeRelated, runPerItem, setData, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
|
|
269
|
+
export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FilterQueryOptions, type FirstLast, type GetItemsIsArrayOptions, type GetItemsIsArrayResult, type GetService, type Handle, type HookForEachOptions, type HookRunPerItemOptions, type HookSetDataOptions, type InferCreateData, type InferCreateDataFromPath, type InferCreateDataSingle, type InferCreateDataSingleFromPath, type InferCreateResult, type InferCreateResultFromPath, type InferCreateResultSingle, type InferCreateResultSingleFromPath, type InferDataFromPath, type InferFindResult, type InferFindResultFromPath, type InferGetResult, type InferGetResultFromPath, type InferPatchData, type InferPatchDataFromPath, type InferPatchResult, type InferPatchResultFromPath, type InferRemoveResult, type InferRemoveResultFromPath, type InferResultFromPath, type InferUpdateData, type InferUpdateDataFromPath, type InferUpdateResult, type InferUpdateResultFromPath, type InitDebounceMixinOptions, type MergeQueryOptions, type OnDeleteAction, type OnDeleteOptions, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
|
package/dist/index.mjs
CHANGED
|
@@ -440,9 +440,7 @@ function mergeQuery(target, source, _options) {
|
|
|
440
440
|
}
|
|
441
441
|
|
|
442
442
|
const getItemsIsArray = (context, options) => {
|
|
443
|
-
const {
|
|
444
|
-
from = "automatic"
|
|
445
|
-
} = options || {};
|
|
443
|
+
const { from = "automatic" } = options || {};
|
|
446
444
|
let itemOrItems;
|
|
447
445
|
if (from === "automatic") {
|
|
448
446
|
itemOrItems = context.type === "before" ? context.data : context.result;
|
|
@@ -568,9 +566,9 @@ const shouldSkip = (hookName, context, options) => {
|
|
|
568
566
|
return false;
|
|
569
567
|
};
|
|
570
568
|
|
|
571
|
-
const isPlainObject = (value) => _.isObject(value) && value.constructor === {}.constructor;
|
|
569
|
+
const isPlainObject$1 = (value) => _.isObject(value) && value.constructor === {}.constructor;
|
|
572
570
|
const validateQueryProperty = (query, operators = []) => {
|
|
573
|
-
if (!isPlainObject(query)) {
|
|
571
|
+
if (!isPlainObject$1(query)) {
|
|
574
572
|
return query;
|
|
575
573
|
}
|
|
576
574
|
for (const key of Object.keys(query)) {
|
|
@@ -578,7 +576,7 @@ const validateQueryProperty = (query, operators = []) => {
|
|
|
578
576
|
throw new BadRequest(`Invalid query parameter ${key}`, query);
|
|
579
577
|
}
|
|
580
578
|
const value = query[key];
|
|
581
|
-
if (isPlainObject(value)) {
|
|
579
|
+
if (isPlainObject$1(value)) {
|
|
582
580
|
query[key] = validateQueryProperty(value, operators);
|
|
583
581
|
}
|
|
584
582
|
}
|
|
@@ -594,6 +592,46 @@ const toJSON = (context) => {
|
|
|
594
592
|
return context;
|
|
595
593
|
};
|
|
596
594
|
|
|
595
|
+
const isPlainObject = (value) => value && [void 0, Object].includes(value.constructor);
|
|
596
|
+
const setQueryKeySafely = (params, key, value, operator = "$eq", options) => {
|
|
597
|
+
var _a;
|
|
598
|
+
const { mutate = false } = options || {};
|
|
599
|
+
if (!mutate) {
|
|
600
|
+
params = structuredClone(params);
|
|
601
|
+
}
|
|
602
|
+
if (!params.query) {
|
|
603
|
+
params.query = {};
|
|
604
|
+
}
|
|
605
|
+
if (!(key in params.query)) {
|
|
606
|
+
if (operator === "$eq") {
|
|
607
|
+
params.query[key] = value;
|
|
608
|
+
} else {
|
|
609
|
+
params.query[key] = {
|
|
610
|
+
[operator]: value
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
return params;
|
|
614
|
+
}
|
|
615
|
+
console.log(
|
|
616
|
+
"params.query[key]",
|
|
617
|
+
params.query[key],
|
|
618
|
+
isPlainObject(params.query[key])
|
|
619
|
+
);
|
|
620
|
+
if (isPlainObject(params.query[key]) && !(operator in params.query[key])) {
|
|
621
|
+
params.query[key][operator] = value;
|
|
622
|
+
} else {
|
|
623
|
+
(_a = params.query).$and ?? (_a.$and = []);
|
|
624
|
+
params.query.$and.push(
|
|
625
|
+
operator === "$eq" ? { [key]: value } : {
|
|
626
|
+
[key]: {
|
|
627
|
+
[operator]: value
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
return params;
|
|
633
|
+
};
|
|
634
|
+
|
|
597
635
|
function checkMulti() {
|
|
598
636
|
return (context) => {
|
|
599
637
|
if (shouldSkip("checkMulti", context)) {
|
|
@@ -807,7 +845,8 @@ function setData(from, to, _options) {
|
|
|
807
845
|
return context;
|
|
808
846
|
}
|
|
809
847
|
const { items } = getItemsIsArray(context);
|
|
810
|
-
|
|
848
|
+
const contextJson = toJSON(context);
|
|
849
|
+
if (!_has(contextJson, from)) {
|
|
811
850
|
if (!context.params?.provider || options.allowUndefined === true) {
|
|
812
851
|
return context;
|
|
813
852
|
}
|
|
@@ -816,7 +855,7 @@ function setData(from, to, _options) {
|
|
|
816
855
|
}
|
|
817
856
|
throw new Forbidden(`Expected field ${from.toString()} not available`);
|
|
818
857
|
}
|
|
819
|
-
const val = _get(
|
|
858
|
+
const val = _get(contextJson, from);
|
|
820
859
|
items.forEach((item) => {
|
|
821
860
|
let overwrite;
|
|
822
861
|
if (typeof options.overwrite === "function") {
|
|
@@ -833,6 +872,12 @@ function setData(from, to, _options) {
|
|
|
833
872
|
};
|
|
834
873
|
}
|
|
835
874
|
|
|
875
|
+
var __defProp = Object.defineProperty;
|
|
876
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
877
|
+
var __publicField = (obj, key, value) => {
|
|
878
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
879
|
+
return value;
|
|
880
|
+
};
|
|
836
881
|
const makeDefaultOptions = () => {
|
|
837
882
|
return {
|
|
838
883
|
leading: false,
|
|
@@ -843,6 +888,12 @@ const makeDefaultOptions = () => {
|
|
|
843
888
|
};
|
|
844
889
|
class DebouncedStore {
|
|
845
890
|
constructor(app, options) {
|
|
891
|
+
__publicField(this, "_app");
|
|
892
|
+
__publicField(this, "_options");
|
|
893
|
+
__publicField(this, "_isRunningById");
|
|
894
|
+
__publicField(this, "_queueById");
|
|
895
|
+
//_waitingById: Record<string, WaitingObject>;
|
|
896
|
+
__publicField(this, "add");
|
|
846
897
|
this._app = app;
|
|
847
898
|
this._options = Object.assign(makeDefaultOptions(), options);
|
|
848
899
|
this._queueById = {};
|
|
@@ -942,4 +993,4 @@ const filterObject = (...keys) => {
|
|
|
942
993
|
return result;
|
|
943
994
|
};
|
|
944
995
|
|
|
945
|
-
export { DebouncedStore, checkMulti, createRelated, debounceMixin, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, parseFields, pushSet, removeRelated, runPerItem, setData, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
|
|
996
|
+
export { DebouncedStore, checkMulti, createRelated, debounceMixin, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "feathers-utils",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Some utils for projects using '@feathersjs/feathers'",
|
|
5
5
|
"author": "fratzinger",
|
|
6
6
|
"repository": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"url": "https://github.com/fratzinger/feathers-utils"
|
|
9
9
|
},
|
|
10
10
|
"engines": {
|
|
11
|
-
"node": ">=
|
|
11
|
+
"node": ">= 18"
|
|
12
12
|
},
|
|
13
13
|
"homepage": "https://github.com/fratzinger/feathers-utils",
|
|
14
14
|
"license": "MIT",
|
|
@@ -40,37 +40,33 @@
|
|
|
40
40
|
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@feathersjs/adapter-commons": "^5.0.
|
|
44
|
-
"@feathersjs/commons": "^5.0.
|
|
45
|
-
"@feathersjs/errors": "^5.0.
|
|
43
|
+
"@feathersjs/adapter-commons": "^5.0.10",
|
|
44
|
+
"@feathersjs/commons": "^5.0.10",
|
|
45
|
+
"@feathersjs/errors": "^5.0.10",
|
|
46
46
|
"fast-equals": "^5.0.1",
|
|
47
|
-
"feathers-hooks-common": "^
|
|
47
|
+
"feathers-hooks-common": "^8.1.1",
|
|
48
48
|
"lodash": "^4.17.21"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@feathersjs/feathers": "^5.0.
|
|
52
|
-
"@feathersjs/memory": "^5.0.
|
|
53
|
-
"@
|
|
54
|
-
"@types/
|
|
55
|
-
"@
|
|
56
|
-
"@
|
|
57
|
-
"@
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"eslint": "^
|
|
62
|
-
"eslint-
|
|
63
|
-
"eslint-import-resolver-typescript": "^3.5.5",
|
|
64
|
-
"eslint-plugin-import": "^2.27.5",
|
|
65
|
-
"eslint-plugin-prettier": "^4.2.1",
|
|
51
|
+
"@feathersjs/feathers": "^5.0.10",
|
|
52
|
+
"@feathersjs/memory": "^5.0.10",
|
|
53
|
+
"@types/lodash": "^4.14.199",
|
|
54
|
+
"@types/node": "^20.8.3",
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
|
56
|
+
"@typescript-eslint/parser": "^6.7.4",
|
|
57
|
+
"@vitest/coverage-v8": "^0.34.6",
|
|
58
|
+
"eslint": "^8.51.0",
|
|
59
|
+
"eslint-config-prettier": "^9.0.0",
|
|
60
|
+
"eslint-import-resolver-typescript": "^3.6.1",
|
|
61
|
+
"eslint-plugin-import": "^2.28.1",
|
|
62
|
+
"eslint-plugin-prettier": "^5.0.0",
|
|
66
63
|
"eslint-plugin-security": "^1.7.1",
|
|
67
|
-
"np": "^8.0.
|
|
68
|
-
"
|
|
69
|
-
"prettier": "^2.8.8",
|
|
64
|
+
"np": "^8.0.4",
|
|
65
|
+
"prettier": "^3.0.3",
|
|
70
66
|
"shx": "^0.3.4",
|
|
71
|
-
"typescript": "^5.
|
|
72
|
-
"unbuild": "^
|
|
73
|
-
"vitest": "^0.
|
|
67
|
+
"typescript": "^5.2.2",
|
|
68
|
+
"unbuild": "^2.0.0",
|
|
69
|
+
"vitest": "^0.34.6"
|
|
74
70
|
},
|
|
75
71
|
"peerDependencies": {
|
|
76
72
|
"@feathersjs/feathers": "^5.0.0"
|
package/src/filters/array.ts
CHANGED
|
@@ -6,7 +6,7 @@ const filterQueryArray =
|
|
|
6
6
|
(arr: any, { operators }: FilterQueryOptions) => {
|
|
7
7
|
if (arr && !Array.isArray(arr)) {
|
|
8
8
|
throw new Error(
|
|
9
|
-
`Invalid query parameter '${key}'. It has to be an array
|
|
9
|
+
`Invalid query parameter '${key}'. It has to be an array`,
|
|
10
10
|
);
|
|
11
11
|
}
|
|
12
12
|
|
package/src/filters/object.ts
CHANGED
|
@@ -7,7 +7,7 @@ const filterQueryObject =
|
|
|
7
7
|
(obj: any, { operators }: FilterQueryOptions) => {
|
|
8
8
|
if (obj && !_isObject(obj)) {
|
|
9
9
|
throw new Error(
|
|
10
|
-
`Invalid query parameter: '${key}'. It has to be an object
|
|
10
|
+
`Invalid query parameter: '${key}'. It has to be an object`,
|
|
11
11
|
);
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@ export interface CreateRelatedOptions<S = Record<string, any>> {
|
|
|
15
15
|
*/
|
|
16
16
|
export function createRelated<
|
|
17
17
|
S = Record<string, any>,
|
|
18
|
-
H extends HookContext = HookContext
|
|
18
|
+
H extends HookContext = HookContext,
|
|
19
19
|
>({
|
|
20
20
|
service,
|
|
21
21
|
multi = true,
|
|
@@ -51,8 +51,8 @@ export function createRelated<
|
|
|
51
51
|
} else {
|
|
52
52
|
await Promise.all(
|
|
53
53
|
dataToCreate.map(async (item) =>
|
|
54
|
-
context.app.service(service as string).create(item)
|
|
55
|
-
)
|
|
54
|
+
context.app.service(service as string).create(item),
|
|
55
|
+
),
|
|
56
56
|
);
|
|
57
57
|
}
|
|
58
58
|
|
package/src/hooks/forEach.ts
CHANGED
|
@@ -6,25 +6,27 @@ import type { GetItemsIsArrayOptions } from "../utils/getItemsIsArray";
|
|
|
6
6
|
import { getItemsIsArray } from "../utils/getItemsIsArray";
|
|
7
7
|
|
|
8
8
|
export interface HookForEachOptions {
|
|
9
|
-
wait?: "sequential" | "parallel" | false
|
|
10
|
-
items?: GetItemsIsArrayOptions["from"]
|
|
9
|
+
wait?: "sequential" | "parallel" | false;
|
|
10
|
+
items?: GetItemsIsArrayOptions["from"];
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export const forEach = (
|
|
14
14
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
-
actionPerItem: (item: any, context: HookContext) => Promisable<any>,
|
|
16
|
-
_options?: HookForEachOptions
|
|
15
|
+
actionPerItem: (item: any, context: HookContext) => Promisable<any>,
|
|
16
|
+
_options?: HookForEachOptions,
|
|
17
17
|
): ReturnAsyncHook => {
|
|
18
18
|
const options: Required<HookForEachOptions> = {
|
|
19
19
|
wait: "parallel",
|
|
20
20
|
items: "automatic",
|
|
21
|
-
..._options
|
|
21
|
+
..._options,
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
return async (context: HookContext): Promise<HookContext> => {
|
|
25
|
-
if (shouldSkip("runForItems", context)) {
|
|
25
|
+
if (shouldSkip("runForItems", context)) {
|
|
26
|
+
return context;
|
|
27
|
+
}
|
|
26
28
|
|
|
27
|
-
const { items } =
|
|
29
|
+
const { items } = getItemsIsArray(context, { from: options.items });
|
|
28
30
|
|
|
29
31
|
const promises: Promise<any>[] = [];
|
|
30
32
|
|
|
@@ -44,4 +46,4 @@ export const forEach = (
|
|
|
44
46
|
|
|
45
47
|
return context;
|
|
46
48
|
};
|
|
47
|
-
};
|
|
49
|
+
};
|
package/src/hooks/index.ts
CHANGED
package/src/hooks/onDelete.ts
CHANGED
|
@@ -16,7 +16,7 @@ export interface OnDeleteOptions {
|
|
|
16
16
|
*/
|
|
17
17
|
export function onDelete<
|
|
18
18
|
S = Record<string, any>,
|
|
19
|
-
H extends HookContext = HookContext
|
|
19
|
+
H extends HookContext = HookContext,
|
|
20
20
|
>(
|
|
21
21
|
service: keyof S,
|
|
22
22
|
{
|
|
@@ -24,7 +24,7 @@ export function onDelete<
|
|
|
24
24
|
keyHere = "id",
|
|
25
25
|
onDelete = "cascade",
|
|
26
26
|
blocking = true,
|
|
27
|
-
}: OnDeleteOptions
|
|
27
|
+
}: OnDeleteOptions,
|
|
28
28
|
) {
|
|
29
29
|
if (!service || !keyThere) {
|
|
30
30
|
throw "initialize hook 'removeRelated' completely!";
|
package/src/hooks/parseFields.ts
CHANGED
|
@@ -5,23 +5,25 @@ import { getItemsIsArray } from "../utils/getItemsIsArray";
|
|
|
5
5
|
* Parse fields to date or number
|
|
6
6
|
* skips undefined fields
|
|
7
7
|
*/
|
|
8
|
-
export const parseFields =
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
8
|
+
export const parseFields =
|
|
9
|
+
(type: "date" | "number", options: { fields: string[] }) =>
|
|
10
|
+
(context: HookContext) => {
|
|
11
|
+
const { items } = getItemsIsArray(context);
|
|
12
|
+
|
|
13
|
+
items.forEach((item) => {
|
|
14
|
+
options.fields.forEach((field) => {
|
|
15
|
+
// ignore undefined fields
|
|
16
|
+
if (!(field in item)) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (type === "date") {
|
|
21
|
+
item[field] = new Date(item[field]);
|
|
22
|
+
} else if (type === "number") {
|
|
23
|
+
item[field] = Number(item[field]);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
23
26
|
});
|
|
24
|
-
});
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
};
|
|
28
|
+
return context;
|
|
29
|
+
};
|
package/src/hooks/runPerItem.ts
CHANGED
|
@@ -8,7 +8,7 @@ export interface HookRunPerItemOptions {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
const makeOptions = (
|
|
11
|
-
options?: HookRunPerItemOptions
|
|
11
|
+
options?: HookRunPerItemOptions,
|
|
12
12
|
): Required<HookRunPerItemOptions> => {
|
|
13
13
|
options = options || {};
|
|
14
14
|
return {
|
|
@@ -24,7 +24,7 @@ const makeOptions = (
|
|
|
24
24
|
export const runPerItem = <H extends HookContext = HookContext>(
|
|
25
25
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
26
|
actionPerItem: (item: any, context: H) => Promisable<any>,
|
|
27
|
-
_options?: HookRunPerItemOptions
|
|
27
|
+
_options?: HookRunPerItemOptions,
|
|
28
28
|
) => {
|
|
29
29
|
const options = makeOptions(_options);
|
|
30
30
|
return async (context: H) => {
|
package/src/hooks/setData.ts
CHANGED
|
@@ -26,7 +26,7 @@ const defaultOptions: Required<HookSetDataOptions> = {
|
|
|
26
26
|
export function setData<H extends HookContext = HookContext>(
|
|
27
27
|
from: PropertyPath,
|
|
28
28
|
to: PropertyPath,
|
|
29
|
-
_options?: HookSetDataOptions
|
|
29
|
+
_options?: HookSetDataOptions,
|
|
30
30
|
) {
|
|
31
31
|
const options: Required<HookSetDataOptions> = {
|
|
32
32
|
...defaultOptions,
|
|
@@ -39,7 +39,9 @@ export function setData<H extends HookContext = HookContext>(
|
|
|
39
39
|
|
|
40
40
|
const { items } = getItemsIsArray(context);
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
const contextJson = toJSON(context);
|
|
43
|
+
|
|
44
|
+
if (!_has(contextJson, from)) {
|
|
43
45
|
if (!context.params?.provider || options.allowUndefined === true) {
|
|
44
46
|
return context;
|
|
45
47
|
}
|
|
@@ -54,7 +56,7 @@ export function setData<H extends HookContext = HookContext>(
|
|
|
54
56
|
throw new Forbidden(`Expected field ${from.toString()} not available`);
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
const val = _get(
|
|
59
|
+
const val = _get(contextJson, from);
|
|
58
60
|
|
|
59
61
|
items.forEach((item: Record<string, unknown>) => {
|
|
60
62
|
let overwrite: boolean;
|
|
@@ -56,7 +56,7 @@ export class DebouncedStore {
|
|
|
56
56
|
private debounceById(
|
|
57
57
|
func: (id: Id, action: DebouncedFunctionApp) => Promise<void>,
|
|
58
58
|
wait: number,
|
|
59
|
-
options?: Partial<DebouncedStoreOptions
|
|
59
|
+
options?: Partial<DebouncedStoreOptions>,
|
|
60
60
|
) {
|
|
61
61
|
return (id: Id, action: (app?: Application) => void | Promise<void>) => {
|
|
62
62
|
if (typeof this._queueById[id] === "function") {
|
|
@@ -68,7 +68,7 @@ export class DebouncedStore {
|
|
|
68
68
|
this.unbounced(id, action);
|
|
69
69
|
},
|
|
70
70
|
wait,
|
|
71
|
-
{ ...options, leading: false }
|
|
71
|
+
{ ...options, leading: false },
|
|
72
72
|
); // leading required for return promise
|
|
73
73
|
return this._queueById[id](id, action);
|
|
74
74
|
};
|
|
@@ -3,13 +3,13 @@ import { DebouncedStore, makeDefaultOptions } from "./DebouncedStore";
|
|
|
3
3
|
import type { DebouncedStoreOptions, InitDebounceMixinOptions } from "./types";
|
|
4
4
|
|
|
5
5
|
export function debounceMixin(
|
|
6
|
-
options?: Partial<InitDebounceMixinOptions
|
|
6
|
+
options?: Partial<InitDebounceMixinOptions>,
|
|
7
7
|
): (app: Application) => void {
|
|
8
8
|
return (app: Application): void => {
|
|
9
9
|
options = options || {};
|
|
10
10
|
const defaultOptions = Object.assign(
|
|
11
11
|
makeDefaultOptions(),
|
|
12
|
-
options?.default
|
|
12
|
+
options?.default,
|
|
13
13
|
);
|
|
14
14
|
|
|
15
15
|
app.mixins.push((service: any, path) => {
|
|
@@ -18,7 +18,7 @@ export function debounceMixin(
|
|
|
18
18
|
// if service already has registered something on `debouncedStore`
|
|
19
19
|
if (service.debouncedStore) {
|
|
20
20
|
console.warn(
|
|
21
|
-
`[feathers-utils] service: '${path}' already has a property 'debouncedStore'. Mixin will skip creating a new debouncedStore
|
|
21
|
+
`[feathers-utils] service: '${path}' already has a property 'debouncedStore'. Mixin will skip creating a new debouncedStore`,
|
|
22
22
|
);
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
@@ -26,7 +26,7 @@ export function debounceMixin(
|
|
|
26
26
|
const serviceOptions = Object.assign({}, defaultOptions, options?.[path]);
|
|
27
27
|
service.debouncedStore = new DebouncedStore(
|
|
28
28
|
app,
|
|
29
|
-
serviceOptions as DebouncedStoreOptions
|
|
29
|
+
serviceOptions as DebouncedStoreOptions,
|
|
30
30
|
);
|
|
31
31
|
});
|
|
32
32
|
};
|
package/src/types.ts
CHANGED
package/src/typesInternal.ts
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
// here are types that are not meant to be exported!
|
|
2
2
|
// just for internal use of this package
|
|
3
3
|
|
|
4
|
-
import { HookContext } from "@feathersjs/feathers/lib";
|
|
4
|
+
import type { HookContext } from "@feathersjs/feathers/lib";
|
|
5
5
|
|
|
6
6
|
export type MaybeArray<T> = T | T[];
|
|
7
7
|
export type Promisable<T> = T | Promise<T>;
|
|
8
8
|
export type Path = Array<string | number>;
|
|
9
9
|
|
|
10
10
|
export type HookType = "before" | "after" | "error";
|
|
11
|
-
export type ServiceMethodName =
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
export type ServiceMethodName =
|
|
12
|
+
| "find"
|
|
13
|
+
| "get"
|
|
14
|
+
| "create"
|
|
15
|
+
| "update"
|
|
16
|
+
| "patch"
|
|
17
|
+
| "remove";
|
|
18
|
+
export type ReturnSyncHook = (context: HookContext) => HookContext;
|
|
19
|
+
export type ReturnAsyncHook = (context: HookContext) => Promise<HookContext>;
|