opinionated-machine 5.1.0 → 5.2.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 +1237 -278
- package/dist/index.d.ts +3 -2
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/AbstractController.d.ts +3 -3
- package/dist/lib/AbstractController.js.map +1 -1
- package/dist/lib/AbstractModule.d.ts +14 -0
- package/dist/lib/AbstractModule.js +16 -0
- package/dist/lib/AbstractModule.js.map +1 -1
- package/dist/lib/DIContext.d.ts +35 -0
- package/dist/lib/DIContext.js +99 -0
- package/dist/lib/DIContext.js.map +1 -1
- package/dist/lib/resolverFunctions.d.ts +33 -0
- package/dist/lib/resolverFunctions.js +46 -0
- package/dist/lib/resolverFunctions.js.map +1 -1
- package/dist/lib/sse/AbstractSSEController.d.ts +163 -0
- package/dist/lib/sse/AbstractSSEController.js +228 -0
- package/dist/lib/sse/AbstractSSEController.js.map +1 -0
- package/dist/lib/sse/SSEConnectionSpy.d.ts +55 -0
- package/dist/lib/sse/SSEConnectionSpy.js +136 -0
- package/dist/lib/sse/SSEConnectionSpy.js.map +1 -0
- package/dist/lib/sse/index.d.ts +5 -0
- package/dist/lib/sse/index.js +6 -0
- package/dist/lib/sse/index.js.map +1 -0
- package/dist/lib/sse/sseContracts.d.ts +132 -0
- package/dist/lib/sse/sseContracts.js +102 -0
- package/dist/lib/sse/sseContracts.js.map +1 -0
- package/dist/lib/sse/sseParser.d.ts +167 -0
- package/dist/lib/sse/sseParser.js +225 -0
- package/dist/lib/sse/sseParser.js.map +1 -0
- package/dist/lib/sse/sseRouteBuilder.d.ts +47 -0
- package/dist/lib/sse/sseRouteBuilder.js +114 -0
- package/dist/lib/sse/sseRouteBuilder.js.map +1 -0
- package/dist/lib/sse/sseTypes.d.ts +164 -0
- package/dist/lib/sse/sseTypes.js +2 -0
- package/dist/lib/sse/sseTypes.js.map +1 -0
- package/dist/lib/testing/index.d.ts +5 -0
- package/dist/lib/testing/index.js +5 -0
- package/dist/lib/testing/index.js.map +1 -0
- package/dist/lib/testing/sseHttpClient.d.ts +203 -0
- package/dist/lib/testing/sseHttpClient.js +262 -0
- package/dist/lib/testing/sseHttpClient.js.map +1 -0
- package/dist/lib/testing/sseInjectClient.d.ts +173 -0
- package/dist/lib/testing/sseInjectClient.js +234 -0
- package/dist/lib/testing/sseInjectClient.js.map +1 -0
- package/dist/lib/testing/sseInjectHelpers.d.ts +59 -0
- package/dist/lib/testing/sseInjectHelpers.js +117 -0
- package/dist/lib/testing/sseInjectHelpers.js.map +1 -0
- package/dist/lib/testing/sseTestServer.d.ts +93 -0
- package/dist/lib/testing/sseTestServer.js +108 -0
- package/dist/lib/testing/sseTestServer.js.map +1 -0
- package/dist/lib/testing/sseTestTypes.d.ts +106 -0
- package/dist/lib/testing/sseTestTypes.js +2 -0
- package/dist/lib/testing/sseTestTypes.js.map +1 -0
- package/package.json +80 -78
package/dist/index.d.ts
CHANGED
|
@@ -4,5 +4,6 @@ export { AbstractTestContextFactory, type CreateTestContextParams, } from './lib
|
|
|
4
4
|
export type { NestedPartial } from './lib/configUtils.js';
|
|
5
5
|
export { type DependencyInjectionOptions, DIContext, type RegisterDependenciesParams, } from './lib/DIContext.js';
|
|
6
6
|
export { ENABLE_ALL, isAnyMessageQueueConsumerEnabled, isEnqueuedJobWorkersEnabled, isJobQueueEnabled, isMessageQueueConsumerEnabled, isPeriodicJobEnabled, resolveJobQueuesEnabled, } from './lib/diConfigUtils.js';
|
|
7
|
-
export
|
|
8
|
-
export
|
|
7
|
+
export * from './lib/resolverFunctions.js';
|
|
8
|
+
export * from './lib/sse/index.js';
|
|
9
|
+
export * from './lib/testing/index.js';
|
package/dist/index.js
CHANGED
|
@@ -3,5 +3,9 @@ export { AbstractModule, } from './lib/AbstractModule.js';
|
|
|
3
3
|
export { AbstractTestContextFactory, } from './lib/AbstractTestContextFactory.js';
|
|
4
4
|
export { DIContext, } from './lib/DIContext.js';
|
|
5
5
|
export { ENABLE_ALL, isAnyMessageQueueConsumerEnabled, isEnqueuedJobWorkersEnabled, isJobQueueEnabled, isMessageQueueConsumerEnabled, isPeriodicJobEnabled, resolveJobQueuesEnabled, } from './lib/diConfigUtils.js';
|
|
6
|
-
export
|
|
6
|
+
export * from './lib/resolverFunctions.js';
|
|
7
|
+
// SSE
|
|
8
|
+
export * from './lib/sse/index.js';
|
|
9
|
+
// SSE testing utilities
|
|
10
|
+
export * from './lib/testing/index.js';
|
|
7
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA8B,MAAM,6BAA6B,CAAA;AAC5F,OAAO,EACL,cAAc,GAGf,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,0BAA0B,GAE3B,MAAM,qCAAqC,CAAA;AAE5C,OAAO,EAEL,SAAS,GAEV,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,UAAU,EACV,gCAAgC,EAChC,2BAA2B,EAC3B,iBAAiB,EACjB,6BAA6B,EAC7B,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA8B,MAAM,6BAA6B,CAAA;AAC5F,OAAO,EACL,cAAc,GAGf,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,0BAA0B,GAE3B,MAAM,qCAAqC,CAAA;AAE5C,OAAO,EAEL,SAAS,GAEV,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,UAAU,EACV,gCAAgC,EAChC,2BAA2B,EAC3B,iBAAiB,EACjB,6BAA6B,EAC7B,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,wBAAwB,CAAA;AAC/B,cAAc,4BAA4B,CAAA;AAC1C,MAAM;AACN,cAAc,oBAAoB,CAAA;AAClC,wBAAwB;AACxB,cAAc,wBAAwB,CAAA"}
|
|
@@ -3,10 +3,10 @@ import type { buildFastifyNoPayloadRoute, buildFastifyPayloadRoute } from '@loka
|
|
|
3
3
|
import type { z } from 'zod/v4';
|
|
4
4
|
type AnyCommonRouteDefinition = CommonRouteDefinition<any, any, any, any, any, any, any, any>;
|
|
5
5
|
type OptionalZodSchema = z.Schema | undefined;
|
|
6
|
-
type FastifyPayloadRouteReturnType<RequestBody extends OptionalZodSchema, ResponseBody extends OptionalZodSchema, Path extends OptionalZodSchema, Query extends OptionalZodSchema, Headers extends OptionalZodSchema, ResponseHeaders extends OptionalZodSchema, IsNonJSONResponseExpected extends boolean, IsEmptyResponseExpected extends boolean> = ReturnType<typeof buildFastifyPayloadRoute<RequestBody, ResponseBody, Path, Query, Headers, ResponseHeaders, IsNonJSONResponseExpected, IsEmptyResponseExpected>>;
|
|
7
|
-
type FastifyNoPayloadRouteReturnType<RequestBody extends OptionalZodSchema, Path extends OptionalZodSchema, Query extends OptionalZodSchema, Headers extends OptionalZodSchema, ResponseHeaders extends OptionalZodSchema> = ReturnType<typeof buildFastifyNoPayloadRoute<RequestBody, Path, Query, Headers, ResponseHeaders>>;
|
|
6
|
+
type FastifyPayloadRouteReturnType<RequestBody extends OptionalZodSchema, ResponseBody extends OptionalZodSchema, Path extends OptionalZodSchema, Query extends OptionalZodSchema, Headers extends OptionalZodSchema, ResponseHeaders extends OptionalZodSchema, IsNonJSONResponseExpected extends boolean, IsEmptyResponseExpected extends boolean, ResponseSchemasByStatusCode extends Record<number, any> | undefined> = ReturnType<typeof buildFastifyPayloadRoute<RequestBody, ResponseBody, Path, Query, Headers, ResponseHeaders, IsNonJSONResponseExpected, IsEmptyResponseExpected, ResponseSchemasByStatusCode>>;
|
|
7
|
+
type FastifyNoPayloadRouteReturnType<RequestBody extends OptionalZodSchema, Path extends OptionalZodSchema, Query extends OptionalZodSchema, Headers extends OptionalZodSchema, ResponseHeaders extends OptionalZodSchema, ResponseSchemasByStatusCode extends Record<number, any> | undefined> = ReturnType<typeof buildFastifyNoPayloadRoute<RequestBody, Path, Query, Headers, ResponseHeaders, ResponseSchemasByStatusCode>>;
|
|
8
8
|
export type BuildRoutesReturnType<APIContracts extends Record<string, AnyCommonRouteDefinition>> = {
|
|
9
|
-
[K in keyof APIContracts]: APIContracts[K] extends PayloadRouteDefinition<infer RequestBody, infer ResponseBody, infer Path, infer Query, infer Headers, infer ResponseHeaders, infer IsNonJSONResponseExpected, infer IsEmptyResponseExpected, infer
|
|
9
|
+
[K in keyof APIContracts]: APIContracts[K] extends PayloadRouteDefinition<infer RequestBody, infer ResponseBody, infer Path, infer Query, infer Headers, infer ResponseHeaders, infer IsNonJSONResponseExpected, infer IsEmptyResponseExpected, infer ResponseSchemasByStatusCode> ? FastifyPayloadRouteReturnType<RequestBody, ResponseBody, Path, Query, Headers, ResponseHeaders, IsNonJSONResponseExpected, IsEmptyResponseExpected, ResponseSchemasByStatusCode> : APIContracts[K] extends GetRouteDefinition<infer GetResponseBody, infer GetPath, infer GetQuery, infer GetHeaders, infer GetResponseHeaders, infer _GetIsNonJSONResponseExpected, infer _GetIsEmptyResponseExpected, infer GetResponseSchemasByStatusCode> | DeleteRouteDefinition<infer DeleteResponseBody, infer DeletePath, infer DeleteQuery, infer DeleteHeaders, infer DeleteResponseHeaders, infer _DeleteIsNonJSONResponseExpected, infer _DeleteIsEmptyResponseExpected, infer DeleteResponseSchemasByStatusCode> ? FastifyNoPayloadRouteReturnType<GetResponseBody | DeleteResponseBody, GetPath | DeletePath, GetQuery | DeleteQuery, GetHeaders | DeleteHeaders, GetResponseHeaders | DeleteResponseHeaders, GetResponseSchemasByStatusCode | DeleteResponseSchemasByStatusCode> : never;
|
|
10
10
|
};
|
|
11
11
|
export declare abstract class AbstractController<APIContracts extends Record<string, AnyCommonRouteDefinition>> {
|
|
12
12
|
abstract buildRoutes(): BuildRoutesReturnType<APIContracts>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractController.js","sourceRoot":"","sources":["../../lib/AbstractController.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AbstractController.js","sourceRoot":"","sources":["../../lib/AbstractController.ts"],"names":[],"mappings":"AAkHA,MAAM,OAAgB,kBAAkB;CAIvC"}
|
|
@@ -10,4 +10,18 @@ export type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) ex
|
|
|
10
10
|
export declare abstract class AbstractModule<ModuleDependencies, ExternalDependencies = never> {
|
|
11
11
|
abstract resolveDependencies(diOptions: DependencyInjectionOptions, externalDependencies: ExternalDependencies): MandatoryNameAndRegistrationPair<ModuleDependencies>;
|
|
12
12
|
abstract resolveControllers(): MandatoryNameAndRegistrationPair<unknown>;
|
|
13
|
+
/**
|
|
14
|
+
* Override to register SSE controllers.
|
|
15
|
+
* Returns empty object by default - no changes needed for modules without SSE.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* public resolveSSEControllers() {
|
|
20
|
+
* return {
|
|
21
|
+
* notificationsSSEController: asSSEControllerClass(NotificationsSSEController),
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
resolveSSEControllers(): MandatoryNameAndRegistrationPair<unknown>;
|
|
13
27
|
}
|
|
@@ -1,3 +1,19 @@
|
|
|
1
1
|
export class AbstractModule {
|
|
2
|
+
/**
|
|
3
|
+
* Override to register SSE controllers.
|
|
4
|
+
* Returns empty object by default - no changes needed for modules without SSE.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* public resolveSSEControllers() {
|
|
9
|
+
* return {
|
|
10
|
+
* notificationsSSEController: asSSEControllerClass(NotificationsSSEController),
|
|
11
|
+
* }
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
resolveSSEControllers() {
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
2
18
|
}
|
|
3
19
|
//# sourceMappingURL=AbstractModule.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractModule.js","sourceRoot":"","sources":["../../lib/AbstractModule.ts"],"names":[],"mappings":"AAcA,MAAM,OAAgB,cAAc;
|
|
1
|
+
{"version":3,"file":"AbstractModule.js","sourceRoot":"","sources":["../../lib/AbstractModule.ts"],"names":[],"mappings":"AAcA,MAAM,OAAgB,cAAc;IAQlC;;;;;;;;;;;;OAYG;IACI,qBAAqB;QAC1B,OAAO,EAAE,CAAA;IACX,CAAC;CACF"}
|
package/dist/lib/DIContext.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { FastifyInstance } from 'fastify';
|
|
|
4
4
|
import type { AbstractModule } from './AbstractModule.js';
|
|
5
5
|
import { type NestedPartial } from './configUtils.js';
|
|
6
6
|
import type { ENABLE_ALL } from './diConfigUtils.js';
|
|
7
|
+
import { type RegisterSSERoutesOptions } from './sse/sseRouteBuilder.js';
|
|
7
8
|
export type RegisterDependenciesParams<Dependencies, Config, ExternalDependencies> = {
|
|
8
9
|
modules: readonly AbstractModule<unknown, ExternalDependencies>[];
|
|
9
10
|
secondaryModules?: readonly AbstractModule<unknown, ExternalDependencies>[];
|
|
@@ -16,17 +17,51 @@ export type DependencyInjectionOptions = {
|
|
|
16
17
|
enqueuedJobWorkersEnabled?: false | typeof ENABLE_ALL | string[];
|
|
17
18
|
messageQueueConsumersEnabled?: false | typeof ENABLE_ALL | string[];
|
|
18
19
|
periodicJobsEnabled?: false | typeof ENABLE_ALL | string[];
|
|
20
|
+
/**
|
|
21
|
+
* Enable SSE test mode features like connection spying.
|
|
22
|
+
* Only relevant for SSE controllers. Set to true in test environments.
|
|
23
|
+
* @default false
|
|
24
|
+
*/
|
|
25
|
+
isTestMode?: boolean;
|
|
19
26
|
};
|
|
20
27
|
export declare class DIContext<Dependencies extends object, Config extends object, ExternalDependencies = undefined> {
|
|
21
28
|
private readonly options;
|
|
22
29
|
readonly awilixManager: AwilixManager;
|
|
23
30
|
readonly diContainer: AwilixContainer<Dependencies>;
|
|
24
31
|
private readonly controllerResolvers;
|
|
32
|
+
private readonly sseControllerNames;
|
|
25
33
|
private readonly appConfig;
|
|
26
34
|
constructor(diContainer: AwilixContainer, options: DependencyInjectionOptions, appConfig: Config, awilixManager?: AwilixManager);
|
|
27
35
|
private registerModule;
|
|
28
36
|
registerDependencies(params: RegisterDependenciesParams<Dependencies, Config, ExternalDependencies>, externalDependencies: ExternalDependencies, resolveControllers?: boolean): void;
|
|
29
37
|
registerRoutes(app: FastifyInstance<any, any, any, any>): void;
|
|
38
|
+
/**
|
|
39
|
+
* Check if any SSE controllers are registered.
|
|
40
|
+
* Use this to conditionally call registerSSERoutes().
|
|
41
|
+
*/
|
|
42
|
+
hasSSEControllers(): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Register SSE routes with the Fastify app.
|
|
45
|
+
*
|
|
46
|
+
* Must be called separately from registerRoutes().
|
|
47
|
+
* Requires @fastify/sse plugin to be registered on the app.
|
|
48
|
+
*
|
|
49
|
+
* @param app - Fastify instance with @fastify/sse registered
|
|
50
|
+
* @param options - Optional configuration for SSE routes
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* // Register @fastify/sse plugin first
|
|
55
|
+
* await app.register(fastifySSE, { heartbeatInterval: 30000 })
|
|
56
|
+
*
|
|
57
|
+
* // Then register SSE routes
|
|
58
|
+
* context.registerSSERoutes(app)
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
registerSSERoutes(app: FastifyInstance<any, any, any, any>, options?: RegisterSSERoutesOptions): void;
|
|
62
|
+
private applySSERouteOptions;
|
|
63
|
+
private applyPreHandlers;
|
|
64
|
+
private applyRateLimit;
|
|
30
65
|
destroy(): Promise<void>;
|
|
31
66
|
init(): Promise<void>;
|
|
32
67
|
}
|
package/dist/lib/DIContext.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { AwilixManager } from 'awilix-manager';
|
|
2
|
+
import { merge } from 'ts-deepmerge';
|
|
2
3
|
import { mergeConfigAndDependencyOverrides } from './configUtils.js';
|
|
4
|
+
import { buildFastifySSERoute } from './sse/sseRouteBuilder.js';
|
|
3
5
|
export class DIContext {
|
|
4
6
|
options;
|
|
5
7
|
awilixManager;
|
|
6
8
|
diContainer;
|
|
7
9
|
// biome-ignore lint/suspicious/noExplicitAny: all controllers are controllers
|
|
8
10
|
controllerResolvers;
|
|
11
|
+
// SSE controller dependency names (resolved from container to preserve singletons)
|
|
12
|
+
sseControllerNames;
|
|
9
13
|
appConfig;
|
|
10
14
|
constructor(diContainer, options, appConfig, awilixManager) {
|
|
11
15
|
this.options = options;
|
|
@@ -21,6 +25,7 @@ export class DIContext {
|
|
|
21
25
|
strictBooleanEnforced: true,
|
|
22
26
|
});
|
|
23
27
|
this.controllerResolvers = [];
|
|
28
|
+
this.sseControllerNames = [];
|
|
24
29
|
}
|
|
25
30
|
registerModule(module, targetDiConfig, externalDependencies, resolveControllers, isPrimaryModule) {
|
|
26
31
|
const resolvedDIConfig = module.resolveDependencies(this.options, externalDependencies);
|
|
@@ -33,6 +38,11 @@ export class DIContext {
|
|
|
33
38
|
}
|
|
34
39
|
if (isPrimaryModule && resolveControllers) {
|
|
35
40
|
this.controllerResolvers.push(...Object.values(module.resolveControllers()));
|
|
41
|
+
// Collect SSE controller names (resolved from container to preserve singletons)
|
|
42
|
+
const sseControllers = module.resolveSSEControllers();
|
|
43
|
+
if (sseControllers && Object.keys(sseControllers).length > 0) {
|
|
44
|
+
this.sseControllerNames.push(...Object.keys(sseControllers));
|
|
45
|
+
}
|
|
36
46
|
}
|
|
37
47
|
}
|
|
38
48
|
registerDependencies(params, externalDependencies, resolveControllers = true) {
|
|
@@ -68,10 +78,99 @@ export class DIContext {
|
|
|
68
78
|
const controller = controllerResolver.resolve(this.diContainer);
|
|
69
79
|
const routes = controller.buildRoutes();
|
|
70
80
|
for (const route of Object.values(routes)) {
|
|
81
|
+
// Cast needed: GET/DELETE routes have body:undefined, POST/PATCH have body:unknown
|
|
82
|
+
// The union is incompatible with app.route() due to handler contravariance
|
|
83
|
+
app.route(route);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if any SSE controllers are registered.
|
|
89
|
+
* Use this to conditionally call registerSSERoutes().
|
|
90
|
+
*/
|
|
91
|
+
hasSSEControllers() {
|
|
92
|
+
return this.sseControllerNames.length > 0;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Register SSE routes with the Fastify app.
|
|
96
|
+
*
|
|
97
|
+
* Must be called separately from registerRoutes().
|
|
98
|
+
* Requires @fastify/sse plugin to be registered on the app.
|
|
99
|
+
*
|
|
100
|
+
* @param app - Fastify instance with @fastify/sse registered
|
|
101
|
+
* @param options - Optional configuration for SSE routes
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* // Register @fastify/sse plugin first
|
|
106
|
+
* await app.register(fastifySSE, { heartbeatInterval: 30000 })
|
|
107
|
+
*
|
|
108
|
+
* // Then register SSE routes
|
|
109
|
+
* context.registerSSERoutes(app)
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
registerSSERoutes(
|
|
113
|
+
// biome-ignore lint/suspicious/noExplicitAny: Fastify instance types are complex
|
|
114
|
+
app, options) {
|
|
115
|
+
if (!this.hasSSEControllers()) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
for (const controllerName of this.sseControllerNames) {
|
|
119
|
+
// Resolve from container to use the singleton instance
|
|
120
|
+
const sseController = this.diContainer.resolve(controllerName);
|
|
121
|
+
const sseRoutes = sseController.buildSSERoutes();
|
|
122
|
+
for (const routeConfig of Object.values(sseRoutes)) {
|
|
123
|
+
const route = buildFastifySSERoute(sseController, routeConfig);
|
|
124
|
+
this.applySSERouteOptions(route, options);
|
|
71
125
|
app.route(route);
|
|
72
126
|
}
|
|
73
127
|
}
|
|
74
128
|
}
|
|
129
|
+
applySSERouteOptions(route, options) {
|
|
130
|
+
if (options?.preHandler) {
|
|
131
|
+
this.applyPreHandlers(route, options.preHandler);
|
|
132
|
+
}
|
|
133
|
+
if (options?.rateLimit) {
|
|
134
|
+
this.applyRateLimit(route, options.rateLimit);
|
|
135
|
+
}
|
|
136
|
+
// Apply SSE-specific options (heartbeatInterval, serializer)
|
|
137
|
+
if (options?.heartbeatInterval !== undefined || options?.serializer !== undefined) {
|
|
138
|
+
// biome-ignore lint/suspicious/noExplicitAny: config types vary by plugins
|
|
139
|
+
const routeWithConfig = route;
|
|
140
|
+
routeWithConfig.config = merge(routeWithConfig.config || {}, {
|
|
141
|
+
sse: {
|
|
142
|
+
...(options.heartbeatInterval !== undefined && {
|
|
143
|
+
heartbeatInterval: options.heartbeatInterval,
|
|
144
|
+
}),
|
|
145
|
+
...(options.serializer !== undefined && { serializer: options.serializer }),
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
applyPreHandlers(route, globalPreHandler) {
|
|
151
|
+
const existingPreHandler = route.preHandler;
|
|
152
|
+
if (!existingPreHandler) {
|
|
153
|
+
route.preHandler = globalPreHandler;
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
// biome-ignore lint/suspicious/noExplicitAny: preHandler types are complex
|
|
157
|
+
const handlers = Array.isArray(existingPreHandler)
|
|
158
|
+
? existingPreHandler
|
|
159
|
+
: [existingPreHandler];
|
|
160
|
+
// biome-ignore lint/suspicious/noExplicitAny: preHandler types are complex
|
|
161
|
+
const globalHandlers = Array.isArray(globalPreHandler)
|
|
162
|
+
? globalPreHandler
|
|
163
|
+
: [globalPreHandler];
|
|
164
|
+
route.preHandler = [...globalHandlers, ...handlers];
|
|
165
|
+
}
|
|
166
|
+
applyRateLimit(route, rateLimit) {
|
|
167
|
+
// biome-ignore lint/suspicious/noExplicitAny: config types vary by plugins
|
|
168
|
+
const routeWithConfig = route;
|
|
169
|
+
routeWithConfig.config = {
|
|
170
|
+
...(routeWithConfig.config || {}),
|
|
171
|
+
rateLimit,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
75
174
|
async destroy() {
|
|
76
175
|
await this.awilixManager.executeDispose();
|
|
77
176
|
await this.diContainer.dispose();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DIContext.js","sourceRoot":"","sources":["../../lib/DIContext.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DIContext.js","sourceRoot":"","sources":["../../lib/DIContext.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,11 +10,44 @@ export interface EnqueuedJobQueueManager {
|
|
|
10
10
|
start(enabled?: string[] | boolean): Promise<void>;
|
|
11
11
|
}
|
|
12
12
|
export declare function asSingletonClass<T = object>(Type: Constructor<T>, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
|
|
13
|
+
/**
|
|
14
|
+
* Register a class with an additional config parameter passed to the constructor.
|
|
15
|
+
* Uses asFunction wrapper internally to pass the config as a second parameter.
|
|
16
|
+
* Requires PROXY injection mode.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* myService: asClassWithConfig(MyService, { enableFeature: true }),
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function asClassWithConfig<T = object, Config = unknown>(Type: Constructor<T>, config: Config, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
|
|
13
24
|
export declare function asSingletonFunction<T>(fn: FunctionReturning<T>, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
|
|
14
25
|
export declare function asServiceClass<T = object>(Type: Constructor<T>, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
|
|
15
26
|
export declare function asUseCaseClass<T = object>(Type: Constructor<T>, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
|
|
16
27
|
export declare function asRepositoryClass<T = object>(Type: Constructor<T>, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
|
|
17
28
|
export declare function asControllerClass<T = object>(Type: Constructor<T>, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
|
|
29
|
+
export type SSEControllerModuleOptions = {
|
|
30
|
+
diOptions: DependencyInjectionOptions;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Register an SSE controller class with the DI container.
|
|
34
|
+
*
|
|
35
|
+
* SSE controllers handle Server-Sent Events connections and require
|
|
36
|
+
* graceful shutdown to close all active connections.
|
|
37
|
+
*
|
|
38
|
+
* When `diOptions.isTestMode` is true, connection spying is enabled
|
|
39
|
+
* allowing tests to await connections via `controller.connectionSpy`.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* // Without test mode
|
|
44
|
+
* notificationsSSEController: asSSEControllerClass(NotificationsSSEController),
|
|
45
|
+
*
|
|
46
|
+
* // With test mode (enables connection spy)
|
|
47
|
+
* notificationsSSEController: asSSEControllerClass(NotificationsSSEController, { diOptions }),
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function asSSEControllerClass<T = object>(Type: Constructor<T>, sseOptions?: SSEControllerModuleOptions, opts?: BuildResolverOptions<T>): BuildResolver<T> & DisposableResolver<T>;
|
|
18
51
|
export type MessageQueueConsumerModuleOptions = {
|
|
19
52
|
queueName: string;
|
|
20
53
|
diOptions: DependencyInjectionOptions;
|
|
@@ -6,6 +6,23 @@ export function asSingletonClass(Type, opts) {
|
|
|
6
6
|
lifetime: 'SINGLETON',
|
|
7
7
|
});
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Register a class with an additional config parameter passed to the constructor.
|
|
11
|
+
* Uses asFunction wrapper internally to pass the config as a second parameter.
|
|
12
|
+
* Requires PROXY injection mode.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* myService: asClassWithConfig(MyService, { enableFeature: true }),
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function asClassWithConfig(Type, config, opts) {
|
|
20
|
+
// biome-ignore lint/suspicious/noExplicitAny: Dynamic constructor invocation with cradle proxy
|
|
21
|
+
return asFunction((cradle) => new Type(cradle, config), {
|
|
22
|
+
...opts,
|
|
23
|
+
lifetime: opts?.lifetime ?? 'SINGLETON',
|
|
24
|
+
});
|
|
25
|
+
}
|
|
9
26
|
export function asSingletonFunction(fn, opts) {
|
|
10
27
|
return asFunction(fn, {
|
|
11
28
|
...opts,
|
|
@@ -40,6 +57,35 @@ export function asControllerClass(Type, opts) {
|
|
|
40
57
|
lifetime: 'SINGLETON',
|
|
41
58
|
});
|
|
42
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Register an SSE controller class with the DI container.
|
|
62
|
+
*
|
|
63
|
+
* SSE controllers handle Server-Sent Events connections and require
|
|
64
|
+
* graceful shutdown to close all active connections.
|
|
65
|
+
*
|
|
66
|
+
* When `diOptions.isTestMode` is true, connection spying is enabled
|
|
67
|
+
* allowing tests to await connections via `controller.connectionSpy`.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* // Without test mode
|
|
72
|
+
* notificationsSSEController: asSSEControllerClass(NotificationsSSEController),
|
|
73
|
+
*
|
|
74
|
+
* // With test mode (enables connection spy)
|
|
75
|
+
* notificationsSSEController: asSSEControllerClass(NotificationsSSEController, { diOptions }),
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export function asSSEControllerClass(Type, sseOptions, opts) {
|
|
79
|
+
const enableConnectionSpy = sseOptions?.diOptions.isTestMode ?? false;
|
|
80
|
+
const sseConfig = enableConnectionSpy ? { enableConnectionSpy: true } : undefined;
|
|
81
|
+
return asClassWithConfig(Type, sseConfig, {
|
|
82
|
+
public: false,
|
|
83
|
+
asyncDispose: 'closeAllConnections',
|
|
84
|
+
asyncDisposePriority: 5, // Close SSE connections early in shutdown
|
|
85
|
+
...opts,
|
|
86
|
+
lifetime: 'SINGLETON',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
43
89
|
export function asMessageQueueHandlerClass(Type, mqOptions, opts) {
|
|
44
90
|
return asClass(Type, {
|
|
45
91
|
// these follow message-queue-toolkit conventions
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolverFunctions.js","sourceRoot":"","sources":["../../lib/resolverFunctions.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"resolverFunctions.js","sourceRoot":"","sources":["../../lib/resolverFunctions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { SSEConnectionSpy } from './SSEConnectionSpy.ts';
|
|
2
|
+
import type { AnySSERouteDefinition } from './sseContracts.ts';
|
|
3
|
+
import type { BuildSSERoutesReturnType, SSEConnection, SSEControllerConfig, SSEMessage } from './sseTypes.ts';
|
|
4
|
+
export type { SSEConnectionEvent } from './SSEConnectionSpy.ts';
|
|
5
|
+
export { SSEConnectionSpy } from './SSEConnectionSpy.ts';
|
|
6
|
+
export type { BuildSSERoutesReturnType, InferSSERequest, SSEConnection, SSEControllerConfig, SSEHandlerConfig, SSELogger, SSEMessage, SSEPreHandler, SSERouteHandler, SSERouteOptions, } from './sseTypes.ts';
|
|
7
|
+
/**
|
|
8
|
+
* Abstract base class for SSE controllers.
|
|
9
|
+
*
|
|
10
|
+
* Provides connection management, broadcasting, and lifecycle hooks.
|
|
11
|
+
* Extend this class to create SSE controllers that handle real-time
|
|
12
|
+
* streaming connections.
|
|
13
|
+
*
|
|
14
|
+
* @template APIContracts - Map of route names to SSE route definitions
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* class NotificationsSSEController extends AbstractSSEController<typeof contracts> {
|
|
19
|
+
* public static contracts = {
|
|
20
|
+
* notifications: buildSSERoute({ ... }),
|
|
21
|
+
* } as const
|
|
22
|
+
*
|
|
23
|
+
* public buildSSERoutes() {
|
|
24
|
+
* return {
|
|
25
|
+
* notifications: {
|
|
26
|
+
* contract: NotificationsSSEController.contracts.notifications,
|
|
27
|
+
* handler: this.handleNotifications,
|
|
28
|
+
* },
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare abstract class AbstractSSEController<APIContracts extends Record<string, AnySSERouteDefinition>> {
|
|
35
|
+
/** Map of connection ID to connection object */
|
|
36
|
+
protected connections: Map<string, SSEConnection>;
|
|
37
|
+
/** Private storage for connection spy */
|
|
38
|
+
private readonly _connectionSpy?;
|
|
39
|
+
/**
|
|
40
|
+
* SSE controllers must override this constructor and call super with their
|
|
41
|
+
* dependencies object and the SSE config.
|
|
42
|
+
*
|
|
43
|
+
* @param _dependencies - The dependencies object (cradle proxy in awilix)
|
|
44
|
+
* @param sseConfig - Optional SSE controller configuration
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* class MySSEController extends AbstractSSEController<MyContracts> {
|
|
49
|
+
* private myService: MyService
|
|
50
|
+
*
|
|
51
|
+
* constructor(deps: { myService: MyService }, sseConfig?: SSEControllerConfig) {
|
|
52
|
+
* super(deps, sseConfig)
|
|
53
|
+
* this.myService = deps.myService
|
|
54
|
+
* }
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
constructor(_dependencies: object, sseConfig?: SSEControllerConfig);
|
|
59
|
+
/**
|
|
60
|
+
* Get the connection spy for testing.
|
|
61
|
+
* Throws an error if spies are not enabled.
|
|
62
|
+
* Enable spies by passing `{ enableConnectionSpy: true }` to the constructor.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* // In test, create controller with spy enabled
|
|
67
|
+
* // Pass dependencies first, then config with enableConnectionSpy
|
|
68
|
+
* const controller = new MySSEController({}, { enableConnectionSpy: true })
|
|
69
|
+
*
|
|
70
|
+
* // Start connection (async)
|
|
71
|
+
* connectSSE(baseUrl, '/api/stream')
|
|
72
|
+
*
|
|
73
|
+
* // Wait for connection - handles race condition
|
|
74
|
+
* const connection = await controller.connectionSpy.waitForConnection()
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @throws Error if connection spy is not enabled
|
|
78
|
+
*/
|
|
79
|
+
get connectionSpy(): SSEConnectionSpy;
|
|
80
|
+
/**
|
|
81
|
+
* Build and return SSE route configurations.
|
|
82
|
+
* Similar pattern to AbstractController.buildRoutes().
|
|
83
|
+
*/
|
|
84
|
+
abstract buildSSERoutes(): BuildSSERoutesReturnType<APIContracts>;
|
|
85
|
+
/**
|
|
86
|
+
* Controller-level hook called when any connection is established.
|
|
87
|
+
* Override this method to add global connection handling logic.
|
|
88
|
+
* This is called AFTER the connection is registered and route-level onConnect.
|
|
89
|
+
*
|
|
90
|
+
* @param connection - The newly established connection
|
|
91
|
+
*/
|
|
92
|
+
protected onConnectionEstablished?(connection: SSEConnection): void;
|
|
93
|
+
/**
|
|
94
|
+
* Controller-level hook called when any connection is closed.
|
|
95
|
+
* Override this method to add global disconnect handling logic.
|
|
96
|
+
* This is called BEFORE the connection is unregistered and route-level onDisconnect.
|
|
97
|
+
*
|
|
98
|
+
* @param connection - The connection being closed
|
|
99
|
+
*/
|
|
100
|
+
protected onConnectionClosed?(connection: SSEConnection): void;
|
|
101
|
+
/**
|
|
102
|
+
* Send an event to a specific connection.
|
|
103
|
+
*
|
|
104
|
+
* @param connectionId - The connection to send to
|
|
105
|
+
* @param message - The SSE message to send
|
|
106
|
+
* @returns true if sent successfully, false if connection not found or closed
|
|
107
|
+
*/
|
|
108
|
+
protected sendEvent<T>(connectionId: string, message: SSEMessage<T>): Promise<boolean>;
|
|
109
|
+
/**
|
|
110
|
+
* Broadcast an event to all connected clients.
|
|
111
|
+
*
|
|
112
|
+
* @param message - The SSE message to broadcast
|
|
113
|
+
* @returns Number of clients the message was sent to
|
|
114
|
+
*/
|
|
115
|
+
protected broadcast<T>(message: SSEMessage<T>): Promise<number>;
|
|
116
|
+
/**
|
|
117
|
+
* Broadcast an event to connections matching a predicate.
|
|
118
|
+
*
|
|
119
|
+
* @param message - The SSE message to broadcast
|
|
120
|
+
* @param predicate - Function to filter connections
|
|
121
|
+
* @returns Number of clients the message was sent to
|
|
122
|
+
*/
|
|
123
|
+
protected broadcastIf<T>(message: SSEMessage<T>, predicate: (connection: SSEConnection) => boolean): Promise<number>;
|
|
124
|
+
/**
|
|
125
|
+
* Get all active connections.
|
|
126
|
+
*/
|
|
127
|
+
protected getConnections(): SSEConnection[];
|
|
128
|
+
/**
|
|
129
|
+
* Get the number of active connections.
|
|
130
|
+
*/
|
|
131
|
+
protected getConnectionCount(): number;
|
|
132
|
+
/**
|
|
133
|
+
* Close a specific connection.
|
|
134
|
+
*
|
|
135
|
+
* This gracefully ends the SSE stream by calling the underlying `reply.sse.close()`.
|
|
136
|
+
* All previously sent data is flushed to the client before the connection terminates.
|
|
137
|
+
* Use this to signal end-of-stream after sending all events (e.g., in request-response
|
|
138
|
+
* style streaming like OpenAI completions).
|
|
139
|
+
*
|
|
140
|
+
* @param connectionId - The connection to close
|
|
141
|
+
* @returns true if connection was found and closed
|
|
142
|
+
*/
|
|
143
|
+
protected closeConnection(connectionId: string): boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Close all active connections.
|
|
146
|
+
* Called during graceful shutdown via asyncDispose.
|
|
147
|
+
*/
|
|
148
|
+
closeAllConnections(): void;
|
|
149
|
+
/**
|
|
150
|
+
* Register a connection (called internally by route builder).
|
|
151
|
+
* Triggers the onConnectionEstablished hook and spy if defined.
|
|
152
|
+
* @internal
|
|
153
|
+
*/
|
|
154
|
+
registerConnection(connection: SSEConnection): void;
|
|
155
|
+
/**
|
|
156
|
+
* Unregister a connection (called internally by route builder).
|
|
157
|
+
* Triggers the onConnectionClosed hook and spy if defined.
|
|
158
|
+
* This method is idempotent - calling it multiple times for the same
|
|
159
|
+
* connection ID has no effect after the first call.
|
|
160
|
+
* @internal
|
|
161
|
+
*/
|
|
162
|
+
unregisterConnection(connectionId: string): void;
|
|
163
|
+
}
|