@zahid15/mockline 0.0.0-stage → 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ All notable changes to Mockline are documented here. This project follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
5
+ [Semantic Versioning](https://semver.org/).
6
+
7
+ ## [0.1.0] - 2026-10-10
8
+
9
+ ### Added
10
+
11
+ - OpenAPI 3.0/3.1 YAML and JSON loading, route compilation, validation, summaries,
12
+ and warnings for unsupported mocking features.
13
+ - Example selection and deterministic JSON Schema response generation with
14
+ reusable schemas, composition, formats, constraints, hints, and recursion
15
+ depth limits.
16
+ - Request validation modes, conditional/sequence response overrides, latency,
17
+ and injected errors.
18
+ - Optional stateful REST collections, pagination, reset, and CRUD operations.
19
+ - In-memory and JSONL request recording with credential-header redaction, plus
20
+ the local inspector API.
21
+ - Guarded HTTP(S) proxying, proxy-response example capture, and debounced
22
+ OpenAPI/config hot reload.
23
+ - A CLI, typed ESM library API, generated configuration schema, tests, examples,
24
+ Docker image, CI, npm provenance/GHCR release workflow, and benchmark notes.
@@ -0,0 +1,20 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our pledge
4
+
5
+ We pledge to make participation in this project a welcoming and respectful
6
+ experience for everyone, regardless of age, body size, disability, ethnicity,
7
+ gender identity and expression, level of experience, nationality, personal
8
+ appearance, race, religion, or sexual identity and orientation.
9
+
10
+ ## Our standards
11
+
12
+ Examples of positive behavior include being considerate, giving and receiving
13
+ constructive feedback gracefully, and focusing on what is best for the project.
14
+ Unacceptable behavior includes harassment, discriminatory language, personal
15
+ attacks, and publishing another person's private information without consent.
16
+
17
+ ## Enforcement
18
+
19
+ Project maintainers are responsible for clarifying and enforcing these standards.
20
+ Report unacceptable behavior privately to jahidhasann67@gmail.com. Reports will be reviewed and handled fairly and confidentially.
@@ -0,0 +1,27 @@
1
+ # Contributing
2
+
3
+ Thanks for helping improve Mockline. Node.js 20+ and pnpm 9 are required for
4
+ development. Before opening a pull request, run:
5
+
6
+ ```sh
7
+ corepack pnpm install --frozen-lockfile
8
+ corepack pnpm schema:config
9
+ corepack pnpm format:check
10
+ corepack pnpm lint
11
+ corepack pnpm typecheck
12
+ corepack pnpm test
13
+ corepack pnpm build
14
+ corepack pnpm publint
15
+ corepack pnpm attw
16
+ corepack pnpm pack:check
17
+ ```
18
+
19
+ Add focused tests and user-facing documentation for behavior changes. Keep
20
+ `src/` strict-TypeScript and free of explicit `any`; preserve loopback defaults,
21
+ Node 20 compatibility, and the minimal runtime dependency set. Regenerate
22
+ `docs/config.schema.json` after config-schema edits.
23
+
24
+ Use conventional commits (for example, `fix: respect path-level servers`). Do
25
+ not commit credentials, generated coverage, local request records, or temporary
26
+ test output. For security issues, follow [SECURITY.md](SECURITY.md) rather than
27
+ opening a public issue.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zahid Hasan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,365 @@
1
- # Temporary Holding Version
1
+ # Mockline
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Mockline is a local-first OpenAPI mock server and TypeScript library. Point it at
4
+ an OpenAPI 3 document to serve documented routes, choose examples or generate
5
+ schema-conforming responses, validate requests, and optionally keep CRUD state
6
+ in memory. It uses Node's built-in HTTP server and binds to loopback by default.
7
+
8
+ > **npm package:** `@zahid15/mockline`. The unscoped name is already taken;
9
+ > the command is still `mockline`. Use the local build until the first release.
10
+
11
+ ## Highlights
12
+
13
+ - OpenAPI 3.0/3.1 YAML and JSON loading, route listing, validation, and warnings
14
+ for features that cannot be mocked automatically.
15
+ - Example-first or seeded schema generation; generated values are repeatable for
16
+ the same seed, route, method, and request counter.
17
+ - Request validation for path, query, header, cookie, and JSON body parameters;
18
+ `off`, `warn`, and `strict` modes.
19
+ - Optional in-memory REST collection detection for list/create/get/replace/
20
+ patch/delete operations, including seed data and pagination.
21
+ - Per-operation response overrides, conditional rules, sequences, latency, and
22
+ injected errors.
23
+ - Request recording with sensitive-header redaction, a local inspector API,
24
+ and opt-in JSONL persistence.
25
+ - Optional upstream proxying for unmatched routes or all requests, with private
26
+ and link-local destinations blocked by default.
27
+ - Atomic OpenAPI/config hot reload, graceful shutdown, bounded request bodies,
28
+ and configurable HTTP timeouts.
29
+ - ESM-only, typed programmatic API; no Express or other HTTP framework.
30
+
31
+ Mockline is for local development, tests, and demos—not production traffic.
32
+
33
+ ## Preview
34
+
35
+ ![Mockline route listing showing HTTP methods, paths, operation IDs, response statuses, and response sources](docs/screenshots/demo.png)
36
+
37
+ Route listings show each operation's default response status and whether its response comes from an example or schema generation.
38
+
39
+ ## Requirements and installation
40
+
41
+ - Node.js 20 or newer.
42
+ - pnpm 9 for working from this repository; npm can be used to install a
43
+ published package.
44
+
45
+ After the first npm release:
46
+
47
+ ```sh
48
+ npm install --global @zahid15/mockline
49
+ mockline --help
50
+ ```
51
+
52
+ To work from a clone before publishing:
53
+
54
+ ```sh
55
+ corepack pnpm install
56
+ corepack pnpm build
57
+ node dist/cli.js --help
58
+ ```
59
+
60
+ ## Quick start
61
+
62
+ Create a starter config and OpenAPI document in an empty directory:
63
+
64
+ ```sh
65
+ mockline init
66
+ mockline routes openapi.yaml
67
+ mockline validate openapi.yaml
68
+ mockline serve openapi.yaml
69
+ ```
70
+
71
+ The server prints its URL (default `http://127.0.0.1:4010`). Try the starter
72
+ route at `GET /pets`, or use `GET /pets?limit=5`. The inspector is available on
73
+ the loopback bind at `GET /__mockline/health`.
74
+
75
+ To use the checked-in Petstore example from the repository root:
76
+
77
+ ```sh
78
+ mockline routes examples/petstore/openapi.yaml
79
+ mockline validate examples/petstore/openapi.yaml
80
+ mockline serve examples/petstore/openapi.yaml \
81
+ --config examples/petstore/mockline.yaml --port 4010
82
+ ```
83
+
84
+ `--port 0` asks the operating system to choose a free port. Use `--host
85
+ 127.0.0.1` explicitly when running in an environment where the bind address is
86
+ important.
87
+
88
+ ## CLI
89
+
90
+ ```text
91
+ mockline init [--force]
92
+ mockline serve <spec> [options]
93
+ mockline routes <spec>
94
+ mockline validate <spec>
95
+ ```
96
+
97
+ `serve` options:
98
+
99
+ | Option | Description |
100
+ | ------------------------------------ | ------------------------------------------------------------------------------------------------------- |
101
+ | `--config <file>` | Read YAML/JSON config; otherwise discover `mockline.yaml`, `.yml`, or `.json` in the current directory. |
102
+ | `--port <port>` | Listen on this port; `0` selects a free port. |
103
+ | `--host <host>` | Bind address. Defaults to `127.0.0.1`. |
104
+ | `--seed <n>` | Set the deterministic generation seed. |
105
+ | `--prefer <example\|generate>` | Choose examples or generated data when both are available. |
106
+ | `--validate <off\|warn\|strict>` | Set request validation behavior. |
107
+ | `--stateful` | Enable detected in-memory REST collections. |
108
+ | `--delay <ms\|min-max>` | Add fixed or uniformly distributed latency in milliseconds. |
109
+ | `--error-rate <0..1>` | Probability of injecting an error response. |
110
+ | `--error-statuses <codes>` | Comma-separated failure statuses, e.g. `500,503`. |
111
+ | `--proxy <url>` | Forward unmatched requests to an HTTP(S) upstream. |
112
+ | `--proxy-all` | Forward all non-inspector requests to the upstream. Requires `--proxy`. |
113
+ | `--proxy-record <file>` | Save upstream responses as JSON examples for later OpenAPI editing. |
114
+ | `--proxy-allow-private` | Allow private/loopback upstream addresses; use only for a trusted upstream. |
115
+ | `--watch` | Reload valid OpenAPI/config changes without restarting. |
116
+ | `--record-file <path>` | Append request records as JSON Lines. |
117
+ | `--enforce-auth` | Require the presence of credentials declared in OpenAPI security schemes. Does not verify credentials. |
118
+ | `--seed-counter` | Vary seeded responses across repeat requests. |
119
+ | `--cors` / `--no-cors` | Enable (default) or disable CORS. |
120
+ | `--inspector` | Explicitly enable the inspector on a non-loopback bind. |
121
+ | `--quiet`, `--verbose`, `--no-color` | Adjust terminal logging. |
122
+
123
+ Run `mockline serve --help` or `mockline --help` for the generated help text.
124
+
125
+ ## Response selection and controls
126
+
127
+ For each matched operation, Mockline chooses the default documented response
128
+ status, negotiates a response media type from `Accept`, and then:
129
+
130
+ 1. Uses an OpenAPI example by default when one is available.
131
+ 2. Otherwise generates a response from its JSON Schema.
132
+ 3. Returns an empty/default body if the operation has neither a schema nor an
133
+ example.
134
+
135
+ Set `prefer: generate` (or `--prefer generate`) to generate instead of using
136
+ examples. `Prefer: example=<name>` can select a named example. `Prefer:
137
+ code=404` or `X-Mockline-Status: 404` selects a documented status. When control
138
+ headers are enabled, `X-Mockline-Delay: 25` adds a 25 ms delay and
139
+ `X-Mockline-Error: true` forces an injected error. The requested error code is
140
+ the first configured `errors.statuses` value. These controls are intended for
141
+ trusted test clients; disable them with `controlHeaders.allow: false` when
142
+ clients should not be able to alter mock behavior.
143
+
144
+ A seeded response is deterministic for a given operation unless
145
+ `generation.counter`/`--seed-counter` is enabled. Supported JSON Schema
146
+ constraints include primitive types, enum/const/default/example values, common
147
+ formats, numeric and string limits, arrays, object properties, compositions,
148
+ discriminators, and recursive references with a depth limit. Unsupported or
149
+ non-JSON response media types need explicit examples; otherwise the server
150
+ returns a clear `501` response and `mockline validate` reports a warning.
151
+
152
+ See [response behavior](docs/behavior.md), [generation](docs/generation.md), and
153
+ [stateful limitations](docs/stateful.md) for the precise rules.
154
+
155
+ ## Configuration
156
+
157
+ `mockline init` creates a commented `mockline.yaml`. A complete schema is in
158
+ [`docs/config.schema.json`](docs/config.schema.json); see
159
+ [`docs/configuration.md`](docs/configuration.md) for field meanings, defaults,
160
+ overrides, and examples.
161
+
162
+ A minimal config:
163
+
164
+ ```yaml
165
+ port: 4010
166
+ host: 127.0.0.1
167
+ seed: 42
168
+ prefer: example
169
+ validate: warn
170
+ stateful:
171
+ enabled: true
172
+ seedItems: 3
173
+ ```
174
+
175
+ CLI options override the corresponding config fields. The config file is
176
+ reloaded by `--watch`; the bound `host` and `port` cannot be changed without a
177
+ restart.
178
+
179
+ ## Stateful mode
180
+
181
+ Enable `stateful.enabled` or pass `--stateful` to let Mockline detect conventional
182
+ collection pairs in the OpenAPI document: a `GET` list response with an array
183
+ schema, a `POST` on the same path, and a `GET` item route whose response schema
184
+ matches the array's item schema and declares the configured ID property. Matching
185
+ `PUT`, `PATCH`, and `DELETE` item operations are handled too. Collections live
186
+ only in memory; `stateful.seedItems` controls the initial seeded count, and
187
+ `limit`/`offset` query parameters are honored when declared by the list
188
+ operation. `POST /__mockline/reset` clears runtime state and regenerates seeds.
189
+
190
+ The collection detector is intentionally structural, not a general workflow
191
+ engine. Operations that do not match the described shape continue to use normal
192
+ example/schema response selection.
193
+
194
+ ## Request validation and auth
195
+
196
+ - `off`: skip request validation.
197
+ - `warn` (default): serve the selected response, add
198
+ `X-Mockline-Validation: failed`, and include issues in request records.
199
+ - `strict`: return an RFC 9457 `application/problem+json` response (`400` for
200
+ parameter/content-type issues, `422` for invalid/missing request bodies).
201
+
202
+ `--enforce-auth` checks that a credential required by the operation's declared
203
+ OpenAPI security scheme is present. It does not validate API keys, JWTs,
204
+ passwords, scopes, or certificates and is not an authorization system.
205
+
206
+ ## Programmatic API
207
+
208
+ ```ts
209
+ import { createMockServer } from '@zahid15/mockline';
210
+
211
+ const server = await createMockServer({
212
+ spec: './openapi.yaml',
213
+ port: 0,
214
+ seed: 42,
215
+ config: {
216
+ validate: 'strict',
217
+ stateful: { enabled: true, seedItems: 2 },
218
+ },
219
+ });
220
+
221
+ try {
222
+ const response = await fetch(`${server.url}/pets`);
223
+ console.log(await response.json());
224
+ console.log(server.requests({ method: 'GET' }));
225
+ } finally {
226
+ await server.close();
227
+ }
228
+ ```
229
+
230
+ `createMockServer` returns the actual `url`, a typed `requests(filter?)` accessor
231
+ (with `.get(id)` and `.clear()`), `reset()`, `setOverride(key, override)`, and
232
+ `close()`. Close each instance when finished so watchers, sockets, and queued
233
+ writes are drained. `reset()` clears state/sequence/counters; it does not clear
234
+ the request history.
235
+
236
+ See [`examples/programmatic.ts`](examples/programmatic.ts); the package includes
237
+ declarations for the complete typed API.
238
+
239
+ A Vitest test can assert recorded requests without a global server:
240
+
241
+ ```ts
242
+ import { expect, it } from 'vitest';
243
+ import { createMockServer } from '@zahid15/mockline';
244
+
245
+ it('records a request', async () => {
246
+ const server = await createMockServer({ spec: './openapi.yaml', port: 0 });
247
+ try {
248
+ await fetch(`${server.url}/pets`);
249
+ expect(server.requests({ method: 'GET' })).toHaveLength(1);
250
+ } finally {
251
+ await server.close();
252
+ }
253
+ });
254
+ ```
255
+
256
+ ## Inspector and recording
257
+
258
+ On a loopback bind, the inspector is enabled by default. Its endpoints are:
259
+
260
+ | Method | Path | Purpose |
261
+ | -------- | -------------------------- | ------------------------------------------------------------------------------------------------------- |
262
+ | `GET` | `/__mockline/health` | Health and operation count. |
263
+ | `GET` | `/__mockline/spec` | OpenAPI summary, schemas, and warnings. |
264
+ | `GET` | `/__mockline/config` | Effective config with upstream URLs and local file paths redacted. |
265
+ | `GET` | `/__mockline/requests` | Recent records; supports `method`, `path`, `status`, `operationId`, `since`, and `limit` query filters. |
266
+ | `GET` | `/__mockline/requests/:id` | One in-memory record. |
267
+ | `DELETE` | `/__mockline/requests` | Clear in-memory history. |
268
+ | `POST` | `/__mockline/reset` | Reset state and deterministic counters. |
269
+
270
+ The inspector has no authentication. It is disabled by default on non-loopback
271
+ binds; `--inspector` opts in and emits a warning. Do not enable it on an
272
+ untrusted/public interface.
273
+
274
+ Request recording is enabled in memory by default (up to 500 entries). Set
275
+ `recording.file` or pass `--record-file` to append JSONL records. Authorization,
276
+ cookie, API-key, and configured headers are redacted. **Request bodies are not
277
+ redacted** and can contain credentials or personal data; keep recording local,
278
+ limit filesystem access, and do not commit generated logs. `DELETE
279
+ /__mockline/requests` clears memory only; it does not erase an existing JSONL
280
+ file. Writes are flushed during graceful close.
281
+
282
+ ## Proxy mode
283
+
284
+ With `proxy.url`, unmatched routes are forwarded upstream. Add `proxy.all: true`
285
+ (or `--proxy-all`) to forward every non-inspector request. Mockline resolves the
286
+ upstream and blocks private, loopback, link-local, and local-only hostnames by
287
+ default to reduce SSRF risk. This best-effort application check is not a
288
+ substitute for network egress controls (for example, DNS rebinding is not
289
+ prevented). Use `proxy.allowPrivate: true` or `--proxy-allow-private` only when
290
+ the upstream is trusted. Redirects are passed through rather than followed;
291
+ hop-by-hop request/response headers are stripped.
292
+
293
+ `proxy.recordFile` or `--proxy-record` saves upstream response examples in a
294
+ JSON file, atomically replacing it after each record. Proxy recording can
295
+ include sensitive response data, so treat that file as private. Proxy mode is
296
+ optional and does not change the default local mock behavior.
297
+
298
+ ## Docker
299
+
300
+ ```sh
301
+ docker build -t mockline .
302
+ docker run --rm -p 127.0.0.1:4010:4010 \
303
+ -v "$PWD/examples/petstore:/data:ro" \
304
+ mockline serve /data/openapi.yaml --host 0.0.0.0 --port 4010 --inspector
305
+ ```
306
+
307
+ The image runs as an unprivileged user and exposes port 4010. It does not start a
308
+ server by default. Inside a container, bind to `0.0.0.0` to make the port
309
+ reachable through Docker; publish only on trusted interfaces and do not enable
310
+ the inspector on an untrusted network.
311
+
312
+ ## Related tools and limits
313
+
314
+ [Prism](https://github.com/stoplightio/prism) also mocks HTTP APIs from OpenAPI.
315
+ [MSW](https://mswjs.io/) defines request handlers for browser and Node tests.
316
+ [json-server](https://github.com/typicode/json-server) serves REST resources from
317
+ JSON data. Mockline combines OpenAPI-driven HTTP responses with a typed server
318
+ API, request inspection and a small in-memory CRUD store.
319
+
320
+ Swagger 2.0, GraphQL, WebSockets, callbacks and webhooks are unsupported. XML
321
+ and other non-JSON media require examples. Complex schemas may validate as a
322
+ spec but fail automatic generation; see [generation limits](docs/generation.md).
323
+
324
+ ## Roadmap
325
+
326
+ - Broaden pattern/composition generation and constrained stateful ID handling.
327
+ - Add richer media serialization and parameter styles.
328
+ - Expand reload support to watch referenced specification files.
329
+
330
+ ## Local demo
331
+
332
+ ```sh
333
+ pnpm demo
334
+ ```
335
+
336
+ This builds the CLI and exercises examples, seeded generation, forced status,
337
+ latency, strict validation, CRUD, redaction and guarded local proxying. It closes
338
+ its servers automatically and saves output in ignored demo-output/.
339
+
340
+ ## Development and release checks
341
+
342
+ ```sh
343
+ corepack pnpm install
344
+ corepack pnpm schema:config
345
+ corepack pnpm format:check
346
+ corepack pnpm lint
347
+ corepack pnpm typecheck
348
+ corepack pnpm test
349
+ corepack pnpm build
350
+ corepack pnpm publint
351
+ corepack pnpm attw
352
+ corepack pnpm pack:check
353
+ corepack pnpm benchmark -- --duration 5 --concurrency 10
354
+ ```
355
+
356
+ The test suite covers Node.js 20 and 22 in CI. See
357
+ [`docs/benchmark.md`](docs/benchmark.md) for the benchmark method and sample
358
+ results, and [`CONTRIBUTING.md`](CONTRIBUTING.md) for project conventions.
359
+
360
+ Before the first release, confirm the npm account owns `@zahidhasann` and
361
+ follow the initial publication steps. The tag-driven workflow validates the
362
+ version, creates a GitHub release, and optionally publishes npm/GHCR when their
363
+ repository variables are enabled. Subsequent npm releases use trusted publishing
364
+ with GitHub Actions OIDC. See the release checklist in
365
+ [`docs/release.md`](docs/release.md).
package/SECURITY.md ADDED
@@ -0,0 +1,28 @@
1
+ # Security policy
2
+
3
+ Mockline is intended for local development, tests, and demos—not as a
4
+ production API server or authorization system.
5
+
6
+ ## Safe use
7
+
8
+ - Keep the bind address at the loopback default (`127.0.0.1`) unless you
9
+ deliberately need network access.
10
+ - The inspector has no authentication. It is disabled on non-loopback binds by
11
+ default; do not opt it in on a public or untrusted interface.
12
+ - `--enforce-auth` only checks that a credential declared in the OpenAPI
13
+ security scheme is present. It never verifies tokens, keys, scopes, or
14
+ permissions.
15
+ - Proxying blocks local/private destinations by default, but that check is a
16
+ best-effort SSRF guard and does not replace network egress controls. DNS
17
+ rebinding is not pinned away. Only configure trusted upstreams, and opt into
18
+ private destinations only when necessary.
19
+ - Request-record headers are redacted by default, but request bodies and proxy
20
+ response examples are not automatically redacted. Protect generated files and
21
+ avoid recording sensitive payloads.
22
+
23
+ ## Reporting a vulnerability
24
+
25
+ Report security issues to jahidhasann67@gmail.com or through GitHub Security
26
+ Advisories for this repository. Include affected versions, impact, and
27
+ reproduction steps; do not include live credentials or personal data. Please do
28
+ not open a public issue for an unpatched vulnerability.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ declare function runCli(argv?: string[]): Promise<number>;
3
+
4
+ export { runCli };