-
Notifications
You must be signed in to change notification settings - Fork 164
feat(event-handler): add base router class #3972
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
Merged
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
8a3ea37
feat(event-handler): add base router class
dreamorosi 7f6d0f6
chore: remove file
dreamorosi 9851298
add methods for all http verbs and unit tests for them
svozza 1711ad1
address PR comments
svozza c50d16c
add Path type to enfoce opening slash
svozza d7baca8
use constants to get HTTP verbs
svozza 0cce09c
Updtae test name
svozza a553aad
add prepare/act/assess comments
svozza 8a2bfcf
add options, trace and connect methods
svozza 8888c3c
Update no logger global console test name
svozza 5dd0f6c
Add route to console test to fix SQ issue
svozza 570ad3d
Add route in log tests to fix SQ issue
svozza 4f4708f
Update debug log test name
svozza 650a580
update custom logger test name
svozza 078108c
Update packages/event-handler/tests/unit/rest/BaseRouter.test.ts
svozza 730dfc5
fix type error in logging unit tests
svozza 7bfd769
Merge branch 'main' into feat/evt_handler_base_router
dreamorosi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
import type { GenericLogger } from '@aws-lambda-powertools/commons/types'; | ||
import { isRecord } from '@aws-lambda-powertools/commons/typeutils'; | ||
import { | ||
getStringFromEnv, | ||
isDevMode, | ||
} from '@aws-lambda-powertools/commons/utils/env'; | ||
import type { Context } from 'aws-lambda'; | ||
import type { ResolveOptions } from '../types/index.js'; | ||
import type { | ||
HttpMethod, | ||
Path, | ||
RouteHandler, | ||
RouteOptions, | ||
RouterOptions, | ||
} from '../types/rest.js'; | ||
import { HttpVerbs } from './constatnts.js'; | ||
|
||
abstract class BaseRouter { | ||
protected context: Record<string, unknown>; | ||
/** | ||
* A logger instance to be used for logging debug, warning, and error messages. | ||
* | ||
* When no logger is provided, we'll only log warnings and errors using the global `console` object. | ||
*/ | ||
protected readonly logger: Pick<GenericLogger, 'debug' | 'warn' | 'error'>; | ||
/** | ||
* Whether the router is running in development mode. | ||
*/ | ||
protected readonly isDev: boolean = false; | ||
|
||
public constructor(options?: RouterOptions) { | ||
this.context = {}; | ||
const alcLogLevel = getStringFromEnv({ | ||
key: 'AWS_LAMBDA_LOG_LEVEL', | ||
defaultValue: '', | ||
}); | ||
this.logger = options?.logger ?? { | ||
debug: alcLogLevel === 'DEBUG' ? console.debug : () => undefined, | ||
error: console.error, | ||
warn: console.warn, | ||
}; | ||
this.isDev = isDevMode(); | ||
} | ||
|
||
public abstract resolve( | ||
event: unknown, | ||
context: Context, | ||
options?: ResolveOptions | ||
): Promise<unknown>; | ||
|
||
public abstract route(handler: RouteHandler, options: RouteOptions): void; | ||
|
||
#handleHttpMethod( | ||
method: HttpMethod, | ||
path: Path, | ||
handler?: RouteHandler | RouteOptions, | ||
options?: RouteOptions | ||
): MethodDecorator | undefined { | ||
if (handler && typeof handler === 'function') { | ||
this.route(handler, { ...(options || {}), method, path }); | ||
return; | ||
} | ||
|
||
return (_target, _propertyKey, descriptor: PropertyDescriptor) => { | ||
const routeOptions = isRecord(handler) ? handler : options; | ||
this.route(descriptor.value, { ...(routeOptions || {}), method, path }); | ||
return descriptor; | ||
}; | ||
} | ||
|
||
public get(path: string, handler: RouteHandler, options?: RouteOptions): void; | ||
public get(path: string, options?: RouteOptions): MethodDecorator; | ||
public get( | ||
path: Path, | ||
handler?: RouteHandler | RouteOptions, | ||
options?: RouteOptions | ||
): MethodDecorator | undefined { | ||
return this.#handleHttpMethod(HttpVerbs.GET, path, handler, options); | ||
} | ||
|
||
public post(path: Path, handler: RouteHandler, options?: RouteOptions): void; | ||
public post(path: Path, options?: RouteOptions): MethodDecorator; | ||
public post( | ||
path: Path, | ||
handler?: RouteHandler | RouteOptions, | ||
options?: RouteOptions | ||
): MethodDecorator | undefined { | ||
return this.#handleHttpMethod(HttpVerbs.POST, path, handler, options); | ||
} | ||
|
||
public put(path: Path, handler: RouteHandler, options?: RouteOptions): void; | ||
public put(path: Path, options?: RouteOptions): MethodDecorator; | ||
public put( | ||
path: Path, | ||
handler?: RouteHandler | RouteOptions, | ||
options?: RouteOptions | ||
): MethodDecorator | undefined { | ||
return this.#handleHttpMethod(HttpVerbs.PUT, path, handler, options); | ||
} | ||
|
||
public patch(path: Path, handler: RouteHandler, options?: RouteOptions): void; | ||
public patch(path: Path, options?: RouteOptions): MethodDecorator; | ||
public patch( | ||
path: Path, | ||
handler?: RouteHandler | RouteOptions, | ||
options?: RouteOptions | ||
): MethodDecorator | undefined { | ||
return this.#handleHttpMethod(HttpVerbs.PATCH, path, handler, options); | ||
} | ||
|
||
public delete( | ||
path: Path, | ||
handler: RouteHandler, | ||
options?: RouteOptions | ||
): void; | ||
public delete(path: Path, options?: RouteOptions): MethodDecorator; | ||
public delete( | ||
path: Path, | ||
handler?: RouteHandler | RouteOptions, | ||
options?: RouteOptions | ||
): MethodDecorator | undefined { | ||
return this.#handleHttpMethod(HttpVerbs.DELETE, path, handler, options); | ||
} | ||
|
||
public head(path: Path, handler: RouteHandler, options?: RouteOptions): void; | ||
public head(path: Path, options?: RouteOptions): MethodDecorator; | ||
public head( | ||
path: Path, | ||
handler?: RouteHandler | RouteOptions, | ||
options?: RouteOptions | ||
): MethodDecorator | undefined { | ||
return this.#handleHttpMethod(HttpVerbs.HEAD, path, handler, options); | ||
} | ||
|
||
public options( | ||
path: Path, | ||
handler: RouteHandler, | ||
options?: RouteOptions | ||
): void; | ||
public options(path: Path, options?: RouteOptions): MethodDecorator; | ||
public options( | ||
path: Path, | ||
handler?: RouteHandler | RouteOptions, | ||
options?: RouteOptions | ||
): MethodDecorator | undefined { | ||
return this.#handleHttpMethod(HttpVerbs.OPTIONS, path, handler, options); | ||
} | ||
|
||
public connect( | ||
path: Path, | ||
handler: RouteHandler, | ||
options?: RouteOptions | ||
): void; | ||
public connect(path: Path, options?: RouteOptions): MethodDecorator; | ||
public connect( | ||
path: Path, | ||
handler?: RouteHandler | RouteOptions, | ||
options?: RouteOptions | ||
): MethodDecorator | undefined { | ||
return this.#handleHttpMethod(HttpVerbs.CONNECT, path, handler, options); | ||
} | ||
|
||
public trace(path: Path, handler: RouteHandler, options?: RouteOptions): void; | ||
public trace(path: Path, options?: RouteOptions): MethodDecorator; | ||
public trace( | ||
path: Path, | ||
handler?: RouteHandler | RouteOptions, | ||
options?: RouteOptions | ||
): MethodDecorator | undefined { | ||
return this.#handleHttpMethod(HttpVerbs.TRACE, path, handler, options); | ||
} | ||
} | ||
|
||
export { BaseRouter }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export const HttpVerbs = { | ||
CONNECT: 'CONNECT', | ||
TRACE: 'TRACE', | ||
GET: 'GET', | ||
POST: 'POST', | ||
PUT: 'PUT', | ||
PATCH: 'PATCH', | ||
DELETE: 'DELETE', | ||
HEAD: 'HEAD', | ||
OPTIONS: 'OPTIONS', | ||
} as const; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import type { GenericLogger } from '@aws-lambda-powertools/commons/types'; | ||
import type { BaseRouter } from '../rest/BaseRouter.js'; | ||
import type { HttpVerbs } from '../rest/constatnts.js'; | ||
|
||
/** | ||
* Options for the {@link BaseRouter} class | ||
*/ | ||
type RouterOptions = { | ||
/** | ||
* A logger instance to be used for logging debug, warning, and error messages. | ||
* | ||
* When no logger is provided, we'll only log warnings and errors using the global `console` object. | ||
*/ | ||
logger?: GenericLogger; | ||
}; | ||
|
||
// biome-ignore lint/suspicious/noExplicitAny: we want to keep arguments and return types as any to accept any type of function | ||
type RouteHandler<T = any, R = any> = (...args: T[]) => R; | ||
|
||
type HttpMethod = keyof typeof HttpVerbs; | ||
|
||
type Path = `/${string}`; | ||
|
||
type RouteOptions = { | ||
method?: HttpMethod; | ||
path?: Path; | ||
}; | ||
|
||
export type { HttpMethod, Path, RouterOptions, RouteHandler, RouteOptions }; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.