@tinyhttp/app
Advanced tools
Comparing version 0.1.20 to 0.1.21
@@ -6,2 +6,3 @@ /// <reference types="node" /> | ||
import { Ranges, Options } from "range-parser"; | ||
import { SerializeOptions } from "@tinyhttp/cookie"; | ||
declare const getQueryParams: (url?: string) => ParsedUrlQuery; | ||
@@ -13,3 +14,2 @@ type URLParams = { | ||
declare const getRouteFromApp: (app: App, handler: Handler) => Middleware; | ||
declare const compileTrust: (val: any) => any; | ||
declare const getProtocol: (req: Request) => Protocol; | ||
@@ -26,2 +26,3 @@ declare const getHeader: (req: Request) => (header: string) => string | string[]; | ||
interface Request extends IncomingMessage { | ||
app: App; | ||
query: ParsedUrlQuery; | ||
@@ -37,14 +38,32 @@ params: URLParams; | ||
range: (size: number, options?: any) => -1 | -2 | Ranges | undefined; | ||
cookies?: any; | ||
signedCookies?: any; | ||
secret?: string | string[]; | ||
} | ||
declare const json: (_: Request, res: Response) => (body: any, ...args: any[]) => Response; | ||
declare const json: (_req: Request, res: Response) => (body: any, ...args: any[]) => Response; | ||
declare const send: (req: Request, res: Response) => (body: any) => Response; | ||
declare const status: (_: Request, res: Response) => (status: number) => Response; | ||
declare const status: (_req: Request, res: Response) => (status: number) => Response; | ||
declare const setCookie: (req: Request, res: Response) => (name: string, value: string | object, options?: SerializeOptions & Partial<{ | ||
signed: boolean; | ||
}>) => Response; | ||
declare const clearCookie: (req: Request, res: Response) => (name: string, options?: SerializeOptions) => Response; | ||
declare const setHeader: (_req: Request, res: Response) => (field: string | object, val: string | any[]) => Response; | ||
declare const setLocationHeader: (req: Request, res: Response) => (url: string) => void; | ||
interface Response extends ServerResponse { | ||
app: App; | ||
header(field: string | object, val: string | any[]): Response; | ||
set(field: string | object, val: string | any[]): Response; | ||
send(body: unknown): Response; | ||
json(body: unknown): Response; | ||
status(status: number): Response; | ||
cookie(name: string, value: string | object, options?: SerializeOptions & Partial<{ | ||
signed: boolean; | ||
}>): Response; | ||
clearCookie(name: string, options?: SerializeOptions): Response; | ||
location(url: string): Response; | ||
} | ||
declare const METHODS: string[]; | ||
type Handler = (req: Request, res: Response) => void | Promise<void>; | ||
type Handler = (req: Request, res: Response, next?: () => void) => void | Promise<void>; | ||
type Method = "GET" | "POST" | "PUT" | "PATCH" | "HEAD" | string; | ||
declare const onError: (err: any, _req: Request, res: Response, _next: () => void) => void; | ||
interface Middleware { | ||
@@ -58,3 +77,4 @@ method?: Method; | ||
middleware: Middleware[]; | ||
constructor(); | ||
noMatchHandler: Handler; | ||
constructor(noMatchHandler?: Handler); | ||
get(url: string | Handler, handler?: Handler): this; | ||
@@ -67,5 +87,6 @@ post(url: string | Handler, handler?: Handler): this; | ||
use(handler: Handler): this; | ||
handle(req: Request, res: Response): void; | ||
listen(port?: number, cb?: () => void, host?: string, backlog?: number): import("http").Server; | ||
} | ||
declare const notFound: () => Handler; | ||
export { METHODS, Handler, Method, Middleware, App, notFound, getQueryParams, URLParams, getURLParams, getRouteFromApp, compileTrust, getProtocol, getHeader, getRangeFromHeader, checkIfXMLHttpRequest, getHostname, getIP, Connection, Protocol, Request, json, send, status, Response }; | ||
export { METHODS, Handler, Method, onError, Middleware, App, notFound, getQueryParams, URLParams, getURLParams, getRouteFromApp, getProtocol, getHeader, getRangeFromHeader, checkIfXMLHttpRequest, getHostname, getIP, Connection, Protocol, Request, json, send, status, setCookie, clearCookie, setHeader, setLocationHeader, Response }; |
@@ -1,1 +0,1 @@ | ||
import{createServer as e}from"http";import t from"regexparam";import{parse as r}from"url";import n from"proxy-addr";import o from"range-parser";import{format as s,parse as d}from"content-type";import u from"@tinyhttp/etag";const a=(e="/")=>r(e,!0).query,i=(e="/",r="/")=>((e,t)=>{let r=0,n={},o=t.pattern.exec(e);for(;r<t.keys.length;)n[t.keys[r]]=(null==o?void 0:o[++r])||null;return n})(e,t(r)),l=(e,t)=>e.routes.find(e=>e.handler.name===t.name),h=e=>"function"==typeof e?e:!0===e?function(){return!0}:"number"==typeof e?(t,r)=>{if(e)return r<e}:("string"==typeof e&&(e=e.split(/ *, */)),n.compile(e||[])),p=e=>{const t=e.connection.encrypted?"https":"http";if(!h(e.connection.remoteAddress))return t;const r=e.headers["X-Forwarded-Proto"]||t,n=r.indexOf(",");return-1!==n?r.substring(0,n).trim():r.trim()},f=e=>t=>e.headers[t.toLowerCase()],m=e=>(t,r)=>{const n=e.get("Range");if(n)return o(t,n,r)},c=e=>"XMLHttpRequest"===e.headers["X-Requested-With"],g=e=>{let t=e.get("X-Forwarded-Host");if(t&&h(e.connection.remoteAddress)||(t=e.get("Host")),t){var r="["===t[0]?t.indexOf("]")+1:0,n=t.indexOf(":",r);return-1!==n?t.substring(0,n):t}},y=e=>n(e,h),H=(e,t)=>{const r=Buffer.isBuffer(e)?e:Buffer.from(e,t);return u(r,{weak:!0})};const C=(e,t)=>(e,...r)=>(t.setHeader("Content-Type","application/json"),"object"==typeof e&&"null"!=e?t.end(JSON.stringify(e,null,2),...r):"string"==typeof e&&t.end(e,...r),t),T=(e,t)=>r=>{let n=r;if("object"==typeof r&&"null"!==r)n=JSON.stringify(r,null,2);else if("string"==typeof r){const e=t.getHeader("Content-Type");"string"==typeof e&&t.setHeader("Content-Type",function(e,t){const r=d(e);return r.parameters.charset=t,s(r)}(e,"utf-8"))}let o;return!t.getHeader("etag")&&(o=H(n,"utf8"))&&t.setHeader("etag",o),204!==t.statusCode&&304!==t.statusCode||(t.removeHeader("Content-Type"),t.removeHeader("Content-Length"),t.removeHeader("Transfer-Encoding"),n=""),"HEAD"===e.method&&t.end(""),"object"==typeof r?null===r?t.end(""):Buffer.isBuffer(r)?t.getHeader("Content-Type")||t.setHeader("content-type","application/octet-stream"):C(0,t)(n,"utf8"):t.end(n,"utf8"),t},w=(e,t)=>e=>(t.statusCode=e,t),b=()=>(e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))},E=["GET","POST","PUT","PATCH","HEAD"],x=({url:e,handler:t,method:r})=>({method:r,handler:t||e,url:"string"==typeof e?e:"*"});class O{constructor(){this.routes=[],this.middleware=[]}get(e,t){return this.routes.push(x({url:e,handler:t,method:"GET"})),this}post(e,t){return this.routes.push(x({url:e,handler:t,method:"POST"})),this}put(e,t){return this.routes.push(x({url:e,handler:t,method:"PUT"})),this}patch(e,t){return this.routes.push(x({url:e,handler:t,method:"PATCH"})),this}head(e,t){return this.routes.push(x({url:e,handler:t,method:"HEAD"})),this}all(e,t){for(const r of E)this.routes.push(x({url:e,handler:t,method:r}));return this}use(e){return this.middleware.push({handler:e}),this}listen(r,n=(()=>console.log(`Started on http://${o}:${r}`)),o="localhost",s){return e((e,r)=>{const n=p(e),o="https"===n;e.protocol=n,e.secure=o,e.connection=Object.assign(e.socket,{encrypted:o}),e.query=a(e.url),e.get=f(e),e.range=m(e),e.xhr=c(e),e.hostname=g(e),r.send=T(e,r),r.json=C(0,r),r.status=w(0,r),this.routes.map(({url:n,method:o,handler:s})=>{e.method===o&&n&&e.url&&t(n).pattern.test(e.url)&&(e.params=i(e.url,n),e.route=l(this,s),r.writableEnded||(r.statusCode=200,s(e,r)))});let s=this.middleware.filter(e=>"logger"!==e.handler.name);s.push({handler:(e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))}});const d=this.middleware.find(e=>"logger"===e.handler.name);d&&s.push(d),s.map(({handler:t})=>{t(e,r)})}).listen(r,o,s,n)}}export{O as App,E as METHODS,c as checkIfXMLHttpRequest,h as compileTrust,f as getHeader,g as getHostname,y as getIP,p as getProtocol,a as getQueryParams,m as getRangeFromHeader,l as getRouteFromApp,i as getURLParams,C as json,b as notFound,T as send,w as status}; | ||
import{STATUS_CODES as e,createServer as t}from"http";import r from"regexparam";import{parse as n}from"url";import o from"range-parser";import s from"proxy-addr";import a from"encodeurl";import{sign as i}from"@tinyhttp/cookie-signature";import d from"mime";import u from"@tinyhttp/cookie";import{format as h,parse as l}from"content-type";import p from"@tinyhttp/etag";const f=e=>"function"==typeof e?e:!0===e?function(){return!0}:"number"==typeof e?(t,r)=>{if(e)return r<e}:("string"==typeof e&&(e=e.split(/ *, */)),s.compile(e||[])),c=(e="/")=>n(e,!0).query,m=(e="/",t="/")=>((e,t)=>{let r=0,n={},o=t.pattern.exec(e);for(;r<t.keys.length;)n[t.keys[r]]=(null==o?void 0:o[++r])||null;return n})(e,r(t)),g=(e,t)=>e.routes.find(e=>e.handler.name===t.name),y=e=>{const t=e.connection.encrypted?"https":"http";if(!f(e.connection.remoteAddress))return t;const r=e.headers["X-Forwarded-Proto"]||t,n=r.indexOf(",");return-1!==n?r.substring(0,n).trim():r.trim()},H=e=>t=>e.headers[t.toLowerCase()],C=e=>(t,r)=>{const n=e.get("Range");if(n)return o(t,n,r)},w=e=>"XMLHttpRequest"===e.headers["X-Requested-With"],T=e=>{let t=e.get("X-Forwarded-Host");if(t&&f(e.connection.remoteAddress)||(t=e.get("Host")),t){var r="["===t[0]?t.indexOf("]")+1:0,n=t.indexOf(":",r);return-1!==n?t.substring(0,n):t}},A=e=>s(e,f),b=(e,t)=>{const r=Buffer.isBuffer(e)?e:Buffer.from(e,t);return p(r,{weak:!0})};const x=(e,t)=>(e,...r)=>(t.setHeader("Content-Type","application/json"),"object"==typeof e&&"null"!=e?t.end(JSON.stringify(e,null,2),...r):"string"==typeof e&&t.end(e,...r),t),k=(e,t)=>r=>{let n=r;if("object"==typeof r&&"null"!==r)n=JSON.stringify(r,null,2);else if("string"==typeof r){const e=t.getHeader("Content-Type");"string"==typeof e&&t.setHeader("Content-Type",function(e,t){const r=l(e);return r.parameters.charset=t,h(r)}(e,"utf-8"))}let o;return!t.getHeader("etag")&&(o=b(n,"utf8"))&&t.setHeader("etag",o),204!==t.statusCode&&304!==t.statusCode||(t.removeHeader("Content-Type"),t.removeHeader("Content-Length"),t.removeHeader("Transfer-Encoding"),n=""),"HEAD"===e.method&&t.end(""),"object"==typeof r?null===r?t.end(""):Buffer.isBuffer(r)?t.getHeader("Content-Type")||t.setHeader("content-type","application/octet-stream"):x(0,t)(n,"utf8"):t.end(n,"utf8"),t},E=(e,t)=>e=>(t.statusCode=e,t),S=(e,t)=>(r,n,o)=>{const s=e.secret,a=o.signed;if(a&&!s)throw new Error('cookieParser("secret") required for signed cookies');let d="object"==typeof n?"j:"+JSON.stringify(n):String(n);return a&&(d="s:"+i(d,s)),o.maxAge&&(o.expires=new Date(Date.now()+o.maxAge),o.maxAge/=1e3),null==o.path&&(o.path="/"),t.setHeader("Set-Cookie",u.serialize(r,String(d),o)),t},O=(e,t)=>(r,n)=>{const o=Object.assign({},{expires:new Date(1),path:"/"},n);return S(e,t)(r,"",o)},j=/;\s*charset\s*=/,P=(e,t)=>(e,r)=>{if("string"==typeof e){let n=Array.isArray(r)?r.map(String):String(r);if("content-type"===e.toLowerCase()){if(Array.isArray(n))throw new TypeError("Content-Type cannot be set to an Array");if(!j.test(n)){const e=d.getType(n.split(";")[0]);e&&(n+="; charset="+e.toLowerCase())}}t.setHeader(e,n)}else for(const r in e)t.setHeader(r,e[r]);return t},B=(e,t)=>r=>{let n=r;return"back"===r&&(n=e.get("Referrer")||"/"),t.setHeader("Location",a(n))},D=()=>(e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))},L=["GET","POST","PUT","PATCH","HEAD"],q=(t,r,n,o)=>{let s=n.statusCode=t.code||t.status||500;"string"==typeof t||Buffer.isBuffer(t)?n.end(t):n.end(t.message||e[s])},v=({url:e,handler:t,method:r})=>({method:r,handler:t||e,url:"string"==typeof e?e:"*"});class N{constructor(e=((e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))})){this.routes=[],this.middleware=[],this.noMatchHandler=e}get(e,t){return this.routes.push(v({url:e,handler:t,method:"GET"})),this}post(e,t){return this.routes.push(v({url:e,handler:t,method:"POST"})),this}put(e,t){return this.routes.push(v({url:e,handler:t,method:"PUT"})),this}patch(e,t){return this.routes.push(v({url:e,handler:t,method:"PATCH"})),this}head(e,t){return this.routes.push(v({url:e,handler:t,method:"HEAD"})),this}all(e,t){for(const r of L)this.routes.push(v({url:e,handler:t,method:r}));return this}use(e){return this.middleware.push({handler:e}),this}handle(e,t){e.app=this;const n=y(e),o="https"===n;e.protocol=n,e.secure=o,e.connection=Object.assign(e.socket,{encrypted:o}),e.query=c(e.url),e.get=H(e),e.range=C(e),e.xhr=w(e),e.hostname=T(e),t.app=this,t.header=t.set=P(0,t),t.send=k(e,t),t.json=x(0,t),t.status=E(0,t),t.cookie=S(e,t),t.clearCookie=O(e,t);for(const n of this.routes){const{url:o,method:s,handler:a}=n;t.writableEnded||e.method===s&&o&&e.url&&r(o).pattern.test(e.url)&&(e.params=m(e.url,o),e.route=g(this,a),t.statusCode=200,a(e,t))}let s=this.middleware.filter(e=>"logger"!==e.handler.name);s.push({handler:this.noMatchHandler});const a=this.middleware.find(e=>"logger"===e.handler.name);a&&s.push(a),s.map(({handler:r})=>{r(e,t)})}listen(e,r=(()=>console.log(`Started on http://${n}:${e}`)),n="localhost",o){return t((e,t)=>{this.handle(e,t)}).listen(e,n,o,r)}}export{N as App,L as METHODS,w as checkIfXMLHttpRequest,O as clearCookie,H as getHeader,T as getHostname,A as getIP,y as getProtocol,c as getQueryParams,C as getRangeFromHeader,g as getRouteFromApp,m as getURLParams,x as json,D as notFound,q as onError,k as send,S as setCookie,P as setHeader,B as setLocationHeader,E as status}; |
@@ -1,1 +0,1 @@ | ||
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=require("http"),r=e(require("regexparam")),s=require("url"),n=e(require("proxy-addr")),o=e(require("range-parser")),u=require("content-type"),a=e(require("@tinyhttp/etag"));const d=(e="/")=>s.parse(e,!0).query,i=(e="/",t="/")=>((e,t)=>{let r=0,s={},n=t.pattern.exec(e);for(;r<t.keys.length;)s[t.keys[r]]=(null==n?void 0:n[++r])||null;return s})(e,r(t)),p=(e,t)=>e.routes.find(e=>e.handler.name===t.name),l=e=>"function"==typeof e?e:!0===e?function(){return!0}:"number"==typeof e?(t,r)=>{if(e)return r<e}:("string"==typeof e&&(e=e.split(/ *, */)),n.compile(e||[])),h=e=>{const t=e.connection.encrypted?"https":"http";if(!l(e.connection.remoteAddress))return t;const r=e.headers["X-Forwarded-Proto"]||t,s=r.indexOf(",");return-1!==s?r.substring(0,s).trim():r.trim()},c=e=>t=>e.headers[t.toLowerCase()],f=e=>(t,r)=>{const s=e.get("Range");if(s)return o(t,s,r)},m=e=>"XMLHttpRequest"===e.headers["X-Requested-With"],g=e=>{let t=e.get("X-Forwarded-Host");if(t&&l(e.connection.remoteAddress)||(t=e.get("Host")),t){var r="["===t[0]?t.indexOf("]")+1:0,s=t.indexOf(":",r);return-1!==s?t.substring(0,s):t}},y=(e,t)=>{const r=Buffer.isBuffer(e)?e:Buffer.from(e,t);return a(r,{weak:!0})};const x=(e,t)=>(e,...r)=>(t.setHeader("Content-Type","application/json"),"object"==typeof e&&"null"!=e?t.end(JSON.stringify(e,null,2),...r):"string"==typeof e&&t.end(e,...r),t),H=(e,t)=>r=>{let s=r;if("object"==typeof r&&"null"!==r)s=JSON.stringify(r,null,2);else if("string"==typeof r){const e=t.getHeader("Content-Type");"string"==typeof e&&t.setHeader("Content-Type",function(e,t){const r=u.parse(e);return r.parameters.charset=t,u.format(r)}(e,"utf-8"))}let n;return!t.getHeader("etag")&&(n=y(s,"utf8"))&&t.setHeader("etag",n),204!==t.statusCode&&304!==t.statusCode||(t.removeHeader("Content-Type"),t.removeHeader("Content-Length"),t.removeHeader("Transfer-Encoding"),s=""),"HEAD"===e.method&&t.end(""),"object"==typeof r?null===r?t.end(""):Buffer.isBuffer(r)?t.getHeader("Content-Type")||t.setHeader("content-type","application/octet-stream"):x(0,t)(s,"utf8"):t.end(s,"utf8"),t},T=(e,t)=>e=>(t.statusCode=e,t),C=()=>(e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))},b=["GET","POST","PUT","PATCH","HEAD"],q=({url:e,handler:t,method:r})=>({method:r,handler:t||e,url:"string"==typeof e?e:"*"});exports.App=class{constructor(){this.routes=[],this.middleware=[]}get(e,t){return this.routes.push(q({url:e,handler:t,method:"GET"})),this}post(e,t){return this.routes.push(q({url:e,handler:t,method:"POST"})),this}put(e,t){return this.routes.push(q({url:e,handler:t,method:"PUT"})),this}patch(e,t){return this.routes.push(q({url:e,handler:t,method:"PATCH"})),this}head(e,t){return this.routes.push(q({url:e,handler:t,method:"HEAD"})),this}all(e,t){for(const r of b)this.routes.push(q({url:e,handler:t,method:r}));return this}use(e){return this.middleware.push({handler:e}),this}listen(e,s=(()=>console.log(`Started on http://${n}:${e}`)),n="localhost",o){return t.createServer((e,t)=>{const s=h(e),n="https"===s;e.protocol=s,e.secure=n,e.connection=Object.assign(e.socket,{encrypted:n}),e.query=d(e.url),e.get=c(e),e.range=f(e),e.xhr=m(e),e.hostname=g(e),t.send=H(e,t),t.json=x(0,t),t.status=T(0,t),this.routes.map(({url:s,method:n,handler:o})=>{e.method===n&&s&&e.url&&r(s).pattern.test(e.url)&&(e.params=i(e.url,s),e.route=p(this,o),t.writableEnded||(t.statusCode=200,o(e,t)))});let o=this.middleware.filter(e=>"logger"!==e.handler.name);o.push({handler:(e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))}});const u=this.middleware.find(e=>"logger"===e.handler.name);u&&o.push(u),o.map(({handler:r})=>{r(e,t)})}).listen(e,n,o,s)}},exports.METHODS=b,exports.checkIfXMLHttpRequest=m,exports.compileTrust=l,exports.getHeader=c,exports.getHostname=g,exports.getIP=e=>n(e,l),exports.getProtocol=h,exports.getQueryParams=d,exports.getRangeFromHeader=f,exports.getRouteFromApp=p,exports.getURLParams=i,exports.json=x,exports.notFound=C,exports.send=H,exports.status=T; | ||
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=require("http"),r=e(require("regexparam")),s=require("url"),o=e(require("range-parser")),n=e(require("proxy-addr")),a=e(require("encodeurl")),i=require("@tinyhttp/cookie-signature"),u=e(require("mime")),d=e(require("@tinyhttp/cookie")),p=require("content-type"),l=e(require("@tinyhttp/etag"));const h=e=>"function"==typeof e?e:!0===e?function(){return!0}:"number"==typeof e?(t,r)=>{if(e)return r<e}:("string"==typeof e&&(e=e.split(/ *, */)),n.compile(e||[])),c=(e="/")=>s.parse(e,!0).query,f=(e="/",t="/")=>((e,t)=>{let r=0,s={},o=t.pattern.exec(e);for(;r<t.keys.length;)s[t.keys[r]]=(null==o?void 0:o[++r])||null;return s})(e,r(t)),g=(e,t)=>e.routes.find(e=>e.handler.name===t.name),m=e=>{const t=e.connection.encrypted?"https":"http";if(!h(e.connection.remoteAddress))return t;const r=e.headers["X-Forwarded-Proto"]||t,s=r.indexOf(",");return-1!==s?r.substring(0,s).trim():r.trim()},y=e=>t=>e.headers[t.toLowerCase()],x=e=>(t,r)=>{const s=e.get("Range");if(s)return o(t,s,r)},H=e=>"XMLHttpRequest"===e.headers["X-Requested-With"],C=e=>{let t=e.get("X-Forwarded-Host");if(t&&h(e.connection.remoteAddress)||(t=e.get("Host")),t){var r="["===t[0]?t.indexOf("]")+1:0,s=t.indexOf(":",r);return-1!==s?t.substring(0,s):t}},w=(e,t)=>{const r=Buffer.isBuffer(e)?e:Buffer.from(e,t);return l(r,{weak:!0})};const T=(e,t)=>(e,...r)=>(t.setHeader("Content-Type","application/json"),"object"==typeof e&&"null"!=e?t.end(JSON.stringify(e,null,2),...r):"string"==typeof e&&t.end(e,...r),t),A=(e,t)=>r=>{let s=r;if("object"==typeof r&&"null"!==r)s=JSON.stringify(r,null,2);else if("string"==typeof r){const e=t.getHeader("Content-Type");"string"==typeof e&&t.setHeader("Content-Type",function(e,t){const r=p.parse(e);return r.parameters.charset=t,p.format(r)}(e,"utf-8"))}let o;return!t.getHeader("etag")&&(o=w(s,"utf8"))&&t.setHeader("etag",o),204!==t.statusCode&&304!==t.statusCode||(t.removeHeader("Content-Type"),t.removeHeader("Content-Length"),t.removeHeader("Transfer-Encoding"),s=""),"HEAD"===e.method&&t.end(""),"object"==typeof r?null===r?t.end(""):Buffer.isBuffer(r)?t.getHeader("Content-Type")||t.setHeader("content-type","application/octet-stream"):T(0,t)(s,"utf8"):t.end(s,"utf8"),t},q=(e,t)=>e=>(t.statusCode=e,t),b=(e,t)=>(r,s,o)=>{const n=e.secret,a=o.signed;if(a&&!n)throw new Error('cookieParser("secret") required for signed cookies');let u="object"==typeof s?"j:"+JSON.stringify(s):String(s);return a&&(u="s:"+i.sign(u,n)),o.maxAge&&(o.expires=new Date(Date.now()+o.maxAge),o.maxAge/=1e3),null==o.path&&(o.path="/"),t.setHeader("Set-Cookie",d.serialize(r,String(u),o)),t},S=(e,t)=>(r,s)=>{const o=Object.assign({},{expires:new Date(1),path:"/"},s);return b(e,t)(r,"",o)},k=/;\s*charset\s*=/,E=(e,t)=>(e,r)=>{if("string"==typeof e){let s=Array.isArray(r)?r.map(String):String(r);if("content-type"===e.toLowerCase()){if(Array.isArray(s))throw new TypeError("Content-Type cannot be set to an Array");if(!k.test(s)){const e=u.getType(s.split(";")[0]);e&&(s+="; charset="+e.toLowerCase())}}t.setHeader(e,s)}else for(const r in e)t.setHeader(r,e[r]);return t},O=()=>(e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))},P=["GET","POST","PUT","PATCH","HEAD"],j=({url:e,handler:t,method:r})=>({method:r,handler:t||e,url:"string"==typeof e?e:"*"});exports.App=class{constructor(e=((e,t)=>{t.writableEnded||(t.statusCode=404,t.end("Not found"))})){this.routes=[],this.middleware=[],this.noMatchHandler=e}get(e,t){return this.routes.push(j({url:e,handler:t,method:"GET"})),this}post(e,t){return this.routes.push(j({url:e,handler:t,method:"POST"})),this}put(e,t){return this.routes.push(j({url:e,handler:t,method:"PUT"})),this}patch(e,t){return this.routes.push(j({url:e,handler:t,method:"PATCH"})),this}head(e,t){return this.routes.push(j({url:e,handler:t,method:"HEAD"})),this}all(e,t){for(const r of P)this.routes.push(j({url:e,handler:t,method:r}));return this}use(e){return this.middleware.push({handler:e}),this}handle(e,t){e.app=this;const s=m(e),o="https"===s;e.protocol=s,e.secure=o,e.connection=Object.assign(e.socket,{encrypted:o}),e.query=c(e.url),e.get=y(e),e.range=x(e),e.xhr=H(e),e.hostname=C(e),t.app=this,t.header=t.set=E(0,t),t.send=A(e,t),t.json=T(0,t),t.status=q(0,t),t.cookie=b(e,t),t.clearCookie=S(e,t);for(const s of this.routes){const{url:o,method:n,handler:a}=s;t.writableEnded||e.method===n&&o&&e.url&&r(o).pattern.test(e.url)&&(e.params=f(e.url,o),e.route=g(this,a),t.statusCode=200,a(e,t))}let n=this.middleware.filter(e=>"logger"!==e.handler.name);n.push({handler:this.noMatchHandler});const a=this.middleware.find(e=>"logger"===e.handler.name);a&&n.push(a),n.map(({handler:r})=>{r(e,t)})}listen(e,r=(()=>console.log(`Started on http://${s}:${e}`)),s="localhost",o){return t.createServer((e,t)=>{this.handle(e,t)}).listen(e,s,o,r)}},exports.METHODS=P,exports.checkIfXMLHttpRequest=H,exports.clearCookie=S,exports.getHeader=y,exports.getHostname=C,exports.getIP=e=>n(e,h),exports.getProtocol=m,exports.getQueryParams=c,exports.getRangeFromHeader=x,exports.getRouteFromApp=g,exports.getURLParams=f,exports.json=T,exports.notFound=O,exports.onError=(e,r,s,o)=>{let n=s.statusCode=e.code||e.status||500;"string"==typeof e||Buffer.isBuffer(e)?s.end(e):s.end(e.message||t.STATUS_CODES[n])},exports.send=A,exports.setCookie=b,exports.setHeader=E,exports.setLocationHeader=(e,t)=>r=>{let s=r;return"back"===r&&(s=e.get("Referrer")||"/"),t.setHeader("Location",a(s))},exports.status=q; |
{ | ||
"name": "@tinyhttp/app", | ||
"version": "0.1.20", | ||
"description": "tinyhttp core", | ||
"homepage": "https://github.com/talentlessguy/tinyhttp", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/talentlessguy/tinyhttp.git", | ||
"directory": "packages/app" | ||
}, | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"module": "dist/index.esm.js", | ||
"files": [ | ||
"dist" | ||
], | ||
"engines": { | ||
"node": ">=14" | ||
}, | ||
"keywords": [ | ||
"tinyhttp", | ||
"node.js", | ||
"web framework", | ||
"web", | ||
"backend" | ||
], | ||
"author": "v1rtl", | ||
"license": "MIT", | ||
"dependencies": { | ||
"@tinyhttp/etag": "workspace:*", | ||
"content-type": "^1.0.4", | ||
"proxy-addr": "^2.0.6", | ||
"range-parser": "^1.2.1", | ||
"regexparam": "^1.3.0" | ||
}, | ||
"devDependencies": { | ||
"@types/content-type": "^1.1.3", | ||
"@types/proxy-addr": "^2.0.0", | ||
"@types/range-parser": "^1.2.3" | ||
} | ||
"name": "@tinyhttp/app", | ||
"version": "0.1.21", | ||
"description": "tinyhttp core", | ||
"homepage": "https://github.com/talentlessguy/tinyhttp", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/talentlessguy/tinyhttp.git", | ||
"directory": "packages/app" | ||
}, | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"module": "dist/index.esm.js", | ||
"files": [ | ||
"dist" | ||
], | ||
"engines": { | ||
"node": ">=14" | ||
}, | ||
"keywords": [ | ||
"tinyhttp", | ||
"node.js", | ||
"web framework", | ||
"web", | ||
"backend" | ||
], | ||
"author": "v1rtl", | ||
"license": "MIT", | ||
"dependencies": { | ||
"@tinyhttp/cookie": "^0.0.5", | ||
"@tinyhttp/cookie-signature": "^0.0.4", | ||
"@tinyhttp/etag": "^0.1.15", | ||
"content-type": "^1.0.4", | ||
"encodeurl": "^1.0.2", | ||
"mime": "^2.4.6", | ||
"proxy-addr": "^2.0.6", | ||
"range-parser": "^1.2.1", | ||
"regexparam": "^1.3.0" | ||
}, | ||
"devDependencies": { | ||
"@types/content-type": "^1.1.3", | ||
"@types/encodeurl": "^1.0.0", | ||
"@types/mime": "^2.0.2", | ||
"@types/proxy-addr": "^2.0.0", | ||
"@types/range-parser": "^1.2.3" | ||
} | ||
} |
@@ -1,33 +0,75 @@ | ||
# @tinyhttp/app | ||
![Twitter](https://img.shields.io/twitter/follow/v1rtl.svg?label=sub%20to%20twitter&style=flat-square) ![npm type definitions](https://img.shields.io/npm/types/@tinyhttp/app?style=flat-square) | ||
![Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/npm/body-parsec.svg?style=flat-square) | ||
![Last commit](https://img.shields.io/github/last-commit/talentlessguy/tinyhttp.svg?style=flat-square) ![NPM](https://img.shields.io/npm/l/@tinyhttp/app?style=flat-square) | ||
tinyhttp core | ||
# @tinyhttp/core | ||
`tinyhttp` core module with `App`, `Request` and `Response` classes. | ||
> ⚠ The project is incomplete. Please don't use in production. | ||
**tinyhttp** is a modern Express-like web framework for Node.js. It uses a bare minimum amount of dependencies trying to avoid legacy. | ||
## Installation | ||
This is a [Node.js](https://nodejs.org/) module available through the | ||
[npm registry](https://www.npmjs.com/). It can be installed using the | ||
[`npm`](https://docs.npmjs.com/getting-started/installing-npm-packages-locally) | ||
or | ||
[`yarn`](https://yarnpkg.com/en/) | ||
command line tools. | ||
Node.js 13 is required. | ||
```sh | ||
npm install @tinyhttp/app --save | ||
# npm | ||
npm i @tinyhttp/app | ||
# pnpm | ||
pnpm i @tinyhttp/app | ||
# yarn | ||
yarn add @tinyhttp/app | ||
``` | ||
## Dependencies | ||
## Features | ||
- [@tinyhttp/etag](https://ghub.io/@tinyhttp/etag): tinyhttp eTag module | ||
- [content-type](https://ghub.io/content-type): Create and parse HTTP Content-Type header | ||
- [proxy-addr](https://ghub.io/proxy-addr): Determine address of proxied request | ||
- [range-parser](https://ghub.io/range-parser): Range header field string parser | ||
- [regexparam](https://ghub.io/regexparam): A tiny (308B) utility that converts route patterns into RegExp. Limited alternative to `path-to-regexp` 🙇 | ||
- Compatible with Express | ||
- Async routes [not tested yet] | ||
- Smaller size | ||
- 0 legacy dependencies | ||
## Dev Dependencies | ||
## Docs | ||
- [@types/proxy-addr](https://ghub.io/@types/proxy-addr): TypeScript definitions for proxy-addr | ||
- [@types/range-parser](https://ghub.io/@types/range-parser): TypeScript definitions for range-parser | ||
Coming soon... | ||
## License | ||
## Example | ||
MIT | ||
At the moment there is only one basic example. I will add more of them once I add all the existing Express `req` / `res` extensions. | ||
```ts | ||
import { App } from '@tinyhttp/app' | ||
import staticFolder from '@tinyhttp/static' | ||
import logger from '@tinyhttp/logger' | ||
const app = new App() | ||
app.all('/', (req, res) => { | ||
res.status(200).send(` | ||
<h1>tinyhttp example</h1> | ||
<ul> | ||
<li>Protocol: ${req.protocol}</li> | ||
<li>HTTPS: ${req.secure ? 'yes' : 'no'}</li> | ||
<li>URL: ${req.url}</li> | ||
<li>Method: ${req.method}</li> | ||
<li>Host: ${req.hostname}</li> | ||
<li>Status: ${res.statusCode}</li> | ||
</ul> | ||
<h2>Request headers</h2> | ||
<pre> | ||
${JSON.stringify(req.headers, null, 2)} | ||
</pre> | ||
`) | ||
}) | ||
app.get('/:first/:second', (req, res) => { | ||
res.json({ URLParams: req.params, QueryParams: req.query }) | ||
}) | ||
app.use(staticFolder()) | ||
app.use(logger()) | ||
app.listen(3000) | ||
``` |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
19180
6
130
76
2
9
5
+ Added@tinyhttp/cookie@^0.0.5
+ Addedencodeurl@^1.0.2
+ Addedmime@^2.4.6
+ Added@tinyhttp/cookie@0.0.5(transitive)
+ Added@tinyhttp/cookie-signature@0.0.4(transitive)
+ Added@tinyhttp/etag@0.1.26(transitive)
+ Addedencodeurl@1.0.2(transitive)
+ Addedmime@2.6.0(transitive)
Updated@tinyhttp/etag@^0.1.15