tsoa

repository·master·Indexed 26 days ago

https://github.com/lukeautry/tsoa

A framework for building OpenAPI-compliant REST APIs in Node.js using TypeScript. tsoa leverages TypeScript types and decorators to automatically generate OpenAPI specifications (version 2.0 or 3.0) and routing code for middleware such as Express, Hapi, or Koa, ensuring the API implementation and documentation remain in sync.

Tokens
7K
Snippets
5
Records
61
Agent score
87%

What's inside tsoa

  1. Overview of tsoa

    master

    tsoa is a tool for building OpenAPI-compliant REST APIs using TypeScript and Node. It uses TypeScript controllers and models as the single source of truth to automatically generate a valid OpenAPI specification (version 2.0 or 3.0) and routes for middleware like Express, Hapi, or Koa.

    Key features include:

    • Automatic generation of OpenAPI paths, definitions, and parameters based on TypeScript types.
    • Support for jsDoc to provide object descriptions.
    • Automatic route generation and request payload validation.
    • Support for both interfaces and classes as models.
  2. Use local interface abstractions to protect API contracts

    master

    Using local interface abstractions instead of direct external types provides a layer of protection against breaking changes in third-party libraries.

    If an external dependency changes its internal data structure (e.g., changing name: string to firstName: string and lastName: string), your TSOA-generated Swagger documentation will remain stable because it is tied to your local IUserAbstraction. You can then handle the translation logic internally within your controller to map your stable API contract to the new library requirements, preventing 400 BAD REQUEST errors for your API consumers.

    import * as externalDependency from 'some-external-dependency';
    
    // Your stable API contract
    interface IUserAbstraction {
        name: string;
    }
    
    @Route('Users')
    export class UsersController {
    
        @Post()
        public async Create(@Body() user: IUserAbstraction): Promise<void> {
            // Translate the stable abstraction into the shape the library now expects
            const namePortions = user.name.split(" ");
            const libUser: externalDependency.IUser = {
                firstName: namePortions[0],
                lastName: namePortions[1]
            };
            
            // Pass the translated object to the dependency
            return externalDependency.doStuff(libUser);
        }
    }
  3. Configure Hapi authentication with tsoa

    master

    If your controllers use security decorators, tsoa generates an authenticateMiddleware function within the routes file. This function uses a provided hapiAuthentication module to validate requests.

    To use this, you must provide an authenticationModule in your tsoa configuration, which should export a hapiAuthentication function compatible with the generated logic.

  4. Configure tsoa via configuration files

    master

    tsoa supports multiple configuration file formats. You can specify the path to your configuration file using the --configuration or -c flag. Supported formats include:

    • JSON: Standard .json files.
    • YAML: .yaml or .yml files.
    • JavaScript: .js or .cjs files (these are imported as modules).

    If no configuration file is provided, the CLI defaults to looking for tsoa.json in the current working directory.

  5. Fix 'No matching model found for referenced type' error

    master

    This error occurs when TSOA attempts to generate a Swagger/OpenAPI model from an interface located in an external dependency (inside node_modules). TSOA does not crawl node_modules for performance and architectural reasons (to prevent external library updates from unintentionally changing your API contract).

    Solution: Create a local interface within your own codebase that mirrors the structure of the external interface. Use this local interface in your TSOA controllers and decorators. Because TypeScript uses structural subtyping, your local interface can be passed into functions expecting the external interface as long as the shapes match.

    import * as externalDependency from 'some-external-dependency';
    
    // 1. Create a local abstraction of the external interface
    interface IUserAbstraction {
        name: string;
    }
    
    @Route('Users')
    export class UsersController {
    
        /**
         * Create a user
         * @param request This is a user creation request description
         */
        @Post()
        public async Create(@Body() user: IUserAbstraction): Promise<void> {
            // 2. Use the local interface for the @Body type
            // 3. Map the local data to the external dependency's expected shape if necessary
            return externalDependency.doStuff(user as any);
        }
    }
  6. Determine if additional properties are allowed in a schema

    master
    When working with Swagger/OpenAPI schemas generated by tsoa, additionalProperties might be undefined. Use the isDefaultForAdditionalPropertiesAllowed function to check if undefined should be interpreted as allowing additional properties (a
  7. Define OpenAPI extensions via JSDoc comments

    master

    tsoa supports defining OpenAPI extensions through JSDoc comments. To use this, provide a JSON-formatted comment block. Each key in the JSON object will be treated as an extension key and its corresponding value will be assigned to it.

    Requirements:

    • The keys within the JSON object must start with the x- prefix to be considered valid OpenAPI extensions.
  8. Generate API metadata with MetadataGenerator.Generate()

    master

    The Generate() method triggers the metadata extraction process. It performs the following steps:

    1. Extracts controller nodes from the program source files.
    2. Builds controller definitions using ControllerGenerator.
    3. Validates that there are no duplicate method signatures (e.g., same HTTP method and path).
    4. Validates that there are no overlapping or duplicate path parameter definitions.

    Returns a Tsoa.Metadata object containing controllers and a referenceTypeMap.