@nexdk/driver-strapi
REST driver for Strapi v5 (flat documents). Strapi wraps responses in { data, meta } and expects { data } on writes. The driver handles both and serializes nested query objects to bracket notation (filters[title][$eq]=…).
Install
Section titled “Install”Not published to npm yet. Build it from the repository (packages/drivers/strapi).
Once published, install the package with everything it needs:
pnpm add nexdk @nexdk/http @nexdk/driver-strapiConfig
Section titled “Config”import { createSdk } from 'nexdk'import { createStrapiDriver } from '@nexdk/driver-strapi'
const sdk = createSdk({ drivers: { strapi: createStrapiDriver({ baseUrl: 'http://localhost:1337', headers: { Authorization: 'Bearer …' }, }), },})
const { data: articles } = await sdk.strapi.articles.get({ filters: { title: { $eq: 'Hello' } }, populate: ['author'],})fetch is optional: pass any function (input, init?) => Promise<Response> (the FetchLike type, exported by nexdk and @nexdk/http) and every HTTP request goes through it instead of globalThis.fetch, for example mock.fetch from shamock or the fetch of bun-types, without a cast.
| Method | Maps to | Notes |
|---|---|---|
get(query?, onEvent?) |
GET /api/{resource} |
query accepts filters, sort, populate, fields, pagination, locale. Returns data as T[]. |
find({ id }, onEvent?) |
GET /api/{resource}/{id} |
Use the documentId. Returns T. |
create(body, onEvent?) |
POST /api/{resource} |
Sends { data: body }. |
update({ id, ...fields }, onEvent?) |
PUT /api/{resource}/{id} |
Sends { data: fields }. |
remove({ id }, onEvent?) |
DELETE /api/{resource}/{id} |
Returns { success: boolean }. |
Pagination
Section titled “Pagination”get follows every page (meta.pagination.pageCount). If pagination sets page, pageSize, start or limit, it makes one request and returns that page only. Strapi caps pagination.pageSize and pagination.limit at 100: a larger value is silently reduced by the server. An empty $in or $notIn list is sent as filters[field][$in]=, which Strapi reads as an empty list.
Query serialization
Section titled “Query serialization”toStrapiQuery is exported. Nested objects and arrays become bracket keys (populate[0]=author). undefined and null are skipped. A query nested deeper than 16 levels, or with a circular reference, throws.
dialectr can build the query with toStrapi.
Errors
Section titled “Errors”The resource name and the id are URL-encoded. A failure emits error with { message, status, errors }, then throws an HttpError. The message is the backend message when there is one and errors is normalized to { field: [message] } when possible (see @nexdk/http); data keeps the raw body. The thrown error and the event carry the same status and errors. The timeout (milliseconds) and signal (AbortSignal) config options abort a request with a status 0 error; neither is set by default. A resource name that is empty, . or .. is refused like an id.
Totals
Section titled “Totals”The array returned by get carries a non-enumerable pagination property with meta.pagination as Strapi sent it ({ page, pageSize, pageCount, total }, or { start, limit, total }), read from the page answer (the first page when get follows every page). It is absent when the answer has no meta.pagination. It does not show up in Object.keys, JSON.stringify or toEqual.
const { data: rows } = await sdk.strapi.articles.get({ pagination: { page: 2, pageSize: 20 } })rows.pagination?.total