@sx3/ultra 0.1.1 → 0.1.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/auth.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { o as Promisable } from "./types-DaFEaXF4.mjs";
2
- import { t as BaseContext } from "./context-iXF4Voqe.mjs";
3
- import "./http-AGiFONuJ.mjs";
4
- import { t as Middleware } from "./middleware-CxmfdaxU.mjs";
1
+ import { s as Promisable } from "./types-CIxyF3Kp.mjs";
2
+ import { n as DeriveRecord, t as BaseContext } from "./context-CEW3UHcp.mjs";
3
+ import "./http-B5yp5gFF.mjs";
4
+ import { t as Middleware } from "./middleware-BcnFIu-U.mjs";
5
5
  import { ProceduresMap, Ultra } from "./ultra.mjs";
6
6
  import { SessionContext } from "./session.mjs";
7
7
 
@@ -22,7 +22,8 @@ type AuthContext<User> = BaseContext & {
22
22
  auth: Auth<User>;
23
23
  };
24
24
  declare function defineConfig<User, P extends Record<string, AuthProviderFactory<User>> = Record<string, AuthProviderFactory<User>>>(config: AuthConfig<P>): AuthConfig<P>;
25
- declare function createAuthModule<User, P extends Record<string, AuthProviderFactory<User>> = Record<string, AuthProviderFactory<User>>>(config: AuthConfig<P>): Ultra<ProceduresMap, unknown, BaseContext<unknown> & {
25
+ declare function createAuthModule<User, P extends Record<string, AuthProviderFactory<User>> = Record<string, AuthProviderFactory<User>>>(config: AuthConfig<P>): Ultra<ProceduresMap, DeriveRecord, {
26
+ server: Bun.Server<DeriveRecord>;
26
27
  auth: Auth<User, P>;
27
28
  }>;
28
29
  declare const isAuthenticated: Middleware<any, any, AuthContext<any>>;
package/dist/client.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import "./context-iXF4Voqe.mjs";
2
- import "./http-AGiFONuJ.mjs";
3
- import { i as Procedure } from "./middleware-CxmfdaxU.mjs";
1
+ import "./context-CEW3UHcp.mjs";
2
+ import "./http-B5yp5gFF.mjs";
3
+ import { i as Procedure } from "./middleware-BcnFIu-U.mjs";
4
4
  import { ProceduresMap, Ultra } from "./ultra.mjs";
5
5
 
6
6
  //#region src/client.d.ts
@@ -0,0 +1,35 @@
1
+ import { s as Promisable } from "./types-CIxyF3Kp.mjs";
2
+ import { BunRequest, Server, ServerWebSocket } from "bun";
3
+
4
+ //#region src/context.d.ts
5
+ type DeriveRecord = Record<PropertyKey, any>;
6
+ type DeriveValue<C> = ((context: C) => Promisable<DeriveRecord>) | DeriveRecord;
7
+ type GetDerived<C, T extends DeriveValue<C>> = T extends ((...args: any[]) => infer R) ? Awaited<R> : T;
8
+ type DeriveUpgradePossibleValue = {
9
+ data: DeriveRecord;
10
+ } | {
11
+ headers: Record<string, string>;
12
+ } | {
13
+ data: DeriveRecord;
14
+ headers: Record<string, string>;
15
+ };
16
+ type DeriveUpgradeValue<C> = ((context: C) => Promisable<DeriveUpgradePossibleValue>) | DeriveUpgradePossibleValue;
17
+ type GetDerivedUpgradeData<C, T extends DeriveUpgradeValue<C>> = T extends ((...args: any[]) => infer R) ? Awaited<R> extends {
18
+ data: infer D;
19
+ } ? D : never : T extends {
20
+ data: infer D;
21
+ } ? D : never;
22
+ type ReplaceSocketData<C, SD> = { [K in keyof C]: K extends 'server' ? Server<SD> : K extends 'ws' ? ServerWebSocket<SD> : C[K] };
23
+ interface BaseContext<SD = unknown> {
24
+ server: Server<SD>;
25
+ }
26
+ interface HTTPContext<SD = unknown> extends BaseContext<SD> {
27
+ request: BunRequest;
28
+ }
29
+ interface WSContext<SD = unknown> extends BaseContext<SD> {
30
+ ws: ServerWebSocket<SD>;
31
+ }
32
+ declare function isHTTP<SD>(context: BaseContext<SD>): context is HTTPContext<SD>;
33
+ declare function isWS<SD>(context: BaseContext<SD>): context is WSContext<SD>;
34
+ //#endregion
35
+ export { DeriveValue as a, HTTPContext as c, isHTTP as d, isWS as f, DeriveUpgradeValue as i, ReplaceSocketData as l, DeriveRecord as n, GetDerived as o, DeriveUpgradePossibleValue as r, GetDerivedUpgradeData as s, BaseContext as t, WSContext as u };
@@ -1,2 +1,2 @@
1
- import { a as DeriveUpgradeValue, c as ExtractDeriveUpgradeData, d as WSContext, f as isHTTP, i as DeriveUpgradePossibleValue, l as HTTPContext, n as DeriveFunction, o as DeriveValue, p as isWS, r as DeriveUpgradeFunction, s as ExtractDerive, t as BaseContext, u as RebindSocketData } from "./context-iXF4Voqe.mjs";
2
- export { BaseContext, DeriveFunction, DeriveUpgradeFunction, DeriveUpgradePossibleValue, DeriveUpgradeValue, DeriveValue, ExtractDerive, ExtractDeriveUpgradeData, HTTPContext, RebindSocketData, WSContext, isHTTP, isWS };
1
+ import { a as DeriveValue, c as HTTPContext, d as isHTTP, f as isWS, i as DeriveUpgradeValue, l as ReplaceSocketData, n as DeriveRecord, o as GetDerived, r as DeriveUpgradePossibleValue, s as GetDerivedUpgradeData, t as BaseContext, u as WSContext } from "./context-CEW3UHcp.mjs";
2
+ export { BaseContext, DeriveRecord, DeriveUpgradePossibleValue, DeriveUpgradeValue, DeriveValue, GetDerived, GetDerivedUpgradeData, HTTPContext, ReplaceSocketData, WSContext, isHTTP, isWS };
package/dist/cors.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { t as BaseContext } from "./context-iXF4Voqe.mjs";
2
- import "./http-AGiFONuJ.mjs";
3
- import { t as Middleware } from "./middleware-CxmfdaxU.mjs";
1
+ import { t as BaseContext } from "./context-CEW3UHcp.mjs";
2
+ import "./http-B5yp5gFF.mjs";
3
+ import { t as Middleware } from "./middleware-BcnFIu-U.mjs";
4
4
 
5
5
  //#region src/cors.d.ts
6
6
  interface CorsConfig {
package/dist/cors.mjs CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./response-DiL4kmkY.mjs";const t={"Access-Control-Allow-Methods":[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`,`OPTIONS`].join(`, `),"Access-Control-Allow-Headers":[`Accept-Language`,`Accept`,`Content-Type`,`Content-Language`,`Range`].join(`, `),"Access-Control-Expose-Headers":[`Cache-Control`,`Content-Language`,`Content-Type`,`Expires`,`Last-Modified`,`Pragma`].join(`, `),"Access-Control-Max-Age":`3600`};function n(n){let r={...t,...n.methods?.length&&{"Access-Control-Allow-Methods":n.methods.join(`, `)},...n.allowedHeaders?.length&&{"Access-Control-Allow-Headers":n.allowedHeaders.join(`, `)},...n.exposedHeaders?.length&&{"Access-Control-Expose-Headers":n.exposedHeaders.join(`, `)},...n.credentials&&!n.origin.includes(`*`)&&{"Access-Control-Allow-Credentials":`true`},...n.maxAge&&{"Access-Control-Max-Age":n.maxAge.toString()}};return async t=>{if(!(`request`in t.context))return t.next();let i=t.context.request.headers.get(`Origin`);if(!i||!n.origin.includes(i))return t.next();if(t.context.request.method===`OPTIONS`)return new Response(null,{status:204,headers:{"Access-Control-Allow-Origin":i,...r}});let a;try{a=e(await t.next())}catch(t){a=e(t)}for(let e in a.headers.set(`Access-Control-Allow-Origin`,i),r)a.headers.set(e,r[e]);return a}}export{n as createCORSMiddleware};
1
+ import{t as e}from"./response-DiL4kmkY.mjs";import{isHTTP as t}from"./context.mjs";const n={"Access-Control-Allow-Methods":[`GET`,`POST`,`PUT`,`PATCH`,`DELETE`,`OPTIONS`].join(`, `),"Access-Control-Allow-Headers":[`Accept-Language`,`Accept`,`Content-Type`,`Content-Language`,`Range`].join(`, `),"Access-Control-Expose-Headers":[`Cache-Control`,`Content-Language`,`Content-Type`,`Expires`,`Last-Modified`,`Pragma`].join(`, `),"Access-Control-Max-Age":`3600`};function r(r){let i={...n,...r.methods?.length&&{"Access-Control-Allow-Methods":r.methods.join(`, `)},...r.allowedHeaders?.length&&{"Access-Control-Allow-Headers":r.allowedHeaders.join(`, `)},...r.exposedHeaders?.length&&{"Access-Control-Expose-Headers":r.exposedHeaders.join(`, `)},...r.credentials&&!r.origin.includes(`*`)&&{"Access-Control-Allow-Credentials":`true`},...r.maxAge&&{"Access-Control-Max-Age":r.maxAge.toString()}};return async n=>{if(!t(n.context))return n.next();let a=n.context.request.headers.get(`Origin`);if(!a||!r.origin.includes(a))return n.next();if(n.context.request.method===`OPTIONS`)return new Response(null,{status:204,headers:{"Access-Control-Allow-Origin":a,...i}});let o;try{o=e(await n.next())}catch(t){o=e(t)}for(let e in o.headers.set(`Access-Control-Allow-Origin`,a),i)o.headers.set(e,i[e]);return o}}export{r as createCORSMiddleware};
@@ -1,4 +1,4 @@
1
- import { o as Promisable } from "./types-DaFEaXF4.mjs";
1
+ import { s as Promisable } from "./types-CIxyF3Kp.mjs";
2
2
  import { BunRequest, Server } from "bun";
3
3
 
4
4
  //#region src/http.d.ts
package/dist/http.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { n as BunRoutes, r as HTTPMethod, t as BunRouteHandler } from "./http-AGiFONuJ.mjs";
1
+ import { n as BunRoutes, r as HTTPMethod, t as BunRouteHandler } from "./http-B5yp5gFF.mjs";
2
2
  export { BunRouteHandler, BunRoutes, HTTPMethod };
@@ -1,5 +1,5 @@
1
- import { o as Promisable } from "./types-DaFEaXF4.mjs";
2
- import { r as HTTPMethod } from "./http-AGiFONuJ.mjs";
1
+ import { s as Promisable } from "./types-CIxyF3Kp.mjs";
2
+ import { r as HTTPMethod } from "./http-B5yp5gFF.mjs";
3
3
  import { c as StandardSchemaV1 } from "./validation-CkRfxQJ_.mjs";
4
4
 
5
5
  //#region src/procedure.d.ts
@@ -1,3 +1,3 @@
1
- import "./http-AGiFONuJ.mjs";
2
- import { n as MiddlewareOptions, t as Middleware } from "./middleware-CxmfdaxU.mjs";
1
+ import "./http-B5yp5gFF.mjs";
2
+ import { n as MiddlewareOptions, t as Middleware } from "./middleware-BcnFIu-U.mjs";
3
3
  export { Middleware, MiddlewareOptions };
@@ -1,3 +1,3 @@
1
- import "./http-AGiFONuJ.mjs";
2
- import { a as ProcedureHandler, i as Procedure, o as ProcedureOptions, r as HTTPOptions } from "./middleware-CxmfdaxU.mjs";
1
+ import "./http-B5yp5gFF.mjs";
2
+ import { a as ProcedureHandler, i as Procedure, o as ProcedureOptions, r as HTTPOptions } from "./middleware-BcnFIu-U.mjs";
3
3
  export { HTTPOptions, Procedure, ProcedureHandler, ProcedureOptions };
package/dist/rpc.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as JSONValue } from "./types-DaFEaXF4.mjs";
1
+ import { o as JSONValue } from "./types-CIxyF3Kp.mjs";
2
2
 
3
3
  //#region src/rpc.d.ts
4
4
  interface ErrorResult {
@@ -1,7 +1,7 @@
1
- import { a as JSONValue, o as Promisable, r as JSONObject, t as DeepReadonly } from "./types-DaFEaXF4.mjs";
2
- import { d as WSContext, l as HTTPContext, t as BaseContext } from "./context-iXF4Voqe.mjs";
3
- import "./http-AGiFONuJ.mjs";
4
- import "./middleware-CxmfdaxU.mjs";
1
+ import { i as JSONObject, o as JSONValue, s as Promisable, t as DeepReadonly } from "./types-CIxyF3Kp.mjs";
2
+ import { n as DeriveRecord, t as BaseContext } from "./context-CEW3UHcp.mjs";
3
+ import "./http-B5yp5gFF.mjs";
4
+ import { i as Procedure } from "./middleware-BcnFIu-U.mjs";
5
5
  import { ProceduresMap, Ultra } from "./ultra.mjs";
6
6
  import { BunRequest, CookieSameSite, RedisClient } from "bun";
7
7
 
@@ -54,25 +54,22 @@ type SessionContext = BaseContext<{
54
54
  };
55
55
  declare function defineConfig<S extends Record<string, SessionStoreFactory>>(config: SessionConfig<S>): SessionConfig<S>;
56
56
  /** Extends context and socket data, initiate session instance every request */
57
- declare function createSessionModule<S extends Record<string, SessionStoreFactory>>(config: SessionConfig<S>): Ultra<ProceduresMap, {
57
+ declare function createSessionModule<S extends Record<string, SessionStoreFactory>>(config: SessionConfig<S>): Ultra<{
58
+ [x: string]: ProceduresMap | Procedure<any, any, any>;
59
+ }, {
60
+ [x: string]: any;
61
+ [x: number]: any;
62
+ [x: symbol]: any;
58
63
  sessionId: string;
59
- }, ((HTTPContext<{
60
- sessionId: string;
61
- }> & Omit<HTTPContext<{
62
- sessionId: string;
63
- }> & Omit<HTTPContext<unknown>, keyof HTTPContext<any>> & {
64
+ }, {
65
+ server: Bun.Server<{
66
+ [x: string]: any;
67
+ [x: number]: any;
68
+ [x: symbol]: any;
69
+ sessionId: string;
70
+ } & DeriveRecord>;
64
71
  session: Session<S>;
65
- }, keyof HTTPContext<any>>) | (WSContext<{
66
- sessionId: string;
67
- }> & Omit<WSContext<{
68
- sessionId: string;
69
- }> & Omit<WSContext<unknown>, keyof WSContext<any>> & {
70
- session: Session<S>;
71
- }, keyof WSContext<any>>)) & ((HTTPContext<{
72
- sessionId: string;
73
- }> & Omit<HTTPContext<unknown>, keyof HTTPContext<any>>) | (WSContext<{
74
- sessionId: string;
75
- }> & Omit<WSContext<unknown>, keyof WSContext<any>>))>;
72
+ }>;
76
73
  /** Stores the ID in a cookie, then moves it to the socket and uses it for requests */
77
74
  declare class Session<Stores extends Record<string, SessionStoreFactory> = Record<string, SessionStoreFactory>> {
78
75
  /** Make random session id */
package/dist/session.mjs CHANGED
@@ -1 +1 @@
1
- import{i as e}from"./error-Dq1biCC8.mjs";import{Ultra as t}from"./ultra.mjs";import{isHTTP as n,isWS as r}from"./context.mjs";import{sign as i,unsign as a}from"./crypto.mjs";import{Cookie as o}from"bun";import{randomBytes as s}from"node:crypto";function c(e){return{...e,cookie:{path:`/`,httpOnly:!0,secure:!0,sameSite:`lax`,maxAge:e.ttlSec,...e?.cookie}}}function l(e){return new t().deriveUpgrade(t=>{let n=u.getOrCreateId(t.request,e);return{headers:{"Set-Cookie":new o(e.name,i(n,e.secret),e.cookie).toString()},data:{sessionId:n}}}).derive(t=>({session:new u(e,t)})).use(async({context:e,next:t})=>{await e.session.initiate();let n=await t();return await e.session.commit(),n})}var u=class t{static makeId(){return s(16).toString(`base64url`)}static getOrCreateId(e,n){let r=e.cookies.get(n.name);return r&&a(r,n.secret)||t.makeId()}config;context;store;sessionIdFromClient=null;sessionId;sessionState=null;modified=!1;constructor(i,o){switch(this.config=i,this.context=o,this.store=i.stores[i.store](i,o),!0){case n(o):{let e=o.request.cookies.get(i.name);e&&(this.sessionIdFromClient=a(e,i.secret));break}case r(o):this.sessionIdFromClient=o.ws.data.sessionId||null;break;default:throw new e(`Session management is only supported for HTTP and WebSocket protocols.`)}this.sessionId=this.sessionIdFromClient||t.makeId()}get id(){return this.sessionId}async initiate(){this.sessionState||=await this.store.read(this.sessionId)||{}}async commit(){if(this.touch(),this.isEmpty&&this.sessionIdFromClient)return this.store.destroy(this.sessionIdFromClient);this.sessionIdFromClient&&this.sessionIdFromClient!==this.sessionId?(await this.store.destroy(this.sessionIdFromClient),await this.store.write(this.sessionId,this.state)):this.modified?await this.store.write(this.sessionId,this.state):await this.store.touch(this.sessionId)}regenerate(){this.sessionId=t.makeId()}get(e,t){return this.state[e]??t??null}set(e,t){this.state[e]=t,this.modified=!0}has(e){return Object.hasOwn(this.state,e)}all(){return this.state}delete(e){delete this.state[e],this.modified=!0}clear(){this.sessionState={},this.modified=!0}get state(){if(!this.sessionState)throw Error(`Session is not initiated yet.`);return this.sessionState}get isEmpty(){return Object.keys(this.state).length===0}touch(){`request`in this.context&&this.context.request.cookies.set(this.config.name,i(this.sessionId,this.config.secret),this.config.cookie)}},d=class{config;connection;constructor(e,t){this.config=e,this.connection=t}async read(e){let t=await this.connection.get(`${this.config.name}:${e}`);return t?JSON.parse(t):null}async write(e,t){await this.connection.set(`${this.config.name}:${e}`,JSON.stringify(t),`EX`,this.config.ttlSec)}async destroy(e){await this.connection.del(`${this.config.name}:${e}`)}async touch(e){await this.connection.expire(`${this.config.name}:${e}`,this.config.ttlSec)}};const f=new Map;var p=class{config;sweepIntervalMs;ttlMs;lastSweepAt=Date.now();constructor(e,t=e.ttlSec){this.config=e,this.sweepIntervalMs=t*1e3,this.ttlMs=e.ttlSec*1e3}read(e){return this.maybeSweep(),f.get(e)?.data??null}write(e,t){this.maybeSweep(),f.set(e,{data:t,touched:Date.now()})}destroy(e){this.maybeSweep(),f.delete(e)}touch(e){this.maybeSweep();let t=f.get(e);t&&(t.touched=Date.now())}maybeSweep(e=Date.now()){if(!(e-this.lastSweepAt<this.sweepIntervalMs)){this.lastSweepAt=e;for(let[t,n]of f)e-n.touched>this.ttlMs&&f.delete(t)}}};export{p as MemorySessionStore,d as RedisSessionStore,u as Session,l as createSessionModule,c as defineConfig};
1
+ import{i as e}from"./error-Dq1biCC8.mjs";import{Ultra as t}from"./ultra.mjs";import{isHTTP as n,isWS as r}from"./context.mjs";import{sign as i,unsign as a}from"./crypto.mjs";import{Cookie as o}from"bun";import{randomBytes as s}from"node:crypto";function c(e){return{...e,cookie:{path:`/`,httpOnly:!0,secure:!0,sameSite:`lax`,maxAge:e.ttlSec,...e?.cookie}}}function l(e){return new t().deriveUpgrade(t=>{let n=u.getOrCreateId(t.request,e);return{headers:{"Set-Cookie":new o(e.name,i(n,e.secret),e.cookie).toString()},data:{sessionId:n}}}).derive(t=>({session:new u(e,t)})).use(async({context:e,next:t})=>{await e.session.initiate();let n=await t();return await e.session.commit(),n})}var u=class t{static makeId(){return s(16).toString(`base64url`)}static getOrCreateId(e,n){let r=e.cookies.get(n.name);return r&&a(r,n.secret)||t.makeId()}config;context;store;sessionIdFromClient=null;sessionId;sessionState=null;modified=!1;constructor(i,o){switch(this.config=i,this.context=o,this.store=i.stores[i.store](i,o),!0){case n(o):{let e=o.request.cookies.get(i.name);e&&(this.sessionIdFromClient=a(e,i.secret));break}case r(o):this.sessionIdFromClient=o.ws.data.sessionId||null;break;default:throw new e(`Session management is only supported for HTTP and WebSocket protocols.`)}this.sessionId=this.sessionIdFromClient||t.makeId()}get id(){return this.sessionId}async initiate(){this.sessionState||=await this.store.read(this.sessionId)||{}}async commit(){if(this.touch(),this.isEmpty&&this.sessionIdFromClient)return this.store.destroy(this.sessionIdFromClient);this.sessionIdFromClient&&this.sessionIdFromClient!==this.sessionId?(await this.store.destroy(this.sessionIdFromClient),await this.store.write(this.sessionId,this.state)):this.modified?await this.store.write(this.sessionId,this.state):await this.store.touch(this.sessionId)}regenerate(){this.sessionId=t.makeId()}get(e,t){return this.state[e]??t??null}set(e,t){this.state[e]=t,this.modified=!0}has(e){return Object.hasOwn(this.state,e)}all(){return this.state}delete(e){delete this.state[e],this.modified=!0}clear(){this.sessionState={},this.modified=!0}get state(){if(!this.sessionState)throw Error(`Session is not initiated yet.`);return this.sessionState}get isEmpty(){return Object.keys(this.state).length===0}touch(){n(this.context)&&this.context.request.cookies.set(this.config.name,i(this.sessionId,this.config.secret),this.config.cookie)}},d=class{config;connection;constructor(e,t){this.config=e,this.connection=t}async read(e){let t=await this.connection.get(`${this.config.name}:${e}`);return t?JSON.parse(t):null}async write(e,t){await this.connection.set(`${this.config.name}:${e}`,JSON.stringify(t),`EX`,this.config.ttlSec)}async destroy(e){await this.connection.del(`${this.config.name}:${e}`)}async touch(e){await this.connection.expire(`${this.config.name}:${e}`,this.config.ttlSec)}};const f=new Map;var p=class{config;sweepIntervalMs;ttlMs;lastSweepAt=Date.now();constructor(e,t=e.ttlSec){this.config=e,this.sweepIntervalMs=t*1e3,this.ttlMs=e.ttlSec*1e3}read(e){return this.maybeSweep(),f.get(e)?.data??null}write(e,t){this.maybeSweep(),f.set(e,{data:t,touched:Date.now()})}destroy(e){this.maybeSweep(),f.delete(e)}touch(e){this.maybeSweep();let t=f.get(e);t&&(t.touched=Date.now())}maybeSweep(e=Date.now()){if(!(e-this.lastSweepAt<this.sweepIntervalMs)){this.lastSweepAt=e;for(let[t,n]of f)e-n.touched>this.ttlMs&&f.delete(t)}}};export{p as MemorySessionStore,d as RedisSessionStore,u as Session,l as createSessionModule,c as defineConfig};
@@ -7,5 +7,8 @@ interface JSONObject {
7
7
  type JSONArray = JSONValue[];
8
8
  type JSONValue = JSONPrimitive | JSONObject | JSONArray;
9
9
  type DeepReadonly<T> = T extends Array<infer R> ? ReadonlyArray<DeepReadonly<R>> : T extends object ? { readonly [P in keyof T]: DeepReadonly<T[P]> } : Readonly<T>;
10
+ type GetReturn<T> = T extends ((...args: any[]) => infer R) ? Awaited<R> : T;
11
+ type ResetRecursion<T> = T & {};
12
+ type Simplify<T> = T extends object ? { [K in keyof T]: T[K] } & {} : T;
10
13
  //#endregion
11
- export { JSONValue as a, JSONPrimitive as i, JSONArray as n, Promisable as o, JSONObject as r, DeepReadonly as t };
14
+ export { JSONPrimitive as a, ResetRecursion as c, JSONObject as i, Simplify as l, GetReturn as n, JSONValue as o, JSONArray as r, Promisable as s, DeepReadonly as t };
package/dist/types.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as JSONValue, i as JSONPrimitive, n as JSONArray, o as Promisable, r as JSONObject, t as DeepReadonly } from "./types-DaFEaXF4.mjs";
2
- export { DeepReadonly, JSONArray, JSONObject, JSONPrimitive, JSONValue, Promisable };
1
+ import { a as JSONPrimitive, c as ResetRecursion, i as JSONObject, l as Simplify, n as GetReturn, o as JSONValue, r as JSONArray, s as Promisable, t as DeepReadonly } from "./types-CIxyF3Kp.mjs";
2
+ export { DeepReadonly, GetReturn, JSONArray, JSONObject, JSONPrimitive, JSONValue, Promisable, ResetRecursion, Simplify };
package/dist/ultra.d.mts CHANGED
@@ -1,7 +1,8 @@
1
- import { a as DeriveUpgradeValue, c as ExtractDeriveUpgradeData, o as DeriveValue, s as ExtractDerive, t as BaseContext, u as RebindSocketData } from "./context-iXF4Voqe.mjs";
2
- import { n as BunRoutes } from "./http-AGiFONuJ.mjs";
1
+ import { l as Simplify } from "./types-CIxyF3Kp.mjs";
2
+ import { a as DeriveValue, i as DeriveUpgradeValue, l as ReplaceSocketData, n as DeriveRecord, o as GetDerived, s as GetDerivedUpgradeData, t as BaseContext } from "./context-CEW3UHcp.mjs";
3
+ import { n as BunRoutes } from "./http-B5yp5gFF.mjs";
3
4
  import { c as StandardSchemaV1 } from "./validation-CkRfxQJ_.mjs";
4
- import { a as ProcedureHandler, i as Procedure, t as Middleware } from "./middleware-CxmfdaxU.mjs";
5
+ import { a as ProcedureHandler, i as Procedure, t as Middleware } from "./middleware-BcnFIu-U.mjs";
5
6
  import { BunRequest, ErrorLike, Server, ServerWebSocket } from "bun";
6
7
 
7
8
  //#region src/ultra.d.ts
@@ -27,7 +28,7 @@ interface UltraOptions {
27
28
  enableByDefault?: boolean;
28
29
  };
29
30
  }
30
- declare class Ultra<Procedures extends ProceduresMap = ProceduresMap, SocketData = unknown, Context extends BaseContext<SocketData> = BaseContext<SocketData>> {
31
+ declare class Ultra<const Procedures extends ProceduresMap = ProceduresMap, const SocketData extends DeriveRecord = DeriveRecord, const Context extends BaseContext<SocketData> = BaseContext<SocketData>> {
31
32
  protected readonly initializers: Map<ProcedureMapInitializer<any, Context>, Set<Middleware<any, any, Context>>>;
32
33
  protected readonly events: Map<keyof ServerEventMap<SocketData>, Set<ServerEventListener<SocketData, any>>>;
33
34
  protected readonly middlewares: Set<Middleware<any, any, Context>>;
@@ -40,11 +41,11 @@ declare class Ultra<Procedures extends ProceduresMap = ProceduresMap, SocketData
40
41
  /** Register procedures */
41
42
  routes<const P extends ProceduresMap>(initializer: ProcedureMapInitializer<P, Context>, middlewares?: Middleware<any, any, Context>[]): Ultra<Procedures & P, SocketData, Context>;
42
43
  /** Register middleware or another Ultra instance */
43
- use<const PluginProcedures extends ProceduresMap, const PluginSocketData, const PluginContext extends BaseContext<PluginSocketData>>(entity: Middleware<any, any, Context> | Ultra<PluginProcedures, PluginSocketData, PluginContext>): Ultra<Procedures & PluginProcedures, SocketData & PluginSocketData, RebindSocketData<Context, SocketData & PluginSocketData> & RebindSocketData<PluginContext, SocketData & PluginSocketData>>;
44
+ use<const PluginProcedures extends ProceduresMap, const PluginSocketData extends DeriveRecord, const PluginContext extends BaseContext<PluginSocketData>>(entity: Middleware<any, any, Context> | Ultra<PluginProcedures, PluginSocketData, PluginContext>): Ultra<Simplify<Procedures & PluginProcedures>, Simplify<SocketData & PluginSocketData>, Simplify<ReplaceSocketData<Context & PluginContext, SocketData & PluginSocketData>>>;
44
45
  /** Extends context values for every request with provided values */
45
- derive<const D extends DeriveValue<Context>>(derive: D): Ultra<Procedures, SocketData, Context & ExtractDerive<Context, D>>;
46
+ derive<const D extends DeriveValue<Context>>(derive: D): Ultra<Procedures, SocketData, Simplify<Context & GetDerived<Context, D>>>;
46
47
  /** Extends socket data and return headers */
47
- deriveUpgrade<const D extends DeriveUpgradeValue<Context>>(derive: D): Ultra<Procedures, SocketData & ExtractDeriveUpgradeData<Context, D>, RebindSocketData<Context, SocketData & ExtractDeriveUpgradeData<Context, D>>>;
48
+ deriveUpgrade<const D extends DeriveUpgradeValue<Context>>(derive: D): Ultra<Procedures, Simplify<SocketData & GetDerivedUpgradeData<Context, D>>, Simplify<ReplaceSocketData<Context, Simplify<SocketData & GetDerivedUpgradeData<Context, D>>>>>;
48
49
  /** Build procedures and start servers */
49
50
  start(options?: StartOptions<SocketData>): Server<SocketData>;
50
51
  /** Stop server */
@@ -53,7 +54,7 @@ declare class Ultra<Procedures extends ProceduresMap = ProceduresMap, SocketData
53
54
  off<E extends keyof ServerEventMap<SocketData>>(event: E, listener: ServerEventListener<SocketData, E>): this;
54
55
  emit<E extends keyof ServerEventMap<SocketData>>(event: E, ...args: ServerEventMap<SocketData>[E]): this;
55
56
  /** Enrich context with derived values */
56
- protected enrichContext(context: BaseContext<SocketData>): Promise<Context>;
57
+ protected enrichContext<const C extends BaseContext>(context: C): Promise<Context>;
57
58
  /** Enrich upgrade options with derived values */
58
59
  protected enrichUpgrade(context: Context): Promise<{
59
60
  data: Record<PropertyKey, any>;
package/dist/ultra.mjs CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./procedure-DMThMtgF.mjs";import{n as t,t as n}from"./response-DiL4kmkY.mjs";import{t as r}from"./rpc-CAwkzxZe.mjs";import{serve as i}from"bun";var a=class{initializers=new Map;events=new Map;middlewares=new Set;derived=new Set;derivedUpgrade=new Set;options={http:{enableByDefault:!1}};httpEnabled=!1;server;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)return console.warn(`Server is already running`),this.server;let{routes:n,handlers:a}=this.build(),o=this.wrapHandler(()=>new Response(`Not Found`,{status:404}),this.middlewares);return this.server=i({...this.httpEnabled&&{routes:{...n,"/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});let n=this.derived.size?await this.enrichContext({server:t,request:e}):{server:t,request:e};if(!t.upgrade(e,await this.enrichUpgrade(n)))return new Response(`WebSocket upgrade failed`,{status:500})},"/*":async(e,t)=>(this.emit(`http:request`,e,t),o({input:null,context:this.derived.size?await this.enrichContext({server:t,request:e}):{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,n)=>{if(this.emit(`ws:message`,e,n),typeof n!=`string`)return;let i=JSON.parse(n);if(!r(i))return;let o=a.get(i.method);if(!o){e.send(`{"id": "${i.id}", "error": {"code": 404, "message": "Not found"}}`);return}try{e.send(t(i.id,await o({input:i.params,context:this.derived.size?await this.enrichContext({server:this.server,ws:e}):{server:this.server,ws:e}})))}catch(n){this.emit(`error`,n),e.send(t(i.id,n))}}},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)}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 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 t=new Map,r={},i=t=>{let n=new e;return t&&n.input(t),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 e){if(t.has(i))throw Error(`Procedure "${i}" already exists`);let e=a.metadata();!this.httpEnabled&&e.http?.enabled&&(this.httpEnabled=!0);let s=new Set([...this.middlewares,...o,...e.middlewares]),c=this.wrapHandler(a.compile(),s);if(t.set(i,c),!e.http?.enabled)continue;let l=`/${i}`,u=async(e,t)=>{this.emit(`http:request`,e,t);let r=e.body;if(r){if(e.method===`GET`){let t=e.url.indexOf(`?`);t!==-1&&t<e.url.length-1&&(r=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`):r=await e.json();break;case t.startsWith(`text`):r=await e.text();break;case t.startsWith(`multipart/form-data`):r=await e.formData();break;default:console.error(`Unsupported Content-Type for procedure ${i}: ${t}`);break}}}try{return n(await c({input:r,context:this.derived.size?await this.enrichContext({server:t,request:e}):{server:t,request:e}}))}catch(e){return this.emit(`error`,e),n(e)}};if(!e.http.method){r[l]=u;continue}r[l]||(r[l]={}),r[l][e.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:t,routes:r}}};export{a as Ultra};
1
+ import{t as e}from"./procedure-DMThMtgF.mjs";import{n as t,t as n}from"./response-DiL4kmkY.mjs";import{t as r}from"./rpc-CAwkzxZe.mjs";import{serve as i}from"bun";var a=class{initializers=new Map;events=new Map;middlewares=new Set;derived=new Set;derivedUpgrade=new Set;options={http:{enableByDefault:!1}};httpEnabled=!1;server;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)return console.warn(`Server is already running`),this.server;let{routes:n,handlers:a}=this.build(),o=this.wrapHandler(()=>new Response(`Not Found`,{status:404}),this.middlewares);return this.server=i({...this.httpEnabled&&{routes:{...n,"/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.enrichUpgrade(this.derived.size?await this.enrichContext({server:t,request:e}):{server:t,request:e})))return new Response(`WebSocket upgrade failed`,{status:500})},"/*":async(e,t)=>(this.emit(`http:request`,e,t),o({input:null,context:this.derived.size?await this.enrichContext({server:t,request:e}):{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,n)=>{if(this.emit(`ws:message`,e,n),typeof n!=`string`)return;let i=JSON.parse(n);if(!r(i))return;let o=a.get(i.method);if(!o){e.send(`{"id": "${i.id}", "error": {"code": 404, "message": "Not found"}}`);return}try{e.send(t(i.id,await o({input:i.params,context:this.derived.size?await this.enrichContext({server:this.server,ws:e}):{server:this.server,ws:e}})))}catch(n){this.emit(`error`,n),e.send(t(i.id,n))}}},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)}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 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 t=new Map,r={},i=t=>{let n=new e;return t&&n.input(t),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 e){if(t.has(i))throw Error(`Procedure "${i}" already exists`);let e=a.metadata();!this.httpEnabled&&e.http?.enabled&&(this.httpEnabled=!0);let s=new Set([...this.middlewares,...o,...e.middlewares]),c=this.wrapHandler(a.compile(),s);if(t.set(i,c),!e.http?.enabled)continue;let l=`/${i}`,u=async(e,t)=>{this.emit(`http:request`,e,t);let r=e.body;if(r){if(e.method===`GET`){let t=e.url.indexOf(`?`);t!==-1&&t<e.url.length-1&&(r=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`):r=await e.json();break;case t.startsWith(`text`):r=await e.text();break;case t.startsWith(`multipart/form-data`):r=await e.formData();break;default:console.error(`Unsupported Content-Type for procedure ${i}: ${t}`);break}}}try{return n(await c({input:r,context:this.derived.size?await this.enrichContext({server:t,request:e}):{server:t,request:e}}))}catch(e){return this.emit(`error`,e),n(e)}};if(!e.http.method){r[l]=u;continue}r[l]||(r[l]={}),r[l][e.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:t,routes:r}}};export{a as Ultra};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sx3/ultra",
3
3
  "type": "module",
4
- "version": "0.1.1",
4
+ "version": "0.1.2",
5
5
  "private": false,
6
6
  "description": "Type-safe RPC over HTTP/WebSocket for Bun",
7
7
  "author": "SX3",
@@ -46,6 +46,7 @@
46
46
  "build": "tsdown",
47
47
  "dev": "tsdown --watch",
48
48
  "test": "bun test && bunx tsc --noEmit",
49
+ "trace:types": "bunx tsc --noEmit --target esnext --skipLibCheck --generateTrace trace ./tests/types-performance.ts",
49
50
  "lint": "eslint ."
50
51
  },
51
52
  "peerDependencies": {
@@ -1,36 +0,0 @@
1
- import { o as Promisable } from "./types-DaFEaXF4.mjs";
2
- import { BunRequest, Server, ServerWebSocket } from "bun";
3
-
4
- //#region src/context.d.ts
5
- type DeriveFunction<C> = (context: C) => Promisable<Record<PropertyKey, any>>;
6
- type DeriveValue<C> = DeriveFunction<C> | Record<PropertyKey, any>;
7
- type ExtractDerive<C, T extends DeriveValue<C>> = T extends ((...args: any[]) => any) ? Awaited<ReturnType<T>> : T;
8
- type DeriveUpgradePossibleValue = {
9
- data: Record<PropertyKey, any>;
10
- } | {
11
- headers: Record<string, string>;
12
- } | {
13
- data: Record<PropertyKey, any>;
14
- headers: Record<string, string>;
15
- };
16
- type DeriveUpgradeFunction<C> = (context: C) => Promisable<DeriveUpgradePossibleValue>;
17
- type DeriveUpgradeValue<C> = DeriveUpgradeFunction<C> | DeriveUpgradePossibleValue;
18
- type ExtractDeriveUpgradeData<C, T extends DeriveUpgradeValue<C>> = T extends ((...args: any[]) => any) ? Awaited<ReturnType<T>> extends {
19
- data: infer D;
20
- } ? D : never : T extends {
21
- data: infer D;
22
- } ? D : never;
23
- type RebindSocketData<C, SD> = C extends HTTPContext<any> ? HTTPContext<SD> & Omit<C, keyof HTTPContext<any>> : C extends WSContext<any> ? WSContext<SD> & Omit<C, keyof WSContext<any>> : C extends BaseContext<any> ? BaseContext<SD> & Omit<C, keyof BaseContext<any>> : C;
24
- interface HTTPContext<SD = unknown> {
25
- server: Server<SD>;
26
- request: BunRequest;
27
- }
28
- interface WSContext<SD = unknown> {
29
- server: Server<SD>;
30
- ws: ServerWebSocket<SD>;
31
- }
32
- type BaseContext<SD = unknown> = HTTPContext<SD> | WSContext<SD>;
33
- declare function isHTTP<SD>(context: BaseContext<SD>): context is HTTPContext<SD>;
34
- declare function isWS<SD>(context: BaseContext<SD>): context is WSContext<SD>;
35
- //#endregion
36
- export { DeriveUpgradeValue as a, ExtractDeriveUpgradeData as c, WSContext as d, isHTTP as f, DeriveUpgradePossibleValue as i, HTTPContext as l, DeriveFunction as n, DeriveValue as o, isWS as p, DeriveUpgradeFunction as r, ExtractDerive as s, BaseContext as t, RebindSocketData as u };