@avtechno/sfr 1.0.18 → 2.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 (42) hide show
  1. package/README.md +893 -45
  2. package/dist/index.mjs +20 -2
  3. package/dist/logger.mjs +9 -37
  4. package/dist/mq.mjs +46 -0
  5. package/dist/observability/index.mjs +143 -0
  6. package/dist/observability/logger.mjs +128 -0
  7. package/dist/observability/metrics.mjs +177 -0
  8. package/dist/observability/middleware/mq.mjs +156 -0
  9. package/dist/observability/middleware/rest.mjs +120 -0
  10. package/dist/observability/middleware/ws.mjs +135 -0
  11. package/dist/observability/tracer.mjs +163 -0
  12. package/dist/sfr-pipeline.mjs +412 -12
  13. package/dist/templates.mjs +8 -1
  14. package/dist/types/index.d.mts +8 -1
  15. package/dist/types/logger.d.mts +9 -3
  16. package/dist/types/mq.d.mts +19 -0
  17. package/dist/types/observability/index.d.mts +45 -0
  18. package/dist/types/observability/logger.d.mts +54 -0
  19. package/dist/types/observability/metrics.d.mts +74 -0
  20. package/dist/types/observability/middleware/mq.d.mts +46 -0
  21. package/dist/types/observability/middleware/rest.d.mts +33 -0
  22. package/dist/types/observability/middleware/ws.d.mts +35 -0
  23. package/dist/types/observability/tracer.d.mts +90 -0
  24. package/dist/types/sfr-pipeline.d.mts +42 -1
  25. package/dist/types/templates.d.mts +1 -6
  26. package/package.json +29 -4
  27. package/src/index.mts +66 -3
  28. package/src/logger.mts +16 -51
  29. package/src/mq.mts +49 -0
  30. package/src/observability/index.mts +184 -0
  31. package/src/observability/logger.mts +169 -0
  32. package/src/observability/metrics.mts +266 -0
  33. package/src/observability/middleware/mq.mts +187 -0
  34. package/src/observability/middleware/rest.mts +143 -0
  35. package/src/observability/middleware/ws.mts +162 -0
  36. package/src/observability/tracer.mts +205 -0
  37. package/src/sfr-pipeline.mts +468 -18
  38. package/src/templates.mts +14 -5
  39. package/src/types/index.d.ts +240 -16
  40. package/dist/example.mjs +0 -33
  41. package/dist/types/example.d.mts +0 -11
  42. package/src/example.mts +0 -35
@@ -37,16 +37,121 @@ declare type RESTHandlerDescriptor<V, H, C> = {
37
37
  };
38
38
 
39
39
  declare type WSHandlerDescriptor<V, H, C> = {
40
- cfg?: SFRConfig;
40
+ cfg?: WSConfig;
41
41
  validators: RequestValidators & V;
42
- handlers: WSRequestHandlers & H & ThisType<HandlerFacilities & C>;
43
- controllers?: RequestControllers & C & ThisType<ControllerFacilities & C>;
42
+ handlers: WSRequestHandlers & H & ThisType<WSHandlerFacilities & C>;
43
+ controllers?: RequestControllers & C & ThisType<ControllerFacilities>;
44
44
  };
45
45
 
46
+ /**
47
+ * WebSocket-specific configuration extending base SFRConfig
48
+ */
49
+ declare type WSConfig = SFRConfig & {
50
+ /**
51
+ * Socket.IO namespace to use (e.g., "/chat", "/notifications")
52
+ * Defaults to "/" if not specified
53
+ */
54
+ namespace?: string;
55
+ };
56
+
57
+ /**
58
+ * Facilities injected into WS handlers
59
+ */
60
+ declare interface WSHandlerFacilities extends HandlerFacilities {
61
+ /** The Socket.IO server instance */
62
+ io: Server;
63
+ /** The current socket connection */
64
+ socket: Socket;
65
+ }
66
+
46
67
  declare interface HandlerFacilities { }
47
68
 
48
69
  declare interface ControllerFacilities { }
49
70
 
71
+ /**
72
+ * Authentication middleware function signature.
73
+ * Return `true` to allow the request, `false` to deny, or an object with error details.
74
+ */
75
+ declare type AuthMiddleware = (
76
+ req: ExpressRequest,
77
+ res: ExpressResponse
78
+ ) => boolean | { error: string; status?: number } | Promise<boolean | { error: string; status?: number }>;
79
+
80
+ /**
81
+ * Authentication configuration for SFR
82
+ */
83
+ declare type AuthConfig = {
84
+ /**
85
+ * Custom authentication middleware function.
86
+ * Called for all non-public routes before the handler executes.
87
+ */
88
+ middleware?: AuthMiddleware;
89
+ }
90
+
91
+ /**
92
+ * Rate limit configuration options.
93
+ * Compatible with express-rate-limit configuration.
94
+ */
95
+ declare type RateLimitConfig = {
96
+ /**
97
+ * Maximum number of requests allowed within the window.
98
+ * @default 100
99
+ */
100
+ max?: number;
101
+ /**
102
+ * Time window in milliseconds.
103
+ * @default 60000 (1 minute)
104
+ */
105
+ windowMs?: number;
106
+ /**
107
+ * Message to return when rate limit is exceeded.
108
+ * @default "Too many requests, please try again later."
109
+ */
110
+ message?: string | object;
111
+ /**
112
+ * HTTP status code to return when rate limit is exceeded.
113
+ * @default 429
114
+ */
115
+ statusCode?: number;
116
+ /**
117
+ * Whether to include rate limit headers in the response.
118
+ * @default true
119
+ */
120
+ standardHeaders?: boolean;
121
+ /**
122
+ * Whether to include legacy rate limit headers.
123
+ * @default false
124
+ */
125
+ legacyHeaders?: boolean;
126
+ /**
127
+ * Custom key generator function. By default, uses req.ip.
128
+ * @param req - Express request object
129
+ * @returns Key to identify the client
130
+ */
131
+ keyGenerator?: (req: ExpressRequest) => string;
132
+ /**
133
+ * Custom skip function. Return true to skip rate limiting for this request.
134
+ * @param req - Express request object
135
+ * @returns Whether to skip rate limiting
136
+ */
137
+ skip?: (req: ExpressRequest) => boolean | Promise<boolean>;
138
+ /**
139
+ * Custom store for rate limit data. If not provided, uses memory store.
140
+ */
141
+ store?: any;
142
+ }
143
+
144
+ /**
145
+ * Global rate limit configuration for SFR
146
+ */
147
+ declare type RateLimitGlobalConfig = {
148
+ /**
149
+ * Default rate limit configuration applied to all routes.
150
+ * Can be overridden per-route using cfg.rate_limit in SFR files.
151
+ */
152
+ default?: RateLimitConfig;
153
+ }
154
+
50
155
  declare type InjectedFacilities = {
51
156
  handlers?: HandlerFacilities;
52
157
  controllers?: ControllerFacilities;
@@ -89,6 +194,13 @@ declare type SFRConfig = {
89
194
  * * Access Authorization
90
195
  */
91
196
  public?: boolean;
197
+ /**
198
+ * Per-route rate limit configuration.
199
+ * If not specified, uses the global default rate limit configuration.
200
+ * Set to `false` to disable rate limiting for this route.
201
+ * Set to an object to override the default configuration.
202
+ */
203
+ rate_limit?: RateLimitConfig | false;
92
204
  };
93
205
 
94
206
  declare type OASConfig = Omit<ServiceManifest, "documents"> & InfoObject
@@ -200,17 +312,41 @@ type CustomRequestHandler= (
200
312
  res: ExpressResponse,
201
313
  next: NextFunction
202
314
  ) => any;
203
- declare type WSRequestHandler = (
204
- ctx: WSRequestCtx,
205
- args?: object
206
- ) => Promise<object>;
315
+ /**
316
+ * WebSocket event handler function signature
317
+ * @param ctx - Context containing io, socket, and validated data
318
+ */
319
+ declare type WSRequestHandler = (ctx: WSRequestCtx) => void | Promise<void>;
320
+
321
+ /**
322
+ * Map of WebSocket event handlers with metadata
323
+ */
207
324
  declare type WSRequestHandlers = {
208
- [event: string]: WSRequestHandler;
325
+ [event: string]: WSHandlerDefinition;
209
326
  };
327
+
328
+ /**
329
+ * Individual WebSocket handler definition with metadata
330
+ */
331
+ declare type WSHandlerDefinition = SFRMetadata & {
332
+ /**
333
+ * The handler function to execute when the event is received
334
+ */
335
+ fn: WSRequestHandler;
336
+ };
337
+
338
+ /**
339
+ * Context passed to WebSocket handlers
340
+ */
210
341
  declare type WSRequestCtx = {
342
+ /** The Socket.IO server instance */
211
343
  io: Server;
344
+ /** The current socket connection */
212
345
  socket: Socket;
213
- args: string[];
346
+ /** The validated event data/payload */
347
+ data: any;
348
+ /** Callback function for acknowledgements (if provided by client) */
349
+ ack?: (...args: any[]) => void;
214
350
  };
215
351
  declare type RequestResponse =
216
352
  | {
@@ -227,10 +363,15 @@ declare type RESTNamespaceDeclaration = {
227
363
  }
228
364
  };
229
365
  declare type WSNamespaceDeclaration = {
230
- [namespace: string]: DeclarationArtifact & {
231
- content: {
232
- handlers: WSRequestHandlers
233
- }
366
+ [namespace: string]: WSDeclarationArtifact
367
+ };
368
+
369
+ declare type WSDeclarationArtifact = DeclarationArtifact & {
370
+ content: {
371
+ cfg: WSConfig;
372
+ validators: RequestValidators;
373
+ controllers: RequestControllers;
374
+ handlers: WSRequestHandlers;
234
375
  }
235
376
  };
236
377
  declare type MQNamespaceDeclaration = {
@@ -316,8 +457,8 @@ declare type PatternMQSet = {
316
457
  "Point-to-Point": TargetedMQ;
317
458
  "Fanout": BroadcastMQ;
318
459
  "Request-Reply": TargetedMQ;
319
- "Direct": TargetedMQ;
320
- "Topic": TargetedMQ;
460
+ "Direct": BroadcastMQ;
461
+ "Topic": BroadcastMQ;
321
462
  }
322
463
 
323
464
  declare type MQHandlerDescriptor<V, H, C> = {
@@ -401,4 +542,87 @@ type AsyncAPIMessage = {
401
542
  contentType: string;
402
543
  payload: any;
403
544
  };
404
- };
545
+ };
546
+
547
+ /* Observability Types */
548
+
549
+ /**
550
+ * Configuration options for SFR observability (tracing, metrics, logging).
551
+ * Service name and version are automatically extracted from OASConfig.
552
+ */
553
+ declare interface ObservabilityOptions {
554
+ /** Enable/disable observability (default: true) */
555
+ enabled?: boolean;
556
+ /** OTLP endpoint URL (default: http://localhost:4318) */
557
+ otlp_endpoint?: string;
558
+ /** Enable auto-instrumentation for common libraries (default: true) */
559
+ auto_instrumentation?: boolean;
560
+ /** Sampling ratio 0.0 - 1.0 (default: 1.0) */
561
+ sampling_ratio?: number;
562
+ /** Log format: 'json' for production, 'pretty' for development */
563
+ log_format?: "json" | "pretty";
564
+ /** Additional resource attributes for traces/metrics */
565
+ resource_attributes?: Record<string, string>;
566
+ /** Enable debug logging for OTel SDK */
567
+ debug?: boolean;
568
+ }
569
+
570
+ /**
571
+ * Logger configuration options.
572
+ */
573
+ declare interface LoggerConfig {
574
+ service_name?: string;
575
+ level?: string;
576
+ format?: "json" | "pretty";
577
+ transports?: any[];
578
+ }
579
+
580
+ /**
581
+ * Pre-defined SFR metrics for all protocols.
582
+ */
583
+ declare interface SFRMetrics {
584
+ // REST Metrics
585
+ rest_requests_total: any;
586
+ rest_request_duration: any;
587
+ rest_errors_total: any;
588
+ rest_request_size: any;
589
+ rest_response_size: any;
590
+
591
+ // WebSocket Metrics
592
+ ws_connections_active: any;
593
+ ws_connections_total: any;
594
+ ws_events_total: any;
595
+ ws_event_duration: any;
596
+ ws_errors_total: any;
597
+
598
+ // MQ Metrics
599
+ mq_messages_received: any;
600
+ mq_messages_published: any;
601
+ mq_processing_duration: any;
602
+ mq_errors_total: any;
603
+ mq_messages_rejected: any;
604
+ mq_messages_acked: any;
605
+ }
606
+
607
+ /**
608
+ * Options for creating a span.
609
+ */
610
+ declare interface SpanOptions {
611
+ /** Name of the span */
612
+ name: string;
613
+ /** Kind of span (default: INTERNAL) */
614
+ kind?: import("@opentelemetry/api").SpanKind;
615
+ /** Initial attributes to set on the span */
616
+ attributes?: Record<string, string | number | boolean>;
617
+ /** Parent context (optional, uses active context if not provided) */
618
+ parent_context?: import("@opentelemetry/api").Context;
619
+ }
620
+
621
+ /**
622
+ * Trace context information.
623
+ */
624
+ declare interface TraceContext {
625
+ trace_id: string;
626
+ span_id: string;
627
+ trace_flags: number;
628
+ }
package/dist/example.mjs DELETED
@@ -1,33 +0,0 @@
1
- import Joi from "joi";
2
- import { REST } from "./templates.mjs";
3
- export default REST({
4
- cfg: {
5
- base_dir: "example",
6
- public: false,
7
- },
8
- validators: {
9
- "get-something": {
10
- "name": Joi.string().required(),
11
- "age": Joi.number().required(),
12
- }
13
- },
14
- handlers: {
15
- GET: {
16
- "get-something": {
17
- description: "Get something I guess?",
18
- async fn(req, res) {
19
- const result = await this.db_call();
20
- res.status(200).json({
21
- data: result
22
- });
23
- }
24
- }
25
- }
26
- },
27
- controllers: {
28
- async db_call() {
29
- /* Perform database calls here through accessing the "this" context (if injections are set) */
30
- return "Something";
31
- }
32
- }
33
- });
@@ -1,11 +0,0 @@
1
- declare const _default: {
2
- GET: {
3
- "get-something": {
4
- description: string;
5
- fn(req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: import("express").Response<any, Record<string, any>>): Promise<void>;
6
- };
7
- };
8
- } & {
9
- db_call(): Promise<string>;
10
- };
11
- export default _default;
package/src/example.mts DELETED
@@ -1,35 +0,0 @@
1
- import Joi from "joi";
2
- import { REST } from "./templates.mjs";
3
-
4
-
5
- export default REST({
6
- cfg : {
7
- base_dir : "example",
8
- public : false,
9
- },
10
- validators: {
11
- "get-something": {
12
- "name": Joi.string().required(),
13
- "age": Joi.number().required(),
14
- }
15
- },
16
- handlers: {
17
- GET : {
18
- "get-something": {
19
- description : "Get something I guess?",
20
- async fn(req, res){
21
- const result = await this.db_call()
22
- res.status(200).json({
23
- data: result
24
- });
25
- }
26
- }
27
- }
28
- },
29
- controllers: {
30
- async db_call(){
31
- /* Perform database calls here through accessing the "this" context (if injections are set) */
32
- return "Something";
33
- }
34
- }
35
- })