mockaton 7.6.2 → 7.7.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 CHANGED
@@ -123,7 +123,14 @@ api/user(default).GET.200.json
123
123
 
124
124
  ---
125
125
 
126
- ## You can write JSON mocks in JavaScript
126
+ ## You can write JSON mocks in JavaScript or TypeScript
127
+ For TypeScript mocks, install [tsx](https://www.npmjs.com/package/tsx) and load it.
128
+ ```shell
129
+ npm install --save-dev tsx
130
+ node --import=tsx my-mockaton.js
131
+ ```
132
+ ---
133
+
127
134
  An Object, Array, or String is sent as JSON.
128
135
 
129
136
  `api/foo.GET.200.js`
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.0",
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 './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',