@apifuse/provider-sdk 2.2.0-beta.1 → 2.2.0-beta.3

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.
@@ -6,9 +6,10 @@ import { z } from "zod";
6
6
  import { AuthAbortError, createAuthFlowHelpers } from "../auth";
7
7
  import {
8
8
  AuthError,
9
+ isProviderError,
10
+ isSessionExpiredError,
11
+ isTransportError,
9
12
  ProviderError,
10
- SessionExpiredError,
11
- TransportError,
12
13
  } from "../errors";
13
14
  import {
14
15
  loadProviderLocaleCatalogs,
@@ -196,7 +197,7 @@ export function resolveProviderProxyAffinityKey(
196
197
  operationId: string,
197
198
  ): string {
198
199
  const connectionKey =
199
- request.connection?.id ?? request.connection?.externalRef;
200
+ resolveOperationConnectionId(request) ?? request.connection?.externalRef;
200
201
  const affinity =
201
202
  typeof provider.proxy === "object"
202
203
  ? provider.proxy.session?.affinity
@@ -207,6 +208,12 @@ export function resolveProviderProxyAffinityKey(
207
208
  return connectionKey ?? provider.id;
208
209
  }
209
210
 
211
+ function resolveOperationConnectionId(
212
+ request: OperationRequest,
213
+ ): string | undefined {
214
+ return request.connection?.id ?? request.connectionId;
215
+ }
216
+
210
217
  function createProviderContext(
211
218
  provider: ProviderDefinition,
212
219
  request: OperationRequest,
@@ -245,7 +252,7 @@ function createProviderContext(
245
252
  values: request.connection?.secrets,
246
253
  });
247
254
  const requestContext = {
248
- connectionId: request.connection?.id,
255
+ connectionId: resolveOperationConnectionId(request),
249
256
  headers: request.headers ?? {},
250
257
  };
251
258
  const context = wrapWithInstrumentation({
@@ -501,7 +508,7 @@ function toErrorResponse(
501
508
  error: unknown,
502
509
  requestId?: string,
503
510
  ): OperationErrorResponse {
504
- if (error instanceof ProviderError) {
511
+ if (isProviderError(error)) {
505
512
  const details = publicProviderErrorDetails(error);
506
513
  return {
507
514
  error: {
@@ -557,7 +564,12 @@ function isPlainRecord(value: unknown): value is Record<string, unknown> {
557
564
  return value !== null && typeof value === "object" && !Array.isArray(value);
558
565
  }
559
566
 
560
- function providerObservabilityDetails(error: ProviderError):
567
+ // Accepts `unknown` so the branded guards narrow cleanly from the top: the
568
+ // subtype error classes are structurally compatible with ProviderError, so
569
+ // narrowing from a ProviderError-typed value would collapse the negative branch
570
+ // to `never`. Narrowing from unknown avoids that while still recognizing errors
571
+ // from a duplicate SDK module instance.
572
+ function providerObservabilityDetails(error: unknown):
561
573
  | {
562
574
  category: ProviderErrorCategory;
563
575
  taxonomyVersion: string;
@@ -570,14 +582,14 @@ function providerObservabilityDetails(error: ProviderError):
570
582
  // operation (see design.md §4.3 D3). Without this branch the auth error would
571
583
  // serialize as a bare 401 with no retryable/category, losing the refresh
572
584
  // signal for exactly the retryOnAuthRefresh operations it is meant to enable.
573
- if (error instanceof SessionExpiredError) {
585
+ if (isSessionExpiredError(error)) {
574
586
  return {
575
587
  category: error.options?.category ?? "credential_expired",
576
588
  taxonomyVersion: PROVIDER_OBSERVABILITY_TAXONOMY_VERSION,
577
589
  retryable: error.options?.retryable ?? false,
578
590
  };
579
591
  }
580
- if (!(error instanceof TransportError)) {
592
+ if (!isTransportError(error)) {
581
593
  return undefined;
582
594
  }
583
595
  const isProxyPoolCode =
@@ -610,7 +622,7 @@ function providerObservabilityDetails(error: ProviderError):
610
622
  }
611
623
 
612
624
  function publicProviderErrorMessage(error: ProviderError): string {
613
- if (error instanceof TransportError) {
625
+ if (isTransportError(error)) {
614
626
  if (error.code === PROXY_AUTH_IP_DENIED_CODE) {
615
627
  return error.message;
616
628
  }
@@ -640,11 +652,11 @@ function toStatusCode(
640
652
  return 400;
641
653
  }
642
654
 
643
- if (error instanceof TransportError) {
655
+ if (isTransportError(error)) {
644
656
  return error.code === "transport_timeout" ? 504 : 502;
645
657
  }
646
658
 
647
- if (error instanceof ProviderError) {
659
+ if (isProviderError(error)) {
648
660
  switch (error.code) {
649
661
  case "AUTH_REQUIRED":
650
662
  case "reauth_required":
@@ -691,7 +703,7 @@ function logProviderError(
691
703
  cost: ProviderRequestCost,
692
704
  ): void {
693
705
  const code =
694
- error instanceof ProviderError
706
+ isProviderError(error)
695
707
  ? (error.code ?? "provider_error")
696
708
  : error instanceof z.ZodError
697
709
  ? "invalid_request"
@@ -699,7 +711,7 @@ function logProviderError(
699
711
  const errorClass = error instanceof Error ? error.name : typeof error;
700
712
  const message = error instanceof Error ? error.message : String(error);
701
713
  const details =
702
- error instanceof ProviderError
714
+ isProviderError(error)
703
715
  ? providerObservabilityDetails(error)
704
716
  : undefined;
705
717
  const emit =
@@ -716,7 +728,7 @@ function logProviderError(
716
728
  code,
717
729
  errorClass,
718
730
  message,
719
- ...(error instanceof TransportError && error.upstreamStatus
731
+ ...(isTransportError(error) && error.upstreamStatus
720
732
  ? { upstreamStatus: error.upstreamStatus }
721
733
  : {}),
722
734
  ...(details
@@ -21,6 +21,7 @@ export const OperationConnectionSchema = z.object({
21
21
  export const OperationRequestSchema = z.object({
22
22
  requestId: z.string(),
23
23
  input: z.record(z.string(), z.unknown()),
24
+ connectionId: z.string().optional(),
24
25
  connection: OperationConnectionSchema.optional(),
25
26
  headers: z.record(z.string(), z.string()).optional(),
26
27
  trace: z.record(z.string(), z.string()).optional(),