@forgecart/sdk 1.2.2 → 1.2.5
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/admin-namespace.d.ts +31 -1
- package/dist/admin-namespace.js +94 -17
- package/dist/admin-types.d.ts +7 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/shop-namespace.d.ts +31 -1
- package/dist/shop-namespace.js +90 -13
- package/package.json +1 -1
- package/src/admin-namespace.ts +100 -16
- package/src/admin-types.ts +8 -3
- package/src/index.ts +4 -0
- package/src/shop-namespace.ts +96 -12
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This file was automatically generated and should not be manually edited.
|
|
5
5
|
* To regenerate, run: npm run codegen:ts
|
|
6
6
|
*
|
|
7
|
-
* Generated at: 2025-12-
|
|
7
|
+
* Generated at: 2025-12-17T10:24:29.306Z
|
|
8
8
|
* Generator version: 1.0.0
|
|
9
9
|
*
|
|
10
10
|
* 🤖 Generated with ForgeCart SDK Generator
|
|
@@ -25,6 +25,30 @@ export interface SDKConfig {
|
|
|
25
25
|
webSocketImpl?: unknown;
|
|
26
26
|
/** Use HTTP only, skip WebSocket initialization (default: false) */
|
|
27
27
|
httpOnly?: boolean;
|
|
28
|
+
/** Enable debug logging with request timing (default: false) */
|
|
29
|
+
debug?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* SDK Logger - Cross-platform logging with colors
|
|
33
|
+
* Respects debug flag for log/warn, errors are always visible
|
|
34
|
+
*/
|
|
35
|
+
export declare class SDKLogger {
|
|
36
|
+
private debug;
|
|
37
|
+
private prefix;
|
|
38
|
+
constructor(debug?: boolean);
|
|
39
|
+
private isNode;
|
|
40
|
+
/**
|
|
41
|
+
* Debug log - only outputs when debug: true
|
|
42
|
+
*/
|
|
43
|
+
log(message: string, ...args: unknown[]): void;
|
|
44
|
+
/**
|
|
45
|
+
* Warning log - only outputs when debug: true
|
|
46
|
+
*/
|
|
47
|
+
warn(message: string, ...args: unknown[]): void;
|
|
48
|
+
/**
|
|
49
|
+
* Error log - always outputs (errors should always be visible)
|
|
50
|
+
*/
|
|
51
|
+
error(message: string, ...args: unknown[]): void;
|
|
28
52
|
}
|
|
29
53
|
export type ActiveAdministratorQueryVariables = Types.ActiveAdministratorQueryVariables;
|
|
30
54
|
export type ActiveAdministratorQuery = Types.ActiveAdministratorQuery;
|
|
@@ -989,7 +1013,12 @@ declare class BaseGraphQLClient {
|
|
|
989
1013
|
private endpoint;
|
|
990
1014
|
private wsEndpoint;
|
|
991
1015
|
private config;
|
|
1016
|
+
private logger;
|
|
992
1017
|
constructor(config: SDKConfig);
|
|
1018
|
+
/**
|
|
1019
|
+
* Extract operation name from GraphQL document
|
|
1020
|
+
*/
|
|
1021
|
+
private getOperationName;
|
|
993
1022
|
/**
|
|
994
1023
|
* Execute a GraphQL query or mutation
|
|
995
1024
|
* Uses WebSocket if available, falls back to HTTP
|
|
@@ -2570,6 +2599,7 @@ declare class ZoneOperations {
|
|
|
2570
2599
|
*/
|
|
2571
2600
|
export declare class AdminNamespace {
|
|
2572
2601
|
private client;
|
|
2602
|
+
private logger;
|
|
2573
2603
|
readonly administrator: AdministratorOperations;
|
|
2574
2604
|
readonly asset: AssetOperations;
|
|
2575
2605
|
readonly blog: BlogOperations;
|
package/dist/admin-namespace.js
CHANGED
|
@@ -5,15 +5,66 @@
|
|
|
5
5
|
* This file was automatically generated and should not be manually edited.
|
|
6
6
|
* To regenerate, run: npm run codegen:ts
|
|
7
7
|
*
|
|
8
|
-
* Generated at: 2025-12-
|
|
8
|
+
* Generated at: 2025-12-17T10:24:29.306Z
|
|
9
9
|
* Generator version: 1.0.0
|
|
10
10
|
*
|
|
11
11
|
* 🤖 Generated with ForgeCart SDK Generator
|
|
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;
|
|
14
|
+
exports.AdminNamespace = exports.AllEvents = exports.CatalogEvents = exports.PaymentEvents = exports.FulfillmentEvents = exports.CustomerEvents = exports.OrderEvents = exports.ProductEvents = exports.SDKLogger = void 0;
|
|
15
15
|
const graphql_request_1 = require("graphql-request");
|
|
16
16
|
const graphql_ws_1 = require("graphql-ws");
|
|
17
|
+
/**
|
|
18
|
+
* SDK Logger - Cross-platform logging with colors
|
|
19
|
+
* Respects debug flag for log/warn, errors are always visible
|
|
20
|
+
*/
|
|
21
|
+
class SDKLogger {
|
|
22
|
+
constructor(debug = false) {
|
|
23
|
+
this.prefix = '[ForgeCart SDK]';
|
|
24
|
+
this.debug = debug;
|
|
25
|
+
}
|
|
26
|
+
isNode() {
|
|
27
|
+
return typeof process !== 'undefined' && process.versions?.node != null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Debug log - only outputs when debug: true
|
|
31
|
+
*/
|
|
32
|
+
log(message, ...args) {
|
|
33
|
+
if (!this.debug)
|
|
34
|
+
return;
|
|
35
|
+
if (this.isNode()) {
|
|
36
|
+
console.log(`\x1b[36m${this.prefix}\x1b[0m ${message}`, ...args);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
console.log(`%c${this.prefix}%c ${message}`, 'color: #06b6d4; font-weight: bold', 'color: inherit', ...args);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Warning log - only outputs when debug: true
|
|
44
|
+
*/
|
|
45
|
+
warn(message, ...args) {
|
|
46
|
+
if (!this.debug)
|
|
47
|
+
return;
|
|
48
|
+
if (this.isNode()) {
|
|
49
|
+
console.warn(`\x1b[33m${this.prefix}\x1b[0m ${message}`, ...args);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.warn(`%c${this.prefix}%c ${message}`, 'color: #eab308; font-weight: bold', 'color: inherit', ...args);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Error log - always outputs (errors should always be visible)
|
|
57
|
+
*/
|
|
58
|
+
error(message, ...args) {
|
|
59
|
+
if (this.isNode()) {
|
|
60
|
+
console.error(`\x1b[31m${this.prefix}\x1b[0m ${message}`, ...args);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
console.error(`%c${this.prefix}%c ${message}`, 'color: #ef4444; font-weight: bold', 'color: inherit', ...args);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.SDKLogger = SDKLogger;
|
|
17
68
|
const activeAdministratorDocument = `query activeAdministrator {
|
|
18
69
|
activeAdministrator {
|
|
19
70
|
id
|
|
@@ -6887,6 +6938,7 @@ class BaseGraphQLClient {
|
|
|
6887
6938
|
this.endpoint = config.endpoint || 'https://api.forgecart.com/admin-api';
|
|
6888
6939
|
this.wsEndpoint = config.wsEndpoint || 'wss://api.forgecart.com/admin-api';
|
|
6889
6940
|
this.config = config;
|
|
6941
|
+
this.logger = new SDKLogger(config?.debug ?? false);
|
|
6890
6942
|
// Custom fetch that captures session token from response headers
|
|
6891
6943
|
const customFetch = async (url, options) => {
|
|
6892
6944
|
const response = await fetch(url, options);
|
|
@@ -6914,26 +6966,50 @@ class BaseGraphQLClient {
|
|
|
6914
6966
|
// Initialize WebSocket connection immediately
|
|
6915
6967
|
this.initializeWebSocket();
|
|
6916
6968
|
}
|
|
6969
|
+
/**
|
|
6970
|
+
* Extract operation name from GraphQL document
|
|
6971
|
+
*/
|
|
6972
|
+
getOperationName(document) {
|
|
6973
|
+
const docString = typeof document === 'string' ? document : String(document);
|
|
6974
|
+
const match = docString.match(/(?:query|mutation|subscription)\s+(\w+)/);
|
|
6975
|
+
return match ? match[1] : 'UnknownOperation';
|
|
6976
|
+
}
|
|
6917
6977
|
/**
|
|
6918
6978
|
* Execute a GraphQL query or mutation
|
|
6919
6979
|
* Uses WebSocket if available, falls back to HTTP
|
|
6920
6980
|
*/
|
|
6921
6981
|
async request(document, variables) {
|
|
6982
|
+
const startTime = this.config.debug ? performance.now() : 0;
|
|
6983
|
+
const operationName = this.config.debug ? this.getOperationName(document) : '';
|
|
6984
|
+
let transport = 'HTTP';
|
|
6922
6985
|
// Try WebSocket first if available
|
|
6923
6986
|
if (this.wsClient && this.wsConnected) {
|
|
6924
6987
|
try {
|
|
6925
|
-
|
|
6988
|
+
transport = 'WebSocket';
|
|
6989
|
+
const result = await this.requestViaWebSocket(document, variables);
|
|
6990
|
+
if (this.config.debug) {
|
|
6991
|
+
this.logger.log(`${operationName} (${transport}) - ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
6992
|
+
}
|
|
6993
|
+
return result;
|
|
6926
6994
|
}
|
|
6927
6995
|
catch (wsError) {
|
|
6928
|
-
|
|
6996
|
+
transport = 'WebSocket -> HTTP';
|
|
6997
|
+
this.logger.warn('WebSocket request failed, falling back to HTTP:', wsError);
|
|
6929
6998
|
// Fall through to HTTP
|
|
6930
6999
|
}
|
|
6931
7000
|
}
|
|
6932
7001
|
// Use HTTP as fallback or when WebSocket is not available
|
|
6933
7002
|
try {
|
|
6934
|
-
|
|
7003
|
+
const result = await this.httpClient.request(document, variables);
|
|
7004
|
+
if (this.config.debug) {
|
|
7005
|
+
this.logger.log(`${operationName} (${transport}) - ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
7006
|
+
}
|
|
7007
|
+
return result;
|
|
6935
7008
|
}
|
|
6936
7009
|
catch (error) {
|
|
7010
|
+
if (this.config.debug) {
|
|
7011
|
+
this.logger.log(`${operationName} (${transport}) - FAILED after ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
7012
|
+
}
|
|
6937
7013
|
this.handleError(error);
|
|
6938
7014
|
throw error;
|
|
6939
7015
|
}
|
|
@@ -6974,7 +7050,7 @@ class BaseGraphQLClient {
|
|
|
6974
7050
|
* Handle GraphQL errors
|
|
6975
7051
|
*/
|
|
6976
7052
|
handleError(error) {
|
|
6977
|
-
|
|
7053
|
+
this.logger.error('GraphQL Error:', error);
|
|
6978
7054
|
}
|
|
6979
7055
|
/**
|
|
6980
7056
|
* Get WebSocket implementation for current environment
|
|
@@ -6994,7 +7070,7 @@ class BaseGraphQLClient {
|
|
|
6994
7070
|
return require('ws');
|
|
6995
7071
|
}
|
|
6996
7072
|
catch (e) {
|
|
6997
|
-
|
|
7073
|
+
this.logger.warn('WebSocket not available. Install "ws" package for Node.js support or provide webSocketImpl in config.');
|
|
6998
7074
|
return undefined;
|
|
6999
7075
|
}
|
|
7000
7076
|
}
|
|
@@ -7013,7 +7089,7 @@ class BaseGraphQLClient {
|
|
|
7013
7089
|
}
|
|
7014
7090
|
const WebSocketImpl = this.getWebSocketImpl();
|
|
7015
7091
|
if (!WebSocketImpl) {
|
|
7016
|
-
|
|
7092
|
+
this.logger.warn('WebSocket not available. Will use HTTP fallback only.');
|
|
7017
7093
|
return;
|
|
7018
7094
|
}
|
|
7019
7095
|
this.wsInitializing = new Promise((resolve, reject) => {
|
|
@@ -7042,7 +7118,7 @@ class BaseGraphQLClient {
|
|
|
7042
7118
|
return params;
|
|
7043
7119
|
}
|
|
7044
7120
|
catch (error) {
|
|
7045
|
-
|
|
7121
|
+
this.logger.error('Error in connectionParams:', error);
|
|
7046
7122
|
return {};
|
|
7047
7123
|
}
|
|
7048
7124
|
},
|
|
@@ -7055,7 +7131,7 @@ class BaseGraphQLClient {
|
|
|
7055
7131
|
on: {
|
|
7056
7132
|
connected: () => {
|
|
7057
7133
|
this.wsConnected = true;
|
|
7058
|
-
|
|
7134
|
+
this.logger.log('WebSocket connected');
|
|
7059
7135
|
if (!isResolved) {
|
|
7060
7136
|
isResolved = true;
|
|
7061
7137
|
resolve();
|
|
@@ -7064,13 +7140,13 @@ class BaseGraphQLClient {
|
|
|
7064
7140
|
closed: () => {
|
|
7065
7141
|
this.wsConnected = false;
|
|
7066
7142
|
if (!this.isDisposing) {
|
|
7067
|
-
|
|
7143
|
+
this.logger.log('WebSocket disconnected');
|
|
7068
7144
|
}
|
|
7069
7145
|
},
|
|
7070
7146
|
error: (error) => {
|
|
7071
7147
|
// Suppress errors during disposal - they're expected
|
|
7072
7148
|
if (!this.isDisposing && this.wsConnected) {
|
|
7073
|
-
|
|
7149
|
+
this.logger.error('WebSocket error:', error);
|
|
7074
7150
|
}
|
|
7075
7151
|
// Don't fail the connection on errors - let retry logic handle it
|
|
7076
7152
|
// Only log errors if we're connected (unexpected errors)
|
|
@@ -7082,7 +7158,7 @@ class BaseGraphQLClient {
|
|
|
7082
7158
|
this.wsInitializing = null;
|
|
7083
7159
|
}
|
|
7084
7160
|
catch (error) {
|
|
7085
|
-
|
|
7161
|
+
this.logger.error('Failed to create WebSocket client:', error);
|
|
7086
7162
|
this.wsInitializing = null;
|
|
7087
7163
|
// Resolve anyway to not block - we'll fallback to HTTP
|
|
7088
7164
|
if (!isResolved) {
|
|
@@ -9417,6 +9493,7 @@ class AdminNamespace {
|
|
|
9417
9493
|
this.retryCount = 0;
|
|
9418
9494
|
this.abortController = null;
|
|
9419
9495
|
this.client = new BaseGraphQLClient(config);
|
|
9496
|
+
this.logger = new SDKLogger(config?.debug ?? false);
|
|
9420
9497
|
this.administrator = new AdministratorOperations(this.client);
|
|
9421
9498
|
this.asset = new AssetOperations(this.client);
|
|
9422
9499
|
this.blog = new BlogOperations(this.client);
|
|
@@ -9530,7 +9607,7 @@ class AdminNamespace {
|
|
|
9530
9607
|
}
|
|
9531
9608
|
catch (error) {
|
|
9532
9609
|
if (this.isListening) {
|
|
9533
|
-
|
|
9610
|
+
this.logger.error('Event subscription error:', error);
|
|
9534
9611
|
await this.handleReconnect();
|
|
9535
9612
|
}
|
|
9536
9613
|
}
|
|
@@ -9544,7 +9621,7 @@ class AdminNamespace {
|
|
|
9544
9621
|
// Calculate delay with exponential backoff
|
|
9545
9622
|
const delay = Math.min(baseDelayMs * Math.pow(backoffMultiplier, this.retryCount), maxDelayMs);
|
|
9546
9623
|
this.retryCount++;
|
|
9547
|
-
|
|
9624
|
+
this.logger.log(`Reconnecting in ${delay}ms (attempt ${this.retryCount}/${maxRetries})`);
|
|
9548
9625
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
9549
9626
|
await this.startSubscription();
|
|
9550
9627
|
}
|
|
@@ -9561,7 +9638,7 @@ class AdminNamespace {
|
|
|
9561
9638
|
handler(event);
|
|
9562
9639
|
}
|
|
9563
9640
|
catch (error) {
|
|
9564
|
-
|
|
9641
|
+
this.logger.error(`Error in event handler for ${eventName}:`, error);
|
|
9565
9642
|
}
|
|
9566
9643
|
}
|
|
9567
9644
|
}
|
|
@@ -9573,7 +9650,7 @@ class AdminNamespace {
|
|
|
9573
9650
|
await this.executeWithTimeout(handler(event), AdminNamespace.BLOCKING_TIMEOUT_MS, `Blocking handler for ${eventName} exceeded ${AdminNamespace.BLOCKING_TIMEOUT_MS}ms`);
|
|
9574
9651
|
}
|
|
9575
9652
|
catch (error) {
|
|
9576
|
-
|
|
9653
|
+
this.logger.error(`Error in blocking event handler for ${eventName}:`, error);
|
|
9577
9654
|
throw error; // Re-throw for blocking handlers
|
|
9578
9655
|
}
|
|
9579
9656
|
}
|
package/dist/admin-types.d.ts
CHANGED
|
@@ -973,6 +973,7 @@ export type CreateCustomerInput = {
|
|
|
973
973
|
};
|
|
974
974
|
export type CreateCustomerResult = Customer | EmailAddressConflictError;
|
|
975
975
|
export type CreateDeploymentInput = {
|
|
976
|
+
envVars?: InputMaybe<Array<EnvVarInput>>;
|
|
976
977
|
type: DeploymentType;
|
|
977
978
|
};
|
|
978
979
|
export type CreateFacetInput = {
|
|
@@ -1900,6 +1901,10 @@ export type EntityEventPayload = {
|
|
|
1900
1901
|
type: Scalars['String']['output'];
|
|
1901
1902
|
};
|
|
1902
1903
|
export type EntityEventType = 'assigned' | 'created' | 'deleted' | 'removed' | 'updated';
|
|
1904
|
+
export type EnvVarInput = {
|
|
1905
|
+
key: Scalars['String']['input'];
|
|
1906
|
+
value: Scalars['String']['input'];
|
|
1907
|
+
};
|
|
1903
1908
|
export type ErrorCode = 'ALREADY_REFUNDED_ERROR' | 'CANCEL_ACTIVE_ORDER_ERROR' | 'CANCEL_PAYMENT_ERROR' | 'CHANNEL_DEFAULT_LANGUAGE_ERROR' | 'COUPON_CODE_EXPIRED_ERROR' | 'COUPON_CODE_INVALID_ERROR' | 'COUPON_CODE_LIMIT_ERROR' | 'CREATE_FULFILLMENT_ERROR' | 'DUPLICATE_ENTITY_ERROR' | 'EMAIL_ADDRESS_CONFLICT_ERROR' | 'EMPTY_ORDER_LINE_SELECTION_ERROR' | 'FACET_IN_USE_ERROR' | 'FULFILLMENT_STATE_TRANSITION_ERROR' | 'GUEST_CHECKOUT_ERROR' | 'INELIGIBLE_SHIPPING_METHOD_ERROR' | 'INSUFFICIENT_STOCK_ERROR' | 'INSUFFICIENT_STOCK_ON_HAND_ERROR' | 'INVALID_CREDENTIALS_ERROR' | 'INVALID_FULFILLMENT_HANDLER_ERROR' | 'ITEMS_ALREADY_FULFILLED_ERROR' | 'LANGUAGE_NOT_AVAILABLE_ERROR' | 'MANUAL_PAYMENT_STATE_ERROR' | 'MIME_TYPE_ERROR' | 'MISSING_CONDITIONS_ERROR' | 'MULTIPLE_ORDER_ERROR' | 'NATIVE_AUTH_STRATEGY_ERROR' | 'NEGATIVE_QUANTITY_ERROR' | 'NOTHING_TO_REFUND_ERROR' | 'NO_ACTIVE_ORDER_ERROR' | 'NO_CHANGES_SPECIFIED_ERROR' | 'ORDER_INTERCEPTOR_ERROR' | 'ORDER_LIMIT_ERROR' | 'ORDER_MODIFICATION_ERROR' | 'ORDER_MODIFICATION_STATE_ERROR' | 'ORDER_STATE_TRANSITION_ERROR' | 'PAYMENT_METHOD_MISSING_ERROR' | 'PAYMENT_ORDER_MISMATCH_ERROR' | 'PAYMENT_STATE_TRANSITION_ERROR' | 'PRODUCT_OPTION_IN_USE_ERROR' | 'QUANTITY_TOO_GREAT_ERROR' | 'REFUND_AMOUNT_ERROR' | 'REFUND_ORDER_STATE_ERROR' | 'REFUND_PAYMENT_ID_MISSING_ERROR' | 'REFUND_STATE_TRANSITION_ERROR' | 'SETTLE_PAYMENT_ERROR' | 'UNKNOWN_ERROR';
|
|
1904
1909
|
export type ErrorResult = {
|
|
1905
1910
|
errorCode: ErrorCode;
|
|
@@ -6185,9 +6190,8 @@ export type SessionInput = {
|
|
|
6185
6190
|
};
|
|
6186
6191
|
export type SetCustomerForDraftOrderResult = EmailAddressConflictError | Order;
|
|
6187
6192
|
export type SetEnvInput = {
|
|
6188
|
-
|
|
6193
|
+
envVars: Array<EnvVarInput>;
|
|
6189
6194
|
type: DeploymentType;
|
|
6190
|
-
value: Scalars['String']['input'];
|
|
6191
6195
|
};
|
|
6192
6196
|
export type SetOrderCustomerInput = {
|
|
6193
6197
|
customerId: Scalars['ID']['input'];
|
|
@@ -6783,7 +6787,7 @@ export type TransitionFulfillmentToStateResult = Fulfillment | FulfillmentStateT
|
|
|
6783
6787
|
export type TransitionOrderToStateResult = Order | OrderStateTransitionError;
|
|
6784
6788
|
export type TransitionPaymentToStateResult = Payment | PaymentStateTransitionError;
|
|
6785
6789
|
export type UnsetEnvInput = {
|
|
6786
|
-
|
|
6790
|
+
keys: Array<Scalars['String']['input']>;
|
|
6787
6791
|
type: DeploymentType;
|
|
6788
6792
|
};
|
|
6789
6793
|
export type UpdateActiveAdministratorInput = {
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export interface ForgeCartSDKConfig {
|
|
|
18
18
|
token: string;
|
|
19
19
|
/** Use HTTP only, skip WebSocket initialization (default: false) */
|
|
20
20
|
httpOnly?: boolean;
|
|
21
|
+
/** Enable debug logging with request timing (default: false) */
|
|
22
|
+
debug?: boolean;
|
|
21
23
|
/** Custom HTTP headers */
|
|
22
24
|
headers?: Record<string, string>;
|
|
23
25
|
/** Custom WebSocket implementation (optional, auto-detected if not provided) */
|
package/dist/index.js
CHANGED
|
@@ -52,6 +52,7 @@ class ForgeCartSDK {
|
|
|
52
52
|
headers,
|
|
53
53
|
webSocketImpl: config.webSocketImpl,
|
|
54
54
|
httpOnly: config.httpOnly,
|
|
55
|
+
debug: config.debug,
|
|
55
56
|
};
|
|
56
57
|
this.admin = new admin_js_1.AdminNamespace(adminConfig);
|
|
57
58
|
const shopConfig = {
|
|
@@ -60,6 +61,7 @@ class ForgeCartSDK {
|
|
|
60
61
|
headers,
|
|
61
62
|
webSocketImpl: config.webSocketImpl,
|
|
62
63
|
httpOnly: config.httpOnly,
|
|
64
|
+
debug: config.debug,
|
|
63
65
|
};
|
|
64
66
|
this.shop = new shop_js_1.ShopNamespace(shopConfig);
|
|
65
67
|
}
|
package/dist/shop-namespace.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This file was automatically generated and should not be manually edited.
|
|
5
5
|
* To regenerate, run: npm run codegen:ts
|
|
6
6
|
*
|
|
7
|
-
* Generated at: 2025-12-
|
|
7
|
+
* Generated at: 2025-12-17T10:24:29.175Z
|
|
8
8
|
* Generator version: 1.0.0
|
|
9
9
|
*
|
|
10
10
|
* 🤖 Generated with ForgeCart SDK Generator
|
|
@@ -25,6 +25,30 @@ export interface SDKConfig {
|
|
|
25
25
|
webSocketImpl?: unknown;
|
|
26
26
|
/** Use HTTP only, skip WebSocket initialization (default: false) */
|
|
27
27
|
httpOnly?: boolean;
|
|
28
|
+
/** Enable debug logging with request timing (default: false) */
|
|
29
|
+
debug?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* SDK Logger - Cross-platform logging with colors
|
|
33
|
+
* Respects debug flag for log/warn, errors are always visible
|
|
34
|
+
*/
|
|
35
|
+
export declare class SDKLogger {
|
|
36
|
+
private debug;
|
|
37
|
+
private prefix;
|
|
38
|
+
constructor(debug?: boolean);
|
|
39
|
+
private isNode;
|
|
40
|
+
/**
|
|
41
|
+
* Debug log - only outputs when debug: true
|
|
42
|
+
*/
|
|
43
|
+
log(message: string, ...args: unknown[]): void;
|
|
44
|
+
/**
|
|
45
|
+
* Warning log - only outputs when debug: true
|
|
46
|
+
*/
|
|
47
|
+
warn(message: string, ...args: unknown[]): void;
|
|
48
|
+
/**
|
|
49
|
+
* Error log - always outputs (errors should always be visible)
|
|
50
|
+
*/
|
|
51
|
+
error(message: string, ...args: unknown[]): void;
|
|
28
52
|
}
|
|
29
53
|
export type AssetQueryVariables = Types.AssetQueryVariables;
|
|
30
54
|
export type AssetQuery = Types.AssetQuery;
|
|
@@ -245,7 +269,12 @@ declare class BaseGraphQLClient {
|
|
|
245
269
|
private endpoint;
|
|
246
270
|
private wsEndpoint;
|
|
247
271
|
private config;
|
|
272
|
+
private logger;
|
|
248
273
|
constructor(config: SDKConfig);
|
|
274
|
+
/**
|
|
275
|
+
* Extract operation name from GraphQL document
|
|
276
|
+
*/
|
|
277
|
+
private getOperationName;
|
|
249
278
|
/**
|
|
250
279
|
* Execute a GraphQL query or mutation
|
|
251
280
|
* Uses WebSocket if available, falls back to HTTP
|
|
@@ -657,6 +686,7 @@ declare class SearchOperations {
|
|
|
657
686
|
*/
|
|
658
687
|
export declare class ShopNamespace {
|
|
659
688
|
private client;
|
|
689
|
+
private logger;
|
|
660
690
|
readonly asset: AssetOperations;
|
|
661
691
|
readonly auth: AuthOperations;
|
|
662
692
|
readonly blog: BlogOperations;
|
package/dist/shop-namespace.js
CHANGED
|
@@ -5,15 +5,66 @@
|
|
|
5
5
|
* This file was automatically generated and should not be manually edited.
|
|
6
6
|
* To regenerate, run: npm run codegen:ts
|
|
7
7
|
*
|
|
8
|
-
* Generated at: 2025-12-
|
|
8
|
+
* Generated at: 2025-12-17T10:24:29.175Z
|
|
9
9
|
* Generator version: 1.0.0
|
|
10
10
|
*
|
|
11
11
|
* 🤖 Generated with ForgeCart SDK Generator
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.ShopNamespace = void 0;
|
|
14
|
+
exports.ShopNamespace = exports.SDKLogger = void 0;
|
|
15
15
|
const graphql_request_1 = require("graphql-request");
|
|
16
16
|
const graphql_ws_1 = require("graphql-ws");
|
|
17
|
+
/**
|
|
18
|
+
* SDK Logger - Cross-platform logging with colors
|
|
19
|
+
* Respects debug flag for log/warn, errors are always visible
|
|
20
|
+
*/
|
|
21
|
+
class SDKLogger {
|
|
22
|
+
constructor(debug = false) {
|
|
23
|
+
this.prefix = '[ForgeCart SDK]';
|
|
24
|
+
this.debug = debug;
|
|
25
|
+
}
|
|
26
|
+
isNode() {
|
|
27
|
+
return typeof process !== 'undefined' && process.versions?.node != null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Debug log - only outputs when debug: true
|
|
31
|
+
*/
|
|
32
|
+
log(message, ...args) {
|
|
33
|
+
if (!this.debug)
|
|
34
|
+
return;
|
|
35
|
+
if (this.isNode()) {
|
|
36
|
+
console.log(`\x1b[36m${this.prefix}\x1b[0m ${message}`, ...args);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
console.log(`%c${this.prefix}%c ${message}`, 'color: #06b6d4; font-weight: bold', 'color: inherit', ...args);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Warning log - only outputs when debug: true
|
|
44
|
+
*/
|
|
45
|
+
warn(message, ...args) {
|
|
46
|
+
if (!this.debug)
|
|
47
|
+
return;
|
|
48
|
+
if (this.isNode()) {
|
|
49
|
+
console.warn(`\x1b[33m${this.prefix}\x1b[0m ${message}`, ...args);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
console.warn(`%c${this.prefix}%c ${message}`, 'color: #eab308; font-weight: bold', 'color: inherit', ...args);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Error log - always outputs (errors should always be visible)
|
|
57
|
+
*/
|
|
58
|
+
error(message, ...args) {
|
|
59
|
+
if (this.isNode()) {
|
|
60
|
+
console.error(`\x1b[31m${this.prefix}\x1b[0m ${message}`, ...args);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
console.error(`%c${this.prefix}%c ${message}`, 'color: #ef4444; font-weight: bold', 'color: inherit', ...args);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.SDKLogger = SDKLogger;
|
|
17
68
|
const assetDocument = `query asset($id: ID!) {
|
|
18
69
|
asset(id: $id) {
|
|
19
70
|
id
|
|
@@ -2203,6 +2254,7 @@ class BaseGraphQLClient {
|
|
|
2203
2254
|
this.endpoint = config.endpoint || 'https://api.forgecart.com/shop-api';
|
|
2204
2255
|
this.wsEndpoint = config.wsEndpoint || 'wss://api.forgecart.com/shop-api';
|
|
2205
2256
|
this.config = config;
|
|
2257
|
+
this.logger = new SDKLogger(config?.debug ?? false);
|
|
2206
2258
|
// Custom fetch that captures session token from response headers
|
|
2207
2259
|
const customFetch = async (url, options) => {
|
|
2208
2260
|
const response = await fetch(url, options);
|
|
@@ -2230,26 +2282,50 @@ class BaseGraphQLClient {
|
|
|
2230
2282
|
// Initialize WebSocket connection immediately
|
|
2231
2283
|
this.initializeWebSocket();
|
|
2232
2284
|
}
|
|
2285
|
+
/**
|
|
2286
|
+
* Extract operation name from GraphQL document
|
|
2287
|
+
*/
|
|
2288
|
+
getOperationName(document) {
|
|
2289
|
+
const docString = typeof document === 'string' ? document : String(document);
|
|
2290
|
+
const match = docString.match(/(?:query|mutation|subscription)\s+(\w+)/);
|
|
2291
|
+
return match ? match[1] : 'UnknownOperation';
|
|
2292
|
+
}
|
|
2233
2293
|
/**
|
|
2234
2294
|
* Execute a GraphQL query or mutation
|
|
2235
2295
|
* Uses WebSocket if available, falls back to HTTP
|
|
2236
2296
|
*/
|
|
2237
2297
|
async request(document, variables) {
|
|
2298
|
+
const startTime = this.config.debug ? performance.now() : 0;
|
|
2299
|
+
const operationName = this.config.debug ? this.getOperationName(document) : '';
|
|
2300
|
+
let transport = 'HTTP';
|
|
2238
2301
|
// Try WebSocket first if available
|
|
2239
2302
|
if (this.wsClient && this.wsConnected) {
|
|
2240
2303
|
try {
|
|
2241
|
-
|
|
2304
|
+
transport = 'WebSocket';
|
|
2305
|
+
const result = await this.requestViaWebSocket(document, variables);
|
|
2306
|
+
if (this.config.debug) {
|
|
2307
|
+
this.logger.log(`${operationName} (${transport}) - ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
2308
|
+
}
|
|
2309
|
+
return result;
|
|
2242
2310
|
}
|
|
2243
2311
|
catch (wsError) {
|
|
2244
|
-
|
|
2312
|
+
transport = 'WebSocket -> HTTP';
|
|
2313
|
+
this.logger.warn('WebSocket request failed, falling back to HTTP:', wsError);
|
|
2245
2314
|
// Fall through to HTTP
|
|
2246
2315
|
}
|
|
2247
2316
|
}
|
|
2248
2317
|
// Use HTTP as fallback or when WebSocket is not available
|
|
2249
2318
|
try {
|
|
2250
|
-
|
|
2319
|
+
const result = await this.httpClient.request(document, variables);
|
|
2320
|
+
if (this.config.debug) {
|
|
2321
|
+
this.logger.log(`${operationName} (${transport}) - ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
2322
|
+
}
|
|
2323
|
+
return result;
|
|
2251
2324
|
}
|
|
2252
2325
|
catch (error) {
|
|
2326
|
+
if (this.config.debug) {
|
|
2327
|
+
this.logger.log(`${operationName} (${transport}) - FAILED after ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
2328
|
+
}
|
|
2253
2329
|
this.handleError(error);
|
|
2254
2330
|
throw error;
|
|
2255
2331
|
}
|
|
@@ -2290,7 +2366,7 @@ class BaseGraphQLClient {
|
|
|
2290
2366
|
* Handle GraphQL errors
|
|
2291
2367
|
*/
|
|
2292
2368
|
handleError(error) {
|
|
2293
|
-
|
|
2369
|
+
this.logger.error('GraphQL Error:', error);
|
|
2294
2370
|
}
|
|
2295
2371
|
/**
|
|
2296
2372
|
* Get WebSocket implementation for current environment
|
|
@@ -2310,7 +2386,7 @@ class BaseGraphQLClient {
|
|
|
2310
2386
|
return require('ws');
|
|
2311
2387
|
}
|
|
2312
2388
|
catch (e) {
|
|
2313
|
-
|
|
2389
|
+
this.logger.warn('WebSocket not available. Install "ws" package for Node.js support or provide webSocketImpl in config.');
|
|
2314
2390
|
return undefined;
|
|
2315
2391
|
}
|
|
2316
2392
|
}
|
|
@@ -2329,7 +2405,7 @@ class BaseGraphQLClient {
|
|
|
2329
2405
|
}
|
|
2330
2406
|
const WebSocketImpl = this.getWebSocketImpl();
|
|
2331
2407
|
if (!WebSocketImpl) {
|
|
2332
|
-
|
|
2408
|
+
this.logger.warn('WebSocket not available. Will use HTTP fallback only.');
|
|
2333
2409
|
return;
|
|
2334
2410
|
}
|
|
2335
2411
|
this.wsInitializing = new Promise((resolve, reject) => {
|
|
@@ -2358,7 +2434,7 @@ class BaseGraphQLClient {
|
|
|
2358
2434
|
return params;
|
|
2359
2435
|
}
|
|
2360
2436
|
catch (error) {
|
|
2361
|
-
|
|
2437
|
+
this.logger.error('Error in connectionParams:', error);
|
|
2362
2438
|
return {};
|
|
2363
2439
|
}
|
|
2364
2440
|
},
|
|
@@ -2371,7 +2447,7 @@ class BaseGraphQLClient {
|
|
|
2371
2447
|
on: {
|
|
2372
2448
|
connected: () => {
|
|
2373
2449
|
this.wsConnected = true;
|
|
2374
|
-
|
|
2450
|
+
this.logger.log('WebSocket connected');
|
|
2375
2451
|
if (!isResolved) {
|
|
2376
2452
|
isResolved = true;
|
|
2377
2453
|
resolve();
|
|
@@ -2380,13 +2456,13 @@ class BaseGraphQLClient {
|
|
|
2380
2456
|
closed: () => {
|
|
2381
2457
|
this.wsConnected = false;
|
|
2382
2458
|
if (!this.isDisposing) {
|
|
2383
|
-
|
|
2459
|
+
this.logger.log('WebSocket disconnected');
|
|
2384
2460
|
}
|
|
2385
2461
|
},
|
|
2386
2462
|
error: (error) => {
|
|
2387
2463
|
// Suppress errors during disposal - they're expected
|
|
2388
2464
|
if (!this.isDisposing && this.wsConnected) {
|
|
2389
|
-
|
|
2465
|
+
this.logger.error('WebSocket error:', error);
|
|
2390
2466
|
}
|
|
2391
2467
|
// Don't fail the connection on errors - let retry logic handle it
|
|
2392
2468
|
// Only log errors if we're connected (unexpected errors)
|
|
@@ -2398,7 +2474,7 @@ class BaseGraphQLClient {
|
|
|
2398
2474
|
this.wsInitializing = null;
|
|
2399
2475
|
}
|
|
2400
2476
|
catch (error) {
|
|
2401
|
-
|
|
2477
|
+
this.logger.error('Failed to create WebSocket client:', error);
|
|
2402
2478
|
this.wsInitializing = null;
|
|
2403
2479
|
// Resolve anyway to not block - we'll fallback to HTTP
|
|
2404
2480
|
if (!isResolved) {
|
|
@@ -3010,6 +3086,7 @@ class SearchOperations {
|
|
|
3010
3086
|
class ShopNamespace {
|
|
3011
3087
|
constructor(config) {
|
|
3012
3088
|
this.client = new BaseGraphQLClient(config);
|
|
3089
|
+
this.logger = new SDKLogger(config?.debug ?? false);
|
|
3013
3090
|
this.asset = new AssetOperations(this.client);
|
|
3014
3091
|
this.auth = new AuthOperations(this.client);
|
|
3015
3092
|
this.blog = new BlogOperations(this.client);
|
package/package.json
CHANGED
package/src/admin-namespace.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This file was automatically generated and should not be manually edited.
|
|
5
5
|
* To regenerate, run: npm run codegen:ts
|
|
6
6
|
*
|
|
7
|
-
* Generated at: 2025-12-
|
|
7
|
+
* Generated at: 2025-12-17T10:24:29.306Z
|
|
8
8
|
* Generator version: 1.0.0
|
|
9
9
|
*
|
|
10
10
|
* 🤖 Generated with ForgeCart SDK Generator
|
|
@@ -30,6 +30,60 @@ export interface SDKConfig {
|
|
|
30
30
|
webSocketImpl?: unknown;
|
|
31
31
|
/** Use HTTP only, skip WebSocket initialization (default: false) */
|
|
32
32
|
httpOnly?: boolean;
|
|
33
|
+
/** Enable debug logging with request timing (default: false) */
|
|
34
|
+
debug?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* SDK Logger - Cross-platform logging with colors
|
|
39
|
+
* Respects debug flag for log/warn, errors are always visible
|
|
40
|
+
*/
|
|
41
|
+
export class SDKLogger {
|
|
42
|
+
private debug: boolean;
|
|
43
|
+
private prefix = '[ForgeCart SDK]';
|
|
44
|
+
|
|
45
|
+
constructor(debug: boolean = false) {
|
|
46
|
+
this.debug = debug;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private isNode(): boolean {
|
|
50
|
+
return typeof process !== 'undefined' && process.versions?.node != null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Debug log - only outputs when debug: true
|
|
55
|
+
*/
|
|
56
|
+
log(message: string, ...args: unknown[]): void {
|
|
57
|
+
if (!this.debug) return;
|
|
58
|
+
if (this.isNode()) {
|
|
59
|
+
console.log(`\x1b[36m${this.prefix}\x1b[0m ${message}`, ...args);
|
|
60
|
+
} else {
|
|
61
|
+
console.log(`%c${this.prefix}%c ${message}`, 'color: #06b6d4; font-weight: bold', 'color: inherit', ...args);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Warning log - only outputs when debug: true
|
|
67
|
+
*/
|
|
68
|
+
warn(message: string, ...args: unknown[]): void {
|
|
69
|
+
if (!this.debug) return;
|
|
70
|
+
if (this.isNode()) {
|
|
71
|
+
console.warn(`\x1b[33m${this.prefix}\x1b[0m ${message}`, ...args);
|
|
72
|
+
} else {
|
|
73
|
+
console.warn(`%c${this.prefix}%c ${message}`, 'color: #eab308; font-weight: bold', 'color: inherit', ...args);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Error log - always outputs (errors should always be visible)
|
|
79
|
+
*/
|
|
80
|
+
error(message: string, ...args: unknown[]): void {
|
|
81
|
+
if (this.isNode()) {
|
|
82
|
+
console.error(`\x1b[31m${this.prefix}\x1b[0m ${message}`, ...args);
|
|
83
|
+
} else {
|
|
84
|
+
console.error(`%c${this.prefix}%c ${message}`, 'color: #ef4444; font-weight: bold', 'color: inherit', ...args);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
33
87
|
}
|
|
34
88
|
|
|
35
89
|
export type ActiveAdministratorQueryVariables = Types.ActiveAdministratorQueryVariables;
|
|
@@ -8170,11 +8224,13 @@ class BaseGraphQLClient {
|
|
|
8170
8224
|
private endpoint: string;
|
|
8171
8225
|
private wsEndpoint: string;
|
|
8172
8226
|
private config: SDKConfig;
|
|
8227
|
+
private logger: SDKLogger;
|
|
8173
8228
|
|
|
8174
8229
|
constructor(config: SDKConfig) {
|
|
8175
8230
|
this.endpoint = config.endpoint || 'https://api.forgecart.com/admin-api';
|
|
8176
8231
|
this.wsEndpoint = config.wsEndpoint || 'wss://api.forgecart.com/admin-api';
|
|
8177
8232
|
this.config = config;
|
|
8233
|
+
this.logger = new SDKLogger(config?.debug ?? false);
|
|
8178
8234
|
|
|
8179
8235
|
// Custom fetch that captures session token from response headers
|
|
8180
8236
|
const customFetch = async (url: RequestInfo | URL, options?: RequestInit): Promise<Response> => {
|
|
@@ -8208,6 +8264,15 @@ class BaseGraphQLClient {
|
|
|
8208
8264
|
this.initializeWebSocket();
|
|
8209
8265
|
}
|
|
8210
8266
|
|
|
8267
|
+
/**
|
|
8268
|
+
* Extract operation name from GraphQL document
|
|
8269
|
+
*/
|
|
8270
|
+
private getOperationName(document: RequestDocument): string {
|
|
8271
|
+
const docString = typeof document === 'string' ? document : String(document);
|
|
8272
|
+
const match = docString.match(/(?:query|mutation|subscription)\s+(\w+)/);
|
|
8273
|
+
return match ? match[1] : 'UnknownOperation';
|
|
8274
|
+
}
|
|
8275
|
+
|
|
8211
8276
|
/**
|
|
8212
8277
|
* Execute a GraphQL query or mutation
|
|
8213
8278
|
* Uses WebSocket if available, falls back to HTTP
|
|
@@ -8216,13 +8281,23 @@ class BaseGraphQLClient {
|
|
|
8216
8281
|
document: RequestDocument,
|
|
8217
8282
|
variables?: V
|
|
8218
8283
|
): Promise<T> {
|
|
8284
|
+
const startTime = this.config.debug ? performance.now() : 0;
|
|
8285
|
+
const operationName = this.config.debug ? this.getOperationName(document) : '';
|
|
8286
|
+
let transport = 'HTTP';
|
|
8287
|
+
|
|
8219
8288
|
|
|
8220
8289
|
// Try WebSocket first if available
|
|
8221
8290
|
if (this.wsClient && this.wsConnected) {
|
|
8222
8291
|
try {
|
|
8223
|
-
|
|
8292
|
+
transport = 'WebSocket';
|
|
8293
|
+
const result = await this.requestViaWebSocket<T>(document, variables);
|
|
8294
|
+
if (this.config.debug) {
|
|
8295
|
+
this.logger.log(`${operationName} (${transport}) - ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
8296
|
+
}
|
|
8297
|
+
return result;
|
|
8224
8298
|
} catch (wsError) {
|
|
8225
|
-
|
|
8299
|
+
transport = 'WebSocket -> HTTP';
|
|
8300
|
+
this.logger.warn('WebSocket request failed, falling back to HTTP:', wsError);
|
|
8226
8301
|
// Fall through to HTTP
|
|
8227
8302
|
}
|
|
8228
8303
|
}
|
|
@@ -8230,8 +8305,15 @@ class BaseGraphQLClient {
|
|
|
8230
8305
|
|
|
8231
8306
|
// Use HTTP as fallback or when WebSocket is not available
|
|
8232
8307
|
try {
|
|
8233
|
-
|
|
8308
|
+
const result = await this.httpClient.request<T>(document, variables);
|
|
8309
|
+
if (this.config.debug) {
|
|
8310
|
+
this.logger.log(`${operationName} (${transport}) - ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
8311
|
+
}
|
|
8312
|
+
return result;
|
|
8234
8313
|
} catch (error) {
|
|
8314
|
+
if (this.config.debug) {
|
|
8315
|
+
this.logger.log(`${operationName} (${transport}) - FAILED after ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
8316
|
+
}
|
|
8235
8317
|
this.handleError(error);
|
|
8236
8318
|
throw error;
|
|
8237
8319
|
}
|
|
@@ -8283,7 +8365,7 @@ class BaseGraphQLClient {
|
|
|
8283
8365
|
* Handle GraphQL errors
|
|
8284
8366
|
*/
|
|
8285
8367
|
private handleError(error: any): void {
|
|
8286
|
-
|
|
8368
|
+
this.logger.error('GraphQL Error:', error);
|
|
8287
8369
|
}
|
|
8288
8370
|
|
|
8289
8371
|
|
|
@@ -8306,7 +8388,7 @@ class BaseGraphQLClient {
|
|
|
8306
8388
|
// Dynamic import for Node.js
|
|
8307
8389
|
return require('ws');
|
|
8308
8390
|
} catch (e) {
|
|
8309
|
-
|
|
8391
|
+
this.logger.warn('WebSocket not available. Install "ws" package for Node.js support or provide webSocketImpl in config.');
|
|
8310
8392
|
return undefined;
|
|
8311
8393
|
}
|
|
8312
8394
|
}
|
|
@@ -8328,7 +8410,7 @@ class BaseGraphQLClient {
|
|
|
8328
8410
|
|
|
8329
8411
|
const WebSocketImpl = this.getWebSocketImpl();
|
|
8330
8412
|
if (!WebSocketImpl) {
|
|
8331
|
-
|
|
8413
|
+
this.logger.warn('WebSocket not available. Will use HTTP fallback only.');
|
|
8332
8414
|
return;
|
|
8333
8415
|
}
|
|
8334
8416
|
|
|
@@ -8361,7 +8443,7 @@ class BaseGraphQLClient {
|
|
|
8361
8443
|
|
|
8362
8444
|
return params;
|
|
8363
8445
|
} catch (error) {
|
|
8364
|
-
|
|
8446
|
+
this.logger.error('Error in connectionParams:', error);
|
|
8365
8447
|
return {};
|
|
8366
8448
|
}
|
|
8367
8449
|
},
|
|
@@ -8374,7 +8456,7 @@ class BaseGraphQLClient {
|
|
|
8374
8456
|
on: {
|
|
8375
8457
|
connected: () => {
|
|
8376
8458
|
this.wsConnected = true;
|
|
8377
|
-
|
|
8459
|
+
this.logger.log('WebSocket connected');
|
|
8378
8460
|
if (!isResolved) {
|
|
8379
8461
|
isResolved = true;
|
|
8380
8462
|
resolve();
|
|
@@ -8383,13 +8465,13 @@ class BaseGraphQLClient {
|
|
|
8383
8465
|
closed: () => {
|
|
8384
8466
|
this.wsConnected = false;
|
|
8385
8467
|
if (!this.isDisposing) {
|
|
8386
|
-
|
|
8468
|
+
this.logger.log('WebSocket disconnected');
|
|
8387
8469
|
}
|
|
8388
8470
|
},
|
|
8389
8471
|
error: (error) => {
|
|
8390
8472
|
// Suppress errors during disposal - they're expected
|
|
8391
8473
|
if (!this.isDisposing && this.wsConnected) {
|
|
8392
|
-
|
|
8474
|
+
this.logger.error('WebSocket error:', error);
|
|
8393
8475
|
}
|
|
8394
8476
|
// Don't fail the connection on errors - let retry logic handle it
|
|
8395
8477
|
// Only log errors if we're connected (unexpected errors)
|
|
@@ -8401,7 +8483,7 @@ class BaseGraphQLClient {
|
|
|
8401
8483
|
this.wsClient = createClient(wsOptions);
|
|
8402
8484
|
this.wsInitializing = null;
|
|
8403
8485
|
} catch (error) {
|
|
8404
|
-
|
|
8486
|
+
this.logger.error('Failed to create WebSocket client:', error);
|
|
8405
8487
|
this.wsInitializing = null;
|
|
8406
8488
|
// Resolve anyway to not block - we'll fallback to HTTP
|
|
8407
8489
|
if (!isResolved) {
|
|
@@ -11055,6 +11137,7 @@ class ZoneOperations {
|
|
|
11055
11137
|
*/
|
|
11056
11138
|
export class AdminNamespace {
|
|
11057
11139
|
private client: BaseGraphQLClient;
|
|
11140
|
+
private logger: SDKLogger;
|
|
11058
11141
|
|
|
11059
11142
|
readonly administrator: AdministratorOperations;
|
|
11060
11143
|
readonly asset: AssetOperations;
|
|
@@ -11113,6 +11196,7 @@ export class AdminNamespace {
|
|
|
11113
11196
|
|
|
11114
11197
|
constructor(config: SDKConfig) {
|
|
11115
11198
|
this.client = new BaseGraphQLClient(config);
|
|
11199
|
+
this.logger = new SDKLogger(config?.debug ?? false);
|
|
11116
11200
|
|
|
11117
11201
|
this.administrator = new AdministratorOperations(this.client);
|
|
11118
11202
|
this.asset = new AssetOperations(this.client);
|
|
@@ -11247,7 +11331,7 @@ export class AdminNamespace {
|
|
|
11247
11331
|
}
|
|
11248
11332
|
} catch (error) {
|
|
11249
11333
|
if (this.isListening) {
|
|
11250
|
-
|
|
11334
|
+
this.logger.error('Event subscription error:', error);
|
|
11251
11335
|
await this.handleReconnect();
|
|
11252
11336
|
}
|
|
11253
11337
|
}
|
|
@@ -11268,7 +11352,7 @@ export class AdminNamespace {
|
|
|
11268
11352
|
);
|
|
11269
11353
|
|
|
11270
11354
|
this.retryCount++;
|
|
11271
|
-
|
|
11355
|
+
this.logger.log(`Reconnecting in ${delay}ms (attempt ${this.retryCount}/${maxRetries})`);
|
|
11272
11356
|
|
|
11273
11357
|
await new Promise(resolve => setTimeout(resolve, delay));
|
|
11274
11358
|
await this.startSubscription();
|
|
@@ -11287,7 +11371,7 @@ export class AdminNamespace {
|
|
|
11287
11371
|
try {
|
|
11288
11372
|
handler(event);
|
|
11289
11373
|
} catch (error) {
|
|
11290
|
-
|
|
11374
|
+
this.logger.error(`Error in event handler for ${eventName}:`, error);
|
|
11291
11375
|
}
|
|
11292
11376
|
}
|
|
11293
11377
|
}
|
|
@@ -11303,7 +11387,7 @@ export class AdminNamespace {
|
|
|
11303
11387
|
`Blocking handler for ${eventName} exceeded ${AdminNamespace.BLOCKING_TIMEOUT_MS}ms`
|
|
11304
11388
|
);
|
|
11305
11389
|
} catch (error) {
|
|
11306
|
-
|
|
11390
|
+
this.logger.error(`Error in blocking event handler for ${eventName}:`, error);
|
|
11307
11391
|
throw error; // Re-throw for blocking handlers
|
|
11308
11392
|
}
|
|
11309
11393
|
}
|
package/src/admin-types.ts
CHANGED
|
@@ -1063,6 +1063,7 @@ export type CreateCustomerInput = {
|
|
|
1063
1063
|
export type CreateCustomerResult = Customer | EmailAddressConflictError;
|
|
1064
1064
|
|
|
1065
1065
|
export type CreateDeploymentInput = {
|
|
1066
|
+
envVars?: InputMaybe<Array<EnvVarInput>>;
|
|
1066
1067
|
type: DeploymentType;
|
|
1067
1068
|
};
|
|
1068
1069
|
|
|
@@ -2095,6 +2096,11 @@ export type EntityEventType =
|
|
|
2095
2096
|
| 'removed'
|
|
2096
2097
|
| 'updated';
|
|
2097
2098
|
|
|
2099
|
+
export type EnvVarInput = {
|
|
2100
|
+
key: Scalars['String']['input'];
|
|
2101
|
+
value: Scalars['String']['input'];
|
|
2102
|
+
};
|
|
2103
|
+
|
|
2098
2104
|
export type ErrorCode =
|
|
2099
2105
|
| 'ALREADY_REFUNDED_ERROR'
|
|
2100
2106
|
| 'CANCEL_ACTIVE_ORDER_ERROR'
|
|
@@ -7389,9 +7395,8 @@ export type SessionInput = {
|
|
|
7389
7395
|
export type SetCustomerForDraftOrderResult = EmailAddressConflictError | Order;
|
|
7390
7396
|
|
|
7391
7397
|
export type SetEnvInput = {
|
|
7392
|
-
|
|
7398
|
+
envVars: Array<EnvVarInput>;
|
|
7393
7399
|
type: DeploymentType;
|
|
7394
|
-
value: Scalars['String']['input'];
|
|
7395
7400
|
};
|
|
7396
7401
|
|
|
7397
7402
|
export type SetOrderCustomerInput = {
|
|
@@ -8078,7 +8083,7 @@ export type TransitionOrderToStateResult = Order | OrderStateTransitionError;
|
|
|
8078
8083
|
export type TransitionPaymentToStateResult = Payment | PaymentStateTransitionError;
|
|
8079
8084
|
|
|
8080
8085
|
export type UnsetEnvInput = {
|
|
8081
|
-
|
|
8086
|
+
keys: Array<Scalars['String']['input']>;
|
|
8082
8087
|
type: DeploymentType;
|
|
8083
8088
|
};
|
|
8084
8089
|
|
package/src/index.ts
CHANGED
|
@@ -20,6 +20,8 @@ export interface ForgeCartSDKConfig {
|
|
|
20
20
|
token: string
|
|
21
21
|
/** Use HTTP only, skip WebSocket initialization (default: false) */
|
|
22
22
|
httpOnly?: boolean
|
|
23
|
+
/** Enable debug logging with request timing (default: false) */
|
|
24
|
+
debug?: boolean
|
|
23
25
|
/** Custom HTTP headers */
|
|
24
26
|
headers?: Record<string, string>
|
|
25
27
|
/** Custom WebSocket implementation (optional, auto-detected if not provided) */
|
|
@@ -75,6 +77,7 @@ export class ForgeCartSDK {
|
|
|
75
77
|
headers,
|
|
76
78
|
webSocketImpl: config.webSocketImpl,
|
|
77
79
|
httpOnly: config.httpOnly,
|
|
80
|
+
debug: config.debug,
|
|
78
81
|
}
|
|
79
82
|
this.admin = new AdminNamespace(adminConfig)
|
|
80
83
|
|
|
@@ -84,6 +87,7 @@ export class ForgeCartSDK {
|
|
|
84
87
|
headers,
|
|
85
88
|
webSocketImpl: config.webSocketImpl,
|
|
86
89
|
httpOnly: config.httpOnly,
|
|
90
|
+
debug: config.debug,
|
|
87
91
|
}
|
|
88
92
|
this.shop = new ShopNamespace(shopConfig)
|
|
89
93
|
}
|
package/src/shop-namespace.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* This file was automatically generated and should not be manually edited.
|
|
5
5
|
* To regenerate, run: npm run codegen:ts
|
|
6
6
|
*
|
|
7
|
-
* Generated at: 2025-12-
|
|
7
|
+
* Generated at: 2025-12-17T10:24:29.175Z
|
|
8
8
|
* Generator version: 1.0.0
|
|
9
9
|
*
|
|
10
10
|
* 🤖 Generated with ForgeCart SDK Generator
|
|
@@ -30,6 +30,60 @@ export interface SDKConfig {
|
|
|
30
30
|
webSocketImpl?: unknown;
|
|
31
31
|
/** Use HTTP only, skip WebSocket initialization (default: false) */
|
|
32
32
|
httpOnly?: boolean;
|
|
33
|
+
/** Enable debug logging with request timing (default: false) */
|
|
34
|
+
debug?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* SDK Logger - Cross-platform logging with colors
|
|
39
|
+
* Respects debug flag for log/warn, errors are always visible
|
|
40
|
+
*/
|
|
41
|
+
export class SDKLogger {
|
|
42
|
+
private debug: boolean;
|
|
43
|
+
private prefix = '[ForgeCart SDK]';
|
|
44
|
+
|
|
45
|
+
constructor(debug: boolean = false) {
|
|
46
|
+
this.debug = debug;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private isNode(): boolean {
|
|
50
|
+
return typeof process !== 'undefined' && process.versions?.node != null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Debug log - only outputs when debug: true
|
|
55
|
+
*/
|
|
56
|
+
log(message: string, ...args: unknown[]): void {
|
|
57
|
+
if (!this.debug) return;
|
|
58
|
+
if (this.isNode()) {
|
|
59
|
+
console.log(`\x1b[36m${this.prefix}\x1b[0m ${message}`, ...args);
|
|
60
|
+
} else {
|
|
61
|
+
console.log(`%c${this.prefix}%c ${message}`, 'color: #06b6d4; font-weight: bold', 'color: inherit', ...args);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Warning log - only outputs when debug: true
|
|
67
|
+
*/
|
|
68
|
+
warn(message: string, ...args: unknown[]): void {
|
|
69
|
+
if (!this.debug) return;
|
|
70
|
+
if (this.isNode()) {
|
|
71
|
+
console.warn(`\x1b[33m${this.prefix}\x1b[0m ${message}`, ...args);
|
|
72
|
+
} else {
|
|
73
|
+
console.warn(`%c${this.prefix}%c ${message}`, 'color: #eab308; font-weight: bold', 'color: inherit', ...args);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Error log - always outputs (errors should always be visible)
|
|
79
|
+
*/
|
|
80
|
+
error(message: string, ...args: unknown[]): void {
|
|
81
|
+
if (this.isNode()) {
|
|
82
|
+
console.error(`\x1b[31m${this.prefix}\x1b[0m ${message}`, ...args);
|
|
83
|
+
} else {
|
|
84
|
+
console.error(`%c${this.prefix}%c ${message}`, 'color: #ef4444; font-weight: bold', 'color: inherit', ...args);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
33
87
|
}
|
|
34
88
|
|
|
35
89
|
export type AssetQueryVariables = Types.AssetQueryVariables;
|
|
@@ -2494,11 +2548,13 @@ class BaseGraphQLClient {
|
|
|
2494
2548
|
private endpoint: string;
|
|
2495
2549
|
private wsEndpoint: string;
|
|
2496
2550
|
private config: SDKConfig;
|
|
2551
|
+
private logger: SDKLogger;
|
|
2497
2552
|
|
|
2498
2553
|
constructor(config: SDKConfig) {
|
|
2499
2554
|
this.endpoint = config.endpoint || 'https://api.forgecart.com/shop-api';
|
|
2500
2555
|
this.wsEndpoint = config.wsEndpoint || 'wss://api.forgecart.com/shop-api';
|
|
2501
2556
|
this.config = config;
|
|
2557
|
+
this.logger = new SDKLogger(config?.debug ?? false);
|
|
2502
2558
|
|
|
2503
2559
|
// Custom fetch that captures session token from response headers
|
|
2504
2560
|
const customFetch = async (url: RequestInfo | URL, options?: RequestInit): Promise<Response> => {
|
|
@@ -2532,6 +2588,15 @@ class BaseGraphQLClient {
|
|
|
2532
2588
|
this.initializeWebSocket();
|
|
2533
2589
|
}
|
|
2534
2590
|
|
|
2591
|
+
/**
|
|
2592
|
+
* Extract operation name from GraphQL document
|
|
2593
|
+
*/
|
|
2594
|
+
private getOperationName(document: RequestDocument): string {
|
|
2595
|
+
const docString = typeof document === 'string' ? document : String(document);
|
|
2596
|
+
const match = docString.match(/(?:query|mutation|subscription)\s+(\w+)/);
|
|
2597
|
+
return match ? match[1] : 'UnknownOperation';
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2535
2600
|
/**
|
|
2536
2601
|
* Execute a GraphQL query or mutation
|
|
2537
2602
|
* Uses WebSocket if available, falls back to HTTP
|
|
@@ -2540,13 +2605,23 @@ class BaseGraphQLClient {
|
|
|
2540
2605
|
document: RequestDocument,
|
|
2541
2606
|
variables?: V
|
|
2542
2607
|
): Promise<T> {
|
|
2608
|
+
const startTime = this.config.debug ? performance.now() : 0;
|
|
2609
|
+
const operationName = this.config.debug ? this.getOperationName(document) : '';
|
|
2610
|
+
let transport = 'HTTP';
|
|
2611
|
+
|
|
2543
2612
|
|
|
2544
2613
|
// Try WebSocket first if available
|
|
2545
2614
|
if (this.wsClient && this.wsConnected) {
|
|
2546
2615
|
try {
|
|
2547
|
-
|
|
2616
|
+
transport = 'WebSocket';
|
|
2617
|
+
const result = await this.requestViaWebSocket<T>(document, variables);
|
|
2618
|
+
if (this.config.debug) {
|
|
2619
|
+
this.logger.log(`${operationName} (${transport}) - ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
2620
|
+
}
|
|
2621
|
+
return result;
|
|
2548
2622
|
} catch (wsError) {
|
|
2549
|
-
|
|
2623
|
+
transport = 'WebSocket -> HTTP';
|
|
2624
|
+
this.logger.warn('WebSocket request failed, falling back to HTTP:', wsError);
|
|
2550
2625
|
// Fall through to HTTP
|
|
2551
2626
|
}
|
|
2552
2627
|
}
|
|
@@ -2554,8 +2629,15 @@ class BaseGraphQLClient {
|
|
|
2554
2629
|
|
|
2555
2630
|
// Use HTTP as fallback or when WebSocket is not available
|
|
2556
2631
|
try {
|
|
2557
|
-
|
|
2632
|
+
const result = await this.httpClient.request<T>(document, variables);
|
|
2633
|
+
if (this.config.debug) {
|
|
2634
|
+
this.logger.log(`${operationName} (${transport}) - ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
2635
|
+
}
|
|
2636
|
+
return result;
|
|
2558
2637
|
} catch (error) {
|
|
2638
|
+
if (this.config.debug) {
|
|
2639
|
+
this.logger.log(`${operationName} (${transport}) - FAILED after ${(performance.now() - startTime).toFixed(0)}ms`);
|
|
2640
|
+
}
|
|
2559
2641
|
this.handleError(error);
|
|
2560
2642
|
throw error;
|
|
2561
2643
|
}
|
|
@@ -2607,7 +2689,7 @@ class BaseGraphQLClient {
|
|
|
2607
2689
|
* Handle GraphQL errors
|
|
2608
2690
|
*/
|
|
2609
2691
|
private handleError(error: any): void {
|
|
2610
|
-
|
|
2692
|
+
this.logger.error('GraphQL Error:', error);
|
|
2611
2693
|
}
|
|
2612
2694
|
|
|
2613
2695
|
|
|
@@ -2630,7 +2712,7 @@ class BaseGraphQLClient {
|
|
|
2630
2712
|
// Dynamic import for Node.js
|
|
2631
2713
|
return require('ws');
|
|
2632
2714
|
} catch (e) {
|
|
2633
|
-
|
|
2715
|
+
this.logger.warn('WebSocket not available. Install "ws" package for Node.js support or provide webSocketImpl in config.');
|
|
2634
2716
|
return undefined;
|
|
2635
2717
|
}
|
|
2636
2718
|
}
|
|
@@ -2652,7 +2734,7 @@ class BaseGraphQLClient {
|
|
|
2652
2734
|
|
|
2653
2735
|
const WebSocketImpl = this.getWebSocketImpl();
|
|
2654
2736
|
if (!WebSocketImpl) {
|
|
2655
|
-
|
|
2737
|
+
this.logger.warn('WebSocket not available. Will use HTTP fallback only.');
|
|
2656
2738
|
return;
|
|
2657
2739
|
}
|
|
2658
2740
|
|
|
@@ -2685,7 +2767,7 @@ class BaseGraphQLClient {
|
|
|
2685
2767
|
|
|
2686
2768
|
return params;
|
|
2687
2769
|
} catch (error) {
|
|
2688
|
-
|
|
2770
|
+
this.logger.error('Error in connectionParams:', error);
|
|
2689
2771
|
return {};
|
|
2690
2772
|
}
|
|
2691
2773
|
},
|
|
@@ -2698,7 +2780,7 @@ class BaseGraphQLClient {
|
|
|
2698
2780
|
on: {
|
|
2699
2781
|
connected: () => {
|
|
2700
2782
|
this.wsConnected = true;
|
|
2701
|
-
|
|
2783
|
+
this.logger.log('WebSocket connected');
|
|
2702
2784
|
if (!isResolved) {
|
|
2703
2785
|
isResolved = true;
|
|
2704
2786
|
resolve();
|
|
@@ -2707,13 +2789,13 @@ class BaseGraphQLClient {
|
|
|
2707
2789
|
closed: () => {
|
|
2708
2790
|
this.wsConnected = false;
|
|
2709
2791
|
if (!this.isDisposing) {
|
|
2710
|
-
|
|
2792
|
+
this.logger.log('WebSocket disconnected');
|
|
2711
2793
|
}
|
|
2712
2794
|
},
|
|
2713
2795
|
error: (error) => {
|
|
2714
2796
|
// Suppress errors during disposal - they're expected
|
|
2715
2797
|
if (!this.isDisposing && this.wsConnected) {
|
|
2716
|
-
|
|
2798
|
+
this.logger.error('WebSocket error:', error);
|
|
2717
2799
|
}
|
|
2718
2800
|
// Don't fail the connection on errors - let retry logic handle it
|
|
2719
2801
|
// Only log errors if we're connected (unexpected errors)
|
|
@@ -2725,7 +2807,7 @@ class BaseGraphQLClient {
|
|
|
2725
2807
|
this.wsClient = createClient(wsOptions);
|
|
2726
2808
|
this.wsInitializing = null;
|
|
2727
2809
|
} catch (error) {
|
|
2728
|
-
|
|
2810
|
+
this.logger.error('Failed to create WebSocket client:', error);
|
|
2729
2811
|
this.wsInitializing = null;
|
|
2730
2812
|
// Resolve anyway to not block - we'll fallback to HTTP
|
|
2731
2813
|
if (!isResolved) {
|
|
@@ -3405,6 +3487,7 @@ class SearchOperations {
|
|
|
3405
3487
|
*/
|
|
3406
3488
|
export class ShopNamespace {
|
|
3407
3489
|
private client: BaseGraphQLClient;
|
|
3490
|
+
private logger: SDKLogger;
|
|
3408
3491
|
|
|
3409
3492
|
readonly asset: AssetOperations;
|
|
3410
3493
|
readonly auth: AuthOperations;
|
|
@@ -3422,6 +3505,7 @@ export class ShopNamespace {
|
|
|
3422
3505
|
|
|
3423
3506
|
constructor(config: SDKConfig) {
|
|
3424
3507
|
this.client = new BaseGraphQLClient(config);
|
|
3508
|
+
this.logger = new SDKLogger(config?.debug ?? false);
|
|
3425
3509
|
|
|
3426
3510
|
this.asset = new AssetOperations(this.client);
|
|
3427
3511
|
this.auth = new AuthOperations(this.client);
|