Skip to content
TypeWire

@tahanabavi/typewire-nestjs

v4.0.0

NestJS integration for the TypeWire ecosystem — serve one set of Zod contracts over every wire your client speaks: REST/HTTP, gRPC (Connect JSON), GraphQL and typesocket WebSocket gateways, with request/response validation on all of them.

OpenAPI / Swagger from contracts

The same contracts generate a full OpenAPI 3.0 document — method, path, params, request body, and responses all derived from the Zod schemas, so your API docs can never drift from what the client calls.

ts
import { NestFactory } from '@nestjs/core'
import { setupContractSwagger } from '@tahanabavi/typewire-nestjs'
import { contracts } from './contracts'

const app = await NestFactory.create(AppModule)

setupContractSwagger(app, contracts, {
path: 'docs',
info: { title: 'My API', version: '1.0.0' },
})

await app.listen(3000)
// Swagger UI → http://localhost:3000/docs
// Raw JSON → http://localhost:3000/docs-json

@nestjs/swagger is an optional peer dependency — install it only if you use setupContractSwagger(). Prefer to serve the document yourself? Build the plain object directly:

ts
import { buildOpenApiDocument } from '@tahanabavi/typewire-nestjs'

const document = buildOpenApiDocument(contracts, {
info: { title: 'My API', version: '1.0.0' },
})
// hand to SwaggerModule.setup(), write to disk, feed a client generator, ...

What the generator maps from each contract endpoint:

ContractOpenAPI
path: "/users/:id"/users/{id} with a required id path parameter
request.path / request.query / request.headerstyped parameters (array query params → explode: true, matching repeated-key serialization)
request.body (or a flat request)requestBody — application/json, or multipart/form-data when bodyType: "form-data"
responsethe success response (201 for POST, 200 otherwise)
z.date() / z.bigint() / file fieldsstring+date-time / string+int64 / string+binary (never throws)
auth: truebearerAuth security requirement + documented 401
—a shared ContractValidationError schema on every 400

Options: bearerAuth (default on), includeValidationError (default on), servers, and successStatus(endpoint) to override the documented success code.

Exports

@tahanabavi/typewire-nestjs

ExportKindPurpose
TypeFetchEndpointdecoratorBind route + validation from an http contract endpoint
UseContractdecoratorValidation only, on manually declared routes — any transport
ContractInput / ContractPath / ContractQuery / ContractBody / ContractHeadersparam decoratorsValidated request data
TypeFetchModulemoduleforRoot() global options
ContractValidationInterceptorinterceptorApplied automatically; exported for advanced wiring
ResponseEnvelopeInterceptor / ContractEnvelopeExceptionFilterinterceptor / filterResponse-envelope success + error wrapping
decryptRequestBody / encryptResponseData / encryptValue / decryptValuefunctionsField-level encryption building blocks
getContractEndpointhelperRead the bound endpoint in guards/interceptors
createPermissionGuardfunctionBuild a guard enforcing the contract's permission key → typed 403
RequirePermissiondecoratorDeclare/override a permission requirement on a route
PermissionGuardConfig / PermissionDecisionLiketypesConfig and decision shapes for the permission guard
setupContractSwaggerhelperBuild + mount Swagger UI from contracts
buildOpenApiDocumentfunctionContracts → plain OpenAPI 3.0 document
InferRequest / InferResponse / ContractHandlertypesEnd-to-end handler typing
ContractValidationException / ContractResponseViolationExceptionexceptionsThrown on 400 / 500
formatZodIssues, coerceInput, validateRequestutilitiesBuilding blocks for custom pipelines
contractFile / isContractFile / CONTRACT_EXPOSED_HEADERSfunction / helpersNon-JSON responseType responses and the headers they need
SkipEnvelopedecoratorExempt a route from the global response envelope
transportOf / isHttpEndpoint / assertTransport / describeContractRoutehelpersRead an endpoint's wire without touching a field it may not have
TYPEFETCH_ENDPOINT_METADATA, TYPEFETCH_OPTIONS_METADATA, TYPEFETCH_MODULE_OPTIONS, TYPEFETCH_PERMISSION_METADATA, TYPEFETCH_SKIP_ENVELOPE_METADATA, PARSED_REQUEST_KEYconstantsMetadata & DI tokens

@tahanabavi/typewire-nestjs/grpc

ExportKindPurpose
GrpcEndpointdecoratorBind a Connect JSON route from a transport: "grpc" contract
GrpcExceptionexceptionThrow a specific gRPC status from a handler
GrpcDeadlineparam decoratorThe caller's deadline, with an AbortSignal
ConnectExceptionFilter / ConnectDeadlineInterceptorfilter / interceptorApplied automatically; exported for manual wiring
toConnectError / codeFromThrownStatus / parseDeadlinefunctionsThe mapping rules, testable on their own
GrpcCode / codeName / statusFromGrpcCodere-exportsFrom @tahanabavi/typefetch-grpc, so a handler needs one import

@tahanabavi/typewire-nestjs/graphql

ExportKindPurpose
ContractGraphQLModulemoduleforRoot({ contracts, path?, allowGet?, requireAllResolvers? })
GraphQLEndpointdecoratorMark a provider method as the resolver for a GraphQL contract
GraphqlExceptionexceptionThrow a specific extensions.code
ContractGraphQLRegistry / ContractGraphQLDispatcherservicesThe operation index and the request pipeline
toGraphqlError / graphqlCodeFromStatus / statusFromGraphqlCodefunctionsThe mapping rules

@tahanabavi/typewire-nestjs/socket

ExportKindPurpose
bindSocketContractsfunctionGive every contract event its wire name and id
SocketEventdecoratorBind a gateway handler to a client->server event
SocketPayload / SocketEventInfoparam decoratorsThe validated frame; the bound event
emitSocketEvent / createSocketEmitterfunctionsPush a server->client event, validated
createSocketPermissionGuardfunctionEnforce an event's contract permission server-side
SocketContractException / SocketAckInterceptorexception / interceptorContract failures on a frame; ack validation
InferSocketRequest / InferSocketAck / InferSocketPayloadtypesEnd-to-end gateway typing

License

MIT © Taha Nabavi