feathers-utils 1.7.2 → 1.8.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.
@@ -6,7 +6,9 @@ const makeOptions = (options) => {
6
6
  wait: true
7
7
  }, options);
8
8
  };
9
- export const runPerItem = (actionPerItem, options) => {
9
+ export const runPerItem = (
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ actionPerItem, options) => {
10
12
  options = makeOptions(options);
11
13
  return async (context) => {
12
14
  if (shouldSkip("runForItems", context)) {
@@ -23,7 +23,14 @@ export function setData(from, to, _options) {
23
23
  }
24
24
  const val = _get(context, from);
25
25
  items.forEach((item) => {
26
- if (!options.overwrite && _has(item, to)) {
26
+ let overwrite;
27
+ if (typeof options.overwrite === "function") {
28
+ overwrite = options.overwrite(item, context);
29
+ }
30
+ else {
31
+ overwrite = options.overwrite;
32
+ }
33
+ if (!overwrite && _has(item, to)) {
27
34
  return;
28
35
  }
29
36
  _set(item, to, val);
@@ -1,12 +1,14 @@
1
- import type { Application, Service } from "@feathersjs/feathers";
1
+ import type { Application, HookContext, Service } from "@feathersjs/feathers";
2
2
  export declare type Path = Array<string | number>;
3
3
  export declare type HookType = "before" | "after" | "error";
4
4
  export declare type ServiceMethodName = "find" | "get" | "create" | "update" | "patch" | "remove";
5
5
  export declare type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
6
6
  export declare type FirstLast = "first" | "last";
7
+ export declare type Predicate<T = any> = (item: T) => boolean;
8
+ export declare type PredicateWithContext<T = any> = (item: T, context: HookContext) => boolean;
7
9
  export interface HookSetDataOptions {
8
10
  allowUndefined?: boolean;
9
- overwrite?: boolean;
11
+ overwrite?: boolean | PredicateWithContext;
10
12
  }
11
13
  export interface AddHookOptions {
12
14
  types: HookType[];
@@ -1,2 +1,2 @@
1
- import { HookContext, PaginationOptions } from "@feathersjs/feathers";
1
+ import type { HookContext, PaginationOptions } from "@feathersjs/feathers";
2
2
  export declare const getPaginate: (context: HookContext) => PaginationOptions | undefined;
@@ -1,2 +1,2 @@
1
- import { HookContext } from "@feathersjs/feathers";
1
+ import type { HookContext } from "@feathersjs/feathers";
2
2
  export declare const isPaginated: (context: HookContext) => boolean;
@@ -1,2 +1,2 @@
1
- import { HookContext } from "@feathersjs/feathers";
1
+ import type { HookContext } from "@feathersjs/feathers";
2
2
  export declare const setResultEmpty: (context: HookContext) => HookContext;
@@ -6,11 +6,11 @@ const shouldSkip_1 = require("../utils/shouldSkip");
6
6
  const isMulti_1 = require("../utils/isMulti");
7
7
  function checkMulti() {
8
8
  return (context) => {
9
- if (shouldSkip_1.shouldSkip("checkMulti", context)) {
9
+ if ((0, shouldSkip_1.shouldSkip)("checkMulti", context)) {
10
10
  return context;
11
11
  }
12
12
  const { service, method } = context;
13
- if (!service.allowsMulti || !isMulti_1.isMulti(context) || method === "find") {
13
+ if (!service.allowsMulti || !(0, isMulti_1.isMulti)(context) || method === "find") {
14
14
  return context;
15
15
  }
16
16
  if (!service.allowsMulti(method)) {
@@ -18,13 +18,15 @@ const makeOptions = (options) => {
18
18
  wait: true
19
19
  }, options);
20
20
  };
21
- const runPerItem = (actionPerItem, options) => {
21
+ const runPerItem = (
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ actionPerItem, options) => {
22
24
  options = makeOptions(options);
23
25
  return (context) => __awaiter(void 0, void 0, void 0, function* () {
24
- if (shouldSkip_1.shouldSkip("runForItems", context)) {
26
+ if ((0, shouldSkip_1.shouldSkip)("runForItems", context)) {
25
27
  return context;
26
28
  }
27
- let items = feathers_hooks_common_1.getItems(context);
29
+ let items = (0, feathers_hooks_common_1.getItems)(context);
28
30
  items = (Array.isArray(items)) ? items : [items];
29
31
  const promises = items.map((item) => __awaiter(void 0, void 0, void 0, function* () {
30
32
  yield actionPerItem(item, context);
@@ -17,23 +17,30 @@ function setData(from, to, _options) {
17
17
  const options = Object.assign({}, defaultOptions, _options);
18
18
  return (context) => {
19
19
  var _a;
20
- let items = feathers_hooks_common_1.getItems(context);
20
+ let items = (0, feathers_hooks_common_1.getItems)(context);
21
21
  items = (Array.isArray(items)) ? items : [items];
22
- if (!has_1.default(context, from)) {
22
+ if (!(0, has_1.default)(context, from)) {
23
23
  if (!((_a = context.params) === null || _a === void 0 ? void 0 : _a.provider) || options.allowUndefined === true) {
24
24
  return context;
25
25
  }
26
- if (!options.overwrite && items.every((item) => has_1.default(item, to))) {
26
+ if (!options.overwrite && items.every((item) => (0, has_1.default)(item, to))) {
27
27
  return context;
28
28
  }
29
29
  throw new errors_1.Forbidden(`Expected field ${from.toString()} not available`);
30
30
  }
31
- const val = get_1.default(context, from);
31
+ const val = (0, get_1.default)(context, from);
32
32
  items.forEach((item) => {
33
- if (!options.overwrite && has_1.default(item, to)) {
33
+ let overwrite;
34
+ if (typeof options.overwrite === "function") {
35
+ overwrite = options.overwrite(item, context);
36
+ }
37
+ else {
38
+ overwrite = options.overwrite;
39
+ }
40
+ if (!overwrite && (0, has_1.default)(item, to)) {
34
41
  return;
35
42
  }
36
- set_1.default(item, to, val);
43
+ (0, set_1.default)(item, to, val);
37
44
  });
38
45
  return context;
39
46
  };
@@ -26,7 +26,7 @@ exports.makeDefaultOptions = makeDefaultOptions;
26
26
  class DebouncedStore {
27
27
  constructor(app, options) {
28
28
  this._app = app;
29
- this._options = Object.assign(exports.makeDefaultOptions(), options);
29
+ this._options = Object.assign((0, exports.makeDefaultOptions)(), options);
30
30
  this._queueById = {};
31
31
  this._isRunningById = {};
32
32
  //this._waitingById = {};
@@ -52,7 +52,7 @@ class DebouncedStore {
52
52
  if (typeof this._queueById[id] === "function") {
53
53
  return this._queueById[id](id, action);
54
54
  }
55
- this._queueById[id] = debounce_1.default((id, action) => {
55
+ this._queueById[id] = (0, debounce_1.default)((id, action) => {
56
56
  this.unbounced(id, action);
57
57
  }, wait, Object.assign(Object.assign({}, options), { leading: false })); // leading required for return promise
58
58
  return this._queueById[id](id, action);
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "DebouncedStore", { enumerable: true, get: functi
6
6
  function debounceMixin(options) {
7
7
  return (app) => {
8
8
  options = options || {};
9
- const defaultOptions = Object.assign(DebouncedStore_1.makeDefaultOptions(), options === null || options === void 0 ? void 0 : options.default);
9
+ const defaultOptions = Object.assign((0, DebouncedStore_1.makeDefaultOptions)(), options === null || options === void 0 ? void 0 : options.default);
10
10
  app.mixins.push((service, path) => {
11
11
  // if path is on blacklist, don't add debouncedStore to service
12
12
  if ((options === null || options === void 0 ? void 0 : options.blacklist) && options.blacklist.includes(path))
package/dist/types.d.ts CHANGED
@@ -1,12 +1,14 @@
1
- import type { Application, Service } from "@feathersjs/feathers";
1
+ import type { Application, HookContext, Service } from "@feathersjs/feathers";
2
2
  export declare type Path = Array<string | number>;
3
3
  export declare type HookType = "before" | "after" | "error";
4
4
  export declare type ServiceMethodName = "find" | "get" | "create" | "update" | "patch" | "remove";
5
5
  export declare type Handle = "target" | "source" | "combine" | "intersect" | "intersectOrFull";
6
6
  export declare type FirstLast = "first" | "last";
7
+ export declare type Predicate<T = any> = (item: T) => boolean;
8
+ export declare type PredicateWithContext<T = any> = (item: T, context: HookContext) => boolean;
7
9
  export interface HookSetDataOptions {
8
10
  allowUndefined?: boolean;
9
- overwrite?: boolean;
11
+ overwrite?: boolean | PredicateWithContext;
10
12
  }
11
13
  export interface AddHookOptions {
12
14
  types: HookType[];
@@ -25,9 +25,9 @@ function filterQuery(query, options) {
25
25
  return service.filterQuery({ query }, optionsForFilterQuery);
26
26
  }
27
27
  else {
28
- return adapter_commons_1.filterQuery(query, optionsForFilterQuery);
28
+ return (0, adapter_commons_1.filterQuery)(query, optionsForFilterQuery);
29
29
  }
30
30
  }
31
- return adapter_commons_1.filterQuery(query, options);
31
+ return (0, adapter_commons_1.filterQuery)(query, options);
32
32
  }
33
33
  exports.filterQuery = filterQuery;
@@ -1,2 +1,2 @@
1
- import { HookContext, PaginationOptions } from "@feathersjs/feathers";
1
+ import type { HookContext, PaginationOptions } from "@feathersjs/feathers";
2
2
  export declare const getPaginate: (context: HookContext) => PaginationOptions | undefined;
@@ -1,2 +1,2 @@
1
- import { HookContext } from "@feathersjs/feathers";
1
+ import type { HookContext } from "@feathersjs/feathers";
2
2
  export declare const isPaginated: (context: HookContext) => boolean;
@@ -6,7 +6,7 @@ const isPaginated = (context) => {
6
6
  if (context.params.paginate === false) {
7
7
  return false;
8
8
  }
9
- const paginate = getPaginate_1.getPaginate(context);
9
+ const paginate = (0, getPaginate_1.getPaginate)(context);
10
10
  return !!paginate;
11
11
  };
12
12
  exports.isPaginated = isPaginated;
@@ -10,7 +10,7 @@ function markHookForSkip(hookName, type, context) {
10
10
  const combinedName = (t === "all")
11
11
  ? hookName
12
12
  : `${type}:${hookName}`;
13
- pushSet_1.pushSet(params, ["skipHooks"], combinedName, { unique: true });
13
+ (0, pushSet_1.pushSet)(params, ["skipHooks"], combinedName, { unique: true });
14
14
  });
15
15
  context.params = params;
16
16
  return context;
@@ -18,14 +18,14 @@ const hasOwnProperty = (obj, key) => {
18
18
  return Object.prototype.hasOwnProperty.call(obj, key);
19
19
  };
20
20
  function handleArray(target, source, key, options) {
21
- const targetVal = get_1.default(target, key);
22
- const sourceVal = get_1.default(source, key);
21
+ const targetVal = (0, get_1.default)(target, key);
22
+ const sourceVal = (0, get_1.default)(source, key);
23
23
  if (!sourceVal && !targetVal) {
24
24
  return;
25
25
  }
26
- const handle = get_1.default(options, ["handle", ...key], options.defaultHandle);
27
- const arr = mergeArrays_1.mergeArrays(targetVal, sourceVal, handle, key, options.actionOnEmptyIntersect);
28
- set_1.default(target, key, arr);
26
+ const handle = (0, get_1.default)(options, ["handle", ...key], options.defaultHandle);
27
+ const arr = (0, mergeArrays_1.mergeArrays)(targetVal, sourceVal, handle, key, options.actionOnEmptyIntersect);
28
+ (0, set_1.default)(target, key, arr);
29
29
  }
30
30
  function handleCircular(target, source, prependKey, options) {
31
31
  if (target === null || target === void 0 ? void 0 : target.$or) {
@@ -52,11 +52,11 @@ function handleCircular(target, source, prependKey, options) {
52
52
  delete source.$and;
53
53
  }
54
54
  }
55
- if (!has_1.default(source, prependKey)) {
55
+ if (!(0, has_1.default)(source, prependKey)) {
56
56
  return;
57
57
  }
58
- if (!has_1.default(target, prependKey)) {
59
- set_1.default(target, prependKey, get_1.default(source, prependKey));
58
+ if (!(0, has_1.default)(target, prependKey)) {
59
+ (0, set_1.default)(target, prependKey, (0, get_1.default)(source, prependKey));
60
60
  return;
61
61
  }
62
62
  const { defaultHandle, actionOnEmptyIntersect } = options;
@@ -64,22 +64,22 @@ function handleCircular(target, source, prependKey, options) {
64
64
  return;
65
65
  }
66
66
  const getTargetVal = () => {
67
- return (prependKey.length > 0) ? get_1.default(target, prependKey) : target;
67
+ return (prependKey.length > 0) ? (0, get_1.default)(target, prependKey) : target;
68
68
  };
69
69
  const getSourceVal = () => {
70
- return (prependKey.length > 0) ? get_1.default(source, prependKey) : source;
70
+ return (prependKey.length > 0) ? (0, get_1.default)(source, prependKey) : source;
71
71
  };
72
72
  const targetVal = getTargetVal();
73
73
  const sourceVal = getSourceVal();
74
- if (isEqual_1.default(targetVal, sourceVal)) {
74
+ if ((0, isEqual_1.default)(targetVal, sourceVal)) {
75
75
  return;
76
76
  }
77
77
  if (defaultHandle === "source") {
78
- set_1.default(target, prependKey, sourceVal);
78
+ (0, set_1.default)(target, prependKey, sourceVal);
79
79
  return;
80
80
  }
81
81
  if (targetVal === null || sourceVal === null) {
82
- set_1.default(target, prependKey, sourceVal);
82
+ (0, set_1.default)(target, prependKey, sourceVal);
83
83
  return;
84
84
  }
85
85
  const typeOfTargetVal = typeof targetVal;
@@ -87,7 +87,7 @@ function handleCircular(target, source, prependKey, options) {
87
87
  if (defaultHandle === "intersect") {
88
88
  actionOnEmptyIntersect(target, source, prependKey);
89
89
  }
90
- set_1.default(target, prependKey, sourceVal);
90
+ (0, set_1.default)(target, prependKey, sourceVal);
91
91
  return;
92
92
  }
93
93
  const typeOfSourceVal = typeof sourceVal;
@@ -96,7 +96,7 @@ function handleCircular(target, source, prependKey, options) {
96
96
  if (isTargetSimple || isSourceSimple) {
97
97
  if (isTargetSimple && isSourceSimple) {
98
98
  if (defaultHandle === "combine") {
99
- set_1.default(target, prependKey, { $in: [...new Set([targetVal, sourceVal])] });
99
+ (0, set_1.default)(target, prependKey, { $in: [...new Set([targetVal, sourceVal])] });
100
100
  return;
101
101
  }
102
102
  else if (defaultHandle === "intersect") {
@@ -110,20 +110,20 @@ function handleCircular(target, source, prependKey, options) {
110
110
  const targetHasIn = hasOwnProperty(targetVal, "$in");
111
111
  const $in = (targetHasIn) ? targetVal["$in"] : sourceVal["$in"];
112
112
  const otherVal = (isTargetSimple) ? targetVal : sourceVal;
113
- if ($in.length === 1 && isEqual_1.default($in[0], otherVal)) {
114
- set_1.default(target, prependKey, otherVal);
113
+ if ($in.length === 1 && (0, isEqual_1.default)($in[0], otherVal)) {
114
+ (0, set_1.default)(target, prependKey, otherVal);
115
115
  return;
116
116
  }
117
117
  else if (defaultHandle === "combine") {
118
- if (!$in.some((x) => isEqual_1.default(x, otherVal))) {
118
+ if (!$in.some((x) => (0, isEqual_1.default)(x, otherVal))) {
119
119
  $in.push(otherVal);
120
120
  }
121
- set_1.default(target, `${prependKey}.$in`, $in);
121
+ (0, set_1.default)(target, `${prependKey}.$in`, $in);
122
122
  return;
123
123
  }
124
124
  else if (defaultHandle === "intersect") {
125
- if ($in.some((x) => isEqual_1.default(x, otherVal))) {
126
- set_1.default(target, prependKey, otherVal);
125
+ if ($in.some((x) => (0, isEqual_1.default)(x, otherVal))) {
126
+ (0, set_1.default)(target, prependKey, otherVal);
127
127
  }
128
128
  else {
129
129
  actionOnEmptyIntersect(target, source, prependKey);
@@ -139,7 +139,7 @@ function handleCircular(target, source, prependKey, options) {
139
139
  const key = prependKey[prependKey.length - 1];
140
140
  if (key === "$or") {
141
141
  if (defaultHandle === "combine") {
142
- const newVals = sourceVal.filter((x) => !targetVal.some((y) => isEqual_1.default(x, y)));
142
+ const newVals = sourceVal.filter((x) => !targetVal.some((y) => (0, isEqual_1.default)(x, y)));
143
143
  targetVal.push(...newVals);
144
144
  }
145
145
  else if (defaultHandle === "intersect") {
@@ -176,7 +176,7 @@ function handleCircular(target, source, prependKey, options) {
176
176
  return;
177
177
  }
178
178
  else if (defaultHandle === "intersect") {
179
- const newVals = sourceVal.filter((x) => !targetVal.some((y) => isEqual_1.default(x, y)));
179
+ const newVals = sourceVal.filter((x) => !targetVal.some((y) => (0, isEqual_1.default)(x, y)));
180
180
  targetVal.push(...newVals);
181
181
  return;
182
182
  }
@@ -185,29 +185,29 @@ function handleCircular(target, source, prependKey, options) {
185
185
  if (defaultHandle === "combine") {
186
186
  let $in = targetVal.concat(sourceVal);
187
187
  $in = [...new Set($in)];
188
- set_1.default(target, prependKey, $in);
188
+ (0, set_1.default)(target, prependKey, $in);
189
189
  return;
190
190
  }
191
191
  else if (defaultHandle === "intersect") {
192
- const $in = targetVal.filter((x) => sourceVal.some((y) => isEqual_1.default(x, y)));
192
+ const $in = targetVal.filter((x) => sourceVal.some((y) => (0, isEqual_1.default)(x, y)));
193
193
  if ($in.length === 0) {
194
194
  actionOnEmptyIntersect(target, source, prependKey);
195
195
  }
196
196
  else if ($in.length === 1) {
197
- set_1.default(target, prependKey.slice(0, -1), $in[0]);
197
+ (0, set_1.default)(target, prependKey.slice(0, -1), $in[0]);
198
198
  return;
199
199
  }
200
200
  else {
201
- set_1.default(target, prependKey, $in);
201
+ (0, set_1.default)(target, prependKey, $in);
202
202
  }
203
203
  }
204
204
  return;
205
205
  }
206
- set_1.default(target, prependKey, sourceVal);
206
+ (0, set_1.default)(target, prependKey, sourceVal);
207
207
  return;
208
208
  }
209
209
  if (typeOfTargetVal !== "object" || typeOfSourceVal !== "object") {
210
- set_1.default(target, prependKey, sourceVal);
210
+ (0, set_1.default)(target, prependKey, sourceVal);
211
211
  return;
212
212
  }
213
213
  // both are objects
@@ -235,7 +235,7 @@ function makeDefaultOptions(options) {
235
235
  }
236
236
  function mergeQuery(target, source, options) {
237
237
  const fullOptions = makeDefaultOptions(options);
238
- const { filters: targetFilters, query: targetQuery } = filterQuery_1.filterQuery(target, {
238
+ const { filters: targetFilters, query: targetQuery } = (0, filterQuery_1.filterQuery)(target, {
239
239
  operators: fullOptions.operators,
240
240
  service: fullOptions.service
241
241
  });
@@ -244,7 +244,7 @@ function mergeQuery(target, source, options) {
244
244
  }
245
245
  let {
246
246
  // eslint-disable-next-line prefer-const
247
- filters: sourceFilters, query: sourceQuery } = filterQuery_1.filterQuery(source, {
247
+ filters: sourceFilters, query: sourceQuery } = (0, filterQuery_1.filterQuery)(source, {
248
248
  operators: fullOptions.operators,
249
249
  service: fullOptions.service
250
250
  });
@@ -265,13 +265,13 @@ function mergeQuery(target, source, options) {
265
265
  handleArray(targetFilters, sourceFilters, ["$select"], fullOptions);
266
266
  // remaining filters
267
267
  delete sourceFilters["$select"];
268
- merge_1.default(targetFilters, sourceFilters);
268
+ (0, merge_1.default)(targetFilters, sourceFilters);
269
269
  //#endregion
270
270
  //#region '$or' / '$and'
271
271
  if ((options === null || options === void 0 ? void 0 : options.useLogicalConjunction) &&
272
272
  (options.defaultHandle === "combine" ||
273
273
  options.defaultHandle === "intersect") &&
274
- !isEmpty_1.default(targetQuery)) {
274
+ !(0, isEmpty_1.default)(targetQuery)) {
275
275
  const logicalOp = (options.defaultHandle === "combine")
276
276
  ? "$or"
277
277
  : "$and";
@@ -301,13 +301,13 @@ function getParentProp(target, path) {
301
301
  return target;
302
302
  }
303
303
  const pathOneUp = path.slice(0, -1);
304
- return get_1.default(target, pathOneUp);
304
+ return (0, get_1.default)(target, pathOneUp);
305
305
  }
306
306
  function cleanOr(target) {
307
307
  if (!target || !Array.isArray(target) || target.length <= 0) {
308
308
  return target;
309
309
  }
310
- if (target.some(x => isEmpty_1.default(x))) {
310
+ if (target.some(x => (0, isEmpty_1.default)(x))) {
311
311
  return undefined;
312
312
  }
313
313
  else {
@@ -318,11 +318,11 @@ function cleanAnd(target) {
318
318
  if (!target || !Array.isArray(target) || target.length <= 0) {
319
319
  return target;
320
320
  }
321
- if (target.every(x => isEmpty_1.default(x))) {
321
+ if (target.every(x => (0, isEmpty_1.default)(x))) {
322
322
  return undefined;
323
323
  }
324
324
  else {
325
- target = target.filter(x => !isEmpty_1.default(x));
325
+ target = target.filter(x => !(0, isEmpty_1.default)(x));
326
326
  return arrayWithoutDuplicates(target);
327
327
  }
328
328
  }
@@ -330,5 +330,5 @@ function arrayWithoutDuplicates(target) {
330
330
  if (!target || !Array.isArray(target)) {
331
331
  return target;
332
332
  }
333
- return uniqWith_1.default(target, isEqual_1.default);
333
+ return (0, uniqWith_1.default)(target, isEqual_1.default);
334
334
  }
@@ -9,14 +9,14 @@ const get_1 = __importDefault(require("lodash/get"));
9
9
  const set_1 = __importDefault(require("lodash/set"));
10
10
  const pushSet = (obj, path, val, options) => {
11
11
  options = options || {};
12
- let arr = get_1.default(obj, path);
12
+ let arr = (0, get_1.default)(obj, path);
13
13
  if (!arr || !Array.isArray(arr)) {
14
14
  arr = [val];
15
- set_1.default(obj, path, arr);
15
+ (0, set_1.default)(obj, path, arr);
16
16
  return arr;
17
17
  }
18
18
  else {
19
- if (options.unique && arr.some(x => isEqual_1.default(x, val))) {
19
+ if (options.unique && arr.some(x => (0, isEqual_1.default)(x, val))) {
20
20
  return arr;
21
21
  }
22
22
  arr.push(val);
@@ -1,2 +1,2 @@
1
- import { HookContext } from "@feathersjs/feathers";
1
+ import type { HookContext } from "@feathersjs/feathers";
2
2
  export declare const setResultEmpty: (context: HookContext) => HookContext;
@@ -7,9 +7,9 @@ const setResultEmpty = (context) => {
7
7
  if (context.result) {
8
8
  return context;
9
9
  }
10
- const multi = __1.isMulti(context);
10
+ const multi = (0, __1.isMulti)(context);
11
11
  if (multi) {
12
- if (context.method === "find" && isPaginated_1.isPaginated(context)) {
12
+ if (context.method === "find" && (0, isPaginated_1.isPaginated)(context)) {
13
13
  context.result = {
14
14
  total: 0,
15
15
  skip: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "feathers-utils",
3
- "version": "1.7.2",
3
+ "version": "1.8.0",
4
4
  "description": "Some utils for projects using '@feathersjs/feathers'",
5
5
  "author": "fratzinger",
6
6
  "repository": {
@@ -21,6 +21,14 @@
21
21
  "directories": {
22
22
  "dist": "dist"
23
23
  },
24
+ "files": [
25
+ "CHANGELOG.md",
26
+ "LICENSE",
27
+ "README.md",
28
+ "src/**",
29
+ "lib/**",
30
+ "dist/**"
31
+ ],
24
32
  "scripts": {
25
33
  "build": "shx rm -rf dist/ && npm run tsc",
26
34
  "tsc": "tsc -p tsconfig.json && tsc -p tsconfig-esm.json",
@@ -31,29 +39,31 @@
31
39
  "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
32
40
  },
33
41
  "dependencies": {
34
- "@feathersjs/adapter-commons": "^4.5.11",
35
- "@feathersjs/errors": "^4.5.11",
36
- "@feathersjs/feathers": "^4.5.11",
37
- "feathers-hooks-common": "^5.0.5",
42
+ "@feathersjs/adapter-commons": "^4.5.12",
43
+ "@feathersjs/errors": "^4.5.12",
44
+ "@feathersjs/feathers": "^4.5.12",
45
+ "feathers-hooks-common": "^5.0.6",
38
46
  "lodash": "^4.17.21",
39
- "type-fest": "^2.5.4"
47
+ "type-fest": "^2.10.0"
40
48
  },
41
49
  "devDependencies": {
42
- "@istanbuljs/nyc-config-typescript": "^1.0.1",
43
- "@types/lodash": "^4.14.168",
44
- "@types/mocha": "^8.2.2",
45
- "@types/node": "^15.0.1",
46
- "@typescript-eslint/eslint-plugin": "^4.22.0",
47
- "@typescript-eslint/parser": "^4.22.0",
50
+ "@istanbuljs/nyc-config-typescript": "^1.0.2",
51
+ "@types/lodash": "^4.14.178",
52
+ "@types/mocha": "^9.1.0",
53
+ "@types/node": "^17.0.12",
54
+ "@typescript-eslint/eslint-plugin": "^5.10.1",
55
+ "@typescript-eslint/parser": "^5.10.1",
48
56
  "cross-env": "^7.0.3",
49
- "eslint": "^7.25.0",
57
+ "eslint": "^8.7.0",
58
+ "eslint-import-resolver-typescript": "^2.5.0",
59
+ "eslint-plugin-import": "^2.25.4",
50
60
  "eslint-plugin-security": "^1.4.0",
51
61
  "feathers-memory": "^4.1.0",
52
- "mocha": "^8.3.2",
53
- "np": "^7.5.0",
62
+ "mocha": "^9.2.0",
63
+ "np": "^7.6.0",
54
64
  "nyc": "^15.1.0",
55
- "shx": "^0.3.3",
56
- "ts-node": "^9.1.1",
57
- "typescript": "^4.2.4"
65
+ "shx": "^0.3.4",
66
+ "ts-node": "^10.4.0",
67
+ "typescript": "^4.5.5"
58
68
  }
59
69
  }
@@ -16,6 +16,7 @@ const makeOptions = (
16
16
  };
17
17
 
18
18
  export const runPerItem = (
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
20
  actionPerItem: (item: any, context: HookContext) => Promisable<any>,
20
21
  options: HookRunPerItemOptions
21
22
  ): ((context: HookContext) => Promise<HookContext>) => {
@@ -44,7 +44,14 @@ export function setData(
44
44
  const val = _get(context, from);
45
45
 
46
46
  items.forEach((item: Record<string, unknown>) => {
47
- if (!options.overwrite && _has(item, to)) { return; }
47
+ let overwrite: boolean;
48
+ if (typeof options.overwrite === "function") {
49
+ overwrite = options.overwrite(item, context);
50
+ } else {
51
+ overwrite = options.overwrite;
52
+ }
53
+
54
+ if (!overwrite && _has(item, to)) { return; }
48
55
 
49
56
  _set(item, to, val);
50
57
  });
@@ -18,58 +18,58 @@ export const makeDefaultOptions = (): DebouncedStoreOptions => {
18
18
  };
19
19
 
20
20
  export class DebouncedStore {
21
- private _app: Application;
22
- private _options: DebouncedStoreOptions;
23
- private _isRunningById: Record<string, unknown>;
24
- _queueById: Record<string, DebouncedFunc<((id: Id, action: DebouncedFunctionApp) => void | Promise<void>)>>;
25
- //_waitingById: Record<string, WaitingObject>;
26
- add;
27
- constructor(app: Application, options?: Partial<DebouncedStoreOptions>) {
28
- this._app = app;
29
- this._options = Object.assign(makeDefaultOptions(), options);
30
- this._queueById = {};
31
- this._isRunningById = {};
32
- //this._waitingById = {};
21
+ private _app: Application;
22
+ private _options: DebouncedStoreOptions;
23
+ private _isRunningById: Record<string, unknown>;
24
+ _queueById: Record<string, DebouncedFunc<((id: Id, action: DebouncedFunctionApp) => void | Promise<void>)>>;
25
+ //_waitingById: Record<string, WaitingObject>;
26
+ add;
27
+ constructor(app: Application, options?: Partial<DebouncedStoreOptions>) {
28
+ this._app = app;
29
+ this._options = Object.assign(makeDefaultOptions(), options);
30
+ this._queueById = {};
31
+ this._isRunningById = {};
32
+ //this._waitingById = {};
33
33
 
34
- this.add = this.debounceById(
35
- this.unbounced,
36
- this._options.wait,
37
- {
38
- leading: this._options.leading,
39
- maxWait: this._options.maxWait,
40
- trailing: this._options.trailing
41
- }
42
- );
43
- }
44
-
45
- private async unbounced(id: Id, action: DebouncedFunctionApp): Promise<void> {
46
- if (this._queueById[id] === undefined) {
47
- return;
34
+ this.add = this.debounceById(
35
+ this.unbounced,
36
+ this._options.wait,
37
+ {
38
+ leading: this._options.leading,
39
+ maxWait: this._options.maxWait,
40
+ trailing: this._options.trailing
48
41
  }
49
- delete this._queueById[id];
50
- this._isRunningById[id] = true;
51
- await action(this._app);
52
- delete this._isRunningById[id];
42
+ );
43
+ }
44
+
45
+ private async unbounced(id: Id, action: DebouncedFunctionApp): Promise<void> {
46
+ if (this._queueById[id] === undefined) {
47
+ return;
53
48
  }
49
+ delete this._queueById[id];
50
+ this._isRunningById[id] = true;
51
+ await action(this._app);
52
+ delete this._isRunningById[id];
53
+ }
54
54
 
55
- private debounceById(
56
- func: ((id: Id, action: DebouncedFunctionApp) => Promise<void>),
57
- wait: number,
58
- options?: Partial<DebouncedStoreOptions>
59
- ) {
60
- return (id: Id, action: ((app?: Application) => void | Promise<void>)) => {
61
- if (typeof this._queueById[id] === "function") {
62
- return this._queueById[id](id, action);
63
- }
64
-
65
- this._queueById[id] = _debounce((id, action) => {
66
- this.unbounced(id, action);
67
- }, wait, { ...options, leading: false }); // leading required for return promise
55
+ private debounceById(
56
+ func: ((id: Id, action: DebouncedFunctionApp) => Promise<void>),
57
+ wait: number,
58
+ options?: Partial<DebouncedStoreOptions>
59
+ ) {
60
+ return (id: Id, action: ((app?: Application) => void | Promise<void>)) => {
61
+ if (typeof this._queueById[id] === "function") {
68
62
  return this._queueById[id](id, action);
69
- };
70
- }
63
+ }
64
+
65
+ this._queueById[id] = _debounce((id, action) => {
66
+ this.unbounced(id, action);
67
+ }, wait, { ...options, leading: false }); // leading required for return promise
68
+ return this._queueById[id](id, action);
69
+ };
70
+ }
71
71
 
72
- cancel(id: Id): void {
73
- delete this._queueById[id];
74
- }
72
+ cancel(id: Id): void {
73
+ delete this._queueById[id];
74
+ }
75
75
  }
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Application, Service } from "@feathersjs/feathers";
1
+ import type { Application, HookContext, Service } from "@feathersjs/feathers";
2
2
 
3
3
  export type Path = Array<string|number>;
4
4
  export type HookType = "before" | "after" | "error";
@@ -7,11 +7,16 @@ export type ServiceMethodName = "find" | "get" | "create" | "update" | "patch" |
7
7
  export type Handle = "target" | "source" | "combine" | "intersect"| "intersectOrFull";
8
8
  export type FirstLast = "first" | "last";
9
9
 
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ export type Predicate<T = any> = (item: T) => boolean
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ export type PredicateWithContext<T = any> = (item: T, context: HookContext) => boolean
14
+
10
15
  //#region hooks
11
16
 
12
17
  export interface HookSetDataOptions {
13
18
  allowUndefined?: boolean
14
- overwrite?: boolean
19
+ overwrite?: boolean | PredicateWithContext
15
20
  }
16
21
 
17
22
  export interface AddHookOptions {
@@ -1,4 +1,4 @@
1
- import { HookContext, PaginationOptions } from "@feathersjs/feathers";
1
+ import type { HookContext, PaginationOptions } from "@feathersjs/feathers";
2
2
 
3
3
  export const getPaginate = (
4
4
  context: HookContext
@@ -1,4 +1,4 @@
1
- import { HookContext } from "@feathersjs/feathers";
1
+ import type { HookContext } from "@feathersjs/feathers";
2
2
  import { getPaginate } from "./getPaginate";
3
3
 
4
4
  export const isPaginated = (
@@ -1,4 +1,4 @@
1
- import { HookContext } from "@feathersjs/feathers";
1
+ import type { HookContext } from "@feathersjs/feathers";
2
2
  import { isMulti } from "..";
3
3
  import { isPaginated } from "./isPaginated";
4
4
 
package/.eslintignore DELETED
@@ -1,3 +0,0 @@
1
- node_modules
2
- dist
3
- coverage
package/.eslintrc.js DELETED
@@ -1,44 +0,0 @@
1
- module.exports = {
2
- root: true,
3
- env: {
4
- node: true,
5
- mocha: true
6
- },
7
- parser: "@typescript-eslint/parser",
8
- plugins: [
9
- "security",
10
- "@typescript-eslint"
11
- ],
12
- extends: [
13
- "eslint:recommended",
14
- "plugin:security/recommended",
15
- "plugin:@typescript-eslint/recommended"
16
- ],
17
- rules: {
18
- "quotes": ["warn", "double", "avoid-escape"],
19
- "indent": ["warn", 2, { "SwitchCase": 1 }],
20
- "semi": ["warn", "always"],
21
- "@typescript-eslint/no-unused-vars": "warn",
22
- "no-console": "off",
23
- "camelcase": "warn",
24
- "require-atomic-updates": "off",
25
- "prefer-destructuring": ["warn", {
26
- "array": false,
27
- "object": true
28
- }, {
29
- "enforceForRenamedProperties": false
30
- }],
31
- "security/detect-object-injection": "off",
32
- "object-curly-spacing": ["warn", "always"],
33
- "prefer-const": ["warn"]
34
- },
35
- overrides: [
36
- {
37
- "files": ["test/**/*.ts"],
38
- "rules": {
39
- "@typescript-eslint/ban-ts-comment": ["off"]
40
- }
41
- }
42
- ]
43
- };
44
-
package/.gitlab-ci.yml DELETED
@@ -1,11 +0,0 @@
1
- .feathers-utils:
2
- only:
3
- changes:
4
- - packages/feathers-utils/**/*
5
-
6
- test:feathers-utils:
7
- variables:
8
- DIR: packages/feathers-utils
9
- extends:
10
- - .feathers-utils
11
- - .test
package/.mocharc.js DELETED
@@ -1,11 +0,0 @@
1
- 'use strict';
2
- const path = require("path");
3
-
4
- module.exports = {
5
- extension: ["ts"],
6
- package: path.join(__dirname, "./package.json"),
7
- ui: "bdd",
8
- spec: [
9
- "./test/**/*.test.ts",
10
- ]
11
- };
package/.nycrc.json DELETED
@@ -1,22 +0,0 @@
1
- {
2
- "extends": "@istanbuljs/nyc-config-typescript",
3
- "cache": false,
4
- "check-coverage": false,
5
- "include": [
6
- "src/**/*.js",
7
- "src/**/*.ts"
8
- ],
9
- "exclude": [
10
- "src/types.ts",
11
- "src/index.ts"
12
- ],
13
- "reporter": [
14
- "html",
15
- "text",
16
- "text-summary",
17
- "lcov"
18
- ],
19
- "sourceMap": true,
20
- "all": true,
21
- "instrument": true
22
- }
package/index.js DELETED
@@ -1,9 +0,0 @@
1
- exports.mergeQuery = require("./src/mergeQuery");
2
- exports.mergeArrays = require("./src/mergeQuery/mergeArrays");
3
- exports.shouldSkip = require("./src/shouldSkip");
4
- exports.pushSet = require("./src/pushSet");
5
- exports.isMulti = require("./src/isMulti");
6
-
7
- exports.hooks = {
8
- checkMulti: require("./src/hooks/checkMulti")
9
- };
package/tsconfig-esm.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "dist/esm",
5
- "moduleResolution": "node",
6
- "target": "ES2020",
7
- "module": "ESNext"
8
- }
9
- }
package/tsconfig.json DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "allowSyntheticDefaultImports": true,
4
- "esModuleInterop": true,
5
- "outDir": "dist",
6
- "moduleResolution": "node",
7
- "target": "es2015",
8
- "module": "commonjs",
9
- "strict": true,
10
- "downlevelIteration": true,
11
- "sourceMap": false,
12
- "declaration": true
13
- },
14
- "include": ["src/**/*"],
15
- "exclude": ["node_modules", "**/*.test.js"]
16
- }
@@ -1,13 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "allowSyntheticDefaultImports": true,
4
- "esModuleInterop": true,
5
- "outDir": "dist",
6
- "moduleResolution": "node",
7
- "target": "es2018",
8
- "sourceMap": true,
9
- "allowJs": true
10
- },
11
- "include": ["src/**/*"],
12
- "exclude": ["node_modules", "**/*.test.js"]
13
- }