| import { HandlerContext } from '@netlify/functions'; | ||
| import { InternalRouteHandler, RouteHandler, RouteOptions, RouteTree, TreeSearchResult } from './types.js'; | ||
| import { InternalRouteHandler, Method, RouteHandler, RouteOptions, RouteTree, TreeSearchResult } from './types.js'; | ||
| import { ZodSchema } from 'zod'; | ||
@@ -11,3 +11,3 @@ import { Logger } from './logger.js'; | ||
| addRoute<TPath extends string = '', TQuerySchema extends ZodSchema | undefined = undefined, TBodySchema extends ZodSchema | undefined = undefined, TContext extends HandlerContext = HandlerContext>({ method, url, handlers, options, }: { | ||
| method: string; | ||
| method: Method; | ||
| url: TPath; | ||
@@ -17,4 +17,4 @@ handlers: RouteHandler<TPath, TQuerySchema, TBodySchema, TContext>[]; | ||
| }): InternalRouteHandler; | ||
| recursiveTreeMatch(url: string, fullUrl: string, method: string, tree?: RouteTree): TreeSearchResult | undefined; | ||
| recursiveTreeMatch(url: string, fullUrl: string, method: Method, tree?: RouteTree): TreeSearchResult | undefined; | ||
| GetAllRoutes(): InternalRouteHandler[]; | ||
| } |
+33
-24
@@ -54,3 +54,2 @@ import { withBodyValidator, withQueryValidator } from './middleware.js'; | ||
| const route = { | ||
| method, | ||
| urlPattern: new UrlPattern(routeUrl), | ||
@@ -65,4 +64,7 @@ handlers, | ||
| } | ||
| if (!this.routeTree.routeHandlers) { | ||
| this.routeTree.routeHandlers = {}; | ||
| } | ||
| if (routeUrl === '/') { | ||
| this.routeTree.routeHandler = route; | ||
| this.routeTree.routeHandlers[method] = route; | ||
| return route; | ||
@@ -82,7 +84,11 @@ } | ||
| if (current.children[component]) { | ||
| current.children[component].routeHandler = route; | ||
| const currentChild = current.children[component]; | ||
| if (!currentChild.routeHandlers) { | ||
| currentChild.routeHandlers = {}; | ||
| } | ||
| currentChild.routeHandlers[method] = route; | ||
| } | ||
| else { | ||
| current.children[component] = { | ||
| routeHandler: route, | ||
| routeHandlers: { [method]: route }, | ||
| }; | ||
@@ -103,9 +109,9 @@ } | ||
| if (url === '/') { | ||
| if (tree.routeHandler) { | ||
| if (tree.routeHandler.method === method && | ||
| tree.routeHandler.urlPattern.match(fullUrl)) { | ||
| if (tree.routeHandlers) { | ||
| const potentialMatch = tree.routeHandlers[method]; | ||
| if (potentialMatch && potentialMatch.urlPattern.match(fullUrl)) { | ||
| return { | ||
| matchedRoute: tree.routeHandler, | ||
| params: tree.routeHandler.urlPattern.parse(fullUrl), | ||
| handlers: tree.routeHandler.handlers, | ||
| matchedRoute: potentialMatch, | ||
| params: potentialMatch.urlPattern.parse(fullUrl), | ||
| handlers: potentialMatch.handlers, | ||
| }; | ||
@@ -120,14 +126,14 @@ } | ||
| // If we're at the end of the URL, return the handlers | ||
| if (node.routeHandler) { | ||
| if (node.routeHandlers) { | ||
| this.logger.debug(`Node is a route handler for ${current}`); | ||
| if (rest.length === 0) { | ||
| if (node.routeHandler.method === method && | ||
| node.routeHandler.urlPattern.match(fullUrl)) { | ||
| const potentialMatch = node.routeHandlers[method]; | ||
| if (potentialMatch && potentialMatch.urlPattern.match(fullUrl)) { | ||
| return { | ||
| matchedRoute: node.routeHandler, | ||
| params: node.routeHandler.urlPattern.parse(fullUrl), | ||
| matchedRoute: potentialMatch, | ||
| params: potentialMatch.urlPattern.parse(fullUrl), | ||
| handlers: [ | ||
| ...(tree.middleware ?? []), | ||
| ...(node.middleware ?? []), | ||
| ...node.routeHandler.handlers, | ||
| ...potentialMatch.handlers, | ||
| ].filter(Boolean), | ||
@@ -164,17 +170,20 @@ }; | ||
| this.logger.debug(`Trying argument node ${argumentNode}...`); | ||
| if (argumentNode.routeHandler) { | ||
| if (argumentNode.routeHandlers) { | ||
| this.logger.debug(`Node is a route handler for ${current}`); | ||
| const potentialMatch = argumentNode.routeHandlers[method]; | ||
| if (rest.length === 0) { | ||
| if (argumentNode.routeHandler.method === method && | ||
| argumentNode.routeHandler.urlPattern.match(fullUrl)) { | ||
| if (potentialMatch && potentialMatch.urlPattern.match(fullUrl)) { | ||
| return { | ||
| matchedRoute: argumentNode.routeHandler, | ||
| params: argumentNode.routeHandler.urlPattern.parse(fullUrl), | ||
| matchedRoute: potentialMatch, | ||
| params: potentialMatch.urlPattern.parse(fullUrl), | ||
| handlers: [ | ||
| ...(tree.middleware ?? []), | ||
| ...(argumentNode.middleware ?? []), | ||
| ...argumentNode.routeHandler.handlers, | ||
| ...potentialMatch.handlers, | ||
| ].filter(Boolean), | ||
| }; | ||
| } | ||
| else { | ||
| this.logger.debug(`Method or URL pattern did not match for ${current}`); | ||
| } | ||
| } | ||
@@ -205,4 +214,4 @@ } | ||
| const recurse = (tree) => { | ||
| if (tree.routeHandler) { | ||
| routes.push(tree.routeHandler); | ||
| if (tree.routeHandlers) { | ||
| routes.push(...Object.values(tree.routeHandlers)); | ||
| } | ||
@@ -209,0 +218,0 @@ if (tree.children) { |
+2
-2
@@ -35,9 +35,9 @@ import { ZodSchema, z } from 'zod'; | ||
| export interface InternalRouteHandler { | ||
| method: string; | ||
| urlPattern: UrlPattern; | ||
| handlers: any[]; | ||
| } | ||
| export type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'; | ||
| export interface RouteTree { | ||
| middleware?: RouteHandler[]; | ||
| routeHandler?: InternalRouteHandler; | ||
| routeHandlers?: Partial<Record<Method, InternalRouteHandler>>; | ||
| children?: { | ||
@@ -44,0 +44,0 @@ [key: string]: RouteTree; |
+1
-1
| { | ||
| "name": "funclify", | ||
| "version": "0.1.8", | ||
| "version": "0.2.0", | ||
| "description": "", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
+2
-1
@@ -10,2 +10,3 @@ import { | ||
| import { | ||
| Method, | ||
| RouteContext, | ||
@@ -268,3 +269,3 @@ RouteHandler, | ||
| } | ||
| const method = event.httpMethod; | ||
| const method = event.httpMethod as Method; | ||
@@ -271,0 +272,0 @@ let components = url.split('/'); |
+38
-32
@@ -5,2 +5,3 @@ import { HandlerContext } from '@netlify/functions'; | ||
| InternalRouteHandler, | ||
| Method, | ||
| RouteHandler, | ||
@@ -80,3 +81,3 @@ RouteOptions, | ||
| }: { | ||
| method: string; | ||
| method: Method; | ||
| url: TPath; | ||
@@ -91,3 +92,2 @@ handlers: RouteHandler<TPath, TQuerySchema, TBodySchema, TContext>[]; | ||
| const route: InternalRouteHandler = { | ||
| method, | ||
| urlPattern: new UrlPattern(routeUrl), | ||
@@ -104,4 +104,8 @@ handlers, | ||
| if (!this.routeTree.routeHandlers) { | ||
| this.routeTree.routeHandlers = {}; | ||
| } | ||
| if (routeUrl === '/') { | ||
| this.routeTree.routeHandler = route; | ||
| this.routeTree.routeHandlers[method] = route; | ||
| return route; | ||
@@ -125,6 +129,10 @@ } | ||
| if (current.children[component]) { | ||
| current.children[component].routeHandler = route; | ||
| const currentChild = current.children[component]; | ||
| if (!currentChild.routeHandlers) { | ||
| currentChild.routeHandlers = {}; | ||
| } | ||
| currentChild.routeHandlers[method] = route; | ||
| } else { | ||
| current.children[component] = { | ||
| routeHandler: route, | ||
| routeHandlers: { [method]: route }, | ||
| }; | ||
@@ -148,3 +156,3 @@ } | ||
| fullUrl: string, | ||
| method: string, | ||
| method: Method, | ||
| tree: RouteTree = this.routeTree | ||
@@ -156,11 +164,9 @@ ): TreeSearchResult | undefined { | ||
| if (url === '/') { | ||
| if (tree.routeHandler) { | ||
| if ( | ||
| tree.routeHandler.method === method && | ||
| tree.routeHandler.urlPattern.match(fullUrl) | ||
| ) { | ||
| if (tree.routeHandlers) { | ||
| const potentialMatch = tree.routeHandlers[method]; | ||
| if (potentialMatch && potentialMatch.urlPattern.match(fullUrl)) { | ||
| return { | ||
| matchedRoute: tree.routeHandler, | ||
| params: tree.routeHandler.urlPattern.parse(fullUrl), | ||
| handlers: tree.routeHandler.handlers, | ||
| matchedRoute: potentialMatch, | ||
| params: potentialMatch.urlPattern.parse(fullUrl), | ||
| handlers: potentialMatch.handlers, | ||
| }; | ||
@@ -176,16 +182,14 @@ } | ||
| // If we're at the end of the URL, return the handlers | ||
| if (node.routeHandler) { | ||
| if (node.routeHandlers) { | ||
| this.logger.debug(`Node is a route handler for ${current}`); | ||
| if (rest.length === 0) { | ||
| if ( | ||
| node.routeHandler.method === method && | ||
| node.routeHandler.urlPattern.match(fullUrl) | ||
| ) { | ||
| const potentialMatch = node.routeHandlers[method]; | ||
| if (potentialMatch && potentialMatch.urlPattern.match(fullUrl)) { | ||
| return { | ||
| matchedRoute: node.routeHandler, | ||
| params: node.routeHandler.urlPattern.parse(fullUrl), | ||
| matchedRoute: potentialMatch, | ||
| params: potentialMatch.urlPattern.parse(fullUrl), | ||
| handlers: [ | ||
| ...(tree.middleware ?? []), | ||
| ...(node.middleware ?? []), | ||
| ...node.routeHandler.handlers, | ||
| ...potentialMatch.handlers, | ||
| ].filter(Boolean), | ||
@@ -235,18 +239,20 @@ }; | ||
| this.logger.debug(`Trying argument node ${argumentNode}...`); | ||
| if (argumentNode.routeHandler) { | ||
| if (argumentNode.routeHandlers) { | ||
| this.logger.debug(`Node is a route handler for ${current}`); | ||
| const potentialMatch = argumentNode.routeHandlers[method]; | ||
| if (rest.length === 0) { | ||
| if ( | ||
| argumentNode.routeHandler.method === method && | ||
| argumentNode.routeHandler.urlPattern.match(fullUrl) | ||
| ) { | ||
| if (potentialMatch && potentialMatch.urlPattern.match(fullUrl)) { | ||
| return { | ||
| matchedRoute: argumentNode.routeHandler, | ||
| params: argumentNode.routeHandler.urlPattern.parse(fullUrl), | ||
| matchedRoute: potentialMatch, | ||
| params: potentialMatch.urlPattern.parse(fullUrl), | ||
| handlers: [ | ||
| ...(tree.middleware ?? []), | ||
| ...(argumentNode.middleware ?? []), | ||
| ...argumentNode.routeHandler.handlers, | ||
| ...potentialMatch.handlers, | ||
| ].filter(Boolean), | ||
| }; | ||
| } else { | ||
| this.logger.debug( | ||
| `Method or URL pattern did not match for ${current}` | ||
| ); | ||
| } | ||
@@ -290,4 +296,4 @@ } | ||
| const recurse = (tree: RouteTree) => { | ||
| if (tree.routeHandler) { | ||
| routes.push(tree.routeHandler); | ||
| if (tree.routeHandlers) { | ||
| routes.push(...Object.values(tree.routeHandlers)); | ||
| } | ||
@@ -294,0 +300,0 @@ |
+10
-2
@@ -88,3 +88,2 @@ import { ZodSchema, z } from 'zod'; | ||
| export interface InternalRouteHandler { | ||
| method: string; | ||
| urlPattern: UrlPattern; | ||
@@ -94,5 +93,14 @@ handlers: any[]; | ||
| export type Method = | ||
| | 'GET' | ||
| | 'POST' | ||
| | 'PUT' | ||
| | 'PATCH' | ||
| | 'DELETE' | ||
| | 'HEAD' | ||
| | 'OPTIONS'; | ||
| export interface RouteTree { | ||
| middleware?: RouteHandler[]; | ||
| routeHandler?: InternalRouteHandler; | ||
| routeHandlers?: Partial<Record<Method, InternalRouteHandler>>; | ||
| children?: { | ||
@@ -99,0 +107,0 @@ [key: string]: RouteTree; |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
81558
1.36%2067
1.08%