Skip to content

Commit 5c6f23f

Browse files
authored
feat(sdk): single and collection query functions
feat(sdk): single and collection query functions
2 parents b86cbf9 + ecbac30 commit 5c6f23f

File tree

21 files changed

+1376
-155
lines changed

21 files changed

+1376
-155
lines changed

README.md

Lines changed: 156 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,218 @@
1-
<h1 align="center">sdk-js</h1>
2-
<h3 align="center">An SDK you can use to easily interface with Strapi from your JavaScript and TypeScript projects</h3>
1+
<p style="text-align: center">
2+
<a href="https://strapi.io/#gh-light-mode-only">
3+
<img src="https://strapi.io/assets/strapi-logo-dark.svg" width="318px" alt="Strapi logo" />
4+
</a>
5+
<a href="https://strapi.io/#gh-dark-mode-only">
6+
<img src="https://strapi.io/assets/strapi-logo-light.svg" width="318px" alt="Strapi logo" />
7+
</a>
8+
</p>
39

10+
<h2 style="text-align: center">Manage Your Strapi Content From Anywhere 🚀</h2>
11+
<p style="text-align: center">Connect your JavaScript/TypeScript apps to a flexible and fully customizable Strapi backend with ease.</p>
12+
<p style="text-align: center"><a href="https://github.com/strapi/strapi">CMS Repository</a> - <a href="https://strapi.io">Website</a></p>
413
<br />
514

6-
<p align="center">
7-
<a href="https://www.npmjs.com/package/@strapi/sdk-js" target="_blank">
8-
<img src="https://img.shields.io/npm/v/@strapi/sdk-js" alt="NPM version" />
15+
<p style="text-align: center">
16+
<a href="https://www.npmjs.org/package/@strapi/sdk-js">
17+
<img src="https://img.shields.io/npm/v/@strapi/sdk-js/latest.svg" alt="NPM Version" />
918
</a>
1019
<a href="https://www.npmjs.com/package/@strapi/sdk-js" target="_blank">
1120
<img src="https://img.shields.io/npm/dm/@strapi/sdk-js" alt="NPM downloads" />
1221
</a>
13-
<a href="https://discord.gg/strapi" target="_blank">
14-
<img src="https://img.shields.io/discord/811989166782021633?style=flat&colorA=4945ff&colorB=4945ff&label=discord&logo=discord&logoColor=f0f0ff" alt="Chat on Discord" />
22+
<a href="https://github.com/strapi/sdk-js/actions/workflows/tests.yml">
23+
<img src="https://github.com/strapi/sdk-js/actions/workflows/tests.yml/badge.svg?branch=main" alt="Tests" />
24+
</a>
25+
<a href="https://discord.strapi.io">
26+
<img src="https://img.shields.io/discord/811989166782021633?label=Discord" alt="Strapi on Discord" />
1527
</a>
1628
</p>
1729

18-
<br />
19-
20-
sdk-js is an SDK you can use to easily interface with Strapi from your JavaScript or TypeScript project.
21-
22-
## Getting Started With Strapi
23-
24-
If you're brand new to Strapi development, it is recommended to follow the [Strapi Quick Start Guide](https://docs.strapi.io/dev-docs/quick-start)
25-
26-
sdk-js is compatible with Strapi v5+ and interfaces with Strapi's REST API. You can read the API docs [here](https://docs.strapi.io/dev-docs/api/rest)
27-
28-
## SDK Purpose
29-
30-
sdk-js is the recommended and easiest way to interface with Strapi from your JavaScript and TypeScript projects.
31-
It allows you to easily create, read, update, and delete Strapi content through strongly typed methods.
32-
33-
<!-- TODO confirm whether this is done in MVP -->
34-
35-
If working with javascript, sdk-js can still help to ease your development workflow through queries based on content type UID's.
30+
<br>
31+
32+
## 📖 Table of contents
33+
34+
1. [Getting Started](#-getting-started)
35+
- [Prerequisites](#pre-requisites)
36+
- [Installation](#installation)
37+
2. [Creating and Configuring an SDK Instance](#-creating-and-configuring-the-sdk-instance)
38+
- [Basic Configuration](#basic-configuration)
39+
- [Authentication](#authentication)
40+
- [API Token Authentication](#api-token-authentication)
41+
3. [API Reference](#-api-reference)
42+
4. [Resource Managers](#-resource-managers)
43+
- [`.collection()`](#collectionresource)
44+
- [`.single()`](#singleresource)
45+
5. [Examples](#-examples)
46+
47+
## 🛠 Getting started
48+
### Pre-Requisites
49+
Before you begin, ensure you have the following:
50+
- A Strapi backend up and running: [quick start guide](https://docs.strapi.io/dev-docs/quick-start).
51+
- The API URL of your Strapi instance: for example, `http://localhost:1337/api`.
52+
- A recent version of [Node.js](https://nodejs.org/en/download/package-manager) installed.
53+
54+
### Installation
55+
Install the SDK as a dependency in your project:
56+
57+
**NPM**
58+
```bash
59+
npm install @strapi/sdk-js
60+
```
3661

37-
## Getting Started With "@strapi/sdk-js"
62+
**Yarn**
63+
```bash
64+
yarn add @strapi/sdk-js
65+
```
3866

39-
In its simplest form, "@strapi/sdk-js" works by being connected to the URL of your Strapi instance and provided auth if required.
67+
**pnpm**
68+
```bash
69+
pnpm add @strapi/sdk-js
70+
```
4071

41-
<!-- TODO confirm examples -->
72+
## ⚙️ Creating and configuring the SDK Instance
73+
### Basic configuration
4274

43-
### Importing the SDK
75+
To interact with your Strapi backend, initialize the SDK with your Strapi API base URL:
4476

45-
```js
46-
import { createStrapiSDK } from '@strapi/sdk-js'; // ES Modules
47-
// const { createStrapiSDK } = require("@strapi/sdk-js"); CommonJS
77+
``` typescript
78+
import { createStrapiSDK } from '@strapi/sdk-js';
4879

49-
const strapiSDK = createStrapiSDK({
50-
baseURL: 'http://localhost:1337',
51-
});
80+
const sdk = createStrapiSDK({ baseURL: 'http://localhost:1337/api' });
5281
```
5382

54-
### Script tag example
83+
Alternatively, use a `<script>` tag in a browser environment:
5584

56-
```html
85+
``` html
5786
<script src="https://cdn.jsdelivr.net/npm/@strapi/sdk-js"></script>
87+
5888
<script>
59-
const strapiSDK = createStrapiSDK({
60-
baseURL: 'http://localhost:1337',
61-
});
89+
const sdk = createStrapiSDK({ baseURL: 'http://localhost:1337/api' });
6290
</script>
6391
```
6492

65-
## Generate the SDK based on your content type schema
93+
### Authentication
94+
The SDK supports multiple authentication strategies for accessing authenticated content in your Strapi backend.
6695

67-
sdk-js becomes most powerful when you generate the SDK based on your content type schema. This allows you access to strongly typed methods for creating, reading, updating and deleting content.
96+
#### API-Token authentication
6897

69-
There are multiple ways to do this:
98+
If your Strapi instance uses API tokens, configure the SDK like this:
7099

71-
### Using the CLI
100+
``` typescript
101+
const sdk = createStrapiSDK({
102+
baseURL: 'http://localhost:1337/api',
103+
auth: {
104+
strategy: 'api-token',
105+
options: { token: 'your-api-token-here' },
106+
},
107+
});
108+
```
72109

73-
sdk-js provides a CLI command to generate the SDK based on your Strapi app content schema.
110+
## 📚 API Reference
74111

75-
<!-- TODO should we provide an output path option to the CLI? -->
112+
The Strapi SDK instance provides key properties and utility methods for content and API interaction:
113+
- **`baseURL`**: base URL of your Strapi backend.
114+
- **`fetch`**: perform generic requests to the Strapi Content API using fetch-like syntax.
115+
- **`.collection(resource: string)`**: get a manager instance for handling collection-type resources.
116+
- **`.single(resource: string)`**: get a manager instance for handling single-type resources.
76117

77-
```sh
78-
# Run this in the root of your Strapi app
79-
npx @strapi/sdk-js@latest generate
118+
## 📁 Resource Managers
119+
### `.collection(resource)`
80120

81-
# You can optionally provide the path to strapi app and run the command from elsewhere
82-
npx @strapi/sdk-js@latest generate --path ../strapi-app
121+
The `.collection()` method provides a manager for working with collection-type resources,
122+
which can have multiple entries.
83123

84-
```
124+
**Note**: the `resource` corresponds to the plural name of your collection type, as defined in the Strapi model.
85125

86-
As opposed to importing the SDK from a CDN or NPM, the generated asset can then be imported and used as per the examples above.
126+
#### Available Methods:
87127

88-
### Providing the SDK with a Strapi Schema
128+
1. **`find(queryParams?)`**: fetch multiple entries.
129+
2. **`findOne(documentID, queryParams?)`**: fetch a single entry by its ID.
130+
3. **`create(data, queryParams?)`**: create a new entry.
131+
4. **`update(documentID, data, queryParams?)`**: update an existing entry.
132+
5. **`delete(documentID, queryParams?)`**: remove an entry.
89133

90-
Alternatively, you can use the SDK from a CDN or NPM, but provide the SDK with a Strapi schema.
134+
#### Examples:
91135

92-
```js
93-
import { createStrapiSDK } from '@strapi/sdk-js';
94-
// TODO clarify where this comes from and how to generate it
95-
import strapiAppSchema from '../path/to/strapi-app-schema.json';
136+
``` typescript
137+
const articles = sdk.collection('articles');
96138

97-
const strapiSDK = createStrapiSDK({
98-
baseURL: 'http://localhost:1337',
99-
schema: strapiAppSchema,
139+
// Fetch all english articles sorted by title
140+
const allArticles = await articles.find({
141+
locale: 'en',
142+
sort: 'title',
100143
});
101-
```
102144

103-
## Interacting with Strapi
145+
// Fetch a single article
146+
const singleArticle = await articles.findOne('article-document-id');
104147

105-
### Fetch
106-
107-
The SDK provides a `fetch` method that allows you to make requests relative to the Strapi Content API.
108-
109-
The params accepted by the `fetch` method are the same as those accepted by the native `fetch` [API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch). With the first param being a relative path to the Strapi Content API.
148+
// Create a new article
149+
const newArticle = await articles.create({ title: 'New Article', content: '...' });
110150

111-
You can refer to the documentation for the [Strapi Content API](https://docs.strapi.io/dev-docs/api/rest) for more information on the available endpoints and their required params.
151+
// Update an existing article
152+
const updatedArticle = await articles.update('article-document-id', { title: 'Updated Title' });
112153

113-
```js
114-
// Create a new article
115-
const response = await strapiSDK.fetch('/articles', {
116-
method: 'POST',
117-
body: {
118-
title: 'My first article',
119-
},
120-
});
154+
// Delete an article
155+
await articles.delete('article-id');
121156
```
157+
### `.single(resource)`
122158

123-
### Query
159+
The `.single()` method provides a manager for working with collection-type resources, which have only one entry.
124160

125-
The SDK also allows you to query your content types based on their UID via the `strapiSdk.query` method.
161+
**Note**: the `resource` corresponds to the singular name of your collection type, as defined in the Strapi model.
126162

127-
`strapiSdk.query` provides a few different use cases:
163+
#### Available Methods:
128164

129-
```js
130-
query<T = AnySchema>(uid: string): T {
131-
return result as T;
132-
}
133-
```
165+
1. **`find(queryParams?)`**: fetch the document.
166+
2. **`update(data, queryParams?)`**: update the document.
167+
3. **`delete(queryParams?)`**: remove the document.
134168

135-
#### Usage as a javascript developer
169+
#### Examples:
170+
``` typescript
171+
const homepage = sdk.single('homepage');
136172

137-
```js
138-
// Here the developer will get basic intellisense based on the AnySchema type.
139-
const jsResult = jsSdk.query('uid');
140-
```
173+
// Fetch the default version of the homepage
174+
const homepageContent = await homepage.find();
141175

142-
#### Usage as a TypeScript developer without a generated SDK
176+
// Fetch the spanish version of the homepage
177+
const homepageContent = await homepage.find({ locale: 'es' });
143178

144-
The developer will manually provide a content type schema to correctly type the inputs and outputs of `sdk.query`.
179+
// Update the homepage draft content
180+
const updatedHomepage = await homepage.update({ title: 'Updated Homepage Title' }, { status: 'draft' });
145181

146-
```js
147-
const tsResult = tsSdk.query < ManuallyProvidedSchema > 'uid';
182+
// Delete the homepage content
183+
await homepage.delete();
148184
```
149185

150-
#### Usage in TypeScript with generated SDK
151-
152-
Assuming the SDK is generated with full type information, the developer will get full autocomplete for the returned data.
186+
## 💡 Examples
153187

154-
```js
155-
const generatedResult = generatedSdk.query('uid'); // Full autocomplete
156-
```
188+
Here’s how to combine `.collection()` and `.single()` methods in a real-world scenario:
157189

158-
### Generated Query API's
190+
``` typescript
191+
const sdk = createStrapiSDK({
192+
baseURL: 'http://localhost:1337/api',
193+
auth: {
194+
strategy: 'api-token',
195+
options: { token: 'your-api-token-here' },
196+
},
197+
});
159198

160-
When you generate the SDK based on your Strapi app schema, the SDK will also generate methods for querying your content types.
199+
async function main() {
200+
// Work with collections
201+
const articles = sdk.collection('articles');
202+
const newArticle = await articles.create({ title: 'Hello World', content: '...' });
203+
console.log('Created Article:', newArticle);
161204

162-
These methods are strongly typed and allow you to query your content types based on their UID.
205+
const allArticles = await articles.find({ sort: 'createdAt:desc' });
206+
console.log('All Articles:', allArticles);
163207

164-
They are available on the SDK instance as `sdk.queries[contentTypePluralName][method]`.
208+
// Work with single types
209+
const homepage = sdk.single('homepage');
210+
const homepageContent = await homepage.find();
211+
console.log('Homepage Content:', homepageContent);
165212

166-
For example, if you have a content type with the plural name of `articles`, the available methods will be `find`, `findOne`, `create`, `update`, and `delete`.
213+
const updatedHomepage = await homepage.update({ title: 'Welcome to the New Homepage' });
214+
console.log('Updated Homepage:', updatedHomepage);
215+
}
167216

168-
```js
169-
// Find all articles
170-
const articles = await strapiSDK.queries.articles.findMany();
217+
main();
171218
```
172-
173-
<!-- TODO refer to docs elsewhere for params accepted for filtering and sorting etc -->

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555
"@commitlint/cli": "19.6.0",
5656
"@commitlint/config-conventional": "19.6.0",
5757
"@commitlint/types": "19.5.0",
58+
"@rollup/plugin-commonjs": "^28.0.1",
59+
"@rollup/plugin-node-resolve": "^15.3.0",
5860
"@rollup/plugin-typescript": "12.1.1",
5961
"@strapi/eslint-config": "0.2.1",
6062
"@types/jest": "^29.5.14",
@@ -75,5 +77,6 @@
7577
"engines": {
7678
"node": ">=18.0.0 <=22.x.x",
7779
"npm": ">=6.0.0"
78-
}
80+
},
81+
"dependencies": {}
7982
}

0 commit comments

Comments
 (0)