@funduck/connectrpc-fastify-nestjs 1.0.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/LICENSE +21 -0
- package/README.md +151 -0
- package/dist/src/connectrpc.d.ts +22 -0
- package/dist/src/connectrpc.js +46 -0
- package/dist/src/connectrpc.js.map +1 -0
- package/dist/src/execution-context.d.ts +22 -0
- package/dist/src/execution-context.js +46 -0
- package/dist/src/execution-context.js.map +1 -0
- package/dist/src/fastify-plugin.d.ts +5 -0
- package/dist/src/fastify-plugin.js +57 -0
- package/dist/src/fastify-plugin.js.map +1 -0
- package/dist/src/guards.d.ts +8 -0
- package/dist/src/guards.js +72 -0
- package/dist/src/guards.js.map +1 -0
- package/dist/src/helpers.d.ts +7 -0
- package/dist/src/helpers.js +63 -0
- package/dist/src/helpers.js.map +1 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/index.js +14 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interfaces.d.ts +66 -0
- package/dist/src/interfaces.js +11 -0
- package/dist/src/interfaces.js.map +1 -0
- package/dist/src/middlewares.d.ts +3 -0
- package/dist/src/middlewares.js +42 -0
- package/dist/src/middlewares.js.map +1 -0
- package/dist/src/stores.d.ts +53 -0
- package/dist/src/stores.js +76 -0
- package/dist/src/stores.js.map +1 -0
- package/dist/src/types.d.ts +9 -0
- package/dist/src/types.js +3 -0
- package/dist/src/types.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +29 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Oleg Milekhin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Connectrpc Fastify Wrapper For Nestjs
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
This package allows to add [Connectrpc](https://github.com/connectrpc/connect-es) into [Nestjs](https://github.com/nestjs/nest) project using the [Fastify](https://github.com/fastify/fastify) server.
|
|
6
|
+
|
|
7
|
+
If you are comfortable with HTTP/1 only and want a compact, ready-to-use setup, this repository is for you.
|
|
8
|
+
|
|
9
|
+
It simplifies the binding of controllers, middlewares, and guards.
|
|
10
|
+
|
|
11
|
+
It uses my another package [Connectrpc Fastify Wrapper](https://github.com/funduck/connectrpc-fastify).
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
This library allows you to:
|
|
16
|
+
* Use only HTTP/1 transport
|
|
17
|
+
* Perform RPC with simple request and response messages
|
|
18
|
+
* Perform RPC with streaming responses
|
|
19
|
+
* Perform RPC with streaming requests
|
|
20
|
+
* Use middlewares
|
|
21
|
+
* Use global guards
|
|
22
|
+
|
|
23
|
+
*Bidirectional streaming RPC is currently out of scope because it requires HTTP/2, which is unstable on public networks. In practice, HTTP/1 provides more consistent performance.*
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## How To Use
|
|
27
|
+
|
|
28
|
+
You can check out the `test` directory for a complete example of server and client integration using NestJS and Fastify. Start reading from `test/app.module.ts`.
|
|
29
|
+
|
|
30
|
+
Except the bootstrap instructions are pretty much the same as in [Connectrpc Fastify Wrapper](https://github.com/funduck/connectrpc-fastify#how-to-use).
|
|
31
|
+
|
|
32
|
+
### Controllers
|
|
33
|
+
Controller must implement the service interface (not all methods) and register itself using `ConnectRPC.registerController`:
|
|
34
|
+
```TS
|
|
35
|
+
@Injectable()
|
|
36
|
+
export class ElizaController implements Service<typeof ElizaService> {
|
|
37
|
+
@Inject(Logger)
|
|
38
|
+
private logger: Logger;
|
|
39
|
+
|
|
40
|
+
constructor() {
|
|
41
|
+
ConnectRPC.registerController(this, ElizaService);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async say(
|
|
45
|
+
request: SayRequest,
|
|
46
|
+
) {
|
|
47
|
+
return {
|
|
48
|
+
sentence: `You said: ${request.sentence}`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ... Other methods are optional
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Middlewares
|
|
57
|
+
Middleware must implement `Middleware` interface and register itself using `ConnectRPC.registerMiddleware`:
|
|
58
|
+
```TS
|
|
59
|
+
@Injectable()
|
|
60
|
+
export class TestMiddleware1 implements Middleware {
|
|
61
|
+
@Inject(Logger)
|
|
62
|
+
private logger: Logger;
|
|
63
|
+
|
|
64
|
+
constructor() {
|
|
65
|
+
ConnectRPC.registerMiddleware(this);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
use(req: FastifyRequest['raw'], res: FastifyReply['raw'], next: () => void) {
|
|
69
|
+
next();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Guards
|
|
76
|
+
Guard must implement `Guard` interface and register itself using `ConnectRPC.registerGuard`:
|
|
77
|
+
```TS
|
|
78
|
+
@Injectable()
|
|
79
|
+
export class TestGuard1 implements Guard {
|
|
80
|
+
@Inject(Logger)
|
|
81
|
+
private logger: Logger;
|
|
82
|
+
|
|
83
|
+
constructor() {
|
|
84
|
+
ConnectRPC.registerGuard(this);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
canActivate(context: ExecutionContext): boolean {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Module Setup
|
|
94
|
+
Configure your NestJS module to use `ConnectRPCModule.forRoot` and register middlewares/guards as providers if necessary:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
@Module({
|
|
98
|
+
imports: [
|
|
99
|
+
// Configure ConnectRPCModule
|
|
100
|
+
ConnectRPCModule.forRoot({
|
|
101
|
+
logger: new Logger('ConnectRPC', { timestamp: true }),
|
|
102
|
+
middlewares: [
|
|
103
|
+
middlewareConfig(TestMiddleware1),
|
|
104
|
+
middlewareConfig(TestMiddleware2, ElizaService),
|
|
105
|
+
middlewareConfig(TestMiddleware3, ElizaService, ['say']),
|
|
106
|
+
],
|
|
107
|
+
}),
|
|
108
|
+
],
|
|
109
|
+
providers: [
|
|
110
|
+
Logger,
|
|
111
|
+
|
|
112
|
+
// Guard is provided the NestJS way
|
|
113
|
+
{ provide: APP_GUARD, useClass: TestGuard1 },
|
|
114
|
+
|
|
115
|
+
// Controllers are provided here instead of `controllers` array
|
|
116
|
+
ElizaController,
|
|
117
|
+
|
|
118
|
+
// Middlewares specific for ConnectRPC are provided here
|
|
119
|
+
TestMiddleware1,
|
|
120
|
+
TestMiddleware2,
|
|
121
|
+
|
|
122
|
+
// Middlewares that are applied via `consumer.apply()` should NOT be provided here
|
|
123
|
+
// Do not instantiate TestMiddleware3 twice!
|
|
124
|
+
],
|
|
125
|
+
})
|
|
126
|
+
export class AppModule implements NestModule {
|
|
127
|
+
configure(consumer: MiddlewareConsumer) {
|
|
128
|
+
consumer.apply(TestMiddleware3).forRoutes('*'); // TestMiddleware3 is instantiated here!
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Server Bootstrap
|
|
134
|
+
Just add the call to `ConnectRPCModule` after creating the app:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
export async function bootstrap() {
|
|
138
|
+
const app = await NestFactory.create<NestFastifyApplication>(
|
|
139
|
+
AppModule,
|
|
140
|
+
new FastifyAdapter(),
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// After the app is created, register the ConnectRPCModule
|
|
144
|
+
await app.get(ConnectRPCModule).registerPlugin();
|
|
145
|
+
|
|
146
|
+
await app.listen(3000);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Feedback
|
|
151
|
+
Please use [Discussions](https://github.com/funduck/connectrpc-fastify-nestjs/discussions) or email me.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { GenService, GenServiceMethods } from '@bufbuild/protobuf/codegenv2';
|
|
2
|
+
import { FastifyInstance } from 'fastify';
|
|
3
|
+
import { Guard, Logger, Middleware, MiddlewareConfigUnion, Service } from './interfaces';
|
|
4
|
+
declare class ConnectRPCClass {
|
|
5
|
+
setLogger(customLogger: Logger): void;
|
|
6
|
+
registerMiddleware(self: Middleware, options?: {
|
|
7
|
+
allowMultipleInstances?: boolean;
|
|
8
|
+
}): void;
|
|
9
|
+
registerController<T extends GenServiceMethods>(self: Service<GenService<T>>, service: GenService<T>, options?: {
|
|
10
|
+
allowMultipleInstances?: boolean;
|
|
11
|
+
}): void;
|
|
12
|
+
registerGuard(self: Guard, options?: {
|
|
13
|
+
allowMultipleInstances?: boolean;
|
|
14
|
+
}): void;
|
|
15
|
+
registerFastifyPlugin(server: FastifyInstance): Promise<void>;
|
|
16
|
+
private _middlewaresInitialized;
|
|
17
|
+
initMiddlewares(server: FastifyInstance, middlewareConfigs: MiddlewareConfigUnion[]): Promise<void>;
|
|
18
|
+
private _guardsInitialized;
|
|
19
|
+
initGuards(server: FastifyInstance): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
export declare const ConnectRPC: ConnectRPCClass;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConnectRPC = void 0;
|
|
4
|
+
const fastify_plugin_1 = require("./fastify-plugin");
|
|
5
|
+
const guards_1 = require("./guards");
|
|
6
|
+
const helpers_1 = require("./helpers");
|
|
7
|
+
const middlewares_1 = require("./middlewares");
|
|
8
|
+
const stores_1 = require("./stores");
|
|
9
|
+
class ConnectRPCClass {
|
|
10
|
+
setLogger(customLogger) {
|
|
11
|
+
(0, helpers_1.setLogger)(customLogger);
|
|
12
|
+
}
|
|
13
|
+
registerMiddleware(self, options) {
|
|
14
|
+
stores_1.MiddlewareStore.registerInstance(self, options);
|
|
15
|
+
}
|
|
16
|
+
registerController(self, service, options) {
|
|
17
|
+
stores_1.ControllersStore.registerInstance(self, service, options);
|
|
18
|
+
}
|
|
19
|
+
registerGuard(self, options) {
|
|
20
|
+
stores_1.GuardsStore.registerInstance(self, options);
|
|
21
|
+
}
|
|
22
|
+
registerFastifyPlugin(server) {
|
|
23
|
+
return (0, fastify_plugin_1.registerFastifyPlugin)(server);
|
|
24
|
+
}
|
|
25
|
+
_middlewaresInitialized = false;
|
|
26
|
+
initMiddlewares(server, middlewareConfigs) {
|
|
27
|
+
if (this._middlewaresInitialized) {
|
|
28
|
+
throw new Error('Middlewares have already been initialized!');
|
|
29
|
+
}
|
|
30
|
+
if (this._guardsInitialized) {
|
|
31
|
+
throw new Error('Middlewares must be initialized before guards!');
|
|
32
|
+
}
|
|
33
|
+
this._middlewaresInitialized = true;
|
|
34
|
+
return (0, middlewares_1.initMiddlewares)(server, middlewareConfigs);
|
|
35
|
+
}
|
|
36
|
+
_guardsInitialized = false;
|
|
37
|
+
initGuards(server) {
|
|
38
|
+
if (this._guardsInitialized) {
|
|
39
|
+
throw new Error('Guards have already been initialized!');
|
|
40
|
+
}
|
|
41
|
+
this._guardsInitialized = true;
|
|
42
|
+
return (0, guards_1.initGuards)(server);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.ConnectRPC = new ConnectRPCClass();
|
|
46
|
+
//# sourceMappingURL=connectrpc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectrpc.js","sourceRoot":"","sources":["../../src/connectrpc.ts"],"names":[],"mappings":";;;AAEA,qDAAyD;AACzD,qCAAsC;AACtC,uCAAsC;AAQtC,+CAAgD;AAChD,qCAA0E;AAE1E,MAAM,eAAe;IACnB,SAAS,CAAC,YAAoB;QAC5B,IAAA,mBAAS,EAAC,YAAY,CAAC,CAAC;IAC1B,CAAC;IAED,kBAAkB,CAChB,IAAgB,EAChB,OAEC;QAED,wBAAe,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAMD,kBAAkB,CAChB,IAA4B,EAC5B,OAAsB,EACtB,OAEC;QAED,yBAAgB,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;IAED,aAAa,CACX,IAAW,EACX,OAEC;QAED,oBAAW,CAAC,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,qBAAqB,CAAC,MAAuB;QAC3C,OAAO,IAAA,sCAAqB,EAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAEO,uBAAuB,GAAG,KAAK,CAAC;IAExC,eAAe,CACb,MAAuB,EACvB,iBAA0C;QAE1C,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QACD,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC;QACpC,OAAO,IAAA,6BAAe,EAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACpD,CAAC;IAEO,kBAAkB,GAAG,KAAK,CAAC;IAEnC,UAAU,CAAC,MAAuB;QAChC,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,OAAO,IAAA,mBAAU,EAAC,MAAM,CAAC,CAAC;IAC5B,CAAC;CACF;AAKY,QAAA,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FastifyReply, FastifyRequest } from 'fastify';
|
|
2
|
+
import { ExecutionContext, Type } from './interfaces';
|
|
3
|
+
export declare class ManualExecutionContext implements ExecutionContext {
|
|
4
|
+
readonly request: FastifyRequest['raw'];
|
|
5
|
+
readonly response: FastifyReply['raw'];
|
|
6
|
+
readonly next: <T = any>() => T;
|
|
7
|
+
readonly args: any[];
|
|
8
|
+
readonly constructorRef: Type<any> | null;
|
|
9
|
+
readonly handler: Function | null;
|
|
10
|
+
constructor(request: FastifyRequest['raw'], response: FastifyReply['raw'], next: <T = any>() => T, args: any[], constructorRef?: Type<any> | null, handler?: Function | null);
|
|
11
|
+
getClass<T = any>(): Type<T>;
|
|
12
|
+
getHandler(): Function;
|
|
13
|
+
getArgs<T extends Array<any> = any[]>(): T;
|
|
14
|
+
getArgByIndex<T = any>(index: number): T;
|
|
15
|
+
switchToHttp(): this & {
|
|
16
|
+
getRequest: () => import("node:http").IncomingMessage;
|
|
17
|
+
getResponse: () => import("node:http").ServerResponse<import("node:http").IncomingMessage>;
|
|
18
|
+
getNext: () => <T = any>() => T;
|
|
19
|
+
};
|
|
20
|
+
switchToRpc(): void;
|
|
21
|
+
switchToWs(): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ManualExecutionContext = void 0;
|
|
4
|
+
class ManualExecutionContext {
|
|
5
|
+
request;
|
|
6
|
+
response;
|
|
7
|
+
next;
|
|
8
|
+
args;
|
|
9
|
+
constructorRef;
|
|
10
|
+
handler;
|
|
11
|
+
constructor(request, response, next, args, constructorRef = null, handler = null) {
|
|
12
|
+
this.request = request;
|
|
13
|
+
this.response = response;
|
|
14
|
+
this.next = next;
|
|
15
|
+
this.args = args;
|
|
16
|
+
this.constructorRef = constructorRef;
|
|
17
|
+
this.handler = handler;
|
|
18
|
+
}
|
|
19
|
+
getClass() {
|
|
20
|
+
return this.constructorRef;
|
|
21
|
+
}
|
|
22
|
+
getHandler() {
|
|
23
|
+
return this.handler;
|
|
24
|
+
}
|
|
25
|
+
getArgs() {
|
|
26
|
+
return this.args;
|
|
27
|
+
}
|
|
28
|
+
getArgByIndex(index) {
|
|
29
|
+
return this.args[index];
|
|
30
|
+
}
|
|
31
|
+
switchToHttp() {
|
|
32
|
+
return Object.assign(this, {
|
|
33
|
+
getRequest: () => this.request,
|
|
34
|
+
getResponse: () => this.response,
|
|
35
|
+
getNext: () => this.next,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
switchToRpc() {
|
|
39
|
+
throw new Error('Context switching to RPC is not supported.');
|
|
40
|
+
}
|
|
41
|
+
switchToWs() {
|
|
42
|
+
throw new Error('Context switching to WebSockets is not supported.');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.ManualExecutionContext = ManualExecutionContext;
|
|
46
|
+
//# sourceMappingURL=execution-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-context.js","sourceRoot":"","sources":["../../src/execution-context.ts"],"names":[],"mappings":";;;AAGA,MAAa,sBAAsB;IAEtB;IACA;IACA;IACA;IACA;IACA;IANX,YACW,OAA8B,EAC9B,QAA6B,EAC7B,IAAsB,EACtB,IAAW,EACX,iBAAmC,IAAI,EACvC,UAA2B,IAAI;QAL/B,YAAO,GAAP,OAAO,CAAuB;QAC9B,aAAQ,GAAR,QAAQ,CAAqB;QAC7B,SAAI,GAAJ,IAAI,CAAkB;QACtB,SAAI,GAAJ,IAAI,CAAO;QACX,mBAAc,GAAd,cAAc,CAAyB;QACvC,YAAO,GAAP,OAAO,CAAwB;IACvC,CAAC;IAEJ,QAAQ;QACN,OAAO,IAAI,CAAC,cAAe,CAAC;IAC9B,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAQ,CAAC;IACvB,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,IAAS,CAAC;IACxB,CAAC;IAED,aAAa,CAAU,KAAa;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAM,CAAC;IAC/B,CAAC;IAED,YAAY;QACV,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;YACzB,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO;YAC9B,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ;YAChC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI;SACzB,CAAC,CAAC;IACL,CAAC;IAED,WAAW;QACT,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IAED,UAAU;QACR,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;CACF;AAzCD,wDAyCC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerFastifyPlugin = registerFastifyPlugin;
|
|
4
|
+
const connect_fastify_1 = require("@connectrpc/connect-fastify");
|
|
5
|
+
const guards_1 = require("./guards");
|
|
6
|
+
const helpers_1 = require("./helpers");
|
|
7
|
+
const stores_1 = require("./stores");
|
|
8
|
+
async function registerFastifyPlugin(server, options = {}) {
|
|
9
|
+
const implementations = new Map();
|
|
10
|
+
for (const { instance, service } of stores_1.ControllersStore.values()) {
|
|
11
|
+
const guards = (0, guards_1.getGuards)(instance);
|
|
12
|
+
if (guards.length > 0) {
|
|
13
|
+
helpers_1.logger.log(`Found ${guards.length} guards on controller ${instance.constructor.name}`);
|
|
14
|
+
}
|
|
15
|
+
const methodMappings = (0, helpers_1.discoverMethodMappings)(instance.__proto__, service);
|
|
16
|
+
const implementation = {};
|
|
17
|
+
for (const methodDesc of service.methods) {
|
|
18
|
+
const { name } = methodDesc;
|
|
19
|
+
const methodName = name[0].toLowerCase() + name.slice(1);
|
|
20
|
+
const controllerMethodName = methodMappings[name];
|
|
21
|
+
if (controllerMethodName) {
|
|
22
|
+
const controllerMethod = instance[controllerMethodName];
|
|
23
|
+
if (controllerMethod) {
|
|
24
|
+
const bindedMethod = controllerMethod.bind(instance);
|
|
25
|
+
implementation[methodName] = (...args) => {
|
|
26
|
+
return bindedMethod(...args);
|
|
27
|
+
};
|
|
28
|
+
stores_1.RouteMetadataStore.registerRoute(service.typeName, name, instance.constructor, controllerMethod, controllerMethodName, instance);
|
|
29
|
+
helpers_1.logger.log(`Binding ${instance.constructor.name}.${controllerMethodName} to ${service.typeName}.${name}`);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
helpers_1.logger.warn(`Method ${controllerMethodName} not found in ${instance.constructor.name}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
implementations.set(service, implementation);
|
|
37
|
+
}
|
|
38
|
+
const routes = (router) => {
|
|
39
|
+
for (const [service, implementation] of implementations.entries()) {
|
|
40
|
+
router.service(service, implementation);
|
|
41
|
+
helpers_1.logger.log(`Registered {/${service.typeName}} route`);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
if (routes.length === 0) {
|
|
45
|
+
helpers_1.logger.warn('No controllers found to register');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
await server.register(connect_fastify_1.fastifyConnectPlugin, {
|
|
49
|
+
grpc: false,
|
|
50
|
+
grpcWeb: false,
|
|
51
|
+
connect: true,
|
|
52
|
+
acceptCompression: options.acceptCompression ?? [],
|
|
53
|
+
routes: routes,
|
|
54
|
+
});
|
|
55
|
+
helpers_1.logger.log('Ready');
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=fastify-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastify-plugin.js","sourceRoot":"","sources":["../../src/fastify-plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FastifyInstance } from 'fastify';
|
|
2
|
+
import { ExecutionContext, Guard } from './interfaces';
|
|
3
|
+
export declare class ManualGuardExecutor {
|
|
4
|
+
executeGuard(guard: Guard, context: ExecutionContext): Promise<boolean>;
|
|
5
|
+
executeGuards(guards: Guard[], context: ExecutionContext): Promise<boolean>;
|
|
6
|
+
}
|
|
7
|
+
export declare function getGuards(controller: any): Guard[];
|
|
8
|
+
export declare function initGuards(server: FastifyInstance): Promise<void>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ManualGuardExecutor = void 0;
|
|
4
|
+
exports.getGuards = getGuards;
|
|
5
|
+
exports.initGuards = initGuards;
|
|
6
|
+
const execution_context_1 = require("./execution-context");
|
|
7
|
+
const helpers_1 = require("./helpers");
|
|
8
|
+
const stores_1 = require("./stores");
|
|
9
|
+
class ManualGuardExecutor {
|
|
10
|
+
async executeGuard(guard, context) {
|
|
11
|
+
const result = guard.canActivate(context);
|
|
12
|
+
if (typeof result === 'boolean') {
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
return await result;
|
|
16
|
+
}
|
|
17
|
+
async executeGuards(guards, context) {
|
|
18
|
+
for (const guard of guards) {
|
|
19
|
+
const canActivate = await this.executeGuard(guard, context);
|
|
20
|
+
if (!canActivate) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.ManualGuardExecutor = ManualGuardExecutor;
|
|
28
|
+
function getGuards(controller) {
|
|
29
|
+
return stores_1.GuardsStore.getAllGuards();
|
|
30
|
+
}
|
|
31
|
+
async function initGuards(server) {
|
|
32
|
+
const guardExecutor = new ManualGuardExecutor();
|
|
33
|
+
server.addHook('preHandler', async (request, reply) => {
|
|
34
|
+
const url = request.url;
|
|
35
|
+
const match = url.match(/^\/([^/]+)\/([^/]+)$/);
|
|
36
|
+
if (!match) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const routeMetadata = stores_1.RouteMetadataStore.getRouteMetadata(url);
|
|
40
|
+
if (!routeMetadata) {
|
|
41
|
+
helpers_1.logger.warn(`No route metadata found for ${url}`);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const { controllerClass, controllerMethod, controllerMethodName, instance, } = routeMetadata;
|
|
45
|
+
const guards = getGuards(instance);
|
|
46
|
+
if (guards.length === 0) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const executionContext = new execution_context_1.ManualExecutionContext(request.raw, reply.raw, (() => undefined), [], controllerClass, controllerMethod);
|
|
50
|
+
try {
|
|
51
|
+
const canActivate = await guardExecutor.executeGuards(guards, executionContext);
|
|
52
|
+
if (!canActivate) {
|
|
53
|
+
reply.code(403).send({
|
|
54
|
+
code: 'permission_denied',
|
|
55
|
+
message: 'Forbidden',
|
|
56
|
+
});
|
|
57
|
+
throw new Error('Guard rejected the request');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (!reply.sent) {
|
|
62
|
+
reply.code(403).send({
|
|
63
|
+
code: 'permission_denied',
|
|
64
|
+
message: error instanceof Error ? error.message : 'Forbidden',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
helpers_1.logger.log('Guards middleware initialized');
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=guards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../../src/guards.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { GenService } from '@bufbuild/protobuf/codegenv2';
|
|
2
|
+
import { FastifyReply, FastifyRequest } from 'fastify';
|
|
3
|
+
import { Logger } from './interfaces';
|
|
4
|
+
export declare function discoverMethodMappings(prototype: any, service: GenService<any>): Record<string, string>;
|
|
5
|
+
export declare function convertMiddlewareToHook(middlewareInstance: any): (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
|
|
6
|
+
export declare let logger: Logger;
|
|
7
|
+
export declare function setLogger(customLogger: Logger): void;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = void 0;
|
|
4
|
+
exports.discoverMethodMappings = discoverMethodMappings;
|
|
5
|
+
exports.convertMiddlewareToHook = convertMiddlewareToHook;
|
|
6
|
+
exports.setLogger = setLogger;
|
|
7
|
+
function discoverMethodMappings(prototype, service) {
|
|
8
|
+
const methodMappings = {};
|
|
9
|
+
const serviceMethods = Array.isArray(service.methods) ? service.methods : [];
|
|
10
|
+
const controllerMethods = Object.getOwnPropertyNames(prototype).filter((name) => name !== 'constructor' && typeof prototype[name] === 'function');
|
|
11
|
+
for (const methodDesc of serviceMethods) {
|
|
12
|
+
const serviceMethodName = methodDesc.name;
|
|
13
|
+
const localName = methodDesc.localName;
|
|
14
|
+
let controllerMethodName = controllerMethods.find((name) => name === localName);
|
|
15
|
+
if (!controllerMethodName) {
|
|
16
|
+
controllerMethodName = controllerMethods.find((name) => name.toLowerCase() === serviceMethodName.toLowerCase());
|
|
17
|
+
}
|
|
18
|
+
if (controllerMethodName) {
|
|
19
|
+
methodMappings[serviceMethodName] = controllerMethodName;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return methodMappings;
|
|
23
|
+
}
|
|
24
|
+
function convertMiddlewareToHook(middlewareInstance) {
|
|
25
|
+
return async (request, reply) => {
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
try {
|
|
28
|
+
middlewareInstance.use(request.raw, reply.raw, (err) => {
|
|
29
|
+
if (err) {
|
|
30
|
+
reject(err);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
resolve();
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
reject(error);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
exports.logger = {
|
|
44
|
+
log: (...args) => {
|
|
45
|
+
console.info(...args);
|
|
46
|
+
},
|
|
47
|
+
error: (...args) => {
|
|
48
|
+
console.error(...args);
|
|
49
|
+
},
|
|
50
|
+
warn: (...args) => {
|
|
51
|
+
console.warn(...args);
|
|
52
|
+
},
|
|
53
|
+
debug: (...args) => {
|
|
54
|
+
console.debug(...args);
|
|
55
|
+
},
|
|
56
|
+
verbose: (...args) => {
|
|
57
|
+
console.log(...args);
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
function setLogger(customLogger) {
|
|
61
|
+
exports.logger = customLogger;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/helpers.ts"],"names":[],"mappings":";;;AAOA,wDAsCC;AAKD,0DAmBC;AAoBD,8BAEC;AApFD,SAAgB,sBAAsB,CACpC,SAAS,EACT,OAAwB;IAExB,MAAM,cAAc,GAA2B,EAAE,CAAC;IAGlD,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAG7E,MAAM,iBAAiB,GAAG,MAAM,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC,MAAM,CACpE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,aAAa,IAAI,OAAO,SAAS,CAAC,IAAI,CAAC,KAAK,UAAU,CAC1E,CAAC;IAGF,KAAK,MAAM,UAAU,IAAI,cAAc,EAAE,CAAC;QACxC,MAAM,iBAAiB,GAAG,UAAU,CAAC,IAAI,CAAC;QAC1C,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC;QAIvC,IAAI,oBAAoB,GAAG,iBAAiB,CAAC,IAAI,CAC/C,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAC7B,CAAC;QAEF,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC1B,oBAAoB,GAAG,iBAAiB,CAAC,IAAI,CAC3C,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,iBAAiB,CAAC,WAAW,EAAE,CACjE,CAAC;QACJ,CAAC;QAED,IAAI,oBAAoB,EAAE,CAAC;YAEzB,cAAc,CAAC,iBAAiB,CAAC,GAAG,oBAAoB,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAKD,SAAgB,uBAAuB,CACrC,kBAAuB;IAEvB,OAAO,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAE,EAAE;QAC5D,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,IAAI,CAAC;gBAEH,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,GAAS,EAAE,EAAE;oBAC3D,IAAI,GAAG,EAAE,CAAC;wBACR,MAAM,CAAC,GAAG,CAAC,CAAC;oBACd,CAAC;yBAAM,CAAC;wBACN,OAAO,EAAE,CAAC;oBACZ,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,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,YAAoB;IAC5C,cAAM,GAAG,YAAY,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function printMsg(): void;
|
|
2
|
+
export { ConnectRPC } from './connectrpc';
|
|
3
|
+
export { middlewareConfig } from './interfaces';
|
|
4
|
+
export type { ExecutionContext, Guard, Logger, Middleware, MiddlewareConfig, MiddlewareConfigUnion, Service, } from './interfaces';
|
|
5
|
+
export { initGuards } from './guards';
|
|
6
|
+
export type { OmitConnectrpcFields } from './types';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.initGuards = exports.middlewareConfig = exports.ConnectRPC = void 0;
|
|
4
|
+
exports.printMsg = printMsg;
|
|
5
|
+
function printMsg() {
|
|
6
|
+
console.log('Thanks for using connectrpc-fastify!');
|
|
7
|
+
}
|
|
8
|
+
var connectrpc_1 = require("./connectrpc");
|
|
9
|
+
Object.defineProperty(exports, "ConnectRPC", { enumerable: true, get: function () { return connectrpc_1.ConnectRPC; } });
|
|
10
|
+
var interfaces_1 = require("./interfaces");
|
|
11
|
+
Object.defineProperty(exports, "middlewareConfig", { enumerable: true, get: function () { return interfaces_1.middlewareConfig; } });
|
|
12
|
+
var guards_1 = require("./guards");
|
|
13
|
+
Object.defineProperty(exports, "initGuards", { enumerable: true, get: function () { return guards_1.initGuards; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,4BAEC;AAFD,SAAgB,QAAQ;IACtB,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;AACtD,CAAC;AAED,2CAA0C;AAAjC,wGAAA,UAAU,OAAA;AAEnB,2CAAgD;AAAvC,8GAAA,gBAAgB,OAAA;AAYzB,mCAAsC;AAA7B,oGAAA,UAAU,OAAA"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { GenMessage, GenService } from '@bufbuild/protobuf/codegenv2';
|
|
2
|
+
import { FastifyReply, FastifyRequest } from 'fastify';
|
|
3
|
+
import { OmitConnectrpcFields } from './types';
|
|
4
|
+
export interface Logger {
|
|
5
|
+
log: (...args: any[]) => void;
|
|
6
|
+
error: (...args: any[]) => void;
|
|
7
|
+
warn: (...args: any[]) => void;
|
|
8
|
+
debug: (...args: any[]) => void;
|
|
9
|
+
verbose: (...args: any[]) => void;
|
|
10
|
+
}
|
|
11
|
+
export interface Middleware {
|
|
12
|
+
use(req: FastifyRequest['raw'], res: FastifyReply['raw'], next: (err?: any) => void): void;
|
|
13
|
+
}
|
|
14
|
+
export interface Type<T = any> extends Function {
|
|
15
|
+
new (...args: any[]): T;
|
|
16
|
+
}
|
|
17
|
+
type ExtractInput<T> = T extends {
|
|
18
|
+
input: GenMessage<infer M>;
|
|
19
|
+
} ? M : never;
|
|
20
|
+
type ExtractOutput<T> = T extends {
|
|
21
|
+
output: GenMessage<infer M>;
|
|
22
|
+
} ? M : never;
|
|
23
|
+
type ServiceMethod<T> = T extends {
|
|
24
|
+
methodKind: 'unary';
|
|
25
|
+
} ? (request: ExtractInput<T>) => Promise<OmitConnectrpcFields<ExtractOutput<T>>> : T extends {
|
|
26
|
+
methodKind: 'server_streaming';
|
|
27
|
+
} ? (request: ExtractInput<T>) => AsyncIterable<OmitConnectrpcFields<ExtractOutput<T>>> : T extends {
|
|
28
|
+
methodKind: 'client_streaming';
|
|
29
|
+
} ? (request: AsyncIterable<ExtractInput<T>>) => Promise<OmitConnectrpcFields<ExtractOutput<T>>> : T extends {
|
|
30
|
+
methodKind: 'bidi_streaming';
|
|
31
|
+
} ? (request: AsyncIterable<ExtractInput<T>>) => AsyncIterable<OmitConnectrpcFields<ExtractOutput<T>>> : never;
|
|
32
|
+
export type Service<T> = T extends GenService<infer Methods> ? {
|
|
33
|
+
[K in keyof Methods]?: ServiceMethod<Methods[K]>;
|
|
34
|
+
} : never;
|
|
35
|
+
export type ServiceMethodNames<T> = T extends GenService<infer Methods> ? {
|
|
36
|
+
[K in keyof Methods]: K;
|
|
37
|
+
}[keyof Methods] : never;
|
|
38
|
+
export type MiddlewareConfigGlobal = {
|
|
39
|
+
use: Type<Middleware>;
|
|
40
|
+
on?: never;
|
|
41
|
+
methods?: never;
|
|
42
|
+
};
|
|
43
|
+
export type MiddlewareConfig<T extends GenService<any>> = {
|
|
44
|
+
use: Type<Middleware>;
|
|
45
|
+
on: T;
|
|
46
|
+
methods?: Array<ServiceMethodNames<T>>;
|
|
47
|
+
};
|
|
48
|
+
export type MiddlewareConfigUnion = MiddlewareConfigGlobal | MiddlewareConfig<any>;
|
|
49
|
+
export declare function middlewareConfig<T extends GenService<any>>(use: Type<Middleware>, on?: T, methods?: Array<ServiceMethodNames<T>>): MiddlewareConfigUnion;
|
|
50
|
+
export interface ExecutionContext {
|
|
51
|
+
getClass<T = any>(): Type<T>;
|
|
52
|
+
getHandler(): Function;
|
|
53
|
+
getArgs<T extends Array<any> = any[]>(): T;
|
|
54
|
+
getArgByIndex<T = any>(index: number): T;
|
|
55
|
+
switchToHttp(): {
|
|
56
|
+
getRequest(): FastifyRequest['raw'];
|
|
57
|
+
getResponse(): FastifyReply['raw'];
|
|
58
|
+
getNext<T = any>(): () => T;
|
|
59
|
+
};
|
|
60
|
+
switchToRpc(): any;
|
|
61
|
+
switchToWs(): any;
|
|
62
|
+
}
|
|
63
|
+
export interface Guard {
|
|
64
|
+
canActivate(context: ExecutionContext): boolean | Promise<boolean>;
|
|
65
|
+
}
|
|
66
|
+
export {};
|