mockaton 0.9.8 → 0.9.10

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 CHANGED
@@ -1,13 +1,13 @@
1
1
  # Mockaton
2
2
  _Mockaton_ is a mock server for developing and testing frontends.
3
3
 
4
- It scans `Config.mocksDir` for files following a specific
5
- file name convention, which is similar to the URL paths. For
4
+ It scans `Config.mocksDir` for files following a specific directory
5
+ and file name convention, which is similar to the URL paths. For
6
6
  example, the following file will be served for `/api/user/1234`
7
7
  ```
8
- api/
9
- api/user/
10
- api/user/[user-id].GET.200.json
8
+ -- api/
9
+ |-- user/
10
+ |-- [user-id].GET.200.json
11
11
  ```
12
12
 
13
13
  By the way, [this browser
@@ -63,11 +63,12 @@ npm install mockaton
63
63
  Create a `my-mockaton.js` file
64
64
  ```js
65
65
  import { resolve } from 'node:path'
66
- import { Mockaton } from 'mockaton'
66
+ import { Mockaton } from 'src/Mockaton'
67
+
67
68
 
68
69
  Mockaton({ // Config options
69
- port: 2345,
70
- mocksDir: resolve('my-mocks-dir')
70
+ port: 2345,
71
+ mocksDir: resolve('my-mocks-dir')
71
72
  })
72
73
  ```
73
74
 
@@ -92,15 +93,16 @@ interface Config {
92
93
 
93
94
  ## Cookies
94
95
  ```js
95
- import { jwtCookie } from 'mockaton'
96
+ import { jwtCookie } from 'src/Mockaton'
97
+
96
98
 
97
99
  Config.cookies = {
98
- 'My Admin User': 'my-cookie=1;Path=/;SameSite=strict',
99
- 'My Normal User': 'my-cookie=0;Path=/;SameSite=strict',
100
- 'My JWT': jwtCookie('my-cookie', {
101
- email: 'john.doe@example.com',
102
- picture: 'https://cdn.auth0.com/avatars/jd.png'
103
- })
100
+ 'My Admin User': 'my-cookie=1;Path=/;SameSite=strict',
101
+ 'My Normal User': 'my-cookie=0;Path=/;SameSite=strict',
102
+ 'My JWT': jwtCookie('my-cookie', {
103
+ email: 'john.doe@example.com',
104
+ picture: 'https://cdn.auth0.com/avatars/jd.png'
105
+ })
104
106
  }
105
107
  ```
106
108
 
@@ -122,23 +124,27 @@ The `Config.allowedExt` regex defaults to: `/\.(json|txt|md|mjs)$/`
122
124
 
123
125
 
124
126
  ### Dynamic Parameters
125
- Anything within square brackets. For example, `api/user/[id]/[age].GET.200.json`
127
+ Anything within square brackets. For example,
128
+ <pre>
129
+ api/user/<b>[id]</b>/<b>[age]</b>.GET.200.json
130
+ </pre>
126
131
 
127
132
  ### Comments
128
- Comments are anything within parentheses, including them, and they are
129
- ignored for URL purposes. In other words, comments have no effect on the
130
- URL mask. For example, these two are for `/api/foo`
131
- ```
132
- api/foo(my comment).GET.200.json(foo)
133
+ Comments are anything within parentheses, including them.
134
+ They are ignored for URL purposes, so they have no effect
135
+ on the URL mask. For example, these two are for `/api/foo`
136
+ <pre>
137
+ api/foo<b>(my comment)</b>.GET.200.json<b>(foo)</b>
133
138
  api/foo.GET.200.json
134
- ```
139
+ </pre>
135
140
 
136
141
  ### Query String Params
137
- ```
138
- api/video?limit=[limit].GET.200.json
139
- ```
140
- The query string behaves like comments in the sense it’s only used for documenting
141
- the URL API contract. In other words, the query string is ignored when routing to it.
142
+ <pre>
143
+ api/video<b>?limit=[limit]</b>.GET.200.json
144
+ </pre>
145
+
146
+ The query string is ignored when routing to it. It’s
147
+ only used for documenting the URL API contract.
142
148
 
143
149
  BTW, in Windows, filenames containing "?" are [not
144
150
  permitted](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file),
@@ -199,7 +205,7 @@ PATCH /mockaton/edit
199
205
  ```
200
206
  PATCH /mockaton/bulk-select
201
207
  {
202
- "comment": "demo-a"
208
+ "comment": "(demo-a)"
203
209
  }
204
210
  ```
205
211
  ---
package/Tests.js CHANGED
@@ -6,10 +6,10 @@ import { describe, it } from 'node:test'
6
6
  import { equal, deepEqual, match } from 'node:assert/strict'
7
7
  import { writeFileSync, mkdtempSync, mkdirSync } from 'node:fs'
8
8
 
9
- import { Route } from './Route.js'
10
- import { mimeFor } from './utils/mime.js'
11
- import { DP, DF } from './ApiConstants.js'
12
- import { Mockaton } from './Mockaton.js'
9
+ import { Route } from './src/Route.js'
10
+ import { mimeFor } from './src/utils/mime.js'
11
+ import { Mockaton } from './src/Mockaton.js'
12
+ import { DP, DF } from './src/ApiConstants.js'
13
13
 
14
14
 
15
15
  const tmpDir = mkdtempSync(tmpdir()) + '/'
package/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { Mockaton } from './Mockaton.js'
2
- export { jwtCookie } from './utils/jwt.js'
1
+ export { Mockaton } from './src/Mockaton.js'
2
+ export { jwtCookie } from './src/utils/jwt.js'
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "mockaton",
3
3
  "description": "A deterministic server-side for developing and testing frontend clients",
4
4
  "type": "module",
5
- "version": "0.9.8",
5
+ "version": "0.9.10",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "license": "MIT",
@@ -5,7 +5,7 @@ import { DF } from './ApiConstants.js'
5
5
  import { cookie } from './cookie.js'
6
6
  import { Config } from './Config.js'
7
7
  import { mimeFor } from './utils/mime.js'
8
- import * as MockBrokerCollection from './mockBrokersCollection.js'
8
+ import * as mockBrokerCollection from './mockBrokersCollection.js'
9
9
  import { parseJSON, JsonBodyParserError } from './utils/http-request.js'
10
10
  import { sendInternalServerError, sendNotFound, sendFile, sendBadRequest } from './utils/http-response.js'
11
11
 
@@ -17,14 +17,14 @@ export async function dispatchMock(req, response) {
17
17
  return
18
18
  }
19
19
 
20
- const mockBroker = MockBrokerCollection.findMatchingBroker(req.method, req.url)
21
- if (!mockBroker) {
20
+ const broker = mockBrokerCollection.getBrokerForUrl(req.method, req.url)
21
+ if (!broker) {
22
22
  sendNotFound(response)
23
23
  return
24
24
  }
25
25
 
26
26
  try {
27
- const { file, status, delay, currentTransform } = mockBroker
27
+ const { file, status, delay, currentTransform } = broker
28
28
  console.log('\n', req.url, '→\n ', file)
29
29
 
30
30
  response.statusCode = status
@@ -33,7 +33,7 @@ export async function dispatchMock(req, response) {
33
33
  response.setHeader('set-cookie', cookie.getCurrent())
34
34
 
35
35
  let mockAsText = readMock(file)
36
- if (mockBroker.currentTransform) {
36
+ if (broker.currentTransform) {
37
37
  const body = await requestBodyForTransform(req, mockAsText)
38
38
  const transformFunc = await importTransformFunc(currentTransform)
39
39
  mockAsText = transformFunc(mockAsText, body, Config)
@@ -4,14 +4,14 @@ import { createServer } from 'node:http'
4
4
  import { DP } from './ApiConstants.js'
5
5
  import { Config, setup } from './Config.js'
6
6
  import { dispatchMock } from './MockDispatcher.js'
7
- import * as MockBrokerCollection from './mockBrokersCollection.js'
7
+ import * as mockBrokerCollection from './mockBrokersCollection.js'
8
8
  import { dispatchStatic, isStatic } from './StaticDispatcher.js'
9
9
  import { apiPatchRequests, apiGetRequests } from './Api.js'
10
10
 
11
11
 
12
12
  export function Mockaton(options) {
13
13
  setup(options)
14
- MockBrokerCollection.init()
14
+ mockBrokerCollection.init()
15
15
 
16
16
  return createServer(async (req, response) => {
17
17
  const { url, method } = req
@@ -20,43 +20,54 @@ import { MockBroker } from './MockBroker.js'
20
20
  let collection = {}
21
21
 
22
22
  export function init() {
23
+ collection = {}
23
24
  cookie.init(Config.cookies)
24
25
 
25
- collection = {}
26
- for (const file of listMocksDirRecursively()) {
26
+ const files = readdirSync(Config.mocksDir, { recursive: true })
27
+ .filter(f => Config.allowedExt.test(f) && lstatSync(join(Config.mocksDir, f)).isFile())
28
+ .sort()
29
+
30
+ for (const file of files) {
27
31
  const { error, method, urlMask } = Route.parseFilename(file)
28
- if (error) // skip
32
+ if (error) {
29
33
  console.error(error, file)
30
- else {
31
- collection[method] ??= {}
32
- if (!(urlMask in collection[method]))
33
- collection[method][urlMask] = new MockBroker(file)
34
- else
35
- collection[method][urlMask].register(file)
34
+ continue
36
35
  }
36
+ collection[method] ??= {}
37
+ if (!(urlMask in collection[method]))
38
+ collection[method][urlMask] = new MockBroker(file)
39
+ else
40
+ collection[method][urlMask].register(file)
37
41
  }
38
42
  forEachBroker(broker => broker.ensureItHas500())
39
43
  }
40
44
 
45
+ function forEachBroker(fn) {
46
+ for (const brokers of Object.values(collection))
47
+ Object.values(brokers).forEach(fn)
48
+ }
49
+
50
+
41
51
  export const getAll = () => collection
52
+
42
53
  export const getBrokerByFilename = file => {
43
54
  const { method, urlMask } = Route.parseFilename(file)
44
55
  return collection[method][urlMask]
45
56
  }
46
57
 
47
-
48
58
  // Searching the routes in reverse order so dynamic params (e.g.
49
59
  // /user/[id]) don’t take precedence over exact paths (e.g.
50
60
  // /user/name). That’s because "[]" chars are lower than alphanumeric ones.
51
61
  // BTW, `urlMasks` always start with "/", so there’s no need to
52
62
  // worry about the primacy of array-like keys when iterating.
53
- export function findMatchingBroker(method, url) {
63
+ export function getBrokerForUrl(method, url) {
54
64
  const brokers = Object.values(collection[method])
55
65
  for (let i = brokers.length - 1; i >= 0; i--)
56
66
  if (brokers[i].urlMaskMatches(url))
57
67
  return brokers[i]
58
68
  }
59
69
 
70
+
60
71
  export function extractAllComments() {
61
72
  const comments = new Set()
62
73
  forEachBroker(broker => {
@@ -70,14 +81,4 @@ export function setMocksMatchingComment(comment) {
70
81
  forEachBroker(broker => broker.setByMatchingComment(comment))
71
82
  }
72
83
 
73
- function listMocksDirRecursively() {
74
- return readdirSync(Config.mocksDir, { recursive: true })
75
- .filter(f => Config.allowedExt.test(f) && lstatSync(join(Config.mocksDir, f)).isFile())
76
- .sort()
77
- }
78
-
79
- function forEachBroker(fn) {
80
- for (const brokers of Object.values(collection))
81
- Object.values(brokers).forEach(fn)
82
- }
83
84
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes