-
Notifications
You must be signed in to change notification settings - Fork 1
docs: add TypeScript SDK reference section #284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
dangrondahl
wants to merge
1
commit into
main
Choose a base branch
from
add_typescript_sdk
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+506
−5
Draft
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| --- | ||
| title: Error handling | ||
| description: How to catch and inspect errors thrown by the Kosli TypeScript SDK. | ||
| --- | ||
|
|
||
| All HTTP errors from the SDK are instances of `KosliError` or one of its subclasses. Network-level failures throw one of the client error classes listed below. | ||
|
|
||
| ## KosliError | ||
|
|
||
| `KosliError` is the base class for any non-2xx HTTP response. It exposes: | ||
|
|
||
| | Property | Type | Description | | ||
| |----------|------|-------------| | ||
| | `message` | `string` | Error message | | ||
| | `statusCode` | `number` | HTTP status code (e.g. `404`, `403`) | | ||
| | `headers` | `Headers` | Response headers | | ||
| | `body` | `string` | Raw response body (may be empty) | | ||
| | `rawResponse` | `Response` | The full HTTP response object | | ||
| | `data$` | varies | Structured error data for specific error types (see below) | | ||
|
|
||
| ## HTTP error classes | ||
|
|
||
| These named subclasses cover the most common API errors: | ||
|
|
||
| | Class | Status | Description | | ||
| |-------|--------|-------------| | ||
| | `BadRequestError` | `400` | Invalid request | | ||
| | `UnauthorizedError` | `401` | Permission denied or not authenticated | | ||
| | `NotFoundError` | `404` | Resource not found | | ||
| | `RateLimitedError` | `429` | Rate limit exceeded | | ||
|
|
||
| ```typescript | ||
| import { Kosli } from "@kosli/sdk"; | ||
| import * as errors from "@kosli/sdk/models/errors"; | ||
|
|
||
| const kosli = new Kosli({ | ||
| httpBearer: process.env["KOSLI_API_KEY"] ?? "", | ||
| }); | ||
|
|
||
| try { | ||
| const trail = await kosli.trails.get({}, { | ||
| org: "my-org", | ||
| flowName: "my-flow", | ||
| trailName: "my-trail", | ||
| }); | ||
| } catch (error) { | ||
| if (error instanceof errors.NotFoundError) { | ||
| console.error("Trail not found"); | ||
| } else if (error instanceof errors.UnauthorizedError) { | ||
| console.error("Access denied:", error.data$.message); | ||
| } else if (error instanceof errors.RateLimitedError) { | ||
| console.error("Rate limit hit - back off and retry"); | ||
| } else if (error instanceof errors.KosliError) { | ||
| console.error(`HTTP ${error.statusCode}: ${error.message}`); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Network errors | ||
|
|
||
| These errors are thrown when the request cannot be completed at the transport level: | ||
|
|
||
| | Class | Description | | ||
| |-------|-------------| | ||
| | `ConnectionError` | The HTTP client could not reach the server | | ||
| | `RequestTimeoutError` | The request was aborted by an `AbortSignal` timeout | | ||
| | `RequestAbortedError` | The request was cancelled by the caller | | ||
| | `InvalidRequestError` | The request could not be constructed (invalid input) | | ||
| | `UnexpectedClientError` | An unrecognised error occurred in the HTTP client | | ||
|
|
||
| Network errors do not have a `statusCode` - handle them separately from `KosliError`: | ||
|
|
||
| ```typescript | ||
| import * as errors from "@kosli/sdk/models/errors"; | ||
|
|
||
| try { | ||
| const result = await kosli.trails.list({}, { org: "my-org", flowName: "my-flow" }); | ||
| } catch (error) { | ||
| if (error instanceof errors.ConnectionError) { | ||
| console.error("Could not connect to Kosli - check your network"); | ||
| } else if (error instanceof errors.RequestTimeoutError) { | ||
| console.error("Request timed out"); | ||
| } else if (error instanceof errors.KosliError) { | ||
| console.error(`API error ${error.statusCode}: ${error.message}`); | ||
| } else { | ||
| throw error; | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Other errors | ||
|
|
||
| A small number of operations can throw additional error types for specific conditions: | ||
|
|
||
| | Class | Status | Description | | ||
| |-------|--------|-------------| | ||
| | `ConflictResponseModelError` | `409` | Conflict (e.g. resource already exists) | | ||
| | `RequestEntityTooLargeResponseModelError` | `413` | Request body too large | | ||
| | `ResponseValidationError` | - | Response from server did not match the expected schema; inspect `error.rawValue` or call `error.pretty()` | | ||
|
|
||
| Check the method's documentation to see which errors apply to a specific operation. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,178 @@ | ||||||
| --- | ||||||
| title: Overview | ||||||
| description: Use the Kosli TypeScript SDK to interact with the Kosli API from Node.js, Bun, Deno, and browser environments. | ||||||
| --- | ||||||
|
|
||||||
| <Warning> | ||||||
| **Early access.** The TypeScript SDK is an unsupported work in progress and may change or be removed without notice. It is provided for evaluation only - do not use it in production. | ||||||
| </Warning> | ||||||
|
|
||||||
| The `@kosli/sdk` package provides a type-safe TypeScript client for the Kosli API. It supports Node.js, Bun, Deno, and all modern browsers. | ||||||
|
|
||||||
| ## Installation | ||||||
|
|
||||||
| Install using your preferred package manager: | ||||||
|
|
||||||
| <CodeGroup> | ||||||
| ```bash npm | ||||||
| npm add @kosli/sdk | ||||||
| ``` | ||||||
|
|
||||||
| ```bash pnpm | ||||||
| pnpm add @kosli/sdk | ||||||
| ``` | ||||||
|
|
||||||
| ```bash bun | ||||||
| bun add @kosli/sdk | ||||||
| ``` | ||||||
|
|
||||||
| ```bash yarn | ||||||
| yarn add @kosli/sdk | ||||||
| ``` | ||||||
| </CodeGroup> | ||||||
|
|
||||||
| <Note> | ||||||
| The package is published as an ES Module (ESM) only. CommonJS projects must use dynamic import: | ||||||
|
|
||||||
| ```typescript | ||||||
| const { Kosli } = await import("@kosli/sdk"); | ||||||
| ``` | ||||||
| </Note> | ||||||
|
|
||||||
| ## Quick start | ||||||
|
|
||||||
| ```typescript | ||||||
| import { Kosli } from "@kosli/sdk"; | ||||||
|
|
||||||
| const kosli = new Kosli({ | ||||||
| httpBearer: process.env["KOSLI_API_KEY"] ?? "", | ||||||
| }); | ||||||
|
|
||||||
| const trails = await kosli.trails.list({}, { | ||||||
| org: "my-org", | ||||||
| flowName: "my-flow", | ||||||
| }); | ||||||
|
|
||||||
| console.log(trails); | ||||||
| ``` | ||||||
|
|
||||||
| ## Authentication | ||||||
|
|
||||||
| Set your API key when constructing the client. This applies it to all requests: | ||||||
|
|
||||||
| ```typescript | ||||||
| import { Kosli } from "@kosli/sdk"; | ||||||
|
|
||||||
| const kosli = new Kosli({ | ||||||
| httpBearer: process.env["KOSLI_API_KEY"] ?? "", | ||||||
| }); | ||||||
| ``` | ||||||
|
|
||||||
| Some operations accept the API key at the call site instead. Use this when you need per-request credentials: | ||||||
|
|
||||||
| ```typescript | ||||||
| const result = await kosli.trails.list( | ||||||
| { httpBearer: process.env["KOSLI_API_KEY"] ?? "" }, // security | ||||||
| { org: "my-org", flowName: "my-flow" }, // request params | ||||||
| ); | ||||||
| ``` | ||||||
|
|
||||||
| See [personal API keys](/user/personal_api_keys) and [service accounts](/administration/authentication/service_accounts) for how to create API keys. | ||||||
|
|
||||||
| ## Server selection | ||||||
|
|
||||||
| By default the SDK targets the EU region. Pass `server: "us"` to use the US region: | ||||||
|
|
||||||
| ```typescript | ||||||
| const kosli = new Kosli({ | ||||||
| httpBearer: process.env["KOSLI_API_KEY"] ?? "", | ||||||
| server: "us", | ||||||
| }); | ||||||
| ``` | ||||||
|
|
||||||
| | Name | URL | Region | | ||||||
| |------|-----|--------| | ||||||
| | `"eu"` | `https://app.kosli.com/api/v2` | EU (default) | | ||||||
| | `"us"` | `https://app.us.kosli.com/api/v2` | US | | ||||||
|
|
||||||
| To point at a custom URL (e.g. a proxy or local instance), use `serverURL` instead: | ||||||
|
|
||||||
| ```typescript | ||||||
| const kosli = new Kosli({ | ||||||
| httpBearer: process.env["KOSLI_API_KEY"] ?? "", | ||||||
| serverURL: "https://app.kosli.com/api/v2", | ||||||
| }); | ||||||
| ``` | ||||||
|
|
||||||
| ## Available resources | ||||||
|
|
||||||
| The client exposes the following resource groups: | ||||||
|
|
||||||
| | Resource | Description | | ||||||
| |----------|-------------| | ||||||
| | `kosli.actions` | Environment and flow actions | | ||||||
| | `kosli.allowlists` | Artifact allowlists | | ||||||
| | `kosli.approvals` | Approvals | | ||||||
| | `kosli.artifacts` | Artifact reporting and lookup | | ||||||
| | `kosli.attestations` | Attestations (custom, JUnit, Jira, Snyk, Sonar, pull request) | | ||||||
| | `kosli.builds` | Builds | | ||||||
| | `kosli.customAttestationTypes` | Custom attestation type management | | ||||||
| | `kosli.deployments` | Deployments | | ||||||
| | `kosli.environments` | Environment management and reporting | | ||||||
| | `kosli.flows` | Flow management | | ||||||
| | `kosli.organizations` | Organization settings and notifications | | ||||||
| | `kosli.policies` | Policy management | | ||||||
| | `kosli.repos` | Repository live artifact lookup | | ||||||
| | `kosli.schemas` | Policy and template schemas | | ||||||
| | `kosli.search` | Artifact search by SHA or fingerprint | | ||||||
| | `kosli.serviceAccounts` | Service account API key management | | ||||||
| | `kosli.snapshots` | Environment snapshots | | ||||||
| | `kosli.tags` | Tag management | | ||||||
| | `kosli.trails` | Trail management | | ||||||
| | `kosli.user` | User settings | | ||||||
|
|
||||||
| ## Standalone functions | ||||||
|
|
||||||
| All methods are also available as individually importable functions, which allows bundlers to tree-shake unused code: | ||||||
|
|
||||||
| ```typescript | ||||||
| import { KosliCore } from "@kosli/sdk/core.js"; | ||||||
| import { trailsList } from "@kosli/sdk/funcs/trails-list.js"; | ||||||
|
|
||||||
| const kosli = new KosliCore({ | ||||||
| httpBearer: process.env["KOSLI_API_KEY"] ?? "", | ||||||
| }); | ||||||
|
|
||||||
| const result = await trailsList(kosli, {}, { | ||||||
| org: "my-org", | ||||||
| flowName: "my-flow", | ||||||
| }); | ||||||
| ``` | ||||||
|
|
||||||
| ## Supported runtimes | ||||||
|
|
||||||
| The SDK requires ECMAScript 2020 or later and the Web Fetch API. Supported environments: | ||||||
|
|
||||||
| - **Browsers**: Chrome, Safari, Edge, Firefox (evergreen) | ||||||
| - **Node.js**: active and maintenance LTS releases (v18, v20+) | ||||||
| - **Bun**: v1 and above | ||||||
| - **Deno**: v1.39+ | ||||||
|
|
||||||
| For TypeScript projects, add `"lib": ["es2020", "dom", "dom.iterable"]` to your `tsconfig.json` to get full type support for async iterables, streams, and fetch-related APIs. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: This reads as though users should set
Suggested change
|
||||||
|
|
||||||
| ## Debugging | ||||||
|
|
||||||
| Pass a logger to emit debug output for all requests and responses: | ||||||
|
|
||||||
| ```typescript | ||||||
| const kosli = new Kosli({ | ||||||
| httpBearer: process.env["KOSLI_API_KEY"] ?? "", | ||||||
| debugLogger: console, | ||||||
| }); | ||||||
| ``` | ||||||
|
|
||||||
| Alternatively, set the environment variable `KOSLI_DEBUG=true`. | ||||||
|
|
||||||
| <Warning> | ||||||
| Debug logging prints headers including your API key in plain text. Use it only during local development. | ||||||
| </Warning> | ||||||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improvement: These additional error types aren't shown in the
import * as errors from "@kosli/sdk/models/errors"examples above. A brief note confirming they come from the same import path would save readers from guessing.