feathers-utils 1.6.1 → 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.
Files changed (87) hide show
  1. package/dist/esm/hooks/checkMulti.d.ts +2 -0
  2. package/dist/esm/hooks/checkMulti.js +18 -0
  3. package/dist/esm/hooks/runPerItem.d.ts +4 -0
  4. package/dist/esm/hooks/runPerItem.js +27 -0
  5. package/dist/esm/hooks/setData.d.ts +4 -0
  6. package/dist/esm/hooks/setData.js +40 -0
  7. package/dist/esm/index.d.ts +30 -0
  8. package/dist/esm/index.js +31 -0
  9. package/dist/esm/mixins/debounce-mixin/DebouncedStore.d.ts +15 -0
  10. package/dist/esm/mixins/debounce-mixin/DebouncedStore.js +46 -0
  11. package/dist/esm/mixins/debounce-mixin/index.d.ts +5 -0
  12. package/dist/esm/mixins/debounce-mixin/index.js +20 -0
  13. package/dist/esm/types.d.ts +61 -0
  14. package/dist/esm/types.js +2 -0
  15. package/dist/esm/utils/addHook.d.ts +3 -0
  16. package/dist/esm/utils/addHook.js +36 -0
  17. package/dist/esm/utils/filterQuery.d.ts +3 -0
  18. package/dist/esm/utils/filterQuery.js +28 -0
  19. package/dist/esm/utils/getPaginate.d.ts +2 -0
  20. package/dist/esm/utils/getPaginate.js +14 -0
  21. package/dist/esm/utils/isMulti.d.ts +2 -0
  22. package/dist/esm/utils/isMulti.js +17 -0
  23. package/dist/esm/utils/isPaginated.d.ts +2 -0
  24. package/dist/esm/utils/isPaginated.js +8 -0
  25. package/dist/esm/utils/markHookForSkip.d.ts +3 -0
  26. package/dist/esm/utils/markHookForSkip.js +14 -0
  27. package/dist/esm/utils/mergeQuery/index.d.ts +3 -0
  28. package/dist/esm/utils/mergeQuery/index.js +327 -0
  29. package/dist/esm/utils/mergeQuery/mergeArrays.d.ts +2 -0
  30. package/dist/esm/utils/mergeQuery/mergeArrays.js +37 -0
  31. package/dist/esm/utils/pushSet.d.ts +2 -0
  32. package/dist/esm/utils/pushSet.js +19 -0
  33. package/dist/esm/utils/setResultEmpty.d.ts +2 -0
  34. package/dist/esm/utils/setResultEmpty.js +25 -0
  35. package/dist/esm/utils/shouldSkip.d.ts +2 -0
  36. package/dist/esm/utils/shouldSkip.js +29 -0
  37. package/dist/hooks/checkMulti.js +2 -2
  38. package/dist/hooks/runPerItem.d.ts +2 -1
  39. package/dist/hooks/runPerItem.js +5 -3
  40. package/dist/hooks/setData.js +13 -6
  41. package/dist/index.d.ts +4 -1
  42. package/dist/index.js +7 -1
  43. package/dist/mixins/debounce-mixin/DebouncedStore.d.ts +1 -1
  44. package/dist/mixins/debounce-mixin/DebouncedStore.js +2 -2
  45. package/dist/mixins/debounce-mixin/index.js +1 -1
  46. package/dist/types.d.ts +4 -2
  47. package/dist/utils/filterQuery.js +2 -2
  48. package/dist/utils/getPaginate.d.ts +2 -0
  49. package/dist/utils/getPaginate.js +15 -0
  50. package/dist/utils/isMulti.js +2 -3
  51. package/dist/utils/isPaginated.d.ts +2 -0
  52. package/dist/utils/isPaginated.js +12 -0
  53. package/dist/utils/markHookForSkip.js +1 -1
  54. package/dist/utils/mergeQuery/index.js +38 -38
  55. package/dist/utils/pushSet.js +3 -3
  56. package/dist/utils/setResultEmpty.d.ts +2 -0
  57. package/dist/utils/setResultEmpty.js +29 -0
  58. package/package.json +40 -24
  59. package/src/hooks/runPerItem.ts +3 -1
  60. package/src/hooks/setData.ts +8 -1
  61. package/src/index.ts +3 -0
  62. package/src/mixins/debounce-mixin/DebouncedStore.ts +49 -49
  63. package/src/types.ts +7 -2
  64. package/src/utils/getPaginate.ts +18 -0
  65. package/src/utils/isMulti.ts +2 -3
  66. package/src/utils/isPaginated.ts +12 -0
  67. package/src/utils/setResultEmpty.ts +28 -0
  68. package/.eslintignore +0 -3
  69. package/.eslintrc.js +0 -44
  70. package/.github/workflows/node.js.yml +0 -45
  71. package/.gitlab-ci.yml +0 -11
  72. package/.mocharc.js +0 -11
  73. package/.nycrc.json +0 -22
  74. package/.vscode/launch.json +0 -28
  75. package/.vscode/settings.json +0 -14
  76. package/index.js +0 -9
  77. package/test/hooks/checkMulti.test.ts +0 -121
  78. package/test/hooks/setData.test.ts +0 -333
  79. package/test/mixins/debounce-mixin.test.ts +0 -174
  80. package/test/utils/addHook.test.ts +0 -307
  81. package/test/utils/isMulti.test.ts +0 -53
  82. package/test/utils/markHookForSkip.test.ts +0 -292
  83. package/test/utils/mergeQuery.test.ts +0 -407
  84. package/test/utils/pushSet.test.ts +0 -66
  85. package/test/utils/shouldSkip.test.ts +0 -67
  86. package/tsconfig.json +0 -16
  87. package/tsconfig.test.json +0 -13
@@ -1,333 +0,0 @@
1
- import assert from "assert";
2
- import { setData } from "../../src";
3
-
4
- describe("hook - setData", function() {
5
- it("sets userId for single item", function() {
6
- const methodsByType = {
7
- "before": ["create", "update", "patch", "remove"],
8
- "after": ["find", "get", "create", "update", "patch", "remove"]
9
- };
10
- Object.keys(methodsByType).forEach(type => {
11
- methodsByType[type].forEach(method => {
12
- const context = {
13
- method,
14
- type,
15
- params: {
16
- user: {
17
- id: 1
18
- }
19
- }
20
- };
21
-
22
- const dataOrResult = (type === "before") ? "data" : "result";
23
- context[dataOrResult] = {};
24
-
25
- //@ts-ignore
26
- const result = setData("params.user.id", "userId")(context);
27
- assert.strictEqual(result[dataOrResult].userId, 1, `'${type}/${method}': ${dataOrResult} has 'userId:1'`);
28
- });
29
- });
30
- });
31
-
32
- it("overwrites userId for single item", function() {
33
- const methodsByType = {
34
- "before": ["create", "update", "patch", "remove"],
35
- "after": ["find", "get", "create", "update", "patch", "remove"]
36
- };
37
- Object.keys(methodsByType).forEach(type => {
38
- methodsByType[type].forEach(method => {
39
- const context = {
40
- method,
41
- type,
42
- params: {
43
- user: {
44
- id: 1
45
- }
46
- }
47
- };
48
-
49
- const dataOrResult = (type === "before") ? "data" : "result";
50
- context[dataOrResult] = { userId: 2 };
51
-
52
- //@ts-ignore
53
- const result = setData("params.user.id", "userId")(context);
54
- assert.strictEqual(result[dataOrResult].userId, 1, `'${type}/${method}': ${dataOrResult} has 'userId:1'`);
55
- });
56
- });
57
- });
58
-
59
- it("sets userId for multiple items", function() {
60
- const methodsByType = {
61
- "before": ["create", "update", "patch", "remove"],
62
- "after": ["find", "get", "create", "update", "patch", "remove"]
63
- };
64
- Object.keys(methodsByType).forEach(type => {
65
- methodsByType[type].forEach(method => {
66
- const context = {
67
- method,
68
- type,
69
- params: {
70
- user: {
71
- id: 1
72
- }
73
- },
74
- };
75
-
76
- const dataOrResult = (type === "before") ? "data" : "result";
77
- context[dataOrResult] = [{}, {}, {}];
78
-
79
- //@ts-ignore
80
- const result = setData("params.user.id", "userId")(context);
81
- result[dataOrResult].forEach(item => {
82
- assert.strictEqual(item.userId, 1, `'${type}/${method}': ${dataOrResult} has 'userId:1'`);
83
- });
84
- });
85
- });
86
- });
87
-
88
- it("overwrites userId for multiple items", function() {
89
- const methodsByType = {
90
- "before": ["create", "update", "patch", "remove"],
91
- "after": ["find", "get", "create", "update", "patch", "remove"]
92
- };
93
- Object.keys(methodsByType).forEach(type => {
94
- methodsByType[type].forEach(method => {
95
- const context = {
96
- method,
97
- type,
98
- params: {
99
- user: {
100
- id: 1
101
- }
102
- }
103
- };
104
-
105
- const dataOrResult = (type === "before") ? "data" : "result";
106
- context[dataOrResult] = [{ userId: 2 }, {}, { userId: "abc" }];
107
-
108
- //@ts-ignore
109
- const result = setData("params.user.id", "userId")(context);
110
- result[dataOrResult].forEach(item => {
111
- assert.strictEqual(item.userId, 1, `'${type}/${method}': ${dataOrResult} has 'userId:1'`);
112
- });
113
- });
114
- });
115
- });
116
-
117
- it("does not change createdById if 'params.user.id' is not provided", function() {
118
- const methodsByType = {
119
- "before": ["create", "update", "patch", "remove"],
120
- "after": ["find", "get", "create", "update", "patch", "remove"]
121
- };
122
- Object.keys(methodsByType).forEach(type => {
123
- methodsByType[type].forEach(method => {
124
- const context = {
125
- method,
126
- type,
127
- params: {}
128
- };
129
-
130
- const dataOrResult = (type === "before") ? "data" : "result";
131
- context[dataOrResult] = { userId: 2 };
132
-
133
- //@ts-ignore
134
- const result = setData("params.user.id", "userId")(context);
135
-
136
- assert.strictEqual(result[dataOrResult].userId, 2, `'${type}/${method}': ${dataOrResult} has 'userId:2'`);
137
- });
138
- });
139
- });
140
-
141
- it("throws if 'external' is set and context.user.id is undefined", function() {
142
- const methodsByType = {
143
- "before": ["create", "update", "patch", "remove"],
144
- "after": ["find", "get", "create", "update", "patch", "remove"]
145
- };
146
- Object.keys(methodsByType).forEach(type => {
147
- methodsByType[type].forEach(method => {
148
- const context = {
149
- method,
150
- type,
151
- params: {
152
- provider: "socket.io"
153
- }
154
- };
155
-
156
- const dataOrResult = (type === "before") ? "data" : "result";
157
- context[dataOrResult] = {};
158
-
159
- assert.throws(
160
- //@ts-ignore
161
- () => setData("params.user.id", "userId")(context),
162
- err => err.name === "Forbidden",
163
- `'${type}/${method}': throws 'Forbidden' error`
164
- );
165
- });
166
- });
167
- });
168
-
169
- it("passes if 'external' and 'allowUndefined: true'", function() {
170
- const methodsByType = {
171
- "before": ["create", "update", "patch", "remove"],
172
- "after": ["find", "get", "create", "update", "patch", "remove"]
173
- };
174
- Object.keys(methodsByType).forEach(type => {
175
- methodsByType[type].forEach(method => {
176
- const context = {
177
- method,
178
- type,
179
- provider: "socket.io",
180
- params: {},
181
- data: {}
182
- };
183
-
184
- assert.doesNotThrow(
185
- //@ts-ignore
186
- () => setData("params.user.id", "userId", { allowUndefined: true })(context),
187
- `'${type}/${method}': passes`
188
- );
189
- });
190
- });
191
- });
192
-
193
- it("passes if 'external' is set and context.user.id is undefined but overwrite: false", function() {
194
- const methodsByType = {
195
- "before": ["create", "update", "patch", "remove"],
196
- "after": ["find", "get", "create", "update", "patch", "remove"]
197
- };
198
- Object.keys(methodsByType).forEach(type => {
199
- methodsByType[type].forEach(method => {
200
- const context = {
201
- method,
202
- type,
203
- params: {
204
- provider: "socket.io"
205
- }
206
- };
207
-
208
- const dataOrResult = (type === "before") ? "data" : "result";
209
- context[dataOrResult] = { userId: 1 };
210
-
211
- assert.doesNotThrow(
212
- //@ts-ignore
213
- () => setData("params.user.id", "userId", { overwrite: false })(context),
214
- `'${type}/${method}': passes`
215
- );
216
- });
217
- });
218
- });
219
-
220
- describe("overwrite: false", function() {
221
- it("sets userId for single item", function() {
222
- const methodsByType = {
223
- "before": ["create", "update", "patch", "remove"],
224
- "after": ["find", "get", "create", "update", "patch", "remove"]
225
- };
226
- Object.keys(methodsByType).forEach(type => {
227
- methodsByType[type].forEach(method => {
228
- const context = {
229
- method,
230
- type,
231
- params: {
232
- user: {
233
- id: 1
234
- }
235
- }
236
- };
237
-
238
- const dataOrResult = (type === "before") ? "data" : "result";
239
- context[dataOrResult] = {};
240
-
241
- //@ts-ignore
242
- const result = setData("params.user.id", "userId", { overwrite: false })(context);
243
- assert.strictEqual(result[dataOrResult].userId, 1, `'${type}/${method}': ${dataOrResult} has 'userId:1'`);
244
- });
245
- });
246
- });
247
-
248
- it("does not overwrite userId for single item", function() {
249
- const methodsByType = {
250
- "before": ["create", "update", "patch", "remove"],
251
- "after": ["find", "get", "create", "update", "patch", "remove"]
252
- };
253
- Object.keys(methodsByType).forEach(type => {
254
- methodsByType[type].forEach(method => {
255
- const context = {
256
- method,
257
- type,
258
- params: {
259
- user: {
260
- id: 1
261
- }
262
- }
263
- };
264
-
265
- const dataOrResult = (type === "before") ? "data" : "result";
266
- context[dataOrResult] = { userId: 2 };
267
-
268
- //@ts-ignore
269
- const result = setData("params.user.id", "userId", { overwrite: false })(context);
270
- assert.strictEqual(result[dataOrResult].userId, 2, `'${type}/${method}': ${dataOrResult} has 'userId:2'`);
271
- });
272
- });
273
- });
274
-
275
- it("sets userId for multiple items", function() {
276
- const methodsByType = {
277
- "before": ["create", "update", "patch", "remove"],
278
- "after": ["find", "get", "create", "update", "patch", "remove"]
279
- };
280
- Object.keys(methodsByType).forEach(type => {
281
- methodsByType[type].forEach(method => {
282
- const context = {
283
- method,
284
- type,
285
- params: {
286
- user: {
287
- id: 1
288
- }
289
- },
290
- };
291
-
292
- const dataOrResult = (type === "before") ? "data" : "result";
293
- context[dataOrResult] = [{}, {}, {}];
294
-
295
- //@ts-ignore
296
- const result = setData("params.user.id", "userId", { overwrite: false })(context);
297
- result[dataOrResult].forEach((item) => {
298
- assert.strictEqual(item.userId, 1, `${type}/${method}': ${dataOrResult} has 'userId:1'`);
299
- });
300
- });
301
- });
302
- });
303
-
304
- it("overwrites userId for multiple items", function() {
305
- const methodsByType = {
306
- "before": ["create", "update", "patch", "remove"],
307
- "after": ["find", "get", "create", "update", "patch", "remove"]
308
- };
309
- Object.keys(methodsByType).forEach(type => {
310
- methodsByType[type].forEach(method => {
311
- const context = {
312
- method,
313
- type,
314
- params: {
315
- user: {
316
- id: 1
317
- }
318
- }
319
- };
320
-
321
- const dataOrResult = (type === "before") ? "data" : "result";
322
- context[dataOrResult] = [{ userId: 0 }, {}, { userId: 2 }];
323
-
324
- //@ts-ignore
325
- const result = setData("params.user.id", "userId", { overwrite: false })(context);
326
- result[dataOrResult].forEach((item, i) => {
327
- assert.strictEqual(item.userId, i, `${type}/${method}': ${dataOrResult} has 'userId:${i}`);
328
- });
329
- });
330
- });
331
- });
332
- });
333
- });
@@ -1,174 +0,0 @@
1
- import assert from "assert";
2
- import feathers from "@feathersjs/feathers";
3
- import createService from "feathers-memory";
4
- import { debounceMixin as makeMixin } from "../../src";
5
- import { performance } from "perf_hooks";
6
-
7
- const mockApp = () => {
8
- const app = feathers();
9
- app.configure(makeMixin({
10
- default: {
11
- wait: 50,
12
- maxWait: 1000
13
- },
14
- blacklist: ["authentication"]
15
- }));
16
- app.use("users", createService());
17
- app.use("tasks", createService());
18
- app.use("posts", createService());
19
-
20
- app.use("authentication", createService());
21
-
22
- const usersService = app.service("users");
23
- const tasksService = app.service("tasks");
24
- const postsService = app.service("posts");
25
- const authenticationService = app.service("authentication");
26
-
27
- return {
28
- app,
29
- usersService,
30
- tasksService,
31
- postsService,
32
- authenticationService
33
- };
34
- };
35
-
36
- describe("mixin: debounce-mixin", function() {
37
- it("initializes debounce-mixin", function() {
38
- const {
39
- usersService,
40
- tasksService,
41
- postsService,
42
- authenticationService
43
- } = mockApp();
44
-
45
- [usersService, tasksService, postsService].forEach(service => {
46
- assert.ok(service.debouncedStore, "service has debounceStore");
47
- assert.strictEqual(typeof service.debouncedStore.add, "function", "service has 'add' function");
48
- });
49
-
50
- assert.strictEqual(authenticationService.debouncedStore, undefined, "authentication has no debounced Store");
51
- });
52
-
53
- it("only gets called once", async function() {
54
- const {
55
- usersService
56
- } = mockApp();
57
- let callCounter = 0;
58
- for (let i = 0; i < 50; i++) {
59
- usersService.debouncedStore.add(1, () => {
60
- callCounter++;
61
- return usersService.create({ id: i, test: true });
62
- });
63
- }
64
- await new Promise(resolve => setTimeout(resolve, 400));
65
- const items = await usersService.find({ query: {}, paginate: false });
66
- assert.strictEqual(items.length, 1, "only has one item");
67
- assert.strictEqual(items[0].id, 49, "called with last iteration");
68
- assert.strictEqual(callCounter, 1, "only called once");
69
- assert.deepStrictEqual(usersService.debouncedStore._queueById, {}, "queue is empty");
70
- assert.deepStrictEqual(usersService.debouncedStore._isRunningById, {}, "nothing is running");
71
- });
72
-
73
- it("doesn't call instantly", async function() {
74
- const {
75
- usersService
76
- } = mockApp();
77
- let callCounter = 0;
78
- for (let i = 0; i < 50; i++) {
79
- usersService.debouncedStore.add(1, () => {
80
- callCounter++;
81
- return usersService.create({ id: i, test: true });
82
- });
83
- }
84
- const items = await usersService.find({ query: {}, paginate: false });
85
- assert.strictEqual(items.length, 0, "hasn't any items yet");
86
- assert.strictEqual(callCounter, 0, "not called yet");
87
- });
88
-
89
- it("stores per id", async function() {
90
- const {
91
- usersService
92
- } = mockApp();
93
- const callCounter = {};
94
- const times = 100;
95
- for (let i = 0; i < times; i++) {
96
- callCounter[i] = 0;
97
- for (let j = 0; j < 50; j++) {
98
- usersService.debouncedStore.add(i, () => {
99
- callCounter[i]++;
100
- return usersService.create({ id: i, test: true });
101
- });
102
- }
103
- }
104
-
105
- await new Promise(resolve => setTimeout(resolve, 400));
106
- const items = await usersService.find({ query: { $sort: { id: 1 } }, paginate: false });
107
- assert.strictEqual(items.length, times, `has ${times} items`);
108
- items.forEach((item, i) => {
109
- assert.strictEqual(item.id, i, "continuous ids");
110
- assert.strictEqual(callCounter[i], 1, "only called once");
111
- });
112
- });
113
-
114
- it("waits per id", function(done) {
115
- const {
116
- usersService
117
- } = mockApp();
118
- const callCounter = {
119
- 1: 0,
120
- 2: 0
121
- };
122
- const times = 60;
123
- usersService.debouncedStore.add(1, () => {
124
- callCounter[1]++;
125
- return usersService.create({ id: 1, test: true });
126
- });
127
- let counter = 0;
128
- const started = performance.now();
129
- const callTwo = () => {
130
- if (counter > times) {
131
- assert(performance.now() - started > 200, "enough time elapsed");
132
- usersService
133
- .find({ query: { $sort: { id: 1 } }, paginate: false })
134
- .then(items => {
135
- assert.strictEqual(items.length, 1, "has just one item yet");
136
- assert.strictEqual(items[0].id, 1, "id is one");
137
- const timeElapsed = performance.now() - started;
138
- assert(timeElapsed > 200, "enough time elapsed");
139
- assert(timeElapsed < 1000, "less than maxWait");
140
- done();
141
- });
142
-
143
- return;
144
- }
145
- setTimeout(() => {
146
- usersService.debouncedStore.add(2, () => {
147
- callCounter[2]++;
148
- return usersService.create({ id: 2, test: true });
149
- });
150
- counter++;
151
- callTwo();
152
- }, 5);
153
- };
154
- callTwo();
155
- });
156
-
157
- it("cancel works", async function() {
158
- const {
159
- usersService
160
- } = mockApp();
161
- let callCounter = 0;
162
- for (let i = 0; i < 50; i++) {
163
- usersService.debouncedStore.add(1, () => {
164
- callCounter++;
165
- return usersService.create({ id: i, test: true });
166
- });
167
- }
168
- usersService.debouncedStore.cancel(1);
169
- await new Promise(resolve => setTimeout(resolve, 400));
170
- const items = await usersService.find({ query: {}, paginate: false });
171
- assert.strictEqual(items.length, 0, "hasn't items");
172
- assert.strictEqual(callCounter, 0, "not called once");
173
- });
174
- });