Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internal refactor: "tagged union" allows us to remove almost all type assertions in TypeResolver #495

Merged
merged 7 commits into from
Oct 3, 2019
Merged
12 changes: 11 additions & 1 deletion README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,16 @@ export interface MyModel {
```

### Overriding route template

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s only related because I had to make changes that would break everyone who has a custom template. Those people using custom templates should probably be told that they’re at risk. If not, then we have to consider every data change to the templates as a breaking change. I don’t want to do that many major versions because people will miss out on cool features then.

If you want functionality that tsoa doesn't provide, then one powerful (but potentially costly approach) is to provide tsoa with a custom handlebars template to use when generating the routes.ts file.

**WARNING** Using a custom template means that you will have a more difficult time migrating to new versions of tsoa since your template interacts with the tsoa internals. So, to get the newest and best features of tsoa, please use one of provided templates by selecting your chosen `"middleware"` (i.e. "koa", "express", or "hapi") and by omitting `"middlewareTemplate"`. **END WARNING**

_Okay, but why would you want to override the route template?_

* Are you using a server framework that we don't yet support? If so, then [please open an issue first](https://github.com/lukeautry/tsoa/issues). It's likely that we will try to accept your custom template as one of the new standard options. If we can't support the new framework, then we'll recommend a custom route template.
* Do you have a very specific requirement? Have you already opened an issue and have the tsoa maintainers opted not to support this feature? Then a custom template might solve your needs best.

Route templates are generated from predefined handlebar templates. You can override and define your own template to use
by defining it in your tsoa.json configuration. Route paths are generated based on the middleware type you have defined.
```json
Expand Down Expand Up @@ -780,7 +790,7 @@ public async find(): Promise<any> {
### Deprecated

Declares this endpoint to be deprecated. Useful for when you are migrating endpoints and wants to keep a outdated
version live until all consumers migrate to use the new endpoint version.
version live until all consumers migrate to use the new endpoint version.

```ts
@Get()
Expand Down
2 changes: 1 addition & 1 deletion src/metadataGeneration/methodGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as ts from 'typescript';
import { getDecorators } from './../utils/decoratorUtils';
import {getJSDocComment, getJSDocDescription, isExistJSDocTag} from './../utils/jsDocUtils';
import { getJSDocComment, getJSDocDescription, isExistJSDocTag } from './../utils/jsDocUtils';
import { GenerateMetadataError } from './exceptions';
import { getInitializerValue } from './initializer-value';
import { MetadataGenerator } from './metadataGenerator';
Expand Down
3 changes: 2 additions & 1 deletion src/metadataGeneration/parameterGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ export class ParameterGenerator {
}

private supportPathDataType(parameterType: Tsoa.Type) {
return ['string', 'integer', 'long', 'float', 'double', 'date', 'datetime', 'buffer', 'boolean', 'enum', 'any'].find(t => t === parameterType.dataType);
const supportedPathDataTypes: Tsoa.TypeStringLiteral[] = ['string', 'integer', 'long', 'float', 'double', 'date', 'datetime', 'buffer', 'boolean', 'enum', 'refEnum', 'any'];
return supportedPathDataTypes.find(t => t === parameterType.dataType);
}

private getValidatedType(parameter: ts.ParameterDeclaration, extractEnum = true) {
Expand Down
121 changes: 106 additions & 15 deletions src/metadataGeneration/tsoa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,46 +95,137 @@ export namespace Tsoa {

export type PrimitiveTypeLiteral = Exclude<TypeStringLiteral, RefTypeLiteral | 'enum' | 'array' | 'void' | 'nestedObjectLiteral' | 'union' | 'intersection'>;

export interface Type {
export interface TypeBase {
dataType: TypeStringLiteral;
}

export interface RefTypeMinimal {
dataType: RefTypeLiteral;
export type PrimitiveType = StringType | BooleanType | DoubleType | FloatType | IntegerType | LongType | VoidType;

/**
* This is one of the possible objects that tsoa creates that helps the code store information about the type it found in the code.
*/
export type Type =
| PrimitiveType
| ObjectsNoPropsType
| EnumType
| ArrayType
| DateTimeType
| DateType
| BinaryType
| BufferType
| ByteType
| AnyType
| RefEnumType
| RefObjectType
| NestedObjectLiteralType
| UnionType
| IntersectionType;

export interface StringType extends TypeBase {
dataType: 'string';
}

export interface BooleanType extends TypeBase {
dataType: 'boolean';
}

/**
* This is the type that occurs when a developer writes `const foo: object = {}` since it can no longer have any properties added to it.
*/
export interface ObjectsNoPropsType extends TypeBase {
dataType: 'object';
}

export interface DoubleType extends TypeBase {
dataType: 'double';
}

export interface FloatType extends TypeBase {
dataType: 'float';
}

export interface EnumerateType extends Type {
export interface IntegerType extends TypeBase {
dataType: 'integer';
}

export interface LongType extends TypeBase {
dataType: 'long';
}

/**
* Not to be confused with `RefEnumType` which is a reusable enum which has a $ref name generated for it. This however, is an inline enum.
*/
export interface EnumType extends TypeBase {
dataType: 'enum';
enums: string[];
enums: Array<string | number>;
}

export interface ArrayType extends TypeBase {
dataType: 'array';

elementType: Type;
}

export interface DateType extends TypeBase {
dataType: 'date';
}

export interface DateTimeType extends TypeBase {
dataType: 'datetime';
}

export interface BinaryType extends TypeBase {
dataType: 'binary';
}

export interface BufferType extends TypeBase {
dataType: 'buffer';
}

export interface ByteType extends TypeBase {
dataType: 'byte';
}

export interface VoidType extends TypeBase {
dataType: 'void';
}

export interface ObjectLiteralType extends Type {
export interface AnyType extends TypeBase {
dataType: 'any';
}

export interface NestedObjectLiteralType extends TypeBase {
dataType: 'nestedObjectLiteral';
properties: Property[];
additionalProperties?: Type;
}

export interface ArrayType extends Type {
dataType: 'array';
elementType: Type;
export interface RefEnumType extends ReferenceTypeBase {
dataType: 'refEnum';
enums: Array<string | number>;
}

export interface RefObjectType extends ReferenceTypeBase {
dataType: 'refObject';
properties: Property[];
additionalProperties?: Type;
}

export interface ReferenceType extends Type, RefTypeMinimal {
export type ReferenceType = RefEnumType | RefObjectType;

export interface ReferenceTypeBase extends TypeBase {
description?: string;
dataType: RefTypeLiteral;
refName: string;
properties?: Property[];
additionalProperties?: Type;
enums?: Array<string | number>;
example?: any;
}

export interface UnionType extends Type {
export interface UnionType extends TypeBase {
dataType: 'union';
types: Type[];
}

export interface IntersectionType extends Type {
export interface IntersectionType extends TypeBase {
dataType: 'intersection';
types: Type[];
}
Expand Down
Loading