feathers-utils 5.1.0 → 6.0.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/README.md +3 -2
- package/dist/index.cjs +117 -32
- package/dist/index.d.cts +13 -8
- package/dist/index.d.mts +13 -8
- package/dist/index.d.ts +13 -8
- package/dist/index.mjs +115 -29
- package/package.json +18 -20
- package/src/filters/object.ts +2 -2
- package/src/hooks/checkMulti.ts +151 -0
- package/src/hooks/setData.ts +509 -0
- package/src/mixins/debounce-mixin/DebouncedStore.ts +1 -9
- package/src/mixins/debounce-mixin/debounceMixin.ts +2 -1
- package/src/mixins/debounce-mixin/utils.ts +10 -0
- package/src/types.ts +1 -0
- package/src/typesInternal.ts +2 -0
- package/src/utils/_utils.internal.ts +16 -0
- package/src/utils/deflattenQuery.ts +109 -0
- package/src/utils/filterQuery.ts +112 -40
- package/src/utils/flattenQuery.ts +198 -0
- package/src/utils/getItemsIsArray.ts +279 -0
- package/src/utils/getPaginate.ts +74 -1
- package/src/utils/index.ts +2 -0
- package/src/utils/isMulti.ts +51 -0
- package/src/utils/isPaginated.ts +72 -0
- package/src/utils/markHookForSkip.ts +411 -0
- package/src/utils/mergeQuery/mergeArrays.ts +68 -0
- package/src/utils/mergeQuery/mergeQuery.ts +464 -3
- package/src/utils/mergeQuery/types.ts +0 -1
- package/src/utils/mergeQuery/utils.ts +93 -5
- package/src/utils/optimizeBatchPatch.ts +54 -22
- package/src/utils/pushSet.ts +67 -1
- package/src/utils/setQueryKeySafely.ts +169 -4
- package/src/utils/setResultEmpty.ts +260 -0
- package/src/utils/shouldSkip.ts +121 -0
- package/src/utils/validateQueryProperty.ts +3 -6
- package/src/utils/internal.utils.ts +0 -9
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import { Forbidden, GeneralError, BadRequest, MethodNotAllowed } from '@feathersjs/errors';
|
|
2
|
-
import
|
|
2
|
+
import { deepEqual } from 'fast-equals';
|
|
3
3
|
import _get from 'lodash/get.js';
|
|
4
4
|
import _set from 'lodash/set.js';
|
|
5
5
|
import _merge from 'lodash/merge.js';
|
|
6
|
-
import _isEmpty from 'lodash/isEmpty.js';
|
|
7
6
|
import _has from 'lodash/has.js';
|
|
8
7
|
import _uniqWith from 'lodash/uniqWith.js';
|
|
9
|
-
import { deepEqual } from 'fast-equals';
|
|
10
|
-
import { _ } from '@feathersjs/commons';
|
|
11
8
|
import { checkContext } from 'feathers-hooks-common';
|
|
12
9
|
import _debounce from 'lodash/debounce.js';
|
|
13
|
-
import _isObject from 'lodash/isObject.js';
|
|
14
10
|
|
|
15
11
|
function defineHooks(hooks) {
|
|
16
12
|
return hooks;
|
|
@@ -34,6 +30,23 @@ function filterQuery(providedQuery) {
|
|
|
34
30
|
}
|
|
35
31
|
return result;
|
|
36
32
|
}
|
|
33
|
+
function reassembleQuery(query) {
|
|
34
|
+
const { $select, $limit, $skip, $sort, query: rest } = query;
|
|
35
|
+
const result = rest;
|
|
36
|
+
if ($select !== void 0) {
|
|
37
|
+
result.$select = $select;
|
|
38
|
+
}
|
|
39
|
+
if ($limit !== void 0) {
|
|
40
|
+
result.$limit = $limit;
|
|
41
|
+
}
|
|
42
|
+
if ($skip !== void 0) {
|
|
43
|
+
result.$skip = $skip;
|
|
44
|
+
}
|
|
45
|
+
if ($sort !== void 0) {
|
|
46
|
+
result.$sort = $sort;
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
37
50
|
|
|
38
51
|
const getItemsIsArray = (context, options) => {
|
|
39
52
|
const { from = "automatic" } = options || {};
|
|
@@ -58,7 +71,9 @@ const getItemsIsArray = (context, options) => {
|
|
|
58
71
|
const hasOwnProperty = (obj, ...keys) => {
|
|
59
72
|
return keys.some((x) => Object.prototype.hasOwnProperty.call(obj, x));
|
|
60
73
|
};
|
|
61
|
-
const
|
|
74
|
+
const isObject = (item) => !!item && typeof item === "object" && !Array.isArray(item);
|
|
75
|
+
const isPlainObject = (value) => isObject(value) && value.constructor === {}.constructor;
|
|
76
|
+
const isEmpty = (obj) => [Object, Array].includes((obj || {}).constructor) && !Object.keys(obj || {}).length;
|
|
62
77
|
|
|
63
78
|
const getPaginate = (context) => {
|
|
64
79
|
if (hasOwnProperty(context.params, "paginate")) {
|
|
@@ -106,7 +121,7 @@ const pushSet = (obj, path, val, options) => {
|
|
|
106
121
|
_set(obj, path, arr);
|
|
107
122
|
return arr;
|
|
108
123
|
} else {
|
|
109
|
-
if (options.unique && arr.some((x) =>
|
|
124
|
+
if (options.unique && arr.some((x) => deepEqual(x, val))) {
|
|
110
125
|
return arr;
|
|
111
126
|
}
|
|
112
127
|
arr.push(val);
|
|
@@ -389,7 +404,7 @@ function cleanOr(target) {
|
|
|
389
404
|
if (!target || !Array.isArray(target) || target.length <= 0) {
|
|
390
405
|
return target;
|
|
391
406
|
}
|
|
392
|
-
if (target.some((x) =>
|
|
407
|
+
if (target.some((x) => isEmpty(x))) {
|
|
393
408
|
return void 0;
|
|
394
409
|
} else {
|
|
395
410
|
return arrayWithoutDuplicates(target);
|
|
@@ -399,10 +414,10 @@ function cleanAnd(target) {
|
|
|
399
414
|
if (!target || !Array.isArray(target) || target.length <= 0) {
|
|
400
415
|
return target;
|
|
401
416
|
}
|
|
402
|
-
if (target.every((x) =>
|
|
417
|
+
if (target.every((x) => isEmpty(x))) {
|
|
403
418
|
return void 0;
|
|
404
419
|
} else {
|
|
405
|
-
target = target.filter((x) => !
|
|
420
|
+
target = target.filter((x) => !isEmpty(x));
|
|
406
421
|
return arrayWithoutDuplicates(target);
|
|
407
422
|
}
|
|
408
423
|
}
|
|
@@ -468,7 +483,7 @@ function mergeQuery(target, source, _options) {
|
|
|
468
483
|
...sourceQuery
|
|
469
484
|
};
|
|
470
485
|
}
|
|
471
|
-
if (options.useLogicalConjunction && (options.defaultHandle === "combine" || options.defaultHandle === "intersect") && !
|
|
486
|
+
if (options.useLogicalConjunction && (options.defaultHandle === "combine" || options.defaultHandle === "intersect") && !isEmpty(targetQuery)) {
|
|
472
487
|
const logicalOp = options.defaultHandle === "combine" ? "$or" : "$and";
|
|
473
488
|
if (hasOwnProperty(sourceQuery, logicalOp)) {
|
|
474
489
|
const andOr = sourceQuery[logicalOp];
|
|
@@ -509,7 +524,7 @@ const setQueryKeySafely = (params, key, value, operator = "$eq", options) => {
|
|
|
509
524
|
}
|
|
510
525
|
return params;
|
|
511
526
|
}
|
|
512
|
-
if (isPlainObject
|
|
527
|
+
if (isPlainObject(params.query[key]) && !(operator in params.query[key])) {
|
|
513
528
|
params.query[key][operator] = value;
|
|
514
529
|
} else {
|
|
515
530
|
(_a = params.query).$and ?? (_a.$and = []);
|
|
@@ -574,9 +589,8 @@ const toJSON = (context) => {
|
|
|
574
589
|
return context;
|
|
575
590
|
};
|
|
576
591
|
|
|
577
|
-
const isPlainObject = (value) => _.isObject(value) && value.constructor === {}.constructor;
|
|
578
592
|
const validateQueryProperty = (query, operators = []) => {
|
|
579
|
-
if (!
|
|
593
|
+
if (!isObject(query)) {
|
|
580
594
|
return query;
|
|
581
595
|
}
|
|
582
596
|
for (const key of Object.keys(query)) {
|
|
@@ -584,7 +598,7 @@ const validateQueryProperty = (query, operators = []) => {
|
|
|
584
598
|
throw new BadRequest(`Invalid query parameter ${key}`, query);
|
|
585
599
|
}
|
|
586
600
|
const value = query[key];
|
|
587
|
-
if (
|
|
601
|
+
if (isObject(value)) {
|
|
588
602
|
query[key] = validateQueryProperty(value, operators);
|
|
589
603
|
}
|
|
590
604
|
}
|
|
@@ -595,13 +609,18 @@ const validateQueryProperty = (query, operators = []) => {
|
|
|
595
609
|
|
|
596
610
|
function optimizeBatchPatch(items, options) {
|
|
597
611
|
const map = [];
|
|
598
|
-
const
|
|
599
|
-
for (const
|
|
600
|
-
const
|
|
612
|
+
const idKey = options?.id ?? "id";
|
|
613
|
+
for (const _data of items) {
|
|
614
|
+
const data = _data;
|
|
615
|
+
const id = _data[idKey];
|
|
616
|
+
delete data[idKey];
|
|
617
|
+
const index = map.findIndex((item) => {
|
|
618
|
+
return deepEqual(item.data, data);
|
|
619
|
+
});
|
|
601
620
|
if (index === -1) {
|
|
602
|
-
map.push({ ids: [
|
|
621
|
+
map.push({ ids: [id], data });
|
|
603
622
|
} else {
|
|
604
|
-
map[index].ids.push(
|
|
623
|
+
map[index].ids.push(id);
|
|
605
624
|
}
|
|
606
625
|
}
|
|
607
626
|
return map.map(({ ids, data }) => {
|
|
@@ -610,13 +629,79 @@ function optimizeBatchPatch(items, options) {
|
|
|
610
629
|
data,
|
|
611
630
|
{
|
|
612
631
|
query: {
|
|
613
|
-
[
|
|
632
|
+
[idKey]: { $in: ids }
|
|
614
633
|
}
|
|
615
634
|
}
|
|
616
635
|
];
|
|
617
636
|
});
|
|
618
637
|
}
|
|
619
638
|
|
|
639
|
+
function flattenQuery(q) {
|
|
640
|
+
if (Array.isArray(q)) {
|
|
641
|
+
return q.map(flattenQuery);
|
|
642
|
+
}
|
|
643
|
+
if (!isObject(q)) {
|
|
644
|
+
return q;
|
|
645
|
+
}
|
|
646
|
+
const { query, $limit, $select, $skip, $sort } = filterQuery(q);
|
|
647
|
+
const res = {};
|
|
648
|
+
function step(object, options) {
|
|
649
|
+
const { prev = [], result = res } = options ?? {};
|
|
650
|
+
Object.keys(object).forEach((key) => {
|
|
651
|
+
const value = object[key];
|
|
652
|
+
if (Array.isArray(value)) {
|
|
653
|
+
const newValues = value.map(
|
|
654
|
+
(v) => step(v, {
|
|
655
|
+
result: {}
|
|
656
|
+
})
|
|
657
|
+
);
|
|
658
|
+
_set(result, [...prev, key], newValues);
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
if (key.startsWith("$")) {
|
|
662
|
+
_set(result, [...prev, key], value);
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
const newKey = !prev.length ? [key] : [...prev.slice(0, -1), `${prev[prev.length - 1]}.${key}`];
|
|
666
|
+
if (!isObject(value)) {
|
|
667
|
+
_set(result, newKey, value);
|
|
668
|
+
return;
|
|
669
|
+
} else {
|
|
670
|
+
step(value, {
|
|
671
|
+
prev: newKey,
|
|
672
|
+
result
|
|
673
|
+
});
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
return result;
|
|
678
|
+
}
|
|
679
|
+
return reassembleQuery({
|
|
680
|
+
$limit,
|
|
681
|
+
$select,
|
|
682
|
+
$skip,
|
|
683
|
+
$sort,
|
|
684
|
+
query: step(query)
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
function deflattenQuery(query) {
|
|
689
|
+
const result = {};
|
|
690
|
+
Object.keys(query).forEach((key) => {
|
|
691
|
+
const value = query[key];
|
|
692
|
+
if (Array.isArray(value)) {
|
|
693
|
+
_set(result, key, value.map(deflattenQuery));
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
if (isObject(value)) {
|
|
697
|
+
_set(result, key, deflattenQuery(value));
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
_set(result, key, query[key]);
|
|
701
|
+
});
|
|
702
|
+
return result;
|
|
703
|
+
}
|
|
704
|
+
|
|
620
705
|
function checkMulti() {
|
|
621
706
|
return (context) => {
|
|
622
707
|
if (shouldSkip("checkMulti", context)) {
|
|
@@ -934,12 +1019,6 @@ const paramsFromClient = defineParamsFromClient(
|
|
|
934
1019
|
FROM_CLIENT_FOR_SERVER_DEFAULT_KEY
|
|
935
1020
|
);
|
|
936
1021
|
|
|
937
|
-
var __defProp = Object.defineProperty;
|
|
938
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
939
|
-
var __publicField = (obj, key, value) => {
|
|
940
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
941
|
-
return value;
|
|
942
|
-
};
|
|
943
1022
|
const makeDefaultOptions = () => {
|
|
944
1023
|
return {
|
|
945
1024
|
leading: false,
|
|
@@ -948,6 +1027,13 @@ const makeDefaultOptions = () => {
|
|
|
948
1027
|
wait: 100
|
|
949
1028
|
};
|
|
950
1029
|
};
|
|
1030
|
+
|
|
1031
|
+
var __defProp = Object.defineProperty;
|
|
1032
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1033
|
+
var __publicField = (obj, key, value) => {
|
|
1034
|
+
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1035
|
+
return value;
|
|
1036
|
+
};
|
|
951
1037
|
class DebouncedStore {
|
|
952
1038
|
constructor(app, options) {
|
|
953
1039
|
__publicField(this, "_app");
|
|
@@ -1040,7 +1126,7 @@ const filterArray = (...keys) => {
|
|
|
1040
1126
|
};
|
|
1041
1127
|
|
|
1042
1128
|
const filterQueryObject = (key) => (obj, { operators }) => {
|
|
1043
|
-
if (obj && !
|
|
1129
|
+
if (obj && !isObject(obj)) {
|
|
1044
1130
|
throw new Error(
|
|
1045
1131
|
`Invalid query parameter: '${key}'. It has to be an object`
|
|
1046
1132
|
);
|
|
@@ -1055,4 +1141,4 @@ const filterObject = (...keys) => {
|
|
|
1055
1141
|
return result;
|
|
1056
1142
|
};
|
|
1057
1143
|
|
|
1058
|
-
export { DebouncedStore, checkMulti, createRelated, debounceMixin, defineHooks, defineParamsForServer, defineParamsFromClient, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated,
|
|
1144
|
+
export { DebouncedStore, checkMulti, createRelated, debounceMixin, defineHooks, defineParamsForServer, defineParamsFromClient, deflattenQuery, filterArray, filterObject, filterQuery, flattenQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, paramsForServer, paramsFromClient, parseFields, pushSet, reassembleQuery, 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
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "Some utils for projects using '@feathersjs/feathers'",
|
|
5
5
|
"author": "fratzinger",
|
|
6
6
|
"repository": {
|
|
@@ -40,33 +40,31 @@
|
|
|
40
40
|
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@feathersjs/
|
|
44
|
-
"@feathersjs/
|
|
45
|
-
"@feathersjs/
|
|
46
|
-
"@feathersjs/errors": "^5.0.11",
|
|
43
|
+
"@feathersjs/adapter-commons": "^5.0.13",
|
|
44
|
+
"@feathersjs/errors": "^5.0.13",
|
|
45
|
+
"@feathersjs/feathers": "^5.0.13",
|
|
47
46
|
"fast-equals": "^5.0.1",
|
|
48
47
|
"feathers-hooks-common": "^8.1.1",
|
|
49
48
|
"lodash": "^4.17.21"
|
|
50
49
|
},
|
|
51
50
|
"devDependencies": {
|
|
52
|
-
"@feathersjs/memory": "^5.0.
|
|
53
|
-
"@types/lodash": "^4.14.
|
|
54
|
-
"@types/node": "^20.
|
|
55
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
56
|
-
"@typescript-eslint/parser": "^6.
|
|
57
|
-
"@vitest/coverage-v8": "^
|
|
58
|
-
"eslint": "^8.
|
|
59
|
-
"eslint-config-prettier": "^9.
|
|
51
|
+
"@feathersjs/memory": "^5.0.13",
|
|
52
|
+
"@types/lodash": "^4.14.202",
|
|
53
|
+
"@types/node": "^20.10.6",
|
|
54
|
+
"@typescript-eslint/eslint-plugin": "^6.16.0",
|
|
55
|
+
"@typescript-eslint/parser": "^6.16.0",
|
|
56
|
+
"@vitest/coverage-v8": "^1.1.0",
|
|
57
|
+
"eslint": "^8.56.0",
|
|
58
|
+
"eslint-config-prettier": "^9.1.0",
|
|
60
59
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
61
|
-
"eslint-plugin-import": "^2.29.
|
|
62
|
-
"eslint-plugin-prettier": "^5.
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"prettier": "^3.1.0",
|
|
60
|
+
"eslint-plugin-import": "^2.29.1",
|
|
61
|
+
"eslint-plugin-prettier": "^5.1.2",
|
|
62
|
+
"np": "^9.2.0",
|
|
63
|
+
"prettier": "^3.1.1",
|
|
66
64
|
"shx": "^0.3.4",
|
|
67
|
-
"typescript": "^5.
|
|
65
|
+
"typescript": "^5.3.3",
|
|
68
66
|
"unbuild": "^2.0.0",
|
|
69
|
-
"vitest": "^
|
|
67
|
+
"vitest": "^1.1.0"
|
|
70
68
|
},
|
|
71
69
|
"peerDependencies": {
|
|
72
70
|
"@feathersjs/feathers": "^5.0.0"
|
package/src/filters/object.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { FilterQueryOptions } from "@feathersjs/adapter-commons";
|
|
2
2
|
import { validateQueryProperty } from "../utils/validateQueryProperty";
|
|
3
|
-
import
|
|
3
|
+
import { isObject } from "../utils/_utils.internal";
|
|
4
4
|
|
|
5
5
|
const filterQueryObject =
|
|
6
6
|
(key: string) =>
|
|
7
7
|
(obj: any, { operators }: FilterQueryOptions) => {
|
|
8
|
-
if (obj && !
|
|
8
|
+
if (obj && !isObject(obj)) {
|
|
9
9
|
throw new Error(
|
|
10
10
|
`Invalid query parameter: '${key}'. It has to be an object`,
|
|
11
11
|
);
|
package/src/hooks/checkMulti.ts
CHANGED
|
@@ -24,3 +24,154 @@ export function checkMulti<H extends HookContext = HookContext>() {
|
|
|
24
24
|
return context;
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
if (import.meta.vitest) {
|
|
29
|
+
const { it, assert } = import.meta.vitest;
|
|
30
|
+
|
|
31
|
+
it("passes if 'allowsMulti' not defined", function () {
|
|
32
|
+
const makeContext = (type: string, method: string) =>
|
|
33
|
+
({
|
|
34
|
+
service: {},
|
|
35
|
+
type,
|
|
36
|
+
method,
|
|
37
|
+
}) as HookContext;
|
|
38
|
+
["before", "after"].forEach((type) => {
|
|
39
|
+
["find", "get", "create", "update", "patch", "remove"].forEach(
|
|
40
|
+
(method) => {
|
|
41
|
+
const context = makeContext(type, method);
|
|
42
|
+
|
|
43
|
+
assert.doesNotThrow(
|
|
44
|
+
() => checkMulti()(context),
|
|
45
|
+
`'${type}:${method}': does not throw`,
|
|
46
|
+
);
|
|
47
|
+
},
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("passes if 'allowsMulti' returns true", function () {
|
|
53
|
+
const makeContext = (type: string, method: string) => {
|
|
54
|
+
const context = {
|
|
55
|
+
service: {
|
|
56
|
+
allowsMulti: () => true,
|
|
57
|
+
},
|
|
58
|
+
method,
|
|
59
|
+
type,
|
|
60
|
+
} as HookContext;
|
|
61
|
+
if (method === "create") {
|
|
62
|
+
type === "before" ? (context.data = []) : (context.result = []);
|
|
63
|
+
}
|
|
64
|
+
return context as HookContext;
|
|
65
|
+
};
|
|
66
|
+
["before", "after"].forEach((type) => {
|
|
67
|
+
["find", "get", "create", "update", "patch", "remove"].forEach(
|
|
68
|
+
(method) => {
|
|
69
|
+
const context = makeContext(type, method);
|
|
70
|
+
assert.doesNotThrow(
|
|
71
|
+
() => checkMulti()(context),
|
|
72
|
+
`'${type}:${method}': does not throw`,
|
|
73
|
+
);
|
|
74
|
+
},
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("passes for 'find', 'get' and 'update'", function () {
|
|
80
|
+
const makeContext = (type: string, method: string) =>
|
|
81
|
+
({
|
|
82
|
+
service: {
|
|
83
|
+
allowsMulti: () => false,
|
|
84
|
+
},
|
|
85
|
+
type,
|
|
86
|
+
method,
|
|
87
|
+
}) as HookContext;
|
|
88
|
+
["before", "after"].forEach((type) => {
|
|
89
|
+
["find", "get", "update"].forEach((method) => {
|
|
90
|
+
const context = makeContext(type, method);
|
|
91
|
+
assert.doesNotThrow(
|
|
92
|
+
() => checkMulti()(context),
|
|
93
|
+
`'${type}:${method}': does not throw`,
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("passes if 'allowsMulti' returns false and is no multi data", function () {
|
|
100
|
+
const makeContext = (type: string, method: string) => {
|
|
101
|
+
const context = {
|
|
102
|
+
service: {
|
|
103
|
+
allowsMulti: (method: string) => method !== "find",
|
|
104
|
+
},
|
|
105
|
+
method,
|
|
106
|
+
type,
|
|
107
|
+
} as HookContext;
|
|
108
|
+
if (method === "create") {
|
|
109
|
+
type === "before" ? (context.data = {}) : (context.result = {});
|
|
110
|
+
}
|
|
111
|
+
if (["patch", "remove"].includes(method)) {
|
|
112
|
+
context.id = 1;
|
|
113
|
+
}
|
|
114
|
+
return context as HookContext;
|
|
115
|
+
};
|
|
116
|
+
["before", "after"].forEach((type) => {
|
|
117
|
+
["create", "patch", "remove"].forEach((method) => {
|
|
118
|
+
const context = makeContext(type, method);
|
|
119
|
+
assert.doesNotThrow(
|
|
120
|
+
() => checkMulti()(context),
|
|
121
|
+
`'${type}:${method}': does not throw`,
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("throws if 'allowsMulti' returns false and multi data", function () {
|
|
128
|
+
const makeContext = (type: string, method: string) => {
|
|
129
|
+
const context = {
|
|
130
|
+
service: {
|
|
131
|
+
allowsMulti: () => false,
|
|
132
|
+
},
|
|
133
|
+
method,
|
|
134
|
+
type,
|
|
135
|
+
} as HookContext;
|
|
136
|
+
if (method === "create") {
|
|
137
|
+
type === "before" ? (context.data = []) : (context.result = []);
|
|
138
|
+
}
|
|
139
|
+
return context as HookContext;
|
|
140
|
+
};
|
|
141
|
+
["before", "after"].forEach((type) => {
|
|
142
|
+
["create", "patch", "remove"].forEach((method) => {
|
|
143
|
+
const context = makeContext(type, method);
|
|
144
|
+
assert.throws(() => checkMulti()(context));
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("can skip hook", function () {
|
|
150
|
+
const makeContext = (type: string, method: string) => {
|
|
151
|
+
const context = {
|
|
152
|
+
service: {
|
|
153
|
+
allowsMulti: () => false,
|
|
154
|
+
},
|
|
155
|
+
method,
|
|
156
|
+
type,
|
|
157
|
+
params: {},
|
|
158
|
+
} as HookContext;
|
|
159
|
+
if (method === "create") {
|
|
160
|
+
type === "before" ? (context.data = []) : (context.result = []);
|
|
161
|
+
}
|
|
162
|
+
return context as HookContext;
|
|
163
|
+
};
|
|
164
|
+
["before", "after"].forEach((type) => {
|
|
165
|
+
["create", "patch", "remove"].forEach((method) => {
|
|
166
|
+
const context = makeContext(type, method);
|
|
167
|
+
context.params = {
|
|
168
|
+
skipHooks: ["checkMulti"],
|
|
169
|
+
};
|
|
170
|
+
assert.doesNotThrow(
|
|
171
|
+
() => checkMulti()(context),
|
|
172
|
+
`'${type}:${method}': throws`,
|
|
173
|
+
);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
}
|