Skip to content

Commit dcb6b29

Browse files
authored
feat(capi-client): add typed Content Delivery API client package (#428)
Introduce a new `@storyblok/api-client` package that provides a modern, typed TS client for the Content Delivery (CAPI) stories endpoints, generated from our OpenAPI spec. This improves DX and consistency when consuming the Stories API. - Add OpenAPI CAPI stories spec and shared schemas for story field types - Generate typed CAPI client (fetch-based) and SDK with `get` and `getAll` helpers - Implement `createApiClient` wrapper with region-aware base URL and access token handling - Add basic tests using MSW + OpenAPI mocks to validate `stories.get` and `stories.getAll` - Configure build (tsdown), linting, testing, and npm packaging for the new package Fixes WDX-281
1 parent 3a314ad commit dcb6b29

File tree

86 files changed

+6105
-31
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+6105
-31
lines changed

.claude/skills/qa-engineer-manual/SKILL.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ scenarios/
129129
- Clean up local artifacts with `./scripts/cleanup-local.sh`. Don't hesitate to clean up between tests to start with a clean slate.
130130
- Place test scripts in `./.claude/tmp/`. Import from the built package: `../../packages/PACKAGE_NAME/dist/index.mjs`.
131131
- Export env vars before running: `set -a && source ./.env.qa-engineer-manual && set +a && node ./.claude/tmp/test-name.mjs`.
132-
- Create the MAPI client with `new ManagementApiClient({ token: { accessToken: token } })` — the token must be wrapped in `{ accessToken: ... }`. Do NOT use `createClient` directly.
133132
- The stories list endpoint does NOT return `content` by default — `story.content?.component` will be `undefined` in list responses. Fetch individual stories for full content.
134133
- When using two spaces (for example, mapping references between source and target), use `STORYBLOK_SPACE_ID_TARGET` for the target (loaded via `.env.qa-engineer-manual`).
135134

@@ -148,7 +147,7 @@ Paths are relative to this `SKILL.md`.
148147

149148
## Troubleshooting
150149

151-
- Load the `STORYBLOK_SPACE_ID`, `STORYBLOK_SPACE_ID_TARGET`, `STORYBLOK_ASSET_TOKEN`, `STORYBLOK_ASSET_TOKEN_TARGET` and `STORYBLOK_TOKEN` environment variables by running `source ./.env.qa-engineer-manual` (do not attempt to read this file).
150+
- Load the `STORYBLOK_SPACE_ID`, `STORYBLOK_SPACE_ID_TARGET`, `STORYBLOK_ASSET_TOKEN`, `STORYBLOK_ASSET_TOKEN_TARGET`, `STORYBLOK_TOKEN`, `STORYBLOK_PREVIEW_TOKEN`, and `STORYBLOK_PREVIEW_TOKEN_TARGET` environment variables by running `source ./.env.qa-engineer-manual` (do not attempt to read this file).
152151
- When running `.mjs` test files, env vars must be **exported** (`set -a && source ./.env.qa-engineer-manual && set +a`) — plain `source` does not propagate to `node` subprocesses.
153152

154153
**MAPI:**
File renamed without changes.

.env.qa-engineer-manual.template

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
STORYBLOK_TOKEN=
2+
STORYBLOK_PREVIEW_TOKEN=
3+
STORYBLOK_PREVIEW_TOKEN_TARGET=
24
STORYBLOK_ASSET_TOKEN=
35
STORYBLOK_ASSET_TOKEN_TARGET=
46
STORYBLOK_SPACE_ID=

.github/workflows/pkg.pr.new.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ jobs:
3232
run: pnpm nx run-many --target=build --parallel=5 -p="tag:npm:public"
3333
- run: |
3434
PATHS=$(pnpm list --recursive --depth=0 --json | jq -r '.[] | select(.private == false) | .path' | tr '\n' ' ')
35-
pnpx pkg-pr-new publish $PATHS --compact --pnpm
35+
pnpx pkg-pr-new publish $PATHS --pnpm

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Inspect the root `package.json` and the `packages/` directory to identify active
1919

2020
## Code style and conventions
2121

22-
Always use linting and type-checking scripts for affected packages after making changes.
22+
Always use linting and type-checking scripts for affected packages after making changes. When encountering lint errors, run the lint command with `--fix` first before attempting to fix issues manually.
2323

2424
### General
2525

packages/astro/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ If you'd like to contribute, please refer to the [contributing guidelines](CONTR
5050

5151
For help, discussion about best practices, or any other conversation that would benefit from being searchable:
5252

53-
- [Discuss Storyblok on Github Discussions](https://github.com/storyblok/monoblok/discussions)
53+
- [Discuss Storyblok on GitHub Discussions](https://github.com/storyblok/monoblok/discussions)
5454

5555
For community support, chatting with other users, please visit:
5656

@@ -65,7 +65,7 @@ For bugs or feature requests, please [submit an issue](https://github.com/storyb
6565
6666
### I can't share my company project code
6767

68-
We understand that you might not be able to share your company's project code. Please provide a minimal reproducible example that demonstrates the issue by using tools like [Stackblitz](https://stackblitz.com) or a link to a Github Repo lease make sure you include a README file with the instructions to build and run the project, important not to include any access token, password or personal information of any kind.
68+
We understand that you might not be able to share your company's project code. Please provide a minimal reproducible example that demonstrates the issue by using tools like [Stackblitz](https://stackblitz.com) or a link to a GitHub repo. Please make sure you include a README file with the instructions to build and run the project, important not to include any access token, password or personal information of any kind.
6969

7070
### Feedback
7171

packages/capi-client/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
src/generated

packages/capi-client/.npmignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*
2+
!dist/
3+
!dist/**
4+
!package.json
5+
!README.md

packages/capi-client/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Storyblok GmbH
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

packages/capi-client/README.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<div align="center">
2+
3+
![Storyblok ImagoType](https://raw.githubusercontent.com/storyblok/.github/refs/heads/main/profile/public/github-banner.png)
4+
5+
<h1 align="center">@storyblok/api-client</h1>
6+
<p>
7+
A modern TypeScript client for the Storyblok Content Delivery API with built-in caching, retry logic, and rate limiting
8+
</p>
9+
<br />
10+
</div>
11+
12+
<p align="center">
13+
<a href="https://npmjs.com/package/@storyblok/api-client">
14+
<img src="https://img.shields.io/npm/v/@storyblok/api-client/latest.svg?style=flat-square&color=8d60ff" alt="@storyblok/api-client" />
15+
</a>
16+
<a href="https://npmjs.com/package/@storyblok/api-client" rel="nofollow">
17+
<img src="https://img.shields.io/npm/dt/@storyblok/api-client.svg?style=appveyor&color=8d60ff" alt="npm">
18+
</a>
19+
<a href="https://storyblok.com/join-discord">
20+
<img src="https://img.shields.io/discord/700316478792138842?label=Join%20Our%20Discord%20Community&style=appveyor&logo=discord&color=8d60ff">
21+
</a>
22+
<a href="https://twitter.com/intent/follow?screen_name=storyblok">
23+
<img src="https://img.shields.io/badge/Follow-%40storyblok-8d60ff?style=appveyor&logo=twitter" alt="Follow @Storyblok" />
24+
</a><br/>
25+
<a href="https://app.storyblok.com/#!/signup?utm_source=github.com&utm_medium=readme&utm_campaign=@storyblok/api-client">
26+
<img src="https://img.shields.io/badge/Try%20Storyblok-Free-8d60ff?style=appveyor&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAABGdBTUEAALGPC/xhBQAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAHqADAAQAAAABAAAAHgAAAADpiRU/AAACRElEQVRIDWNgGGmAEd3D3Js3LPrP8D8WXZwSPiMjw6qvPoHhyGYwIXNAbGpbCjbzP0MYuj0YFqMroBV/wCxmIeSju64eDNzMBJUxvP/9i2Hnq5cM1devMnz984eQsQwETeRhYWHgIcJiXqC6VHlFBjUeXgav40cIWkz1oLYXFmGwFBImaDFBHyObcOzdW4aSq5eRhRiE2dgYlpuYoYSKJi8vw3GgWnyAJIs/AuPu4scPGObd/fqVQZ+PHy7+6udPOBsXgySLDfn5GRYYmaKYJcXBgWLpsx8/GPa8foWiBhuHJIsl2DkYQqWksZkDFgP5PObcKYYff//iVAOTIDlx/QPqRMb/YSYBaWlOToZIaVkGZmAZSQiQ5OPtwHwacuo4iplMQEu6tXUZMhSUGDiYmBjylFQYvv/7x9B04xqKOnQOyT5GN+Df//8M59ASXKyMHLoyDD5JPtbj42OYrm+EYgg70JfuYuIoYmLs7AwMjIzA+uY/zjAnyWJpDk6GOFnCvrn86SOwmsNtKciVFAc1ileBHFDC67lzG10Yg0+SjzF0ownsf/OaofvOLYaDQJoQIGix94ljv1gIZI8Pv38zPvj2lQWYf3HGKbpDCFp85v07NnRN1OBTPY6JdRSGxcCw2k6sZuLVMZ5AV4s1TozPnGGFKbz+/PE7IJsHmC//MDMyhXBw8e6FyRFLv3Z0/IKuFqvFyIqAzd1PwBzJw8jAGPfVx38JshwlbIygxmYY43/GQmpais0ODDHuzevLMARHBcgIAQAbOJHZW0/EyQAAAABJRU5ErkJggg==" alt="Follow @Storyblok" />
27+
</a>
28+
</p>
29+
30+
## Features
31+
32+
- **Type-Safe**: Generated from OpenAPI specifications with full TypeScript support
33+
- **Caching**: Pluggable cache providers with `cache-first`, `network-first`, and `swr` strategies
34+
- **Retry Logic**: Built-in retry with exponential backoff and jitter
35+
- **Rate Limiting**: Preventive rate limiting with automatic tier detection
36+
- **Region Support**: Automatic regional endpoint selection (`eu`, `us`, `ap`, `ca`, `cn`)
37+
- **Relation Inlining**: Optional inlining of resolved relations directly into story content
38+
39+
## Documentation
40+
41+
For complete documentation, please visit [package reference](https://www.storyblok.com/docs/packages/storyblok-api-client)
42+
43+
## Contributing
44+
45+
If you'd like to contribute, please refer to the [contributing guidelines](../../CONTRIBUTING.md).
46+
47+
## Community
48+
49+
For help, discussion about best practices, or any other conversation that would benefit from being searchable:
50+
51+
- [Discuss Storyblok on GitHub Discussions](https://github.com/storyblok/monoblok/discussions)
52+
53+
For community support, chatting with other users, please visit:
54+
55+
- [Discuss Storyblok on Discord](https://storyblok.com/join-discord)
56+
57+
## Support
58+
59+
For bugs or feature requests, please [submit an issue](https://github.com/storyblok/monoblok/issues/new/choose).
60+
61+
> [!IMPORTANT]
62+
> Please search existing issues before submitting a new one. Issues without a minimal reproducible example will be closed. [Why reproductions are Required](https://antfu.me/posts/why-reproductions-are-required).
63+
64+
### I can't share my company project code
65+
66+
We understand that you might not be able to share your company's project code. Please provide a minimal reproducible example that demonstrates the issue by using tools like [Stackblitz](https://stackblitz.com) or a link to a GitHub repo. Please make sure you include a README file with the instructions to build and run the project, important not to include any access token, password or personal information of any kind.
67+
68+
### Feedback
69+
70+
If you have a question, please ask in the [Discuss Storyblok on Discord](https://storyblok.com/join-discord) channel.
71+
72+
## License
73+
74+
[License](/LICENSE)

0 commit comments

Comments
 (0)