@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.
Files changed (127) hide show
  1. package/.npmignore +1 -5
  2. package/LICENSE.md +1 -1
  3. package/README.md +177 -12
  4. package/dist/core-sdk-info.d.ts +2 -0
  5. package/dist/core-sdk-info.js +6 -0
  6. package/dist/core-sdk-info.js.map +1 -0
  7. package/dist/devkit/console.utils.d.ts +2 -0
  8. package/dist/devkit/console.utils.js +5 -0
  9. package/dist/devkit/console.utils.js.map +1 -0
  10. package/dist/devkit/environment.utils.d.ts +2 -0
  11. package/dist/devkit/environment.utils.js +12 -0
  12. package/dist/devkit/environment.utils.js.map +1 -0
  13. package/dist/devkit/script.utils.js +3 -3
  14. package/dist/devkit/script.utils.js.map +1 -1
  15. package/dist/devkit_api.d.ts +3 -0
  16. package/dist/devkit_api.js +3 -1
  17. package/dist/devkit_api.js.map +1 -1
  18. package/dist/http/http.adapter.d.ts +1 -1
  19. package/dist/http/http.adapter.js +78 -24
  20. package/dist/http/http.adapter.js.map +1 -1
  21. package/dist/http/http.models.d.ts +42 -32
  22. package/dist/http/http.service.js +294 -220
  23. package/dist/http/http.service.js.map +1 -1
  24. package/dist/models/core.models.d.ts +34 -29
  25. package/dist/models/error.models.d.ts +48 -27
  26. package/dist/models/error.models.js +40 -1
  27. package/dist/models/error.models.js.map +1 -1
  28. package/dist/models/json.models.d.ts +13 -4
  29. package/dist/models/json.models.js +10 -1
  30. package/dist/models/json.models.js.map +1 -1
  31. package/dist/models/utility.types.d.ts +16 -0
  32. package/dist/models/utility.types.js +2 -0
  33. package/dist/models/utility.types.js.map +1 -0
  34. package/dist/public_api.d.ts +19 -11
  35. package/dist/public_api.js +15 -6
  36. package/dist/public_api.js.map +1 -1
  37. package/dist/sdk/queries/fetch-sdk-query.d.ts +7 -0
  38. package/dist/sdk/queries/fetch-sdk-query.js +24 -0
  39. package/dist/sdk/queries/fetch-sdk-query.js.map +1 -0
  40. package/dist/sdk/queries/mutation-sdk-query.d.ts +4 -0
  41. package/dist/sdk/queries/mutation-sdk-query.js +17 -0
  42. package/dist/sdk/queries/mutation-sdk-query.js.map +1 -0
  43. package/dist/sdk/queries/paged-fetch-sdk-query.d.ts +6 -0
  44. package/dist/sdk/queries/paged-fetch-sdk-query.js +145 -0
  45. package/dist/sdk/queries/paged-fetch-sdk-query.js.map +1 -0
  46. package/dist/sdk/resolve-query.d.ts +8 -0
  47. package/dist/sdk/resolve-query.js +108 -0
  48. package/dist/sdk/resolve-query.js.map +1 -0
  49. package/dist/sdk/sdk-config.d.ts +3 -0
  50. package/dist/sdk/sdk-config.js +4 -0
  51. package/dist/sdk/sdk-config.js.map +1 -0
  52. package/dist/sdk/sdk-models.d.ts +101 -36
  53. package/dist/sdk/sdk-utils.d.ts +2 -0
  54. package/dist/sdk/sdk-utils.js +9 -0
  55. package/dist/sdk/sdk-utils.js.map +1 -0
  56. package/dist/testkit/poll.utils.d.ts +5 -0
  57. package/dist/testkit/poll.utils.js +24 -0
  58. package/dist/testkit/poll.utils.js.map +1 -0
  59. package/dist/testkit/testkit.utils.d.ts +20 -0
  60. package/dist/testkit/testkit.utils.js +100 -0
  61. package/dist/testkit/testkit.utils.js.map +1 -0
  62. package/dist/testkit_api.d.ts +3 -1
  63. package/dist/testkit_api.js +3 -2
  64. package/dist/testkit_api.js.map +1 -1
  65. package/dist/utils/abort.utils.d.ts +12 -0
  66. package/dist/utils/abort.utils.js +29 -0
  67. package/dist/utils/abort.utils.js.map +1 -0
  68. package/dist/utils/core.utils.d.ts +3 -1
  69. package/dist/utils/core.utils.js +22 -2
  70. package/dist/utils/core.utils.js.map +1 -1
  71. package/dist/utils/error.utils.d.ts +18 -7
  72. package/dist/utils/error.utils.js +35 -7
  73. package/dist/utils/error.utils.js.map +1 -1
  74. package/dist/utils/header.utils.d.ts +6 -1
  75. package/dist/utils/header.utils.js +37 -6
  76. package/dist/utils/header.utils.js.map +1 -1
  77. package/dist/utils/retry.utils.d.ts +16 -11
  78. package/dist/utils/retry.utils.js +131 -63
  79. package/dist/utils/retry.utils.js.map +1 -1
  80. package/dist/utils/sdk-version.utils.js +2 -2
  81. package/dist/utils/sdk-version.utils.js.map +1 -1
  82. package/dist/utils/try-catch.utils.d.ts +15 -0
  83. package/dist/utils/{try.utils.js → try-catch.utils.js} +1 -1
  84. package/dist/utils/try-catch.utils.js.map +1 -0
  85. package/dist/utils/type.utils.d.ts +2 -0
  86. package/dist/utils/type.utils.js +5 -0
  87. package/dist/utils/type.utils.js.map +1 -0
  88. package/dist/utils/url.utils.d.ts +5 -0
  89. package/dist/utils/url.utils.js +10 -0
  90. package/dist/utils/url.utils.js.map +1 -0
  91. package/package.json +61 -64
  92. package/dist/models/utility.models.d.ts +0 -20
  93. package/dist/models/utility.models.js +0 -2
  94. package/dist/models/utility.models.js.map +0 -1
  95. package/dist/sdk/sdk-queries.d.ts +0 -30
  96. package/dist/sdk/sdk-queries.js +0 -152
  97. package/dist/sdk/sdk-queries.js.map +0 -1
  98. package/dist/sdk-info.d.ts +0 -5
  99. package/dist/sdk-info.js +0 -6
  100. package/dist/sdk-info.js.map +0 -1
  101. package/dist/testkit/test.utils.d.ts +0 -15
  102. package/dist/testkit/test.utils.js +0 -42
  103. package/dist/testkit/test.utils.js.map +0 -1
  104. package/dist/utils/try.utils.d.ts +0 -14
  105. package/dist/utils/try.utils.js.map +0 -1
  106. package/lib/devkit/script.utils.ts +0 -12
  107. package/lib/devkit_api.ts +0 -3
  108. package/lib/http/http.adapter.ts +0 -38
  109. package/lib/http/http.models.ts +0 -122
  110. package/lib/http/http.service.ts +0 -320
  111. package/lib/models/core.models.ts +0 -89
  112. package/lib/models/error.models.ts +0 -83
  113. package/lib/models/json.models.ts +0 -9
  114. package/lib/models/utility.models.ts +0 -21
  115. package/lib/public_api.ts +0 -45
  116. package/lib/sdk/sdk-models.ts +0 -85
  117. package/lib/sdk/sdk-queries.ts +0 -232
  118. package/lib/sdk-info.ts +0 -5
  119. package/lib/testkit/test.utils.ts +0 -79
  120. package/lib/testkit/testkit.models.ts +0 -7
  121. package/lib/testkit_api.ts +0 -3
  122. package/lib/utils/core.utils.ts +0 -3
  123. package/lib/utils/error.utils.ts +0 -48
  124. package/lib/utils/header.utils.ts +0 -40
  125. package/lib/utils/retry.utils.ts +0 -156
  126. package/lib/utils/sdk-version.utils.ts +0 -16
  127. package/lib/utils/try.utils.ts +0 -30
package/.npmignore CHANGED
@@ -1,10 +1,6 @@
1
1
  # Ignore everything
2
2
  *
3
-
4
- # But descend into directories
5
-
6
- # Recursively allow files under subtree
7
- !/lib/**
3
+ # And allow following
8
4
  !/dist/**
9
5
  !package.json
10
6
  !.npmignore
package/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # MIT License
2
2
 
3
- Copyright (c) 2025 Kontent s.r.o.
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 validation) and only swap out the underlying HTTP client, you can do so by supplying a custom `HttpAdapter` to the `getDefaultHttpService` method.
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
- const httpService = await getDefaultHttpService({
66
+ import { AdapterAbortError, AdapterParseError, getDefaultHttpService } from "@kontent-ai/core-sdk";
67
+
68
+ const httpService = getDefaultHttpService({
44
69
  adapter: {
45
- requestAsync: async (options) => {
46
- // Execute the request using your custom HTTP client
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
- isValidResponse: <true | false>,
49
- responseHeaders: <arrayOfHeaders>,
50
- status: <statusCode>,
51
- statusText: <statusText>,
52
- toJsonAsync: async () => <responseInJson>,
53
- toBlobAsync: async () => <responseInBlob>,
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,2 @@
1
+ import type { SDKInfo } from "./models/core.models.js";
2
+ export declare const coreSdkInfo: SDKInfo;
@@ -0,0 +1,6 @@
1
+ export const coreSdkInfo = {
2
+ host: "npmjs.com",
3
+ version: "12.0.0-preview.21",
4
+ name: "@kontent-ai/core-sdk",
5
+ };
6
+ //# sourceMappingURL=core-sdk-info.js.map
@@ -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,2 @@
1
+ export type ConsoleColor = "red" | "green" | "yellow" | "blue" | "cyan" | "magenta" | "white" | "gray";
2
+ export declare function colorize(color: ConsoleColor, text: string): string;
@@ -0,0 +1,5 @@
1
+ import { styleText } from "node:util";
2
+ export function colorize(color, text) {
3
+ return styleText(color, text);
4
+ }
5
+ //# sourceMappingURL=console.utils.js.map
@@ -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,2 @@
1
+ export declare function getEnvironmentRequiredValue(variableName: string): string;
2
+ export declare function getEnvironmentOptionalValue(variableName: string): string | undefined;
@@ -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 chalk from "chalk";
2
+ import { colorize } from "./console.utils.js";
3
3
  export function deleteFolderRecursive(path) {
4
- console.log(`Deleting existing folder '${chalk.yellow(path)}'`);
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 '${chalk.yellow(path)}' deleted successfully`);
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,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,UAAU,qBAAqB,CAAC,IAAY;IACjD,OAAO,CAAC,GAAG,CAAC,6BAA6B,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChE,MAAM,CAAC,IAAI,EAAE;QACZ,SAAS,EAAE,IAAI;QACf,KAAK,EAAE,IAAI;KACX,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;AACpE,CAAC"}
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"}
@@ -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";
@@ -1,4 +1,6 @@
1
- // biome-ignore lint/performance/noBarrelFile: One barrel for the Devkit API is fine
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
@@ -1 +1 @@
1
- {"version":3,"file":"devkit_api.js","sourceRoot":"","sources":["../lib/devkit_api.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC"}
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 { toFetchHeaders, toSdkHeaders } from "../utils/header.utils.js";
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
- requestAsync: async (options) => {
5
- const response = await fetch(options.url, {
6
- method: options.method,
7
- headers: toFetchHeaders(options.requestHeaders ?? []),
8
- body: options.body,
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 sdkResponseHeaders = toSdkHeaders(response.headers);
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":"AAEA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGxE,MAAM,UAAU,qBAAqB;IACpC,OAAO;QACN,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YAC/B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;gBACzC,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;gBACrD,IAAI,EAAE,OAAO,CAAC,IAAI;aAClB,CAAC,CAAC;YAEH,MAAM,kBAAkB,GAAG,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAE1D,OAAO;gBACN,eAAe,EAAE,QAAQ,CAAC,EAAE;gBAC5B,eAAe,EAAE,kBAAkB;gBACnC,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE;gBAC9C,WAAW,EAAE,KAAK,IAAI,EAAE;oBACvB,MAAM,yBAAyB,GAAG,kBAAkB;yBAClD,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAM,cAA2C,CAAC,WAAW,EAAE,CAAC;wBACjG,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;oBAEvB,IAAI,yBAAyB,EAAE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;wBAC7D,sHAAsH;wBACtH,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAc,CAAC;oBAC7C,CAAC;oBAED,OAAO,IAAI,CAAC;gBACb,CAAC;aACD,CAAC;QACH,CAAC;KACD,CAAC;AACH,CAAC"}
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, LiteralUnionNumber, RetryStrategyOptions } from "../models/core.models.js";
2
- import type { CoreSdkError } from "../models/error.models.js";
3
- import type { JsonValue } from "../models/json.models.js";
4
- type Success<TData> = {
5
- readonly success: true;
6
- readonly response: TData;
7
- readonly error?: never;
8
- };
9
- type Failure = {
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
- readonly error: CoreSdkError;
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 HttpResponse<TResponseData extends JsonValue | Blob, TBodyData extends JsonValue | Blob> = HttpResult<{
35
- readonly data: TResponseData;
36
- readonly body: TBodyData;
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: Omit<AdapterResponse, "toJsonAsync" | "toBlobAsync">;
38
+ readonly adapterResponse: AdapterResponse<TPayload>;
40
39
  }>;
41
- export type ExecuteRequestOptions<TBodyData extends JsonValue | Blob> = {
40
+ export type ExecuteRequestOptions<TRequestBody extends HttpRequestBody> = {
42
41
  readonly url: string;
43
42
  readonly method: HttpMethod;
44
- readonly body: TBodyData;
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<Blob>, "url" | "requestHeaders">;
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
- requestAsync<TResponseData extends JsonValue, TBodyData extends JsonValue>(opts: ExecuteRequestOptions<TBodyData>): Promise<HttpResponse<TResponseData, TBodyData>>;
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
- downloadFileAsync(opts: DownloadFileRequestOptions): Promise<HttpResponse<Blob, null>>;
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
- uploadFileAsync<TResponseData extends JsonValue>(opts: UploadFileRequestOptions): Promise<HttpResponse<TResponseData, Blob>>;
73
+ uploadFile<TResponsePayload extends JsonValue>(opts: UploadFileRequestOptions): Promise<HttpResponse<TResponsePayload, Blob>>;
74
74
  };
75
- export type AdapterResponse<TStatusCode extends HttpServiceStatus = HttpServiceStatus> = {
76
- readonly toJsonAsync: () => Promise<JsonValue>;
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: TStatusCode;
78
+ readonly status: HttpServiceStatus;
81
79
  readonly statusText: string;
80
+ readonly url: string;
82
81
  };
83
- export type AdapterRequestOptions = {
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: string | Blob | undefined | null;
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 requestAsync: (options: AdapterRequestOptions) => Promise<AdapterResponse>;
111
+ readonly executeRequest?: (options: AdapterExecuteRequestOptions) => Promise<AdapterResponse<JsonValue>>;
112
+ readonly downloadFile?: (options: AdapterDownloadFileOptions) => Promise<AdapterResponse<Blob>>;
102
113
  };
103
- export {};