@bit-js/blitz
Advanced tools
Comparing version 1.0.14 to 1.0.15
import { Radix } from './radix'; | ||
import type { MatchFunction, Options } from './radix/tree/types'; | ||
import type { Options } from './radix/tree/types'; | ||
import { Context as BaseContext } from './types'; | ||
@@ -34,6 +34,2 @@ export * as internal from './radix'; | ||
/** | ||
* Build the fallback handler (include fallbackRouter) | ||
*/ | ||
buildFallback(): MatchFunction<any> | Handler; | ||
/** | ||
* Build the router | ||
@@ -40,0 +36,0 @@ */ |
// @bun | ||
var __defProp=Object.defineProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true,configurable:true,set:(newValue)=>all[name]=()=>newValue})};var exports_radix={};__export(exports_radix,{Tree:()=>{{return Tree}},Radix:()=>{{return Radix}}});class PathParts{inertParts=[];paramParts=[]}function splitPath(path){const parts=new PathParts;const{inertParts,paramParts}=parts;let paramIdx=path.indexOf(":"),start=0;while(paramIdx!==-1){if(paramIdx!==start)inertParts.push(path.substring(start,paramIdx));start=path.indexOf("/",paramIdx+1);if(start===-1){paramParts.push(path.substring(paramIdx+1));return parts}paramParts.push(path.substring(paramIdx+1,start));paramIdx=path.indexOf(":",start+1)}inertParts.push(path.substring(start));return parts}function plus(num,val){if(val===0)return num;const plusIdx=num.indexOf("+");return plusIdx===-1?Number.isNaN(+num)?`${num}+${val.toString()}`:(+num+val).toString():`${num.substring(0,plusIdx)}+${+num.substring(plusIdx+1)+val}`}class ParamNode{paramName;store=null;inert=null;constructor(name){if(name==="$")throw new Error('Parameter name should not be "$" to avoid collision with wildcard parameter');this.paramName=name}}class InertStore{store={};size=0;lastChild;put(item){this.lastChild=item;this.store[item.key]=item;++this.size}}class Node{part;key;store=null;inert=null;params=null;wildcardStore=null;setPart(part){this.part=part;this.key=part.charCodeAt(0).toString()}constructor(part){this.setPart(part)}reset(part,firstChild){this.setPart(part);this.inert=new InertStore;this.inert.put(firstChild);this.store=this.params=this.wildcardStore=null}clone(part){const node=new Node(part);node.store=this.store;node.inert=this.inert;node.params=this.params;node.wildcardStore=this.wildcardStore;return node}param(paramName){if(this.params===null)this.params=new ParamNode(paramName);else if(this.params.paramName!==paramName)throw new Error(`Cannot create route with parameter "${paramName}" because a route already exists with a different parameter name ("${this.params.paramName}") in the same location`);return this.params}compile(ctx,prevPathLen,isChildParam,isNestedChildParam){const{builder}=ctx;const{part}=this;const pathLen=plus(prevPathLen,part.length-1);const isNotRoot=part.length!==1;if(isNotRoot){builder.push(ctx.createTopLevelCheck(part,prevPathLen,pathLen));builder.push("{")}if(this.store!==null)builder.push(`if(path.length===${pathLen})${ctx.yield(this.store)};`);if(this.inert!==null){const nextPathLen=plus(pathLen,1);if(this.inert.size===1){const{lastChild}=this.inert;builder.push(`if(path.charCodeAt(${pathLen})===${lastChild.key}){`);lastChild.compile(ctx,nextPathLen,isChildParam,isNestedChildParam);builder.push("}")}else{const{store}=this.inert;builder.push(`switch(path.charCodeAt(${pathLen})){`);for(const key in store){builder.push(`case ${key}:`);store[key].compile(ctx,nextPathLen,isChildParam,isNestedChildParam);builder.push("break;")}builder.push("}")}}if(this.params!==null){const{params}=this;const prevIndex=isChildParam?"p":pathLen;if(isChildParam){if(!isNestedChildParam)builder.push("let ");builder.push(`p=${pathLen};`)}const nextSlashIndex=ctx.searchPath("/",prevIndex),hasInert=params.inert!==null,hasStore=params.store!==null,{paramName}=params;if(hasInert){if(!isChildParam)builder.push("let ");builder.push(`i=${nextSlashIndex};`)}if(hasStore){builder.push(`if(${hasInert?"i":nextSlashIndex}===-1){`);const value=ctx.slicePath(prevIndex);builder.push("c.params");builder.push(isChildParam?`.${paramName}=${value};`:`={${paramName}:${value}};`);builder.push(ctx.yield(params.store));builder.push("}")}if(hasInert){const value=ctx.substringPath(prevIndex,"i");if(!hasStore)builder.push(`if(i!==-1){`);builder.push("c.params");builder.push(isChildParam?`.${paramName}=${value};`:`={${paramName}:${value}};`);params.inert.compile(ctx,"i+1",true,isChildParam);if(!hasStore)builder.push("}")}}if(this.wildcardStore!==null){const value=ctx.slicePath(pathLen);builder.push("c.params");builder.push(isChildParam?`.\$=${value};`:`={\$:${value}};`);builder.push(ctx.yield(this.wildcardStore));builder.push(";")}if(isNotRoot)builder.push("}")}}function getArgs(value){return value.length===0?"()":"(c)"}class BuildContext{builder;paramsKeys=[];paramsValues=[];options;currentID=0;constructor(options,builder=[]){this.builder=builder;options.invokeResultFunction??=false;this.options=options}insert(value){const key="f"+this.currentID.toString();++this.currentID;this.paramsKeys.push(key);this.paramsValues.push(value);return key}yield(value){if(typeof value==="undefined")return"return";if(typeof value!=="function"){if(typeof value!=="symbol"&&typeof value!=="object")return`return ${JSON.stringify(value)}`}const key=this.insert(value);return this.options.invokeResultFunction?`return ${key}${getArgs(value)}`:`return ${key}`}yieldToken(value){return this.options.invokeResultFunction?`return ${value}(c)`:`return ${value}`}slicePath(idx){return idx==="0"?"path":`path.substring(${idx})`}substringPath(start,end){return`path.substring(${start},${end})`}searchPath(token,startIdx){return`path.indexOf('${token}'${startIdx==="0"?"":","+startIdx})`}createTopLevelCheck(part,prevPathLen,pathLen){if(part.length<15){const result=[];for(let i=1,{length}=part;i<length;++i){result.push(`if(path.charCodeAt(${prevPathLen})===${part.charCodeAt(i)})`);prevPathLen=plus(prevPathLen,1)}return result.join("")}return`if(path.substring(${prevPathLen},${pathLen})==='${part.substring(1)}')`}build(){return Function(...this.paramsKeys,`return (c)=>{${this.builder.join("")}}`)(...this.paramsValues)}}var replaceValue=function(_,value){if(value===null)return;if(value instanceof Map){const obj={};for(const pair of value)obj[String.fromCharCode(pair[0])]=pair[1];return obj}if(typeof value==="function")return value.toString();return value};class Tree{root=null;staticMap=null;store(path,store){if(path.includes(":")||path.charCodeAt(path.length-1)===42)this.storeDynamic(path,store);else this.storeStatic(path,store);return store}storeStatic(path,store){if(path.charCodeAt(0)===47)path=path.slice(1);if(path.charCodeAt(path.length-1)===47)path=path.slice(0,-1);this.staticMap??={};this.staticMap[path]??=store}storeDynamic(path,store){if(path.charCodeAt(0)!==47)path="/"+path;const isWildcard=path.charCodeAt(path.length-1)===42;if(isWildcard)path=path.slice(0,-1);const{inertParts,paramParts}=splitPath(path);let node=this.root??=new Node("/"),paramPartsIndex=0;for(let i=0,{length}=inertParts;i<length;++i){if(i!==0){const params=node.param(paramParts[paramPartsIndex]);++paramPartsIndex;if(params.inert===null){node=params.inert=new Node(inertParts[i]);continue}node=params.inert}let part=inertParts[i];for(let j=0;;){if(j===part.length){if(j<node.part.length)node.reset(part,node.clone(node.part.slice(j)));break}if(j===node.part.length){if(node.inert===null)node.inert=new InertStore;else{const inert=node.inert.store[part.charCodeAt(j).toString()];if(typeof inert!=="undefined"){node=inert;part=part.slice(j);j=0;continue}}const childNode=new Node(part.slice(j));node.inert.put(childNode);node=childNode;break}if(part[j]!==node.part[j]){const newChild=new Node(part.slice(j));const oldNode=node.clone(node.part.slice(j));node.reset(node.part.slice(0,j),oldNode);node.inert.put(newChild);node=newChild;break}++j}}if(paramPartsIndex<paramParts.length)node.param(paramParts[paramPartsIndex]).store??=store;if(isWildcard)node.wildcardStore??=store;else node.store??=store}compile(options,fallback){const{staticMap,root}=this;if(root===null){if(options.invokeResultFunction===true){const fnFallback=typeof fallback==="function"?fallback:()=>fallback;return staticMap===null?fallback:(ctx2)=>(staticMap[ctx2.path]??fnFallback)(ctx2)}return staticMap===null?()=>fallback:(ctx2)=>staticMap[ctx2.path]??fallback}const ctx=new BuildContext(options,["const{path}=c;"]);if(staticMap!==null)ctx.builder.push(`const m=${ctx.insert(staticMap)}[path];if(typeof m!=='undefined')${ctx.yieldToken("m")};`);root.compile(ctx,"0",false,false);if(root.wildcardStore===null)ctx.builder.push(ctx.yield(fallback));return ctx.build()}debug(space){return JSON.stringify(this.root,replaceValue,space)}}class Radix{tree=new Tree;routes(routes){for(let i=0,{length}=routes;i<length;++i)this.put(...routes[i]);return this}put(path,handler){this.tree.store(path,handler);return this}static create(routes){return new this().routes(routes)}buildMatcher(options,fallback){options.invokeResultFunction=false;return this.tree.compile(options,fallback)}buildCaller(options,fallback){options.invokeResultFunction=true;return this.tree.compile(options,fallback)}}function extendContext(C,defaultOpts){if(typeof defaultOpts==="undefined")return C;const parts=[];for(const prop in defaultOpts)parts.push(`${prop}=${JSON.stringify(defaultOpts[prop])}`);return Function(`return (C)=>{return class A extends C{${parts.join()}}}`)()(C)}class Context{req;path;pathStart;pathEnd;params;constructor(req){this.req=req;const start=req.url.indexOf("/",12)+1,end=req.url.indexOf("?",start);this.pathStart=start;if(end===-1){this.path=req.url.substring(start);this.pathEnd=req.url.length}else{this.path=req.url.substring(start,end);this.pathEnd=end}}headers;status;statusText}class Blitz{options;methodRouter;fallbackRouter;fallback=noop;constructor(options={}){this.options=options;this.options=options}put(method,path,handler){this.methodRouter??={};this.methodRouter[method]??=new Radix;this.methodRouter[method].put(path,handler)}handle(path,handler){this.fallbackRouter??=new Radix;this.fallbackRouter.put(path,handler)}buildFallback(){return typeof this.fallbackRouter==="undefined"?this.fallback:this.fallbackRouter.buildCaller(this.options,this.fallback)}build(Construct=Context){const{methodRouter}=this,fallback=this.buildFallback();if(typeof methodRouter==="undefined")return(req)=>fallback(new Construct(req));const methodCaller={};for(const method in methodRouter)methodCaller[method]=methodRouter[method].buildCaller(this.options,fallback);return(req)=>(methodCaller[req.method]??fallback)(new Construct(req))}}var noop=()=>null;export{exports_radix as internal,extendContext,Blitz as default,Context}; | ||
var __defProp=Object.defineProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true,configurable:true,set:(newValue)=>all[name]=()=>newValue})};var exports_radix={};__export(exports_radix,{Tree:()=>{{return Tree}},Radix:()=>{{return Radix}}});class PathParts{inertParts=[];paramParts=[]}function splitPath(path){const parts=new PathParts;const{inertParts,paramParts}=parts;let paramIdx=path.indexOf(":"),start=0;while(paramIdx!==-1){if(paramIdx!==start)inertParts.push(path.substring(start,paramIdx));start=path.indexOf("/",paramIdx+1);if(start===-1){paramParts.push(path.substring(paramIdx+1));return parts}paramParts.push(path.substring(paramIdx+1,start));paramIdx=path.indexOf(":",start+1)}inertParts.push(path.substring(start));return parts}function plus(num,val){if(val===0)return num;const plusIdx=num.indexOf("+");return plusIdx===-1?Number.isNaN(+num)?`${num}+${val.toString()}`:(+num+val).toString():`${num.substring(0,plusIdx)}+${+num.substring(plusIdx+1)+val}`}class ParamNode{paramName;store=null;inert=null;constructor(name){if(name==="$")throw new Error('Parameter name should not be "$" to avoid collision with wildcard parameter');this.paramName=name}}class InertStore{store={};size=0;lastChild;put(item){this.lastChild=item;this.store[item.key]=item;++this.size}}class Node{part;key;store=null;inert=null;params=null;wildcardStore=null;setPart(part){this.part=part;this.key=part.charCodeAt(0).toString()}constructor(part){this.setPart(part)}reset(part,firstChild){this.setPart(part);this.inert=new InertStore;this.inert.put(firstChild);this.store=this.params=this.wildcardStore=null}clone(part){const node=new Node(part);node.store=this.store;node.inert=this.inert;node.params=this.params;node.wildcardStore=this.wildcardStore;return node}param(paramName){if(this.params===null)this.params=new ParamNode(paramName);else if(this.params.paramName!==paramName)throw new Error(`Cannot create route with parameter "${paramName}" because a route already exists with a different parameter name ("${this.params.paramName}") in the same location`);return this.params}compile(ctx,prevPathLen,isChildParam,isNestedChildParam){const{builder}=ctx;const{part}=this;const pathLen=plus(prevPathLen,part.length-1);const isNotRoot=part.length!==1;if(isNotRoot){builder.push(ctx.createTopLevelCheck(part,prevPathLen,pathLen));builder.push("{")}if(this.store!==null)builder.push(`if(path.length===${pathLen})${ctx.yield(this.store)};`);if(this.inert!==null){const nextPathLen=plus(pathLen,1);if(this.inert.size===1){const{lastChild}=this.inert;builder.push(`if(path.charCodeAt(${pathLen})===${lastChild.key}){`);lastChild.compile(ctx,nextPathLen,isChildParam,isNestedChildParam);builder.push("}")}else{const{store}=this.inert;builder.push(`switch(path.charCodeAt(${pathLen})){`);for(const key in store){builder.push(`case ${key}:`);store[key].compile(ctx,nextPathLen,isChildParam,isNestedChildParam);builder.push("break;")}builder.push("}")}}if(this.params!==null){const{params}=this;const prevIndex=isChildParam?"p":pathLen;if(isChildParam){if(!isNestedChildParam)builder.push("let ");builder.push(`p=${pathLen};`)}const nextSlashIndex=ctx.searchPath("/",prevIndex),hasInert=params.inert!==null,hasStore=params.store!==null,{paramName}=params;if(hasInert){if(!isChildParam)builder.push("let ");builder.push(`i=${nextSlashIndex};`)}if(hasStore){builder.push(`if(${hasInert?"i":nextSlashIndex}===-1){`);const value=ctx.slicePath(prevIndex);builder.push("c.params");builder.push(isChildParam?`.${paramName}=${value};`:`={${paramName}:${value}};`);builder.push(ctx.yield(params.store));builder.push("}")}if(hasInert){const value=ctx.substringPath(prevIndex,"i");if(!hasStore)builder.push(`if(i!==-1){`);builder.push("c.params");builder.push(isChildParam?`.${paramName}=${value};`:`={${paramName}:${value}};`);params.inert.compile(ctx,"i+1",true,isChildParam);if(!hasStore)builder.push("}")}}if(this.wildcardStore!==null){const value=ctx.slicePath(pathLen);builder.push("c.params");builder.push(isChildParam?`.\$=${value};`:`={\$:${value}};`);builder.push(ctx.yield(this.wildcardStore));builder.push(";")}if(isNotRoot)builder.push("}")}}function getArgs(value){return value.length===0?"()":"(c)"}class BuildContext{builder;paramsKeys=[];paramsValues=[];options;currentID=0;constructor(options,builder=[]){this.builder=builder;options.invokeResultFunction??=false;this.options=options}insert(value){const key="f"+this.currentID.toString();++this.currentID;this.paramsKeys.push(key);this.paramsValues.push(value);return key}yield(value){if(typeof value==="undefined")return"return";if(typeof value!=="function"){if(typeof value!=="symbol"&&typeof value!=="object")return`return ${JSON.stringify(value)}`}const key=this.insert(value);return this.options.invokeResultFunction?`return ${key}${getArgs(value)}`:`return ${key}`}yieldToken(value){return this.options.invokeResultFunction?`return ${value}(c)`:`return ${value}`}slicePath(idx){return idx==="0"?"path":`path.substring(${idx})`}substringPath(start,end){return`path.substring(${start},${end})`}searchPath(token,startIdx){return`path.indexOf('${token}'${startIdx==="0"?"":","+startIdx})`}createTopLevelCheck(part,prevPathLen,pathLen){const{length}=part;if(length<16){const result=new Array(length);result[0]="";for(let i=1;i<length;++i){result[i]=`if(path.charCodeAt(${prevPathLen})===${part.charCodeAt(i)})`;prevPathLen=plus(prevPathLen,1)}return result.join("")}return`if(path.substring(${prevPathLen},${pathLen})==='${part.substring(1)}')`}build(){return Function(...this.paramsKeys,`return (c)=>{${this.builder.join("")}}`)(...this.paramsValues)}}var replaceValue=function(_,value){if(value===null)return;if(value instanceof Map){const obj={};for(const pair of value)obj[String.fromCharCode(pair[0])]=pair[1];return obj}if(typeof value==="function")return value.toString();return value};class Tree{root=null;staticMap=null;store(path,store){if(path.includes(":")||path.charCodeAt(path.length-1)===42)this.storeDynamic(path,store);else this.storeStatic(path,store);return store}storeStatic(path,store){if(path.charCodeAt(0)===47)path=path.slice(1);if(path.charCodeAt(path.length-1)===47)path=path.slice(0,-1);this.staticMap??={};this.staticMap[path]??=store}storeDynamic(path,store){if(path.charCodeAt(0)!==47)path="/"+path;const isWildcard=path.charCodeAt(path.length-1)===42;if(isWildcard)path=path.slice(0,-1);const{inertParts,paramParts}=splitPath(path);let node=this.root??=new Node("/"),paramPartsIndex=0;for(let i=0,{length}=inertParts;i<length;++i){if(i!==0){const params=node.param(paramParts[paramPartsIndex]);++paramPartsIndex;if(params.inert===null){node=params.inert=new Node(inertParts[i]);continue}node=params.inert}let part=inertParts[i];for(let j=0;;){if(j===part.length){if(j<node.part.length)node.reset(part,node.clone(node.part.slice(j)));break}if(j===node.part.length){if(node.inert===null)node.inert=new InertStore;else{const inert=node.inert.store[part.charCodeAt(j).toString()];if(typeof inert!=="undefined"){node=inert;part=part.slice(j);j=0;continue}}const childNode=new Node(part.slice(j));node.inert.put(childNode);node=childNode;break}if(part[j]!==node.part[j]){const newChild=new Node(part.slice(j));const oldNode=node.clone(node.part.slice(j));node.reset(node.part.slice(0,j),oldNode);node.inert.put(newChild);node=newChild;break}++j}}if(paramPartsIndex<paramParts.length)node.param(paramParts[paramPartsIndex]).store??=store;if(isWildcard)node.wildcardStore??=store;else node.store??=store}compile(options,fallback){const{staticMap,root}=this;if(root===null){if(options.invokeResultFunction===true){const fnFallback=typeof fallback==="function"?fallback:()=>fallback;return staticMap===null?fallback:(ctx2)=>(staticMap[ctx2.path]??fnFallback)(ctx2)}return staticMap===null?()=>fallback:(ctx2)=>staticMap[ctx2.path]??fallback}const ctx=new BuildContext(options,["const{path}=c;"]);if(staticMap!==null)ctx.builder.push(`const m=${ctx.insert(staticMap)}[path];if(typeof m!=='undefined')${ctx.yieldToken("m")};`);root.compile(ctx,"0",false,false);if(root.wildcardStore===null)ctx.builder.push(ctx.yield(fallback));return ctx.build()}debug(space){return JSON.stringify(this.root,replaceValue,space)}}class Radix{tree=new Tree;routes(routes){for(let i=0,{length}=routes;i<length;++i)this.put(...routes[i]);return this}put(path,handler){this.tree.store(path,handler);return this}static create(routes){return new this().routes(routes)}buildMatcher(options,fallback){options.invokeResultFunction=false;return this.tree.compile(options,fallback)}buildCaller(options,fallback){options.invokeResultFunction=true;return this.tree.compile(options,fallback)}}function extendContext(C,defaultOpts){if(typeof defaultOpts==="undefined")return C;const parts=[];for(const prop in defaultOpts)parts.push(`${prop}=${JSON.stringify(defaultOpts[prop])}`);return Function(`return (C)=>{return class A extends C{${parts.join()}}}`)()(C)}class Context{req;path;pathStart;pathEnd;params;constructor(req){this.req=req;const start=req.url.indexOf("/",12)+1,end=req.url.indexOf("?",start);this.pathStart=start;if(end===-1){this.path=req.url.substring(start);this.pathEnd=req.url.length}else{this.path=req.url.substring(start,end);this.pathEnd=end}}headers;status;statusText}class Blitz{options;methodRouter;fallbackRouter;fallback=noop;constructor(options={}){this.options=options;this.options=options}put(method,path,handler){((this.methodRouter??={})[method]??=new Radix).put(path,handler)}handle(path,handler){(this.fallbackRouter??=new Radix).put(path,handler)}build(Construct=Context){const{methodRouter,fallbackRouter}=this;const fallback=typeof fallbackRouter==="undefined"?this.fallback:fallbackRouter.buildCaller(this.options,this.fallback);if(typeof methodRouter==="undefined")return(req)=>fallback(new Construct(req));const methodCaller={};for(const method in methodRouter)methodCaller[method]=methodRouter[method].buildCaller(this.options,fallback);return(req)=>(methodCaller[req.method]??fallback)(new Construct(req))}}var noop=()=>null;export{exports_radix as internal,extendContext,Blitz as default,Context}; |
{ | ||
"name": "@bit-js/blitz", | ||
"main": "lib/index.js", | ||
"version": "1.0.14", | ||
"version": "1.0.15", | ||
"type": "module", | ||
@@ -6,0 +6,0 @@ "devDependencies": { |
19100
319