Skip to content

Commit 914b084

Browse files
committed
WIP
1 parent 2582a05 commit 914b084

File tree

83 files changed

+2282
-630
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+2282
-630
lines changed

README.md

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## feathers-hooks-common
22

3-
### WIP Changes:
3+
#### hooks
44

55
- added alterData, alterResult, deprecated alterItems
66
- added discardData, discardResult, deprecated discard
@@ -10,23 +10,54 @@
1010
- added lowercaseData, lowercaseResult, deprecated lowercase
1111
- added setNowData, setNowResult, deprecated setNow
1212

13-
- added getDataIsArray, getResultIsArray, deprecated getItems
14-
- added replaceData, replaceResult, deprecated replaceItems
15-
1613
- removed several checks that are handled by typescript
1714
- removed check for `preventChanges(true, ...fieldNames)`
1815

1916
- renamed 'keepQuery' to 'pickQuery', added alias
17+
- renamed 'required' to 'checkRequired', added alias
18+
19+
- added throwIf
20+
- added throwIfIsProvider
21+
- added throwIfIsMulti
22+
- added paramsForServer2 & paramsForClient2
2023

21-
- added utils from feathers-utils
24+
- added 'onDelete' & 'createRelated'
2225

23-
- getPaginate
24-
- isMulti
25-
- isPaginated
26-
- setResultEmpty
26+
- rm support for spread argument
27+
28+
#### predicates
29+
30+
- renamed 'isNot' to 'not' (added alias for 'isNot')
31+
- added predicate isMulti
32+
- added predicate isPaginated
33+
- added predicate isContext
34+
35+
#### utils
36+
37+
- added getDataIsArray, getResultIsArray, deprecated getItems
38+
- added replaceData, replaceResult, deprecated replaceItems
39+
- added util getPaginate
40+
- added util setResultEmpty
41+
42+
- add onDelete
2743

2844
- stashBefore multi
2945

46+
- new: createRelated
47+
- new: onDelete
48+
49+
- softDelete: added 'transformParams' & added 'key' option
50+
51+
### Hooks to discuss
52+
53+
- cache
54+
- populate
55+
- dePopulate
56+
- fgraphql
57+
- fastJoin
58+
- sequelizeConvert
59+
- serialize
60+
3061
<p align="center">
3162
<img src="https://hooks-common.feathersjs.com/feathers-hooks-common-logo.png" width="200">
3263
</p>

eslint.config.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export default tseslint.config(
3636
},
3737
rules: {
3838
'import-x/no-dynamic-require': 'warn',
39-
'import-x/no-nodejs-modules': 'off',
39+
'import-x/no-nodejs-modules': 'error',
4040
},
4141
},
4242
{
@@ -45,6 +45,7 @@ export default tseslint.config(
4545
'@typescript-eslint/no-explicit-any': 'off',
4646
'@typescript-eslint/ban-ts-comment': 'off',
4747
'@typescript-eslint/no-unused-vars': 'off',
48+
'import-x/no-nodejs-modules': 'off',
4849
},
4950
},
5051
eslintPluginPrettierRecommended,

package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"update-dependencies": "ncu -u -x ajv",
2929
"test:unit": "vitest run",
3030
"coverage": "vitest run --coverage",
31-
"test": "npm run lint && npm run coverage"
31+
"test": "npm run lint && npm run coverage",
32+
"vitest": "vitest"
3233
},
3334
"repository": {
3435
"type": "git",
@@ -64,6 +65,7 @@
6465
"dependencies": {
6566
"@feathersjs/errors": "^5.0.31",
6667
"ajv": "^6.12.6",
68+
"fast-copy": "^3.0.2",
6769
"graphql": "^16.10.0",
6870
"lodash": "^4.17.21",
6971
"neotraverse": "^0.6.18"
@@ -87,8 +89,8 @@
8789
"@typescript-eslint/parser": "^8.21.0",
8890
"@vitest/coverage-v8": "^3.0.3",
8991
"eslint": "^9.18.0",
90-
"eslint-import-resolver-typescript": "^3.7.0",
9192
"eslint-config-prettier": "^10.0.1",
93+
"eslint-import-resolver-typescript": "^3.7.0",
9294
"eslint-plugin-import-x": "^4.6.1",
9395
"eslint-plugin-prettier": "^5.2.3",
9496
"mongodb": "^5.9.2",

src/common/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export function isPromise(p: any): p is Promise<any> {
2-
return !!p && (typeof p === 'object' || typeof p === 'function') && typeof p.then === 'function';
2+
return p instanceof Promise;
33
}
44

55
export { setFields } from './set-fields';

src/hooks/alter-items/alter-data.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { HookContext } from '@feathersjs/feathers';
22
import { replaceData } from '../../utils/replace-items/replace-data';
3-
import { isPromise } from 'util/types';
3+
import { isPromise } from '../../common';
44

55
/**
66
* Make changes to data items. Very flexible.
Lines changed: 103 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { assert } from 'vitest';
22
import { alterResult } from './alter-result';
3+
import { HookContext } from '@feathersjs/feathers';
34

45
let hookAfter: any;
56
let hookFindPaginate: any;
@@ -40,13 +41,15 @@ describe('alterResult', () => {
4041
alterResult((rec: any) => {
4142
delete rec.last;
4243
})(hookFindPaginate);
44+
4345
assert.deepEqual(hookFindPaginate.result.data, [{ first: 'John' }, { first: 'Jane' }]);
4446
});
4547

4648
it('updates hook after::find with no pagination', () => {
4749
alterResult((rec: any) => {
4850
rec.new = rec.first;
4951
})(hookFind);
52+
5053
assert.deepEqual(hookFind.result, [
5154
{ first: 'John', last: 'Doe', new: 'John' },
5255
{ first: 'Jane', last: 'Doe', new: 'Jane' },
@@ -57,16 +60,19 @@ describe('alterResult', () => {
5760
alterResult((rec: any) => {
5861
rec.new = rec.first;
5962
})(hookAfter);
63+
6064
assert.deepEqual(hookAfter.result, { first: 'Jane', last: 'Doe', new: 'Jane' });
6165
});
6266

6367
it('updates hook after::find with pagination with new item returned', () => {
6468
alterResult((rec: any) => Object.assign({}, { first: rec.first }))(hookFindPaginate);
69+
6570
assert.deepEqual(hookFindPaginate.result.data, [{ first: 'John' }, { first: 'Jane' }]);
6671
});
6772

6873
it('updates hook after::find with pagination with new item returned', () => {
6974
alterResult((rec: any) => Object.assign({}, rec, { new: rec.first }))(hookFind);
75+
7076
assert.deepEqual(hookFind.result, [
7177
{ first: 'John', last: 'Doe', new: 'John' },
7278
{ first: 'Jane', last: 'Doe', new: 'Jane' },
@@ -75,69 +81,124 @@ describe('alterResult', () => {
7581

7682
it('updates hook after with new item returned', () => {
7783
alterResult((rec: any) => Object.assign({}, rec, { new: rec.first }))(hookAfter);
84+
7885
assert.deepEqual(hookAfter.result, { first: 'Jane', last: 'Doe', new: 'Jane' });
7986
});
8087

81-
it('updates hook after::create', () => {
82-
return alterResult((rec: any) => {
88+
it('updates hook after::create', async () => {
89+
await alterResult((rec: any) => {
8390
rec.new = rec.first;
8491
return Promise.resolve();
85-
// @ts-ignore
86-
})(hookAfter).then(() => {
87-
assert.deepEqual(hookAfter.result, { first: 'Jane', last: 'Doe', new: 'Jane' });
88-
});
92+
})(hookAfter);
93+
94+
assert.deepEqual(hookAfter.result, { first: 'Jane', last: 'Doe', new: 'Jane' });
8995
});
9096

91-
it('updates hook after::create with new item returned', () => {
92-
// @ts-ignore
93-
return alterResult((rec: any) => Promise.resolve(Object.assign({}, rec, { new: rec.first })))(
97+
it('updates hook after::create with new item returned', async () => {
98+
await alterResult((rec: any) => Promise.resolve(Object.assign({}, rec, { new: rec.first })))(
9499
hookAfter,
95-
).then(() => {
96-
assert.deepEqual(hookAfter.result, { first: 'Jane', last: 'Doe', new: 'Jane' });
97-
});
100+
);
101+
102+
assert.deepEqual(hookAfter.result, { first: 'Jane', last: 'Doe', new: 'Jane' });
98103
});
99104

100-
it('updates hook after::find with pagination', () => {
101-
return alterResult((rec: any) => {
105+
it('updates hook after::find with pagination', async () => {
106+
await alterResult((rec: any) => {
102107
delete rec.last;
103108
return Promise.resolve();
104-
// @ts-ignore
105-
})(hookFindPaginate).then(() => {
106-
assert.deepEqual(hookFindPaginate.result.data, [{ first: 'John' }, { first: 'Jane' }]);
107-
});
109+
})(hookFindPaginate);
110+
111+
assert.deepEqual(hookFindPaginate.result.data, [{ first: 'John' }, { first: 'Jane' }]);
108112
});
109113

110-
it('updates hook after::find with no pagination', () => {
111-
return alterResult((rec: any) => {
114+
it('updates hook after::find with no pagination', async () => {
115+
await alterResult((rec: any) => {
112116
rec.new = rec.first;
113117
return Promise.resolve();
114-
// @ts-ignore
115-
})(hookFind).then(() => {
116-
assert.deepEqual(hookFind.result, [
117-
{ first: 'John', last: 'Doe', new: 'John' },
118-
{ first: 'Jane', last: 'Doe', new: 'Jane' },
119-
]);
120-
});
118+
})(hookFind);
119+
120+
assert.deepEqual(hookFind.result, [
121+
{ first: 'John', last: 'Doe', new: 'John' },
122+
{ first: 'Jane', last: 'Doe', new: 'Jane' },
123+
]);
121124
});
122125

123-
it('updates hook after::find with pagination with new item returned', () => {
124-
// @ts-ignore
125-
return alterResult((rec: any) => Promise.resolve(Object.assign({}, { first: rec.first })))(
126+
it('updates hook after::find with pagination with new item returned', async () => {
127+
await alterResult((rec: any) => Promise.resolve(Object.assign({}, { first: rec.first })))(
126128
hookFindPaginate,
127-
).then(() => {
128-
assert.deepEqual(hookFindPaginate.result.data, [{ first: 'John' }, { first: 'Jane' }]);
129-
});
129+
);
130+
131+
assert.deepEqual(hookFindPaginate.result.data, [{ first: 'John' }, { first: 'Jane' }]);
130132
});
131133

132-
it('updates hook after::find with no pagination with new item returned', () => {
133-
// @ts-ignore
134-
return alterResult((rec: any) => Promise.resolve(Object.assign({}, rec, { new: rec.first })))(
134+
it('updates hook after::find with no pagination with new item returned', async () => {
135+
await alterResult((rec: any) => Promise.resolve(Object.assign({}, rec, { new: rec.first })))(
135136
hookFind,
136-
).then(() => {
137-
assert.deepEqual(hookFind.result, [
138-
{ first: 'John', last: 'Doe', new: 'John' },
139-
{ first: 'Jane', last: 'Doe', new: 'Jane' },
140-
]);
141-
});
137+
);
138+
139+
assert.deepEqual(hookFind.result, [
140+
{ first: 'John', last: 'Doe', new: 'John' },
141+
{ first: 'Jane', last: 'Doe', new: 'Jane' },
142+
]);
143+
});
144+
145+
it('updates dispatch', () => {
146+
const context = {
147+
type: 'after',
148+
method: 'create',
149+
params: { provider: 'rest' },
150+
result: { first: 'Jane', last: 'Doe' },
151+
dispatch: { first: 'Jack', last: 'Doe' },
152+
} as HookContext;
153+
154+
alterResult(
155+
(rec: any) => {
156+
rec.new = rec.first;
157+
},
158+
{ dispatch: true },
159+
)(context);
160+
161+
assert.deepEqual(context.result, { first: 'Jane', last: 'Doe' });
162+
assert.deepEqual(context.dispatch, { first: 'Jack', last: 'Doe', new: 'Jack' });
163+
});
164+
165+
it('updates dispatch even though it is not defined', () => {
166+
const context = {
167+
type: 'after',
168+
method: 'create',
169+
params: { provider: 'rest' },
170+
result: { first: 'Jane', last: 'Doe' },
171+
dispatch: undefined,
172+
} as HookContext;
173+
174+
alterResult(
175+
(rec: any) => {
176+
rec.new = rec.first;
177+
},
178+
{ dispatch: true },
179+
)(context);
180+
181+
assert.deepEqual(context.result, { first: 'Jane', last: 'Doe' });
182+
assert.deepEqual(context.dispatch, { first: 'Jane', last: 'Doe', new: 'Jane' });
183+
});
184+
185+
it('updates dispatch and result', () => {
186+
const context = {
187+
type: 'after',
188+
method: 'create',
189+
params: { provider: 'rest' },
190+
result: { first: 'Jane', last: 'Doe' },
191+
dispatch: { first: 'Jack', last: 'Doe' },
192+
} as HookContext;
193+
194+
alterResult(
195+
(rec: any) => {
196+
rec.new = rec.first;
197+
},
198+
{ dispatch: 'both' },
199+
)(context);
200+
201+
assert.deepEqual(context.result, { first: 'Jane', last: 'Doe', new: 'Jane' });
202+
assert.deepEqual(context.dispatch, { first: 'Jack', last: 'Doe', new: 'Jack' });
142203
});
143204
});

src/hooks/alter-items/alter-result.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
import type { HookContext, NextFunction } from '@feathersjs/feathers';
22
import { isPromise } from '../../common';
33
import { replaceResult } from '../../utils/replace-items/replace-result';
4+
import { DispatchOption } from '../../types';
5+
6+
export type AlterResultOptions = {
7+
dispatch?: DispatchOption;
8+
};
49

510
/**
611
* Make changes to result items. Very flexible.
712
* @see https://hooks-common.feathersjs.com/hooks.html#alteritems
813
*/
914
export const alterResult =
10-
<T = any, H extends HookContext = HookContext>(cb: (record: T, context: H) => any) =>
15+
<T = any, H extends HookContext = HookContext>(
16+
cb: (record: T, context: H) => any,
17+
options?: AlterResultOptions,
18+
) =>
1119
(context: H, next?: NextFunction) =>
1220
replaceResult(
1321
context,
@@ -22,5 +30,6 @@ export const alterResult =
2230
},
2331
{
2432
next,
33+
dispatch: options?.dispatch,
2534
},
2635
);

0 commit comments

Comments
 (0)