@funduck/connectrpc-fastify 1.0.15 → 1.0.17
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 +9 -8
- package/dist/connectrpc.d.ts +17 -7
- package/dist/connectrpc.js +30 -11
- package/dist/connectrpc.js.map +1 -1
- package/dist/context-values.d.ts +3 -0
- package/dist/context-values.js +4 -1
- package/dist/context-values.js.map +1 -1
- package/dist/fastify-plugin.js +7 -11
- package/dist/fastify-plugin.js.map +1 -1
- package/dist/helpers.d.ts +7 -7
- package/dist/helpers.js +77 -45
- package/dist/helpers.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/interceptors.d.ts +4 -0
- package/dist/interceptors.js +44 -2
- package/dist/interceptors.js.map +1 -1
- package/dist/interfaces.d.ts +53 -17
- package/dist/interfaces.js +12 -0
- package/dist/interfaces.js.map +1 -1
- package/dist/middlewares.d.ts +1 -0
- package/dist/middlewares.js +33 -42
- package/dist/middlewares.js.map +1 -1
- package/dist/stores.d.ts +16 -1
- package/dist/stores.js +31 -2
- package/dist/stores.js.map +1 -1
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -55,7 +55,7 @@ export class ElizaController implements Service<typeof ElizaService> {
|
|
|
55
55
|
}
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
Create Fastify server, initialize controller and
|
|
58
|
+
Create Fastify server, initialize controller and initialize ConnectRPC.
|
|
59
59
|
```TS
|
|
60
60
|
const fastify = Fastify({
|
|
61
61
|
logger: true,
|
|
@@ -63,7 +63,7 @@ const fastify = Fastify({
|
|
|
63
63
|
|
|
64
64
|
new ElizaController();
|
|
65
65
|
|
|
66
|
-
await ConnectRPC.
|
|
66
|
+
await ConnectRPC.init(fastify);
|
|
67
67
|
|
|
68
68
|
try {
|
|
69
69
|
await fastify.listen({ port: 3000 });
|
|
@@ -106,13 +106,13 @@ const fastify = Fastify({ logger: true });
|
|
|
106
106
|
new ElizaController();
|
|
107
107
|
new AuthMiddleware();
|
|
108
108
|
|
|
109
|
-
await ConnectRPC.
|
|
110
|
-
|
|
111
|
-
ConnectRPC.initMiddlewares(fastify, [
|
|
109
|
+
await ConnectRPC.init(fastify, {
|
|
110
|
+
middlewares: [
|
|
112
111
|
middlewareConfig(AuthMiddleware), // Global - for all services and methods
|
|
113
112
|
// middlewareConfig(AuthMiddleware, ElizaService), // for all ElizaService methods
|
|
114
113
|
// middlewareConfig(AuthMiddleware, ElizaService, ['say']), // for specific method only
|
|
115
|
-
]
|
|
114
|
+
]
|
|
115
|
+
});
|
|
116
116
|
|
|
117
117
|
await fastify.listen({ port: 3000 });
|
|
118
118
|
```
|
|
@@ -157,20 +157,21 @@ For type safety use `interceptorConfig` helper.
|
|
|
157
157
|
```TS
|
|
158
158
|
import { interceptorConfig } from '@funduck/connectrpc-fastify';
|
|
159
159
|
|
|
160
|
-
const fastify = Fastify({ logger:
|
|
160
|
+
const fastify = Fastify({ logger: false });
|
|
161
161
|
|
|
162
162
|
new AuthMiddleware();
|
|
163
163
|
new LoggingInterceptor();
|
|
164
164
|
new ElizaController();
|
|
165
165
|
|
|
166
166
|
await ConnectRPC.init(fastify, {
|
|
167
|
+
logger: false,
|
|
167
168
|
interceptors: [
|
|
168
169
|
interceptorConfig(LoggingInterceptor), // Global - for all services and methods
|
|
169
170
|
// interceptorConfig(LoggingInterceptor, ElizaService), // for all ElizaService methods
|
|
170
171
|
// interceptorConfig(LoggingInterceptor, ElizaService, ['say']), // for specific method only
|
|
171
172
|
],
|
|
172
173
|
middlewares: [
|
|
173
|
-
middlewareConfig(AuthMiddleware), // Global
|
|
174
|
+
middlewareConfig(AuthMiddleware), // Global - for all services and methods
|
|
174
175
|
],
|
|
175
176
|
});
|
|
176
177
|
|
package/dist/connectrpc.d.ts
CHANGED
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
import { GenService, GenServiceMethods } from '@bufbuild/protobuf/codegenv2';
|
|
2
2
|
import { FastifyInstance } from 'fastify';
|
|
3
|
-
import { Logger, Middleware, MiddlewareConfigUnion, Service } from './interfaces';
|
|
3
|
+
import { Interceptor, InterceptorConfigUnion, Logger, Middleware, MiddlewareConfigUnion, Service } from './interfaces';
|
|
4
4
|
declare class ConnectRPCClass {
|
|
5
|
-
setLogger(customLogger: Logger): void;
|
|
5
|
+
setLogger(customLogger: Logger | boolean): void;
|
|
6
|
+
/** Should be called in middleware constructor */
|
|
6
7
|
registerMiddleware(self: Middleware, options?: {
|
|
7
8
|
allowMultipleInstances?: boolean;
|
|
8
9
|
}): void;
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
/** Should be called in interceptor constructor */
|
|
11
|
+
registerInterceptor(self: Interceptor, options?: {
|
|
12
|
+
allowMultipleInstances?: boolean;
|
|
13
|
+
}): void;
|
|
14
|
+
/** Should be called in controller constructor */
|
|
13
15
|
registerController<T extends GenServiceMethods>(self: Service<GenService<T>>, service: GenService<T>, options?: {
|
|
14
16
|
allowMultipleInstances?: boolean;
|
|
15
17
|
}): void;
|
|
18
|
+
/** Initialize ConnectRPC with interceptors, Fastify plugin, and middlewares */
|
|
19
|
+
init(server: FastifyInstance, options?: {
|
|
20
|
+
logger?: Logger | false;
|
|
21
|
+
interceptors?: InterceptorConfigUnion[];
|
|
22
|
+
middlewares?: MiddlewareConfigUnion[];
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
/** Clear all registered controllers, routes, middlewares, and interceptors. Useful for testing */
|
|
25
|
+
clear(): void;
|
|
26
|
+
initInterceptors(configs: InterceptorConfigUnion[]): void;
|
|
16
27
|
registerFastifyPlugin(server: FastifyInstance): Promise<void>;
|
|
17
|
-
private _middlewaresInitialized;
|
|
18
28
|
initMiddlewares(server: FastifyInstance, middlewareConfigs: MiddlewareConfigUnion[]): Promise<void>;
|
|
19
29
|
}
|
|
20
30
|
/**
|
package/dist/connectrpc.js
CHANGED
|
@@ -3,33 +3,52 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ConnectRPC = void 0;
|
|
4
4
|
const fastify_plugin_1 = require("./fastify-plugin");
|
|
5
5
|
const helpers_1 = require("./helpers");
|
|
6
|
+
const interceptors_1 = require("./interceptors");
|
|
6
7
|
const middlewares_1 = require("./middlewares");
|
|
7
8
|
const stores_1 = require("./stores");
|
|
8
9
|
class ConnectRPCClass {
|
|
9
|
-
constructor() {
|
|
10
|
-
this._middlewaresInitialized = false;
|
|
11
|
-
}
|
|
12
10
|
setLogger(customLogger) {
|
|
13
11
|
(0, helpers_1.setLogger)(customLogger);
|
|
14
12
|
}
|
|
13
|
+
/** Should be called in middleware constructor */
|
|
15
14
|
registerMiddleware(self, options) {
|
|
16
15
|
stores_1.MiddlewareStore.registerInstance(self, options);
|
|
17
16
|
}
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
/** Should be called in interceptor constructor */
|
|
18
|
+
registerInterceptor(self, options) {
|
|
19
|
+
stores_1.InterceptorStore.registerInstance(self, options);
|
|
20
|
+
}
|
|
21
|
+
/** Should be called in controller constructor */
|
|
22
22
|
registerController(self, service, options) {
|
|
23
23
|
stores_1.ControllersStore.registerInstance(self, service, options);
|
|
24
24
|
}
|
|
25
|
+
/** Initialize ConnectRPC with interceptors, Fastify plugin, and middlewares */
|
|
26
|
+
async init(server, options) {
|
|
27
|
+
if (options?.logger != null) {
|
|
28
|
+
this.setLogger(options.logger);
|
|
29
|
+
}
|
|
30
|
+
if (options?.interceptors) {
|
|
31
|
+
this.initInterceptors(options.interceptors);
|
|
32
|
+
}
|
|
33
|
+
await this.registerFastifyPlugin(server);
|
|
34
|
+
if (options?.middlewares) {
|
|
35
|
+
this.initMiddlewares(server, options.middlewares);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Clear all registered controllers, routes, middlewares, and interceptors. Useful for testing */
|
|
39
|
+
clear() {
|
|
40
|
+
stores_1.ControllersStore.clear();
|
|
41
|
+
stores_1.RouteMetadataStore.clear();
|
|
42
|
+
stores_1.MiddlewareStore.clear();
|
|
43
|
+
stores_1.InterceptorStore.clear();
|
|
44
|
+
}
|
|
45
|
+
initInterceptors(configs) {
|
|
46
|
+
(0, interceptors_1.initInterceptors)(configs);
|
|
47
|
+
}
|
|
25
48
|
registerFastifyPlugin(server) {
|
|
26
49
|
return (0, fastify_plugin_1.registerFastifyPlugin)(server);
|
|
27
50
|
}
|
|
28
51
|
initMiddlewares(server, middlewareConfigs) {
|
|
29
|
-
if (this._middlewaresInitialized) {
|
|
30
|
-
throw new Error('Middlewares have already been initialized!');
|
|
31
|
-
}
|
|
32
|
-
this._middlewaresInitialized = true;
|
|
33
52
|
return (0, middlewares_1.initMiddlewares)(server, middlewareConfigs);
|
|
34
53
|
}
|
|
35
54
|
}
|
package/dist/connectrpc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connectrpc.js","sourceRoot":"","sources":["../src/connectrpc.ts"],"names":[],"mappings":";;;AAEA,qDAAyD;AACzD,uCAAsC;
|
|
1
|
+
{"version":3,"file":"connectrpc.js","sourceRoot":"","sources":["../src/connectrpc.ts"],"names":[],"mappings":";;;AAEA,qDAAyD;AACzD,uCAAsC;AACtC,iDAAkD;AASlD,+CAAgD;AAChD,qCAKkB;AAElB,MAAM,eAAe;IACnB,SAAS,CAAC,YAA8B;QACtC,IAAA,mBAAS,EAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IAED,iDAAiD;IACjD,kBAAkB,CAChB,IAAgB,EAChB,OAEC;QAED,wBAAe,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAED,kDAAkD;IAClD,mBAAmB,CACjB,IAAiB,EACjB,OAEC;QAED,yBAAgB,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAED,iDAAiD;IACjD,kBAAkB,CAChB,IAA4B,EAC5B,OAAsB,EACtB,OAEC;QAED,yBAAgB,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;IAED,+EAA+E;IAC/E,KAAK,CAAC,IAAI,CACR,MAAuB,EACvB,OAIC;QAED,IAAI,OAAO,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QACD,IAAI,OAAO,EAAE,YAAY,EAAE,CAAC;YAC1B,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,OAAO,EAAE,WAAW,EAAE,CAAC;YACzB,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,kGAAkG;IAClG,KAAK;QACH,yBAAgB,CAAC,KAAK,EAAE,CAAC;QACzB,2BAAkB,CAAC,KAAK,EAAE,CAAC;QAC3B,wBAAe,CAAC,KAAK,EAAE,CAAC;QACxB,yBAAgB,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC;IAED,gBAAgB,CAAC,OAAiC;QAChD,IAAA,+BAAgB,EAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAED,qBAAqB,CAAC,MAAuB;QAC3C,OAAO,IAAA,sCAAqB,EAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,eAAe,CACb,MAAuB,EACvB,iBAA0C;QAE1C,OAAO,IAAA,6BAAe,EAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACpD,CAAC;CACF;AAED;;GAEG;AACU,QAAA,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC"}
|
package/dist/context-values.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ContextKey, ContextValues } from '@connectrpc/connect';
|
|
2
|
+
import { Type } from './interfaces';
|
|
2
3
|
/**
|
|
3
4
|
* Custom ContextValues implementation that extends the standard ConnectRPC ContextValues
|
|
4
5
|
* with an entries() method to iterate over key-value pairs.
|
|
@@ -27,3 +28,5 @@ export declare class CustomContextValues implements ContextValues {
|
|
|
27
28
|
* Create a new CustomContextValues instance
|
|
28
29
|
*/
|
|
29
30
|
export declare function createCustomContextValues(): CustomContextValues;
|
|
31
|
+
export declare const controllerClassContextKey: ContextKey<Type<any> | null>;
|
|
32
|
+
export declare const controllerMethodContextKey: ContextKey<Function | null>;
|
package/dist/context-values.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CustomContextValues = void 0;
|
|
3
|
+
exports.controllerMethodContextKey = exports.controllerClassContextKey = exports.CustomContextValues = void 0;
|
|
4
4
|
exports.createCustomContextValues = createCustomContextValues;
|
|
5
|
+
const connect_1 = require("@connectrpc/connect");
|
|
5
6
|
/**
|
|
6
7
|
* Custom ContextValues implementation that extends the standard ConnectRPC ContextValues
|
|
7
8
|
* with an entries() method to iterate over key-value pairs.
|
|
@@ -50,4 +51,6 @@ exports.CustomContextValues = CustomContextValues;
|
|
|
50
51
|
function createCustomContextValues() {
|
|
51
52
|
return new CustomContextValues();
|
|
52
53
|
}
|
|
54
|
+
exports.controllerClassContextKey = (0, connect_1.createContextKey)(null);
|
|
55
|
+
exports.controllerMethodContextKey = (0, connect_1.createContextKey)(null);
|
|
53
56
|
//# sourceMappingURL=context-values.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-values.js","sourceRoot":"","sources":["../src/context-values.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"context-values.js","sourceRoot":"","sources":["../src/context-values.ts"],"names":[],"mappings":";;;AAsDA,8DAEC;AAxDD,iDAI6B;AAG7B;;;GAGG;AACH,MAAa,mBAAmB;IAAhC;QACU,WAAM,GAAG,IAAI,GAAG,EAAmB,CAAC;IAqC9C,CAAC;IAnCC;;OAEG;IACH,GAAG,CAAI,GAAkB;QACvB,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAM,CAAC;QACtC,CAAC;QACD,OAAO,GAAG,CAAC,YAAY,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,GAAG,CAAI,GAAkB,EAAE,KAAQ;QACjC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,GAAwB;QAC7B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3B,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,CAAC,OAAO;QACN,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;YAChD,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;CACF;AAtCD,kDAsCC;AAED;;GAEG;AACH,SAAgB,yBAAyB;IACvC,OAAO,IAAI,mBAAmB,EAAE,CAAC;AACnC,CAAC;AAEY,QAAA,yBAAyB,GAAG,IAAA,0BAAgB,EACvD,IAAI,CACL,CAAC;AACW,QAAA,0BAA0B,GAAG,IAAA,0BAAgB,EACxD,IAAI,CACL,CAAC"}
|
package/dist/fastify-plugin.js
CHANGED
|
@@ -9,25 +9,21 @@ async function registerFastifyPlugin(server, options = {}) {
|
|
|
9
9
|
// Create implementations from controller instances
|
|
10
10
|
const implementations = new Map();
|
|
11
11
|
for (const { instance, service } of stores_1.ControllersStore.values()) {
|
|
12
|
-
const methodMappings = (0, helpers_1.discoverMethodMappings)(instance.__proto__, service);
|
|
13
12
|
// Create the implementation object
|
|
14
13
|
const implementation = {};
|
|
15
14
|
// Bind each method from the service
|
|
16
15
|
for (const methodDesc of service.methods) {
|
|
17
|
-
const { name } = methodDesc;
|
|
18
|
-
const
|
|
19
|
-
// Check if there's a mapped controller method
|
|
20
|
-
const controllerMethodName = methodMappings[name];
|
|
16
|
+
const { name: methodName } = methodDesc; // This is in PascalCase, e.g., "Say" as in service .proto file
|
|
17
|
+
const controllerMethodName = methodName[0].toLowerCase() + methodName.slice(1); // This is in camelCase, e.g., "say" as in controller
|
|
21
18
|
if (controllerMethodName) {
|
|
22
19
|
const controllerMethod = instance[controllerMethodName];
|
|
23
20
|
if (controllerMethod) {
|
|
24
21
|
// Bind the method with proper 'this' context
|
|
25
22
|
const bindedMethod = controllerMethod.bind(instance);
|
|
26
|
-
implementation[
|
|
27
|
-
// Store route metadata for
|
|
28
|
-
stores_1.RouteMetadataStore.registerRoute(service.typeName,
|
|
29
|
-
instance.constructor
|
|
30
|
-
helpers_1.logger.log(`Binding ${instance.constructor.name}.${controllerMethodName} to ${service.typeName}.${name}`);
|
|
23
|
+
implementation[controllerMethodName] = bindedMethod;
|
|
24
|
+
// Store route metadata for interceptors
|
|
25
|
+
stores_1.RouteMetadataStore.registerRoute(service.typeName, methodName, instance.constructor, controllerMethod, controllerMethodName, instance);
|
|
26
|
+
helpers_1.logger.log(`Binding ${instance.constructor.name}.${controllerMethodName} to ${service.typeName}.${methodName}`);
|
|
31
27
|
}
|
|
32
28
|
else {
|
|
33
29
|
helpers_1.logger.warn(`Method ${controllerMethodName} not found in ${instance.constructor.name}`);
|
|
@@ -55,7 +51,7 @@ async function registerFastifyPlugin(server, options = {}) {
|
|
|
55
51
|
grpcWeb: false,
|
|
56
52
|
connect: true,
|
|
57
53
|
acceptCompression: options.acceptCompression ?? [],
|
|
58
|
-
interceptors: [interceptors_1.contextInterceptor],
|
|
54
|
+
interceptors: [interceptors_1.contextInterceptor, ...interceptors_1.initializedInterceptors],
|
|
59
55
|
routes: routes,
|
|
60
56
|
});
|
|
61
57
|
helpers_1.logger.log('Ready');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fastify-plugin.js","sourceRoot":"","sources":["../src/fastify-plugin.ts"],"names":[],"mappings":";;AASA,
|
|
1
|
+
{"version":3,"file":"fastify-plugin.js","sourceRoot":"","sources":["../src/fastify-plugin.ts"],"names":[],"mappings":";;AASA,sDA6EC;AApFD,iEAAmE;AAGnE,uCAAmC;AACnC,iDAA6E;AAC7E,qCAAgE;AAEzD,KAAK,UAAU,qBAAqB,CACzC,MAAuB,EACvB,UAEI,EAAE;IAEN,mDAAmD;IACnD,MAAM,eAAe,GAAG,IAAI,GAAG,EAAwB,CAAC;IAExD,KAAK,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,yBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9D,mCAAmC;QACnC,MAAM,cAAc,GAAQ,EAAE,CAAC;QAE/B,oCAAoC;QACpC,KAAK,MAAM,UAAU,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACzC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,UAAU,CAAC,CAAC,+DAA+D;YACxG,MAAM,oBAAoB,GACxB,UAAU,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,qDAAqD;YAE1G,IAAI,oBAAoB,EAAE,CAAC;gBACzB,MAAM,gBAAgB,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAAC;gBAExD,IAAI,gBAAgB,EAAE,CAAC;oBACrB,6CAA6C;oBAC7C,MAAM,YAAY,GAAG,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACrD,cAAc,CAAC,oBAAoB,CAAC,GAAG,YAAY,CAAC;oBAEpD,wCAAwC;oBACxC,2BAAkB,CAAC,aAAa,CAC9B,OAAO,CAAC,QAAQ,EAChB,UAAU,EACV,QAAQ,CAAC,WAAW,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,QAAQ,CACT,CAAC;oBAEF,gBAAM,CAAC,GAAG,CACR,WAAW,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,oBAAoB,OAAO,OAAO,CAAC,QAAQ,IAAI,UAAU,EAAE,CACpG,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,gBAAM,CAAC,IAAI,CACT,UAAU,oBAAoB,iBAAiB,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,CAC3E,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,eAAe,CAAC,GAAG,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,MAAqB,EAAE,EAAE;QACvC,KAAK,MAAM,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC;YAClE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;YACxC,gBAAM,CAAC,GAAG,CAAC,gBAAgB,OAAO,CAAC,QAAQ,SAAS,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,gBAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAChD,OAAO;IACT,CAAC;IAED,MAAM,MAAM,CAAC,QAAQ,CAAC,sCAAoB,EAAE;QAC1C,yEAAyE;QACzE,oCAAoC;QACpC,0CAA0C;QAC1C,yCAAyC;QACzC,IAAI,EAAE,KAAK;QACX,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,IAAI;QACb,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,IAAI,EAAE;QAClD,YAAY,EAAE,CAAC,iCAAkB,EAAE,GAAG,sCAAuB,CAAC;QAC9D,MAAM,EAAE,MAAM;KACf,CAAC,CAAC;IAEH,gBAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACtB,CAAC"}
|
package/dist/helpers.d.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { GenService } from '@bufbuild/protobuf/codegenv2';
|
|
2
1
|
import { FastifyReply, FastifyRequest } from 'fastify';
|
|
3
|
-
import { Logger } from './interfaces';
|
|
4
|
-
|
|
5
|
-
* Automatically discover method mappings by matching service methods to controller methods
|
|
6
|
-
*/
|
|
7
|
-
export declare function discoverMethodMappings(prototype: any, service: GenService<any>): Record<string, string>;
|
|
2
|
+
import { Logger, Middleware, RouteConfigGlobal, RouteConfigService } from './interfaces';
|
|
3
|
+
export declare function callMiddlewareAsync(middleware: Middleware, req: FastifyRequest, res: FastifyReply): Promise<void>;
|
|
8
4
|
/**
|
|
9
5
|
* Helper to convert NestJS middleware to Fastify hook
|
|
10
6
|
*/
|
|
11
7
|
export declare function convertMiddlewareToHook(middlewareInstance: any): (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
12
8
|
export declare let logger: Logger;
|
|
13
|
-
export declare function setLogger(customLogger: Logger): void;
|
|
9
|
+
export declare function setLogger(customLogger: Logger | boolean): void;
|
|
14
10
|
/**
|
|
15
11
|
* Generate a unique request ID
|
|
16
12
|
*/
|
|
17
13
|
export declare function generateRequestId(): string;
|
|
14
|
+
/** Returns checker function for url */
|
|
15
|
+
export declare function buildRouteConfigChecker<T extends RouteConfigGlobal | RouteConfigService<any>>(configs: T[]): (url: string, checkConfig?: T) => T[];
|
|
16
|
+
/** Returns the pathname part of a URL which should be used to parse service name and method name */
|
|
17
|
+
export declare function getURLPath(url: string): string;
|
package/dist/helpers.js
CHANGED
|
@@ -1,77 +1,68 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.logger = void 0;
|
|
4
|
-
exports.
|
|
4
|
+
exports.callMiddlewareAsync = callMiddlewareAsync;
|
|
5
5
|
exports.convertMiddlewareToHook = convertMiddlewareToHook;
|
|
6
6
|
exports.setLogger = setLogger;
|
|
7
7
|
exports.generateRequestId = generateRequestId;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
// Try to find a matching controller method
|
|
22
|
-
// First try exact match with localName (camelCase), then try case-insensitive
|
|
23
|
-
let controllerMethodName = controllerMethods.find((name) => name === localName);
|
|
24
|
-
if (!controllerMethodName) {
|
|
25
|
-
controllerMethodName = controllerMethods.find((name) => name.toLowerCase() === serviceMethodName.toLowerCase());
|
|
8
|
+
exports.buildRouteConfigChecker = buildRouteConfigChecker;
|
|
9
|
+
exports.getURLPath = getURLPath;
|
|
10
|
+
function callMiddlewareAsync(middleware, req, res) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
try {
|
|
13
|
+
middleware.use(req.raw, res.raw, (err) => {
|
|
14
|
+
if (err) {
|
|
15
|
+
reject(err);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
resolve();
|
|
19
|
+
}
|
|
20
|
+
});
|
|
26
21
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
methodMappings[serviceMethodName] = controllerMethodName;
|
|
22
|
+
catch (error) {
|
|
23
|
+
reject(error);
|
|
30
24
|
}
|
|
31
|
-
}
|
|
32
|
-
return methodMappings;
|
|
25
|
+
});
|
|
33
26
|
}
|
|
34
27
|
/**
|
|
35
28
|
* Helper to convert NestJS middleware to Fastify hook
|
|
36
29
|
*/
|
|
37
30
|
function convertMiddlewareToHook(middlewareInstance) {
|
|
38
31
|
return async (request, reply) => {
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
// NestJS middleware expects raw req/res
|
|
42
|
-
middlewareInstance.use(request.raw, reply.raw, (err) => {
|
|
43
|
-
if (err) {
|
|
44
|
-
reject(err);
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
resolve();
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
reject(error);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
32
|
+
await callMiddlewareAsync(middlewareInstance, request, reply);
|
|
55
33
|
};
|
|
56
34
|
}
|
|
57
35
|
exports.logger = {
|
|
58
36
|
log: (...args) => {
|
|
59
|
-
|
|
37
|
+
console.info(...args);
|
|
60
38
|
},
|
|
61
39
|
error: (...args) => {
|
|
62
|
-
|
|
40
|
+
console.error(...args);
|
|
63
41
|
},
|
|
64
42
|
warn: (...args) => {
|
|
65
|
-
|
|
43
|
+
console.warn(...args);
|
|
66
44
|
},
|
|
67
45
|
debug: (...args) => {
|
|
68
|
-
|
|
46
|
+
console.debug(...args);
|
|
69
47
|
},
|
|
70
48
|
verbose: (...args) => {
|
|
71
|
-
|
|
49
|
+
console.log(...args);
|
|
72
50
|
},
|
|
73
51
|
};
|
|
74
52
|
function setLogger(customLogger) {
|
|
53
|
+
if (typeof customLogger == 'boolean') {
|
|
54
|
+
if (customLogger === false) {
|
|
55
|
+
// Disable logging
|
|
56
|
+
exports.logger = {
|
|
57
|
+
log: () => { },
|
|
58
|
+
error: () => { },
|
|
59
|
+
warn: () => { },
|
|
60
|
+
debug: () => { },
|
|
61
|
+
verbose: () => { },
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
75
66
|
exports.logger = customLogger;
|
|
76
67
|
}
|
|
77
68
|
/**
|
|
@@ -80,4 +71,45 @@ function setLogger(customLogger) {
|
|
|
80
71
|
function generateRequestId() {
|
|
81
72
|
return `req_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
|
|
82
73
|
}
|
|
74
|
+
/** Returns checker function for url */
|
|
75
|
+
function buildRouteConfigChecker(configs) {
|
|
76
|
+
const configMethods = configs.map((config) => ({
|
|
77
|
+
config: config,
|
|
78
|
+
methods: new Set(
|
|
79
|
+
// Convert method names to set with PascalCase
|
|
80
|
+
(config.methods || []).map((m) => m[0].toUpperCase() + m.slice(1))),
|
|
81
|
+
}));
|
|
82
|
+
/** Returns matched route configs for a given URL */
|
|
83
|
+
return (url, checkConfig) => {
|
|
84
|
+
// Parse the URL to get service and method
|
|
85
|
+
// Format: /package.ServiceName/MethodName
|
|
86
|
+
const match = url.match(/^\/([^/]+)\/([^/]+)$/);
|
|
87
|
+
if (!match) {
|
|
88
|
+
// Not a ConnectRPC route, skip
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
const [, serviceName, methodName] = match;
|
|
92
|
+
const matchedConfigs = [];
|
|
93
|
+
for (const { config, methods } of configMethods) {
|
|
94
|
+
// If checkConfig is provided, only match that specific config
|
|
95
|
+
if (checkConfig && config !== checkConfig) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
// Check if config should apply to this service
|
|
99
|
+
if (config.on && config.on.typeName !== serviceName) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
// Check if config should apply to this method
|
|
103
|
+
if (methods.size && !methods.has(methodName)) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
matchedConfigs.push(config);
|
|
107
|
+
}
|
|
108
|
+
return matchedConfigs;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/** Returns the pathname part of a URL which should be used to parse service name and method name */
|
|
112
|
+
function getURLPath(url) {
|
|
113
|
+
return URL.parse(url)?.pathname || url;
|
|
114
|
+
}
|
|
83
115
|
//# sourceMappingURL=helpers.js.map
|
package/dist/helpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":";;;AAQA,kDAkBC;AAKD,0DAMC;AAoBD,8BAeC;AAKD,8CAEC;AAGD,0DA+CC;AAGD,gCAEC;AA9HD,SAAgB,mBAAmB,CACjC,UAAsB,EACtB,GAAmB,EACnB,GAAiB;IAEjB,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,IAAI,CAAC;YACH,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,GAAS,EAAE,EAAE;gBAC7C,IAAI,GAAG,EAAE,CAAC;oBACR,MAAM,CAAC,GAAG,CAAC,CAAC;gBACd,CAAC;qBAAM,CAAC;oBACN,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAgB,uBAAuB,CACrC,kBAAuB;IAEvB,OAAO,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAE,EAAE;QAC5D,MAAM,mBAAmB,CAAC,kBAAkB,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IAChE,CAAC,CAAC;AACJ,CAAC;AAEU,QAAA,MAAM,GAAW;IAC1B,GAAG,EAAE,CAAC,GAAG,IAAW,EAAE,EAAE;QACtB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,KAAK,EAAE,CAAC,GAAG,IAAW,EAAE,EAAE;QACxB,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,EAAE,CAAC,GAAG,IAAW,EAAE,EAAE;QACvB,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,KAAK,EAAE,CAAC,GAAG,IAAW,EAAE,EAAE;QACxB,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,EAAE,CAAC,GAAG,IAAW,EAAE,EAAE;QAC1B,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACvB,CAAC;CACF,CAAC;AAEF,SAAgB,SAAS,CAAC,YAA8B;IACtD,IAAI,OAAO,YAAY,IAAI,SAAS,EAAE,CAAC;QACrC,IAAI,YAAY,KAAK,KAAK,EAAE,CAAC;YAC3B,kBAAkB;YAClB,cAAM,GAAG;gBACP,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;gBACb,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;gBACf,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;gBACd,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;gBACf,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;aAClB,CAAC;QACJ,CAAC;QACD,OAAO;IACT,CAAC;IACD,cAAM,GAAG,YAAY,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB;IAC/B,OAAO,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AAC5E,CAAC;AAED,uCAAuC;AACvC,SAAgB,uBAAuB,CAErC,OAAY;IACZ,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,IAAI,GAAG;QACd,8CAA8C;QAC9C,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CACnE;KACF,CAAC,CAAC,CAAC;IAEJ,oDAAoD;IACpD,OAAO,CAAC,GAAW,EAAE,WAAe,EAAE,EAAE;QACtC,0CAA0C;QAC1C,0CAA0C;QAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAEhD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,+BAA+B;YAC/B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC;QAE1C,MAAM,cAAc,GAAQ,EAAE,CAAC;QAE/B,KAAK,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,EAAE,CAAC;YAChD,8DAA8D;YAC9D,IAAI,WAAW,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;gBAC1C,SAAS;YACX,CAAC;YAED,+CAA+C;YAC/C,IAAI,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,EAAE,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;gBACpD,SAAS;YACX,CAAC;YAED,8CAA8C;YAC9C,IAAI,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC7C,SAAS;YACX,CAAC;YAED,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QAED,OAAO,cAAc,CAAC;IACxB,CAAC,CAAC;AACJ,CAAC;AAED,oGAAoG;AACpG,SAAgB,UAAU,CAAC,GAAW;IACpC,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,QAAQ,IAAI,GAAG,CAAC;AACzC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare function printMsg(): void;
|
|
2
2
|
export { ConnectRPC } from './connectrpc';
|
|
3
|
-
export { CustomContextValues, createCustomContextValues, } from './context-values';
|
|
4
|
-
export { middlewareConfig } from './interfaces';
|
|
5
|
-
export type { Logger, Middleware, MiddlewareConfig, MiddlewareConfigUnion, Service, } from './interfaces';
|
|
3
|
+
export { CustomContextValues, controllerClassContextKey, controllerMethodContextKey, createCustomContextValues, } from './context-values';
|
|
4
|
+
export { interceptorConfig, middlewareConfig } from './interfaces';
|
|
5
|
+
export type { AnyFn, Interceptor, Logger, Middleware, MiddlewareConfig, MiddlewareConfigUnion, Service, } from './interfaces';
|
|
6
6
|
export type { OmitConnectrpcFields } from './types';
|
|
7
7
|
export { getCustomContextValues } from './middlewares';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getCustomContextValues = exports.middlewareConfig = exports.createCustomContextValues = exports.CustomContextValues = exports.ConnectRPC = void 0;
|
|
3
|
+
exports.getCustomContextValues = exports.middlewareConfig = exports.interceptorConfig = exports.createCustomContextValues = exports.controllerMethodContextKey = exports.controllerClassContextKey = exports.CustomContextValues = exports.ConnectRPC = void 0;
|
|
4
4
|
exports.printMsg = printMsg;
|
|
5
5
|
function printMsg() {
|
|
6
6
|
console.error('connectrpc-fastify is in development mode! not ready for production yet!');
|
|
@@ -9,8 +9,11 @@ var connectrpc_1 = require("./connectrpc");
|
|
|
9
9
|
Object.defineProperty(exports, "ConnectRPC", { enumerable: true, get: function () { return connectrpc_1.ConnectRPC; } });
|
|
10
10
|
var context_values_1 = require("./context-values");
|
|
11
11
|
Object.defineProperty(exports, "CustomContextValues", { enumerable: true, get: function () { return context_values_1.CustomContextValues; } });
|
|
12
|
+
Object.defineProperty(exports, "controllerClassContextKey", { enumerable: true, get: function () { return context_values_1.controllerClassContextKey; } });
|
|
13
|
+
Object.defineProperty(exports, "controllerMethodContextKey", { enumerable: true, get: function () { return context_values_1.controllerMethodContextKey; } });
|
|
12
14
|
Object.defineProperty(exports, "createCustomContextValues", { enumerable: true, get: function () { return context_values_1.createCustomContextValues; } });
|
|
13
15
|
var interfaces_1 = require("./interfaces");
|
|
16
|
+
Object.defineProperty(exports, "interceptorConfig", { enumerable: true, get: function () { return interfaces_1.interceptorConfig; } });
|
|
14
17
|
Object.defineProperty(exports, "middlewareConfig", { enumerable: true, get: function () { return interfaces_1.middlewareConfig; } });
|
|
15
18
|
var middlewares_1 = require("./middlewares");
|
|
16
19
|
Object.defineProperty(exports, "getCustomContextValues", { enumerable: true, get: function () { return middlewares_1.getCustomContextValues; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,4BAIC;AAJD,SAAgB,QAAQ;IACtB,OAAO,CAAC,KAAK,CACX,0EAA0E,CAC3E,CAAC;AACJ,CAAC;AAED,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AAEnB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,4BAIC;AAJD,SAAgB,QAAQ;IACtB,OAAO,CAAC,KAAK,CACX,0EAA0E,CAC3E,CAAC;AACJ,CAAC;AAED,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AAEnB,mDAK0B;AAJxB,qHAAA,mBAAmB,OAAA;AACnB,2HAAA,yBAAyB,OAAA;AACzB,4HAAA,0BAA0B,OAAA;AAC1B,2HAAA,yBAAyB,OAAA;AAG3B,2CAAmE;AAA1D,+GAAA,iBAAiB,OAAA;AAAE,8GAAA,gBAAgB,OAAA;AAc5C,6CAAuD;AAA9C,qHAAA,sBAAsB,OAAA"}
|
package/dist/interceptors.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { Interceptor } from '@connectrpc/connect';
|
|
2
|
+
import { InterceptorConfigUnion } from './interfaces';
|
|
2
3
|
/**
|
|
3
4
|
* ContextInterceptor - copies context values from MiddlewareContextStore to HandlerContext
|
|
4
5
|
* This interceptor should be first in the chain to ensure context values are available
|
|
5
6
|
* to subsequent interceptors and controllers.
|
|
6
7
|
*/
|
|
7
8
|
export declare const contextInterceptor: Interceptor;
|
|
9
|
+
/** Here we store the initialized interceptors after configuration */
|
|
10
|
+
export declare let initializedInterceptors: Interceptor[];
|
|
11
|
+
export declare function initInterceptors(configs: InterceptorConfigUnion[]): void;
|
package/dist/interceptors.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.contextInterceptor = void 0;
|
|
3
|
+
exports.initializedInterceptors = exports.contextInterceptor = void 0;
|
|
4
|
+
exports.initInterceptors = initInterceptors;
|
|
5
|
+
const context_values_1 = require("./context-values");
|
|
6
|
+
const helpers_1 = require("./helpers");
|
|
7
|
+
const middlewares_1 = require("./middlewares");
|
|
4
8
|
const stores_1 = require("./stores");
|
|
5
9
|
/**
|
|
6
10
|
* ContextInterceptor - copies context values from MiddlewareContextStore to HandlerContext
|
|
@@ -9,7 +13,7 @@ const stores_1 = require("./stores");
|
|
|
9
13
|
*/
|
|
10
14
|
const contextInterceptor = (next) => async (req) => {
|
|
11
15
|
// Get the request ID from headers
|
|
12
|
-
const requestId = req.header.get(
|
|
16
|
+
const requestId = req.header.get(middlewares_1.xServerRequestIdHeader);
|
|
13
17
|
if (requestId) {
|
|
14
18
|
const middlewareContext = stores_1.MiddlewareContextStore.get(requestId);
|
|
15
19
|
if (middlewareContext) {
|
|
@@ -19,8 +23,46 @@ const contextInterceptor = (next) => async (req) => {
|
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
25
|
}
|
|
26
|
+
const meta = stores_1.RouteMetadataStore.getRouteMetadata(req.url);
|
|
27
|
+
if (meta) {
|
|
28
|
+
// Set controller class and method in context values, so interceptors can access them
|
|
29
|
+
req.contextValues.set(context_values_1.controllerClassContextKey, meta.controllerClass);
|
|
30
|
+
req.contextValues.set(context_values_1.controllerMethodContextKey, meta.controllerMethod);
|
|
31
|
+
}
|
|
22
32
|
// Continue with the next interceptor or handler
|
|
23
33
|
return await next(req);
|
|
24
34
|
};
|
|
25
35
|
exports.contextInterceptor = contextInterceptor;
|
|
36
|
+
/** Here we store the initialized interceptors after configuration */
|
|
37
|
+
exports.initializedInterceptors = [];
|
|
38
|
+
function initInterceptors(configs) {
|
|
39
|
+
const routeChecker = (0, helpers_1.buildRouteConfigChecker)(configs);
|
|
40
|
+
exports.initializedInterceptors = [];
|
|
41
|
+
for (const config of configs) {
|
|
42
|
+
const interceptorInstance = stores_1.InterceptorStore.getInstance(config.use);
|
|
43
|
+
if (!interceptorInstance) {
|
|
44
|
+
helpers_1.logger.error(`Interceptor ${config.use.name} not registered. Make sure to decorate it with @Interceptor().`);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
// Create the interceptor function that checks route configs before applying
|
|
48
|
+
const interceptor = (next) => async (req) => {
|
|
49
|
+
const configsForUrl = routeChecker((0, helpers_1.getURLPath)(req.url), config);
|
|
50
|
+
const shouldApply = configsForUrl.length > 0;
|
|
51
|
+
if (shouldApply) {
|
|
52
|
+
return await interceptorInstance.use(next)(req);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
return await next(req);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
exports.initializedInterceptors.push(interceptor);
|
|
59
|
+
const serviceInfo = config.on
|
|
60
|
+
? ` to service ${config.on.typeName}`
|
|
61
|
+
: ' to all services';
|
|
62
|
+
const methodInfo = config.methods
|
|
63
|
+
? ` methods [${config.methods.join(', ')}]`
|
|
64
|
+
: ' all methods';
|
|
65
|
+
helpers_1.logger.log(`Registered interceptor: ${config.use.name}${serviceInfo}${methodInfo}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
26
68
|
//# sourceMappingURL=interceptors.js.map
|
package/dist/interceptors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interceptors.js","sourceRoot":"","sources":["../src/interceptors.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"interceptors.js","sourceRoot":"","sources":["../src/interceptors.ts"],"names":[],"mappings":"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"}
|
package/dist/interfaces.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { GenMessage, GenService } from '@bufbuild/protobuf/codegenv2';
|
|
2
|
-
import { HandlerContext } from '@connectrpc/connect';
|
|
2
|
+
import { HandlerContext, StreamRequest, StreamResponse, UnaryRequest, UnaryResponse } from '@connectrpc/connect';
|
|
3
3
|
import { FastifyReply, FastifyRequest } from 'fastify';
|
|
4
4
|
import { OmitConnectrpcFields } from './types';
|
|
5
5
|
export interface Logger {
|
|
@@ -12,6 +12,17 @@ export interface Logger {
|
|
|
12
12
|
export interface Middleware {
|
|
13
13
|
use(req: FastifyRequest['raw'], res: FastifyReply['raw'], next: (err?: any) => void): void;
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Copy-paste from @connectrpc/connect Interceptor types
|
|
17
|
+
*
|
|
18
|
+
* AnyFn represents the client-side invocation of an RPC. Interceptors can wrap
|
|
19
|
+
* this invocation, add request headers, and wrap parts of the request or
|
|
20
|
+
* response to inspect and log.
|
|
21
|
+
*/
|
|
22
|
+
export type AnyFn = (req: UnaryRequest | StreamRequest) => Promise<UnaryResponse | StreamResponse>;
|
|
23
|
+
export interface Interceptor {
|
|
24
|
+
use(next: AnyFn): AnyFn;
|
|
25
|
+
}
|
|
15
26
|
export interface Type<T = any> extends Function {
|
|
16
27
|
new (...args: any[]): T;
|
|
17
28
|
}
|
|
@@ -68,28 +79,14 @@ export type Service<T> = T extends GenService<infer Methods> ? {
|
|
|
68
79
|
export type ServiceMethodNames<T> = T extends GenService<infer Methods> ? {
|
|
69
80
|
[K in keyof Methods]: K;
|
|
70
81
|
}[keyof Methods] : never;
|
|
71
|
-
|
|
72
|
-
* Middleware configuration for ConnectRPC routes - without service specified
|
|
73
|
-
*/
|
|
74
|
-
export type MiddlewareConfigGlobal = {
|
|
75
|
-
/**
|
|
76
|
-
* The middleware class to apply (must be decorated with @Middleware())
|
|
77
|
-
*/
|
|
78
|
-
use: Type<Middleware>;
|
|
82
|
+
export type RouteConfigGlobal = {
|
|
79
83
|
/**
|
|
80
84
|
* Middleware applies to all services and all methods
|
|
81
85
|
*/
|
|
82
86
|
on?: never;
|
|
83
87
|
methods?: never;
|
|
84
88
|
};
|
|
85
|
-
|
|
86
|
-
* Middleware configuration for ConnectRPC routes - with service specified
|
|
87
|
-
*/
|
|
88
|
-
export type MiddlewareConfig<T extends GenService<any>> = {
|
|
89
|
-
/**
|
|
90
|
-
* The middleware class to apply (must be decorated with @Middleware())
|
|
91
|
-
*/
|
|
92
|
-
use: Type<Middleware>;
|
|
89
|
+
export type RouteConfigService<T extends GenService<any>> = {
|
|
93
90
|
/**
|
|
94
91
|
* The service to apply middleware to
|
|
95
92
|
*/
|
|
@@ -101,6 +98,24 @@ export type MiddlewareConfig<T extends GenService<any>> = {
|
|
|
101
98
|
*/
|
|
102
99
|
methods?: Array<ServiceMethodNames<T>>;
|
|
103
100
|
};
|
|
101
|
+
/**
|
|
102
|
+
* Middleware configuration for ConnectRPC routes - without service specified
|
|
103
|
+
*/
|
|
104
|
+
export type MiddlewareConfigGlobal = {
|
|
105
|
+
/**
|
|
106
|
+
* The middleware class to apply (must be decorated with @Middleware())
|
|
107
|
+
*/
|
|
108
|
+
use: Type<Middleware>;
|
|
109
|
+
} & RouteConfigGlobal;
|
|
110
|
+
/**
|
|
111
|
+
* Middleware configuration for ConnectRPC routes - with service specified
|
|
112
|
+
*/
|
|
113
|
+
export type MiddlewareConfig<T extends GenService<any>> = {
|
|
114
|
+
/**
|
|
115
|
+
* The middleware class to apply (must be decorated with @Middleware())
|
|
116
|
+
*/
|
|
117
|
+
use: Type<Middleware>;
|
|
118
|
+
} & RouteConfigService<T>;
|
|
104
119
|
/**
|
|
105
120
|
* Middleware configuration for ConnectRPC routes
|
|
106
121
|
*/
|
|
@@ -110,4 +125,25 @@ export type MiddlewareConfigUnion = MiddlewareConfigGlobal | MiddlewareConfig<an
|
|
|
110
125
|
* This ensures proper type inference for method names based on the service
|
|
111
126
|
*/
|
|
112
127
|
export declare function middlewareConfig<T extends GenService<any>>(use: Type<Middleware>, on?: T, methods?: Array<ServiceMethodNames<T>>): MiddlewareConfigUnion;
|
|
128
|
+
export type InterceptorConfigGlobal = {
|
|
129
|
+
/**
|
|
130
|
+
* The interceptor class to apply (must be decorated with @Interceptor())
|
|
131
|
+
*/
|
|
132
|
+
use: Type<Interceptor>;
|
|
133
|
+
} & RouteConfigGlobal;
|
|
134
|
+
export type InterceptorConfig<T extends GenService<any>> = {
|
|
135
|
+
/**
|
|
136
|
+
* The interceptor class to apply (must be decorated with @Interceptor())
|
|
137
|
+
*/
|
|
138
|
+
use: Type<Interceptor>;
|
|
139
|
+
} & RouteConfigService<T>;
|
|
140
|
+
/**
|
|
141
|
+
* Interceptor configuration for ConnectRPC routes
|
|
142
|
+
*/
|
|
143
|
+
export type InterceptorConfigUnion = InterceptorConfigGlobal | InterceptorConfig<any>;
|
|
144
|
+
/**
|
|
145
|
+
* Helper function to create a type-safe interceptor configuration
|
|
146
|
+
* This ensures proper type inference for method names based on the service
|
|
147
|
+
*/
|
|
148
|
+
export declare function interceptorConfig<T extends GenService<any>>(use: Type<Interceptor>, on?: T, methods?: Array<ServiceMethodNames<T>>): InterceptorConfigUnion;
|
|
113
149
|
export {};
|
package/dist/interfaces.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.middlewareConfig = middlewareConfig;
|
|
4
|
+
exports.interceptorConfig = interceptorConfig;
|
|
4
5
|
/**
|
|
5
6
|
* Helper function to create a type-safe middleware configuration
|
|
6
7
|
* This ensures proper type inference for method names based on the service
|
|
@@ -12,4 +13,15 @@ function middlewareConfig(use, on, methods) {
|
|
|
12
13
|
methods,
|
|
13
14
|
};
|
|
14
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Helper function to create a type-safe interceptor configuration
|
|
18
|
+
* This ensures proper type inference for method names based on the service
|
|
19
|
+
*/
|
|
20
|
+
function interceptorConfig(use, on, methods) {
|
|
21
|
+
return {
|
|
22
|
+
use,
|
|
23
|
+
on,
|
|
24
|
+
methods,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
15
27
|
//# sourceMappingURL=interfaces.js.map
|
package/dist/interfaces.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":";;AA2KA,4CAUC;AA2BD,8CAUC;AAnDD;;;GAGG;AACH,SAAgB,gBAAgB,CAC9B,GAAqB,EACrB,EAAM,EACN,OAAsC;IAEtC,OAAO;QACL,GAAG;QACH,EAAE;QACF,OAAO;KACR,CAAC;AACJ,CAAC;AAuBD;;;GAGG;AACH,SAAgB,iBAAiB,CAC/B,GAAsB,EACtB,EAAM,EACN,OAAsC;IAEtC,OAAO;QACL,GAAG;QACH,EAAE;QACF,OAAO;KACR,CAAC;AACJ,CAAC"}
|
package/dist/middlewares.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FastifyInstance, FastifyRequest } from 'fastify';
|
|
2
2
|
import { MiddlewareConfigUnion } from './interfaces';
|
|
3
|
+
export declare const xServerRequestIdHeader = "x-server-request-id";
|
|
3
4
|
/** This method allows middleware to access custom context values associated with a request */
|
|
4
5
|
export declare function getCustomContextValues(req: FastifyRequest['raw']): import("./context-values").CustomContextValues | null;
|
|
5
6
|
export declare function initMiddlewares(server: FastifyInstance, middlewareConfigs: MiddlewareConfigUnion[]): Promise<void>;
|
package/dist/middlewares.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.xServerRequestIdHeader = void 0;
|
|
3
4
|
exports.getCustomContextValues = getCustomContextValues;
|
|
4
5
|
exports.initMiddlewares = initMiddlewares;
|
|
5
6
|
const context_values_1 = require("./context-values");
|
|
6
7
|
const helpers_1 = require("./helpers");
|
|
7
8
|
const stores_1 = require("./stores");
|
|
9
|
+
exports.xServerRequestIdHeader = 'x-server-request-id';
|
|
8
10
|
function setupCustomContextValues(req) {
|
|
9
11
|
const requestId = (0, helpers_1.generateRequestId)();
|
|
10
12
|
// Store the request ID in a custom header
|
|
11
|
-
req.headers[
|
|
13
|
+
req.headers[exports.xServerRequestIdHeader] = requestId;
|
|
12
14
|
// Create and store the middleware context with ContextValues
|
|
13
15
|
stores_1.MiddlewareContextStore.set(requestId, {
|
|
14
16
|
contextValues: (0, context_values_1.createCustomContextValues)(),
|
|
@@ -16,7 +18,7 @@ function setupCustomContextValues(req) {
|
|
|
16
18
|
}
|
|
17
19
|
/** This method allows middleware to access custom context values associated with a request */
|
|
18
20
|
function getCustomContextValues(req) {
|
|
19
|
-
const requestId = req.headers[
|
|
21
|
+
const requestId = req.headers[exports.xServerRequestIdHeader];
|
|
20
22
|
if (requestId) {
|
|
21
23
|
const middlewareContext = stores_1.MiddlewareContextStore.get(requestId);
|
|
22
24
|
if (middlewareContext) {
|
|
@@ -26,7 +28,7 @@ function getCustomContextValues(req) {
|
|
|
26
28
|
return null;
|
|
27
29
|
}
|
|
28
30
|
function clearCustomContextValues(req) {
|
|
29
|
-
const requestId = req.headers[
|
|
31
|
+
const requestId = req.headers[exports.xServerRequestIdHeader];
|
|
30
32
|
if (requestId) {
|
|
31
33
|
stores_1.MiddlewareContextStore.delete(requestId);
|
|
32
34
|
}
|
|
@@ -40,49 +42,38 @@ async function initMiddlewares(server, middlewareConfigs) {
|
|
|
40
42
|
clearCustomContextValues(request.raw);
|
|
41
43
|
});
|
|
42
44
|
});
|
|
43
|
-
helpers_1.logger.log('Applied context middleware for storing
|
|
45
|
+
helpers_1.logger.log('Applied context middleware for storing ContextValues');
|
|
46
|
+
// Check all registered middlewares
|
|
44
47
|
for (const config of middlewareConfigs) {
|
|
45
|
-
// Convert method names to set with PascalCase
|
|
46
|
-
const methods = new Set((config.methods || []).map((m) => m[0].toUpperCase() + m.slice(1)));
|
|
47
|
-
// Get the middleware instance from the store
|
|
48
48
|
const middlewareInstance = stores_1.MiddlewareStore.getInstance(config.use);
|
|
49
49
|
if (!middlewareInstance) {
|
|
50
|
-
helpers_1.logger.
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
if (typeof middlewareInstance.use === 'function') {
|
|
54
|
-
const hook = (0, helpers_1.convertMiddlewareToHook)(middlewareInstance);
|
|
55
|
-
// Create a filtered hook that checks service and method
|
|
56
|
-
const filteredHook = async (request, reply) => {
|
|
57
|
-
const url = request.url;
|
|
58
|
-
// Parse the URL to get service and method
|
|
59
|
-
// Format: /package.ServiceName/MethodName
|
|
60
|
-
const match = url.match(/^\/([^/]+)\/([^/]+)$/);
|
|
61
|
-
if (!match) {
|
|
62
|
-
// Not a ConnectRPC route, skip
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
const [, serviceName, methodName] = match;
|
|
66
|
-
// Check if middleware should apply to this service
|
|
67
|
-
if (config.on && config.on.typeName !== serviceName) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
// Check if middleware should apply to this method
|
|
71
|
-
if (methods.size && !methods.has(methodName)) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
// Apply the middleware
|
|
75
|
-
await hook(request, reply);
|
|
76
|
-
};
|
|
77
|
-
server.addHook('onRequest', filteredHook);
|
|
78
|
-
const serviceInfo = config.on
|
|
79
|
-
? ` to service ${config.on.typeName}`
|
|
80
|
-
: ' to all services';
|
|
81
|
-
const methodInfo = config.methods
|
|
82
|
-
? ` methods [${config.methods.join(', ')}]`
|
|
83
|
-
: ' all methods';
|
|
84
|
-
helpers_1.logger.log(`Applied middleware: ${config.use.name}${serviceInfo}${methodInfo}`);
|
|
50
|
+
helpers_1.logger.error(`Middleware ${config.use.name} not found in store. Did you forget to add MiddlewareStore.registerInstance(this) in the constructor? Or did you forget to instantiate the middleware?`);
|
|
51
|
+
process.exit(1);
|
|
85
52
|
}
|
|
53
|
+
const serviceInfo = config.on
|
|
54
|
+
? ` to service ${config.on.typeName}`
|
|
55
|
+
: ' to all services';
|
|
56
|
+
const methodInfo = config.methods
|
|
57
|
+
? ` methods [${config.methods.join(', ')}]`
|
|
58
|
+
: ' all methods';
|
|
59
|
+
helpers_1.logger.log(`Applied middleware: ${config.use.name}${serviceInfo}${methodInfo}`);
|
|
86
60
|
}
|
|
61
|
+
const routeChecker = (0, helpers_1.buildRouteConfigChecker)(middlewareConfigs);
|
|
62
|
+
server.addHook('onRequest', async (request, reply) => {
|
|
63
|
+
const url = request.url;
|
|
64
|
+
const configs = routeChecker(url);
|
|
65
|
+
try {
|
|
66
|
+
for (const config of configs) {
|
|
67
|
+
const middlewareInstance = stores_1.MiddlewareStore.getInstance(config.use);
|
|
68
|
+
await (0, helpers_1.callMiddlewareAsync)(middlewareInstance, request, reply);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
helpers_1.logger.error(`Error in middleware for request ${request.url}:`, error);
|
|
73
|
+
if (!reply.sent) {
|
|
74
|
+
reply.status(500).send({ error: 'Internal Server Error' });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
87
78
|
}
|
|
88
79
|
//# sourceMappingURL=middlewares.js.map
|
package/dist/middlewares.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middlewares.js","sourceRoot":"","sources":["../src/middlewares.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"middlewares.js","sourceRoot":"","sources":["../src/middlewares.ts"],"names":[],"mappings":"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"}
|
package/dist/stores.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GenService, GenServiceMethods } from '@bufbuild/protobuf/codegenv2';
|
|
2
2
|
import { CustomContextValues } from './context-values';
|
|
3
|
-
import { Middleware, Service, Type } from './interfaces';
|
|
3
|
+
import { Interceptor, Middleware, Service, Type } from './interfaces';
|
|
4
4
|
declare class ControllersStoreClass {
|
|
5
5
|
private controllers;
|
|
6
6
|
values(): {
|
|
@@ -99,4 +99,19 @@ declare class MiddlewareContextStoreClass {
|
|
|
99
99
|
delete(requestId: string): void;
|
|
100
100
|
}
|
|
101
101
|
export declare const MiddlewareContextStore: MiddlewareContextStoreClass;
|
|
102
|
+
declare class InterceptorStoreClass {
|
|
103
|
+
private interceptors;
|
|
104
|
+
clear(): void;
|
|
105
|
+
/**
|
|
106
|
+
* Register an interceptor instance by a unique key
|
|
107
|
+
*/
|
|
108
|
+
registerInstance(self: Interceptor, { allowMultipleInstances, }?: {
|
|
109
|
+
allowMultipleInstances?: boolean;
|
|
110
|
+
}): void;
|
|
111
|
+
/**
|
|
112
|
+
* Get an interceptor instance by its unique key
|
|
113
|
+
*/
|
|
114
|
+
getInstance(interceptorClass: Type<Interceptor>): Interceptor | null;
|
|
115
|
+
}
|
|
116
|
+
export declare const InterceptorStore: InterceptorStoreClass;
|
|
102
117
|
export {};
|
package/dist/stores.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MiddlewareContextStore = exports.RouteMetadataStore = exports.MiddlewareStore = exports.ControllersStore = void 0;
|
|
3
|
+
exports.InterceptorStore = exports.MiddlewareContextStore = exports.RouteMetadataStore = exports.MiddlewareStore = exports.ControllersStore = void 0;
|
|
4
|
+
const helpers_1 = require("./helpers");
|
|
4
5
|
class ControllersStoreClass {
|
|
5
6
|
constructor() {
|
|
6
7
|
this.controllers = new Map();
|
|
@@ -91,7 +92,7 @@ class RouteMetadataStoreClass {
|
|
|
91
92
|
* Get route metadata by URL path
|
|
92
93
|
*/
|
|
93
94
|
getRouteMetadata(urlPath) {
|
|
94
|
-
return this.routes.get(urlPath) || null;
|
|
95
|
+
return this.routes.get((0, helpers_1.getURLPath)(urlPath)) || null;
|
|
95
96
|
}
|
|
96
97
|
/**
|
|
97
98
|
* Get all registered routes
|
|
@@ -133,4 +134,32 @@ class MiddlewareContextStoreClass {
|
|
|
133
134
|
}
|
|
134
135
|
}
|
|
135
136
|
exports.MiddlewareContextStore = new MiddlewareContextStoreClass();
|
|
137
|
+
class InterceptorStoreClass {
|
|
138
|
+
constructor() {
|
|
139
|
+
this.interceptors = new Map();
|
|
140
|
+
}
|
|
141
|
+
// For testing purposes
|
|
142
|
+
clear() {
|
|
143
|
+
this.interceptors.clear();
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Register an interceptor instance by a unique key
|
|
147
|
+
*/
|
|
148
|
+
registerInstance(self, { allowMultipleInstances = false, } = {}) {
|
|
149
|
+
const interceptorClass = self.constructor;
|
|
150
|
+
const key = interceptorClass.name;
|
|
151
|
+
if (!allowMultipleInstances && this.interceptors.has(key)) {
|
|
152
|
+
throw new Error(`Interceptor ${interceptorClass.name} is already registered! This may happen if you export interceptor as provider and also register it in some Nest module.`);
|
|
153
|
+
}
|
|
154
|
+
this.interceptors.set(key, self);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get an interceptor instance by its unique key
|
|
158
|
+
*/
|
|
159
|
+
getInstance(interceptorClass) {
|
|
160
|
+
const key = interceptorClass.name;
|
|
161
|
+
return this.interceptors.get(key) || null;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
exports.InterceptorStore = new InterceptorStoreClass();
|
|
136
165
|
//# sourceMappingURL=stores.js.map
|
package/dist/stores.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stores.js","sourceRoot":"","sources":["../src/stores.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"stores.js","sourceRoot":"","sources":["../src/stores.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funduck/connectrpc-fastify",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.17",
|
|
4
4
|
"author": "Oleg Milekhin <qlfunduck@gmail.com>",
|
|
5
5
|
"description": "Wrapper for official @connectrpc/connect and fastify. Simplifies configuration, type safe binding to controller, simplifies use of middlewares and guards.",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"test": "npm run compile-proto && jest --verbose",
|
|
13
13
|
"test:coverage": "npm run compile-proto && jest --coverage --runInBand",
|
|
14
14
|
"publish:check": "npm test && npm run build && npm publish --tag latest --access public --dry-run",
|
|
15
|
-
"publish:latest": "npm publish --tag latest --access public"
|
|
15
|
+
"publish:latest": "npm test && npm run build && npm publish --tag latest --access public"
|
|
16
16
|
},
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"peerDependencies": {
|
|
@@ -23,16 +23,20 @@
|
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@bufbuild/buf": "^1.64.0",
|
|
26
|
+
"@bufbuild/protobuf": "^2.10.2",
|
|
26
27
|
"@bufbuild/protoc-gen-es": "^2.10.2",
|
|
27
28
|
"@connectrpc/connect": "^2.1.1",
|
|
29
|
+
"@connectrpc/connect-fastify": "^2.1.1",
|
|
28
30
|
"@connectrpc/connect-node": "^2.1.1",
|
|
29
31
|
"@types/jest": "^30.0.0",
|
|
30
32
|
"@types/node": "^25.0.9",
|
|
33
|
+
"fastify": "^5.6.2",
|
|
31
34
|
"jest": "^30.2.0",
|
|
32
35
|
"prettier-plugin-organize-imports": "^4.3.0",
|
|
36
|
+
"reflect-metadata": "^0.2.2",
|
|
33
37
|
"ts-jest": "^29.4.6",
|
|
34
38
|
"ts-node": "^10.9.2",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
39
|
+
"type-fest": "^5.4.1",
|
|
40
|
+
"typescript": "^5.9.3"
|
|
37
41
|
}
|
|
38
42
|
}
|