@mapl/router 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,4 @@
1
1
  import type { Router } from "./index.js";
2
- declare const _default: (router: Router<string>, methodInput: string, parsePath: string, startIdx: 0 | 1) => string;
2
+ declare let;
3
+ declare const _default: (router: Router<string>, methodInput: string, start: 0 | 1) => string;
3
4
  export default _default;
@@ -1 +1 @@
1
- import compilePath from"../path/compiler.js";export default (router,methodInput,parsePath,startIdx)=>{let pathRouters=router[1];let methods=router[0];let hasAllMethodHandler=router.length===3;let parsePathStr=hasAllMethodHandler?`"){`+parsePath:`"){`;let str=(hasAllMethodHandler?parsePath+`if(`:`if(`)+methodInput+`==="`+methods[0]+parsePathStr+compilePath(pathRouters[0],startIdx)+`}`;for(let i=1;i<pathRouters.length;i++)str+=`else if(`+methodInput+`==="`+methods[i]+parsePathStr+compilePath(pathRouters[i],startIdx)+`}`;return hasAllMethodHandler?str+compilePath(router[2],startIdx):str};
1
+ import{isEmptyNode}from"../tree/node.js";import{compile}from"../tree/compiler.js";let STR,START_IDX;let each=(value,path)=>{STR+=`case"${START_IDX===1?path:path.slice(1)}":{${value}}`};let compileSubrouter=(mp,node)=>{if(mp.size>0){STR+=`switch(p){`;mp.forEach(each);STR+=`}`}isEmptyNode(node)||(STR+=`{let l=p.length;${compile(node,0,START_IDX,``)}}`)};export default (router,methodInput,start)=>{STR=``;START_IDX=start;let methods=router[0];if(methods.length>0){let nodes=router[1];let maps=router[2];STR+=`switch(${methodInput}){`;for(let i=0;i<methods.length;i++){STR+=`case"${methods[i]}":`;compileSubrouter(maps[i],nodes[i])}STR+=`}`}router.length===3||compileSubrouter(router[4],router[3]);return STR};
package/method/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Router as PathRouter } from "../path/index.js";
2
- export type Router<T = unknown> = [string[], PathRouter<T>[]] | [string[], PathRouter<T>[], PathRouter<T>];
1
+ import { type Node } from "../tree/node.js";
2
+ export type Router<T = unknown> = [string[], Node<T>[], Map<string, T>[]] | [string[], Node<T>[], Map<string, T>[], Node<T>, Map<string, T>];
3
3
  export declare const createRouter: <T>() => Router<T>;
4
4
  export declare const insertItem: <T>(router: Router<T>, method: string, path: string, item: T) => void;
package/method/index.js CHANGED
@@ -1 +1 @@
1
- import{createRouter as createPathRouter,insertItem as insertItemToPath}from"../path/index.js";export let createRouter=()=>[[],[]];export let insertItem=(router,method,path,item)=>{if(method.length>0){let idx=router[0].indexOf(method);if(idx>-1)insertItemToPath(router[1][idx],path,item);else{let newRouter=createPathRouter();insertItemToPath(newRouter,path,item);router[0].push(method);router[1].push(newRouter)}}else{router.length===2&&router.push(createPathRouter());insertItemToPath(router[2],path,item)}};
1
+ import{createRoot,insert}from"../tree/node.js";export let createRouter=()=>[[],[],[]];export let insertItem=(router,method,path,item)=>{if(method!==``){let idx=router[0].indexOf(method);if(idx>-1)path.includes(`*`)?insert(router[1][idx],1,path,1,item):router[2][idx].set(path,item);else{router[0].push(method);let node=createRoot();router[1].push(node);let mp=new Map;router[2].push(mp);path.includes(`*`)?insert(node,1,path,1,item):mp.set(path,item)}}else{router.length===3&&router.push(createRoot(),new Map);path.includes(`*`)?insert(router[3],1,path,1,item):router[4].set(path,item)}};
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@mapl/router","version":"0.9.1","description":"The fastest possible JS router","repository":{"type":"git","url":"git+https://github.com/mapljs/router.git"},"license":"MIT","type":"module","exports":{"./utils":"./utils.js","./constants":"./constants.js","./path":"./path/index.js","./path/compiler":"./path/compiler.js","./method":"./method/index.js","./tree/compiler":"./tree/compiler.js","./tree/node":"./tree/node.js","./method/compiler":"./method/compiler.js"}}
1
+ {"name":"@mapl/router","version":"0.10.0","description":"The fastest possible JS router","repository":{"type":"git","url":"git+https://github.com/mapljs/router.git"},"license":"MIT","type":"module","exports":{"./method":"./method/index.js","./utils":"./utils.js","./method/compiler":"./method/compiler.js","./tree/match":"./tree/match.js","./constants":"./constants.js","./tree/compiler":"./tree/compiler.js","./tree/node":"./tree/node.js"}}
package/tree/compiler.js CHANGED
@@ -1 +1 @@
1
- export let shouldBoundCheck=node=>node[1]==null&&(node[2].length!==1||node[3][0][0].length===1||node[4]!==null||node[5]!==null);export let compile=(node,paramCount,idx,idxPrefix)=>{let builder=``;let currentIdx=idxPrefix+idx;node[1]==null||(builder+=`if(l===${currentIdx}){${node[1]}}`);if(node[2].length>0){let childrenFirstChar=node[2];let children=node[3];if(children.length>1){builder+=`switch(p.charCodeAt(${currentIdx})){`;for(let i=0;i<children.length;i++){let childNode=children[i];let nodePath=childNode[0];let nextIdx=idx+nodePath.length;builder+=`case `+childrenFirstChar[i]+(shouldBoundCheck(childNode)?`:if(l>${idxPrefix+nextIdx})`:`:`)+(nodePath.length>1?`if(p`+(nodePath.length>2?`.startsWith("${nodePath.slice(1)}",${idxPrefix+(idx+1)})){`:`.charCodeAt(${idxPrefix+(idx+1)})===${nodePath.charCodeAt(1)}){`):`{`)+compile(childNode,paramCount,nextIdx,idxPrefix)+`}`}builder+=`}`}else{let childNode=children[0];let nodePath=childNode[0];let nextIdx=idx+nodePath.length;builder+=(shouldBoundCheck(childNode)?`if(l>${idxPrefix+nextIdx})if(p`:`if(p`)+(nodePath.length>1?`.startsWith("${nodePath}",${currentIdx})){`:`.charCodeAt(${currentIdx})===${childrenFirstChar[0]}){`)+compile(childNode,paramCount,nextIdx,idxPrefix)+`}`}}if(node[4]!=null){let params=node[4];let hasChild=params[0]!=null;if(hasChild){let childNode=params[0];if(paramCount>0){builder+=`let i=${currentIdx};`;currentIdx=`i`}else builder+=`let `;builder+=`j=p.indexOf("/",${currentIdx});if(j>${currentIdx}){let q${paramCount}=p.slice(`+currentIdx+(shouldBoundCheck(childNode)?`,j);if(l>j+1){${compile(childNode,paramCount+1,1,`j+`)}}}`:`,j);${compile(childNode,paramCount+1,1,`j+`)}}`)}params[1]!=null&&(builder+=(hasChild?`else if(j===-1){let q`:`if(!p.includes("/",${currentIdx})){let q`)+paramCount+(currentIdx===`0`?`=p;`:`=p.slice(${currentIdx});`)+params[1]+`}`)}node[5]==null||(builder+=`let q`+paramCount+(currentIdx===`0`?`=p;`:`=p.slice(${currentIdx});`)+node[5]);return builder};
1
+ export let shouldBoundCheck=node=>node[1]==null&&(node[2].length!==1||node[3][0][0].length===1||node[4]!==null||node[5]!==null);export let compile=(node,paramCount,idx,idxPrefix)=>{let builder=``;let currentIdx=idxPrefix+idx;node[1]==null||(builder+=`if(l===${currentIdx}){${node[1]}}`);if(node[2].length>0){let childrenFirstChar=node[2];let children=node[3];if(children.length>1){builder+=`switch(p.charCodeAt(${currentIdx})){`;for(let i=0;i<children.length;i++){let childNode=children[i];let nodePath=childNode[0];let nextIdx=idx+nodePath.length;builder+=`case `+childrenFirstChar[i]+(shouldBoundCheck(childNode)?`:if(l>${idxPrefix+nextIdx})`:`:`)+(nodePath.length>1?`if(p.`+(nodePath.length>2?`startsWith("${nodePath.slice(1)}",${idxPrefix+(idx+1)})){`:`charCodeAt(${idxPrefix+(idx+1)})===${nodePath.charCodeAt(1)}){`):`{`)+compile(childNode,paramCount,nextIdx,idxPrefix)+`}`}builder+=`}`}else{let childNode=children[0];let nodePath=childNode[0];builder+=(shouldBoundCheck(childNode)?`if(l>${idxPrefix+(idx+nodePath.length)})if(p.`:`if(p.`)+(nodePath.length>1?`startsWith("${nodePath}",${currentIdx})){`:`charCodeAt(${currentIdx})===${childrenFirstChar[0]}){`)+compile(childNode,paramCount,idx+nodePath.length,idxPrefix)+`}`}}if(node[4]!=null){let params=node[4];let hasChild=params[0]!=null;if(hasChild){let childNode=params[0];if(paramCount>0){builder+=`let i=${currentIdx};j=p.indexOf("/",`;currentIdx=`i`}else builder+=`let j=p.indexOf("/",`;let needBoundCheck=shouldBoundCheck(childNode);builder+=currentIdx+`);if(j>`+currentIdx+(needBoundCheck?`){if(l>j+1){let q`:`){let q`)+paramCount+`=p.slice(${currentIdx},j);`+compile(childNode,paramCount+1,1,`j+`)+(needBoundCheck?`}}`:`}`)}params[1]!=null&&(builder+=(hasChild?`else if(j===-1){let q`:`if(!p.includes("/",${currentIdx})){let q`)+paramCount+(currentIdx===`0`?`=p;`:`=p.slice(${currentIdx});`)+params[1]+`}`)}node[5]==null||(builder+=`let q`+paramCount+(currentIdx===`0`?`=p;`:`=p.slice(${currentIdx});`)+node[5]);return builder};
@@ -0,0 +1,4 @@
1
+ import type { Node } from "./node.js";
2
+ export declare let PARAMS!: string[];
3
+ export declare const init: (path: string) => void;
4
+ export declare const match: <T>(node: Node<T>, start: number) => T | null;
package/tree/match.js ADDED
@@ -0,0 +1 @@
1
+ export let PARAMS;let PATH;let PATH_LEN;export let init=path=>{PATH=path;PATH_LEN=path.length;PARAMS=[]};export let match=(node,start)=>{if(start===PATH_LEN)return node[1];if(node[2].length>0){let childId=node[2].indexOf(PATH.charCodeAt(start));if(childId>-1){let child=node[3][childId];let part=child[0];if(part.length===1||PATH.startsWith(part,start)){let matched=match(child,start+part.length);if(matched!==null)return matched}}}if(node[4]!==null){let paramNode=node[4];if(paramNode[0]===null){if(!PATH.includes(`/`,start)){PARAMS.push(PATH.slice(start));return paramNode[1]}}else{let endIdx=PATH.indexOf(`/`,start);if(endIdx===-1){if(paramNode[1]!==null){PARAMS.push(PATH.slice(start));return paramNode[1]}}else if(endIdx>start){PARAMS.push(PATH.slice(start,endIdx));let matched=match(paramNode[0],endIdx+1);if(matched!==null)return matched;PARAMS.pop()}}}if(node[5]!==null){PARAMS.push(PATH.slice(start));return node[5]}return null};
package/tree/node.d.ts CHANGED
@@ -1,6 +1,40 @@
1
- export type Node<T = unknown> = [part: string, store: T | null, childrenFirstChar: number[], children: Node<T>[], params: ParamNode<T> | null, wildcardStore: T | null];
2
- export type ParamNode<T = unknown> = [child: Node<T> | null, store: T | null];
1
+ export interface Node<T = unknown> {
2
+ /**
3
+ * Part
4
+ */
5
+ 0: string;
6
+ /**
7
+ * Store
8
+ */
9
+ 1: T | null;
10
+ /**
11
+ * Children first chars
12
+ */
13
+ 2: number[];
14
+ /**
15
+ * Children nodes
16
+ */
17
+ 3: Node<T>[];
18
+ /**
19
+ * Parameter node
20
+ */
21
+ 4: ParamNode<T> | null;
22
+ /**
23
+ * Wildcard store
24
+ */
25
+ 5: T | null;
26
+ }
27
+ export interface ParamNode<T = unknown> {
28
+ /**
29
+ * Child node
30
+ */
31
+ 0: Node<T> | null;
32
+ /**
33
+ * Store
34
+ */
35
+ 1: T | null;
36
+ }
3
37
  export declare const isEmptyNode: (node: Node<any>) => boolean;
4
- export declare const insertNewParam: <T>(root: Node<T>, path: string, currentIdx: number, value: T) => void;
5
- export declare const insertNewBranch: <T>(root: Node<T>, path: string, currentIdx: number, value: T) => void;
38
+ export declare const createRoot: <T>() => Node<T>;
39
+ export declare const insertNewBranch: <T>(root: Node<T>, path: string, startIdx: number, nextParamIdx: number, value: T) => void;
6
40
  export declare const insert: <T>(root: Node<T>, nodePartIdx: number, path: string, pathIdx: number, value: T) => void;
package/tree/node.js CHANGED
@@ -1 +1 @@
1
- export let isEmptyNode=node=>node[1]===null&&node[2].length===0&&node[4]===null&&node[5]===null;export let insertNewParam=(root,path,currentIdx,value)=>{if(currentIdx+2===path.length&&path.charCodeAt(currentIdx+1)===42){root[5]=value;return}if(currentIdx+1===path.length){root[4]=[null,value];return}let nextNode=[`/`,null,[],[],null,null];root[4]=[nextNode,null];root=nextNode;insertNewBranch(root,path,currentIdx+2,value)};export let insertNewBranch=(root,path,currentIdx,value)=>{let startIdx=currentIdx;currentIdx=path.indexOf(`*`,startIdx);if(currentIdx>-1){if(startIdx<currentIdx){let nextNode=[path.slice(startIdx,currentIdx),null,[],[],null,null];root[2].push(path.charCodeAt(startIdx));root[3].push(nextNode);root=nextNode}insertNewParam(root,path,currentIdx,value)}else{root[2].push(path.charCodeAt(startIdx));root[3].push([path.slice(startIdx),value,[],[],null,null])}};export let insert=(root,nodePartIdx,path,pathIdx,value)=>{let nodePart=root[0];while(pathIdx<path.length)if(nodePartIdx===nodePart.length)if(path.charCodeAt(pathIdx)===42){if(pathIdx+2===path.length&&path.charCodeAt(pathIdx+1)===42){root[5]=value;return}if(root[4]===null){insertNewParam(root,path,pathIdx,value);return}if(pathIdx+1===path.length){root[4][1]=value;return}root=root[4][0]??=[`/`,null,[],[],null,null];nodePartIdx=1;nodePart=`/`;pathIdx+=2}else{let childrenFirstChar=root[2];let nextNodeId=childrenFirstChar.indexOf(path.charCodeAt(pathIdx));if(nextNodeId===-1){insertNewBranch(root,path,pathIdx,value);return}root=root[3][nextNodeId];nodePartIdx=1;nodePart=root[0];pathIdx++}else if(path.charCodeAt(pathIdx)!==nodePart.charCodeAt(nodePartIdx)){root[3]=[[nodePart.slice(nodePartIdx),root[1],root[2],root[3],root[4],root[5]]];root[2]=[nodePart.charCodeAt(nodePartIdx)];root[0]=nodePart.slice(0,nodePartIdx);root[1]=root[4]=root[5]=null;insertNewBranch(root,path,pathIdx,value);return}else{nodePartIdx++;pathIdx++}if(nodePartIdx<nodePart.length){root[3]=[[nodePart.slice(nodePartIdx),root[1],root[2],root[3],root[4],root[5]]];root[2]=[nodePart.charCodeAt(nodePartIdx)];root[0]=nodePart.slice(0,nodePartIdx);root[4]=root[5]=null}root[1]=value};
1
+ export let isEmptyNode=node=>node[1]==null&&node[2].length===0&&node[4]==null&&node[5]==null;export let createRoot=()=>[`/`,null,[],[],null,null];export let insertNewBranch=(root,path,startIdx,nextParamIdx,value)=>{while(nextParamIdx>-1){if(startIdx<nextParamIdx){let nextNode=[path.slice(startIdx,nextParamIdx),null,[],[],null,null];root[2].push(path.charCodeAt(startIdx));root[3].push(nextNode);root=nextNode}if(nextParamIdx+2===path.length)root[5]=value;else if(nextParamIdx+1===path.length)root[4]=[null,value];else{let nextNode=createRoot();root[4]=[nextNode,null];root=nextNode;startIdx=nextParamIdx+2;nextParamIdx=path.indexOf(`*`,startIdx);continue}return}root[2].push(path.charCodeAt(startIdx));root[3].push([path.slice(startIdx),value,[],[],null,null])};export let insert=(root,nodePartIdx,path,pathIdx,value)=>{let nodePart=root[0];while(pathIdx<path.length)if(nodePartIdx===nodePart.length)if(path.charCodeAt(pathIdx)===42){if(pathIdx+2===path.length)root[5]=value;else if(root[4]===null)insertNewBranch(root,path,pathIdx,pathIdx,value);else if(pathIdx+1===path.length)root[4][1]=value;else{root=root[4][0]??=createRoot();nodePartIdx=1;nodePart=`/`;pathIdx+=2;continue}return}else{let nextNodeId=root[2].indexOf(path.charCodeAt(pathIdx));if(nextNodeId===-1){insertNewBranch(root,path,pathIdx,path.indexOf(`*`,pathIdx+1),value);return}root=root[3][nextNodeId];nodePartIdx=1;nodePart=root[0];pathIdx++}else if(path.charCodeAt(pathIdx)!==nodePart.charCodeAt(nodePartIdx)){root[3]=[[nodePart.slice(nodePartIdx),root[1],root[2],root[3],root[4],root[5]]];root[2]=[nodePart.charCodeAt(nodePartIdx)];root[0]=nodePart.slice(0,nodePartIdx);root[1]=root[4]=root[5]=null;insertNewBranch(root,path,pathIdx,path.indexOf(`*`,pathIdx),value);return}else{nodePartIdx++;pathIdx++}if(nodePartIdx<nodePart.length){root[3]=[[nodePart.slice(nodePartIdx),root[1],root[2],root[3],root[4],root[5]]];root[2]=[nodePart.charCodeAt(nodePartIdx)];root[0]=nodePart.slice(0,nodePartIdx);root[4]=root[5]=null}root[1]=value};
@@ -1,7 +0,0 @@
1
- import type { Router } from "./index.js";
2
- declare const _default: (router: Router<string>, startIndex: 0 | 1) => string;
3
- /**
4
- * If `startIndex === 1`, input path should start with `/`.
5
- * If `startIndex === 0`, input path should have sliced first `/`.
6
- */
7
- export default _default;
package/path/compiler.js DELETED
@@ -1 +0,0 @@
1
- import{compile}from"../tree/compiler.js";import{isEmptyNode}from"../tree/node.js";export default (router,startIndex)=>{let str=``;if(router.length>1){str=`if(p==="`+(startIndex===1?router[1]:router[1].slice(1))+`"){`+router[2]+`}`;for(let i=3;i<router.length;i+=2)str+=`else if(p==="`+(startIndex===1?router[i]:router[i].slice(1))+`"){`+router[i+1]+`}`}return isEmptyNode(router[0])?str:str+`let l=p.length;`+compile(router[0],0,startIndex,``)};
package/path/index.d.ts DELETED
@@ -1,9 +0,0 @@
1
- import { type Node } from "../tree/node.js";
2
- /**
3
- * @example
4
- * [createNode('/'), '/', 'return new Response("Hi");', '/param/*', 'return new Response(p0)'];
5
- */
6
- export type Router<T = unknown> = [root: Node<T>, ...staticMap: any[]];
7
- export declare const createRouter: <T>() => Router<T>;
8
- export declare const insertItem: <T>(router: Router<T>, path: string, item: T) => void;
9
- export declare const createStaticMap: <T>(router: Router<T>) => Map<string, T>;
package/path/index.js DELETED
@@ -1 +0,0 @@
1
- import{insert}from"../tree/node.js";export let createRouter=()=>[[`/`,null,[],[],null,null]];export let insertItem=(router,path,item)=>{path.includes(`*`)?insert(router[0],1,path,1,item):router.push(path,item)};export let createStaticMap=router=>{let mp=new Map;for(let i=1;i<router.length;i+=2)mp.set(router[i],router[i+1]);return mp};