@meshtrade/api-web 1.30.0 → 1.31.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.
Files changed (43) hide show
  1. package/dist/meshtrade/compliance/client/v1/client_pb.d.ts +17 -9
  2. package/dist/meshtrade/compliance/client/v1/client_pb.js +1 -1
  3. package/dist/meshtrade/compliance/client/v1/service_web_meshts.d.ts +62 -7
  4. package/dist/meshtrade/compliance/client/v1/service_web_meshts.js +118 -28
  5. package/dist/meshtrade/config/index.d.ts +160 -0
  6. package/dist/meshtrade/config/index.js +210 -0
  7. package/dist/meshtrade/iam/api_user/v1/api_user_pb.d.ts +12 -4
  8. package/dist/meshtrade/iam/api_user/v1/api_user_pb.js +1 -1
  9. package/dist/meshtrade/iam/api_user/v1/service_web_meshts.d.ts +62 -7
  10. package/dist/meshtrade/iam/api_user/v1/service_web_meshts.js +167 -35
  11. package/dist/meshtrade/iam/group/v1/group_pb.d.ts +8 -0
  12. package/dist/meshtrade/iam/group/v1/group_pb.js +1 -1
  13. package/dist/meshtrade/iam/group/v1/service_web_meshts.d.ts +62 -7
  14. package/dist/meshtrade/iam/group/v1/service_web_meshts.js +134 -30
  15. package/dist/meshtrade/iam/user/v1/service_web_meshts.d.ts +62 -7
  16. package/dist/meshtrade/iam/user/v1/service_web_meshts.js +159 -34
  17. package/dist/meshtrade/iam/user/v1/user_pb.d.ts +10 -2
  18. package/dist/meshtrade/iam/user/v1/user_pb.js +1 -1
  19. package/dist/meshtrade/{common/connectInterceptors.d.ts → interceptors/index.d.ts} +23 -17
  20. package/dist/meshtrade/{common/connectInterceptors.js → interceptors/index.js} +61 -24
  21. package/dist/meshtrade/ledger/transaction/v1/service_web_meshts.d.ts +62 -7
  22. package/dist/meshtrade/ledger/transaction/v1/service_web_meshts.js +110 -27
  23. package/dist/meshtrade/market_data/price/v1/service_web_meshts.d.ts +62 -7
  24. package/dist/meshtrade/market_data/price/v1/service_web_meshts.js +102 -26
  25. package/dist/meshtrade/reporting/account_report/v1/service_web_meshts.d.ts +62 -7
  26. package/dist/meshtrade/reporting/account_report/v1/service_web_meshts.js +110 -27
  27. package/dist/meshtrade/studio/instrument/v1/instrument_pb.d.ts +8 -0
  28. package/dist/meshtrade/studio/instrument/v1/instrument_pb.js +1 -1
  29. package/dist/meshtrade/trading/limit_order/v1/limit_order_pb.d.ts +16 -8
  30. package/dist/meshtrade/trading/limit_order/v1/limit_order_pb.js +1 -1
  31. package/dist/meshtrade/trading/limit_order/v1/service_web_meshts.d.ts +62 -7
  32. package/dist/meshtrade/trading/limit_order/v1/service_web_meshts.js +151 -33
  33. package/dist/meshtrade/trading/market_order/v1/service_web_meshts.d.ts +62 -7
  34. package/dist/meshtrade/trading/market_order/v1/service_web_meshts.js +102 -26
  35. package/dist/meshtrade/wallet/account/v1/account_pb.d.ts +8 -0
  36. package/dist/meshtrade/wallet/account/v1/account_pb.js +1 -1
  37. package/dist/meshtrade/wallet/account/v1/service_web_meshts.d.ts +62 -7
  38. package/dist/meshtrade/wallet/account/v1/service_web_meshts.js +167 -35
  39. package/package.json +19 -2
  40. package/dist/meshtrade/common/config.d.ts +0 -7
  41. package/dist/meshtrade/common/config.js +0 -9
  42. package/dist/meshtrade/common/validation.d.ts +0 -62
  43. package/dist/meshtrade/common/validation.js +0 -77
@@ -7,28 +7,87 @@ exports.UserServiceWeb = void 0;
7
7
  const connect_1 = require("@connectrpc/connect");
8
8
  const connect_web_1 = require("@connectrpc/connect-web");
9
9
  const service_pb_1 = require("./service_pb");
10
- const config_1 = require("../../../common/config");
11
- const validation_1 = require("../../../common/validation");
12
- const connectInterceptors_1 = require("../../../common/connectInterceptors");
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
  * Web client for interacting with the meshtrade.iam.user.v1 user v1 API resource service.
15
- * Uses Connect-ES with gRPC-Web transport for browser-compatible gRPC communication.
16
+ * Uses Connect-ES with gRPC-Web transport for browser-based communication.
17
+ *
18
+ * Supports flexible authentication modes using functional options pattern:
19
+ *
20
+ * 1. **No Authentication** (public APIs):
21
+ * ```typescript
22
+ * const client = new UserServiceWeb(
23
+ * WithServerUrl("http://localhost:10000")
24
+ * );
25
+ * ```
26
+ *
27
+ * 2. **API Key Authentication** (backend services):
28
+ * ```typescript
29
+ * const client = new UserServiceWeb(
30
+ * WithAPIKey("your-api-key"),
31
+ * WithGroup("groups/01ARZ3NDEKTSV4YWVF8F5BH32"),
32
+ * WithServerUrl("https://api.example.com")
33
+ * );
34
+ * ```
35
+ *
36
+ * 3. **JWT Token Authentication** (Next.js frontend with user session):
37
+ * ```typescript
38
+ * const client = new UserServiceWeb(
39
+ * WithJWTAccessToken("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."),
40
+ * WithServerUrl("https://api.example.com")
41
+ * );
42
+ * ```
43
+ *
44
+ * 4. **JWT with Group Context** (user session with specific group):
45
+ * ```typescript
46
+ * const client = new UserServiceWeb(
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)
16
58
  */
17
59
  class UserServiceWeb {
18
60
  /**
19
61
  * Constructs an instance of UserServiceWeb.
20
- * @param {ConfigOpts} [config] - Optional configuration for the client.
21
- * @param {Interceptor[]} [interceptors] - For internal use by `withGroup`.
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
22
70
  */
23
- constructor(config, interceptors) {
24
- this._config = (0, config_1.getConfigFromOpts)(config);
25
- this._interceptors = interceptors || [];
26
- // Create the gRPC-Web transport with interceptors
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));
86
+ }
87
+ // Create the gRPC-Web transport for browser with interceptors
27
88
  const transport = (0, connect_web_1.createGrpcWebTransport)({
28
89
  baseUrl: this._config.apiServerURL,
29
90
  interceptors: this._interceptors,
30
- // Enable credentials (cookies) for cross-origin requests
31
- fetch: (input, init) => globalThis.fetch(input, { ...init, credentials: 'include' }),
32
91
  });
33
92
  // Construct the Connect-ES client
34
93
  this._client = (0, connect_1.createClient)(service_pb_1.UserService, transport);
@@ -37,26 +96,36 @@ class UserServiceWeb {
37
96
  * Returns a new client instance configured to send the specified group
38
97
  * resource name in the request headers for subsequent API calls.
39
98
  *
99
+ * This method creates a new client with the same authentication configuration
100
+ * but with the group context updated to the specified value.
101
+ *
102
+ * **Compatibility**: Works with all authentication modes:
103
+ * - **API key auth**: Creates new client with API key + new group
104
+ * - **JWT auth**: Creates new client with JWT + new group
105
+ * - **No auth**: Creates new client with standalone group interceptor
106
+ *
40
107
  * @param {string} group - The operating group context to inject into the request
41
108
  * in the format `groups/{ulid}` where {ulid} is a 26-character ULID.
42
109
  * Example: 'groups/01ARZ3NDEKTSV4YWVF8F5BH32'
43
110
  * @returns {UserServiceWeb} A new, configured instance of the client.
44
- * @throws {Error} If the group format is invalid (validation occurs in createGroupInterceptor)
111
+ * @throws {Error} If the group format is invalid
45
112
  */
46
113
  withGroup(group) {
47
- // Check if a group interceptor already exists.
48
- // Group interceptors are identified by having a 'groupContext' property
49
- const hasGroupInterceptor = this._interceptors.some((interceptor) => interceptor.groupContext !== undefined);
50
- if (hasGroupInterceptor) {
51
- throw new Error("Attempted to set group context twice. A group has already been set for this client instance.");
52
- }
53
- // Create a new interceptor for the group context
54
- const groupInterceptor = (0, connectInterceptors_1.createGroupInterceptor)(group);
55
- // Return a new client instance with the existing interceptors plus the new one
56
- return new UserServiceWeb(this._config, [
57
- ...this._interceptors,
58
- groupInterceptor,
59
- ]);
114
+ // Build new options array with existing auth and updated group
115
+ const newOpts = [];
116
+ // Add server URL
117
+ newOpts.push((0, config_1.WithServerUrl)(this._config.apiServerURL));
118
+ // Add authentication (preserve existing mode)
119
+ if (this._config.apiKey) {
120
+ newOpts.push((0, config_1.WithAPIKey)(this._config.apiKey));
121
+ }
122
+ else if (this._config.jwtToken) {
123
+ newOpts.push((0, config_1.WithJWTAccessToken)(this._config.jwtToken));
124
+ }
125
+ // Add the new group
126
+ newOpts.push((0, config_1.WithGroup)(group));
127
+ // Return a new client instance with updated configuration
128
+ return new UserServiceWeb(...newOpts);
60
129
  }
61
130
  /**
62
131
  * Performs assignrolestouser operation on user.
@@ -65,7 +134,14 @@ class UserServiceWeb {
65
134
  */
66
135
  assignRolesToUser(request) {
67
136
  // Validate request
68
- (0, validation_1.validateRequest)(request);
137
+ const result = this._validator.validate(service_pb_2.AssignRolesToUserRequestSchema, request);
138
+ if (result.kind === "invalid") {
139
+ const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
140
+ throw new Error(`Validation failed: ${violations}`);
141
+ }
142
+ else if (result.kind === "error") {
143
+ throw result.error;
144
+ }
69
145
  return this._client.assignRolesToUser(request);
70
146
  }
71
147
  /**
@@ -75,7 +151,14 @@ class UserServiceWeb {
75
151
  */
76
152
  revokeRolesFromUser(request) {
77
153
  // Validate request
78
- (0, validation_1.validateRequest)(request);
154
+ const result = this._validator.validate(service_pb_2.RevokeRolesFromUserRequestSchema, request);
155
+ if (result.kind === "invalid") {
156
+ const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
157
+ throw new Error(`Validation failed: ${violations}`);
158
+ }
159
+ else if (result.kind === "error") {
160
+ throw result.error;
161
+ }
79
162
  return this._client.revokeRolesFromUser(request);
80
163
  }
81
164
  /**
@@ -85,7 +168,14 @@ class UserServiceWeb {
85
168
  */
86
169
  getUser(request) {
87
170
  // Validate request
88
- (0, validation_1.validateRequest)(request);
171
+ const result = this._validator.validate(service_pb_2.GetUserRequestSchema, request);
172
+ if (result.kind === "invalid") {
173
+ const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
174
+ throw new Error(`Validation failed: ${violations}`);
175
+ }
176
+ else if (result.kind === "error") {
177
+ throw result.error;
178
+ }
89
179
  return this._client.getUser(request);
90
180
  }
91
181
  /**
@@ -95,7 +185,14 @@ class UserServiceWeb {
95
185
  */
96
186
  getUserByEmail(request) {
97
187
  // Validate request
98
- (0, validation_1.validateRequest)(request);
188
+ const result = this._validator.validate(service_pb_2.GetUserByEmailRequestSchema, request);
189
+ if (result.kind === "invalid") {
190
+ const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
191
+ throw new Error(`Validation failed: ${violations}`);
192
+ }
193
+ else if (result.kind === "error") {
194
+ throw result.error;
195
+ }
99
196
  return this._client.getUserByEmail(request);
100
197
  }
101
198
  /**
@@ -105,7 +202,14 @@ class UserServiceWeb {
105
202
  */
106
203
  listUsers(request) {
107
204
  // Validate request
108
- (0, validation_1.validateRequest)(request);
205
+ const result = this._validator.validate(service_pb_2.ListUsersRequestSchema, request);
206
+ if (result.kind === "invalid") {
207
+ const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
208
+ throw new Error(`Validation failed: ${violations}`);
209
+ }
210
+ else if (result.kind === "error") {
211
+ throw result.error;
212
+ }
109
213
  return this._client.listUsers(request);
110
214
  }
111
215
  /**
@@ -115,7 +219,14 @@ class UserServiceWeb {
115
219
  */
116
220
  searchUsers(request) {
117
221
  // Validate request
118
- (0, validation_1.validateRequest)(request);
222
+ const result = this._validator.validate(service_pb_2.SearchUsersRequestSchema, request);
223
+ if (result.kind === "invalid") {
224
+ const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
225
+ throw new Error(`Validation failed: ${violations}`);
226
+ }
227
+ else if (result.kind === "error") {
228
+ throw result.error;
229
+ }
119
230
  return this._client.searchUsers(request);
120
231
  }
121
232
  /**
@@ -125,7 +236,14 @@ class UserServiceWeb {
125
236
  */
126
237
  createUser(request) {
127
238
  // Validate request
128
- (0, validation_1.validateRequest)(request);
239
+ const result = this._validator.validate(service_pb_2.CreateUserRequestSchema, request);
240
+ if (result.kind === "invalid") {
241
+ const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
242
+ throw new Error(`Validation failed: ${violations}`);
243
+ }
244
+ else if (result.kind === "error") {
245
+ throw result.error;
246
+ }
129
247
  return this._client.createUser(request);
130
248
  }
131
249
  /**
@@ -135,7 +253,14 @@ class UserServiceWeb {
135
253
  */
136
254
  updateUser(request) {
137
255
  // Validate request
138
- (0, validation_1.validateRequest)(request);
256
+ const result = this._validator.validate(service_pb_2.UpdateUserRequestSchema, request);
257
+ if (result.kind === "invalid") {
258
+ const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
259
+ throw new Error(`Validation failed: ${violations}`);
260
+ }
261
+ else if (result.kind === "error") {
262
+ throw result.error;
263
+ }
139
264
  return this._client.updateUser(request);
140
265
  }
141
266
  }
@@ -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 = 3;
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 = 4;
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)("CiBtZXNodHJhZGUvaWFtL3VzZXIvdjEvdXNlci5wcm90bxIVbWVzaHRyYWRlLmlhbS51c2VyLnYxIosDCgRVc2VyErQBCgRuYW1lGAEgASgJQqUBukihAboBnQEKFG5hbWUuZm9ybWF0Lm9wdGlvbmFsEjJuYW1lIG11c3QgYmUgZW1wdHkgb3IgaW4gdGhlIGZvcm1hdCB1c2Vycy97VUxJRHYyfRpRc2l6ZSh0aGlzKSA9PSAwIHx8IHRoaXMubWF0Y2hlcygnXnVzZXJzL1swMTIzNDU2Nzg5QUJDREVGR0hKS01OUFFSU1RWV1hZWl17MjZ9JCcpEksKBW93bmVyGAIgASgJQjy6SDnIAQFyNDIvXmdyb3Vwcy9bMDEyMzQ1Njc4OUFCQ0RFRkdISktNTlBRUlNUVldYWVpdezI2fSSYASESGQoFZW1haWwYAyABKAlCCrpIB8gBAXICYAESZAoFcm9sZXMYBCADKAlCVbpIUpIBTyJNcksQLxgwMkVeZ3JvdXBzL1swMTIzNDU2Nzg5QUJDREVGR0hKS01OUFFSU1RWV1hZWl17MjZ9L3JvbGVzL1sxLTldWzAtOV17Niw3fSRCTwocY28ubWVzaHRyYWRlLmFwaS5pYW0udXNlci52MVovZ2l0aHViLmNvbS9tZXNodHJhZGUvYXBpL2dvL2lhbS91c2VyL3YxO3VzZXJfdjFiBnByb3RvMw", [validate_pb_1.file_buf_validate_validate]);
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.
@@ -1,23 +1,9 @@
1
1
  /**
2
- * Connect-ES interceptors for the Meshtrade API client (Web/Browser).
2
+ * Connect-ES interceptors for the Meshtrade API client.
3
3
  *
4
4
  * Provides interceptor utilities for use with @connectrpc/connect clients,
5
- * including group context injection for multi-tenant operations.
6
- *
7
- * ## Authentication in Browser Environments
8
- *
9
- * The Web SDK uses browser-native cookie-based authentication via the
10
- * `credentials: 'include'` fetch option. This automatically sends HTTP-only
11
- * cookies (like AccessToken) with each request, which is the standard and
12
- * secure authentication pattern for browser applications.
13
- *
14
- * Unlike the Node.js SDK which supports explicit API key and JWT interceptors,
15
- * the Web SDK relies on the browser's automatic cookie handling. This is why
16
- * this module only provides group context and logging interceptors - authentication
17
- * is handled implicitly by the browser's cookie mechanism.
18
- *
19
- * For backend/server-side authentication needs, use the Node.js SDK instead
20
- * (@meshtrade/api-node), which provides explicit API key and JWT token support.
5
+ * including authentication (API key, JWT) and group context injection for
6
+ * multi-tenant operations.
21
7
  */
22
8
  import { Interceptor } from "@connectrpc/connect";
23
9
  /**
@@ -54,6 +40,26 @@ import { Interceptor } from "@connectrpc/connect";
54
40
  export declare function createGroupInterceptor(group: string): Interceptor & {
55
41
  groupContext: string;
56
42
  };
43
+ /**
44
+ * Creates a Connect-ES interceptor that injects API key authentication.
45
+ *
46
+ * @param apiKey - The API key for authentication
47
+ * @returns An interceptor that adds x-api-key header
48
+ * @throws {Error} If apiKey is empty
49
+ */
50
+ export declare function createApiKeyInterceptor(apiKey: string): Interceptor & {
51
+ apiKeyAuth: true;
52
+ };
53
+ /**
54
+ * Creates a Connect-ES interceptor that injects JWT token authentication.
55
+ *
56
+ * @param jwtToken - The JWT token from the user's session
57
+ * @returns An interceptor that adds AccessToken cookie
58
+ * @throws {Error} If jwtToken is empty
59
+ */
60
+ export declare function createJwtInterceptor(jwtToken: string): Interceptor & {
61
+ jwtAuth: true;
62
+ };
57
63
  /**
58
64
  * Creates a logging interceptor that logs all requests and responses.
59
65
  * Useful for debugging and development.
@@ -1,29 +1,33 @@
1
1
  "use strict";
2
2
  /**
3
- * Connect-ES interceptors for the Meshtrade API client (Web/Browser).
3
+ * Connect-ES interceptors for the Meshtrade API client.
4
4
  *
5
5
  * Provides interceptor utilities for use with @connectrpc/connect clients,
6
- * including group context injection for multi-tenant operations.
7
- *
8
- * ## Authentication in Browser Environments
9
- *
10
- * The Web SDK uses browser-native cookie-based authentication via the
11
- * `credentials: 'include'` fetch option. This automatically sends HTTP-only
12
- * cookies (like AccessToken) with each request, which is the standard and
13
- * secure authentication pattern for browser applications.
14
- *
15
- * Unlike the Node.js SDK which supports explicit API key and JWT interceptors,
16
- * the Web SDK relies on the browser's automatic cookie handling. This is why
17
- * this module only provides group context and logging interceptors - authentication
18
- * is handled implicitly by the browser's cookie mechanism.
19
- *
20
- * For backend/server-side authentication needs, use the Node.js SDK instead
21
- * (@meshtrade/api-node), which provides explicit API key and JWT token support.
6
+ * including authentication (API key, JWT) and group context injection for
7
+ * multi-tenant operations.
22
8
  */
23
9
  Object.defineProperty(exports, "__esModule", { value: true });
24
10
  exports.createGroupInterceptor = createGroupInterceptor;
11
+ exports.createApiKeyInterceptor = createApiKeyInterceptor;
12
+ exports.createJwtInterceptor = createJwtInterceptor;
25
13
  exports.createLoggingInterceptor = createLoggingInterceptor;
26
- const validation_1 = require("./validation");
14
+ /**
15
+ * HTTP header names for authentication.
16
+ * Must match the server-side header constants.
17
+ */
18
+ const API_KEY_HEADER = "x-api-key";
19
+ const GROUP_HEADER = "x-group";
20
+ const COOKIE_HEADER = "cookie";
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
+ }
27
31
  /**
28
32
  * Creates a Connect-ES interceptor that injects operating group context
29
33
  * into API requests by adding an `x-group` header.
@@ -57,21 +61,54 @@ const validation_1 = require("./validation");
57
61
  */
58
62
  function createGroupInterceptor(group) {
59
63
  // Validate the group resource name format
60
- if (!(0, validation_1.isValidGroupResourceName)(group)) {
64
+ if (!isValidGroupResourceName(group)) {
61
65
  throw new Error(`Invalid group format: "${group}". Group must be in the format "groups/{ulid}" ` +
62
66
  `where {ulid} is a 26-character ULID (e.g., "groups/01ARZ3NDEKTSV4YWVF8F5BH32").`);
63
67
  }
64
68
  // Create the interceptor function
65
69
  const interceptor = (next) => async (req) => {
66
- // Add the x-group header to the request
67
- req.header.set("x-group", group);
68
- // Call the next interceptor in the chain
70
+ req.header.set(GROUP_HEADER, group);
69
71
  return await next(req);
70
72
  };
71
73
  // Add a marker property so we can identify group interceptors
72
74
  // This is used in the withGroup method to prevent double-setting
73
75
  return Object.assign(interceptor, { groupContext: group });
74
76
  }
77
+ /**
78
+ * Creates a Connect-ES interceptor that injects API key authentication.
79
+ *
80
+ * @param apiKey - The API key for authentication
81
+ * @returns An interceptor that adds x-api-key header
82
+ * @throws {Error} If apiKey is empty
83
+ */
84
+ function createApiKeyInterceptor(apiKey) {
85
+ if (!apiKey || apiKey.trim() === "") {
86
+ throw new Error("API key cannot be empty");
87
+ }
88
+ const interceptor = (next) => async (req) => {
89
+ req.header.set(API_KEY_HEADER, apiKey);
90
+ return await next(req);
91
+ };
92
+ return Object.assign(interceptor, { apiKeyAuth: true });
93
+ }
94
+ /**
95
+ * Creates a Connect-ES interceptor that injects JWT token authentication.
96
+ *
97
+ * @param jwtToken - The JWT token from the user's session
98
+ * @returns An interceptor that adds AccessToken cookie
99
+ * @throws {Error} If jwtToken is empty
100
+ */
101
+ function createJwtInterceptor(jwtToken) {
102
+ if (!jwtToken || jwtToken.trim() === "") {
103
+ throw new Error("JWT token cannot be empty");
104
+ }
105
+ const interceptor = (next) => async (req) => {
106
+ const cookieValue = `${ACCESS_TOKEN_COOKIE_NAME}=${jwtToken}`;
107
+ req.header.set(COOKIE_HEADER, cookieValue);
108
+ return await next(req);
109
+ };
110
+ return Object.assign(interceptor, { jwtAuth: true });
111
+ }
75
112
  /**
76
113
  * Creates a logging interceptor that logs all requests and responses.
77
114
  * Useful for debugging and development.
@@ -96,7 +133,7 @@ function createLoggingInterceptor() {
96
133
  headers[key] = value;
97
134
  });
98
135
  // Log the request
99
- console.log(`[Connect] ${req.method.name} request:`, {
136
+ console.debug(`[Connect] ${req.method.name} request:`, {
100
137
  service: req.service.typeName,
101
138
  method: req.method.name,
102
139
  headers,
@@ -105,7 +142,7 @@ function createLoggingInterceptor() {
105
142
  // Call the next interceptor and get the response
106
143
  const response = await next(req);
107
144
  // Log successful response
108
- console.log(`[Connect] ${req.method.name} response:`, {
145
+ console.debug(`[Connect] ${req.method.name} response:`, {
109
146
  service: req.service.typeName,
110
147
  method: req.method.name,
111
148
  status: "success",
@@ -1,29 +1,84 @@
1
- import { Interceptor } from "@connectrpc/connect";
2
1
  import { GetTransactionStateRequest, GetTransactionStateResponse, MonitorTransactionStateRequest, MonitorTransactionStateResponse } from "./service_pb";
3
- import { ConfigOpts } from "../../../common/config";
2
+ import { ClientOption } from "../../../config";
4
3
  /**
5
4
  * Web client for interacting with the meshtrade.ledger.transaction.v1 transaction v1 API resource service.
6
- * Uses Connect-ES with gRPC-Web transport for browser-compatible gRPC communication.
5
+ * Uses Connect-ES with gRPC-Web transport for browser-based communication.
6
+ *
7
+ * Supports flexible authentication modes using functional options pattern:
8
+ *
9
+ * 1. **No Authentication** (public APIs):
10
+ * ```typescript
11
+ * const client = new TransactionServiceWeb(
12
+ * WithServerUrl("http://localhost:10000")
13
+ * );
14
+ * ```
15
+ *
16
+ * 2. **API Key Authentication** (backend services):
17
+ * ```typescript
18
+ * const client = new TransactionServiceWeb(
19
+ * WithAPIKey("your-api-key"),
20
+ * WithGroup("groups/01ARZ3NDEKTSV4YWVF8F5BH32"),
21
+ * WithServerUrl("https://api.example.com")
22
+ * );
23
+ * ```
24
+ *
25
+ * 3. **JWT Token Authentication** (Next.js frontend with user session):
26
+ * ```typescript
27
+ * const client = new TransactionServiceWeb(
28
+ * WithJWTAccessToken("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."),
29
+ * WithServerUrl("https://api.example.com")
30
+ * );
31
+ * ```
32
+ *
33
+ * 4. **JWT with Group Context** (user session with specific group):
34
+ * ```typescript
35
+ * const client = new TransactionServiceWeb(
36
+ * WithJWTAccessToken("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."),
37
+ * WithGroup("groups/01ARZ3NDEKTSV4YWVF8F5BH32"),
38
+ * WithServerUrl("https://api.example.com")
39
+ * );
40
+ * ```
41
+ *
42
+ * Available options:
43
+ * - `WithAPIKey(key)` - API key authentication (mutually exclusive with JWT)
44
+ * - `WithJWTAccessToken(token)` - JWT authentication (mutually exclusive with API key)
45
+ * - `WithGroup(group)` - Group context (optional, works with both auth modes)
46
+ * - `WithServerUrl(url)` - Custom server URL (optional, defaults to production)
7
47
  */
8
48
  export declare class TransactionServiceWeb {
9
49
  private _client;
10
50
  private readonly _config;
11
51
  private readonly _interceptors;
52
+ private readonly _validator;
12
53
  /**
13
54
  * Constructs an instance of TransactionServiceWeb.
14
- * @param {ConfigOpts} [config] - Optional configuration for the client.
15
- * @param {Interceptor[]} [interceptors] - For internal use by `withGroup`.
55
+ *
56
+ * Uses functional options pattern for flexible configuration:
57
+ * - `WithAPIKey(key)` - API key authentication
58
+ * - `WithJWTAccessToken(token)` - JWT authentication
59
+ * - `WithGroup(group)` - Group context (optional)
60
+ * - `WithServerUrl(url)` - Custom server URL (optional)
61
+ *
62
+ * @param {...ClientOption} opts - Variable number of configuration options
16
63
  */
17
- constructor(config?: ConfigOpts, interceptors?: Interceptor[]);
64
+ constructor(...opts: ClientOption[]);
18
65
  /**
19
66
  * Returns a new client instance configured to send the specified group
20
67
  * resource name in the request headers for subsequent API calls.
21
68
  *
69
+ * This method creates a new client with the same authentication configuration
70
+ * but with the group context updated to the specified value.
71
+ *
72
+ * **Compatibility**: Works with all authentication modes:
73
+ * - **API key auth**: Creates new client with API key + new group
74
+ * - **JWT auth**: Creates new client with JWT + new group
75
+ * - **No auth**: Creates new client with standalone group interceptor
76
+ *
22
77
  * @param {string} group - The operating group context to inject into the request
23
78
  * in the format `groups/{ulid}` where {ulid} is a 26-character ULID.
24
79
  * Example: 'groups/01ARZ3NDEKTSV4YWVF8F5BH32'
25
80
  * @returns {TransactionServiceWeb} A new, configured instance of the client.
26
- * @throws {Error} If the group format is invalid (validation occurs in createGroupInterceptor)
81
+ * @throws {Error} If the group format is invalid
27
82
  */
28
83
  withGroup(group: string): TransactionServiceWeb;
29
84
  /**