@themainstack/communication 1.0.1 → 1.0.2

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.
@@ -89,7 +89,8 @@ function generateProtoFromMethods(methods, options = {}) {
89
89
  if (value.length > 0) {
90
90
  const firstItem = value[0];
91
91
  if (typeof firstItem === "object") {
92
- const nestedName = capitalize(key).replace(/s$/, "");
92
+ // Scope nested naming: Parent_Child
93
+ const nestedName = `${msgName}_${capitalize(key).replace(/s$/, "")}`;
93
94
  type = analyzeMessage(firstItem, nestedName);
94
95
  }
95
96
  else {
@@ -103,7 +104,8 @@ function generateProtoFromMethods(methods, options = {}) {
103
104
  }
104
105
  }
105
106
  else if (valueType === "object") {
106
- const nestedName = capitalize(key);
107
+ // Scope nested naming: Parent_Child
108
+ const nestedName = `${msgName}_${capitalize(key)}`;
107
109
  type = analyzeMessage(value, nestedName);
108
110
  }
109
111
  // Use snake_case for proto fields
@@ -127,6 +127,69 @@ export async function startGrpcServer() {
127
127
  }
128
128
  ```
129
129
 
130
+ ### 1.3.1 Organizing Handlers in Separate Files (Recommended)
131
+
132
+ For services with many gRPC methods, you can keep your code clean by defining handlers in separate files and importing them:
133
+
134
+ **Step 1: Define handlers in separate files**
135
+
136
+ ```typescript
137
+ // fee-service/src/grpc/handlers/withdrawal-fee.handler.ts
138
+ import { FeesService } from '../../fee/fees.service';
139
+
140
+ const feesService = new FeesService();
141
+
142
+ export const withdrawalFeeHandler = {
143
+ name: 'CalculateWithdrawalFee',
144
+ handler: async (request: any) => {
145
+ const result = await feesService.calculateFeesForPlan(
146
+ 'starter',
147
+ request.currency,
148
+ request.amount,
149
+ 'withdrawal',
150
+ );
151
+ return { /* mapped response */ };
152
+ },
153
+ requestSample: () => ({ merchantId: '', amount: 0, currency: '' }),
154
+ responseSample: () => ({ dollarAmount: 0, fee: 0 }),
155
+ };
156
+ ```
157
+
158
+ ```typescript
159
+ // fee-service/src/grpc/handlers/deposit-fee.handler.ts
160
+ export const depositFeeHandler = {
161
+ name: 'CalculateDepositFee',
162
+ handler: async (request: any) => { /* logic */ },
163
+ requestSample: () => ({ /* ... */ }),
164
+ responseSample: () => ({ /* ... */ }),
165
+ };
166
+ ```
167
+
168
+ **Step 2: Import and use them in your bootstrap file**
169
+
170
+ ```typescript
171
+ // fee-service/src/grpc/grpc-bootstrap.ts
172
+ import { GrpcServerFactory } from '@themainstack/communication';
173
+ import { withdrawalFeeHandler } from './handlers/withdrawal-fee.handler';
174
+ import { depositFeeHandler } from './handlers/deposit-fee.handler';
175
+
176
+ export async function startGrpcServer() {
177
+ const server = await GrpcServerFactory.createServer({
178
+ packageName: 'fee.v1',
179
+ serviceName: 'FeeService',
180
+ port: parseInt(process.env.GRPC_PORT || '50053'),
181
+ }, [
182
+ withdrawalFeeHandler, // Clean imports!
183
+ depositFeeHandler,
184
+ ]);
185
+
186
+ await server.start();
187
+ return server;
188
+ }
189
+ ```
190
+
191
+ This keeps your bootstrap file as a simple **configuration list** while the actual business logic lives in dedicated handler files.
192
+
130
193
  ### 1.4 Integrate with main.ts
131
194
 
132
195
  ```typescript
@@ -47,8 +47,8 @@ async function startServer() {
47
47
 
48
48
  const server = await GrpcServerFactory.createServer(
49
49
  {
50
- packageName: 'calculator.v1',
51
- serviceName: 'CalculatorService',
50
+ packageName: 'fee.v1',
51
+ serviceName: 'FeeService',
52
52
  port: 50055,
53
53
  protoOutputDir: path.join(__dirname, 'grpc'),
54
54
  },
@@ -58,11 +58,11 @@ async function startServer() {
58
58
  handler: calculateFee, // Your existing function!
59
59
  requestSample: () => ({ merchantId: '', amount: 0, currency: '' }),
60
60
  responseSample: () => ({
61
- originalAmount: 0,
62
- fee: 0,
61
+ originalAmount: 100,
62
+ fee: 10,
63
63
  totalAmount: 0,
64
- currency: '',
65
- feePercentage: 0
64
+ currency: 'USD',
65
+ feePercentage: 10
66
66
  }),
67
67
  },
68
68
  ]
@@ -81,8 +81,8 @@ async function callServer() {
81
81
  await new Promise(resolve => setTimeout(resolve, 500));
82
82
 
83
83
  const client = GrpcClientFactory.createClient<any>({
84
- serviceName: 'CalculatorService',
85
- packageName: 'calculator.v1',
84
+ serviceName: 'FeeService',
85
+ packageName: 'fee.v1',
86
86
  protoPath: path.join(__dirname, 'grpc', 'calculator.proto'),
87
87
  url: 'localhost:50055',
88
88
  });
@@ -108,11 +108,6 @@ async function callServer() {
108
108
 
109
109
  // RUN THE DEMO
110
110
  async function main() {
111
- console.log('------------------------------------------------------------');
112
- console.log(' @themainstack/communication - Full gRPC Demo');
113
- console.log('------------------------------------------------------------');
114
- console.log('');
115
-
116
111
  // Start server
117
112
  const server = await startServer();
118
113
 
@@ -130,10 +125,6 @@ async function main() {
130
125
  // Stop server
131
126
  await server.stop();
132
127
  }
133
-
134
- console.log('------------------------------------------------------------');
135
- console.log(' Demo Complete!');
136
- console.log('------------------------------------------------------------');
137
128
  }
138
129
 
139
130
  main().catch(console.error);
@@ -4,57 +4,19 @@ package fee.v1;
4
4
 
5
5
  // FeeService - Auto-generated gRPC service
6
6
  service FeeService {
7
- rpc CalculateWithdrawalFee (CalculateWithdrawalFeeRequest) returns (CalculateWithdrawalFeeResponse) {}
7
+ rpc CalculateFee (CalculateFeeRequest) returns (CalculateFeeResponse) {}
8
8
  }
9
9
 
10
- message CalculateWithdrawalFeeResponse {
11
- double dollar_amount = 1;
12
- double dollar_transaction_fee = 2;
13
- int32 local_transaction_fee = 3;
14
- string local_currency = 4;
15
- string local_amount = 5;
16
- double exchange_rate = 6;
17
- repeated AppliedFee applied_fees = 7;
18
- repeated string applied_fee_ids = 8;
19
- Tax tax = 9;
10
+ message CalculateFeeResponse {
11
+ int32 original_amount = 1;
12
+ int32 fee = 2;
13
+ int32 total_amount = 3;
14
+ string currency = 4;
15
+ int32 fee_percentage = 5;
20
16
  }
21
17
 
22
- message Tax {
23
- string id = 1;
24
- double dollar_tax = 2;
25
- int32 local_tax = 3;
26
- int32 gateway_recorded_tax = 4;
27
- int32 surplus_on_gateway_recorded_tax = 5;
28
- repeated Breakdown breakdown = 6;
29
- }
30
-
31
- message Breakdown {
32
- string country = 1;
33
- int32 flat_amount = 2;
34
- string percentage_decimal = 3;
35
- string rate_type = 4;
36
- string state = 5;
37
- string tax_type = 6;
38
- string taxability_reason = 7;
39
- }
40
-
41
- message AppliedFee {
42
- string id = 1;
43
- string type = 2;
44
- string display_name = 3;
45
- double amount = 4;
46
- string amount_type = 5;
47
- int32 extra = 6;
48
- double value = 7;
49
- double value_usd = 8;
50
- bool is_mainstack = 9;
51
- bool is_processor = 10;
52
- bool is_deposit = 11;
53
- }
54
-
55
- message CalculateWithdrawalFeeRequest {
18
+ message CalculateFeeRequest {
56
19
  string merchant_id = 1;
57
- double amount = 2;
20
+ int32 amount = 2;
58
21
  string currency = 3;
59
- string payout_method = 4;
60
22
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@themainstack/communication",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "private": false,
5
5
  "description": "Unified gRPC framework for inter-service communication - auto-generates protos, creates servers, and provides type-safe clients",
6
6
  "main": "dist/index.js",
@@ -23,4 +23,4 @@
23
23
  "@grpc/grpc-js": "^1.14.3",
24
24
  "@grpc/proto-loader": "^0.8.0"
25
25
  }
26
- }
26
+ }
@@ -0,0 +1 @@
1
+ //registry.npmjs.org/:_authToken=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
@@ -177,7 +177,7 @@ export class GrpcServerFactory {
177
177
  this.server.bindAsync(
178
178
  address,
179
179
  grpc.ServerCredentials.createInsecure(),
180
- (error, port) => {
180
+ (error: Error | null, port: number) => {
181
181
  if (error) {
182
182
  reject(error);
183
183
  return;
@@ -109,7 +109,8 @@ export function generateProtoFromMethods(
109
109
  if (value.length > 0) {
110
110
  const firstItem = value[0];
111
111
  if (typeof firstItem === "object") {
112
- const nestedName = capitalize(key).replace(/s$/, "");
112
+ // Scope nested naming: Parent_Child
113
+ const nestedName = `${msgName}_${capitalize(key).replace(/s$/, "")}`;
113
114
  type = analyzeMessage(firstItem, nestedName);
114
115
  } else {
115
116
  type = typeof firstItem === "number"
@@ -120,7 +121,8 @@ export function generateProtoFromMethods(
120
121
  type = "string";
121
122
  }
122
123
  } else if (valueType === "object") {
123
- const nestedName = capitalize(key);
124
+ // Scope nested naming: Parent_Child
125
+ const nestedName = `${msgName}_${capitalize(key)}`;
124
126
  type = analyzeMessage(value, nestedName);
125
127
  }
126
128