@cleverbrush/server 3.1.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -0
- package/dist/Endpoint.d.ts +8 -0
- package/dist/Server.d.ts +2 -0
- package/dist/chunk-RQOGR2EW.js +2 -0
- package/dist/chunk-RQOGR2EW.js.map +1 -0
- package/dist/contract.d.ts +104 -0
- package/dist/contract.js +1 -1
- package/dist/contract.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/dist/chunk-W3HQGZZH.js +0 -2
- package/dist/chunk-W3HQGZZH.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as me,b as oe,c as ge,d as ye,e as be,f as Se,g as Re,h as ve}from"./chunk-W3HQGZZH.js";var P=class{static ok(e,t){return new v(e,200,t)}static created(e,t,r){let n={...r};return t&&(n.location=t),new v(e,201,n)}static accepted(e,t){return new v(e,202,t)}static noContent(){return new D}static badRequest(e,t){return new v(e,400,t)}static unauthorized(e,t){return new v(e,401,t)}static forbidden(e,t){return new v(e,403,t)}static notFound(e,t){return new v(e,404,t)}static conflict(e,t){return new v(e,409,t)}static redirect(e,t=!1){return new _(e,t)}static json(e,t=200,r){return new v(e,t,r)}static file(e,t,r="application/octet-stream"){return new j(e,t,r)}static content(e,t,r=200){return new q(e,t,r)}static stream(e,t,r){return new H(e,t,r)}static status(e,t){return new O(e,t)}},v=class extends P{body;status;headers;constructor(e,t=200,r){super(),this.body=e,this.status=t,this.headers=r??{}}async executeAsync(e,t,r){for(let[n,o]of Object.entries(this.headers))t.setHeader(n,o);if(this.body===null||this.body===void 0){t.writeHead(this.status),t.end();return}t.writeHead(this.status,{"content-type":"application/json"}),t.end(JSON.stringify(this.body))}},j=class extends P{content;fileName;contentType;constructor(e,t,r="application/octet-stream"){super(),this.content=e,this.fileName=t,this.contentType=r}async executeAsync(e,t,r){t.writeHead(200,{"content-type":this.contentType,"content-disposition":`attachment; filename="${this.fileName}"`,"content-length":String(this.content.byteLength)}),t.end(this.content)}},q=class extends P{body;contentType;status;constructor(e,t,r=200){super(),this.body=e,this.contentType=t,this.status=r}async executeAsync(e,t,r){t.writeHead(this.status,{"content-type":this.contentType}),t.end(this.body)}},H=class extends P{readable;contentType;fileName;constructor(e,t,r){super(),this.readable=e,this.contentType=t,this.fileName=r}async executeAsync(e,t,r){let n={"content-type":this.contentType};this.fileName&&(n["content-disposition"]=`attachment; filename="${this.fileName}"`),t.writeHead(200,n),await new Promise((o,i)=>{this.readable.on("error",i),t.on("error",i),this.readable.on("end",o),this.readable.pipe(t,{end:!0})})}},O=class extends P{status;headers;constructor(e,t){super(),this.status=e,this.headers=t??{}}async executeAsync(e,t,r){t.writeHead(this.status,this.headers),t.end()}},_=class extends P{url;permanent;constructor(e,t=!1){super(),this.url=e,this.permanent=t}async executeAsync(e,t,r){t.writeHead(this.permanent?301:302,{location:this.url}),t.end()}},D=class extends P{async executeAsync(e,t,r){t.writeHead(204),t.end()}};var we={400:"Bad Request",401:"Unauthorized",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",409:"Conflict",415:"Unsupported Media Type",422:"Unprocessable Content",500:"Internal Server Error",503:"Service Unavailable"};function g(s,e,t,r){return{type:`https://httpstatuses.com/${s}`,status:s,title:e??we[s]??"Error",...t!==void 0?{detail:t}:{},...r}}function X(s){return g(400,"Bad Request","One or more validation errors occurred.",{errors:s})}function S(s){return JSON.stringify(s)}var R="application/problem+json";var w=class extends Error{status;title;detail;extensions;constructor(e,t,r,n){super(r??t??`HTTP ${e}`),this.name="HttpError",this.status=e,this.title=t??`HTTP ${e}`,this.detail=r,this.extensions=n}toProblemDetails(){return g(this.status,this.title,this.detail,this.extensions)}},Y=class extends w{constructor(e){super(404,"Not Found",e),this.name="NotFoundError"}},Z=class extends w{constructor(e){super(400,"Bad Request",e),this.name="BadRequestError"}},G=class extends w{constructor(e){super(401,"Unauthorized",e),this.name="UnauthorizedError"}},Q=class extends w{constructor(e){super(403,"Forbidden",e),this.name="ForbiddenError"}},K=class extends w{constructor(e){super(409,"Conflict",e),this.name="ConflictError"}};import{URL as Pe}from"url";import{any as te,boolean as Te,func as se,object as xe,promise as ie,record as re,string as C}from"@cleverbrush/schema";function T(s){return JSON.parse(s,(e,t)=>{if(!(e==="__proto__"||e==="constructor"))return t})}function x(s,e=64){ee(s,0,e)}function ee(s,e,t){if(!(s===null||typeof s!="object")){if(e>=t)throw new Error(`JSON nesting depth exceeds maximum of ${t}`);if(Array.isArray(s))for(let r of s)ee(r,e+1,t);else for(let r of Object.values(s))ee(r,e+1,t)}}var Ce=xe({method:C(),url:C(),pathParams:re(C(),C()),queryParams:re(C(),C()),headers:re(C(),C()),items:te(),body:se().hasReturnType(ie(te())),json:se().hasReturnType(ie(te())),responded:Te()}),E=5*1024*1024,k=class{request;response;url;method;headers;items=new Map;maxBodySize;#e={};_queryParams;#t;#r=null;#i=!1;#o=void 0;#d=!1;responded=!1;principal=void 0;constructor(e,t,r){this.request=e,this.response=t,this.method=(e.method??"GET").toUpperCase(),this.maxBodySize=r??E;let n=e.url??"/";this.url=new Pe(n,`http://${e.headers.host??"localhost"}`);let o={};for(let[i,c]of Object.entries(e.headers))typeof c=="string"?o[i]=c:Array.isArray(c)&&(o[i]=c.join(", "));this.headers=o}get pathParams(){return this.#e}set pathParams(e){this.#e=e}get queryParams(){if(this._queryParams)return this._queryParams;let e={};for(let[t,r]of this.url.searchParams)e[t]=r;return e}get services(){return this.#t}set services(e){this.#t=e}async body(){return this.#i?this.#r:(this.#r=await new Promise((e,t)=>{let r=[],n=0;this.request.on("data",o=>{if(n+=o.length,n>this.maxBodySize){this.request.destroy(),t(new w(413,"Payload Too Large"));return}r.push(o)}),this.request.on("end",()=>e(Buffer.concat(r))),this.request.on("error",t)}),this.#i=!0,this.#r)}async json(){if(this.#d)return this.#o;let t=(await this.body()).toString("utf-8");return t.length>0&&(this.#o=T(t),x(this.#o)),this.#d=!0,this.#o}};import*as $ from"http";import*as fe from"https";import{AuthorizationService as Me,PolicyBuilder as Ne,Principal as U,parseCookies as je,requireRole as qe}from"@cleverbrush/auth";import{ServiceCollection as He}from"@cleverbrush/di";import{WebSocketServer as Oe}from"ws";var Ae={mimeType:"application/json",serialize(s){return JSON.stringify(s)},deserialize(s){let e=T(s);return x(e),e}};function ke(s){return s.split(",").map(e=>{let t=e.trim(),[r,...n]=t.split(";").map(i=>i.trim()),o=1;for(let i of n){let[c,d]=i.split("=");c?.trim()==="q"&&d&&(o=parseFloat(d),Number.isNaN(o)&&(o=1))}return{mimeType:r.toLowerCase(),quality:o}}).sort((e,t)=>t.quality-e.quality)}var I=class{#e=new Map;constructor(){this.register(Ae)}register(e){this.#e.set(e.mimeType.toLowerCase(),e)}selectResponseHandler(e){if(!e)return this.#e.get("application/json")??null;let t=ke(e);for(let{mimeType:r}of t){if(r==="*/*")return this.#e.get("application/json")??null;let n=this.#e.get(r);if(n)return n}return null}selectRequestHandler(e){if(!e)return null;let t=e.split(";")[0].trim().toLowerCase();return this.#e.get(t)??null}};var M=class{#e=[];add(e){this.#e.push(e)}async execute(e,t){let r=0,n=async()=>{if(r<this.#e.length){let o=this.#e[r++];await o(e,n)}else await t()};await n()}};function ae(s){return s.bodySchema!=null}async function de(s,e,t,r){let n=[],o={};if(o.context=t,s.authRoles!==null&&t.principal!==void 0&&(o.principal=t.principal),e&&Object.keys(e).length>0&&(o.params=e),s.bodySchema){let i=await s.bodySchema.validateAsync(r,{doNotStopOnFirstError:!0});if(i.valid)o.body=i.object;else{let c=typeof i.getInvalidProperties=="function"?i.getInvalidProperties:null,d=!1;if(c)for(let a of c()){let l=a.descriptor.toJsonPointer();for(let h of a.errors)n.push({pointer:`/body${l}`,detail:h}),d=!0}if(!d)for(let a of i.errors??[])n.push({pointer:"/body",detail:a.message})}}if(s.querySchema){let i=s.querySchema.introspect();if(i.type!=="object"||!i.properties)throw new Error("Endpoint query schema must be an object schema whose properties map to query parameter names.");let c=i.properties,d={};for(let[a,l]of Object.entries(c)){let h=t.queryParams[a],u=await l.validateAsync(h,{doNotStopOnFirstError:!0});if(u.valid)d[a]=u.object;else for(let y of u.errors??[])n.push({pointer:`/query/${a}`,detail:y.message})}o.query=d}if(s.headerSchema){let i=s.headerSchema.introspect();if(i.type!=="object"||!i.properties)throw new Error("Endpoint headers schema must be an object schema whose properties map to header names.");let c=i.properties,d={};for(let[a,l]of Object.entries(c)){let h=t.headers[a.toLowerCase()],u=await l.validateAsync(h,{doNotStopOnFirstError:!0});if(u.valid)d[a]=u.object;else for(let y of u.errors??[])n.push({pointer:`/headers/${a}`,detail:y.message})}o.headers=d}if(n.length>0)return{valid:!1,problemDetails:X(n)};if(s.serviceSchemas){if(!t.services)throw new Error("Endpoint declares .inject() dependencies but no service provider is available. Register services via createServer().services() before handling this endpoint.");let i={};for(let[c,d]of Object.entries(s.serviceSchemas))i[c]=t.services.get(d);return{valid:!0,args:[o,i]}}return{valid:!0,args:[o]}}function B(s){let e=decodeURI(s);return e.length>1&&e.endsWith("/")?e.slice(0,-1):e}function ce(s){return typeof s!="string"&&typeof s.validate=="function"}var J=class{#e=new Map;#t=[];addRoute(e){let{method:t,basePath:r,pathTemplate:n}=e.endpoint,o=t.toUpperCase(),c={basePath:B(r),routePath:n,registration:e};this.#e.has(o)||this.#e.set(o,[]),this.#e.get(o).push(c)}match(e,t){let r;try{r=B(t)}catch{return{match:null,methodNotAllowed:!1,badRequest:!0}}let n=e.toUpperCase(),o=this.#e.get(n);if(o)for(let c of o){let d=this.#r(c,r);if(d)return{match:d,methodNotAllowed:!1}}let i=[];for(let[c,d]of this.#e)if(c!==n){for(let a of d)if(this.#r(a,r)){i.push(c);break}}return i.length>0?{match:null,methodNotAllowed:!0,allowedMethods:i}:{match:null,methodNotAllowed:!1}}#r(e,t){let{basePath:r,routePath:n}=e;if(r&&!t.startsWith(r))return null;let o=r?t.slice(r.length):t;if(ce(n)){let d=n.validate(o);return d.valid?{registration:e.registration,parsedPath:d.object}:null}let i=B(n);return(o.length===0?"/":o)===i?{registration:e.registration,parsedPath:null}:null}addSubscriptionRoute(e){let{basePath:t,pathTemplate:r}=e.endpoint,n=B(t);this.#t.push({basePath:n,routePath:r,registration:e})}matchSubscription(e){let t;try{t=B(e)}catch{return null}for(let r of this.#t){let{basePath:n,routePath:o}=r;if(n&&!t.startsWith(n))continue;let i=n?t.slice(n.length):t;if(ce(o)){let a=o.validate(i);if(a.valid)return{registration:r.registration,parsedPath:a.object};continue}let c=B(o);if((i.length===0?"/":i)===c)return{registration:r.registration,parsedPath:null}}return null}};import{Readable as Be,Writable as Ee}from"stream";var F=class extends Be{method;url;headers;socket=null;#e;#t=!1;constructor(e){super(),this.method=e.method,this.url=e.url;let t={};for(let[r,n]of Object.entries(e.headers??{}))t[r.toLowerCase()]=n;this.headers={host:"localhost",...t},this.#e=e.body!=null&&e.body.length>0?Buffer.from(e.body,"utf-8"):Buffer.alloc(0)}_read(){this.#t||(this.#t=!0,this.#e.length>0&&this.push(this.#e),this.push(null))}},z=class extends Ee{statusCode=200;headersSent=!1;#e=[];#t={};#r=200;_write(e,t,r){this.#e.push(Buffer.isBuffer(e)?e:Buffer.from(e)),r()}writeHead(e,t){if(this.#r=e,this.statusCode=e,t!=null&&typeof t=="object"&&!Array.isArray(t))for(let[r,n]of Object.entries(t))this.#t[r.toLowerCase()]=Array.isArray(n)?n.join(", "):String(n);return this.headersSent=!0,this}setHeader(e,t){return this.#t[e.toLowerCase()]=Array.isArray(t)?t.join(", "):String(t),this}getHeader(e){return this.#t[e.toLowerCase()]}end(e,...t){if(e!=null&&typeof e!="function"){let r=Buffer.isBuffer(e)||e instanceof Uint8Array?Buffer.from(e):Buffer.from(String(e),"utf-8");this.#e.push(r),super.end(...t)}else typeof e=="function"?super.end(e):super.end(...t);return this}toResult(){return{status:this.#r,headers:{...this.#t},body:Buffer.concat(this.#e).toString("utf-8")}}};function le(s){return{type:"message",data:s}}function ue(s,e){return{type:"tracked",id:s,data:e}}function pe(){return{type:"pong"}}function A(s,e){return{type:"error",code:s,message:e}}function he(s){let e;try{e=T(s),x(e)}catch{return null}if(typeof e!="object"||e===null)return null;let t=e;return t.type==="ping"?{type:"ping"}:t.type==="message"&&"data"in t?{type:"message",data:t.data}:null}var L=class{#e=new He;#t=[];#r=[];#i=[];#o=[];#d=new I;#a={};#s=null;#n=null;#c=!1;#l=null;services(e){return e(this.#e),this}use(e){return this.#o.push(e),this}contentType(e){return this.#d.register(e),this}useAuthentication(e){return this.#s=e,this}useAuthorization(e){return this.#n=e??{},this}withHealthcheck(){return this.#c=!0,this}useBatching(e={}){return this.#l=e,this}handle(e,t,r){return this.#t.push({endpoint:e.introspect(),handler:t,middlewares:r?.middlewares}),this}handleAll(e){for(let t of e._entries)this.#t.push({endpoint:t.endpoint.introspect(),handler:t.handler,middlewares:t.middlewares});for(let t of e._subscriptions)this.#r.push({endpoint:t.endpoint.introspect(),handler:t.handler,middlewares:t.middlewares});return this}getRegistrations(){return[...this.#t]}getSubscriptionRegistrations(){return[...this.#r]}webhook(e){return this.#i.push(e),this}getWebhooks(){return[...this.#i]}getAuthenticationConfig(){return this.#s}async listen(e,t){let r=new J;for(let l of this.#t)r.addRoute(l);for(let l of this.#r)r.addSubscriptionRoute(l);let n=this.#e.buildServiceProvider({validateScopes:!1}),o=[];if(this.#s&&o.push(Je(this.#s)),this.#n!==null){let l=new Map;if(this.#n.policies)for(let[u,y]of Object.entries(this.#n.policies)){let p=new Ne;y(p),l.set(u,p.build(u))}let h=new Me(l);o.push(Fe(h,this.#s))}let i=[...o,...this.#o],c=new W(r,n,this.#d,i,this.#c,this.#r.length>0,this.#l,this.#a.maxBodySize),d=e??this.#a.port??3e3,a=t??this.#a.host??"0.0.0.0";return await c.start(d,a,this.#a),c}},_e=1024,W=class{#e;#t;#r;#i;#o;#d;#a;#s;#n=null;#c=null;#l=new Set;constructor(e,t,r,n,o=!1,i=!1,c=null,d=E){this.#e=e,this.#t=t,this.#r=r,this.#i=n,this.#o=o,this.#d=i,this.#a=c,this.#s=d}async start(e,t,r){let n=(o,i)=>{this.#u(o,i).catch(c=>{i.headersSent||(i.writeHead(500,{"content-type":R}),i.end(S(g(500))))})};r.https?this.#n=fe.createServer({key:r.https.key,cert:r.https.cert},n):this.#n=$.createServer(n),await new Promise(o=>{this.#n.listen(e,t,o)}),this.#d&&(this.#c=new Oe({noServer:!0,maxPayload:this.#s}),this.#n.on("upgrade",(o,i,c)=>{let d=new URL(o.url??"/",`http://${o.headers.host??"localhost"}`).pathname,a=this.#e.matchSubscription(d);if(!a){i.write(`HTTP/1.1 404 Not Found\r
|
|
1
|
+
import{a as me,b as oe,c as ge,d as ye,e as be,f as Se,g as Re,h as ve,i as we,j as Pe,k as xe,l as Te}from"./chunk-RQOGR2EW.js";var P=class{static ok(e,t){return new v(e,200,t)}static created(e,t,r){let n={...r};return t&&(n.location=t),new v(e,201,n)}static accepted(e,t){return new v(e,202,t)}static noContent(){return new D}static badRequest(e,t){return new v(e,400,t)}static unauthorized(e,t){return new v(e,401,t)}static forbidden(e,t){return new v(e,403,t)}static notFound(e,t){return new v(e,404,t)}static conflict(e,t){return new v(e,409,t)}static redirect(e,t=!1){return new _(e,t)}static json(e,t=200,r){return new v(e,t,r)}static file(e,t,r="application/octet-stream"){return new j(e,t,r)}static content(e,t,r=200){return new q(e,t,r)}static stream(e,t,r){return new H(e,t,r)}static status(e,t){return new O(e,t)}},v=class extends P{body;status;headers;constructor(e,t=200,r){super(),this.body=e,this.status=t,this.headers=r??{}}async executeAsync(e,t,r){for(let[n,o]of Object.entries(this.headers))t.setHeader(n,o);if(this.body===null||this.body===void 0){t.writeHead(this.status),t.end();return}t.writeHead(this.status,{"content-type":"application/json"}),t.end(JSON.stringify(this.body))}},j=class extends P{content;fileName;contentType;constructor(e,t,r="application/octet-stream"){super(),this.content=e,this.fileName=t,this.contentType=r}async executeAsync(e,t,r){t.writeHead(200,{"content-type":this.contentType,"content-disposition":`attachment; filename="${this.fileName}"`,"content-length":String(this.content.byteLength)}),t.end(this.content)}},q=class extends P{body;contentType;status;constructor(e,t,r=200){super(),this.body=e,this.contentType=t,this.status=r}async executeAsync(e,t,r){t.writeHead(this.status,{"content-type":this.contentType}),t.end(this.body)}},H=class extends P{readable;contentType;fileName;constructor(e,t,r){super(),this.readable=e,this.contentType=t,this.fileName=r}async executeAsync(e,t,r){let n={"content-type":this.contentType};this.fileName&&(n["content-disposition"]=`attachment; filename="${this.fileName}"`),t.writeHead(200,n),await new Promise((o,i)=>{this.readable.on("error",i),t.on("error",i),this.readable.on("end",o),this.readable.pipe(t,{end:!0})})}},O=class extends P{status;headers;constructor(e,t){super(),this.status=e,this.headers=t??{}}async executeAsync(e,t,r){t.writeHead(this.status,this.headers),t.end()}},_=class extends P{url;permanent;constructor(e,t=!1){super(),this.url=e,this.permanent=t}async executeAsync(e,t,r){t.writeHead(this.permanent?301:302,{location:this.url}),t.end()}},D=class extends P{async executeAsync(e,t,r){t.writeHead(204),t.end()}};var Ce={400:"Bad Request",401:"Unauthorized",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",409:"Conflict",415:"Unsupported Media Type",422:"Unprocessable Content",500:"Internal Server Error",503:"Service Unavailable"};function g(s,e,t,r){return{type:`https://httpstatuses.com/${s}`,status:s,title:e??Ce[s]??"Error",...t!==void 0?{detail:t}:{},...r}}function G(s){return g(400,"Bad Request","One or more validation errors occurred.",{errors:s})}function S(s){return JSON.stringify(s)}var R="application/problem+json";var w=class extends Error{status;title;detail;extensions;constructor(e,t,r,n){super(r??t??`HTTP ${e}`),this.name="HttpError",this.status=e,this.title=t??`HTTP ${e}`,this.detail=r,this.extensions=n}toProblemDetails(){return g(this.status,this.title,this.detail,this.extensions)}},X=class extends w{constructor(e){super(404,"Not Found",e),this.name="NotFoundError"}},Y=class extends w{constructor(e){super(400,"Bad Request",e),this.name="BadRequestError"}},Z=class extends w{constructor(e){super(401,"Unauthorized",e),this.name="UnauthorizedError"}},Q=class extends w{constructor(e){super(403,"Forbidden",e),this.name="ForbiddenError"}},K=class extends w{constructor(e){super(409,"Conflict",e),this.name="ConflictError"}};import{URL as Ae}from"url";import{any as te,boolean as ke,func as se,object as Be,promise as ie,record as re,string as C}from"@cleverbrush/schema";function x(s){return JSON.parse(s,(e,t)=>{if(!(e==="__proto__"||e==="constructor"))return t})}function T(s,e=64){ee(s,0,e)}function ee(s,e,t){if(!(s===null||typeof s!="object")){if(e>=t)throw new Error(`JSON nesting depth exceeds maximum of ${t}`);if(Array.isArray(s))for(let r of s)ee(r,e+1,t);else for(let r of Object.values(s))ee(r,e+1,t)}}var Me=Be({method:C(),url:C(),pathParams:re(C(),C()),queryParams:re(C(),C()),headers:re(C(),C()),items:te(),body:se().hasReturnType(ie(te())),json:se().hasReturnType(ie(te())),responded:ke()}),M=5*1024*1024,k=class{request;response;url;method;headers;items=new Map;maxBodySize;#e={};_queryParams;#t;#r=null;#i=!1;#o=void 0;#d=!1;responded=!1;principal=void 0;constructor(e,t,r){this.request=e,this.response=t,this.method=(e.method??"GET").toUpperCase(),this.maxBodySize=r??M;let n=e.url??"/";this.url=new Ae(n,`http://${e.headers.host??"localhost"}`);let o={};for(let[i,c]of Object.entries(e.headers))typeof c=="string"?o[i]=c:Array.isArray(c)&&(o[i]=c.join(", "));this.headers=o}get pathParams(){return this.#e}set pathParams(e){this.#e=e}get queryParams(){if(this._queryParams)return this._queryParams;let e={};for(let[t,r]of this.url.searchParams)e[t]=r;return e}get services(){return this.#t}set services(e){this.#t=e}async body(){return this.#i?this.#r:(this.#r=await new Promise((e,t)=>{let r=[],n=0;this.request.on("data",o=>{if(n+=o.length,n>this.maxBodySize){this.request.destroy(),t(new w(413,"Payload Too Large"));return}r.push(o)}),this.request.on("end",()=>e(Buffer.concat(r))),this.request.on("error",t)}),this.#i=!0,this.#r)}async json(){if(this.#d)return this.#o;let t=(await this.body()).toString("utf-8");return t.length>0&&(this.#o=x(t),T(this.#o)),this.#d=!0,this.#o}};import*as $ from"http";import*as fe from"https";import{AuthorizationService as He,PolicyBuilder as Oe,Principal as U,parseCookies as _e,requireRole as De}from"@cleverbrush/auth";import{ServiceCollection as Ie}from"@cleverbrush/di";import{WebSocketServer as Je}from"ws";var Ee={mimeType:"application/json",serialize(s){return JSON.stringify(s)},deserialize(s){let e=x(s);return T(e),e}};function Ne(s){return s.split(",").map(e=>{let t=e.trim(),[r,...n]=t.split(";").map(i=>i.trim()),o=1;for(let i of n){let[c,d]=i.split("=");c?.trim()==="q"&&d&&(o=parseFloat(d),Number.isNaN(o)&&(o=1))}return{mimeType:r.toLowerCase(),quality:o}}).sort((e,t)=>t.quality-e.quality)}var I=class{#e=new Map;constructor(){this.register(Ee)}register(e){this.#e.set(e.mimeType.toLowerCase(),e)}selectResponseHandler(e){if(!e)return this.#e.get("application/json")??null;let t=Ne(e);for(let{mimeType:r}of t){if(r==="*/*")return this.#e.get("application/json")??null;let n=this.#e.get(r);if(n)return n}return null}selectRequestHandler(e){if(!e)return null;let t=e.split(";")[0].trim().toLowerCase();return this.#e.get(t)??null}};var E=class{#e=[];add(e){this.#e.push(e)}async execute(e,t){let r=0,n=async()=>{if(r<this.#e.length){let o=this.#e[r++];await o(e,n)}else await t()};await n()}};function ae(s){return s.bodySchema!=null}async function de(s,e,t,r){let n=[],o={};if(o.context=t,s.authRoles!==null&&t.principal!==void 0&&(o.principal=t.principal),e&&Object.keys(e).length>0&&(o.params=e),s.bodySchema){let i=await s.bodySchema.validateAsync(r,{doNotStopOnFirstError:!0});if(i.valid)o.body=i.object;else{let c=typeof i.getInvalidProperties=="function"?i.getInvalidProperties:null,d=!1;if(c)for(let a of c()){let l=a.descriptor.toJsonPointer();for(let h of a.errors)n.push({pointer:`/body${l}`,detail:h}),d=!0}if(!d)for(let a of i.errors??[])n.push({pointer:"/body",detail:a.message})}}if(s.querySchema){let i=s.querySchema.introspect();if(i.type!=="object"||!i.properties)throw new Error("Endpoint query schema must be an object schema whose properties map to query parameter names.");let c=i.properties,d={};for(let[a,l]of Object.entries(c)){let h=t.queryParams[a],u=await l.validateAsync(h,{doNotStopOnFirstError:!0});if(u.valid)d[a]=u.object;else for(let y of u.errors??[])n.push({pointer:`/query/${a}`,detail:y.message})}o.query=d}if(s.headerSchema){let i=s.headerSchema.introspect();if(i.type!=="object"||!i.properties)throw new Error("Endpoint headers schema must be an object schema whose properties map to header names.");let c=i.properties,d={};for(let[a,l]of Object.entries(c)){let h=t.headers[a.toLowerCase()],u=await l.validateAsync(h,{doNotStopOnFirstError:!0});if(u.valid)d[a]=u.object;else for(let y of u.errors??[])n.push({pointer:`/headers/${a}`,detail:y.message})}o.headers=d}if(n.length>0)return{valid:!1,problemDetails:G(n)};if(s.serviceSchemas){if(!t.services)throw new Error("Endpoint declares .inject() dependencies but no service provider is available. Register services via createServer().services() before handling this endpoint.");let i={};for(let[c,d]of Object.entries(s.serviceSchemas))i[c]=t.services.get(d);return{valid:!0,args:[o,i]}}return{valid:!0,args:[o]}}function B(s){let e=decodeURI(s);return e.length>1&&e.endsWith("/")?e.slice(0,-1):e}function ce(s){return typeof s!="string"&&typeof s.validate=="function"}var J=class{#e=new Map;#t=[];addRoute(e){let{method:t,basePath:r,pathTemplate:n}=e.endpoint,o=t.toUpperCase(),c={basePath:B(r),routePath:n,registration:e};this.#e.has(o)||this.#e.set(o,[]),this.#e.get(o).push(c)}match(e,t){let r;try{r=B(t)}catch{return{match:null,methodNotAllowed:!1,badRequest:!0}}let n=e.toUpperCase(),o=this.#e.get(n);if(o)for(let c of o){let d=this.#r(c,r);if(d)return{match:d,methodNotAllowed:!1}}let i=[];for(let[c,d]of this.#e)if(c!==n){for(let a of d)if(this.#r(a,r)){i.push(c);break}}return i.length>0?{match:null,methodNotAllowed:!0,allowedMethods:i}:{match:null,methodNotAllowed:!1}}#r(e,t){let{basePath:r,routePath:n}=e;if(r&&!t.startsWith(r))return null;let o=r?t.slice(r.length):t;if(ce(n)){let d=n.validate(o);return d.valid?{registration:e.registration,parsedPath:d.object}:null}let i=B(n);return(o.length===0?"/":o)===i?{registration:e.registration,parsedPath:null}:null}addSubscriptionRoute(e){let{basePath:t,pathTemplate:r}=e.endpoint,n=B(t);this.#t.push({basePath:n,routePath:r,registration:e})}matchSubscription(e){let t;try{t=B(e)}catch{return null}for(let r of this.#t){let{basePath:n,routePath:o}=r;if(n&&!t.startsWith(n))continue;let i=n?t.slice(n.length):t;if(ce(o)){let a=o.validate(i);if(a.valid)return{registration:r.registration,parsedPath:a.object};continue}let c=B(o);if((i.length===0?"/":i)===c)return{registration:r.registration,parsedPath:null}}return null}};import{Readable as je,Writable as qe}from"stream";var F=class extends je{method;url;headers;socket=null;#e;#t=!1;constructor(e){super(),this.method=e.method,this.url=e.url;let t={};for(let[r,n]of Object.entries(e.headers??{}))t[r.toLowerCase()]=n;this.headers={host:"localhost",...t},this.#e=e.body!=null&&e.body.length>0?Buffer.from(e.body,"utf-8"):Buffer.alloc(0)}_read(){this.#t||(this.#t=!0,this.#e.length>0&&this.push(this.#e),this.push(null))}},z=class extends qe{statusCode=200;headersSent=!1;#e=[];#t={};#r=200;_write(e,t,r){this.#e.push(Buffer.isBuffer(e)?e:Buffer.from(e)),r()}writeHead(e,t){if(this.#r=e,this.statusCode=e,t!=null&&typeof t=="object"&&!Array.isArray(t))for(let[r,n]of Object.entries(t))this.#t[r.toLowerCase()]=Array.isArray(n)?n.join(", "):String(n);return this.headersSent=!0,this}setHeader(e,t){return this.#t[e.toLowerCase()]=Array.isArray(t)?t.join(", "):String(t),this}getHeader(e){return this.#t[e.toLowerCase()]}end(e,...t){if(e!=null&&typeof e!="function"){let r=Buffer.isBuffer(e)||e instanceof Uint8Array?Buffer.from(e):Buffer.from(String(e),"utf-8");this.#e.push(r),super.end(...t)}else typeof e=="function"?super.end(e):super.end(...t);return this}toResult(){return{status:this.#r,headers:{...this.#t},body:Buffer.concat(this.#e).toString("utf-8")}}};function le(s){return{type:"message",data:s}}function ue(s,e){return{type:"tracked",id:s,data:e}}function pe(){return{type:"pong"}}function A(s,e){return{type:"error",code:s,message:e}}function he(s){let e;try{e=x(s),T(e)}catch{return null}if(typeof e!="object"||e===null)return null;let t=e;return t.type==="ping"?{type:"ping"}:t.type==="message"&&"data"in t?{type:"message",data:t.data}:null}var L=class{#e=new Ie;#t=[];#r=[];#i=[];#o=[];#d=new I;#a={};#s=null;#n=null;#c=!1;#l=null;services(e){return e(this.#e),this}use(e){return this.#o.push(e),this}contentType(e){return this.#d.register(e),this}useAuthentication(e){return this.#s=e,this}useAuthorization(e){return this.#n=e??{},this}withHealthcheck(){return this.#c=!0,this}useBatching(e={}){return this.#l=e,this}handle(e,t,r){return this.#t.push({endpoint:e.introspect(),handler:t,middlewares:r?.middlewares}),this}handleAll(e){for(let t of e._entries)this.#t.push({endpoint:t.endpoint.introspect(),handler:t.handler,middlewares:t.middlewares});for(let t of e._subscriptions)this.#r.push({endpoint:t.endpoint.introspect(),handler:t.handler,middlewares:t.middlewares});return this}getRegistrations(){return[...this.#t]}getSubscriptionRegistrations(){return[...this.#r]}webhook(e){return this.#i.push(e),this}getWebhooks(){return[...this.#i]}getAuthenticationConfig(){return this.#s}async listen(e,t){let r=new J;for(let l of this.#t)r.addRoute(l);for(let l of this.#r)r.addSubscriptionRoute(l);let n=this.#e.buildServiceProvider({validateScopes:!1}),o=[];if(this.#s&&o.push(Le(this.#s)),this.#n!==null){let l=new Map;if(this.#n.policies)for(let[u,y]of Object.entries(this.#n.policies)){let p=new Oe;y(p),l.set(u,p.build(u))}let h=new He(l);o.push(We(h,this.#s))}let i=[...o,...this.#o],c=new W(r,n,this.#d,i,this.#c,this.#r.length>0,this.#l,this.#a.maxBodySize),d=e??this.#a.port??3e3,a=t??this.#a.host??"0.0.0.0";return await c.start(d,a,this.#a),c}},Fe=1024,W=class{#e;#t;#r;#i;#o;#d;#a;#s;#n=null;#c=null;#l=new Set;constructor(e,t,r,n,o=!1,i=!1,c=null,d=M){this.#e=e,this.#t=t,this.#r=r,this.#i=n,this.#o=o,this.#d=i,this.#a=c,this.#s=d}async start(e,t,r){let n=(o,i)=>{this.#u(o,i).catch(c=>{i.headersSent||(i.writeHead(500,{"content-type":R}),i.end(S(g(500))))})};r.https?this.#n=fe.createServer({key:r.https.key,cert:r.https.cert},n):this.#n=$.createServer(n),await new Promise(o=>{this.#n.listen(e,t,o)}),this.#d&&(this.#c=new Je({noServer:!0,maxPayload:this.#s}),this.#n.on("upgrade",(o,i,c)=>{let d=new URL(o.url??"/",`http://${o.headers.host??"localhost"}`).pathname,a=this.#e.matchSubscription(d);if(!a){i.write(`HTTP/1.1 404 Not Found\r
|
|
2
2
|
\r
|
|
3
|
-
`),i.destroy();return}this.#c.handleUpgrade(o,i,c,l=>{this.#f(l,o,a.registration,a.parsedPath)})}))}async close(){for(let e of this.#l)e.close(1001,"Server shutting down");this.#l.clear(),this.#c&&(await new Promise((e,t)=>{this.#c.close(r=>{r?t(r):e()})}),this.#c=null),this.#n&&(await new Promise((e,t)=>{this.#n.close(r=>{r?t(r):e()})}),this.#n=null)}get address(){let e=this.#n?.address();return!e||typeof e=="string"?null:{port:e.port,host:e.address}}async#u(e,t){let r=this.#t.createScope();try{let n=new k(e,t,this.#s),o=n.url.pathname,i=n.method;if(this.#o&&i==="GET"&&o==="/health"){t.writeHead(200),t.end();return}if(this.#a!==null&&i==="POST"&&o===(this.#a.path??"/__batch")){await this.#p(e,t);return}let c=this.#e.match(i,o);if(!c.match){if(c.badRequest){let y=g(400);t.writeHead(400,{"content-type":R}),t.end(S(y));return}if(c.methodNotAllowed){let y=g(405,"Method Not Allowed");t.writeHead(405,{"content-type":R,allow:c.allowedMethods.join(", ")}),t.end(S(y));return}let u=g(404);t.writeHead(404,{"content-type":R}),t.end(S(u));return}let{registration:d,parsedPath:a}=c.match,l=d.endpoint;if(a){let u={};ne(a,"",u),n.pathParams=u}n.services=r.serviceProvider,n.items.set("__endpoint_meta",l);let h=new
|
|
3
|
+
`),i.destroy();return}this.#c.handleUpgrade(o,i,c,l=>{this.#f(l,o,a.registration,a.parsedPath)})}))}async close(){for(let e of this.#l)e.close(1001,"Server shutting down");this.#l.clear(),this.#c&&(await new Promise((e,t)=>{this.#c.close(r=>{r?t(r):e()})}),this.#c=null),this.#n&&(await new Promise((e,t)=>{this.#n.close(r=>{r?t(r):e()})}),this.#n=null)}get address(){let e=this.#n?.address();return!e||typeof e=="string"?null:{port:e.port,host:e.address}}async#u(e,t){let r=this.#t.createScope();try{let n=new k(e,t,this.#s),o=n.url.pathname,i=n.method;if(this.#o&&i==="GET"&&o==="/health"){t.writeHead(200),t.end();return}if(this.#a!==null&&i==="POST"&&o===(this.#a.path??"/__batch")){await this.#p(e,t);return}let c=this.#e.match(i,o);if(!c.match){if(c.badRequest){let y=g(400);t.writeHead(400,{"content-type":R}),t.end(S(y));return}if(c.methodNotAllowed){let y=g(405,"Method Not Allowed");t.writeHead(405,{"content-type":R,allow:c.allowedMethods.join(", ")}),t.end(S(y));return}let u=g(404);t.writeHead(404,{"content-type":R}),t.end(S(u));return}let{registration:d,parsedPath:a}=c.match,l=d.endpoint;if(a){let u={};ne(a,"",u),n.pathParams=u}n.services=r.serviceProvider,n.items.set("__endpoint_meta",l);let h=new E;for(let u of this.#i)h.add(u);if(d.middlewares)for(let u of d.middlewares)h.add(u);await h.execute(n,async()=>{if(n.responded)return;let u;if(ae(l)){let f=e.headers["content-type"],m=this.#r.selectRequestHandler(f);if(m){let N=(await n.body()).toString("utf-8");if(N.length>0)try{u=m.deserialize(N)}catch{let V=g(400,"Malformed request body");t.writeHead(400,{"content-type":R}),t.end(S(V)),n.responded=!0;return}}else if(f){let b=g(415);t.writeHead(415,{"content-type":R}),t.end(S(b)),n.responded=!0;return}}let y=await de(l,a,n,u);if(!y.valid){t.writeHead(400,{"content-type":R}),t.end(S(y.problemDetails)),n.responded=!0;return}let p=d.handler(...y.args);p instanceof Promise&&(p=await p),!n.responded&&(await this.#h(e,t,p),n.responded=!0)})}catch(n){if(t.headersSent)return;if(n instanceof w){let o=n.toProblemDetails();t.writeHead(o.status,{"content-type":R}),t.end(S(o))}else{console.error("[server] Unhandled error:",n);let o=g(500);t.writeHead(500,{"content-type":R}),t.end(S(o))}}finally{try{await r.asyncDispose()}catch{}}}async#p(e,t){let r=this.#a,n=r.maxSize??20,o=r.parallel??!0,i;try{let a=await Ue(e,this.#s),l=x(a.toString("utf-8"));if(T(l),i=l,!Array.isArray(i?.requests))throw new Error("requests must be an array")}catch(a){if(a instanceof w&&a.status===413){let h=g(413,"Payload Too Large");t.writeHead(413,{"content-type":R}),t.end(S(h));return}let l=g(400,"Invalid batch request body");t.writeHead(400,{"content-type":R}),t.end(S(l));return}if(i.requests.length>n){let a=g(400,`Batch size ${i.requests.length} exceeds maximum of ${n}`);t.writeHead(400,{"content-type":R}),t.end(S(a));return}let c=async a=>{let l=new F({method:(a.method??"GET").toUpperCase(),url:a.url,headers:a.headers??{},body:a.body}),h=new z;return await this.#u(l,h),h.toResult()},d;if(o)d=await Promise.all(i.requests.map(c));else{d=[];for(let a of i.requests)d.push(await c(a))}t.writeHead(200,{"content-type":"application/json"}),t.end(JSON.stringify({responses:d}))}async#h(e,t,r){r instanceof P?await r.executeAsync(e,t,this.#r):r==null?(t.writeHead(204),t.end()):await new v(r,200).executeAsync(e,t,this.#r)}#f(e,t,r,n){this.#l.add(e);let o=this.#t.createScope(),i=new AbortController,c=r.endpoint,d=new $.ServerResponse(t),a=new k(t,d);if(n){let h={};ne(n,"",h),a.pathParams=h}a.services=o.serviceProvider,a.items.set("__endpoint_meta",c);let l=new E;for(let h of this.#i)l.add(h);if(r.middlewares)for(let h of r.middlewares)l.add(h);l.execute(a,async()=>{if(a.responded){e.close(1008,"Unauthorized");return}this.#m(e,a,c,r.handler,n,o,i)}).catch(()=>{e.close(1011,"Internal Server Error")}),e.on("close",()=>{this.#l.delete(e),i.abort(),o.asyncDispose().catch(()=>{})}),e.on("error",()=>{this.#l.delete(e),i.abort(),o.asyncDispose().catch(()=>{})})}#m(e,t,r,n,o,i,c){let d=[],a=null,l=!1,h={[Symbol.asyncIterator](){return{next(){return d.length>0?Promise.resolve({value:d.shift(),done:!1}):l?Promise.resolve({value:void 0,done:!0}):new Promise(p=>{a=()=>{a=null,d.length>0?p({value:d.shift(),done:!1}):p({value:void 0,done:!0})}})},return(){return l=!0,Promise.resolve({value:void 0,done:!0})}}}};e.on("message",p=>{let f=typeof p=="string"?p:p.toString("utf-8"),m=he(f);if(!m){e.send(JSON.stringify(A(400,"Invalid frame format")));return}if(m.type==="ping"){e.send(JSON.stringify(pe()));return}if(d.length>=Fe){e.send(JSON.stringify(A(429,"Message queue full \u2014 slow down or reconnect"))),e.close(1008,"Message queue overflow");return}if(r.incomingSchema){let b=r.incomingSchema.validate(m.data);if(!b.valid){let N=(b.errors??[]).map(V=>V.message).join("; ");e.send(JSON.stringify(A(422,`Validation failed: ${N}`)));return}d.push(b.object)}else d.push(m.data);a&&a()}),e.on("close",()=>{l=!0,a&&a()});let u={context:t,signal:c.signal};if(o&&Object.keys(o).length>0&&(u.params=o),r.querySchema){let p={};for(let[m,b]of t.url.searchParams.entries())p[m]=b;let f=r.querySchema.validate(p);if(!f.valid){let m=(f.errors??[]).map(b=>b.message).join("; ");e.close(1002,`Query validation failed: ${m}`);return}u.query=f.object}if(r.headerSchema){let p=r.headerSchema.validate(t.headers);if(!p.valid){let f=(p.errors??[]).map(m=>m.message).join("; ");e.close(1002,`Header validation failed: ${f}`);return}u.headers=p.object}t.principal!==void 0&&(u.principal=t.principal),r.incomingSchema,u.incoming=h;let y=[u];if(r.serviceSchemas){let p={};for(let[f,m]of Object.entries(r.serviceSchemas))p[f]=i.serviceProvider.get(m);y.push(p)}(async()=>{try{let p=n(...y);for await(let f of p){if(e.readyState!==e.OPEN)break;let m;if(oe(f)){let b=r.outgoingSchema?r.outgoingSchema.validate(f.data):{valid:!0,object:f.data};if(!b.valid){e.send(JSON.stringify(A(500,"Outgoing validation failed")));continue}m=JSON.stringify(ue(f.id,b.object))}else{let b=r.outgoingSchema?r.outgoingSchema.validate(f):{valid:!0,object:f};if(!b.valid){e.send(JSON.stringify(A(500,"Outgoing validation failed")));continue}m=JSON.stringify(le(b.object))}e.send(m)}}catch(p){e.readyState===e.OPEN&&(p instanceof Error&&console.error("[server] Subscription handler error:",p),e.send(JSON.stringify(A(500,"Internal error"))),e.close(1011,"Handler error"))}})()}};function ze(s){let e=new L;return s&&(e.__options=s),e}function Ue(s,e=M){return new Promise((t,r)=>{let n=[],o=0;s.on("data",i=>{if(o+=i.length,o>e){s.destroy(),r(new w(413,"Payload Too Large"));return}n.push(i)}),s.on("end",()=>t(Buffer.concat(n))),s.on("error",r)})}function ne(s,e,t){for(let[r,n]of Object.entries(s)){let o=e?`${e}.${r}`:r;n!==null&&typeof n=="object"&&!Array.isArray(n)?ne(n,o,t):t[o]=String(n)}}function Le(s){let e=new Map;for(let t of s.schemes)e.set(t.name,t);return async(t,r)=>{let n=e.get(s.defaultScheme);if(!n){t.principal=U.anonymous(),await r();return}let o={headers:t.headers,cookies:_e(t.headers.cookie??""),items:t.items},i=await n.authenticate(o);i.succeeded?t.principal=i.principal:t.principal=U.anonymous(),await r()}}function We(s,e){let t={};if(e){for(let r of e.schemes)if(r.challenge){let n=r.challenge();t[n.headerName.toLowerCase()]=n.headerValue}}return async(r,n)=>{let o=r.items.get("__endpoint_meta");if(!o||o.authRoles===null){await n();return}let i=r.principal;if(!i||!(i instanceof U)||!i.isAuthenticated){let c=g(401,"Unauthorized"),d={"content-type":R,...t};r.response.writeHead(401,d),r.response.end(S(c)),r.responded=!0;return}if(o.authRoles.length>0&&!(await s.authorize(i,[De(...o.authRoles)])).allowed){let d=g(403,"Forbidden");r.response.writeHead(403,{"content-type":R}),r.response.end(S(d)),r.responded=!0;return}i instanceof U&&(r.principal=i.value),await n()}}function $e(s,e){return{name:s,...e}}export{P as ActionResult,Y as BadRequestError,K as ConflictError,q as ContentResult,M as DEFAULT_MAX_BODY_SIZE,be as EndpointBuilder,j as FileResult,Q as ForbiddenError,w as HttpError,Me as IRequestContext,v as JsonResult,D as NoContentResult,X as NotFoundError,_ as RedirectResult,k as RequestContext,W as Server,L as ServerBuilder,O as StatusCodeResult,H as StreamResult,ge as SubscriptionBuilder,Z as UnauthorizedError,Se as createEndpoints,g as createProblemDetails,ze as createServer,G as createValidationProblemDetails,we as defineApi,$e as defineWebhook,Re as endpoint,ye as mapHandlers,Pe as mergeContracts,Te as omitGroups,xe as pickGroups,ve as route,me as tracked};
|
|
4
4
|
//# sourceMappingURL=index.js.map
|