@kontent-ai/core-sdk 12.0.0-preview.2 → 12.0.0-preview.21
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/.npmignore +1 -5
- package/LICENSE.md +1 -1
- package/README.md +177 -12
- package/dist/core-sdk-info.d.ts +2 -0
- package/dist/core-sdk-info.js +6 -0
- package/dist/core-sdk-info.js.map +1 -0
- package/dist/devkit/console.utils.d.ts +2 -0
- package/dist/devkit/console.utils.js +5 -0
- package/dist/devkit/console.utils.js.map +1 -0
- package/dist/devkit/environment.utils.d.ts +2 -0
- package/dist/devkit/environment.utils.js +12 -0
- package/dist/devkit/environment.utils.js.map +1 -0
- package/dist/devkit/script.utils.js +3 -3
- package/dist/devkit/script.utils.js.map +1 -1
- package/dist/devkit_api.d.ts +3 -0
- package/dist/devkit_api.js +3 -1
- package/dist/devkit_api.js.map +1 -1
- package/dist/http/http.adapter.d.ts +1 -1
- package/dist/http/http.adapter.js +78 -24
- package/dist/http/http.adapter.js.map +1 -1
- package/dist/http/http.models.d.ts +42 -32
- package/dist/http/http.service.js +294 -220
- package/dist/http/http.service.js.map +1 -1
- package/dist/models/core.models.d.ts +34 -29
- package/dist/models/error.models.d.ts +48 -27
- package/dist/models/error.models.js +40 -1
- package/dist/models/error.models.js.map +1 -1
- package/dist/models/json.models.d.ts +13 -4
- package/dist/models/json.models.js +10 -1
- package/dist/models/json.models.js.map +1 -1
- package/dist/models/utility.types.d.ts +16 -0
- package/dist/models/utility.types.js +2 -0
- package/dist/models/utility.types.js.map +1 -0
- package/dist/public_api.d.ts +19 -11
- package/dist/public_api.js +15 -6
- package/dist/public_api.js.map +1 -1
- package/dist/sdk/queries/fetch-sdk-query.d.ts +7 -0
- package/dist/sdk/queries/fetch-sdk-query.js +24 -0
- package/dist/sdk/queries/fetch-sdk-query.js.map +1 -0
- package/dist/sdk/queries/mutation-sdk-query.d.ts +4 -0
- package/dist/sdk/queries/mutation-sdk-query.js +17 -0
- package/dist/sdk/queries/mutation-sdk-query.js.map +1 -0
- package/dist/sdk/queries/paged-fetch-sdk-query.d.ts +6 -0
- package/dist/sdk/queries/paged-fetch-sdk-query.js +145 -0
- package/dist/sdk/queries/paged-fetch-sdk-query.js.map +1 -0
- package/dist/sdk/resolve-query.d.ts +8 -0
- package/dist/sdk/resolve-query.js +108 -0
- package/dist/sdk/resolve-query.js.map +1 -0
- package/dist/sdk/sdk-config.d.ts +3 -0
- package/dist/sdk/sdk-config.js +4 -0
- package/dist/sdk/sdk-config.js.map +1 -0
- package/dist/sdk/sdk-models.d.ts +101 -36
- package/dist/sdk/sdk-utils.d.ts +2 -0
- package/dist/sdk/sdk-utils.js +9 -0
- package/dist/sdk/sdk-utils.js.map +1 -0
- package/dist/testkit/poll.utils.d.ts +5 -0
- package/dist/testkit/poll.utils.js +24 -0
- package/dist/testkit/poll.utils.js.map +1 -0
- package/dist/testkit/testkit.utils.d.ts +20 -0
- package/dist/testkit/testkit.utils.js +100 -0
- package/dist/testkit/testkit.utils.js.map +1 -0
- package/dist/testkit_api.d.ts +3 -1
- package/dist/testkit_api.js +3 -2
- package/dist/testkit_api.js.map +1 -1
- package/dist/utils/abort.utils.d.ts +12 -0
- package/dist/utils/abort.utils.js +29 -0
- package/dist/utils/abort.utils.js.map +1 -0
- package/dist/utils/core.utils.d.ts +3 -1
- package/dist/utils/core.utils.js +22 -2
- package/dist/utils/core.utils.js.map +1 -1
- package/dist/utils/error.utils.d.ts +18 -7
- package/dist/utils/error.utils.js +35 -7
- package/dist/utils/error.utils.js.map +1 -1
- package/dist/utils/header.utils.d.ts +6 -1
- package/dist/utils/header.utils.js +37 -6
- package/dist/utils/header.utils.js.map +1 -1
- package/dist/utils/retry.utils.d.ts +16 -11
- package/dist/utils/retry.utils.js +131 -63
- package/dist/utils/retry.utils.js.map +1 -1
- package/dist/utils/sdk-version.utils.js +2 -2
- package/dist/utils/sdk-version.utils.js.map +1 -1
- package/dist/utils/try-catch.utils.d.ts +15 -0
- package/dist/utils/{try.utils.js → try-catch.utils.js} +1 -1
- package/dist/utils/try-catch.utils.js.map +1 -0
- package/dist/utils/type.utils.d.ts +2 -0
- package/dist/utils/type.utils.js +5 -0
- package/dist/utils/type.utils.js.map +1 -0
- package/dist/utils/url.utils.d.ts +5 -0
- package/dist/utils/url.utils.js +10 -0
- package/dist/utils/url.utils.js.map +1 -0
- package/package.json +61 -64
- package/dist/models/utility.models.d.ts +0 -20
- package/dist/models/utility.models.js +0 -2
- package/dist/models/utility.models.js.map +0 -1
- package/dist/sdk/sdk-queries.d.ts +0 -30
- package/dist/sdk/sdk-queries.js +0 -152
- package/dist/sdk/sdk-queries.js.map +0 -1
- package/dist/sdk-info.d.ts +0 -5
- package/dist/sdk-info.js +0 -6
- package/dist/sdk-info.js.map +0 -1
- package/dist/testkit/test.utils.d.ts +0 -15
- package/dist/testkit/test.utils.js +0 -42
- package/dist/testkit/test.utils.js.map +0 -1
- package/dist/utils/try.utils.d.ts +0 -14
- package/dist/utils/try.utils.js.map +0 -1
- package/lib/devkit/script.utils.ts +0 -12
- package/lib/devkit_api.ts +0 -3
- package/lib/http/http.adapter.ts +0 -38
- package/lib/http/http.models.ts +0 -122
- package/lib/http/http.service.ts +0 -320
- package/lib/models/core.models.ts +0 -89
- package/lib/models/error.models.ts +0 -83
- package/lib/models/json.models.ts +0 -9
- package/lib/models/utility.models.ts +0 -21
- package/lib/public_api.ts +0 -45
- package/lib/sdk/sdk-models.ts +0 -85
- package/lib/sdk/sdk-queries.ts +0 -232
- package/lib/sdk-info.ts +0 -5
- package/lib/testkit/test.utils.ts +0 -79
- package/lib/testkit/testkit.models.ts +0 -7
- package/lib/testkit_api.ts +0 -3
- package/lib/utils/core.utils.ts +0 -3
- package/lib/utils/error.utils.ts +0 -48
- package/lib/utils/header.utils.ts +0 -40
- package/lib/utils/retry.utils.ts +0 -156
- package/lib/utils/sdk-version.utils.ts +0 -16
- package/lib/utils/try.utils.ts +0 -30
package/.npmignore
CHANGED
package/LICENSE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2026 Kontent s.r.o.
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
6
|
|
package/README.md
CHANGED
|
@@ -12,6 +12,22 @@ The **Core SDK** provides foundational functionality leveraged by dependent Kont
|
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
+
## Requirements
|
|
16
|
+
|
|
17
|
+
Before using this package, make sure your environment matches the published package requirements:
|
|
18
|
+
|
|
19
|
+
- Node.js `>=22`
|
|
20
|
+
- ESM-compatible runtime, because the package is published as an ES module
|
|
21
|
+
- Peer dependencies: `zod` and `ts-pattern`
|
|
22
|
+
|
|
23
|
+
With modern package managers such as npm, peer dependencies are typically installed automatically, so you usually only need:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install @kontent-ai/core-sdk
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
15
31
|
## HTTP Request Infrastructure
|
|
16
32
|
|
|
17
33
|
The SDK includes a default implementation of the `HttpService` and `HttpAdapter` components, which handle HTTP requests to the Kontent.ai APIs.
|
|
@@ -25,32 +41,98 @@ These implementations are designed to work out-of-the-box but are also fully cus
|
|
|
25
41
|
The `HttpService` comes with several built-in capabilities, such as:
|
|
26
42
|
|
|
27
43
|
- **Retry policies**
|
|
28
|
-
- **Request validation**
|
|
44
|
+
- **Request parsing and validation** (URL parsing, body serialization)
|
|
29
45
|
- **Automatic header and tracking management**
|
|
30
46
|
- **Kontent.ai-specific error extraction**
|
|
31
47
|
|
|
32
48
|
To customize these behaviors entirely, you can replace the `HttpService` with your own implementation.
|
|
33
49
|
|
|
34
|
-
However, if your goal is to retain the core features (e.g., retry policies, request
|
|
50
|
+
However, if your goal is to retain the core features (e.g., retry policies, request parsing) and only swap out the underlying HTTP client, you can do so by supplying a custom `HttpAdapter` to the `getDefaultHttpService` method.
|
|
35
51
|
|
|
36
52
|
---
|
|
37
53
|
|
|
38
54
|
## Example: Custom `HttpAdapter` Implementation
|
|
39
55
|
|
|
40
|
-
Below is an example demonstrating how to provide your own HTTP client by implementing a custom `HttpAdapter
|
|
56
|
+
Below is an example demonstrating how to provide your own HTTP client by implementing a custom `HttpAdapter`. Both `executeRequest` and `downloadFile` are optional, so you only need to implement the methods you want to override.
|
|
57
|
+
|
|
58
|
+
If you want the SDK to preserve specific `error.details.reason` values for custom adapters, throw:
|
|
59
|
+
|
|
60
|
+
- `AdapterAbortError` when the request is aborted
|
|
61
|
+
- `AdapterParseError` when the response cannot be parsed as JSON or `Blob`
|
|
62
|
+
|
|
63
|
+
If you throw some other error, the SDK will classify it as `adapterError`.
|
|
41
64
|
|
|
42
65
|
```typescript
|
|
43
|
-
|
|
66
|
+
import { AdapterAbortError, AdapterParseError, getDefaultHttpService } from "@kontent-ai/core-sdk";
|
|
67
|
+
|
|
68
|
+
const httpService = getDefaultHttpService({
|
|
44
69
|
adapter: {
|
|
45
|
-
|
|
46
|
-
|
|
70
|
+
executeRequest: async (options) => {
|
|
71
|
+
let response: Response;
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
response = await fetch(options.url, {
|
|
75
|
+
method: options.method,
|
|
76
|
+
headers: Object.fromEntries((options.requestHeaders ?? []).map((header) => [header.name, header.value])),
|
|
77
|
+
body: options.body,
|
|
78
|
+
signal: options.abortSignal ?? undefined,
|
|
79
|
+
});
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
82
|
+
throw new AdapterAbortError(error);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let payload = null;
|
|
89
|
+
|
|
90
|
+
if (response.headers.get("content-type")?.includes("application/json")) {
|
|
91
|
+
try {
|
|
92
|
+
payload = await response.json();
|
|
93
|
+
} catch (error) {
|
|
94
|
+
throw new AdapterParseError(error);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
47
98
|
return {
|
|
48
|
-
|
|
49
|
-
responseHeaders:
|
|
50
|
-
status:
|
|
51
|
-
statusText:
|
|
52
|
-
|
|
53
|
-
|
|
99
|
+
payload,
|
|
100
|
+
responseHeaders: [...response.headers.entries()].map(([name, value]) => ({ name, value })),
|
|
101
|
+
status: response.status,
|
|
102
|
+
statusText: response.statusText,
|
|
103
|
+
url: options.url,
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
downloadFile: async (options) => {
|
|
107
|
+
let response: Response;
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
response = await fetch(options.url, {
|
|
111
|
+
headers: Object.fromEntries((options.requestHeaders ?? []).map((header) => [header.name, header.value])),
|
|
112
|
+
signal: options.abortSignal ?? undefined,
|
|
113
|
+
});
|
|
114
|
+
} catch (error) {
|
|
115
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
116
|
+
throw new AdapterAbortError(error);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
let payload: Blob;
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
payload = await response.blob();
|
|
126
|
+
} catch (error) {
|
|
127
|
+
throw new AdapterParseError(error);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
payload,
|
|
132
|
+
responseHeaders: [...response.headers.entries()].map(([name, value]) => ({ name, value })),
|
|
133
|
+
status: response.status,
|
|
134
|
+
statusText: response.statusText,
|
|
135
|
+
url: options.url,
|
|
54
136
|
};
|
|
55
137
|
},
|
|
56
138
|
},
|
|
@@ -58,3 +140,86 @@ const httpService = await getDefaultHttpService({
|
|
|
58
140
|
```
|
|
59
141
|
|
|
60
142
|
This approach gives you fine-grained control over how requests are made, while still benefiting from the core service's additional functionalities.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Error Handling
|
|
147
|
+
|
|
148
|
+
All operations return a discriminated `success`/`error` result — the SDK never throws. Errors are represented by `KontentSdkError`, which carries a `details` object with a `reason` discriminant that can be narrowed for type-safe handling:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
const { success, response, error } = await httpService.request({
|
|
152
|
+
url: "https://manage.kontent.ai/v2/projects/...",
|
|
153
|
+
method: "GET"
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
if (!success) {
|
|
157
|
+
switch (error.details.reason) {
|
|
158
|
+
case "unauthorized":
|
|
159
|
+
// error.details includes: status, statusText, responseHeaders, kontentErrorResponse
|
|
160
|
+
console.error("Check your API key:", error.details.kontentErrorResponse?.message);
|
|
161
|
+
break;
|
|
162
|
+
case "notFound":
|
|
163
|
+
console.error("Resource not found:", error.url);
|
|
164
|
+
break;
|
|
165
|
+
case "invalidResponse":
|
|
166
|
+
// Any non-2xx response that isn't 401 or 404
|
|
167
|
+
console.error(`HTTP ${error.details.status}:`, error.details.kontentErrorResponse?.message);
|
|
168
|
+
break;
|
|
169
|
+
case "parseError":
|
|
170
|
+
// The response claimed to be JSON, but parsing it failed
|
|
171
|
+
console.error("Failed to parse response:", error.details.originalError);
|
|
172
|
+
break;
|
|
173
|
+
case "adapterError":
|
|
174
|
+
// Network failure, timeout, or other transport-level issue
|
|
175
|
+
console.error("Request failed:", error.details.originalError);
|
|
176
|
+
break;
|
|
177
|
+
case "invalidUrl":
|
|
178
|
+
// The provided URL could not be parsed before the request was sent
|
|
179
|
+
console.error("Invalid URL:", error.details.originalError);
|
|
180
|
+
break;
|
|
181
|
+
case "invalidBody":
|
|
182
|
+
// The request body could not be serialized before the request was sent
|
|
183
|
+
console.error("Invalid body:", error.details.originalError);
|
|
184
|
+
break;
|
|
185
|
+
case "validationFailed":
|
|
186
|
+
// Zod schema validation failed (when responseValidation is enabled)
|
|
187
|
+
console.error("Unexpected response shape for", error.details.url, error.details.zodError);
|
|
188
|
+
break;
|
|
189
|
+
case "noResponses":
|
|
190
|
+
// Paging query completed without any responses
|
|
191
|
+
console.error("No data returned for", error.details.url);
|
|
192
|
+
break;
|
|
193
|
+
case "aborted":
|
|
194
|
+
// The request was cancelled before it could complete
|
|
195
|
+
console.error("Request was aborted:", error.details.originalError);
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// response is fully typed here
|
|
202
|
+
console.log(response.payload);
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Retry Strategy
|
|
208
|
+
|
|
209
|
+
The default `HttpService` includes configurable retry logic. HTTP 429 (rate limit) responses are always retried automatically with a delay based on the `Retry-After` header. All other HTTP error responses are not retried.
|
|
210
|
+
|
|
211
|
+
For transport-level failures (network errors, timeouts), you can control retry behavior via `canRetryAdapterError`:
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
const httpService = getDefaultHttpService({
|
|
215
|
+
retryStrategy: {
|
|
216
|
+
maxRetries: 3,
|
|
217
|
+
canRetryAdapterError: (error) => {
|
|
218
|
+
// `error` is typed as KontentSdkError<ErrorDetailsFor<"adapterError">>
|
|
219
|
+
// Return true to retry, false to stop
|
|
220
|
+
return true;
|
|
221
|
+
},
|
|
222
|
+
logRetryAttempt: "logToConsole",
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core-sdk-info.js","sourceRoot":"","sources":["../lib/core-sdk-info.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAY;IACnC,IAAI,EAAE,WAAW;IACjB,OAAO,EAAE,aAAa;IACtB,IAAI,EAAE,sBAAsB;CAC5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.utils.js","sourceRoot":"","sources":["../../lib/devkit/console.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAItC,MAAM,UAAU,QAAQ,CAAC,KAAmB,EAAE,IAAY;IACzD,OAAO,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { colorize } from "./console.utils.js";
|
|
2
|
+
export function getEnvironmentRequiredValue(variableName) {
|
|
3
|
+
const value = getEnvironmentOptionalValue(variableName);
|
|
4
|
+
if (!value) {
|
|
5
|
+
throw new Error(`Missing environment variable '${colorize("red", variableName)}'`);
|
|
6
|
+
}
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
export function getEnvironmentOptionalValue(variableName) {
|
|
10
|
+
return process.env[variableName];
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=environment.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"environment.utils.js","sourceRoot":"","sources":["../../lib/devkit/environment.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,UAAU,2BAA2B,CAAC,YAAoB;IAC/D,MAAM,KAAK,GAAG,2BAA2B,CAAC,YAAY,CAAC,CAAC;IAExD,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC;IACpF,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,YAAoB;IAC/D,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { rmSync } from "node:fs";
|
|
2
|
-
import
|
|
2
|
+
import { colorize } from "./console.utils.js";
|
|
3
3
|
export function deleteFolderRecursive(path) {
|
|
4
|
-
console.log(`Deleting existing folder '${
|
|
4
|
+
console.log(`Deleting existing folder '${colorize("yellow", path)}'`);
|
|
5
5
|
rmSync(path, {
|
|
6
6
|
recursive: true,
|
|
7
7
|
force: true,
|
|
8
8
|
});
|
|
9
|
-
console.log(`Folder '${
|
|
9
|
+
console.log(`Folder '${colorize("yellow", path)}' deleted successfully`);
|
|
10
10
|
}
|
|
11
11
|
//# sourceMappingURL=script.utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"script.utils.js","sourceRoot":"","sources":["../../lib/devkit/script.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,
|
|
1
|
+
{"version":3,"file":"script.utils.js","sourceRoot":"","sources":["../../lib/devkit/script.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,UAAU,qBAAqB,CAAC,IAAY;IACjD,OAAO,CAAC,GAAG,CAAC,6BAA6B,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACtE,MAAM,CAAC,IAAI,EAAE;QACZ,SAAS,EAAE,IAAI;QACf,KAAK,EAAE,IAAI;KACX,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,WAAW,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,wBAAwB,CAAC,CAAC;AAC1E,CAAC"}
|
package/dist/devkit_api.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
|
+
/** biome-ignore-all lint/performance/noBarrelFile: One barrel for exported API is fine */
|
|
2
|
+
export { type ConsoleColor, colorize } from "./devkit/console.utils.js";
|
|
3
|
+
export { getEnvironmentOptionalValue, getEnvironmentRequiredValue } from "./devkit/environment.utils.js";
|
|
1
4
|
export { deleteFolderRecursive } from "./devkit/script.utils.js";
|
|
2
5
|
export { replaceSdkVersionPlaceholder } from "./utils/sdk-version.utils.js";
|
package/dist/devkit_api.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
/** biome-ignore-all lint/performance/noBarrelFile: One barrel for exported API is fine */
|
|
2
|
+
export { colorize } from "./devkit/console.utils.js";
|
|
3
|
+
export { getEnvironmentOptionalValue, getEnvironmentRequiredValue } from "./devkit/environment.utils.js";
|
|
2
4
|
export { deleteFolderRecursive } from "./devkit/script.utils.js";
|
|
3
5
|
export { replaceSdkVersionPlaceholder } from "./utils/sdk-version.utils.js";
|
|
4
6
|
//# sourceMappingURL=devkit_api.js.map
|
package/dist/devkit_api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devkit_api.js","sourceRoot":"","sources":["../lib/devkit_api.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"devkit_api.js","sourceRoot":"","sources":["../lib/devkit_api.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAE1F,OAAO,EAAqB,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,2BAA2B,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACzG,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { HttpAdapter } from "./http.models.js";
|
|
2
|
-
export declare function getDefaultHttpAdapter(): HttpAdapter
|
|
2
|
+
export declare function getDefaultHttpAdapter(): Required<HttpAdapter>;
|
|
@@ -1,31 +1,85 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AdapterAbortError, AdapterParseError } from "../models/error.models.js";
|
|
2
|
+
import { runWithAbortSignal } from "../utils/abort.utils.js";
|
|
3
|
+
import { isApplicationJsonResponseType, toFetchHeaders, toSdkHeaders } from "../utils/header.utils.js";
|
|
4
|
+
import { tryCatchAsync } from "../utils/try-catch.utils.js";
|
|
2
5
|
export function getDefaultHttpAdapter() {
|
|
3
6
|
return {
|
|
4
|
-
|
|
5
|
-
const response = await
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
executeRequest: async (options) => {
|
|
8
|
+
const response = await getResponse(options);
|
|
9
|
+
const sdkHeaders = toSdkHeaders(response.headers);
|
|
10
|
+
const payload = isApplicationJsonResponseType(sdkHeaders)
|
|
11
|
+
? await parseResponse({
|
|
12
|
+
parseFunc: async () => (await response.json()),
|
|
13
|
+
abortSignal: options.abortSignal,
|
|
14
|
+
})
|
|
15
|
+
: null;
|
|
16
|
+
return createAdapterResponse(options.url, response, payload, sdkHeaders);
|
|
17
|
+
},
|
|
18
|
+
downloadFile: async (options) => {
|
|
19
|
+
const response = await getResponse({
|
|
20
|
+
...options,
|
|
21
|
+
method: "GET",
|
|
9
22
|
});
|
|
10
|
-
const
|
|
11
|
-
return
|
|
12
|
-
isValidResponse: response.ok,
|
|
13
|
-
responseHeaders: sdkResponseHeaders,
|
|
14
|
-
status: response.status,
|
|
15
|
-
statusText: response.statusText,
|
|
16
|
-
toBlobAsync: async () => await response.blob(),
|
|
17
|
-
toJsonAsync: async () => {
|
|
18
|
-
const contentTypeResponseHeader = sdkResponseHeaders
|
|
19
|
-
.find((m) => m.name.toLowerCase() === "Content-Type".toLowerCase())
|
|
20
|
-
?.value.toLowerCase();
|
|
21
|
-
if (contentTypeResponseHeader?.includes("application/json")) {
|
|
22
|
-
// Includes instead of equal due to the fact that the header value can be 'application/json; charset=utf-8' or similar
|
|
23
|
-
return (await response.json());
|
|
24
|
-
}
|
|
25
|
-
return null;
|
|
26
|
-
},
|
|
27
|
-
};
|
|
23
|
+
const file = await parseResponse({ parseFunc: async () => response.blob(), abortSignal: options.abortSignal });
|
|
24
|
+
return createAdapterResponse(options.url, response, file, toSdkHeaders(response.headers));
|
|
28
25
|
},
|
|
29
26
|
};
|
|
30
27
|
}
|
|
28
|
+
async function getResponse(options) {
|
|
29
|
+
const { error, data, success } = await tryCatchAsync(async () => await fetch(options.url, {
|
|
30
|
+
method: options.method,
|
|
31
|
+
headers: toFetchHeaders(options.requestHeaders ?? []),
|
|
32
|
+
body: options.body ?? null,
|
|
33
|
+
signal: options.abortSignal ?? null,
|
|
34
|
+
}));
|
|
35
|
+
if (success) {
|
|
36
|
+
return data;
|
|
37
|
+
}
|
|
38
|
+
if (isAbortError(error)) {
|
|
39
|
+
// this is to notify the HttpService that the request was aborted
|
|
40
|
+
// HttpService will then convert the error to a KontentSdkError with the reason "aborted"
|
|
41
|
+
throw new AdapterAbortError(error);
|
|
42
|
+
}
|
|
43
|
+
// re-throw original error
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
async function parseResponse({ parseFunc, abortSignal, }) {
|
|
47
|
+
const runParseFunc = async () => {
|
|
48
|
+
const { success, data, error } = await tryCatchAsync(async () => {
|
|
49
|
+
return await parseFunc();
|
|
50
|
+
});
|
|
51
|
+
if (!success) {
|
|
52
|
+
// this is to notify the HttpService that the response is not valid JSON or BLOB
|
|
53
|
+
// HttpService will then convert the error to a KontentSdkError with the reason "parseError"
|
|
54
|
+
throw new AdapterParseError(error);
|
|
55
|
+
}
|
|
56
|
+
return data;
|
|
57
|
+
};
|
|
58
|
+
if (!abortSignal) {
|
|
59
|
+
return await runParseFunc();
|
|
60
|
+
}
|
|
61
|
+
const { isAborted, data } = await runWithAbortSignal({
|
|
62
|
+
func: runParseFunc,
|
|
63
|
+
abortSignal: abortSignal,
|
|
64
|
+
});
|
|
65
|
+
if (isAborted) {
|
|
66
|
+
throw new AdapterAbortError(new Error("Adapter has aborted the request while parsing the response."));
|
|
67
|
+
}
|
|
68
|
+
return data;
|
|
69
|
+
}
|
|
70
|
+
function isAbortError(error) {
|
|
71
|
+
if (!error || typeof error !== "object") {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return "name" in error && error.name === "AbortError";
|
|
75
|
+
}
|
|
76
|
+
function createAdapterResponse(url, response, payload, responseHeaders) {
|
|
77
|
+
return {
|
|
78
|
+
responseHeaders,
|
|
79
|
+
status: response.status,
|
|
80
|
+
statusText: response.statusText,
|
|
81
|
+
url: url,
|
|
82
|
+
payload,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
31
85
|
//# sourceMappingURL=http.adapter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.adapter.js","sourceRoot":"","sources":["../../lib/http/http.adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"http.adapter.js","sourceRoot":"","sources":["../../lib/http/http.adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
import type { Header, HttpMethod,
|
|
2
|
-
import type {
|
|
3
|
-
import type { JsonValue } from "../models/json.models.js";
|
|
4
|
-
type
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
readonly success: false;
|
|
1
|
+
import type { Header, HttpMethod, RetryStrategyOptions } from "../models/core.models.js";
|
|
2
|
+
import type { KontentSdkError } from "../models/error.models.js";
|
|
3
|
+
import type { JsonObject, JsonValue } from "../models/json.models.js";
|
|
4
|
+
import type { LiteralUnionNumber } from "../models/utility.types.js";
|
|
5
|
+
import type { QueryResponse } from "../sdk/sdk-models.js";
|
|
6
|
+
import type { Failure, Success } from "../utils/try-catch.utils.js";
|
|
7
|
+
export type HttpResult<TResponse> = Success<{
|
|
8
|
+
readonly response: TResponse;
|
|
9
|
+
}> | Failure<{
|
|
11
10
|
readonly response?: never;
|
|
12
|
-
|
|
13
|
-
};
|
|
14
|
-
export type HttpResult<TData> = Success<TData> | Failure;
|
|
11
|
+
}, KontentSdkError>;
|
|
15
12
|
/**
|
|
16
13
|
* Helper status codes for the HTTP service.
|
|
17
14
|
* It can be any valid number status code as this type only serves as a helper.
|
|
@@ -31,23 +28,26 @@ export type DefaultHttpServiceConfig = {
|
|
|
31
28
|
*/
|
|
32
29
|
readonly adapter?: HttpAdapter;
|
|
33
30
|
};
|
|
34
|
-
export type
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
export type HttpPayload = JsonValue | Blob;
|
|
32
|
+
export type HttpRequestBody = JsonObject | Blob | null;
|
|
33
|
+
export type HttpResponse<TPayload extends AdapterPayload, TRequestBody extends HttpRequestBody> = HttpResult<{
|
|
34
|
+
readonly payload: TPayload;
|
|
35
|
+
readonly body?: TRequestBody;
|
|
37
36
|
readonly method: HttpMethod;
|
|
38
37
|
readonly requestHeaders: readonly Header[];
|
|
39
|
-
readonly adapterResponse:
|
|
38
|
+
readonly adapterResponse: AdapterResponse<TPayload>;
|
|
40
39
|
}>;
|
|
41
|
-
export type ExecuteRequestOptions<
|
|
40
|
+
export type ExecuteRequestOptions<TRequestBody extends HttpRequestBody> = {
|
|
42
41
|
readonly url: string;
|
|
43
42
|
readonly method: HttpMethod;
|
|
44
|
-
readonly body
|
|
43
|
+
readonly body?: TRequestBody;
|
|
45
44
|
readonly requestHeaders?: readonly Header[];
|
|
45
|
+
readonly abortSignal?: AbortSignal | undefined;
|
|
46
46
|
};
|
|
47
47
|
export type UploadFileRequestOptions = Omit<ExecuteRequestOptions<Blob>, "method"> & {
|
|
48
48
|
readonly method: Extract<HttpMethod, "POST" | "PUT" | "PATCH">;
|
|
49
49
|
};
|
|
50
|
-
export type DownloadFileRequestOptions = Pick<ExecuteRequestOptions<
|
|
50
|
+
export type DownloadFileRequestOptions = Pick<ExecuteRequestOptions<null>, "url" | "requestHeaders" | "abortSignal">;
|
|
51
51
|
/**
|
|
52
52
|
* Represents the HTTP service used for making requests to the Kontent.ai API.
|
|
53
53
|
*
|
|
@@ -62,29 +62,39 @@ export type HttpService = {
|
|
|
62
62
|
/**
|
|
63
63
|
* Executes request with the given method and body.
|
|
64
64
|
*/
|
|
65
|
-
|
|
65
|
+
request<TResponsePayload extends JsonValue, TRequestBody extends HttpRequestBody>(opts: ExecuteRequestOptions<TRequestBody>): Promise<HttpResponse<TResponsePayload, TRequestBody>>;
|
|
66
66
|
/**
|
|
67
67
|
* Downloads a file from the given URL as a blob.
|
|
68
68
|
*/
|
|
69
|
-
|
|
69
|
+
downloadFile(opts: DownloadFileRequestOptions): Promise<HttpResponse<Blob, null>>;
|
|
70
70
|
/**
|
|
71
71
|
* This method is used to upload a kontent.ai binary file.
|
|
72
72
|
*/
|
|
73
|
-
|
|
73
|
+
uploadFile<TResponsePayload extends JsonValue>(opts: UploadFileRequestOptions): Promise<HttpResponse<TResponsePayload, Blob>>;
|
|
74
74
|
};
|
|
75
|
-
export type AdapterResponse<
|
|
76
|
-
readonly
|
|
77
|
-
readonly toBlobAsync: () => Promise<Blob>;
|
|
78
|
-
readonly isValidResponse: boolean;
|
|
75
|
+
export type AdapterResponse<TPayload extends AdapterPayload> = {
|
|
76
|
+
readonly payload: TPayload;
|
|
79
77
|
readonly responseHeaders: readonly Header[];
|
|
80
|
-
readonly status:
|
|
78
|
+
readonly status: HttpServiceStatus;
|
|
81
79
|
readonly statusText: string;
|
|
80
|
+
readonly url: string;
|
|
82
81
|
};
|
|
83
|
-
export type
|
|
82
|
+
export type AdapterBody = string | Blob | null;
|
|
83
|
+
export type AdapterPayload = JsonValue | Blob;
|
|
84
|
+
export type AdapterExecuteRequestOptions = {
|
|
84
85
|
readonly url: string;
|
|
85
86
|
readonly method: HttpMethod;
|
|
86
|
-
readonly body
|
|
87
|
+
readonly body?: AdapterBody;
|
|
87
88
|
readonly requestHeaders?: readonly Header[];
|
|
89
|
+
readonly abortSignal?: AbortSignal | undefined;
|
|
90
|
+
};
|
|
91
|
+
export type AdapterDownloadFileOptions = Pick<AdapterExecuteRequestOptions, "url" | "requestHeaders" | "abortSignal">;
|
|
92
|
+
export type GetNextPageData<TResponsePayload extends JsonValue, TMeta> = (response: QueryResponse<TResponsePayload, TMeta>) => {
|
|
93
|
+
readonly continuationToken?: string | undefined;
|
|
94
|
+
readonly nextPageUrl?: string | undefined;
|
|
95
|
+
};
|
|
96
|
+
export type PaginationConfig = {
|
|
97
|
+
readonly maxPagesCount?: number;
|
|
88
98
|
};
|
|
89
99
|
/**
|
|
90
100
|
* Defines the adapter responsible solely for executing HTTP requests.
|
|
@@ -98,6 +108,6 @@ export type AdapterRequestOptions = {
|
|
|
98
108
|
* Alternatively, you may implement the entire `HttpService` interface to create a fully customized HTTP service.
|
|
99
109
|
*/
|
|
100
110
|
export type HttpAdapter = {
|
|
101
|
-
readonly
|
|
111
|
+
readonly executeRequest?: (options: AdapterExecuteRequestOptions) => Promise<AdapterResponse<JsonValue>>;
|
|
112
|
+
readonly downloadFile?: (options: AdapterDownloadFileOptions) => Promise<AdapterResponse<Blob>>;
|
|
102
113
|
};
|
|
103
|
-
export {};
|