mock-config-server 3.2.0 → 3.3.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 +153 -3
- package/dist/bin/validateMockServerConfig/helpers/isDescriptorValueValid/isDescriptorValueValid.d.ts +2 -1
- package/dist/bin/validateMockServerConfig/helpers/isDescriptorValueValid/isDescriptorValueValid.js +30 -7
- package/dist/bin/validateMockServerConfig/validateGraphqlConfig/validateGraphqlConfig.js +9 -3
- package/dist/bin/validateMockServerConfig/validateGraphqlConfig/validateRoutes/validateRoutes.js +67 -18
- package/dist/bin/validateMockServerConfig/validateQueue/validateQueue.d.ts +1 -0
- package/dist/bin/validateMockServerConfig/validateQueue/validateQueue.js +29 -0
- package/dist/bin/validateMockServerConfig/validateRestConfig/validateRoutes/validateRoutes.js +67 -18
- package/dist/bin/validateMockServerConfig/validateSettings/validateSettings.d.ts +1 -0
- package/dist/bin/validateMockServerConfig/validateSettings/validateSettings.js +34 -0
- package/dist/src/core/database/createDatabaseRoutes/helpers/createNestedDatabaseRoutes/createNestedDatabaseRoutes.js +45 -2
- package/dist/src/core/database/createDatabaseRoutes/helpers/filter/filter.d.ts +2 -1
- package/dist/src/core/database/createDatabaseRoutes/helpers/pagination/pagination.d.ts +13 -0
- package/dist/src/core/database/createDatabaseRoutes/helpers/pagination/pagination.js +36 -0
- package/dist/src/core/database/createDatabaseRoutes/helpers/sort/sort.d.ts +2 -0
- package/dist/src/core/database/createDatabaseRoutes/helpers/sort/sort.js +42 -0
- package/dist/src/core/graphql/createGraphQLRoutes/createGraphQLRoutes.d.ts +7 -1
- package/dist/src/core/graphql/createGraphQLRoutes/createGraphQLRoutes.js +65 -24
- package/dist/src/core/middlewares/notFoundMiddleware/notFoundMiddleware.js +1 -3
- package/dist/src/core/middlewares/requestInterceptorMiddleware/requestInterceptorMiddleware.d.ts +7 -1
- package/dist/src/core/middlewares/requestInterceptorMiddleware/requestInterceptorMiddleware.js +6 -2
- package/dist/src/core/rest/createRestRoutes/createRestRoutes.d.ts +7 -1
- package/dist/src/core/rest/createRestRoutes/createRestRoutes.js +55 -12
- package/dist/src/server/createDatabaseMockServer/createDatabaseMockServer.js +4 -1
- package/dist/src/server/createGraphQLMockServer/createGraphQLMockServer.js +11 -4
- package/dist/src/server/createMockServer/createMockServer.js +28 -9
- package/dist/src/server/createRestMockServer/createRestMockServer.js +11 -4
- package/dist/src/server/index.d.ts +3 -3
- package/dist/src/server/index.js +23 -23
- package/dist/src/static/views/components/header/index.js +1 -1
- package/dist/src/static/views/features/scheme/index.js +31 -31
- package/dist/src/static/views/features/tab/index.js +12 -12
- package/dist/src/utils/helpers/entities/isEntityDescriptor/isEntityDescriptor.d.ts +2 -1
- package/dist/src/utils/helpers/graphql/getGraphQLInput/getGraphQLInput.d.ts +7 -2
- package/dist/src/utils/helpers/graphql/getGraphQLInput/getGraphQLInput.js +6 -4
- package/dist/src/utils/helpers/graphql/parseQuery/parseQuery.d.ts +1 -1
- package/dist/src/utils/helpers/graphql/parseQuery/parseQuery.js +1 -1
- package/dist/src/utils/helpers/interceptors/callResponseInterceptors/callResponseInterceptors.js +19 -10
- package/dist/src/utils/types/graphql.d.ts +60 -51
- package/dist/src/utils/types/index.d.ts +1 -0
- package/dist/src/utils/types/index.js +11 -0
- package/dist/src/utils/types/interceptors.d.ts +1 -1
- package/dist/src/utils/types/rest.d.ts +47 -40
- package/dist/src/utils/types/utils.d.ts +8 -0
- package/dist/src/utils/types/utils.js +1 -0
- package/dist/src/utils/types/values.d.ts +0 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ $ npx mock-config-server
|
|
|
73
73
|
- `baseUrl?` {string} part of the url that will be substituted at the beginning of graphql request url (default: `'/'`)
|
|
74
74
|
- `configs` {Array<GraphQLRequestConfig>} configs for mock requests, [read](#configs)
|
|
75
75
|
- `interceptors?` {Interceptors} functions to change request or response parameters, [read](#interceptors)
|
|
76
|
-
- `database?` Database config for mock requests [read](#
|
|
76
|
+
- `database?` Database config for mock requests [read](#database)
|
|
77
77
|
- `data` {Object | string} initial data for database
|
|
78
78
|
- `routes?` {Object | string} map of custom routes for database
|
|
79
79
|
- `staticPath?` {StaticPath} entity for working with static files, [read](#static-path)
|
|
@@ -99,13 +99,16 @@ Configs are the fundamental part of the mock server. These configs are easy to f
|
|
|
99
99
|
##### GraphQL request config
|
|
100
100
|
|
|
101
101
|
- `operationType` {query | mutation} graphql operation type
|
|
102
|
-
- `operationName
|
|
102
|
+
- `operationName?` {string | RegExp} graphql operation name
|
|
103
|
+
- `query?`: {string} graphql query as string
|
|
103
104
|
- `routes` {GraphQLRouteConfig[]} request routes
|
|
104
105
|
- `data` {any} mock data of request
|
|
105
106
|
- `entities?` Object<headers | cookies | query | variables> object that helps in data retrieval
|
|
106
107
|
- `interceptors?` {Interceptors} functions to change request or response parameters, [read](#interceptors)
|
|
107
108
|
- `interceptors?` {Interceptors} functions to change request or response parameters, [read](#interceptors)
|
|
108
109
|
|
|
110
|
+
> Every graphql config should contain `operationName` or `query` or both of them
|
|
111
|
+
|
|
109
112
|
##### Rest example
|
|
110
113
|
|
|
111
114
|
```javascript
|
|
@@ -270,6 +273,35 @@ const mockServerConfig = {
|
|
|
270
273
|
module.exports = mockServerConfig;
|
|
271
274
|
```
|
|
272
275
|
|
|
276
|
+
Also you can use array as value for REST body and GraphQL variables entities: in this case mock-config-server will iterate
|
|
277
|
+
over array until `checkMode=equals` finds a match or return 404
|
|
278
|
+
|
|
279
|
+
```javascript
|
|
280
|
+
/** @type {import('mock-config-server').MockServerConfig} */
|
|
281
|
+
const mockServerConfig = {
|
|
282
|
+
rest: {
|
|
283
|
+
baseUrl: '/api',
|
|
284
|
+
configs: [
|
|
285
|
+
{
|
|
286
|
+
path: '/user',
|
|
287
|
+
method: 'post',
|
|
288
|
+
routes: [
|
|
289
|
+
{
|
|
290
|
+
entities: {
|
|
291
|
+
// if body equals to { key1: 'value1' } or ['value1'] then mock-config-server return data
|
|
292
|
+
body: [{ key1: 'value1' }, ['value1']]
|
|
293
|
+
},
|
|
294
|
+
data: 'Some user data'
|
|
295
|
+
}
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
module.exports = mockServerConfig;
|
|
303
|
+
```
|
|
304
|
+
|
|
273
305
|
`function checkMode` is the most powerful way to describe your `entities` logic, but in most cases you will be fine using other `checkModes`.
|
|
274
306
|
|
|
275
307
|
`Function value` has the following signature `(actualValue, checkFunction) => boolean`.
|
|
@@ -381,6 +413,66 @@ const mockServerConfig = {
|
|
|
381
413
|
module.exports = mockServerConfig;
|
|
382
414
|
```
|
|
383
415
|
|
|
416
|
+
#### Polling
|
|
417
|
+
|
|
418
|
+
Routes support polling for data. To add polling for data, you must specify the `polling setting` and change `data` property to `queue`.
|
|
419
|
+
|
|
420
|
+
> After receiving the last value from polling, the queue is reset and the next request will return the first value from the queue.
|
|
421
|
+
|
|
422
|
+
```javascript
|
|
423
|
+
/** @type {import('mock-config-server').MockServerConfig} */
|
|
424
|
+
const mockServerConfig = {
|
|
425
|
+
rest: {
|
|
426
|
+
baseUrl: '/api',
|
|
427
|
+
configs: [
|
|
428
|
+
{
|
|
429
|
+
path: '/user',
|
|
430
|
+
method: 'get',
|
|
431
|
+
routes: [
|
|
432
|
+
{
|
|
433
|
+
settings: { polling: true },
|
|
434
|
+
queue: [
|
|
435
|
+
{ data: { emoji: '🦁', name: 'Nursultan' } },
|
|
436
|
+
{ data: { emoji: '☄', name: 'Dmitriy' } }
|
|
437
|
+
]
|
|
438
|
+
}
|
|
439
|
+
]
|
|
440
|
+
}
|
|
441
|
+
]
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
export default mockServerConfig;
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
Using the additional `time` properties in milliseconds, you can specify how much time certain data should be returned
|
|
449
|
+
|
|
450
|
+
```javascript
|
|
451
|
+
/** @type {import('mock-config-server').MockServerConfig} */
|
|
452
|
+
const mockServerConfig = {
|
|
453
|
+
rest: {
|
|
454
|
+
baseUrl: '/api',
|
|
455
|
+
configs: [
|
|
456
|
+
{
|
|
457
|
+
path: '/user',
|
|
458
|
+
method: 'get',
|
|
459
|
+
routes: [
|
|
460
|
+
{
|
|
461
|
+
settings: { polling: true },
|
|
462
|
+
queue: [
|
|
463
|
+
{ time: 5000, data: { emoji: '🦁', name: 'Nursultan' } },
|
|
464
|
+
{ data: { emoji: '☄', name: 'Dmitriy' } }
|
|
465
|
+
]
|
|
466
|
+
}
|
|
467
|
+
]
|
|
468
|
+
}
|
|
469
|
+
]
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
export default mockServerConfig;
|
|
474
|
+
```
|
|
475
|
+
|
|
384
476
|
#### Static Path
|
|
385
477
|
|
|
386
478
|
Entity for connecting statics to the server, like HTML, JSON, PNG, etc.
|
|
@@ -547,6 +639,64 @@ GET /users?id=1&id=2
|
|
|
547
639
|
GET /users?author.name=siberiacancode
|
|
548
640
|
```
|
|
549
641
|
|
|
642
|
+
### Pagination
|
|
643
|
+
|
|
644
|
+
> Use \_page and optionally \_limit to paginate returned data.
|
|
645
|
+
|
|
646
|
+
```
|
|
647
|
+
GET /users?_page=1
|
|
648
|
+
GET /users?_page=1&_limit=5
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
> **\_limit** is 10 by default
|
|
652
|
+
|
|
653
|
+
The returned data has the format:
|
|
654
|
+
|
|
655
|
+
```
|
|
656
|
+
{
|
|
657
|
+
_link: Link,
|
|
658
|
+
results: Data[]
|
|
659
|
+
}
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
In the **Link** header you'll get **count**, **pages**, **next** and **prev** links.
|
|
663
|
+
|
|
664
|
+
#### Link
|
|
665
|
+
|
|
666
|
+
- `count` {number} total count of elements
|
|
667
|
+
- `pages` {number} count of pages
|
|
668
|
+
- `next` {string | null} query string for next link
|
|
669
|
+
- `prev` {string | null} query string for prev link
|
|
670
|
+
|
|
671
|
+
### Sort
|
|
672
|
+
|
|
673
|
+
> Use \_sort and \_order, use . to access deep properties
|
|
674
|
+
|
|
675
|
+
```
|
|
676
|
+
GET /users?_sort=name
|
|
677
|
+
GET /users/1/transfers?_sort=id&_order=asc
|
|
678
|
+
GET /users?_sort=address.city&_order=desc
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
> **\_order** is 'asc' by default
|
|
682
|
+
|
|
683
|
+
For multiple fields:
|
|
684
|
+
|
|
685
|
+
```
|
|
686
|
+
GET /users?_sort=id&_order=desc&_sort=name&_order=asc
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
### Slice
|
|
690
|
+
|
|
691
|
+
> X-Total-Count header is included in the response
|
|
692
|
+
|
|
693
|
+
```
|
|
694
|
+
GET /users?_begin=20
|
|
695
|
+
GET /users?_begin=20&_end=30
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
Works exactly as [slice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice), \_begin and \_end are optional
|
|
699
|
+
|
|
550
700
|
### File example
|
|
551
701
|
|
|
552
702
|
```javascript
|
|
@@ -601,7 +751,7 @@ Examples:
|
|
|
601
751
|
<br />
|
|
602
752
|
<sub style="font-size:13px"><b>👹 MiaInturi</b></sub>
|
|
603
753
|
</a>
|
|
604
|
-
</td>
|
|
754
|
+
</td>
|
|
605
755
|
<td align="center" style="word-wrap: break-word; width: 100.0; height: 100.0">
|
|
606
756
|
<a href="https://github.com/RiceWithMeat">
|
|
607
757
|
<img src="https://avatars.githubusercontent.com/u/47690223?v=4"
|
package/dist/bin/validateMockServerConfig/helpers/isDescriptorValueValid/isDescriptorValueValid.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { CheckMode } from '../../../../src/utils/types';
|
|
2
|
+
export declare const isDescriptorValueValid: (checkMode: CheckMode, value: unknown) => boolean | undefined;
|
package/dist/bin/validateMockServerConfig/helpers/isDescriptorValueValid/isDescriptorValueValid.js
CHANGED
|
@@ -5,16 +5,39 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.isDescriptorValueValid = void 0;
|
|
7
7
|
var _constants = require("../../../../src/utils/constants");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
var _helpers = require("../../../../src/utils/helpers");
|
|
9
|
+
// ✅ important:
|
|
10
|
+
// should validate all properties over nesting
|
|
11
|
+
const isObjectOrArrayValid = value => {
|
|
12
|
+
if (typeof value === 'boolean' || typeof value === 'number' || typeof value === 'string' || value === null) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(value)) {
|
|
16
|
+
return value.every(isObjectOrArrayValid);
|
|
17
|
+
}
|
|
18
|
+
if ((0, _helpers.isPlainObject)(value)) {
|
|
19
|
+
for (const key in value) {
|
|
20
|
+
if (!isObjectOrArrayValid(value[key])) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
13
23
|
}
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
};
|
|
28
|
+
const isDescriptorValueValid = (checkMode, value) => {
|
|
29
|
+
if (_constants.CHECK_ACTUAL_VALUE_CHECK_MODES.includes(checkMode)) {
|
|
30
|
+
return typeof value === 'undefined';
|
|
31
|
+
}
|
|
32
|
+
if (_constants.COMPARE_WITH_DESCRIPTOR_ANY_VALUE_CHECK_MODES.includes(checkMode)) {
|
|
33
|
+
const isValueObjectOrArray = (0, _helpers.isPlainObject)(value) || Array.isArray(value);
|
|
34
|
+
if (isValueObjectOrArray) return isObjectOrArrayValid(value);
|
|
35
|
+
return typeof value === 'boolean' || typeof value === 'number' || typeof value === 'string' || value === null;
|
|
36
|
+
}
|
|
37
|
+
if (_constants.COMPARE_WITH_DESCRIPTOR_STRING_VALUE_CHECK_MODES.includes(checkMode)) {
|
|
14
38
|
return typeof value === 'boolean' || typeof value === 'number' || typeof value === 'string';
|
|
15
39
|
}
|
|
16
|
-
if (checkMode === 'function') return typeof value === 'function';
|
|
40
|
+
if (checkMode === 'function') return typeof value === 'function' && value.length <= 2;
|
|
17
41
|
if (checkMode === 'regExp') return value instanceof RegExp;
|
|
18
|
-
throw new Error('Invalid checkMode');
|
|
19
42
|
};
|
|
20
43
|
exports.isDescriptorValueValid = isDescriptorValueValid;
|
|
@@ -14,15 +14,21 @@ const validateConfigs = configs => {
|
|
|
14
14
|
configs.forEach((config, index) => {
|
|
15
15
|
const {
|
|
16
16
|
operationType,
|
|
17
|
-
operationName
|
|
17
|
+
operationName,
|
|
18
|
+
query
|
|
18
19
|
} = config;
|
|
20
|
+
if (typeof operationName === 'undefined' && typeof query === 'undefined') {
|
|
21
|
+
throw new Error(`configs[${index}]`);
|
|
22
|
+
}
|
|
19
23
|
if (operationType !== 'query' && operationType !== 'mutation') {
|
|
20
24
|
throw new Error(`configs[${index}].operationType`);
|
|
21
25
|
}
|
|
22
|
-
|
|
23
|
-
if (!isOperationNameStringOrRegExp) {
|
|
26
|
+
if (typeof operationName !== 'undefined' && typeof operationName !== 'string' && !(operationName instanceof RegExp)) {
|
|
24
27
|
throw new Error(`configs[${index}].operationName`);
|
|
25
28
|
}
|
|
29
|
+
if (typeof query !== 'undefined' && typeof query !== 'string') {
|
|
30
|
+
throw new Error(`configs[${index}].query`);
|
|
31
|
+
}
|
|
26
32
|
try {
|
|
27
33
|
(0, _validateRoutes.validateRoutes)(config.routes, operationType);
|
|
28
34
|
(0, _validateInterceptors.validateInterceptors)(config.interceptors);
|
package/dist/bin/validateMockServerConfig/validateGraphqlConfig/validateRoutes/validateRoutes.js
CHANGED
|
@@ -7,30 +7,44 @@ exports.validateRoutes = void 0;
|
|
|
7
7
|
var _helpers = require("../../../../src/utils/helpers");
|
|
8
8
|
var _helpers2 = require("../../helpers");
|
|
9
9
|
var _validateInterceptors = require("../../validateInterceptors/validateInterceptors");
|
|
10
|
+
var _validateQueue = require("../../validateQueue/validateQueue");
|
|
11
|
+
var _validateSettings = require("../../validateSettings/validateSettings");
|
|
10
12
|
const ALLOWED_ENTITIES_BY_OPERATION_TYPE = {
|
|
11
13
|
query: ['headers', 'cookies', 'query', 'variables'],
|
|
12
14
|
mutation: ['headers', 'cookies', 'query', 'variables']
|
|
13
15
|
};
|
|
14
16
|
const validateEntity = (entity, entityName) => {
|
|
15
|
-
const {
|
|
16
|
-
checkMode: topLevelCheckMode,
|
|
17
|
-
value: topLevelValue
|
|
18
|
-
} = (0, _helpers.convertToEntityDescriptor)(entity);
|
|
19
17
|
const isVariables = entityName === 'variables';
|
|
20
|
-
const
|
|
21
|
-
if (
|
|
22
|
-
if (!
|
|
18
|
+
const isEntityTopLevelDescriptor = (0, _helpers.isEntityDescriptor)(entity);
|
|
19
|
+
if (isEntityTopLevelDescriptor) {
|
|
20
|
+
if (!isVariables) {
|
|
21
|
+
throw new Error(entityName);
|
|
22
|
+
}
|
|
23
|
+
if (!(0, _helpers2.isCheckModeValid)(entity.checkMode, 'variables')) {
|
|
23
24
|
throw new Error('variables.checkMode');
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
throw new Error(
|
|
26
|
+
const isDescriptorValueObjectOrArray = (0, _helpers.isPlainObject)(entity.value) || Array.isArray(entity.value);
|
|
27
|
+
if (!isDescriptorValueObjectOrArray || !(0, _helpers2.isDescriptorValueValid)(entity.checkMode, entity.value)) {
|
|
28
|
+
throw new Error('variables.value');
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const isEntityArray = Array.isArray(entity);
|
|
33
|
+
if (isEntityArray) {
|
|
34
|
+
if (!isVariables) {
|
|
35
|
+
throw new Error(entityName);
|
|
28
36
|
}
|
|
37
|
+
entity.forEach((entityElement, index) => {
|
|
38
|
+
const isEntityElementObjectOrArray = (0, _helpers.isPlainObject)(entityElement) || Array.isArray(entityElement);
|
|
39
|
+
if (!isEntityElementObjectOrArray || !(0, _helpers2.isDescriptorValueValid)('equals', entityElement)) {
|
|
40
|
+
throw new Error(`${entityName}[${index}]`);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return;
|
|
29
44
|
}
|
|
30
|
-
const isEntityObject = (0, _helpers.isPlainObject)(entity)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
Object.entries(topLevelValue).forEach(([key, valueOrDescriptor]) => {
|
|
45
|
+
const isEntityObject = (0, _helpers.isPlainObject)(entity);
|
|
46
|
+
if (isEntityObject) {
|
|
47
|
+
Object.entries(entity).forEach(([key, valueOrDescriptor]) => {
|
|
34
48
|
const {
|
|
35
49
|
checkMode,
|
|
36
50
|
value
|
|
@@ -41,15 +55,25 @@ const validateEntity = (entity, entityName) => {
|
|
|
41
55
|
const isDescriptor = (0, _helpers.isEntityDescriptor)(valueOrDescriptor);
|
|
42
56
|
const errorMessage = `${entityName}.${key}${isDescriptor ? '.value' : ''}`;
|
|
43
57
|
const isValueArray = Array.isArray(value);
|
|
44
|
-
if (isValueArray
|
|
58
|
+
if (isValueArray) {
|
|
45
59
|
value.forEach((element, index) => {
|
|
46
|
-
if (
|
|
60
|
+
if (isVariables) {
|
|
61
|
+
if ((0, _helpers2.isDescriptorValueValid)(checkMode, element)) return;
|
|
62
|
+
throw new Error(`${errorMessage}[${index}]`);
|
|
63
|
+
}
|
|
64
|
+
const isElementObjectOrArray = (0, _helpers.isPlainObject)(element) || Array.isArray(element);
|
|
65
|
+
if (isElementObjectOrArray || !(0, _helpers2.isDescriptorValueValid)(checkMode, element)) {
|
|
47
66
|
throw new Error(`${errorMessage}[${index}]`);
|
|
48
67
|
}
|
|
49
68
|
});
|
|
50
69
|
return;
|
|
51
70
|
}
|
|
52
|
-
if (
|
|
71
|
+
if (isVariables) {
|
|
72
|
+
if ((0, _helpers2.isDescriptorValueValid)(checkMode, value)) return;
|
|
73
|
+
throw new Error(errorMessage);
|
|
74
|
+
}
|
|
75
|
+
const isValueObject = (0, _helpers.isPlainObject)(value);
|
|
76
|
+
if (isValueObject || !(0, _helpers2.isDescriptorValueValid)(checkMode, value)) {
|
|
53
77
|
throw new Error(errorMessage);
|
|
54
78
|
}
|
|
55
79
|
});
|
|
@@ -84,10 +108,35 @@ const validateRoutes = (routes, operationType) => {
|
|
|
84
108
|
const isRouteObject = (0, _helpers.isPlainObject)(route);
|
|
85
109
|
if (isRouteObject) {
|
|
86
110
|
const isRouteHasDataProperty = ('data' in route);
|
|
87
|
-
|
|
111
|
+
const isRouteHasQueueProperty = ('queue' in route);
|
|
112
|
+
if (!isRouteHasDataProperty && !isRouteHasQueueProperty) {
|
|
113
|
+
throw new Error(`routes[${index}]`);
|
|
114
|
+
}
|
|
115
|
+
if (isRouteHasDataProperty && isRouteHasQueueProperty) {
|
|
88
116
|
throw new Error(`routes[${index}]`);
|
|
89
117
|
}
|
|
118
|
+
const {
|
|
119
|
+
settings
|
|
120
|
+
} = route;
|
|
121
|
+
const isRouteSettingsObject = (0, _helpers.isPlainObject)(settings);
|
|
122
|
+
if (isRouteHasQueueProperty) {
|
|
123
|
+
try {
|
|
124
|
+
(0, _validateQueue.validateQueue)(route.queue);
|
|
125
|
+
if (!isRouteSettingsObject) {
|
|
126
|
+
throw new Error('settings');
|
|
127
|
+
}
|
|
128
|
+
if (!(isRouteSettingsObject && settings !== null && settings !== void 0 && settings.polling)) {
|
|
129
|
+
throw new Error('settings.polling');
|
|
130
|
+
}
|
|
131
|
+
} catch (error) {
|
|
132
|
+
throw new Error(`routes[${index}].${error.message}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (isRouteHasDataProperty && isRouteSettingsObject && settings !== null && settings !== void 0 && settings.polling) {
|
|
136
|
+
throw new Error(`routes[${index}].settings.polling`);
|
|
137
|
+
}
|
|
90
138
|
try {
|
|
139
|
+
(0, _validateSettings.validateSettings)(route.settings);
|
|
91
140
|
validateEntities(route.entities, operationType);
|
|
92
141
|
(0, _validateInterceptors.validateInterceptors)(route.interceptors);
|
|
93
142
|
} catch (error) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const validateQueue: (queue: unknown) => void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.validateQueue = void 0;
|
|
7
|
+
var _helpers = require("../../../src/utils/helpers");
|
|
8
|
+
const validateQueue = queue => {
|
|
9
|
+
const isQueueArray = Array.isArray(queue);
|
|
10
|
+
if (!isQueueArray) {
|
|
11
|
+
throw new Error('queue');
|
|
12
|
+
}
|
|
13
|
+
queue.forEach((queueElement, index) => {
|
|
14
|
+
const isQueueElementObject = (0, _helpers.isPlainObject)(queueElement);
|
|
15
|
+
if (isQueueElementObject) {
|
|
16
|
+
const isQueueElementDataProperty = ('data' in queueElement);
|
|
17
|
+
if (!isQueueElementDataProperty) {
|
|
18
|
+
throw new Error(`queue[${index}].data`);
|
|
19
|
+
}
|
|
20
|
+
const isQueueElementTimeProperty = ('time' in queueElement);
|
|
21
|
+
if (isQueueElementTimeProperty && typeof queueElement.time !== 'number') {
|
|
22
|
+
throw new Error(`queue[${index}].time`);
|
|
23
|
+
}
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
throw new Error(`queue[${index}]`);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
exports.validateQueue = validateQueue;
|
package/dist/bin/validateMockServerConfig/validateRestConfig/validateRoutes/validateRoutes.js
CHANGED
|
@@ -7,6 +7,8 @@ exports.validateRoutes = void 0;
|
|
|
7
7
|
var _helpers = require("../../../../src/utils/helpers");
|
|
8
8
|
var _helpers2 = require("../../helpers");
|
|
9
9
|
var _validateInterceptors = require("../../validateInterceptors/validateInterceptors");
|
|
10
|
+
var _validateQueue = require("../../validateQueue/validateQueue");
|
|
11
|
+
var _validateSettings = require("../../validateSettings/validateSettings");
|
|
10
12
|
const ALLOWED_ENTITIES_BY_METHOD = {
|
|
11
13
|
get: ['headers', 'cookies', 'query', 'params'],
|
|
12
14
|
delete: ['headers', 'cookies', 'query', 'params'],
|
|
@@ -16,25 +18,37 @@ const ALLOWED_ENTITIES_BY_METHOD = {
|
|
|
16
18
|
options: ['headers', 'cookies', 'query', 'params']
|
|
17
19
|
};
|
|
18
20
|
const validateEntity = (entity, entityName) => {
|
|
19
|
-
const {
|
|
20
|
-
checkMode: topLevelCheckMode,
|
|
21
|
-
value: topLevelValue
|
|
22
|
-
} = (0, _helpers.convertToEntityDescriptor)(entity);
|
|
23
21
|
const isBody = entityName === 'body';
|
|
24
|
-
const
|
|
25
|
-
if (
|
|
26
|
-
if (!
|
|
22
|
+
const isEntityTopLevelDescriptor = (0, _helpers.isEntityDescriptor)(entity);
|
|
23
|
+
if (isEntityTopLevelDescriptor) {
|
|
24
|
+
if (!isBody) {
|
|
25
|
+
throw new Error(entityName);
|
|
26
|
+
}
|
|
27
|
+
if (!(0, _helpers2.isCheckModeValid)(entity.checkMode, 'body')) {
|
|
27
28
|
throw new Error('body.checkMode');
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
throw new Error(
|
|
30
|
+
const isDescriptorValueObjectOrArray = (0, _helpers.isPlainObject)(entity.value) || Array.isArray(entity.value);
|
|
31
|
+
if (!isDescriptorValueObjectOrArray || !(0, _helpers2.isDescriptorValueValid)(entity.checkMode, entity.value)) {
|
|
32
|
+
throw new Error('body.value');
|
|
33
|
+
}
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const isEntityArray = Array.isArray(entity);
|
|
37
|
+
if (isEntityArray) {
|
|
38
|
+
if (!isBody) {
|
|
39
|
+
throw new Error(entityName);
|
|
32
40
|
}
|
|
41
|
+
entity.forEach((entityElement, index) => {
|
|
42
|
+
const isEntityElementObjectOrArray = (0, _helpers.isPlainObject)(entityElement) || Array.isArray(entityElement);
|
|
43
|
+
if (!isEntityElementObjectOrArray || !(0, _helpers2.isDescriptorValueValid)('equals', entityElement)) {
|
|
44
|
+
throw new Error(`${entityName}[${index}]`);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
33
48
|
}
|
|
34
|
-
const isEntityObject = (0, _helpers.isPlainObject)(entity)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
Object.entries(topLevelValue).forEach(([key, valueOrDescriptor]) => {
|
|
49
|
+
const isEntityObject = (0, _helpers.isPlainObject)(entity);
|
|
50
|
+
if (isEntityObject) {
|
|
51
|
+
Object.entries(entity).forEach(([key, valueOrDescriptor]) => {
|
|
38
52
|
const {
|
|
39
53
|
checkMode,
|
|
40
54
|
value
|
|
@@ -45,15 +59,25 @@ const validateEntity = (entity, entityName) => {
|
|
|
45
59
|
const isDescriptor = (0, _helpers.isEntityDescriptor)(valueOrDescriptor);
|
|
46
60
|
const errorMessage = `${entityName}.${key}${isDescriptor ? '.value' : ''}`;
|
|
47
61
|
const isValueArray = Array.isArray(value);
|
|
48
|
-
if (isValueArray
|
|
62
|
+
if (isValueArray) {
|
|
49
63
|
value.forEach((element, index) => {
|
|
50
|
-
if (
|
|
64
|
+
if (isBody) {
|
|
65
|
+
if ((0, _helpers2.isDescriptorValueValid)(checkMode, element)) return;
|
|
66
|
+
throw new Error(`${errorMessage}[${index}]`);
|
|
67
|
+
}
|
|
68
|
+
const isElementObjectOrArray = (0, _helpers.isPlainObject)(element) || Array.isArray(element);
|
|
69
|
+
if (isElementObjectOrArray || !(0, _helpers2.isDescriptorValueValid)(checkMode, element)) {
|
|
51
70
|
throw new Error(`${errorMessage}[${index}]`);
|
|
52
71
|
}
|
|
53
72
|
});
|
|
54
73
|
return;
|
|
55
74
|
}
|
|
56
|
-
if (
|
|
75
|
+
if (isBody) {
|
|
76
|
+
if ((0, _helpers2.isDescriptorValueValid)(checkMode, value)) return;
|
|
77
|
+
throw new Error(errorMessage);
|
|
78
|
+
}
|
|
79
|
+
const isValueObject = (0, _helpers.isPlainObject)(value);
|
|
80
|
+
if (isValueObject || !(0, _helpers2.isDescriptorValueValid)(checkMode, value)) {
|
|
57
81
|
throw new Error(errorMessage);
|
|
58
82
|
}
|
|
59
83
|
});
|
|
@@ -88,10 +112,35 @@ const validateRoutes = (routes, method) => {
|
|
|
88
112
|
const isRouteObject = (0, _helpers.isPlainObject)(route);
|
|
89
113
|
if (isRouteObject) {
|
|
90
114
|
const isRouteHasDataProperty = ('data' in route);
|
|
91
|
-
|
|
115
|
+
const isRouteHasQueueProperty = ('queue' in route);
|
|
116
|
+
if (!isRouteHasDataProperty && !isRouteHasQueueProperty) {
|
|
117
|
+
throw new Error(`routes[${index}]`);
|
|
118
|
+
}
|
|
119
|
+
if (isRouteHasDataProperty && isRouteHasQueueProperty) {
|
|
92
120
|
throw new Error(`routes[${index}]`);
|
|
93
121
|
}
|
|
122
|
+
const {
|
|
123
|
+
settings
|
|
124
|
+
} = route;
|
|
125
|
+
const isRouteSettingsObject = (0, _helpers.isPlainObject)(settings);
|
|
126
|
+
if (isRouteHasQueueProperty) {
|
|
127
|
+
try {
|
|
128
|
+
(0, _validateQueue.validateQueue)(route.queue);
|
|
129
|
+
if (!isRouteSettingsObject) {
|
|
130
|
+
throw new Error('settings');
|
|
131
|
+
}
|
|
132
|
+
if (!(isRouteSettingsObject && settings !== null && settings !== void 0 && settings.polling)) {
|
|
133
|
+
throw new Error('settings.polling');
|
|
134
|
+
}
|
|
135
|
+
} catch (error) {
|
|
136
|
+
throw new Error(`routes[${index}].${error.message}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (isRouteHasDataProperty && isRouteSettingsObject && settings !== null && settings !== void 0 && settings.polling) {
|
|
140
|
+
throw new Error(`routes[${index}].settings.polling`);
|
|
141
|
+
}
|
|
94
142
|
try {
|
|
143
|
+
(0, _validateSettings.validateSettings)(route.settings);
|
|
95
144
|
validateEntities(route.entities, method);
|
|
96
145
|
(0, _validateInterceptors.validateInterceptors)(route.interceptors);
|
|
97
146
|
} catch (error) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const validateSettings: (settings: unknown) => void;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.validateSettings = void 0;
|
|
7
|
+
var _helpers = require("../../../src/utils/helpers");
|
|
8
|
+
const ALLOWED_SETTINGS = ['polling'];
|
|
9
|
+
const validateSetting = (setting, settingName) => {
|
|
10
|
+
if (settingName === 'polling' && typeof setting !== 'boolean') {
|
|
11
|
+
throw new Error('polling');
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const validateSettings = settings => {
|
|
15
|
+
const isSettingsObject = (0, _helpers.isPlainObject)(settings);
|
|
16
|
+
if (isSettingsObject) {
|
|
17
|
+
Object.keys(settings).forEach(settingName => {
|
|
18
|
+
const isSettingAllowed = ALLOWED_SETTINGS.includes(settingName);
|
|
19
|
+
if (!isSettingAllowed) {
|
|
20
|
+
throw new Error(`settings.${settingName}`);
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
validateSetting(settings[settingName], settingName);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
throw new Error(`settings.${error.message}`);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (typeof settings !== 'undefined') {
|
|
31
|
+
throw new Error('settings');
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
exports.validateSettings = validateSettings;
|
|
@@ -6,16 +6,59 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.createNestedDatabaseRoutes = void 0;
|
|
7
7
|
var _array = require("../array");
|
|
8
8
|
var _filter = require("../filter/filter");
|
|
9
|
+
var _pagination = require("../pagination/pagination");
|
|
10
|
+
var _sort2 = require("../sort/sort");
|
|
9
11
|
const createNestedDatabaseRoutes = (router, database, storage) => {
|
|
10
12
|
Object.keys(database).forEach(key => {
|
|
11
13
|
const collectionPath = `/${key}`;
|
|
12
14
|
const itemPath = `/${key}/:id`;
|
|
13
15
|
router.route(collectionPath).get((request, response) => {
|
|
16
|
+
var _request$query;
|
|
14
17
|
let data = storage.read(key);
|
|
15
18
|
if (request.query && Object.keys(request.query).length) {
|
|
16
|
-
|
|
19
|
+
const {
|
|
20
|
+
_page,
|
|
21
|
+
_limit,
|
|
22
|
+
_begin,
|
|
23
|
+
_end,
|
|
24
|
+
_sort,
|
|
25
|
+
_order,
|
|
26
|
+
...filters
|
|
27
|
+
} = request.query;
|
|
28
|
+
data = (0, _filter.filter)(data, filters);
|
|
29
|
+
}
|
|
30
|
+
if ((_request$query = request.query) !== null && _request$query !== void 0 && _request$query._page) {
|
|
31
|
+
data = (0, _pagination.pagination)(data, request.query);
|
|
32
|
+
if (data._link) {
|
|
33
|
+
const links = {};
|
|
34
|
+
const fullUrl = `${request.protocol}://${request.get('host')}${request.originalUrl}`;
|
|
35
|
+
if (data._link.first) {
|
|
36
|
+
links.first = fullUrl.replace(`page=${data._link.current}`, `page=${data._link.first}`);
|
|
37
|
+
}
|
|
38
|
+
if (data._link.prev) {
|
|
39
|
+
links.prev = fullUrl.replace(`page=${data._link.current}`, `page=${data._link.prev}`);
|
|
40
|
+
}
|
|
41
|
+
if (data._link.next) {
|
|
42
|
+
links.next = fullUrl.replace(`page=${data._link.current}`, `page=${data._link.next}`);
|
|
43
|
+
}
|
|
44
|
+
if (data._link.last) {
|
|
45
|
+
links.last = fullUrl.replace(`page=${data._link.current}`, `page=${data._link.last}`);
|
|
46
|
+
}
|
|
47
|
+
data._link = {
|
|
48
|
+
...data._link,
|
|
49
|
+
...links
|
|
50
|
+
};
|
|
51
|
+
response.links(links);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (request.query && request.query._sort) {
|
|
55
|
+
data = (0, _sort2.sort)(data, request.query);
|
|
56
|
+
}
|
|
57
|
+
if (request.query._begin || request.query._end) {
|
|
58
|
+
var _request$query$_begin;
|
|
59
|
+
data = data.slice((_request$query$_begin = request.query._begin) !== null && _request$query$_begin !== void 0 ? _request$query$_begin : 0, request.query._end);
|
|
60
|
+
response.set('X-Total-Count', data.length);
|
|
17
61
|
}
|
|
18
|
-
|
|
19
62
|
// ✅ important:
|
|
20
63
|
// set 'Cache-Control' header for explicit browsers response revalidate
|
|
21
64
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ParsedUrlQuery } from 'node:querystring';
|
|
2
|
+
export declare const filter: (array: any[], filters: ParsedUrlQuery) => any[];
|