@danielgl/steampunk 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/dist/main.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var N=Object.defineProperty;var fe=Object.getOwnPropertyDescriptor;var pe=Object.getOwnPropertyNames;var he=Object.prototype.hasOwnProperty;var a=(t,e)=>N(t,"name",{value:e,configurable:!0});var w=(t,e)=>()=>(t&&(e=t(t=0)),e);var D=(t,e)=>{for(var r in e)N(t,r,{get:e[r],enumerable:!0})},me=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of pe(e))!he.call(t,s)&&s!==r&&N(t,s,{get:()=>e[s],enumerable:!(n=fe(e,s))||n.enumerable});return t};var J=t=>me(N({},"__esModule",{value:!0}),t);function A(){return t=>{Reflect.defineMetadata(ge,!0,t)}}function K(t){return(e,r,n)=>{let s=Reflect.getMetadata(H,e)||[];s.push({index:n,token:t}),Reflect.defineMetadata(H,s,e)}}var Te,ge,H,I=w(()=>{"use strict";Te=require("reflect-metadata"),ge=Symbol("INJECTABLE_WATERMARK"),H=Symbol("INJECT_METADATA");a(A,"Injectable");a(K,"Inject")});function z(t){return(e,r)=>{let n={required:!0,roles:t};r!==void 0?Reflect.defineMetadata(O,n,e.constructor,r):Reflect.defineMetadata(O,n,e)}}var ke,O,P=w(()=>{"use strict";ke=require("reflect-metadata"),O=Symbol("AUTHORIZE_METADATA");a(z,"Authorize")});var S,q=w(()=>{"use strict";S=class t{static{a(this,"HttpResult")}status;body;headers;constructor(e,r,n={}){this.status=e,this.body=r!==void 0&&typeof r!="string"?JSON.stringify(r):r,this.headers=n}static ok(e){return new t(200,e)}static created(e,r){let n={};return r&&(n.Location=r),new t(201,e,n)}static noContent(){return new t(204)}static badRequest(e="Bad Request",r){let n=typeof e=="string"?{message:e,errors:r}:e;return new t(400,n)}static unauthorized(e="Unauthorized"){let r=typeof e=="string"?{message:e}:e;return new t(401,r)}static forbidden(e="Forbidden"){let r=typeof e=="string"?{message:e}:e;return new t(403,r)}static notFound(e="Not Found"){let r=typeof e=="string"?{message:e}:e;return new t(404,r)}static conflict(e="Conflict"){let r=typeof e=="string"?{message:e}:e;return new t(409,r)}static unprocessableEntity(e="Unprocessable Entity",r){let n=typeof e=="string"?{message:e,errors:r}:e;return new t(422,n)}static internalServerError(e="Internal Server Error"){let r=typeof e=="string"?{message:e}:e;return new t(500,r)}toResponse(){if(this.status===204||this.body===void 0)return new Response(null,{status:this.status,headers:this.headers});let e={"Content-Type":"application/json",...this.headers};return new Response(this.body,{status:this.status,headers:e})}}});function G(t=""){return e=>{Reflect.defineMetadata(L,t,e),A()(e)}}function k(t,e,r){let n=`${U.toString()}_${e.toString()}`;Reflect.hasMetadata(n,t.constructor)||Reflect.defineMetadata(n,[],t.constructor);let s=Reflect.getMetadata(n,t.constructor);s.push(r),Reflect.defineMetadata(n,s,t.constructor)}var _e,L,v,U,j,X,Q,Z,V,Y,C,ee,te,re,B=w(()=>{"use strict";_e=require("reflect-metadata");I();L=Symbol("CONTROLLER_WATERMARK"),v=Symbol("ROUTE_METADATA"),U=Symbol("PARAM_METADATA");a(G,"Controller");j=a(t=>(e="")=>(r,n)=>{Reflect.hasMetadata(v,r.constructor)||Reflect.defineMetadata(v,[],r.constructor);let s=Reflect.getMetadata(v,r.constructor);s.push({method:t,path:e,methodName:n.toString()}),Reflect.defineMetadata(v,s,r.constructor)},"createRouteDecorator"),X=j("GET"),Q=j("POST"),Z=j("PUT"),V=j("DELETE"),Y=j("PATCH"),C=(function(t){return t[t.Route=0]="Route",t[t.Query=1]="Query",t[t.Body=2]="Body",t[t.Context=3]="Context",t})({}),ee=a(t=>(e,r,n)=>{k(e,r,{type:0,index:n,name:t})},"FromRoute"),te=a(t=>(e,r,n)=>{k(e,r,{type:1,index:n,name:t})},"FromQuery"),re=a(()=>(t,e,r)=>{k(t,e,{type:2,index:r})},"FromBody");a(k,"addParamMetadata")});var oe={};D(oe,{JwtAuthService:()=>y});function ye(t,e,r,n){var s=arguments.length,o=s<3?e:n===null?n=Object.getOwnPropertyDescriptor(e,r):n,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(t,e,r,n);else for(var c=t.length-1;c>=0;c--)(i=t[c])&&(o=(s<3?i(o):s>3?i(e,r,o):i(e,r))||o);return s>3&&o&&Object.defineProperty(e,r,o),o}function ne(t,e){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(t,e)}function $(t){return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function se(t){let e=t+"==".slice(2-t.length*3&3);return atob(e.replace(/-/g,"+").replace(/_/g,"/"))}var y,F=w(()=>{"use strict";I();a(ye,"_ts_decorate");a(ne,"_ts_metadata");a($,"base64UrlEncode");a(se,"base64UrlDecode");y=class{static{a(this,"JwtAuthService")}secret;expiresIn;constructor(e){this.secret=e.secret,this.expiresIn=e.expiresIn??3600}async getKey(){let e=new TextEncoder;return crypto.subtle.importKey("raw",e.encode(this.secret),{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}async sign(e){let r={alg:"HS256",typ:"JWT"},n=Math.floor(Date.now()/1e3),s={...e,iat:n,exp:n+this.expiresIn},o=$(JSON.stringify(r)),i=$(JSON.stringify(s)),c=`${o}.${i}`,l=await this.getKey(),u=new TextEncoder,p=await crypto.subtle.sign("HMAC",l,u.encode(c)),f=$(String.fromCharCode(...new Uint8Array(p)));return`${c}.${f}`}async verify(e){let r=e.split(".");if(r.length!==3)throw new Error("Invalid JWT format");let n=r[0],s=r[1],o=r[2],i=`${n}.${s}`,c=await this.getKey(),l=new TextEncoder,u=Uint8Array.from(se(o),m=>m.charCodeAt(0));if(!await crypto.subtle.verify("HMAC",c,u,l.encode(i)))throw new Error("Invalid JWT signature");let f=JSON.parse(se(s)),b=Math.floor(Date.now()/1e3);if(f.exp!==void 0&&f.exp<b)throw new Error("JWT expired");return f}};y=ye([A(),ne("design:type",Function),ne("design:paramtypes",[typeof JwtOptions>"u"?Object:JwtOptions])],y)});var ie={};D(ie,{Router:()=>W});async function we(t,e,r){if(!r.required)return null;let n=t.request.headers.get("authorization");if(!n||!n.startsWith("Bearer "))return new Response(JSON.stringify({message:"Unauthorized"}),{status:401,headers:{"Content-Type":"application/json"}});let s=n.slice(7),o;try{let{JwtAuthService:c}=(F(),J(oe));o=e.resolve(c)}catch{return new Response(JSON.stringify({message:"JWT service not configured"}),{status:500,headers:{"Content-Type":"application/json"}})}let i;try{i=await o.verify(s)}catch{return new Response(JSON.stringify({message:"Unauthorized: invalid or expired token"}),{status:401,headers:{"Content-Type":"application/json"}})}if(r.roles&&r.roles.length>0){let c=i.roles??[];if(!r.roles.some(u=>c.includes(u)))return new Response(JSON.stringify({message:"Forbidden: insufficient permissions"}),{status:403,headers:{"Content-Type":"application/json"}})}return t.items.set("user",i),null}var W,ae=w(()=>{"use strict";P();q();B();a(we,"checkAuth");W=class{static{a(this,"Router")}routes=[];registerControllers(e){for(let r of e){let n=Reflect.getMetadata(L,r);if(n===void 0)continue;let s=Reflect.getMetadata(v,r)||[];for(let o of s){let i=`/${n}/${o.path}`.replace(/\/+/g,"/");i!=="/"&&i.endsWith("/")&&(i=i.slice(0,-1));let c=new URLPattern({pathname:i});this.routes.push({method:o.method,pattern:c,controller:r,methodName:o.methodName})}}}middleware(){return async(e,r)=>{for(let n of this.routes){if(n.method!==e.method)continue;let s=n.pattern.exec({pathname:e.path});if(s){let o=e.items.get("scope");if(!o)throw new Error("DI Scope not found in HttpContext");let i=Reflect.getMetadata(O,n.controller,n.methodName),c=Reflect.getMetadata(O,n.controller),l=i??c;if(l){let d=await we(e,o,l);if(d)return d}let u=o.resolve(n.controller),p=`${U.toString()}_${n.methodName}`,f=Reflect.getMetadata(p,n.controller)||[],b=u[n.methodName].length,m=new Array(b).fill(void 0),de=f.some(d=>d.type===C.Body),_;de&&(_=await e.request.json().catch(()=>({})));let ue=new URL(e.request.url);for(let d of f)d.type===C.Route&&d.name?m[d.index]=s.pathname.groups[d.name]:d.type===C.Query&&d.name?m[d.index]=ue.searchParams.get(d.name):d.type===C.Body?m[d.index]=_:d.type===C.Context&&(m[d.index]=e);let g=await u[n.methodName](...m);return g instanceof Response?g:g instanceof S?g.toResponse():typeof g=="object"?Response.json(g):new Response(String(g))}}return r()}}}});var Ae={};D(Ae,{Authorize:()=>z,Controller:()=>G,Delete:()=>V,FromBody:()=>re,FromQuery:()=>te,FromRoute:()=>ee,Get:()=>X,HttpContext:()=>x,HttpResult:()=>S,Inject:()=>K,Injectable:()=>A,JwtAuthService:()=>y,Patch:()=>Y,Post:()=>Q,Put:()=>Z,ServiceCollection:()=>T,ServiceProvider:()=>R,WebApplication:()=>M,WebApplicationBuilder:()=>E,cors:()=>ce,throttle:()=>le});module.exports=J(Ae);var Se=require("reflect-metadata");I();var h=(function(t){return t[t.Singleton=0]="Singleton",t[t.Transient=1]="Transient",t[t.Scoped=2]="Scoped",t})({});var R=class t{static{a(this,"ServiceProvider")}descriptors;parent;singletonInstances=new Map;scopedInstances=new Map;constructor(e,r){this.descriptors=e,this.parent=r}createScope(){return new t(this.descriptors,this.parent||this)}resolve(e){let r=this.descriptors.find(n=>n.token===e);if(!r){if(this.parent)return this.parent.resolve(e);throw new Error(`Service not registered for token: ${e.toString()}`)}switch(r.lifetime){case h.Singleton:return this.resolveSingleton(r);case h.Scoped:return this.resolveScoped(r);case h.Transient:return this.resolveTransient(r)}}resolveSingleton(e){let r=this.parent||this;if(r.singletonInstances.has(e.token))return r.singletonInstances.get(e.token);let n=this.createInstance(e);return r.singletonInstances.set(e.token,n),n}resolveScoped(e){if(this.parent,this.scopedInstances.has(e.token))return this.scopedInstances.get(e.token);let r=this.createInstance(e);return this.scopedInstances.set(e.token,r),r}resolveTransient(e){return this.createInstance(e)}createInstance(e){if(e.implementationInstance!==void 0)return e.implementationInstance;if(e.implementationFactory)return e.implementationFactory(this);if(e.implementationType)return this.instantiateClass(e.implementationType);throw new Error(`Invalid service descriptor for token: ${e.token.toString()}`)}instantiateClass(e){let r=Reflect.getMetadata("design:paramtypes",e)||[],n=Reflect.getMetadata(H,e)||[],s=r.map((o,i)=>{let c=n.find(u=>u.index===i),l=c?c.token:o;if(!l||l===Object||l===String||l===Number||l===Boolean)throw new Error(`Cannot resolve parameter at index ${i} for ${e.name}. Token could not be determined or is primitive. Cannot inject primitive types directly without @Inject().`);return this.resolve(l)});return new e(...s)}};var T=class{static{a(this,"ServiceCollection")}descriptors=[];add(e){return this.descriptors.push(e),this}addSingleton(e,r){return this.add({token:e,implementationType:r||e,lifetime:h.Singleton})}addSingletonInstance(e,r){return this.add({token:e,implementationInstance:r,lifetime:h.Singleton})}addTransient(e,r){return this.add({token:e,implementationType:r||e,lifetime:h.Transient})}addScoped(e,r){return this.add({token:e,implementationType:r||e,lifetime:h.Scoped})}buildServiceProvider(){return new R(this.descriptors)}addControllers(e){return e.forEach(r=>this.addTransient(r)),this}};var x=class{static{a(this,"HttpContext")}request;items=new Map;constructor(e){this.request=e}get method(){return this.request.method}get url(){return this.request.url}get path(){return new URL(this.request.url).pathname}};var E=class{static{a(this,"WebApplicationBuilder")}services;constructor(){this.services=new T}build(){let e=this.services.buildServiceProvider();return new M(e)}};var M=class{static{a(this,"WebApplication")}services;middlewares=[];controllersToMap=[];constructor(e){this.services=e}static createBuilder(){return new E}use(e){return this.middlewares.push(e),this}mapControllers(e){return this.controllersToMap.push(...e),this}async executePipeline(e){let r=-1,n=a(async o=>{if(o<=r)throw new Error("next() called multiple times");r=o;let i=this.middlewares[o];if(o===this.middlewares.length)return new Response(JSON.stringify({message:"Not found"}),{status:404});if(i)return i(e,n.bind(null,o+1))},"dispatch");return await n(0)||new Response(JSON.stringify({message:"Internal Server Error"}),{status:500})}run(e=3e3){let r=this;if(this.controllersToMap.length>0){let{Router:n}=(ae(),J(ie)),s=new n;s.registerControllers(this.controllersToMap),this.use(s.middleware())}Bun.serve({port:e,async fetch(n){let s=r.services.createScope(),o=new x(n);return o.items.set("scope",s),r.executePipeline(o)}}),console.log(`\u{1F680} Steampunk application is running on http://localhost:${e}`)}};q();I();B();P();F();function ce(t={}){return async(e,r)=>{let{request:n}=e,s=n.headers.get("origin"),o=await r();o||(o=new Response);let i=new Response(o.body,o);if(t.origin?typeof t.origin=="string"?i.headers.set("Access-Control-Allow-Origin",t.origin):Array.isArray(t.origin)&&s?t.origin.includes(s)&&i.headers.set("Access-Control-Allow-Origin",s):typeof t.origin=="function"&&s&&t.origin(s)&&i.headers.set("Access-Control-Allow-Origin",s):i.headers.set("Access-Control-Allow-Origin","*"),t.methods){let c=Array.isArray(t.methods)?t.methods.join(", "):t.methods;i.headers.set("Access-Control-Allow-Methods",c)}else i.headers.set("Access-Control-Allow-Methods","GET,HEAD,PUT,PATCH,POST,DELETE");if(t.allowedHeaders){let c=Array.isArray(t.allowedHeaders)?t.allowedHeaders.join(", "):t.allowedHeaders;i.headers.set("Access-Control-Allow-Headers",c)}else{let c=n.headers.get("access-control-request-headers");c&&i.headers.set("Access-Control-Allow-Headers",c)}if(t.exposedHeaders){let c=Array.isArray(t.exposedHeaders)?t.exposedHeaders.join(", "):t.exposedHeaders;i.headers.set("Access-Control-Expose-Headers",c)}return t.credentials&&i.headers.set("Access-Control-Allow-Credentials","true"),t.maxAge!==void 0&&i.headers.set("Access-Control-Max-Age",t.maxAge.toString()),n.method==="OPTIONS"?new Response(null,{headers:i.headers,status:204}):i}}a(ce,"cors");function le(t){let e=a(s=>{let o=s.request?.headers?.get("x-forwarded-for");return o?o.split(",")[0].trim():"global"},"defaultKeyGenerator"),r=t.keyGenerator||e,n=new Map;return async(s,o)=>{let i=r(s),c=Date.now(),l=n.get(i);if(l?c>l.resetTime?(l.count=1,l.resetTime=c+t.windowMs):l.count++:(l={count:1,resetTime:c+t.windowMs},n.set(i,l)),Math.random()<.05)for(let[f,b]of n.entries())Date.now()>b.resetTime&&n.delete(f);if(l.count>t.limit){let f=Math.ceil((l.resetTime-c)/1e3);return new Response("Too Many Requests",{status:429,headers:{"Retry-After":f.toString(),"X-RateLimit-Limit":t.limit.toString(),"X-RateLimit-Remaining":"0","X-RateLimit-Reset":Math.ceil(l.resetTime/1e3).toString()}})}let u=await o();u||(u=new Response);let p=new Response(u.body,u);return p.headers.set("X-RateLimit-Limit",t.limit.toString()),p.headers.set("X-RateLimit-Remaining",Math.max(0,t.limit-l.count).toString()),p.headers.set("X-RateLimit-Reset",Math.ceil(l.resetTime/1e3).toString()),p}}a(le,"throttle");0&&(module.exports={Authorize,Controller,Delete,FromBody,FromQuery,FromRoute,Get,HttpContext,HttpResult,Inject,Injectable,JwtAuthService,Patch,Post,Put,ServiceCollection,ServiceProvider,WebApplication,WebApplicationBuilder,cors,throttle});
1
+ "use strict";var H=Object.defineProperty;var he=Object.getOwnPropertyDescriptor;var me=Object.getOwnPropertyNames;var ge=Object.prototype.hasOwnProperty;var a=(t,e)=>H(t,"name",{value:e,configurable:!0});var R=(t,e)=>()=>(t&&(e=t(t=0)),e);var J=(t,e)=>{for(var r in e)H(t,r,{get:e[r],enumerable:!0})},ye=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of me(e))!ge.call(t,s)&&s!==r&&H(t,s,{get:()=>e[s],enumerable:!(n=he(e,s))||n.enumerable});return t};var L=t=>ye(H({},"__esModule",{value:!0}),t);function T(){return t=>{Reflect.defineMetadata(we,!0,t)}}function G(t){return(e,r,n)=>{let s=Reflect.getMetadata(D,e)||[];s.push({index:n,token:t}),Reflect.defineMetadata(D,s,e)}}var Ee,we,D,I=R(()=>{"use strict";Ee=require("reflect-metadata"),we=Symbol("INJECTABLE_WATERMARK"),D=Symbol("INJECT_METADATA");a(T,"Injectable");a(G,"Inject")});function X(t){return(e,r)=>{let n={required:!0,roles:t};r!==void 0?Reflect.defineMetadata(O,n,e.constructor,r):Reflect.defineMetadata(O,n,e)}}var $e,O,q=R(()=>{"use strict";$e=require("reflect-metadata"),O=Symbol("AUTHORIZE_METADATA");a(X,"Authorize")});var y,U=R(()=>{"use strict";y=class t{static{a(this,"HttpResult")}status;body;headers;constructor(e,r,n={}){this.status=e,this.body=r!==void 0&&typeof r!="string"?JSON.stringify(r):r,this.headers=n}static ok(e){return new t(200,e)}static created(e,r){let n={};return r&&(n.Location=r),new t(201,e,n)}static noContent(){return new t(204)}static badRequest(e="Bad Request",r){let n=typeof e=="string"?{message:e,errors:r}:e;return new t(400,n)}static unauthorized(e="Unauthorized"){let r=typeof e=="string"?{message:e}:e;return new t(401,r)}static forbidden(e="Forbidden"){let r=typeof e=="string"?{message:e}:e;return new t(403,r)}static notFound(e="Not Found"){let r=typeof e=="string"?{message:e}:e;return new t(404,r)}static conflict(e="Conflict"){let r=typeof e=="string"?{message:e}:e;return new t(409,r)}static unprocessableEntity(e="Unprocessable Entity",r){let n=typeof e=="string"?{message:e,errors:r}:e;return new t(422,n)}static internalServerError(e="Internal Server Error"){let r=typeof e=="string"?{message:e}:e;return new t(500,r)}toResponse(){if(this.status===204||this.body===void 0)return new Response(null,{status:this.status,headers:this.headers});let e={"Content-Type":"application/json",...this.headers};return new Response(this.body,{status:this.status,headers:e})}}});function Q(t=""){return e=>{Reflect.defineMetadata(k,t,e),T()(e)}}function re(t,e){return(r,n,s)=>{$(r,n,{type:0,index:s,name:t,schema:e})}}function ne(t,e){return(r,n,s)=>{$(r,n,{type:1,index:s,name:t,schema:e})}}function se(t){return(e,r,n)=>{$(e,r,{type:2,index:n,schema:t})}}function $(t,e,r){let n=`${B.toString()}_${e.toString()}`;Reflect.hasMetadata(n,t.constructor)||Reflect.defineMetadata(n,[],t.constructor);let s=Reflect.getMetadata(n,t.constructor);s.push(r),Reflect.defineMetadata(n,s,t.constructor)}var ze,k,C,B,j,Z,V,Y,ee,te,w,F=R(()=>{"use strict";ze=require("reflect-metadata");I();k=Symbol("CONTROLLER_WATERMARK"),C=Symbol("ROUTE_METADATA"),B=Symbol("PARAM_METADATA");a(Q,"Controller");j=a(t=>(e="")=>(r,n)=>{Reflect.hasMetadata(C,r.constructor)||Reflect.defineMetadata(C,[],r.constructor);let s=Reflect.getMetadata(C,r.constructor);s.push({method:t,path:e,methodName:n.toString()}),Reflect.defineMetadata(C,s,r.constructor)},"createRouteDecorator"),Z=j("GET"),V=j("POST"),Y=j("PUT"),ee=j("DELETE"),te=j("PATCH"),w=(function(t){return t[t.Route=0]="Route",t[t.Query=1]="Query",t[t.Body=2]="Body",t[t.Context=3]="Context",t})({});a(re,"FromRoute");a(ne,"FromQuery");a(se,"FromBody");a($,"addParamMetadata")});var ae={};J(ae,{JwtAuthService:()=>A});function Ae(t,e,r,n){var s=arguments.length,o=s<3?e:n===null?n=Object.getOwnPropertyDescriptor(e,r):n,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(t,e,r,n);else for(var c=t.length-1;c>=0;c--)(i=t[c])&&(o=(s<3?i(o):s>3?i(e,r,o):i(e,r))||o);return s>3&&o&&Object.defineProperty(e,r,o),o}function oe(t,e){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(t,e)}function W(t){return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function ie(t){let e=t+"==".slice(2-t.length*3&3);return atob(e.replace(/-/g,"+").replace(/_/g,"/"))}var A,_=R(()=>{"use strict";I();a(Ae,"_ts_decorate");a(oe,"_ts_metadata");a(W,"base64UrlEncode");a(ie,"base64UrlDecode");A=class{static{a(this,"JwtAuthService")}secret;expiresIn;constructor(e){this.secret=e.secret,this.expiresIn=e.expiresIn??3600}async getKey(){let e=new TextEncoder;return crypto.subtle.importKey("raw",e.encode(this.secret),{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}async sign(e){let r={alg:"HS256",typ:"JWT"},n=Math.floor(Date.now()/1e3),s={...e,iat:n,exp:n+this.expiresIn},o=W(JSON.stringify(r)),i=W(JSON.stringify(s)),c=`${o}.${i}`,l=await this.getKey(),u=new TextEncoder,p=await crypto.subtle.sign("HMAC",l,u.encode(c)),f=W(String.fromCharCode(...new Uint8Array(p)));return`${c}.${f}`}async verify(e){let r=e.split(".");if(r.length!==3)throw new Error("Invalid JWT format");let n=r[0],s=r[1],o=r[2],i=`${n}.${s}`,c=await this.getKey(),l=new TextEncoder,u=Uint8Array.from(ie(o),N=>N.charCodeAt(0));if(!await crypto.subtle.verify("HMAC",c,u,l.encode(i)))throw new Error("Invalid JWT signature");let f=JSON.parse(ie(s)),b=Math.floor(Date.now()/1e3);if(f.exp!==void 0&&f.exp<b)throw new Error("JWT expired");return f}};A=Ae([T(),oe("design:type",Function),oe("design:paramtypes",[typeof JwtOptions>"u"?Object:JwtOptions])],A)});var ce={};J(ce,{Router:()=>K});async function Re(t,e,r){if(!r.required)return null;let n=t.request.headers.get("authorization");if(!n||!n.startsWith("Bearer "))return new Response(JSON.stringify({message:"Unauthorized"}),{status:401,headers:{"Content-Type":"application/json"}});let s=n.slice(7),o;try{let{JwtAuthService:c}=(_(),L(ae));o=e.resolve(c)}catch{return new Response(JSON.stringify({message:"JWT service not configured"}),{status:500,headers:{"Content-Type":"application/json"}})}let i;try{i=await o.verify(s)}catch{return new Response(JSON.stringify({message:"Unauthorized: invalid or expired token"}),{status:401,headers:{"Content-Type":"application/json"}})}if(r.roles&&r.roles.length>0){let c=i.roles??[];if(!r.roles.some(u=>c.includes(u)))return new Response(JSON.stringify({message:"Forbidden: insufficient permissions"}),{status:403,headers:{"Content-Type":"application/json"}})}return t.items.set("user",i),null}var K,le=R(()=>{"use strict";q();U();F();a(Re,"checkAuth");K=class{static{a(this,"Router")}routes=[];registerControllers(e){for(let r of e){let n=Reflect.getMetadata(k,r);if(n===void 0)continue;let s=Reflect.getMetadata(C,r)||[];for(let o of s){let i=`/${n}/${o.path}`.replace(/\/+/g,"/");i!=="/"&&i.endsWith("/")&&(i=i.slice(0,-1));let c=new URLPattern({pathname:i});this.routes.push({method:o.method,pattern:c,controller:r,methodName:o.methodName})}}}middleware(){return async(e,r)=>{for(let n of this.routes){if(n.method!==e.method)continue;let s=n.pattern.exec({pathname:e.path});if(s){let o=e.items.get("scope");if(!o)throw new Error("DI Scope not found in HttpContext");let i=Reflect.getMetadata(O,n.controller,n.methodName),c=Reflect.getMetadata(O,n.controller),l=i??c;if(l){let d=await Re(e,o,l);if(d)return d}let u=o.resolve(n.controller),p=`${B.toString()}_${n.methodName}`,f=Reflect.getMetadata(p,n.controller)||[],b=u[n.methodName].length,N=new Array(b).fill(void 0),fe=f.some(d=>d.type===w.Body),z;fe&&(z=await e.request.json().catch(()=>({})));let pe=new URL(e.request.url);for(let d of f){let g;if(d.type===w.Route&&d.name?g=s.pathname.groups[d.name]:d.type===w.Query&&d.name?g=pe.searchParams.get(d.name):d.type===w.Body?g=z:d.type===w.Context&&(g=e),d.schema){let P=d.schema.safeParse(g);if(!P.success)return y.unprocessableEntity("Validation failed",{errors:P.error.errors,target:w[d.type].toLowerCase(),name:d.name}).toResponse();g=P.data}N[d.index]=g}let m=await u[n.methodName](...N);return m instanceof Response?m:m instanceof y?m.toResponse():typeof m=="object"?Response.json(m):new Response(String(m))}}return r()}}}});var Te={};J(Te,{Authorize:()=>X,Controller:()=>Q,Delete:()=>ee,FromBody:()=>se,FromQuery:()=>ne,FromRoute:()=>re,Get:()=>Z,HttpContext:()=>M,HttpResult:()=>y,Inject:()=>G,Injectable:()=>T,JwtAuthService:()=>A,Patch:()=>te,Post:()=>V,Put:()=>Y,ServiceCollection:()=>E,ServiceProvider:()=>x,WebApplication:()=>v,WebApplicationBuilder:()=>S,cors:()=>de,throttle:()=>ue});module.exports=L(Te);var Ce=require("reflect-metadata");I();var h=(function(t){return t[t.Singleton=0]="Singleton",t[t.Transient=1]="Transient",t[t.Scoped=2]="Scoped",t})({});var x=class t{static{a(this,"ServiceProvider")}descriptors;parent;singletonInstances=new Map;scopedInstances=new Map;constructor(e,r){this.descriptors=e,this.parent=r}createScope(){return new t(this.descriptors,this.parent||this)}resolve(e){let r=this.descriptors.find(n=>n.token===e);if(!r){if(this.parent)return this.parent.resolve(e);throw new Error(`Service not registered for token: ${e.toString()}`)}switch(r.lifetime){case h.Singleton:return this.resolveSingleton(r);case h.Scoped:return this.resolveScoped(r);case h.Transient:return this.resolveTransient(r)}}resolveSingleton(e){let r=this.parent||this;if(r.singletonInstances.has(e.token))return r.singletonInstances.get(e.token);let n=this.createInstance(e);return r.singletonInstances.set(e.token,n),n}resolveScoped(e){if(this.parent,this.scopedInstances.has(e.token))return this.scopedInstances.get(e.token);let r=this.createInstance(e);return this.scopedInstances.set(e.token,r),r}resolveTransient(e){return this.createInstance(e)}createInstance(e){if(e.implementationInstance!==void 0)return e.implementationInstance;if(e.implementationFactory)return e.implementationFactory(this);if(e.implementationType)return this.instantiateClass(e.implementationType);throw new Error(`Invalid service descriptor for token: ${e.token.toString()}`)}instantiateClass(e){let r=Reflect.getMetadata("design:paramtypes",e)||[],n=Reflect.getMetadata(D,e)||[],s=r.map((o,i)=>{let c=n.find(u=>u.index===i),l=c?c.token:o;if(!l||l===Object||l===String||l===Number||l===Boolean)throw new Error(`Cannot resolve parameter at index ${i} for ${e.name}. Token could not be determined or is primitive. Cannot inject primitive types directly without @Inject().`);return this.resolve(l)});return new e(...s)}};var E=class{static{a(this,"ServiceCollection")}descriptors=[];add(e){return this.descriptors.push(e),this}addSingleton(e,r){return this.add({token:e,implementationType:r||e,lifetime:h.Singleton})}addSingletonInstance(e,r){return this.add({token:e,implementationInstance:r,lifetime:h.Singleton})}addTransient(e,r){return this.add({token:e,implementationType:r||e,lifetime:h.Transient})}addScoped(e,r){return this.add({token:e,implementationType:r||e,lifetime:h.Scoped})}buildServiceProvider(){return new x(this.descriptors)}addControllers(e){return e.forEach(r=>this.addTransient(r)),this}};var M=class{static{a(this,"HttpContext")}request;items=new Map;constructor(e){this.request=e}get method(){return this.request.method}get url(){return this.request.url}get path(){return new URL(this.request.url).pathname}};var S=class{static{a(this,"WebApplicationBuilder")}services;constructor(){this.services=new E}build(){let e=this.services.buildServiceProvider();return new v(e)}};var v=class{static{a(this,"WebApplication")}services;middlewares=[];controllersToMap=[];constructor(e){this.services=e}static createBuilder(){return new S}use(e){return this.middlewares.push(e),this}mapControllers(e){return this.controllersToMap.push(...e),this}async executePipeline(e){let r=-1,n=a(async o=>{if(o<=r)throw new Error("next() called multiple times");r=o;let i=this.middlewares[o];if(o===this.middlewares.length)return new Response(JSON.stringify({message:"Not found"}),{status:404});if(i)return i(e,n.bind(null,o+1))},"dispatch");return await n(0)||new Response(JSON.stringify({message:"Internal Server Error"}),{status:500})}run(e=3e3){let r=this;if(this.controllersToMap.length>0){let{Router:n}=(le(),L(ce)),s=new n;s.registerControllers(this.controllersToMap),this.use(s.middleware())}Bun.serve({port:e,async fetch(n){let s=r.services.createScope(),o=new M(n);return o.items.set("scope",s),r.executePipeline(o)}}),console.log(`\u{1F680} Steampunk application is running on http://localhost:${e}`)}};U();I();F();q();_();function de(t={}){return async(e,r)=>{let{request:n}=e,s=n.headers.get("origin"),o=await r();o||(o=new Response);let i=new Response(o.body,o);if(t.origin?typeof t.origin=="string"?i.headers.set("Access-Control-Allow-Origin",t.origin):Array.isArray(t.origin)&&s?t.origin.includes(s)&&i.headers.set("Access-Control-Allow-Origin",s):typeof t.origin=="function"&&s&&t.origin(s)&&i.headers.set("Access-Control-Allow-Origin",s):i.headers.set("Access-Control-Allow-Origin","*"),t.methods){let c=Array.isArray(t.methods)?t.methods.join(", "):t.methods;i.headers.set("Access-Control-Allow-Methods",c)}else i.headers.set("Access-Control-Allow-Methods","GET,HEAD,PUT,PATCH,POST,DELETE");if(t.allowedHeaders){let c=Array.isArray(t.allowedHeaders)?t.allowedHeaders.join(", "):t.allowedHeaders;i.headers.set("Access-Control-Allow-Headers",c)}else{let c=n.headers.get("access-control-request-headers");c&&i.headers.set("Access-Control-Allow-Headers",c)}if(t.exposedHeaders){let c=Array.isArray(t.exposedHeaders)?t.exposedHeaders.join(", "):t.exposedHeaders;i.headers.set("Access-Control-Expose-Headers",c)}return t.credentials&&i.headers.set("Access-Control-Allow-Credentials","true"),t.maxAge!==void 0&&i.headers.set("Access-Control-Max-Age",t.maxAge.toString()),n.method==="OPTIONS"?new Response(null,{headers:i.headers,status:204}):i}}a(de,"cors");function ue(t){let e=a(s=>{let o=s.request?.headers?.get("x-forwarded-for");return o?o.split(",")[0].trim():"global"},"defaultKeyGenerator"),r=t.keyGenerator||e,n=new Map;return async(s,o)=>{let i=r(s),c=Date.now(),l=n.get(i);if(l?c>l.resetTime?(l.count=1,l.resetTime=c+t.windowMs):l.count++:(l={count:1,resetTime:c+t.windowMs},n.set(i,l)),Math.random()<.05)for(let[f,b]of n.entries())Date.now()>b.resetTime&&n.delete(f);if(l.count>t.limit){let f=Math.ceil((l.resetTime-c)/1e3);return new Response("Too Many Requests",{status:429,headers:{"Retry-After":f.toString(),"X-RateLimit-Limit":t.limit.toString(),"X-RateLimit-Remaining":"0","X-RateLimit-Reset":Math.ceil(l.resetTime/1e3).toString()}})}let u=await o();u||(u=new Response);let p=new Response(u.body,u);return p.headers.set("X-RateLimit-Limit",t.limit.toString()),p.headers.set("X-RateLimit-Remaining",Math.max(0,t.limit-l.count).toString()),p.headers.set("X-RateLimit-Reset",Math.ceil(l.resetTime/1e3).toString()),p}}a(ue,"throttle");0&&(module.exports={Authorize,Controller,Delete,FromBody,FromQuery,FromRoute,Get,HttpContext,HttpResult,Inject,Injectable,JwtAuthService,Patch,Post,Put,ServiceCollection,ServiceProvider,WebApplication,WebApplicationBuilder,cors,throttle});
package/dist/main.d.cts CHANGED
@@ -107,9 +107,9 @@ declare const Post: (path?: string) => MethodDecorator;
107
107
  declare const Put: (path?: string) => MethodDecorator;
108
108
  declare const Delete: (path?: string) => MethodDecorator;
109
109
  declare const Patch: (path?: string) => MethodDecorator;
110
- declare const FromRoute: (name: string) => ParameterDecorator;
111
- declare const FromQuery: (name: string) => ParameterDecorator;
112
- declare const FromBody: () => ParameterDecorator;
110
+ declare function FromRoute(name: string, schema?: any): ParameterDecorator;
111
+ declare function FromQuery(name: string, schema?: any): ParameterDecorator;
112
+ declare function FromBody(schema?: any): ParameterDecorator;
113
113
 
114
114
  interface AuthorizeOptions {
115
115
  required: boolean;
package/dist/main.d.ts CHANGED
@@ -107,9 +107,9 @@ declare const Post: (path?: string) => MethodDecorator;
107
107
  declare const Put: (path?: string) => MethodDecorator;
108
108
  declare const Delete: (path?: string) => MethodDecorator;
109
109
  declare const Patch: (path?: string) => MethodDecorator;
110
- declare const FromRoute: (name: string) => ParameterDecorator;
111
- declare const FromQuery: (name: string) => ParameterDecorator;
112
- declare const FromBody: () => ParameterDecorator;
110
+ declare function FromRoute(name: string, schema?: any): ParameterDecorator;
111
+ declare function FromQuery(name: string, schema?: any): ParameterDecorator;
112
+ declare function FromBody(schema?: any): ParameterDecorator;
113
113
 
114
114
  interface AuthorizeOptions {
115
115
  required: boolean;
package/dist/main.js CHANGED
@@ -1 +1 @@
1
- var N=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var ee=Object.getOwnPropertyNames;var te=Object.prototype.hasOwnProperty;var a=(t,e)=>N(t,"name",{value:e,configurable:!0});var y=(t,e)=>()=>(t&&(e=t(t=0)),e);var W=(t,e)=>{for(var r in e)N(t,r,{get:e[r],enumerable:!0})},re=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of ee(e))!te.call(t,s)&&s!==r&&N(t,s,{get:()=>e[s],enumerable:!(n=Y(e,s))||n.enumerable});return t};var _=t=>re(N({},"__esModule",{value:!0}),t);import"reflect-metadata";function x(){return t=>{Reflect.defineMetadata(ne,!0,t)}}function se(t){return(e,r,n)=>{let s=Reflect.getMetadata(H,e)||[];s.push({index:n,token:t}),Reflect.defineMetadata(H,s,e)}}var ne,H,E=y(()=>{"use strict";ne=Symbol("INJECTABLE_WATERMARK"),H=Symbol("INJECT_METADATA");a(x,"Injectable");a(se,"Inject")});import"reflect-metadata";function oe(t){return(e,r)=>{let n={required:!0,roles:t};r!==void 0?Reflect.defineMetadata(I,n,e.constructor,r):Reflect.defineMetadata(I,n,e)}}var I,D=y(()=>{"use strict";I=Symbol("AUTHORIZE_METADATA");a(oe,"Authorize")});var O,J=y(()=>{"use strict";O=class t{static{a(this,"HttpResult")}status;body;headers;constructor(e,r,n={}){this.status=e,this.body=r!==void 0&&typeof r!="string"?JSON.stringify(r):r,this.headers=n}static ok(e){return new t(200,e)}static created(e,r){let n={};return r&&(n.Location=r),new t(201,e,n)}static noContent(){return new t(204)}static badRequest(e="Bad Request",r){let n=typeof e=="string"?{message:e,errors:r}:e;return new t(400,n)}static unauthorized(e="Unauthorized"){let r=typeof e=="string"?{message:e}:e;return new t(401,r)}static forbidden(e="Forbidden"){let r=typeof e=="string"?{message:e}:e;return new t(403,r)}static notFound(e="Not Found"){let r=typeof e=="string"?{message:e}:e;return new t(404,r)}static conflict(e="Conflict"){let r=typeof e=="string"?{message:e}:e;return new t(409,r)}static unprocessableEntity(e="Unprocessable Entity",r){let n=typeof e=="string"?{message:e,errors:r}:e;return new t(422,n)}static internalServerError(e="Internal Server Error"){let r=typeof e=="string"?{message:e}:e;return new t(500,r)}toResponse(){if(this.status===204||this.body===void 0)return new Response(null,{status:this.status,headers:this.headers});let e={"Content-Type":"application/json",...this.headers};return new Response(this.body,{status:this.status,headers:e})}}});import"reflect-metadata";function ie(t=""){return e=>{Reflect.defineMetadata(P,t,e),x()(e)}}function L(t,e,r){let n=`${q.toString()}_${e.toString()}`;Reflect.hasMetadata(n,t.constructor)||Reflect.defineMetadata(n,[],t.constructor);let s=Reflect.getMetadata(n,t.constructor);s.push(r),Reflect.defineMetadata(n,s,t.constructor)}var P,w,q,j,ae,ce,le,de,ue,A,fe,pe,he,U=y(()=>{"use strict";E();P=Symbol("CONTROLLER_WATERMARK"),w=Symbol("ROUTE_METADATA"),q=Symbol("PARAM_METADATA");a(ie,"Controller");j=a(t=>(e="")=>(r,n)=>{Reflect.hasMetadata(w,r.constructor)||Reflect.defineMetadata(w,[],r.constructor);let s=Reflect.getMetadata(w,r.constructor);s.push({method:t,path:e,methodName:n.toString()}),Reflect.defineMetadata(w,s,r.constructor)},"createRouteDecorator"),ae=j("GET"),ce=j("POST"),le=j("PUT"),de=j("DELETE"),ue=j("PATCH"),A=(function(t){return t[t.Route=0]="Route",t[t.Query=1]="Query",t[t.Body=2]="Body",t[t.Context=3]="Context",t})({}),fe=a(t=>(e,r,n)=>{L(e,r,{type:0,index:n,name:t})},"FromRoute"),pe=a(t=>(e,r,n)=>{L(e,r,{type:1,index:n,name:t})},"FromQuery"),he=a(()=>(t,e,r)=>{L(t,e,{type:2,index:r})},"FromBody");a(L,"addParamMetadata")});var G={};W(G,{JwtAuthService:()=>R});function me(t,e,r,n){var s=arguments.length,o=s<3?e:n===null?n=Object.getOwnPropertyDescriptor(e,r):n,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(t,e,r,n);else for(var c=t.length-1;c>=0;c--)(i=t[c])&&(o=(s<3?i(o):s>3?i(e,r,o):i(e,r))||o);return s>3&&o&&Object.defineProperty(e,r,o),o}function K(t,e){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(t,e)}function k(t){return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function z(t){let e=t+"==".slice(2-t.length*3&3);return atob(e.replace(/-/g,"+").replace(/_/g,"/"))}var R,B=y(()=>{"use strict";E();a(me,"_ts_decorate");a(K,"_ts_metadata");a(k,"base64UrlEncode");a(z,"base64UrlDecode");R=class{static{a(this,"JwtAuthService")}secret;expiresIn;constructor(e){this.secret=e.secret,this.expiresIn=e.expiresIn??3600}async getKey(){let e=new TextEncoder;return crypto.subtle.importKey("raw",e.encode(this.secret),{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}async sign(e){let r={alg:"HS256",typ:"JWT"},n=Math.floor(Date.now()/1e3),s={...e,iat:n,exp:n+this.expiresIn},o=k(JSON.stringify(r)),i=k(JSON.stringify(s)),c=`${o}.${i}`,l=await this.getKey(),u=new TextEncoder,p=await crypto.subtle.sign("HMAC",l,u.encode(c)),f=k(String.fromCharCode(...new Uint8Array(p)));return`${c}.${f}`}async verify(e){let r=e.split(".");if(r.length!==3)throw new Error("Invalid JWT format");let n=r[0],s=r[1],o=r[2],i=`${n}.${s}`,c=await this.getKey(),l=new TextEncoder,u=Uint8Array.from(z(o),m=>m.charCodeAt(0));if(!await crypto.subtle.verify("HMAC",c,u,l.encode(i)))throw new Error("Invalid JWT signature");let f=JSON.parse(z(s)),T=Math.floor(Date.now()/1e3);if(f.exp!==void 0&&f.exp<T)throw new Error("JWT expired");return f}};R=me([x(),K("design:type",Function),K("design:paramtypes",[typeof JwtOptions>"u"?Object:JwtOptions])],R)});var X={};W(X,{Router:()=>$});async function ge(t,e,r){if(!r.required)return null;let n=t.request.headers.get("authorization");if(!n||!n.startsWith("Bearer "))return new Response(JSON.stringify({message:"Unauthorized"}),{status:401,headers:{"Content-Type":"application/json"}});let s=n.slice(7),o;try{let{JwtAuthService:c}=(B(),_(G));o=e.resolve(c)}catch{return new Response(JSON.stringify({message:"JWT service not configured"}),{status:500,headers:{"Content-Type":"application/json"}})}let i;try{i=await o.verify(s)}catch{return new Response(JSON.stringify({message:"Unauthorized: invalid or expired token"}),{status:401,headers:{"Content-Type":"application/json"}})}if(r.roles&&r.roles.length>0){let c=i.roles??[];if(!r.roles.some(u=>c.includes(u)))return new Response(JSON.stringify({message:"Forbidden: insufficient permissions"}),{status:403,headers:{"Content-Type":"application/json"}})}return t.items.set("user",i),null}var $,Q=y(()=>{"use strict";D();J();U();a(ge,"checkAuth");$=class{static{a(this,"Router")}routes=[];registerControllers(e){for(let r of e){let n=Reflect.getMetadata(P,r);if(n===void 0)continue;let s=Reflect.getMetadata(w,r)||[];for(let o of s){let i=`/${n}/${o.path}`.replace(/\/+/g,"/");i!=="/"&&i.endsWith("/")&&(i=i.slice(0,-1));let c=new URLPattern({pathname:i});this.routes.push({method:o.method,pattern:c,controller:r,methodName:o.methodName})}}}middleware(){return async(e,r)=>{for(let n of this.routes){if(n.method!==e.method)continue;let s=n.pattern.exec({pathname:e.path});if(s){let o=e.items.get("scope");if(!o)throw new Error("DI Scope not found in HttpContext");let i=Reflect.getMetadata(I,n.controller,n.methodName),c=Reflect.getMetadata(I,n.controller),l=i??c;if(l){let d=await ge(e,o,l);if(d)return d}let u=o.resolve(n.controller),p=`${q.toString()}_${n.methodName}`,f=Reflect.getMetadata(p,n.controller)||[],T=u[n.methodName].length,m=new Array(T).fill(void 0),Z=f.some(d=>d.type===A.Body),F;Z&&(F=await e.request.json().catch(()=>({})));let V=new URL(e.request.url);for(let d of f)d.type===A.Route&&d.name?m[d.index]=s.pathname.groups[d.name]:d.type===A.Query&&d.name?m[d.index]=V.searchParams.get(d.name):d.type===A.Body?m[d.index]=F:d.type===A.Context&&(m[d.index]=e);let g=await u[n.methodName](...m);return g instanceof Response?g:g instanceof O?g.toResponse():typeof g=="object"?Response.json(g):new Response(String(g))}}return r()}}}});E();import"reflect-metadata";var h=(function(t){return t[t.Singleton=0]="Singleton",t[t.Transient=1]="Transient",t[t.Scoped=2]="Scoped",t})({});var M=class t{static{a(this,"ServiceProvider")}descriptors;parent;singletonInstances=new Map;scopedInstances=new Map;constructor(e,r){this.descriptors=e,this.parent=r}createScope(){return new t(this.descriptors,this.parent||this)}resolve(e){let r=this.descriptors.find(n=>n.token===e);if(!r){if(this.parent)return this.parent.resolve(e);throw new Error(`Service not registered for token: ${e.toString()}`)}switch(r.lifetime){case h.Singleton:return this.resolveSingleton(r);case h.Scoped:return this.resolveScoped(r);case h.Transient:return this.resolveTransient(r)}}resolveSingleton(e){let r=this.parent||this;if(r.singletonInstances.has(e.token))return r.singletonInstances.get(e.token);let n=this.createInstance(e);return r.singletonInstances.set(e.token,n),n}resolveScoped(e){if(this.parent,this.scopedInstances.has(e.token))return this.scopedInstances.get(e.token);let r=this.createInstance(e);return this.scopedInstances.set(e.token,r),r}resolveTransient(e){return this.createInstance(e)}createInstance(e){if(e.implementationInstance!==void 0)return e.implementationInstance;if(e.implementationFactory)return e.implementationFactory(this);if(e.implementationType)return this.instantiateClass(e.implementationType);throw new Error(`Invalid service descriptor for token: ${e.token.toString()}`)}instantiateClass(e){let r=Reflect.getMetadata("design:paramtypes",e)||[],n=Reflect.getMetadata(H,e)||[],s=r.map((o,i)=>{let c=n.find(u=>u.index===i),l=c?c.token:o;if(!l||l===Object||l===String||l===Number||l===Boolean)throw new Error(`Cannot resolve parameter at index ${i} for ${e.name}. Token could not be determined or is primitive. Cannot inject primitive types directly without @Inject().`);return this.resolve(l)});return new e(...s)}};var S=class{static{a(this,"ServiceCollection")}descriptors=[];add(e){return this.descriptors.push(e),this}addSingleton(e,r){return this.add({token:e,implementationType:r||e,lifetime:h.Singleton})}addSingletonInstance(e,r){return this.add({token:e,implementationInstance:r,lifetime:h.Singleton})}addTransient(e,r){return this.add({token:e,implementationType:r||e,lifetime:h.Transient})}addScoped(e,r){return this.add({token:e,implementationType:r||e,lifetime:h.Scoped})}buildServiceProvider(){return new M(this.descriptors)}addControllers(e){return e.forEach(r=>this.addTransient(r)),this}};var v=class{static{a(this,"HttpContext")}request;items=new Map;constructor(e){this.request=e}get method(){return this.request.method}get url(){return this.request.url}get path(){return new URL(this.request.url).pathname}};var C=class{static{a(this,"WebApplicationBuilder")}services;constructor(){this.services=new S}build(){let e=this.services.buildServiceProvider();return new b(e)}};var b=class{static{a(this,"WebApplication")}services;middlewares=[];controllersToMap=[];constructor(e){this.services=e}static createBuilder(){return new C}use(e){return this.middlewares.push(e),this}mapControllers(e){return this.controllersToMap.push(...e),this}async executePipeline(e){let r=-1,n=a(async o=>{if(o<=r)throw new Error("next() called multiple times");r=o;let i=this.middlewares[o];if(o===this.middlewares.length)return new Response(JSON.stringify({message:"Not found"}),{status:404});if(i)return i(e,n.bind(null,o+1))},"dispatch");return await n(0)||new Response(JSON.stringify({message:"Internal Server Error"}),{status:500})}run(e=3e3){let r=this;if(this.controllersToMap.length>0){let{Router:n}=(Q(),_(X)),s=new n;s.registerControllers(this.controllersToMap),this.use(s.middleware())}Bun.serve({port:e,async fetch(n){let s=r.services.createScope(),o=new v(n);return o.items.set("scope",s),r.executePipeline(o)}}),console.log(`\u{1F680} Steampunk application is running on http://localhost:${e}`)}};J();E();U();D();B();function ye(t={}){return async(e,r)=>{let{request:n}=e,s=n.headers.get("origin"),o=await r();o||(o=new Response);let i=new Response(o.body,o);if(t.origin?typeof t.origin=="string"?i.headers.set("Access-Control-Allow-Origin",t.origin):Array.isArray(t.origin)&&s?t.origin.includes(s)&&i.headers.set("Access-Control-Allow-Origin",s):typeof t.origin=="function"&&s&&t.origin(s)&&i.headers.set("Access-Control-Allow-Origin",s):i.headers.set("Access-Control-Allow-Origin","*"),t.methods){let c=Array.isArray(t.methods)?t.methods.join(", "):t.methods;i.headers.set("Access-Control-Allow-Methods",c)}else i.headers.set("Access-Control-Allow-Methods","GET,HEAD,PUT,PATCH,POST,DELETE");if(t.allowedHeaders){let c=Array.isArray(t.allowedHeaders)?t.allowedHeaders.join(", "):t.allowedHeaders;i.headers.set("Access-Control-Allow-Headers",c)}else{let c=n.headers.get("access-control-request-headers");c&&i.headers.set("Access-Control-Allow-Headers",c)}if(t.exposedHeaders){let c=Array.isArray(t.exposedHeaders)?t.exposedHeaders.join(", "):t.exposedHeaders;i.headers.set("Access-Control-Expose-Headers",c)}return t.credentials&&i.headers.set("Access-Control-Allow-Credentials","true"),t.maxAge!==void 0&&i.headers.set("Access-Control-Max-Age",t.maxAge.toString()),n.method==="OPTIONS"?new Response(null,{headers:i.headers,status:204}):i}}a(ye,"cors");function we(t){let e=a(s=>{let o=s.request?.headers?.get("x-forwarded-for");return o?o.split(",")[0].trim():"global"},"defaultKeyGenerator"),r=t.keyGenerator||e,n=new Map;return async(s,o)=>{let i=r(s),c=Date.now(),l=n.get(i);if(l?c>l.resetTime?(l.count=1,l.resetTime=c+t.windowMs):l.count++:(l={count:1,resetTime:c+t.windowMs},n.set(i,l)),Math.random()<.05)for(let[f,T]of n.entries())Date.now()>T.resetTime&&n.delete(f);if(l.count>t.limit){let f=Math.ceil((l.resetTime-c)/1e3);return new Response("Too Many Requests",{status:429,headers:{"Retry-After":f.toString(),"X-RateLimit-Limit":t.limit.toString(),"X-RateLimit-Remaining":"0","X-RateLimit-Reset":Math.ceil(l.resetTime/1e3).toString()}})}let u=await o();u||(u=new Response);let p=new Response(u.body,u);return p.headers.set("X-RateLimit-Limit",t.limit.toString()),p.headers.set("X-RateLimit-Remaining",Math.max(0,t.limit-l.count).toString()),p.headers.set("X-RateLimit-Reset",Math.ceil(l.resetTime/1e3).toString()),p}}a(we,"throttle");export{oe as Authorize,ie as Controller,de as Delete,he as FromBody,pe as FromQuery,fe as FromRoute,ae as Get,v as HttpContext,O as HttpResult,se as Inject,x as Injectable,R as JwtAuthService,ue as Patch,ce as Post,le as Put,S as ServiceCollection,M as ServiceProvider,b as WebApplication,C as WebApplicationBuilder,ye as cors,we as throttle};
1
+ var H=Object.defineProperty;var te=Object.getOwnPropertyDescriptor;var re=Object.getOwnPropertyNames;var ne=Object.prototype.hasOwnProperty;var a=(t,e)=>H(t,"name",{value:e,configurable:!0});var w=(t,e)=>()=>(t&&(e=t(t=0)),e);var K=(t,e)=>{for(var r in e)H(t,r,{get:e[r],enumerable:!0})},se=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of re(e))!ne.call(t,s)&&s!==r&&H(t,s,{get:()=>e[s],enumerable:!(n=te(e,s))||n.enumerable});return t};var z=t=>se(H({},"__esModule",{value:!0}),t);import"reflect-metadata";function E(){return t=>{Reflect.defineMetadata(oe,!0,t)}}function ie(t){return(e,r,n)=>{let s=Reflect.getMetadata(D,e)||[];s.push({index:n,token:t}),Reflect.defineMetadata(D,s,e)}}var oe,D,M=w(()=>{"use strict";oe=Symbol("INJECTABLE_WATERMARK"),D=Symbol("INJECT_METADATA");a(E,"Injectable");a(ie,"Inject")});import"reflect-metadata";function ae(t){return(e,r)=>{let n={required:!0,roles:t};r!==void 0?Reflect.defineMetadata(O,n,e.constructor,r):Reflect.defineMetadata(O,n,e)}}var O,J=w(()=>{"use strict";O=Symbol("AUTHORIZE_METADATA");a(ae,"Authorize")});var A,L=w(()=>{"use strict";A=class t{static{a(this,"HttpResult")}status;body;headers;constructor(e,r,n={}){this.status=e,this.body=r!==void 0&&typeof r!="string"?JSON.stringify(r):r,this.headers=n}static ok(e){return new t(200,e)}static created(e,r){let n={};return r&&(n.Location=r),new t(201,e,n)}static noContent(){return new t(204)}static badRequest(e="Bad Request",r){let n=typeof e=="string"?{message:e,errors:r}:e;return new t(400,n)}static unauthorized(e="Unauthorized"){let r=typeof e=="string"?{message:e}:e;return new t(401,r)}static forbidden(e="Forbidden"){let r=typeof e=="string"?{message:e}:e;return new t(403,r)}static notFound(e="Not Found"){let r=typeof e=="string"?{message:e}:e;return new t(404,r)}static conflict(e="Conflict"){let r=typeof e=="string"?{message:e}:e;return new t(409,r)}static unprocessableEntity(e="Unprocessable Entity",r){let n=typeof e=="string"?{message:e,errors:r}:e;return new t(422,n)}static internalServerError(e="Internal Server Error"){let r=typeof e=="string"?{message:e}:e;return new t(500,r)}toResponse(){if(this.status===204||this.body===void 0)return new Response(null,{status:this.status,headers:this.headers});let e={"Content-Type":"application/json",...this.headers};return new Response(this.body,{status:this.status,headers:e})}}});import"reflect-metadata";function ce(t=""){return e=>{Reflect.defineMetadata(q,t,e),E()(e)}}function he(t,e){return(r,n,s)=>{k(r,n,{type:0,index:s,name:t,schema:e})}}function me(t,e){return(r,n,s)=>{k(r,n,{type:1,index:s,name:t,schema:e})}}function ge(t){return(e,r,n)=>{k(e,r,{type:2,index:n,schema:t})}}function k(t,e,r){let n=`${U.toString()}_${e.toString()}`;Reflect.hasMetadata(n,t.constructor)||Reflect.defineMetadata(n,[],t.constructor);let s=Reflect.getMetadata(n,t.constructor);s.push(r),Reflect.defineMetadata(n,s,t.constructor)}var q,R,U,j,le,de,ue,fe,pe,y,B=w(()=>{"use strict";M();q=Symbol("CONTROLLER_WATERMARK"),R=Symbol("ROUTE_METADATA"),U=Symbol("PARAM_METADATA");a(ce,"Controller");j=a(t=>(e="")=>(r,n)=>{Reflect.hasMetadata(R,r.constructor)||Reflect.defineMetadata(R,[],r.constructor);let s=Reflect.getMetadata(R,r.constructor);s.push({method:t,path:e,methodName:n.toString()}),Reflect.defineMetadata(R,s,r.constructor)},"createRouteDecorator"),le=j("GET"),de=j("POST"),ue=j("PUT"),fe=j("DELETE"),pe=j("PATCH"),y=(function(t){return t[t.Route=0]="Route",t[t.Query=1]="Query",t[t.Body=2]="Body",t[t.Context=3]="Context",t})({});a(he,"FromRoute");a(me,"FromQuery");a(ge,"FromBody");a(k,"addParamMetadata")});var Q={};K(Q,{JwtAuthService:()=>T});function ye(t,e,r,n){var s=arguments.length,o=s<3?e:n===null?n=Object.getOwnPropertyDescriptor(e,r):n,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(t,e,r,n);else for(var c=t.length-1;c>=0;c--)(i=t[c])&&(o=(s<3?i(o):s>3?i(e,r,o):i(e,r))||o);return s>3&&o&&Object.defineProperty(e,r,o),o}function G(t,e){if(typeof Reflect=="object"&&typeof Reflect.metadata=="function")return Reflect.metadata(t,e)}function $(t){return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function X(t){let e=t+"==".slice(2-t.length*3&3);return atob(e.replace(/-/g,"+").replace(/_/g,"/"))}var T,F=w(()=>{"use strict";M();a(ye,"_ts_decorate");a(G,"_ts_metadata");a($,"base64UrlEncode");a(X,"base64UrlDecode");T=class{static{a(this,"JwtAuthService")}secret;expiresIn;constructor(e){this.secret=e.secret,this.expiresIn=e.expiresIn??3600}async getKey(){let e=new TextEncoder;return crypto.subtle.importKey("raw",e.encode(this.secret),{name:"HMAC",hash:"SHA-256"},!1,["sign","verify"])}async sign(e){let r={alg:"HS256",typ:"JWT"},n=Math.floor(Date.now()/1e3),s={...e,iat:n,exp:n+this.expiresIn},o=$(JSON.stringify(r)),i=$(JSON.stringify(s)),c=`${o}.${i}`,l=await this.getKey(),u=new TextEncoder,p=await crypto.subtle.sign("HMAC",l,u.encode(c)),f=$(String.fromCharCode(...new Uint8Array(p)));return`${c}.${f}`}async verify(e){let r=e.split(".");if(r.length!==3)throw new Error("Invalid JWT format");let n=r[0],s=r[1],o=r[2],i=`${n}.${s}`,c=await this.getKey(),l=new TextEncoder,u=Uint8Array.from(X(o),N=>N.charCodeAt(0));if(!await crypto.subtle.verify("HMAC",c,u,l.encode(i)))throw new Error("Invalid JWT signature");let f=JSON.parse(X(s)),x=Math.floor(Date.now()/1e3);if(f.exp!==void 0&&f.exp<x)throw new Error("JWT expired");return f}};T=ye([E(),G("design:type",Function),G("design:paramtypes",[typeof JwtOptions>"u"?Object:JwtOptions])],T)});var Z={};K(Z,{Router:()=>W});async function we(t,e,r){if(!r.required)return null;let n=t.request.headers.get("authorization");if(!n||!n.startsWith("Bearer "))return new Response(JSON.stringify({message:"Unauthorized"}),{status:401,headers:{"Content-Type":"application/json"}});let s=n.slice(7),o;try{let{JwtAuthService:c}=(F(),z(Q));o=e.resolve(c)}catch{return new Response(JSON.stringify({message:"JWT service not configured"}),{status:500,headers:{"Content-Type":"application/json"}})}let i;try{i=await o.verify(s)}catch{return new Response(JSON.stringify({message:"Unauthorized: invalid or expired token"}),{status:401,headers:{"Content-Type":"application/json"}})}if(r.roles&&r.roles.length>0){let c=i.roles??[];if(!r.roles.some(u=>c.includes(u)))return new Response(JSON.stringify({message:"Forbidden: insufficient permissions"}),{status:403,headers:{"Content-Type":"application/json"}})}return t.items.set("user",i),null}var W,V=w(()=>{"use strict";J();L();B();a(we,"checkAuth");W=class{static{a(this,"Router")}routes=[];registerControllers(e){for(let r of e){let n=Reflect.getMetadata(q,r);if(n===void 0)continue;let s=Reflect.getMetadata(R,r)||[];for(let o of s){let i=`/${n}/${o.path}`.replace(/\/+/g,"/");i!=="/"&&i.endsWith("/")&&(i=i.slice(0,-1));let c=new URLPattern({pathname:i});this.routes.push({method:o.method,pattern:c,controller:r,methodName:o.methodName})}}}middleware(){return async(e,r)=>{for(let n of this.routes){if(n.method!==e.method)continue;let s=n.pattern.exec({pathname:e.path});if(s){let o=e.items.get("scope");if(!o)throw new Error("DI Scope not found in HttpContext");let i=Reflect.getMetadata(O,n.controller,n.methodName),c=Reflect.getMetadata(O,n.controller),l=i??c;if(l){let d=await we(e,o,l);if(d)return d}let u=o.resolve(n.controller),p=`${U.toString()}_${n.methodName}`,f=Reflect.getMetadata(p,n.controller)||[],x=u[n.methodName].length,N=new Array(x).fill(void 0),Y=f.some(d=>d.type===y.Body),_;Y&&(_=await e.request.json().catch(()=>({})));let ee=new URL(e.request.url);for(let d of f){let g;if(d.type===y.Route&&d.name?g=s.pathname.groups[d.name]:d.type===y.Query&&d.name?g=ee.searchParams.get(d.name):d.type===y.Body?g=_:d.type===y.Context&&(g=e),d.schema){let P=d.schema.safeParse(g);if(!P.success)return A.unprocessableEntity("Validation failed",{errors:P.error.errors,target:y[d.type].toLowerCase(),name:d.name}).toResponse();g=P.data}N[d.index]=g}let m=await u[n.methodName](...N);return m instanceof Response?m:m instanceof A?m.toResponse():typeof m=="object"?Response.json(m):new Response(String(m))}}return r()}}}});M();import"reflect-metadata";var h=(function(t){return t[t.Singleton=0]="Singleton",t[t.Transient=1]="Transient",t[t.Scoped=2]="Scoped",t})({});var S=class t{static{a(this,"ServiceProvider")}descriptors;parent;singletonInstances=new Map;scopedInstances=new Map;constructor(e,r){this.descriptors=e,this.parent=r}createScope(){return new t(this.descriptors,this.parent||this)}resolve(e){let r=this.descriptors.find(n=>n.token===e);if(!r){if(this.parent)return this.parent.resolve(e);throw new Error(`Service not registered for token: ${e.toString()}`)}switch(r.lifetime){case h.Singleton:return this.resolveSingleton(r);case h.Scoped:return this.resolveScoped(r);case h.Transient:return this.resolveTransient(r)}}resolveSingleton(e){let r=this.parent||this;if(r.singletonInstances.has(e.token))return r.singletonInstances.get(e.token);let n=this.createInstance(e);return r.singletonInstances.set(e.token,n),n}resolveScoped(e){if(this.parent,this.scopedInstances.has(e.token))return this.scopedInstances.get(e.token);let r=this.createInstance(e);return this.scopedInstances.set(e.token,r),r}resolveTransient(e){return this.createInstance(e)}createInstance(e){if(e.implementationInstance!==void 0)return e.implementationInstance;if(e.implementationFactory)return e.implementationFactory(this);if(e.implementationType)return this.instantiateClass(e.implementationType);throw new Error(`Invalid service descriptor for token: ${e.token.toString()}`)}instantiateClass(e){let r=Reflect.getMetadata("design:paramtypes",e)||[],n=Reflect.getMetadata(D,e)||[],s=r.map((o,i)=>{let c=n.find(u=>u.index===i),l=c?c.token:o;if(!l||l===Object||l===String||l===Number||l===Boolean)throw new Error(`Cannot resolve parameter at index ${i} for ${e.name}. Token could not be determined or is primitive. Cannot inject primitive types directly without @Inject().`);return this.resolve(l)});return new e(...s)}};var v=class{static{a(this,"ServiceCollection")}descriptors=[];add(e){return this.descriptors.push(e),this}addSingleton(e,r){return this.add({token:e,implementationType:r||e,lifetime:h.Singleton})}addSingletonInstance(e,r){return this.add({token:e,implementationInstance:r,lifetime:h.Singleton})}addTransient(e,r){return this.add({token:e,implementationType:r||e,lifetime:h.Transient})}addScoped(e,r){return this.add({token:e,implementationType:r||e,lifetime:h.Scoped})}buildServiceProvider(){return new S(this.descriptors)}addControllers(e){return e.forEach(r=>this.addTransient(r)),this}};var C=class{static{a(this,"HttpContext")}request;items=new Map;constructor(e){this.request=e}get method(){return this.request.method}get url(){return this.request.url}get path(){return new URL(this.request.url).pathname}};var b=class{static{a(this,"WebApplicationBuilder")}services;constructor(){this.services=new v}build(){let e=this.services.buildServiceProvider();return new I(e)}};var I=class{static{a(this,"WebApplication")}services;middlewares=[];controllersToMap=[];constructor(e){this.services=e}static createBuilder(){return new b}use(e){return this.middlewares.push(e),this}mapControllers(e){return this.controllersToMap.push(...e),this}async executePipeline(e){let r=-1,n=a(async o=>{if(o<=r)throw new Error("next() called multiple times");r=o;let i=this.middlewares[o];if(o===this.middlewares.length)return new Response(JSON.stringify({message:"Not found"}),{status:404});if(i)return i(e,n.bind(null,o+1))},"dispatch");return await n(0)||new Response(JSON.stringify({message:"Internal Server Error"}),{status:500})}run(e=3e3){let r=this;if(this.controllersToMap.length>0){let{Router:n}=(V(),z(Z)),s=new n;s.registerControllers(this.controllersToMap),this.use(s.middleware())}Bun.serve({port:e,async fetch(n){let s=r.services.createScope(),o=new C(n);return o.items.set("scope",s),r.executePipeline(o)}}),console.log(`\u{1F680} Steampunk application is running on http://localhost:${e}`)}};L();M();B();J();F();function Ae(t={}){return async(e,r)=>{let{request:n}=e,s=n.headers.get("origin"),o=await r();o||(o=new Response);let i=new Response(o.body,o);if(t.origin?typeof t.origin=="string"?i.headers.set("Access-Control-Allow-Origin",t.origin):Array.isArray(t.origin)&&s?t.origin.includes(s)&&i.headers.set("Access-Control-Allow-Origin",s):typeof t.origin=="function"&&s&&t.origin(s)&&i.headers.set("Access-Control-Allow-Origin",s):i.headers.set("Access-Control-Allow-Origin","*"),t.methods){let c=Array.isArray(t.methods)?t.methods.join(", "):t.methods;i.headers.set("Access-Control-Allow-Methods",c)}else i.headers.set("Access-Control-Allow-Methods","GET,HEAD,PUT,PATCH,POST,DELETE");if(t.allowedHeaders){let c=Array.isArray(t.allowedHeaders)?t.allowedHeaders.join(", "):t.allowedHeaders;i.headers.set("Access-Control-Allow-Headers",c)}else{let c=n.headers.get("access-control-request-headers");c&&i.headers.set("Access-Control-Allow-Headers",c)}if(t.exposedHeaders){let c=Array.isArray(t.exposedHeaders)?t.exposedHeaders.join(", "):t.exposedHeaders;i.headers.set("Access-Control-Expose-Headers",c)}return t.credentials&&i.headers.set("Access-Control-Allow-Credentials","true"),t.maxAge!==void 0&&i.headers.set("Access-Control-Max-Age",t.maxAge.toString()),n.method==="OPTIONS"?new Response(null,{headers:i.headers,status:204}):i}}a(Ae,"cors");function Re(t){let e=a(s=>{let o=s.request?.headers?.get("x-forwarded-for");return o?o.split(",")[0].trim():"global"},"defaultKeyGenerator"),r=t.keyGenerator||e,n=new Map;return async(s,o)=>{let i=r(s),c=Date.now(),l=n.get(i);if(l?c>l.resetTime?(l.count=1,l.resetTime=c+t.windowMs):l.count++:(l={count:1,resetTime:c+t.windowMs},n.set(i,l)),Math.random()<.05)for(let[f,x]of n.entries())Date.now()>x.resetTime&&n.delete(f);if(l.count>t.limit){let f=Math.ceil((l.resetTime-c)/1e3);return new Response("Too Many Requests",{status:429,headers:{"Retry-After":f.toString(),"X-RateLimit-Limit":t.limit.toString(),"X-RateLimit-Remaining":"0","X-RateLimit-Reset":Math.ceil(l.resetTime/1e3).toString()}})}let u=await o();u||(u=new Response);let p=new Response(u.body,u);return p.headers.set("X-RateLimit-Limit",t.limit.toString()),p.headers.set("X-RateLimit-Remaining",Math.max(0,t.limit-l.count).toString()),p.headers.set("X-RateLimit-Reset",Math.ceil(l.resetTime/1e3).toString()),p}}a(Re,"throttle");export{ae as Authorize,ce as Controller,fe as Delete,ge as FromBody,me as FromQuery,he as FromRoute,le as Get,C as HttpContext,A as HttpResult,ie as Inject,E as Injectable,T as JwtAuthService,pe as Patch,de as Post,ue as Put,v as ServiceCollection,S as ServiceProvider,I as WebApplication,b as WebApplicationBuilder,Ae as cors,Re as throttle};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danielgl/steampunk",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "type": "module",
5
5
  "description": "A high-performance, DX-focused web framework for Bun, inspired by ASP.NET Core.",
6
6
  "main": "./dist/main.cjs",
@@ -59,6 +59,7 @@
59
59
  "typescript": "^5"
60
60
  },
61
61
  "dependencies": {
62
- "reflect-metadata": "^0.2.2"
62
+ "reflect-metadata": "^0.2.2",
63
+ "zod": "^4.3.6"
63
64
  }
64
65
  }