@financial-times/content-curation-client 5.1.0 → 5.3.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.
@@ -1,5 +1,10 @@
1
+ import { baseObjectOutputType } from 'zod';
2
+ import { objectUtil } from 'zod';
1
3
  import { Options } from 'tsup';
2
4
  import { z } from 'zod';
5
+ import { ZodLiteral } from 'zod';
6
+ import { ZodNumber } from 'zod';
7
+ import { ZodString } from 'zod';
3
8
  import { ZodTypeAny } from 'zod';
4
9
 
5
10
  /**
@@ -17,7 +22,7 @@ export { ApiClient }
17
22
  export { ApiClient as ApiClient_alias_1 }
18
23
 
19
24
  /**
20
- * Configuration options for the API client
25
+ * Configuration options for the API client.
21
26
  */
22
27
  declare type ApiClientConfig = {
23
28
  baseUrl: string;
@@ -34,21 +39,73 @@ export { ApiClientConfig }
34
39
  export { ApiClientConfig as ApiClientConfig_alias_1 }
35
40
 
36
41
  /**
37
- * API-level error thrown when { status: 'error' } is returned
42
+ * Base error type for all failures surfaced by the client package.
38
43
  */
39
44
  declare class ApiClientError extends Error {
40
- payload: z.infer<typeof ApiErrorPayloadSchema>;
41
- statusCode: number;
42
- requestId?: string | undefined;
43
- code: string;
45
+ /** The machine-readable error payload exposed by the client. */
46
+ payload: ApiClientErrorPayload;
47
+ /** The machine-readable error code. */
48
+ code: ApiClientErrorPayload["code"];
49
+ /** Additional diagnostic detail captured by the client. */
44
50
  details?: string;
51
+ /** The API path associated with the failing request. */
45
52
  path?: string;
53
+ /** Optional timestamp supplied by the upstream service. */
46
54
  timestamp?: string;
47
- constructor(payload: z.infer<typeof ApiErrorPayloadSchema>, statusCode: number, requestId?: string | undefined);
55
+ /** Indicates whether the failure originated from transport, gateway, or service handling. */
56
+ origin: ApiClientErrorOrigin;
57
+ /** The fully qualified request URL, when available. */
58
+ url?: string;
59
+ /** The response content type, when a response was received. */
60
+ contentType?: string;
61
+ /** A truncated copy of the raw response body, when captured. */
62
+ bodyText?: string;
63
+ /** The upstream request identifier, when available. */
64
+ requestId?: string;
65
+ /** The HTTP status code reported by the service or gateway. */
66
+ statusCode: number;
67
+ /** The underlying thrown error, if there was one. */
68
+ cause?: unknown;
69
+ constructor(payload: ApiClientErrorPayload, statusCode: number, requestId?: string, metadata?: ApiClientErrorMetadata);
48
70
  }
49
71
  export { ApiClientError }
50
72
  export { ApiClientError as ApiClientError_alias_1 }
51
73
 
74
+ /** Machine-readable codes exposed by the client error model. */
75
+ declare type ApiClientErrorCode = ApiErrorPayload["code"] | "API_GATEWAY_ERROR" | "API_TRANSPORT_ERROR";
76
+ export { ApiClientErrorCode }
77
+ export { ApiClientErrorCode as ApiClientErrorCode_alias_1 }
78
+
79
+ declare type ApiClientErrorMetadata = {
80
+ origin: ApiClientErrorOrigin;
81
+ url?: string;
82
+ contentType?: string;
83
+ bodyText?: string;
84
+ cause?: unknown;
85
+ };
86
+
87
+ /** Where the failing request broke down. */
88
+ declare type ApiClientErrorOrigin = "transport" | "gateway" | "service";
89
+ export { ApiClientErrorOrigin }
90
+ export { ApiClientErrorOrigin as ApiClientErrorOrigin_alias_1 }
91
+
92
+ /**
93
+ * Shared error payload shape used by all client-generated errors.
94
+ *
95
+ * Service-origin errors use the validated `ApiErrorPayload` returned by the API.
96
+ * Gateway and transport errors synthesize the same top-level fields so callers
97
+ * can handle them consistently.
98
+ */
99
+ declare type ApiClientErrorPayload = {
100
+ code: ApiClientErrorCode;
101
+ message: string;
102
+ details?: string;
103
+ path?: string;
104
+ timestamp?: string;
105
+ };
106
+ export { ApiClientErrorPayload }
107
+ export { ApiClientErrorPayload as ApiClientErrorPayload_alias_1 }
108
+
52
109
  /**
53
110
  * Strongly‐typed enum for all possible API error codes.
54
111
  */
@@ -142,6 +199,18 @@ declare const ApiErrorResponseSchema: z.ZodObject<{
142
199
  export { ApiErrorResponseSchema }
143
200
  export { ApiErrorResponseSchema as ApiErrorResponseSchema_alias_1 }
144
201
 
202
+ /**
203
+ * Error raised when the request reached API Gateway but did not produce a
204
+ * valid service-level error envelope.
205
+ */
206
+ declare class ApiGatewayError extends ApiClientError {
207
+ payload: ApiClientErrorPayload;
208
+ origin: "gateway";
209
+ constructor(payload: ApiClientErrorPayload, statusCode: number, requestId?: string, metadata?: Omit<ApiClientErrorMetadata, "origin">);
210
+ }
211
+ export { ApiGatewayError }
212
+ export { ApiGatewayError as ApiGatewayError_alias_1 }
213
+
145
214
  /**
146
215
  * Union of success or error envelopes, discriminated on `status`.
147
216
  */
@@ -213,6 +282,19 @@ declare function ApiResponseSchema<T extends ZodTypeAny>(dataSchema: T): z.ZodDi
213
282
  export { ApiResponseSchema }
214
283
  export { ApiResponseSchema as ApiResponseSchema_alias_1 }
215
284
 
285
+ /**
286
+ * Error raised when the root service returns a valid JSON API error envelope,
287
+ * or when a successful response cannot be interpreted as the expected API
288
+ * success envelope.
289
+ */
290
+ declare class ApiServiceError extends ApiClientError {
291
+ payload: ApiErrorPayload;
292
+ origin: "service";
293
+ constructor(payload: ApiErrorPayload, statusCode: number, requestId?: string, metadata?: Omit<ApiClientErrorMetadata, "origin">);
294
+ }
295
+ export { ApiServiceError }
296
+ export { ApiServiceError as ApiServiceError_alias_1 }
297
+
216
298
  /**
217
299
  * Schema for a successful API response, given some data schema T.
218
300
  */
@@ -238,11 +320,40 @@ declare function ApiSuccessResponseSchema<T extends ZodTypeAny>(dataSchema: T):
238
320
  export { ApiSuccessResponseSchema }
239
321
  export { ApiSuccessResponseSchema as ApiSuccessResponseSchema_alias_1 }
240
322
 
323
+ /**
324
+ * Error raised when the request fails before any HTTP response is available.
325
+ */
326
+ declare class ApiTransportError extends ApiClientError {
327
+ payload: ApiClientErrorPayload;
328
+ origin: "transport";
329
+ /** Whether the failure was caused by an abort, timeout, or generic network problem. */
330
+ transportKind: ApiTransportKind;
331
+ constructor(payload: ApiClientErrorPayload, statusCode: number, requestId: string | undefined, metadata: ApiTransportErrorMetadata);
332
+ }
333
+ export { ApiTransportError }
334
+ export { ApiTransportError as ApiTransportError_alias_1 }
335
+
336
+ declare type ApiTransportErrorMetadata = Omit<ApiClientErrorMetadata, "origin"> & {
337
+ transportKind: ApiTransportKind;
338
+ };
339
+
340
+ /** The transport failure mode when no HTTP response was received. */
341
+ declare type ApiTransportKind = "abort" | "timeout" | "network";
342
+ export { ApiTransportKind }
343
+ export { ApiTransportKind as ApiTransportKind_alias_1 }
344
+
345
+ /**
346
+ * Shared HTTP client for Content Curation API requests.
347
+ *
348
+ * The public sub-clients delegate to this class so request validation, fetch
349
+ * execution, response parsing, and error classification all happen in one place.
350
+ */
241
351
  export declare class BaseApiClient {
242
352
  protected config: ApiClientConfig;
243
353
  constructor(config: ApiClientConfig);
244
354
  /**
245
- * Generic HTTP request to a JSON API
355
+ * Performs a request against the JSON API, validates the response envelope,
356
+ * and returns the typed `data` payload on success.
246
357
  */
247
358
  protected request<ReqSchema extends ZodTypeAny | undefined, ResponseDataSchema extends ZodTypeAny>(method: "GET" | "PUT" | "POST" | "DELETE", path: string, opts: {
248
359
  requestSchema?: ReqSchema;
@@ -250,17 +361,56 @@ export declare class BaseApiClient {
250
361
  responseDataSchema: ResponseDataSchema;
251
362
  }): Promise<z.infer<ResponseDataSchema>>;
252
363
  /**
253
- * GET convenience method inferring response type from schema
364
+ * GET convenience method inferring response type from schema.
254
365
  */
255
366
  protected get<ResponseDataSchema extends ZodTypeAny>(path: string, responseDataSchema: ResponseDataSchema): Promise<z.infer<ResponseDataSchema>>;
256
367
  /**
257
- * PUT convenience method inferring both request and response types
368
+ * PUT convenience method inferring both request and response types.
258
369
  */
259
370
  protected put<ReqSchema extends ZodTypeAny, ResponseDataSchema extends ZodTypeAny>(path: string, body: z.infer<ReqSchema>, requestSchema: ReqSchema, responseDataSchema: ResponseDataSchema): Promise<z.infer<ResponseDataSchema>>;
260
371
  }
261
372
 
373
+ /**
374
+ * Builds a gateway-origin client error after the caller has already decided the response does not
375
+ * represent a validated service error envelope.
376
+ */
377
+ export declare function createGatewayError(path: string, url: string, statusCode: number, options: GatewayErrorOptions): ApiGatewayError;
378
+
379
+ /**
380
+ * Classifies a non-success HTTP response as either a validated service error or
381
+ * a gateway-origin failure.
382
+ */
383
+ declare function createResponseError(path: string, url: string, response: Response, responseBody: ResponseBodyDiagnostics): ApiGatewayError | ApiServiceError;
384
+ export { createResponseError }
385
+ export { createResponseError as createResponseError_alias_1 }
386
+
387
+ /**
388
+ * Wraps a fetch failure that happened before any response was available.
389
+ */
390
+ declare function createTransportError(path: string, url: string, error: unknown): ApiTransportError;
391
+ export { createTransportError }
392
+ export { createTransportError as createTransportError_alias_1 }
393
+
394
+ /**
395
+ * Builds the fallback service error used when a 2xx response cannot be interpreted as the
396
+ * expected Content Curation API success envelope.
397
+ */
398
+ export declare function createUnexpectedServiceResponseError(path: string, url: string, options: UnexpectedServiceResponseOptions): ApiServiceError;
399
+
262
400
  export declare const default_alias: Options | Options[] | ((overrideOptions: Options) => Options | Options[] | Promise<Options | Options[]>);
263
401
 
402
+ /**
403
+ * Builds the diagnostic detail string used when a non-success response should be treated as a
404
+ * gateway-origin failure rather than a validated service error.
405
+ */
406
+ export declare function describeGatewayResponse(statusCode: number, responseBody: ResponseBodyDiagnostics): string;
407
+
408
+ /**
409
+ * Builds the diagnostic detail string used when a 2xx response cannot be understood as the
410
+ * expected Content Curation API success envelope.
411
+ */
412
+ export declare function describeUnexpectedSuccessResponse(responseBody: ResponseBodyDiagnostics): string;
413
+
264
414
  declare type Draft = z.infer<typeof DraftSchema>;
265
415
  export { Draft }
266
416
  export { Draft as Draft_alias_1 }
@@ -1850,6 +2000,24 @@ declare type ExperimentSliceType = z.infer<typeof ExperimentSlice.OutputSchema>;
1850
2000
  export { ExperimentSliceType }
1851
2001
  export { ExperimentSliceType as ExperimentSliceType_alias_1 }
1852
2002
 
2003
+ declare type GatewayErrorOptions = {
2004
+ contentType?: string;
2005
+ bodyText?: string;
2006
+ details: string;
2007
+ requestId?: string;
2008
+ cause?: unknown;
2009
+ };
2010
+
2011
+ /**
2012
+ * Extracts the response content type, if one was provided.
2013
+ */
2014
+ export declare function getResponseContentType(response: Response): string | undefined;
2015
+
2016
+ /**
2017
+ * Extracts the upstream request identifier, if one was provided.
2018
+ */
2019
+ export declare function getResponseRequestId(response: Response): string | undefined;
2020
+
1853
2021
  declare const HeroSlice: {
1854
2022
  InputSchema: z.ZodObject<{
1855
2023
  type: z.ZodLiteral<"Hero">;
@@ -4462,6 +4630,11 @@ declare type InteractiveSliceType = z.infer<typeof InteractiveSlice.OutputSchema
4462
4630
  export { InteractiveSliceType }
4463
4631
  export { InteractiveSliceType as InteractiveSliceType_alias_1 }
4464
4632
 
4633
+ /**
4634
+ * Returns `true` when a status code should always be treated as an API Gateway failure.
4635
+ */
4636
+ export declare function isGatewayStatusCode(statusCode: number): boolean;
4637
+
4465
4638
  declare type LegacyBlock = z.infer<typeof LegacyBlockSchema>;
4466
4639
  export { LegacyBlock }
4467
4640
  export { LegacyBlock as LegacyBlock_alias_1 }
@@ -8694,6 +8867,61 @@ declare const PageStructureOutputSchema: z.ZodObject<{
8694
8867
  export { PageStructureOutputSchema }
8695
8868
  export { PageStructureOutputSchema as PageStructureOutputSchema_alias_1 }
8696
8869
 
8870
+ /**
8871
+ * Attempts to validate a consumed response body as a service-level error envelope.
8872
+ */
8873
+ export declare function parseApiErrorResponse(responseBody: ResponseBodyDiagnostics): {
8874
+ statusCode: number;
8875
+ requestId: string;
8876
+ status: "error";
8877
+ error: {
8878
+ code: "UNAUTHORIZED" | "NOT_FOUND" | "INTERNAL_SERVER_ERROR" | "INVALID_INPUT_DATA";
8879
+ message: string;
8880
+ path?: string | undefined;
8881
+ details?: string | undefined;
8882
+ timestamp?: string | undefined;
8883
+ };
8884
+ } | null;
8885
+
8886
+ /**
8887
+ * Attempts to validate a consumed response body as a success-or-error API envelope.
8888
+ */
8889
+ export declare function parseApiResponse<ResponseDataSchema extends ZodTypeAny>(responseDataSchema: ResponseDataSchema, responseBody: ResponseBodyDiagnostics): {
8890
+ statusCode: number;
8891
+ requestId: string;
8892
+ status: "error";
8893
+ error: {
8894
+ code: "UNAUTHORIZED" | "NOT_FOUND" | "INTERNAL_SERVER_ERROR" | "INVALID_INPUT_DATA";
8895
+ message: string;
8896
+ path?: string | undefined;
8897
+ details?: string | undefined;
8898
+ timestamp?: string | undefined;
8899
+ };
8900
+ } | (objectUtil.addQuestionMarks<baseObjectOutputType< {
8901
+ statusCode: ZodNumber;
8902
+ requestId: ZodString;
8903
+ } & {
8904
+ status: ZodLiteral<"success">;
8905
+ data: ResponseDataSchema;
8906
+ }>, any> extends infer T ? { [k in keyof T]: T[k]; } : never) | null;
8907
+
8908
+ /**
8909
+ * Validates an outbound request body when the caller supplied a schema.
8910
+ *
8911
+ * Requests without a body, or without a schema, pass through unchanged.
8912
+ */
8913
+ declare function parseRequestBody<ReqSchema extends ZodTypeAny | undefined>(requestSchema: ReqSchema | undefined, body: (ReqSchema extends ZodTypeAny ? z.infer<ReqSchema> : unknown) | undefined): (ReqSchema extends ZodTypeAny ? z.infer<ReqSchema> : unknown) | undefined;
8914
+ export { parseRequestBody }
8915
+ export { parseRequestBody as parseRequestBody_alias_1 }
8916
+
8917
+ /**
8918
+ * Interprets a successful HTTP response as either a valid Content Curation API
8919
+ * success envelope or a service-origin failure.
8920
+ */
8921
+ declare function parseSuccessfulResponse<ResponseDataSchema extends ZodTypeAny>(path: string, url: string, response: Response, responseBody: ResponseBodyDiagnostics, responseDataSchema: ResponseDataSchema): z.infer<ResponseDataSchema>;
8922
+ export { parseSuccessfulResponse }
8923
+ export { parseSuccessfulResponse as parseSuccessfulResponse_alias_1 }
8924
+
8697
8925
  declare type PersistPageDraftInput = z.infer<typeof PersistPageDraftInputSchema>;
8698
8926
  export { PersistPageDraftInput }
8699
8927
  export { PersistPageDraftInput as PersistPageDraftInput_alias_1 }
@@ -10363,6 +10591,30 @@ declare const ProseMirrorDocSchema: z.ZodObject<{
10363
10591
  export { ProseMirrorDocSchema }
10364
10592
  export { ProseMirrorDocSchema as ProseMirrorDocSchema_alias_1 }
10365
10593
 
10594
+ /**
10595
+ * Consumes the HTTP response body and converts body-read failures into the same
10596
+ * client error model used for normal gateway and service failures.
10597
+ */
10598
+ declare function readApiResponseBody(path: string, url: string, response: Response): Promise<ResponseBodyDiagnostics>;
10599
+ export { readApiResponseBody }
10600
+ export { readApiResponseBody as readApiResponseBody_alias_1 }
10601
+
10602
+ /**
10603
+ * Reads a response body exactly once, truncates diagnostic text, and only parses JSON when the
10604
+ * declared content type says that is appropriate.
10605
+ */
10606
+ export declare function readResponseBody(response: Response): Promise<ResponseBodyDiagnostics>;
10607
+
10608
+ /**
10609
+ * Captured information from a response body after the client has consumed it exactly once.
10610
+ */
10611
+ export declare type ResponseBodyDiagnostics = {
10612
+ contentType?: string;
10613
+ bodyText?: string;
10614
+ json?: unknown;
10615
+ jsonParseError?: Error;
10616
+ };
10617
+
10366
10618
  /** Rich text editor TS type. */
10367
10619
  declare type RichTextEditorType = z.infer<typeof ProseMirrorDocSchema>;
10368
10620
  export { RichTextEditorType }
@@ -13145,4 +13397,6 @@ declare type TopperSliceType = z.infer<typeof TopperSlice.OutputSchema>;
13145
13397
  export { TopperSliceType }
13146
13398
  export { TopperSliceType as TopperSliceType_alias_1 }
13147
13399
 
13400
+ declare type UnexpectedServiceResponseOptions = GatewayErrorOptions;
13401
+
13148
13402
  export { }