-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4fb9f98
commit ec71c27
Showing
23 changed files
with
782 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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 @@ | ||
import { ConfigObject, OasKeys, ResolverKeys } from "."; | ||
|
||
export const createConfig = <K extends ResolverKeys, O extends OasKeys = "3.1">( | ||
params?: ConfigObject<K, O>, | ||
) => { | ||
const resolver = (params?.resolver || "zod") as ResolverKeys; | ||
|
||
const oas = (params?.oas || "3.1") as OasKeys; | ||
|
||
return { resolver, oas }; | ||
}; |
This file contains 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,27 @@ | ||
import { resolverObj } from "./resolvers/resolverObj"; | ||
import { ConfigObject, OasKeys } from "./types"; | ||
import { ResolverKeys } from "./resolvers"; | ||
import { Http } from "./httpStatus"; | ||
import { createConfig } from "./config"; | ||
import { Oas } from "./docs"; | ||
|
||
/** | ||
* CreateRocket: generates a kit to workr back end in next.js with app folder | ||
* | ||
*/ | ||
export const createRocket = < | ||
K extends ResolverKeys = "zod", | ||
O extends OasKeys = "3.1", | ||
>( | ||
params?: ConfigObject<K, O>, | ||
) => { | ||
const config = createConfig(params); | ||
|
||
const Route = resolverObj[config.resolver] as K extends "yup" | ||
? typeof resolverObj.yup | ||
: typeof resolverObj.zod; | ||
|
||
const OpenApi = Oas[config.oas]; | ||
|
||
return { Route, Http, OpenApi }; | ||
}; |
This file contains 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,18 @@ | ||
import { oas31 } from "openapi3-ts"; | ||
|
||
export const Oas = { | ||
"3.0": (doc?: oas31.OpenAPIObject) => { | ||
if (!doc) return oas31.OpenApiBuilder.create(doc); | ||
|
||
if (!doc.openapi) doc.openapi = "3.0.3"; | ||
|
||
return oas31.OpenApiBuilder.create(doc); | ||
}, | ||
"3.1": (doc?: oas31.OpenAPIObject) => { | ||
if (!doc) return oas31.OpenApiBuilder.create(doc); | ||
|
||
if (!doc.openapi) doc.openapi = "3.1.0"; | ||
|
||
return oas31.OpenApiBuilder.create(doc); | ||
}, | ||
}; |
This file contains 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,3 @@ | ||
import { Oas } from "."; | ||
|
||
export type OasKeys = keyof typeof Oas; |
This file contains 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 @@ | ||
export * as Http from "http-status-codes"; |
This file contains 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,2 @@ | ||
export * from "./types"; | ||
export { createRocket } from "./createRocket"; |
This file contains 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,4 @@ | ||
export * from "./resolverObj"; | ||
export type * from "./types"; | ||
export * as YubResolver from "./yup"; | ||
export * as ZodResolver from "./zod"; |
This file contains 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,24 @@ | ||
export const formatParams = (params: Record<any, any>) => { | ||
const paramsEntry = Object.entries(params).map(([key, value]) => { | ||
// en caso de que sea array | ||
if (Array.isArray(value)) { | ||
return value.map((vItem) => { | ||
const vItemoNumber = Number(vItem); | ||
|
||
if (vItemoNumber !== 0 && !vItemoNumber) { | ||
return [key, value]; | ||
} else { | ||
return [key, vItemoNumber]; | ||
} | ||
}); | ||
} | ||
|
||
const valueToNumber = Number(value); | ||
if (valueToNumber !== 0 && !valueToNumber) { | ||
return [key, value]; | ||
} else { | ||
return [key, valueToNumber]; | ||
} | ||
}); | ||
return Object.fromEntries(paramsEntry); | ||
}; |
This file contains 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,7 @@ | ||
import { yupRoute } from "./yup/route"; | ||
import { zodRoute } from "./zod/route"; | ||
|
||
export const resolverObj = { | ||
yup: yupRoute, | ||
zod: zodRoute, | ||
}; |
This file contains 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,10 @@ | ||
import { StatusCodes } from "http-status-codes"; | ||
import { resolverObj } from "./resolverObj"; | ||
export * from "./zod/types"; | ||
export * from "./yup/types"; | ||
|
||
export type ResolverKeys = keyof typeof resolverObj; | ||
|
||
export interface ReplyInit extends Omit<ResponseInit, "status"> { | ||
status?: StatusCodes; | ||
} |
This file contains 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,119 @@ | ||
import { NextRequest } from "next/server"; | ||
import { ObjectSchema, AnyObject, InferType } from "yup"; | ||
import { IYupSchemasValid } from "../types"; | ||
import { headers as Headers } from "next/headers"; | ||
import { ReadonlyHeaders } from "next/dist/server/web/spec-extension/adapters/headers"; | ||
|
||
export default class ValidAndFormat< | ||
B extends ObjectSchema<AnyObject>, | ||
C extends ObjectSchema<AnyObject>, | ||
Q extends ObjectSchema<AnyObject>, | ||
H extends ObjectSchema<AnyObject>, | ||
R extends ObjectSchema<AnyObject>, | ||
> { | ||
Schemas?: IYupSchemasValid<B, C, Q, H, R>; | ||
NativeContext: InferType<C>; | ||
nativeRequest: NextRequest; | ||
bodyNative: InferType<B> = {}; | ||
|
||
constructor( | ||
nativeRequest: NextRequest, | ||
context: InferType<C>, | ||
Schemas?: IYupSchemasValid<B, C, Q, H, R>, | ||
) { | ||
this.Schemas = Schemas; | ||
this.NativeContext = context; | ||
this.nativeRequest = nativeRequest; | ||
} | ||
|
||
headers(): InferType<H> | ReadonlyHeaders { | ||
if (!this.Schemas?.headers) return Headers(); | ||
|
||
return this.Schemas.headers.validateSync(Headers()); | ||
} | ||
|
||
context(): InferType<C> { | ||
if (!this.Schemas?.context) return this.NativeContext; | ||
|
||
return this.Schemas.context.validateSync(this.NativeContext); | ||
} | ||
|
||
private getQueryWhoNoHasSchema() { | ||
return (queriesArray: Array<keyof InferType<Q>>): Partial<InferType<Q>> => { | ||
// | ||
const resQueries: any = {}; | ||
|
||
const symbolsReq = Object.getOwnPropertySymbols(this.nativeRequest); | ||
|
||
const UrlNative = symbolsReq | ||
.filter((S) => { | ||
//@ts-ignore | ||
const item = this.nativeRequest[S]; | ||
|
||
return item?.url; | ||
}) | ||
.map<URL>((S) => { | ||
//@ts-ignore | ||
const item = this.nativeRequest[S]; | ||
|
||
return item?.url; | ||
})[0]; | ||
|
||
const validUrlNative = Object.keys(this.nativeRequest).includes("url"); | ||
|
||
const url = validUrlNative ? new URL(this.nativeRequest.url) : UrlNative; | ||
|
||
queriesArray.map((q) => { | ||
resQueries[q] = url.searchParams.get(String(q)); | ||
}); | ||
|
||
return resQueries; | ||
}; | ||
} | ||
|
||
private createGetQueryWhoHasSchema(queryFormat: InferType<Q>) { | ||
return (queriesArray: Array<keyof InferType<Q>>): Partial<InferType<Q>> => { | ||
const querysEntrys = Object.entries(queryFormat); | ||
|
||
const queryFilter = querysEntrys.filter(([k]) => | ||
queriesArray.includes(k), | ||
); | ||
|
||
const queryObj = Object.fromEntries(queryFilter) as Partial<InferType<Q>>; | ||
|
||
return queryObj; | ||
}; | ||
} | ||
|
||
query() { | ||
if (!this.Schemas?.query) return this.getQueryWhoNoHasSchema(); | ||
|
||
const keys = Object.keys(this.Schemas.query.fields); | ||
|
||
const query = this.getQueryWhoNoHasSchema()(keys); | ||
|
||
const queryFormat = this.Schemas.query.validateSync(query) as InferType<Q>; | ||
|
||
const getQueryWhoHasSchema = this.createGetQueryWhoHasSchema(queryFormat); | ||
|
||
return getQueryWhoHasSchema; | ||
} | ||
|
||
private async defineBody() { | ||
const valid_methods = !["DELETE", "GET"].includes( | ||
this.nativeRequest.method, | ||
); | ||
|
||
if (valid_methods && this.Schemas?.body) { | ||
this.bodyNative = await this.nativeRequest.json(); | ||
} | ||
} | ||
|
||
async body(): Promise<InferType<B>> { | ||
await this.defineBody(); | ||
|
||
if (!this.Schemas?.body) return this.bodyNative; | ||
|
||
return this.Schemas.body.validateSync(this.bodyNative); | ||
} | ||
} |
This file contains 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,5 @@ | ||
export * from "./requestFactory"; | ||
export * from "./responseFactory"; | ||
export * from "./route"; | ||
export * from "./types"; | ||
export * from "./ValidAndFormat"; |
This file contains 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,40 @@ | ||
import { NextRequest } from "next/server"; | ||
import { IYupSchemasValid } from "./types"; | ||
import { IYupRequestFactoryResp } from "./types"; | ||
import { AnyObject, InferType, ObjectSchema } from "yup"; | ||
import ValidAndFormat from "./ValidAndFormat"; | ||
|
||
export const requestFactory = async < | ||
B extends ObjectSchema<AnyObject>, | ||
C extends ObjectSchema<AnyObject>, | ||
Q extends ObjectSchema<AnyObject>, | ||
H extends ObjectSchema<AnyObject>, | ||
R extends ObjectSchema<AnyObject>, | ||
>( | ||
nativeRequest: NextRequest, | ||
context: InferType<C>, | ||
Schemas?: IYupSchemasValid<B, C, Q, H, R>, | ||
) => { | ||
const validAndFormat = new ValidAndFormat<B, C, Q, H, R>( | ||
nativeRequest, | ||
context, | ||
Schemas, | ||
); | ||
|
||
const Headers = validAndFormat.headers(); | ||
|
||
const Context = validAndFormat.context(); | ||
|
||
const Query = validAndFormat.query(); | ||
|
||
const body = await validAndFormat.body(); | ||
|
||
const resp = { | ||
getHeaders: () => Headers, | ||
getContext: () => Context, | ||
getQuery: (keys: Array<keyof InferType<Q> | string>) => Query(keys), | ||
getBody: () => body, | ||
}; | ||
|
||
return { ...resp, ...nativeRequest } as IYupRequestFactoryResp<B, C, Q>; | ||
}; |
This file contains 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,26 @@ | ||
import { getReasonPhrase } from "http-status-codes"; | ||
import { NextResponse } from "next/server"; | ||
import { ISchema, InferType } from "yup"; | ||
import { ReplyInit } from "../types"; | ||
|
||
export const responseFactory = <R extends ISchema<any>,>( | ||
respnseSchemas?: R, | ||
) => { | ||
return { | ||
rewrite: NextResponse.redirect, | ||
|
||
next: NextResponse.next, | ||
|
||
redirect: NextResponse.redirect, | ||
|
||
json: (body: InferType<R>, init?: ReplyInit) => { | ||
if (respnseSchemas) respnseSchemas.validate(body); | ||
|
||
if (init?.status && !init?.statusText) { | ||
init.statusText = getReasonPhrase(init.status); | ||
} | ||
|
||
return NextResponse.json<InferType<R>>(body, init); | ||
}, | ||
}; | ||
}; |
This file contains 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,43 @@ | ||
import { NextRequest, NextResponse } from "next/server"; | ||
import { requestFactory } from "./requestFactory"; | ||
import { responseFactory } from "./responseFactory"; | ||
import { IYupRouteParams, YupActionReturnType } from "./types"; | ||
import { AnyObject, InferType, ObjectSchema } from "yup"; | ||
|
||
export const yupRoute = < | ||
B extends ObjectSchema<AnyObject>, | ||
C extends ObjectSchema<AnyObject>, | ||
Q extends ObjectSchema<AnyObject>, | ||
H extends ObjectSchema<AnyObject>, | ||
R extends ObjectSchema<AnyObject>, | ||
>( | ||
P: IYupRouteParams<B, C, Q, H, R> | IYupRouteParams<B, C, Q, H, R>["Handler"], | ||
) => { | ||
return async ( | ||
nextRequest: NextRequest, | ||
context: InferType<C>, | ||
): Promise<YupActionReturnType<B, C, Q, H, R>> => { | ||
try { | ||
if (typeof P === "object") { | ||
const { schemas, Handler } = P; | ||
const req = await requestFactory<B, C, Q, H, R>( | ||
nextRequest, | ||
context, | ||
schemas, | ||
); | ||
|
||
const reply = responseFactory(schemas?.response); | ||
|
||
return Handler(req, reply, context); | ||
} | ||
|
||
const req = await requestFactory<B, C, Q, H, R>(nextRequest, context); | ||
|
||
const reply = responseFactory(); | ||
|
||
return P(req, reply, context); | ||
} catch (error) { | ||
return NextResponse.json((error as any).errors, { status: 400 }); | ||
} | ||
}; | ||
}; |
Oops, something went wrong.