@forgecart/sdk 1.202609201502.0 → 1.202609211357.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.
@@ -2127,6 +2127,7 @@ export type EcomInboundEvent = {
2127
2127
  extResourceId?: Maybe<Scalars['String']['output']>;
2128
2128
  id: Scalars['ID']['output'];
2129
2129
  lastErrorCode?: Maybe<Scalars['String']['output']>;
2130
+ platformMessage?: Maybe<Scalars['String']['output']>;
2130
2131
  processedAt?: Maybe<Scalars['DateTime']['output']>;
2131
2132
  providerCode: Scalars['String']['output'];
2132
2133
  status: Scalars['String']['output'];
@@ -2204,6 +2205,7 @@ export type EcomVariantLink = {
2204
2205
  id: Scalars['ID']['output'];
2205
2206
  lastErrorCode?: Maybe<Scalars['String']['output']>;
2206
2207
  lastPushedAt?: Maybe<Scalars['DateTime']['output']>;
2208
+ platformMessage?: Maybe<Scalars['String']['output']>;
2207
2209
  productId?: Maybe<Scalars['ID']['output']>;
2208
2210
  syncState: Scalars['String']['output'];
2209
2211
  updatedAt: Scalars['DateTime']['output'];
@@ -11720,7 +11722,7 @@ export type AdminDeploymentStatusChangedSubscription = {
11720
11722
  deploymentStatusChanged: Pick<Deployment, 'id' | 'type' | 'status' | 'url' | 'errorMessage' | 'instances' | 'lastDeployedAt'>;
11721
11723
  };
11722
11724
  export type EcomConnectionFieldsFragment = Pick<EcomConnection, 'id' | 'createdAt' | 'updatedAt' | 'providerCode' | 'externalAccountId' | 'externalScope' | 'status' | 'statusErrorCode' | 'commerceMode' | 'syncCatalog' | 'syncInventory' | 'ingestOrders' | 'syncCustomers' | 'orchestrateRefunds' | 'inventoryShortfallPolicy' | 'ingestExternalStockAdjustments' | 'defaultStockLocationId' | 'shopCurrencyCode' | 'channelPluginId'>;
11723
- export type EcomInboundEventFieldsFragment = Pick<EcomInboundEvent, 'id' | 'createdAt' | 'connectionId' | 'providerCode' | 'extEventId' | 'topic' | 'extResourceId' | 'status' | 'attempts' | 'lastErrorCode' | 'processedAt'>;
11725
+ export type EcomInboundEventFieldsFragment = Pick<EcomInboundEvent, 'id' | 'createdAt' | 'connectionId' | 'providerCode' | 'extEventId' | 'topic' | 'extResourceId' | 'status' | 'attempts' | 'lastErrorCode' | 'platformMessage' | 'processedAt'>;
11724
11726
  export type EcomConnectionsQueryVariables = Exact<{
11725
11727
  [key: string]: never;
11726
11728
  }>;
@@ -11745,7 +11747,7 @@ export type EcomBlockedInboundEventsQueryVariables = Exact<{
11745
11747
  connectionId: Scalars['ID']['input'];
11746
11748
  }>;
11747
11749
  export type EcomBlockedInboundEventsQuery = {
11748
- ecomBlockedInboundEvents: Array<Pick<EcomInboundEvent, 'id' | 'createdAt' | 'connectionId' | 'providerCode' | 'extEventId' | 'topic' | 'extResourceId' | 'status' | 'attempts' | 'lastErrorCode' | 'processedAt'>>;
11750
+ ecomBlockedInboundEvents: Array<Pick<EcomInboundEvent, 'id' | 'createdAt' | 'connectionId' | 'providerCode' | 'extEventId' | 'topic' | 'extResourceId' | 'status' | 'attempts' | 'lastErrorCode' | 'platformMessage' | 'processedAt'>>;
11749
11751
  };
11750
11752
  export type CreateEcomConnectionMutationVariables = Exact<{
11751
11753
  input: CreateEcomConnectionInput;
@@ -11793,14 +11795,14 @@ export type RetryEcomInboundEventMutationVariables = Exact<{
11793
11795
  eventId: Scalars['ID']['input'];
11794
11796
  }>;
11795
11797
  export type RetryEcomInboundEventMutation = {
11796
- retryEcomInboundEvent: Pick<EcomInboundEvent, 'id' | 'createdAt' | 'connectionId' | 'providerCode' | 'extEventId' | 'topic' | 'extResourceId' | 'status' | 'attempts' | 'lastErrorCode' | 'processedAt'>;
11798
+ retryEcomInboundEvent: Pick<EcomInboundEvent, 'id' | 'createdAt' | 'connectionId' | 'providerCode' | 'extEventId' | 'topic' | 'extResourceId' | 'status' | 'attempts' | 'lastErrorCode' | 'platformMessage' | 'processedAt'>;
11797
11799
  };
11798
- export type EcomVariantLinkFieldsFragment = Pick<EcomVariantLink, 'id' | 'createdAt' | 'updatedAt' | 'connectionId' | 'productId' | 'variantId' | 'extProductId' | 'extVariantId' | 'extInventoryItemId' | 'syncState' | 'desiredState' | 'lastErrorCode' | 'attempts' | 'lastPushedAt'>;
11800
+ export type EcomVariantLinkFieldsFragment = Pick<EcomVariantLink, 'id' | 'createdAt' | 'updatedAt' | 'connectionId' | 'productId' | 'variantId' | 'extProductId' | 'extVariantId' | 'extInventoryItemId' | 'syncState' | 'desiredState' | 'lastErrorCode' | 'platformMessage' | 'attempts' | 'lastPushedAt'>;
11799
11801
  export type EcomVariantLinksQueryVariables = Exact<{
11800
11802
  connectionId: Scalars['ID']['input'];
11801
11803
  }>;
11802
11804
  export type EcomVariantLinksQuery = {
11803
- ecomVariantLinks: Array<Pick<EcomVariantLink, 'id' | 'createdAt' | 'updatedAt' | 'connectionId' | 'productId' | 'variantId' | 'extProductId' | 'extVariantId' | 'extInventoryItemId' | 'syncState' | 'desiredState' | 'lastErrorCode' | 'attempts' | 'lastPushedAt'>>;
11805
+ ecomVariantLinks: Array<Pick<EcomVariantLink, 'id' | 'createdAt' | 'updatedAt' | 'connectionId' | 'productId' | 'variantId' | 'extProductId' | 'extVariantId' | 'extInventoryItemId' | 'syncState' | 'desiredState' | 'lastErrorCode' | 'platformMessage' | 'attempts' | 'lastPushedAt'>>;
11804
11806
  };
11805
11807
  export type TriggerEcomBackfillMutationVariables = Exact<{
11806
11808
  connectionId: Scalars['ID']['input'];
@@ -11812,13 +11814,13 @@ export type RetryEcomVariantLinkMutationVariables = Exact<{
11812
11814
  input: RetryEcomVariantLinkInput;
11813
11815
  }>;
11814
11816
  export type RetryEcomVariantLinkMutation = {
11815
- retryEcomVariantLink: Pick<EcomVariantLink, 'id' | 'createdAt' | 'updatedAt' | 'connectionId' | 'productId' | 'variantId' | 'extProductId' | 'extVariantId' | 'extInventoryItemId' | 'syncState' | 'desiredState' | 'lastErrorCode' | 'attempts' | 'lastPushedAt'>;
11817
+ retryEcomVariantLink: Pick<EcomVariantLink, 'id' | 'createdAt' | 'updatedAt' | 'connectionId' | 'productId' | 'variantId' | 'extProductId' | 'extVariantId' | 'extInventoryItemId' | 'syncState' | 'desiredState' | 'lastErrorCode' | 'platformMessage' | 'attempts' | 'lastPushedAt'>;
11816
11818
  };
11817
11819
  export type RelinkEcomVariantMutationVariables = Exact<{
11818
11820
  input: RelinkEcomVariantInput;
11819
11821
  }>;
11820
11822
  export type RelinkEcomVariantMutation = {
11821
- relinkEcomVariant: Pick<EcomVariantLink, 'id' | 'createdAt' | 'updatedAt' | 'connectionId' | 'productId' | 'variantId' | 'extProductId' | 'extVariantId' | 'extInventoryItemId' | 'syncState' | 'desiredState' | 'lastErrorCode' | 'attempts' | 'lastPushedAt'>;
11823
+ relinkEcomVariant: Pick<EcomVariantLink, 'id' | 'createdAt' | 'updatedAt' | 'connectionId' | 'productId' | 'variantId' | 'extProductId' | 'extVariantId' | 'extInventoryItemId' | 'syncState' | 'desiredState' | 'lastErrorCode' | 'platformMessage' | 'attempts' | 'lastPushedAt'>;
11822
11824
  };
11823
11825
  export type EcomLocationLinkFieldsFragment = Pick<EcomLocationLink, 'id' | 'stockLocationId' | 'extLocationId' | 'authority'>;
11824
11826
  export type EcomLocationLinksQueryVariables = Exact<{
@@ -11870,7 +11872,7 @@ export type EcomInboundEventsQueryVariables = Exact<{
11870
11872
  connectionId: Scalars['ID']['input'];
11871
11873
  }>;
11872
11874
  export type EcomInboundEventsQuery = {
11873
- ecomInboundEvents: Array<Pick<EcomInboundEvent, 'id' | 'createdAt' | 'connectionId' | 'providerCode' | 'extEventId' | 'topic' | 'extResourceId' | 'status' | 'attempts' | 'lastErrorCode' | 'processedAt'>>;
11875
+ ecomInboundEvents: Array<Pick<EcomInboundEvent, 'id' | 'createdAt' | 'connectionId' | 'providerCode' | 'extEventId' | 'topic' | 'extResourceId' | 'status' | 'attempts' | 'lastErrorCode' | 'platformMessage' | 'processedAt'>>;
11874
11876
  };
11875
11877
  export type EcomOrderLinkQueryVariables = Exact<{
11876
11878
  orderId: Scalars['ID']['input'];
@@ -155,7 +155,7 @@ export declare class BaseGraphQLClient {
155
155
  * subscriptions; wrong for mutations: a re-sent create races its own
156
156
  * first attempt (observed: activatePlugin re-sent under load — the
157
157
  * winner committed, the caller received the loser's duplicate-name
158
- * error). With `singleDelivery` the operation arms once a live (ACKed)
158
+ * error). For a MUTATION the guard arms once a live (ACKed)
159
159
  * socket could have carried it; a close while armed fails the operation
160
160
  * with WS_MUTATION_DELIVERY_INTERRUPTED instead of silently
161
161
  * re-executing it — the in-flight attempt's outcome is genuinely
@@ -163,16 +163,55 @@ export declare class BaseGraphQLClient {
163
163
  * BEFORE the first ACK stay retryable, so shouldRetry keeps healing
164
164
  * transient non-101 handshake refusals for mutations too.
165
165
  *
166
- * The operation also carries a HANDSHAKE bound (#2102) — never an
167
- * operation-lifetime one. subscribe() IS query() here, so a deadline on
168
- * the whole operation would kill every long-lived subscription; the bound
169
- * is armed only while the socket has not ACKed, and once it has, the wait
170
- * is the server streaming and nothing bounds it.
166
+ * The operation carries TWO bounds, and KIND is what tells them apart.
167
+ * The HANDSHAKE bound (#2102) is armed only while the socket has not ACKed
168
+ * and ends an operation no socket could have carried. The FIRST-VALUE
169
+ * deadline (#1905) covers the other half of the same hang — an ACKed socket
170
+ * that simply withholds the reply, which no bound reached: a read gives up
171
+ * at 10 s, a write at 60 s, and a subscription never, because its first
172
+ * value may be minutes away by design. It measures the wait for the first
173
+ * sink callback, never the operation's lifetime, so a connected stream runs
174
+ * for as long as the server streams it. Both bounds raise the same typed
175
+ * code, so one consumer branch answers for both.
171
176
  */
172
177
  private executeWsOperation;
178
+ /**
179
+ * A live tail. It is NOT query() any more (#1905): a subscription is the one
180
+ * kind whose first value may legitimately be minutes away, so it is the one
181
+ * kind that carries no first-value deadline. The HANDSHAKE bound still
182
+ * applies — a socket that never ACKed carried no operation, stream or not.
183
+ */
173
184
  subscribe<T>(document: string, variables?: Record<string, unknown>): Observable<T>;
174
185
  upload<T>(document: string, variables: Record<string, unknown>): QueryObservable<T>;
175
186
  private getPerOperationExtensions;
187
+ /**
188
+ * The first-value budget for this operation, or undefined when it carries
189
+ * none. A get*, not a find*: derived configuration, never a lookup (#1905).
190
+ *
191
+ * The OPERATION's declared budget wins over its kind default (#2245): a
192
+ * kind default sizes the average operation, and one whose server work is
193
+ * itself bounded in seconds must cover that bound, or the client always
194
+ * wins the race and hides the server's own fallback behind a transport
195
+ * error.
196
+ */
197
+ private getFirstValueBudgetMs;
198
+ /**
199
+ * The name the document declares: `query ChannelPlugins` gives
200
+ * "ChannelPlugins". Every generated document is a named operation, so the
201
+ * fallback serves only a hand-written anonymous one — and a timeout that
202
+ * cannot say WHICH operation stalled is most of a forensic dead end.
203
+ */
204
+ private operationNameOf;
205
+ /**
206
+ * The ONE typed error both transport bounds raise (#1905). `code` is what
207
+ * consumers actually read — extractErrorCode / isErrorCode duck-type
208
+ * response.errors[0].extensions.code (error-utils.ts) — so a bound without
209
+ * one is invisible to them however loud its message is. `variables` is the
210
+ * uniform, i18n-ready channel the house error contract ships (codes on the
211
+ * wire, copy owned by the frontend); `detail` carries whatever attribution
212
+ * is specific to the bound that raised it, such as #2102's endpoint.
213
+ */
214
+ private wsTimeoutError;
176
215
  /**
177
216
  * Uniform error contract for the sink-level error path. graphql-ws
178
217
  * delivers a server ErrorMessage payload as a raw GraphQLError[] —
@@ -15,6 +15,7 @@ exports.clearTransactionToken = clearTransactionToken;
15
15
  const rxjs_1 = require("rxjs");
16
16
  const graphql_ws_1 = require("graphql-ws");
17
17
  const upload_1 = require("./upload");
18
+ const sdk_types_generated_1 = require("./sdk-types.generated");
18
19
  class SDKLogger {
19
20
  prefix = "[ForgeCartSDK]";
20
21
  info(message, data) {
@@ -47,6 +48,63 @@ class QueryObservable extends rxjs_1.Observable {
47
48
  }
48
49
  }
49
50
  exports.QueryObservable = QueryObservable;
51
+ /**
52
+ * The three GraphQL operation kinds. This is the discriminator the
53
+ * FIRST-VALUE deadline is scoped by, because only a subscription may
54
+ * legitimately wait minutes for its first value — so only a subscription
55
+ * carries no deadline at all (#1905).
56
+ */
57
+ var WsOperationKind;
58
+ (function (WsOperationKind) {
59
+ WsOperationKind["QUERY"] = "QUERY";
60
+ WsOperationKind["MUTATION"] = "MUTATION";
61
+ WsOperationKind["SUBSCRIPTION"] = "SUBSCRIPTION";
62
+ })(WsOperationKind || (WsOperationKind = {}));
63
+ /**
64
+ * The transport bounds, in milliseconds (#1905). Module-local on purpose:
65
+ * they are the SDK's own contract rather than a consumer knob, so nothing
66
+ * here widens the public surface or moves a tracked .d.ts.
67
+ *
68
+ * CONNECTION_ACK bounds the graphql-ws handshake socket-wide. The server
69
+ * sends connection_ack only after onConnect resolves — up to three DB
70
+ * round-trips here — so 8 s is about an order of magnitude above a healthy
71
+ * handshake, and deliberately BELOW the read deadline: a dead socket has
72
+ * already closed and re-dialled before any consumer gives up on it.
73
+ *
74
+ * QUERY_FIRST_VALUE bounds a read. Three independent ceilings put it under
75
+ * 15 s — the dashboard per-assertion budget, the 15 s this repo already
76
+ * imposes on a raw WS op under a manufactured held-transaction convoy, and
77
+ * a healthy full-shell boot at ~1.7 s. 10 s is roughly 20x a healthy admin
78
+ * read and still leaves e2e margin.
79
+ *
80
+ * MUTATION_FIRST_VALUE bounds a write. A write is not idempotent, so failing
81
+ * one that may have committed is the expensive direction; the house already
82
+ * accepts that honesty on a CLOSE (WS_MUTATION_DELIVERY_INTERRUPTED), and
83
+ * silence is weaker evidence than a close. 60 s is above every mutation a UI
84
+ * flow can await today and still finite, so no spinner spins forever.
85
+ */
86
+ var WsTimeoutBudgetMs;
87
+ (function (WsTimeoutBudgetMs) {
88
+ WsTimeoutBudgetMs[WsTimeoutBudgetMs["CONNECTION_ACK"] = 8000] = "CONNECTION_ACK";
89
+ WsTimeoutBudgetMs[WsTimeoutBudgetMs["QUERY_FIRST_VALUE"] = 10000] = "QUERY_FIRST_VALUE";
90
+ WsTimeoutBudgetMs[WsTimeoutBudgetMs["MUTATION_FIRST_VALUE"] = 60000] = "MUTATION_FIRST_VALUE";
91
+ })(WsTimeoutBudgetMs || (WsTimeoutBudgetMs = {}));
92
+ /**
93
+ * The per-OPERATION first-value budgets (#2245). A kind default sizes the
94
+ * average operation of that kind; an operation that holds the socket for a
95
+ * BOUNDED piece of server work must cover that work, or the client bound —
96
+ * armed first, at SEND — wins the race and the server's own degradation
97
+ * contract becomes unreachable: the packer's 60 s inline budget under an
98
+ * equal 60 s MUTATION_FIRST_VALUE made every fallback a WEBSOCKET_TIMEOUT.
99
+ *
100
+ * Generated from the SDK generator's declarations, where each entry carries
101
+ * the server constants it covers and a unit test pins it to them. Keyed by
102
+ * operation NAME — what the transport recovers from the document it is about
103
+ * to send, and the identity of the server path being bounded.
104
+ */
105
+ const WS_FIRST_VALUE_BUDGET_MS_BY_OPERATION = {
106
+ RefreshShippingRateGroups: 90_000,
107
+ };
50
108
  // Liveness of each underlying socket, keyed on the WsClient because
51
109
  // fork()ed clients share one socket. An operation that existed while its
52
110
  // socket was ACK-live may already sit on the server — that is the arming
@@ -124,6 +182,15 @@ class BaseGraphQLClient {
124
182
  headers: this.getHeaders(),
125
183
  }),
126
184
  lazyCloseTimeout: 15_000,
185
+ // Without this graphql-ws never waits for connection_ack at all: the
186
+ // option defaults to 0 and the timer is armed only for a finite value
187
+ // > 0, so a socket whose ack never arrived stayed OPEN forever. No
188
+ // operation-level bound can repair that — a bound ends one operation,
189
+ // this ends the dead socket and re-dials. On expiry graphql-ws closes
190
+ // with CloseCode.ConnectionAcknowledgementTimeout = 4504 (the option's
191
+ // own doc comment says 4418 and is stale), which is deliberately NOT in
192
+ // its fatal list, so shouldRetry below keeps healing exactly as before.
193
+ connectionAckWaitTimeout: WsTimeoutBudgetMs.CONNECTION_ACK,
127
194
  // graphql-ws treats a non-101 upgrade response as FATAL by
128
195
  // default (zero retries) — a fresh handshake landing on a
129
196
  // transient refusal (LB blip, server backlog under load) dies
@@ -277,13 +344,13 @@ class BaseGraphQLClient {
277
344
  }
278
345
  }
279
346
  query(document, variables) {
280
- return this.executeWsOperation(document, variables, false);
347
+ return this.executeWsOperation(document, variables, WsOperationKind.QUERY);
281
348
  }
282
349
  mutate(document, variables) {
283
350
  if (variables && this.containsFiles(variables)) {
284
351
  return this.upload(document, variables);
285
352
  }
286
- return this.executeWsOperation(document, variables, true);
353
+ return this.executeWsOperation(document, variables, WsOperationKind.MUTATION);
287
354
  }
288
355
  /**
289
356
  * One GraphQL operation over the shared graphql-ws socket.
@@ -293,7 +360,7 @@ class BaseGraphQLClient {
293
360
  * subscriptions; wrong for mutations: a re-sent create races its own
294
361
  * first attempt (observed: activatePlugin re-sent under load — the
295
362
  * winner committed, the caller received the loser's duplicate-name
296
- * error). With `singleDelivery` the operation arms once a live (ACKed)
363
+ * error). For a MUTATION the guard arms once a live (ACKed)
297
364
  * socket could have carried it; a close while armed fails the operation
298
365
  * with WS_MUTATION_DELIVERY_INTERRUPTED instead of silently
299
366
  * re-executing it — the in-flight attempt's outcome is genuinely
@@ -301,15 +368,24 @@ class BaseGraphQLClient {
301
368
  * BEFORE the first ACK stay retryable, so shouldRetry keeps healing
302
369
  * transient non-101 handshake refusals for mutations too.
303
370
  *
304
- * The operation also carries a HANDSHAKE bound (#2102) — never an
305
- * operation-lifetime one. subscribe() IS query() here, so a deadline on
306
- * the whole operation would kill every long-lived subscription; the bound
307
- * is armed only while the socket has not ACKed, and once it has, the wait
308
- * is the server streaming and nothing bounds it.
371
+ * The operation carries TWO bounds, and KIND is what tells them apart.
372
+ * The HANDSHAKE bound (#2102) is armed only while the socket has not ACKed
373
+ * and ends an operation no socket could have carried. The FIRST-VALUE
374
+ * deadline (#1905) covers the other half of the same hang — an ACKed socket
375
+ * that simply withholds the reply, which no bound reached: a read gives up
376
+ * at 10 s, a write at 60 s, and a subscription never, because its first
377
+ * value may be minutes away by design. It measures the wait for the first
378
+ * sink callback, never the operation's lifetime, so a connected stream runs
379
+ * for as long as the server streams it. Both bounds raise the same typed
380
+ * code, so one consumer branch answers for both.
309
381
  */
310
- executeWsOperation(document, variables, singleDelivery) {
382
+ executeWsOperation(document, variables, kind) {
311
383
  return new QueryObservable((subscriber) => {
312
384
  const client = this.getWsClient();
385
+ // A MUTATION property, unchanged in meaning by the kind discriminator
386
+ // that replaced the boolean this method used to take.
387
+ const singleDelivery = kind === WsOperationKind.MUTATION;
388
+ const firstValueBudgetMs = this.getFirstValueBudgetMs(kind, this.operationNameOf(document));
313
389
  let disposed = false;
314
390
  // Delivery latch: once ANY sink callback has fired, the wire has
315
391
  // spoken and a socket close can no longer mean "delivery unknown".
@@ -322,10 +398,23 @@ class BaseGraphQLClient {
322
398
  // any handler logic so every interleave is covered.
323
399
  let settled = false;
324
400
  let connectionTimer;
401
+ // The FIRST-VALUE deadline (#1905). Its handle is typed the same
402
+ // runtime-neutral way as the handshake bound's: node hands back a Timeout
403
+ // object and a browser a number, and the generated client must typecheck
404
+ // in both without an @types/node-only name.
405
+ let operationDeadline;
325
406
  // This operation's entry in the socket's pending-handshake registry,
326
407
  // present for exactly as long as the bound is armed (#2102).
327
408
  let pendingEntry;
328
409
  const offConnectionEvents = [];
410
+ // Disarms the first-value deadline. Reached on the first sink callback
411
+ // and on teardown — the two ways an operation stops waiting for a value.
412
+ const clearOperationDeadline = () => {
413
+ if (operationDeadline === undefined)
414
+ return;
415
+ clearTimeout(operationDeadline);
416
+ operationDeadline = undefined;
417
+ };
329
418
  // Disarms the bound AND deregisters the operation, because those are one
330
419
  // fact: a handshake that no longer needs bounding is one dispose() no
331
420
  // longer has to settle. Reached on the ACK, on the delivery latch and on
@@ -340,13 +429,50 @@ class BaseGraphQLClient {
340
429
  clearTimeout(connectionTimer);
341
430
  connectionTimer = undefined;
342
431
  };
343
- // The wire answering IS proof the handshake completed, so the latch and
344
- // the handshake bound fall together — and a timer that outlived its
345
- // operation would hold the event loop open (a hung test worker).
432
+ // The wire answering IS proof the handshake completed AND the first value
433
+ // arrived, so the latch and BOTH bounds fall together — and a timer that
434
+ // outlived its operation would hold the event loop open (a hung worker).
346
435
  const settle = () => {
347
436
  settled = true;
437
+ clearOperationDeadline();
348
438
  clearConnectionTimeout();
349
439
  };
440
+ // Armed BEFORE the operation is sent, so the budget measures the caller's
441
+ // own wait rather than a window that opens once graphql-ws gets round to
442
+ // it. A subscription has no budget and arms nothing at all (#1905).
443
+ if (firstValueBudgetMs !== undefined) {
444
+ operationDeadline = setTimeout(() => {
445
+ operationDeadline = undefined;
446
+ // The #2102 doctrine, for the same reason: unreffed, this bound outlives
447
+ // its client and fires under whatever event loop is alive then, so an
448
+ // operation with nothing left to report must report NOTHING rather than
449
+ // erroring onto whoever happens to be running.
450
+ if (disposed || settled || this.disposed || (WS_CONNECTION_STATE.get(client)?.disposed ?? false))
451
+ return;
452
+ // While an unanswered HANDSHAKE bound is armed and comes due no later
453
+ // than this one, it owns the failure: it names the socket that never
454
+ // ACKed, which is the more specific fault, and both errors carry the
455
+ // same code anyway. At the shipped defaults the two coincide exactly
456
+ // (10_000 ms), so without this the winner would be arming order.
457
+ if (connectionTimer !== undefined && this.connectionTimeout <= firstValueBudgetMs)
458
+ return;
459
+ const operationName = this.operationNameOf(document);
460
+ this.logger.error("WS operation timed out before its first value", {
461
+ operation: operationName,
462
+ kind,
463
+ timeoutMs: firstValueBudgetMs,
464
+ });
465
+ // subscriber.error tears the subscription down synchronously, disposing
466
+ // the pending graphql-ws operation before its retry loop can re-send
467
+ // what this caller has already given up on.
468
+ subscriber.error(this.wsTimeoutError(sdk_types_generated_1.SdkErrorCode.WEBSOCKET_TIMEOUT, operationName, kind, firstValueBudgetMs));
469
+ }, firstValueBudgetMs);
470
+ // Same unref reasoning as the handshake bound: the deadline must FIRE
471
+ // while the app is alive without ever being the reason it stays alive.
472
+ const deadlineHandle = operationDeadline;
473
+ if (typeof deadlineHandle === "object" && typeof deadlineHandle.unref === "function")
474
+ deadlineHandle.unref();
475
+ }
350
476
  const cleanup = client.subscribe({
351
477
  query: document,
352
478
  variables,
@@ -423,8 +549,13 @@ class BaseGraphQLClient {
423
549
  endpoint: this.endpoint,
424
550
  timeoutMs,
425
551
  });
426
- const message = "WS_CONNECTION_TIMEOUT";
427
- subscriber.error(new ClientError({ errors: [{ message, extensions: { endpoint: this.endpoint, timeoutMs } }] }, message));
552
+ // Carries the SAME typed code the first-value deadline raises (#1905).
553
+ // Every consumer reads extensions.code (extractErrorCode / isErrorCode
554
+ // in error-utils.ts) and this error had none, so no guard could branch
555
+ // on it however loud the message was. The MESSAGE stays
556
+ // WS_CONNECTION_TIMEOUT: the two bounds must remain distinguishable to
557
+ // a human reading a log and identical to a consumer reading the code.
558
+ subscriber.error(this.wsTimeoutError("WS_CONNECTION_TIMEOUT", this.operationNameOf(document), kind, timeoutMs, { endpoint: this.endpoint, timeoutMs }));
428
559
  }, this.connectionTimeout);
429
560
  // The bound must FIRE while the app is alive, but it must never be the
430
561
  // reason the app stays alive: a pending handshake is something the host
@@ -472,6 +603,7 @@ class BaseGraphQLClient {
472
603
  }
473
604
  return () => {
474
605
  disposed = true;
606
+ clearOperationDeadline();
475
607
  clearConnectionTimeout();
476
608
  for (const off of offConnectionEvents)
477
609
  off();
@@ -479,8 +611,14 @@ class BaseGraphQLClient {
479
611
  };
480
612
  });
481
613
  }
614
+ /**
615
+ * A live tail. It is NOT query() any more (#1905): a subscription is the one
616
+ * kind whose first value may legitimately be minutes away, so it is the one
617
+ * kind that carries no first-value deadline. The HANDSHAKE bound still
618
+ * applies — a socket that never ACKed carried no operation, stream or not.
619
+ */
482
620
  subscribe(document, variables) {
483
- return this.query(document, variables);
621
+ return this.executeWsOperation(document, variables, WsOperationKind.SUBSCRIPTION);
484
622
  }
485
623
  upload(document, variables) {
486
624
  return new QueryObservable((subscriber) => {
@@ -499,6 +637,56 @@ class BaseGraphQLClient {
499
637
  return undefined;
500
638
  return { "forgecart-transaction-token": this.transactionToken };
501
639
  }
640
+ /**
641
+ * The first-value budget for this operation, or undefined when it carries
642
+ * none. A get*, not a find*: derived configuration, never a lookup (#1905).
643
+ *
644
+ * The OPERATION's declared budget wins over its kind default (#2245): a
645
+ * kind default sizes the average operation, and one whose server work is
646
+ * itself bounded in seconds must cover that bound, or the client always
647
+ * wins the race and hides the server's own fallback behind a transport
648
+ * error.
649
+ */
650
+ getFirstValueBudgetMs(kind, operationName) {
651
+ // A SUBSCRIPTION is the one kind whose first value may legitimately be
652
+ // minutes away, so it carries no bound and no declaration can give it one.
653
+ if (kind === WsOperationKind.SUBSCRIPTION)
654
+ return undefined;
655
+ const declared = WS_FIRST_VALUE_BUDGET_MS_BY_OPERATION[operationName];
656
+ if (declared !== undefined)
657
+ return declared;
658
+ if (kind === WsOperationKind.QUERY)
659
+ return WsTimeoutBudgetMs.QUERY_FIRST_VALUE;
660
+ return WsTimeoutBudgetMs.MUTATION_FIRST_VALUE;
661
+ }
662
+ /**
663
+ * The name the document declares: `query ChannelPlugins` gives
664
+ * "ChannelPlugins". Every generated document is a named operation, so the
665
+ * fallback serves only a hand-written anonymous one — and a timeout that
666
+ * cannot say WHICH operation stalled is most of a forensic dead end.
667
+ */
668
+ operationNameOf(document) {
669
+ const named = /\b(?:query|mutation|subscription)\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(document);
670
+ return named?.[1] ?? "anonymous";
671
+ }
672
+ /**
673
+ * The ONE typed error both transport bounds raise (#1905). `code` is what
674
+ * consumers actually read — extractErrorCode / isErrorCode duck-type
675
+ * response.errors[0].extensions.code (error-utils.ts) — so a bound without
676
+ * one is invisible to them however loud its message is. `variables` is the
677
+ * uniform, i18n-ready channel the house error contract ships (codes on the
678
+ * wire, copy owned by the frontend); `detail` carries whatever attribution
679
+ * is specific to the bound that raised it, such as #2102's endpoint.
680
+ */
681
+ wsTimeoutError(message, operationName, kind, timeoutMs, detail) {
682
+ const extensions = {
683
+ ...detail,
684
+ code: sdk_types_generated_1.SdkErrorCode.WEBSOCKET_TIMEOUT,
685
+ classification: "TRANSPORT_ERROR",
686
+ variables: { operationName, kind, timeoutMs: String(timeoutMs) },
687
+ };
688
+ return new ClientError({ errors: [{ message, extensions }] }, message);
689
+ }
502
690
  /**
503
691
  * Uniform error contract for the sink-level error path. graphql-ws
504
692
  * delivers a server ErrorMessage payload as a raw GraphQLError[] —
@@ -187,7 +187,7 @@ export declare const adminAdminDeploymentStatusChangedDocument = "subscription A
187
187
  export declare const adminEcomConnectionsDocument = "query EcomConnections {\n ecomConnections {\n ...EcomConnectionFields\n }\n}\n\nfragment EcomConnectionFields on EcomConnection {\n id\n createdAt\n updatedAt\n providerCode\n externalAccountId\n externalScope\n status\n statusErrorCode\n commerceMode\n syncCatalog\n syncInventory\n ingestOrders\n syncCustomers\n orchestrateRefunds\n inventoryShortfallPolicy\n ingestExternalStockAdjustments\n defaultStockLocationId\n shopCurrencyCode\n channelPluginId\n}";
188
188
  export declare const adminEcomConnectionDocument = "query EcomConnection($id: ID!) {\n ecomConnection(id: $id) {\n ...EcomConnectionFields\n }\n}\n\nfragment EcomConnectionFields on EcomConnection {\n id\n createdAt\n updatedAt\n providerCode\n externalAccountId\n externalScope\n status\n statusErrorCode\n commerceMode\n syncCatalog\n syncInventory\n ingestOrders\n syncCustomers\n orchestrateRefunds\n inventoryShortfallPolicy\n ingestExternalStockAdjustments\n defaultStockLocationId\n shopCurrencyCode\n channelPluginId\n}";
189
189
  export declare const adminEcomSyncHealthDocument = "query EcomSyncHealth($connectionId: ID!) {\n ecomSyncHealth(connectionId: $connectionId) {\n connectionId\n status\n statusErrorCode\n lastReconcileAt\n consecutiveFailureCount\n cursors\n blockedEventCount\n failedEventCount\n domains {\n domain\n pending\n pushing\n synced\n error\n orphaned\n archived\n pendingExternal\n oldestPendingAgeSeconds\n }\n }\n}";
190
- export declare const adminEcomBlockedInboundEventsDocument = "query EcomBlockedInboundEvents($connectionId: ID!) {\n ecomBlockedInboundEvents(connectionId: $connectionId) {\n ...EcomInboundEventFields\n }\n}\n\nfragment EcomInboundEventFields on EcomInboundEvent {\n id\n createdAt\n connectionId\n providerCode\n extEventId\n topic\n extResourceId\n status\n attempts\n lastErrorCode\n processedAt\n}";
190
+ export declare const adminEcomBlockedInboundEventsDocument = "query EcomBlockedInboundEvents($connectionId: ID!) {\n ecomBlockedInboundEvents(connectionId: $connectionId) {\n ...EcomInboundEventFields\n }\n}\n\nfragment EcomInboundEventFields on EcomInboundEvent {\n id\n createdAt\n connectionId\n providerCode\n extEventId\n topic\n extResourceId\n status\n attempts\n lastErrorCode\n platformMessage\n processedAt\n}";
191
191
  export declare const adminCreateEcomConnectionDocument = "mutation CreateEcomConnection($input: CreateEcomConnectionInput!) {\n createEcomConnection(input: $input) {\n ...EcomConnectionFields\n }\n}\n\nfragment EcomConnectionFields on EcomConnection {\n id\n createdAt\n updatedAt\n providerCode\n externalAccountId\n externalScope\n status\n statusErrorCode\n commerceMode\n syncCatalog\n syncInventory\n ingestOrders\n syncCustomers\n orchestrateRefunds\n inventoryShortfallPolicy\n ingestExternalStockAdjustments\n defaultStockLocationId\n shopCurrencyCode\n channelPluginId\n}";
192
192
  export declare const adminUpdateEcomConnectionDocument = "mutation UpdateEcomConnection($input: UpdateEcomConnectionInput!) {\n updateEcomConnection(input: $input) {\n ...EcomConnectionFields\n }\n}\n\nfragment EcomConnectionFields on EcomConnection {\n id\n createdAt\n updatedAt\n providerCode\n externalAccountId\n externalScope\n status\n statusErrorCode\n commerceMode\n syncCatalog\n syncInventory\n ingestOrders\n syncCustomers\n orchestrateRefunds\n inventoryShortfallPolicy\n ingestExternalStockAdjustments\n defaultStockLocationId\n shopCurrencyCode\n channelPluginId\n}";
193
193
  export declare const adminPauseEcomConnectionDocument = "mutation PauseEcomConnection($id: ID!) {\n pauseEcomConnection(id: $id) {\n ...EcomConnectionFields\n }\n}\n\nfragment EcomConnectionFields on EcomConnection {\n id\n createdAt\n updatedAt\n providerCode\n externalAccountId\n externalScope\n status\n statusErrorCode\n commerceMode\n syncCatalog\n syncInventory\n ingestOrders\n syncCustomers\n orchestrateRefunds\n inventoryShortfallPolicy\n ingestExternalStockAdjustments\n defaultStockLocationId\n shopCurrencyCode\n channelPluginId\n}";
@@ -195,11 +195,11 @@ export declare const adminResumeEcomConnectionDocument = "mutation ResumeEcomCon
195
195
  export declare const adminDeleteEcomConnectionDocument = "mutation DeleteEcomConnection($id: ID!) {\n deleteEcomConnection(id: $id) {\n ...EcomConnectionFields\n }\n}\n\nfragment EcomConnectionFields on EcomConnection {\n id\n createdAt\n updatedAt\n providerCode\n externalAccountId\n externalScope\n status\n statusErrorCode\n commerceMode\n syncCatalog\n syncInventory\n ingestOrders\n syncCustomers\n orchestrateRefunds\n inventoryShortfallPolicy\n ingestExternalStockAdjustments\n defaultStockLocationId\n shopCurrencyCode\n channelPluginId\n}";
196
196
  export declare const adminRetryEcomConnectionDocument = "mutation RetryEcomConnection($id: ID!) {\n retryEcomConnection(id: $id) {\n ...EcomConnectionFields\n }\n}\n\nfragment EcomConnectionFields on EcomConnection {\n id\n createdAt\n updatedAt\n providerCode\n externalAccountId\n externalScope\n status\n statusErrorCode\n commerceMode\n syncCatalog\n syncInventory\n ingestOrders\n syncCustomers\n orchestrateRefunds\n inventoryShortfallPolicy\n ingestExternalStockAdjustments\n defaultStockLocationId\n shopCurrencyCode\n channelPluginId\n}";
197
197
  export declare const adminTriggerEcomReconcileDocument = "mutation TriggerEcomReconcile($connectionId: ID!) {\n triggerEcomReconcile(connectionId: $connectionId) {\n ...EcomConnectionFields\n }\n}\n\nfragment EcomConnectionFields on EcomConnection {\n id\n createdAt\n updatedAt\n providerCode\n externalAccountId\n externalScope\n status\n statusErrorCode\n commerceMode\n syncCatalog\n syncInventory\n ingestOrders\n syncCustomers\n orchestrateRefunds\n inventoryShortfallPolicy\n ingestExternalStockAdjustments\n defaultStockLocationId\n shopCurrencyCode\n channelPluginId\n}";
198
- export declare const adminRetryEcomInboundEventDocument = "mutation RetryEcomInboundEvent($eventId: ID!) {\n retryEcomInboundEvent(eventId: $eventId) {\n ...EcomInboundEventFields\n }\n}\n\nfragment EcomInboundEventFields on EcomInboundEvent {\n id\n createdAt\n connectionId\n providerCode\n extEventId\n topic\n extResourceId\n status\n attempts\n lastErrorCode\n processedAt\n}";
199
- export declare const adminEcomVariantLinksDocument = "query EcomVariantLinks($connectionId: ID!) {\n ecomVariantLinks(connectionId: $connectionId) {\n ...EcomVariantLinkFields\n }\n}\n\nfragment EcomVariantLinkFields on EcomVariantLink {\n id\n createdAt\n updatedAt\n connectionId\n productId\n variantId\n extProductId\n extVariantId\n extInventoryItemId\n syncState\n desiredState\n lastErrorCode\n attempts\n lastPushedAt\n}";
198
+ export declare const adminRetryEcomInboundEventDocument = "mutation RetryEcomInboundEvent($eventId: ID!) {\n retryEcomInboundEvent(eventId: $eventId) {\n ...EcomInboundEventFields\n }\n}\n\nfragment EcomInboundEventFields on EcomInboundEvent {\n id\n createdAt\n connectionId\n providerCode\n extEventId\n topic\n extResourceId\n status\n attempts\n lastErrorCode\n platformMessage\n processedAt\n}";
199
+ export declare const adminEcomVariantLinksDocument = "query EcomVariantLinks($connectionId: ID!) {\n ecomVariantLinks(connectionId: $connectionId) {\n ...EcomVariantLinkFields\n }\n}\n\nfragment EcomVariantLinkFields on EcomVariantLink {\n id\n createdAt\n updatedAt\n connectionId\n productId\n variantId\n extProductId\n extVariantId\n extInventoryItemId\n syncState\n desiredState\n lastErrorCode\n platformMessage\n attempts\n lastPushedAt\n}";
200
200
  export declare const adminTriggerEcomBackfillDocument = "mutation TriggerEcomBackfill($connectionId: ID!) {\n triggerEcomBackfill(connectionId: $connectionId) {\n ...EcomConnectionFields\n }\n}\n\nfragment EcomConnectionFields on EcomConnection {\n id\n createdAt\n updatedAt\n providerCode\n externalAccountId\n externalScope\n status\n statusErrorCode\n commerceMode\n syncCatalog\n syncInventory\n ingestOrders\n syncCustomers\n orchestrateRefunds\n inventoryShortfallPolicy\n ingestExternalStockAdjustments\n defaultStockLocationId\n shopCurrencyCode\n channelPluginId\n}";
201
- export declare const adminRetryEcomVariantLinkDocument = "mutation RetryEcomVariantLink($input: RetryEcomVariantLinkInput!) {\n retryEcomVariantLink(input: $input) {\n ...EcomVariantLinkFields\n }\n}\n\nfragment EcomVariantLinkFields on EcomVariantLink {\n id\n createdAt\n updatedAt\n connectionId\n productId\n variantId\n extProductId\n extVariantId\n extInventoryItemId\n syncState\n desiredState\n lastErrorCode\n attempts\n lastPushedAt\n}";
202
- export declare const adminRelinkEcomVariantDocument = "mutation RelinkEcomVariant($input: RelinkEcomVariantInput!) {\n relinkEcomVariant(input: $input) {\n ...EcomVariantLinkFields\n }\n}\n\nfragment EcomVariantLinkFields on EcomVariantLink {\n id\n createdAt\n updatedAt\n connectionId\n productId\n variantId\n extProductId\n extVariantId\n extInventoryItemId\n syncState\n desiredState\n lastErrorCode\n attempts\n lastPushedAt\n}";
201
+ export declare const adminRetryEcomVariantLinkDocument = "mutation RetryEcomVariantLink($input: RetryEcomVariantLinkInput!) {\n retryEcomVariantLink(input: $input) {\n ...EcomVariantLinkFields\n }\n}\n\nfragment EcomVariantLinkFields on EcomVariantLink {\n id\n createdAt\n updatedAt\n connectionId\n productId\n variantId\n extProductId\n extVariantId\n extInventoryItemId\n syncState\n desiredState\n lastErrorCode\n platformMessage\n attempts\n lastPushedAt\n}";
202
+ export declare const adminRelinkEcomVariantDocument = "mutation RelinkEcomVariant($input: RelinkEcomVariantInput!) {\n relinkEcomVariant(input: $input) {\n ...EcomVariantLinkFields\n }\n}\n\nfragment EcomVariantLinkFields on EcomVariantLink {\n id\n createdAt\n updatedAt\n connectionId\n productId\n variantId\n extProductId\n extVariantId\n extInventoryItemId\n syncState\n desiredState\n lastErrorCode\n platformMessage\n attempts\n lastPushedAt\n}";
203
203
  export declare const adminEcomLocationLinksDocument = "query EcomLocationLinks($connectionId: ID!) {\n ecomLocationLinks(connectionId: $connectionId) {\n ...EcomLocationLinkFields\n }\n}\n\nfragment EcomLocationLinkFields on EcomLocationLink {\n id\n stockLocationId\n extLocationId\n authority\n}";
204
204
  export declare const adminEcomExternalLocationsDocument = "query EcomExternalLocations($connectionId: ID!) {\n ecomExternalLocations(connectionId: $connectionId) {\n extLocationId\n name\n active\n }\n}";
205
205
  export declare const adminSetEcomLocationLinksDocument = "mutation SetEcomLocationLinks($input: SetEcomLocationLinksInput!) {\n setEcomLocationLinks(input: $input) {\n ...EcomLocationLinkFields\n }\n}\n\nfragment EcomLocationLinkFields on EcomLocationLink {\n id\n stockLocationId\n extLocationId\n authority\n}";
@@ -207,7 +207,7 @@ export declare const adminEcomGdprRequestsDocument = "query EcomGdprRequests($co
207
207
  export declare const adminCompleteEcomGdprRequestDocument = "mutation CompleteEcomGdprRequest($id: ID!) {\n completeEcomGdprRequest(id: $id) {\n ...EcomGdprRequestFields\n }\n}\n\nfragment EcomGdprRequestFields on EcomGdprRequest {\n id\n createdAt\n updatedAt\n connectionId\n providerCode\n kind\n status\n extRequestId\n extCustomerId\n customerId\n subjectEmail\n extOrderIds\n dueAt\n completedAt\n}";
208
208
  export declare const adminRefundExternalPaymentDocument = "mutation RefundExternalPayment($input: CreateRefundInput!) {\n refundExternalPayment(input: $input) {\n id\n createdAt\n updatedAt\n total\n reason\n state\n transactionId\n method\n paymentId\n }\n}";
209
209
  export declare const adminRetryExternalRefundDocument = "mutation RetryExternalRefund($refundId: ID!) {\n retryExternalRefund(refundId: $refundId) {\n id\n createdAt\n updatedAt\n total\n reason\n state\n transactionId\n method\n paymentId\n }\n}";
210
- export declare const adminEcomInboundEventsDocument = "query EcomInboundEvents($connectionId: ID!) {\n ecomInboundEvents(connectionId: $connectionId) {\n ...EcomInboundEventFields\n }\n}\n\nfragment EcomInboundEventFields on EcomInboundEvent {\n id\n createdAt\n connectionId\n providerCode\n extEventId\n topic\n extResourceId\n status\n attempts\n lastErrorCode\n processedAt\n}";
210
+ export declare const adminEcomInboundEventsDocument = "query EcomInboundEvents($connectionId: ID!) {\n ecomInboundEvents(connectionId: $connectionId) {\n ...EcomInboundEventFields\n }\n}\n\nfragment EcomInboundEventFields on EcomInboundEvent {\n id\n createdAt\n connectionId\n providerCode\n extEventId\n topic\n extResourceId\n status\n attempts\n lastErrorCode\n platformMessage\n processedAt\n}";
211
211
  export declare const adminEcomOrderLinkDocument = "query EcomOrderLink($orderId: ID!) {\n order(id: $orderId) {\n id\n ecomOrderLink {\n ...EcomOrderLinkFields\n }\n }\n}\n\nfragment EcomOrderLinkFields on EcomOrderLink {\n id\n createdAt\n updatedAt\n connectionId\n providerCode\n orderId\n extOrderId\n extOrderNumber\n source\n state\n correlationId\n financialStatus\n externalVersion\n appliedAt\n lineMap\n}";
212
212
  export declare const adminEcomOrderRefundLinksDocument = "query EcomOrderRefundLinks($orderId: ID!) {\n order(id: $orderId) {\n id\n payments {\n id\n refunds {\n id\n ecomRefundLink {\n ...EcomRefundLinkFields\n }\n }\n }\n }\n}\n\nfragment EcomRefundLinkFields on EcomRefundLink {\n id\n createdAt\n updatedAt\n connectionId\n providerCode\n refundId\n paymentId\n orderLinkId\n extRefundId\n cid\n direction\n state\n}";
213
213
  export declare const adminAdminEmailLayoutsDocument = "query AdminEmailLayouts {\n emailLayouts {\n ...EmailLayoutDetail\n }\n}\n\nfragment EmailLayoutDetail on EmailLayout {\n id\n createdAt\n updatedAt\n name\n bodyMjml\n source\n isDefault\n}";
@@ -6656,6 +6656,7 @@ fragment EcomInboundEventFields on EcomInboundEvent {
6656
6656
  status
6657
6657
  attempts
6658
6658
  lastErrorCode
6659
+ platformMessage
6659
6660
  processedAt
6660
6661
  }`;
6661
6662
  exports.adminCreateEcomConnectionDocument = `mutation CreateEcomConnection($input: CreateEcomConnectionInput!) {
@@ -6864,6 +6865,7 @@ fragment EcomInboundEventFields on EcomInboundEvent {
6864
6865
  status
6865
6866
  attempts
6866
6867
  lastErrorCode
6868
+ platformMessage
6867
6869
  processedAt
6868
6870
  }`;
6869
6871
  exports.adminEcomVariantLinksDocument = `query EcomVariantLinks($connectionId: ID!) {
@@ -6885,6 +6887,7 @@ fragment EcomVariantLinkFields on EcomVariantLink {
6885
6887
  syncState
6886
6888
  desiredState
6887
6889
  lastErrorCode
6890
+ platformMessage
6888
6891
  attempts
6889
6892
  lastPushedAt
6890
6893
  }`;
@@ -6934,6 +6937,7 @@ fragment EcomVariantLinkFields on EcomVariantLink {
6934
6937
  syncState
6935
6938
  desiredState
6936
6939
  lastErrorCode
6940
+ platformMessage
6937
6941
  attempts
6938
6942
  lastPushedAt
6939
6943
  }`;
@@ -6956,6 +6960,7 @@ fragment EcomVariantLinkFields on EcomVariantLink {
6956
6960
  syncState
6957
6961
  desiredState
6958
6962
  lastErrorCode
6963
+ platformMessage
6959
6964
  attempts
6960
6965
  lastPushedAt
6961
6966
  }`;
@@ -7077,6 +7082,7 @@ fragment EcomInboundEventFields on EcomInboundEvent {
7077
7082
  status
7078
7083
  attempts
7079
7084
  lastErrorCode
7085
+ platformMessage
7080
7086
  processedAt
7081
7087
  }`;
7082
7088
  exports.adminEcomOrderLinkDocument = `query EcomOrderLink($orderId: ID!) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forgecart/sdk",
3
- "version": "1.202609201502.0",
3
+ "version": "1.202609211357.0",
4
4
  "description": "ForgeCart Client SDK",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",