@sx3/ultra 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/auth.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as DefaultSocketData, t as BaseContext } from "./context-ChCsZh7S.mjs";
2
- import { o as Promisable, r as JSONObject } from "./types-Cn69QrjS.mjs";
2
+ import { o as Promisable } from "./types-Cn69QrjS.mjs";
3
3
  import "./http-BqWCMASL.mjs";
4
4
  import { t as Middleware } from "./middleware-COKreBGP.mjs";
5
5
  import { ProceduresMap, Ultra } from "./ultra.mjs";
@@ -13,27 +13,27 @@ interface AuthProvider<User> {
13
13
  logout: () => Promisable<void>;
14
14
  setUser: (user: User) => Promisable<void>;
15
15
  }
16
- type AuthProviderFactory<User = any> = (context: BaseContext) => AuthProvider<User>;
16
+ type AuthProviderFactory<User = any> = (context: AuthContext<User>) => AuthProvider<User>;
17
17
  interface AuthConfig<P extends Record<string, AuthProviderFactory> = Record<string, AuthProviderFactory>> {
18
18
  provider: keyof P;
19
19
  providers: P;
20
20
  }
21
- type AuthContext<User extends JSONObject> = BaseContext & {
22
- session: Session;
21
+ type AuthContext<User> = BaseContext & {
22
+ session: Session<any>;
23
23
  auth: Auth<User>;
24
24
  };
25
- declare function defineConfig<User extends JSONObject, P extends Record<string, AuthProviderFactory<User>> = Record<string, AuthProviderFactory<User>>>(config: AuthConfig<P>): AuthConfig<P>;
26
- declare function createAuthModule<User extends JSONObject, P extends Record<string, AuthProviderFactory<User>> = Record<string, AuthProviderFactory<User>>>(config: AuthConfig<P>): Ultra<ProceduresMap, BaseContext & {
25
+ declare function defineConfig<User, P extends Record<string, AuthProviderFactory<User>> = Record<string, AuthProviderFactory<User>>>(config: AuthConfig<P>): AuthConfig<P>;
26
+ declare function createAuthModule<User, P extends Record<string, AuthProviderFactory<User>> = Record<string, AuthProviderFactory<User>>>(config: AuthConfig<P>): Ultra<ProceduresMap, BaseContext & {
27
27
  auth: Auth<User, P>;
28
28
  }, DefaultSocketData>;
29
- declare const isAuthenticated: Middleware<unknown, unknown, AuthContext<JSONObject>>;
30
- declare const isGuest: Middleware<unknown, unknown, AuthContext<JSONObject>>;
31
- declare class Auth<User extends JSONObject, Providers extends Record<string, AuthProviderFactory<User>> = Record<string, AuthProviderFactory<User>>> {
29
+ declare const isAuthenticated: Middleware<any, any, AuthContext<any>>;
30
+ declare const isGuest: Middleware<any, any, AuthContext<any>>;
31
+ declare class Auth<User, Providers extends Record<string, AuthProviderFactory<User>> = Record<string, AuthProviderFactory<User>>> {
32
32
  protected readonly config: AuthConfig<Providers>;
33
- protected readonly context: BaseContext;
33
+ protected readonly context: AuthContext<User>;
34
34
  protected readonly usingProvider: keyof Providers;
35
35
  protected readonly providerCache: Map<keyof Providers, AuthProvider<User>>;
36
- constructor(config: AuthConfig<Providers>, context: BaseContext, provider?: keyof Providers, providerCache?: Map<keyof Providers, AuthProvider<User>>);
36
+ constructor(config: AuthConfig<Providers>, context: AuthContext<User>, provider?: keyof Providers, providerCache?: Map<keyof Providers, AuthProvider<User>>);
37
37
  use(provider: keyof Providers): Auth<User, Providers>;
38
38
  get user(): User | null;
39
39
  check(): Promisable<boolean>;
@@ -42,11 +42,11 @@ declare class Auth<User extends JSONObject, Providers extends Record<string, Aut
42
42
  setUser(user: User): Promisable<void>;
43
43
  protected get provider(): AuthProvider<User>;
44
44
  }
45
- declare class SessionAuthProvider<User extends JSONObject> implements AuthProvider<User> {
45
+ declare class SessionAuthProvider<User> implements AuthProvider<User> {
46
46
  protected readonly context: AuthContext<User>;
47
47
  protected readonly sessionKey: string;
48
48
  constructor(context: AuthContext<User>, sessionKey?: string);
49
- get user(): User;
49
+ get user(): NonNullable<User> | null;
50
50
  check(): boolean;
51
51
  login(user: User): void;
52
52
  logout(): void;
package/dist/auth.mjs CHANGED
@@ -1,84 +1 @@
1
- import { r as UnauthorizedError } from "./error-CII1zMOR.mjs";
2
- import { Ultra } from "./ultra.mjs";
3
-
4
- //#region src/auth.ts
5
- function defineConfig(config) {
6
- return config;
7
- }
8
- function createAuthModule(config) {
9
- return new Ultra().derive((context) => ({ auth: new Auth(config, context) }));
10
- }
11
- const isAuthenticated = async (options) => {
12
- if (!await options.context.auth.check()) return new UnauthorizedError();
13
- return options.next();
14
- };
15
- const isGuest = async (options) => {
16
- if (await options.context.auth.check()) return new UnauthorizedError();
17
- return options.next();
18
- };
19
- var Auth = class Auth {
20
- config;
21
- context;
22
- usingProvider;
23
- providerCache;
24
- constructor(config, context, provider = config.provider, providerCache = /* @__PURE__ */ new Map()) {
25
- this.config = config;
26
- this.context = context;
27
- this.usingProvider = provider;
28
- this.providerCache = providerCache;
29
- }
30
- use(provider) {
31
- return new Auth(this.config, this.context, provider, this.providerCache);
32
- }
33
- get user() {
34
- return this.provider.user;
35
- }
36
- check() {
37
- return this.provider.check();
38
- }
39
- login(user) {
40
- return this.provider.login(user);
41
- }
42
- logout() {
43
- return this.provider.logout();
44
- }
45
- setUser(user) {
46
- return this.provider.setUser(user);
47
- }
48
- get provider() {
49
- const cached = this.providerCache.get(this.usingProvider);
50
- if (cached) return cached;
51
- const providerFactory = this.config.providers[this.usingProvider];
52
- if (!providerFactory) throw new Error(`Auth provider "${String(this.usingProvider)}" is not configured.`);
53
- const instance = providerFactory(this.context);
54
- this.providerCache.set(this.usingProvider, instance);
55
- return instance;
56
- }
57
- };
58
- var SessionAuthProvider = class {
59
- context;
60
- sessionKey;
61
- constructor(context, sessionKey = "user") {
62
- this.context = context;
63
- this.sessionKey = sessionKey;
64
- }
65
- get user() {
66
- return this.context.session.get(this.sessionKey) || null;
67
- }
68
- check() {
69
- return this.user !== null;
70
- }
71
- login(user) {
72
- this.setUser(user);
73
- this.context.session.regenerate();
74
- }
75
- logout() {
76
- this.context.session.delete(this.sessionKey);
77
- }
78
- setUser(user) {
79
- this.context.session.set(this.sessionKey, user);
80
- }
81
- };
82
-
83
- //#endregion
84
- export { Auth, SessionAuthProvider, createAuthModule, defineConfig, isAuthenticated, isGuest };
1
+ import{r as e}from"./error-Dq1biCC8.mjs";import{Ultra as t}from"./ultra.mjs";function n(e){return e}function r(e){return new t().derive(t=>({auth:new o(e,t)}))}const i=async t=>await t.context.auth.check()?t.next():new e,a=async t=>await t.context.auth.check()?new e:t.next();var o=class e{config;context;usingProvider;providerCache;constructor(e,t,n=e.provider,r=new Map){this.config=e,this.context=t,this.usingProvider=n,this.providerCache=r}use(t){return new e(this.config,this.context,t,this.providerCache)}get user(){return this.provider.user}check(){return this.provider.check()}login(e){return this.provider.login(e)}logout(){return this.provider.logout()}setUser(e){return this.provider.setUser(e)}get provider(){let e=this.providerCache.get(this.usingProvider);if(e)return e;let t=this.config.providers[this.usingProvider];if(!t)throw Error(`Auth provider "${String(this.usingProvider)}" is not configured.`);let n=t(this.context);return this.providerCache.set(this.usingProvider,n),n}},s=class{context;sessionKey;constructor(e,t=`user`){this.context=e,this.sessionKey=t}get user(){return this.context.session.get(this.sessionKey)||null}check(){return this.user!==null}login(e){this.setUser(e),this.context.session.regenerate()}logout(){this.context.session.delete(this.sessionKey)}setUser(e){this.context.session.set(this.sessionKey,e)}};export{o as Auth,s as SessionAuthProvider,r as createAuthModule,n as defineConfig,i as isAuthenticated,a as isGuest};
package/dist/client.mjs CHANGED
@@ -1,131 +1 @@
1
- //#region src/client.ts
2
- function proxyClient(invoke, path = []) {
3
- return new Proxy(() => {}, {
4
- get(_, prop) {
5
- if (typeof prop === "string") return proxyClient(invoke, [...path, prop]);
6
- },
7
- apply(_, __, args) {
8
- if (!path.length) throw new Error("Cannot call client root; select a procedure first");
9
- const method = path.join("/");
10
- const params = args[0];
11
- const callOptions = args[1];
12
- return invoke(method, params, callOptions);
13
- }
14
- });
15
- }
16
- function mergeHeaders(...sources) {
17
- const result = new Headers();
18
- for (const headersInit of sources) {
19
- if (!headersInit) continue;
20
- new Headers(headersInit).forEach((value, key) => result.set(key, value));
21
- }
22
- return result;
23
- }
24
- function createHTTPClient(clientOptions) {
25
- const invoke = async (method, params, callOptions) => {
26
- const options = {
27
- ...clientOptions,
28
- ...callOptions
29
- };
30
- const timeout = options?.timeout || 1e4;
31
- const controller = new AbortController();
32
- const httpMethod = options?.method || "POST";
33
- let url = `${options.baseUrl}/${method}`;
34
- const headers = mergeHeaders(clientOptions?.headers, options?.headers, callOptions?.headers);
35
- let body = null;
36
- const abortTimeout = setTimeout(() => controller.abort(`Timeout: ${timeout}`), timeout);
37
- switch (true) {
38
- case httpMethod === "GET": {
39
- body = null;
40
- if (!params) break;
41
- if (typeof params !== "object") throw new Error("GET requests params to be an object for query string generation");
42
- const entries = Object.entries(params).filter(([, v]) => v !== void 0 && v !== null).map(([k, v]) => [k, String(v)]);
43
- const queryString = new URLSearchParams(entries).toString();
44
- if (queryString) url += `?${queryString}`;
45
- break;
46
- }
47
- case params instanceof FormData:
48
- body = params;
49
- break;
50
- case typeof params === "string":
51
- headers.set("Content-Type", "text/plain");
52
- body = params;
53
- break;
54
- default:
55
- headers.set("Content-Type", "application/json");
56
- body = JSON.stringify(params);
57
- }
58
- try {
59
- const response = await fetch(url, {
60
- method: httpMethod,
61
- ...body && { body },
62
- ...options,
63
- signal: controller.signal,
64
- headers
65
- });
66
- if (!response.ok) throw new Error(`HTTP error: ${response.statusText} ${response.status} `);
67
- const type = response.headers.get("Content-Type") || "";
68
- switch (true) {
69
- case type.includes("application/json"): return await response.json();
70
- case type.includes("text/"): return await response.text();
71
- default: return await response.blob();
72
- }
73
- } catch (error) {
74
- if (error.name === "AbortError") throw new Error(`Request aborted: ${error.message}`);
75
- throw error;
76
- } finally {
77
- clearTimeout(abortTimeout);
78
- }
79
- };
80
- return proxyClient(invoke);
81
- }
82
- function createWebSocketClient(options) {
83
- const { timeout = 1e4 } = options;
84
- const makeId = () => Math.random().toString(36);
85
- const invoke = (method, params, callOptions) => {
86
- const socket = options.socket();
87
- const readyState = socket.readyState;
88
- if (typeof readyState === "number" && readyState !== WebSocket.OPEN) return Promise.reject(/* @__PURE__ */ new Error("WebSocket is not open"));
89
- const { promise, resolve, reject } = Promise.withResolvers();
90
- const mergedTimeout = callOptions?.timeout ?? timeout;
91
- let rejectTimeout;
92
- const requestId = makeId();
93
- const listener = (event) => {
94
- try {
95
- const response = JSON.parse(event.data);
96
- if (response.id !== requestId) return;
97
- clearTimeout(rejectTimeout);
98
- socket.removeEventListener("message", listener);
99
- if ("error" in response) return reject(response.error);
100
- return resolve(response.result);
101
- } catch (error) {
102
- reject(error);
103
- }
104
- };
105
- socket.addEventListener("message", listener);
106
- rejectTimeout = setTimeout(() => {
107
- socket.removeEventListener("message", listener);
108
- reject(`Timeout: ${mergedTimeout}`);
109
- }, mergedTimeout);
110
- socket.send(JSON.stringify({
111
- id: requestId,
112
- method,
113
- params
114
- }));
115
- return promise;
116
- };
117
- return proxyClient(invoke);
118
- }
119
- function createSuperClient(options) {
120
- const invoke = (method, params, callOptions) => {
121
- const client = options.pick(method, params, callOptions);
122
- const segments = method.split("/").filter(Boolean);
123
- let target = client;
124
- for (const segment of segments) if (target[segment]) target = target[segment];
125
- return target(params, callOptions);
126
- };
127
- return proxyClient(invoke);
128
- }
129
-
130
- //#endregion
131
- export { createHTTPClient, createSuperClient, createWebSocketClient };
1
+ function e(t,n=[]){return new Proxy(()=>{},{get(r,i){if(typeof i==`string`)return e(t,[...n,i])},apply(e,r,i){if(!n.length)throw Error(`Cannot call client root; select a procedure first`);let a=n.join(`/`),o=i[0],s=i[1];return t(a,o,s)}})}function t(...e){let t=new Headers;for(let n of e)n&&new Headers(n).forEach((e,n)=>t.set(n,e));return t}function n(n){return e(async(e,r,i)=>{let a={...n,...i},o=a?.timeout||1e4,s=new AbortController,c=a?.method||`POST`,l=`${a.baseUrl}/${e}`,u=t(n?.headers,a?.headers,i?.headers),d=null,f=setTimeout(()=>s.abort(`Timeout: ${o}`),o);switch(!0){case c===`GET`:{if(d=null,!r)break;if(typeof r!=`object`)throw Error(`GET requests params to be an object for query string generation`);let e=Object.entries(r).filter(([,e])=>e!=null).map(([e,t])=>[e,String(t)]),t=new URLSearchParams(e).toString();t&&(l+=`?${t}`);break}case r instanceof FormData:d=r;break;case typeof r==`string`:u.set(`Content-Type`,`text/plain`),d=r;break;default:u.set(`Content-Type`,`application/json`),d=JSON.stringify(r)}try{let e=await fetch(l,{method:c,...d&&{body:d},...a,signal:s.signal,headers:u});if(!e.ok)throw Error(`HTTP error: ${e.statusText} ${e.status} `);let t=e.headers.get(`Content-Type`)||``;switch(!0){case t.includes(`application/json`):return await e.json();case t.includes(`text/`):return await e.text();default:return await e.blob()}}catch(e){throw e.name===`AbortError`?Error(`Request aborted: ${e.message}`):e}finally{clearTimeout(f)}})}function r(t){let{timeout:n=1e4}=t,r=()=>Math.random().toString(36);return e((e,i,a)=>{let o=t.socket(),s=o.readyState;if(typeof s==`number`&&s!==WebSocket.OPEN)return Promise.reject(Error(`WebSocket is not open`));let{promise:c,resolve:l,reject:u}=Promise.withResolvers(),d=a?.timeout??n,f,p=r(),m=e=>{try{let t=JSON.parse(e.data);return t.id===p?(clearTimeout(f),o.removeEventListener(`message`,m),`error`in t?u(t.error):l(t.result)):void 0}catch(e){u(e)}};return o.addEventListener(`message`,m),f=setTimeout(()=>{o.removeEventListener(`message`,m),u(`Timeout: ${d}`)},d),o.send(JSON.stringify({id:p,method:e,params:i})),c})}function i(t){return e((e,n,r)=>{let i=t.pick(e,n,r),a=e.split(`/`).filter(Boolean),o=i;for(let e of a)o[e]&&(o=o[e]);return o(n,r)})}export{n as createHTTPClient,i as createSuperClient,r as createWebSocketClient};
package/dist/context.mjs CHANGED
@@ -1,10 +1 @@
1
- //#region src/context.ts
2
- function isHTTP(context) {
3
- return "request" in context;
4
- }
5
- function isWS(context) {
6
- return "ws" in context;
7
- }
8
-
9
- //#endregion
10
- export { isHTTP, isWS };
1
+ function e(e){return`request`in e}function t(e){return`ws`in e}export{e as isHTTP,t as isWS};
package/dist/cors.mjs CHANGED
@@ -1,58 +1 @@
1
- import { t as toHTTPResponse } from "./response-CNhIkAYG.mjs";
2
-
3
- //#region src/cors.ts
4
- const DEFAULT_HEADERS = {
5
- "Access-Control-Allow-Methods": [
6
- "GET",
7
- "POST",
8
- "PUT",
9
- "PATCH",
10
- "DELETE",
11
- "OPTIONS"
12
- ].join(", "),
13
- "Access-Control-Allow-Headers": [
14
- "Accept-Language",
15
- "Accept",
16
- "Content-Type",
17
- "Content-Language",
18
- "Range"
19
- ].join(", "),
20
- "Access-Control-Expose-Headers": [
21
- "Cache-Control",
22
- "Content-Language",
23
- "Content-Type",
24
- "Expires",
25
- "Last-Modified",
26
- "Pragma"
27
- ].join(", "),
28
- "Access-Control-Max-Age": "3600"
29
- };
30
- function createCORSMiddleware(config) {
31
- const cachedHeaders = {
32
- ...DEFAULT_HEADERS,
33
- ...config.methods?.length && { "Access-Control-Allow-Methods": config.methods.join(", ") },
34
- ...config.allowedHeaders?.length && { "Access-Control-Allow-Headers": config.allowedHeaders.join(", ") },
35
- ...config.exposedHeaders?.length && { "Access-Control-Expose-Headers": config.exposedHeaders.join(", ") },
36
- ...config.credentials && !config.origin.includes("*") && { "Access-Control-Allow-Credentials": "true" },
37
- ...config.maxAge && { "Access-Control-Max-Age": config.maxAge.toString() }
38
- };
39
- return async (options) => {
40
- if (!("request" in options.context)) return options.next();
41
- const origin = options.context.request.headers.get("Origin");
42
- if (!origin || !config.origin.includes(origin)) return options.next();
43
- if (options.context.request.method === "OPTIONS") return new Response(null, {
44
- status: 204,
45
- headers: {
46
- "Access-Control-Allow-Origin": origin,
47
- ...cachedHeaders
48
- }
49
- });
50
- const response = toHTTPResponse(await options.next());
51
- response.headers.set("Access-Control-Allow-Origin", origin);
52
- for (const header in cachedHeaders) response.headers.set(header, cachedHeaders[header]);
53
- return response;
54
- };
55
- }
56
-
57
- //#endregion
58
- export { createCORSMiddleware };
1
+ import{t as e}from"./response-CnnOFeUL.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=e(await t.next());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};
package/dist/crypto.mjs CHANGED
@@ -1,44 +1 @@
1
- import { createCipheriv, createDecipheriv, createHmac, randomBytes, timingSafeEqual } from "node:crypto";
2
-
3
- //#region src/crypto.ts
4
- const ALGO = "aes-256-gcm";
5
- const ENCODING = "base64url";
6
- const IV_LEN = 12;
7
- const TAG_LEN = 16;
8
- function sign(value, secret) {
9
- const base64 = Buffer.from(value).toString(ENCODING);
10
- return `${base64}.${createHmac("sha256", secret).update(base64).digest(ENCODING)}`;
11
- }
12
- function unsign(signedValue, secret) {
13
- const [base64, sig] = signedValue.split(".");
14
- if (!base64 || !sig) return null;
15
- const expectedSig = createHmac("sha256", secret).update(base64).digest(ENCODING);
16
- const a = Buffer.from(sig, ENCODING);
17
- const b = Buffer.from(expectedSig, ENCODING);
18
- if (a.length !== b.length || !timingSafeEqual(a, b)) return null;
19
- return Buffer.from(base64, ENCODING).toString();
20
- }
21
- function encrypt(value, secret) {
22
- const iv = randomBytes(IV_LEN);
23
- const cipher = createCipheriv(ALGO, secret, iv);
24
- let enc = cipher.update(value, "utf-8", ENCODING);
25
- enc += cipher.final(ENCODING);
26
- return Buffer.concat([
27
- iv,
28
- cipher.getAuthTag(),
29
- Buffer.from(enc, ENCODING)
30
- ]).toString(ENCODING);
31
- }
32
- function decrypt(encrypted, secret) {
33
- const data = Buffer.from(encrypted, ENCODING);
34
- if (data.length < IV_LEN + TAG_LEN) return null;
35
- const iv = data.subarray(0, IV_LEN);
36
- const tag = data.subarray(IV_LEN, IV_LEN + TAG_LEN);
37
- const cipherText = data.subarray(IV_LEN + TAG_LEN);
38
- const decipher = createDecipheriv(ALGO, secret, iv);
39
- decipher.setAuthTag(tag);
40
- return `${decipher.update(cipherText, void 0, "utf-8")}${decipher.final("utf-8")}`;
41
- }
42
-
43
- //#endregion
44
- export { decrypt, encrypt, sign, unsign };
1
+ import{createCipheriv as e,createDecipheriv as t,createHmac as n,randomBytes as r,timingSafeEqual as i}from"node:crypto";const a=`aes-256-gcm`,o=`base64url`;function s(e,t){let r=Buffer.from(e).toString(o);return`${r}.${n(`sha256`,t).update(r).digest(o)}`}function c(e,t){let[r,a]=e.split(`.`);if(!r||!a)return null;let s=n(`sha256`,t).update(r).digest(o),c=Buffer.from(a,o),l=Buffer.from(s,o);return c.length!==l.length||!i(c,l)?null:Buffer.from(r,o).toString()}function l(t,n){let i=r(12),s=e(a,n,i),c=s.update(t,`utf-8`,o);return c+=s.final(o),Buffer.concat([i,s.getAuthTag(),Buffer.from(c,o)]).toString(o)}function u(e,n){let r=Buffer.from(e,o);if(r.length<28)return null;let i=r.subarray(0,12),s=r.subarray(12,28),c=r.subarray(28),l=t(a,n,i);return l.setAuthTag(s),`${l.update(c,void 0,`utf-8`)}${l.final(`utf-8`)}`}export{u as decrypt,l as encrypt,s as sign,c as unsign};
@@ -0,0 +1 @@
1
+ var e=class extends Error{status;constructor(e,t,n){super(e),this.name=t,this.status=n}toResponse(){return Response.json({error:{name:this.name,message:this.message}},{status:this.status})}toJSON(){return{name:this.name,message:this.message,status:this.status}}},t=class extends e{constructor(e=`Validation failed`){super(e,`ValidationError`,422)}},n=class extends e{constructor(e=`Unauthorized`){super(e,`UnauthorizedError`,401)}},r=class extends e{constructor(e=`Not Found`){super(e,`NotFoundError`,404)}},i=class extends e{constructor(e=`Unsupported Protocol`){super(e,`UnsupportedProtocolError`,400)}};export{t as a,i,e as n,n as r,r as t};
package/dist/error.mjs CHANGED
@@ -1,3 +1 @@
1
- import { a as ValidationError, i as UnsupportedProtocolError, n as UltraError, r as UnauthorizedError, t as NotFoundError } from "./error-CII1zMOR.mjs";
2
-
3
- export { NotFoundError, UltraError, UnauthorizedError, UnsupportedProtocolError, ValidationError };
1
+ import{a as e,i as t,n,r,t as i}from"./error-Dq1biCC8.mjs";export{i as NotFoundError,n as UltraError,r as UnauthorizedError,t as UnsupportedProtocolError,e as ValidationError};
package/dist/http.mjs CHANGED
@@ -1 +1 @@
1
- export { };
1
+ export{};
@@ -1 +1 @@
1
- export { };
1
+ export{};
@@ -0,0 +1 @@
1
+ import{t as e}from"./validation-BY5LC99k.mjs";var t=class{inputSchema;outputSchema;handlerFunction;middleware=new Set;httpOptions;input(e){return e&&(this.inputSchema=e),this}output(e){return e&&(this.outputSchema=e),this}handler(e){return this.handlerFunction=e,this}http(e){return this.httpOptions={...e,enabled:!0},this}use(e){return this.middleware.add(e),this}wrap(){if(!this.handlerFunction)throw Error(`Procedure handler is not defined`);if(!this.inputSchema&&!this.outputSchema&&!this.middleware.size)return this.handlerFunction;let t=this.handlerFunction;switch(!0){case!this.inputSchema&&!this.outputSchema:break;case!this.inputSchema:{let n=t;t=async t=>e(this.outputSchema,await n(t));break}case!this.outputSchema:{let n=t;t=async t=>n({...t,input:await e(this.inputSchema,t.input)});break}default:{let n=t;t=async t=>{let r=await n({...t,input:await e(this.inputSchema,t.input)});return e(this.outputSchema,r)}}}if(this.middleware.size){let e=Array.from(this.middleware);for(let n=e.length-1;n>=0;n--){let r=e[n],i=t;t=e=>r({...e,next:()=>i(e)})}}return t}getInfo(){return{http:this.httpOptions,hasInput:!!this.inputSchema,hasOutput:!!this.outputSchema}}};export{t};
@@ -1,3 +1 @@
1
- import { t as Procedure } from "./procedure-BN1rLLRX.mjs";
2
-
3
- export { Procedure };
1
+ import{t as e}from"./procedure-DRzVmxaT.mjs";export{e as Procedure};
@@ -0,0 +1 @@
1
+ import{n as e}from"./error-Dq1biCC8.mjs";function t(t){switch(!0){case t instanceof Response:return t;case t instanceof e:return t.toResponse();case t instanceof Error:return new Response(`Internal Server Error`,{status:500});case typeof t==`object`:return Response.json(t);case!t:return new Response(null,{status:204});default:return new Response(String(t))}}function n(t,n){let r;switch(!0){case n instanceof e:r={id:t,error:{code:n.status,message:n.message}};break;case n instanceof Error:r={id:t,error:{code:500,message:n.message}};break;case n instanceof Response:r={id:t,error:{code:n.status,message:n.statusText}};break;case typeof n==`object`||typeof n==`number`||typeof n==`boolean`:r={id:t,result:n};break;default:r={id:t,result:String(n)}}return JSON.stringify(r)}export{n,t};
package/dist/response.mjs CHANGED
@@ -1,3 +1 @@
1
- import { n as toRPCResponse, t as toHTTPResponse } from "./response-CNhIkAYG.mjs";
2
-
3
- export { toHTTPResponse, toRPCResponse };
1
+ import{n as e,t}from"./response-CnnOFeUL.mjs";export{t as toHTTPResponse,e as toRPCResponse};
@@ -0,0 +1 @@
1
+ function e(e){return!!e&&typeof e==`object`&&`id`in e&&`method`in e}export{e as t};
package/dist/rpc.mjs CHANGED
@@ -1,3 +1 @@
1
- import { t as isRPC } from "./rpc-_rBI0z-9.mjs";
2
-
3
- export { isRPC };
1
+ import{t as e}from"./rpc-CAwkzxZe.mjs";export{e as isRPC};
package/dist/session.mjs CHANGED
@@ -1,181 +1 @@
1
- import { i as UnsupportedProtocolError } from "./error-CII1zMOR.mjs";
2
- import { Ultra } from "./ultra.mjs";
3
- import { isHTTP, isWS } from "./context.mjs";
4
- import { sign, unsign } from "./crypto.mjs";
5
- import { randomBytes } from "node:crypto";
6
-
7
- //#region src/session.ts
8
- function defineConfig(config) {
9
- return {
10
- ...config,
11
- cookie: {
12
- path: "/",
13
- httpOnly: true,
14
- secure: true,
15
- sameSite: "lax",
16
- maxAge: config.ttlSec,
17
- ...config?.cookie
18
- }
19
- };
20
- }
21
- /** Extends context and socket data, initiate session instance every request */
22
- function createSessionModule(config) {
23
- return new Ultra().deriveWS((context) => ({ sessionId: Session.getOrCreateId(context.request, config) })).derive((context) => ({ session: new Session(config, context) })).use(async ({ context, next }) => {
24
- await context.session.initiate();
25
- const response = await next();
26
- await context.session.commit();
27
- return response;
28
- });
29
- }
30
- /** Stores the ID in a cookie, then moves it to the socket and uses it for requests */
31
- var Session = class Session {
32
- /** Make random session id */
33
- static makeId() {
34
- return randomBytes(16).toString("base64url");
35
- }
36
- /** Get existing session ID from request cookie or create a new one */
37
- static getOrCreateId(request, config) {
38
- const cookie = request.cookies.get(config.name);
39
- if (cookie) return unsign(cookie, config.secret) || Session.makeId();
40
- return Session.makeId();
41
- }
42
- config;
43
- context;
44
- store;
45
- sessionIdFromClient = null;
46
- sessionId;
47
- sessionState = null;
48
- modified = false;
49
- constructor(config, context) {
50
- this.config = config;
51
- this.context = context;
52
- this.store = config.stores[config.store](config, context);
53
- switch (true) {
54
- case isHTTP(context): {
55
- const cookie = context.request.cookies.get(config.name);
56
- if (cookie) this.sessionIdFromClient = unsign(cookie, config.secret);
57
- break;
58
- }
59
- case isWS(context):
60
- this.sessionIdFromClient = context.ws.data.sessionId || null;
61
- break;
62
- default: throw new UnsupportedProtocolError("Session management is only supported for HTTP and WebSocket protocols.");
63
- }
64
- this.sessionId = this.sessionIdFromClient || Session.makeId();
65
- }
66
- get id() {
67
- return this.sessionId;
68
- }
69
- /** Load data from session store */
70
- async initiate() {
71
- if (this.sessionState) return;
72
- this.sessionState = await this.store.read(this.sessionId) || {};
73
- }
74
- /** Commit data to session store */
75
- async commit() {
76
- this.touch();
77
- if (this.isEmpty && this.sessionIdFromClient) return this.store.destroy(this.sessionIdFromClient);
78
- if (this.sessionIdFromClient && this.sessionIdFromClient !== this.sessionId) {
79
- await this.store.destroy(this.sessionIdFromClient);
80
- await this.store.write(this.sessionId, this.state);
81
- } else if (this.modified) await this.store.write(this.sessionId, this.state);
82
- else await this.store.touch(this.sessionId);
83
- }
84
- /** Change session id */
85
- regenerate() {
86
- this.sessionId = Session.makeId();
87
- }
88
- get(key, defaultValue) {
89
- return this.state[key] ?? defaultValue ?? null;
90
- }
91
- set(key, value) {
92
- this.state[key] = value;
93
- this.modified = true;
94
- }
95
- has(key) {
96
- return Object.hasOwn(this.state, key);
97
- }
98
- all() {
99
- return this.state;
100
- }
101
- delete(key) {
102
- delete this.state[key];
103
- this.modified = true;
104
- }
105
- clear() {
106
- this.sessionState = {};
107
- this.modified = true;
108
- }
109
- get state() {
110
- if (!this.sessionState) throw new Error("Session is not initiated yet.");
111
- return this.sessionState;
112
- }
113
- get isEmpty() {
114
- return Object.keys(this.state).length === 0;
115
- }
116
- touch() {
117
- if ("request" in this.context) this.context.request.cookies.set(this.config.name, sign(this.sessionId, this.config.secret), this.config.cookie);
118
- }
119
- };
120
- var RedisSessionStore = class {
121
- config;
122
- connection;
123
- constructor(config, connection) {
124
- this.config = config;
125
- this.connection = connection;
126
- }
127
- async read(sessionId) {
128
- const value = await this.connection.get(`${this.config.name}:${sessionId}`);
129
- if (!value) return null;
130
- return JSON.parse(value);
131
- }
132
- async write(sessionId, data) {
133
- await this.connection.set(`${this.config.name}:${sessionId}`, JSON.stringify(data), "EX", this.config.ttlSec);
134
- }
135
- async destroy(sessionId) {
136
- await this.connection.del(`${this.config.name}:${sessionId}`);
137
- }
138
- async touch(sessionId) {
139
- await this.connection.expire(`${this.config.name}:${sessionId}`, this.config.ttlSec);
140
- }
141
- };
142
- var MemorySessionStore = class {
143
- config;
144
- sessions = /* @__PURE__ */ new Map();
145
- sweepIntervalMs;
146
- ttlMs;
147
- lastSweepAt = Date.now();
148
- constructor(config, sweepIntervalSec = config.ttlSec) {
149
- this.config = config;
150
- this.sweepIntervalMs = sweepIntervalSec * 1e3;
151
- this.ttlMs = config.ttlSec * 1e3;
152
- }
153
- read(sessionId) {
154
- this.maybeSweep();
155
- return this.sessions.get(sessionId)?.data || null;
156
- }
157
- write(sessionId, data) {
158
- this.maybeSweep();
159
- this.sessions.set(sessionId, {
160
- data,
161
- touched: Date.now()
162
- });
163
- }
164
- destroy(sessionId) {
165
- this.maybeSweep();
166
- this.sessions.delete(sessionId);
167
- }
168
- touch(sessionId) {
169
- this.maybeSweep();
170
- const entry = this.sessions.get(sessionId);
171
- if (entry) entry.touched = Date.now();
172
- }
173
- maybeSweep(now = Date.now()) {
174
- if (now - this.lastSweepAt < this.sweepIntervalMs) return;
175
- this.lastSweepAt = now;
176
- for (const [sessionId, entry] of this.sessions) if (now - entry.touched > this.ttlMs) this.sessions.delete(sessionId);
177
- }
178
- };
179
-
180
- //#endregion
181
- export { MemorySessionStore, RedisSessionStore, Session, createSessionModule, 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{randomBytes as o}from"node:crypto";function s(e){return{...e,cookie:{path:`/`,httpOnly:!0,secure:!0,sameSite:`lax`,maxAge:e.ttlSec,...e?.cookie}}}function c(e){return new t().deriveWS(t=>({sessionId:l.getOrCreateId(t.request,e)})).derive(t=>({session:new l(e,t)})).use(async({context:e,next:t})=>{await e.session.initiate();let n=await t();return await e.session.commit(),n})}var l=class t{static makeId(){return o(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)}},u=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)}},d=class{config;sessions=new Map;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(),this.sessions.get(e)?.data||null}write(e,t){this.maybeSweep(),this.sessions.set(e,{data:t,touched:Date.now()})}destroy(e){this.maybeSweep(),this.sessions.delete(e)}touch(e){this.maybeSweep();let t=this.sessions.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 this.sessions)e-n.touched>this.ttlMs&&this.sessions.delete(t)}}};export{d as MemorySessionStore,u as RedisSessionStore,l as Session,c as createSessionModule,s as defineConfig};
package/dist/types.mjs CHANGED
@@ -1 +1 @@
1
- export { };
1
+ export{};
package/dist/ultra.d.mts CHANGED
@@ -43,7 +43,7 @@ declare class Ultra<Procedures extends ProceduresMap = ProceduresMap, Context ex
43
43
  /** Register procedures */
44
44
  routes<const P extends ProceduresMap>(initializer: ProcedureMapInitializer<P, Context>): Ultra<Procedures & P, Context, SocketData>;
45
45
  /** Register middleware or another Ultra instance */
46
- use<const PluginProcedures extends ProceduresMap, const PluginContext extends BaseContext, const PluginSocketData extends DefaultSocketData>(entity: Middleware<unknown, unknown, Context> | Ultra<PluginProcedures, PluginContext, PluginSocketData>): Ultra<Procedures & PluginProcedures, Context & PluginContext, SocketData & PluginSocketData>;
46
+ use<const PluginProcedures extends ProceduresMap, const PluginContext extends BaseContext, const PluginSocketData extends DefaultSocketData>(entity: Middleware<any, any, Context> | Ultra<PluginProcedures, PluginContext, PluginSocketData>): Ultra<Procedures & PluginProcedures, Context & PluginContext, SocketData & PluginSocketData>;
47
47
  /** Extends context values for every request with provided values */
48
48
  derive<const D extends DeriveValue<Context>>(derive: D): Ultra<Procedures, Context & ExtractDerive<Context, D>, SocketData>;
49
49
  /** Extends WS data for every ws connection */