{"id":19924364,"url":"https://github.com/kontent-ai/core-sdk-js","last_synced_at":"2026-04-02T19:01:30.292Z","repository":{"id":35240650,"uuid":"213578574","full_name":"kontent-ai/core-sdk-js","owner":"kontent-ai","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-30T12:23:15.000Z","size":1931,"stargazers_count":4,"open_issues_count":1,"forks_count":3,"subscribers_count":14,"default_branch":"main","last_synced_at":"2026-03-30T12:24:13.842Z","etag":null,"topics":["kontent-ai","kontent-ai-tool"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kontent-ai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-10-08T07:41:21.000Z","updated_at":"2026-03-30T12:23:19.000Z","dependencies_parsed_at":"2024-04-17T00:32:13.448Z","dependency_job_id":"bb8b6724-e95c-4378-ab34-129b7921a5ad","html_url":"https://github.com/kontent-ai/core-sdk-js","commit_stats":null,"previous_names":["kontent-ai/kontent-core-js","kentico/kontent-core-js"],"tags_count":79,"template":false,"template_full_name":null,"purl":"pkg:github/kontent-ai/core-sdk-js","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kontent-ai%2Fcore-sdk-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kontent-ai%2Fcore-sdk-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kontent-ai%2Fcore-sdk-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kontent-ai%2Fcore-sdk-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kontent-ai","download_url":"https://codeload.github.com/kontent-ai/core-sdk-js/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kontent-ai%2Fcore-sdk-js/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31313845,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kontent-ai","kontent-ai-tool"],"created_at":"2024-11-12T22:17:09.552Z","updated_at":"2026-04-02T19:01:30.276Z","avatar_url":"https://github.com/kontent-ai.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![npm version](https://badge.fury.io/js//%40kontent-ai%2Fcore-sdk.svg)](https://www.npmjs.com/package/@kontent-ai/core-sdk)\n[![Build](https://github.com/kontent-ai/core-sdk-js/actions/workflows/build.yml/badge.svg)](https://github.com/kontent-ai/core-sdk-js/actions/workflows/build.yml)\n[![Unit Tests](https://github.com/kontent-ai/core-sdk-js/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/kontent-ai/core-sdk-js/actions/workflows/unit-tests.yml)\n[![Integration Tests](https://github.com/kontent-ai/core-sdk-js/actions/workflows/integration-tests.yml/badge.svg)](https://github.com/kontent-ai/core-sdk-js/actions/workflows/integration-tests.yml)\n[![npm](https://img.shields.io/npm/dt/@kontent-ai/core-sdk.svg)](https://www.npmjs.com/package/@kontent-ai/core-sdk)\n[![Known Vulnerabilities](https://snyk.io/test/github/Kontent-ai/core-sdk-js/badge.svg)](https://snyk.io/test/github/kontent-ai/core-sdk-js)\n[![GitHub license](https://img.shields.io/github/license/Kontent-ai/core-sdk-js.svg)](https://github.com/kontent-ai/core-sdk-js)\n\n# Core SDK Overview\n\nThe **Core SDK** provides foundational functionality leveraged by dependent Kontent.ai SDKs, such as [`@kontent-ai/delivery-sdk`](https://www.npmjs.com/package/@kontent-ai/delivery-sdk) and [`@kontent-ai/management-sdk`](https://www.npmjs.com/package/@kontent-ai/management-sdk).\n\n---\n\n## Requirements\n\nBefore using this package, make sure your environment matches the published package requirements:\n\n- Node.js `\u003e=22`\n- ESM-compatible runtime, because the package is published as an ES module\n- Peer dependencies: `zod` and `ts-pattern`\n\nWith modern package managers such as npm, peer dependencies are typically installed automatically, so you usually only need:\n\n```bash\nnpm install @kontent-ai/core-sdk\n```\n\n---\n\n## HTTP Request Infrastructure\n\nThe SDK includes a default implementation of the `HttpService` and `HttpAdapter` components, which handle HTTP requests to the Kontent.ai APIs.\n\nThese implementations are designed to work out-of-the-box but are also fully customizable. Developers may replace them with custom versions to extend or override the default behavior, depending on specific application requirements.\n\n---\n\n## Customization Options\n\nThe `HttpService` comes with several built-in capabilities, such as:\n\n- **Retry policies**\n- **Request parsing and validation** (URL parsing, body serialization)\n- **Automatic header and tracking management**\n- **Kontent.ai-specific error extraction**\n\nTo customize these behaviors entirely, you can replace the `HttpService` with your own implementation.\n\nHowever, 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.\n\n---\n\n## Example: Custom `HttpAdapter` Implementation\n\nBelow 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.\n\nIf you want the SDK to preserve specific `error.details.reason` values for custom adapters, throw:\n\n- `AdapterAbortError` when the request is aborted\n- `AdapterParseError` when the response cannot be parsed as JSON or `Blob`\n\nIf you throw some other error, the SDK will classify it as `adapterError`.\n\n```typescript\nimport { AdapterAbortError, AdapterParseError, getDefaultHttpService } from \"@kontent-ai/core-sdk\";\n\nconst httpService = getDefaultHttpService({\n  adapter: {\n    executeRequest: async (options) =\u003e {\n      let response: Response;\n\n      try {\n        response = await fetch(options.url, {\n          method: options.method,\n          headers: Object.fromEntries((options.requestHeaders ?? []).map((header) =\u003e [header.name, header.value])),\n          body: options.body,\n          signal: options.abortSignal ?? undefined,\n        });\n      } catch (error) {\n        if (error instanceof DOMException \u0026\u0026 error.name === \"AbortError\") {\n          throw new AdapterAbortError(error);\n        }\n\n        throw error;\n      }\n\n      let payload = null;\n\n      if (response.headers.get(\"content-type\")?.includes(\"application/json\")) {\n        try {\n          payload = await response.json();\n        } catch (error) {\n          throw new AdapterParseError(error);\n        }\n      }\n\n      return {\n        payload,\n        responseHeaders: [...response.headers.entries()].map(([name, value]) =\u003e ({ name, value })),\n        status: response.status,\n        statusText: response.statusText,\n        url: options.url,\n      };\n    },\n    downloadFile: async (options) =\u003e {\n      let response: Response;\n\n      try {\n        response = await fetch(options.url, {\n          headers: Object.fromEntries((options.requestHeaders ?? []).map((header) =\u003e [header.name, header.value])),\n          signal: options.abortSignal ?? undefined,\n        });\n      } catch (error) {\n        if (error instanceof DOMException \u0026\u0026 error.name === \"AbortError\") {\n          throw new AdapterAbortError(error);\n        }\n\n        throw error;\n      }\n\n      let payload: Blob;\n\n      try {\n        payload = await response.blob();\n      } catch (error) {\n        throw new AdapterParseError(error);\n      }\n\n      return {\n        payload,\n        responseHeaders: [...response.headers.entries()].map(([name, value]) =\u003e ({ name, value })),\n        status: response.status,\n        statusText: response.statusText,\n        url: options.url,\n      };\n    },\n  },\n});\n```\n\nThis approach gives you fine-grained control over how requests are made, while still benefiting from the core service's additional functionalities.\n\n---\n\n## Error Handling\n\nAll 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:\n\n```typescript\nconst { success, response, error } = await httpService.request({\n  url: \"https://manage.kontent.ai/v2/projects/...\",\n  method: \"GET\"\n});\n\nif (!success) {\n  switch (error.details.reason) {\n    case \"unauthorized\":\n      // error.details includes: status, statusText, responseHeaders, kontentErrorResponse\n      console.error(\"Check your API key:\", error.details.kontentErrorResponse?.message);\n      break;\n    case \"notFound\":\n      console.error(\"Resource not found:\", error.url);\n      break;\n    case \"invalidResponse\":\n      // Any non-2xx response that isn't 401 or 404\n      console.error(`HTTP ${error.details.status}:`, error.details.kontentErrorResponse?.message);\n      break;\n    case \"parseError\":\n      // The response claimed to be JSON, but parsing it failed\n      console.error(\"Failed to parse response:\", error.details.originalError);\n      break;\n    case \"adapterError\":\n      // Network failure, timeout, or other transport-level issue\n      console.error(\"Request failed:\", error.details.originalError);\n      break;\n    case \"invalidUrl\":\n      // The provided URL could not be parsed before the request was sent\n      console.error(\"Invalid URL:\", error.details.originalError);\n      break;\n    case \"invalidBody\":\n      // The request body could not be serialized before the request was sent\n      console.error(\"Invalid body:\", error.details.originalError);\n      break;\n    case \"validationFailed\":\n      // Zod schema validation failed (when responseValidation is enabled)\n      console.error(\"Unexpected response shape for\", error.details.url, error.details.zodError);\n      break;\n    case \"aborted\":\n      // The request was cancelled before it could complete\n      console.error(\"Request was aborted:\", error.details.originalError);\n      break;\n  }\n  return;\n}\n\n// response is fully typed here\nconsole.log(response.payload);\n```\n\n---\n\n## Retry Strategy\n\nThe 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.\n\nFor transport-level failures (network errors, timeouts), you can control retry behavior via `canRetryAdapterError`:\n\n```typescript\nconst httpService = getDefaultHttpService({\n  retryStrategy: {\n    maxRetries: 3,\n    canRetryAdapterError: (error) =\u003e {\n      // `error` is typed as KontentSdkError\u003cErrorDetailsFor\u003c\"adapterError\"\u003e\u003e\n      // Return true to retry, false to stop\n      return true;\n    },\n    logRetryAttempt: \"logToConsole\",\n  },\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkontent-ai%2Fcore-sdk-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkontent-ai%2Fcore-sdk-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkontent-ai%2Fcore-sdk-js/lists"}