feathers-utils 1.9.4 → 1.10.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 +5 -3
- package/dist/esm/hooks/createRelated.d.ts +3 -0
- package/dist/esm/hooks/createRelated.js +25 -0
- package/dist/esm/hooks/removeRelated.d.ts +3 -0
- package/dist/esm/hooks/removeRelated.js +28 -0
- package/dist/esm/hooks/runPerItem.d.ts +1 -1
- package/dist/esm/hooks/runPerItem.js +2 -2
- package/dist/esm/index.d.ts +3 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/types.d.ts +12 -0
- package/dist/hooks/createRelated.d.ts +3 -0
- package/dist/hooks/createRelated.js +38 -0
- package/dist/hooks/removeRelated.d.ts +3 -0
- package/dist/hooks/removeRelated.js +41 -0
- package/dist/hooks/runPerItem.d.ts +1 -1
- package/dist/hooks/runPerItem.js +2 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.js +10 -2
- package/dist/types.d.ts +12 -0
- package/package.json +8 -7
- package/src/hooks/createRelated.ts +44 -0
- package/src/hooks/removeRelated.ts +40 -0
- package/src/hooks/runPerItem.ts +3 -3
- package/src/index.ts +3 -0
- package/src/types.ts +14 -0
package/README.md
CHANGED
|
@@ -19,9 +19,11 @@ npm i feathers-utils
|
|
|
19
19
|
|
|
20
20
|
### Hooks
|
|
21
21
|
|
|
22
|
-
- `checkMulti
|
|
23
|
-
- `
|
|
24
|
-
- `
|
|
22
|
+
- `checkMulti`: throws if the request is **multi** data, but the service has `allowsMulti(method)` returns `false`
|
|
23
|
+
- `createRelated`: simply create related items from a hook.
|
|
24
|
+
- `removeRelated`: simple remove related items from a hook. Basically `cascade` at feathers level.
|
|
25
|
+
- `runPerItem`: run a function for every item. Meant for `multi:true`.
|
|
26
|
+
- `setData`: map properties from `context` to `data`. Something like `userId: context.params.user.id`
|
|
25
27
|
|
|
26
28
|
### Mixins
|
|
27
29
|
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { HookContext } from "@feathersjs/feathers";
|
|
2
|
+
import type { CreateRelatedOptions } from "../types";
|
|
3
|
+
export declare function createRelated<S = Record<string, any>>({ service, multi, data, createItemsInDataArraySeparately }: CreateRelatedOptions<S>): (context: HookContext) => Promise<HookContext>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { checkContext } from "feathers-hooks-common";
|
|
2
|
+
import { getItemsIsArray } from "../utils/getItemsIsArray";
|
|
3
|
+
export function createRelated({ service, multi = true, data, createItemsInDataArraySeparately = true }) {
|
|
4
|
+
if (!service || !data) {
|
|
5
|
+
throw "initialize hook 'createRelated' completely!";
|
|
6
|
+
}
|
|
7
|
+
return async (context) => {
|
|
8
|
+
checkContext(context, "after", undefined, "createRelated");
|
|
9
|
+
const { items } = getItemsIsArray(context);
|
|
10
|
+
let dataToCreate = (await Promise.all(items.map(async (item) => data(item, context)))).filter(x => !!x);
|
|
11
|
+
if (createItemsInDataArraySeparately) {
|
|
12
|
+
dataToCreate = dataToCreate.flat();
|
|
13
|
+
}
|
|
14
|
+
if (!dataToCreate || dataToCreate.length <= 0) {
|
|
15
|
+
return context;
|
|
16
|
+
}
|
|
17
|
+
if (multi) {
|
|
18
|
+
await context.app.service(service).create(dataToCreate);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
await Promise.all(dataToCreate.map(async (item) => context.app.service(service).create(item)));
|
|
22
|
+
}
|
|
23
|
+
return context;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { HookContext } from "@feathersjs/feathers";
|
|
2
|
+
import type { RemoveRelatedOptions } from "../types";
|
|
3
|
+
export declare function removeRelated<S = Record<string, any>>({ service, keyThere, keyHere, blocking }: RemoveRelatedOptions<S>): (context: HookContext) => Promise<HookContext>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { checkContext } from "feathers-hooks-common";
|
|
2
|
+
import { getItemsIsArray } from "../utils/getItemsIsArray";
|
|
3
|
+
export function removeRelated({ service, keyThere, keyHere = "id", blocking = true }) {
|
|
4
|
+
if (!service || !keyThere) {
|
|
5
|
+
throw "initialize hook 'removeRelated' completely!";
|
|
6
|
+
}
|
|
7
|
+
return async (context) => {
|
|
8
|
+
checkContext(context, "after", "remove", "removeRelated");
|
|
9
|
+
const { items } = getItemsIsArray(context);
|
|
10
|
+
let ids = items.map(x => x[keyHere]).filter(x => !!x);
|
|
11
|
+
ids = [...new Set(ids)];
|
|
12
|
+
if (!ids || ids.length <= 0) {
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
const promise = context.app.service(service).remove(null, {
|
|
16
|
+
query: {
|
|
17
|
+
[keyThere]: {
|
|
18
|
+
$in: ids
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
paginate: false
|
|
22
|
+
});
|
|
23
|
+
if (blocking) {
|
|
24
|
+
await promise;
|
|
25
|
+
}
|
|
26
|
+
return context;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { HookRunPerItemOptions, ReturnAsyncHook, Promisable } from "../types";
|
|
2
2
|
import type { HookContext } from "@feathersjs/feathers";
|
|
3
|
-
export declare const runPerItem: (actionPerItem: (item: any, context: HookContext) => Promisable<any>,
|
|
3
|
+
export declare const runPerItem: (actionPerItem: (item: any, context: HookContext) => Promisable<any>, _options?: HookRunPerItemOptions | undefined) => ReturnAsyncHook;
|
|
@@ -8,8 +8,8 @@ const makeOptions = (options) => {
|
|
|
8
8
|
};
|
|
9
9
|
export const runPerItem = (
|
|
10
10
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
|
-
actionPerItem,
|
|
12
|
-
options = makeOptions(
|
|
11
|
+
actionPerItem, _options) => {
|
|
12
|
+
const options = makeOptions(_options);
|
|
13
13
|
return async (context) => {
|
|
14
14
|
if (shouldSkip("runForItems", context)) {
|
|
15
15
|
return context;
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -4,10 +4,12 @@ import { runPerItem } from "./hooks/runPerItem";
|
|
|
4
4
|
export declare const hooks: {
|
|
5
5
|
checkMulti: typeof checkMulti;
|
|
6
6
|
setData: typeof setData;
|
|
7
|
-
runPerItem: (actionPerItem: (item: any, context: import("@feathersjs/feathers").HookContext<any, import("@feathersjs/feathers").Service<any>>) => any,
|
|
7
|
+
runPerItem: (actionPerItem: (item: any, context: import("@feathersjs/feathers").HookContext<any, import("@feathersjs/feathers").Service<any>>) => any, _options?: import("./types").HookRunPerItemOptions | undefined) => import("./types").ReturnAsyncHook;
|
|
8
8
|
};
|
|
9
9
|
export { checkMulti };
|
|
10
|
+
export { createRelated } from "./hooks/createRelated";
|
|
10
11
|
export { setData };
|
|
12
|
+
export { removeRelated } from "./hooks/removeRelated";
|
|
11
13
|
export { runPerItem };
|
|
12
14
|
import { debounceMixin, DebouncedStore } from "./mixins/debounce-mixin";
|
|
13
15
|
export declare const mixins: {
|
package/dist/esm/index.js
CHANGED
|
@@ -8,7 +8,9 @@ export const hooks = {
|
|
|
8
8
|
runPerItem
|
|
9
9
|
};
|
|
10
10
|
export { checkMulti };
|
|
11
|
+
export { createRelated } from "./hooks/createRelated";
|
|
11
12
|
export { setData };
|
|
13
|
+
export { removeRelated } from "./hooks/removeRelated";
|
|
12
14
|
export { runPerItem };
|
|
13
15
|
import { debounceMixin, DebouncedStore } from "./mixins/debounce-mixin";
|
|
14
16
|
export const mixins = {
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -24,6 +24,18 @@ export interface AddHookOptions {
|
|
|
24
24
|
export interface HookRunPerItemOptions {
|
|
25
25
|
wait?: boolean;
|
|
26
26
|
}
|
|
27
|
+
export interface RemoveRelatedOptions<S = Record<string, any>> {
|
|
28
|
+
service: keyof S;
|
|
29
|
+
keyThere: string;
|
|
30
|
+
keyHere: string;
|
|
31
|
+
blocking?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface CreateRelatedOptions<S = Record<string, any>> {
|
|
34
|
+
service: keyof S;
|
|
35
|
+
multi?: boolean;
|
|
36
|
+
data: (item: any, context: HookContext) => Promisable<Record<string, any>>;
|
|
37
|
+
createItemsInDataArraySeparately?: boolean;
|
|
38
|
+
}
|
|
27
39
|
export interface InitDebounceMixinOptions {
|
|
28
40
|
default: Partial<DebouncedStoreOptions>;
|
|
29
41
|
blacklist: string[];
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { HookContext } from "@feathersjs/feathers";
|
|
2
|
+
import type { CreateRelatedOptions } from "../types";
|
|
3
|
+
export declare function createRelated<S = Record<string, any>>({ service, multi, data, createItemsInDataArraySeparately }: CreateRelatedOptions<S>): (context: HookContext) => Promise<HookContext>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.createRelated = void 0;
|
|
13
|
+
const feathers_hooks_common_1 = require("feathers-hooks-common");
|
|
14
|
+
const getItemsIsArray_1 = require("../utils/getItemsIsArray");
|
|
15
|
+
function createRelated({ service, multi = true, data, createItemsInDataArraySeparately = true }) {
|
|
16
|
+
if (!service || !data) {
|
|
17
|
+
throw "initialize hook 'createRelated' completely!";
|
|
18
|
+
}
|
|
19
|
+
return (context) => __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
(0, feathers_hooks_common_1.checkContext)(context, "after", undefined, "createRelated");
|
|
21
|
+
const { items } = (0, getItemsIsArray_1.getItemsIsArray)(context);
|
|
22
|
+
let dataToCreate = (yield Promise.all(items.map((item) => __awaiter(this, void 0, void 0, function* () { return data(item, context); })))).filter(x => !!x);
|
|
23
|
+
if (createItemsInDataArraySeparately) {
|
|
24
|
+
dataToCreate = dataToCreate.flat();
|
|
25
|
+
}
|
|
26
|
+
if (!dataToCreate || dataToCreate.length <= 0) {
|
|
27
|
+
return context;
|
|
28
|
+
}
|
|
29
|
+
if (multi) {
|
|
30
|
+
yield context.app.service(service).create(dataToCreate);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
yield Promise.all(dataToCreate.map((item) => __awaiter(this, void 0, void 0, function* () { return context.app.service(service).create(item); })));
|
|
34
|
+
}
|
|
35
|
+
return context;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
exports.createRelated = createRelated;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { HookContext } from "@feathersjs/feathers";
|
|
2
|
+
import type { RemoveRelatedOptions } from "../types";
|
|
3
|
+
export declare function removeRelated<S = Record<string, any>>({ service, keyThere, keyHere, blocking }: RemoveRelatedOptions<S>): (context: HookContext) => Promise<HookContext>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.removeRelated = void 0;
|
|
13
|
+
const feathers_hooks_common_1 = require("feathers-hooks-common");
|
|
14
|
+
const getItemsIsArray_1 = require("../utils/getItemsIsArray");
|
|
15
|
+
function removeRelated({ service, keyThere, keyHere = "id", blocking = true }) {
|
|
16
|
+
if (!service || !keyThere) {
|
|
17
|
+
throw "initialize hook 'removeRelated' completely!";
|
|
18
|
+
}
|
|
19
|
+
return (context) => __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
(0, feathers_hooks_common_1.checkContext)(context, "after", "remove", "removeRelated");
|
|
21
|
+
const { items } = (0, getItemsIsArray_1.getItemsIsArray)(context);
|
|
22
|
+
let ids = items.map(x => x[keyHere]).filter(x => !!x);
|
|
23
|
+
ids = [...new Set(ids)];
|
|
24
|
+
if (!ids || ids.length <= 0) {
|
|
25
|
+
return context;
|
|
26
|
+
}
|
|
27
|
+
const promise = context.app.service(service).remove(null, {
|
|
28
|
+
query: {
|
|
29
|
+
[keyThere]: {
|
|
30
|
+
$in: ids
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
paginate: false
|
|
34
|
+
});
|
|
35
|
+
if (blocking) {
|
|
36
|
+
yield promise;
|
|
37
|
+
}
|
|
38
|
+
return context;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
exports.removeRelated = removeRelated;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { HookRunPerItemOptions, ReturnAsyncHook, Promisable } from "../types";
|
|
2
2
|
import type { HookContext } from "@feathersjs/feathers";
|
|
3
|
-
export declare const runPerItem: (actionPerItem: (item: any, context: HookContext) => Promisable<any>,
|
|
3
|
+
export declare const runPerItem: (actionPerItem: (item: any, context: HookContext) => Promisable<any>, _options?: HookRunPerItemOptions | undefined) => ReturnAsyncHook;
|
package/dist/hooks/runPerItem.js
CHANGED
|
@@ -20,8 +20,8 @@ const makeOptions = (options) => {
|
|
|
20
20
|
};
|
|
21
21
|
const runPerItem = (
|
|
22
22
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
-
actionPerItem,
|
|
24
|
-
options = makeOptions(
|
|
23
|
+
actionPerItem, _options) => {
|
|
24
|
+
const options = makeOptions(_options);
|
|
25
25
|
return (context) => __awaiter(void 0, void 0, void 0, function* () {
|
|
26
26
|
if ((0, shouldSkip_1.shouldSkip)("runForItems", context)) {
|
|
27
27
|
return context;
|
package/dist/index.d.ts
CHANGED
|
@@ -4,10 +4,12 @@ import { runPerItem } from "./hooks/runPerItem";
|
|
|
4
4
|
export declare const hooks: {
|
|
5
5
|
checkMulti: typeof checkMulti;
|
|
6
6
|
setData: typeof setData;
|
|
7
|
-
runPerItem: (actionPerItem: (item: any, context: import("@feathersjs/feathers").HookContext<any, import("@feathersjs/feathers").Service<any>>) => any,
|
|
7
|
+
runPerItem: (actionPerItem: (item: any, context: import("@feathersjs/feathers").HookContext<any, import("@feathersjs/feathers").Service<any>>) => any, _options?: import("./types").HookRunPerItemOptions | undefined) => import("./types").ReturnAsyncHook;
|
|
8
8
|
};
|
|
9
9
|
export { checkMulti };
|
|
10
|
+
export { createRelated } from "./hooks/createRelated";
|
|
10
11
|
export { setData };
|
|
12
|
+
export { removeRelated } from "./hooks/removeRelated";
|
|
11
13
|
export { runPerItem };
|
|
12
14
|
import { debounceMixin, DebouncedStore } from "./mixins/debounce-mixin";
|
|
13
15
|
export declare const mixins: {
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -10,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
10
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
15
|
};
|
|
12
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.shouldSkip = exports.getItemsIsArray = exports.filterQuery = exports.markHookForSkip = exports.setResultEmpty = exports.pushSet = exports.mergeArrays = exports.mergeQuery = exports.isPaginated = exports.isMulti = exports.getPaginate = exports.addHook = exports.DebouncedStore = exports.debounceMixin = exports.mixins = exports.runPerItem = exports.setData = exports.checkMulti = exports.hooks = void 0;
|
|
17
|
+
exports.shouldSkip = exports.getItemsIsArray = exports.filterQuery = exports.markHookForSkip = exports.setResultEmpty = exports.pushSet = exports.mergeArrays = exports.mergeQuery = exports.isPaginated = exports.isMulti = exports.getPaginate = exports.addHook = exports.DebouncedStore = exports.debounceMixin = exports.mixins = exports.runPerItem = exports.removeRelated = exports.setData = exports.createRelated = exports.checkMulti = exports.hooks = void 0;
|
|
14
18
|
// hooks
|
|
15
19
|
const checkMulti_1 = require("./hooks/checkMulti");
|
|
16
20
|
Object.defineProperty(exports, "checkMulti", { enumerable: true, get: function () { return checkMulti_1.checkMulti; } });
|
|
@@ -23,6 +27,10 @@ exports.hooks = {
|
|
|
23
27
|
setData: setData_1.setData,
|
|
24
28
|
runPerItem: runPerItem_1.runPerItem
|
|
25
29
|
};
|
|
30
|
+
var createRelated_1 = require("./hooks/createRelated");
|
|
31
|
+
Object.defineProperty(exports, "createRelated", { enumerable: true, get: function () { return createRelated_1.createRelated; } });
|
|
32
|
+
var removeRelated_1 = require("./hooks/removeRelated");
|
|
33
|
+
Object.defineProperty(exports, "removeRelated", { enumerable: true, get: function () { return removeRelated_1.removeRelated; } });
|
|
26
34
|
const debounce_mixin_1 = require("./mixins/debounce-mixin");
|
|
27
35
|
Object.defineProperty(exports, "debounceMixin", { enumerable: true, get: function () { return debounce_mixin_1.debounceMixin; } });
|
|
28
36
|
Object.defineProperty(exports, "DebouncedStore", { enumerable: true, get: function () { return debounce_mixin_1.DebouncedStore; } });
|
package/dist/types.d.ts
CHANGED
|
@@ -24,6 +24,18 @@ export interface AddHookOptions {
|
|
|
24
24
|
export interface HookRunPerItemOptions {
|
|
25
25
|
wait?: boolean;
|
|
26
26
|
}
|
|
27
|
+
export interface RemoveRelatedOptions<S = Record<string, any>> {
|
|
28
|
+
service: keyof S;
|
|
29
|
+
keyThere: string;
|
|
30
|
+
keyHere: string;
|
|
31
|
+
blocking?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface CreateRelatedOptions<S = Record<string, any>> {
|
|
34
|
+
service: keyof S;
|
|
35
|
+
multi?: boolean;
|
|
36
|
+
data: (item: any, context: HookContext) => Promisable<Record<string, any>>;
|
|
37
|
+
createItemsInDataArraySeparately?: boolean;
|
|
38
|
+
}
|
|
27
39
|
export interface InitDebounceMixinOptions {
|
|
28
40
|
default: Partial<DebouncedStoreOptions>;
|
|
29
41
|
blacklist: string[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "feathers-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Some utils for projects using '@feathersjs/feathers'",
|
|
5
5
|
"author": "fratzinger",
|
|
6
6
|
"repository": {
|
|
@@ -42,17 +42,18 @@
|
|
|
42
42
|
"@feathersjs/adapter-commons": "^4.5.12",
|
|
43
43
|
"@feathersjs/errors": "^4.5.12",
|
|
44
44
|
"@feathersjs/feathers": "^4.5.12",
|
|
45
|
+
"feathers-hooks-common": "^5.0.6",
|
|
45
46
|
"lodash": "^4.17.21"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
49
|
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
|
49
|
-
"@types/lodash": "^4.14.
|
|
50
|
+
"@types/lodash": "^4.14.179",
|
|
50
51
|
"@types/mocha": "^9.1.0",
|
|
51
|
-
"@types/node": "^17.0.
|
|
52
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
53
|
-
"@typescript-eslint/parser": "^5.
|
|
52
|
+
"@types/node": "^17.0.21",
|
|
53
|
+
"@typescript-eslint/eslint-plugin": "^5.13.0",
|
|
54
|
+
"@typescript-eslint/parser": "^5.13.0",
|
|
54
55
|
"cross-env": "^7.0.3",
|
|
55
|
-
"eslint": "^8.
|
|
56
|
+
"eslint": "^8.10.0",
|
|
56
57
|
"eslint-import-resolver-typescript": "^2.5.0",
|
|
57
58
|
"eslint-plugin-import": "^2.25.4",
|
|
58
59
|
"eslint-plugin-security": "^1.4.0",
|
|
@@ -62,6 +63,6 @@
|
|
|
62
63
|
"nyc": "^15.1.0",
|
|
63
64
|
"shx": "^0.3.4",
|
|
64
65
|
"ts-node": "^10.5.0",
|
|
65
|
-
"typescript": "^4.
|
|
66
|
+
"typescript": "^4.6.2"
|
|
66
67
|
}
|
|
67
68
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { HookContext } from "@feathersjs/feathers";
|
|
2
|
+
import { checkContext } from "feathers-hooks-common";
|
|
3
|
+
import type { CreateRelatedOptions } from "../types";
|
|
4
|
+
import { getItemsIsArray } from "../utils/getItemsIsArray";
|
|
5
|
+
|
|
6
|
+
export function createRelated<S = Record<string, any>>({
|
|
7
|
+
service,
|
|
8
|
+
multi = true,
|
|
9
|
+
data,
|
|
10
|
+
createItemsInDataArraySeparately = true
|
|
11
|
+
}: CreateRelatedOptions<S>) {
|
|
12
|
+
if (!service || !data) {
|
|
13
|
+
throw "initialize hook 'createRelated' completely!";
|
|
14
|
+
}
|
|
15
|
+
return async (context: HookContext): Promise<HookContext> => {
|
|
16
|
+
checkContext(context, "after", undefined, "createRelated");
|
|
17
|
+
|
|
18
|
+
const { items } = getItemsIsArray(context);
|
|
19
|
+
|
|
20
|
+
let dataToCreate = (await Promise.all(
|
|
21
|
+
items.map(async item => data(item, context))
|
|
22
|
+
)).filter(x => !!x);
|
|
23
|
+
|
|
24
|
+
if (createItemsInDataArraySeparately) {
|
|
25
|
+
dataToCreate = dataToCreate.flat();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!dataToCreate || dataToCreate.length <= 0) {
|
|
29
|
+
return context;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (multi) {
|
|
33
|
+
await context.app.service(service as string).create(dataToCreate);
|
|
34
|
+
} else {
|
|
35
|
+
await Promise.all(
|
|
36
|
+
dataToCreate.map(async item =>
|
|
37
|
+
context.app.service(service as string).create(item)
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return context;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { HookContext } from "@feathersjs/feathers";
|
|
2
|
+
import { checkContext } from "feathers-hooks-common";
|
|
3
|
+
import type { RemoveRelatedOptions } from "../types";
|
|
4
|
+
import { getItemsIsArray } from "../utils/getItemsIsArray";
|
|
5
|
+
|
|
6
|
+
export function removeRelated<S = Record<string, any>>({
|
|
7
|
+
service,
|
|
8
|
+
keyThere,
|
|
9
|
+
keyHere = "id",
|
|
10
|
+
blocking = true
|
|
11
|
+
}: RemoveRelatedOptions<S>) {
|
|
12
|
+
if (!service || !keyThere) {
|
|
13
|
+
throw "initialize hook 'removeRelated' completely!";
|
|
14
|
+
}
|
|
15
|
+
return async (context: HookContext): Promise<HookContext> => {
|
|
16
|
+
checkContext(context, "after", "remove", "removeRelated");
|
|
17
|
+
|
|
18
|
+
const { items } = getItemsIsArray(context);
|
|
19
|
+
|
|
20
|
+
let ids = items.map(x => x[keyHere]).filter(x => !!x);
|
|
21
|
+
ids = [...new Set(ids)];
|
|
22
|
+
|
|
23
|
+
if (!ids || ids.length <= 0) { return context; }
|
|
24
|
+
|
|
25
|
+
const promise: Promise<any> = context.app.service(service as string).remove(null, {
|
|
26
|
+
query: {
|
|
27
|
+
[keyThere]: {
|
|
28
|
+
$in: ids
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
paginate: false
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if (blocking) {
|
|
35
|
+
await promise;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return context;
|
|
39
|
+
};
|
|
40
|
+
}
|
package/src/hooks/runPerItem.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { HookContext } from "@feathersjs/feathers";
|
|
|
5
5
|
import { getItemsIsArray } from "../utils/getItemsIsArray";
|
|
6
6
|
|
|
7
7
|
const makeOptions = (
|
|
8
|
-
options
|
|
8
|
+
options?: HookRunPerItemOptions
|
|
9
9
|
): Required<HookRunPerItemOptions> => {
|
|
10
10
|
options = options || {};
|
|
11
11
|
return Object.assign({
|
|
@@ -16,9 +16,9 @@ const makeOptions = (
|
|
|
16
16
|
export const runPerItem = (
|
|
17
17
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
18
|
actionPerItem: (item: any, context: HookContext) => Promisable<any>,
|
|
19
|
-
|
|
19
|
+
_options?: HookRunPerItemOptions
|
|
20
20
|
): ReturnAsyncHook => {
|
|
21
|
-
options = makeOptions(
|
|
21
|
+
const options = makeOptions(_options);
|
|
22
22
|
return async (context: HookContext): Promise<HookContext> => {
|
|
23
23
|
if (shouldSkip("runForItems", context)) { return context; }
|
|
24
24
|
const { items } = getItemsIsArray(context);
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// hooks
|
|
2
2
|
import { checkMulti } from "./hooks/checkMulti";
|
|
3
3
|
import { setData } from "./hooks/setData";
|
|
4
|
+
|
|
4
5
|
import { runPerItem } from "./hooks/runPerItem";
|
|
5
6
|
|
|
6
7
|
export const hooks = {
|
|
@@ -10,7 +11,9 @@ export const hooks = {
|
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
export { checkMulti };
|
|
14
|
+
export { createRelated } from "./hooks/createRelated";
|
|
13
15
|
export { setData };
|
|
16
|
+
export { removeRelated } from "./hooks/removeRelated";
|
|
14
17
|
export { runPerItem };
|
|
15
18
|
|
|
16
19
|
import { debounceMixin, DebouncedStore } from "./mixins/debounce-mixin";
|
package/src/types.ts
CHANGED
|
@@ -36,6 +36,20 @@ export interface HookRunPerItemOptions {
|
|
|
36
36
|
wait?: boolean
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
export interface RemoveRelatedOptions<S = Record<string, any>> {
|
|
40
|
+
service: keyof S
|
|
41
|
+
keyThere: string
|
|
42
|
+
keyHere: string
|
|
43
|
+
blocking?: boolean
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface CreateRelatedOptions<S = Record<string, any>> {
|
|
47
|
+
service: keyof S
|
|
48
|
+
multi?: boolean
|
|
49
|
+
data: (item: any, context: HookContext) => Promisable<Record<string, any>>
|
|
50
|
+
createItemsInDataArraySeparately?: boolean
|
|
51
|
+
}
|
|
52
|
+
|
|
39
53
|
//#endregion
|
|
40
54
|
|
|
41
55
|
//#region mixins
|