Skip to content
Draft
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: 2 additions & 2 deletions apps/example-todo-app/src/app/edge/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ const route_spec = {
auth: "none",
} as const

export const GET = withRouteSpecEdge(route_spec)((req) => {
return req.responseEdge.status(200).json({ return: true })
export const GET = withRouteSpecEdge(route_spec)((req, res) => {
return res.status(200).json({ return: true })
})
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { UnauthorizedException, MiddlewareEdge } from "nextlove"
import { NextloveRequest, NextloveResponse } from "nextlove/dist/edge-helpers"

export const withAuthTokenEdge: MiddlewareEdge<{
auth: {
authorized_by: "auth_token"
export const withAuthTokenEdge: MiddlewareEdge<NextloveRequest,
NextloveResponse,
{
auth: {
authorized_by: "auth_token"
}
}
}> = (next) => async (req) => {
> = (next) => async (req, res) => {
const authorization = req.headers.get("authorization")

if (authorization?.split("Bearer ")?.[1] !== "auth_token") {
Expand All @@ -18,7 +22,7 @@ export const withAuthTokenEdge: MiddlewareEdge<{
authorized_by: "auth_token",
}

return next(req)
return next(req, res)
}

export default withAuthTokenEdge
14 changes: 7 additions & 7 deletions packages/nextlove/src/exceptions-middleware-egde/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NextloveRequest } from "../edge-helpers";
import { NextloveRequest, NextloveResponse } from "../edge-helpers"
import unwrappedWithExceptionHandlingEdge, {
WithExceptionHandlingEdgeOptions,
} from "./with-exception-handling"
Expand All @@ -8,13 +8,13 @@ export interface ExceptionHandlingEdgeOptions {
}

export const withExceptionHandlingEdge =
({
exceptionHandlingOptions,
}: ExceptionHandlingEdgeOptions = {}) =>
({ exceptionHandlingOptions }: ExceptionHandlingEdgeOptions = {}) =>
(next: (req: NextloveRequest) => Promise<void>) =>
(req: NextloveRequest) => {

return unwrappedWithExceptionHandlingEdge(exceptionHandlingOptions)(next)(req)
(req: NextloveRequest, res: NextloveResponse) => {
return unwrappedWithExceptionHandlingEdge(exceptionHandlingOptions)(next)(
req,
res
)
}

export * from "../http-exceptions"
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NextloveRequest } from "../edge-helpers"
import { NextloveRequest, NextloveResponse } from "../edge-helpers"
import { HttpException } from "../http-exceptions"

export interface WithExceptionHandlingEdgeOptions {
Expand All @@ -10,11 +10,10 @@ export interface WithExceptionHandlingEdgeOptions {

const withExceptionHandlingEdge =
(options: WithExceptionHandlingEdgeOptions = {}) =>
(next: (req: NextloveRequest) => Promise<void>) =>
async (req: NextloveRequest) => {
const res = req.responseEdge
(next: (req: NextloveRequest, res: NextloveResponse) => Promise<void>) =>
async (req: NextloveRequest, res: NextloveResponse) => {
try {
return await next(req)
return await next(req, res)
} catch (error: unknown) {
let errorContext: any = {}

Expand Down
19 changes: 9 additions & 10 deletions packages/nextlove/src/exceptions-middleware-nodejs/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { NextApiRequest, NextApiResponse } from "next";
import { NextApiRequest, NextApiResponse } from "next"
import unwrappedWithExceptionHandling, {
WithExceptionHandlingOptions,
} from "./with-exception-handling";
import withOkStatus, { WithOkStatusOptions } from "./with-ok-status";
} from "./with-exception-handling"
import withOkStatus, { WithOkStatusOptions } from "./with-ok-status"

export interface ExceptionHandlingOptions {
addOkStatus?: boolean;
okStatusOptions?: WithOkStatusOptions;
exceptionHandlingOptions?: WithExceptionHandlingOptions;
addOkStatus?: boolean
okStatusOptions?: WithOkStatusOptions
exceptionHandlingOptions?: WithExceptionHandlingOptions
}

export const withExceptionHandling =
Expand All @@ -21,12 +21,11 @@ export const withExceptionHandling =
if (addOkStatus) {
return withOkStatus(okStatusOptions)(
unwrappedWithExceptionHandling(exceptionHandlingOptions)(next)
)(req, res);
)(req, res)
}

return unwrappedWithExceptionHandling(exceptionHandlingOptions)(next)(
req,
res
);
};

)
}
17 changes: 10 additions & 7 deletions packages/nextlove/src/types-edge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export interface RouteSpecEdge<
JsonBody extends ParamDef = z.ZodObject<any, any, any, any, any>,
QueryParams extends ParamDef = z.ZodObject<any, any, any, any, any>,
CommonParams extends ParamDef = z.ZodObject<any, any, any, any, any>,
Middlewares extends readonly MiddlewareEdge<any, any>[] = any[],
Middlewares extends readonly MiddlewareEdge<any, any, any, any>[] = any[],
JsonResponse extends ParamDef = z.ZodObject<any, any, any, any, any>,
FormData extends ParamDef = z.ZodTypeAny
> {
Expand All @@ -29,25 +29,25 @@ export interface RouteSpecEdge<
}

export type MiddlewareEdgeChainOutput<
MWChain extends readonly MiddlewareEdge<any, any>[]
MWChain extends readonly MiddlewareEdge<any, any, any, any>[]
> = MWChain extends readonly []
? {}
: MWChain extends readonly [infer First, ...infer Rest]
? First extends MiddlewareEdge<infer T, any>
? First extends MiddlewareEdge<any, any, infer T, any>
? T &
(Rest extends readonly MiddlewareEdge<any, any>[]
(Rest extends readonly MiddlewareEdge<any, any, any, any>[]
? MiddlewareEdgeChainOutput<Rest>
: never)
: never
: never

export type AuthMiddlewaresEdge = {
[auth_type: string]: MiddlewareEdge<any, any>
[auth_type: string]: MiddlewareEdge<any, any, any, any>
}

export interface SetupParamsEdge<
AuthMW extends AuthMiddlewaresEdge = AuthMiddlewaresEdge,
GlobalMW extends MiddlewareEdge<any, any>[] = any[]
GlobalMW extends MiddlewareEdge<any, any, any, any>[] = any[]
> {
authMiddlewareMap: AuthMW
globalMiddlewares: GlobalMW
Expand Down Expand Up @@ -99,13 +99,15 @@ export type RouteEdgeFunction<
> = (
req: (SP["authMiddlewareMap"] &
typeof defaultMiddlewareMap)[RS["auth"]] extends MiddlewareEdge<
any,
any,
infer AuthMWOut,
any
>
? Omit<NextloveRequest, "responseEdge"> &
AuthMWOut &
MiddlewareEdgeChainOutput<
RS["middlewares"] extends readonly MiddlewareEdge<any, any>[]
RS["middlewares"] extends readonly MiddlewareEdge<any, any, any, any>[]
? [...SP["globalMiddlewares"], ...RS["middlewares"]]
: SP["globalMiddlewares"]
> & {
Expand All @@ -129,6 +131,7 @@ export type RouteEdgeFunction<
ErrorNextloveResponseMethods
}
: `unknown auth type: ${RS["auth"]}. You should configure this auth type in your auth_middlewares w/ createWithRouteSpec, or maybe you need to add "as const" to your route spec definition.`,
res: NextloveResponse
) => NextResponse | Promise<NextResponse>

export type CreateWithRouteSpecEdgeFunction = <
Expand Down
19 changes: 14 additions & 5 deletions packages/nextlove/src/with-route-spec-edge/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { wrappersEdge } from "../wrappers-edge"
import { withValidationEdge } from "./with-validation-edge"
import { NextloveRequest, getResponse } from "../edge-helpers"
import { NextloveRequest, NextloveResponse, getResponse } from "../edge-helpers"
import { CreateWithRouteSpecEdgeFunction, RouteSpecEdge } from "../types-edge"
import { withExceptionHandlingEdge } from "../exceptions-middleware-egde"

Expand All @@ -26,7 +26,7 @@ export const createWithRouteSpecEdge: CreateWithRouteSpecEdgeFunction = ((
} = setupParams

const withRouteSpec = (spec: RouteSpecEdge) => {
const createRouteExport = (userDefinedRouteFn: (req: NextloveRequest) => any) => {
const createRouteExport = (userDefinedRouteFn: (req: NextloveRequest, res: NextloveResponse) => any) => {
const rootRequestHandler = async (
req: NextloveRequest,
) => {
Expand All @@ -35,13 +35,22 @@ export const createWithRouteSpecEdge: CreateWithRouteSpecEdgeFunction = ((
addOkStatus: setupParams.addOkStatus,
})

const res = req.responseEdge

authMiddlewareMap["none"] = (next) => next;

const auth_middleware = authMiddlewareMap[spec.auth]
if (!auth_middleware) throw new Error(`Unknown auth type: ${spec.auth}`)

return wrappersEdge<NextloveRequest, NextloveRequest, NextloveRequest, NextloveRequest
, NextloveRequest, NextloveRequest
return wrappersEdge<
NextloveRequest,
NextloveResponse,
NextloveRequest,
NextloveRequest,
NextloveRequest,
NextloveRequest,
NextloveRequest,
NextloveRequest
>(
...((exceptionHandlingMiddleware
? [exceptionHandlingMiddleware]
Expand All @@ -61,7 +70,7 @@ export const createWithRouteSpecEdge: CreateWithRouteSpecEdgeFunction = ((
shouldValidateGetRequestBody,
}),
userDefinedRouteFn
)(req)
)(req, res)
}

rootRequestHandler._setupParams = setupParams
Expand Down
28 changes: 13 additions & 15 deletions packages/nextlove/src/with-route-spec-edge/with-validation-edge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
InternalServerErrorException,
} from "../http-exceptions"
import { isEmpty } from "lodash"
import { NextloveRequest } from "../edge-helpers"
import { NextloveRequest, NextloveResponse } from "../edge-helpers"
import { parseQueryParams, zodIssueToString } from "../zod-helpers"

export interface RequestInput<
Expand All @@ -26,15 +26,15 @@ export interface RequestInput<
// NOTE: we should be able to use the same validation logic for both the nodejs and edge runtime
function validateJsonResponse<JsonResponse extends z.ZodTypeAny>(
jsonResponse: JsonResponse | undefined,
req: NextloveRequest
res: NextloveResponse
) {
const original_res_json = req.responseEdge.json
const override_res_json: NextloveRequest["responseEdge"]["json"] = (
const original_res_json = res.json
const override_res_json: NextloveResponse["json"] = (
body,
params
) => {
const is_success =
req.responseEdge.statusCode >= 200 && req.responseEdge.statusCode < 300
res.statusCode >= 200 && res.statusCode < 300
if (!is_success) {
return original_res_json(body, params)
}
Expand All @@ -52,7 +52,9 @@ function validateJsonResponse<JsonResponse extends z.ZodTypeAny>(
return original_res_json(body, params)
}

req.responseEdge.json = override_res_json
res.json = override_res_json

return res;
}

export const withValidationEdge =
Expand All @@ -72,7 +74,7 @@ export const withValidationEdge =
>
) =>
(next) =>
async (req: NextloveRequest) => {
async (req: NextloveRequest, res: NextloveResponse) => {
if (
(input.formData && input.jsonBody) ||
(input.formData && input.commonParams)
Expand Down Expand Up @@ -180,12 +182,8 @@ export const withValidationEdge =
})
}

/**
* this will override the res.json method to validate the response
*/
if (input.shouldValidateResponses) {
validateJsonResponse(input.jsonResponse, req)
}

return next(req)
return next(
req,
input.shouldValidateResponses ? validateJsonResponse(input.jsonResponse, res) : res
)
}
Loading