Files
payloadcms/test/helpers/rest.ts
T. R. Bernstein 4a5f01a78f
Some checks failed
ci / changes (push) Has been cancelled
ci / lint (push) Has been cancelled
ci / build (push) Has been cancelled
ci / tests-unit (push) Has been cancelled
ci / tests-types (push) Has been cancelled
ci / int-cosmosdb (push) Has been cancelled
ci / int-documentdb (push) Has been cancelled
ci / int-firestore (push) Has been cancelled
ci / int-mongodb (push) Has been cancelled
ci / int-postgres (push) Has been cancelled
ci / int-postgres-custom-schema (push) Has been cancelled
ci / int-postgres-uuid (push) Has been cancelled
ci / int-sqlite (push) Has been cancelled
ci / int-sqlite-uuid (push) Has been cancelled
ci / int-supabase (push) Has been cancelled
ci / e2e-_community (push) Has been cancelled
ci / e2e-access-control (push) Has been cancelled
ci / e2e-admin-bar (push) Has been cancelled
ci / e2e-admin-root (push) Has been cancelled
ci / e2e-admin__e2e__document-view (push) Has been cancelled
ci / e2e-admin__e2e__general (push) Has been cancelled
ci / e2e-admin__e2e__list-view (push) Has been cancelled
ci / e2e-auth (push) Has been cancelled
ci / e2e-auth-basic (push) Has been cancelled
ci / e2e-bulk-edit (push) Has been cancelled
ci / e2e-field-error-states (push) Has been cancelled
ci / e2e-fields-relationship (push) Has been cancelled
ci / e2e-fields__collections__Array (push) Has been cancelled
ci / e2e-fields__collections__Blocks#config.blockreferences.ts (push) Has been cancelled
ci / e2e-fields__collections__Blocks (push) Has been cancelled
ci / e2e-fields__collections__Checkbox (push) Has been cancelled
ci / e2e-fields__collections__Collapsible (push) Has been cancelled
ci / e2e-fields__collections__ConditionalLogic (push) Has been cancelled
ci / e2e-fields__collections__CustomID (push) Has been cancelled
ci / e2e-fields__collections__Date (push) Has been cancelled
ci / e2e-fields__collections__Email (push) Has been cancelled
ci / e2e-fields__collections__Indexed (push) Has been cancelled
ci / e2e-fields__collections__JSON (push) Has been cancelled
ci / e2e-fields__collections__Number (push) Has been cancelled
ci / e2e-fields__collections__Point (push) Has been cancelled
ci / e2e-fields__collections__Radio (push) Has been cancelled
ci / e2e-fields__collections__Relationship (push) Has been cancelled
ci / e2e-fields__collections__Row (push) Has been cancelled
ci / e2e-fields__collections__Select (push) Has been cancelled
ci / e2e-fields__collections__Tabs (push) Has been cancelled
ci / e2e-fields__collections__Tabs2 (push) Has been cancelled
ci / e2e-fields__collections__Text (push) Has been cancelled
ci / e2e-fields__collections__UI (push) Has been cancelled
ci / e2e-fields__collections__Upload (push) Has been cancelled
ci / e2e-folders (push) Has been cancelled
ci / e2e-form-state (push) Has been cancelled
ci / e2e-group-by (push) Has been cancelled
ci / e2e-hooks (push) Has been cancelled
ci / e2e-i18n (push) Has been cancelled
ci / e2e-joins (push) Has been cancelled
ci / e2e-lexical__collections__LexicalHeadingFeature (push) Has been cancelled
ci / e2e-lexical__collections__LexicalJSXConverter (push) Has been cancelled
ci / e2e-lexical__collections__LexicalLinkFeature (push) Has been cancelled
ci / e2e-lexical__collections__Lexical__e2e__blocks#config.blockreferences.ts (push) Has been cancelled
ci / e2e-lexical__collections__Lexical__e2e__blocks (push) Has been cancelled
ci / e2e-lexical__collections__Lexical__e2e__main (push) Has been cancelled
ci / e2e-lexical__collections__OnDemandForm (push) Has been cancelled
ci / e2e-lexical__collections__RichText (push) Has been cancelled
ci / e2e-lexical__collections___LexicalFullyFeatured (push) Has been cancelled
ci / e2e-lexical__collections___LexicalFullyFeatured__db (push) Has been cancelled
ci / e2e-live-preview (push) Has been cancelled
ci / e2e-localization (push) Has been cancelled
ci / e2e-locked-documents (push) Has been cancelled
ci / e2e-plugin-cloud-storage (push) Has been cancelled
ci / e2e-plugin-form-builder (push) Has been cancelled
ci / e2e-plugin-import-export (push) Has been cancelled
ci / e2e-plugin-multi-tenant (push) Has been cancelled
ci / e2e-plugin-nested-docs (push) Has been cancelled
ci / e2e-plugin-seo (push) Has been cancelled
ci / e2e-query-presets (push) Has been cancelled
ci / e2e-sort (push) Has been cancelled
ci / e2e-trash (push) Has been cancelled
ci / e2e-uploads (push) Has been cancelled
ci / e2e-versions (push) Has been cancelled
ci / e2e-turbo-_community (push) Has been cancelled
ci / e2e-turbo-access-control (push) Has been cancelled
ci / e2e-turbo-admin-bar (push) Has been cancelled
ci / e2e-turbo-admin-root (push) Has been cancelled
ci / e2e-turbo-admin__e2e__document-view (push) Has been cancelled
ci / e2e-turbo-admin__e2e__general (push) Has been cancelled
ci / e2e-turbo-admin__e2e__list-view (push) Has been cancelled
ci / e2e-turbo-auth (push) Has been cancelled
ci / e2e-turbo-auth-basic (push) Has been cancelled
ci / e2e-turbo-bulk-edit (push) Has been cancelled
ci / e2e-turbo-field-error-states (push) Has been cancelled
ci / e2e-turbo-fields-relationship (push) Has been cancelled
ci / e2e-turbo-fields__collections__Array (push) Has been cancelled
ci / e2e-turbo-fields__collections__Blocks#config.blockreferences.ts (push) Has been cancelled
ci / e2e-turbo-fields__collections__Blocks (push) Has been cancelled
ci / e2e-turbo-fields__collections__Checkbox (push) Has been cancelled
ci / e2e-turbo-fields__collections__Collapsible (push) Has been cancelled
ci / e2e-turbo-fields__collections__ConditionalLogic (push) Has been cancelled
ci / e2e-turbo-fields__collections__CustomID (push) Has been cancelled
ci / e2e-turbo-fields__collections__Date (push) Has been cancelled
ci / e2e-turbo-fields__collections__Email (push) Has been cancelled
ci / e2e-turbo-fields__collections__Indexed (push) Has been cancelled
ci / e2e-turbo-fields__collections__JSON (push) Has been cancelled
ci / e2e-turbo-fields__collections__Number (push) Has been cancelled
ci / e2e-turbo-fields__collections__Point (push) Has been cancelled
ci / e2e-turbo-fields__collections__Radio (push) Has been cancelled
ci / e2e-turbo-fields__collections__Relationship (push) Has been cancelled
ci / e2e-turbo-fields__collections__Row (push) Has been cancelled
ci / e2e-turbo-fields__collections__Select (push) Has been cancelled
ci / e2e-turbo-fields__collections__Tabs (push) Has been cancelled
ci / e2e-turbo-fields__collections__Tabs2 (push) Has been cancelled
ci / e2e-turbo-fields__collections__Text (push) Has been cancelled
ci / e2e-turbo-fields__collections__UI (push) Has been cancelled
ci / e2e-turbo-fields__collections__Upload (push) Has been cancelled
ci / e2e-turbo-folders (push) Has been cancelled
ci / e2e-turbo-form-state (push) Has been cancelled
ci / e2e-turbo-group-by (push) Has been cancelled
ci / e2e-turbo-hooks (push) Has been cancelled
ci / e2e-turbo-i18n (push) Has been cancelled
ci / e2e-turbo-joins (push) Has been cancelled
ci / e2e-turbo-lexical__collections__LexicalHeadingFeature (push) Has been cancelled
ci / e2e-turbo-lexical__collections__LexicalJSXConverter (push) Has been cancelled
ci / e2e-turbo-lexical__collections__LexicalLinkFeature (push) Has been cancelled
ci / e2e-turbo-lexical__collections__Lexical__e2e__blocks#config.blockreferences.ts (push) Has been cancelled
ci / e2e-turbo-lexical__collections__Lexical__e2e__blocks (push) Has been cancelled
ci / e2e-turbo-lexical__collections__Lexical__e2e__main (push) Has been cancelled
ci / e2e-turbo-lexical__collections__OnDemandForm (push) Has been cancelled
ci / e2e-turbo-lexical__collections__RichText (push) Has been cancelled
ci / e2e-turbo-lexical__collections___LexicalFullyFeatured (push) Has been cancelled
ci / e2e-turbo-lexical__collections___LexicalFullyFeatured__db (push) Has been cancelled
ci / e2e-turbo-live-preview (push) Has been cancelled
ci / e2e-turbo-localization (push) Has been cancelled
ci / e2e-turbo-locked-documents (push) Has been cancelled
ci / e2e-turbo-plugin-cloud-storage (push) Has been cancelled
ci / e2e-turbo-plugin-form-builder (push) Has been cancelled
ci / e2e-turbo-plugin-import-export (push) Has been cancelled
ci / e2e-turbo-plugin-multi-tenant (push) Has been cancelled
ci / e2e-turbo-plugin-nested-docs (push) Has been cancelled
ci / e2e-turbo-plugin-seo (push) Has been cancelled
ci / e2e-turbo-query-presets (push) Has been cancelled
ci / e2e-turbo-sort (push) Has been cancelled
ci / e2e-turbo-trash (push) Has been cancelled
ci / e2e-turbo-uploads (push) Has been cancelled
ci / e2e-turbo-versions (push) Has been cancelled
ci / build-template-blank-mongodb (push) Has been cancelled
ci / build-template-website-mongodb (push) Has been cancelled
ci / build-template-with-payload-cloud-mongodb (push) Has been cancelled
ci / build-template-with-vercel-mongodb-mongodb (push) Has been cancelled
ci / build-template-plugin- (push) Has been cancelled
ci / build-template-with-postgres-postgres (push) Has been cancelled
ci / build-template-with-vercel-postgres-postgres (push) Has been cancelled
ci / tests-type-generation (push) Has been cancelled
ci / All Green (push) Has been cancelled
ci / Publish Canary (push) Has been cancelled
ci / analyze (push) Has been cancelled
publish-prerelease / publish-prerelease-${{ github.ref_name }}-${{ github.sha }} (push) Has been cancelled
lock-issues / lock_issues (push) Has been cancelled
stale / stale (push) Has been cancelled
audit-dependencies / audit (push) Has been cancelled
activity-notifications / run (push) Has been cancelled
chore: Update code to new repo
2025-10-08 23:27:45 +02:00

410 lines
9.5 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import type { PaginatedDocs, TypedUser, Where } from 'tbsh-cms'
import * as qs from 'qs-esm'
import { devUser } from '../credentials.js'
type Args = {
defaultSlug: string
serverURL: string
}
type LoginArgs = {
collection: string
email: string
password: string
}
type LogoutArgs = {
collection: string
}
type CreateArgs<T = any> = {
auth?: boolean
data: T
file?: boolean
slug?: string
}
type FindArgs = {
auth?: boolean
depth?: number
limit?: number
page?: number
query?: Where
slug?: string
sort?: string
}
type FindByIDArgs = {
auth?: boolean
id: number | string
options?: {
depth?: number
limit?: number
page?: number
}
query?: Where
slug?: string
}
type UpdateArgs<T = any> = {
auth?: boolean
data: Partial<T>
id: string
query?: any
slug?: string
}
type UpdateManyArgs<T = any> = {
auth?: boolean
data: Partial<T>
slug?: string
where: any
}
type DeleteArgs = {
auth?: boolean
id: string
slug?: string
}
type DeleteManyArgs = {
auth?: boolean
slug?: string
where: any
}
type FindGlobalArgs<T = any> = {
auth?: boolean
slug?: string
}
type UpdateGlobalArgs<T = any> = {
auth?: boolean
data: Partial<T>
slug?: string
}
type DocResponse<T> = {
doc: T
errors?: { data: any; message: string; name: string }[]
status: number
}
type DocsResponse<T> = {
docs: T[]
errors?: { data: any; id: number | string; message: string; name: string }[]
status: number
}
const headers = {
Authorization: '',
'Content-Type': 'application/json',
}
type QueryResponse<T> = {
result: PaginatedDocs<T>
status: number
}
export class RESTClient {
private defaultSlug: string
private token: string
serverURL: string
public user: TypedUser
constructor(args: Args) {
this.serverURL = args.serverURL
this.defaultSlug = args.defaultSlug
}
async create<T = any>(args: CreateArgs): Promise<DocResponse<T>> {
const options = {
body: args.file ? args.data : JSON.stringify(args.data),
headers: {
...(args.file ? [] : headers),
Authorization: '',
},
method: 'POST',
}
if (args?.auth !== false && this.token) {
options.headers.Authorization = `JWT ${this.token}`
}
const slug = args.slug || this.defaultSlug
const response = await fetch(`${this.serverURL}/api/${slug}`, options)
const { status } = response
const { doc } = await response.json()
return { doc, status }
}
async delete<T = any>(id: string, args?: DeleteArgs): Promise<DocResponse<T>> {
const options = {
headers: { ...headers },
method: 'DELETE',
}
if (args?.auth !== false && this.token) {
options.headers.Authorization = `JWT ${this.token}`
}
const slug = args?.slug || this.defaultSlug
const response = await fetch(`${this.serverURL}/api/${slug}/${id}`, options)
const { status } = response
const doc = await response.json()
return { doc, status }
}
async deleteMany<T = any>(args: DeleteManyArgs): Promise<DocsResponse<T>> {
const { where } = args
const options = {
headers: { ...headers },
method: 'DELETE',
}
if (args?.auth !== false && this.token) {
options.headers.Authorization = `JWT ${this.token}`
}
const formattedQs = qs.stringify(
{
...(where ? { where } : {}),
},
{
addQueryPrefix: true,
},
)
const slug = args?.slug || this.defaultSlug
const response = await fetch(`${this.serverURL}/api/${slug}${formattedQs}`, options)
const { status } = response
const json = await response.json()
return { docs: json.docs, errors: json.errors, status }
}
async endpoint<T = any>(
path: string,
method = 'GET',
params: any = undefined,
): Promise<{ data: T; status: number }> {
const options = {
body: JSON.stringify(params),
headers: { ...headers },
method,
}
const response = await fetch(`${this.serverURL}${path}`, options)
const { status } = response
const data = await response.json()
return { data, status }
}
async endpointWithAuth<T = any>(
path: string,
method = 'GET',
params: any = undefined,
): Promise<{ data: T; status: number }> {
const options = {
body: JSON.stringify(params),
headers: { ...headers },
method,
}
if (this.token) {
options.headers.Authorization = `JWT ${this.token}`
}
const response = await fetch(`${this.serverURL}${path}`, options)
const { status } = response
const data = await response.json()
return { data, status }
}
async find<T = any>(args?: FindArgs): Promise<QueryResponse<T>> {
const options = {
headers: { ...headers },
}
if (args?.auth !== false && this.token) {
options.headers.Authorization = `JWT ${this.token}`
}
const whereQuery = qs.stringify(
{
...(args?.query ? { where: args.query } : {}),
limit: args?.limit,
page: args?.page,
sort: args?.sort,
},
{
addQueryPrefix: true,
},
)
const slug = args?.slug || this.defaultSlug
const response = await fetch(`${this.serverURL}/api/${slug}${whereQuery}`, options)
const { status } = response
const result = await response.json()
if (result.errors) {
throw new Error(result.errors[0].message)
}
return { result, status }
}
async findByID<T = any>(args: FindByIDArgs): Promise<DocResponse<T>> {
const options = {
headers: { ...headers },
}
if (args?.auth !== false && this.token) {
options.headers.Authorization = `JWT ${this.token}`
}
const slug = args?.slug || this.defaultSlug
const formattedOpts = qs.stringify(args?.options || {}, { addQueryPrefix: true })
const response = await fetch(
`${this.serverURL}/api/${slug}/${args.id}${formattedOpts}`,
options,
)
const { status } = response
const doc = await response.json()
return { doc, status }
}
async findGlobal<T = any>(args?: FindGlobalArgs): Promise<DocResponse<T>> {
const options = {
headers: { ...headers },
}
if (args?.auth !== false && this.token) {
options.headers.Authorization = `JWT ${this.token}`
}
const slug = args?.slug || this.defaultSlug
const response = await fetch(`${this.serverURL}/api/globals/${slug}`, options)
const { status } = response
const doc = await response.json()
return { doc, status }
}
async login(incomingArgs?: LoginArgs): Promise<string> {
const args = incomingArgs ?? {
collection: 'users',
email: devUser.email,
password: devUser.password,
}
const response = await fetch(`${this.serverURL}/api/${args.collection}/login`, {
body: JSON.stringify({
email: args.email,
password: args.password,
}),
headers,
method: 'POST',
})
const { user } = await response.json()
let token = user.token
// If the token is not in the response body, then we can extract it from the cookies
if (!token) {
const setCookie = response.headers.get('Set-Cookie')
const tokenMatchResult = setCookie?.match(/payload-token=(?<token>.+?);/)
token = tokenMatchResult?.groups?.token
}
this.user = user
this.token = token
return token
}
async logout(incomingArgs?: LogoutArgs): Promise<void> {
const args = incomingArgs ?? {
collection: 'users',
}
await fetch(`${this.serverURL}/api/${args.collection}/logout`, {
headers,
method: 'POST',
})
this.token = ''
}
async update<T = any>(args: UpdateArgs<T>): Promise<DocResponse<T>> {
const { id, data, query } = args
const options = {
body: JSON.stringify(data),
headers: { ...headers },
method: 'PATCH',
}
if (args?.auth !== false && this.token) {
options.headers.Authorization = `JWT ${this.token}`
}
const formattedQs = qs.stringify(query)
const slug = args.slug || this.defaultSlug
const response = await fetch(`${this.serverURL}/api/${slug}/${id}${formattedQs}`, options)
const { status } = response
const json = await response.json()
return { doc: json.doc, errors: json.errors, status }
}
async updateGlobal<T = any>(args: UpdateGlobalArgs): Promise<DocResponse<T>> {
const { data } = args
const options = {
body: JSON.stringify(data),
headers: { ...headers },
method: 'POST',
}
if (args?.auth !== false && this.token) {
options.headers.Authorization = `JWT ${this.token}`
}
const slug = args?.slug || this.defaultSlug
const response = await fetch(`${this.serverURL}/api/globals/${slug}`, options)
const { status } = response
const { result } = await response.json()
return { doc: result, status }
}
async updateMany<T = any>(args: UpdateManyArgs<T>): Promise<DocsResponse<T>> {
const { data, where } = args
const options = {
body: JSON.stringify(data),
headers: { ...headers },
method: 'PATCH',
}
if (args?.auth !== false && this.token) {
options.headers.Authorization = `JWT ${this.token}`
}
const formattedQs = qs.stringify(
{
...(where ? { where } : {}),
},
{
addQueryPrefix: true,
},
)
const slug = args?.slug || this.defaultSlug
const response = await fetch(`${this.serverURL}/api/${slug}${formattedQs}`, options)
const { status } = response
const json = await response.json()
return { docs: json.docs, errors: json.errors, status }
}
}