@sx3/ultra 0.3.0 → 0.3.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.
Files changed (2) hide show
  1. package/dist/ultra.mjs +1 -1
  2. package/package.json +1 -1
package/dist/ultra.mjs CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./error-45bzsfk8.mjs";import{t}from"./procedure-DqhXrslI.mjs";import{n,t as r}from"./response-C6th92gD.mjs";import{t as i}from"./rpc-XjW9_Smw.mjs";import{inflateSync as a,serve as o}from"bun";var s=class{initializers=new Map;events=new Map;middlewares=new Set;derived=new Set;derivedUpgrade=new Set;options={http:{enableByDefault:!1}};httpEnabled=!1;server=null;handlers=null;constructor(e){e&&(this.options={...this.options,...e}),this.httpEnabled=this.options.http?.enableByDefault??!1}routes(e,t){let n=this.initializers.get(e);return n?t?.forEach(e=>n.add(e)):this.initializers.set(e,new Set(t)),this}use(e){return typeof e==`function`?(this.middlewares.add(e),this):(this.merge(e),this)}derive(e){return this.derived.add(e),this}deriveUpgrade(e){return this.derivedUpgrade.add(e),this}start(e){if(this.server)throw Error(`Server is already running. Create a new Ultra instance or stop the existing server first.`);let{routes:t,handlers:n}=this.build();this.handlers=n;let r=new TextDecoder,s=this.wrapHandler(()=>new Response(`Not Found`,{status:404}),this.middlewares);return this.server=o({...this.httpEnabled&&{routes:{...t,"/ws":async(e,t)=>{if(this.emit(`http:request`,e,t),!this.derivedUpgrade.size)return t.upgrade(e)?void 0:new Response(`WebSocket upgrade failed`,{status:500});if(!t.upgrade(e,await this.enrichContext({server:t,request:e}).then(e=>this.enrichUpgrade(e))))return new Response(`WebSocket upgrade failed`,{status:500})},"/*":async(e,t)=>(this.emit(`http:request`,e,t),s({input:null,context:await this.enrichContext({server:t,request:e})}))}},websocket:{data:{},open:e=>{this.emit(`ws:open`,e)},close:(e,t,n)=>{this.emit(`ws:close`,e,t,n)},message:async(e,t)=>{this.emit(`ws:message`,e,t);let n=null;try{n=typeof t==`string`?JSON.parse(t):JSON.parse(r.decode(a(t)))}catch(e){console.error(`Message payload parsing failed`,e);return}let o=Array.isArray(n)?n.filter(i):i(n)?[n]:null;if(!o||!o.length)return;let s=await this.enrichContext({server:this.server,ws:e});for(let t of o)this.handleRPC(t,e,s)}},error:e=>(this.emit(`unhandled:error`,e),console.error(`Unhandled server error:`,e),new Response(`Internal server error`,{status:500})),...e}),this.emit(`server:started`,this.server),this.server}async stop(e=!1){if(!this.server)return console.error(`Server is not running`);await this.server.stop(e),this.emit(`server:stopped`,this.server,e),this.server=null,this.handlers=null}on(e,t){return this.events.has(e)||this.events.set(e,new Set),this.events.get(e).add(t),this}off(e,t){return this.events.get(e)?.delete(t),this}emit(e,...t){return this.events.get(e)?.forEach(e=>e(...t)),this}async handleRPC(t,r,i){let a=this.handlers.get(t.method);if(!a){r.send(n(t.id,new e));return}try{r.send(n(t.id,await a({input:t.params,context:i})))}catch(e){this.emit(`error`,e),r.send(n(t.id,e))}}async enrichContext(e){for(let t of this.derived)e={...e,...typeof t==`function`?await t(e):t};return e}async enrichUpgrade(e){let t={data:{},headers:new Headers};for(let n of this.derivedUpgrade){let r=typeof n==`function`?await n(e):n;if(`data`in r&&(t.data={...t.data,...r.data}),`headers`in r)for(let[e,n]of Object.entries(r.headers))t.headers.set(e,n)}return t}merge(e){for(let[t,n]of e.initializers){let e=this.initializers.get(t);e?n.forEach(t=>e.add(t)):this.initializers.set(t,new Set(n))}e.derived.forEach(e=>this.derived.add(e)),e.derivedUpgrade.forEach(e=>this.derivedUpgrade.add(e)),e.middlewares.forEach(e=>this.middlewares.add(e)),e.events.forEach((e,t)=>{this.events.has(t)||this.events.set(t,new Set);let n=this.events.get(t);e.forEach(e=>n.add(e))})}wrapHandler(e,t){if(!t.size)return e;let n=Array.from(t),r=n.length;return async t=>{let i=0,a=()=>i===r?e(t):n[i++]({...t,next:a});return a()}}build(){let e=new Map,n={},i=e=>{let n=new t;return e&&n.input(e),this.options.http?.enableByDefault&&n.http(),n};for(let[a,o]of this.initializers){let s=a(i),c=[];for(let e in s)c.push({path:e,value:s[e]});for(;c.length;){let{path:i,value:a}=c.pop();if(a instanceof t){if(e.has(i))throw Error(`Procedure "${i}" already exists`);let t=a.metadata();!this.httpEnabled&&t.http?.enabled&&(this.httpEnabled=!0);let s=new Set([...this.middlewares,...o,...t.middlewares]),c=this.wrapHandler(a.compile(),s);if(e.set(i,c),!t.http?.enabled)continue;let l=`/${i}`,u=async(e,t)=>{this.emit(`http:request`,e,t);let n=e.body;if(n){if(e.method===`GET`){let t=e.url.indexOf(`?`);t!==-1&&t<e.url.length-1&&(n=Object.fromEntries(new URLSearchParams(e.url.slice(t+1)).entries()))}else if(e.headers.get(`Content-Length`)!==`0`){let t=e.headers.get(`Content-Type`);if(t)switch(!0){case t.startsWith(`application/json`):n=await e.json();break;case t.startsWith(`text`):n=await e.text();break;case t.startsWith(`multipart/form-data`):n=await e.formData();break;default:console.error(`Unsupported Content-Type for procedure ${i}: ${t}`);break}}}try{return r(await c({input:n,context:await this.enrichContext({server:t,request:e})}))}catch(e){return this.emit(`error`,e),r(e)}};if(!t.http.method){n[l]=u;continue}n[l]||(n[l]={}),n[l][t.http.method]=u;continue}for(let[e,t]of Object.entries(a)){let n=i?`${i}/${e}`:e;c.push({path:n,value:t})}}}return{handlers:e,routes:n}}};export{s as Ultra};
1
+ import{t as e}from"./error-45bzsfk8.mjs";import{t}from"./procedure-DqhXrslI.mjs";import{n,t as r}from"./response-C6th92gD.mjs";import{t as i}from"./rpc-XjW9_Smw.mjs";import{inflateSync as a,serve as o}from"bun";var s=class{initializers=new Map;events=new Map;middlewares=new Set;derived=new Set;derivedUpgrade=new Set;options={http:{enableByDefault:!1}};httpEnabled=!1;server=null;handlers=null;constructor(e){e&&(this.options={...this.options,...e}),this.httpEnabled=this.options.http?.enableByDefault??!1}routes(e,t){let n=this.initializers.get(e);return n?t?.forEach(e=>n.add(e)):this.initializers.set(e,new Set(t)),this}use(e){return typeof e==`function`?(this.middlewares.add(e),this):(this.merge(e),this)}derive(e){return this.derived.add(e),this}deriveUpgrade(e){return this.derivedUpgrade.add(e),this}start(e){if(this.server)throw Error(`Server is already running. Create a new Ultra instance or stop the existing server first.`);let{routes:t,handlers:n}=this.build();this.handlers=n;let r=new TextDecoder,s=this.wrapHandler(()=>new Response(`Not Found`,{status:404}),this.middlewares);return this.server=o({...this.httpEnabled&&{routes:{...t,"/ws":async(e,t)=>{if(this.emit(`http:request`,e,t),!this.derivedUpgrade.size)return t.upgrade(e)?void 0:new Response(`WebSocket upgrade failed`,{status:500});if(!t.upgrade(e,await this.enrichContext({server:t,request:e}).then(e=>this.enrichUpgrade(e))))return new Response(`WebSocket upgrade failed`,{status:500})},"/*":async(e,t)=>(this.emit(`http:request`,e,t),s({input:null,context:await this.enrichContext({server:t,request:e})}))}},websocket:{data:{},open:e=>{this.emit(`ws:open`,e)},close:(e,t,n)=>{this.emit(`ws:close`,e,t,n)},message:async(e,t)=>{this.emit(`ws:message`,e,t);let n=null;try{n=typeof t==`string`?JSON.parse(t):JSON.parse(r.decode(a(t)))}catch(e){console.error(`Message payload parsing failed`,e);return}let o=Array.isArray(n)?n.filter(i):i(n)?[n]:null;if(!o||!o.length)return;let s=await this.enrichContext({server:this.server,ws:e});for(let t of o)this.handleRPC(t,e,s)}},error:e=>(this.emit(`unhandled:error`,e),console.error(`Unhandled server error:`,e),new Response(`Internal server error`,{status:500})),...e}),this.emit(`server:started`,this.server),this.server}async stop(e=!1){if(!this.server)return console.error(`Server is not running`);await this.server.stop(e),this.emit(`server:stopped`,this.server,e),this.server=null,this.handlers=null}on(e,t){return this.events.has(e)||this.events.set(e,new Set),this.events.get(e).add(t),this}off(e,t){return this.events.get(e)?.delete(t),this}emit(e,...t){return this.events.get(e)?.forEach(e=>e(...t)),this}async handleRPC(t,r,i){let a=this.handlers.get(t.method);if(!a){r.send(n(t.id,new e));return}try{r.send(n(t.id,await a({input:t.params,context:i})))}catch(e){this.emit(`error`,e),r.send(n(t.id,e))}}async enrichContext(e){for(let t of this.derived)Object.assign(e,typeof t==`function`?await t(e):t);return e}async enrichUpgrade(e){let t={data:{},headers:new Headers};for(let n of this.derivedUpgrade){let r=typeof n==`function`?await n(e):n;if(`data`in r&&Object.assign(t.data,r.data),`headers`in r)for(let[e,n]of Object.entries(r.headers))t.headers.set(e,n)}return t}merge(e){for(let[t,n]of e.initializers){let e=this.initializers.get(t);e?n.forEach(t=>e.add(t)):this.initializers.set(t,new Set(n))}e.derived.forEach(e=>this.derived.add(e)),e.derivedUpgrade.forEach(e=>this.derivedUpgrade.add(e)),e.middlewares.forEach(e=>this.middlewares.add(e)),e.events.forEach((e,t)=>{this.events.has(t)||this.events.set(t,new Set);let n=this.events.get(t);e.forEach(e=>n.add(e))})}wrapHandler(e,t){if(!t.size)return e;let n=Array.from(t),r=n.length;return async t=>{let i=0,a=()=>i===r?e(t):n[i++]({...t,next:a});return a()}}build(){let e=new Map,n={},i=e=>{let n=new t;return e&&n.input(e),this.options.http?.enableByDefault&&n.http(),n};for(let[a,o]of this.initializers){let s=a(i),c=[];for(let e in s)c.push({path:e,value:s[e]});for(;c.length;){let{path:i,value:a}=c.pop();if(a instanceof t){if(e.has(i))throw Error(`Procedure "${i}" already exists`);let t=a.metadata();!this.httpEnabled&&t.http?.enabled&&(this.httpEnabled=!0);let s=new Set([...this.middlewares,...o,...t.middlewares]),c=this.wrapHandler(a.compile(),s);if(e.set(i,c),!t.http?.enabled)continue;let l=`/${i}`,u=async(e,t)=>{this.emit(`http:request`,e,t);let n=e.body;if(n){if(e.method===`GET`){let t=e.url.indexOf(`?`);t!==-1&&t<e.url.length-1&&(n=Object.fromEntries(new URLSearchParams(e.url.slice(t+1)).entries()))}else if(e.headers.get(`Content-Length`)!==`0`){let t=e.headers.get(`Content-Type`);if(t)switch(!0){case t.startsWith(`application/json`):n=await e.json();break;case t.startsWith(`text`):n=await e.text();break;case t.startsWith(`multipart/form-data`):n=await e.formData();break;default:console.error(`Unsupported Content-Type for procedure ${i}: ${t}`);break}}}try{return r(await c({input:n,context:await this.enrichContext({server:t,request:e})}))}catch(e){return this.emit(`error`,e),r(e)}};if(!t.http.method){n[l]=u;continue}n[l]||(n[l]={}),n[l][t.http.method]=u;continue}for(let[e,t]of Object.entries(a)){let n=i?`${i}/${e}`:e;c.push({path:n,value:t})}}}return{handlers:e,routes:n}}};export{s as Ultra};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sx3/ultra",
3
3
  "type": "module",
4
- "version": "0.3.0",
4
+ "version": "0.3.2",
5
5
  "private": false,
6
6
  "description": "Type-safe RPC over HTTP/WebSocket for Bun",
7
7
  "author": "SX3",