Skip to content

Commit

Permalink
Merge branch 'main' into #102
Browse files Browse the repository at this point in the history
# Conflicts:
#	.eslintrc.js
#	src/core/graphql/createGraphQLRoutes/createGraphQLRoutes.ts
#	src/core/middlewares/notFoundMiddleware/notFoundMiddleware.ts
#	src/core/rest/createRestRoutes/createRestRoutes.ts
#	src/server/createGraphQLMockServer/createGraphQLMockServer.ts
#	src/server/createMockServer/createMockServer.ts
#	src/server/createRestMockServer/createRestMockServer.ts
#	src/utils/helpers/interceptors/callRequestInterceptor/callRequestInterceptor.test.ts
#	src/utils/types/graphql.ts
#	src/utils/types/rest.ts
#	src/utils/types/utils.ts
  • Loading branch information
RiceWithMeat committed Apr 6, 2024
2 parents c427ea0 + df0a653 commit 7344d74
Show file tree
Hide file tree
Showing 207 changed files with 8,156 additions and 4,433 deletions.
5 changes: 4 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ module.exports = {
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-enum-comparison': 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/naming-convention': 'off',
'@typescript-eslint/no-namespace': 'off',
'no-underscore-dangle': 'off',
'no-restricted-syntax': 'off',
'promise/always-return': ['error', { ignoreLastCallback: true }],
'@typescript-eslint/no-namespace': 'off',
'arrow-body-style': ['error', 'as-needed'],
'no-console': ['warn', { allow: ['info', 'dir', 'error'] }]
}
}
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,9 @@ Temporary Items
# Local
.env
dist
mock-server-build
mock-server.config.*
!bin/templates/**/mock-server.config.*
mock-requests

# Logs
logs
Expand Down
2 changes: 1 addition & 1 deletion .husky/commit-msg
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ then
branch=$(git symbolic-ref --short HEAD)
emoji=$(cat .emoji)
message=$(cat "$1")
if echo "$message" | (! grep -q "^${branch} ${emoji}*")
if echo "$message" | (! grep -q "^${branch} ${emoji}*") && echo "$message" | (! grep -q "^Merge pull request*") && echo "$message" | (! grep -q "^Merge branch*")
then
echo "$branch $emoji $(cat $1)" > "$1"
fi
Expand Down
266 changes: 260 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ $ npx mock-config-server
- `baseUrl?` {string} part of the url that will be substituted at the beginning of graphql request url (default: `'/'`)
- `configs` {Array<GraphQLRequestConfig>} configs for mock requests, [read](#configs)
- `interceptors?` {Interceptors} functions to change request or response parameters, [read](#interceptors)
- `database?` Database config for mock requests [read](#Database)
- `database?` Database config for mock requests [read](#database)
- `data` {Object | string} initial data for database
- `routes?` {Object | string} map of custom routes for database
- `staticPath?` {StaticPath} entity for working with static files, [read](#static-path)
Expand All @@ -88,24 +88,36 @@ Configs are the fundamental part of the mock server. These configs are easy to f

##### Rest request config

Every route must be configured to handle response content in one of three ways: data or [queue](#polling) or [file](#file-responses).

- `path` {string | RegExp} request path
- `method` {GET | POST | DELETE | PUT | PATCH} rest api method
- `method` {get | post | delete | put | patch | options} rest api method
- `routes` {RestRouteConfig[]} request routes
- `data` {any} mock data of request
- `data?` {any} mock data of request
- `queue?` {Array<{ time?: number; data: any}>} queue for polling with opportunity to set time for each response
- `file?` {string} path to file for return in response
- `settings?` {Settings} settings for route (polling on/off, etc.)
- `entities?` Object<headers | cookies | query | params | body> object that helps in data retrieval
- `interceptors?` {Interceptors} functions to change request or response parameters, [read](#interceptors)
- `interceptors?` {Interceptors} functions to change request or response parameters, [read](#interceptors)

##### GraphQL request config

Every route must be configured to handle response content in one of two ways: data or [queue](#polling).

- `operationType` {query | mutation} graphql operation type
- `operationName` {string} graphql operation name
- `operationName?` {string | RegExp} graphql operation name
- `query?`: {string} graphql query as string
- `routes` {GraphQLRouteConfig[]} request routes
- `data` {any} mock data of request
- `data?` {any} mock data of request
- `queue?` {Array<{ time?: number; data: any}>} queue for polling with opportunity to set time for each response
- `settings?` {Settings} settings for route (polling on/off, etc.)
- `entities?` Object<headers | cookies | query | variables> object that helps in data retrieval
- `interceptors?` {Interceptors} functions to change request or response parameters, [read](#interceptors)
- `interceptors?` {Interceptors} functions to change request or response parameters, [read](#interceptors)

> Every graphql config should contain `operationName` or `query` or both of them
##### Rest example

```javascript
Expand Down Expand Up @@ -270,6 +282,35 @@ const mockServerConfig = {
module.exports = mockServerConfig;
```

Also you can use array as value for REST body and GraphQL variables entities: in this case mock-config-server will iterate
over array until `checkMode=equals` finds a match or return 404

```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
configs: [
{
path: '/user',
method: 'post',
routes: [
{
entities: {
// if body equals to { key1: 'value1' } or ['value1'] then mock-config-server return data
body: [{ key1: 'value1' }, ['value1']]
},
data: 'Some user data'
}
]
}
]
}
};

module.exports = mockServerConfig;
```

`function checkMode` is the most powerful way to describe your `entities` logic, but in most cases you will be fine using other `checkModes`.

`Function value` has the following signature `(actualValue, checkFunction) => boolean`.
Expand Down Expand Up @@ -381,6 +422,126 @@ const mockServerConfig = {
module.exports = mockServerConfig;
```

#### Polling

Routes support polling for data. To add polling for data, you must specify the `polling setting` and change `data` property to `queue`.

> After receiving the last value from polling, the queue is reset and the next request will return the first value from the queue.
```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
configs: [
{
path: '/user',
method: 'get',
routes: [
{
settings: { polling: true },
queue: [
{ data: { emoji: '🦁', name: 'Nursultan' } },
{ data: { emoji: '', name: 'Dmitriy' } }
]
}
]
}
]
}
};

export default mockServerConfig;
```

Using the additional `time` properties in milliseconds, you can specify how much time certain data should be returned

```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
configs: [
{
path: '/user',
method: 'get',
routes: [
{
settings: { polling: true },
queue: [
{ time: 5000, data: { emoji: '🦁', name: 'Nursultan' } },
{ data: { emoji: '', name: 'Dmitriy' } }
]
}
]
}
]
}
};

export default mockServerConfig;
```

#### File responses

Rest routes support paths to files. If a route is matched, the server will send data from the file. If the file is not found, the server will return 404.

```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
configs: [
{
path: '/files/settings',
method: 'get',
routes: [
{
file: './settings.json'
}
]
}
]
}
};

export default mockServerConfig;
```

> If the file path is absolute, then this path will be used as is. If the file path is relative, it will be appended to the current working directory.
If the file exists, response interceptors will receive null as the data argument.

```javascript
/** @type {import('mock-config-server').MockServerConfig} */
const mockServerConfig = {
rest: {
baseUrl: '/api',
configs: [
{
path: '/files/settings',
method: 'get',
routes: [
{
file: './settings.json',
interceptors: {
response: (data) => {
console.log(data); // null
return data;
}
}
}
]
}
]
}
};

export default mockServerConfig;
```

> Any changes to the data will not affect the file (and the response, respectively).
#### Static Path

Entity for connecting statics to the server, like HTML, JSON, PNG, etc.
Expand Down Expand Up @@ -547,6 +708,78 @@ GET /users?id=1&id=2
GET /users?author.name=siberiacancode
```

### Pagination

> Use \_page and optionally \_limit to paginate returned data.
```
GET /users?_page=1
GET /users?_page=1&_limit=5
```

> **\_limit** is 10 by default
The returned data has the format:

```
{
_link: Link,
results: Data[]
}
```

In the **Link** header you'll get **count**, **pages**, **next** and **prev** links.

#### Link

- `count` {number} total count of elements
- `pages` {number} count of pages
- `next` {string | null} query string for next link
- `prev` {string | null} query string for prev link

### Sort

> Use \_sort and \_order, use . to access deep properties
```
GET /users?_sort=name
GET /users/1/transfers?_sort=id&_order=asc
GET /users?_sort=address.city&_order=desc
```

> **\_order** is 'asc' by default
For multiple fields:

```
GET /users?_sort=id&_order=desc&_sort=name&_order=asc
```

### Slice

> X-Total-Count header is included in the response
```
GET /users?_begin=20
GET /users?_begin=20&_end=30
```

Works exactly as [slice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice), \_begin and \_end are optional

### Full text search

> Add \_q parameter for search data, search can be done by strings and numbers
```
GET /users?_q=siberia
```

For multiple search

```
GET /users?_q=siberia&_q=24
```

### File example

```javascript
Expand Down Expand Up @@ -580,6 +813,18 @@ Examples:
mcs --help
```

# Init Command

The init command is used to initialize a new project or set up the initial configuration for a tool. It helps users get started with a new project by providing a streamlined setup process.

```
mcs init
Examples:
mcs init
mcs init --baseurl /base/url --port 3000
```

## ✨ Contributors

<table>
Expand All @@ -601,7 +846,7 @@ Examples:
<br />
<sub style="font-size:13px"><b>👹 MiaInturi</b></sub>
</a>
</td>
</td>
<td align="center" style="word-wrap: break-word; width: 100.0; height: 100.0">
<a href="https://github.com/RiceWithMeat">
<img src="https://avatars.githubusercontent.com/u/47690223?v=4"
Expand All @@ -619,6 +864,15 @@ Examples:
<br />
<sub style="font-size:13px"><b>🎱️ anv296</b></sub>
</a>
</td>
<td align="center" style="word-wrap: break-word; width: 100.0; height: 100.0">
<a href="https://github.com/kvelian">
<img src="https://avatars.githubusercontent.com/u/81089091?s=400&u=7c4fcc6d120f4b13ccbd03a9a384622b6523c376&v=4"
width="100;"
alt="kvelian" />
<br />
<sub style="font-size:13px"><b>🌵 kvelian</b></sub>
</a>
</td>
</tr>
</table>
6 changes: 3 additions & 3 deletions babel.config.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"ignore": ["./**/*.test.ts"],
"ignore": ["./**/*.test.ts", "./bin/templates/*"],
"presets": [
"@babel/preset-typescript",
[
"@babel/preset-env",
{
"targets": {
"node": "10.0"
"node": "12.0"
}
}
]
]
}
}
Loading

0 comments on commit 7344d74

Please sign in to comment.