@crossdelta/cloudevents 0.5.6 → 0.6.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.
Files changed (70) hide show
  1. package/README.md +48 -28
  2. package/dist/index.cjs +1602 -0
  3. package/dist/index.d.mts +812 -0
  4. package/dist/index.d.ts +812 -9
  5. package/dist/index.js +1574 -6
  6. package/package.json +20 -18
  7. package/dist/adapters/cloudevents/cloudevents.d.ts +0 -14
  8. package/dist/adapters/cloudevents/cloudevents.js +0 -58
  9. package/dist/adapters/cloudevents/index.d.ts +0 -8
  10. package/dist/adapters/cloudevents/index.js +0 -7
  11. package/dist/adapters/cloudevents/parsers/binary-mode.d.ts +0 -5
  12. package/dist/adapters/cloudevents/parsers/binary-mode.js +0 -32
  13. package/dist/adapters/cloudevents/parsers/pubsub.d.ts +0 -5
  14. package/dist/adapters/cloudevents/parsers/pubsub.js +0 -54
  15. package/dist/adapters/cloudevents/parsers/raw-event.d.ts +0 -5
  16. package/dist/adapters/cloudevents/parsers/raw-event.js +0 -17
  17. package/dist/adapters/cloudevents/parsers/structured-mode.d.ts +0 -5
  18. package/dist/adapters/cloudevents/parsers/structured-mode.js +0 -18
  19. package/dist/adapters/cloudevents/types.d.ts +0 -29
  20. package/dist/adapters/cloudevents/types.js +0 -1
  21. package/dist/domain/contract-helper.d.ts +0 -63
  22. package/dist/domain/contract-helper.js +0 -61
  23. package/dist/domain/discovery.d.ts +0 -24
  24. package/dist/domain/discovery.js +0 -201
  25. package/dist/domain/handler-factory.d.ts +0 -49
  26. package/dist/domain/handler-factory.js +0 -169
  27. package/dist/domain/index.d.ts +0 -6
  28. package/dist/domain/index.js +0 -4
  29. package/dist/domain/types.d.ts +0 -108
  30. package/dist/domain/types.js +0 -6
  31. package/dist/domain/validation.d.ts +0 -37
  32. package/dist/domain/validation.js +0 -53
  33. package/dist/infrastructure/errors.d.ts +0 -53
  34. package/dist/infrastructure/errors.js +0 -54
  35. package/dist/infrastructure/index.d.ts +0 -4
  36. package/dist/infrastructure/index.js +0 -2
  37. package/dist/infrastructure/logging.d.ts +0 -18
  38. package/dist/infrastructure/logging.js +0 -27
  39. package/dist/middlewares/cloudevents-middleware.d.ts +0 -171
  40. package/dist/middlewares/cloudevents-middleware.js +0 -276
  41. package/dist/middlewares/index.d.ts +0 -1
  42. package/dist/middlewares/index.js +0 -1
  43. package/dist/processing/dlq-safe.d.ts +0 -82
  44. package/dist/processing/dlq-safe.js +0 -108
  45. package/dist/processing/handler-cache.d.ts +0 -36
  46. package/dist/processing/handler-cache.js +0 -94
  47. package/dist/processing/idempotency.d.ts +0 -51
  48. package/dist/processing/idempotency.js +0 -112
  49. package/dist/processing/index.d.ts +0 -4
  50. package/dist/processing/index.js +0 -4
  51. package/dist/processing/validation.d.ts +0 -41
  52. package/dist/processing/validation.js +0 -48
  53. package/dist/publishing/index.d.ts +0 -2
  54. package/dist/publishing/index.js +0 -2
  55. package/dist/publishing/nats.publisher.d.ts +0 -19
  56. package/dist/publishing/nats.publisher.js +0 -115
  57. package/dist/publishing/pubsub.publisher.d.ts +0 -39
  58. package/dist/publishing/pubsub.publisher.js +0 -84
  59. package/dist/transports/nats/base-message-processor.d.ts +0 -44
  60. package/dist/transports/nats/base-message-processor.js +0 -118
  61. package/dist/transports/nats/index.d.ts +0 -5
  62. package/dist/transports/nats/index.js +0 -5
  63. package/dist/transports/nats/jetstream-consumer.d.ts +0 -217
  64. package/dist/transports/nats/jetstream-consumer.js +0 -367
  65. package/dist/transports/nats/jetstream-message-processor.d.ts +0 -9
  66. package/dist/transports/nats/jetstream-message-processor.js +0 -32
  67. package/dist/transports/nats/nats-consumer.d.ts +0 -36
  68. package/dist/transports/nats/nats-consumer.js +0 -84
  69. package/dist/transports/nats/nats-message-processor.d.ts +0 -11
  70. package/dist/transports/nats/nats-message-processor.js +0 -32
@@ -1,54 +0,0 @@
1
- // HTTP Response Functions
2
- /**
3
- * Handles errors with full context logging
4
- */
5
- export const handleErrorWithContext = (error, context, additionalInfo) => {
6
- const errorInfo = {
7
- message: error.message,
8
- stack: error.stack,
9
- url: context.req.url,
10
- method: context.req.method,
11
- headers: Object.fromEntries(context.req.raw.headers.entries()),
12
- ...additionalInfo,
13
- };
14
- console.error('[Error Handler]', JSON.stringify(errorInfo, null, 2));
15
- return errorInfo;
16
- };
17
- /**
18
- * Converts an error to a standardized response format
19
- */
20
- export const errorToResponse = (error, type = 'InternalError') => ({
21
- error: {
22
- type,
23
- message: error.message,
24
- timestamp: new Date().toISOString(),
25
- },
26
- });
27
- /**
28
- * Creates a standardized error response
29
- */
30
- export const createErrorResponse = (type, message, details) => ({
31
- error: {
32
- type,
33
- message,
34
- timestamp: new Date().toISOString(),
35
- details,
36
- },
37
- });
38
- // Application Error Factory Functions
39
- export const createValidationError = (eventType, details) => ({
40
- type: 'ValidationError',
41
- eventType,
42
- message: `Validation failed for event type: ${eventType}`,
43
- details,
44
- });
45
- export const createNoHandlerFoundError = (eventType) => ({
46
- type: 'NoHandlerFoundError',
47
- eventType,
48
- message: `No handler found for event type: ${eventType}`,
49
- });
50
- export const createCloudEventParseError = (message, cause) => ({
51
- type: 'CloudEventParseError',
52
- message,
53
- cause,
54
- });
@@ -1,4 +0,0 @@
1
- export type { CloudEventParseError, ErrorResponse, NoHandlerFoundError, SuccessResponse, ValidationError, } from './errors';
2
- export { createCloudEventParseError, createErrorResponse, createNoHandlerFoundError, createValidationError, errorToResponse, handleErrorWithContext, } from './errors';
3
- export type { Logger } from './logging';
4
- export { createLogger, logger } from './logging';
@@ -1,2 +0,0 @@
1
- export { createCloudEventParseError, createErrorResponse, createNoHandlerFoundError, createValidationError, errorToResponse, handleErrorWithContext, } from './errors';
2
- export { createLogger, logger } from './logging';
@@ -1,18 +0,0 @@
1
- /**
2
- * Logger interface for structured logging
3
- */
4
- export interface Logger {
5
- log: (message: string, args?: unknown) => void;
6
- info: (message: string, args?: unknown) => void;
7
- warn: (message: string, error?: unknown) => void;
8
- error: (message: string, error?: unknown) => void;
9
- debug: (message: string, args?: unknown) => void;
10
- }
11
- /**
12
- * Creates a logger with configurable output based on enabled flag
13
- */
14
- export declare const createLogger: (enabled: boolean) => Logger;
15
- /**
16
- * Default logger instance (enabled by default)
17
- */
18
- export declare const logger: Logger;
@@ -1,27 +0,0 @@
1
- /**
2
- * Logging Infrastructure
3
- *
4
- * Provides structured logging with configurable output levels
5
- * and CloudEvents-specific logging utilities
6
- */
7
- const LOG_PREFIX = 'cloudevents';
8
- /**
9
- * Creates a logger with configurable output based on enabled flag
10
- */
11
- export const createLogger = (enabled) => {
12
- const logWithArgs = (consoleFn, message, args) => {
13
- const formattedMessage = `[${LOG_PREFIX}] ${message}`;
14
- args !== undefined ? consoleFn(formattedMessage, args) : consoleFn(formattedMessage);
15
- };
16
- return {
17
- log: (message, args) => enabled && logWithArgs(console.log, message, args),
18
- info: (message, args) => enabled && logWithArgs(console.info, message, args),
19
- warn: (message, error) => enabled && logWithArgs(console.warn, message, error),
20
- error: (message, error) => logWithArgs(console.error, message, error),
21
- debug: (message, args) => logWithArgs(console.debug, message, args),
22
- };
23
- };
24
- /**
25
- * Default logger instance (enabled by default)
26
- */
27
- export const logger = createLogger(true);
@@ -1,171 +0,0 @@
1
- /**
2
- * CloudEvents Middleware for Hono - Simplified Core
3
- *
4
- * Supports automatic handler discovery and manual registration.
5
- * Handles event validation, routing, and safeParse mode for graceful degradation.
6
- * Includes optional DLQ-Safe mode for Pub/Sub Push endpoints.
7
- */
8
- import type { Context } from 'hono';
9
- import type { HandlerConstructor } from '../domain';
10
- import { clearHandlerCache } from '../processing';
11
- /**
12
- * Configuration options for CloudEvents middleware
13
- *
14
- * @interface CloudEventsOptions
15
- */
16
- export interface CloudEventsOptions {
17
- /**
18
- * Directory path for automatic handler discovery
19
- *
20
- * @example './src/events' or './handlers'
21
- * @default undefined
22
- */
23
- discover?: string;
24
- /**
25
- * Array of handler constructors for manual registration
26
- *
27
- * @example [CustomerCreatedHandler, OrderProcessedHandler]
28
- * @default []
29
- */
30
- handlers?: HandlerConstructor[];
31
- /**
32
- * Logging configuration
33
- *
34
- * - `false`: No logging (production default)
35
- * - `true`: Basic structured logging
36
- * - `'pretty'`: Human-readable format (development)
37
- * - `'structured'`: JSON format (production)
38
- *
39
- * @default false
40
- */
41
- log?: boolean | 'pretty' | 'structured';
42
- /**
43
- * Google Cloud Pub/Sub topic for quarantining invalid messages
44
- *
45
- * When specified, enables DLQ-Safe mode:
46
- * - Always returns HTTP 204 to prevent redelivery
47
- * - Quarantines validation errors and malformed events
48
- * - Non-blocking background processing
49
- *
50
- * @example 'projects/my-project/topics/quarantine-topic'
51
- * @default undefined
52
- */
53
- quarantineTopic?: string;
54
- /**
55
- * Google Cloud Pub/Sub topic for publishing recoverable handler errors
56
- *
57
- * Used in DLQ-Safe mode to publish errors that can be retried later:
58
- * - Handler execution failures
59
- * - Temporary processing errors
60
- * - Network timeouts
61
- *
62
- * @example 'projects/my-project/topics/error-topic'
63
- * @default undefined
64
- */
65
- errorTopic?: string;
66
- /**
67
- * Google Cloud Project ID
68
- *
69
- * @example 'my-production-project'
70
- * @default Detected from environment (GOOGLE_CLOUD_PROJECT, etc.)
71
- */
72
- projectId?: string;
73
- /**
74
- * CloudEvent source identifier
75
- *
76
- * @example 'my-service' or 'https://my-domain.com/service'
77
- * @default Auto-detected from environment
78
- */
79
- source?: string;
80
- /**
81
- * Set for message deduplication based on CloudEvent ID
82
- *
83
- * Automatically managed by the middleware to prevent duplicate processing.
84
- * Can be provided for custom deduplication logic.
85
- *
86
- * @default new Set<string>()
87
- */
88
- processedMessageIds?: Set<string>;
89
- }
90
- export { clearHandlerCache };
91
- /**
92
- * CloudEvents middleware for Hono applications
93
- *
94
- * Provides automatic CloudEvent processing with handler discovery, validation,
95
- * and optional DLQ-Safe mode for Google Cloud Pub/Sub Push endpoints.
96
- *
97
- * @example
98
- * ```typescript
99
- * import { Hono } from 'hono'
100
- * import { cloudEvents } from '@orderboss/cloudevents'
101
- *
102
- * const app = new Hono()
103
- *
104
- * // Basic usage with handler discovery
105
- * app.use('*', cloudEvents({
106
- * discover: './src/events/*.event.{ts,js}',
107
- * log: true
108
- * }))
109
- *
110
- * // Manual handler registration
111
- * app.use('*', cloudEvents({
112
- * handlers: [CustomerCreatedHandler, OrderProcessedHandler],
113
- * log: 'pretty'
114
- * }))
115
- *
116
- * // DLQ-Safe mode for Pub/Sub Push
117
- * app.use('*', cloudEvents({
118
- * discover: './src/events/*.event.{ts,js}',
119
- * quarantineTopic: 'quarantine-topic',
120
- * errorTopic: 'error-topic',
121
- * projectId: 'my-project',
122
- * log: 'structured'
123
- * }))
124
- * ```
125
- *
126
- * @param options - Configuration options for the middleware
127
- * @param options.discover - Directory path for automatic handler discovery (e.g., './src/events')
128
- * @param options.handlers - Array of handler constructors for manual registration
129
- * @param options.log - Enable logging: false (default), true, 'pretty' (dev), or 'structured' (prod)
130
- * @param options.quarantineTopic - Pub/Sub topic for quarantining invalid messages (enables DLQ-Safe mode)
131
- * @param options.errorTopic - Pub/Sub topic for publishing recoverable handler errors
132
- * @param options.projectId - Google Cloud Project ID (defaults to environment detection)
133
- * @param options.source - CloudEvent source identifier (defaults to auto-detection)
134
- * @param options.processedMessageIds - Set for message deduplication (automatically managed)
135
- *
136
- * @returns Hono middleware function that processes CloudEvents
137
- *
138
- * @remarks
139
- * **Handler Discovery:**
140
- * - Automatically discovers handlers in the specified directory
141
- * - Handlers must export a class that extends the base handler pattern
142
- * - Supports nested directories and TypeScript files
143
- *
144
- * **Event Format Support:**
145
- * - CloudEvents Structured mode (JSON with specversion)
146
- * - CloudEvents Binary mode (headers + data)
147
- * - Google Pub/Sub Push format
148
- * - Raw event data (wrapped in CloudEvent)
149
- *
150
- * **DLQ-Safe Mode:**
151
- * - Activated when `quarantineTopic` is specified
152
- * - Always returns HTTP 204 to prevent Pub/Sub redelivery
153
- * - Quarantines invalid messages to specified topic
154
- * - Publishes handler errors to error topic
155
- * - All DLQ operations are non-blocking for optimal performance
156
- *
157
- * **Standard Mode:**
158
- * - Returns HTTP 200 for successful processing
159
- * - Returns HTTP 422 for validation errors
160
- * - Returns HTTP 500 for handler errors
161
- * - Allows Pub/Sub DLQ behavior for unhandled errors
162
- *
163
- * **Performance Features:**
164
- * - Handler caching for improved startup time
165
- * - Dynamic parser loading for optimal bundle size
166
- * - Message deduplication based on CloudEvent ID
167
- * - Background processing for DLQ operations
168
- *
169
- * @since 1.0.0
170
- */
171
- export declare function cloudEvents(options?: CloudEventsOptions): (ctx: Context, next: () => Promise<void>) => Promise<void | Response>;
@@ -1,276 +0,0 @@
1
- import { parseEventFromContext } from '../adapters/cloudevents';
2
- import { handleErrorWithContext, logger } from '../infrastructure';
3
- import { addProcessedMessage, clearHandlerCache, createCacheKey, createProcessingContext, getCachedHandlers, isDlqSafeMode, isHandlerMatching, publishRecoverableError, quarantineMessage, setupHandlers, throwValidationError, validateEventData, } from '../processing';
4
- // Export clearHandlerCache for testing
5
- export { clearHandlerCache };
6
- /**
7
- * Logs middleware initialization status
8
- */
9
- const logInitialization = (options, log) => {
10
- if (isDlqSafeMode(options)) {
11
- const quarantine = options.quarantineTopic || 'not configured';
12
- const errorTopic = options.errorTopic || 'not configured';
13
- const projectId = options.projectId || 'default';
14
- const source = options.source || 'auto-detected';
15
- if (log === 'pretty') {
16
- logger.info('DLQ-Safe mode enabled');
17
- logger.info(` • Quarantine topic: ${quarantine}`);
18
- logger.info(` • Error topic: ${errorTopic}`);
19
- logger.info(` • Project ID: ${projectId}`);
20
- logger.info(` • Source: ${source}`);
21
- }
22
- else {
23
- logger.info('CloudEvents middleware initialized', {
24
- mode: 'DLQ-Safe',
25
- quarantineTopic: quarantine,
26
- errorTopic: errorTopic,
27
- projectId: projectId,
28
- source: source,
29
- });
30
- }
31
- }
32
- else {
33
- if (log === 'pretty') {
34
- logger.info('DLQ-Safe mode disabled - using standard error handling');
35
- }
36
- else {
37
- logger.info('CloudEvents middleware initialized', {
38
- mode: 'Standard',
39
- note: 'Using standard error handling',
40
- });
41
- }
42
- }
43
- };
44
- /**
45
- * Executes a single handler with error handling
46
- */
47
- const executeHandler = async (handler, eventData, context) => {
48
- try {
49
- await handler.handle(eventData, context);
50
- }
51
- catch (error) {
52
- logger.error(`Handler execution failed for ${handler.name}:`, error);
53
- throw error;
54
- }
55
- };
56
- /**
57
- * Processes handlers in DLQ-safe or standard mode
58
- */
59
- const processHandlerSafely = async (handler, eventData, ctx, processingContext, options) => {
60
- const validationResult = validateEventData(handler, eventData);
61
- if ('error' in validationResult) {
62
- if (validationResult.shouldSkip) {
63
- return; // Skip this handler in safeParse mode
64
- }
65
- if (isDlqSafeMode(options)) {
66
- // Non-blocking quarantine - don't wait for DLQ publishing
67
- queueMicrotask(() => {
68
- quarantineMessage(processingContext, 'validation_error', options, validationResult.error).catch((error) => {
69
- logger.error('Failed to quarantine validation error:', error);
70
- });
71
- });
72
- return;
73
- }
74
- throwValidationError(handler.name, validationResult.error);
75
- }
76
- // Execute handler
77
- try {
78
- await executeHandler(handler, eventData, ctx);
79
- }
80
- catch (error) {
81
- if (isDlqSafeMode(options)) {
82
- // Non-blocking error publishing - don't wait for DLQ publishing
83
- queueMicrotask(() => {
84
- publishRecoverableError(processingContext, error, options).catch((publishError) => {
85
- logger.error('Failed to publish recoverable error:', publishError);
86
- });
87
- });
88
- return;
89
- }
90
- throw error;
91
- }
92
- };
93
- /**
94
- * Executes all matching handlers for an event
95
- */
96
- const executeMatchingHandlers = async (handlers, eventType, eventData, ctx, processingContext, options) => {
97
- const matchingHandlers = handlers.filter(isHandlerMatching(eventType, eventData, ctx));
98
- if (matchingHandlers.length === 0) {
99
- const errorMessage = `No handlers found for event type: ${eventType}`;
100
- if (isDlqSafeMode(options)) {
101
- // Non-blocking quarantine - don't wait for DLQ publishing
102
- queueMicrotask(() => {
103
- quarantineMessage(processingContext, 'no_handler', options, new Error(errorMessage)).catch((error) => {
104
- logger.error('Failed to quarantine no_handler error:', error);
105
- });
106
- });
107
- return;
108
- }
109
- throw new Error(errorMessage);
110
- }
111
- // Process all matching handlers
112
- await Promise.all(matchingHandlers.map((handler) => processHandlerSafely(handler, eventData, ctx, processingContext, options)));
113
- };
114
- /**
115
- * Main CloudEvent processing function
116
- */
117
- const processCloudEvent = async (ctx, options) => {
118
- const cacheKey = createCacheKey(options.discover, options.handlers);
119
- const handlers = getCachedHandlers(cacheKey);
120
- try {
121
- const { event, cloudEventData } = await parseEventFromContext(ctx);
122
- // Use cloudEventData as primary source, fallback to event
123
- const eventData = cloudEventData || event;
124
- if (!eventData) {
125
- throw new Error('Failed to parse CloudEvent from request');
126
- }
127
- const eventType = eventData.type;
128
- const eventPayload = eventData.data;
129
- const context = cloudEventData || {};
130
- const messageId = eventData.id || 'unknown';
131
- // Deduplication check
132
- const dedupeSet = options.processedMessageIds || new Set();
133
- if (dedupeSet.has(messageId)) {
134
- logger.info(`Duplicate message ${messageId} detected, skipping processing`);
135
- return ctx.json({ status: 'duplicate', messageId }, 200);
136
- }
137
- addProcessedMessage(messageId);
138
- dedupeSet.add(messageId);
139
- const processingContext = createProcessingContext(eventType, eventPayload, context, event || eventData);
140
- if (options.log) {
141
- logger.info(`Processing event type: ${eventType}`);
142
- }
143
- // Execute handlers
144
- await executeMatchingHandlers(handlers, eventType, eventPayload, context, processingContext, options);
145
- // Return success response
146
- return isDlqSafeMode(options)
147
- ? ctx.body(null, 204) // Always 204 in DLQ-safe mode
148
- : ctx.json({ status: 'processed', eventType, messageId }, 200);
149
- }
150
- catch (error) {
151
- // Handle ValidationError specifically
152
- if (error && typeof error === 'object' && 'type' in error && error.type === 'ValidationError') {
153
- return ctx.json({ error }, 422);
154
- }
155
- handleErrorWithContext(error, ctx, { isDlqSafe: isDlqSafeMode(options) });
156
- return ctx.json({ error: 'Internal Server Error' }, 500);
157
- }
158
- };
159
- /**
160
- * CloudEvents middleware for Hono applications
161
- *
162
- * Provides automatic CloudEvent processing with handler discovery, validation,
163
- * and optional DLQ-Safe mode for Google Cloud Pub/Sub Push endpoints.
164
- *
165
- * @example
166
- * ```typescript
167
- * import { Hono } from 'hono'
168
- * import { cloudEvents } from '@orderboss/cloudevents'
169
- *
170
- * const app = new Hono()
171
- *
172
- * // Basic usage with handler discovery
173
- * app.use('*', cloudEvents({
174
- * discover: './src/events/*.event.{ts,js}',
175
- * log: true
176
- * }))
177
- *
178
- * // Manual handler registration
179
- * app.use('*', cloudEvents({
180
- * handlers: [CustomerCreatedHandler, OrderProcessedHandler],
181
- * log: 'pretty'
182
- * }))
183
- *
184
- * // DLQ-Safe mode for Pub/Sub Push
185
- * app.use('*', cloudEvents({
186
- * discover: './src/events/*.event.{ts,js}',
187
- * quarantineTopic: 'quarantine-topic',
188
- * errorTopic: 'error-topic',
189
- * projectId: 'my-project',
190
- * log: 'structured'
191
- * }))
192
- * ```
193
- *
194
- * @param options - Configuration options for the middleware
195
- * @param options.discover - Directory path for automatic handler discovery (e.g., './src/events')
196
- * @param options.handlers - Array of handler constructors for manual registration
197
- * @param options.log - Enable logging: false (default), true, 'pretty' (dev), or 'structured' (prod)
198
- * @param options.quarantineTopic - Pub/Sub topic for quarantining invalid messages (enables DLQ-Safe mode)
199
- * @param options.errorTopic - Pub/Sub topic for publishing recoverable handler errors
200
- * @param options.projectId - Google Cloud Project ID (defaults to environment detection)
201
- * @param options.source - CloudEvent source identifier (defaults to auto-detection)
202
- * @param options.processedMessageIds - Set for message deduplication (automatically managed)
203
- *
204
- * @returns Hono middleware function that processes CloudEvents
205
- *
206
- * @remarks
207
- * **Handler Discovery:**
208
- * - Automatically discovers handlers in the specified directory
209
- * - Handlers must export a class that extends the base handler pattern
210
- * - Supports nested directories and TypeScript files
211
- *
212
- * **Event Format Support:**
213
- * - CloudEvents Structured mode (JSON with specversion)
214
- * - CloudEvents Binary mode (headers + data)
215
- * - Google Pub/Sub Push format
216
- * - Raw event data (wrapped in CloudEvent)
217
- *
218
- * **DLQ-Safe Mode:**
219
- * - Activated when `quarantineTopic` is specified
220
- * - Always returns HTTP 204 to prevent Pub/Sub redelivery
221
- * - Quarantines invalid messages to specified topic
222
- * - Publishes handler errors to error topic
223
- * - All DLQ operations are non-blocking for optimal performance
224
- *
225
- * **Standard Mode:**
226
- * - Returns HTTP 200 for successful processing
227
- * - Returns HTTP 422 for validation errors
228
- * - Returns HTTP 500 for handler errors
229
- * - Allows Pub/Sub DLQ behavior for unhandled errors
230
- *
231
- * **Performance Features:**
232
- * - Handler caching for improved startup time
233
- * - Dynamic parser loading for optimal bundle size
234
- * - Message deduplication based on CloudEvent ID
235
- * - Background processing for DLQ operations
236
- *
237
- * @since 1.0.0
238
- */
239
- export function cloudEvents(options = {}) {
240
- const { discover, handlers = [], log = false } = options;
241
- const cacheKey = createCacheKey(discover, handlers);
242
- // Setup handlers immediately when middleware is created
243
- if (log) {
244
- setupHandlers(cacheKey, discover, handlers, log)
245
- // Log configuration status based on log format preference
246
- .then(() => logInitialization(options, log))
247
- .catch((error) => logger.error('Failed to setup handlers during initialization:', error));
248
- }
249
- return async (ctx, next) => {
250
- if (ctx.req.method !== 'POST') {
251
- return next();
252
- }
253
- await setupHandlers(cacheKey, discover, handlers, log);
254
- try {
255
- return await processCloudEvent(ctx, options);
256
- }
257
- catch (error) {
258
- // In DLQ-safe mode, always return 204 to prevent DLQ
259
- if (isDlqSafeMode(options)) {
260
- logger.error('Error during request processing (DLQ-safe mode):', error);
261
- queueMicrotask(async () => {
262
- try {
263
- const processingContext = createProcessingContext('unknown', null, null, null);
264
- await quarantineMessage(processingContext, 'processing_error', options, error);
265
- }
266
- catch (quarantineError) {
267
- const errorMessage = quarantineError instanceof Error ? quarantineError.message : 'Unknown error';
268
- logger.error(`Failed to quarantine error: ${errorMessage}`);
269
- }
270
- });
271
- return ctx.body(null, 204);
272
- }
273
- throw error;
274
- }
275
- };
276
- }
@@ -1 +0,0 @@
1
- export { clearHandlerCache, cloudEvents } from './cloudevents-middleware';
@@ -1 +0,0 @@
1
- export { clearHandlerCache, cloudEvents } from './cloudevents-middleware';
@@ -1,82 +0,0 @@
1
- /**
2
- * DLQ-Safe mode utilities
3
- * Handles quarantine and error publishing for CloudEvents processing
4
- */
5
- /**
6
- * Reason codes for quarantined messages
7
- */
8
- export type QuarantineReason = 'parse_error' | 'no_handler' | 'validation_error' | 'unhandled_error' | 'processing_error';
9
- /**
10
- * Structure of messages published to the quarantine topic
11
- */
12
- export interface QuarantineMessage {
13
- /** Original CloudEvent ID */
14
- originalMessageId: string;
15
- /** Original CloudEvent type */
16
- originalEventType: string;
17
- /** Original event data payload */
18
- originalEventData: unknown;
19
- /** Original event context/metadata */
20
- originalEventContext: unknown;
21
- /** Full original CloudEvent if available */
22
- originalCloudEvent: unknown;
23
- /** ISO timestamp when message was quarantined */
24
- quarantinedAt: string;
25
- /** Reason for quarantine */
26
- quarantineReason: QuarantineReason;
27
- /** Error message if applicable */
28
- error?: string;
29
- }
30
- /**
31
- * Structure of messages published to the error topic (recoverable errors)
32
- */
33
- export interface ErrorMessage {
34
- /** Original CloudEvent ID */
35
- originalMessageId: string;
36
- /** Original CloudEvent type */
37
- originalEventType: string;
38
- /** Original event data payload */
39
- originalEventData: unknown;
40
- /** Original event context/metadata */
41
- originalEventContext: unknown;
42
- /** Full original CloudEvent if available */
43
- originalCloudEvent: unknown;
44
- /** ISO timestamp when error occurred */
45
- errorTimestamp: string;
46
- /** Error details */
47
- error: {
48
- message: string;
49
- stack?: string;
50
- type: string;
51
- };
52
- }
53
- export interface ProcessingContext {
54
- messageId: string;
55
- eventType: string;
56
- eventData: unknown;
57
- eventContext: unknown;
58
- timestamp: string;
59
- originalCloudEvent: unknown;
60
- }
61
- export interface DlqOptions {
62
- quarantineTopic?: string;
63
- errorTopic?: string;
64
- projectId?: string;
65
- source?: string;
66
- }
67
- /**
68
- * Checks if DLQ-Safe mode is enabled
69
- */
70
- export declare const isDlqSafeMode: (options: DlqOptions) => boolean;
71
- /**
72
- * Publishes a message to the quarantine topic for "poison messages" that can't be processed
73
- */
74
- export declare const quarantineMessage: (processingContext: ProcessingContext, reason: QuarantineReason, options: DlqOptions, error?: unknown) => Promise<void>;
75
- /**
76
- * Publishes recoverable processing errors to the error topic
77
- */
78
- export declare const publishRecoverableError: (processingContext: ProcessingContext, error: unknown, options: DlqOptions) => Promise<void>;
79
- /**
80
- * Creates processing context from event data
81
- */
82
- export declare const createProcessingContext: (eventType: string, eventData: unknown, context: unknown, originalCloudEvent: unknown) => ProcessingContext;