feathers-utils 4.0.0 → 4.2.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 +1 -0
- package/dist/index.cjs +174 -144
- package/dist/index.d.cts +44 -29
- package/dist/index.d.mts +44 -29
- package/dist/index.d.ts +44 -29
- package/dist/index.mjs +170 -142
- package/package.json +2 -2
- package/src/utils/defineHooks.ts +16 -0
- package/src/utils/index.ts +5 -3
- package/src/utils/optimizeBatchPatch.ts +66 -0
package/README.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const errors = require('@feathersjs/errors');
|
|
4
|
+
const _isEqual = require('lodash/isEqual.js');
|
|
5
|
+
const _get = require('lodash/get.js');
|
|
6
|
+
const _set = require('lodash/set.js');
|
|
4
7
|
const _merge = require('lodash/merge.js');
|
|
5
8
|
const _isEmpty = require('lodash/isEmpty.js');
|
|
6
|
-
const _get = require('lodash/get.js');
|
|
7
9
|
const _has = require('lodash/has.js');
|
|
8
|
-
const _set = require('lodash/set.js');
|
|
9
10
|
const _uniqWith = require('lodash/uniqWith.js');
|
|
10
11
|
const fastEquals = require('fast-equals');
|
|
11
|
-
const _isEqual = require('lodash/isEqual.js');
|
|
12
12
|
const commons = require('@feathersjs/commons');
|
|
13
13
|
const feathersHooksCommon = require('feathers-hooks-common');
|
|
14
14
|
const _debounce = require('lodash/debounce.js');
|
|
@@ -16,16 +16,130 @@ const _isObject = require('lodash/isObject.js');
|
|
|
16
16
|
|
|
17
17
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
18
18
|
|
|
19
|
+
const _isEqual__default = /*#__PURE__*/_interopDefaultCompat(_isEqual);
|
|
20
|
+
const _get__default = /*#__PURE__*/_interopDefaultCompat(_get);
|
|
21
|
+
const _set__default = /*#__PURE__*/_interopDefaultCompat(_set);
|
|
19
22
|
const _merge__default = /*#__PURE__*/_interopDefaultCompat(_merge);
|
|
20
23
|
const _isEmpty__default = /*#__PURE__*/_interopDefaultCompat(_isEmpty);
|
|
21
|
-
const _get__default = /*#__PURE__*/_interopDefaultCompat(_get);
|
|
22
24
|
const _has__default = /*#__PURE__*/_interopDefaultCompat(_has);
|
|
23
|
-
const _set__default = /*#__PURE__*/_interopDefaultCompat(_set);
|
|
24
25
|
const _uniqWith__default = /*#__PURE__*/_interopDefaultCompat(_uniqWith);
|
|
25
|
-
const _isEqual__default = /*#__PURE__*/_interopDefaultCompat(_isEqual);
|
|
26
26
|
const _debounce__default = /*#__PURE__*/_interopDefaultCompat(_debounce);
|
|
27
27
|
const _isObject__default = /*#__PURE__*/_interopDefaultCompat(_isObject);
|
|
28
28
|
|
|
29
|
+
function defineHooks(hooks) {
|
|
30
|
+
return hooks;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function filterQuery(providedQuery) {
|
|
34
|
+
providedQuery ?? (providedQuery = {});
|
|
35
|
+
const { $select, $limit, $skip, $sort, ...query } = providedQuery;
|
|
36
|
+
const result = { query };
|
|
37
|
+
if ("$select" in providedQuery) {
|
|
38
|
+
result.$select = $select;
|
|
39
|
+
}
|
|
40
|
+
if ("$limit" in providedQuery) {
|
|
41
|
+
result.$limit = $limit;
|
|
42
|
+
}
|
|
43
|
+
if ("$skip" in providedQuery) {
|
|
44
|
+
result.$skip = $skip;
|
|
45
|
+
}
|
|
46
|
+
if ("$sort" in providedQuery) {
|
|
47
|
+
result.$sort = $sort;
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const getItemsIsArray = (context, options) => {
|
|
53
|
+
const { from = "automatic" } = options || {};
|
|
54
|
+
let itemOrItems;
|
|
55
|
+
if (from === "automatic") {
|
|
56
|
+
itemOrItems = context.type === "before" ? context.data : context.result;
|
|
57
|
+
} else if (from === "data") {
|
|
58
|
+
itemOrItems = context.data;
|
|
59
|
+
} else if (from === "result") {
|
|
60
|
+
itemOrItems = context.result;
|
|
61
|
+
}
|
|
62
|
+
if ((from === "automatic" || from === "result") && context.type === "after") {
|
|
63
|
+
itemOrItems = itemOrItems && context.method === "find" ? itemOrItems.data || itemOrItems : itemOrItems;
|
|
64
|
+
}
|
|
65
|
+
const isArray = Array.isArray(itemOrItems);
|
|
66
|
+
return {
|
|
67
|
+
items: isArray ? itemOrItems : itemOrItems != null ? [itemOrItems] : [],
|
|
68
|
+
isArray
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const hasOwnProperty = (obj, ...keys) => {
|
|
73
|
+
return keys.some((x) => Object.prototype.hasOwnProperty.call(obj, x));
|
|
74
|
+
};
|
|
75
|
+
const isPlainObject$1 = (value) => value && [void 0, Object].includes(value.constructor);
|
|
76
|
+
|
|
77
|
+
const getPaginate = (context) => {
|
|
78
|
+
if (hasOwnProperty(context.params, "paginate")) {
|
|
79
|
+
return context.params.paginate || void 0;
|
|
80
|
+
}
|
|
81
|
+
if (context.params.paginate === false) {
|
|
82
|
+
return void 0;
|
|
83
|
+
}
|
|
84
|
+
let options = context.service?.options || {};
|
|
85
|
+
options = {
|
|
86
|
+
...options,
|
|
87
|
+
...context.params.adapter
|
|
88
|
+
};
|
|
89
|
+
return options.paginate || void 0;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const isMulti = (context) => {
|
|
93
|
+
const { method } = context;
|
|
94
|
+
if (method === "find") {
|
|
95
|
+
return true;
|
|
96
|
+
} else if (["patch", "remove"].includes(method)) {
|
|
97
|
+
return context.id == null;
|
|
98
|
+
} else if (method === "create") {
|
|
99
|
+
const items = context.type === "before" ? context.data : context.result;
|
|
100
|
+
return Array.isArray(items);
|
|
101
|
+
} else if (["get", "update"].includes(method)) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const isPaginated = (context) => {
|
|
108
|
+
if (context.params.paginate === false || context.method !== "find") {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
const paginate = getPaginate(context);
|
|
112
|
+
return !!paginate;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const pushSet = (obj, path, val, options) => {
|
|
116
|
+
options = options || {};
|
|
117
|
+
let arr = _get__default(obj, path);
|
|
118
|
+
if (!arr || !Array.isArray(arr)) {
|
|
119
|
+
arr = [val];
|
|
120
|
+
_set__default(obj, path, arr);
|
|
121
|
+
return arr;
|
|
122
|
+
} else {
|
|
123
|
+
if (options.unique && arr.some((x) => _isEqual__default(x, val))) {
|
|
124
|
+
return arr;
|
|
125
|
+
}
|
|
126
|
+
arr.push(val);
|
|
127
|
+
return arr;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
function markHookForSkip(hookName, type, context) {
|
|
132
|
+
context = context || {};
|
|
133
|
+
const params = context.params || {};
|
|
134
|
+
const types = Array.isArray(type) ? type : [type];
|
|
135
|
+
types.forEach((t) => {
|
|
136
|
+
const combinedName = t === "all" ? hookName : `${type}:${hookName}`;
|
|
137
|
+
pushSet(params, ["skipHooks"], combinedName, { unique: true });
|
|
138
|
+
});
|
|
139
|
+
context.params = params;
|
|
140
|
+
return context;
|
|
141
|
+
}
|
|
142
|
+
|
|
29
143
|
function mergeArrays(targetArr, sourceArr, handle, prependKey, actionOnEmptyIntersect) {
|
|
30
144
|
if (!sourceArr && !targetArr) {
|
|
31
145
|
return;
|
|
@@ -65,11 +179,6 @@ function mergeArrays(targetArr, sourceArr, handle, prependKey, actionOnEmptyInte
|
|
|
65
179
|
return void 0;
|
|
66
180
|
}
|
|
67
181
|
|
|
68
|
-
const hasOwnProperty = (obj, ...keys) => {
|
|
69
|
-
return keys.some((x) => Object.prototype.hasOwnProperty.call(obj, x));
|
|
70
|
-
};
|
|
71
|
-
const isPlainObject$1 = (value) => value && [void 0, Object].includes(value.constructor);
|
|
72
|
-
|
|
73
182
|
function handleArray(target, source, key, options) {
|
|
74
183
|
const targetVal = _get__default(target, key);
|
|
75
184
|
const sourceVal = _get__default(source, key);
|
|
@@ -352,25 +461,6 @@ function areQueriesOverlapping(target, source) {
|
|
|
352
461
|
return false;
|
|
353
462
|
}
|
|
354
463
|
|
|
355
|
-
function filterQuery(providedQuery) {
|
|
356
|
-
providedQuery ?? (providedQuery = {});
|
|
357
|
-
const { $select, $limit, $skip, $sort, ...query } = providedQuery;
|
|
358
|
-
const result = { query };
|
|
359
|
-
if ("$select" in providedQuery) {
|
|
360
|
-
result.$select = $select;
|
|
361
|
-
}
|
|
362
|
-
if ("$limit" in providedQuery) {
|
|
363
|
-
result.$limit = $limit;
|
|
364
|
-
}
|
|
365
|
-
if ("$skip" in providedQuery) {
|
|
366
|
-
result.$skip = $skip;
|
|
367
|
-
}
|
|
368
|
-
if ("$sort" in providedQuery) {
|
|
369
|
-
result.$sort = $sort;
|
|
370
|
-
}
|
|
371
|
-
return result;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
464
|
function mergeQuery(target, source, _options) {
|
|
375
465
|
const options = makeDefaultOptions$1(_options);
|
|
376
466
|
const { query: targetQuery, ...targetFilters } = filterQuery(target);
|
|
@@ -414,92 +504,40 @@ function mergeQuery(target, source, _options) {
|
|
|
414
504
|
};
|
|
415
505
|
}
|
|
416
506
|
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if (
|
|
421
|
-
|
|
422
|
-
} else if (from === "data") {
|
|
423
|
-
itemOrItems = context.data;
|
|
424
|
-
} else if (from === "result") {
|
|
425
|
-
itemOrItems = context.result;
|
|
426
|
-
}
|
|
427
|
-
if ((from === "automatic" || from === "result") && context.type === "after") {
|
|
428
|
-
itemOrItems = itemOrItems && context.method === "find" ? itemOrItems.data || itemOrItems : itemOrItems;
|
|
429
|
-
}
|
|
430
|
-
const isArray = Array.isArray(itemOrItems);
|
|
431
|
-
return {
|
|
432
|
-
items: isArray ? itemOrItems : itemOrItems != null ? [itemOrItems] : [],
|
|
433
|
-
isArray
|
|
434
|
-
};
|
|
435
|
-
};
|
|
436
|
-
|
|
437
|
-
const getPaginate = (context) => {
|
|
438
|
-
if (hasOwnProperty(context.params, "paginate")) {
|
|
439
|
-
return context.params.paginate || void 0;
|
|
440
|
-
}
|
|
441
|
-
if (context.params.paginate === false) {
|
|
442
|
-
return void 0;
|
|
507
|
+
const setQueryKeySafely = (params, key, value, operator = "$eq", options) => {
|
|
508
|
+
var _a;
|
|
509
|
+
const { mutate = false } = options || {};
|
|
510
|
+
if (!mutate) {
|
|
511
|
+
params = structuredClone(params);
|
|
443
512
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
...options,
|
|
447
|
-
...context.params.adapter
|
|
448
|
-
};
|
|
449
|
-
return options.paginate || void 0;
|
|
450
|
-
};
|
|
451
|
-
|
|
452
|
-
const isMulti = (context) => {
|
|
453
|
-
const { method } = context;
|
|
454
|
-
if (method === "find") {
|
|
455
|
-
return true;
|
|
456
|
-
} else if (["patch", "remove"].includes(method)) {
|
|
457
|
-
return context.id == null;
|
|
458
|
-
} else if (method === "create") {
|
|
459
|
-
const items = context.type === "before" ? context.data : context.result;
|
|
460
|
-
return Array.isArray(items);
|
|
461
|
-
} else if (["get", "update"].includes(method)) {
|
|
462
|
-
return false;
|
|
513
|
+
if (!params.query) {
|
|
514
|
+
params.query = {};
|
|
463
515
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
516
|
+
if (!(key in params.query)) {
|
|
517
|
+
if (operator === "$eq") {
|
|
518
|
+
params.query[key] = value;
|
|
519
|
+
} else {
|
|
520
|
+
params.query[key] = {
|
|
521
|
+
[operator]: value
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
return params;
|
|
470
525
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
};
|
|
474
|
-
|
|
475
|
-
const pushSet = (obj, path, val, options) => {
|
|
476
|
-
options = options || {};
|
|
477
|
-
let arr = _get__default(obj, path);
|
|
478
|
-
if (!arr || !Array.isArray(arr)) {
|
|
479
|
-
arr = [val];
|
|
480
|
-
_set__default(obj, path, arr);
|
|
481
|
-
return arr;
|
|
526
|
+
if (isPlainObject$1(params.query[key]) && !(operator in params.query[key])) {
|
|
527
|
+
params.query[key][operator] = value;
|
|
482
528
|
} else {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
529
|
+
(_a = params.query).$and ?? (_a.$and = []);
|
|
530
|
+
params.query.$and.push(
|
|
531
|
+
operator === "$eq" ? { [key]: value } : {
|
|
532
|
+
[key]: {
|
|
533
|
+
[operator]: value
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
);
|
|
488
537
|
}
|
|
538
|
+
return params;
|
|
489
539
|
};
|
|
490
540
|
|
|
491
|
-
function markHookForSkip(hookName, type, context) {
|
|
492
|
-
context = context || {};
|
|
493
|
-
const params = context.params || {};
|
|
494
|
-
const types = Array.isArray(type) ? type : [type];
|
|
495
|
-
types.forEach((t) => {
|
|
496
|
-
const combinedName = t === "all" ? hookName : `${type}:${hookName}`;
|
|
497
|
-
pushSet(params, ["skipHooks"], combinedName, { unique: true });
|
|
498
|
-
});
|
|
499
|
-
context.params = params;
|
|
500
|
-
return context;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
541
|
const setResultEmpty = (context) => {
|
|
504
542
|
if (context.result) {
|
|
505
543
|
return context;
|
|
@@ -543,6 +581,13 @@ const shouldSkip = (hookName, context, options) => {
|
|
|
543
581
|
return false;
|
|
544
582
|
};
|
|
545
583
|
|
|
584
|
+
const toJSON = (context) => {
|
|
585
|
+
if (context.toJSON) {
|
|
586
|
+
return context.toJSON();
|
|
587
|
+
}
|
|
588
|
+
return context;
|
|
589
|
+
};
|
|
590
|
+
|
|
546
591
|
const isPlainObject = (value) => commons._.isObject(value) && value.constructor === {}.constructor;
|
|
547
592
|
const validateQueryProperty = (query, operators = []) => {
|
|
548
593
|
if (!isPlainObject(query)) {
|
|
@@ -562,46 +607,29 @@ const validateQueryProperty = (query, operators = []) => {
|
|
|
562
607
|
};
|
|
563
608
|
};
|
|
564
609
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
const setQueryKeySafely = (params, key, value, operator = "$eq", options) => {
|
|
573
|
-
var _a;
|
|
574
|
-
const { mutate = false } = options || {};
|
|
575
|
-
if (!mutate) {
|
|
576
|
-
params = structuredClone(params);
|
|
577
|
-
}
|
|
578
|
-
if (!params.query) {
|
|
579
|
-
params.query = {};
|
|
580
|
-
}
|
|
581
|
-
if (!(key in params.query)) {
|
|
582
|
-
if (operator === "$eq") {
|
|
583
|
-
params.query[key] = value;
|
|
610
|
+
function optimizeBatchPatch(items, options) {
|
|
611
|
+
const map = [];
|
|
612
|
+
const id = options?.id ?? "id";
|
|
613
|
+
for (const [id2, data] of items) {
|
|
614
|
+
const index = map.findIndex((item) => fastEquals.deepEqual(item.data, data));
|
|
615
|
+
if (index === -1) {
|
|
616
|
+
map.push({ ids: [id2], data });
|
|
584
617
|
} else {
|
|
585
|
-
|
|
586
|
-
[operator]: value
|
|
587
|
-
};
|
|
618
|
+
map[index].ids.push(id2);
|
|
588
619
|
}
|
|
589
|
-
return params;
|
|
590
620
|
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
[operator]: value
|
|
621
|
+
return map.map(({ ids, data }) => {
|
|
622
|
+
return ids.length === 1 ? [ids[0], data, void 0] : [
|
|
623
|
+
null,
|
|
624
|
+
data,
|
|
625
|
+
{
|
|
626
|
+
query: {
|
|
627
|
+
[id]: { $in: ids }
|
|
599
628
|
}
|
|
600
629
|
}
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
};
|
|
630
|
+
];
|
|
631
|
+
});
|
|
632
|
+
}
|
|
605
633
|
|
|
606
634
|
function checkMulti() {
|
|
607
635
|
return (context) => {
|
|
@@ -968,6 +996,7 @@ exports.DebouncedStore = DebouncedStore;
|
|
|
968
996
|
exports.checkMulti = checkMulti;
|
|
969
997
|
exports.createRelated = createRelated;
|
|
970
998
|
exports.debounceMixin = debounceMixin;
|
|
999
|
+
exports.defineHooks = defineHooks;
|
|
971
1000
|
exports.filterArray = filterArray;
|
|
972
1001
|
exports.filterObject = filterObject;
|
|
973
1002
|
exports.filterQuery = filterQuery;
|
|
@@ -981,6 +1010,7 @@ exports.markHookForSkip = markHookForSkip;
|
|
|
981
1010
|
exports.mergeArrays = mergeArrays;
|
|
982
1011
|
exports.mergeQuery = mergeQuery;
|
|
983
1012
|
exports.onDelete = onDelete;
|
|
1013
|
+
exports.optimizeBatchPatch = optimizeBatchPatch;
|
|
984
1014
|
exports.parseFields = parseFields;
|
|
985
1015
|
exports.pushSet = pushSet;
|
|
986
1016
|
exports.removeRelated = removeRelated;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _feathersjs_feathers from '@feathersjs/feathers';
|
|
2
|
-
import { HookContext, Application, Id, Query, Params } from '@feathersjs/feathers';
|
|
2
|
+
import { HookContext, Application, Id, HookOptions, 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 { PaginationOptions, FilterQueryOptions } from '@feathersjs/adapter-commons';
|
|
@@ -125,28 +125,14 @@ declare class DebouncedStore {
|
|
|
125
125
|
|
|
126
126
|
declare function debounceMixin(options?: Partial<InitDebounceMixinOptions>): (app: Application$1) => void;
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
[key: string]: Handle;
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
declare function mergeArrays<T>(targetArr: T[] | undefined, sourceArr: T[] | undefined, handle: Handle, prependKey?: Path, actionOnEmptyIntersect?: ActionOnEmptyIntersect): T[] | undefined;
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Merges two queries into one.
|
|
144
|
-
* @param target Query to be merged into
|
|
145
|
-
* @param source Query to be merged from
|
|
146
|
-
* @param _options
|
|
147
|
-
* @returns Query
|
|
148
|
-
*/
|
|
149
|
-
declare function mergeQuery(target: Query, source: Query, _options?: Partial<MergeQueryOptions>): Query;
|
|
128
|
+
declare function defineHooks<A extends Application = Application, S = {
|
|
129
|
+
find: any;
|
|
130
|
+
get: any;
|
|
131
|
+
create: any;
|
|
132
|
+
update: any;
|
|
133
|
+
patch: any;
|
|
134
|
+
remove: any;
|
|
135
|
+
}, Options = HookOptions<A, S>>(hooks: Options): Options;
|
|
150
136
|
|
|
151
137
|
type FilterQueryResult<Q extends Query> = {
|
|
152
138
|
$select: Q["$select"] extends any ? Q["$select"] : never;
|
|
@@ -192,6 +178,29 @@ declare const isPaginated: <H extends HookContext<_feathersjs_feathers.Applicati
|
|
|
192
178
|
*/
|
|
193
179
|
declare function markHookForSkip<H extends HookContext = HookContext>(hookName: string, type: "all" | MaybeArray<HookType>, context?: H): H;
|
|
194
180
|
|
|
181
|
+
type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
|
|
182
|
+
type FirstLast = "first" | "last";
|
|
183
|
+
type ActionOnEmptyIntersect = (target: unknown, source: unknown, prependKey: Path) => void;
|
|
184
|
+
interface MergeQueryOptions {
|
|
185
|
+
defaultHandle: Handle;
|
|
186
|
+
actionOnEmptyIntersect: ActionOnEmptyIntersect;
|
|
187
|
+
useLogicalConjunction: boolean;
|
|
188
|
+
handle?: {
|
|
189
|
+
[key: string]: Handle;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
declare function mergeArrays<T>(targetArr: T[] | undefined, sourceArr: T[] | undefined, handle: Handle, prependKey?: Path, actionOnEmptyIntersect?: ActionOnEmptyIntersect): T[] | undefined;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Merges two queries into one.
|
|
197
|
+
* @param target Query to be merged into
|
|
198
|
+
* @param source Query to be merged from
|
|
199
|
+
* @param _options
|
|
200
|
+
* @returns Query
|
|
201
|
+
*/
|
|
202
|
+
declare function mergeQuery(target: Query, source: Query, _options?: Partial<MergeQueryOptions>): Query;
|
|
203
|
+
|
|
195
204
|
interface PushSetOptions {
|
|
196
205
|
unique?: boolean;
|
|
197
206
|
}
|
|
@@ -200,6 +209,11 @@ interface PushSetOptions {
|
|
|
200
209
|
*/
|
|
201
210
|
declare const pushSet: (obj: Record<string, unknown>, path: string | Path, val: unknown, options?: PushSetOptions) => unknown[];
|
|
202
211
|
|
|
212
|
+
type SetQueryKeySafelyOptions = {
|
|
213
|
+
mutate?: boolean;
|
|
214
|
+
};
|
|
215
|
+
declare const setQueryKeySafely: <P extends Params<_feathersjs_feathers.Query> = Params<_feathersjs_feathers.Query>>(params: P, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => P;
|
|
216
|
+
|
|
203
217
|
/**
|
|
204
218
|
* util to set `context.result` to an empty array or object, depending on the hook type
|
|
205
219
|
*/
|
|
@@ -213,17 +227,18 @@ type ShouldSkipOptions = {
|
|
|
213
227
|
*/
|
|
214
228
|
declare const shouldSkip: <H extends HookContext<_feathersjs_feathers.Application<any, any>, any> = HookContext<_feathersjs_feathers.Application<any, any>, any>>(hookName: string, context: H, options?: ShouldSkipOptions) => boolean;
|
|
215
229
|
|
|
230
|
+
declare const toJSON: (context: HookContext) => HookContext<_feathersjs_feathers.Application<any, any>, any>;
|
|
231
|
+
|
|
216
232
|
/**
|
|
217
233
|
* util to validate a query for operators
|
|
218
234
|
*/
|
|
219
235
|
declare const validateQueryProperty: (query: any, operators?: string[]) => Query;
|
|
220
236
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
type SetQueryKeySafelyOptions = {
|
|
224
|
-
mutate?: boolean;
|
|
237
|
+
type OptimizeBatchPatchOptions = {
|
|
238
|
+
id?: string;
|
|
225
239
|
};
|
|
226
|
-
|
|
240
|
+
type OptimizeBatchPatchResultItem<T = Record<string, unknown>, P = Params> = [Id, T, P | undefined];
|
|
241
|
+
declare function optimizeBatchPatch<T extends Record<string, unknown>, P extends Params>(items: Map<Id, T>, options?: OptimizeBatchPatchOptions): OptimizeBatchPatchResultItem<T, P>[];
|
|
227
242
|
|
|
228
243
|
declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
|
|
229
244
|
|
|
@@ -275,4 +290,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
|
|
|
275
290
|
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;
|
|
276
291
|
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;
|
|
277
292
|
|
|
278
|
-
export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FirstLast, type GetItemsIsArrayFrom, 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 SetQueryKeySafelyOptions, 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 };
|
|
293
|
+
export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FirstLast, type GetItemsIsArrayFrom, 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 OptimizeBatchPatchOptions, type OptimizeBatchPatchResultItem, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, defineHooks, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _feathersjs_feathers from '@feathersjs/feathers';
|
|
2
|
-
import { HookContext, Application, Id, Query, Params } from '@feathersjs/feathers';
|
|
2
|
+
import { HookContext, Application, Id, HookOptions, 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 { PaginationOptions, FilterQueryOptions } from '@feathersjs/adapter-commons';
|
|
@@ -125,28 +125,14 @@ declare class DebouncedStore {
|
|
|
125
125
|
|
|
126
126
|
declare function debounceMixin(options?: Partial<InitDebounceMixinOptions>): (app: Application$1) => void;
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
[key: string]: Handle;
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
declare function mergeArrays<T>(targetArr: T[] | undefined, sourceArr: T[] | undefined, handle: Handle, prependKey?: Path, actionOnEmptyIntersect?: ActionOnEmptyIntersect): T[] | undefined;
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Merges two queries into one.
|
|
144
|
-
* @param target Query to be merged into
|
|
145
|
-
* @param source Query to be merged from
|
|
146
|
-
* @param _options
|
|
147
|
-
* @returns Query
|
|
148
|
-
*/
|
|
149
|
-
declare function mergeQuery(target: Query, source: Query, _options?: Partial<MergeQueryOptions>): Query;
|
|
128
|
+
declare function defineHooks<A extends Application = Application, S = {
|
|
129
|
+
find: any;
|
|
130
|
+
get: any;
|
|
131
|
+
create: any;
|
|
132
|
+
update: any;
|
|
133
|
+
patch: any;
|
|
134
|
+
remove: any;
|
|
135
|
+
}, Options = HookOptions<A, S>>(hooks: Options): Options;
|
|
150
136
|
|
|
151
137
|
type FilterQueryResult<Q extends Query> = {
|
|
152
138
|
$select: Q["$select"] extends any ? Q["$select"] : never;
|
|
@@ -192,6 +178,29 @@ declare const isPaginated: <H extends HookContext<_feathersjs_feathers.Applicati
|
|
|
192
178
|
*/
|
|
193
179
|
declare function markHookForSkip<H extends HookContext = HookContext>(hookName: string, type: "all" | MaybeArray<HookType>, context?: H): H;
|
|
194
180
|
|
|
181
|
+
type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
|
|
182
|
+
type FirstLast = "first" | "last";
|
|
183
|
+
type ActionOnEmptyIntersect = (target: unknown, source: unknown, prependKey: Path) => void;
|
|
184
|
+
interface MergeQueryOptions {
|
|
185
|
+
defaultHandle: Handle;
|
|
186
|
+
actionOnEmptyIntersect: ActionOnEmptyIntersect;
|
|
187
|
+
useLogicalConjunction: boolean;
|
|
188
|
+
handle?: {
|
|
189
|
+
[key: string]: Handle;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
declare function mergeArrays<T>(targetArr: T[] | undefined, sourceArr: T[] | undefined, handle: Handle, prependKey?: Path, actionOnEmptyIntersect?: ActionOnEmptyIntersect): T[] | undefined;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Merges two queries into one.
|
|
197
|
+
* @param target Query to be merged into
|
|
198
|
+
* @param source Query to be merged from
|
|
199
|
+
* @param _options
|
|
200
|
+
* @returns Query
|
|
201
|
+
*/
|
|
202
|
+
declare function mergeQuery(target: Query, source: Query, _options?: Partial<MergeQueryOptions>): Query;
|
|
203
|
+
|
|
195
204
|
interface PushSetOptions {
|
|
196
205
|
unique?: boolean;
|
|
197
206
|
}
|
|
@@ -200,6 +209,11 @@ interface PushSetOptions {
|
|
|
200
209
|
*/
|
|
201
210
|
declare const pushSet: (obj: Record<string, unknown>, path: string | Path, val: unknown, options?: PushSetOptions) => unknown[];
|
|
202
211
|
|
|
212
|
+
type SetQueryKeySafelyOptions = {
|
|
213
|
+
mutate?: boolean;
|
|
214
|
+
};
|
|
215
|
+
declare const setQueryKeySafely: <P extends Params<_feathersjs_feathers.Query> = Params<_feathersjs_feathers.Query>>(params: P, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => P;
|
|
216
|
+
|
|
203
217
|
/**
|
|
204
218
|
* util to set `context.result` to an empty array or object, depending on the hook type
|
|
205
219
|
*/
|
|
@@ -213,17 +227,18 @@ type ShouldSkipOptions = {
|
|
|
213
227
|
*/
|
|
214
228
|
declare const shouldSkip: <H extends HookContext<_feathersjs_feathers.Application<any, any>, any> = HookContext<_feathersjs_feathers.Application<any, any>, any>>(hookName: string, context: H, options?: ShouldSkipOptions) => boolean;
|
|
215
229
|
|
|
230
|
+
declare const toJSON: (context: HookContext) => HookContext<_feathersjs_feathers.Application<any, any>, any>;
|
|
231
|
+
|
|
216
232
|
/**
|
|
217
233
|
* util to validate a query for operators
|
|
218
234
|
*/
|
|
219
235
|
declare const validateQueryProperty: (query: any, operators?: string[]) => Query;
|
|
220
236
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
type SetQueryKeySafelyOptions = {
|
|
224
|
-
mutate?: boolean;
|
|
237
|
+
type OptimizeBatchPatchOptions = {
|
|
238
|
+
id?: string;
|
|
225
239
|
};
|
|
226
|
-
|
|
240
|
+
type OptimizeBatchPatchResultItem<T = Record<string, unknown>, P = Params> = [Id, T, P | undefined];
|
|
241
|
+
declare function optimizeBatchPatch<T extends Record<string, unknown>, P extends Params>(items: Map<Id, T>, options?: OptimizeBatchPatchOptions): OptimizeBatchPatchResultItem<T, P>[];
|
|
227
242
|
|
|
228
243
|
declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
|
|
229
244
|
|
|
@@ -275,4 +290,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
|
|
|
275
290
|
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;
|
|
276
291
|
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;
|
|
277
292
|
|
|
278
|
-
export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FirstLast, type GetItemsIsArrayFrom, 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 SetQueryKeySafelyOptions, 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 };
|
|
293
|
+
export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FirstLast, type GetItemsIsArrayFrom, 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 OptimizeBatchPatchOptions, type OptimizeBatchPatchResultItem, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, defineHooks, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
|
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, Params } from '@feathersjs/feathers';
|
|
2
|
+
import { HookContext, Application, Id, HookOptions, 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 { PaginationOptions, FilterQueryOptions } from '@feathersjs/adapter-commons';
|
|
@@ -125,28 +125,14 @@ declare class DebouncedStore {
|
|
|
125
125
|
|
|
126
126
|
declare function debounceMixin(options?: Partial<InitDebounceMixinOptions>): (app: Application$1) => void;
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
[key: string]: Handle;
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
declare function mergeArrays<T>(targetArr: T[] | undefined, sourceArr: T[] | undefined, handle: Handle, prependKey?: Path, actionOnEmptyIntersect?: ActionOnEmptyIntersect): T[] | undefined;
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Merges two queries into one.
|
|
144
|
-
* @param target Query to be merged into
|
|
145
|
-
* @param source Query to be merged from
|
|
146
|
-
* @param _options
|
|
147
|
-
* @returns Query
|
|
148
|
-
*/
|
|
149
|
-
declare function mergeQuery(target: Query, source: Query, _options?: Partial<MergeQueryOptions>): Query;
|
|
128
|
+
declare function defineHooks<A extends Application = Application, S = {
|
|
129
|
+
find: any;
|
|
130
|
+
get: any;
|
|
131
|
+
create: any;
|
|
132
|
+
update: any;
|
|
133
|
+
patch: any;
|
|
134
|
+
remove: any;
|
|
135
|
+
}, Options = HookOptions<A, S>>(hooks: Options): Options;
|
|
150
136
|
|
|
151
137
|
type FilterQueryResult<Q extends Query> = {
|
|
152
138
|
$select: Q["$select"] extends any ? Q["$select"] : never;
|
|
@@ -192,6 +178,29 @@ declare const isPaginated: <H extends HookContext<_feathersjs_feathers.Applicati
|
|
|
192
178
|
*/
|
|
193
179
|
declare function markHookForSkip<H extends HookContext = HookContext>(hookName: string, type: "all" | MaybeArray<HookType>, context?: H): H;
|
|
194
180
|
|
|
181
|
+
type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
|
|
182
|
+
type FirstLast = "first" | "last";
|
|
183
|
+
type ActionOnEmptyIntersect = (target: unknown, source: unknown, prependKey: Path) => void;
|
|
184
|
+
interface MergeQueryOptions {
|
|
185
|
+
defaultHandle: Handle;
|
|
186
|
+
actionOnEmptyIntersect: ActionOnEmptyIntersect;
|
|
187
|
+
useLogicalConjunction: boolean;
|
|
188
|
+
handle?: {
|
|
189
|
+
[key: string]: Handle;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
declare function mergeArrays<T>(targetArr: T[] | undefined, sourceArr: T[] | undefined, handle: Handle, prependKey?: Path, actionOnEmptyIntersect?: ActionOnEmptyIntersect): T[] | undefined;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Merges two queries into one.
|
|
197
|
+
* @param target Query to be merged into
|
|
198
|
+
* @param source Query to be merged from
|
|
199
|
+
* @param _options
|
|
200
|
+
* @returns Query
|
|
201
|
+
*/
|
|
202
|
+
declare function mergeQuery(target: Query, source: Query, _options?: Partial<MergeQueryOptions>): Query;
|
|
203
|
+
|
|
195
204
|
interface PushSetOptions {
|
|
196
205
|
unique?: boolean;
|
|
197
206
|
}
|
|
@@ -200,6 +209,11 @@ interface PushSetOptions {
|
|
|
200
209
|
*/
|
|
201
210
|
declare const pushSet: (obj: Record<string, unknown>, path: string | Path, val: unknown, options?: PushSetOptions) => unknown[];
|
|
202
211
|
|
|
212
|
+
type SetQueryKeySafelyOptions = {
|
|
213
|
+
mutate?: boolean;
|
|
214
|
+
};
|
|
215
|
+
declare const setQueryKeySafely: <P extends Params<_feathersjs_feathers.Query> = Params<_feathersjs_feathers.Query>>(params: P, key: string, value: any, operator?: string, options?: SetQueryKeySafelyOptions) => P;
|
|
216
|
+
|
|
203
217
|
/**
|
|
204
218
|
* util to set `context.result` to an empty array or object, depending on the hook type
|
|
205
219
|
*/
|
|
@@ -213,17 +227,18 @@ type ShouldSkipOptions = {
|
|
|
213
227
|
*/
|
|
214
228
|
declare const shouldSkip: <H extends HookContext<_feathersjs_feathers.Application<any, any>, any> = HookContext<_feathersjs_feathers.Application<any, any>, any>>(hookName: string, context: H, options?: ShouldSkipOptions) => boolean;
|
|
215
229
|
|
|
230
|
+
declare const toJSON: (context: HookContext) => HookContext<_feathersjs_feathers.Application<any, any>, any>;
|
|
231
|
+
|
|
216
232
|
/**
|
|
217
233
|
* util to validate a query for operators
|
|
218
234
|
*/
|
|
219
235
|
declare const validateQueryProperty: (query: any, operators?: string[]) => Query;
|
|
220
236
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
type SetQueryKeySafelyOptions = {
|
|
224
|
-
mutate?: boolean;
|
|
237
|
+
type OptimizeBatchPatchOptions = {
|
|
238
|
+
id?: string;
|
|
225
239
|
};
|
|
226
|
-
|
|
240
|
+
type OptimizeBatchPatchResultItem<T = Record<string, unknown>, P = Params> = [Id, T, P | undefined];
|
|
241
|
+
declare function optimizeBatchPatch<T extends Record<string, unknown>, P extends Params>(items: Map<Id, T>, options?: OptimizeBatchPatchOptions): OptimizeBatchPatchResultItem<T, P>[];
|
|
227
242
|
|
|
228
243
|
declare const filterArray: <T extends string[]>(...keys: T) => { [key in T[number]]: (value: any, options: FilterQueryOptions) => any; };
|
|
229
244
|
|
|
@@ -275,4 +290,4 @@ type InferRemoveResultFromPath<App extends Application, Path extends string, IdO
|
|
|
275
290
|
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;
|
|
276
291
|
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;
|
|
277
292
|
|
|
278
|
-
export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FirstLast, type GetItemsIsArrayFrom, 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 SetQueryKeySafelyOptions, 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 };
|
|
293
|
+
export { type ActionOnEmptyIntersect, type CreateRelatedOptions, type DebouncedFunctionApp, type DebouncedService, DebouncedStore, type DebouncedStoreOptions, type FirstLast, type GetItemsIsArrayFrom, 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 OptimizeBatchPatchOptions, type OptimizeBatchPatchResultItem, type Predicate, type PredicateWithContext, type PushSetOptions, type RemoveRelatedOptions, type SetQueryKeySafelyOptions, type ShouldSkipOptions, checkMulti, createRelated, debounceMixin, defineHooks, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, parseFields, pushSet, removeRelated, runPerItem, setData, setQueryKeySafely, setResultEmpty, shouldSkip, toJSON, validateQueryProperty };
|
package/dist/index.mjs
CHANGED
|
@@ -1,17 +1,131 @@
|
|
|
1
1
|
import { Forbidden, GeneralError, BadRequest, MethodNotAllowed } from '@feathersjs/errors';
|
|
2
|
+
import _isEqual from 'lodash/isEqual.js';
|
|
3
|
+
import _get from 'lodash/get.js';
|
|
4
|
+
import _set from 'lodash/set.js';
|
|
2
5
|
import _merge from 'lodash/merge.js';
|
|
3
6
|
import _isEmpty from 'lodash/isEmpty.js';
|
|
4
|
-
import _get from 'lodash/get.js';
|
|
5
7
|
import _has from 'lodash/has.js';
|
|
6
|
-
import _set from 'lodash/set.js';
|
|
7
8
|
import _uniqWith from 'lodash/uniqWith.js';
|
|
8
9
|
import { deepEqual } from 'fast-equals';
|
|
9
|
-
import _isEqual from 'lodash/isEqual.js';
|
|
10
10
|
import { _ } from '@feathersjs/commons';
|
|
11
11
|
import { checkContext } from 'feathers-hooks-common';
|
|
12
12
|
import _debounce from 'lodash/debounce.js';
|
|
13
13
|
import _isObject from 'lodash/isObject.js';
|
|
14
14
|
|
|
15
|
+
function defineHooks(hooks) {
|
|
16
|
+
return hooks;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function filterQuery(providedQuery) {
|
|
20
|
+
providedQuery ?? (providedQuery = {});
|
|
21
|
+
const { $select, $limit, $skip, $sort, ...query } = providedQuery;
|
|
22
|
+
const result = { query };
|
|
23
|
+
if ("$select" in providedQuery) {
|
|
24
|
+
result.$select = $select;
|
|
25
|
+
}
|
|
26
|
+
if ("$limit" in providedQuery) {
|
|
27
|
+
result.$limit = $limit;
|
|
28
|
+
}
|
|
29
|
+
if ("$skip" in providedQuery) {
|
|
30
|
+
result.$skip = $skip;
|
|
31
|
+
}
|
|
32
|
+
if ("$sort" in providedQuery) {
|
|
33
|
+
result.$sort = $sort;
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const getItemsIsArray = (context, options) => {
|
|
39
|
+
const { from = "automatic" } = options || {};
|
|
40
|
+
let itemOrItems;
|
|
41
|
+
if (from === "automatic") {
|
|
42
|
+
itemOrItems = context.type === "before" ? context.data : context.result;
|
|
43
|
+
} else if (from === "data") {
|
|
44
|
+
itemOrItems = context.data;
|
|
45
|
+
} else if (from === "result") {
|
|
46
|
+
itemOrItems = context.result;
|
|
47
|
+
}
|
|
48
|
+
if ((from === "automatic" || from === "result") && context.type === "after") {
|
|
49
|
+
itemOrItems = itemOrItems && context.method === "find" ? itemOrItems.data || itemOrItems : itemOrItems;
|
|
50
|
+
}
|
|
51
|
+
const isArray = Array.isArray(itemOrItems);
|
|
52
|
+
return {
|
|
53
|
+
items: isArray ? itemOrItems : itemOrItems != null ? [itemOrItems] : [],
|
|
54
|
+
isArray
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const hasOwnProperty = (obj, ...keys) => {
|
|
59
|
+
return keys.some((x) => Object.prototype.hasOwnProperty.call(obj, x));
|
|
60
|
+
};
|
|
61
|
+
const isPlainObject$1 = (value) => value && [void 0, Object].includes(value.constructor);
|
|
62
|
+
|
|
63
|
+
const getPaginate = (context) => {
|
|
64
|
+
if (hasOwnProperty(context.params, "paginate")) {
|
|
65
|
+
return context.params.paginate || void 0;
|
|
66
|
+
}
|
|
67
|
+
if (context.params.paginate === false) {
|
|
68
|
+
return void 0;
|
|
69
|
+
}
|
|
70
|
+
let options = context.service?.options || {};
|
|
71
|
+
options = {
|
|
72
|
+
...options,
|
|
73
|
+
...context.params.adapter
|
|
74
|
+
};
|
|
75
|
+
return options.paginate || void 0;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const isMulti = (context) => {
|
|
79
|
+
const { method } = context;
|
|
80
|
+
if (method === "find") {
|
|
81
|
+
return true;
|
|
82
|
+
} else if (["patch", "remove"].includes(method)) {
|
|
83
|
+
return context.id == null;
|
|
84
|
+
} else if (method === "create") {
|
|
85
|
+
const items = context.type === "before" ? context.data : context.result;
|
|
86
|
+
return Array.isArray(items);
|
|
87
|
+
} else if (["get", "update"].includes(method)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const isPaginated = (context) => {
|
|
94
|
+
if (context.params.paginate === false || context.method !== "find") {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
const paginate = getPaginate(context);
|
|
98
|
+
return !!paginate;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const pushSet = (obj, path, val, options) => {
|
|
102
|
+
options = options || {};
|
|
103
|
+
let arr = _get(obj, path);
|
|
104
|
+
if (!arr || !Array.isArray(arr)) {
|
|
105
|
+
arr = [val];
|
|
106
|
+
_set(obj, path, arr);
|
|
107
|
+
return arr;
|
|
108
|
+
} else {
|
|
109
|
+
if (options.unique && arr.some((x) => _isEqual(x, val))) {
|
|
110
|
+
return arr;
|
|
111
|
+
}
|
|
112
|
+
arr.push(val);
|
|
113
|
+
return arr;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
function markHookForSkip(hookName, type, context) {
|
|
118
|
+
context = context || {};
|
|
119
|
+
const params = context.params || {};
|
|
120
|
+
const types = Array.isArray(type) ? type : [type];
|
|
121
|
+
types.forEach((t) => {
|
|
122
|
+
const combinedName = t === "all" ? hookName : `${type}:${hookName}`;
|
|
123
|
+
pushSet(params, ["skipHooks"], combinedName, { unique: true });
|
|
124
|
+
});
|
|
125
|
+
context.params = params;
|
|
126
|
+
return context;
|
|
127
|
+
}
|
|
128
|
+
|
|
15
129
|
function mergeArrays(targetArr, sourceArr, handle, prependKey, actionOnEmptyIntersect) {
|
|
16
130
|
if (!sourceArr && !targetArr) {
|
|
17
131
|
return;
|
|
@@ -51,11 +165,6 @@ function mergeArrays(targetArr, sourceArr, handle, prependKey, actionOnEmptyInte
|
|
|
51
165
|
return void 0;
|
|
52
166
|
}
|
|
53
167
|
|
|
54
|
-
const hasOwnProperty = (obj, ...keys) => {
|
|
55
|
-
return keys.some((x) => Object.prototype.hasOwnProperty.call(obj, x));
|
|
56
|
-
};
|
|
57
|
-
const isPlainObject$1 = (value) => value && [void 0, Object].includes(value.constructor);
|
|
58
|
-
|
|
59
168
|
function handleArray(target, source, key, options) {
|
|
60
169
|
const targetVal = _get(target, key);
|
|
61
170
|
const sourceVal = _get(source, key);
|
|
@@ -338,25 +447,6 @@ function areQueriesOverlapping(target, source) {
|
|
|
338
447
|
return false;
|
|
339
448
|
}
|
|
340
449
|
|
|
341
|
-
function filterQuery(providedQuery) {
|
|
342
|
-
providedQuery ?? (providedQuery = {});
|
|
343
|
-
const { $select, $limit, $skip, $sort, ...query } = providedQuery;
|
|
344
|
-
const result = { query };
|
|
345
|
-
if ("$select" in providedQuery) {
|
|
346
|
-
result.$select = $select;
|
|
347
|
-
}
|
|
348
|
-
if ("$limit" in providedQuery) {
|
|
349
|
-
result.$limit = $limit;
|
|
350
|
-
}
|
|
351
|
-
if ("$skip" in providedQuery) {
|
|
352
|
-
result.$skip = $skip;
|
|
353
|
-
}
|
|
354
|
-
if ("$sort" in providedQuery) {
|
|
355
|
-
result.$sort = $sort;
|
|
356
|
-
}
|
|
357
|
-
return result;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
450
|
function mergeQuery(target, source, _options) {
|
|
361
451
|
const options = makeDefaultOptions$1(_options);
|
|
362
452
|
const { query: targetQuery, ...targetFilters } = filterQuery(target);
|
|
@@ -400,92 +490,40 @@ function mergeQuery(target, source, _options) {
|
|
|
400
490
|
};
|
|
401
491
|
}
|
|
402
492
|
|
|
403
|
-
const
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
if (
|
|
407
|
-
|
|
408
|
-
} else if (from === "data") {
|
|
409
|
-
itemOrItems = context.data;
|
|
410
|
-
} else if (from === "result") {
|
|
411
|
-
itemOrItems = context.result;
|
|
412
|
-
}
|
|
413
|
-
if ((from === "automatic" || from === "result") && context.type === "after") {
|
|
414
|
-
itemOrItems = itemOrItems && context.method === "find" ? itemOrItems.data || itemOrItems : itemOrItems;
|
|
415
|
-
}
|
|
416
|
-
const isArray = Array.isArray(itemOrItems);
|
|
417
|
-
return {
|
|
418
|
-
items: isArray ? itemOrItems : itemOrItems != null ? [itemOrItems] : [],
|
|
419
|
-
isArray
|
|
420
|
-
};
|
|
421
|
-
};
|
|
422
|
-
|
|
423
|
-
const getPaginate = (context) => {
|
|
424
|
-
if (hasOwnProperty(context.params, "paginate")) {
|
|
425
|
-
return context.params.paginate || void 0;
|
|
426
|
-
}
|
|
427
|
-
if (context.params.paginate === false) {
|
|
428
|
-
return void 0;
|
|
493
|
+
const setQueryKeySafely = (params, key, value, operator = "$eq", options) => {
|
|
494
|
+
var _a;
|
|
495
|
+
const { mutate = false } = options || {};
|
|
496
|
+
if (!mutate) {
|
|
497
|
+
params = structuredClone(params);
|
|
429
498
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
...options,
|
|
433
|
-
...context.params.adapter
|
|
434
|
-
};
|
|
435
|
-
return options.paginate || void 0;
|
|
436
|
-
};
|
|
437
|
-
|
|
438
|
-
const isMulti = (context) => {
|
|
439
|
-
const { method } = context;
|
|
440
|
-
if (method === "find") {
|
|
441
|
-
return true;
|
|
442
|
-
} else if (["patch", "remove"].includes(method)) {
|
|
443
|
-
return context.id == null;
|
|
444
|
-
} else if (method === "create") {
|
|
445
|
-
const items = context.type === "before" ? context.data : context.result;
|
|
446
|
-
return Array.isArray(items);
|
|
447
|
-
} else if (["get", "update"].includes(method)) {
|
|
448
|
-
return false;
|
|
499
|
+
if (!params.query) {
|
|
500
|
+
params.query = {};
|
|
449
501
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
502
|
+
if (!(key in params.query)) {
|
|
503
|
+
if (operator === "$eq") {
|
|
504
|
+
params.query[key] = value;
|
|
505
|
+
} else {
|
|
506
|
+
params.query[key] = {
|
|
507
|
+
[operator]: value
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
return params;
|
|
456
511
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
};
|
|
460
|
-
|
|
461
|
-
const pushSet = (obj, path, val, options) => {
|
|
462
|
-
options = options || {};
|
|
463
|
-
let arr = _get(obj, path);
|
|
464
|
-
if (!arr || !Array.isArray(arr)) {
|
|
465
|
-
arr = [val];
|
|
466
|
-
_set(obj, path, arr);
|
|
467
|
-
return arr;
|
|
512
|
+
if (isPlainObject$1(params.query[key]) && !(operator in params.query[key])) {
|
|
513
|
+
params.query[key][operator] = value;
|
|
468
514
|
} else {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
515
|
+
(_a = params.query).$and ?? (_a.$and = []);
|
|
516
|
+
params.query.$and.push(
|
|
517
|
+
operator === "$eq" ? { [key]: value } : {
|
|
518
|
+
[key]: {
|
|
519
|
+
[operator]: value
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
);
|
|
474
523
|
}
|
|
524
|
+
return params;
|
|
475
525
|
};
|
|
476
526
|
|
|
477
|
-
function markHookForSkip(hookName, type, context) {
|
|
478
|
-
context = context || {};
|
|
479
|
-
const params = context.params || {};
|
|
480
|
-
const types = Array.isArray(type) ? type : [type];
|
|
481
|
-
types.forEach((t) => {
|
|
482
|
-
const combinedName = t === "all" ? hookName : `${type}:${hookName}`;
|
|
483
|
-
pushSet(params, ["skipHooks"], combinedName, { unique: true });
|
|
484
|
-
});
|
|
485
|
-
context.params = params;
|
|
486
|
-
return context;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
527
|
const setResultEmpty = (context) => {
|
|
490
528
|
if (context.result) {
|
|
491
529
|
return context;
|
|
@@ -529,6 +567,13 @@ const shouldSkip = (hookName, context, options) => {
|
|
|
529
567
|
return false;
|
|
530
568
|
};
|
|
531
569
|
|
|
570
|
+
const toJSON = (context) => {
|
|
571
|
+
if (context.toJSON) {
|
|
572
|
+
return context.toJSON();
|
|
573
|
+
}
|
|
574
|
+
return context;
|
|
575
|
+
};
|
|
576
|
+
|
|
532
577
|
const isPlainObject = (value) => _.isObject(value) && value.constructor === {}.constructor;
|
|
533
578
|
const validateQueryProperty = (query, operators = []) => {
|
|
534
579
|
if (!isPlainObject(query)) {
|
|
@@ -548,46 +593,29 @@ const validateQueryProperty = (query, operators = []) => {
|
|
|
548
593
|
};
|
|
549
594
|
};
|
|
550
595
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
const setQueryKeySafely = (params, key, value, operator = "$eq", options) => {
|
|
559
|
-
var _a;
|
|
560
|
-
const { mutate = false } = options || {};
|
|
561
|
-
if (!mutate) {
|
|
562
|
-
params = structuredClone(params);
|
|
563
|
-
}
|
|
564
|
-
if (!params.query) {
|
|
565
|
-
params.query = {};
|
|
566
|
-
}
|
|
567
|
-
if (!(key in params.query)) {
|
|
568
|
-
if (operator === "$eq") {
|
|
569
|
-
params.query[key] = value;
|
|
596
|
+
function optimizeBatchPatch(items, options) {
|
|
597
|
+
const map = [];
|
|
598
|
+
const id = options?.id ?? "id";
|
|
599
|
+
for (const [id2, data] of items) {
|
|
600
|
+
const index = map.findIndex((item) => deepEqual(item.data, data));
|
|
601
|
+
if (index === -1) {
|
|
602
|
+
map.push({ ids: [id2], data });
|
|
570
603
|
} else {
|
|
571
|
-
|
|
572
|
-
[operator]: value
|
|
573
|
-
};
|
|
604
|
+
map[index].ids.push(id2);
|
|
574
605
|
}
|
|
575
|
-
return params;
|
|
576
606
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
[operator]: value
|
|
607
|
+
return map.map(({ ids, data }) => {
|
|
608
|
+
return ids.length === 1 ? [ids[0], data, void 0] : [
|
|
609
|
+
null,
|
|
610
|
+
data,
|
|
611
|
+
{
|
|
612
|
+
query: {
|
|
613
|
+
[id]: { $in: ids }
|
|
585
614
|
}
|
|
586
615
|
}
|
|
587
|
-
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
};
|
|
616
|
+
];
|
|
617
|
+
});
|
|
618
|
+
}
|
|
591
619
|
|
|
592
620
|
function checkMulti() {
|
|
593
621
|
return (context) => {
|
|
@@ -950,4 +978,4 @@ const filterObject = (...keys) => {
|
|
|
950
978
|
return result;
|
|
951
979
|
};
|
|
952
980
|
|
|
953
|
-
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 };
|
|
981
|
+
export { DebouncedStore, checkMulti, createRelated, debounceMixin, defineHooks, filterArray, filterObject, filterQuery, forEach, getItemsIsArray, getPaginate, isMulti, isPaginated, makeDefaultOptions, markHookForSkip, mergeArrays, mergeQuery, onDelete, optimizeBatchPatch, 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": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "Some utils for projects using '@feathersjs/feathers'",
|
|
5
5
|
"author": "fratzinger",
|
|
6
6
|
"repository": {
|
|
@@ -40,6 +40,7 @@
|
|
|
40
40
|
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
+
"@feathersjs/feathers": "^5.0.11",
|
|
43
44
|
"@feathersjs/adapter-commons": "^5.0.11",
|
|
44
45
|
"@feathersjs/commons": "^5.0.11",
|
|
45
46
|
"@feathersjs/errors": "^5.0.11",
|
|
@@ -48,7 +49,6 @@
|
|
|
48
49
|
"lodash": "^4.17.21"
|
|
49
50
|
},
|
|
50
51
|
"devDependencies": {
|
|
51
|
-
"@feathersjs/feathers": "^5.0.11",
|
|
52
52
|
"@feathersjs/memory": "^5.0.11",
|
|
53
53
|
"@types/lodash": "^4.14.201",
|
|
54
54
|
"@types/node": "^20.9.0",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Application, HookOptions } from "@feathersjs/feathers";
|
|
2
|
+
|
|
3
|
+
export function defineHooks<
|
|
4
|
+
A extends Application = Application,
|
|
5
|
+
S = {
|
|
6
|
+
find: any;
|
|
7
|
+
get: any;
|
|
8
|
+
create: any;
|
|
9
|
+
update: any;
|
|
10
|
+
patch: any;
|
|
11
|
+
remove: any;
|
|
12
|
+
},
|
|
13
|
+
Options = HookOptions<A, S>,
|
|
14
|
+
>(hooks: Options): Options {
|
|
15
|
+
return hooks;
|
|
16
|
+
}
|
package/src/utils/index.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
export * from "./
|
|
1
|
+
export * from "./defineHooks";
|
|
2
2
|
export * from "./filterQuery";
|
|
3
3
|
export * from "./getItemsIsArray";
|
|
4
4
|
export * from "./getPaginate";
|
|
5
5
|
export * from "./isMulti";
|
|
6
6
|
export * from "./isPaginated";
|
|
7
7
|
export * from "./markHookForSkip";
|
|
8
|
+
export * from "./mergeQuery";
|
|
8
9
|
export * from "./pushSet";
|
|
10
|
+
export * from "./setQueryKeySafely";
|
|
9
11
|
export * from "./setResultEmpty";
|
|
10
12
|
export * from "./shouldSkip";
|
|
11
|
-
export * from "./validateQueryProperty";
|
|
12
13
|
export * from "./toJSON";
|
|
13
|
-
export * from "./
|
|
14
|
+
export * from "./validateQueryProperty";
|
|
15
|
+
export * from "./optimizeBatchPatch";
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Id, Params } from "@feathersjs/feathers";
|
|
2
|
+
import { deepEqual } from "fast-equals";
|
|
3
|
+
|
|
4
|
+
export type OptimizeBatchPatchOptions = {
|
|
5
|
+
id?: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type OptimizeBatchPatchResultItem<
|
|
9
|
+
T = Record<string, unknown>,
|
|
10
|
+
P = Params,
|
|
11
|
+
> = [Id, T, P | undefined];
|
|
12
|
+
|
|
13
|
+
export function optimizeBatchPatch<
|
|
14
|
+
T extends Record<string, unknown>,
|
|
15
|
+
P extends Params,
|
|
16
|
+
>(
|
|
17
|
+
items: Map<Id, T>,
|
|
18
|
+
options?: OptimizeBatchPatchOptions,
|
|
19
|
+
): OptimizeBatchPatchResultItem<T, P>[] {
|
|
20
|
+
const map: { ids: Id[]; data: T }[] = [];
|
|
21
|
+
|
|
22
|
+
const id = options?.id ?? "id";
|
|
23
|
+
|
|
24
|
+
for (const [id, data] of items) {
|
|
25
|
+
const index = map.findIndex((item) => deepEqual(item.data, data));
|
|
26
|
+
|
|
27
|
+
if (index === -1) {
|
|
28
|
+
map.push({ ids: [id], data });
|
|
29
|
+
} else {
|
|
30
|
+
map[index].ids.push(id);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return map.map(({ ids, data }) => {
|
|
35
|
+
return ids.length === 1
|
|
36
|
+
? ([ids[0], data, undefined] as OptimizeBatchPatchResultItem<T, P>)
|
|
37
|
+
: ([
|
|
38
|
+
null,
|
|
39
|
+
data,
|
|
40
|
+
{
|
|
41
|
+
query: {
|
|
42
|
+
[id]: { $in: ids },
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
] as OptimizeBatchPatchResultItem<T, P>);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (import.meta.vitest) {
|
|
50
|
+
const { it, expect } = import.meta.vitest;
|
|
51
|
+
it("optimizeBatchPatch", () => {
|
|
52
|
+
const items = new Map<Id, Record<string, unknown>>([
|
|
53
|
+
["1", { name: "John" }],
|
|
54
|
+
["2", { name: "Jane" }],
|
|
55
|
+
["3", { name: "John" }],
|
|
56
|
+
["4", { name: "Jane" }],
|
|
57
|
+
[5, { name: "Jack" }],
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
expect(optimizeBatchPatch(items)).toEqual([
|
|
61
|
+
[null, { name: "John" }, { query: { id: { $in: ["1", "3"] } } }],
|
|
62
|
+
[null, { name: "Jane" }, { query: { id: { $in: ["2", "4"] } } }],
|
|
63
|
+
[5, { name: "Jack" }, undefined],
|
|
64
|
+
]);
|
|
65
|
+
});
|
|
66
|
+
}
|