@spfn/core 0.1.0-alpha.82 → 0.1.0-alpha.84
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/dist/cache/index.js +6 -136
- package/dist/cache/index.js.map +1 -1
- package/dist/codegen/generators/index.js +6 -134
- package/dist/codegen/generators/index.js.map +1 -1
- package/dist/codegen/index.d.ts +5 -0
- package/dist/codegen/index.js +21 -145
- package/dist/codegen/index.js.map +1 -1
- package/dist/db/index.d.ts +1 -0
- package/dist/db/index.js +41 -135
- package/dist/db/index.js.map +1 -1
- package/dist/env/index.js +6 -134
- package/dist/env/index.js.map +1 -1
- package/dist/events/index.d.ts +183 -0
- package/dist/events/index.js +77 -0
- package/dist/events/index.js.map +1 -0
- package/dist/index.js +174 -180
- package/dist/index.js.map +1 -1
- package/dist/logger/index.d.ts +90 -34
- package/dist/logger/index.js +7 -137
- package/dist/logger/index.js.map +1 -1
- package/dist/middleware/index.js +22 -138
- package/dist/middleware/index.js.map +1 -1
- package/dist/route/index.js +12 -152
- package/dist/route/index.js.map +1 -1
- package/dist/server/index.d.ts +110 -4
- package/dist/server/index.js +174 -180
- package/dist/server/index.js.map +1 -1
- package/package.json +7 -4
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event handler function type
|
|
3
|
+
*/
|
|
4
|
+
type EventHandler<T = any> = (data: T) => Promise<void> | void;
|
|
5
|
+
/**
|
|
6
|
+
* EventEmitter interface
|
|
7
|
+
*
|
|
8
|
+
* All event emitter adapters must implement this interface
|
|
9
|
+
*/
|
|
10
|
+
interface EventEmitter {
|
|
11
|
+
/**
|
|
12
|
+
* Subscribe to an event
|
|
13
|
+
*
|
|
14
|
+
* @param event - Event name
|
|
15
|
+
* @param handler - Event handler function
|
|
16
|
+
*/
|
|
17
|
+
on(event: string, handler: EventHandler): void;
|
|
18
|
+
/**
|
|
19
|
+
* Emit an event
|
|
20
|
+
*
|
|
21
|
+
* @param event - Event name
|
|
22
|
+
* @param data - Event data
|
|
23
|
+
*/
|
|
24
|
+
emit(event: string, data?: any): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Unsubscribe from an event
|
|
27
|
+
*
|
|
28
|
+
* @param event - Event name
|
|
29
|
+
*/
|
|
30
|
+
off(event: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Clear all event subscriptions
|
|
33
|
+
*/
|
|
34
|
+
clear(): void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Event Emitter
|
|
39
|
+
*
|
|
40
|
+
* Adapter-based event emitter for decoupled communication between packages.
|
|
41
|
+
*
|
|
42
|
+
* Default adapter: InMemoryEventEmitter (single-instance)
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* // Subscribe to events
|
|
47
|
+
* import { on } from '@spfn/core/events';
|
|
48
|
+
*
|
|
49
|
+
* on('user:created', async (data) => {
|
|
50
|
+
* console.log('User created:', data.email);
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
53
|
+
* // Emit events
|
|
54
|
+
* import { emit } from '@spfn/core/events';
|
|
55
|
+
*
|
|
56
|
+
* await emit('user:created', {
|
|
57
|
+
* userId: '123',
|
|
58
|
+
* email: 'user@example.com'
|
|
59
|
+
* });
|
|
60
|
+
*
|
|
61
|
+
* // Switch to Redis adapter (multi-instance)
|
|
62
|
+
* import { setEventEmitter } from '@spfn/core/events';
|
|
63
|
+
* import { RedisEventEmitter } from '@spfn/core/events/adapters';
|
|
64
|
+
*
|
|
65
|
+
* setEventEmitter(new RedisEventEmitter({
|
|
66
|
+
* host: 'localhost',
|
|
67
|
+
* port: 6379
|
|
68
|
+
* }));
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Set the event emitter adapter
|
|
74
|
+
*
|
|
75
|
+
* @param adapter - EventEmitter adapter implementation
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* import { setEventEmitter } from '@spfn/core/events';
|
|
80
|
+
* import { InMemoryEventEmitter } from '@spfn/core/events/adapters';
|
|
81
|
+
*
|
|
82
|
+
* setEventEmitter(new InMemoryEventEmitter());
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
declare function setEventEmitter(adapter: EventEmitter): void;
|
|
86
|
+
/**
|
|
87
|
+
* Get the current event emitter adapter
|
|
88
|
+
*
|
|
89
|
+
* @returns Current EventEmitter instance
|
|
90
|
+
*/
|
|
91
|
+
declare function getEventEmitter(): EventEmitter;
|
|
92
|
+
/**
|
|
93
|
+
* Subscribe to an event
|
|
94
|
+
*
|
|
95
|
+
* @param event - Event name
|
|
96
|
+
* @param handler - Event handler function
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* on('user:created', async (data) => {
|
|
101
|
+
* console.log('User created:', data.email);
|
|
102
|
+
* });
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
declare function on(event: string, handler: EventHandler): void;
|
|
106
|
+
/**
|
|
107
|
+
* Emit an event
|
|
108
|
+
*
|
|
109
|
+
* @param event - Event name
|
|
110
|
+
* @param data - Event data
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* await emit('user:created', {
|
|
115
|
+
* userId: '123',
|
|
116
|
+
* email: 'user@example.com'
|
|
117
|
+
* });
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
declare function emit(event: string, data?: any): Promise<void>;
|
|
121
|
+
/**
|
|
122
|
+
* Unsubscribe from an event
|
|
123
|
+
*
|
|
124
|
+
* @param event - Event name
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* off('user:created');
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
declare function off(event: string): void;
|
|
132
|
+
/**
|
|
133
|
+
* Clear all event subscriptions
|
|
134
|
+
*
|
|
135
|
+
* Useful for testing or cleanup
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* // In tests
|
|
140
|
+
* beforeEach(() => {
|
|
141
|
+
* clear();
|
|
142
|
+
* });
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
declare function clear(): void;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* In-Memory Event Emitter
|
|
149
|
+
*
|
|
150
|
+
* Simple in-process event emitter for single-instance deployments.
|
|
151
|
+
* Events are not shared across multiple server instances.
|
|
152
|
+
*
|
|
153
|
+
* Use this adapter for:
|
|
154
|
+
* - Development
|
|
155
|
+
* - Single-instance production deployments
|
|
156
|
+
* - When you don't need distributed events
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* import { setEventEmitter } from '@spfn/core/events';
|
|
161
|
+
* import { InMemoryEventEmitter } from '@spfn/core/events/adapters';
|
|
162
|
+
*
|
|
163
|
+
* setEventEmitter(new InMemoryEventEmitter());
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
|
|
167
|
+
declare class InMemoryEventEmitter implements EventEmitter {
|
|
168
|
+
private listeners;
|
|
169
|
+
on(event: string, handler: EventHandler): void;
|
|
170
|
+
emit(event: string, data?: any): Promise<void>;
|
|
171
|
+
off(event: string): void;
|
|
172
|
+
clear(): void;
|
|
173
|
+
/**
|
|
174
|
+
* Get list of registered events (for debugging)
|
|
175
|
+
*/
|
|
176
|
+
getEvents(): string[];
|
|
177
|
+
/**
|
|
178
|
+
* Get number of handlers for an event (for debugging)
|
|
179
|
+
*/
|
|
180
|
+
getHandlerCount(event: string): number;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export { type EventEmitter, type EventHandler, InMemoryEventEmitter, clear, emit, getEventEmitter, off, on, setEventEmitter };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// src/events/adapters/memory.ts
|
|
2
|
+
var InMemoryEventEmitter = class {
|
|
3
|
+
listeners = /* @__PURE__ */ new Map();
|
|
4
|
+
on(event, handler) {
|
|
5
|
+
if (!this.listeners.has(event)) {
|
|
6
|
+
this.listeners.set(event, []);
|
|
7
|
+
}
|
|
8
|
+
this.listeners.get(event).push(handler);
|
|
9
|
+
}
|
|
10
|
+
async emit(event, data) {
|
|
11
|
+
const handlers = this.listeners.get(event) || [];
|
|
12
|
+
if (handlers.length === 0) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const results = await Promise.allSettled(
|
|
16
|
+
handlers.map(async (handler) => {
|
|
17
|
+
try {
|
|
18
|
+
return await handler(data);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
);
|
|
24
|
+
const failed = results.filter((r) => r.status === "rejected");
|
|
25
|
+
if (failed.length > 0) {
|
|
26
|
+
console.error(
|
|
27
|
+
`[Events] ${failed.length}/${handlers.length} handlers failed for event "${event}"`,
|
|
28
|
+
{
|
|
29
|
+
errors: failed.map((r) => r.reason)
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
off(event) {
|
|
35
|
+
this.listeners.delete(event);
|
|
36
|
+
}
|
|
37
|
+
clear() {
|
|
38
|
+
this.listeners.clear();
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get list of registered events (for debugging)
|
|
42
|
+
*/
|
|
43
|
+
getEvents() {
|
|
44
|
+
return Array.from(this.listeners.keys());
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get number of handlers for an event (for debugging)
|
|
48
|
+
*/
|
|
49
|
+
getHandlerCount(event) {
|
|
50
|
+
return this.listeners.get(event)?.length || 0;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// src/events/emitter.ts
|
|
55
|
+
var emitter = new InMemoryEventEmitter();
|
|
56
|
+
function setEventEmitter(adapter) {
|
|
57
|
+
emitter = adapter;
|
|
58
|
+
}
|
|
59
|
+
function getEventEmitter() {
|
|
60
|
+
return emitter;
|
|
61
|
+
}
|
|
62
|
+
function on(event, handler) {
|
|
63
|
+
emitter.on(event, handler);
|
|
64
|
+
}
|
|
65
|
+
async function emit(event, data) {
|
|
66
|
+
await emitter.emit(event, data);
|
|
67
|
+
}
|
|
68
|
+
function off(event) {
|
|
69
|
+
emitter.off(event);
|
|
70
|
+
}
|
|
71
|
+
function clear() {
|
|
72
|
+
emitter.clear();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export { InMemoryEventEmitter, clear, emit, getEventEmitter, off, on, setEventEmitter };
|
|
76
|
+
//# sourceMappingURL=index.js.map
|
|
77
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/events/adapters/memory.ts","../../src/events/emitter.ts"],"names":[],"mappings":";AAsBO,IAAM,uBAAN,MACP;AAAA,EACY,SAAA,uBAAgB,GAAA,EAA4B;AAAA,EAEpD,EAAA,CAAG,OAAe,OAAA,EAClB;AACI,IAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA,EAC7B;AACI,MAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAA,EAAO,EAAE,CAAA;AAAA,IAChC;AACA,IAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA,CAAG,KAAK,OAAO,CAAA;AAAA,EAC3C;AAAA,EAEA,MAAM,IAAA,CAAK,KAAA,EAAe,IAAA,EAC1B;AACI,IAAA,MAAM,WAAW,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAK,KAAK,EAAC;AAE/C,IAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EACxB;AACI,MAAA;AAAA,IACJ;AAIA,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,UAAA;AAAA,MAC1B,QAAA,CAAS,GAAA,CAAI,OAAO,OAAA,KACpB;AACI,QAAA,IACA;AACI,UAAA,OAAO,MAAM,QAAQ,IAAI,CAAA;AAAA,QAC7B,SACO,KAAA,EACP;AAEI,UAAA,MAAM,KAAA;AAAA,QACV;AAAA,MACJ,CAAC;AAAA,KACL;AAGA,IAAA,MAAM,SAAS,OAAA,CAAQ,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,WAAW,UAAU,CAAA;AAC1D,IAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EACpB;AACI,MAAA,OAAA,CAAQ,KAAA;AAAA,QACJ,YAAY,MAAA,CAAO,MAAM,IAAI,QAAA,CAAS,MAAM,+BAA+B,KAAK,CAAA,CAAA,CAAA;AAAA,QAChF;AAAA,UACI,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,CAAA,CAAA,KAAM,EAA4B,MAAM;AAAA;AAC/D,OACJ;AAAA,IACJ;AAAA,EACJ;AAAA,EAEA,IAAI,KAAA,EACJ;AACI,IAAA,IAAA,CAAK,SAAA,CAAU,OAAO,KAAK,CAAA;AAAA,EAC/B;AAAA,EAEA,KAAA,GACA;AACI,IAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GACA;AACI,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,KAAA,EAChB;AACI,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAK,GAAG,MAAA,IAAU,CAAA;AAAA,EAChD;AACJ;;;AC7DA,IAAI,OAAA,GAAwB,IAAI,oBAAA,EAAqB;AAe9C,SAAS,gBAAgB,OAAA,EAChC;AACI,EAAA,OAAA,GAAU,OAAA;AACd;AAOO,SAAS,eAAA,GAChB;AACI,EAAA,OAAO,OAAA;AACX;AAeO,SAAS,EAAA,CAAG,OAAe,OAAA,EAClC;AACI,EAAA,OAAA,CAAQ,EAAA,CAAG,OAAO,OAAO,CAAA;AAC7B;AAgBA,eAAsB,IAAA,CAAK,OAAe,IAAA,EAC1C;AACI,EAAA,MAAM,OAAA,CAAQ,IAAA,CAAK,KAAA,EAAO,IAAI,CAAA;AAClC;AAYO,SAAS,IAAI,KAAA,EACpB;AACI,EAAA,OAAA,CAAQ,IAAI,KAAK,CAAA;AACrB;AAeO,SAAS,KAAA,GAChB;AACI,EAAA,OAAA,CAAQ,KAAA,EAAM;AAClB","file":"index.js","sourcesContent":["/**\n * In-Memory Event Emitter\n *\n * Simple in-process event emitter for single-instance deployments.\n * Events are not shared across multiple server instances.\n *\n * Use this adapter for:\n * - Development\n * - Single-instance production deployments\n * - When you don't need distributed events\n *\n * @example\n * ```typescript\n * import { setEventEmitter } from '@spfn/core/events';\n * import { InMemoryEventEmitter } from '@spfn/core/events/adapters';\n *\n * setEventEmitter(new InMemoryEventEmitter());\n * ```\n */\n\nimport type { EventEmitter, EventHandler } from '../types';\n\nexport class InMemoryEventEmitter implements EventEmitter\n{\n private listeners = new Map<string, EventHandler[]>();\n\n on(event: string, handler: EventHandler): void\n {\n if (!this.listeners.has(event))\n {\n this.listeners.set(event, []);\n }\n this.listeners.get(event)!.push(handler);\n }\n\n async emit(event: string, data?: any): Promise<void>\n {\n const handlers = this.listeners.get(event) || [];\n\n if (handlers.length === 0)\n {\n return;\n }\n\n // Execute all handlers in parallel\n // Failures in individual handlers don't affect others\n const results = await Promise.allSettled(\n handlers.map(async (handler) =>\n {\n try\n {\n return await handler(data);\n }\n catch (error)\n {\n // Catch and re-throw for Promise.allSettled\n throw error;\n }\n })\n );\n\n // Log failed handlers for debugging\n const failed = results.filter(r => r.status === 'rejected');\n if (failed.length > 0)\n {\n console.error(\n `[Events] ${failed.length}/${handlers.length} handlers failed for event \"${event}\"`,\n {\n errors: failed.map(r => (r as PromiseRejectedResult).reason),\n }\n );\n }\n }\n\n off(event: string): void\n {\n this.listeners.delete(event);\n }\n\n clear(): void\n {\n this.listeners.clear();\n }\n\n /**\n * Get list of registered events (for debugging)\n */\n getEvents(): string[]\n {\n return Array.from(this.listeners.keys());\n }\n\n /**\n * Get number of handlers for an event (for debugging)\n */\n getHandlerCount(event: string): number\n {\n return this.listeners.get(event)?.length || 0;\n }\n}","/**\n * Event Emitter\n *\n * Adapter-based event emitter for decoupled communication between packages.\n *\n * Default adapter: InMemoryEventEmitter (single-instance)\n *\n * @example\n * ```typescript\n * // Subscribe to events\n * import { on } from '@spfn/core/events';\n *\n * on('user:created', async (data) => {\n * console.log('User created:', data.email);\n * });\n *\n * // Emit events\n * import { emit } from '@spfn/core/events';\n *\n * await emit('user:created', {\n * userId: '123',\n * email: 'user@example.com'\n * });\n *\n * // Switch to Redis adapter (multi-instance)\n * import { setEventEmitter } from '@spfn/core/events';\n * import { RedisEventEmitter } from '@spfn/core/events/adapters';\n *\n * setEventEmitter(new RedisEventEmitter({\n * host: 'localhost',\n * port: 6379\n * }));\n * ```\n */\n\nimport type { EventEmitter, EventHandler } from './types';\nimport { InMemoryEventEmitter } from './adapters/memory';\n\nlet emitter: EventEmitter = new InMemoryEventEmitter();\n\n/**\n * Set the event emitter adapter\n *\n * @param adapter - EventEmitter adapter implementation\n *\n * @example\n * ```typescript\n * import { setEventEmitter } from '@spfn/core/events';\n * import { InMemoryEventEmitter } from '@spfn/core/events/adapters';\n *\n * setEventEmitter(new InMemoryEventEmitter());\n * ```\n */\nexport function setEventEmitter(adapter: EventEmitter): void\n{\n emitter = adapter;\n}\n\n/**\n * Get the current event emitter adapter\n *\n * @returns Current EventEmitter instance\n */\nexport function getEventEmitter(): EventEmitter\n{\n return emitter;\n}\n\n/**\n * Subscribe to an event\n *\n * @param event - Event name\n * @param handler - Event handler function\n *\n * @example\n * ```typescript\n * on('user:created', async (data) => {\n * console.log('User created:', data.email);\n * });\n * ```\n */\nexport function on(event: string, handler: EventHandler): void\n{\n emitter.on(event, handler);\n}\n\n/**\n * Emit an event\n *\n * @param event - Event name\n * @param data - Event data\n *\n * @example\n * ```typescript\n * await emit('user:created', {\n * userId: '123',\n * email: 'user@example.com'\n * });\n * ```\n */\nexport async function emit(event: string, data?: any): Promise<void>\n{\n await emitter.emit(event, data);\n}\n\n/**\n * Unsubscribe from an event\n *\n * @param event - Event name\n *\n * @example\n * ```typescript\n * off('user:created');\n * ```\n */\nexport function off(event: string): void\n{\n emitter.off(event);\n}\n\n/**\n * Clear all event subscriptions\n *\n * Useful for testing or cleanup\n *\n * @example\n * ```typescript\n * // In tests\n * beforeEach(() => {\n * clear();\n * });\n * ```\n */\nexport function clear(): void\n{\n emitter.clear();\n}"]}
|