@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.
package/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # Content Curation API Client
2
2
 
3
- A TypeScript client library for interacting with the Content Curation API.
3
+ TypeScript client library for interacting with the Content Curation API.
4
4
 
5
5
  ## Features
6
6
 
7
- - Fully typed API using Zod schemas for validation
8
- - Simple promise-based API for fetching and updating homepage and page structures
9
- - Comprehensive error handling
10
- - TypeScript-friendly with exported types
7
+ - Zod-validated request and response types
8
+ - Promise-based clients for homepage and page endpoints
9
+ - Typed transport, gateway, and service error handling
10
+ - Support for custom `fetch` implementations
11
11
 
12
12
  ## Installation
13
13
 
@@ -15,11 +15,12 @@ A TypeScript client library for interacting with the Content Curation API.
15
15
  npm install @financial-times/content-curation-client
16
16
  ```
17
17
 
18
- ## Usage
18
+ ## API access
19
19
 
20
- ### API Key
20
+ If you do not already have one, you can request an API Gateway key by completing the
21
+ [API Key Request Form](https://apigateway.in.ft.com/key-form).
21
22
 
22
- If you don’t already have one, you can request an API Gateway key by completing the [API Key Request Form](https://apigateway.in.ft.com/key-form).
23
+ ## Usage
23
24
 
24
25
  ### Initialize the client
25
26
 
@@ -35,38 +36,34 @@ const client = new ApiClient({
35
36
  ### Get homepage structure
36
37
 
37
38
  ```typescript
38
- // Fetch a homepage structure by pageId
39
39
  const pageId = "123e4567-e89b-12d3-a456-426614174000";
40
40
  const homepage = await client.homepage.getStructure(pageId);
41
41
 
42
- // Fetch available homepage structures by homepageListId
43
- const homepageListId = "123e4567-e89b-12d3-a456-426614174000";
44
- const structures = await client.homepage.getStructuresByHomepageListId(homepageListId);
45
-
46
- console.log(homepage.data.properties.title);
42
+ console.log(homepage.properties.title);
47
43
  ```
48
44
 
49
45
  ### Get page structure
50
46
 
51
47
  ```typescript
52
- // Fetch a page structure by pageId
53
48
  const pageId = "123e4567-e89b-12d3-a456-426614174999";
54
49
  const page = await client.page.getStructure(pageId);
55
50
 
56
- console.log(page.data.properties.title);
51
+ console.log(page.properties.title);
57
52
  ```
58
53
 
59
54
  ### Update homepage structure
60
55
 
61
56
  ```typescript
62
- import { HomepageDataApi } from "@financial-times/content-curation-client";
57
+ import { HomepageStructureInput } from "@financial-times/content-curation-client";
63
58
 
64
- // Create or update homepage structure
65
- const homepageStructure: Omit<HomepageDataApi, "type"> = {
59
+ const pageId = "58de2dc7-980b-4d51-8e45-9798f0c6b6bf";
60
+
61
+ const homepageStructure: Omit<HomepageStructureInput, "type"> = {
66
62
  properties: {
67
- pageId: "58de2dc7-980b-4d51-8e45-9798f0c6b6bf",
63
+ pageId,
68
64
  homepageListId: "123e4567-e89b-12d3-a456-426614174000",
69
65
  title: "My Updated Homepage",
66
+ publicationId: "homepage-publication-id",
70
67
  },
71
68
  children: [
72
69
  {
@@ -77,20 +74,10 @@ const homepageStructure: Omit<HomepageDataApi, "type"> = {
77
74
  },
78
75
  },
79
76
  },
80
- {
81
- type: "FlourishGraphic",
82
- properties: {
83
- heading: {
84
- text: "Interactive Chart",
85
- },
86
- flourishId: "visualisation-123",
87
- displayBehaviour: "standalone",
88
- },
89
- },
90
77
  ],
91
78
  };
92
79
 
93
- const result = await client.homepage.upsertStructure(pageId, homepageStructure);
80
+ const homepage = await client.homepage.upsertStructure(pageId, homepageStructure);
94
81
  ```
95
82
 
96
83
  ### Update page structure
@@ -98,11 +85,13 @@ const result = await client.homepage.upsertStructure(pageId, homepageStructure);
98
85
  ```typescript
99
86
  import { PageStructureInput } from "@financial-times/content-curation-client";
100
87
 
101
- // Create or update page structure
88
+ const pageId = "123e4567-e89b-12d3-a456-426614174999";
89
+
102
90
  const pageStructure: Omit<PageStructureInput, "type"> = {
103
91
  properties: {
104
- pageId: "123e4567-e89b-12d3-a456-426614174999",
92
+ pageId,
105
93
  title: "My Updated Page",
94
+ publicationId: "page-publication-id",
106
95
  },
107
96
  children: [
108
97
  {
@@ -116,58 +105,80 @@ const pageStructure: Omit<PageStructureInput, "type"> = {
116
105
  ],
117
106
  };
118
107
 
119
- const result = await client.page.upsertStructure(pageId, pageStructure);
108
+ const page = await client.page.upsertStructure(pageId, pageStructure);
120
109
  ```
121
110
 
122
- ### Error handling
111
+ ## Error handling
112
+
113
+ Client methods throw `ApiClientError` for any client-generated failure. You can narrow that
114
+ base class into transport, gateway, and service errors when you need more specific handling.
123
115
 
124
116
  ```typescript
125
- import { ApiError } from "@financial-times/content-curation-client";
117
+ import {
118
+ ApiClientError,
119
+ ApiGatewayError,
120
+ ApiServiceError,
121
+ ApiTransportError,
122
+ } from "@financial-times/content-curation-client";
126
123
 
127
124
  try {
128
- const homepageStructure = await client.homepage.getStructure("invalid-id");
125
+ await client.page.getStructure("123e4567-e89b-12d3-a456-426614174999");
129
126
  } catch (error) {
130
- if (error instanceof ApiError) {
131
- console.error(`API Error (${error.status}): ${error.message}`);
132
-
133
- if (error.errors) {
134
- console.error("Validation errors:", error.errors);
135
- }
127
+ if (error instanceof ApiTransportError) {
128
+ console.error(error.transportKind, error.message, error.cause);
129
+ } else if (error instanceof ApiGatewayError) {
130
+ console.error(error.statusCode, error.contentType, error.bodyText);
131
+ } else if (error instanceof ApiServiceError) {
132
+ console.error(error.code, error.message, error.details);
133
+ } else if (error instanceof ApiClientError) {
134
+ console.error(error.origin, error.message);
136
135
  } else {
137
- console.error("Unknown error:", error);
136
+ throw error;
138
137
  }
139
138
  }
140
139
  ```
141
140
 
141
+ ### Error metadata
142
+
143
+ All `ApiClientError` instances expose:
144
+
145
+ - `origin`: `"transport" | "gateway" | "service"`
146
+ - `statusCode`: `0` for transport failures, otherwise the HTTP status code
147
+ - `requestId`: the upstream request identifier when available
148
+ - `url`: the request URL when available
149
+ - `contentType`: the response `content-type` when a response was received
150
+ - `bodyText`: truncated raw response text when the client captured it
151
+ - `cause`: the original thrown error for wrapped failures
152
+
153
+ `ApiTransportError` also exposes `transportKind`, and `ApiServiceError` is the subtype whose
154
+ `payload` is guaranteed to match the server-side `ApiErrorPayload` schema.
155
+
142
156
  ## Advanced usage
143
157
 
144
158
  ### Custom fetch implementation
145
159
 
146
- You can provide your own fetch implementation, which is useful for caching, testing, and adding other custom behavior:
160
+ You can provide your own `fetch` implementation for testing or integration with your own
161
+ runtime concerns:
147
162
 
148
163
  ```typescript
149
164
  import { ApiClient } from "@financial-times/content-curation-client";
150
165
 
151
166
  const client = new ApiClient({
152
- baseUrl: "https://your-api-url.com/api",
167
+ baseUrl: "https://api-t.ft.com/content-curation",
153
168
  apiKey: "your-api-key",
154
169
  fetch: customFetchFunction,
155
170
  });
156
171
  ```
157
172
 
158
- ## Types
173
+ ## Useful exported types
159
174
 
160
175
  ```typescript
161
- import {
162
- HomepageDataApi,
163
- HomepageStructureApiResponse,
164
- HomepageSliceApiResponse,
176
+ import type {
177
+ ApiErrorPayload,
178
+ HomepageStructureInput,
179
+ HomepageStructureOutput,
180
+ PageDraft,
165
181
  PageStructureInput,
166
182
  PageStructureOutput,
167
183
  } from "@financial-times/content-curation-client";
168
-
169
- // Use types in your code
170
- const myPageStructureResponse: PageStructureOutput = {
171
- /* ... */
172
- };
173
184
  ```
@@ -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 { }