feat: add Payload SDK package
Adds Payload SDK package, which can be used to query Payload REST API in a fully type safe way. Has support for all necessary operations, including auth, type safe select, populate, joins properties and simplified file uploading.
Its interface is very similar to the Local API, can't even notice the difference: Example:
import { PayloadSDK } from '@payloadcms/sdk'
import type { Config } from './payload-types'
// Pass your config from generated types as generic
const sdk = new PayloadSDK<Config>({
baseURL: 'https://example.com/api',
})
// Find operation
const posts = await sdk.find({
collection: 'posts',
draft: true,
limit: 10,
locale: 'en',
page: 1,
where: { _status: { equals: 'published' } },
})
// Find by ID operation
const posts = await sdk.findByID({
id,
collection: 'posts',
draft: true,
locale: 'en',
})
// Auth login operation
const result = await sdk.login({
collection: 'users',
data: {
email: '[email protected]',
password: '12345',
},
})
// Create operation
const result = await sdk.create({
collection: 'posts',
data: { text: 'text' },
})
// Create operation with a file
// `file` can be either a Blob | File object or a string URL
const result = await sdk.create({ collection: 'media', file, data: {} })
// Count operation
const result = await sdk.count({ collection: 'posts', where: { id: { equals: post.id } } })
// Update (by ID) operation
const result = await sdk.update({
collection: 'posts',
id: post.id,
data: {
text: 'updated-text',
},
})
// Update (bulk) operation
const result = await sdk.update({
collection: 'posts',
where: {
id: {
equals: post.id,
},
},
data: { text: 'updated-text-bulk' },
})
// Delete (by ID) operation
const result = await sdk.delete({ id: post.id, collection: 'posts' })
// Delete (bulk) operation
const result = await sdk.delete({ where: { id: { equals: post.id } }, collection: 'posts' })
// Find Global operation
const result = await sdk.findGlobal({ slug: 'global' })
// Update Global operation
const result = await sdk.updateGlobal({ slug: 'global', data: { text: 'some-updated-global' } })
// Auth Login operation
const result = await sdk.login({
collection: 'users',
data: { email: '[email protected]', password: '123456' },
})
// Auth Me operation
const result = await sdk.me(
{ collection: 'users' },
{
headers: {
Authorization: `JWT ${user.token}`,
},
},
)
// Auth Refresh Token operation
const result = await sdk.refreshToken(
{ collection: 'users' },
{ headers: { Authorization: `JWT ${user.token}` } },
)
// Auth Forgot Password operation
const result = await sdk.forgotPassword({
collection: 'users',
data: { email: user.email },
})
// Auth Reset Password operation
const result = await sdk.resetPassword({
collection: 'users',
data: { password: '1234567', token: resetPasswordToken },
})
// Find Versions operation
const result = await sdk.findVersions({
collection: 'posts',
where: { parent: { equals: post.id } },
})
// Find Version by ID operation
const result = await sdk.findVersionByID({ collection: 'posts', id: version.id })
// Restore Version operation
const result = await sdk.restoreVersion({
collection: 'posts',
id,
})
// Find Global Versions operation
const result = await sdk.findGlobalVersions({
slug: 'global',
})
// Find Global Version by ID operation
const result = await sdk.findGlobalVersionByID({ id: version.id, slug: 'global' })
// Restore Global Version operation
const result = await sdk.restoreGlobalVersion({
slug: 'global',
id
})
Every operation has optional 3rd parameter which is used to add additional data to the RequestInit object (like headers):
await sdk.me({
collection: "users"
}, {
// RequestInit object
headers: {
Authorization: `JWT ${token}`
}
})
To query custom endpoints, you can use the request method, which is used internally for all other methods:
await sdk.request({
method: 'POST',
path: '/send-data',
json: {
id: 1,
},
})
Custom fetch implementation and baseInit for shared RequestInit properties:
const sdk = new PayloadSDK<Config>({
baseInit: { credentials: 'include' },
baseURL: 'https://example.com/api',
fetch: async (url, init) => {
console.log('before req')
const response = await fetch(url, init)
console.log('after req')
return response
},
})
Can't wait for this. By the way you've got a typo at packages/sdk/src/auth/rseetPassword.ts.
Any reason we couldn't use this for all test suites that use the REST client?
We could and I thought about this. And actually the same can be in e2e's, we have a custom SDK there but untyped
Just thinking it could be as another chore PR, though maybe worth here as well
What we are calling SDK is really a REST Client. I wonder if we should consider alternate names.
I think we want to use the same package for the realtime API client.
Any updates on this? I would love this feature especially for building custom ui components
// Pass your config from generated types as generic const sdk = new PayloadSDK<Config>({ baseURL: 'https://example.com/api', })
Wouldn't it be better if we passed an autogenerated config parser as an argument? A type parameter here is a way to lie to the TypeScript compiler, and it might fail if for example the client hasn't received the latest update yet.
Wouldn't it be better if we passed an autogenerated config parser as an argument? A type parameter here is a way to lie to the TypeScript compiler, and it might fail if for example the client hasn't received the latest update yet.
I'm not sure what do you mean by "an autogenerated config parser".
I think lying to the Typescript compiler is a user issue.
If you meant to just use import type { GeneratedTypes } from 'payload' directly, you wouldn't be able to use this package outside of Payload projects.
I mean something like:
const sdk = new PayloadSDK(schemaParser, {
baseURL: 'https://example.com/api',
})
Where schemaParser is a variable that actually exists at runtime. Think of a parser like the one you could make with zod, which in this case follows the collections model with its fields.
When I said "autogenerated" I meant it because it is doable and it would be annoying if all users had to do it by hand and keep it in sync with the config.
Lying to the TS compiler is not just a programmer's problem, as there can be problems beyond their control. For example, the one I mentioned where the server is updated with a different schema, but a client that has not yet updated the latest version of the app and receives incorrect data.
The only problem I can think of is that some users may not want to expose their DB schema if it contains sensitive information, and in such cases a type cast could be used as a fallback.
EDIT: Or in case the parser is overkill, to define the type it would be more correct to use an assertion than a type parameter:
const sdk = new PayloadSDK({
baseURL: 'https://example.com/api',
}) as PayloadSDK<Config>
Before merging this, I want to discuss how Next.js cache can be introduced into this in the future. It might have API ramifications and I don't want to have to introduce breaking changes to this SDK after we release it - so maybe we can schedule some time to talk ideas here next week or so
This is exactly what I am looking for, this sounds amazing! It brings a lot of value as payloadcms sells the idea of "typescript first" but currently clients using the rest api don't have any type inference by default
It brings a lot of value as payloadcms sells the idea of "typescript first"
Agreed! This PR and #9782 Would greatly increase the type-safety for payload. @jmikrut Would it make sense to implement a bunch of Next.js caching primitives in an SDK? I could see the PayloadSDK being used inside non-nextjs apps/code in a monorepo specifically.
Will there be any way to type custom endpoints?
Also, I'd love to make a React Query wrapper for Payload SDK, similar to the new tRPC syntax: https://trpc.io/blog/introducing-tanstack-react-query-client
This would be great, can't wait to use it!
Hey @r1tsuu
Thanks for this PR. Is there anything outstanding for it to be merged?
I'm waiting for it!
Will this be merged at some point?
any newes?
excited for this ❤️
It seems this PR has been abandoned. Any plans to continue or should it be closed?
It seems this PR has been abandoned. Any plans to continue or should it be closed?
I hope not, we need this !
Would be awesome to have the reorder endpoint exposed in the local API and sdk:
await payload.reorder({
collection: 'tasks',
docsToMove: ['doc123'],
newKeyWillBe: 'greater',
orderableFieldName: '_order',
target: {
id: 'doc456',
key: 'a5' // Current _order value of doc456
}
})
Hi, I’ve been following this PR for a while. It would be really helpful for my use case. Is there any update or plan to continue work on this? Thanks!
Would be super helpful, can't wait for this to go through 🙌
Hey guys, any news for this PR ?
📦 esbuild Bundle Analysis for payload
This analysis was generated by esbuild-bundle-analyzer. 🤖
| Meta File | Out File | Size (raw) | Note |
|---|---|---|---|
| packages/next/meta_index.json | esbuild/index.js | 753.50 KB | 🆕 Added |
| packages/payload/meta_index.json | esbuild/index.js | 1.22 MB | 🆕 Added |
| packages/payload/meta_shared.json | esbuild/exports/shared.js | 162.07 KB | 🆕 Added |
| packages/richtext-lexical/meta_client.json | esbuild/exports/client_optimized/index.js | 263.56 KB | 🆕 Added |
| packages/ui/meta_client.json | esbuild/exports/client_optimized/index.js | 1.14 MB | 🆕 Added |
| packages/ui/meta_shared.json | esbuild/exports/shared_optimized/index.js | 14.39 KB | 🆕 Added |
Largest paths
These visualization shows top 20 largest paths in the bundle.Meta file: packages/next/meta_index.json, Out file: esbuild/index.js
| Path | Size |
|---|---|
| ../../node_modules | ${{\color{Goldenrod}{ ████████████████████ }}}$ 80.4%, 601.78 KB |
| dist/views/Version | ${{\color{Goldenrod}{ █▋ }}}$ 6.6%, 49.59 KB |
| dist/views/Document | ${{\color{Goldenrod}{ ▌ }}}$ 2.0%, 15.01 KB |
| dist/views/List | ${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 10.29 KB |
| dist/views/Root | ${{\color{Goldenrod}{ ▎ }}}$ 1.1%, 8.24 KB |
| dist/views/API | ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 5.98 KB |
| dist/views/Versions | ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 5.96 KB |
| dist/views/Account | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 5.32 KB |
| dist/elements/DocumentHeader | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 4.67 KB |
| dist/elements/Nav | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 4.67 KB |
| dist/views/Login | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 4.39 KB |
| dist/views/Dashboard | ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 3.68 KB |
| dist/layouts/Root | ${{\color{Goldenrod}{ }}}$ 0.4%, 3.11 KB |
| dist/views/ForgotPassword | ${{\color{Goldenrod}{ }}}$ 0.4%, 3.09 KB |
| dist/templates/Default | ${{\color{Goldenrod}{ }}}$ 0.4%, 2.83 KB |
| dist/views/CreateFirstUser | ${{\color{Goldenrod}{ }}}$ 0.4%, 2.76 KB |
| dist/views/BrowseByFolder | ${{\color{Goldenrod}{ }}}$ 0.3%, 2.60 KB |
| dist/views/CollectionFolders | ${{\color{Goldenrod}{ }}}$ 0.3%, 2.46 KB |
| dist/views/ResetPassword | ${{\color{Goldenrod}{ }}}$ 0.3%, 2.41 KB |
| dist/views/Logout | ${{\color{Goldenrod}{ }}}$ 0.3%, 1.91 KB |
| (other) | ${{\color{Goldenrod}{ ████▉ }}}$ 19.6%, 147.05 KB |
Meta file: packages/payload/meta_index.json, Out file: esbuild/index.js
| Path | Size |
|---|---|
| ../../node_modules | ${{\color{Goldenrod}{ █████████████████▎ }}}$ 69.4%, 841.01 KB |
| dist/fields/hooks | ${{\color{Goldenrod}{ ▉ }}}$ 3.5%, 41.86 KB |
| dist/collections/operations | ${{\color{Goldenrod}{ ▊ }}}$ 3.0%, 36.19 KB |
| dist/auth/operations | ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 15.30 KB |
| dist/queues/operations | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 12.04 KB |
| dist/globals/operations | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 11.90 KB |
| dist/fields/config | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 11.57 KB |
| dist/utilities/configToJSONSchema.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 11.54 KB |
| dist/fields/validations.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 10.04 KB |
| dist/bin/generateImportMap | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.27 KB |
| dist/collections/config | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.80 KB |
| dist/database/migrations | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.79 KB |
| dist/uploads/fetchAPI-multipart | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.74 KB |
| dist/index.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.42 KB |
| dist/collections/endpoints | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.40 KB |
| dist/config/orderable | ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 6.25 KB |
| dist/auth/strategies | ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 5.50 KB |
| dist/config/sanitize.js | ${{\color{Goldenrod}{ }}}$ 0.4%, 5.44 KB |
| dist/auth/endpoints | ${{\color{Goldenrod}{ }}}$ 0.4%, 5.41 KB |
| dist/utilities/telemetry | ${{\color{Goldenrod}{ }}}$ 0.4%, 5.31 KB |
| (other) | ${{\color{Goldenrod}{ ███████▋ }}}$ 30.6%, 370.34 KB |
Meta file: packages/payload/meta_shared.json, Out file: esbuild/exports/shared.js
| Path | Size |
|---|---|
| ../../node_modules | ${{\color{Goldenrod}{ ███████████████████▉ }}}$ 79.9%, 126.93 KB |
| dist/fields/validations.js | ${{\color{Goldenrod}{ █▌ }}}$ 6.3%, 10.04 KB |
| dist/fields/baseFields | ${{\color{Goldenrod}{ ▍ }}}$ 1.8%, 2.79 KB |
| dist/utilities/deepCopyObject.js | ${{\color{Goldenrod}{ ▍ }}}$ 1.6%, 2.48 KB |
| dist/auth/cookies.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 1.55 KB |
| dist/utilities/flattenTopLevelFields.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 1.42 KB |
| dist/fields/config | ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 1.28 KB |
| dist/utilities/flattenAllFields.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 943 B |
| dist/folders/utils | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 916 B |
| dist/utilities/unflatten.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 779 B |
| dist/utilities/sanitizeUserDataForEmail.js | ${{\color{Goldenrod}{ }}}$ 0.4%, 713 B |
| dist/collections/config | ${{\color{Goldenrod}{ }}}$ 0.4%, 570 B |
| dist/bin/generateImportMap | ${{\color{Goldenrod}{ }}}$ 0.4%, 559 B |
| dist/auth/sessions.js | ${{\color{Goldenrod}{ }}}$ 0.3%, 545 B |
| dist/utilities/getSafeRedirect.js | ${{\color{Goldenrod}{ }}}$ 0.3%, 423 B |
| dist/utilities/deepMerge.js | ${{\color{Goldenrod}{ }}}$ 0.3%, 413 B |
| dist/utilities/getFieldPermissions.js | ${{\color{Goldenrod}{ }}}$ 0.2%, 391 B |
| dist/utilities/formatLabels.js | ${{\color{Goldenrod}{ }}}$ 0.2%, 380 B |
| dist/utilities/appendUploadSelectFields.js | ${{\color{Goldenrod}{ }}}$ 0.2%, 360 B |
| dist/utilities/transformColumnPreferences.js | ${{\color{Goldenrod}{ }}}$ 0.2%, 348 B |
| (other) | ${{\color{Goldenrod}{ █████ }}}$ 20.1%, 31.87 KB |
Meta file: packages/richtext-lexical/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
| Path | Size |
|---|---|
| dist/lexical/plugins | ${{\color{Goldenrod}{ ██▉ }}}$ 11.6%, 30.17 KB |
| dist/features/experimental_table | ${{\color{Goldenrod}{ ██▎ }}}$ 9.1%, 23.66 KB |
| dist/lexical/ui | ${{\color{Goldenrod}{ ██▎ }}}$ 9.0%, 23.36 KB |
| dist/features/blocks | ${{\color{Goldenrod}{ ██▏ }}}$ 8.6%, 22.41 KB |
| dist/packages/@lexical | ${{\color{Goldenrod}{ █▊ }}}$ 7.3%, 18.99 KB |
| dist/features/link | ${{\color{Goldenrod}{ █▋ }}}$ 6.9%, 17.96 KB |
| dist/features/toolbars | ${{\color{Goldenrod}{ █▋ }}}$ 6.8%, 17.59 KB |
| dist/features/upload | ${{\color{Goldenrod}{ █▎ }}}$ 5.2%, 13.48 KB |
| dist/features/textState | ${{\color{Goldenrod}{ █ }}}$ 4.2%, 11.02 KB |
| dist/features/relationship | ${{\color{Goldenrod}{ ▉ }}}$ 3.5%, 9.09 KB |
| dist/lexical/utils | ${{\color{Goldenrod}{ ▊ }}}$ 3.1%, 8.08 KB |
| dist/features/debug | ${{\color{Goldenrod}{ ▋ }}}$ 2.8%, 7.39 KB |
| dist/features/converters | ${{\color{Goldenrod}{ ▋ }}}$ 2.7%, 7.04 KB |
| dist/utilities/fieldsDrawer | ${{\color{Goldenrod}{ ▋ }}}$ 2.7%, 7.01 KB |
| dist/lexical/config | ${{\color{Goldenrod}{ ▌ }}}$ 2.0%, 5.10 KB |
| dist/features/lists | ${{\color{Goldenrod}{ ▍ }}}$ 1.9%, 4.95 KB |
| dist/lexical/theme | ${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 4.01 KB |
| dist/features/format | ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 3.46 KB |
| dist/lexical/LexicalEditor.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 3.17 KB |
| dist/features/indent | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 2.50 KB |
| (other) | ${{\color{Goldenrod}{ ██████████████████████ }}}$ 88.4%, 230.33 KB |
Meta file: packages/ui/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
| Path | Size |
|---|---|
| ../../node_modules | ${{\color{Goldenrod}{ ████████████▋ }}}$ 50.6%, 572.93 KB |
| dist/elements/FolderView | ${{\color{Goldenrod}{ ▋ }}}$ 2.6%, 29.14 KB |
| dist/elements/BulkUpload | ${{\color{Goldenrod}{ ▌ }}}$ 2.4%, 26.94 KB |
| dist/elements/WhereBuilder | ${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 16.16 KB |
| dist/views/Edit | ${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 15.69 KB |
| dist/fields/Relationship | ${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 15.39 KB |
| dist/elements/Table | ${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 15.29 KB |
| dist/forms/Form | ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 14.96 KB |
| dist/fields/Blocks | ${{\color{Goldenrod}{ ▎ }}}$ 1.1%, 12.67 KB |
| dist/fields/Upload | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 11.50 KB |
| dist/elements/PublishButton | ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 8.72 KB |
| dist/providers/Folders | ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 8.50 KB |
| dist/elements/LivePreview | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.37 KB |
| dist/elements/QueryPresets | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.27 KB |
| dist/elements/ListHeader | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 7.83 KB |
| dist/elements/HTMLDiff | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 7.81 KB |
| dist/fields/Array | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 7.53 KB |
| dist/views/CollectionFolder | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 7.37 KB |
| dist/views/List | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 6.96 KB |
| dist/elements/ReactSelect | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 6.91 KB |
| (other) | ${{\color{Goldenrod}{ ████████████▎ }}}$ 49.4%, 559.63 KB |
Meta file: packages/ui/meta_shared.json, Out file: esbuild/exports/shared_optimized/index.js
| Path | Size |
|---|---|
| dist/graphics/Logo | ${{\color{Goldenrod}{ █████▋ }}}$ 22.6%, 3.12 KB |
| ../../node_modules | ${{\color{Goldenrod}{ ████▊ }}}$ 19.2%, 2.65 KB |
| dist/graphics/Icon | ${{\color{Goldenrod}{ ██▊ }}}$ 11.0%, 1.52 KB |
| dist/utilities/formatDocTitle | ${{\color{Goldenrod}{ ██▍ }}}$ 9.6%, 1.32 KB |
| dist/providers/TableColumns | ${{\color{Goldenrod}{ █▌ }}}$ 6.2%, 862 B |
| dist/utilities/groupNavItems.js | ${{\color{Goldenrod}{ █▍ }}}$ 5.9%, 814 B |
| dist/utilities/api.js | ${{\color{Goldenrod}{ █▍ }}}$ 5.5%, 756 B |
| dist/elements/Translation | ${{\color{Goldenrod}{ ▉ }}}$ 3.6%, 493 B |
| dist/utilities/handleTakeOver.js | ${{\color{Goldenrod}{ ▊ }}}$ 3.2%, 440 B |
| dist/elements/withMergedProps | ${{\color{Goldenrod}{ ▋ }}}$ 2.5%, 339 B |
| dist/elements/WithServerSideProps | ${{\color{Goldenrod}{ ▍ }}}$ 1.7%, 232 B |
| dist/utilities/handleGoBack.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 168 B |
| dist/fields/mergeFieldStyles.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 159 B |
| dist/forms/Form | ${{\color{Goldenrod}{ ▎ }}}$ 1.1%, 147 B |
| dist/utilities/abortAndIgnore.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.1%, 146 B |
| dist/utilities/hasSavePermission.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 136 B |
| dist/utilities/handleBackToDashboard.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 129 B |
| dist/utilities/findLocaleFromCode.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 84 B |
| dist/utilities/sanitizeID.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 77 B |
| dist/utilities/isEditing.js | ${{\color{Goldenrod}{ }}}$ 0.4%, 59 B |
| (other) | ${{\color{Goldenrod}{ ███████████████████▎ }}}$ 77.4%, 10.68 KB |
Details
Next to the size is how much the size has increased or decreased compared with the base branch of this PR.
- ‼️: Size increased by 20% or more. Special attention should be given to this.
- ⚠️: Size increased in acceptable range (lower than 20%).
- ✅: No change or even downsized.
- 🗑️: The out file is deleted: not found in base branch.
- 🆕: The out file is newly found: will be added to base branch.
🫶
🚀 This is included in version v3.58.0
What are some use cases for this? Out of curiosity.
Anything that's not Next. I've been using it in SvelteKit
Just to broaden that slightly, it's useful when you host your frontend separately to your Payload backend. I ended up building my own SDK as I wasn't able to wait for this one to land, but it's been really valuable having it.