From c52b9baa919fd8efcbad0cc399d4d94fe1237150 Mon Sep 17 00:00:00 2001 From: DrMint <29893320+DrMint@users.noreply.github.com> Date: Sat, 13 Jul 2024 10:55:10 +0200 Subject: [PATCH] Added payload shared library --- payload/blocks.ts | 47 ++++ payload/constants.ts | 83 ++++++ payload/endpoint-types.ts | 550 ++++++++++++++++++++++++++++++++++++++ payload/rich-text.ts | 211 +++++++++++++++ payload/sdk.ts | 222 +++++++++++++++ payload/webhooks.ts | 8 + 6 files changed, 1121 insertions(+) create mode 100644 payload/blocks.ts create mode 100644 payload/constants.ts create mode 100644 payload/endpoint-types.ts create mode 100644 payload/rich-text.ts create mode 100644 payload/sdk.ts create mode 100644 payload/webhooks.ts diff --git a/payload/blocks.ts b/payload/blocks.ts new file mode 100644 index 0000000..c3bfc20 --- /dev/null +++ b/payload/blocks.ts @@ -0,0 +1,47 @@ +import { RichTextContent } from "./rich-text"; + +export interface TranscriptBlock extends GenericBlock { + lines: (LineBlock | CueBlock)[]; + blockType: "transcriptBlock"; + } + + export interface BreakBlock extends GenericBlock { + type: "Scene break" | "Empty space" | "Solid line" | "Dotted line"; + blockType: "breakBlock"; + } + + export interface SectionBlock extends GenericBlock { + content: RichTextContent; + blockType: "sectionBlock"; + } + + export interface CueBlock extends GenericBlock { + content: RichTextContent; + blockType: "cueBlock"; + } + + export interface LineBlock extends GenericBlock { + content: RichTextContent; + blockType: "lineBlock"; + } + + export interface GenericBlock { + id?: string | null; + blockName?: string | null; + blockType: string; + } + + export const isBlockTranscriptBlock = (block: GenericBlock): block is TranscriptBlock => + block.blockType === "transcriptBlock"; + + export const isBlockBreakBlock = (block: GenericBlock): block is BreakBlock => + block.blockType === "breakBlock"; + + export const isBlockSectionBlock = (block: GenericBlock): block is SectionBlock => + block.blockType === "sectionBlock"; + + export const isBlockCueBlock = (block: GenericBlock): block is CueBlock => + block.blockType === "cueBlock"; + + export const isBlockLineBlock = (block: GenericBlock): block is LineBlock => + block.blockType === "lineBlock"; \ No newline at end of file diff --git a/payload/constants.ts b/payload/constants.ts new file mode 100644 index 0000000..5a723b5 --- /dev/null +++ b/payload/constants.ts @@ -0,0 +1,83 @@ +export enum Collections { + Attributes = "attributes", + Audios = "audios", + ChronologyEvents = "chronology-events", + Collectibles = "collectibles", + CreditsRole = "credits-roles", + Currencies = "currencies", + Files = "files", + Folders = "folders", + GenericContents = "generic-contents", + Images = "images", + Languages = "languages", + MediaThumbnails = "media-thumbnails", + Pages = "pages", + Recorders = "recorders", + Scans = "scans", + Tags = "tags", + Videos = "videos", + VideosChannels = "videos-channels", + VideosSubtitles = "videos-subtitles", + Wordings = "wordings", + WebsiteConfig = "website-config", +} + +export enum CollectionGroups { + Collections = "Collections", + Media = "Media", + Meta = "Meta", +} + +export enum LanguageCodes { + en = "English", + fr = "French", + ja = "Japan", + es = "Spanish", + "pt-br" = "Portuguese", + "zh" = "Chinese", +} + +export enum BreakBlockType { + sceneBreak = "Scene break", + space = "Empty space", + solidLine = "Solid line", + dottedLine = "Dotted line", +} + +export enum CollectibleBindingTypes { + Paperback = "Paperback", + Hardcover = "Hardcover", +} + +export enum CollectiblePageOrders { + LeftToRight = "Left to right", + RightToLeft = "Right to left", +} + +export enum CollectibleNature { + Physical = "Physical", + Digital = "Digital", +} + +export enum CollectibleContentType { + None = "None", + Indexes = "Index-based", + Pages = "Page-based", +} + +export enum RecordersRoles { + Admin = "Admin", + Recorder = "Recorder", + Api = "Api", +} + +export enum CollectionStatus { + Draft = "draft", + Published = "published", +} + +export enum AttributeTypes { + Number = "Number", + Text = "Text", + Tags = "Tags", +} diff --git a/payload/endpoint-types.ts b/payload/endpoint-types.ts new file mode 100644 index 0000000..c40a395 --- /dev/null +++ b/payload/endpoint-types.ts @@ -0,0 +1,550 @@ +import { AttributeTypes, CollectibleBindingTypes, CollectibleNature, CollectiblePageOrders, Collections } from "./constants"; +import { RichTextContent } from "./rich-text"; + +export interface EndpointCurrency { + id: string; +} + +export interface EndpointLanguage { + id: string; + name: string; + selectable: boolean; +} + +export type EndpointFolderPreview = { + id: string; + slug: string; + icon?: string; + translations: { + language: string; + title: string; + }[]; + }; + + export type EndpointFolder = Omit & { + translations: (EndpointFolderPreview["translations"][number] & { + description?: RichTextContent; + })[]; + sections: + | { type: "single"; subfolders: EndpointFolderPreview[] } + | { + type: "multiple"; + sections: { + translations: { language: string; name: string }[]; + subfolders: EndpointFolderPreview[]; + }[]; + }; + files: ( + | { + relationTo: Collections.Collectibles; + value: EndpointCollectiblePreview; + } + | { + relationTo: Collections.Pages; + value: EndpointPagePreview; + } + | { + relationTo: Collections.Images; + value: EndpointImagePreview; + } + | { + relationTo: Collections.Audios; + value: EndpointAudioPreview; + } + | { + relationTo: Collections.Videos; + value: EndpointVideoPreview; + } + | { + relationTo: Collections.Files; + value: EndpointFilePreview; + } + )[]; + parentPages: EndpointSource[]; + }; + + export type EndpointWebsiteConfig = { + home: { + backgroundImage?: EndpointPayloadImage; + folders: (EndpointFolderPreview & { + lightThumbnail?: EndpointPayloadImage; + darkThumbnail?: EndpointPayloadImage; + })[]; + }; + timeline: { + backgroundImage?: EndpointPayloadImage; + breaks: number[]; + eventCount: number; + eras: { + startingYear: number; + endingYear: number; + name: string; + }[]; + }; + defaultOpenGraphImage?: EndpointPayloadImage; + }; + + export type EndpointRecorderPreview = { + id: string; + username: string; + }; + + export type EndpointRecorder = EndpointRecorderPreview & { + avatar?: EndpointPayloadImage; + translations: { + language: string; + biography: RichTextContent; + }[]; + languages: string[]; + }; + + export type EndpointWording = { + name: string; + translations: { + language: string; + name: string; + }[]; + }; + + export type EndpointTag = { + id: string; + slug: string; + page?: { slug: string }; + translations: { + language: string; + name: string; + }[]; + }; + + export type EndpointGenericAttribute = { + id: string; + slug: string; + icon: string; + translations: { + language: string; + name: string; + }[]; + }; + + export type EndpointNumberAttribute = EndpointGenericAttribute & { + type: AttributeTypes.Number; + value: number; + }; + + export type EndpointTextAttribute = EndpointGenericAttribute & { + type: AttributeTypes.Text; + value: string; + }; + + export type EndpointTagsAttribute = EndpointGenericAttribute & { + type: AttributeTypes.Tags; + value: EndpointTag[]; + }; + + export type EndpointAttribute = + | EndpointNumberAttribute + | EndpointTextAttribute + | EndpointTagsAttribute; + + export type EndpointRole = { + id: string; + icon: string; + translations: { + language: string; + name: string; + }[]; + }; + + export type EndpointCredit = { + role: EndpointRole; + recorders: EndpointRecorderPreview[]; + }; + + export type EndpointPagePreview = { + id: string; + slug: string; + thumbnail?: EndpointPayloadImage; + attributes: EndpointAttribute[]; + translations: { + language: string; + pretitle?: string; + title: string; + subtitle?: string; + }[]; + updatedAt: string; + }; + + export type EndpointPage = Omit & { + backgroundImage?: EndpointPayloadImage; + translations: (EndpointPagePreview["translations"][number] & { + sourceLanguage: string; + summary?: RichTextContent; + content: RichTextContent; + credits: EndpointCredit[]; + toc: TableOfContentEntry[]; + })[]; + createdAt: string; + updatedBy?: EndpointRecorderPreview; + parentPages: EndpointSource[]; + }; + + export type EndpointCollectiblePreview = { + id: string; + slug: string; + thumbnail?: EndpointPayloadImage; + translations: { + language: string; + pretitle?: string; + title: string; + subtitle?: string; + }[]; + attributes: EndpointAttribute[]; + releaseDate?: string; + languages: string[]; + price?: { + amount: number; + currency: string; + }; + }; + + export type EndpointCollectible = Omit & { + translations: (EndpointCollectiblePreview["translations"][number] & { + description?: RichTextContent; + })[]; + backgroundImage?: EndpointPayloadImage; + nature: CollectibleNature; + gallery?: { count: number; thumbnail: EndpointPayloadImage }; + scans?: { count: number; thumbnail: EndpointPayloadImage }; + urls: { url: string; label: string }[]; + size?: { + width: number; + height: number; + thickness?: number; + }; + weight?: number; + pageInfo?: { + pageCount: number; + bindingType?: CollectibleBindingTypes; + pageOrder?: CollectiblePageOrders; + }; + subitems: EndpointCollectiblePreview[]; + files: EndpointFilePreview[]; + contents: { + content: + | { + relationTo: Collections.Pages; + value: EndpointPagePreview; + } + | { + relationTo: Collections.Audios; + value: EndpointAudioPreview; + } + | { + relationTo: Collections.Videos; + value: EndpointVideoPreview; + } + | { + relationTo: Collections.GenericContents; + value: { + translations: { + language: string; + name: string; + }[]; + }; + }; + + range?: + | { + type: "pageRange"; + start: number; + end: number; + } + | { + type: "timeRange"; + start: string; + end: string; + } + | { + type: "other"; + translations: { + language: string; + note: RichTextContent; + }[]; + }; + }[]; + createdAt: string; + updatedAt: string; + updatedBy?: EndpointRecorderPreview; + parentPages: EndpointSource[]; + }; + + export type EndpointCollectibleScans = { + slug: string; + thumbnail?: EndpointPayloadImage; + translations: { + language: string; + pretitle?: string; + title: string; + subtitle?: string; + description?: RichTextContent; + }[]; + credits: EndpointCredit[]; + cover?: { + front?: EndpointScanImage; + spine?: EndpointScanImage; + back?: EndpointScanImage; + insideFront?: EndpointScanImage; + insideBack?: EndpointScanImage; + flapFront?: EndpointScanImage; + flapBack?: EndpointScanImage; + insideFlapFront?: EndpointScanImage; + insideFlapBack?: EndpointScanImage; + }; + dustjacket?: { + front?: EndpointScanImage; + spine?: EndpointScanImage; + back?: EndpointScanImage; + insideFront?: EndpointScanImage; + insideSpine?: EndpointScanImage; + insideBack?: EndpointScanImage; + flapFront?: EndpointScanImage; + flapBack?: EndpointScanImage; + insideFlapFront?: EndpointScanImage; + insideFlapBack?: EndpointScanImage; + }; + obi?: { + front?: EndpointScanImage; + spine?: EndpointScanImage; + back?: EndpointScanImage; + insideFront?: EndpointScanImage; + insideSpine?: EndpointScanImage; + insideBack?: EndpointScanImage; + flapFront?: EndpointScanImage; + flapBack?: EndpointScanImage; + insideFlapFront?: EndpointScanImage; + insideFlapBack?: EndpointScanImage; + }; + pages: EndpointScanImage[]; + parentPages: EndpointSource[]; + }; + + export type EndpointCollectibleGallery = { + slug: string; + thumbnail?: EndpointPayloadImage; + translations: { + language: string; + pretitle?: string; + title: string; + subtitle?: string; + description?: RichTextContent; + }[]; + images: EndpointPayloadImage[]; + parentPages: EndpointSource[]; + }; + + export type EndpointCollectibleGalleryImage = { + slug: string; + translations: { + language: string; + pretitle?: string; + title: string; + subtitle?: string; + description?: RichTextContent; + }[]; + image: EndpointImage; + previousIndex?: string; + nextIndex?: string; + parentPages: EndpointSource[]; + }; + + export type EndpointCollectibleScanPage = { + slug: string; + translations: { + language: string; + pretitle?: string; + title: string; + subtitle?: string; + description?: RichTextContent; + }[]; + image: EndpointScanImage; + previousIndex?: string; + nextIndex?: string; + parentPages: EndpointSource[]; + }; + + export type EndpointScanImage = PayloadImage & { + index: string; + sizes: PayloadImage[]; + }; + + export type TableOfContentEntry = { + prefix: string; + title: string; + type: "sceneBreak" | "break" | "section"; + index: number; + children: TableOfContentEntry[]; + }; + + export type EndpointChronologyEvent = { + id: string; + date: { + year: number; + month?: number; + day?: number; + }; + events: { + sources: EndpointSource[]; + translations: { + language: string; + sourceLanguage: string; + title?: string; + description?: RichTextContent; + notes?: RichTextContent; + credits: EndpointCredit[]; + }[]; + }[]; + }; + + export type EndpointSourcePreview = { + id: string; + slug: string; + translations: { language: string; pretitle?: string; title: string; subtitle?: string }[]; + }; + + export type EndpointSource = + | { type: "url"; url: string; label: string } + | { + type: "collectible"; + collectible: EndpointSourcePreview; + range?: + | { type: "page"; page: number } + | { type: "timestamp"; timestamp: string } + | { type: "custom"; translations: { language: string; note: string }[] }; + } + | { type: "page"; page: EndpointSourcePreview } + | { type: "folder"; folder: EndpointSourcePreview } + | { type: "scans"; collectible: EndpointSourcePreview } + | { type: "gallery"; collectible: EndpointSourcePreview }; + + export type EndpointMediaPreview = { + id: string; + url: string; + filename: string; + mimeType: string; + attributes: EndpointAttribute[]; + translations: { + language: string; + pretitle?: string; + title: string; + subtitle?: string; + }[]; + }; + + export type EndpointMedia = Omit & { + filesize: number; + updatedAt: string; + createdAt: string; + translations: (EndpointMediaPreview["translations"][number] & { + description?: RichTextContent; + })[]; + credits: EndpointCredit[]; + }; + + export type EndpointImagePreview = EndpointMediaPreview & { + width: number; + height: number; + sizes: PayloadImage[]; + openGraph?: PayloadImage; + }; + + export type EndpointImage = EndpointMedia & { + width: number; + height: number; + sizes: PayloadImage[]; + openGraph?: PayloadImage; + }; + + export type EndpointAudioPreview = EndpointMediaPreview & { + thumbnail?: EndpointPayloadImage; + duration: number; + }; + + export type EndpointAudio = EndpointMedia & { + thumbnail?: EndpointPayloadImage; + duration: number; + }; + + export type EndpointVideoPreview = EndpointMediaPreview & { + thumbnail?: EndpointPayloadImage; + subtitles: { + language: string; + url: string; + }[]; + duration: number; + }; + + export type EndpointVideo = EndpointMedia & { + thumbnail?: EndpointPayloadImage; + subtitles: { + language: string; + url: string; + }[]; + platform?: { + channel: { + url: string; + title: string; + subscribers: number; + }; + views?: number; + likes?: number; + dislikes?: number; + url: string; + publishedDate: string; + }; + duration: number; + }; + + export type EndpointFilePreview = EndpointMediaPreview & { + filesize: number; + thumbnail?: EndpointPayloadImage; + }; + + export type EndpointFile = EndpointMedia & { + filesize: number; + thumbnail?: EndpointPayloadImage; + }; + + export type EndpointPayloadImage = PayloadImage & { + sizes: PayloadImage[]; + openGraph?: PayloadImage; + }; + + export type PayloadMedia = { + id: string; + url: string; + mimeType: string; + filename: string; + filesize: number; + }; + + export type PayloadImage = PayloadMedia & { + width: number; + height: number; + }; + + export type EndpointAllSDKUrls = { + urls: string[]; + }; + + export type EndpointAllIds = { + collectibles: { slugs: string[] }; + pages: { slugs: string[] }; + folders: { slugs: string[] }; + videos: { ids: string[] }; + audios: { ids: string[] }; + images: { ids: string[] }; + files: { ids: string[] }; + recorders: { ids: string[] }; + chronologyEvents: { ids: string[] }; + }; + \ No newline at end of file diff --git a/payload/rich-text.ts b/payload/rich-text.ts new file mode 100644 index 0000000..6b5538a --- /dev/null +++ b/payload/rich-text.ts @@ -0,0 +1,211 @@ +import { Collections } from "./constants"; +import { + EndpointAudioPreview, + EndpointImagePreview, + EndpointVideoPreview, +} from "./endpoint-types"; +import { + GenericBlock, + SectionBlock, + TranscriptBlock, + BreakBlock, + isBlockTranscriptBlock, + isBlockBreakBlock, +} from "./blocks"; + +export type RichTextContent = { + root: { + children: RichTextNode[]; + direction: ("ltr" | "rtl") | null; + format: "left" | "start" | "center" | "right" | "end" | "justify" | ""; + indent: number; + type: string; + version: number; + }; + [k: string]: unknown; +}; + +export type RichTextNode = { + type: string; + version: number; + [k: string]: unknown; +}; + +export interface RichTextNodeWithChildren extends RichTextNode { + children: RichTextNode[]; +} + +export interface RichTextParagraphNode extends RichTextNodeWithChildren { + type: "paragraph"; + format: "left" | "start" | "center" | "right" | "end" | "justify" | ""; +} + +export interface RichTextListNode extends RichTextNode { + type: "list"; + children: RichTextNodeWithChildren[]; + listType: string; +} + +export interface RichTextListNumberNode extends RichTextListNode { + listType: "number"; +} + +export interface RichTextListBulletNode extends RichTextListNode { + listType: "bullet"; +} + +export interface RichTextListCheckNode extends RichTextListNode { + listType: "check"; +} + +export interface RichTextLinebreakNode extends RichTextNode { + type: "linebreak"; +} + +export interface RichTextUploadNode extends RichTextNode { + type: "upload"; + relationTo: string; +} + +export interface RichTextUploadImageNode extends RichTextUploadNode { + relationTo: Collections.Images; + value: EndpointImagePreview; +} + +export interface RichTextUploadVideoNode extends RichTextUploadNode { + relationTo: Collections.Videos; + value: EndpointVideoPreview; +} + +export interface RichTextUploadAudioNode extends RichTextUploadNode { + relationTo: Collections.Audios; + value: EndpointAudioPreview; +} + +export interface RichTextTextNode extends RichTextNode { + type: "text"; + format: number; + text: string; +} + +export interface RichTextTabNode extends RichTextNode { + type: "tab"; + format: number; +} + +export interface RichTextLinkNode extends RichTextNodeWithChildren { + type: "link"; + fields: { + linkType: "internal" | "custom"; + }; +} + +export interface RichTextLinkInternalNode extends RichTextLinkNode { + fields: { + linkType: "internal"; + newTab: boolean; + doc: { + relationTo: string; + value: any; + }; + }; +} + +export interface RichTextLinkCustomNode extends RichTextLinkNode { + fields: { + linkType: "custom"; + newTab: boolean; + url: string; + }; +} + +export interface RichTextBlockNode extends RichTextNode { + type: "block"; + fields: GenericBlock; +} + +export interface RichTextSectionBlock extends RichTextBlockNode { + fields: SectionBlock; + anchorHash: string; +} + +export interface RichTextTranscriptBlock extends RichTextBlockNode { + fields: TranscriptBlock; +} + +export interface RichTextBreakBlock extends RichTextBlockNode { + fields: BreakBlock; + anchorHash: string; +} + +export const isNodeParagraphNode = ( + node: RichTextNode +): node is RichTextParagraphNode => node.type === "paragraph"; + +export const isNodeUploadNode = ( + node: RichTextNode +): node is RichTextUploadNode => node.type === "upload"; + +export const isUploadNodeImageNode = ( + node: RichTextUploadNode +): node is RichTextUploadImageNode => node.relationTo === Collections.Images; + +export const isUploadNodeVideoNode = ( + node: RichTextUploadNode +): node is RichTextUploadVideoNode => node.relationTo === Collections.Videos; + +export const isUploadNodeAudioNode = ( + node: RichTextUploadNode +): node is RichTextUploadAudioNode => node.relationTo === Collections.Audios; + +export const isNodeListNode = (node: RichTextNode): node is RichTextListNode => + node.type === "list"; + +export const isListNodeNumberListNode = ( + node: RichTextListNode +): node is RichTextListNumberNode => node.listType === "number"; + +export const isListNodeBulletListNode = ( + node: RichTextListNode +): node is RichTextListBulletNode => node.listType === "bullet"; + +export const isListNodeCheckListNode = ( + node: RichTextListNode +): node is RichTextListCheckNode => node.listType === "check"; + +export const isNodeLinebreakNode = ( + node: RichTextNode +): node is RichTextLinebreakNode => node.type === "linebreak"; + +export const isNodeTextNode = (node: RichTextNode): node is RichTextTextNode => + node.type === "text"; + +export const isNodeTabNode = (node: RichTextNode): node is RichTextTabNode => + node.type === "tab"; + +export const isNodeLinkNode = (node: RichTextNode): node is RichTextLinkNode => + node.type === "link"; + +export const isLinkNodeInternalLinkNode = ( + node: RichTextLinkNode +): node is RichTextLinkInternalNode => node.fields.linkType === "internal"; + +export const isLinkNodeCustomLinkNode = ( + node: RichTextLinkNode +): node is RichTextLinkCustomNode => node.fields.linkType === "custom"; + +export const isNodeBlockNode = ( + node: RichTextNode +): node is RichTextBlockNode => node.type === "block"; + +export const isBlockNodeSectionBlock = ( + node: RichTextBlockNode +): node is RichTextSectionBlock => node.fields.blockType === "sectionBlock"; + +export const isBlockNodeTranscriptBlock = ( + node: RichTextBlockNode +): node is RichTextTranscriptBlock => isBlockTranscriptBlock(node.fields); + +export const isBlockNodeBreakBlock = ( + node: RichTextBlockNode +): node is RichTextBreakBlock => isBlockBreakBlock(node.fields); diff --git a/payload/sdk.ts b/payload/sdk.ts new file mode 100644 index 0000000..9e77583 --- /dev/null +++ b/payload/sdk.ts @@ -0,0 +1,222 @@ +import { Collections } from "./constants"; +import { + EndpointAllIds, + EndpointAllSDKUrls, + EndpointAudio, + EndpointChronologyEvent, + EndpointCollectible, + EndpointCollectibleGallery, + EndpointCollectibleGalleryImage, + EndpointCollectibleScanPage, + EndpointCollectibleScans, + EndpointCurrency, + EndpointFile, + EndpointFolder, + EndpointImage, + EndpointLanguage, + EndpointPage, + EndpointRecorder, + EndpointVideo, + EndpointWebsiteConfig, + EndpointWording, +} from "./endpoint-types"; + +export const getSDKEndpoint = { + getConfigEndpoint: () => `/globals/${Collections.WebsiteConfig}/config`, + getFolderEndpoint: (slug: string) => `/${Collections.Folders}/slug/${slug}`, + getLanguagesEndpoint: () => `/${Collections.Languages}/all`, + getCurrenciesEndpoint: () => `/${Collections.Currencies}/all`, + getWordingsEndpoint: () => `/${Collections.Wordings}/all`, + getPageEndpoint: (slug: string) => `/${Collections.Pages}/slug/${slug}`, + getCollectibleEndpoint: (slug: string) => + `/${Collections.Collectibles}/slug/${slug}`, + getCollectibleScansEndpoint: (slug: string) => + `/${Collections.Collectibles}/slug/${slug}/scans`, + getCollectibleScanPageEndpoint: (slug: string, index: string) => + `/${Collections.Collectibles}/slug/${slug}/scans/${index}`, + getCollectibleGalleryEndpoint: (slug: string) => + `/${Collections.Collectibles}/slug/${slug}/gallery`, + getCollectibleGalleryImageEndpoint: (slug: string, index: string) => + `/${Collections.Collectibles}/slug/${slug}/gallery/${index}`, + getChronologyEventsEndpoint: () => `/${Collections.ChronologyEvents}/all`, + getChronologyEventByIDEndpoint: (id: string) => + `/${Collections.ChronologyEvents}/id/${id}`, + getImageByIDEndpoint: (id: string) => `/${Collections.Images}/id/${id}`, + getAudioByIDEndpoint: (id: string) => `/${Collections.Audios}/id/${id}`, + getVideoByIDEndpoint: (id: string) => `/${Collections.Videos}/id/${id}`, + getFileByIDEndpoint: (id: string) => `/${Collections.Files}/id/${id}`, + getRecorderByIDEndpoint: (id: string) => `/${Collections.Recorders}/id/${id}`, + getAllSDKUrlsEndpoint: () => `/all-sdk-urls`, + getAllIds: () => `/all-ids`, + getLoginEndpoint: () => `/${Collections.Recorders}/login`, +}; + +type PayloadSDKResponse = { + data: T; + endpointCalled: string; +}; + +type PayloadTokenCache = { + set: (token: string, expirationTimestamp: number) => void; + get: () => string | undefined; +}; + +type PayloadDataCache = { + set: (url: string, response: any) => void; + get: (url: string) => any | undefined; +}; + +export class PayloadSDK { + private tokenCache: PayloadTokenCache | undefined; + private dataCache: PayloadDataCache | undefined; + + constructor( + private readonly apiURL: string, + private readonly email: string, + private readonly password: string + ) {} + + addTokenCache(tokenCache: PayloadTokenCache) { + this.tokenCache = tokenCache; + } + + addDataCache(dataCache: PayloadDataCache) { + this.dataCache = dataCache; + } + + private logResponse(res: Response) { + console.log(res.status, res.statusText, res.url); + } + + private async refreshToken() { + const loginUrl = `${this.apiURL}${getSDKEndpoint.getLoginEndpoint()}`; + const loginResult = await fetch(loginUrl, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ email: this.email, password: this.password }), + }); + this.logResponse(loginResult); + + if (loginResult.status !== 200) { + throw new Error("Unable to login"); + } + + const { token, exp } = (await loginResult.json()) as { + token: string; + exp: number; + }; + this.tokenCache?.set(token, exp); + return token; + } + + async request(endpoint: string): Promise> { + const cachedResponse = this.dataCache?.get(endpoint); + if (cachedResponse) { + return cachedResponse; + } + + const result = await fetch(`${this.apiURL}${endpoint}`, { + headers: { + Authorization: `JWT ${ + this.tokenCache?.get() ?? (await this.refreshToken()) + }`, + }, + }); + this.logResponse(result); + + if (!result.ok) { + throw new Error("Unhandled fetch error"); + } + + const response = { data: await result.json(), endpointCalled: endpoint }; + this.dataCache?.set(endpoint, response); + return response; + } + + async getConfig(): Promise> { + return await this.request(getSDKEndpoint.getConfigEndpoint()); + } + async getFolder(slug: string): Promise> { + return await this.request(getSDKEndpoint.getFolderEndpoint(slug)); + } + async getLanguages(): Promise> { + return await this.request(getSDKEndpoint.getLanguagesEndpoint()); + } + async getCurrencies(): Promise> { + return await this.request(getSDKEndpoint.getCurrenciesEndpoint()); + } + async getWordings(): Promise> { + return await this.request(getSDKEndpoint.getWordingsEndpoint()); + } + async getPage(slug: string): Promise> { + return await this.request(getSDKEndpoint.getPageEndpoint(slug)); + } + async getCollectible( + slug: string + ): Promise> { + return await this.request(getSDKEndpoint.getCollectibleEndpoint(slug)); + } + async getCollectibleScans( + slug: string + ): Promise> { + return await this.request(getSDKEndpoint.getCollectibleScansEndpoint(slug)); + } + async getCollectibleScanPage( + slug: string, + index: string + ): Promise> { + return await this.request( + getSDKEndpoint.getCollectibleScanPageEndpoint(slug, index) + ); + } + async getCollectibleGallery( + slug: string + ): Promise> { + return await this.request( + getSDKEndpoint.getCollectibleGalleryEndpoint(slug) + ); + } + async getCollectibleGalleryImage( + slug: string, + index: string + ): Promise> { + return await this.request( + getSDKEndpoint.getCollectibleGalleryImageEndpoint(slug, index) + ); + } + async getChronologyEvents(): Promise< + PayloadSDKResponse + > { + return await this.request(getSDKEndpoint.getChronologyEventsEndpoint()); + } + async getChronologyEventByID( + id: string + ): Promise> { + return await this.request( + getSDKEndpoint.getChronologyEventByIDEndpoint(id) + ); + } + async getImageByID(id: string): Promise> { + return await this.request(getSDKEndpoint.getImageByIDEndpoint(id)); + } + async getAudioByID(id: string): Promise> { + return await this.request(getSDKEndpoint.getAudioByIDEndpoint(id)); + } + async getVideoByID(id: string): Promise> { + return await this.request(getSDKEndpoint.getVideoByIDEndpoint(id)); + } + async getFileByID(id: string): Promise> { + return await this.request(getSDKEndpoint.getFileByIDEndpoint(id)); + } + async getRecorderByID( + id: string + ): Promise> { + return await this.request(getSDKEndpoint.getRecorderByIDEndpoint(id)); + } + async getAllSdkUrls(): Promise> { + return await this.request(getSDKEndpoint.getAllSDKUrlsEndpoint()); + } + async getAllIds(): Promise> { + return await this.request(getSDKEndpoint.getAllIds()); + } +} diff --git a/payload/webhooks.ts b/payload/webhooks.ts new file mode 100644 index 0000000..aa631c9 --- /dev/null +++ b/payload/webhooks.ts @@ -0,0 +1,8 @@ +import { Collections } from "./constants"; + +export type AfterOperationWebHookMessage = { + collection: Collections; + id?: string; + addedDependantIds: string[]; + urls: string[]; + }; \ No newline at end of file