@meshtrade/api-web 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.
Files changed (44) 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_pb.js +1 -1
  32. package/dist/meshtrade/trading/limit_order/v1/service_web_meshts.d.ts +62 -7
  33. package/dist/meshtrade/trading/limit_order/v1/service_web_meshts.js +151 -33
  34. package/dist/meshtrade/trading/market_order/v1/service_web_meshts.d.ts +62 -7
  35. package/dist/meshtrade/trading/market_order/v1/service_web_meshts.js +102 -26
  36. package/dist/meshtrade/wallet/account/v1/account_pb.d.ts +8 -0
  37. package/dist/meshtrade/wallet/account/v1/account_pb.js +1 -1
  38. package/dist/meshtrade/wallet/account/v1/service_web_meshts.d.ts +62 -7
  39. package/dist/meshtrade/wallet/account/v1/service_web_meshts.js +167 -35
  40. package/package.json +19 -2
  41. package/dist/meshtrade/common/config.d.ts +0 -7
  42. package/dist/meshtrade/common/config.js +0 -9
  43. package/dist/meshtrade/common/validation.d.ts +0 -62
  44. package/dist/meshtrade/common/validation.js +0 -77
@@ -7,28 +7,87 @@ exports.AccountServiceWeb = 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.wallet.account.v1 account 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 AccountServiceWeb(
23
+ * WithServerUrl("http://localhost:10000")
24
+ * );
25
+ * ```
26
+ *
27
+ * 2. **API Key Authentication** (backend services):
28
+ * ```typescript
29
+ * const client = new AccountServiceWeb(
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 AccountServiceWeb(
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 AccountServiceWeb(
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 AccountServiceWeb {
18
60
  /**
19
61
  * Constructs an instance of AccountServiceWeb.
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.AccountService, transport);
@@ -37,26 +96,36 @@ class AccountServiceWeb {
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 {AccountServiceWeb} 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 AccountServiceWeb(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 AccountServiceWeb(...newOpts);
60
129
  }
61
130
  /**
62
131
  * Creates a new account.
@@ -65,7 +134,14 @@ class AccountServiceWeb {
65
134
  */
66
135
  createAccount(request) {
67
136
  // Validate request
68
- (0, validation_1.validateRequest)(request);
137
+ const result = this._validator.validate(service_pb_2.CreateAccountRequestSchema, 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.createAccount(request);
70
146
  }
71
147
  /**
@@ -75,7 +151,14 @@ class AccountServiceWeb {
75
151
  */
76
152
  updateAccount(request) {
77
153
  // Validate request
78
- (0, validation_1.validateRequest)(request);
154
+ const result = this._validator.validate(service_pb_2.UpdateAccountRequestSchema, 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.updateAccount(request);
80
163
  }
81
164
  /**
@@ -85,7 +168,14 @@ class AccountServiceWeb {
85
168
  */
86
169
  openAccount(request) {
87
170
  // Validate request
88
- (0, validation_1.validateRequest)(request);
171
+ const result = this._validator.validate(service_pb_2.OpenAccountRequestSchema, 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.openAccount(request);
90
180
  }
91
181
  /**
@@ -95,7 +185,14 @@ class AccountServiceWeb {
95
185
  */
96
186
  addSignatoriesToAccount(request) {
97
187
  // Validate request
98
- (0, validation_1.validateRequest)(request);
188
+ const result = this._validator.validate(service_pb_2.AddSignatoriesToAccountRequestSchema, 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.addSignatoriesToAccount(request);
100
197
  }
101
198
  /**
@@ -105,7 +202,14 @@ class AccountServiceWeb {
105
202
  */
106
203
  removeSignatoriesFromAccount(request) {
107
204
  // Validate request
108
- (0, validation_1.validateRequest)(request);
205
+ const result = this._validator.validate(service_pb_2.RemoveSignatoriesFromAccountRequestSchema, 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.removeSignatoriesFromAccount(request);
110
214
  }
111
215
  /**
@@ -115,7 +219,14 @@ class AccountServiceWeb {
115
219
  */
116
220
  getAccount(request) {
117
221
  // Validate request
118
- (0, validation_1.validateRequest)(request);
222
+ const result = this._validator.validate(service_pb_2.GetAccountRequestSchema, 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.getAccount(request);
120
231
  }
121
232
  /**
@@ -125,7 +236,14 @@ class AccountServiceWeb {
125
236
  */
126
237
  getAccountByNumber(request) {
127
238
  // Validate request
128
- (0, validation_1.validateRequest)(request);
239
+ const result = this._validator.validate(service_pb_2.GetAccountByNumberRequestSchema, 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.getAccountByNumber(request);
130
248
  }
131
249
  /**
@@ -135,7 +253,14 @@ class AccountServiceWeb {
135
253
  */
136
254
  listAccounts(request) {
137
255
  // Validate request
138
- (0, validation_1.validateRequest)(request);
256
+ const result = this._validator.validate(service_pb_2.ListAccountsRequestSchema, 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.listAccounts(request);
140
265
  }
141
266
  /**
@@ -145,7 +270,14 @@ class AccountServiceWeb {
145
270
  */
146
271
  searchAccounts(request) {
147
272
  // Validate request
148
- (0, validation_1.validateRequest)(request);
273
+ const result = this._validator.validate(service_pb_2.SearchAccountsRequestSchema, request);
274
+ if (result.kind === "invalid") {
275
+ const violations = result.violations.map(v => `${v.field.toString()}: ${v.message}`).join("; ");
276
+ throw new Error(`Validation failed: ${violations}`);
277
+ }
278
+ else if (result.kind === "error") {
279
+ throw result.error;
280
+ }
149
281
  return this._client.searchAccounts(request);
150
282
  }
151
283
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meshtrade/api-web",
3
- "version": "1.30.2",
3
+ "version": "1.32.0",
4
4
  "description": "Mesh Typescript SDK",
5
5
  "author": "Bernard Bussy <bernard@meshtrade.co>",
6
6
  "license": "UNLICENSED",
@@ -81,6 +81,16 @@
81
81
  "require": "./dist/meshtrade/option/v1/index.js",
82
82
  "import": "./dist/meshtrade/option/v1/index.js"
83
83
  },
84
+ "./config": {
85
+ "types": "./dist/meshtrade/config/index.d.ts",
86
+ "require": "./dist/meshtrade/config/index.js",
87
+ "import": "./dist/meshtrade/config/index.js"
88
+ },
89
+ "./interceptors": {
90
+ "types": "./dist/meshtrade/interceptors/index.d.ts",
91
+ "require": "./dist/meshtrade/interceptors/index.js",
92
+ "import": "./dist/meshtrade/interceptors/index.js"
93
+ },
84
94
  "./*": {
85
95
  "types": "./dist/meshtrade/*",
86
96
  "require": "./dist/meshtrade/*",
@@ -128,6 +138,12 @@
128
138
  "option/v1": [
129
139
  "dist/meshtrade/option/v1/index.d.ts"
130
140
  ],
141
+ "config": [
142
+ "dist/meshtrade/config/index.d.ts"
143
+ ],
144
+ "interceptors": [
145
+ "dist/meshtrade/interceptors/index.d.ts"
146
+ ],
131
147
  "*": [
132
148
  "dist/meshtrade/*"
133
149
  ]
@@ -138,6 +154,7 @@
138
154
  ],
139
155
  "dependencies": {
140
156
  "@bufbuild/protobuf": "^2.10.1",
157
+ "@bufbuild/protovalidate": "^1.0.0",
141
158
  "@connectrpc/connect": "^2.1.0",
142
159
  "@connectrpc/connect-web": "^2.1.0",
143
160
  "bignumber.js": "^9.3.0"
@@ -159,7 +176,7 @@
159
176
  },
160
177
  "scripts": {
161
178
  "clean": "rimraf ./dist",
162
- "build:ts": "tsc",
179
+ "build:ts": "tsc --project tsconfig.build.json",
163
180
  "build": "yarn run clean && yarn run build:ts",
164
181
  "lint": "eslint . --ext .ts",
165
182
  "test": "jest"
@@ -1,7 +0,0 @@
1
- export type ConfigOpts = {
2
- apiServerURL?: string;
3
- };
4
- export type Config = {
5
- apiServerURL: string;
6
- };
7
- export declare function getConfigFromOpts(config?: ConfigOpts): Config;
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getConfigFromOpts = getConfigFromOpts;
4
- function getConfigFromOpts(config) {
5
- const apiServerURL = config?.apiServerURL ?? "http://localhost:10000";
6
- return {
7
- apiServerURL,
8
- };
9
- }
@@ -1,62 +0,0 @@
1
- /**
2
- * Generic validation utilities for Meshtrade API resource names and identifiers.
3
- */
4
- /**
5
- * Validates if a string is a valid ULID (Universally Unique Lexicographically Sortable Identifier).
6
- *
7
- * Note: This implementation uses a simplified character set for ULIDs that includes
8
- * all uppercase letters A-Z and digits 0-9, unlike the standard ULID specification
9
- * which excludes certain ambiguous characters (I, L, O, U).
10
- *
11
- * ULIDs in this system are 26-character identifiers that are:
12
- * - Lexicographically sortable
13
- * - Uppercase alphanumeric only
14
- * - Contain timestamp information for natural ordering
15
- *
16
- * @param ulid - The string to validate as a ULID
17
- * @returns true if the string is a valid ULID format, false otherwise
18
- *
19
- * @example
20
- * ```typescript
21
- * isValidULID('01ARZ3NDEKTSV4YWVF8F5BH32'); // true
22
- * isValidULID('invalid'); // false
23
- * isValidULID('01arz3ndektsv4ywvf8f5bh32'); // false (lowercase)
24
- * ```
25
- */
26
- export declare function isValidULID(ulid: string): boolean;
27
- /**
28
- * Validates if a resource name follows the groups/{ulid} format.
29
- *
30
- * Group resource names in the Meshtrade API follow the pattern "groups/{ulid}"
31
- * where {ulid} is a 26-character ULID identifier.
32
- *
33
- * @param resourceName - The resource name string to validate
34
- * @returns true if the resource name is a valid group resource name, false otherwise
35
- *
36
- * @example
37
- * ```typescript
38
- * isValidGroupResourceName('groups/01ARZ3NDEKTSV4YWVF8F5BH32'); // true
39
- * isValidGroupResourceName('groups/invalid'); // false
40
- * isValidGroupResourceName('users/01ARZ3NDEKTSV4YWVF8F5BH32'); // false
41
- * isValidGroupResourceName('01ARZ3NDEKTSV4YWVF8F5BH32'); // false
42
- * ```
43
- */
44
- export declare function isValidGroupResourceName(resourceName: string): boolean;
45
- /**
46
- * Validates a protobuf request message before sending to the server.
47
- *
48
- * This function serves as a client-side validation hook that can be extended
49
- * to include protovalidate integration or other validation logic.
50
- *
51
- * Currently performs basic null/undefined checks. Future enhancements may include
52
- * protovalidate integration for comprehensive message validation.
53
- *
54
- * @param request - The protobuf request message to validate
55
- * @throws {Error} If the request is null or undefined
56
- *
57
- * @example
58
- * ```typescript
59
- * validateRequest(myRequest); // Throws if request is invalid
60
- * ```
61
- */
62
- export declare function validateRequest(request: unknown): void;
@@ -1,77 +0,0 @@
1
- "use strict";
2
- /**
3
- * Generic validation utilities for Meshtrade API resource names and identifiers.
4
- */
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.isValidULID = isValidULID;
7
- exports.isValidGroupResourceName = isValidGroupResourceName;
8
- exports.validateRequest = validateRequest;
9
- /**
10
- * Validates if a string is a valid ULID (Universally Unique Lexicographically Sortable Identifier).
11
- *
12
- * Note: This implementation uses a simplified character set for ULIDs that includes
13
- * all uppercase letters A-Z and digits 0-9, unlike the standard ULID specification
14
- * which excludes certain ambiguous characters (I, L, O, U).
15
- *
16
- * ULIDs in this system are 26-character identifiers that are:
17
- * - Lexicographically sortable
18
- * - Uppercase alphanumeric only
19
- * - Contain timestamp information for natural ordering
20
- *
21
- * @param ulid - The string to validate as a ULID
22
- * @returns true if the string is a valid ULID format, false otherwise
23
- *
24
- * @example
25
- * ```typescript
26
- * isValidULID('01ARZ3NDEKTSV4YWVF8F5BH32'); // true
27
- * isValidULID('invalid'); // false
28
- * isValidULID('01arz3ndektsv4ywvf8f5bh32'); // false (lowercase)
29
- * ```
30
- */
31
- function isValidULID(ulid) {
32
- return /^[0-9A-Z]{26}$/.test(ulid);
33
- }
34
- /**
35
- * Validates if a resource name follows the groups/{ulid} format.
36
- *
37
- * Group resource names in the Meshtrade API follow the pattern "groups/{ulid}"
38
- * where {ulid} is a 26-character ULID identifier.
39
- *
40
- * @param resourceName - The resource name string to validate
41
- * @returns true if the resource name is a valid group resource name, false otherwise
42
- *
43
- * @example
44
- * ```typescript
45
- * isValidGroupResourceName('groups/01ARZ3NDEKTSV4YWVF8F5BH32'); // true
46
- * isValidGroupResourceName('groups/invalid'); // false
47
- * isValidGroupResourceName('users/01ARZ3NDEKTSV4YWVF8F5BH32'); // false
48
- * isValidGroupResourceName('01ARZ3NDEKTSV4YWVF8F5BH32'); // false
49
- * ```
50
- */
51
- function isValidGroupResourceName(resourceName) {
52
- return /^groups\/[0-9A-Z]{26}$/.test(resourceName);
53
- }
54
- /**
55
- * Validates a protobuf request message before sending to the server.
56
- *
57
- * This function serves as a client-side validation hook that can be extended
58
- * to include protovalidate integration or other validation logic.
59
- *
60
- * Currently performs basic null/undefined checks. Future enhancements may include
61
- * protovalidate integration for comprehensive message validation.
62
- *
63
- * @param request - The protobuf request message to validate
64
- * @throws {Error} If the request is null or undefined
65
- *
66
- * @example
67
- * ```typescript
68
- * validateRequest(myRequest); // Throws if request is invalid
69
- * ```
70
- */
71
- function validateRequest(request) {
72
- if (request === null || request === undefined) {
73
- throw new Error("Request cannot be null or undefined");
74
- }
75
- // Future: Integrate protovalidate for comprehensive message validation
76
- // For now, basic validation is sufficient as the server also validates
77
- }