@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.
Files changed (42) hide show
  1. package/LICENSE +192 -0
  2. package/README.md +161 -0
  3. package/dist/decorators/grpc-method.decorator.d.ts +32 -0
  4. package/dist/decorators/grpc-method.decorator.d.ts.map +1 -0
  5. package/dist/decorators/grpc-method.decorator.js +47 -0
  6. package/dist/decorators/grpc-method.decorator.test.d.ts +2 -0
  7. package/dist/decorators/grpc-method.decorator.test.d.ts.map +1 -0
  8. package/dist/decorators/grpc-method.decorator.test.js +130 -0
  9. package/dist/grpc.client.d.ts +50 -0
  10. package/dist/grpc.client.d.ts.map +1 -0
  11. package/dist/grpc.client.js +188 -0
  12. package/dist/grpc.client.module.d.ts +65 -0
  13. package/dist/grpc.client.module.d.ts.map +1 -0
  14. package/dist/grpc.client.module.js +104 -0
  15. package/dist/grpc.client.module.test.d.ts +2 -0
  16. package/dist/grpc.client.module.test.d.ts.map +1 -0
  17. package/dist/grpc.client.module.test.js +86 -0
  18. package/dist/grpc.client.test.d.ts +2 -0
  19. package/dist/grpc.client.test.d.ts.map +1 -0
  20. package/dist/grpc.client.test.js +216 -0
  21. package/dist/grpc.client.types.d.ts +66 -0
  22. package/dist/grpc.client.types.d.ts.map +1 -0
  23. package/dist/grpc.client.types.js +2 -0
  24. package/dist/grpc.module.d.ts +73 -0
  25. package/dist/grpc.module.d.ts.map +1 -0
  26. package/dist/grpc.module.js +134 -0
  27. package/dist/grpc.module.test.d.ts +2 -0
  28. package/dist/grpc.module.test.d.ts.map +1 -0
  29. package/dist/grpc.module.test.js +208 -0
  30. package/dist/grpc.server.d.ts +37 -0
  31. package/dist/grpc.server.d.ts.map +1 -0
  32. package/dist/grpc.server.js +208 -0
  33. package/dist/grpc.server.test.d.ts +2 -0
  34. package/dist/grpc.server.test.d.ts.map +1 -0
  35. package/dist/grpc.server.test.js +441 -0
  36. package/dist/grpc.types.d.ts +61 -0
  37. package/dist/grpc.types.d.ts.map +1 -0
  38. package/dist/grpc.types.js +2 -0
  39. package/dist/index.d.ts +14 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +20 -0
  42. 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,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=grpc.module.test.d.ts.map
@@ -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"}