Skip to content
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
8 changes: 8 additions & 0 deletions docs/2.utils/9.more.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,18 @@ const app = new H3();

<!-- automd:jsdocs src="../../src/utils/event.ts" -->

### `getEventContext(event)`

Gets the context of the event, if it does not exists, initializes a new context on `req.context`.

### `isEvent(input)`

Checks if the input is an H3Event object.

### `isHTTPEvent(input)`

Checks if the input is an object with `{ req: Request }` signature.

### `mockEvent(_request, options?)`

<!-- /automd -->
Expand Down
1 change: 0 additions & 1 deletion src/adapters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import type {
import type { H3 } from "./h3.ts";
import type { H3EventContext } from "./types/context.ts";
import type { EventHandler, EventHandlerResponse } from "./types/handler.ts";
import type { H3Event } from "./event.ts";

export type NodeHandler = (
req: NodeServerRequest,
Expand Down
14 changes: 13 additions & 1 deletion src/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,21 @@ import type {
} from "./types/handler.ts";
import type { H3Core } from "./h3.ts";

export class H3Event<
export interface HTTPEvent<
_RequestT extends EventHandlerRequest = EventHandlerRequest,
> {
/**
* Incoming HTTP request info.
*
* [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Request)
*/
req: TypedServerRequest<_RequestT>;
}

export class H3Event<
_RequestT extends EventHandlerRequest = EventHandlerRequest,
> implements HTTPEvent<_RequestT>
{
/**
* Access to the H3 application instance.
*/
Expand Down
9 changes: 7 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ export { H3Core, H3 } from "./h3.ts";
// Event

export type { H3EventContext } from "./types/context.ts";
export { H3Event } from "./event.ts";
export { isEvent, mockEvent } from "./utils/event.ts";
export { H3Event, type HTTPEvent } from "./event.ts";
export {
isEvent,
isHTTPEvent,
mockEvent,
getEventContext,
} from "./utils/event.ts";

// Handler and Middleware

Expand Down
6 changes: 3 additions & 3 deletions src/types/handler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { ServerRequest } from "srvx";
import type { TypedRequest, TypedResponse, ResponseHeaderMap } from "fetchdts";
import type { H3Event } from "../event.ts";
import type { H3Event, HTTPEvent } from "../event.ts";
import type { MaybePromise } from "./_utils.ts";
import type { H3RouteMeta } from "./h3.ts";

Expand Down Expand Up @@ -72,6 +72,6 @@ export interface DynamicEventHandler extends EventHandlerWithFetch {

export type InferEventInput<
Key extends keyof EventHandlerRequest,
Event extends H3Event,
Event extends HTTPEvent,
T,
> = void extends T ? (Event extends H3Event<infer E> ? E[Key] : never) : T;
> = void extends T ? (Event extends HTTPEvent<infer E> ? E[Key] : never) : T;
11 changes: 6 additions & 5 deletions src/utils/auth.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HTTPError } from "../index.ts";
import { getEventContext, HTTPError } from "../index.ts";

import type { H3Event, Middleware } from "../index.ts";
import type { H3EventContext, HTTPEvent, Middleware } from "../index.ts";

type _BasicAuthOptions = {
/**
Expand Down Expand Up @@ -43,7 +43,7 @@ export type BasicAuthOptions = Partial<_BasicAuthOptions> &
* });
*/
export async function requireBasicAuth(
event: H3Event,
event: HTTPEvent,
opts: BasicAuthOptions,
): Promise<true> {
if (!opts.validate && !opts.password) {
Expand Down Expand Up @@ -75,7 +75,8 @@ export async function requireBasicAuth(
throw autheFailed(event, opts?.realm);
}

event.context.basicAuth = { username, password, realm: opts.realm };
const context = getEventContext<H3EventContext>(event);
context.basicAuth = { username, password, realm: opts.realm };

return true;
}
Expand All @@ -96,7 +97,7 @@ export function basicAuth(opts: BasicAuthOptions): Middleware {
};
}

function autheFailed(event: H3Event, realm: string = "") {
function autheFailed(event: HTTPEvent, realm: string = "") {
return new HTTPError({
status: 401,
statusText: "Authentication required",
Expand Down
12 changes: 6 additions & 6 deletions src/utils/body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { HTTPError } from "../error.ts";
import { validateData } from "./internal/validate.ts";
import { parseURLEncodedBody } from "./internal/body.ts";

import type { H3Event } from "../event.ts";
import type { HTTPEvent } from "../event.ts";
import type { InferEventInput } from "../types/handler.ts";
import type { ValidateResult } from "./internal/validate.ts";
import type {
Expand All @@ -25,7 +25,7 @@ import type {
*/
export async function readBody<
T,
_Event extends H3Event = H3Event,
_Event extends HTTPEvent = HTTPEvent,
_T = InferEventInput<"body", _Event, T>,
>(event: _Event): Promise<undefined | _T> {
const text = await event.req.text();
Expand All @@ -50,11 +50,11 @@ export async function readBody<
}

export async function readValidatedBody<
Event extends H3Event,
Event extends HTTPEvent,
S extends StandardSchemaV1,
>(event: Event, validate: S): Promise<InferOutput<S>>;
export async function readValidatedBody<
Event extends H3Event,
Event extends HTTPEvent,
OutputT,
InputT = InferEventInput<"body", Event, OutputT>,
>(
Expand Down Expand Up @@ -85,14 +85,14 @@ export async function readValidatedBody<
* const body = await readValidatedBody(event, objectSchema);
* });
*
* @param event The H3Event passed by the handler.
* @param event The HTTPEvent passed by the handler.
* @param validate The function to use for body validation. It will be called passing the read request body. If the result is not false, the parsed body will be returned.
* @throws If the validation function returns `false` or throws, a validation error will be thrown.
* @return {*} The `Object`, `Array`, `String`, `Number`, `Boolean`, or `null` value corresponding to the request JSON body.
* @see {readBody}
*/
export async function readValidatedBody(
event: H3Event,
event: HTTPEvent,
validate: any,
): Promise<any> {
const _body = await readBody(event);
Expand Down
10 changes: 5 additions & 5 deletions src/utils/cookie.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { CookieSerializeOptions, SetCookie } from "cookie-es";
import type { H3Event } from "../event.ts";
import type { H3Event, HTTPEvent } from "../event.ts";
import {
parse as parseCookie,
serialize as serializeCookie,
Expand All @@ -8,26 +8,26 @@ import {

/**
* Parse the request to get HTTP Cookie header string and returning an object of all cookie name-value pairs.
* @param event {H3Event} H3 event or req passed by h3 handler
* @param event {HTTPEvent} H3 event or req passed by h3 handler
* @returns Object of cookie name-value pairs
* ```ts
* const cookies = parseCookies(event)
* ```
*/
export function parseCookies(event: H3Event): Record<string, string> {
export function parseCookies(event: HTTPEvent): Record<string, string> {
return parseCookie(event.req.headers.get("cookie") || "");
}

/**
* Get a cookie value by name.
* @param event {H3Event} H3 event or req passed by h3 handler
* @param event {HTTPEvent} H3 event or req passed by h3 handler
* @param name Name of the cookie to get
* @returns {*} Value of the cookie (String or undefined)
* ```ts
* const authorization = getCookie(request, 'Authorization')
* ```
*/
export function getCookie(event: H3Event, name: string): string | undefined {
export function getCookie(event: HTTPEvent, name: string): string | undefined {
return parseCookies(event)[name];
}

Expand Down
4 changes: 2 additions & 2 deletions src/utils/cors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { H3Event } from "../event.ts";
import type { H3Event, HTTPEvent } from "../event.ts";
import { noContent } from "./response.ts";
import {
createAllowHeaderHeaders,
Expand Down Expand Up @@ -79,7 +79,7 @@ export interface CorsOptions {
/**
* Check if the incoming request is a CORS preflight request.
*/
export function isPreflightRequest(event: H3Event): boolean {
export function isPreflightRequest(event: HTTPEvent): boolean {
const origin = event.req.headers.get("origin");
const accessControlRequestMethod = event.req.headers.get(
"access-control-request-method",
Expand Down
25 changes: 24 additions & 1 deletion src/utils/event.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { H3Event } from "../event.ts";
import { H3Event, type HTTPEvent } from "../event.ts";
import type { H3EventContext } from "../types/context.ts";
import type { ServerRequestContext } from "srvx";

/**
* Checks if the input is an H3Event object.
Expand All @@ -11,6 +12,28 @@ export function isEvent(input: any): input is H3Event {
return input instanceof H3Event || input?.constructor?.__is_event__;
}

/**
* Checks if the input is an object with `{ req: Request }` signature.
* @param input - The input to check.
* @returns True if the input is is `{ req: Request }`
*/
export function isHTTPEvent(input: any): input is HTTPEvent {
return input?.req instanceof Request;
}

/**
* Gets the context of the event, if it does not exists, initializes a new context on `req.context`.
*/
export function getEventContext<
T extends ServerRequestContext | H3EventContext,
>(event: HTTPEvent | H3Event): T {
if ((event as H3Event).context) {
return (event as H3Event).context as T;
}
event.req.context ??= {};
return event.req.context as T;
}

export function mockEvent(
_request: string | URL | Request,
options?: RequestInit & { h3?: H3EventContext },
Expand Down
6 changes: 3 additions & 3 deletions src/utils/fingerprint.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { H3Event } from "../event.ts";
import type { HTTPEvent } from "../event.ts";
import { getRequestIP } from "./request.ts";

export interface RequestFingerprintOptions {
Expand Down Expand Up @@ -28,7 +28,7 @@ export interface RequestFingerprintOptions {
* @experimental Behavior of this utility might change in the future versions
*/
export async function getRequestFingerprint(
event: H3Event,
event: HTTPEvent,
opts: RequestFingerprintOptions = {},
): Promise<string | null> {
const fingerprint: unknown[] = [];
Expand All @@ -44,7 +44,7 @@ export async function getRequestFingerprint(
}

if (opts.url === true) {
fingerprint.push(event.url.href);
fingerprint.push(event.req.url);
}

if (opts.userAgent === true) {
Expand Down
Loading