directus 9.15.1 → 9.17.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 (107) hide show
  1. package/dist/__utils__/items-utils.d.ts +2 -0
  2. package/dist/__utils__/items-utils.js +36 -0
  3. package/dist/__utils__/schemas.d.ts +13 -0
  4. package/dist/__utils__/schemas.js +304 -0
  5. package/dist/__utils__/snapshots.d.ts +5 -0
  6. package/dist/__utils__/snapshots.js +897 -0
  7. package/dist/app.js +8 -7
  8. package/dist/auth/drivers/ldap.js +1 -0
  9. package/dist/auth/drivers/local.js +6 -0
  10. package/dist/auth/drivers/oauth2.js +1 -0
  11. package/dist/auth/drivers/openid.js +1 -0
  12. package/dist/cli/index.test.d.ts +1 -0
  13. package/dist/cli/index.test.js +58 -0
  14. package/dist/cli/utils/create-env/env-stub.liquid +6 -2
  15. package/dist/controllers/activity.js +1 -0
  16. package/dist/controllers/assets.js +20 -16
  17. package/dist/controllers/auth.js +6 -9
  18. package/dist/controllers/files.test.d.ts +1 -0
  19. package/dist/controllers/files.test.js +49 -0
  20. package/dist/controllers/server.js +0 -1
  21. package/dist/database/migrations/20220826A-add-origin-to-accountability.d.ts +3 -0
  22. package/dist/database/migrations/20220826A-add-origin-to-accountability.js +21 -0
  23. package/dist/database/migrations/run.test.d.ts +1 -0
  24. package/dist/database/migrations/run.test.js +92 -0
  25. package/dist/database/system-data/fields/activity.yaml +6 -0
  26. package/dist/database/system-data/fields/sessions.yaml +2 -0
  27. package/dist/env.js +15 -0
  28. package/dist/env.test.d.ts +8 -0
  29. package/dist/env.test.js +39 -0
  30. package/dist/extensions.d.ts +1 -0
  31. package/dist/extensions.js +16 -3
  32. package/dist/flows.js +28 -17
  33. package/dist/mailer.js +1 -0
  34. package/dist/middleware/authenticate.d.ts +1 -1
  35. package/dist/middleware/authenticate.js +1 -0
  36. package/dist/middleware/authenticate.test.d.ts +1 -0
  37. package/dist/middleware/authenticate.test.js +214 -0
  38. package/dist/middleware/extract-token.test.d.ts +1 -0
  39. package/dist/middleware/extract-token.test.js +60 -0
  40. package/dist/middleware/validate-batch.d.ts +1 -2
  41. package/dist/middleware/validate-batch.js +10 -13
  42. package/dist/middleware/validate-batch.test.d.ts +1 -0
  43. package/dist/middleware/validate-batch.test.js +82 -0
  44. package/dist/operations/exec/index.d.ts +5 -0
  45. package/dist/operations/exec/index.js +26 -0
  46. package/dist/operations/exec/index.test.d.ts +1 -0
  47. package/dist/operations/exec/index.test.js +95 -0
  48. package/dist/operations/notification/index.js +9 -6
  49. package/dist/operations/request/index.js +22 -3
  50. package/dist/operations/transform/index.d.ts +1 -1
  51. package/dist/operations/transform/index.js +1 -1
  52. package/dist/services/authentication.js +13 -3
  53. package/dist/services/files.js +3 -2
  54. package/dist/services/files.test.d.ts +1 -0
  55. package/dist/services/files.test.js +53 -0
  56. package/dist/services/flows.js +4 -0
  57. package/dist/services/graphql/index.d.ts +2 -2
  58. package/dist/services/graphql/index.js +78 -75
  59. package/dist/services/items.js +98 -42
  60. package/dist/services/items.test.d.ts +1 -0
  61. package/dist/services/items.test.js +765 -0
  62. package/dist/services/payload.d.ts +7 -4
  63. package/dist/services/payload.js +63 -12
  64. package/dist/services/payload.test.d.ts +1 -0
  65. package/dist/services/payload.test.js +94 -0
  66. package/dist/services/server.js +10 -7
  67. package/dist/services/shares.js +2 -1
  68. package/dist/services/specifications.test.d.ts +1 -0
  69. package/dist/services/specifications.test.js +96 -0
  70. package/dist/types/items.d.ts +11 -0
  71. package/dist/utils/apply-query.js +7 -3
  72. package/dist/utils/apply-snapshot.js +15 -0
  73. package/dist/utils/apply-snapshot.test.d.ts +1 -0
  74. package/dist/utils/apply-snapshot.test.js +305 -0
  75. package/dist/utils/async-handler.d.ts +2 -6
  76. package/dist/utils/async-handler.js +1 -13
  77. package/dist/utils/async-handler.test.d.ts +1 -0
  78. package/dist/utils/async-handler.test.js +18 -0
  79. package/dist/utils/calculate-field-depth.test.d.ts +1 -0
  80. package/dist/utils/calculate-field-depth.test.js +76 -0
  81. package/dist/utils/filter-items.test.d.ts +1 -0
  82. package/dist/utils/filter-items.test.js +60 -0
  83. package/dist/utils/get-cache-key.test.d.ts +1 -0
  84. package/dist/utils/get-cache-key.test.js +53 -0
  85. package/dist/utils/get-column-path.test.d.ts +1 -0
  86. package/dist/utils/get-column-path.test.js +136 -0
  87. package/dist/utils/get-config-from-env.test.d.ts +1 -0
  88. package/dist/utils/get-config-from-env.test.js +19 -0
  89. package/dist/utils/get-graphql-type.d.ts +1 -1
  90. package/dist/utils/get-graphql-type.js +4 -1
  91. package/dist/utils/get-os-info.d.ts +9 -0
  92. package/dist/utils/get-os-info.js +47 -0
  93. package/dist/utils/get-relation-info.test.d.ts +1 -0
  94. package/dist/utils/get-relation-info.test.js +88 -0
  95. package/dist/utils/get-relation-type.test.d.ts +1 -0
  96. package/dist/utils/get-relation-type.test.js +69 -0
  97. package/dist/utils/get-string-byte-size.test.d.ts +1 -0
  98. package/dist/utils/get-string-byte-size.test.js +8 -0
  99. package/dist/utils/is-directus-jwt.test.d.ts +1 -0
  100. package/dist/utils/is-directus-jwt.test.js +26 -0
  101. package/dist/utils/jwt.test.d.ts +1 -0
  102. package/dist/utils/jwt.test.js +36 -0
  103. package/dist/utils/merge-permissions.test.d.ts +1 -0
  104. package/dist/utils/merge-permissions.test.js +80 -0
  105. package/dist/utils/validate-keys.test.d.ts +1 -0
  106. package/dist/utils/validate-keys.test.js +97 -0
  107. package/package.json +14 -12
@@ -0,0 +1,305 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
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);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const knex_1 = __importDefault(require("knex"));
30
+ const knex_mock_client_1 = require("knex-mock-client");
31
+ const schemas_1 = require("../__utils__/schemas");
32
+ const services_1 = require("../services");
33
+ const apply_snapshot_1 = require("./apply-snapshot");
34
+ const getSchema = __importStar(require("./get-schema"));
35
+ const snapshots_1 = require("../__utils__/snapshots");
36
+ jest.mock('../../src/database/index', () => {
37
+ return {
38
+ getDatabaseClient: jest.fn().mockReturnValue('postgres'),
39
+ };
40
+ });
41
+ jest.requireMock('../../src/database/index');
42
+ class Client_PG extends knex_mock_client_1.MockClient {
43
+ }
44
+ describe('applySnapshot', () => {
45
+ let db;
46
+ let tracker;
47
+ beforeEach(() => {
48
+ db = (0, knex_1.default)({ client: Client_PG });
49
+ tracker = (0, knex_mock_client_1.getTracker)();
50
+ });
51
+ afterEach(() => {
52
+ tracker.reset();
53
+ jest.clearAllMocks();
54
+ });
55
+ describe('Creating new collection(s)', () => {
56
+ it('Creates new top-level collection(s)', async () => {
57
+ const expected = {
58
+ collection: 'test_table_2',
59
+ meta: {
60
+ accountability: 'all',
61
+ collection: 'test_table_2',
62
+ group: null,
63
+ hidden: true,
64
+ icon: 'import_export',
65
+ item_duplication_fields: null,
66
+ note: null,
67
+ singleton: false,
68
+ translations: {},
69
+ },
70
+ schema: { comment: null, name: 'test_table_2', schema: 'public' },
71
+ fields: [
72
+ {
73
+ collection: 'test_table_2',
74
+ field: 'id',
75
+ meta: {
76
+ collection: 'test_table_2',
77
+ conditions: null,
78
+ display: null,
79
+ display_options: null,
80
+ field: 'id',
81
+ group: null,
82
+ hidden: true,
83
+ interface: null,
84
+ note: null,
85
+ options: null,
86
+ readonly: false,
87
+ required: false,
88
+ sort: null,
89
+ special: null,
90
+ translations: {},
91
+ validation: null,
92
+ validation_message: null,
93
+ width: 'full',
94
+ },
95
+ schema: {
96
+ comment: null,
97
+ data_type: 'uuid',
98
+ default_value: null,
99
+ foreign_key_column: null,
100
+ foreign_key_schema: null,
101
+ foreign_key_table: null,
102
+ generation_expression: null,
103
+ has_auto_increment: false,
104
+ is_generated: false,
105
+ is_nullable: false,
106
+ is_primary_key: true,
107
+ is_unique: true,
108
+ max_length: null,
109
+ name: 'id',
110
+ numeric_precision: null,
111
+ numeric_scale: null,
112
+ schema: 'public',
113
+ table: 'test_table_2',
114
+ },
115
+ type: 'uuid',
116
+ },
117
+ ],
118
+ };
119
+ // Stop call to db later on in apply-snapshot
120
+ jest.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(schemas_1.snapshotApplyTestSchema));
121
+ // We are not actually testing that createOne works, just that is is called correctly
122
+ const createOneCollectionSpy = jest
123
+ .spyOn(services_1.CollectionsService.prototype, 'createOne')
124
+ .mockImplementation(jest.fn());
125
+ const createFieldSpy = jest.spyOn(services_1.FieldsService.prototype, 'createField').mockImplementation(jest.fn());
126
+ await (0, apply_snapshot_1.applySnapshot)(snapshots_1.snapshotCreateCollectionNotNested, {
127
+ database: db,
128
+ current: snapshots_1.snapshotBeforeCreateCollection,
129
+ schema: schemas_1.snapshotApplyTestSchema,
130
+ });
131
+ expect(createOneCollectionSpy).toHaveBeenCalledTimes(1);
132
+ expect(createOneCollectionSpy).toHaveBeenCalledWith(expected);
133
+ // There should be no fields left to create
134
+ // they will get filtered in createCollections
135
+ expect(createFieldSpy).toHaveBeenCalledTimes(0);
136
+ });
137
+ it('Creates the highest-level nested collection(s) with existing parents and any children', async () => {
138
+ const expected = {
139
+ collection: 'test_table_2',
140
+ meta: {
141
+ accountability: 'all',
142
+ collection: 'test_table_2',
143
+ group: 'test_table',
144
+ hidden: true,
145
+ icon: 'import_export',
146
+ item_duplication_fields: null,
147
+ note: null,
148
+ singleton: false,
149
+ translations: {},
150
+ },
151
+ schema: { comment: null, name: 'test_table_2', schema: 'public' },
152
+ fields: [
153
+ {
154
+ collection: 'test_table_2',
155
+ field: 'id',
156
+ meta: {
157
+ collection: 'test_table_2',
158
+ conditions: null,
159
+ display: null,
160
+ display_options: null,
161
+ field: 'id',
162
+ group: null,
163
+ hidden: true,
164
+ interface: null,
165
+ note: null,
166
+ options: null,
167
+ readonly: false,
168
+ required: false,
169
+ sort: null,
170
+ special: null,
171
+ translations: {},
172
+ validation: null,
173
+ validation_message: null,
174
+ width: 'full',
175
+ },
176
+ schema: {
177
+ comment: null,
178
+ data_type: 'uuid',
179
+ default_value: null,
180
+ foreign_key_column: null,
181
+ foreign_key_schema: null,
182
+ foreign_key_table: null,
183
+ generation_expression: null,
184
+ has_auto_increment: false,
185
+ is_generated: false,
186
+ is_nullable: false,
187
+ is_primary_key: true,
188
+ is_unique: true,
189
+ max_length: null,
190
+ name: 'id',
191
+ numeric_precision: null,
192
+ numeric_scale: null,
193
+ schema: 'public',
194
+ table: 'test_table_2',
195
+ },
196
+ type: 'uuid',
197
+ },
198
+ ],
199
+ };
200
+ const expected2 = {
201
+ collection: 'test_table_3',
202
+ fields: [
203
+ {
204
+ collection: 'test_table_3',
205
+ field: 'id',
206
+ meta: {
207
+ collection: 'test_table_3',
208
+ conditions: null,
209
+ display: null,
210
+ display_options: null,
211
+ field: 'id',
212
+ group: null,
213
+ hidden: true,
214
+ interface: null,
215
+ note: null,
216
+ options: null,
217
+ readonly: false,
218
+ required: false,
219
+ sort: null,
220
+ special: null,
221
+ translations: {},
222
+ validation: null,
223
+ validation_message: null,
224
+ width: 'full',
225
+ },
226
+ schema: {
227
+ comment: null,
228
+ data_type: 'uuid',
229
+ default_value: null,
230
+ foreign_key_column: null,
231
+ foreign_key_schema: null,
232
+ foreign_key_table: null,
233
+ generation_expression: null,
234
+ has_auto_increment: false,
235
+ is_generated: false,
236
+ is_nullable: false,
237
+ is_primary_key: true,
238
+ is_unique: true,
239
+ max_length: null,
240
+ name: 'id',
241
+ numeric_precision: null,
242
+ numeric_scale: null,
243
+ schema: 'public',
244
+ table: 'test_table_3',
245
+ },
246
+ type: 'uuid',
247
+ },
248
+ ],
249
+ meta: {
250
+ accountability: 'all',
251
+ collection: 'test_table_3',
252
+ group: 'test_table_2',
253
+ hidden: true,
254
+ icon: 'import_export',
255
+ item_duplication_fields: null,
256
+ note: null,
257
+ singleton: false,
258
+ translations: {},
259
+ },
260
+ schema: { comment: null, name: 'test_table_3', schema: 'public' },
261
+ };
262
+ // Stop call to db later on in apply-snapshot
263
+ jest.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(schemas_1.snapshotApplyTestSchema));
264
+ // We are not actually testing that createOne works, just that is is called correctly
265
+ const createOneCollectionSpy = jest
266
+ .spyOn(services_1.CollectionsService.prototype, 'createOne')
267
+ .mockImplementation(jest.fn());
268
+ const createFieldSpy = jest.spyOn(services_1.FieldsService.prototype, 'createField').mockImplementation(jest.fn());
269
+ await (0, apply_snapshot_1.applySnapshot)(snapshots_1.snapshotCreateCollection, {
270
+ database: db,
271
+ current: snapshots_1.snapshotBeforeCreateCollection,
272
+ schema: schemas_1.snapshotApplyTestSchema,
273
+ });
274
+ expect(createOneCollectionSpy).toHaveBeenCalledTimes(2);
275
+ expect(createOneCollectionSpy).toHaveBeenCalledWith(expected);
276
+ expect(createOneCollectionSpy).toHaveBeenCalledWith(expected2);
277
+ // There should be no fields left to create
278
+ // they will get filtered in createCollections
279
+ expect(createFieldSpy).toHaveBeenCalledTimes(0);
280
+ });
281
+ });
282
+ describe('Delete collections', () => {
283
+ it('Deletes interrelated collections', async () => {
284
+ const snapshotToApply = {
285
+ version: 1,
286
+ directus: '0.0.0',
287
+ collections: [],
288
+ fields: [],
289
+ relations: [],
290
+ };
291
+ // Stop call to db later on in apply-snapshot
292
+ jest.spyOn(getSchema, 'getSchema').mockReturnValue(Promise.resolve(schemas_1.snapshotApplyTestSchema));
293
+ // We are not actually testing that deleteOne works, just that is is called correctly
294
+ const deleteOneCollectionSpy = jest
295
+ .spyOn(services_1.CollectionsService.prototype, 'deleteOne')
296
+ .mockImplementation(jest.fn());
297
+ await (0, apply_snapshot_1.applySnapshot)(snapshotToApply, {
298
+ database: db,
299
+ current: snapshots_1.snapshotBeforeDeleteCollection,
300
+ schema: schemas_1.snapshotApplyTestSchema,
301
+ });
302
+ expect(deleteOneCollectionSpy).toHaveBeenCalledTimes(3);
303
+ });
304
+ });
305
+ });
@@ -1,7 +1,3 @@
1
- import { ErrorRequestHandler, RequestHandler } from 'express';
2
- /**
3
- * Handles promises in routes.
4
- */
5
- declare function asyncHandler(handler: RequestHandler): RequestHandler;
6
- declare function asyncHandler(handler: ErrorRequestHandler): ErrorRequestHandler;
1
+ import type { RequestHandler, Request, Response, NextFunction } from 'express';
2
+ declare const asyncHandler: (fn: RequestHandler) => (req: Request, res: Response, next: NextFunction) => Promise<void>;
7
3
  export default asyncHandler;
@@ -1,16 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- function asyncHandler(handler) {
4
- if (handler.length === 2 || handler.length === 3) {
5
- const scoped = (req, res, next) => Promise.resolve(handler(req, res, next)).catch(next);
6
- return scoped;
7
- }
8
- else if (handler.length === 4) {
9
- const scoped = (err, req, res, next) => Promise.resolve(handler(err, req, res, next)).catch(next);
10
- return scoped;
11
- }
12
- else {
13
- throw new Error(`Failed to asyncHandle() function "${handler.name}"`);
14
- }
15
- }
3
+ const asyncHandler = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
16
4
  exports.default = asyncHandler;
@@ -0,0 +1 @@
1
+ import '../../src/types/express.d.ts';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ require("../../src/types/express.d.ts");
7
+ const async_handler_1 = __importDefault(require("./async-handler"));
8
+ let mockRequest;
9
+ let mockResponse;
10
+ const nextFunction = jest.fn();
11
+ test('Wraps async middleware in Promise resolve that will catch rejects and pass them to the nextFn', async () => {
12
+ const err = new Error('testing');
13
+ const middleware = async (_req, _res, _next) => {
14
+ throw err;
15
+ };
16
+ await (0, async_handler_1.default)(middleware)(mockRequest, mockResponse, nextFunction);
17
+ expect(nextFunction).toHaveBeenCalledWith(err);
18
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const calculate_field_depth_1 = require("../../src/utils/calculate-field-depth");
4
+ test('Calculates basic depth', () => {
5
+ const filter = {
6
+ name: {
7
+ _eq: 'test',
8
+ },
9
+ };
10
+ const result = (0, calculate_field_depth_1.calculateFieldDepth)(filter);
11
+ expect(result).toBe(1);
12
+ });
13
+ test('Calculates relational depth', () => {
14
+ const filter = {
15
+ author: {
16
+ name: {
17
+ _eq: 'test',
18
+ },
19
+ },
20
+ };
21
+ const result = (0, calculate_field_depth_1.calculateFieldDepth)(filter);
22
+ expect(result).toBe(2);
23
+ });
24
+ test('Ignores _and/_or', () => {
25
+ const filter = {
26
+ _and: [
27
+ {
28
+ _or: [
29
+ {
30
+ author: {
31
+ name: {
32
+ _eq: 'Directus',
33
+ },
34
+ },
35
+ },
36
+ {
37
+ status: {
38
+ _eq: 'published',
39
+ },
40
+ },
41
+ ],
42
+ },
43
+ {
44
+ category: {
45
+ _eq: 'recipes',
46
+ },
47
+ },
48
+ ],
49
+ };
50
+ const result = (0, calculate_field_depth_1.calculateFieldDepth)(filter);
51
+ expect(result).toBe(2);
52
+ });
53
+ test('Skips underscore prefix in tree', () => {
54
+ const deep = {
55
+ translations: {
56
+ _filter: {
57
+ language_id: {
58
+ code: {
59
+ _eq: 'nl-NL',
60
+ },
61
+ },
62
+ },
63
+ },
64
+ };
65
+ const result = (0, calculate_field_depth_1.calculateFieldDepth)(deep);
66
+ expect(result).toBe(3);
67
+ });
68
+ test('Calculates _sort in deep correctly', () => {
69
+ const deep = {
70
+ articles: {
71
+ _sort: ['sort', 'category.type.sort'],
72
+ },
73
+ };
74
+ const result = (0, calculate_field_depth_1.calculateFieldDepth)(deep, ['_sort']);
75
+ expect(result).toBe(4);
76
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const filter_items_1 = require("../../src/utils/filter-items");
4
+ const items = [
5
+ {
6
+ role: '9bc9fea0-f761-4107-bfb7-b3d06c125e98',
7
+ permissions: {},
8
+ validation: null,
9
+ presets: null,
10
+ fields: ['*'],
11
+ system: true,
12
+ collection: 'directus_settings',
13
+ action: 'read',
14
+ },
15
+ {
16
+ role: '9bc9fea0-f761-4107-bfb7-b3d06c125e98',
17
+ permissions: {
18
+ user: {
19
+ _eq: '$CURRENT_USER',
20
+ },
21
+ },
22
+ validation: null,
23
+ presets: null,
24
+ fields: ['*'],
25
+ system: true,
26
+ collection: 'directus_presets',
27
+ action: 'delete',
28
+ },
29
+ ];
30
+ describe('filter items', () => {
31
+ test('return items when no filter', () => {
32
+ const result = (0, filter_items_1.filterItems)(items, undefined);
33
+ expect(result).toStrictEqual(items);
34
+ });
35
+ test('return items when empty filter used', () => {
36
+ const result = (0, filter_items_1.filterItems)(items, {});
37
+ expect(result).toStrictEqual(items);
38
+ });
39
+ test('return filtered items when nested empty filter used', () => {
40
+ const result = (0, filter_items_1.filterItems)(items, {
41
+ _and: [
42
+ {
43
+ action: {
44
+ _eq: 'read',
45
+ },
46
+ },
47
+ {},
48
+ ],
49
+ });
50
+ expect(result).toStrictEqual(items.filter((item) => item.action === 'read'));
51
+ });
52
+ test('return filtered items', () => {
53
+ const result = (0, filter_items_1.filterItems)(items, {
54
+ action: {
55
+ _eq: 'read',
56
+ },
57
+ });
58
+ expect(result).toStrictEqual(items.filter((item) => item.action === 'read'));
59
+ });
60
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const get_cache_key_1 = require("../../src/utils/get-cache-key");
4
+ const restUrl = 'http://localhost/items/example';
5
+ const graphQlUrl = 'http://localhost/graphql';
6
+ const accountability = { user: '00000000-0000-0000-0000-000000000000' };
7
+ const requests = [
8
+ {
9
+ name: 'as unauthenticated request',
10
+ params: { originalUrl: restUrl },
11
+ key: '17da8272c9a0ec6eea38a37d6d78bddeb7c79045',
12
+ },
13
+ {
14
+ name: 'as authenticated request',
15
+ params: { originalUrl: restUrl, accountability },
16
+ key: '99a6394222a3d7d149ac1662fc2fff506932db58',
17
+ },
18
+ {
19
+ name: 'a request with a fields query',
20
+ params: { originalUrl: restUrl, sanitizedQuery: { fields: ['id', 'name'] } },
21
+ key: 'aa6e2d8a78de4dfb4af6eaa230d1cd9b7d31ed19',
22
+ },
23
+ {
24
+ name: 'a request with a filter query',
25
+ params: { originalUrl: restUrl, sanitizedQuery: { filter: { name: { _eq: 'test' } } } },
26
+ key: 'd7eb8970f0429e1cf85e12eb5bb8669f618b09d3',
27
+ },
28
+ {
29
+ name: 'a GraphQL query request',
30
+ params: { originalUrl: graphQlUrl, query: { query: 'query { test { id } }' } },
31
+ key: '201731b75c627c60554512d819b6935b54c73814',
32
+ },
33
+ ];
34
+ const cases = requests.map(({ name, params, key }) => [name, params, key]);
35
+ describe('get cache key', () => {
36
+ test.each(cases)('should create a cache key for %s', (_, params, key) => {
37
+ expect((0, get_cache_key_1.getCacheKey)(params)).toEqual(key);
38
+ });
39
+ test('should create a unique key for each request', () => {
40
+ const keys = requests.map((r) => r.key);
41
+ const hasDuplicate = keys.some((key) => keys.indexOf(key) !== keys.lastIndexOf(key));
42
+ expect(hasDuplicate).toBeFalsy();
43
+ });
44
+ test('should create a unique key for GraphQL requests with different variables', () => {
45
+ const query = 'query Test ($name: String) { test (filter: { name: { _eq: $name } }) { id } }';
46
+ const operationName = 'test';
47
+ const variables1 = JSON.stringify({ name: 'test 1' });
48
+ const variables2 = JSON.stringify({ name: 'test 2' });
49
+ const req1 = { originalUrl: graphQlUrl, query: { query, operationName, variables: variables1 } };
50
+ const req2 = { originalUrl: graphQlUrl, query: { query, operationName, variables: variables2 } };
51
+ expect((0, get_cache_key_1.getCacheKey)(req1)).not.toEqual((0, get_cache_key_1.getCacheKey)(req2));
52
+ });
53
+ });
@@ -0,0 +1 @@
1
+ export {};