@dotcms/client 26.9.23-2 → 26.9.24-1-next.2772
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/index.cjs.js +96 -35
- package/index.esm.js +96 -35
- package/package.json +3 -3
- package/src/lib/client/adapters/fetch-http-client.d.ts +10 -16
package/index.cjs.js
CHANGED
|
@@ -4,7 +4,7 @@ var consola = require('consola');
|
|
|
4
4
|
var types = require('@dotcms/types');
|
|
5
5
|
var internal = require('./internal.cjs.js');
|
|
6
6
|
|
|
7
|
-
const SDK_VERSION = "26.9.
|
|
7
|
+
const SDK_VERSION = "26.9.24-1-next.2772";
|
|
8
8
|
|
|
9
9
|
const DOTCMS_VERSION_HEADER = 'x-dotcms-version';
|
|
10
10
|
const DOTCMS_MIN_SDK_HEADER = 'x-dotcms-min-sdk';
|
|
@@ -93,25 +93,23 @@ const checkSdkCompatibility = (headers, ownVersion) => {
|
|
|
93
93
|
*
|
|
94
94
|
* Extends BaseHttpClient to provide a standard interface for making HTTP requests.
|
|
95
95
|
* This implementation uses the native Fetch API and handles:
|
|
96
|
-
* - JSON
|
|
96
|
+
* - JSON response parsing
|
|
97
97
|
* - HTTP error response parsing and conversion to DotHttpError
|
|
98
98
|
* - Network error handling and wrapping
|
|
99
|
-
* -
|
|
99
|
+
* - Diagnosing misconfiguration: a response in a format other than JSON, or a request
|
|
100
|
+
* that was redirected to another origin, is named as such in the error message
|
|
101
|
+
*
|
|
102
|
+
* Every SDK caller talks to a dotCMS JSON endpoint, so a successful response with a
|
|
103
|
+
* non-JSON content type is rejected rather than returned.
|
|
100
104
|
*
|
|
101
105
|
* @example
|
|
102
106
|
* ```typescript
|
|
103
107
|
* const client = new FetchHttpClient();
|
|
104
108
|
*
|
|
105
|
-
* // JSON request
|
|
106
109
|
* const data = await client.request<MyType>('/api/data', {
|
|
107
110
|
* method: 'GET',
|
|
108
111
|
* headers: { 'Authorization': 'Bearer token' }
|
|
109
112
|
* });
|
|
110
|
-
*
|
|
111
|
-
* // Non-JSON request (e.g., file download)
|
|
112
|
-
* const response = await client.request<Response>('/api/file.pdf', {
|
|
113
|
-
* method: 'GET'
|
|
114
|
-
* });
|
|
115
113
|
* ```
|
|
116
114
|
*/
|
|
117
115
|
class FetchHttpClient extends types.BaseHttpClient {
|
|
@@ -122,12 +120,13 @@ class FetchHttpClient extends types.BaseHttpClient {
|
|
|
122
120
|
* Automatically handles response parsing based on Content-Type headers and converts
|
|
123
121
|
* HTTP errors to standardized DotHttpError instances.
|
|
124
122
|
*
|
|
125
|
-
* @template T - The
|
|
126
|
-
* For non-JSON responses, T should be Response or the expected response type.
|
|
123
|
+
* @template T - The parsed JSON body type.
|
|
127
124
|
* @param url - The URL to send the request to.
|
|
128
125
|
* @param options - Optional fetch options including method, headers, body, etc.
|
|
129
|
-
* @returns Promise that resolves with the parsed
|
|
126
|
+
* @returns Promise that resolves with the parsed JSON body, or the Response object when the
|
|
127
|
+
* response carries no content type at all.
|
|
130
128
|
* @throws {DotHttpError} - Throws DotHttpError for HTTP errors (4xx/5xx status codes).
|
|
129
|
+
* @throws {DotHttpError} - Throws DotHttpError (status 502) for a successful response whose content type is not JSON.
|
|
131
130
|
* @throws {DotHttpError} - Throws DotHttpError for network errors (connection issues, timeouts).
|
|
132
131
|
*
|
|
133
132
|
* @example
|
|
@@ -144,11 +143,6 @@ class FetchHttpClient extends types.BaseHttpClient {
|
|
|
144
143
|
* headers: { 'Content-Type': 'application/json' },
|
|
145
144
|
* body: JSON.stringify({ name: 'John', email: 'john@example.com' })
|
|
146
145
|
* });
|
|
147
|
-
*
|
|
148
|
-
* // File download (non-JSON response)
|
|
149
|
-
* const response = await client.request<Response>('/api/files/document.pdf', {
|
|
150
|
-
* method: 'GET'
|
|
151
|
-
* });
|
|
152
146
|
* ```
|
|
153
147
|
*/
|
|
154
148
|
async request(url, options) {
|
|
@@ -160,35 +154,62 @@ class FetchHttpClient extends types.BaseHttpClient {
|
|
|
160
154
|
// e.g. an older server) and never throws, so this can't affect the actual
|
|
161
155
|
// request/response handling below.
|
|
162
156
|
checkSdkCompatibility(response.headers, SDK_VERSION);
|
|
157
|
+
const contentType = response.headers.get('content-type');
|
|
158
|
+
// application/json and the structured-syntax variants (problem+json,
|
|
159
|
+
// graphql-response+json, ...), in any case.
|
|
160
|
+
const isJson = /^application\/([\w.-]+\+)?json\b/i.test(contentType ?? '');
|
|
163
161
|
if (!response.ok) {
|
|
164
162
|
// Parse response body for error context
|
|
165
163
|
let errorBody;
|
|
166
164
|
try {
|
|
167
|
-
|
|
168
|
-
if (contentType?.includes('application/json')) {
|
|
169
|
-
errorBody = await response.json();
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
errorBody = await response.text();
|
|
173
|
-
}
|
|
165
|
+
errorBody = isJson ? await response.json() : await response.text();
|
|
174
166
|
}
|
|
175
167
|
catch {
|
|
176
168
|
errorBody = response.statusText;
|
|
177
169
|
}
|
|
178
|
-
//
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
170
|
+
// The status alone hides the cause, so name what else went wrong: the redirect
|
|
171
|
+
// first (it is usually the root cause), then the unexpected format.
|
|
172
|
+
const hints = [
|
|
173
|
+
describeCrossOriginRedirect(url, response),
|
|
174
|
+
contentType && !isJson
|
|
175
|
+
? `The response was '${contentType}', not JSON, so it may not have come from the dotCMS API: a proxy, a load balancer or another server can answer this way.`
|
|
176
|
+
: undefined
|
|
177
|
+
].filter(Boolean);
|
|
178
|
+
const status = `HTTP ${response.status}: ${response.statusText}`;
|
|
179
|
+
const message = hints.length ? `${status}. ${hints.join(' ')}` : status;
|
|
180
|
+
throw this.createHttpError(response.status, response.statusText, toPlainHeaders(response.headers), errorBody, message);
|
|
184
181
|
}
|
|
185
|
-
|
|
186
|
-
const contentType = response.headers.get('content-type');
|
|
187
|
-
if (contentType?.includes('application/json')) {
|
|
182
|
+
if (isJson) {
|
|
188
183
|
return response.json();
|
|
189
184
|
}
|
|
190
|
-
//
|
|
191
|
-
//
|
|
185
|
+
// Every SDK caller talks to a JSON endpoint, so a successful answer in another
|
|
186
|
+
// format means something other than the dotCMS API answered (a login page, a
|
|
187
|
+
// proxy, the wrong port). Returning the Response would only move the failure
|
|
188
|
+
// downstream.
|
|
189
|
+
if (contentType) {
|
|
190
|
+
let body;
|
|
191
|
+
try {
|
|
192
|
+
body = await response.text();
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
body = undefined;
|
|
196
|
+
}
|
|
197
|
+
const crossOriginRedirect = describeCrossOriginRedirect(url, response);
|
|
198
|
+
const sameOriginRedirect = !crossOriginRedirect && response.redirected && response.url
|
|
199
|
+
? ` after a redirect to '${response.url}'`
|
|
200
|
+
: '';
|
|
201
|
+
const message = [
|
|
202
|
+
`Expected a JSON response from '${url}' but received '${contentType}' (HTTP ${response.status})${sameOriginRedirect}, which is not JSON. dotCMS API endpoints answer in JSON, so something other than the dotCMS API answered (a login page, a proxy or another server): check that dotcmsUrl points at your dotCMS instance.`,
|
|
203
|
+
crossOriginRedirect
|
|
204
|
+
]
|
|
205
|
+
.filter(Boolean)
|
|
206
|
+
.join(' ');
|
|
207
|
+
// Reported as 502 Bad Gateway, not the real 2xx: callers forward error.status
|
|
208
|
+
// as their own response status, and an error must never read as success. The
|
|
209
|
+
// real status is in the message and the body in data.
|
|
210
|
+
throw this.createHttpError(502, 'Bad Gateway', toPlainHeaders(response.headers), body, message);
|
|
211
|
+
}
|
|
212
|
+
// No content type at all: hand back the Response untouched.
|
|
192
213
|
return response;
|
|
193
214
|
}
|
|
194
215
|
catch (error) {
|
|
@@ -200,6 +221,46 @@ class FetchHttpClient extends types.BaseHttpClient {
|
|
|
200
221
|
}
|
|
201
222
|
}
|
|
202
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Explains a redirect that took the request to a different origin, or returns undefined
|
|
226
|
+
* when there was no redirect, it stayed on the same origin, or either URL can't be parsed.
|
|
227
|
+
*
|
|
228
|
+
* A changed origin almost always means `dotcmsUrl` names a scheme or host the server moves
|
|
229
|
+
* away from (e.g. `http://` answered with a 301 to `https://`), and the hop itself breaks the
|
|
230
|
+
* request: fetch drops the Authorization header on a cross-origin redirect, and a 301, 302 or
|
|
231
|
+
* 303 turns a POST into a GET without its body.
|
|
232
|
+
*
|
|
233
|
+
* @param requestUrl - The URL the SDK asked for.
|
|
234
|
+
* @param response - The response fetch ended on after following redirects.
|
|
235
|
+
* @returns A sentence naming both URLs and `dotcmsUrl`, or undefined.
|
|
236
|
+
*/
|
|
237
|
+
function describeCrossOriginRedirect(requestUrl, response) {
|
|
238
|
+
if (!response.redirected || !response.url) {
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
if (new URL(requestUrl).origin === new URL(response.url).origin) {
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
return `The request to '${requestUrl}' was redirected to '${response.url}', a different origin. Check that dotcmsUrl uses the exact scheme and host your dotCMS instance serves: a cross-origin redirect drops the Authorization header, and a 301, 302 or 303 turns a POST into a GET without its body.`;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Copies fetch Headers into a plain object, the shape createHttpError expects.
|
|
253
|
+
*
|
|
254
|
+
* @param headers - The response headers.
|
|
255
|
+
* @returns The headers keyed by lower-case name.
|
|
256
|
+
*/
|
|
257
|
+
function toPlainHeaders(headers) {
|
|
258
|
+
const plain = {};
|
|
259
|
+
headers.forEach((value, key) => {
|
|
260
|
+
plain[key] = value;
|
|
261
|
+
});
|
|
262
|
+
return plain;
|
|
263
|
+
}
|
|
203
264
|
|
|
204
265
|
/*! *****************************************************************************
|
|
205
266
|
Copyright (c) Microsoft Corporation.
|
package/index.esm.js
CHANGED
|
@@ -2,7 +2,7 @@ import { consola } from 'consola';
|
|
|
2
2
|
import { BaseHttpClient, DISTANCE_FUNCTIONS, DotHttpError, DotErrorAISearch, DotErrorContent, DotErrorNavigation, UVE_MODE, DotErrorPage } from '@dotcms/types';
|
|
3
3
|
import { graphqlToPageEntity } from './internal.esm.js';
|
|
4
4
|
|
|
5
|
-
const SDK_VERSION = "26.9.
|
|
5
|
+
const SDK_VERSION = "26.9.24-1-next.2772";
|
|
6
6
|
|
|
7
7
|
const DOTCMS_VERSION_HEADER = 'x-dotcms-version';
|
|
8
8
|
const DOTCMS_MIN_SDK_HEADER = 'x-dotcms-min-sdk';
|
|
@@ -91,25 +91,23 @@ const checkSdkCompatibility = (headers, ownVersion) => {
|
|
|
91
91
|
*
|
|
92
92
|
* Extends BaseHttpClient to provide a standard interface for making HTTP requests.
|
|
93
93
|
* This implementation uses the native Fetch API and handles:
|
|
94
|
-
* - JSON
|
|
94
|
+
* - JSON response parsing
|
|
95
95
|
* - HTTP error response parsing and conversion to DotHttpError
|
|
96
96
|
* - Network error handling and wrapping
|
|
97
|
-
* -
|
|
97
|
+
* - Diagnosing misconfiguration: a response in a format other than JSON, or a request
|
|
98
|
+
* that was redirected to another origin, is named as such in the error message
|
|
99
|
+
*
|
|
100
|
+
* Every SDK caller talks to a dotCMS JSON endpoint, so a successful response with a
|
|
101
|
+
* non-JSON content type is rejected rather than returned.
|
|
98
102
|
*
|
|
99
103
|
* @example
|
|
100
104
|
* ```typescript
|
|
101
105
|
* const client = new FetchHttpClient();
|
|
102
106
|
*
|
|
103
|
-
* // JSON request
|
|
104
107
|
* const data = await client.request<MyType>('/api/data', {
|
|
105
108
|
* method: 'GET',
|
|
106
109
|
* headers: { 'Authorization': 'Bearer token' }
|
|
107
110
|
* });
|
|
108
|
-
*
|
|
109
|
-
* // Non-JSON request (e.g., file download)
|
|
110
|
-
* const response = await client.request<Response>('/api/file.pdf', {
|
|
111
|
-
* method: 'GET'
|
|
112
|
-
* });
|
|
113
111
|
* ```
|
|
114
112
|
*/
|
|
115
113
|
class FetchHttpClient extends BaseHttpClient {
|
|
@@ -120,12 +118,13 @@ class FetchHttpClient extends BaseHttpClient {
|
|
|
120
118
|
* Automatically handles response parsing based on Content-Type headers and converts
|
|
121
119
|
* HTTP errors to standardized DotHttpError instances.
|
|
122
120
|
*
|
|
123
|
-
* @template T - The
|
|
124
|
-
* For non-JSON responses, T should be Response or the expected response type.
|
|
121
|
+
* @template T - The parsed JSON body type.
|
|
125
122
|
* @param url - The URL to send the request to.
|
|
126
123
|
* @param options - Optional fetch options including method, headers, body, etc.
|
|
127
|
-
* @returns Promise that resolves with the parsed
|
|
124
|
+
* @returns Promise that resolves with the parsed JSON body, or the Response object when the
|
|
125
|
+
* response carries no content type at all.
|
|
128
126
|
* @throws {DotHttpError} - Throws DotHttpError for HTTP errors (4xx/5xx status codes).
|
|
127
|
+
* @throws {DotHttpError} - Throws DotHttpError (status 502) for a successful response whose content type is not JSON.
|
|
129
128
|
* @throws {DotHttpError} - Throws DotHttpError for network errors (connection issues, timeouts).
|
|
130
129
|
*
|
|
131
130
|
* @example
|
|
@@ -142,11 +141,6 @@ class FetchHttpClient extends BaseHttpClient {
|
|
|
142
141
|
* headers: { 'Content-Type': 'application/json' },
|
|
143
142
|
* body: JSON.stringify({ name: 'John', email: 'john@example.com' })
|
|
144
143
|
* });
|
|
145
|
-
*
|
|
146
|
-
* // File download (non-JSON response)
|
|
147
|
-
* const response = await client.request<Response>('/api/files/document.pdf', {
|
|
148
|
-
* method: 'GET'
|
|
149
|
-
* });
|
|
150
144
|
* ```
|
|
151
145
|
*/
|
|
152
146
|
async request(url, options) {
|
|
@@ -158,35 +152,62 @@ class FetchHttpClient extends BaseHttpClient {
|
|
|
158
152
|
// e.g. an older server) and never throws, so this can't affect the actual
|
|
159
153
|
// request/response handling below.
|
|
160
154
|
checkSdkCompatibility(response.headers, SDK_VERSION);
|
|
155
|
+
const contentType = response.headers.get('content-type');
|
|
156
|
+
// application/json and the structured-syntax variants (problem+json,
|
|
157
|
+
// graphql-response+json, ...), in any case.
|
|
158
|
+
const isJson = /^application\/([\w.-]+\+)?json\b/i.test(contentType ?? '');
|
|
161
159
|
if (!response.ok) {
|
|
162
160
|
// Parse response body for error context
|
|
163
161
|
let errorBody;
|
|
164
162
|
try {
|
|
165
|
-
|
|
166
|
-
if (contentType?.includes('application/json')) {
|
|
167
|
-
errorBody = await response.json();
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
errorBody = await response.text();
|
|
171
|
-
}
|
|
163
|
+
errorBody = isJson ? await response.json() : await response.text();
|
|
172
164
|
}
|
|
173
165
|
catch {
|
|
174
166
|
errorBody = response.statusText;
|
|
175
167
|
}
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
168
|
+
// The status alone hides the cause, so name what else went wrong: the redirect
|
|
169
|
+
// first (it is usually the root cause), then the unexpected format.
|
|
170
|
+
const hints = [
|
|
171
|
+
describeCrossOriginRedirect(url, response),
|
|
172
|
+
contentType && !isJson
|
|
173
|
+
? `The response was '${contentType}', not JSON, so it may not have come from the dotCMS API: a proxy, a load balancer or another server can answer this way.`
|
|
174
|
+
: undefined
|
|
175
|
+
].filter(Boolean);
|
|
176
|
+
const status = `HTTP ${response.status}: ${response.statusText}`;
|
|
177
|
+
const message = hints.length ? `${status}. ${hints.join(' ')}` : status;
|
|
178
|
+
throw this.createHttpError(response.status, response.statusText, toPlainHeaders(response.headers), errorBody, message);
|
|
182
179
|
}
|
|
183
|
-
|
|
184
|
-
const contentType = response.headers.get('content-type');
|
|
185
|
-
if (contentType?.includes('application/json')) {
|
|
180
|
+
if (isJson) {
|
|
186
181
|
return response.json();
|
|
187
182
|
}
|
|
188
|
-
//
|
|
189
|
-
//
|
|
183
|
+
// Every SDK caller talks to a JSON endpoint, so a successful answer in another
|
|
184
|
+
// format means something other than the dotCMS API answered (a login page, a
|
|
185
|
+
// proxy, the wrong port). Returning the Response would only move the failure
|
|
186
|
+
// downstream.
|
|
187
|
+
if (contentType) {
|
|
188
|
+
let body;
|
|
189
|
+
try {
|
|
190
|
+
body = await response.text();
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
body = undefined;
|
|
194
|
+
}
|
|
195
|
+
const crossOriginRedirect = describeCrossOriginRedirect(url, response);
|
|
196
|
+
const sameOriginRedirect = !crossOriginRedirect && response.redirected && response.url
|
|
197
|
+
? ` after a redirect to '${response.url}'`
|
|
198
|
+
: '';
|
|
199
|
+
const message = [
|
|
200
|
+
`Expected a JSON response from '${url}' but received '${contentType}' (HTTP ${response.status})${sameOriginRedirect}, which is not JSON. dotCMS API endpoints answer in JSON, so something other than the dotCMS API answered (a login page, a proxy or another server): check that dotcmsUrl points at your dotCMS instance.`,
|
|
201
|
+
crossOriginRedirect
|
|
202
|
+
]
|
|
203
|
+
.filter(Boolean)
|
|
204
|
+
.join(' ');
|
|
205
|
+
// Reported as 502 Bad Gateway, not the real 2xx: callers forward error.status
|
|
206
|
+
// as their own response status, and an error must never read as success. The
|
|
207
|
+
// real status is in the message and the body in data.
|
|
208
|
+
throw this.createHttpError(502, 'Bad Gateway', toPlainHeaders(response.headers), body, message);
|
|
209
|
+
}
|
|
210
|
+
// No content type at all: hand back the Response untouched.
|
|
190
211
|
return response;
|
|
191
212
|
}
|
|
192
213
|
catch (error) {
|
|
@@ -198,6 +219,46 @@ class FetchHttpClient extends BaseHttpClient {
|
|
|
198
219
|
}
|
|
199
220
|
}
|
|
200
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Explains a redirect that took the request to a different origin, or returns undefined
|
|
224
|
+
* when there was no redirect, it stayed on the same origin, or either URL can't be parsed.
|
|
225
|
+
*
|
|
226
|
+
* A changed origin almost always means `dotcmsUrl` names a scheme or host the server moves
|
|
227
|
+
* away from (e.g. `http://` answered with a 301 to `https://`), and the hop itself breaks the
|
|
228
|
+
* request: fetch drops the Authorization header on a cross-origin redirect, and a 301, 302 or
|
|
229
|
+
* 303 turns a POST into a GET without its body.
|
|
230
|
+
*
|
|
231
|
+
* @param requestUrl - The URL the SDK asked for.
|
|
232
|
+
* @param response - The response fetch ended on after following redirects.
|
|
233
|
+
* @returns A sentence naming both URLs and `dotcmsUrl`, or undefined.
|
|
234
|
+
*/
|
|
235
|
+
function describeCrossOriginRedirect(requestUrl, response) {
|
|
236
|
+
if (!response.redirected || !response.url) {
|
|
237
|
+
return undefined;
|
|
238
|
+
}
|
|
239
|
+
try {
|
|
240
|
+
if (new URL(requestUrl).origin === new URL(response.url).origin) {
|
|
241
|
+
return undefined;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
return undefined;
|
|
246
|
+
}
|
|
247
|
+
return `The request to '${requestUrl}' was redirected to '${response.url}', a different origin. Check that dotcmsUrl uses the exact scheme and host your dotCMS instance serves: a cross-origin redirect drops the Authorization header, and a 301, 302 or 303 turns a POST into a GET without its body.`;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Copies fetch Headers into a plain object, the shape createHttpError expects.
|
|
251
|
+
*
|
|
252
|
+
* @param headers - The response headers.
|
|
253
|
+
* @returns The headers keyed by lower-case name.
|
|
254
|
+
*/
|
|
255
|
+
function toPlainHeaders(headers) {
|
|
256
|
+
const plain = {};
|
|
257
|
+
headers.forEach((value, key) => {
|
|
258
|
+
plain[key] = value;
|
|
259
|
+
});
|
|
260
|
+
return plain;
|
|
261
|
+
}
|
|
201
262
|
|
|
202
263
|
/*! *****************************************************************************
|
|
203
264
|
Copyright (c) Microsoft Corporation.
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dotcms/client",
|
|
3
|
-
"version": "26.9.
|
|
3
|
+
"version": "26.9.24-1-next.2772",
|
|
4
4
|
"description": "Official JavaScript library for interacting with DotCMS REST APIs.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/dotCMS/core.git#main"
|
|
8
8
|
},
|
|
9
9
|
"peerDependencies": {
|
|
10
|
-
"@dotcms/types": "26.9.
|
|
10
|
+
"@dotcms/types": "26.9.24-1-next.2772"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"consola": "^3.4.2"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@dotcms/types": "26.9.
|
|
16
|
+
"@dotcms/types": "26.9.24-1-next.2772"
|
|
17
17
|
},
|
|
18
18
|
"keywords": [
|
|
19
19
|
"dotCMS",
|
|
@@ -4,25 +4,23 @@ import { BaseHttpClient, DotRequestOptions } from '@dotcms/types';
|
|
|
4
4
|
*
|
|
5
5
|
* Extends BaseHttpClient to provide a standard interface for making HTTP requests.
|
|
6
6
|
* This implementation uses the native Fetch API and handles:
|
|
7
|
-
* - JSON
|
|
7
|
+
* - JSON response parsing
|
|
8
8
|
* - HTTP error response parsing and conversion to DotHttpError
|
|
9
9
|
* - Network error handling and wrapping
|
|
10
|
-
* -
|
|
10
|
+
* - Diagnosing misconfiguration: a response in a format other than JSON, or a request
|
|
11
|
+
* that was redirected to another origin, is named as such in the error message
|
|
12
|
+
*
|
|
13
|
+
* Every SDK caller talks to a dotCMS JSON endpoint, so a successful response with a
|
|
14
|
+
* non-JSON content type is rejected rather than returned.
|
|
11
15
|
*
|
|
12
16
|
* @example
|
|
13
17
|
* ```typescript
|
|
14
18
|
* const client = new FetchHttpClient();
|
|
15
19
|
*
|
|
16
|
-
* // JSON request
|
|
17
20
|
* const data = await client.request<MyType>('/api/data', {
|
|
18
21
|
* method: 'GET',
|
|
19
22
|
* headers: { 'Authorization': 'Bearer token' }
|
|
20
23
|
* });
|
|
21
|
-
*
|
|
22
|
-
* // Non-JSON request (e.g., file download)
|
|
23
|
-
* const response = await client.request<Response>('/api/file.pdf', {
|
|
24
|
-
* method: 'GET'
|
|
25
|
-
* });
|
|
26
24
|
* ```
|
|
27
25
|
*/
|
|
28
26
|
export declare class FetchHttpClient extends BaseHttpClient {
|
|
@@ -33,12 +31,13 @@ export declare class FetchHttpClient extends BaseHttpClient {
|
|
|
33
31
|
* Automatically handles response parsing based on Content-Type headers and converts
|
|
34
32
|
* HTTP errors to standardized DotHttpError instances.
|
|
35
33
|
*
|
|
36
|
-
* @template T - The
|
|
37
|
-
* For non-JSON responses, T should be Response or the expected response type.
|
|
34
|
+
* @template T - The parsed JSON body type.
|
|
38
35
|
* @param url - The URL to send the request to.
|
|
39
36
|
* @param options - Optional fetch options including method, headers, body, etc.
|
|
40
|
-
* @returns Promise that resolves with the parsed
|
|
37
|
+
* @returns Promise that resolves with the parsed JSON body, or the Response object when the
|
|
38
|
+
* response carries no content type at all.
|
|
41
39
|
* @throws {DotHttpError} - Throws DotHttpError for HTTP errors (4xx/5xx status codes).
|
|
40
|
+
* @throws {DotHttpError} - Throws DotHttpError (status 502) for a successful response whose content type is not JSON.
|
|
42
41
|
* @throws {DotHttpError} - Throws DotHttpError for network errors (connection issues, timeouts).
|
|
43
42
|
*
|
|
44
43
|
* @example
|
|
@@ -55,11 +54,6 @@ export declare class FetchHttpClient extends BaseHttpClient {
|
|
|
55
54
|
* headers: { 'Content-Type': 'application/json' },
|
|
56
55
|
* body: JSON.stringify({ name: 'John', email: 'john@example.com' })
|
|
57
56
|
* });
|
|
58
|
-
*
|
|
59
|
-
* // File download (non-JSON response)
|
|
60
|
-
* const response = await client.request<Response>('/api/files/document.pdf', {
|
|
61
|
-
* method: 'GET'
|
|
62
|
-
* });
|
|
63
57
|
* ```
|
|
64
58
|
*/
|
|
65
59
|
request<T = unknown>(url: string, options?: DotRequestOptions): Promise<T>;
|