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

Support registry and async in toHttpEvent handlers #9

Merged
merged 1 commit into from
Oct 31, 2023
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
20 changes: 10 additions & 10 deletions packages/rest/src/runtime/error.mts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {HttpRequest, HttpResponse} from './http-event.mjs';
import {Result} from "@nornir/core";
import {AttachmentRegistry, Result} from "@nornir/core";

/**
* Base error type for exceptions in rest handlers.
* Can be directly converted into a HTTP response.
*/
export abstract class NornirRestError extends Error implements NodeJS.ErrnoException {
public abstract toHttpResponse(): HttpResponse;
public abstract toHttpResponse(registry: AttachmentRegistry): HttpResponse | Promise<HttpResponse>;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
public static isNornirRestError(err: any): err is NornirRestError {
Expand All @@ -25,18 +25,18 @@ export abstract class NornirRestRequestError<Request extends HttpRequest> extend
super(message);
}

abstract toHttpResponse(): HttpResponse;
abstract toHttpResponse(registry: AttachmentRegistry): HttpResponse | Promise<HttpResponse>;
}

interface ErrorMapping {
errorMatch(error: unknown): boolean;
toHttpResponse(error: unknown): HttpResponse;
toHttpResponse(error: unknown, registry: AttachmentRegistry): HttpResponse | Promise<HttpResponse>;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function mapErrorClass<T extends NodeJS.ErrnoException, TClass extends new (...args: any) => T>(error: TClass, toHttpResponse: (err: T) => HttpResponse): ErrorMapping;
export function mapErrorClass<T extends NodeJS.ErrnoException, TClass extends new (...args: any) => T>(error: TClass, toHttpResponse: (err: T, registry: AttachmentRegistry) => HttpResponse | Promise<HttpResponse>): ErrorMapping;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function mapErrorClass<T extends Error, TClass extends new (...args: any) => T>(error: TClass, toHttpResponse: (err: T) => HttpResponse): ErrorMapping {
export function mapErrorClass<T extends Error, TClass extends new (...args: any) => T>(error: TClass, toHttpResponse: (err: T, registry: AttachmentRegistry) => HttpResponse | Promise<HttpResponse>): ErrorMapping {
return {
errorMatch: (err: unknown): err is T => err instanceof error,
toHttpResponse
Expand All @@ -50,19 +50,19 @@ export function mapError<T>(errorMatch: (err: unknown) => err is T, toHttpRespon
}
}

export function httpErrorHandler(errorMappings?: ErrorMapping[]): (input: Result<HttpResponse>) => HttpResponse {
export function httpErrorHandler(errorMappings?: ErrorMapping[]): (input: Result<HttpResponse>, registry: AttachmentRegistry) => Promise<HttpResponse> {
const defaultedErrorMappings = errorMappings || [];

return (input: Result<HttpResponse>) => {
return async (input: Result<HttpResponse>, registry: AttachmentRegistry) => {
if (input.isErr) {
const error = input.error;
const mapping = defaultedErrorMappings.find(mapping => mapping.errorMatch(error));
const responseConverter = mapping?.toHttpResponse
if (responseConverter != undefined) {
return responseConverter(error);
return responseConverter(error, registry);
}
if (NornirRestError.isNornirRestError(error)) {
return error.toHttpResponse();
return error.toHttpResponse(registry);
}
}
return input.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion packages/test/src/rest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
) {}
}

const frameworkChain = nornir<UnparsedHttpEvent>()
.use(normalizeEventHeaders)
.use(httpEventParser({
"text/csv": body => ({ cool: "stuff" }),

Check warning on line 36 in packages/test/src/rest.ts

View workflow job for this annotation

GitHub Actions / Lint Back-end code

'body' is defined but never used. Allowed unused args must match /^_/u
}))
.use(router())
.useResult(httpErrorHandler([
mapErrorClass(TestError, err => ({
mapErrorClass(TestError, (err) => ({

Check warning on line 40 in packages/test/src/rest.ts

View workflow job for this annotation

GitHub Actions / Lint Back-end code

'err' is defined but never used. Allowed unused args must match /^_/u

Check warning on line 40 in packages/test/src/rest.ts

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🕹️ Function is not covered

Warning! Not covered function
statusCode: HttpStatusCode.InternalServerError,
headers: {
"content-type": AnyMimeType,
Expand Down
Loading