mockapi-msi 2.0.1 → 2.5.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
@@ -1,120 +1,357 @@
1
- # Dynamic mocking descriptive API (MockAPI)
2
-
3
- MockAPI help you buiding your app when requires connecting to a not yet built external API.
4
-
5
- MockAPI let you create fake responses with pre defined and dynamic data for defined endpoints.
6
-
7
- MockAPI also is intended to help you when, during testing phase, you cannot afford complex and expensive products (And you do not need them) that requires bulky configuration steps or depends directly on third party providers that you cannot control.
8
-
9
- ## Version 2.0.1 notes
10
-
11
- - A bug related to custom handlers was detected and fixed.
12
-
13
- ## Version 2.0.0 notes
14
-
15
- - Using NodeJS managers such as NVM causes configuration file not being picked from the execution/working folder.
16
- - New CORE class created and code moved from the main module.
17
- - Additional checking for the configuration file.
18
- - Folder file readear incorrect path contactenation fixed.
19
-
20
- ## Configuration file
21
-
22
- MockAPI can be used as it is. Without any additional coding activity. Just configure your endpoints and run ```main.js``` file.
23
-
24
- ### Configuring MockAPI
25
-
26
- Edit ```.mockapi-config``` to add your own endpoints, responses, parsers and data. Use standard YAML notation for this file.
27
-
28
- #### Main entry points
29
-
30
- **port** - Specify the HTTP port to be used by MockAPI to expose the defined endpoints.
31
-
32
- **enableCors** - Enable/Disable CORS for MockAPI.
33
-
34
- **externalModulesPath** - Optional configuration. Allows to specify a different path where the user custom handlers are located.
35
-
36
- **data** -
37
- Holds and describe the available data for all endpoints and responses.
38
-
39
- **endpoints** - Describe all available endpoints, its verbs and responses.
40
-
41
- **log** - Define MockAPI log level.
42
-
43
- **customHandlers** - Import a custom HTTP data handler. Use these custom handlers to manipulate the output of your responses for a particular endpoint.
44
-
45
- Within ```data``` entry, it is possible to define how the data must be handled. There are three built-in readers that comes with MockAPI.
46
-
47
- **csv** - Reads the defined data as CSV.
48
-
49
- **text** - Considers the data source as plain text.
50
-
51
- **folder** - Reads the files from the folder matching the incoming request name.
52
-
53
- #### Data definition
54
-
55
- ```yaml
56
- myRows:
57
- path: "./testdata/data.csv"
58
- reader: csv
59
- properties:
60
- - json
61
- - seq
62
- - 0
63
- ```
64
- The previous example defines a data source called ```myRows```, which will read the data from the defined ```path```, using the ```csv``` handler, parsing each row as ```json```, reading the values in a ```sequential``` order, starting from record ```0```.
65
-
66
- #### Endpoint definition
67
-
68
- ```yaml
69
- "/users":
70
- verb: get
71
- data: myRows
72
- responseStatus: 200
73
- responseContentType: "application/json"
74
- ```
75
- From the previous code snippet, we are defining an endpoint ```[MockAPI URL]:[PORT]/users```, which will accept ```get``` requests, answering always with ```200``` status code, using data from ```myRows``` data definition in ```JSON``` format.
76
-
77
- #### Custom handlers
78
-
79
- A custom handler let you manipulate the data as your will. First, define the handler as follows:
80
-
81
- ```yaml
82
- customHandlers:
83
- "custom":
84
- "myCustomHandler"
85
- ```
86
- The previous code defines a custom handler called ```custom``` and will use the script code called ```myCustomHandler```. The custom code must be placed inside of ```scripts``` folder and coded in JavaScript with NodeJS support.
87
-
88
- Your custom script must implement the following export format:
89
-
90
- ```javascript
91
- module.exports = {
92
- process: [Your function entry point]
93
- };
94
- ```
95
-
96
- #### Setting up the log level
97
-
98
- MockAPI logs information into the execution console. There are different levels of logs that can be used.
99
-
100
- ```yaml
101
- log: verbose
102
- #debug <- Useful for custom handlers
103
- #error <- Only exposes internal errors
104
- #verbose <- Logs debug, information and errors
105
- #none <- Turn off the logs
106
- ```
107
-
108
- ## MockAPI CLI
109
-
110
- MockAPI provides a small but helpful CLI. Type ```mockapi --help``` to get the available commands from the CLI once MockAPI is installed.
111
-
112
- #### The ```init``` command
113
-
114
- Once MockAPI is globally installed, you will need a configuration file with minimal information to be able of start mocking the API. The ```init``` command argument will lead you through different basic questions helping you to initialize this configuration file.
115
-
116
- ```powershell
117
- mockapi --init
118
- ```
119
-
120
- You can skip every question which will assign some default values to the configuration file. Later you could change these values using any text editor.
1
+ # Dynamic mocking descriptive API (MockAPI)
2
+
3
+ MockAPI help you buiding your app when requires connecting to a not yet built external API.
4
+
5
+ MockAPI let you create fake responses with pre defined and dynamic data for defined endpoints.
6
+
7
+ MockAPI also is intended to help you when, during testing phase, you cannot afford complex and expensive products (And you do not need them) that requires bulky configuration steps or depends directly on third party providers that you cannot control.
8
+
9
+ ## Version 2.5.0 notes
10
+
11
+ - **OpenAPI JSON endpoint**: MockAPI now generates and serves an OpenAPI document at `/openapi.json` based on your configured endpoints.
12
+ - **Interactive docs page**: Swagger UI is available at `/docs`, allowing users to inspect and try endpoints directly from the browser.
13
+ - **OpenAPI configuration**: New optional `openApi` section allows enabling/disabling docs and overriding docs/spec paths and metadata.
14
+
15
+ ## Version 2.4.0 notes
16
+
17
+ - **HTTPS support**: New `tls` configuration option with `cert` and `key` paths. When provided, MockAPI starts an HTTPS server instead of HTTP.
18
+ - **Unit tests**: Test suite added using Node.js built-in test runner. Tests cover CSV parsing, URL parsing, path matching, HttpException, and Core HTTP server behavior. Run with `npm test`.
19
+
20
+ ## Version 2.3.0 notes
21
+
22
+ - **CORS fine-tuning**: `enableCors` now accepts an object to configure specific origins, methods, and headers. Preflight (OPTIONS) requests are handled automatically. Boolean `true` is still supported for allow-all behavior.
23
+ - **Graceful shutdown**: The server now handles `SIGTERM` and `SIGINT` signals, cleanly closing the HTTP server and config watcher before exiting.
24
+ - **Static file serving**: New `staticPath` configuration option serves files from a local directory. Requests that don't match any endpoint will attempt to serve a static file before returning 404.
25
+
26
+ ## Version 2.2.0 notes
27
+
28
+ - **Path parameters**: Endpoints now support path parameters using `:param` syntax (e.g., `/users/:id`). Extracted parameters are available in custom handlers via `requestInformation.params`.
29
+ - **Query parameters**: Query string parameters are now parsed and available in custom handlers via `requestInformation.query`.
30
+ - **Response delay**: Endpoints can now simulate slow APIs with a `delay` property (in milliseconds).
31
+ - **Hot-reload**: The configuration file is watched for changes. Endpoints and data sources are automatically reloaded without restarting the server.
32
+
33
+ ## Version 2.1.0 notes
34
+
35
+ - Codebase modernized to ES6 classes (`HttpException`, `Log`, `CSV`).
36
+ - CSV parser rewritten with RFC 4180 compliant state machine. Correctly handles commas inside quoted fields, escaped quotes, and mixed line endings (`\r\n`, `\n`, `\r`).
37
+ - Fixed bug in `urlParser` (`searchParamss` typo).
38
+ - Fixed bug in `moduleProxy.execute()` referencing a variable outside its scope.
39
+ - Fixed invalid top-level `return` statements in `main.js`.
40
+ - Docker image updated from Node 12 (EOL) to Node 20 LTS; switched to `npm ci --omit=dev`.
41
+ - Removed deprecated `version` key from Docker Compose files.
42
+ - `package.json` updated with `files`, `keywords`, and engine requirement bumped to `>=18`.
43
+ - Custom handler example (`myCustomHandler.js`) modernized with JSDoc and meaningful sample logic.
44
+ - ASCII art banner displayed on application startup.
45
+
46
+ ## Version 2.0.1 notes
47
+
48
+ - A bug related to custom handlers was detected and fixed.
49
+
50
+ ## Version 2.0.0 notes
51
+
52
+ - Using NodeJS managers such as NVM causes configuration file not being picked from the execution/working folder.
53
+ - New CORE class created and code moved from the main module.
54
+ - Additional checking for the configuration file.
55
+ - Folder file readear incorrect path contactenation fixed.
56
+
57
+ ## Configuration file
58
+
59
+ MockAPI can be used as it is. Without any additional coding activity. Just configure your endpoints and run ```main.js``` file.
60
+
61
+ ### Configuring MockAPI
62
+
63
+ Edit ```.mockapi-config``` to add your own endpoints, responses, parsers and data. Use standard YAML notation for this file.
64
+
65
+ #### Main entry points
66
+
67
+ **port** - Specify the HTTP port to be used by MockAPI to expose the defined endpoints.
68
+
69
+ **enableCors** - Configure CORS for MockAPI. Accepts ```true``` for allow-all behavior, or an object for fine-grained control.
70
+
71
+ **externalModulesPath** - Optional configuration. Allows to specify a different path where the user custom handlers are located.
72
+
73
+ **staticPath** - Optional configuration. Path to a local directory to serve static files from. Requests that don't match any endpoint will fall back to static file serving.
74
+
75
+ **openApi** - Optional configuration to enable/disable generated OpenAPI docs and customize routes and document metadata.
76
+
77
+ **data** -
78
+ Holds and describe the available data for all endpoints and responses.
79
+
80
+ **endpoints** - Describe all available endpoints, its verbs and responses.
81
+
82
+ **log** - Define MockAPI log level.
83
+
84
+ **customHandlers** - Import a custom HTTP data handler. Use these custom handlers to manipulate the output of your responses for a particular endpoint.
85
+
86
+ Within ```data``` entry, it is possible to define how the data must be handled. There are three built-in readers that comes with MockAPI.
87
+
88
+ **csv** - Reads the defined data as CSV.
89
+
90
+ **text** - Considers the data source as plain text.
91
+
92
+ **folder** - Reads the files from the folder matching the incoming request name.
93
+
94
+ #### Data definition
95
+
96
+ ```yaml
97
+ myRows:
98
+ path: "./testdata/data.csv"
99
+ reader: csv
100
+ properties:
101
+ - json
102
+ - seq
103
+ - 0
104
+ ```
105
+ The previous example defines a data source called ```myRows```, which will read the data from the defined ```path```, using the ```csv``` handler, parsing each row as ```json```, reading the values in a ```sequential``` order, starting from record ```0```.
106
+
107
+ #### Endpoint definition
108
+
109
+ ```yaml
110
+ "/users":
111
+ verb: get
112
+ data: myRows
113
+ responseStatus: 200
114
+ responseContentType: "application/json"
115
+ ```
116
+ From the previous code snippet, we are defining an endpoint ```[MockAPI URL]:[PORT]/users```, which will accept ```get``` requests, answering always with ```200``` status code, using data from ```myRows``` data definition in ```JSON``` format.
117
+
118
+ #### Path parameters
119
+
120
+ Endpoints support path parameters using the ```:param``` syntax. Parameters are extracted from the URL and made available to custom handlers.
121
+
122
+ ```yaml
123
+ "/users/:id":
124
+ verb: get
125
+ data: myRows
126
+ responseStatus: 200
127
+ responseContentType: "application/json"
128
+ ```
129
+
130
+ A request to ```/users/42``` will match this endpoint and extract ```{ id: "42" }``` as path parameters. Multiple path parameters are supported (e.g., ```/users/:userId/orders/:orderId```).
131
+
132
+ A custom handler can then use these parameters:
133
+
134
+ ```javascript
135
+ const process = (requestInformation, data) => {
136
+ const userId = requestInformation.params.id;
137
+ // requestInformation.params contains all extracted path parameters
138
+ // requestInformation.query contains all query string parameters
139
+ return JSON.stringify({ userId, data: JSON.parse(data) });
140
+ };
141
+
142
+ module.exports = { process };
143
+ ```
144
+
145
+ Combining path and query parameters, a request to ```/users/42?fields=name,email``` would provide:
146
+
147
+ ```javascript
148
+ requestInformation.params // { id: "42" }
149
+ requestInformation.query // { fields: "name,email" }
150
+ ```
151
+
152
+ #### Query parameters
153
+
154
+ Query string parameters are automatically parsed from the request URL. For example, a request to ```/users?role=admin&active=true``` will make ```{ role: "admin", active: "true" }``` available in custom handlers via ```requestInformation.query```.
155
+
156
+ #### Response delay
157
+
158
+ Simulate slow API responses by adding a ```delay``` property (in milliseconds) to any endpoint:
159
+
160
+ ```yaml
161
+ "/users":
162
+ verb: get
163
+ data: myRows
164
+ delay: 2000
165
+ responseStatus: 200
166
+ responseContentType: "application/json"
167
+ ```
168
+
169
+ The previous example will wait ```2000ms``` before sending the response, which is useful for testing loading states, spinners and timeout handling.
170
+
171
+ #### Hot-reload
172
+
173
+ MockAPI watches the ```.mockapi-config``` file for changes. When the file is saved, endpoints and data sources are automatically reloaded without restarting the server. This allows you to add, remove, or modify endpoints while the server is running.
174
+
175
+ #### OpenAPI docs
176
+
177
+ MockAPI can auto-generate OpenAPI docs from your configured endpoints and expose them with built-in routes:
178
+
179
+ - ``/openapi.json`` - generated OpenAPI document
180
+ - ``/docs`` - Swagger UI page powered by the generated document
181
+
182
+ These routes update automatically when `.mockapi-config` changes (hot-reload).
183
+ The `/docs` page loads Swagger UI assets from `unpkg.com`.
184
+
185
+ To customize or disable this feature, use the optional `openApi` section:
186
+
187
+ ```yaml
188
+ openApi:
189
+ enabled: true
190
+ docsPath: "/docs"
191
+ specPath: "/openapi.json"
192
+ info:
193
+ title: "My Mock API"
194
+ version: "1.0.0"
195
+ description: "Generated from MockAPI configuration."
196
+ ```
197
+
198
+ Disable docs completely:
199
+
200
+ ```yaml
201
+ openApi:
202
+ enabled: false
203
+ ```
204
+
205
+ #### CORS configuration
206
+
207
+ CORS can be configured in three ways:
208
+
209
+ **Disabled** (default):
210
+ ```yaml
211
+ enableCors: false
212
+ ```
213
+
214
+ **Allow all** (same as previous versions):
215
+ ```yaml
216
+ enableCors: true
217
+ ```
218
+
219
+ **Fine-grained control** — specify allowed origins, methods, and headers:
220
+ ```yaml
221
+ enableCors:
222
+ origins:
223
+ - "http://localhost:3000"
224
+ - "https://myapp.example.com"
225
+ methods:
226
+ - GET
227
+ - POST
228
+ - PUT
229
+ headers:
230
+ - Content-Type
231
+ - Authorization
232
+ ```
233
+
234
+ When using fine-grained CORS, MockAPI automatically handles ```OPTIONS``` preflight requests. If the request origin is not in the allowed list, CORS headers are not set.
235
+
236
+ #### Static file serving
237
+
238
+ MockAPI can serve static files from a local directory. Add the ```staticPath``` property to your configuration:
239
+
240
+ ```yaml
241
+ staticPath: "./public"
242
+ ```
243
+
244
+ When a request does not match any configured endpoint, MockAPI will attempt to serve a matching file from the specified directory. The file's MIME type is determined automatically from its extension. Supported types include HTML, CSS, JavaScript, JSON, PNG, JPG, GIF, SVG, PDF, and more.
245
+
246
+ For example, with ```staticPath: "./public"```, a request to ```/images/logo.png``` will serve the file at ```./public/images/logo.png```.
247
+
248
+ #### HTTPS
249
+
250
+ MockAPI supports HTTPS. Add a ```tls``` section to your configuration with the paths to your certificate and private key files:
251
+
252
+ ```yaml
253
+ tls:
254
+ cert: "./certs/server.crt"
255
+ key: "./certs/server.key"
256
+ ```
257
+
258
+ When TLS is configured, MockAPI starts an HTTPS server instead of HTTP. If the certificate files cannot be read, MockAPI falls back to HTTP and logs an error.
259
+
260
+ To generate a self-signed certificate for local development:
261
+
262
+ ```bash
263
+ openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.crt -days 365 -nodes -subj "/CN=localhost"
264
+ ```
265
+
266
+ #### Custom handlers
267
+
268
+ A custom handler let you manipulate the data as your will. First, define the handler as follows:
269
+
270
+ ```yaml
271
+ customHandlers:
272
+ "custom":
273
+ "myCustomHandler"
274
+ ```
275
+ The previous code defines a custom handler called ```custom``` and will use the script code called ```myCustomHandler```. The custom code must be placed inside of ```scripts``` folder and coded in JavaScript with NodeJS support.
276
+
277
+ Your custom script must implement the following export format:
278
+
279
+ ```javascript
280
+ module.exports = {
281
+ process: [Your function entry point]
282
+ };
283
+ ```
284
+
285
+ #### Setting up the log level
286
+
287
+ MockAPI logs information into the execution console. There are different levels of logs that can be used.
288
+
289
+ ```yaml
290
+ log: verbose
291
+ #debug <- Useful for custom handlers
292
+ #error <- Only exposes internal errors
293
+ #verbose <- Logs debug, information and errors
294
+ #none <- Turn off the logs
295
+ ```
296
+
297
+ ## MockAPI CLI
298
+
299
+ MockAPI provides a small but helpful CLI. Type ```mockapi --help``` to get the available commands from the CLI once MockAPI is installed.
300
+
301
+ #### The ```init``` command
302
+
303
+ Once MockAPI is globally installed, you will need a configuration file with minimal information to be able of start mocking the API. The ```init``` command argument will lead you through different basic questions helping you to initialize this configuration file.
304
+
305
+ ```powershell
306
+ mockapi --init
307
+ ```
308
+
309
+ You can skip every question which will assign some default values to the configuration file. Later you could change these values using any text editor.
310
+
311
+ ## Running MockAPI with Docker
312
+
313
+ MockAPI includes Docker support for running the application in a containerized environment.
314
+
315
+ ### Building the Docker image
316
+
317
+ ```bash
318
+ docker build -t mockapi .
319
+ ```
320
+
321
+ ### Running with Docker
322
+
323
+ ```bash
324
+ docker run -p 3001:8001 -v $(pwd)/.mockapi-config:/usr/src/app/.mockapi-config mockapi
325
+ ```
326
+
327
+ This maps port `3001` on your host to port `8001` inside the container and mounts your local configuration file into the container. Adjust the port mapping to match the `port` value in your `.mockapi-config` file.
328
+
329
+ ### Running with Docker Compose
330
+
331
+ #### Production mode
332
+
333
+ ```bash
334
+ docker compose up
335
+ ```
336
+
337
+ This builds and starts MockAPI using the `docker-compose.yml` file, exposing the API on port `3001`.
338
+
339
+ #### Debug mode
340
+
341
+ ```bash
342
+ docker compose -f docker-compose.debug.yml up
343
+ ```
344
+
345
+ This starts MockAPI with the Node.js inspector enabled on port `9229`, allowing you to attach a debugger. The API is available on port `3000`.
346
+
347
+ ### Mounting custom data and handlers
348
+
349
+ To use your own data files and custom handlers with Docker, mount them as volumes:
350
+
351
+ ```bash
352
+ docker run -p 3001:8001 \
353
+ -v $(pwd)/.mockapi-config:/usr/src/app/.mockapi-config \
354
+ -v $(pwd)/testdata:/usr/src/app/testdata \
355
+ -v $(pwd)/apiHandlers:/usr/src/app/apiHandlers \
356
+ mockapi
357
+ ```
@@ -1,9 +1,26 @@
1
- const action = function (requestInformation, data) {
2
- console.log(data);
3
- console.log(requestInformation);
4
- return JSON.stringify("Hello from custom module");
5
- };
6
-
7
- module.exports = {
8
- process: action
9
- };
1
+ /**
2
+ * Example custom handler for MockAPI.
3
+ *
4
+ * Custom handlers let you manipulate the response for an endpoint.
5
+ * When an endpoint uses a handler, this module processes the data
6
+ * instead of returning it directly.
7
+ *
8
+ * @param {Object} requestInformation - Incoming request details.
9
+ * @param {string} requestInformation.method - HTTP method (get, post, etc.).
10
+ * @param {string} requestInformation.url - Matched endpoint URL.
11
+ * @param {string} requestInformation.body - Raw request body.
12
+ * @param {string} data - Pre-processed data from the configured data reader.
13
+ * @returns {string} The response body to send back to the client.
14
+ */
15
+ const process = (requestInformation, data) => {
16
+ // Example: wrap the data in an envelope with request metadata
17
+ const response = {
18
+ endpoint: requestInformation.url,
19
+ method: requestInformation.method,
20
+ payload: data ? JSON.parse(data) : null
21
+ };
22
+
23
+ return JSON.stringify(response);
24
+ };
25
+
26
+ module.exports = { process };
package/main.js CHANGED
@@ -1,53 +1,87 @@
1
- #!/usr/bin/env node
2
-
3
- 'use strict';
4
-
5
- const LOG = require('./modules/log');
6
- const YAML = require('yaml');
7
- const constants = require('./modules/constants');
8
- const readers = require('./modules/readers');
9
- const ModuleProxy = require('./modules/moduleProxy');
10
- const CLI = require('./modules/cli');
11
- const CORE = require('./modules/core');
12
-
13
- const rootPath = process.cwd();
14
- const configFilePath = `${rootPath}/${constants.CONFIG_FILE_NAME}`;
15
-
16
- const cli = new CLI(configFilePath);
17
-
18
- if (cli.hasCommands()) {
19
- cli.executeCommandLine();
20
- return false;
21
- }
22
-
23
- if (!readers.file_exists(configFilePath)) {
24
- console.log(`Configuration file not found. Please run ${constants.COLOR.fgGreen}--init${constants.COLOR.reset} using the CLI.`);
25
- return false;
26
- }
27
-
28
- const configFile = readers.text_reader(configFilePath);
29
- const parsedConfiguration = YAML.parse(configFile());
30
-
31
- if (parsedConfiguration.port === undefined) throw new Error("port property is required");
32
-
33
- const logLevel = parsedConfiguration.log || constants.LOG_LEVELS.ALL;
34
- const log = new LOG(logLevel);
35
- const moduleProxy = new ModuleProxy(`file://${rootPath}/${(parsedConfiguration.externalModulesPath || constants.EXTERNAL_MODULES_PATH)}`, log);
36
-
37
- if (parsedConfiguration.customHandlers !== undefined) {
38
- moduleProxy.load(parsedConfiguration.customHandlers);
39
- }
40
-
41
- log.message(``);
42
- log.message(`Mock API configuration:`);
43
- log.message(` PORT: ${constants.COLOR.fgGreen}${parsedConfiguration.port}${constants.COLOR.reset}`);
44
- log.message(` CORS enabled: ${parsedConfiguration.enableCors ? constants.COLOR.fgGreen : constants.COLOR.fgRed}${parsedConfiguration.enableCors}${constants.COLOR.reset}`);
45
- log.message(``);
46
-
47
- log.message(`> Mock API attempting to use port: ${constants.COLOR.fgRed}${parsedConfiguration.port}${constants.COLOR.reset}`)
48
-
49
- const core = new CORE(log, parsedConfiguration, moduleProxy);
50
- core.run();
51
-
52
- log.message(`> Mock API listening on port: ${constants.COLOR.fgGreen}${parsedConfiguration.port}${constants.COLOR.reset}`)
53
- log.message(``);
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict';
4
+
5
+ const LOG = require('./modules/log');
6
+ const YAML = require('yaml');
7
+ const constants = require('./modules/constants');
8
+ const readers = require('./modules/readers');
9
+ const ModuleProxy = require('./modules/moduleProxy');
10
+ const CLI = require('./modules/cli');
11
+ const CORE = require('./modules/core');
12
+ const banner = require('./modules/banner');
13
+ const ConfigWatcher = require('./modules/configWatcher');
14
+
15
+ const rootPath = process.cwd();
16
+ const configFilePath = `${rootPath}/${constants.CONFIG_FILE_NAME}`;
17
+
18
+ const cli = new CLI(configFilePath);
19
+
20
+ if (cli.hasCommands()) {
21
+ cli.executeCommandLine();
22
+ process.exit(0);
23
+ }
24
+
25
+ if (!readers.file_exists(configFilePath)) {
26
+ console.log(`Configuration file not found. Please run ${constants.COLOR.fgGreen}--init${constants.COLOR.reset} using the CLI.`);
27
+ process.exit(1);
28
+ }
29
+
30
+ const configFile = readers.text_reader(configFilePath);
31
+ const parsedConfiguration = YAML.parse(configFile());
32
+
33
+ if (parsedConfiguration.port === undefined) throw new Error("port property is required");
34
+
35
+ const logLevel = parsedConfiguration.log || constants.LOG_LEVELS.ALL;
36
+ const log = new LOG(logLevel);
37
+ const moduleProxy = new ModuleProxy(`file://${rootPath}/${(parsedConfiguration.externalModulesPath || constants.EXTERNAL_MODULES_PATH)}`, log);
38
+
39
+ if (parsedConfiguration.customHandlers !== undefined) {
40
+ moduleProxy.load(parsedConfiguration.customHandlers);
41
+ }
42
+
43
+ log.message(``);
44
+ banner.display();
45
+ log.message(`Mock API configuration:`);
46
+ log.message(` PORT: ${constants.COLOR.fgGreen}${parsedConfiguration.port}${constants.COLOR.reset}`);
47
+ log.message(` CORS enabled: ${parsedConfiguration.enableCors ? constants.COLOR.fgGreen : constants.COLOR.fgRed}${!!parsedConfiguration.enableCors}${constants.COLOR.reset}`);
48
+ log.message(` HTTPS: ${parsedConfiguration.tls ? constants.COLOR.fgGreen + 'enabled' : constants.COLOR.fgRed + 'disabled'}${constants.COLOR.reset}`);
49
+ if (parsedConfiguration.staticPath) {
50
+ log.message(` Static files: ${constants.COLOR.fgGreen}${parsedConfiguration.staticPath}${constants.COLOR.reset}`);
51
+ }
52
+ log.message(``);
53
+
54
+ const protocol = parsedConfiguration.tls ? 'https' : 'http';
55
+
56
+ log.message(`> Mock API attempting to use port: ${constants.COLOR.fgRed}${parsedConfiguration.port}${constants.COLOR.reset}`)
57
+
58
+ const core = new CORE(log, parsedConfiguration, moduleProxy);
59
+ core.run();
60
+
61
+ log.message(`> Mock API listening on ${constants.COLOR.fgGreen}${protocol}://localhost:${parsedConfiguration.port}${constants.COLOR.reset}`);
62
+
63
+ const watcher = new ConfigWatcher(configFilePath, log, (newConfig) => {
64
+ core.reload(newConfig);
65
+ log.message(`> Configuration reloaded. Endpoints updated.`);
66
+ });
67
+ watcher.watch();
68
+
69
+ log.message(`> Hot-reload enabled. Watching ${constants.COLOR.fgYellow}${constants.CONFIG_FILE_NAME}${constants.COLOR.reset} for changes.`);
70
+ log.message(``);
71
+
72
+ let isShuttingDown = false;
73
+
74
+ const shutdown = (signal) => {
75
+ if (isShuttingDown) return;
76
+ isShuttingDown = true;
77
+
78
+ log.message(`\n> ${signal} received. Shutting down gracefully...`);
79
+ watcher.stop();
80
+ core.stop(() => {
81
+ log.message(`> Mock API stopped.`);
82
+ process.exit(0);
83
+ });
84
+ };
85
+
86
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
87
+ process.on('SIGINT', () => shutdown('SIGINT'));