@bit-js/blitz
Advanced tools
Comparing version 1.3.7 to 1.3.8
// @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_internal={};__export(exports_internal,{Tree:()=>{{return Tree}},Radix:()=>{{return Radix}},Edge:()=>{{return Edge}},Context:()=>{{return Context}},BaseRouter:()=>{{return BaseRouter}}});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 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}var commonPrefixEnd=function(part,otherPart){const minLen=Math.min(part.length,otherPart.length);for(let i=1;i<minLen;++i)if(part[i]!==otherPart[i])return i;return minLen};var replaceValue=function(key,value){if(value===null||key in ignoreKeys)return;if(typeof value==="function")return value.toString();return value};class ParamNode{name;store=null;inert=null;constructor(name){if(name==="$")throw new Error('Parameter name should not be "$" to avoid collision with wildcard parameter');this.name=name}merge(node){if(this.name!==node.name)throw new Error(`Cannot create merge route with parameter "${node.name}" because a route already exists with a different parameter name ("${this.name}") in the same location`);this.store??=node.store;if(node.inert!==null){if(this.inert===null)this.inert=node.inert;else this.inert.mergeWithInert(node.inert)}}mergeWithRoot(node){if(this.inert===null)this.inert=node;else this.inert.mergeWithRoot(node)}debug(){return JSON.parse(JSON.stringify(this,replaceValue))}}class InertStore{store={};size=0;lastChild;put(item){this.lastChild=item;this.store[item.part.charCodeAt(0)]=item;++this.size}}class Node{part;store=null;inert=null;params=null;wildcardStore=null;constructor(part){this.part=part}reset(part,firstChild){const inert=new InertStore;inert.put(firstChild);this.inert=inert;this.part=part;this.store=this.params=this.wildcardStore=null}split(part,firstChild,secondChild){const inert=new InertStore;inert.put(firstChild);inert.put(secondChild);this.inert=inert;this.part=part;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}setInert(node){const store=(this.inert??=new InertStore).store[node.part.charCodeAt(0)];if(typeof store==="undefined")this.inert.put(node);else store.mergeWithInert(node)}insert(path,store){let node=this;const lastIdx=path.length-1;const isWildcard=path.charCodeAt(lastIdx)===42;const{inertParts,paramParts}=splitPath(isWildcard?path.substring(0,lastIdx):path);let paramPartsIndex=0;for(let i=0,{length}=inertParts;i<length;++i){if(i!==0){const params=node.param(paramParts[paramPartsIndex++]);if(params.inert===null){node=params.inert=new Node(inertParts[i]);continue}node=params.inert}let inertPart=inertParts[i];for(let j=0;;){if(j===inertPart.length){if(j<node.part.length)node.reset(inertPart,node.clone(node.part.substring(j)));break}if(j===node.part.length){if(node.inert===null)node.inert=new InertStore;else{const inert=node.inert.store[inertPart.charCodeAt(j)];if(typeof inert!=="undefined"){node=inert;inertPart=inertPart.substring(j);j=0;continue}}const childNode=new Node(inertPart.substring(j));node.inert.put(childNode);node=childNode;break}if(inertPart[j]!==node.part[j]){const newChild=new Node(inertPart.substring(j));node.split(node.part.substring(0,j),node.clone(node.part.substring(j)),newChild);node=newChild;break}++j}}if(paramPartsIndex<paramParts.length){const paramNode=node.param(paramParts[paramPartsIndex]);paramNode.store??=store;return paramNode}else if(isWildcard)node.wildcardStore??=store;else node.store??=store;return node}cloneSelf(){return this.clone(this.part)}mergeWithRoot(node){const{part}=this;const{length}=part;if(length===1)return this.mergeExact(node);if((this.store??=node.store)===null){if(part.charCodeAt(length-1)!==47)this.part+="/";this.mergeExact(node)}else{const newNode=new Node("/");newNode.mergeExact(node);this.setInert(newNode)}}mergeWithInert(node){const currentPart=this.part;const otherPart=node.part;if(currentPart===otherPart)return this.mergeExact(node);const prefixEnd=commonPrefixEnd(currentPart,otherPart);if(prefixEnd===currentPart.length)return this.setInert(node.clone(otherPart.substring(prefixEnd)));if(prefixEnd===otherPart.length){const newNode=node.cloneSelf();newNode.setInert(this.clone(currentPart.substring(prefixEnd)));this.part=newNode.part;this.store=newNode.store;this.inert=newNode.inert;this.params=newNode.params;this.wildcardStore=newNode.wildcardStore;return}this.split(prefixEnd===0?"/":currentPart.substring(0,prefixEnd),this.clone(currentPart.substring(prefixEnd)),node.clone(otherPart.substring(prefixEnd)))}mergeExact(node){this.store??=node.store;this.wildcardStore??=node.wildcardStore;if(node.inert!==null){if(this.inert===null)this.inert=node.inert;else{const newStore=node.inert.store;for(const key in newStore)this.setInert(newStore[key])}}if(node.params!==null){if(this.params===null)this.params=node.params;else this.params.merge(node.params)}}param(paramName){if(this.params===null)this.params=new ParamNode(paramName);else if(this.params.name!==paramName)throw new Error(`Cannot create route with parameter "${paramName}" because a route already exists with a different parameter name ("${this.params.name}") 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)+"{");const hasStore=this.store!==null;if(hasStore)builder.push(`if(path.length===${pathLen})return ${ctx.inlineValue(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.part.charCodeAt(0)}){`);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 paramHasInert=params.inert!==null,paramHasStore=params.store!==null,{name}=params;const nextSlashIdx=ctx.searchPath("/",prevIndex);if(!paramHasStore||paramHasInert){if(!isChildParam)builder.push("let ");builder.push(`i=${nextSlashIdx};`)}if(paramHasStore){builder.push(`if(${paramHasInert?"i":nextSlashIdx}===-1){`);const value=ctx.slicePath(prevIndex);builder.push(`c.params${isChildParam?`.${name}=${value};`:`={${name}:${value}};`}`);builder.push("return "+ctx.inlineValue(params.store));builder.push("}")}if(paramHasInert){const value=ctx.substringPath(prevIndex,"i");builder.push(paramHasStore?`if(i!==${prevIndex}){`:`if(i!==-1&&i!==${prevIndex}){`);builder.push(`c.params${isChildParam?`.${name}=${value};`:`={${name}:${value}};`}`);params.inert.compile(ctx,"i+1",true,isChildParam);builder.push("}")}}if(this.wildcardStore!==null){if(!hasStore)builder.push(`if(path.length!==${pathLen}){`);const value=ctx.slicePath(pathLen);builder.push(`c.params${isChildParam?`.\$=${value};`:`={\$:${value}};`}`);builder.push("return "+ctx.inlineValue(this.wildcardStore));builder.push(";");if(!hasStore)builder.push("}")}if(isNotRoot)builder.push("}")}matchRoute(path,param,startIdx){const{part}=this;const{length}=path;const pathPartLen=part.length;const pathPartEndIndex=startIdx+pathPartLen;if(pathPartLen>1&&(pathPartEndIndex>length||path.indexOf(part,startIdx)!==startIdx))return null;if(pathPartEndIndex===length)return this.store;if(this.inert!==null){const staticChild=this.inert.store[path.charCodeAt(pathPartEndIndex)];if(typeof staticChild!=="undefined"){const route=staticChild.matchRoute(path,param,pathPartEndIndex);if(route!==null)return route}}if(this.params!==null){const{params}=this;const slashIndex=path.indexOf("/",pathPartEndIndex);if(slashIndex===-1){if(params.store!==null){param[params.name]=path.substring(pathPartEndIndex);return params.store}}else if(slashIndex!==pathPartEndIndex&¶ms.inert!==null){const route=params.inert.matchRoute(path,param,slashIndex);if(route!==null){param[params.name]=path.substring(pathPartEndIndex,slashIndex);return route}}}if(this.wildcardStore!==null){param.$=path.substring(pathPartEndIndex);return this.wildcardStore}return null}debug(){return JSON.parse(JSON.stringify(this,replaceValue))}}var ignoreKeys={lastChild:null};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}inlineValue(value){if(typeof value==="undefined")return"";if(typeof value!=="function"){if(typeof value!=="symbol"&&typeof value!=="object")return JSON.stringify(value)}return this.options.invokeResultFunction?this.insert(value)+getArgs(value):this.insert(value)}inlineToken(value){return this.options.invokeResultFunction?value+"(c)":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<15){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)}')`}inline(){return this.paramsKeys.length===0?`(()=>(c)=>{${this.builder.join("")}})`:`(({paramsValues:[${this.paramsKeys}]})=>(c)=>{${this.builder.join("")}})`}build(){return Function(...this.paramsKeys,`return (c)=>{${this.builder.join("")}}`)(...this.paramsValues)}}class Tree{root=null;staticMap=null;store(path,store){if(path.charCodeAt(0)!==47)throw new Error("Path should start with a slash");const{length}=path;const lastCharCode=path.charCodeAt(length-1);if(length!==1&&lastCharCode===47)throw new Error("Path should not end with a slash");if(lastCharCode===42||path.includes(":"))(this.root??=new Node("/")).insert(path,store);else(this.staticMap??={})[path]??=store;return store}mergeRoot(base,root){if(this.root===null){if(base.length===1){this.root=root;return}else this.root=new Node("/")}this.root.insert(base,null).mergeWithRoot(root)}mergeStatic(base,staticMap){if(base.length<2){if(this.staticMap===null)this.staticMap=staticMap;else{const oldStaticMap=this.staticMap;for(const key in staticMap)oldStaticMap[key]??=staticMap[key]}}else{if(base.includes(":"))throw new Error(`Base cannot includes patterns, instead recieved: ${base}`);const oldStaticMap=this.staticMap??={};for(const key in staticMap)oldStaticMap[key.length===1?base:`${base}${key}`]??=staticMap[key]}}merge(base,tree){if(base.charCodeAt(0)!==47)throw new Error("Path should start with a slash");const{length}=base;if(length!==1&&base.charCodeAt(length-1)===47)throw new Error("Path should not end with a slash");const{staticMap,root}=tree;if(root!==null)this.mergeRoot(base,root);if(staticMap!==null)this.mergeStatic(base,staticMap)}inspect(options,fallback){const{staticMap,root}=this;const builder=["const {path}=c;"];const ctx=new BuildContext(options,builder);if(staticMap!==null)builder.push(root===null?`return ${ctx.inlineToken(`(${ctx.insert(staticMap)}[path]??${ctx.insert(fallback)})`)};`:`const m=${ctx.insert(staticMap)}[path];if(m!==undefined)return ${ctx.inlineToken("m")};`);if(root!==null){root.compile(ctx,"1",false,false);if(root.wildcardStore===null)builder.push("return "+ctx.inlineValue(fallback))}return ctx}compile(options,fallback){if(this.root===null){const{staticMap}=this;return options.invokeResultFunction===true?staticMap===null?fallback:(ctx)=>(staticMap[ctx.path]??fallback)(ctx):staticMap===null?()=>fallback:(ctx)=>staticMap[ctx.path]??fallback}return this.inspect(options,fallback).build()}compileMatcher(options,fallback){const{root,staticMap}=this;if(root===null)return options.invokeResultFunction===true?staticMap===null?fallback:(ctx)=>(staticMap[ctx.path]??fallback)(ctx):staticMap===null?()=>fallback:(ctx)=>staticMap[ctx.path]??fallback;if(staticMap===null)return options.invokeResultFunction===true?(ctx)=>(root.matchRoute(ctx.path,ctx.params={},0)??fallback)(ctx):(ctx)=>root.matchRoute(ctx.path,ctx.params={},0)??fallback;return options.invokeResultFunction===true?(ctx)=>{const{path}=ctx;return(staticMap[path]??root.matchRoute(path,ctx.params={},0)??fallback)(ctx)}:(ctx)=>{const{path}=ctx;return staticMap[path]??root.matchRoute(path,ctx.params={},0)??fallback}}}class Context{path;params}class Options{invokeResultFunction}class BaseRouter{tree=new Tree;on(path,handler){this.tree.store(path,handler);return this}route(base,router){this.tree.merge(base,router.tree)}}class Radix extends BaseRouter{buildMatcher(options,fallback){options.invokeResultFunction=false;return this.tree.compile(options,fallback)}buildCaller(options,fallback){options.invokeResultFunction=true;return this.tree.compile(options,fallback)}inspect(options,fallback){return this.tree.inspect(options,fallback)}}class Edge extends BaseRouter{buildMatcher(options,fallback){options.invokeResultFunction=false;return this.tree.compileMatcher(options,fallback)}buildCaller(options,fallback){options.invokeResultFunction=true;return this.tree.compileMatcher(options,fallback)}}class Context2{path;pathStart;pathEnd;params;req;constructor(req){const{url}=req;const start=url.indexOf("/",12);const end=url.indexOf("?",start+1);this.pathStart=start;this.req=req;this.path=url.substring(start,this.pathEnd=end===-1?url.length:end)}}class Router{options;methodRouter;fallbackRouter;fallback=noop;constructor(options=new Options){this.options=options;options.invokeResultFunction=true;this.options=options}route(base,{methodRouter:otherMethodRouter,fallbackRouter:otherFallbackRouter}){if(typeof otherMethodRouter!=="undefined"){const methodRouter=this.methodRouter??={};for(const method in otherMethodRouter){const router=methodRouter[method];if(typeof router==="undefined")methodRouter[method]=otherMethodRouter[method];else router.route(base,otherMethodRouter[method])}}if(typeof otherFallbackRouter!=="undefined"){const{fallbackRouter}=this;if(typeof fallbackRouter==="undefined")this.fallbackRouter=otherFallbackRouter;else fallbackRouter.route(base,otherFallbackRouter)}}build(Construct=Context2){const{methodRouter,options}=this;const fallback=this.fallbackRouter?.buildCaller(options,this.fallback)??this.fallback;if(methodRouter===undefined)return(req)=>fallback(new Construct(req));const methodCaller={};for(const method in methodRouter)methodCaller[method]=methodRouter[method].buildCaller(options,fallback);return(req)=>(methodCaller[req.method]??fallback)(new Construct(req))}}var noop=()=>null;class Blitz extends Router{on(method,path,handler){((this.methodRouter??={})[method]??=new Radix).on(path,handler)}handle(path,handler){(this.fallbackRouter??=new Radix).on(path,handler)}fallbackRouterContext;methodRouterContext;setupInline(){const{methodRouter,fallbackRouter,options,fallback}=this;this.fallbackRouterContext=fallbackRouter?.inspect(options,fallback);if(methodRouter!==undefined){const ctx=this.methodRouterContext={};for(const key in methodRouter)ctx[key]=methodRouter[key].inspect(options,fallback)}return this}inline({routerImportSource,contextImportSource}){const{methodRouter,fallbackRouter}=this;const literal=`/**@ts-nocheck*/import r from ${JSON.stringify(routerImportSource)};import {Context} from ${JSON.stringify(contextImportSource)};${fallbackRouter===undefined?"const {fallback}=r":`const fallback=${this.fallbackRouterContext?.inline()}(r.fallbackRouterContext)`};`;if(methodRouter===undefined)return literal+"export default (c)=>fallback(new Context(c))";const{methodRouterContext}=this;const keys=Object.keys(methodRouter);return`${literal}const {methodRouterContext:{${keys}}}=r;const o={${keys.map((key)=>`${key}:${methodRouterContext[key].inline()}(${key})`).join(",")}};export default (c)=>(o[c.method]??fallback)(new Context(c))`}}class EdgeRouter extends Router{on(method,path,handler){((this.methodRouter??={})[method]??=new Edge).on(path,handler)}handle(path,handler){(this.fallbackRouter??=new Edge).on(path,handler)}}var trimPath=function(path){const startExt=path.lastIndexOf(".");return startExt===-1?path.endsWith("/index")?path.length===6?"/":path.substring(path.length-6):path:path.charCodeAt(startExt-1)===120&&path.charCodeAt(startExt-2)===101&&path.charCodeAt(startExt-3)===100&&path.charCodeAt(startExt-4)===110&&path.charCodeAt(startExt-5)===105?startExt===6?"/":path.substring(0,startExt-6):path.substring(0,startExt)};var normalize=function(path){return path.replace(/\/\/|\\\\|\\/g,"/")};var defaultStyleMap={basic(path){let bracketIdx=path.indexOf("[");let pathBuilder=path.charCodeAt(0)===47?"":"/";let startIdx=0;while(bracketIdx!==-1){pathBuilder+=path.substring(startIdx,bracketIdx);if(path.charCodeAt(bracketIdx+1)===46&&path.charCodeAt(bracketIdx+2)===46&&path.charCodeAt(bracketIdx+3)===46)return trimPath(pathBuilder+"*");pathBuilder+=":";startIdx=path.indexOf("]",bracketIdx);pathBuilder+=path.substring(bracketIdx+1,startIdx);++startIdx;bracketIdx=path.indexOf("[",startIdx)}return trimPath(pathBuilder+path.substring(startIdx))},preserve(path){return path.charCodeAt(0)===47?path:"/"+path}};var compileOptions={invokeResultFunction:false};class RequestContext extends Context2{result}class Router2{static Context=RequestContext;style;on;scanFiles;constructor({style,on,scan}){this.style=typeof style==="undefined"?defaultStyleMap.basic:typeof style==="string"?defaultStyleMap[style]:style;this.on=on;this.scanFiles=scan}scan(cwd="."){const{on,style,scanFiles}=this;const router=new Radix;const files=scanFiles(cwd);if(Array.isArray(files))for(let i=0,{length}=files;i<length;++i){const path=files[i];const route=style(path);if(route===null)continue;router.on(route,on(normalize(cwd+path)))}else for(const path of files){const route=style(path);if(route===null)continue;router.on(route,on(normalize(cwd+path)))}const match=router.buildMatcher(compileOptions,null);return(req)=>{const ctx=new RequestContext(req);ctx.result=match(ctx);return ctx}}}var fs_default=Router2;export{exports_internal as internal,Blitz as default,fs_default as FileSystemRouter,EdgeRouter,Context2 as Context,Router as BaseRouter}; | ||
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_internal={};__export(exports_internal,{Tree:()=>{{return Tree}},Radix:()=>{{return Radix}},Edge:()=>{{return Edge}},Context:()=>{{return Context}},BaseRouter:()=>{{return BaseRouter}}});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 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}var commonPrefixEnd=function(part,otherPart){const minLen=Math.min(part.length,otherPart.length);for(let i=1;i<minLen;++i)if(part[i]!==otherPart[i])return i;return minLen};var replaceValue=function(key,value){if(value===null||key in ignoreKeys)return;if(typeof value==="function")return value.toString();return value};class ParamNode{name;store=null;inert=null;constructor(name){if(name==="$")throw new Error('Parameter name should not be "$" to avoid collision with wildcard parameter');this.name=name}merge(node){if(this.name!==node.name)throw new Error(`Cannot create merge route with parameter "${node.name}" because a route already exists with a different parameter name ("${this.name}") in the same location`);this.store??=node.store;if(node.inert!==null){if(this.inert===null)this.inert=node.inert;else this.inert.mergeWithInert(node.inert)}}mergeWithRoot(node){if(this.inert===null)this.inert=node;else this.inert.mergeWithRoot(node)}debug(){return JSON.parse(JSON.stringify(this,replaceValue))}}class InertStore{store={};size=0;lastChild;put(item){this.lastChild=item;this.store[item.part.charCodeAt(0)]=item;++this.size}}class Node{part;store=null;inert=null;params=null;wildcardStore=null;constructor(part){this.part=part}reset(part,firstChild){const inert=new InertStore;inert.put(firstChild);this.inert=inert;this.part=part;this.store=this.params=this.wildcardStore=null}split(part,firstChild,secondChild){const inert=new InertStore;inert.put(firstChild);inert.put(secondChild);this.inert=inert;this.part=part;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}setInert(node){const store=(this.inert??=new InertStore).store[node.part.charCodeAt(0)];if(typeof store==="undefined")this.inert.put(node);else store.mergeWithInert(node)}insert(path,store){let node=this;const lastIdx=path.length-1;const isWildcard=path.charCodeAt(lastIdx)===42;const{inertParts,paramParts}=splitPath(isWildcard?path.substring(0,lastIdx):path);let paramPartsIndex=0;for(let i=0,{length}=inertParts;i<length;++i){if(i!==0){const params=node.param(paramParts[paramPartsIndex++]);if(params.inert===null){node=params.inert=new Node(inertParts[i]);continue}node=params.inert}let inertPart=inertParts[i];for(let j=0;;){if(j===inertPart.length){if(j<node.part.length)node.reset(inertPart,node.clone(node.part.substring(j)));break}if(j===node.part.length){if(node.inert===null)node.inert=new InertStore;else{const inert=node.inert.store[inertPart.charCodeAt(j)];if(typeof inert!=="undefined"){node=inert;inertPart=inertPart.substring(j);j=0;continue}}const childNode=new Node(inertPart.substring(j));node.inert.put(childNode);node=childNode;break}if(inertPart[j]!==node.part[j]){const newChild=new Node(inertPart.substring(j));node.split(node.part.substring(0,j),node.clone(node.part.substring(j)),newChild);node=newChild;break}++j}}if(paramPartsIndex<paramParts.length){const paramNode=node.param(paramParts[paramPartsIndex]);paramNode.store??=store;return paramNode}else if(isWildcard)node.wildcardStore??=store;else node.store??=store;return node}cloneSelf(){return this.clone(this.part)}mergeWithRoot(node){const{part}=this;const{length}=part;if(length===1)return this.mergeExact(node);if((this.store??=node.store)===null){if(part.charCodeAt(length-1)!==47)this.part+="/";this.mergeExact(node)}else{const newNode=new Node("/");newNode.mergeExact(node);this.setInert(newNode)}}mergeWithInert(node){const currentPart=this.part;const otherPart=node.part;if(currentPart===otherPart)return this.mergeExact(node);const prefixEnd=commonPrefixEnd(currentPart,otherPart);if(prefixEnd===currentPart.length)return this.setInert(node.clone(otherPart.substring(prefixEnd)));if(prefixEnd===otherPart.length){const newNode=node.cloneSelf();newNode.setInert(this.clone(currentPart.substring(prefixEnd)));this.part=newNode.part;this.store=newNode.store;this.inert=newNode.inert;this.params=newNode.params;this.wildcardStore=newNode.wildcardStore;return}this.split(prefixEnd===0?"/":currentPart.substring(0,prefixEnd),this.clone(currentPart.substring(prefixEnd)),node.clone(otherPart.substring(prefixEnd)))}mergeExact(node){this.store??=node.store;this.wildcardStore??=node.wildcardStore;if(node.inert!==null){if(this.inert===null)this.inert=node.inert;else{const newStore=node.inert.store;for(const key in newStore)this.setInert(newStore[key])}}if(node.params!==null){if(this.params===null)this.params=node.params;else this.params.merge(node.params)}}param(paramName){if(this.params===null)this.params=new ParamNode(paramName);else if(this.params.name!==paramName)throw new Error(`Cannot create route with parameter "${paramName}" because a route already exists with a different parameter name ("${this.params.name}") 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)+"{");const hasStore=this.store!==null;if(hasStore)builder.push(`if(path.length===${pathLen})return ${ctx.inlineValue(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.part.charCodeAt(0)}){`);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 paramHasInert=params.inert!==null,paramHasStore=params.store!==null,{name}=params;const nextSlashIdx=ctx.searchPath("/",prevIndex);if(!paramHasStore||paramHasInert){if(!isChildParam)builder.push("let ");builder.push(`i=${nextSlashIdx};`)}if(paramHasStore){builder.push(`if(${paramHasInert?"i":nextSlashIdx}===-1){`);const value=ctx.slicePath(prevIndex);builder.push(`c.params${isChildParam?`.${name}=${value};`:`={${name}:${value}};`}`);builder.push("return "+ctx.inlineValue(params.store));builder.push("}")}if(paramHasInert){const value=ctx.substringPath(prevIndex,"i");builder.push(paramHasStore?`if(i!==${prevIndex}){`:`if(i!==-1&&i!==${prevIndex}){`);builder.push(`c.params${isChildParam?`.${name}=${value};`:`={${name}:${value}};`}`);params.inert.compile(ctx,"i+1",true,isChildParam);builder.push("}")}}if(this.wildcardStore!==null){if(!hasStore)builder.push(`if(path.length!==${pathLen}){`);const value=ctx.slicePath(pathLen);builder.push(`c.params${isChildParam?`.\$=${value};`:`={\$:${value}};`}`);builder.push("return "+ctx.inlineValue(this.wildcardStore));builder.push(";");if(!hasStore)builder.push("}")}if(isNotRoot)builder.push("}")}loadDependencies(dependencies){if(this.store!==null)dependencies.push(this.store);if(this.inert!==null){const{store}=this.inert;for(const key in store)store[key].loadDependencies(dependencies)}if(this.params!==null){const{params}=this;if(params.store!==null)dependencies.push(params.store);if(params.inert!==null)params.inert.loadDependencies(dependencies)}if(this.wildcardStore!==null)dependencies.push(this.wildcardStore)}matchRoute(path,param,startIdx){const{part}=this;const{length}=path;const pathPartLen=part.length;const pathPartEndIndex=startIdx+pathPartLen;if(pathPartLen>1&&(pathPartEndIndex>length||path.indexOf(part,startIdx)!==startIdx))return null;if(pathPartEndIndex===length)return this.store;if(this.inert!==null){const staticChild=this.inert.store[path.charCodeAt(pathPartEndIndex)];if(typeof staticChild!=="undefined"){const route=staticChild.matchRoute(path,param,pathPartEndIndex);if(route!==null)return route}}if(this.params!==null){const{params}=this;const slashIndex=path.indexOf("/",pathPartEndIndex);if(slashIndex===-1){if(params.store!==null){param[params.name]=path.substring(pathPartEndIndex);return params.store}}else if(slashIndex!==pathPartEndIndex&¶ms.inert!==null){const route=params.inert.matchRoute(path,param,slashIndex);if(route!==null){param[params.name]=path.substring(pathPartEndIndex,slashIndex);return route}}}if(this.wildcardStore!==null){param.$=path.substring(pathPartEndIndex);return this.wildcardStore}return null}debug(){return JSON.parse(JSON.stringify(this,replaceValue))}}var ignoreKeys={lastChild:null};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}inlineValue(value){if(typeof value==="undefined")return"";if(typeof value!=="function"){if(typeof value!=="symbol"&&typeof value!=="object")return JSON.stringify(value)}return this.options.invokeResultFunction?this.insert(value)+getArgs(value):this.insert(value)}inlineToken(value){return this.options.invokeResultFunction?value+"(c)":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<15){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)}')`}inline(){return this.paramsKeys.length===0?`(()=>(c)=>{${this.builder.join("")}})`:`((${this.paramsKeys})=>(c)=>{${this.builder.join("")}})`}build(){return Function(...this.paramsKeys,`return (c)=>{${this.builder.join("")}}`)(...this.paramsValues)}}class Tree{root=null;staticMap=null;store(path,store){if(path.charCodeAt(0)!==47)throw new Error("Path should start with a slash");const{length}=path;const lastCharCode=path.charCodeAt(length-1);if(length!==1&&lastCharCode===47)throw new Error("Path should not end with a slash");if(lastCharCode===42||path.includes(":"))(this.root??=new Node("/")).insert(path,store);else(this.staticMap??={})[path]??=store;return store}mergeRoot(base,root){if(this.root===null){if(base.length===1){this.root=root;return}else this.root=new Node("/")}this.root.insert(base,null).mergeWithRoot(root)}mergeStatic(base,staticMap){if(base.length<2){if(this.staticMap===null)this.staticMap=staticMap;else{const oldStaticMap=this.staticMap;for(const key in staticMap)oldStaticMap[key]??=staticMap[key]}}else{if(base.includes(":"))throw new Error(`Base cannot includes patterns, instead recieved: ${base}`);const oldStaticMap=this.staticMap??={};for(const key in staticMap)oldStaticMap[key.length===1?base:`${base}${key}`]??=staticMap[key]}}merge(base,tree){if(base.charCodeAt(0)!==47)throw new Error("Path should start with a slash");const{length}=base;if(length!==1&&base.charCodeAt(length-1)===47)throw new Error("Path should not end with a slash");const{staticMap,root}=tree;if(root!==null)this.mergeRoot(base,root);if(staticMap!==null)this.mergeStatic(base,staticMap)}getDependencies(fallback){const{root}=this;const dependencies=[];if(this.staticMap!==null){dependencies.push(this.staticMap);if(root===null)dependencies.push(fallback)}if(root!==null){root.loadDependencies(dependencies);if(root.wildcardStore===null)dependencies.push(fallback)}return dependencies}inspect(options,fallback){const{staticMap,root}=this;const builder=["const {path}=c;"];const ctx=new BuildContext(options,builder);if(staticMap!==null)builder.push(root===null?`return ${ctx.inlineToken(`(${ctx.insert(staticMap)}[path]??${ctx.insert(fallback)})`)};`:`const m=${ctx.insert(staticMap)}[path];if(m!==undefined)return ${ctx.inlineToken("m")};`);if(root!==null){root.compile(ctx,"1",false,false);if(root.wildcardStore===null)builder.push("return "+ctx.inlineValue(fallback))}return ctx}compile(options,fallback){if(this.root===null){const{staticMap}=this;return options.invokeResultFunction===true?staticMap===null?fallback:(ctx)=>(staticMap[ctx.path]??fallback)(ctx):staticMap===null?()=>fallback:(ctx)=>staticMap[ctx.path]??fallback}return this.inspect(options,fallback).build()}compileMatcher(options,fallback){const{root,staticMap}=this;if(root===null)return options.invokeResultFunction===true?staticMap===null?fallback:(ctx)=>(staticMap[ctx.path]??fallback)(ctx):staticMap===null?()=>fallback:(ctx)=>staticMap[ctx.path]??fallback;if(staticMap===null)return options.invokeResultFunction===true?(ctx)=>(root.matchRoute(ctx.path,ctx.params={},0)??fallback)(ctx):(ctx)=>root.matchRoute(ctx.path,ctx.params={},0)??fallback;return options.invokeResultFunction===true?(ctx)=>{const{path}=ctx;return(staticMap[path]??root.matchRoute(path,ctx.params={},0)??fallback)(ctx)}:(ctx)=>{const{path}=ctx;return staticMap[path]??root.matchRoute(path,ctx.params={},0)??fallback}}}class Context{path;params}class Options{invokeResultFunction}class BaseRouter{tree=new Tree;on(path,handler){this.tree.store(path,handler);return this}route(base,router){this.tree.merge(base,router.tree)}}class Radix extends BaseRouter{buildMatcher(options,fallback){options.invokeResultFunction=false;return this.tree.compile(options,fallback)}buildCaller(options,fallback){options.invokeResultFunction=true;return this.tree.compile(options,fallback)}inline(options,fallback){return this.tree.inspect(options,fallback).inline()}getDependencies(fallback){return this.tree.getDependencies(fallback)}}class Edge extends BaseRouter{buildMatcher(options,fallback){options.invokeResultFunction=false;return this.tree.compileMatcher(options,fallback)}buildCaller(options,fallback){options.invokeResultFunction=true;return this.tree.compileMatcher(options,fallback)}}class Context2{path;pathStart;pathEnd;params;req;constructor(req){const{url}=req;const start=url.indexOf("/",12);const end=url.indexOf("?",start+1);this.pathStart=start;this.req=req;this.path=url.substring(start,this.pathEnd=end===-1?url.length:end)}}class Router{options;methodRouter;fallbackRouter;fallback=noop;constructor(options=new Options){this.options=options;options.invokeResultFunction=true;this.options=options}route(base,{methodRouter:otherMethodRouter,fallbackRouter:otherFallbackRouter}){if(typeof otherMethodRouter!=="undefined"){const methodRouter=this.methodRouter??={};for(const method in otherMethodRouter){const router=methodRouter[method];if(typeof router==="undefined")methodRouter[method]=otherMethodRouter[method];else router.route(base,otherMethodRouter[method])}}if(typeof otherFallbackRouter!=="undefined"){const{fallbackRouter}=this;if(typeof fallbackRouter==="undefined")this.fallbackRouter=otherFallbackRouter;else fallbackRouter.route(base,otherFallbackRouter)}}build(Construct=Context2){const{methodRouter,options}=this;const fallback=this.fallbackRouter?.buildCaller(options,this.fallback)??this.fallback;if(methodRouter===undefined)return(req)=>fallback(new Construct(req));const methodCaller={};for(const method in methodRouter)methodCaller[method]=methodRouter[method].buildCaller(options,fallback);return(req)=>(methodCaller[req.method]??fallback)(new Construct(req))}}var noop=()=>null;class Blitz extends Router{on(method,path,handler){((this.methodRouter??={})[method]??=new Radix).on(path,handler)}handle(path,handler){(this.fallbackRouter??=new Radix).on(path,handler)}inline({routerImportSource,contextImportSource}){const{methodRouter,fallbackRouter,options}=this;const literal=`/**@ts-nocheck*/import r from ${JSON.stringify(routerImportSource)};import {Context} from ${JSON.stringify(contextImportSource)};${fallbackRouter===undefined?"const {fallback}=r":`const fallback=${fallbackRouter.inline(options,noop)}(...r.fallbackRouter.getDependencies(r.fallback))`};`;if(methodRouter===undefined)return literal+"export default (c)=>fallback(new Context(c))";const keys=Object.keys(methodRouter);return`${literal}const {methodRouter}=r;const o={${keys.map((key)=>`${key}:${methodRouter[key].inline(options,noop)}(...methodRouter.${key}.getDependencies(fallback))`).join(",")}};export default (c)=>(o[c.method]??fallback)(new Context(c))`}}class EdgeRouter extends Router{on(method,path,handler){((this.methodRouter??={})[method]??=new Edge).on(path,handler)}handle(path,handler){(this.fallbackRouter??=new Edge).on(path,handler)}}var trimPath=function(path){const startExt=path.lastIndexOf(".");return startExt===-1?path.endsWith("/index")?path.length===6?"/":path.substring(path.length-6):path:path.charCodeAt(startExt-1)===120&&path.charCodeAt(startExt-2)===101&&path.charCodeAt(startExt-3)===100&&path.charCodeAt(startExt-4)===110&&path.charCodeAt(startExt-5)===105?startExt===6?"/":path.substring(0,startExt-6):path.substring(0,startExt)};var normalize=function(path){return path.replace(/\/\/|\\\\|\\/g,"/")};var defaultStyleMap={basic(path){let bracketIdx=path.indexOf("[");let pathBuilder=path.charCodeAt(0)===47?"":"/";let startIdx=0;while(bracketIdx!==-1){pathBuilder+=path.substring(startIdx,bracketIdx);if(path.charCodeAt(bracketIdx+1)===46&&path.charCodeAt(bracketIdx+2)===46&&path.charCodeAt(bracketIdx+3)===46)return trimPath(pathBuilder+"*");pathBuilder+=":";startIdx=path.indexOf("]",bracketIdx);pathBuilder+=path.substring(bracketIdx+1,startIdx);++startIdx;bracketIdx=path.indexOf("[",startIdx)}return trimPath(pathBuilder+path.substring(startIdx))},preserve(path){return path.charCodeAt(0)===47?path:"/"+path}};var compileOptions={invokeResultFunction:false};class RequestContext extends Context2{result}class Router2{static Context=RequestContext;style;on;scanFiles;constructor({style,on,scan}){this.style=typeof style==="undefined"?defaultStyleMap.basic:typeof style==="string"?defaultStyleMap[style]:style;this.on=on;this.scanFiles=scan}scan(cwd="."){const{on,style,scanFiles}=this;const router=new Edge;const files=scanFiles(cwd);if(Array.isArray(files))for(let i=0,{length}=files;i<length;++i){const path=files[i];const route=style(path);if(route===null)continue;router.on(route,on(normalize(cwd+path)))}else for(const path of files){const route=style(path);if(route===null)continue;router.on(route,on(normalize(cwd+path)))}const match=router.buildMatcher(compileOptions,null);return(req)=>{const ctx=new RequestContext(req);ctx.result=match(ctx);return ctx}}}var fs_default=Router2;export{exports_internal as internal,Blitz as default,fs_default as FileSystemRouter,EdgeRouter,Context2 as Context,Router as BaseRouter}; |
@@ -29,3 +29,2 @@ import { Tree } from './tree'; | ||
buildCaller(options: Options, fallback: T | null): MatchFunction<ReturnOf<T>>; | ||
inspect(options: Options, fallback: T | null): import("./compiler/context").default; | ||
} | ||
@@ -32,0 +31,0 @@ export declare class Edge<T> extends BaseRouter<T> { |
import { Node } from './nodes'; | ||
import type { Matcher, Options } from './types'; | ||
import BuildContext from '../compiler/context'; | ||
export declare class Tree { | ||
@@ -22,6 +21,2 @@ /** | ||
/** | ||
* Get the build context | ||
*/ | ||
inspect(options: Options, fallback: any): BuildContext; | ||
/** | ||
* Build a function | ||
@@ -28,0 +23,0 @@ */ |
@@ -40,1 +40,2 @@ /// <reference types="node" /> | ||
} | ||
export declare const noop: any; |
import { Radix, Edge } from '../internal'; | ||
import type BuildContext from '../internal/compiler/context'; | ||
import type { GenericHandler } from '../types'; | ||
@@ -24,9 +23,3 @@ import Router from './base'; | ||
handle(path: string, handler: Handler): void; | ||
fallbackRouterContext?: BuildContext; | ||
methodRouterContext?: Record<string, BuildContext>; | ||
/** | ||
* Setup all required states for inlining | ||
*/ | ||
setupInline(): this; | ||
/** | ||
* Inline the router into a file | ||
@@ -33,0 +26,0 @@ */ |
{ | ||
"name": "@bit-js/blitz", | ||
"main": "lib/index.js", | ||
"version": "1.3.7", | ||
"version": "1.3.8", | ||
"type": "module", | ||
@@ -6,0 +6,0 @@ "devDependencies": { |
@@ -47,6 +47,6 @@ # Blitz | ||
In the source file, add a line to setup the required state: | ||
In the source file, export your router: | ||
```ts | ||
export default router.setupInline(); | ||
export default router; | ||
``` | ||
@@ -57,3 +57,3 @@ | ||
```ts | ||
import router from "./main.ts"; | ||
import router from "./main"; | ||
@@ -64,3 +64,3 @@ // Use specific runtime write function | ||
router.inline({ | ||
routerImportSource: "./main.ts", | ||
routerImportSource: "./main", | ||
contextImportSource: "@bit-js/blitz", | ||
@@ -67,0 +67,0 @@ }), |
33571
372