Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,21 @@
drift — without reaching into the internal `AttachmentRecord` shape or the
IndexedDB layer. Purely additive; no existing behavior changes.
(`@apicircle/ui-components`)
- **`parseOpenApiRequestBodies(source, format, deps)` parser export
(`@apicircle/mock-server-core`).** A new additive export that returns each
operation's **request-body schema** — the one part of an operation's contract
the mock pipeline deliberately drops (`MockEndpoint` carries no request body,
since the mock server never validates request bodies). It walks the same
dereferenced operations as `parseOpenApiToEndpoints` and emits
`{ method, path, contentType, schema, required }` per operation: OpenAPI 3.x
`requestBody` content (a JSON media type preferred) and Swagger 2.0
`in: 'body'` parameters both reduce to the same shape. Exposed browser-safe
from the `/parsing` subpath and swagger-parser-backed from the Node root
(mirroring `parseOpenApiToEndpoints`), so a consumer — e.g. the Lens
code-vs-spec contract-drift check — can read a request body's declared shape
and join it to the endpoint table by `(method, path)`, without touching
`MockEndpoint` or the mock runtime. Purely additive.
(`@apicircle/mock-server-core`)

## 1.3.0 - 2026-07-18

Expand Down
25 changes: 25 additions & 0 deletions docs/mock-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,31 @@ const handle = await startMockServer({
await handle.close();
```

### Request-body schemas

`parseSourceToEndpoints` intentionally drops request bodies — the mock server
responds, it never validates the request payload, so `MockEndpoint` carries no
request-body shape. When a consumer needs the shape a spec _declares_ for a
request (e.g. the Lens edition's code-vs-spec contract drift), the additive
`parseOpenApiRequestBodies(source, format, deps)` export returns it separately,
one entry per operation that declares a body:

```ts
import { parseOpenApiRequestBodies } from '@apicircle/mock-server-core';
// browser / renderer: '@apicircle/mock-server-core/parsing'

const { requestBodies } = await parseOpenApiRequestBodies(rawSpec, 'yaml');
// → [{ method: 'POST', path: '/pets', contentType: 'application/json',
// schema: { … }, required: true }, … ]
```

OpenAPI 3.x `requestBody` (a JSON media type preferred) and Swagger 2.0
`in: 'body'` parameters both reduce to the same `{ method, path, contentType,
schema, required }` shape. It follows the same two-entry-point `$ref` contract
as the endpoint parser (root = swagger-parser, `/parsing` = in-document only)
and leaves `MockEndpoint` and the mock runtime untouched; join it back to
`parseSourceToEndpoints` by `(method, path)` for an operation's full contract.

## Port binding errors

`startMockServer` (and the Desktop / VS Code / CLI wrappers around it) throws
Expand Down
23 changes: 23 additions & 0 deletions packages/mock-server-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,29 @@ slow regions, and "what does the app do when this call returns 500?".
await handle.close();
```

## Extracting request-body schemas

The mock pipeline doesn't model request bodies — a mock server responds, it
doesn't validate what you send it — so `parseSourceToEndpoints` drops them. When
you need the **shape a spec declares for a request** (say, to diff it against
what your code actually reads), `parseOpenApiRequestBodies` returns it directly:

```ts
import { parseOpenApiRequestBodies } from '@apicircle/mock-server-core';
// browser / renderer: import from '@apicircle/mock-server-core/parsing'

const { requestBodies, warnings } = await parseOpenApiRequestBodies(rawYamlOrJson, 'yaml');
// → [{ method: 'POST', path: '/pets', contentType: 'application/json',
// schema: { type: 'object', properties: { … } }, required: true }, … ]
```

One entry per operation that declares a body: OpenAPI 3.x `requestBody` (a JSON
media type preferred) and Swagger 2.0 `in: 'body'` parameters both reduce to the
same `{ method, path, contentType, schema, required }` shape. Join it back to
`parseSourceToEndpoints` by `(method, path)` for an operation's full contract.
Same `$ref` contract as the endpoint parser — the Node root resolves external
refs via swagger-parser; the `/parsing` subpath resolves in-document refs only.

## Format support matrix

| Format | Versions | What we pull out |
Expand Down
8 changes: 5 additions & 3 deletions packages/mock-server-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ export type { MockServerHandle, ServeOptions } from './runtime/nodeAdapter';
export { MockServerStartError } from './runtime/nodeAdapter';
export type { BuildRouterOptions } from './handlers/buildRouter';
export { openApiPathToHono } from './handlers/buildRouter';
// The Node entry exposes the swagger-parser-backed OpenAPI parser as the
// canonical `parseOpenApiToEndpoints` so CLI / MCP consumers get full
// external-reference resolution.
// The Node entry exposes the swagger-parser-backed OpenAPI parsers as the
// canonical `parseOpenApiToEndpoints` / `parseOpenApiRequestBodies` so CLI /
// MCP consumers get full external-reference resolution.
export { parseOpenApiToEndpointsNode as parseOpenApiToEndpoints } from './parsers/openapiNode';
export { parseOpenApiRequestBodiesNode as parseOpenApiRequestBodies } from './parsers/openapiNode';
export type { ParseOpenApiRequestBodiesResult, OpenApiRequestBodySpec } from './parsers/openapi';
export { parsePostmanToEndpoints } from './parsers/postman';
export { parseInsomniaToEndpoints } from './parsers/insomnia';
export { schemaToExample } from './faker/schemaToExample';
Expand Down
Loading
Loading