mockaton 7.6.2 → 7.7.1

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
@@ -58,8 +58,9 @@ _Reset_ button is for registering newly added, removed, or renamed mocks.
58
58
 
59
59
 
60
60
  ## Basic Usage
61
+ `tsx` is only needed if you want to write mocks in TypeScript
61
62
  ```
62
- npm install mockaton
63
+ npm install mockaton tsx
63
64
  ```
64
65
  Create a `my-mockaton.js` file
65
66
  ```js
@@ -74,7 +75,7 @@ Mockaton({
74
75
  ```
75
76
 
76
77
  ```sh
77
- node my-mockaton.js
78
+ node --import=tsx my-mockaton.js
78
79
  ```
79
80
 
80
81
  ## Config Options
@@ -123,7 +124,14 @@ api/user(default).GET.200.json
123
124
 
124
125
  ---
125
126
 
126
- ## You can write JSON mocks in JavaScript
127
+ ## You can write JSON mocks in JavaScript or TypeScript
128
+ For TypeScript mocks, install [tsx](https://www.npmjs.com/package/tsx) and load it.
129
+ ```shell
130
+ npm install --save-dev tsx
131
+ node --import=tsx my-mockaton.js
132
+ ```
133
+ ---
134
+
127
135
  An Object, Array, or String is sent as JSON.
128
136
 
129
137
  `api/foo.GET.200.js`
@@ -373,7 +381,7 @@ await mockaton.reset()
373
381
 
374
382
  <div style="display: flex; align-items: center; gap: 20px">
375
383
  <img src="./sample-mocks/api/user/avatar.GET.200.png" width="170"/>
376
- <p style="font-size: 18px">“Use Mockaton” - Albert Einstein</p>
384
+ <p style="font-size: 18px">“Use Mockaton”</p>
377
385
  </div>
378
386
 
379
387
 
package/_usage_example.js CHANGED
@@ -1,5 +1,3 @@
1
- #!/usr/bin/env node
2
-
3
1
  import { join } from 'node:path'
4
2
  import { Mockaton, jwtCookie } from './index.js' // from 'mockaton'
5
3
 
package/package.json CHANGED
@@ -2,13 +2,17 @@
2
2
  "name": "mockaton",
3
3
  "description": "A deterministic server-side for developing and testing frontend clients",
4
4
  "type": "module",
5
- "version": "7.6.2",
5
+ "version": "7.7.1",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "license": "MIT",
9
9
  "repository": "https://github.com/ericfortis/mockaton",
10
10
  "scripts": {
11
11
  "test": "node --test",
12
- "demo": "./_usage_example.js"
12
+ "demo": "node _usage_example.js",
13
+ "demo:ts": "node --import=tsx _usage_example.js"
14
+ },
15
+ "optionalDependencies": {
16
+ "tsx": "4.19.1"
13
17
  }
14
18
  }
@@ -0,0 +1,9 @@
1
+ import scores from './typescript-scores.GET.200'
2
+
3
+ export default [
4
+ ...scores,
5
+ { id: 103 },
6
+ { id: 104 },
7
+ { id: 105 },
8
+ ]
9
+
@@ -0,0 +1,6 @@
1
+ export default [
2
+ { id: 100 },
3
+ { id: 101 },
4
+ { id: 102 },
5
+ ]
6
+
package/src/Dashboard.js CHANGED
@@ -145,7 +145,6 @@ function ResetButton() {
145
145
  }
146
146
 
147
147
  function StaticFilesList({ staticFiles }) {
148
- console.log(staticFiles)
149
148
  if (!staticFiles.length)
150
149
  return null
151
150
  return (
package/src/Filename.js CHANGED
@@ -19,13 +19,16 @@ export function filenameIsValid(file) {
19
19
  console.error(error, file)
20
20
  return !error
21
21
  }
22
+
22
23
  function validateFilename(file) {
23
24
  const tokens = file.replace(reComments, '').split('.')
24
25
  if (tokens.length < 4)
25
26
  return 'Invalid Filename Convention'
27
+
26
28
  const { status, method } = parseFilename(file)
27
29
  if (!responseStatusIsValid(status))
28
30
  return `Invalid HTTP Response Status: "${status}"`
31
+
29
32
  if (!httpMethods.includes(method))
30
33
  return `Unrecognized HTTP Method: "${method}"`
31
34
  }
package/src/MockBroker.js CHANGED
@@ -64,9 +64,9 @@ export class MockBroker {
64
64
  }
65
65
 
66
66
  extractComments() {
67
- let comments = []
67
+ const comments = []
68
68
  for (const file of this.mocks)
69
- comments = comments.concat(extractComments(file))
69
+ comments.push(...extractComments(file))
70
70
  return comments
71
71
  }
72
72
 
@@ -25,33 +25,59 @@ export async function dispatchMock(req, response) {
25
25
  console.log(decodeURIComponent(req.url), ' → ', file)
26
26
  const filePath = join(Config.mocksDir, file)
27
27
 
28
- let mockBody
29
- if (file.endsWith('.js')) {
30
- response.setHeader('Content-Type', mimeFor('.json'))
31
- const jsExport = (await import(filePath + '?' + Date.now())).default // date for cache busting
32
- mockBody = typeof jsExport === 'function'
33
- ? await jsExport(req, response)
34
- : JSON.stringify(jsExport, null, 2)
35
- }
36
- else {
37
- response.setHeader('Content-Type', mimeFor(file))
38
- mockBody = broker.isTemp500
39
- ? ''
40
- : read(filePath)
41
- }
28
+ response.statusCode = status
42
29
 
43
30
  if (cookie.getCurrent())
44
31
  response.setHeader('Set-Cookie', cookie.getCurrent())
45
32
 
46
- response.writeHead(status, Config.extraHeaders)
33
+ for (let i = 0; i < Config.extraHeaders.length; i += 2)
34
+ response.setHeader(Config.extraHeaders[i], Config.extraHeaders[i + 1])
35
+
36
+ const [mime, mockBody] = broker.isTemp500
37
+ ? temp500Plugin(filePath, req, response)
38
+ : await preprocessPlugins(filePath, req, response)
39
+
40
+ response.setHeader('Content-Type', mime)
47
41
  setTimeout(() => response.end(mockBody), delay)
48
42
  }
49
43
  catch (error) {
50
44
  if (error instanceof JsonBodyParserError)
51
45
  sendBadRequest(response, error)
52
- else if (error.code === 'ENOENT')
53
- sendNotFound(response) // file has been deleted
46
+ else if (error.code === 'ENOENT') // mock-file has been deleted
47
+ sendNotFound(response)
48
+ else if (error.code === 'ERR_UNKNOWN_FILE_EXTENSION') {
49
+ if (error.toString().includes('Unknown file extension ".ts"'))
50
+ console.log('Looks like you need a TypeScript compiler\n',
51
+ ' npm install tsx\n',
52
+ ' node --import=tsx my-mockaton.js\n')
53
+ sendInternalServerError(response, error)
54
+ }
54
55
  else
55
56
  sendInternalServerError(response, error)
56
57
  }
57
58
  }
59
+
60
+ // TODO expose to userland for custom plugins such yaml -> json
61
+ async function preprocessPlugins(filePath, req, response) {
62
+ if (filePath.endsWith('.js') || filePath.endsWith('.ts'))
63
+ return await jsPlugin(filePath, req, response)
64
+ return readPlugin(filePath, req, response)
65
+ }
66
+
67
+ function temp500Plugin(filePath) {
68
+ return [mimeFor(filePath), '']
69
+ }
70
+
71
+ async function jsPlugin(filePath, req, response) {
72
+ const jsExport = (await import(filePath + '?' + Date.now())).default // date for cache busting
73
+ const mockBody = typeof jsExport === 'function'
74
+ ? await jsExport(req, response)
75
+ : JSON.stringify(jsExport, null, 2)
76
+ const mime = response.getHeader('Content-Type') // jsFunc are allowed to set it
77
+ || mimeFor('.json')
78
+ return [mime, mockBody]
79
+ }
80
+
81
+ function readPlugin(filePath) {
82
+ return [mimeFor(filePath), read(filePath)]
83
+ }
@@ -24,7 +24,6 @@ const fixtureCustomMime = [
24
24
  'api/custom-mime.GET.200.my_custom_extension',
25
25
  'Custom Extension and MIME'
26
26
  ]
27
-
28
27
  const fixtureNonDefaultInName = [
29
28
  '/api/the-route',
30
29
  'api/the-route(default).GET.200.json',
@@ -35,7 +34,6 @@ const fixtureDefaultInName = [
35
34
  'api/the-route(default).GET.200.json',
36
35
  'default my route body content'
37
36
  ]
38
-
39
37
  const fixtureDelayed = [
40
38
  '/api/delayed',
41
39
  'api/delayed.GET.200.json',