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

fix tsoa endpoint #111

Merged
merged 1 commit into from
Aug 21, 2024
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## v16.1.3

- Fix `@alanszp/express`: Fix types for `BaseApi.buildAuthEndpoint`. Now it recognizes view and command and infers endpoint response correctly.

## v16.1.2

- Fix `@alanszp/queue`: `Worker.processFailed` now logs an error instead of a warning.
Expand Down
59 changes: 24 additions & 35 deletions packages/express/src/endpoints/BaseApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,43 @@ function isViewable<T>(object: unknown): object is Viewable<T> {
);
}

type DefaultViewFnReturn<CommandReturnType> =
CommandReturnType extends Viewable<infer ViewReturnType>
? ViewReturnType
: CommandReturnType;

type InferReturnType<
ViewFunction extends
| ((crt: CommandReturnType, input: unknown) => unknown)
| undefined,
CommandReturnType
> = ViewFunction extends (crt: CommandReturnType, input: unknown) => unknown
? ReturnType<ViewFunction>
: DefaultViewFnReturn<CommandReturnType>;

export type BuildAuthEndpointOptions<
Input extends BaseModel,
CommandReturnType,
ViewReturnType,
ViewFunction extends
| ((crt: CommandReturnType, input: Input) => ViewReturnType)
| ((crt: CommandReturnType, input: Input) => unknown)
| undefined
> = {
request: AuthRequest;
inputConstructor: (jwtUser: JWTUser) => Promise<Input> | Input;
command: (
input: Input
) => Promise<CommandReturnType & Partial<Viewable<ViewReturnType>>>;
command: (input: Input) => Promise<CommandReturnType>;
returnCode?: number;
view?: ViewFunction;
getLogger: () => ILogger;
};

type InferReturnType<ViewFunction, CommandReturnType, ViewReturnType> =
ViewFunction extends undefined // If no view function is provided
? CommandReturnType extends Viewable<ViewReturnType> // If the command response has a toView method
? ViewReturnType // Return the view return type
: CommandReturnType // Otherwise, it doesn't have a toView method, return the command return type
: ViewReturnType; // Otherwise, it has a view function, return the view return type

export class BaseApi extends Controller {
protected async buildAuthEndpoint<
Input extends BaseModel,
CommandReturnType,
ViewReturnType,
ViewFunction extends
| ((crt: CommandReturnType, input: Input) => ViewReturnType)
| undefined
| ((crt: CommandReturnType, input: Input) => unknown)
| undefined,
EndpointReturnType extends InferReturnType<ViewFunction, CommandReturnType>
>({
request,
inputConstructor,
Expand All @@ -62,11 +66,8 @@ export class BaseApi extends Controller {
}: BuildAuthEndpointOptions<
Input,
CommandReturnType,
ViewReturnType,
ViewFunction
>): Promise<
InferReturnType<ViewFunction, CommandReturnType, ViewReturnType>
> {
>): Promise<EndpointReturnType> {
const { path, method, user } = request;
const baseLog = `${snakeCase(path)}.${snakeCase(method)}`;
const logger = getLogger();
Expand All @@ -82,27 +83,15 @@ export class BaseApi extends Controller {

// If a view function is provided, use it to transform the command response
if (view) {
return view(commandResponse, input) as InferReturnType<
ViewFunction,
CommandReturnType,
ViewReturnType
>;
return view(commandResponse, input) as EndpointReturnType;
}

// If the command response is viewable, use it to transform the command response
if (isViewable<ViewReturnType>(commandResponse)) {
return commandResponse.toView() as InferReturnType<
ViewFunction,
CommandReturnType,
ViewReturnType
>;
if (isViewable<EndpointReturnType>(commandResponse)) {
return commandResponse.toView();
}

// Otherwise, return the command response as is
return commandResponse as InferReturnType<
ViewFunction,
CommandReturnType,
ViewReturnType
>;
return commandResponse as EndpointReturnType;
}
}
Loading