@meshtrade/api-node 1.30.2 → 1.32.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/dist/meshtrade/compliance/client/v1/client_pb.d.ts +17 -9
- package/dist/meshtrade/compliance/client/v1/client_pb.js +1 -1
- package/dist/meshtrade/compliance/client/v1/service_node_meshts.d.ts +46 -21
- package/dist/meshtrade/compliance/client/v1/service_node_meshts.js +98 -56
- package/dist/meshtrade/config/index.d.ts +160 -0
- package/dist/meshtrade/config/index.js +210 -0
- package/dist/meshtrade/iam/api_user/v1/api_user_pb.d.ts +12 -4
- package/dist/meshtrade/iam/api_user/v1/api_user_pb.js +1 -1
- package/dist/meshtrade/iam/api_user/v1/service_node_meshts.d.ts +46 -21
- package/dist/meshtrade/iam/api_user/v1/service_node_meshts.js +149 -65
- package/dist/meshtrade/iam/group/v1/group_pb.d.ts +8 -0
- package/dist/meshtrade/iam/group/v1/group_pb.js +1 -1
- package/dist/meshtrade/iam/group/v1/service_node_meshts.d.ts +46 -21
- package/dist/meshtrade/iam/group/v1/service_node_meshts.js +114 -58
- package/dist/meshtrade/iam/user/v1/service_node_meshts.d.ts +46 -21
- package/dist/meshtrade/iam/user/v1/service_node_meshts.js +141 -64
- package/dist/meshtrade/iam/user/v1/user_pb.d.ts +10 -2
- package/dist/meshtrade/iam/user/v1/user_pb.js +1 -1
- package/dist/meshtrade/{common/connectInterceptors.d.ts → interceptors/index.d.ts} +6 -64
- package/dist/meshtrade/{common/connectInterceptors.js → interceptors/index.js} +20 -90
- package/dist/meshtrade/ledger/transaction/v1/service_node_meshts.d.ts +46 -21
- package/dist/meshtrade/ledger/transaction/v1/service_node_meshts.js +90 -55
- package/dist/meshtrade/market_data/price/v1/service_node_meshts.d.ts +46 -21
- package/dist/meshtrade/market_data/price/v1/service_node_meshts.js +82 -54
- package/dist/meshtrade/reporting/account_report/v1/service_node_meshts.d.ts +46 -21
- package/dist/meshtrade/reporting/account_report/v1/service_node_meshts.js +90 -55
- package/dist/meshtrade/studio/instrument/v1/instrument_pb.d.ts +8 -0
- package/dist/meshtrade/studio/instrument/v1/instrument_pb.js +1 -1
- package/dist/meshtrade/trading/limit_order/v1/limit_order_pb.d.ts +16 -8
- package/dist/meshtrade/trading/limit_order/v1/limit_order_pb.js +1 -1
- package/dist/meshtrade/trading/limit_order/v1/service_node_meshts.d.ts +46 -21
- package/dist/meshtrade/trading/limit_order/v1/service_node_meshts.js +133 -63
- package/dist/meshtrade/trading/limit_order/v1/service_pb.js +1 -1
- package/dist/meshtrade/trading/market_order/v1/service_node_meshts.d.ts +46 -21
- package/dist/meshtrade/trading/market_order/v1/service_node_meshts.js +82 -54
- package/dist/meshtrade/wallet/account/v1/account_pb.d.ts +8 -0
- package/dist/meshtrade/wallet/account/v1/account_pb.js +1 -1
- package/dist/meshtrade/wallet/account/v1/service_node_meshts.d.ts +46 -21
- package/dist/meshtrade/wallet/account/v1/service_node_meshts.js +149 -65
- package/package.json +19 -2
- package/dist/meshtrade/common/config.d.ts +0 -50
- package/dist/meshtrade/common/config.js +0 -34
- package/dist/meshtrade/common/validation.d.ts +0 -62
- package/dist/meshtrade/common/validation.js +0 -77
|
@@ -7,62 +7,82 @@ exports.UserServiceNode = void 0;
|
|
|
7
7
|
const connect_1 = require("@connectrpc/connect");
|
|
8
8
|
const connect_node_1 = require("@connectrpc/connect-node");
|
|
9
9
|
const service_pb_1 = require("./service_pb");
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
10
|
+
const service_pb_2 = require("./service_pb");
|
|
11
|
+
const config_1 = require("../../../config");
|
|
12
|
+
const protovalidate_1 = require("@bufbuild/protovalidate");
|
|
13
|
+
const interceptors_1 = require("../../../interceptors");
|
|
13
14
|
/**
|
|
14
15
|
* Node.js client for interacting with the meshtrade.iam.user.v1 user v1 API resource service.
|
|
15
16
|
* Uses Connect-ES with gRPC transport for Node.js gRPC communication.
|
|
16
17
|
*
|
|
17
|
-
* Supports
|
|
18
|
+
* Supports flexible authentication modes using functional options pattern:
|
|
18
19
|
*
|
|
19
20
|
* 1. **No Authentication** (public APIs):
|
|
20
21
|
* ```typescript
|
|
21
|
-
* const client = new UserServiceNode(
|
|
22
|
+
* const client = new UserServiceNode(
|
|
23
|
+
* WithServerUrl("http://localhost:10000")
|
|
24
|
+
* );
|
|
22
25
|
* ```
|
|
23
26
|
*
|
|
24
27
|
* 2. **API Key Authentication** (backend services):
|
|
25
28
|
* ```typescript
|
|
26
|
-
* const client = new UserServiceNode(
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
29
|
+
* const client = new UserServiceNode(
|
|
30
|
+
* WithAPIKey("your-api-key"),
|
|
31
|
+
* WithGroup("groups/01ARZ3NDEKTSV4YWVF8F5BH32"),
|
|
32
|
+
* WithServerUrl("https://api.example.com")
|
|
33
|
+
* );
|
|
31
34
|
* ```
|
|
32
35
|
*
|
|
33
36
|
* 3. **JWT Token Authentication** (Next.js backend with user session):
|
|
34
37
|
* ```typescript
|
|
35
|
-
* const client = new UserServiceNode(
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
38
|
+
* const client = new UserServiceNode(
|
|
39
|
+
* WithJWTAccessToken("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."),
|
|
40
|
+
* WithServerUrl("https://api.example.com")
|
|
41
|
+
* );
|
|
39
42
|
* ```
|
|
43
|
+
*
|
|
44
|
+
* 4. **JWT with Group Context** (user session with specific group):
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const client = new UserServiceNode(
|
|
47
|
+
* WithJWTAccessToken("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."),
|
|
48
|
+
* WithGroup("groups/01ARZ3NDEKTSV4YWVF8F5BH32"),
|
|
49
|
+
* WithServerUrl("https://api.example.com")
|
|
50
|
+
* );
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* Available options:
|
|
54
|
+
* - `WithAPIKey(key)` - API key authentication (mutually exclusive with JWT)
|
|
55
|
+
* - `WithJWTAccessToken(token)` - JWT authentication (mutually exclusive with API key)
|
|
56
|
+
* - `WithGroup(group)` - Group context (optional, works with both auth modes)
|
|
57
|
+
* - `WithServerUrl(url)` - Custom server URL (optional, defaults to production)
|
|
40
58
|
*/
|
|
41
59
|
class UserServiceNode {
|
|
42
60
|
/**
|
|
43
61
|
* Constructs an instance of UserServiceNode.
|
|
44
|
-
*
|
|
45
|
-
*
|
|
62
|
+
*
|
|
63
|
+
* Uses functional options pattern for flexible configuration:
|
|
64
|
+
* - `WithAPIKey(key)` - API key authentication
|
|
65
|
+
* - `WithJWTAccessToken(token)` - JWT authentication
|
|
66
|
+
* - `WithGroup(group)` - Group context (optional)
|
|
67
|
+
* - `WithServerUrl(url)` - Custom server URL (optional)
|
|
68
|
+
*
|
|
69
|
+
* @param {...ClientOption} opts - Variable number of configuration options
|
|
46
70
|
*/
|
|
47
|
-
constructor(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this._interceptors
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// JWT authentication mode
|
|
63
|
-
this._interceptors.push((0, connectInterceptors_1.createJwtInterceptor)(this._config.jwtToken));
|
|
64
|
-
}
|
|
65
|
-
// If neither is configured, no authentication (public API mode)
|
|
71
|
+
constructor(...opts) {
|
|
72
|
+
// Build configuration from options
|
|
73
|
+
this._config = (0, config_1.buildConfigFromOptions)(...opts);
|
|
74
|
+
// Initialize validator for request validation
|
|
75
|
+
this._validator = (0, protovalidate_1.createValidator)();
|
|
76
|
+
this._interceptors = [];
|
|
77
|
+
this._interceptors.push((0, interceptors_1.createLoggingInterceptor)());
|
|
78
|
+
if (this._config.apiKey) {
|
|
79
|
+
this._interceptors.push((0, interceptors_1.createApiKeyInterceptor)(this._config.apiKey));
|
|
80
|
+
}
|
|
81
|
+
if (this._config.jwtToken) {
|
|
82
|
+
this._interceptors.push((0, interceptors_1.createJwtInterceptor)(this._config.jwtToken));
|
|
83
|
+
}
|
|
84
|
+
if (this._config.group) {
|
|
85
|
+
this._interceptors.push((0, interceptors_1.createGroupInterceptor)(this._config.group));
|
|
66
86
|
}
|
|
67
87
|
// Create the gRPC transport for Node.js with interceptors
|
|
68
88
|
// Note: gRPC transport uses HTTP/2 by default
|
|
@@ -77,35 +97,36 @@ class UserServiceNode {
|
|
|
77
97
|
* Returns a new client instance configured to send the specified group
|
|
78
98
|
* resource name in the request headers for subsequent API calls.
|
|
79
99
|
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
100
|
+
* This method creates a new client with the same authentication configuration
|
|
101
|
+
* but with the group context updated to the specified value.
|
|
102
|
+
*
|
|
103
|
+
* **Compatibility**: Works with all authentication modes:
|
|
104
|
+
* - **API key auth**: Creates new client with API key + new group
|
|
105
|
+
* - **JWT auth**: Creates new client with JWT + new group
|
|
106
|
+
* - **No auth**: Creates new client with standalone group interceptor
|
|
84
107
|
*
|
|
85
108
|
* @param {string} group - The operating group context to inject into the request
|
|
86
109
|
* in the format `groups/{ulid}` where {ulid} is a 26-character ULID.
|
|
87
110
|
* Example: 'groups/01ARZ3NDEKTSV4YWVF8F5BH32'
|
|
88
111
|
* @returns {UserServiceNode} A new, configured instance of the client.
|
|
89
|
-
* @throws {Error} If used with JWT authentication or no authentication
|
|
90
112
|
* @throws {Error} If the group format is invalid
|
|
91
113
|
*/
|
|
92
114
|
withGroup(group) {
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return new UserServiceNode(this._config, newInterceptors);
|
|
115
|
+
// Build new options array with existing auth and updated group
|
|
116
|
+
const newOpts = [];
|
|
117
|
+
// Add server URL
|
|
118
|
+
newOpts.push((0, config_1.WithServerUrl)(this._config.apiServerURL));
|
|
119
|
+
// Add authentication (preserve existing mode)
|
|
120
|
+
if (this._config.apiKey) {
|
|
121
|
+
newOpts.push((0, config_1.WithAPIKey)(this._config.apiKey));
|
|
122
|
+
}
|
|
123
|
+
else if (this._config.jwtToken) {
|
|
124
|
+
newOpts.push((0, config_1.WithJWTAccessToken)(this._config.jwtToken));
|
|
125
|
+
}
|
|
126
|
+
// Add the new group
|
|
127
|
+
newOpts.push((0, config_1.WithGroup)(group));
|
|
128
|
+
// Return a new client instance with updated configuration
|
|
129
|
+
return new UserServiceNode(...newOpts);
|
|
109
130
|
}
|
|
110
131
|
/**
|
|
111
132
|
* Performs assignrolestouser operation on user.
|
|
@@ -114,7 +135,14 @@ class UserServiceNode {
|
|
|
114
135
|
*/
|
|
115
136
|
assignRolesToUser(request) {
|
|
116
137
|
// Validate request
|
|
117
|
-
(
|
|
138
|
+
const result = this._validator.validate(service_pb_2.AssignRolesToUserRequestSchema, request);
|
|
139
|
+
if (result.kind === "invalid") {
|
|
140
|
+
const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
|
|
141
|
+
throw new Error(`Validation failed: ${violations}`);
|
|
142
|
+
}
|
|
143
|
+
else if (result.kind === "error") {
|
|
144
|
+
throw result.error;
|
|
145
|
+
}
|
|
118
146
|
return this._client.assignRolesToUser(request);
|
|
119
147
|
}
|
|
120
148
|
/**
|
|
@@ -124,7 +152,14 @@ class UserServiceNode {
|
|
|
124
152
|
*/
|
|
125
153
|
revokeRolesFromUser(request) {
|
|
126
154
|
// Validate request
|
|
127
|
-
(
|
|
155
|
+
const result = this._validator.validate(service_pb_2.RevokeRolesFromUserRequestSchema, request);
|
|
156
|
+
if (result.kind === "invalid") {
|
|
157
|
+
const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
|
|
158
|
+
throw new Error(`Validation failed: ${violations}`);
|
|
159
|
+
}
|
|
160
|
+
else if (result.kind === "error") {
|
|
161
|
+
throw result.error;
|
|
162
|
+
}
|
|
128
163
|
return this._client.revokeRolesFromUser(request);
|
|
129
164
|
}
|
|
130
165
|
/**
|
|
@@ -134,7 +169,14 @@ class UserServiceNode {
|
|
|
134
169
|
*/
|
|
135
170
|
getUser(request) {
|
|
136
171
|
// Validate request
|
|
137
|
-
(
|
|
172
|
+
const result = this._validator.validate(service_pb_2.GetUserRequestSchema, request);
|
|
173
|
+
if (result.kind === "invalid") {
|
|
174
|
+
const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
|
|
175
|
+
throw new Error(`Validation failed: ${violations}`);
|
|
176
|
+
}
|
|
177
|
+
else if (result.kind === "error") {
|
|
178
|
+
throw result.error;
|
|
179
|
+
}
|
|
138
180
|
return this._client.getUser(request);
|
|
139
181
|
}
|
|
140
182
|
/**
|
|
@@ -144,7 +186,14 @@ class UserServiceNode {
|
|
|
144
186
|
*/
|
|
145
187
|
getUserByEmail(request) {
|
|
146
188
|
// Validate request
|
|
147
|
-
(
|
|
189
|
+
const result = this._validator.validate(service_pb_2.GetUserByEmailRequestSchema, request);
|
|
190
|
+
if (result.kind === "invalid") {
|
|
191
|
+
const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
|
|
192
|
+
throw new Error(`Validation failed: ${violations}`);
|
|
193
|
+
}
|
|
194
|
+
else if (result.kind === "error") {
|
|
195
|
+
throw result.error;
|
|
196
|
+
}
|
|
148
197
|
return this._client.getUserByEmail(request);
|
|
149
198
|
}
|
|
150
199
|
/**
|
|
@@ -154,7 +203,14 @@ class UserServiceNode {
|
|
|
154
203
|
*/
|
|
155
204
|
listUsers(request) {
|
|
156
205
|
// Validate request
|
|
157
|
-
(
|
|
206
|
+
const result = this._validator.validate(service_pb_2.ListUsersRequestSchema, request);
|
|
207
|
+
if (result.kind === "invalid") {
|
|
208
|
+
const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
|
|
209
|
+
throw new Error(`Validation failed: ${violations}`);
|
|
210
|
+
}
|
|
211
|
+
else if (result.kind === "error") {
|
|
212
|
+
throw result.error;
|
|
213
|
+
}
|
|
158
214
|
return this._client.listUsers(request);
|
|
159
215
|
}
|
|
160
216
|
/**
|
|
@@ -164,7 +220,14 @@ class UserServiceNode {
|
|
|
164
220
|
*/
|
|
165
221
|
searchUsers(request) {
|
|
166
222
|
// Validate request
|
|
167
|
-
(
|
|
223
|
+
const result = this._validator.validate(service_pb_2.SearchUsersRequestSchema, request);
|
|
224
|
+
if (result.kind === "invalid") {
|
|
225
|
+
const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
|
|
226
|
+
throw new Error(`Validation failed: ${violations}`);
|
|
227
|
+
}
|
|
228
|
+
else if (result.kind === "error") {
|
|
229
|
+
throw result.error;
|
|
230
|
+
}
|
|
168
231
|
return this._client.searchUsers(request);
|
|
169
232
|
}
|
|
170
233
|
/**
|
|
@@ -174,7 +237,14 @@ class UserServiceNode {
|
|
|
174
237
|
*/
|
|
175
238
|
createUser(request) {
|
|
176
239
|
// Validate request
|
|
177
|
-
(
|
|
240
|
+
const result = this._validator.validate(service_pb_2.CreateUserRequestSchema, request);
|
|
241
|
+
if (result.kind === "invalid") {
|
|
242
|
+
const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
|
|
243
|
+
throw new Error(`Validation failed: ${violations}`);
|
|
244
|
+
}
|
|
245
|
+
else if (result.kind === "error") {
|
|
246
|
+
throw result.error;
|
|
247
|
+
}
|
|
178
248
|
return this._client.createUser(request);
|
|
179
249
|
}
|
|
180
250
|
/**
|
|
@@ -184,7 +254,14 @@ class UserServiceNode {
|
|
|
184
254
|
*/
|
|
185
255
|
updateUser(request) {
|
|
186
256
|
// Validate request
|
|
187
|
-
(
|
|
257
|
+
const result = this._validator.validate(service_pb_2.UpdateUserRequestSchema, request);
|
|
258
|
+
if (result.kind === "invalid") {
|
|
259
|
+
const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
|
|
260
|
+
throw new Error(`Validation failed: ${violations}`);
|
|
261
|
+
}
|
|
262
|
+
else if (result.kind === "error") {
|
|
263
|
+
throw result.error;
|
|
264
|
+
}
|
|
188
265
|
return this._client.updateUser(request);
|
|
189
266
|
}
|
|
190
267
|
}
|
|
@@ -33,12 +33,20 @@ export type User = Message<"meshtrade.iam.user.v1.User"> & {
|
|
|
33
33
|
* @generated from field: string owner = 2;
|
|
34
34
|
*/
|
|
35
35
|
owner: string;
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* Ownership hiearchy of groups that have access to this resource in the format groups/{group_id}.
|
|
39
|
+
* System set on creation.
|
|
40
|
+
*
|
|
41
|
+
* @generated from field: repeated string owners = 3;
|
|
42
|
+
*/
|
|
43
|
+
owners: string[];
|
|
36
44
|
/**
|
|
37
45
|
*
|
|
38
46
|
* The unique email address of this user.
|
|
39
47
|
* This field is required on creation and must be a valid email format.
|
|
40
48
|
*
|
|
41
|
-
* @generated from field: string email =
|
|
49
|
+
* @generated from field: string email = 4;
|
|
42
50
|
*/
|
|
43
51
|
email: string;
|
|
44
52
|
/**
|
|
@@ -47,7 +55,7 @@ export type User = Message<"meshtrade.iam.user.v1.User"> & {
|
|
|
47
55
|
* prepended by the name of the group in which they have been assigned that role.
|
|
48
56
|
* e.g. groups/{ULIDv2}/roles/{role}, where role is a value of the meshtrade.iam.role.v1.Role enum.
|
|
49
57
|
*
|
|
50
|
-
* @generated from field: repeated string roles =
|
|
58
|
+
* @generated from field: repeated string roles = 5;
|
|
51
59
|
*/
|
|
52
60
|
roles: string[];
|
|
53
61
|
};
|
|
@@ -9,7 +9,7 @@ const validate_pb_1 = require("../../../../buf/validate/validate_pb");
|
|
|
9
9
|
/**
|
|
10
10
|
* Describes the file meshtrade/iam/user/v1/user.proto.
|
|
11
11
|
*/
|
|
12
|
-
exports.file_meshtrade_iam_user_v1_user = (0, codegenv2_1.fileDesc)("
|
|
12
|
+
exports.file_meshtrade_iam_user_v1_user = (0, codegenv2_1.fileDesc)("CiBtZXNodHJhZGUvaWFtL3VzZXIvdjEvdXNlci5wcm90bxIVbWVzaHRyYWRlLmlhbS51c2VyLnYxItsDCgRVc2VyErQBCgRuYW1lGAEgASgJQqUBukihAboBnQEKFG5hbWUuZm9ybWF0Lm9wdGlvbmFsEjJuYW1lIG11c3QgYmUgZW1wdHkgb3IgaW4gdGhlIGZvcm1hdCB1c2Vycy97VUxJRHYyfRpRc2l6ZSh0aGlzKSA9PSAwIHx8IHRoaXMubWF0Y2hlcygnXnVzZXJzL1swMTIzNDU2Nzg5QUJDREVGR0hKS01OUFFSU1RWV1hZWl17MjZ9JCcpEksKBW93bmVyGAIgASgJQjy6SDnIAQFyNDIvXmdyb3Vwcy9bMDEyMzQ1Njc4OUFCQ0RFRkdISktNTlBRUlNUVldYWVpdezI2fSSYASESTgoGb3duZXJzGAMgAygJQj66SDuSATgiNnI0Mi9eZ3JvdXBzL1swMTIzNDU2Nzg5QUJDREVGR0hKS01OUFFSU1RWV1hZWl17MjZ9JJgBIRIZCgVlbWFpbBgEIAEoCUIKukgHyAEBcgJgARJkCgVyb2xlcxgFIAMoCUJVukhSkgFPIk1ySxAvGDAyRV5ncm91cHMvWzAxMjM0NTY3ODlBQkNERUZHSEpLTU5QUVJTVFZXWFlaXXsyNn0vcm9sZXMvWzEtOV1bMC05XXs2LDd9JEJPChxjby5tZXNodHJhZGUuYXBpLmlhbS51c2VyLnYxWi9naXRodWIuY29tL21lc2h0cmFkZS9hcGkvZ28vaWFtL3VzZXIvdjE7dXNlcl92MWIGcHJvdG8z", [validate_pb_1.file_buf_validate_validate]);
|
|
13
13
|
/**
|
|
14
14
|
* Describes the message meshtrade.iam.user.v1.User.
|
|
15
15
|
* Use `create(UserSchema)` to create a new message.
|
|
@@ -41,79 +41,21 @@ export declare function createGroupInterceptor(group: string): Interceptor & {
|
|
|
41
41
|
groupContext: string;
|
|
42
42
|
};
|
|
43
43
|
/**
|
|
44
|
-
* Creates a Connect-ES interceptor that injects API key authentication
|
|
45
|
-
* into API requests by adding `x-api-key` and `x-group` headers.
|
|
46
|
-
*
|
|
47
|
-
* This authentication mode is used for service-to-service communication
|
|
48
|
-
* where a backend service authenticates using an API key and operates
|
|
49
|
-
* within a specific group context.
|
|
50
|
-
*
|
|
51
|
-
* Both the API key and group are required and validated. The group must
|
|
52
|
-
* follow the resource name format: `groups/{ulid}` where {ulid} is a
|
|
53
|
-
* 26-character ULID.
|
|
44
|
+
* Creates a Connect-ES interceptor that injects API key authentication.
|
|
54
45
|
*
|
|
55
46
|
* @param apiKey - The API key for authentication
|
|
56
|
-
* @
|
|
57
|
-
* @
|
|
58
|
-
* @throws {Error} If apiKey is empty or group format is invalid
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* ```typescript
|
|
62
|
-
* const authInterceptor = createApiKeyInterceptor(
|
|
63
|
-
* 'your-api-key',
|
|
64
|
-
* 'groups/01ARZ3NDEKTSV4YWVF8F5BH32'
|
|
65
|
-
* );
|
|
66
|
-
*
|
|
67
|
-
* const transport = createGrpcTransport({
|
|
68
|
-
* baseUrl: 'https://api.example.com',
|
|
69
|
-
* interceptors: [authInterceptor]
|
|
70
|
-
* });
|
|
71
|
-
* ```
|
|
47
|
+
* @returns An interceptor that adds x-api-key header
|
|
48
|
+
* @throws {Error} If apiKey is empty
|
|
72
49
|
*/
|
|
73
|
-
export declare function createApiKeyInterceptor(apiKey: string
|
|
50
|
+
export declare function createApiKeyInterceptor(apiKey: string): Interceptor & {
|
|
74
51
|
apiKeyAuth: true;
|
|
75
|
-
groupContext: string;
|
|
76
52
|
};
|
|
77
53
|
/**
|
|
78
|
-
* Creates a Connect-ES interceptor that injects JWT token authentication
|
|
79
|
-
* into API requests by adding a `Cookie` header with the AccessToken.
|
|
80
|
-
*
|
|
81
|
-
* This authentication mode is used in Next.js backends where the server
|
|
82
|
-
* has access to the user's JWT token from their browser session. The JWT
|
|
83
|
-
* is injected as a cookie so the server can extract it in the same way
|
|
84
|
-
* it would from a browser request.
|
|
85
|
-
*
|
|
86
|
-
* The JWT token is added as: `Cookie: AccessToken=<jwt>`
|
|
87
|
-
*
|
|
88
|
-
* This allows the server-side authentication middleware to extract it as:
|
|
89
|
-
* ```go
|
|
90
|
-
* if cookieHeader := request.Attributes.Request.Http.Headers["cookie"]; cookieHeader != "" {
|
|
91
|
-
* cookies := parseHTTPCookies(cookieHeader)
|
|
92
|
-
* for _, cookie := range cookies {
|
|
93
|
-
* if cookie.Name == "AccessToken" && cookie.Value != "" {
|
|
94
|
-
* authContext.AccessToken = cookie.Value
|
|
95
|
-
* break
|
|
96
|
-
* }
|
|
97
|
-
* }
|
|
98
|
-
* }
|
|
99
|
-
* ```
|
|
54
|
+
* Creates a Connect-ES interceptor that injects JWT token authentication.
|
|
100
55
|
*
|
|
101
56
|
* @param jwtToken - The JWT token from the user's session
|
|
102
|
-
* @returns An interceptor
|
|
57
|
+
* @returns An interceptor that adds AccessToken cookie
|
|
103
58
|
* @throws {Error} If jwtToken is empty
|
|
104
|
-
*
|
|
105
|
-
* @example
|
|
106
|
-
* ```typescript
|
|
107
|
-
* // In a Next.js API route
|
|
108
|
-
* const authInterceptor = createJwtInterceptor(
|
|
109
|
-
* 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
|
|
110
|
-
* );
|
|
111
|
-
*
|
|
112
|
-
* const transport = createGrpcTransport({
|
|
113
|
-
* baseUrl: 'https://api.example.com',
|
|
114
|
-
* interceptors: [authInterceptor]
|
|
115
|
-
* });
|
|
116
|
-
* ```
|
|
117
59
|
*/
|
|
118
60
|
export declare function createJwtInterceptor(jwtToken: string): Interceptor & {
|
|
119
61
|
jwtAuth: true;
|
|
@@ -11,7 +11,6 @@ exports.createGroupInterceptor = createGroupInterceptor;
|
|
|
11
11
|
exports.createApiKeyInterceptor = createApiKeyInterceptor;
|
|
12
12
|
exports.createJwtInterceptor = createJwtInterceptor;
|
|
13
13
|
exports.createLoggingInterceptor = createLoggingInterceptor;
|
|
14
|
-
const validation_1 = require("./validation");
|
|
15
14
|
/**
|
|
16
15
|
* HTTP header names for authentication.
|
|
17
16
|
* Must match the server-side header constants.
|
|
@@ -20,6 +19,15 @@ const API_KEY_HEADER = "x-api-key";
|
|
|
20
19
|
const GROUP_HEADER = "x-group";
|
|
21
20
|
const COOKIE_HEADER = "cookie";
|
|
22
21
|
const ACCESS_TOKEN_COOKIE_NAME = "AccessToken";
|
|
22
|
+
/**
|
|
23
|
+
* Validates if a resource name follows the groups/{ulid} format.
|
|
24
|
+
*
|
|
25
|
+
* @param resourceName - The resource name string to validate
|
|
26
|
+
* @returns true if the resource name is a valid group resource name, false otherwise
|
|
27
|
+
*/
|
|
28
|
+
function isValidGroupResourceName(resourceName) {
|
|
29
|
+
return /^groups\/[0-9A-Z]{26}$/.test(resourceName);
|
|
30
|
+
}
|
|
23
31
|
/**
|
|
24
32
|
* Creates a Connect-ES interceptor that injects operating group context
|
|
25
33
|
* into API requests by adding an `x-group` header.
|
|
@@ -53,15 +61,13 @@ const ACCESS_TOKEN_COOKIE_NAME = "AccessToken";
|
|
|
53
61
|
*/
|
|
54
62
|
function createGroupInterceptor(group) {
|
|
55
63
|
// Validate the group resource name format
|
|
56
|
-
if (!
|
|
64
|
+
if (!isValidGroupResourceName(group)) {
|
|
57
65
|
throw new Error(`Invalid group format: "${group}". Group must be in the format "groups/{ulid}" ` +
|
|
58
66
|
`where {ulid} is a 26-character ULID (e.g., "groups/01ARZ3NDEKTSV4YWVF8F5BH32").`);
|
|
59
67
|
}
|
|
60
68
|
// Create the interceptor function
|
|
61
69
|
const interceptor = (next) => async (req) => {
|
|
62
|
-
|
|
63
|
-
req.header.set("x-group", group);
|
|
64
|
-
// Call the next interceptor in the chain
|
|
70
|
+
req.header.set(GROUP_HEADER, group);
|
|
65
71
|
return await next(req);
|
|
66
72
|
};
|
|
67
73
|
// Add a marker property so we can identify group interceptors
|
|
@@ -69,114 +75,38 @@ function createGroupInterceptor(group) {
|
|
|
69
75
|
return Object.assign(interceptor, { groupContext: group });
|
|
70
76
|
}
|
|
71
77
|
/**
|
|
72
|
-
* Creates a Connect-ES interceptor that injects API key authentication
|
|
73
|
-
* into API requests by adding `x-api-key` and `x-group` headers.
|
|
74
|
-
*
|
|
75
|
-
* This authentication mode is used for service-to-service communication
|
|
76
|
-
* where a backend service authenticates using an API key and operates
|
|
77
|
-
* within a specific group context.
|
|
78
|
-
*
|
|
79
|
-
* Both the API key and group are required and validated. The group must
|
|
80
|
-
* follow the resource name format: `groups/{ulid}` where {ulid} is a
|
|
81
|
-
* 26-character ULID.
|
|
78
|
+
* Creates a Connect-ES interceptor that injects API key authentication.
|
|
82
79
|
*
|
|
83
80
|
* @param apiKey - The API key for authentication
|
|
84
|
-
* @
|
|
85
|
-
* @
|
|
86
|
-
* @throws {Error} If apiKey is empty or group format is invalid
|
|
87
|
-
*
|
|
88
|
-
* @example
|
|
89
|
-
* ```typescript
|
|
90
|
-
* const authInterceptor = createApiKeyInterceptor(
|
|
91
|
-
* 'your-api-key',
|
|
92
|
-
* 'groups/01ARZ3NDEKTSV4YWVF8F5BH32'
|
|
93
|
-
* );
|
|
94
|
-
*
|
|
95
|
-
* const transport = createGrpcTransport({
|
|
96
|
-
* baseUrl: 'https://api.example.com',
|
|
97
|
-
* interceptors: [authInterceptor]
|
|
98
|
-
* });
|
|
99
|
-
* ```
|
|
81
|
+
* @returns An interceptor that adds x-api-key header
|
|
82
|
+
* @throws {Error} If apiKey is empty
|
|
100
83
|
*/
|
|
101
|
-
function createApiKeyInterceptor(apiKey
|
|
102
|
-
// Validate inputs
|
|
84
|
+
function createApiKeyInterceptor(apiKey) {
|
|
103
85
|
if (!apiKey || apiKey.trim() === "") {
|
|
104
86
|
throw new Error("API key cannot be empty");
|
|
105
87
|
}
|
|
106
|
-
if (!(0, validation_1.isValidGroupResourceName)(group)) {
|
|
107
|
-
throw new Error(`Invalid group format: "${group}". Group must be in the format "groups/{ulid}" ` +
|
|
108
|
-
`where {ulid} is a 26-character ULID (e.g., "groups/01ARZ3NDEKTSV4YWVF8F5BH32").`);
|
|
109
|
-
}
|
|
110
|
-
// Create the interceptor function
|
|
111
88
|
const interceptor = (next) => async (req) => {
|
|
112
|
-
// Add authentication headers to the request
|
|
113
89
|
req.header.set(API_KEY_HEADER, apiKey);
|
|
114
|
-
req.header.set(GROUP_HEADER, group);
|
|
115
|
-
// Call the next interceptor in the chain
|
|
116
90
|
return await next(req);
|
|
117
91
|
};
|
|
118
|
-
|
|
119
|
-
return Object.assign(interceptor, {
|
|
120
|
-
apiKeyAuth: true,
|
|
121
|
-
groupContext: group,
|
|
122
|
-
});
|
|
92
|
+
return Object.assign(interceptor, { apiKeyAuth: true });
|
|
123
93
|
}
|
|
124
94
|
/**
|
|
125
|
-
* Creates a Connect-ES interceptor that injects JWT token authentication
|
|
126
|
-
* into API requests by adding a `Cookie` header with the AccessToken.
|
|
127
|
-
*
|
|
128
|
-
* This authentication mode is used in Next.js backends where the server
|
|
129
|
-
* has access to the user's JWT token from their browser session. The JWT
|
|
130
|
-
* is injected as a cookie so the server can extract it in the same way
|
|
131
|
-
* it would from a browser request.
|
|
132
|
-
*
|
|
133
|
-
* The JWT token is added as: `Cookie: AccessToken=<jwt>`
|
|
134
|
-
*
|
|
135
|
-
* This allows the server-side authentication middleware to extract it as:
|
|
136
|
-
* ```go
|
|
137
|
-
* if cookieHeader := request.Attributes.Request.Http.Headers["cookie"]; cookieHeader != "" {
|
|
138
|
-
* cookies := parseHTTPCookies(cookieHeader)
|
|
139
|
-
* for _, cookie := range cookies {
|
|
140
|
-
* if cookie.Name == "AccessToken" && cookie.Value != "" {
|
|
141
|
-
* authContext.AccessToken = cookie.Value
|
|
142
|
-
* break
|
|
143
|
-
* }
|
|
144
|
-
* }
|
|
145
|
-
* }
|
|
146
|
-
* ```
|
|
95
|
+
* Creates a Connect-ES interceptor that injects JWT token authentication.
|
|
147
96
|
*
|
|
148
97
|
* @param jwtToken - The JWT token from the user's session
|
|
149
|
-
* @returns An interceptor
|
|
98
|
+
* @returns An interceptor that adds AccessToken cookie
|
|
150
99
|
* @throws {Error} If jwtToken is empty
|
|
151
|
-
*
|
|
152
|
-
* @example
|
|
153
|
-
* ```typescript
|
|
154
|
-
* // In a Next.js API route
|
|
155
|
-
* const authInterceptor = createJwtInterceptor(
|
|
156
|
-
* 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
|
|
157
|
-
* );
|
|
158
|
-
*
|
|
159
|
-
* const transport = createGrpcTransport({
|
|
160
|
-
* baseUrl: 'https://api.example.com',
|
|
161
|
-
* interceptors: [authInterceptor]
|
|
162
|
-
* });
|
|
163
|
-
* ```
|
|
164
100
|
*/
|
|
165
101
|
function createJwtInterceptor(jwtToken) {
|
|
166
|
-
// Validate input
|
|
167
102
|
if (!jwtToken || jwtToken.trim() === "") {
|
|
168
103
|
throw new Error("JWT token cannot be empty");
|
|
169
104
|
}
|
|
170
|
-
// Create the interceptor function
|
|
171
105
|
const interceptor = (next) => async (req) => {
|
|
172
|
-
// Add JWT as a cookie header
|
|
173
|
-
// Format: "Cookie: AccessToken=<jwt>"
|
|
174
106
|
const cookieValue = `${ACCESS_TOKEN_COOKIE_NAME}=${jwtToken}`;
|
|
175
107
|
req.header.set(COOKIE_HEADER, cookieValue);
|
|
176
|
-
// Call the next interceptor in the chain
|
|
177
108
|
return await next(req);
|
|
178
109
|
};
|
|
179
|
-
// Add marker property for identification
|
|
180
110
|
return Object.assign(interceptor, { jwtAuth: true });
|
|
181
111
|
}
|
|
182
112
|
/**
|
|
@@ -203,7 +133,7 @@ function createLoggingInterceptor() {
|
|
|
203
133
|
headers[key] = value;
|
|
204
134
|
});
|
|
205
135
|
// Log the request
|
|
206
|
-
console.
|
|
136
|
+
console.debug(`[Connect] ${req.method.name} request:`, {
|
|
207
137
|
service: req.service.typeName,
|
|
208
138
|
method: req.method.name,
|
|
209
139
|
headers,
|
|
@@ -212,7 +142,7 @@ function createLoggingInterceptor() {
|
|
|
212
142
|
// Call the next interceptor and get the response
|
|
213
143
|
const response = await next(req);
|
|
214
144
|
// Log successful response
|
|
215
|
-
console.
|
|
145
|
+
console.debug(`[Connect] ${req.method.name} response:`, {
|
|
216
146
|
service: req.service.typeName,
|
|
217
147
|
method: req.method.name,
|
|
218
148
|
status: "success",
|