@sx3/ultra 0.0.1

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 (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +512 -0
  3. package/dist/auth.d.mts +56 -0
  4. package/dist/auth.mjs +84 -0
  5. package/dist/client.d.mts +27 -0
  6. package/dist/client.mjs +131 -0
  7. package/dist/context-ChCsZh7S.d.mts +17 -0
  8. package/dist/context.d.mts +2 -0
  9. package/dist/context.mjs +10 -0
  10. package/dist/cors.d.mts +16 -0
  11. package/dist/cors.mjs +58 -0
  12. package/dist/crypto.d.mts +7 -0
  13. package/dist/crypto.mjs +44 -0
  14. package/dist/error-CII1zMOR.mjs +45 -0
  15. package/dist/error.d.mts +25 -0
  16. package/dist/error.mjs +3 -0
  17. package/dist/http-BqWCMASL.d.mts +10 -0
  18. package/dist/http.d.mts +3 -0
  19. package/dist/http.mjs +1 -0
  20. package/dist/middleware-COKreBGP.d.mts +43 -0
  21. package/dist/middleware.d.mts +4 -0
  22. package/dist/middleware.mjs +1 -0
  23. package/dist/procedure-BN1rLLRX.mjs +86 -0
  24. package/dist/procedure.d.mts +4 -0
  25. package/dist/procedure.mjs +3 -0
  26. package/dist/response-CNhIkAYG.mjs +59 -0
  27. package/dist/response.d.mts +5 -0
  28. package/dist/response.mjs +3 -0
  29. package/dist/rpc-Ch2UXReT.d.mts +23 -0
  30. package/dist/rpc-_rBI0z-9.mjs +7 -0
  31. package/dist/rpc.d.mts +2 -0
  32. package/dist/rpc.mjs +3 -0
  33. package/dist/session.d.mts +115 -0
  34. package/dist/session.mjs +181 -0
  35. package/dist/types-Cn69QrjS.d.mts +11 -0
  36. package/dist/types.d.mts +2 -0
  37. package/dist/types.mjs +1 -0
  38. package/dist/ultra.d.mts +69 -0
  39. package/dist/ultra.mjs +273 -0
  40. package/dist/validation-CkRfxQJ_.d.mts +57 -0
  41. package/dist/validation-Cop5Wvlr.mjs +12 -0
  42. package/dist/validation.d.mts +2 -0
  43. package/dist/validation.mjs +3 -0
  44. package/package.json +55 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-PRESENT SX3 <https://github.com/SX-3>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,512 @@
1
+ # Ultra
2
+
3
+ Type-safe and fast RPC over HTTP/WebSocket for [Bun](https://bun.sh).
4
+
5
+ ## Оглавление
6
+
7
+ - [Install](#install)
8
+ - [Quick start](#quick-start)
9
+ - [Core concepts](#core-concepts)
10
+ - [Modules](#modules)
11
+ - [Type safety](#type-safety)
12
+ - [Protocol independence](#protocol-independence)
13
+ - [Middleware](#middleware)
14
+ - [Validation](#validation)
15
+ - [Context](#context)
16
+ - [Built-in features](#built-in-features)
17
+ - [CORS](#cors)
18
+ - [Sessions](#sessions)
19
+ - [Authentication](#authentication)
20
+ - [Crypto](#crypto)
21
+
22
+ ---
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ bun add @sx3/ultra
28
+ ```
29
+
30
+ ## Quick start
31
+
32
+ Write a simple server with two modules: users and books.
33
+
34
+ ```ts
35
+ // server.ts
36
+ import { Ultra } from '@sx3/ultra';
37
+
38
+ // User module
39
+ const users = new Ultra().routes(input => ({
40
+ users: {
41
+ list: input().http().handler(() => [
42
+ { id: 1, name: 'Alice' },
43
+ { id: 2, name: 'Bob' }
44
+ ])
45
+ }
46
+ }));
47
+
48
+ // Book module
49
+ const books = new Ultra().routes(input => ({
50
+ books: {
51
+ list: input().http().handler(() => [
52
+ { id: 1, title: 'TypeScript' },
53
+ { id: 2, title: 'Brave New World' }
54
+ ]),
55
+ }
56
+ }));
57
+
58
+ // Root module
59
+ const server = new Ultra()
60
+ .use(users)
61
+ .use(books)
62
+ .on('server:started', (bunServer) => {
63
+ console.log(`Server started at ${bunServer.url}`);
64
+ })
65
+ .start();
66
+
67
+ // Type for client usage
68
+ export type Server = typeof server;
69
+ ```
70
+
71
+ Create a client to call the server methods.
72
+
73
+ ```ts
74
+ // clients.ts
75
+ import type { Server } from './server';
76
+ import { createHTTPClient } from '@sx3/ultra/client';
77
+
78
+ const http = createHTTPClient<Server>({
79
+ baseUrl: 'http://localhost:3000',
80
+ });
81
+
82
+ const users = await http.users.list(); // [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
83
+ const books = await http.books.list(); // [{ id: 1, title: 'TypeScript' }, { id: 2, title: 'Brave New World' }]
84
+ ```
85
+
86
+ Create WebSocket client to call server methods over WebSocket.
87
+
88
+ ```ts
89
+ // clients.ts
90
+ import type { Server } from './server';
91
+ import { createWebSocketClient } from '@sx3/ultra/client';
92
+
93
+ let socket = new WebSocket('ws://localhost:3000/ws');
94
+ const ws = createWebSocketClient<Server>({
95
+ // Socket getter function
96
+ socket: () => socket,
97
+ });
98
+
99
+ const users = await ws.users.list(); // [{ id: 1, name: 'Alice' } ...]
100
+ ```
101
+
102
+ Or create [super client](#protocol-independence) for dynamic transport switching.
103
+
104
+ ## Middleware
105
+
106
+ Middleware just functions that run before your route handlers. You can use them to add authentication, logging, error handling, etc.
107
+
108
+ ```ts
109
+ import { Ultra } from '@sx3/ultra';
110
+ import { UnauthorizedError } from '@sx3/ultra/error';
111
+
112
+ // Simple authentication middleware
113
+ async function isAuthenticated({ context, next }) {
114
+ if (!await context.auth.check()) return new UnauthorizedError();
115
+ return next();
116
+ }
117
+
118
+ const app = new Ultra()
119
+ .use(isAuthenticated) // Apply middleware globally
120
+ .routes(input => ({
121
+ profile: {
122
+ get: input()
123
+ .use(isAuthenticated) // Apply middleware to specific route
124
+ .http()
125
+ .handler(({ context }) => {
126
+ return context.auth.user; // Access authenticated user
127
+ }),
128
+ },
129
+ }));
130
+ ```
131
+
132
+ ## Validation
133
+
134
+ Ultra supports any library compatible with [Standard Schema](https://standardschema.dev/schema#what-schema-libraries-implement-the-spec).
135
+
136
+ ```ts
137
+ import { Ultra } from '@sx3/ultra';
138
+ import { createHTTPClient } from '@sx3/ultra/client';
139
+ // import * as z from 'zod';
140
+ import * as s from 'sury';
141
+
142
+ const LoginSchema = s.schema({
143
+ name: s.string(),
144
+ password: s.string(),
145
+ });
146
+
147
+ const UserSchema = s.schema({
148
+ id: s.number(),
149
+ name: s.string(),
150
+ });
151
+
152
+ const auth = new Ultra().routes(input => ({
153
+ auth: {
154
+ // Schema for runtime input validation
155
+ login: input(LoginSchema)
156
+ // Schema for runtime output validation
157
+ .output(UserSchema)
158
+ .http()
159
+ .handler(({ input }) => {
160
+ // input is typed and validated as { name: string; password: string }
161
+ const user = { id: 1, name: input.name };
162
+
163
+ return user;
164
+ }),
165
+ }
166
+ }));
167
+
168
+ const client = createHTTPClient<typeof auth>({
169
+ baseUrl: 'http://localhost:3000',
170
+ });
171
+
172
+ const user = await client.auth.login({ name: 'Alice', password: 'secret' }); // user is typed as { id: number; name: string }
173
+ ```
174
+
175
+ Difference between runtime validation and TypeScript types:
176
+
177
+ ```ts
178
+ import * as z from 'zod';
179
+
180
+ const api = new Ultra().routes(input => ({
181
+ // Ultra checks input and output data
182
+ validated: input(z.object({ a: z.number(), b: z.number() }))
183
+ .output(z.number())
184
+ .http()
185
+ .handler(({ input }) => {
186
+ // input is typed and validated as { a: number; b: number }
187
+ return input.a + input.b;
188
+ }),
189
+
190
+ // You are confident in your types and don't want to waste CPU/memory on validation.
191
+ typed: input<{ a: number; b: number }>()
192
+ .output<number>()
193
+ .http()
194
+ .handler(({ input }) => {
195
+ // input is typed as { a: number; b: number } but NOT validated
196
+ return input.a + input.b;
197
+ }),
198
+ }));
199
+ ```
200
+
201
+ ## Context
202
+
203
+ Ultra provides context system that allows you to share data across your application.
204
+ You can extend the context with a function or value. Example from session module:
205
+
206
+ ```ts
207
+ // session.ts
208
+
209
+ export function createSessionModule<S extends Record<string, SessionStoreFactory>>(config: SessionConfig<S>) {
210
+ // Create module
211
+ return new Ultra()
212
+ // deriveWS to add sessionId to WebSocket data object | run each socket connection | use for store data in WS connection
213
+ .deriveWS((context: HTTPContext) => ({ sessionId: Session.getOrCreateId(context.request, config) }))
214
+ // derive function add session instance to context | run each request
215
+ .derive(context => ({ session: new Session(config, context) }))
216
+ // Middleware to initiate and commit session on each request
217
+ .use(async ({ context, next }) => {
218
+ await context.session.initiate();
219
+ const response = await next();
220
+ await context.session.commit();
221
+ return response;
222
+ });
223
+ }
224
+ ```
225
+
226
+ You can add a static value for each request:
227
+
228
+ ```ts
229
+ const app = new Ultra().derive({ appName: 'My Ultra App' });
230
+ ```
231
+
232
+ ## Core concepts
233
+
234
+ ### Modules
235
+
236
+ Each module is a self-contained application.
237
+
238
+ ```ts
239
+ // auth.ts
240
+
241
+ // This is a self-contained application. It declares all its dependencies.
242
+ const auth = new Ultra()
243
+ .use(cors) // Use CORS middleware
244
+ .use(session) // Use session module
245
+ .routes(input => ({
246
+ auth: {
247
+ login: input(s.schema({ login: s.string(), password: s.string() }))
248
+ .http()
249
+ .handler(({ input }) => {
250
+ // Handle login
251
+ }),
252
+ }
253
+ }));
254
+
255
+ // You can run it independently
256
+ auth.start();
257
+
258
+ // Or use it as a module in another application
259
+ const main = new Ultra()
260
+ .use(auth)
261
+ .start();
262
+ ```
263
+
264
+ You can use modules as many times as you like.
265
+
266
+ ```ts
267
+ const moduleA = new Ultra();
268
+
269
+ const moduleB = new Ultra()
270
+ .use(moduleA); // Use first time
271
+
272
+ const moduleC = new Ultra()
273
+ .use(moduleB)
274
+ .use(moduleA); // Use second time
275
+
276
+ const mainApp = new Ultra()
277
+ .use(moduleA)
278
+ .use(moduleB)
279
+ .use(moduleC)
280
+ .start();
281
+ ```
282
+
283
+ It may seem like modules will be duplicated and cause conflicts, but Ultra, under the hood, deduplicates everything that is connected to it.
284
+
285
+ This applies not only to modules:
286
+
287
+ ```ts
288
+ // Derive function
289
+ function requestIdDerive(context) {
290
+ console.log('Deriving!');
291
+ return { requestId: crypto.randomUUID() };
292
+ }
293
+
294
+ // Middleware
295
+ async function logger({ next }) {
296
+ console.log('Request!');
297
+ return next();
298
+ }
299
+
300
+ // Routes
301
+ function routes(input) {
302
+ return {
303
+ ping: input().http().handler(() => {
304
+ console.log('Handling ping!');
305
+ return 'pong';
306
+ }),
307
+ };
308
+ }
309
+
310
+ const a = new Ultra()
311
+ .derive(requestIdDerive)
312
+ .use(logger)
313
+ .routes(routes);
314
+
315
+ const b = new Ultra()
316
+ .derive(requestIdDerive)
317
+ .use(logger)
318
+ .routes(routes);
319
+
320
+ const app = new Ultra()
321
+ .derive(requestIdDerive)
322
+ .use(logger)
323
+ .use(a)
324
+ .use(b)
325
+ .routes(routes)
326
+ .start();
327
+
328
+ fetch('http://localhost:3000/ping'); // Printed: Deriving!, Request!, Handling ping!
329
+ ```
330
+
331
+ ### Type safety
332
+
333
+ Ultra provides end-to-end type safety for your server and clients.
334
+
335
+ ```ts
336
+ import { Ultra } from '@sx3/ultra';
337
+ import { createSuperClient } from '@sx3/ultra/client';
338
+
339
+ const math = new Ultra().routes(input => ({
340
+ math: {
341
+ add: input<{ a: number; b: number }>()
342
+ .http()
343
+ .handler(({ input }) => {
344
+ // input is typed as { a: number; b: number }
345
+ return input.a + input.b;
346
+ }),
347
+ }
348
+ }));
349
+
350
+ const client = createSuperClient<typeof math>({/** ... */});
351
+
352
+ const result = await client.math.add({ a: 1, b: 2 }); // the result is automatically inferred as a number
353
+ ```
354
+
355
+ ### Protocol independence
356
+
357
+ Ultra strives to be independent of specific protocols. You simply call functions and the application decides how to send the data.
358
+
359
+ ```ts
360
+ // clients.ts
361
+ import type { Server } from './server';
362
+ import { createHTTPClient, createSuperClient, createWebSocketClient } from '@sx3/ultra/client';
363
+
364
+ const http = createHTTPClient<Server>({
365
+ baseUrl: 'http://localhost:3000',
366
+ });
367
+
368
+ let socket = new WebSocket('ws://localhost:3000/ws');
369
+ const ws = createWebSocketClient<Server>({
370
+ socket: () => socket,
371
+ });
372
+
373
+ const api = createSuperClient<Server>({
374
+ // Transport picker function | if WebSocket is open, use it; otherwise, use HTTP
375
+ pick: (method: string, params: unknown, options?: any) => {
376
+ if (socket.readyState === WebSocket.OPEN) return ws;
377
+ return http;
378
+ }
379
+ });
380
+
381
+ const users = await api.users.list(); // [{ id: 1, name: 'Alice' } ...]
382
+ ```
383
+
384
+ Currently only HTTP and WebSockets are supported.
385
+
386
+ ## Built-in features
387
+
388
+ Ultra has several built-in features to make your life easier.
389
+
390
+ ### CORS
391
+
392
+ ```ts
393
+ import { Ultra } from '@sx3/ultra';
394
+ import { createCORSMiddleware } from '@sx3/ultra/cors';
395
+
396
+ const cors = createCORSMiddleware({
397
+ origin: ['http://localhost:5173'],
398
+ credentials: true,
399
+ // methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
400
+ // allowedHeaders: ['Content-Type', 'Authorization'],
401
+ // exposedHeaders: ['X-Custom-Header'],
402
+ // maxAge: 3600,
403
+ });
404
+
405
+ const app = new Ultra().use(cors); // Apply CORS middleware globally
406
+ ```
407
+
408
+ ### Sessions
409
+
410
+ Multiple session stores are supported: in-memory, Redis, and custom stores.
411
+
412
+ ```ts
413
+ // session.ts
414
+ import { env } from '#app/env';
415
+ import { createSessionModule, defineConfig, MemorySessionStore, RedisSessionStore } from '@/sx3/ultra/session';
416
+
417
+ export const config = defineConfig({
418
+ // Name for cookie or prefix for redis key
419
+ name: 'session',
420
+ ttl: 3600, // 1 hour
421
+ store: 'redis',
422
+ secret: env.APP_KEY,
423
+ cookie: {
424
+ path: '/',
425
+ httpOnly: true,
426
+ secure: env.NODE_ENV === 'production',
427
+ sameSite: 'lax',
428
+ },
429
+ stores: {
430
+ redis: config => new RedisSessionStore(config, redis),
431
+ memory: config => new MemorySessionStore(config),
432
+ },
433
+ });
434
+
435
+ export const session = createSessionModule(config);
436
+
437
+ // server.ts
438
+ import { Ultra } from '@sx3/ultra';
439
+ import { session } from './session';
440
+
441
+ const app = new Ultra().use(session).routes(input => ({
442
+ profile: {
443
+ get: input().http().handler(({ context: { session } }) => {
444
+ // Access session data
445
+ session.get('user');
446
+ session.set('user', { id: 1, name: 'Alice' });
447
+ }),
448
+ },
449
+ })).start();
450
+ ```
451
+
452
+ ### Authentication
453
+
454
+ Auth module requires [session module](#sessions).
455
+
456
+ ```ts
457
+ // auth.ts
458
+ import { Ultra } from '@sx3/ultra';
459
+ import { createAuthModule, defineConfig, SessionAuthProvider } from '@sx3/ultra/auth';
460
+
461
+ interface User {
462
+ name: string;
463
+ age: number;
464
+ }
465
+
466
+ const config = defineConfig<User>({
467
+ provider: 'session',
468
+ providers: {
469
+ session: context => new SessionAuthProvider<User>(context),
470
+ },
471
+ });
472
+
473
+ export const auth = createAuthModule<User>(config);
474
+
475
+ // server.ts
476
+ import { auth } from './auth';
477
+ import { session } from './session';
478
+ import { isAuthenticated, isGuest } from '@sx3/ultra/auth';
479
+
480
+ const app = new Ultra()
481
+ .use(session)
482
+ .use(auth)
483
+ .routes(input => ({
484
+ // Just example
485
+ auth: {
486
+ login: input(LoginSchema)
487
+ .output(UserSchema)
488
+ .http()
489
+ .use(isGuest)
490
+ .handler(async ({ input, context }) => {
491
+ // ... check credentials logic
492
+ // then
493
+ await context.auth.login(user);
494
+ return user;
495
+ }),
496
+
497
+ logout: input()
498
+ .http()
499
+ .use(isAuthenticated)
500
+ .handler(({ context }) => context.auth.logout()),
501
+
502
+ profile: input().use(isAuthenticated).http().handler(({ context }) => context.auth.user!),
503
+ }
504
+ }))
505
+ .start();
506
+ ```
507
+
508
+ ### Crypto
509
+
510
+ Crypto functions are available [here](https://github.com/SX-3/ultra/blob/main/src/crypto.ts).
511
+
512
+ Inspired by [Elysia](https://elysiajs.com/) and [oRPC](https://orpc.dev/) powered by [Bun](https://bun.sh).
@@ -0,0 +1,56 @@
1
+ import { n as DefaultSocketData, t as BaseContext } from "./context-ChCsZh7S.mjs";
2
+ import { o as Promisable, r as JSONObject } from "./types-Cn69QrjS.mjs";
3
+ import "./http-BqWCMASL.mjs";
4
+ import { t as Middleware } from "./middleware-COKreBGP.mjs";
5
+ import { ProceduresMap, Ultra } from "./ultra.mjs";
6
+ import { Session } from "./session.mjs";
7
+
8
+ //#region src/auth.d.ts
9
+ interface AuthProvider<User> {
10
+ user: User | null;
11
+ check: () => Promisable<boolean>;
12
+ login: (user: User) => Promisable<void>;
13
+ logout: () => Promisable<void>;
14
+ setUser: (user: User) => Promisable<void>;
15
+ }
16
+ type AuthProviderFactory<User = any> = (context: BaseContext) => AuthProvider<User>;
17
+ interface AuthConfig<P extends Record<string, AuthProviderFactory> = Record<string, AuthProviderFactory>> {
18
+ provider: keyof P;
19
+ providers: P;
20
+ }
21
+ type AuthContext<User extends JSONObject> = BaseContext & {
22
+ session: Session;
23
+ auth: Auth<User>;
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 & {
27
+ auth: Auth<User, P>;
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>>> {
32
+ protected readonly config: AuthConfig<Providers>;
33
+ protected readonly context: BaseContext;
34
+ protected readonly usingProvider: keyof Providers;
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>>);
37
+ use(provider: keyof Providers): Auth<User, Providers>;
38
+ get user(): User | null;
39
+ check(): Promisable<boolean>;
40
+ login(user: User): Promisable<void>;
41
+ logout(): Promisable<void>;
42
+ setUser(user: User): Promisable<void>;
43
+ protected get provider(): AuthProvider<User>;
44
+ }
45
+ declare class SessionAuthProvider<User extends JSONObject> implements AuthProvider<User> {
46
+ protected readonly context: AuthContext<User>;
47
+ protected readonly sessionKey: string;
48
+ constructor(context: AuthContext<User>, sessionKey?: string);
49
+ get user(): User;
50
+ check(): boolean;
51
+ login(user: User): void;
52
+ logout(): void;
53
+ setUser(user: User): void;
54
+ }
55
+ //#endregion
56
+ export { Auth, AuthContext, AuthProvider, SessionAuthProvider, createAuthModule, defineConfig, isAuthenticated, isGuest };
package/dist/auth.mjs ADDED
@@ -0,0 +1,84 @@
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 };
@@ -0,0 +1,27 @@
1
+ import "./context-ChCsZh7S.mjs";
2
+ import "./http-BqWCMASL.mjs";
3
+ import { i as Procedure } from "./middleware-COKreBGP.mjs";
4
+ import { ProceduresMap, Ultra } from "./ultra.mjs";
5
+
6
+ //#region src/client.d.ts
7
+ type GetProcedures<T> = T extends Ultra<infer P> ? P : never;
8
+ type BuildProcedure<P, CO> = P extends Procedure<infer I, infer O, any> ? (undefined extends I ? (input?: I, callOptions?: CO) => Promise<O> : (input: I, callOptions?: CO) => Promise<O>) : never;
9
+ type BuildClient<P extends ProceduresMap, CO> = { [K in keyof P]: P[K] extends Procedure<any, any, any> ? BuildProcedure<P[K], CO> : P[K] extends ProceduresMap ? BuildClient<P[K], CO> : never };
10
+ type Invoke<CO> = (method: string, params: unknown, callOptions?: CO) => Promise<unknown>;
11
+ interface HTTPClientOptions extends Omit<RequestInit, 'body'> {
12
+ baseUrl: string;
13
+ timeout?: number;
14
+ }
15
+ declare function createHTTPClient<B extends Ultra>(clientOptions: HTTPClientOptions): BuildClient<GetProcedures<B>, Partial<HTTPClientOptions>>;
16
+ interface WebSocketClientOptions {
17
+ socket: () => WebSocket;
18
+ timeout?: number;
19
+ }
20
+ declare function createWebSocketClient<B extends Ultra>(options: WebSocketClientOptions): BuildClient<GetProcedures<B>, Partial<WebSocketClientOptions>>;
21
+ type ClientsCallsParams = Partial<WebSocketClientOptions> | Partial<HTTPClientOptions>;
22
+ interface SuperClientOptions<B extends Ultra> {
23
+ pick: (...args: Parameters<Invoke<ClientsCallsParams>>) => BuildClient<GetProcedures<B>, ClientsCallsParams>;
24
+ }
25
+ declare function createSuperClient<B extends Ultra>(options: SuperClientOptions<B>): BuildClient<GetProcedures<B>, ClientsCallsParams>;
26
+ //#endregion
27
+ export { createHTTPClient, createSuperClient, createWebSocketClient };