@hazeljs/grpc 0.2.0-alpha.1
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 +192 -0
- package/README.md +161 -0
- package/dist/decorators/grpc-method.decorator.d.ts +32 -0
- package/dist/decorators/grpc-method.decorator.d.ts.map +1 -0
- package/dist/decorators/grpc-method.decorator.js +47 -0
- package/dist/decorators/grpc-method.decorator.test.d.ts +2 -0
- package/dist/decorators/grpc-method.decorator.test.d.ts.map +1 -0
- package/dist/decorators/grpc-method.decorator.test.js +130 -0
- package/dist/grpc.client.d.ts +50 -0
- package/dist/grpc.client.d.ts.map +1 -0
- package/dist/grpc.client.js +188 -0
- package/dist/grpc.client.module.d.ts +65 -0
- package/dist/grpc.client.module.d.ts.map +1 -0
- package/dist/grpc.client.module.js +104 -0
- package/dist/grpc.client.module.test.d.ts +2 -0
- package/dist/grpc.client.module.test.d.ts.map +1 -0
- package/dist/grpc.client.module.test.js +86 -0
- package/dist/grpc.client.test.d.ts +2 -0
- package/dist/grpc.client.test.d.ts.map +1 -0
- package/dist/grpc.client.test.js +216 -0
- package/dist/grpc.client.types.d.ts +66 -0
- package/dist/grpc.client.types.d.ts.map +1 -0
- package/dist/grpc.client.types.js +2 -0
- package/dist/grpc.module.d.ts +73 -0
- package/dist/grpc.module.d.ts.map +1 -0
- package/dist/grpc.module.js +134 -0
- package/dist/grpc.module.test.d.ts +2 -0
- package/dist/grpc.module.test.d.ts.map +1 -0
- package/dist/grpc.module.test.js +208 -0
- package/dist/grpc.server.d.ts +37 -0
- package/dist/grpc.server.d.ts.map +1 -0
- package/dist/grpc.server.js +208 -0
- package/dist/grpc.server.test.d.ts +2 -0
- package/dist/grpc.server.test.d.ts.map +1 -0
- package/dist/grpc.server.test.js +441 -0
- package/dist/grpc.types.d.ts +61 -0
- package/dist/grpc.types.d.ts.map +1 -0
- package/dist/grpc.types.js +2 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/package.json +57 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { ProtoLoaderOptions } from './grpc.types';
|
|
2
|
+
import type { ChannelCredentials } from '@grpc/grpc-js';
|
|
3
|
+
/**
|
|
4
|
+
* Service instance shape returned by Discovery (matches @hazeljs/discovery ServiceInstance)
|
|
5
|
+
*/
|
|
6
|
+
export interface GrpcServiceInstanceLike {
|
|
7
|
+
host: string;
|
|
8
|
+
port: number;
|
|
9
|
+
protocol?: 'http' | 'https' | 'grpc';
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Discovery client interface for optional Discovery integration.
|
|
13
|
+
* Matches @hazeljs/discovery DiscoveryClient API.
|
|
14
|
+
*/
|
|
15
|
+
export interface GrpcDiscoveryClientLike {
|
|
16
|
+
getInstance(serviceName: string, strategy?: string, filter?: {
|
|
17
|
+
zone?: string;
|
|
18
|
+
tags?: string[];
|
|
19
|
+
metadata?: Record<string, unknown>;
|
|
20
|
+
status?: unknown;
|
|
21
|
+
}): Promise<GrpcServiceInstanceLike | null>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Discovery configuration for GrpcClientService.
|
|
25
|
+
* Used when resolving gRPC service URLs via service discovery.
|
|
26
|
+
*/
|
|
27
|
+
export interface GrpcClientDiscoveryConfig {
|
|
28
|
+
/** Discovery client instance (from @hazeljs/discovery) */
|
|
29
|
+
client: GrpcDiscoveryClientLike;
|
|
30
|
+
/** Service name to resolve (e.g. 'product-service') */
|
|
31
|
+
serviceName: string;
|
|
32
|
+
/** Load balancing strategy. @default 'round-robin' */
|
|
33
|
+
loadBalancingStrategy?: string;
|
|
34
|
+
/** Optional filter for service instances (e.g. filter by protocol: 'grpc') */
|
|
35
|
+
filter?: {
|
|
36
|
+
zone?: string;
|
|
37
|
+
tags?: string[];
|
|
38
|
+
metadata?: Record<string, unknown>;
|
|
39
|
+
status?: unknown;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* gRPC client configuration options
|
|
44
|
+
*/
|
|
45
|
+
export interface GrpcClientOptions {
|
|
46
|
+
/** Path to .proto file(s). Can be a single path or array of paths. */
|
|
47
|
+
protoPath: string | string[];
|
|
48
|
+
/** Package name as defined in the .proto file (e.g. 'hero', 'catalog') */
|
|
49
|
+
package: string;
|
|
50
|
+
/** Default URL for gRPC services when not using Discovery (e.g. 'localhost:50051') */
|
|
51
|
+
defaultUrl?: string;
|
|
52
|
+
/** Options passed to @grpc/proto-loader */
|
|
53
|
+
loader?: ProtoLoaderOptions;
|
|
54
|
+
/** Channel credentials (default: createInsecure) */
|
|
55
|
+
credentials?: ChannelCredentials;
|
|
56
|
+
/** Optional Discovery config for dynamic service resolution */
|
|
57
|
+
discovery?: GrpcClientDiscoveryConfig;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Extended options for GrpcClientModule.forRoot
|
|
61
|
+
*/
|
|
62
|
+
export interface GrpcClientModuleConfig extends GrpcClientOptions {
|
|
63
|
+
/** Whether this is a global module. @default true */
|
|
64
|
+
isGlobal?: boolean;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=grpc.client.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grpc.client.types.d.ts","sourceRoot":"","sources":["../src/grpc.client.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;CACtC;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,WAAW,CACT,WAAW,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,GACA,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;CAC5C;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,0DAA0D;IAC1D,MAAM,EAAE,uBAAuB,CAAC;IAChC,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,8EAA8E;IAC9E,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC7B,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,oDAAoD;IACpD,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,+DAA+D;IAC/D,SAAS,CAAC,EAAE,yBAAyB,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { GrpcServer } from './grpc.server';
|
|
2
|
+
import type { GrpcModuleConfig, GrpcModuleOptions } from './grpc.types';
|
|
3
|
+
/**
|
|
4
|
+
* gRPC module for HazelJS
|
|
5
|
+
* Provides gRPC server support with decorator-based RPC handlers
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // app.module.ts
|
|
10
|
+
* @HazelModule({
|
|
11
|
+
* imports: [
|
|
12
|
+
* GrpcModule.forRoot({
|
|
13
|
+
* protoPath: join(__dirname, 'hero.proto'),
|
|
14
|
+
* package: 'hero',
|
|
15
|
+
* url: '0.0.0.0:50051',
|
|
16
|
+
* })
|
|
17
|
+
* ],
|
|
18
|
+
* providers: [HeroGrpcController],
|
|
19
|
+
* })
|
|
20
|
+
* export class AppModule {}
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare class GrpcModule {
|
|
24
|
+
/**
|
|
25
|
+
* Configure gRPC module with options
|
|
26
|
+
*/
|
|
27
|
+
static forRoot(options: GrpcModuleConfig): {
|
|
28
|
+
module: typeof GrpcModule;
|
|
29
|
+
providers: Array<{
|
|
30
|
+
provide: typeof GrpcServer;
|
|
31
|
+
useFactory: () => GrpcServer;
|
|
32
|
+
}>;
|
|
33
|
+
exports: Array<typeof GrpcServer>;
|
|
34
|
+
global: boolean;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Configure gRPC module asynchronously
|
|
38
|
+
*/
|
|
39
|
+
static forRootAsync(options: {
|
|
40
|
+
useFactory: (...args: unknown[]) => Promise<GrpcModuleOptions> | GrpcModuleOptions;
|
|
41
|
+
inject?: unknown[];
|
|
42
|
+
}): {
|
|
43
|
+
module: typeof GrpcModule;
|
|
44
|
+
providers: Array<{
|
|
45
|
+
provide: string | typeof GrpcServer;
|
|
46
|
+
useFactory: unknown;
|
|
47
|
+
inject?: unknown[];
|
|
48
|
+
}>;
|
|
49
|
+
exports: Array<typeof GrpcServer>;
|
|
50
|
+
global: boolean;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Register gRPC handlers from a provider instance (with @GrpcMethod decorators)
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const heroController = container.resolve(HeroGrpcController);
|
|
58
|
+
* GrpcModule.registerHandlersFromProvider(heroController);
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
static registerHandlersFromProvider(provider: object): void;
|
|
62
|
+
/**
|
|
63
|
+
* Register gRPC handlers from multiple provider classes
|
|
64
|
+
* Resolves each from the container and registers their @GrpcMethod handlers
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* GrpcModule.registerHandlersFromProviders([HeroGrpcController, UserGrpcController]);
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
static registerHandlersFromProviders(providerClasses: (new (...args: unknown[]) => object)[]): void;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=grpc.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grpc.module.d.ts","sourceRoot":"","sources":["../src/grpc.module.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAExE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAIa,UAAU;IACrB;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG;QACzC,MAAM,EAAE,OAAO,UAAU,CAAC;QAC1B,SAAS,EAAE,KAAK,CAAC;YACf,OAAO,EAAE,OAAO,UAAU,CAAC;YAC3B,UAAU,EAAE,MAAM,UAAU,CAAC;SAC9B,CAAC,CAAC;QACH,OAAO,EAAE,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;QAClC,MAAM,EAAE,OAAO,CAAC;KACjB;IAsBD;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE;QAC3B,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,iBAAiB,CAAC,GAAG,iBAAiB,CAAC;QACnF,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;KACpB,GAAG;QACF,MAAM,EAAE,OAAO,UAAU,CAAC;QAC1B,SAAS,EAAE,KAAK,CAAC;YACf,OAAO,EAAE,MAAM,GAAG,OAAO,UAAU,CAAC;YACpC,UAAU,EAAE,OAAO,CAAC;YACpB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;SACpB,CAAC,CAAC;QACH,OAAO,EAAE,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;QAClC,MAAM,EAAE,OAAO,CAAC;KACjB;IAwBD;;;;;;;;OAQG;IACH,MAAM,CAAC,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAgB3D;;;;;;;;OAQG;IACH,MAAM,CAAC,6BAA6B,CAClC,eAAe,EAAE,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,MAAM,CAAC,EAAE,GACtD,IAAI;CAWR"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
var GrpcModule_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.GrpcModule = void 0;
|
|
14
|
+
const core_1 = require("@hazeljs/core");
|
|
15
|
+
const core_2 = require("@hazeljs/core");
|
|
16
|
+
const core_3 = __importDefault(require("@hazeljs/core"));
|
|
17
|
+
const grpc_server_1 = require("./grpc.server");
|
|
18
|
+
/**
|
|
19
|
+
* gRPC module for HazelJS
|
|
20
|
+
* Provides gRPC server support with decorator-based RPC handlers
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // app.module.ts
|
|
25
|
+
* @HazelModule({
|
|
26
|
+
* imports: [
|
|
27
|
+
* GrpcModule.forRoot({
|
|
28
|
+
* protoPath: join(__dirname, 'hero.proto'),
|
|
29
|
+
* package: 'hero',
|
|
30
|
+
* url: '0.0.0.0:50051',
|
|
31
|
+
* })
|
|
32
|
+
* ],
|
|
33
|
+
* providers: [HeroGrpcController],
|
|
34
|
+
* })
|
|
35
|
+
* export class AppModule {}
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
let GrpcModule = GrpcModule_1 = class GrpcModule {
|
|
39
|
+
/**
|
|
40
|
+
* Configure gRPC module with options
|
|
41
|
+
*/
|
|
42
|
+
static forRoot(options) {
|
|
43
|
+
const { isGlobal = true, ...grpcOptions } = options;
|
|
44
|
+
core_3.default.info('Configuring gRPC module...');
|
|
45
|
+
const grpcServerProvider = {
|
|
46
|
+
provide: grpc_server_1.GrpcServer,
|
|
47
|
+
useFactory: () => {
|
|
48
|
+
const server = new grpc_server_1.GrpcServer();
|
|
49
|
+
server.configure(grpcOptions);
|
|
50
|
+
return server;
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
module: GrpcModule_1,
|
|
55
|
+
providers: [grpcServerProvider],
|
|
56
|
+
exports: [grpc_server_1.GrpcServer],
|
|
57
|
+
global: isGlobal,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Configure gRPC module asynchronously
|
|
62
|
+
*/
|
|
63
|
+
static forRootAsync(options) {
|
|
64
|
+
return {
|
|
65
|
+
module: GrpcModule_1,
|
|
66
|
+
providers: [
|
|
67
|
+
{
|
|
68
|
+
provide: 'GRPC_OPTIONS',
|
|
69
|
+
useFactory: options.useFactory,
|
|
70
|
+
inject: options.inject || [],
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
provide: grpc_server_1.GrpcServer,
|
|
74
|
+
useFactory: (grpcOptions) => {
|
|
75
|
+
const server = new grpc_server_1.GrpcServer();
|
|
76
|
+
server.configure(grpcOptions);
|
|
77
|
+
return server;
|
|
78
|
+
},
|
|
79
|
+
inject: ['GRPC_OPTIONS'],
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
exports: [grpc_server_1.GrpcServer],
|
|
83
|
+
global: true,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Register gRPC handlers from a provider instance (with @GrpcMethod decorators)
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* const heroController = container.resolve(HeroGrpcController);
|
|
92
|
+
* GrpcModule.registerHandlersFromProvider(heroController);
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
static registerHandlersFromProvider(provider) {
|
|
96
|
+
try {
|
|
97
|
+
const container = core_2.Container.getInstance();
|
|
98
|
+
const grpcServer = container.resolve(grpc_server_1.GrpcServer);
|
|
99
|
+
if (!grpcServer) {
|
|
100
|
+
core_3.default.warn('GrpcServer not found in DI container');
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
grpcServer.registerHandlersFromProvider(provider);
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
core_3.default.error('Error registering gRPC handlers from provider:', error);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Register gRPC handlers from multiple provider classes
|
|
111
|
+
* Resolves each from the container and registers their @GrpcMethod handlers
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* GrpcModule.registerHandlersFromProviders([HeroGrpcController, UserGrpcController]);
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
static registerHandlersFromProviders(providerClasses) {
|
|
119
|
+
const container = core_2.Container.getInstance();
|
|
120
|
+
const grpcServer = container.resolve(grpc_server_1.GrpcServer);
|
|
121
|
+
if (!grpcServer) {
|
|
122
|
+
core_3.default.warn('GrpcServer not found in DI container');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
grpcServer.registerHandlersFromProviders(providerClasses);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
exports.GrpcModule = GrpcModule;
|
|
129
|
+
exports.GrpcModule = GrpcModule = GrpcModule_1 = __decorate([
|
|
130
|
+
(0, core_1.HazelModule)({
|
|
131
|
+
providers: [],
|
|
132
|
+
exports: [],
|
|
133
|
+
})
|
|
134
|
+
], GrpcModule);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grpc.module.test.d.ts","sourceRoot":"","sources":["../src/grpc.module.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const core_1 = require("@hazeljs/core");
|
|
16
|
+
const grpc_module_1 = require("./grpc.module");
|
|
17
|
+
const grpc_server_1 = require("./grpc.server");
|
|
18
|
+
const grpc_method_decorator_1 = require("./decorators/grpc-method.decorator");
|
|
19
|
+
const path_1 = __importDefault(require("path"));
|
|
20
|
+
describe('GrpcModule', () => {
|
|
21
|
+
let container;
|
|
22
|
+
const originalGetInstance = core_1.Container.getInstance;
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
container = core_1.Container.createTestInstance();
|
|
25
|
+
core_1.Container.getInstance = jest.fn(() => container);
|
|
26
|
+
});
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
core_1.Container.getInstance = originalGetInstance;
|
|
29
|
+
});
|
|
30
|
+
describe('forRoot', () => {
|
|
31
|
+
it('should return module config with providers and exports', () => {
|
|
32
|
+
const protoPath = path_1.default.join(__dirname, '__fixtures__', 'hero.proto');
|
|
33
|
+
const config = grpc_module_1.GrpcModule.forRoot({
|
|
34
|
+
protoPath,
|
|
35
|
+
package: 'hero',
|
|
36
|
+
});
|
|
37
|
+
expect(config.module).toBe(grpc_module_1.GrpcModule);
|
|
38
|
+
expect(config.providers).toHaveLength(1);
|
|
39
|
+
expect(config.providers[0].provide).toBe(grpc_server_1.GrpcServer);
|
|
40
|
+
expect(config.providers[0].useFactory).toBeDefined();
|
|
41
|
+
expect(config.exports).toContain(grpc_server_1.GrpcServer);
|
|
42
|
+
expect(config.global).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
it('should use isGlobal option', () => {
|
|
45
|
+
const protoPath = path_1.default.join(__dirname, '__fixtures__', 'hero.proto');
|
|
46
|
+
const config = grpc_module_1.GrpcModule.forRoot({
|
|
47
|
+
protoPath,
|
|
48
|
+
package: 'hero',
|
|
49
|
+
isGlobal: false,
|
|
50
|
+
});
|
|
51
|
+
expect(config.global).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
it('should default isGlobal to true when not provided', () => {
|
|
54
|
+
const protoPath = path_1.default.join(__dirname, '__fixtures__', 'hero.proto');
|
|
55
|
+
const config = grpc_module_1.GrpcModule.forRoot({
|
|
56
|
+
protoPath,
|
|
57
|
+
package: 'hero',
|
|
58
|
+
});
|
|
59
|
+
expect(config.global).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
it('should create configured GrpcServer via factory', () => {
|
|
62
|
+
const protoPath = path_1.default.join(__dirname, '__fixtures__', 'hero.proto');
|
|
63
|
+
const config = grpc_module_1.GrpcModule.forRoot({
|
|
64
|
+
protoPath,
|
|
65
|
+
package: 'hero',
|
|
66
|
+
url: '0.0.0.0:50052',
|
|
67
|
+
});
|
|
68
|
+
const factory = config.providers[0].useFactory;
|
|
69
|
+
const server = factory();
|
|
70
|
+
expect(server).toBeInstanceOf(grpc_server_1.GrpcServer);
|
|
71
|
+
expect(server.getServer()).toBeNull();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe('forRootAsync', () => {
|
|
75
|
+
it('should return module config with async providers', () => {
|
|
76
|
+
const protoPath = path_1.default.join(__dirname, '__fixtures__', 'hero.proto');
|
|
77
|
+
const config = grpc_module_1.GrpcModule.forRootAsync({
|
|
78
|
+
useFactory: () => ({ protoPath, package: 'hero' }),
|
|
79
|
+
});
|
|
80
|
+
expect(config.module).toBe(grpc_module_1.GrpcModule);
|
|
81
|
+
expect(config.providers).toHaveLength(2);
|
|
82
|
+
expect(config.providers[0].provide).toBe('GRPC_OPTIONS');
|
|
83
|
+
expect(config.providers[1].provide).toBe(grpc_server_1.GrpcServer);
|
|
84
|
+
expect(config.global).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
it('should support inject option', () => {
|
|
87
|
+
const config = grpc_module_1.GrpcModule.forRootAsync({
|
|
88
|
+
useFactory: () => ({ protoPath: 'test.proto', package: 'test' }),
|
|
89
|
+
inject: ['ConfigService'],
|
|
90
|
+
});
|
|
91
|
+
expect(config.providers[0]).toHaveProperty('inject', ['ConfigService']);
|
|
92
|
+
});
|
|
93
|
+
it('should create GrpcServer with async options', async () => {
|
|
94
|
+
const protoPath = path_1.default.join(__dirname, '__fixtures__', 'hero.proto');
|
|
95
|
+
const config = grpc_module_1.GrpcModule.forRootAsync({
|
|
96
|
+
useFactory: async () => ({ protoPath, package: 'hero' }),
|
|
97
|
+
});
|
|
98
|
+
const optionsFactory = config.providers[0].useFactory;
|
|
99
|
+
const options = await optionsFactory();
|
|
100
|
+
const serverFactory = config.providers[1].useFactory;
|
|
101
|
+
const server = serverFactory(options);
|
|
102
|
+
expect(server).toBeInstanceOf(grpc_server_1.GrpcServer);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe('registerHandlersFromProvider', () => {
|
|
106
|
+
it('should register gRPC handlers from provider with @GrpcMethod', () => {
|
|
107
|
+
const protoPath = path_1.default.join(__dirname, '__fixtures__', 'hero.proto');
|
|
108
|
+
const grpcServer = new grpc_server_1.GrpcServer();
|
|
109
|
+
grpcServer.configure({ protoPath, package: 'hero' });
|
|
110
|
+
container.register(grpc_server_1.GrpcServer, grpcServer);
|
|
111
|
+
class TestController {
|
|
112
|
+
findOne(data) {
|
|
113
|
+
return { id: data.id, name: 'Hero' };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
__decorate([
|
|
117
|
+
(0, grpc_method_decorator_1.GrpcMethod)('HeroService', 'FindOne'),
|
|
118
|
+
__metadata("design:type", Function),
|
|
119
|
+
__metadata("design:paramtypes", [Object]),
|
|
120
|
+
__metadata("design:returntype", void 0)
|
|
121
|
+
], TestController.prototype, "findOne", null);
|
|
122
|
+
const controller = new TestController();
|
|
123
|
+
grpc_module_1.GrpcModule.registerHandlersFromProvider(controller);
|
|
124
|
+
expect(grpcServer.getServer()).toBeNull();
|
|
125
|
+
});
|
|
126
|
+
it('should handle GrpcServer not in container', () => {
|
|
127
|
+
const emptyContainer = core_1.Container.createTestInstance();
|
|
128
|
+
emptyContainer.register(grpc_server_1.GrpcServer, undefined);
|
|
129
|
+
core_1.Container.getInstance = jest.fn(() => emptyContainer);
|
|
130
|
+
class TestController {
|
|
131
|
+
findOne() {
|
|
132
|
+
return { id: 1, name: 'Hero' };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
__decorate([
|
|
136
|
+
(0, grpc_method_decorator_1.GrpcMethod)('HeroService', 'FindOne'),
|
|
137
|
+
__metadata("design:type", Function),
|
|
138
|
+
__metadata("design:paramtypes", []),
|
|
139
|
+
__metadata("design:returntype", void 0)
|
|
140
|
+
], TestController.prototype, "findOne", null);
|
|
141
|
+
expect(() => {
|
|
142
|
+
grpc_module_1.GrpcModule.registerHandlersFromProvider(new TestController());
|
|
143
|
+
}).not.toThrow();
|
|
144
|
+
});
|
|
145
|
+
it('should handle errors during registration gracefully', () => {
|
|
146
|
+
core_1.Container.getInstance = jest.fn(() => {
|
|
147
|
+
throw new Error('Container error');
|
|
148
|
+
});
|
|
149
|
+
class TestController {
|
|
150
|
+
findOne() {
|
|
151
|
+
return { id: 1, name: 'Hero' };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
__decorate([
|
|
155
|
+
(0, grpc_method_decorator_1.GrpcMethod)('HeroService', 'FindOne'),
|
|
156
|
+
__metadata("design:type", Function),
|
|
157
|
+
__metadata("design:paramtypes", []),
|
|
158
|
+
__metadata("design:returntype", void 0)
|
|
159
|
+
], TestController.prototype, "findOne", null);
|
|
160
|
+
expect(() => {
|
|
161
|
+
grpc_module_1.GrpcModule.registerHandlersFromProvider(new TestController());
|
|
162
|
+
}).not.toThrow();
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
describe('registerHandlersFromProviders', () => {
|
|
166
|
+
it('should register handlers from multiple provider classes', () => {
|
|
167
|
+
const protoPath = path_1.default.join(__dirname, '__fixtures__', 'hero.proto');
|
|
168
|
+
const grpcServer = new grpc_server_1.GrpcServer();
|
|
169
|
+
grpcServer.configure({ protoPath, package: 'hero' });
|
|
170
|
+
container.register(grpc_server_1.GrpcServer, grpcServer);
|
|
171
|
+
class HeroController {
|
|
172
|
+
findOne(data) {
|
|
173
|
+
return { id: data.id, name: 'Hero' };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
__decorate([
|
|
177
|
+
(0, grpc_method_decorator_1.GrpcMethod)('HeroService', 'FindOne'),
|
|
178
|
+
__metadata("design:type", Function),
|
|
179
|
+
__metadata("design:paramtypes", [Object]),
|
|
180
|
+
__metadata("design:returntype", void 0)
|
|
181
|
+
], HeroController.prototype, "findOne", null);
|
|
182
|
+
const heroInstance = new HeroController();
|
|
183
|
+
container.register(HeroController, heroInstance);
|
|
184
|
+
grpc_module_1.GrpcModule.registerHandlersFromProviders([HeroController]);
|
|
185
|
+
expect(grpcServer.getServer()).toBeNull();
|
|
186
|
+
});
|
|
187
|
+
it('should handle GrpcServer not in container', () => {
|
|
188
|
+
const emptyContainer = core_1.Container.createTestInstance();
|
|
189
|
+
emptyContainer.register(grpc_server_1.GrpcServer, undefined);
|
|
190
|
+
core_1.Container.getInstance = jest.fn(() => emptyContainer);
|
|
191
|
+
class TestController {
|
|
192
|
+
findOne() {
|
|
193
|
+
return { id: 1, name: 'Hero' };
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
__decorate([
|
|
197
|
+
(0, grpc_method_decorator_1.GrpcMethod)('HeroService', 'FindOne'),
|
|
198
|
+
__metadata("design:type", Function),
|
|
199
|
+
__metadata("design:paramtypes", []),
|
|
200
|
+
__metadata("design:returntype", void 0)
|
|
201
|
+
], TestController.prototype, "findOne", null);
|
|
202
|
+
container.register(TestController, new TestController());
|
|
203
|
+
expect(() => {
|
|
204
|
+
grpc_module_1.GrpcModule.registerHandlersFromProviders([TestController]);
|
|
205
|
+
}).not.toThrow();
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as grpc from '@grpc/grpc-js';
|
|
2
|
+
import type { GrpcModuleOptions } from './grpc.types';
|
|
3
|
+
/**
|
|
4
|
+
* gRPC Server service - manages gRPC server lifecycle and RPC handler registration
|
|
5
|
+
*/
|
|
6
|
+
export declare class GrpcServer {
|
|
7
|
+
private server;
|
|
8
|
+
private packageDefinition;
|
|
9
|
+
private protoDescriptor;
|
|
10
|
+
private options;
|
|
11
|
+
private handlerMap;
|
|
12
|
+
/**
|
|
13
|
+
* Configure the server with proto path and options
|
|
14
|
+
*/
|
|
15
|
+
configure(options: GrpcModuleOptions): void;
|
|
16
|
+
/**
|
|
17
|
+
* Register RPC handlers from a provider instance (with @GrpcMethod decorators)
|
|
18
|
+
*/
|
|
19
|
+
registerHandlersFromProvider(provider: object): void;
|
|
20
|
+
/**
|
|
21
|
+
* Register handlers from multiple provider classes (resolved from DI container)
|
|
22
|
+
*/
|
|
23
|
+
registerHandlersFromProviders(providerClasses: (new (...args: unknown[]) => object)[]): void;
|
|
24
|
+
/**
|
|
25
|
+
* Start the gRPC server and bind to the configured URL
|
|
26
|
+
*/
|
|
27
|
+
start(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Shutdown the gRPC server gracefully
|
|
30
|
+
*/
|
|
31
|
+
close(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Get the underlying gRPC Server instance (for advanced use)
|
|
34
|
+
*/
|
|
35
|
+
getServer(): grpc.Server | null;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=grpc.server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grpc.server.d.ts","sourceRoot":"","sources":["../src/grpc.server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,IAAI,MAAM,eAAe,CAAC;AAItC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAStD;;GAEG;AACH,qBACa,UAAU;IACrB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,iBAAiB,CAAkC;IAC3D,OAAO,CAAC,eAAe,CAAwC;IAC/D,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,UAAU,CACN;IAEZ;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAuB3C;;OAEG;IACH,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IA2BpD;;OAEG;IACH,6BAA6B,CAAC,eAAe,EAAE,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,MAAM,CAAC,EAAE,GAAG,IAAI;IAY5F;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoE5B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmB5B;;OAEG;IACH,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI;CAGhC"}
|