@elsium-ai/app 0.2.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -332,6 +332,104 @@ app.use('*', rateLimitMiddleware({
332
332
 
333
333
  ---
334
334
 
335
+ ## SSE Utilities
336
+
337
+ Helper functions for building Server-Sent Events responses in Hono handlers.
338
+
339
+ ### `sseHeaders`
340
+
341
+ A constant object containing the standard HTTP headers for SSE responses.
342
+
343
+ ```ts
344
+ const sseHeaders: Record<string, string>
345
+ // { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }
346
+ ```
347
+
348
+ ### `formatSSE`
349
+
350
+ Formats an event name and data payload into the SSE wire format.
351
+
352
+ ```ts
353
+ function formatSSE(event: string, data: unknown): string
354
+ ```
355
+
356
+ | Parameter | Type | Description |
357
+ | --- | --- | --- |
358
+ | `event` | `string` | The SSE event name. |
359
+ | `data` | `unknown` | The data payload (will be JSON-stringified). |
360
+
361
+ **Returns:** A formatted SSE string (e.g., `event: text_delta\ndata: {"text":"Hello"}\n\n`).
362
+
363
+ ### `streamResponse`
364
+
365
+ Converts a `ReadableStream` into a Hono `Response` with the correct SSE headers.
366
+
367
+ ```ts
368
+ function streamResponse(stream: ReadableStream): Response
369
+ ```
370
+
371
+ | Parameter | Type | Description |
372
+ | --- | --- | --- |
373
+ | `stream` | `ReadableStream` | The stream to send as the response body. |
374
+
375
+ **Returns:** A `Response` object with SSE headers.
376
+
377
+ ```ts
378
+ import { sseHeaders, formatSSE, streamResponse } from '@elsium-ai/app'
379
+
380
+ // In a Hono route handler
381
+ app.post('/my-stream', (c) => {
382
+ const stream = new ReadableStream({
383
+ start(controller) {
384
+ controller.enqueue(new TextEncoder().encode(formatSSE('text_delta', { text: 'Hello' })))
385
+ controller.enqueue(new TextEncoder().encode(formatSSE('message_end', { done: true })))
386
+ controller.close()
387
+ },
388
+ })
389
+ return streamResponse(stream)
390
+ })
391
+ ```
392
+
393
+ ---
394
+
395
+ ## Tenant Budget Middleware
396
+
397
+ ### `tenantBudgetMiddleware`
398
+
399
+ Creates a Hono middleware that enforces per-tenant token and cost budgets using sliding windows. Each tenant is identified from the request context and tracked independently.
400
+
401
+ ```ts
402
+ function tenantBudgetMiddleware(config?: {
403
+ windowMs?: number
404
+ maxTokensPerWindow?: number
405
+ maxCostPerWindow?: number
406
+ }): (c: Context, next: Next) => Promise<Response | void>
407
+ ```
408
+
409
+ | Parameter | Type | Default | Description |
410
+ | --- | --- | --- | --- |
411
+ | `config.windowMs` | `number` | `60_000` | Sliding window duration in milliseconds. |
412
+ | `config.maxTokensPerWindow` | `number` | `undefined` | Maximum tokens allowed per tenant per window. |
413
+ | `config.maxCostPerWindow` | `number` | `undefined` | Maximum cost (USD) allowed per tenant per window. |
414
+
415
+ **Responses on failure:**
416
+ - `429` with `{ error: 'Tenant budget exceeded' }` when the tenant's usage exceeds the configured limits.
417
+
418
+ ```ts
419
+ import { tenantBudgetMiddleware } from '@elsium-ai/app'
420
+ import { Hono } from 'hono'
421
+
422
+ const app = new Hono()
423
+
424
+ app.use('*', tenantBudgetMiddleware({
425
+ windowMs: 60_000,
426
+ maxTokensPerWindow: 100_000,
427
+ maxCostPerWindow: 1.0,
428
+ }))
429
+ ```
430
+
431
+ ---
432
+
335
433
  ## Routes
336
434
 
337
435
  ### `createRoutes`
package/dist/index.d.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  export { createApp } from './app';
2
2
  export type { ElsiumApp } from './app';
3
- export type { AppConfig, ServerConfig, CorsConfig, AuthConfig, RateLimitConfig, ChatRequest, ChatResponse, CompleteRequest, HealthResponse, MetricsResponse, } from './types';
3
+ export type { AppConfig, ServerConfig, CorsConfig, AuthConfig, RateLimitConfig, ChatRequest, ChatResponse, CompleteRequest, HealthResponse, MetricsResponse, StreamChatEvent, StreamCompleteEvent, } from './types';
4
+ export { sseHeaders, formatSSE, streamResponse } from './sse';
4
5
  export { corsMiddleware, authMiddleware, rateLimitMiddleware, requestIdMiddleware, requestLoggerMiddleware, } from './middleware';
5
6
  export { createRoutes } from './routes';
6
7
  export type { RoutesDeps } from './routes';
7
8
  export { createRBAC } from './rbac';
8
9
  export type { Permission, Role, RBACConfig, RBAC } from './rbac';
10
+ export { tenantMiddleware, tenantRateLimitMiddleware, tenantBudgetMiddleware } from './tenant';
11
+ export type { TenantMiddlewareConfig } from './tenant';
9
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,YAAY,EACX,SAAS,EACT,YAAY,EACZ,UAAU,EACV,UAAU,EACV,eAAe,EACf,WAAW,EACX,YAAY,EACZ,eAAe,EACf,cAAc,EACd,eAAe,GACf,MAAM,SAAS,CAAA;AAGhB,OAAO,EACN,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,GACvB,MAAM,cAAc,CAAA;AAGrB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1C,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACnC,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtC,YAAY,EACX,SAAS,EACT,YAAY,EACZ,UAAU,EACV,UAAU,EACV,eAAe,EACf,WAAW,EACX,YAAY,EACZ,eAAe,EACf,cAAc,EACd,eAAe,EACf,eAAe,EACf,mBAAmB,GACnB,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,OAAO,CAAA;AAG7D,OAAO,EACN,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,GACvB,MAAM,cAAc,CAAA;AAGrB,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AACvC,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1C,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACnC,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAGhE,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA;AAC9F,YAAY,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAA"}