@forgecart/sdk 1.0.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/admin-namespace.d.ts +168 -1
- package/dist/admin-namespace.js +442 -9
- package/dist/admin-types.d.ts +433 -4
- package/dist/admin-types.js +2 -1
- package/dist/admin.js +20 -2
- package/dist/index.d.ts +9 -11
- package/dist/index.js +33 -15
- package/dist/shop-namespace.d.ts +3 -1
- package/dist/shop-namespace.js +49 -8
- package/dist/shop-types.d.ts +43 -4
- package/dist/shop-types.js +2 -1
- package/dist/shop.js +20 -2
- package/package.json +10 -5
- package/src/admin-namespace.ts +582 -4
- package/src/admin-types.ts +460 -4
- package/src/index.ts +31 -17
- package/src/shop-namespace.ts +50 -3
- package/src/shop-types.ts +48 -4
package/dist/admin-namespace.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* @forgecart/sdk - Auto-generated TypeScript SDK
|
|
3
4
|
*
|
|
4
5
|
* This file was automatically generated and should not be manually edited.
|
|
5
6
|
* To regenerate, run: npm run codegen:ts
|
|
6
7
|
*
|
|
7
|
-
* Generated at: 2025-12-
|
|
8
|
+
* Generated at: 2025-12-15T07:01:16.361Z
|
|
8
9
|
* Generator version: 1.0.0
|
|
9
10
|
*
|
|
10
11
|
* 🤖 Generated with ForgeCart SDK Generator
|
|
11
12
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.AdminNamespace = exports.AllEvents = exports.CatalogEvents = exports.PaymentEvents = exports.FulfillmentEvents = exports.CustomerEvents = exports.OrderEvents = exports.ProductEvents = void 0;
|
|
15
|
+
const graphql_request_1 = require("graphql-request");
|
|
16
|
+
const graphql_ws_1 = require("graphql-ws");
|
|
14
17
|
const activeAdministratorDocument = `query activeAdministrator {
|
|
15
18
|
activeAdministrator {
|
|
16
19
|
id
|
|
@@ -3375,6 +3378,96 @@ const deleteCustomerNoteDocument = `mutation deleteCustomerNote($id: ID!) {
|
|
|
3375
3378
|
message
|
|
3376
3379
|
}
|
|
3377
3380
|
}`;
|
|
3381
|
+
const deploymentsDocument = `query Deployments {
|
|
3382
|
+
deployments {
|
|
3383
|
+
id
|
|
3384
|
+
type
|
|
3385
|
+
status
|
|
3386
|
+
url
|
|
3387
|
+
instances
|
|
3388
|
+
lastDeployedAt
|
|
3389
|
+
errorMessage
|
|
3390
|
+
}
|
|
3391
|
+
}`;
|
|
3392
|
+
const deploymentDocument = `query Deployment($type: DeploymentType!) {
|
|
3393
|
+
deployment(type: $type) {
|
|
3394
|
+
id
|
|
3395
|
+
type
|
|
3396
|
+
status
|
|
3397
|
+
url
|
|
3398
|
+
instances
|
|
3399
|
+
lastDeployedAt
|
|
3400
|
+
errorMessage
|
|
3401
|
+
}
|
|
3402
|
+
}`;
|
|
3403
|
+
const deploymentEnvDocument = `query DeploymentEnv($type: DeploymentType!) {
|
|
3404
|
+
deploymentEnv(type: $type) {
|
|
3405
|
+
key
|
|
3406
|
+
value
|
|
3407
|
+
}
|
|
3408
|
+
}`;
|
|
3409
|
+
const channelInfoDocument = `query ChannelInfo {
|
|
3410
|
+
channelInfo {
|
|
3411
|
+
id
|
|
3412
|
+
code
|
|
3413
|
+
name
|
|
3414
|
+
domain
|
|
3415
|
+
hasApplication
|
|
3416
|
+
applicationName
|
|
3417
|
+
}
|
|
3418
|
+
}`;
|
|
3419
|
+
const validateChannelTokenDocument = `query ValidateChannelToken {
|
|
3420
|
+
validateChannelToken
|
|
3421
|
+
}`;
|
|
3422
|
+
const createDeploymentDocument = `mutation CreateDeployment($input: CreateDeploymentInput!) {
|
|
3423
|
+
createDeployment(input: $input) {
|
|
3424
|
+
id
|
|
3425
|
+
type
|
|
3426
|
+
status
|
|
3427
|
+
url
|
|
3428
|
+
instances
|
|
3429
|
+
lastDeployedAt
|
|
3430
|
+
errorMessage
|
|
3431
|
+
}
|
|
3432
|
+
}`;
|
|
3433
|
+
const deleteDeploymentDocument = `mutation DeleteDeployment($type: DeploymentType!) {
|
|
3434
|
+
deleteDeployment(type: $type)
|
|
3435
|
+
}`;
|
|
3436
|
+
const scaleDeploymentDocument = `mutation ScaleDeployment($input: ScaleDeploymentInput!) {
|
|
3437
|
+
scaleDeployment(input: $input) {
|
|
3438
|
+
id
|
|
3439
|
+
type
|
|
3440
|
+
status
|
|
3441
|
+
url
|
|
3442
|
+
instances
|
|
3443
|
+
lastDeployedAt
|
|
3444
|
+
errorMessage
|
|
3445
|
+
}
|
|
3446
|
+
}`;
|
|
3447
|
+
const setDeploymentEnvDocument = `mutation SetDeploymentEnv($input: SetEnvInput!) {
|
|
3448
|
+
setDeploymentEnv(input: $input)
|
|
3449
|
+
}`;
|
|
3450
|
+
const unsetDeploymentEnvDocument = `mutation UnsetDeploymentEnv($input: UnsetEnvInput!) {
|
|
3451
|
+
unsetDeploymentEnv(input: $input)
|
|
3452
|
+
}`;
|
|
3453
|
+
const refreshDeploymentStatusDocument = `mutation RefreshDeploymentStatus($type: DeploymentType!) {
|
|
3454
|
+
refreshDeploymentStatus(type: $type) {
|
|
3455
|
+
id
|
|
3456
|
+
type
|
|
3457
|
+
status
|
|
3458
|
+
url
|
|
3459
|
+
instances
|
|
3460
|
+
lastDeployedAt
|
|
3461
|
+
errorMessage
|
|
3462
|
+
}
|
|
3463
|
+
}`;
|
|
3464
|
+
const deploymentLogsDocument = `subscription DeploymentLogs($type: DeploymentType!) {
|
|
3465
|
+
deploymentLogs(type: $type) {
|
|
3466
|
+
timestamp
|
|
3467
|
+
message
|
|
3468
|
+
type
|
|
3469
|
+
}
|
|
3470
|
+
}`;
|
|
3378
3471
|
const entityDuplicatorsDocument = `query entityDuplicators {
|
|
3379
3472
|
entityDuplicators {
|
|
3380
3473
|
code
|
|
@@ -3404,6 +3497,18 @@ const duplicateEntityDocument = `mutation duplicateEntity($input: DuplicateEntit
|
|
|
3404
3497
|
}
|
|
3405
3498
|
}
|
|
3406
3499
|
}`;
|
|
3500
|
+
const entityEventDocument = `subscription entityEvent($categories: [EventCategory!]) {
|
|
3501
|
+
entityEvent(categories: $categories) {
|
|
3502
|
+
channelId
|
|
3503
|
+
eventName
|
|
3504
|
+
eventClass
|
|
3505
|
+
type
|
|
3506
|
+
entityId
|
|
3507
|
+
entity
|
|
3508
|
+
input
|
|
3509
|
+
timestamp
|
|
3510
|
+
}
|
|
3511
|
+
}`;
|
|
3407
3512
|
const facetDocument = `query facet($id: ID!) {
|
|
3408
3513
|
facet(id: $id) {
|
|
3409
3514
|
id
|
|
@@ -6782,9 +6887,29 @@ class BaseGraphQLClient {
|
|
|
6782
6887
|
this.endpoint = config.endpoint || 'https://api.forgecart.com/admin-api';
|
|
6783
6888
|
this.wsEndpoint = config.wsEndpoint || 'wss://api.forgecart.com/admin-api';
|
|
6784
6889
|
this.config = config;
|
|
6785
|
-
//
|
|
6786
|
-
|
|
6890
|
+
// Custom fetch that captures session token from response headers
|
|
6891
|
+
const customFetch = async (url, options) => {
|
|
6892
|
+
const response = await fetch(url, options);
|
|
6893
|
+
// Capture session token from response header
|
|
6894
|
+
const authToken = response.headers.get('forge-auth-token');
|
|
6895
|
+
if (authToken && authToken !== this.authToken) {
|
|
6896
|
+
this.authToken = authToken;
|
|
6897
|
+
// Reconnect WebSocket with new token
|
|
6898
|
+
if (this.wsClient) {
|
|
6899
|
+
this.wsConnected = false;
|
|
6900
|
+
this.wsClient.dispose();
|
|
6901
|
+
this.wsClient = null;
|
|
6902
|
+
this.wsInitializing = null;
|
|
6903
|
+
this.initializeWebSocket();
|
|
6904
|
+
}
|
|
6905
|
+
}
|
|
6906
|
+
return response;
|
|
6907
|
+
};
|
|
6908
|
+
// Initialize HTTP client with custom fetch
|
|
6909
|
+
this.httpClient = new graphql_request_1.GraphQLClient(this.endpoint, {
|
|
6787
6910
|
headers: config.headers || {},
|
|
6911
|
+
credentials: 'include',
|
|
6912
|
+
fetch: customFetch,
|
|
6788
6913
|
});
|
|
6789
6914
|
// Initialize WebSocket connection immediately
|
|
6790
6915
|
this.initializeWebSocket();
|
|
@@ -6878,6 +7003,10 @@ class BaseGraphQLClient {
|
|
|
6878
7003
|
* Connects immediately and tracks connection state
|
|
6879
7004
|
*/
|
|
6880
7005
|
initializeWebSocket() {
|
|
7006
|
+
// Skip WebSocket if httpOnly mode is enabled
|
|
7007
|
+
if (this.config.httpOnly) {
|
|
7008
|
+
return;
|
|
7009
|
+
}
|
|
6881
7010
|
// Prevent multiple simultaneous initializations
|
|
6882
7011
|
if (this.wsClient || this.wsInitializing) {
|
|
6883
7012
|
return;
|
|
@@ -6897,7 +7026,20 @@ class BaseGraphQLClient {
|
|
|
6897
7026
|
keepAlive: 10000, // Send keep-alive pings every 10 seconds
|
|
6898
7027
|
connectionParams: async () => {
|
|
6899
7028
|
try {
|
|
6900
|
-
|
|
7029
|
+
const params = {};
|
|
7030
|
+
// Add session token if available
|
|
7031
|
+
if (this.authToken) {
|
|
7032
|
+
params.Authorization = `bearer ${this.authToken}`;
|
|
7033
|
+
}
|
|
7034
|
+
// Pass all configured headers (including forge-token for channel)
|
|
7035
|
+
if (this.config.headers) {
|
|
7036
|
+
Object.entries(this.config.headers).forEach(([key, value]) => {
|
|
7037
|
+
if (value) {
|
|
7038
|
+
params[key] = value;
|
|
7039
|
+
}
|
|
7040
|
+
});
|
|
7041
|
+
}
|
|
7042
|
+
return params;
|
|
6901
7043
|
}
|
|
6902
7044
|
catch (error) {
|
|
6903
7045
|
console.error('Error in connectionParams:', error);
|
|
@@ -6936,7 +7078,7 @@ class BaseGraphQLClient {
|
|
|
6936
7078
|
},
|
|
6937
7079
|
},
|
|
6938
7080
|
};
|
|
6939
|
-
this.wsClient = createClient(wsOptions);
|
|
7081
|
+
this.wsClient = (0, graphql_ws_1.createClient)(wsOptions);
|
|
6940
7082
|
this.wsInitializing = null;
|
|
6941
7083
|
}
|
|
6942
7084
|
catch (error) {
|
|
@@ -7033,6 +7175,40 @@ class BaseGraphQLClient {
|
|
|
7033
7175
|
}
|
|
7034
7176
|
}
|
|
7035
7177
|
}
|
|
7178
|
+
// Event categories for filtering
|
|
7179
|
+
exports.ProductEvents = [
|
|
7180
|
+
'product.created', 'product.updated', 'product.deleted',
|
|
7181
|
+
'product.variant.created', 'product.variant.updated', 'product.variant.deleted',
|
|
7182
|
+
'product.option.created', 'product.option.updated', 'product.option.deleted',
|
|
7183
|
+
'product.optionGroup.created', 'product.optionGroup.updated', 'product.optionGroup.deleted',
|
|
7184
|
+
'product.variant.price.updated',
|
|
7185
|
+
];
|
|
7186
|
+
exports.OrderEvents = [
|
|
7187
|
+
'order.stateTransition', 'order.placementStateTransition', 'order.line.event',
|
|
7188
|
+
'order.paymentStateTransition', 'order.refundStateTransition',
|
|
7189
|
+
'order.coupon.applied', 'order.coupon.removed',
|
|
7190
|
+
];
|
|
7191
|
+
exports.CustomerEvents = [
|
|
7192
|
+
'customer.created', 'customer.updated', 'customer.deleted',
|
|
7193
|
+
'customer.address.created', 'customer.address.updated', 'customer.address.deleted',
|
|
7194
|
+
'customer.groupChange', 'customer.login', 'customer.loginfail',
|
|
7195
|
+
];
|
|
7196
|
+
exports.FulfillmentEvents = [
|
|
7197
|
+
'fulfillment.created', 'fulfillment.stateTransition',
|
|
7198
|
+
];
|
|
7199
|
+
exports.PaymentEvents = [
|
|
7200
|
+
'payment.stateTransition', 'payment.method.created', 'payment.method.updated', 'payment.method.deleted',
|
|
7201
|
+
];
|
|
7202
|
+
exports.CatalogEvents = [
|
|
7203
|
+
'collection.created', 'collection.updated', 'collection.deleted', 'collection.modification',
|
|
7204
|
+
'facet.created', 'facet.updated', 'facet.deleted',
|
|
7205
|
+
'facetValue.created', 'facetValue.updated', 'facetValue.deleted',
|
|
7206
|
+
'asset.created', 'asset.updated', 'asset.deleted',
|
|
7207
|
+
];
|
|
7208
|
+
exports.AllEvents = [
|
|
7209
|
+
...exports.ProductEvents, ...exports.OrderEvents, ...exports.CustomerEvents,
|
|
7210
|
+
...exports.FulfillmentEvents, ...exports.PaymentEvents, ...exports.CatalogEvents,
|
|
7211
|
+
];
|
|
7036
7212
|
/**
|
|
7037
7213
|
* Administrator operations
|
|
7038
7214
|
*/
|
|
@@ -7072,9 +7248,16 @@ class AdministratorOperations {
|
|
|
7072
7248
|
}
|
|
7073
7249
|
/**
|
|
7074
7250
|
* login mutation
|
|
7251
|
+
* Automatically sets the auth token on successful login
|
|
7075
7252
|
*/
|
|
7076
7253
|
async login(variables) {
|
|
7077
|
-
|
|
7254
|
+
const response = await this.client.request(loginDocument, variables);
|
|
7255
|
+
// Auto-set auth token if login was successful
|
|
7256
|
+
const loginResult = response?.login;
|
|
7257
|
+
if (loginResult && loginResult.__typename === 'CurrentUser' && loginResult.sessionToken) {
|
|
7258
|
+
this.client.setAuthToken(loginResult.sessionToken);
|
|
7259
|
+
}
|
|
7260
|
+
return response;
|
|
7078
7261
|
}
|
|
7079
7262
|
/**
|
|
7080
7263
|
* logout mutation
|
|
@@ -7977,6 +8160,89 @@ class CustomerOperations {
|
|
|
7977
8160
|
return await this.client.request(deleteCustomerNoteDocument, variables);
|
|
7978
8161
|
}
|
|
7979
8162
|
}
|
|
8163
|
+
/**
|
|
8164
|
+
* Deployment operations
|
|
8165
|
+
*/
|
|
8166
|
+
class DeploymentOperations {
|
|
8167
|
+
constructor(client) {
|
|
8168
|
+
this.client = client;
|
|
8169
|
+
}
|
|
8170
|
+
/**
|
|
8171
|
+
* Deployments query
|
|
8172
|
+
*/
|
|
8173
|
+
async deployments() {
|
|
8174
|
+
return await this.client.request(deploymentsDocument);
|
|
8175
|
+
}
|
|
8176
|
+
/**
|
|
8177
|
+
* Deployment query
|
|
8178
|
+
*/
|
|
8179
|
+
async deployment(variables) {
|
|
8180
|
+
return await this.client.request(deploymentDocument, variables);
|
|
8181
|
+
}
|
|
8182
|
+
/**
|
|
8183
|
+
* DeploymentEnv query
|
|
8184
|
+
*/
|
|
8185
|
+
async deploymentEnv(variables) {
|
|
8186
|
+
return await this.client.request(deploymentEnvDocument, variables);
|
|
8187
|
+
}
|
|
8188
|
+
/**
|
|
8189
|
+
* ChannelInfo query
|
|
8190
|
+
*/
|
|
8191
|
+
async channelInfo() {
|
|
8192
|
+
return await this.client.request(channelInfoDocument);
|
|
8193
|
+
}
|
|
8194
|
+
/**
|
|
8195
|
+
* ValidateChannelToken query
|
|
8196
|
+
*/
|
|
8197
|
+
async validateChannelToken() {
|
|
8198
|
+
return await this.client.request(validateChannelTokenDocument);
|
|
8199
|
+
}
|
|
8200
|
+
/**
|
|
8201
|
+
* CreateDeployment mutation
|
|
8202
|
+
*/
|
|
8203
|
+
async createDeployment(variables) {
|
|
8204
|
+
return await this.client.request(createDeploymentDocument, variables);
|
|
8205
|
+
}
|
|
8206
|
+
/**
|
|
8207
|
+
* DeleteDeployment mutation
|
|
8208
|
+
*/
|
|
8209
|
+
async deleteDeployment(variables) {
|
|
8210
|
+
return await this.client.request(deleteDeploymentDocument, variables);
|
|
8211
|
+
}
|
|
8212
|
+
/**
|
|
8213
|
+
* ScaleDeployment mutation
|
|
8214
|
+
*/
|
|
8215
|
+
async scaleDeployment(variables) {
|
|
8216
|
+
return await this.client.request(scaleDeploymentDocument, variables);
|
|
8217
|
+
}
|
|
8218
|
+
/**
|
|
8219
|
+
* SetDeploymentEnv mutation
|
|
8220
|
+
*/
|
|
8221
|
+
async setDeploymentEnv(variables) {
|
|
8222
|
+
return await this.client.request(setDeploymentEnvDocument, variables);
|
|
8223
|
+
}
|
|
8224
|
+
/**
|
|
8225
|
+
* UnsetDeploymentEnv mutation
|
|
8226
|
+
*/
|
|
8227
|
+
async unsetDeploymentEnv(variables) {
|
|
8228
|
+
return await this.client.request(unsetDeploymentEnvDocument, variables);
|
|
8229
|
+
}
|
|
8230
|
+
/**
|
|
8231
|
+
* RefreshDeploymentStatus mutation
|
|
8232
|
+
*/
|
|
8233
|
+
async refreshDeploymentStatus(variables) {
|
|
8234
|
+
return await this.client.request(refreshDeploymentStatusDocument, variables);
|
|
8235
|
+
}
|
|
8236
|
+
/**
|
|
8237
|
+
* DeploymentLogs subscription
|
|
8238
|
+
*/
|
|
8239
|
+
async *deploymentLogs(variables) {
|
|
8240
|
+
const iterator = this.client.subscribe(deploymentLogsDocument, variables);
|
|
8241
|
+
for await (const data of iterator) {
|
|
8242
|
+
yield data;
|
|
8243
|
+
}
|
|
8244
|
+
}
|
|
8245
|
+
}
|
|
7980
8246
|
/**
|
|
7981
8247
|
* EntityDuplication operations
|
|
7982
8248
|
*/
|
|
@@ -7997,6 +8263,23 @@ class EntityDuplicationOperations {
|
|
|
7997
8263
|
return await this.client.request(duplicateEntityDocument, variables);
|
|
7998
8264
|
}
|
|
7999
8265
|
}
|
|
8266
|
+
/**
|
|
8267
|
+
* EntityEvents operations
|
|
8268
|
+
*/
|
|
8269
|
+
class EntityEventsOperations {
|
|
8270
|
+
constructor(client) {
|
|
8271
|
+
this.client = client;
|
|
8272
|
+
}
|
|
8273
|
+
/**
|
|
8274
|
+
* entityEvent subscription
|
|
8275
|
+
*/
|
|
8276
|
+
async *entityEvent(variables) {
|
|
8277
|
+
const iterator = this.client.subscribe(entityEventDocument, variables);
|
|
8278
|
+
for await (const data of iterator) {
|
|
8279
|
+
yield data;
|
|
8280
|
+
}
|
|
8281
|
+
}
|
|
8282
|
+
}
|
|
8000
8283
|
/**
|
|
8001
8284
|
* Facet operations
|
|
8002
8285
|
*/
|
|
@@ -9122,8 +9405,17 @@ class ZoneOperations {
|
|
|
9122
9405
|
* Admin namespace
|
|
9123
9406
|
* Contains categorized operations for admin API
|
|
9124
9407
|
*/
|
|
9125
|
-
|
|
9408
|
+
class AdminNamespace {
|
|
9126
9409
|
constructor(config) {
|
|
9410
|
+
// Event handler registry and state
|
|
9411
|
+
this.eventRegistry = {
|
|
9412
|
+
handlers: new Map(),
|
|
9413
|
+
blockingHandlers: new Map(),
|
|
9414
|
+
};
|
|
9415
|
+
this.eventSubscription = null;
|
|
9416
|
+
this.isListening = false;
|
|
9417
|
+
this.retryCount = 0;
|
|
9418
|
+
this.abortController = null;
|
|
9127
9419
|
this.client = new BaseGraphQLClient(config);
|
|
9128
9420
|
this.administrator = new AdministratorOperations(this.client);
|
|
9129
9421
|
this.asset = new AssetOperations(this.client);
|
|
@@ -9135,7 +9427,9 @@ export class AdminNamespace {
|
|
|
9135
9427
|
this.customFields = new CustomFieldsOperations(this.client);
|
|
9136
9428
|
this.customerGroup = new CustomerGroupOperations(this.client);
|
|
9137
9429
|
this.customer = new CustomerOperations(this.client);
|
|
9430
|
+
this.deployment = new DeploymentOperations(this.client);
|
|
9138
9431
|
this.entityDuplication = new EntityDuplicationOperations(this.client);
|
|
9432
|
+
this.entityEvents = new EntityEventsOperations(this.client);
|
|
9139
9433
|
this.facet = new FacetOperations(this.client);
|
|
9140
9434
|
this.fulfillment = new FulfillmentOperations(this.client);
|
|
9141
9435
|
this.globalSettings = new GlobalSettingsOperations(this.client);
|
|
@@ -9178,4 +9472,143 @@ export class AdminNamespace {
|
|
|
9178
9472
|
dispose() {
|
|
9179
9473
|
this.client.dispose();
|
|
9180
9474
|
}
|
|
9475
|
+
/**
|
|
9476
|
+
* Register a non-blocking event handler
|
|
9477
|
+
* The callback will be called for each matching event without waiting
|
|
9478
|
+
*/
|
|
9479
|
+
registerEventHandler(eventName, callback) {
|
|
9480
|
+
if (!this.eventRegistry.handlers.has(eventName)) {
|
|
9481
|
+
this.eventRegistry.handlers.set(eventName, new Set());
|
|
9482
|
+
}
|
|
9483
|
+
this.eventRegistry.handlers.get(eventName).add(callback);
|
|
9484
|
+
void this.ensureEventListening();
|
|
9485
|
+
return {
|
|
9486
|
+
unsubscribe: () => {
|
|
9487
|
+
this.eventRegistry.handlers.get(eventName)?.delete(callback);
|
|
9488
|
+
},
|
|
9489
|
+
};
|
|
9490
|
+
}
|
|
9491
|
+
/**
|
|
9492
|
+
* Register a blocking event handler
|
|
9493
|
+
* The callback must complete within 1000ms or it will timeout
|
|
9494
|
+
*/
|
|
9495
|
+
registerBlockingEventHandler(eventName, callback) {
|
|
9496
|
+
if (!this.eventRegistry.blockingHandlers.has(eventName)) {
|
|
9497
|
+
this.eventRegistry.blockingHandlers.set(eventName, new Set());
|
|
9498
|
+
}
|
|
9499
|
+
this.eventRegistry.blockingHandlers.get(eventName).add(callback);
|
|
9500
|
+
void this.ensureEventListening();
|
|
9501
|
+
return {
|
|
9502
|
+
unsubscribe: () => {
|
|
9503
|
+
this.eventRegistry.blockingHandlers.get(eventName)?.delete(callback);
|
|
9504
|
+
},
|
|
9505
|
+
};
|
|
9506
|
+
}
|
|
9507
|
+
/**
|
|
9508
|
+
* Start listening to events with retry logic
|
|
9509
|
+
*/
|
|
9510
|
+
async ensureEventListening() {
|
|
9511
|
+
if (this.isListening)
|
|
9512
|
+
return;
|
|
9513
|
+
this.isListening = true;
|
|
9514
|
+
this.retryCount = 0;
|
|
9515
|
+
this.abortController = new AbortController();
|
|
9516
|
+
await this.startSubscription();
|
|
9517
|
+
}
|
|
9518
|
+
async startSubscription() {
|
|
9519
|
+
try {
|
|
9520
|
+
this.eventSubscription = this.client.subscribe(entityEventDocument, {});
|
|
9521
|
+
// Reset retry count on successful connection
|
|
9522
|
+
this.retryCount = 0;
|
|
9523
|
+
// Process events
|
|
9524
|
+
for await (const result of this.eventSubscription) {
|
|
9525
|
+
if (!this.isListening)
|
|
9526
|
+
break;
|
|
9527
|
+
const event = result.entityEvent;
|
|
9528
|
+
await this.dispatchEvent(event);
|
|
9529
|
+
}
|
|
9530
|
+
}
|
|
9531
|
+
catch (error) {
|
|
9532
|
+
if (this.isListening) {
|
|
9533
|
+
console.error('Event subscription error:', error);
|
|
9534
|
+
await this.handleReconnect();
|
|
9535
|
+
}
|
|
9536
|
+
}
|
|
9537
|
+
}
|
|
9538
|
+
async handleReconnect() {
|
|
9539
|
+
const { maxRetries, baseDelayMs, maxDelayMs, backoffMultiplier } = AdminNamespace.RECONNECT_CONFIG;
|
|
9540
|
+
if (this.retryCount >= maxRetries) {
|
|
9541
|
+
this.isListening = false;
|
|
9542
|
+
throw new Error(`Max reconnection attempts (${maxRetries}) exceeded`);
|
|
9543
|
+
}
|
|
9544
|
+
// Calculate delay with exponential backoff
|
|
9545
|
+
const delay = Math.min(baseDelayMs * Math.pow(backoffMultiplier, this.retryCount), maxDelayMs);
|
|
9546
|
+
this.retryCount++;
|
|
9547
|
+
console.log(`Reconnecting in ${delay}ms (attempt ${this.retryCount}/${maxRetries})`);
|
|
9548
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
9549
|
+
await this.startSubscription();
|
|
9550
|
+
}
|
|
9551
|
+
/**
|
|
9552
|
+
* Dispatch event to registered handlers
|
|
9553
|
+
*/
|
|
9554
|
+
async dispatchEvent(event) {
|
|
9555
|
+
const eventName = event.eventName;
|
|
9556
|
+
// Non-blocking handlers (fire-and-forget)
|
|
9557
|
+
const handlers = this.eventRegistry.handlers.get(eventName);
|
|
9558
|
+
if (handlers) {
|
|
9559
|
+
for (const handler of handlers) {
|
|
9560
|
+
try {
|
|
9561
|
+
handler(event);
|
|
9562
|
+
}
|
|
9563
|
+
catch (error) {
|
|
9564
|
+
console.error(`Error in event handler for ${eventName}:`, error);
|
|
9565
|
+
}
|
|
9566
|
+
}
|
|
9567
|
+
}
|
|
9568
|
+
// Blocking handlers (with timeout)
|
|
9569
|
+
const blockingHandlers = this.eventRegistry.blockingHandlers.get(eventName);
|
|
9570
|
+
if (blockingHandlers) {
|
|
9571
|
+
for (const handler of blockingHandlers) {
|
|
9572
|
+
try {
|
|
9573
|
+
await this.executeWithTimeout(handler(event), AdminNamespace.BLOCKING_TIMEOUT_MS, `Blocking handler for ${eventName} exceeded ${AdminNamespace.BLOCKING_TIMEOUT_MS}ms`);
|
|
9574
|
+
}
|
|
9575
|
+
catch (error) {
|
|
9576
|
+
console.error(`Error in blocking event handler for ${eventName}:`, error);
|
|
9577
|
+
throw error; // Re-throw for blocking handlers
|
|
9578
|
+
}
|
|
9579
|
+
}
|
|
9580
|
+
}
|
|
9581
|
+
}
|
|
9582
|
+
/**
|
|
9583
|
+
* Execute promise with timeout
|
|
9584
|
+
*/
|
|
9585
|
+
async executeWithTimeout(promise, timeoutMs, errorMessage) {
|
|
9586
|
+
return Promise.race([
|
|
9587
|
+
promise,
|
|
9588
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(errorMessage)), timeoutMs)),
|
|
9589
|
+
]);
|
|
9590
|
+
}
|
|
9591
|
+
/**
|
|
9592
|
+
* Stop all event listening
|
|
9593
|
+
*/
|
|
9594
|
+
stopEventListening() {
|
|
9595
|
+
this.isListening = false;
|
|
9596
|
+
this.retryCount = 0;
|
|
9597
|
+
if (this.abortController) {
|
|
9598
|
+
this.abortController.abort();
|
|
9599
|
+
this.abortController = null;
|
|
9600
|
+
}
|
|
9601
|
+
this.eventSubscription = null;
|
|
9602
|
+
this.eventRegistry.handlers.clear();
|
|
9603
|
+
this.eventRegistry.blockingHandlers.clear();
|
|
9604
|
+
}
|
|
9181
9605
|
}
|
|
9606
|
+
exports.AdminNamespace = AdminNamespace;
|
|
9607
|
+
// Reconnection configuration
|
|
9608
|
+
AdminNamespace.RECONNECT_CONFIG = {
|
|
9609
|
+
maxRetries: 5,
|
|
9610
|
+
baseDelayMs: 1000,
|
|
9611
|
+
maxDelayMs: 30000,
|
|
9612
|
+
backoffMultiplier: 2,
|
|
9613
|
+
};
|
|
9614
|
+
AdminNamespace.BLOCKING_TIMEOUT_MS = 1000;
|