import type { ApplyDisableErrors, PaginatedDocs, SelectType, TypeWithVersion } from 'payload' import type { ForgotPasswordOptions } from './auth/forgotPassword.js' import type { LoginOptions, LoginResult } from './auth/login.js' import type { MeOptions, MeResult } from './auth/me.js' import type { ResetPasswordOptions, ResetPasswordResult } from './auth/resetPassword.js' import type { CountOptions } from './collections/count.js' import type { CreateOptions } from './collections/create.js' import type { DeleteByIDOptions, DeleteManyOptions, DeleteOptions } from './collections/delete.js' import type { FindOptions } from './collections/find.js' import type { FindByIDOptions } from './collections/findByID.js' import type { FindVersionByIDOptions } from './collections/findVersionByID.js' import type { FindVersionsOptions } from './collections/findVersions.js' import type { RestoreVersionByIDOptions } from './collections/restoreVersion.js' import type { FindGlobalVersionByIDOptions } from './globals/findVersionByID.js' import type { FindGlobalVersionsOptions } from './globals/findVersions.js' import type { RestoreGlobalVersionByIDOptions } from './globals/restoreVersion.js' import type { UpdateGlobalOptions } from './globals/update.js' import type { AuthCollectionSlug, BulkOperationResult, CollectionSlug, DataFromCollectionSlug, DataFromGlobalSlug, GlobalSlug, PayloadGeneratedTypes, SelectFromCollectionSlug, SelectFromGlobalSlug, TransformCollectionWithSelect, TransformGlobalWithSelect, } from './types.js' import type { OperationArgs } from './utilities/buildSearchParams.js' import { forgotPassword } from './auth/forgotPassword.js' import { login } from './auth/login.js' import { me } from './auth/me.js' import { type RefreshOptions, type RefreshResult, refreshToken } from './auth/refreshToken.js' import { resetPassword } from './auth/resetPassword.js' import { verifyEmail, type VerifyEmailOptions } from './auth/verifyEmail.js' import { count } from './collections/count.js' import { create } from './collections/create.js' import { deleteOperation } from './collections/delete.js' import { find } from './collections/find.js' import { findByID } from './collections/findByID.js' import { findVersionByID } from './collections/findVersionByID.js' import { findVersions } from './collections/findVersions.js' import { restoreVersion } from './collections/restoreVersion.js' import { update, type UpdateByIDOptions, type UpdateManyOptions, type UpdateOptions, } from './collections/update.js' import { findGlobal, type FindGlobalOptions } from './globals/findOne.js' import { findGlobalVersionByID } from './globals/findVersionByID.js' import { findGlobalVersions } from './globals/findVersions.js' import { restoreGlobalVersion } from './globals/restoreVersion.js' import { updateGlobal } from './globals/update.js' import { buildSearchParams } from './utilities/buildSearchParams.js' type Args = { /** Base passed `RequestInit` to `fetch`. For base headers / credentials include etc. */ baseInit?: RequestInit /** * Base API URL for requests. * @example 'https://example.com/api' */ baseURL: string /** * This option allows you to pass a custom `fetch` implementation. * The function always receives `path` as the first parameter and `RequestInit` as the second. * @example For testing without needing an HTTP server: * ```typescript * import type { GeneratedTypes, SanitizedConfig } from 'payload'; * import config from '@payload-config'; * import { REST_DELETE, REST_GET, REST_PATCH, REST_POST, REST_PUT } from '@payloadcms/next/routes'; * import { PayloadSDK } from '@payloadcms/sdk'; * * export type TypedPayloadSDK = PayloadSDK; * * const api = { * GET: REST_GET(config), * POST: REST_POST(config), * PATCH: REST_PATCH(config), * DELETE: REST_DELETE(config), * PUT: REST_PUT(config), * }; * * const awaitedConfig = await config; * * export const sdk = new PayloadSDK({ * baseURL: '', * fetch: (path: string, init: RequestInit) => { * const [slugs, search] = path.slice(1).split('?'); * const url = `${awaitedConfig.serverURL || 'http://localhost:3000'}${awaitedConfig.routes.api}/${slugs}${search ? `?${search}` : ''}`; * * if (init.body instanceof FormData) { * const file = init.body.get('file') as Blob; * if (file && init.headers instanceof Headers) { * init.headers.set('Content-Length', file.size.toString()); * } * } * * const request = new Request(url, init); * * const params = { * params: Promise.resolve({ * slug: slugs.split('/'), * }), * }; * * return api[init.method.toUpperCase()](request, params); * }, * }); * ``` */ fetch?: typeof fetch } /** * @experimental */ export class PayloadSDK { baseInit: RequestInit baseURL: string fetch: typeof fetch constructor(args: Args) { this.baseURL = args.baseURL this.fetch = args.fetch ?? globalThis.fetch this.baseInit = args.baseInit ?? {} } /** * @description Performs count operation * @param options * @returns count of documents satisfying query */ count>( options: CountOptions, init?: RequestInit, ): Promise<{ totalDocs: number }> { return count(this, options, init) } /** * @description Performs create operation * @param options * @returns created document */ create, TSelect extends SelectType>( options: CreateOptions, init?: RequestInit, ): Promise> { return create(this, options, init) } delete, TSelect extends SelectFromCollectionSlug>( options: DeleteManyOptions, init?: RequestInit, ): Promise> delete, TSelect extends SelectFromCollectionSlug>( options: DeleteByIDOptions, init?: RequestInit, ): Promise> /** * @description Update one or more documents * @param options * @returns Updated document(s) */ delete, TSelect extends SelectFromCollectionSlug>( options: DeleteOptions, init?: RequestInit, ): Promise< BulkOperationResult | TransformCollectionWithSelect > { return deleteOperation(this, options, init) } /** * @description Find documents with criteria * @param options * @returns documents satisfying query */ find, TSelect extends SelectType>( options: FindOptions, init?: RequestInit, ): Promise>> { return find(this, options, init) } /** * @description Find document by ID * @param options * @returns document with specified ID */ findByID< TSlug extends CollectionSlug, TDisableErrors extends boolean, TSelect extends SelectType, >( options: FindByIDOptions, init?: RequestInit, ): Promise, TDisableErrors>> { return findByID(this, options, init) } findGlobal, TSelect extends SelectFromGlobalSlug>( options: FindGlobalOptions, init?: RequestInit, ): Promise> { return findGlobal(this, options, init) } findGlobalVersionByID, TDisableErrors extends boolean>( options: FindGlobalVersionByIDOptions, init?: RequestInit, ): Promise>, TDisableErrors>> { return findGlobalVersionByID(this, options, init) } findGlobalVersions>( options: FindGlobalVersionsOptions, init?: RequestInit, ): Promise>>> { return findGlobalVersions(this, options, init) } findVersionByID, TDisableErrors extends boolean>( options: FindVersionByIDOptions, init?: RequestInit, ): Promise< ApplyDisableErrors>, TDisableErrors> > { return findVersionByID(this, options, init) } findVersions>( options: FindVersionsOptions, init?: RequestInit, ): Promise>>> { return findVersions(this, options, init) } forgotPassword>( options: ForgotPasswordOptions, init?: RequestInit, ): Promise<{ message: string }> { return forgotPassword(this, options, init) } login>( options: LoginOptions, init?: RequestInit, ): Promise> { return login(this, options, init) } me>( options: MeOptions, init?: RequestInit, ): Promise> { return me(this, options, init) } refreshToken>( options: RefreshOptions, init?: RequestInit, ): Promise> { return refreshToken(this, options, init) } async request({ args = {}, file, init: incomingInit, json, method, path, }: { args?: OperationArgs file?: Blob init?: RequestInit json?: unknown method: 'DELETE' | 'GET' | 'PATCH' | 'POST' | 'PUT' path: string }): Promise { const headers = new Headers({ ...this.baseInit.headers, ...incomingInit?.headers }) const init: RequestInit = { method, ...this.baseInit, ...incomingInit, headers, } if (json) { if (file) { const formData = new FormData() formData.append('file', file) formData.append('_payload', JSON.stringify(json)) init.body = formData } else { headers.set('Content-Type', 'application/json') init.body = JSON.stringify(json) } } const response = await this.fetch(`${this.baseURL}${path}${buildSearchParams(args)}`, init) return response } resetPassword>( options: ResetPasswordOptions, init?: RequestInit, ): Promise> { return resetPassword(this, options, init) } restoreGlobalVersion>( options: RestoreGlobalVersionByIDOptions, init?: RequestInit, ): Promise>> { return restoreGlobalVersion(this, options, init) } restoreVersion>( options: RestoreVersionByIDOptions, init?: RequestInit, ): Promise> { return restoreVersion(this, options, init) } update, TSelect extends SelectFromCollectionSlug>( options: UpdateManyOptions, init?: RequestInit, ): Promise> update, TSelect extends SelectFromCollectionSlug>( options: UpdateByIDOptions, init?: RequestInit, ): Promise> /** * @description Update one or more documents * @param options * @returns Updated document(s) */ update, TSelect extends SelectFromCollectionSlug>( options: UpdateOptions, init?: RequestInit, ): Promise< BulkOperationResult | TransformCollectionWithSelect > { return update(this, options, init) } updateGlobal, TSelect extends SelectFromGlobalSlug>( options: UpdateGlobalOptions, init?: RequestInit, ): Promise> { return updateGlobal(this, options, init) } verifyEmail>( options: VerifyEmailOptions, init?: RequestInit, ): Promise<{ message: string }> { return verifyEmail(this, options, init) } }