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
410 lines
9.5 KiB
TypeScript
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 }
|
|
}
|
|
}
|