@mapl/router 0.0.1 → 0.0.2

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.
package/README.md CHANGED
@@ -1,60 +1,3 @@
1
1
  # `@mapl/router`
2
2
 
3
3
  A fast compiled radix tree router.
4
-
5
- ```ts
6
- import {
7
- PARAMS,
8
- PATHNAME,
9
- PATHNAME_LEN,
10
- compileNode,
11
- type RouterCompilerState,
12
- } from "@mapl/router/tree/compiler";
13
- import { createNode, insertItem } from "@mapl/router/tree/node";
14
- import { getExternalKeys, getContent } from "@mapl/compiler";
15
-
16
- // Initialize the root node
17
- const root = createNode("/");
18
-
19
- // Add some routes
20
- insertItem(root, "/", 0);
21
- insertItem(root, "/user/*", 1);
22
- insertItem(root, "/**", 2);
23
-
24
- // Initialize the compiler state
25
- const state: RouterCompilerState<any> = {
26
- contentBuilder: [],
27
- declarationBuilders: [],
28
- localVarCount: 0,
29
- externalValues: [],
30
-
31
- // Same args as compileNode except the first one
32
- compileItem: (item, state) => {
33
- state.contentBuilder.push(`return f${state.externalValues.length};`);
34
- state.externalValues.push(item);
35
- },
36
- };
37
-
38
- // Compile from root node
39
- compileNode(root, state, false, false, 0, "");
40
-
41
- // Create the match function using the result state
42
- const match = Function(
43
- ...getExternalKeys(state),
44
- `return (${PATHNAME},${PARAMS})=>{const ${PATHNAME_LEN}=${PATHNAME}.length;${getContent(state)}}`,
45
- )(...state.externalValues);
46
-
47
- // Example usage
48
- const res0 = match("/", []);
49
- res0; // 0
50
-
51
- const params1 = [];
52
- const res1 = match("/user/0", params1);
53
- params1; // ['0']
54
- res1; // 1
55
-
56
- const params2 = [];
57
- const res2 = match("/navigate/to/about", params2);
58
- params2; // ['navigate/to/about']
59
- res2; // 2
60
- ```
package/constants.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export declare const PATHNAME = "__req_p";
2
+ export declare const PATHNAME_LEN = "__req_pl";
3
+ export declare const PARAMS = "__req_ps";
4
+ export declare const PREV_PARAM_INDEX = "__req_ppi";
5
+ export declare const CURRENT_PARAM_INDEX = "__req_cpi";
package/constants.js ADDED
@@ -0,0 +1 @@
1
+ export const PATHNAME="__req_p";export const PATHNAME_LEN="__req_pl";export const PARAMS="__req_ps";export const PREV_PARAM_INDEX="__req_ppi";export const CURRENT_PARAM_INDEX="__req_cpi";
package/index.d.ts CHANGED
@@ -1 +1,6 @@
1
- export {};
1
+ import { type Node } from './tree/node';
2
+ import type { RouterCompilerState } from './types';
3
+ export type Router = [staticMap: Record<string, any> | null, root: Node | null];
4
+ export declare function createRouter(): Router;
5
+ export declare function insertItem(router: Router, path: string, item: any): void;
6
+ export declare function compileRouter(router: Router, state: RouterCompilerState): void;
package/index.js ADDED
@@ -0,0 +1 @@
1
+ export function createRouter(){return[null,null]}export function insertItem(router,path,item){if(path.includes("*"))nodeInsertItem(router[1]??=createNode("/"),path,item);else(router[0]??={})[path.slice(1)]=item}export function compileRouter(router,state){if(router[0]!==null){const staticMap=router[0];const contentBuilder=state.contentBuilder;for(const key in staticMap){contentBuilder.push(`if(${PATHNAME}===${JSON.stringify(key)}){`);state.compileItem(staticMap[key],state,false);contentBuilder.push("}")}}if(router[1]!==null)compileNode(router[1],state,false,false,-1,"")}import{PATHNAME}from"./constants";import{compileNode}from"./tree/compiler";import{createNode,insertItem as nodeInsertItem}from"./tree/node";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapl/router",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Fast compiled router for all runtimes",
5
5
  "keywords": [
6
6
  "fast",
@@ -1,13 +1,3 @@
1
+ import type { RouterCompilerState } from '../types';
1
2
  import type { Node } from './node';
2
- import type { CompilerState } from '@mapl/compiler';
3
- type ParametersExcludeState<T> = T extends (arg0: any, arg1: any, ...rest: infer R) => any ? R : never;
4
- export interface RouterCompilerState<Item> extends CompilerState {
5
- compileItem: (item: Item, state: this, ...args: ParametersExcludeState<typeof compileNode>) => void;
6
- }
7
- export declare const PATHNAME = "__req_p";
8
- export declare const PATHNAME_LEN = "__req_pl";
9
- export declare const PARAMS = "__req_ps";
10
- export declare const PREV_PARAM_INDEX = "__req_ppi";
11
- export declare const CURRENT_PARAM_INDEX = "__req_cpi";
12
- export declare function compileNode(node: Node, state: RouterCompilerState<any>, hasParam: boolean, hasMultipleParams: boolean, startIndexValue: number, startIndexPrefix: string): void;
13
- export {};
3
+ export declare function compileNode(node: Node, state: RouterCompilerState, hasParam: boolean, hasMultipleParams: boolean, startIndexValue: number, startIndexPrefix: string): void;
package/tree/compiler.js CHANGED
@@ -1 +1 @@
1
- export function compileNode(node,state,hasParam,hasMultipleParams,startIndexValue,startIndexPrefix){const builder=state.contentBuilder;const part=node[0];const partLen=part.length;startIndexValue++;if(partLen!==1){builder.push(`if(__req_pl>${startIndexPrefix}${startIndexValue+partLen-2})`);for(let i=1;i<partLen;i++,startIndexValue++)builder.push(`if(__req_p.charCodeAt(${startIndexPrefix}${startIndexValue})===${part.charCodeAt(i)})`);builder.push("{")}if(node[1]!==null){builder.push(`if(__req_pl===${startIndexPrefix}${startIndexValue}){`);state.compileItem(node[1],state,hasParam,hasMultipleParams,startIndexValue,startIndexPrefix);builder.push("}")}if(node[2]!==null){const children=node[2];const childrenKeys=Object.keys(children);if(childrenKeys.length===1){builder.push(`if(__req_p.charCodeAt(${startIndexPrefix}${startIndexValue})===${childrenKeys[0]}){`);compileNode(children[childrenKeys[0]],state,hasParam,hasMultipleParams,startIndexValue,startIndexPrefix);builder.push("}")}else{builder.push(`switch(__req_p.charCodeAt(${startIndexPrefix}${startIndexValue})){`);for(let i=0,l=childrenKeys.length;i<l;i++){builder.push(`case ${childrenKeys[i]}:`);compileNode(children[childrenKeys[i]],state,hasParam,hasMultipleParams,startIndexValue,startIndexPrefix);builder.push("break;")}builder.push("}")}}if(node[3]!==null){const params=node[3];const hasStore=params[1]!==null;const hasChild=params[0]!==null;const requireAllocation=hasParam?hasMultipleParams:hasChild||!hasStore;if(requireAllocation)builder.push("{");if(hasParam)builder.push(`${hasMultipleParams?"":"let "}__req_ppi=${startIndexPrefix}${startIndexValue};`);const currentIndex=hasParam?"__req_ppi":`${startIndexPrefix}${startIndexValue}`;const slashIndex=`__req_p.indexOf('/',${currentIndex})`;if(hasChild||!hasStore)builder.push(`${hasParam?"":"let "}__req_cpi=${slashIndex};`);if(hasStore){builder.push(`if(${hasChild?"__req_cpi":slashIndex}===-1){__req_ps.push(__req_p.slice(${currentIndex}));`);state.compileItem(params[1],state,true,hasParam,startIndexValue,startIndexPrefix);builder.push("}")}if(hasChild){builder.push(`if(${hasStore?"":"__req_cpi!==-1&&"}__req_cpi!==${currentIndex}){__req_ps.push(__req_p.substring(${currentIndex},__req_cpi));`);compileNode(params[0],state,true,hasParam,0,"__req_cpi+");builder.push("__req_ps.pop();}")}if(requireAllocation)builder.push("}")}if(node[4]!==null){const noStore=node[1]===null;if(noStore)builder.push(`if(__req_pl!==${startIndexPrefix}${startIndexValue}){`);builder.push(`__req_ps.push(__req_p.slice(${startIndexPrefix}${startIndexValue}));`);state.compileItem(node[4],state,hasParam,hasMultipleParams,startIndexValue,startIndexPrefix);if(noStore)builder.push("}")}if(partLen!==1)builder.push("}")}export const PATHNAME="__req_p";export const PATHNAME_LEN="__req_pl";export const PARAMS="__req_ps";export const PREV_PARAM_INDEX="__req_ppi";export const CURRENT_PARAM_INDEX="__req_cpi";
1
+ export function compileNode(node,state,hasParam,hasMultipleParams,startIndexValue,startIndexPrefix){const builder=state.contentBuilder;const part=node[0];const partLen=part.length;startIndexValue++;if(partLen!==1){builder.push(`if(${PATHNAME_LEN}>${startIndexPrefix}${startIndexValue+partLen-2})`);for(let i=1;i<partLen;i++,startIndexValue++)builder.push(`if(${PATHNAME}.charCodeAt(${startIndexPrefix}${startIndexValue})===${part.charCodeAt(i)})`);builder.push("{")}if(node[1]!==null){builder.push(`if(${PATHNAME_LEN}===${startIndexPrefix}${startIndexValue}){`);state.compileItem(node[1],state,hasParam);builder.push("}")}if(node[2]!==null){const children=node[2];const childrenKeys=Object.keys(children);if(childrenKeys.length===1){builder.push(`if(${PATHNAME}.charCodeAt(${startIndexPrefix}${startIndexValue})===${childrenKeys[0]}){`);compileNode(children[childrenKeys[0]],state,hasParam,hasMultipleParams,startIndexValue,startIndexPrefix);builder.push("}")}else{builder.push(`switch(${PATHNAME}.charCodeAt(${startIndexPrefix}${startIndexValue})){`);for(let i=0,l=childrenKeys.length;i<l;i++){builder.push(`case ${childrenKeys[i]}:`);compileNode(children[childrenKeys[i]],state,hasParam,hasMultipleParams,startIndexValue,startIndexPrefix);builder.push("break;")}builder.push("}")}}if(node[3]!==null){const params=node[3];const hasStore=params[1]!==null;const hasChild=params[0]!==null;const requireAllocation=hasParam?hasMultipleParams:hasChild||!hasStore;if(requireAllocation)builder.push("{");if(hasParam)builder.push(`${hasMultipleParams?"":"let "}${PREV_PARAM_INDEX}=${startIndexPrefix}${startIndexValue};`);const currentIndex=hasParam?PREV_PARAM_INDEX:`${startIndexPrefix}${startIndexValue}`;const slashIndex=`${PATHNAME}.indexOf('/',${currentIndex})`;if(hasChild||!hasStore)builder.push(`${hasParam?"":"let "}${CURRENT_PARAM_INDEX}=${slashIndex};`);if(hasStore){builder.push(`if(${hasChild?CURRENT_PARAM_INDEX:slashIndex}===-1){${PARAMS}.push(${PATHNAME}.slice(${currentIndex}));`);state.compileItem(params[1],state,true);builder.push("}")}if(hasChild){builder.push(`if(${hasStore?"":`${CURRENT_PARAM_INDEX}!==-1&&`}${CURRENT_PARAM_INDEX}!==${currentIndex}){${PARAMS}.push(${PATHNAME}.substring(${currentIndex},${CURRENT_PARAM_INDEX}));`);compileNode(params[0],state,true,hasParam,0,`${CURRENT_PARAM_INDEX}+`);builder.push(`${PARAMS}.pop();}`)}if(requireAllocation)builder.push("}")}if(node[4]!==null){const noStore=node[1]===null;if(noStore)builder.push(`if(${PATHNAME_LEN}!==${startIndexPrefix}${startIndexValue}){`);builder.push(`${PARAMS}.push(${PATHNAME}.slice(${startIndexPrefix}${startIndexValue}));`);state.compileItem(node[4],state,hasParam);if(noStore)builder.push("}")}if(partLen!==1)builder.push("}")}import{CURRENT_PARAM_INDEX,PARAMS,PATHNAME,PATHNAME_LEN,PREV_PARAM_INDEX}from"../constants";
package/types.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { CompilerState } from '@mapl/compiler';
2
+ export interface RouterCompilerState extends CompilerState {
3
+ compileItem: (item: unknown, state: RouterCompilerState, hasParam: boolean) => void;
4
+ }
package/tree/matcher.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import type { Node } from './node';
2
- export declare function matchItem(node: Node, path: string, params: string[], startIdx: number): unknown;
package/tree/matcher.js DELETED
@@ -1 +0,0 @@
1
- export function matchItem(node,path,params,startIdx){const part=node[0];const pathPartLen=part.length;const pathLen=path.length;if(pathPartLen>1){if(startIdx+pathPartLen>pathLen)return null;startIdx++;for(let i=1;i<pathPartLen;i++,startIdx++){if(part.charCodeAt(i)!==path.charCodeAt(startIdx))return null}}else startIdx++;if(startIdx===pathLen)return node[1];if(node[2]!==null){const child=node[2][path.charCodeAt(startIdx)];if(typeof child!=="undefined"){const matchResult=matchItem(child,path,params,startIdx);if(matchResult!==null)return matchResult}}if(node[3]!==null){const paramsNode=node[3];const slashIdx=path.indexOf("/",startIdx);if(slashIdx===-1){if(paramsNode[1]!==null){params.push(path.slice(startIdx));return paramsNode[1]}}else if(slashIdx!==startIdx&&paramsNode[0]!==null){params.push(path.substring(startIdx,slashIdx));const matchResult=matchItem(paramsNode[0],path,params,slashIdx);if(matchResult!==null)return matchResult;params.pop()}}if(node[4]!==null){params.push(path.slice(startIdx));return node[4]}return null}