Skip to content

Modernize the Delivery SDK (v17) - #411

Open
Enngage wants to merge 221 commits into
masterfrom
modernization
Open

Modernize the Delivery SDK (v17)#411
Enngage wants to merge 221 commits into
masterfrom
modernization

Conversation

@Enngage

@Enngage Enngage commented Jun 16, 2026

Copy link
Copy Markdown
Member

A ground-up rewrite of the SDK on a modern, functional TypeScript foundation.

Highlights

  • New query API — fluent builders are replaced by explicit request objects (client.listContentItems({
    query, filters })), with renamed, discoverable methods (fetchContentItem, listContentItems,
    fetchTaxonomy, …).
  • Safe & throwing execution — every query offers fetchSafe/fetchPageSafe/fetchAllPagesSafe (return {
    success, response, error }, never throw) alongside the throwing variants.
  • Zod as the source of truth — all response types are inferred from Zod schemas, with optional
    runtime validation of responses.
  • Stronger typing — a DeliveryClientSchema (content types & taxonomies as maps) narrows every
    codename; element codenames are scoped per content type; ContentItemOf + the Elements namespace give
    fully-typed item models and type guards.
  • Per-query response types — FetchContentItemResponse, ListContentItemsResponse, etc. for easy result
    annotation.
  • Linked-item resolution — rich-text & modular-content elements are resolved onto an items array by
    default; use .raw() for a serialization-safe payload.
  • Docs — rewritten README.md (basic usage, config, safe/unsafe queries, error handling, paging, type
    guards) and a full v16 → v17 migration.md.

…ct type check instead of string & type literal
@Enngage
Enngage requested review from a team and IvanKiral as code owners June 16, 2026 11:56
Comment thread migration.md
const raw = await client.fetchContentItem({ codename: "warrior" }).raw().fetch();
```

> v17 does **not** ship a rich-text-to-HTML resolver or portable-text transformer. `element.value` is the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

link to rich-text resolver

Comment thread migration.md
}
```

> You don't need to write these by hand — `@kontent-ai/model-generator` emits a type guard

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

link would be nice there as well :D

Comment thread migration.md
## Installation

v17 requires Node.js ≥ 22 and has three peer dependencies that were previously bundled:
`@kontent-ai/core-sdk`, `zod`, and `ts-pattern`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why ts-pattern as peer dep? :D

Comment thread .claude/settings.json
@@ -0,0 +1,3 @@
{
"hooks": {}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this file needed? :D

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are newer versions of those checkout i believe. something like v7. check also the other workflows

expect(params.has("system.language")).toBe(false);
});

it("omits filter with undefined value", () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: this is the same test as the one above ("omits undefined filter values" / "omits filter with undefined value") - one can go, or make them check different things :D

/**
* Matches the format of the order parameter in the Delivery API.
*
* @example

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: these @example blocks open ```ts but never close the fence, so they render a bit off in tooltips

Comment thread .nvmrc
@@ -0,0 +1 @@
lts/* No newline at end of file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.nvmrc is lts/* (floating) while engines says >= 22, and all the workflows read the node version from here - so CI runs on whatever lts happens to be that day. should we pin a concrete major?

Comment thread package.json
"test": "vitest run --config=vitest.config.ts --coverage",
"test:unit": "vitest run --config=vitest-unit.config.ts",
"test:integration": "vitest run --config=vitest-integration.config.ts",
"test:types": "tsgo -p sample/tsconfig.json",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have a test:types script for the sample/ types but nothing in CI runs it, so the public-api type samples never actually get checked. add a step for it?

isNotEmptyRichText: "neq",
};

export type ObjectFilter<TSystemProperties extends string, TElementProperties extends string> = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we export Filter / ObjectFilter, but i don't think there's an ergonomic way to type a standalone filter array with them. inline works, as const works, but the moment you write const f: Filter<...>[] = [...] you hand-build the generics - the system-props union has no dedicated export (you'd write keyof ContentItemSystemPayload<DeliveryClientSchema>), and bare string fails because system.${string} is wider than the query wants. the only discoverable options are verbose (NonNullable<ListContentItemsQueryRequest<MySchema>['filters']>, or the keyof ... + AllElementCodenamesOf<MySchema> combo).

could we expose a convenience type like ContentItemFilter<TSchema> that pre-binds system + element props? and maybe a short Filters section in the README - right now it's only in the migration guide :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants