@crossdelta/cloudevents 0.5.7 → 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 +20 -0
  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,201 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { dirname, join } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
- import { glob } from 'glob';
5
- import { logger } from '../infrastructure';
6
- import { isValidHandler } from './validation';
7
- /**
8
- * Gets the search directories for event handler discovery.
9
- * @returns Array of search directory paths.
10
- */
11
- const getSearchDirectories = () => {
12
- const directories = new Set();
13
- directories.add(process.cwd());
14
- try {
15
- const currentDir = dirname(fileURLToPath(import.meta.url));
16
- directories.add(currentDir);
17
- // For monorepo tests: also check packages/cloudevents if we're in dist/
18
- if (currentDir.includes('/dist/')) {
19
- const pkgRoot = currentDir.split('/dist/')[0];
20
- if (pkgRoot)
21
- directories.add(pkgRoot);
22
- }
23
- }
24
- catch {
25
- // Ignore resolution errors; fallback to process.cwd()
26
- }
27
- // Filter out directories that don't exist (e.g., during hot-reload)
28
- return [...directories].filter((dir) => existsSync(dir));
29
- };
30
- /**
31
- * Loads and validates handlers from a TypeScript/JavaScript file.
32
- */
33
- const loadHandlers = async (filePath, filter) => {
34
- try {
35
- // Check if file exists before import to avoid ENOENT during hot-reload
36
- if (!existsSync(filePath)) {
37
- return [];
38
- }
39
- const module = await import(filePath);
40
- return Object.entries(module)
41
- .filter(([name, handler]) => isValidHandler(handler) && (!filter || filter(name, handler)))
42
- .map(([name, handler]) => {
43
- const HandlerClass = handler;
44
- // Only override with export name if:
45
- // 1. Export is named (not 'default')
46
- // 2. Handler has no meaningful name (empty or generic class names)
47
- const hasNoMeaningfulName = !HandlerClass.name || HandlerClass.name === '' || HandlerClass.name === 'HandlerClass';
48
- const isNamedExport = name !== 'default';
49
- if (hasNoMeaningfulName && isNamedExport) {
50
- return Object.defineProperty(HandlerClass, 'name', { value: name, configurable: true });
51
- }
52
- return HandlerClass;
53
- });
54
- }
55
- catch (error) {
56
- // Comprehensive error logging for debugging
57
- logger?.warn(`Failed to load ${filePath}`);
58
- logger?.warn(`Error type: ${typeof error}`);
59
- logger?.warn(`Error constructor: ${error?.constructor?.name}`);
60
- if (error instanceof Error) {
61
- logger?.warn(`Error message: ${error.message}`);
62
- if (error.stack) {
63
- logger?.warn(`Stack trace:\n${error.stack}`);
64
- }
65
- }
66
- else {
67
- logger?.warn(`Error value: ${String(error)}`);
68
- try {
69
- logger?.warn(`Error JSON: ${JSON.stringify(error, null, 2)}`);
70
- }
71
- catch {
72
- logger?.warn('(Error is not JSON-serializable)');
73
- }
74
- }
75
- return [];
76
- }
77
- };
78
- /**
79
- * Deduplicates handlers by class name to avoid loading the same handler from .ts and .js
80
- * @param handlers - Array of handler constructors
81
- * @returns Array of unique handlers
82
- */
83
- const deduplicateHandlers = (handlers) => handlers.reduce((acc, handler) => {
84
- const existing = acc.find((h) => h.name === handler.name);
85
- if (!existing) {
86
- acc.push(handler);
87
- }
88
- return acc;
89
- }, []);
90
- /**
91
- * Discovers files matching the pattern across multiple search paths
92
- * @param pattern - Glob pattern to match
93
- * @param searchPaths - Array of directories to search in
94
- * @param logger - Logger instance for debug output
95
- * @param log - Whether logging is enabled
96
- * @returns Promise resolving to array of unique file paths
97
- */
98
- /**
99
- * Simple, elegant file discovery using glob patterns
100
- */
101
- const EXTENSION_FALLBACKS = ['js', 'mjs', 'cjs'];
102
- const expandPatternVariants = (pattern, preferCompiled) => {
103
- if (!/\.tsx?\b/.test(pattern)) {
104
- return [pattern];
105
- }
106
- const basePattern = pattern;
107
- const compiledVariants = EXTENSION_FALLBACKS.map((ext) => basePattern.replace(/\.tsx?\b/g, `.${ext}`));
108
- const ordered = preferCompiled ? [...compiledVariants, basePattern] : [basePattern, ...compiledVariants];
109
- return [...new Set(ordered)];
110
- };
111
- /**
112
- * Check if a directory path should be scanned (exists and is accessible)
113
- */
114
- const shouldScanDirectory = (basePath, variant) => {
115
- if (!existsSync(basePath)) {
116
- return false;
117
- }
118
- // For patterns with directory prefixes like "dist/...", check if prefix dir exists
119
- const dirPrefix = variant.match(/^([^*{[]+)\//)?.[1];
120
- if (dirPrefix) {
121
- const fullDirPath = join(basePath, dirPrefix);
122
- return existsSync(fullDirPath);
123
- }
124
- return true;
125
- };
126
- const discoverFiles = async (pattern, basePath, preferCompiled) => {
127
- // Don't add src/dist prefix for test patterns or absolute paths
128
- const isTestPattern = pattern.startsWith('test/');
129
- const prefixedPattern = isTestPattern ? pattern : `{src,dist,build,lib,out}/${pattern}`;
130
- const patterns = preferCompiled ? [prefixedPattern, pattern] : [pattern, prefixedPattern];
131
- const allFiles = [];
132
- for (const globPattern of patterns) {
133
- const variants = expandPatternVariants(globPattern, preferCompiled);
134
- for (const variant of variants) {
135
- try {
136
- // Check if directory should be scanned to avoid scandir errors during hot-reload
137
- if (!shouldScanDirectory(basePath, variant)) {
138
- continue;
139
- }
140
- const files = await glob(variant, {
141
- cwd: basePath,
142
- absolute: true,
143
- nodir: true,
144
- windowsPathsNoEscape: true,
145
- });
146
- // Filter out files that no longer exist (race condition during hot-reload)
147
- const existingFiles = files.filter((f) => existsSync(f));
148
- allFiles.push(...existingFiles);
149
- }
150
- catch {
151
- // Ignore errors silently - directory might have been deleted during hot-reload
152
- }
153
- }
154
- }
155
- return [...new Set(allFiles)]; // Remove duplicates
156
- };
157
- /**
158
- * Discovers event handlers from files matching the given glob pattern.
159
- *
160
- * @param pattern - Glob pattern to match handler files (e.g., 'events/*.handler.ts')
161
- * @param options - Configuration options
162
- * @returns Promise resolving to array of discovered handler constructors
163
- *
164
- * @example
165
- * ```typescript
166
- * // Discover all handlers in events directory
167
- * const handlers = await discoverHandlers('events/*.handler.ts')
168
- *
169
- * // With filtering and logging
170
- * const handlers = await discoverHandlers('events/*.handler.ts', {
171
- * filter: (name, handler) => name.includes('Customer'),
172
- * log: true
173
- * })
174
- * ```
175
- */
176
- export const discoverHandlers = async (pattern, options = {}) => {
177
- const { filter } = options;
178
- const searchDirectories = getSearchDirectories();
179
- const preferCompiled = searchDirectories.some((dir) => dir.includes('/dist/') || dir.includes('\\dist\\'));
180
- try {
181
- const uniqueFiles = new Set();
182
- for (const basePath of searchDirectories) {
183
- const discoveredFiles = await discoverFiles(pattern, basePath, preferCompiled);
184
- for (const file of discoveredFiles) {
185
- uniqueFiles.add(file);
186
- }
187
- }
188
- if (uniqueFiles.size === 0) {
189
- logger.warn(`No files found matching pattern: ${pattern}`);
190
- return [];
191
- }
192
- const handlers = await Promise.all([...uniqueFiles].map((file) => loadHandlers(file, filter)));
193
- const flatHandlers = handlers.flat();
194
- const uniqueHandlers = deduplicateHandlers(flatHandlers);
195
- return uniqueHandlers;
196
- }
197
- catch (error) {
198
- logger.error('Discovery failed:', error);
199
- return [];
200
- }
201
- };
@@ -1,49 +0,0 @@
1
- import { type ZodTypeAny, z } from 'zod';
2
- import type { EventContext } from '../adapters/cloudevents';
3
- import type { HandleEventOptions, HandlerConstructor } from './types';
4
- /**
5
- * Creates an event handler using the handleEvent pattern
6
- * Compatible with the new middleware system
7
- *
8
- * Supports both inline schemas (Basic Mode) and shared contracts (Advanced Mode).
9
- *
10
- * @example Basic Mode - Data-only schema inline
11
- * ```typescript
12
- * export default handleEvent({
13
- * type: 'orderboss.orders.created',
14
- * schema: z.object({ orderId: z.string(), total: z.number() }),
15
- * }, async (data) => {
16
- * console.log('Order created:', data.orderId)
17
- * })
18
- * ```
19
- *
20
- * @example Advanced Mode - With shared contract
21
- * ```typescript
22
- * import { OrderCreatedContract } from '@orderboss/contracts'
23
- *
24
- * export default handleEvent(OrderCreatedContract, async (data) => {
25
- * console.log('Order created:', data.orderId)
26
- * })
27
- * ```
28
- *
29
- * @example With tenant filtering
30
- * ```typescript
31
- * export default handleEvent({
32
- * type: 'orderboss.orders.created',
33
- * schema: OrderSchema,
34
- * tenantId: ['tenant-a', 'tenant-b'],
35
- * }, async (data, context) => {
36
- * console.log(`Order for tenant ${context?.tenantId}:`, data)
37
- * })
38
- * ```
39
- */
40
- export declare function handleEvent<TSchema extends ZodTypeAny>(schemaOrOptions: TSchema | HandleEventOptions<TSchema> | HandleEventOptions, handler: (payload: TSchema['_output'], context?: EventContext) => Promise<void> | void, eventType?: string): HandlerConstructor;
41
- /**
42
- * Creates an event schema with type inference
43
- * Automatically enforces the presence of a 'type' field
44
- */
45
- export declare function eventSchema<T extends Record<string, ZodTypeAny>>(schema: T & {
46
- type: ZodTypeAny;
47
- }): z.ZodObject<T & {
48
- type: ZodTypeAny;
49
- } extends infer T_1 ? { -readonly [P in keyof T_1]: T_1[P]; } : never, z.core.$strip>;
@@ -1,169 +0,0 @@
1
- import { z } from 'zod';
2
- /**
3
- * Extracts type value from Zod v4+ value getter
4
- */
5
- function extractFromValueGetter(typeField) {
6
- if ('value' in typeField && typeof typeField.value === 'string') {
7
- return typeField.value;
8
- }
9
- return undefined;
10
- }
11
- /**
12
- * Extracts type value from Zod _def (v3 and v4)
13
- */
14
- function extractFromTypeDef(typeField) {
15
- if (!('_def' in typeField))
16
- return undefined;
17
- const typeDef = typeField._def;
18
- // Try _def.values array (Zod v4)
19
- if (Array.isArray(typeDef.values) && typeDef.values.length > 0) {
20
- return String(typeDef.values[0]);
21
- }
22
- // Fallback to _def.value (Zod v3)
23
- if (typeof typeDef.value === 'string') {
24
- return typeDef.value;
25
- }
26
- return undefined;
27
- }
28
- /**
29
- * Extracts event type from a schema's type field
30
- */
31
- function extractFromTypeField(shape) {
32
- const typeField = shape.type;
33
- if (!typeField || typeof typeField !== 'object' || typeField === null) {
34
- return undefined;
35
- }
36
- const field = typeField;
37
- return extractFromValueGetter(field) ?? extractFromTypeDef(field);
38
- }
39
- /**
40
- * Extracts event type from schema
41
- * Supports both old Zod (_def.value) and new Zod (_def.values / value getter)
42
- */
43
- function extractEventTypeFromSchema(schema) {
44
- if (!('shape' in schema) || !schema.shape || typeof schema.shape !== 'object') {
45
- return undefined;
46
- }
47
- return extractFromTypeField(schema.shape);
48
- }
49
- /**
50
- * Creates a tenant match function from tenant ID configuration
51
- */
52
- function createTenantMatcher(tenantId) {
53
- const tenantIds = Array.isArray(tenantId) ? tenantId : [tenantId];
54
- return (event) => {
55
- if (!event.tenantId)
56
- return false;
57
- return tenantIds.includes(event.tenantId);
58
- };
59
- }
60
- /**
61
- * Combines multiple match functions with AND logic
62
- */
63
- function combineMatchers(matchers) {
64
- return (event) => matchers.every((matcher) => matcher(event));
65
- }
66
- /**
67
- * Creates an event handler using the handleEvent pattern
68
- * Compatible with the new middleware system
69
- *
70
- * Supports both inline schemas (Basic Mode) and shared contracts (Advanced Mode).
71
- *
72
- * @example Basic Mode - Data-only schema inline
73
- * ```typescript
74
- * export default handleEvent({
75
- * type: 'orderboss.orders.created',
76
- * schema: z.object({ orderId: z.string(), total: z.number() }),
77
- * }, async (data) => {
78
- * console.log('Order created:', data.orderId)
79
- * })
80
- * ```
81
- *
82
- * @example Advanced Mode - With shared contract
83
- * ```typescript
84
- * import { OrderCreatedContract } from '@orderboss/contracts'
85
- *
86
- * export default handleEvent(OrderCreatedContract, async (data) => {
87
- * console.log('Order created:', data.orderId)
88
- * })
89
- * ```
90
- *
91
- * @example With tenant filtering
92
- * ```typescript
93
- * export default handleEvent({
94
- * type: 'orderboss.orders.created',
95
- * schema: OrderSchema,
96
- * tenantId: ['tenant-a', 'tenant-b'],
97
- * }, async (data, context) => {
98
- * console.log(`Order for tenant ${context?.tenantId}:`, data)
99
- * })
100
- * ```
101
- */
102
- export function handleEvent(schemaOrOptions, handler, eventType) {
103
- // Handle both API formats
104
- let schema;
105
- let finalEventType = eventType;
106
- let matchFn;
107
- let safeParse = false;
108
- if (schemaOrOptions && typeof schemaOrOptions === 'object' && 'schema' in schemaOrOptions) {
109
- const options = schemaOrOptions;
110
- schema = options.schema;
111
- finalEventType = options.type || eventType;
112
- safeParse = options.safeParse ?? false;
113
- // Build match function from options
114
- const matchers = [];
115
- if (options.tenantId) {
116
- matchers.push(createTenantMatcher(options.tenantId));
117
- }
118
- if (options.match) {
119
- matchers.push(options.match);
120
- }
121
- if (matchers.length === 1) {
122
- matchFn = matchers[0];
123
- }
124
- else if (matchers.length > 1) {
125
- matchFn = combineMatchers(matchers);
126
- }
127
- }
128
- else {
129
- schema = schemaOrOptions;
130
- }
131
- // Try to extract event type from schema if not provided
132
- if (!finalEventType) {
133
- finalEventType = extractEventTypeFromSchema(schema);
134
- }
135
- // Fallback to unknown event
136
- if (!finalEventType) {
137
- finalEventType = 'unknown.event';
138
- }
139
- // Create handler class with proper naming (e.g., "orderboss.orders.created" → "OrdersCreatedHandler")
140
- const handlerName = `${finalEventType
141
- .split('.')
142
- .slice(-2) // Take last 2 segments (e.g., ["orders", "created"])
143
- .map(s => s.charAt(0).toUpperCase() + s.slice(1)) // Capitalize
144
- .join('')}Handler`;
145
- const HandlerClass = class extends Object {
146
- static __eventarcMetadata = {
147
- schema,
148
- declaredType: finalEventType,
149
- match: matchFn,
150
- safeParse,
151
- };
152
- async handle(payload, context) {
153
- await Promise.resolve(handler(payload, context));
154
- }
155
- };
156
- // Set the class name properly
157
- Object.defineProperty(HandlerClass, 'name', {
158
- value: handlerName,
159
- configurable: true,
160
- });
161
- return HandlerClass;
162
- }
163
- /**
164
- * Creates an event schema with type inference
165
- * Automatically enforces the presence of a 'type' field
166
- */
167
- export function eventSchema(schema) {
168
- return z.object(schema);
169
- }
@@ -1,6 +0,0 @@
1
- export { createContract } from './contract-helper';
2
- export { discoverHandlers } from './discovery';
3
- export { eventSchema, handleEvent } from './handler-factory';
4
- export type { ChannelConfig, ChannelMetadata, EnrichedEvent, EventHandler, HandleEventOptions, HandlerConstructor, HandlerMetadata, IdempotencyStore, InferEventData, MatchFn, RoutingConfig, } from './types';
5
- export type { HandlerValidationError, ValidationErrorDetail } from './validation';
6
- export { extractTypeFromSchema, isValidHandler } from './validation';
@@ -1,4 +0,0 @@
1
- export { createContract } from './contract-helper';
2
- export { discoverHandlers } from './discovery';
3
- export { eventSchema, handleEvent } from './handler-factory';
4
- export { extractTypeFromSchema, isValidHandler } from './validation';
@@ -1,108 +0,0 @@
1
- /**
2
- * Domain Types
3
- *
4
- * Core business logic types for handlers, events, and domain operations
5
- */
6
- import type { ZodTypeAny } from 'zod';
7
- import type { EventContext } from '../adapters/cloudevents/types';
8
- /**
9
- * Event handler interface
10
- */
11
- export interface EventHandler<T = unknown> {
12
- handle(payload: T, context?: unknown): Promise<void> | void;
13
- }
14
- /**
15
- * Constructor type for event handler classes that implement the EventHandler interface
16
- */
17
- export type HandlerConstructor<T = unknown> = (new (...args: unknown[]) => EventHandler<T>) & {
18
- __eventarcMetadata?: {
19
- schema: ZodTypeAny;
20
- declaredType?: string;
21
- match?: (event: EnrichedEvent<T>) => boolean;
22
- safeParse?: boolean;
23
- };
24
- };
25
- /**
26
- * Enriched event with both data and context
27
- */
28
- export interface EnrichedEvent<T> extends EventContext {
29
- data: T;
30
- /** Tenant identifier for multi-tenant event routing */
31
- tenantId?: string;
32
- }
33
- /**
34
- * Match function type for custom event matching
35
- */
36
- export type MatchFn<T> = (event: EnrichedEvent<T>) => boolean;
37
- /**
38
- * Handler metadata attached to handler constructors
39
- */
40
- export type HandlerMetadata<S extends ZodTypeAny> = {
41
- schema: S;
42
- declaredType?: string;
43
- match?: MatchFn<unknown>;
44
- safeParse: boolean;
45
- };
46
- /**
47
- * Channel metadata for NATS JetStream routing
48
- */
49
- export interface ChannelMetadata {
50
- /** JetStream stream name (e.g., 'ORDERS') */
51
- stream: string;
52
- /** NATS subject (defaults to event type if not specified) */
53
- subject: string;
54
- }
55
- /**
56
- * Channel configuration input (subject is optional, defaults to type)
57
- */
58
- export interface ChannelConfig {
59
- /** JetStream stream name (e.g., 'ORDERS') */
60
- stream: string;
61
- /** NATS subject (optional, defaults to event type) */
62
- subject?: string;
63
- }
64
- /**
65
- * Options for creating event handlers
66
- *
67
- * Note: In Zod v4, we use a more relaxed schema constraint to allow
68
- * contracts defined in external packages to work correctly.
69
- */
70
- export interface HandleEventOptions<S = ZodTypeAny> {
71
- schema: S;
72
- type?: string;
73
- match?: MatchFn<unknown>;
74
- safeParse?: boolean;
75
- /** Filter events by tenant ID(s). If set, only events matching these tenant(s) are processed. */
76
- tenantId?: string | string[];
77
- /** Channel metadata for NATS JetStream routing (optional) */
78
- channel?: ChannelConfig;
79
- }
80
- /**
81
- * Routing configuration for type → subject → stream mapping
82
- */
83
- export interface RoutingConfig {
84
- /** Map event type prefix to NATS subject prefix, e.g., { 'orderboss.orders': 'orders' } */
85
- typeToSubjectMap?: Record<string, string>;
86
- /** Map event type prefix to stream name, e.g., { 'orderboss.orders': 'ORDERS' } */
87
- typeToStreamMap?: Record<string, string>;
88
- /** Default subject prefix when no mapping found */
89
- defaultSubjectPrefix?: string;
90
- }
91
- /**
92
- * Idempotency store interface for deduplication
93
- */
94
- export interface IdempotencyStore {
95
- /** Check if a message has already been processed */
96
- has(messageId: string): Promise<boolean> | boolean;
97
- /** Mark a message as processed */
98
- add(messageId: string, ttlMs?: number): Promise<void> | void;
99
- /** Clear the store (useful for testing) */
100
- clear?(): Promise<void> | void;
101
- }
102
- /**
103
- * Type helper to extract data type from a Zod schema
104
- * Handles both data-only schemas and full CloudEvent schemas with a 'data' field
105
- */
106
- export type InferEventData<S extends ZodTypeAny> = S['_output'] extends {
107
- data: infer D;
108
- } ? D : S['_output'];
@@ -1,6 +0,0 @@
1
- /**
2
- * Domain Types
3
- *
4
- * Core business logic types for handlers, events, and domain operations
5
- */
6
- export {};
@@ -1,37 +0,0 @@
1
- /**
2
- * Domain Validation
3
- *
4
- * Core business logic for validating events, handlers, and schemas
5
- * Contains no infrastructure concerns - pure domain logic
6
- */
7
- import type { ZodTypeAny } from 'zod';
8
- /**
9
- * Validation error detail for individual field errors
10
- */
11
- export interface ValidationErrorDetail {
12
- code?: string;
13
- message: string;
14
- path?: (string | number)[];
15
- expected?: string;
16
- received?: string;
17
- validation?: string;
18
- }
19
- /**
20
- * Handler validation error with handler information
21
- */
22
- export interface HandlerValidationError {
23
- handlerName: string;
24
- validationErrors: ValidationErrorDetail[];
25
- }
26
- /**
27
- * Validates whether an exported value is a valid event handler
28
- * Checks for either eventarc metadata or a handle method in the prototype
29
- */
30
- export declare function isValidHandler(value: unknown): boolean;
31
- /**
32
- * Extracts the event type from a Zod schema by looking for a literal 'type' field
33
- *
34
- * @param schema - Zod schema to extract type from
35
- * @returns Event type string or undefined if not found
36
- */
37
- export declare const extractTypeFromSchema: (schema: ZodTypeAny) => string | undefined;
@@ -1,53 +0,0 @@
1
- /**
2
- * Domain Validation
3
- *
4
- * Core business logic for validating events, handlers, and schemas
5
- * Contains no infrastructure concerns - pure domain logic
6
- */
7
- /**
8
- * Type guards for schema shape analysis
9
- */
10
- const hasShape = (schema) => 'shape' in schema &&
11
- schema.shape !== null &&
12
- schema.shape !== undefined &&
13
- typeof schema.shape === 'object';
14
- const hasTypeField = (shape) => 'type' in shape &&
15
- shape.type !== null &&
16
- shape.type !== undefined &&
17
- typeof shape.type === 'object' &&
18
- 'value' in shape.type;
19
- const extractTypeValue = (typeField) => typeof typeField.value === 'string' ? typeField.value : undefined;
20
- /**
21
- * Safely extracts type from schema shape
22
- */
23
- const safeExtractType = (schema) => {
24
- if (!hasShape(schema))
25
- return undefined;
26
- if (!hasTypeField(schema.shape))
27
- return undefined;
28
- return extractTypeValue(schema.shape.type);
29
- };
30
- /**
31
- * Validates whether an exported value is a valid event handler
32
- * Checks for either eventarc metadata or a handle method in the prototype
33
- */
34
- export function isValidHandler(value) {
35
- if (typeof value !== 'function')
36
- return false;
37
- const handler = value;
38
- return !!(handler.__eventarcMetadata || handler.prototype?.handle);
39
- }
40
- /**
41
- * Extracts the event type from a Zod schema by looking for a literal 'type' field
42
- *
43
- * @param schema - Zod schema to extract type from
44
- * @returns Event type string or undefined if not found
45
- */
46
- export const extractTypeFromSchema = (schema) => {
47
- try {
48
- return safeExtractType(schema);
49
- }
50
- catch {
51
- return undefined;
52
- }
53
- };
@@ -1,53 +0,0 @@
1
- import type { Context } from 'hono';
2
- import type { HandlerValidationError } from '../domain';
3
- export type ErrorResponse = {
4
- error: {
5
- type: string;
6
- message: string;
7
- timestamp: string;
8
- details?: unknown;
9
- };
10
- };
11
- export type SuccessResponse = {
12
- message: string;
13
- timestamp: string;
14
- };
15
- export type ValidationError = {
16
- type: 'ValidationError';
17
- eventType: string;
18
- message: string;
19
- details: HandlerValidationError[];
20
- };
21
- export type NoHandlerFoundError = {
22
- type: 'NoHandlerFoundError';
23
- eventType: string;
24
- message: string;
25
- };
26
- export type CloudEventParseError = {
27
- type: 'CloudEventParseError';
28
- message: string;
29
- cause?: Error;
30
- };
31
- /**
32
- * Handles errors with full context logging
33
- */
34
- export declare const handleErrorWithContext: (error: Error, context: Context, additionalInfo?: Record<string, unknown>) => {
35
- message: string;
36
- stack: string | undefined;
37
- url: string;
38
- method: string;
39
- headers: {
40
- [k: string]: string;
41
- };
42
- };
43
- /**
44
- * Converts an error to a standardized response format
45
- */
46
- export declare const errorToResponse: (error: Error, type?: string) => ErrorResponse;
47
- /**
48
- * Creates a standardized error response
49
- */
50
- export declare const createErrorResponse: (type: string, message: string, details?: unknown) => ErrorResponse;
51
- export declare const createValidationError: (eventType: string, details: HandlerValidationError[]) => ValidationError;
52
- export declare const createNoHandlerFoundError: (eventType: string) => NoHandlerFoundError;
53
- export declare const createCloudEventParseError: (message: string, cause?: Error) => CloudEventParseError;