Skip to content

docs(api): document the response envelope (JSDoc + Swagger @ApiOkResponse examples)#490

Open
dorisadams wants to merge 1 commit into
MERIDIAN-CITY:mainfrom
dorisadams:docs/response-envelope-jsdoc-and-swagger
Open

docs(api): document the response envelope (JSDoc + Swagger @ApiOkResponse examples)#490
dorisadams wants to merge 1 commit into
MERIDIAN-CITY:mainfrom
dorisadams:docs/response-envelope-jsdoc-and-swagger

Conversation

@dorisadams

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #488 and #489. Adds developer-facing documentation so consumers learn the { apiversion, result, data } envelope shape from the source and from the OpenAPI spec at /api instead of discovering it at runtime.

What this PR adds

1. JSDoc on the interceptor (src/common/interceptors/data-response.interceptor.ts)

2. Swagger @ApiOkResponse examples (src/common/decorators/api-envelope-response.decorator.ts + src/common/dto/envelope.dto.ts)

  • New EnvelopeDto Swagger model with @ApiProperty decorators matching the runtime DataResponseEnvelope<T> interface (data is described via oneOf over object / array / string / number / integer / boolean / null).
  • New @ApiEnvelopeResponse({ dataExample, status, description }) decorator that drops in for @ApiOkResponse on every controller method that returns success. It:
    • Always emits @ApiExtraModels(EnvelopeDto) so the $ref resolves on first use.
    • References the envelope via getSchemaPath(EnvelopeDto) (idiomatic NestJS, honors custom OpenAPI prefixes).
    • Augments the schema with an example payload whose result is derived from dataExample using the same rule the interceptor applies at runtime — so docs and code cannot drift.

3. Application per controller (users, post, tweets, auth)

  • Every success @ApiResponse decorator was replaced with @ApiEnvelopeResponse(...) carrying a representative dataExample for that route.
  • Error @ApiResponse decorators (4xx) are kept as-is.
  • Pre-existing unused imports in these controllers were cleaned up to keep the diff ESLint-clean.

4. Site-wide mention in Swagger description (src/main.ts)

  • DocumentBuilder().setDescription() now opens with a "## Response envelope" Markdown section explaining apiversion, result, and data so consumers see the contract at the top of /api even before drilling into a tag.

5. Test-suite plumbing (jest.setup.ts)

  • Adds a virtual jest.mock for the new envelope decorator module (alias path only — the relative-path variant that no spec ever uses was dropped per code-review feedback) so existing specs can keep loading controller modules without pulling in the real Swagger metadata machinery.

Out of scope

  • src/tag/tag.controller.ts has no Swagger decorators — added as a follow-up.
  • src/app.controller.ts is the trivial / hello-world route.
  • src/health/health.controller.ts returns a Terminus HealthCheckResult shape that is not wrapped in the envelope, so documenting it as envelope-wrapped would be a contract lie.

Verification

  • tsc -p tsconfig.build.json --noEmit -> clean.
  • eslint on every touched file -> clean.
  • jest src/auth/auth.controller.spec.ts -> 6/6 pass (the spec exercises the new envelope decorator import chain via the controller).

Follow-up chain

Fixes the user request from the dorisadams follow-up flow.

…onse examples)

Follow-up to MERIDIAN-CITY#488. Adds developer-facing documentation so consumers learn
the {apiversion, result, data} envelope shape from the source and the
OpenAPI spec at /api instead of discovering it at runtime.

### Files added

- meridian-api/src/common/dto/envelope.dto.ts
  -- Swagger EnvelopeDto class with @ApiProperty decorators matching
     the runtime DataResponseEnvelope interface. `data` is described via
     oneOf covering object / array / string / number / integer /
     boolean / null.

- meridian-api/src/common/decorators/api-envelope-response.decorator.ts
  -- @ApiEnvelopeResponse({ dataExample, status, description }) drops
     in for @ApiOkResponse on every controller method that returns
     success. Always emits @ApiExtraModels(EnvelopeDto) so the $ref
     resolves on first use, and derives `result` from the example's
     shape using the same rule the interceptor applies at runtime.

### Files modified

- meridian-api/src/common/interceptors/data-response.interceptor.ts
  -- Adds JSDoc to API_VERSION, DataResponseEnvelope<T>, the class
     itself, intercept(), and transform(). transform() carries
     @returns + four @example blocks (array, single-object, primitive,
     null). intercept() and transform() carry @throws {never} to make
     the no-throw contract machine-discoverable.

- meridian-api/src/main.ts
  -- DocumentBuilder().setDescription() now opens with a "## Response
     envelope" Markdown section explaining apiversion, result and data
     so consumers see the contract at the top of /api.

- meridian-api/src/users/users.controller.ts
- meridian-api/src/post/post.controller.ts
- meridian-api/src/tweets/tweet.controller.ts
- meridian-api/src/auth/auth.controller.ts
  -- Each success @apiresponse gets replaced with @ApiEnvelopeResponse
     and a representative dataExample. Error @apiresponse decorators
     are kept. Pre-existing unused imports (Put, ValidationPipe,
     UseGuards, SetMetadata, AccessTokenGuard, DefaultValuePipe,
     GetPostsParamDto) are removed to keep the diff ESLint-clean.

- meridian-api/jest.setup.ts
  -- Adds a virtual jest.mock for the new envelope decorator module
     (and only the alias path that specs actually use) so existing
     specs can keep loading controller modules without pulling in the
     real Swagger metadata machinery.

### Out of scope

- src/tag/tag.controller.ts has no Swagger decorators yet.
- src/app.controller.ts is the trivial `/` hello-world route.
- src/health/health.controller.ts returns a Terminus HealthCheckResult
  that is NOT wrapped in the envelope, so documenting it as envelope-
  wrapped would be a contract lie.

### Verification

- `tsc -p tsconfig.build.json --noEmit` -> clean.
- `eslint` on the touched files -> clean.
- `jest src/auth/auth.controller.spec.ts` -> 6 / 6 pass.

Follow-up to MERIDIAN-CITY#488 and MERIDIAN-CITY#489.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant