From c8ac12f97814b0effa9be7753869d0fcd75b448b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cdongming=E2=80=9D?= <“lidongming@aituringflow.com”> Date: Sun, 28 Dec 2025 22:42:09 +0800 Subject: [PATCH] first commit --- .gitea/workflows/deploy.yml | 134 + .gitignore | 25 + .vscode/extensions.json | 4 + .vscode/launch.json | 11 + AGENT.md | 116 + README.md | 62 + astro.config.mjs | 21 + package.json | 21 + public/favicon.svg | 9 + src/clientsdk/client.gen.ts | 16 + src/clientsdk/client/client.gen.ts | 301 + src/clientsdk/client/index.ts | 25 + src/clientsdk/client/types.gen.ts | 241 + src/clientsdk/client/utils.gen.ts | 332 + src/clientsdk/core/auth.gen.ts | 42 + src/clientsdk/core/bodySerializer.gen.ts | 100 + src/clientsdk/core/params.gen.ts | 176 + src/clientsdk/core/pathSerializer.gen.ts | 181 + src/clientsdk/core/queryKeySerializer.gen.ts | 136 + src/clientsdk/core/serverSentEvents.gen.ts | 266 + src/clientsdk/core/types.gen.ts | 118 + src/clientsdk/core/utils.gen.ts | 143 + src/clientsdk/index.ts | 4 + src/clientsdk/querySerializer.ts | 28 + src/clientsdk/sdk.gen.ts | 1098 ++++ src/clientsdk/types.gen.ts | 6179 ++++++++++++++++++ src/components/Footer.astro | 10 + src/components/Header.astro | 15 + src/components/PostCard.astro | 30 + src/config.ts | 3 + src/layouts/Layout.astro | 22 + src/pages/categories/[slug].astro | 101 + src/pages/categories/index.astro | 58 + src/pages/index.astro | 81 + src/pages/posts/[slug].astro | 102 + src/styles/global.css | 2 + tsconfig.json | 5 + 37 files changed, 10218 insertions(+) create mode 100644 .gitea/workflows/deploy.yml create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 AGENT.md create mode 100644 README.md create mode 100644 astro.config.mjs create mode 100644 package.json create mode 100644 public/favicon.svg create mode 100644 src/clientsdk/client.gen.ts create mode 100644 src/clientsdk/client/client.gen.ts create mode 100644 src/clientsdk/client/index.ts create mode 100644 src/clientsdk/client/types.gen.ts create mode 100644 src/clientsdk/client/utils.gen.ts create mode 100644 src/clientsdk/core/auth.gen.ts create mode 100644 src/clientsdk/core/bodySerializer.gen.ts create mode 100644 src/clientsdk/core/params.gen.ts create mode 100644 src/clientsdk/core/pathSerializer.gen.ts create mode 100644 src/clientsdk/core/queryKeySerializer.gen.ts create mode 100644 src/clientsdk/core/serverSentEvents.gen.ts create mode 100644 src/clientsdk/core/types.gen.ts create mode 100644 src/clientsdk/core/utils.gen.ts create mode 100644 src/clientsdk/index.ts create mode 100644 src/clientsdk/querySerializer.ts create mode 100644 src/clientsdk/sdk.gen.ts create mode 100644 src/clientsdk/types.gen.ts create mode 100644 src/components/Footer.astro create mode 100644 src/components/Header.astro create mode 100644 src/components/PostCard.astro create mode 100644 src/config.ts create mode 100644 src/layouts/Layout.astro create mode 100644 src/pages/categories/[slug].astro create mode 100644 src/pages/categories/index.astro create mode 100644 src/pages/index.astro create mode 100644 src/pages/posts/[slug].astro create mode 100644 src/styles/global.css create mode 100644 tsconfig.json diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..2c2ffa8 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,134 @@ +name: Deploy to Cloudflare Pages + +on: + push: + tags: + - 'deploy-*' # 只在推送 deploy-* 标签时触发 + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Parse tag to env + run: | + # 获取 tag 名称(Gitea Actions 使用 GITHUB_REF_NAME) + TAG_NAME="${GITHUB_REF_NAME}" + echo "TAG_NAME=$TAG_NAME" + + # Tag 格式: deploy-{project_name}-{deploymentId_no_dashes} + # 例如: deploy-b7ea026a-cf09-4e31-9f29-b55d7c652b71-123e4567e89b12d3a456426614174000 + + # 去掉 "deploy-" 前缀 + PREFIX="deploy-" + REST="${TAG_NAME#$PREFIX}" + + # deploymentId(无破折号)固定是最后32个字符 + DEPLOYMENT_ID="${REST: -32}" + + # project_name 是剩余部分(去掉最后的 "-" 和 deploymentId) + PROJECT_NAME="${REST%-${DEPLOYMENT_ID}}" + + echo "PROJECT_NAME=$PROJECT_NAME" >> "$GITHUB_ENV" + echo "DEPLOYMENT_ID=$DEPLOYMENT_ID" >> "$GITHUB_ENV" + #echo "DOMAIN=${PROJECT_NAME}-preview.turingflowai.com" >> "$GITHUB_ENV" + + # 调试输出 + echo "Parsed PROJECT_NAME: $PROJECT_NAME" + echo "Parsed DEPLOYMENT_ID: $DEPLOYMENT_ID" + + - name: Check toolchain (debug only, 可选) + run: | + node -v || echo "node not found" + npm -v || echo "npm not found" + curl --version || echo "curl not found" + + # 已经在 node:20-bookworm-slim 容器内,无需再 setup-node + # - name: Setup Node + # uses: actions/setup-node@v4 + # with: + # node-version: '20' + + - name: Use CN npm registry + run: | + npm config set registry http://repo.myhuaweicloud.com/repository/npm/ + + - name: Install dependencies + run: | + npm ci --no-audit --no-fund + + - name: Build + run: npm run build + + - name: Deploy to Cloudflare Pages + env: + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }} + CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }} + PROJECT_NAME: ${{ env.PROJECT_NAME }} + DOMAIN: ${{ env.DOMAIN }} + run: | + set -euo pipefail + echo "[deploy] project: $PROJECT_NAME" + echo "[deploy] domain: $DOMAIN" + + # 部署到 Cloudflare Pages (假定构建产物在 dist/) + npx wrangler pages deploy dist \ + --project-name "$PROJECT_NAME" \ + --branch main + + # 绑定自定义域名:-preview.turingflowai.com + #curl --fail -X POST \ + # "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/pages/projects/${PROJECT_NAME}/domains" \ + # -H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \ + # -H "Content-Type: application/json" \ + # -d '{"name":"'"${DOMAIN}"'"}' \ + # || true + + - name: Notify Deploy Service (success) + if: success() + env: + DEPLOY_SERVICE_CALLBACK_URL: ${{ secrets.DEPLOY_SERVICE_CALLBACK_URL }} + DEPLOY_SERVICE_TOKEN: ${{ secrets.DEPLOY_SERVICE_TOKEN }} + DEPLOYMENT_ID: ${{ env.DEPLOYMENT_ID }} + run: | + set -euo pipefail + + # 获取当前 commit SHA (Gitea Actions 使用 GITHUB_SHA) + COMMIT_SHA="${GITHUB_SHA}" + + curl -X POST "$DEPLOY_SERVICE_CALLBACK_URL" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $DEPLOY_SERVICE_TOKEN" \ + -d '{ + "deploymentId": "'"${DEPLOYMENT_ID}"'", + "status": "deployed", + "commitSha": "'"${COMMIT_SHA}"'", + "cfDeploymentId": "", + "errorMessage": null + }' + + - name: Notify Deploy Service (failure) + if: failure() + env: + DEPLOY_SERVICE_CALLBACK_URL: ${{ secrets.DEPLOY_SERVICE_CALLBACK_URL }} + DEPLOY_SERVICE_TOKEN: ${{ secrets.DEPLOY_SERVICE_TOKEN }} + DEPLOYMENT_ID: ${{ env.DEPLOYMENT_ID }} + run: | + set -euo pipefail + + # 获取当前 commit SHA + COMMIT_SHA="${GITHUB_SHA}" + + curl -X POST "$DEPLOY_SERVICE_CALLBACK_URL" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $DEPLOY_SERVICE_TOKEN" \ + -d '{ + "deploymentId": "'"${DEPLOYMENT_ID}"'", + "status": "failed", + "commitSha": "'"${COMMIT_SHA}"'", + "cfDeploymentId": "", + "errorMessage": "see Gitea Actions logs" + }' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5975753 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# build output +dist/ +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.local +.env.production + +# macOS-specific files +.DS_Store + +# jetbrains setting folder +.idea/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..22a1505 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d642209 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} diff --git a/AGENT.md b/AGENT.md new file mode 100644 index 0000000..82ffb13 --- /dev/null +++ b/AGENT.md @@ -0,0 +1,116 @@ +# Client SDK Usage Guide + +This project uses an auto-generated SDK powered by `@hey-api/openapi-ts` to interact with the PayloadCMS multi-tenant backend. + +## SDK Structure + +- **Core Methods**: `src/clientsdk/sdk.gen.ts` (Contains classes like `Posts`, `Categories`, `Pages`, `Media`) +- **Type Definitions**: `src/clientsdk/types.gen.ts` (Contains interfaces like `Post`, `Category`, `Media`) +- **Query Serializer**: `src/clientsdk/querySerializer.ts` (Handles nested object serialization for PayloadCMS queries) +- **Client Factory**: `src/clientsdk/client/index.ts` (Use `createClient` to initialize a client instance) + +## 1. Initialization + +You must initialize the client with the correct `baseUrl`, `querySerializer`, and tenant headers. + +```typescript +import { createClient } from '../clientsdk/client'; +import { customQuerySerializer } from '../clientsdk/querySerializer'; +import { TENANT_SLUG, TENANT_API_KEY, API_URL } from '../config'; + +const client = createClient({ + baseUrl: API_URL, + querySerializer: customQuerySerializer, // CRITICAL: Required for nested where queries + headers: { + 'X-Tenant-Slug': TENANT_SLUG, + 'X-API-Key': TENANT_API_KEY, + }, +}); +``` + +## 2. Common Operations + +### Fetching a List (with Sorting & Limits) +```typescript +import { Posts } from '../clientsdk/sdk.gen'; + +const response = await Posts.listPosts({ + client, + query: { + limit: 10, + sort: '-createdAt', // Prefix with '-' for descending + }, +}); + +// Access the data +const posts = response.data?.docs || []; +``` + +### Fetching a Single Document by Slug (Filtering) +PayloadCMS uses a specific `where` query syntax. The `customQuerySerializer` handles the translation to `where[slug][equals]=my-slug`. + +```typescript +const response = await Posts.listPosts({ + client, + query: { + where: { + slug: { + equals: 'my-article-slug', + }, + }, + limit: 1, + }, +}); + +const post = response.data?.docs?.[0]; +``` + +### Filtering by Category Slug +```typescript +const response = await Posts.listPosts({ + client, + query: { + where: { + 'categories.slug': { + equals: 'news', + }, + }, + }, +}); +``` + +## 3. Data Patterns + +### Relationships +- **Categories**: In this project, categories are a **many-to-many** relationship. Always treat `post.categories` as an array. + - Correct: `post.categories?.[0]?.title` + - Incorrect: `post.category.title` +- **Media**: Images (like `heroImage`) are objects containing `url`, `alt`, and `sizes`. + - Example: `{post.heroImage?.alt}` + +### Rich Text (Lexical) +PayloadCMS provides Lexical rich text. We typically use `post.content_html` which is pre-rendered to HTML on the server. +- **React**: `
` +- **Vue**: `
` +- **Astro**: `
` + +## 4. TypeScript Usage + +Always use the generated types for better DX and safety. + +```typescript +import type { Post, Category, Media } from '../clientsdk/types.gen'; + +function formatPost(post: Post) { + return { + title: post.title, + date: new Date(post.createdAt).toLocaleDateString() + }; +} +``` + +## 5. Troubleshooting + +- **CORS Issues**: Ensure `API_URL` in `config.ts` matches the backend port (default 3000). +- **Empty Results**: Check if the `X-Tenant-Slug` header matches the slug assigned to your content in the CMS admin panel. +- **Nested Query Error**: If you see "Deeply-nested arrays/objects aren’t supported", verify that you are passing the `customQuerySerializer` to the `createClient` options. diff --git a/README.md b/README.md new file mode 100644 index 0000000..55ce35a --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +# Astro Starter Kit: Blog + +```sh +pnpm create astro@latest -- --template blog +``` + +> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! + +Features: + +- ✅ Minimal styling (make it your own!) +- ✅ 100/100 Lighthouse performance +- ✅ SEO-friendly with canonical URLs and OpenGraph data +- ✅ Sitemap support +- ✅ RSS Feed support +- ✅ Markdown & MDX support + +## 🚀 Project Structure + +Inside of your Astro project, you'll see the following folders and files: + +```text +├── public/ +├── src/ +│   ├── components/ +│   ├── content/ +│   ├── layouts/ +│   └── pages/ +├── astro.config.mjs +├── README.md +├── package.json +└── tsconfig.json +``` + +Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. + +There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. + +The `src/content/` directory contains "collections" of related Markdown and MDX documents. Use `getCollection()` to retrieve posts from `src/content/blog/`, and type-check your frontmatter using an optional schema. See [Astro's Content Collections docs](https://docs.astro.build/en/guides/content-collections/) to learn more. + +Any static assets, like images, can be placed in the `public/` directory. + +## 🧞 Commands + +All commands are run from the root of the project, from a terminal: + +| Command | Action | +| :------------------------ | :----------------------------------------------- | +| `pnpm install` | Installs dependencies | +| `pnpm dev` | Starts local dev server at `localhost:4321` | +| `pnpm build` | Build your production site to `./dist/` | +| `pnpm preview` | Preview your build locally, before deploying | +| `pnpm astro ...` | Run CLI commands like `astro add`, `astro check` | +| `pnpm astro -- --help` | Get help using the Astro CLI | + +## 👀 Want to learn more? + +Check out [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). + +## Credit + +This theme is based off of the lovely [Bear Blog](https://github.com/HermanMartinus/bearblog/). diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 0000000..c04bb89 --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,21 @@ +// @ts-check +import { defineConfig } from 'astro/config'; +import tailwindcss from '@tailwindcss/vite'; +import node from '@astrojs/node'; + +// https://astro.build/config +export default defineConfig({ + output: 'server', + adapter: node({ + mode: 'standalone' + }), + vite: { + plugins: [tailwindcss()], + define: { + 'import.meta.env.PUBLIC_TENANT_SLUG': JSON.stringify(process.env.PUBLIC_TENANT_SLUG), + 'import.meta.env.PUBLIC_TENANT_API_KEY': JSON.stringify(process.env.PUBLIC_TENANT_API_KEY), + 'import.meta.env.PUBLIC_API_URL': JSON.stringify(process.env.PUBLIC_API_URL), + }, + } +}); + diff --git a/package.json b/package.json new file mode 100644 index 0000000..ccbc09e --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "astro-template", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "build": "astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/node": "^9.5.1", + "@tailwindcss/vite": "^4.1.18", + "astro": "^5.16.6", + "axios": "^1.13.2", + "tailwindcss": "^4.1.18" + }, + "devDependencies": { + "@tailwindcss/typography": "^0.5.19" + } +} diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..f157bd1 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,9 @@ + + + + diff --git a/src/clientsdk/client.gen.ts b/src/clientsdk/client.gen.ts new file mode 100644 index 0000000..6d73486 --- /dev/null +++ b/src/clientsdk/client.gen.ts @@ -0,0 +1,16 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { type ClientOptions, type Config, createClient, createConfig } from './client'; +import type { ClientOptions as ClientOptions2 } from './types.gen'; + +/** + * The `createClientConfig()` function will be called on client initialization + * and the returned object will become the client's initial configuration. + * + * You may want to initialize your client this way instead of calling + * `setConfig()`. This is useful for example if you're using Next.js + * to ensure your client always has the correct values. + */ +export type CreateClientConfig = (override?: Config) => Config & T>; + +export const client = createClient(createConfig({ baseUrl: 'http://localhost:3000' })); diff --git a/src/clientsdk/client/client.gen.ts b/src/clientsdk/client/client.gen.ts new file mode 100644 index 0000000..c2a5190 --- /dev/null +++ b/src/clientsdk/client/client.gen.ts @@ -0,0 +1,301 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { createSseClient } from '../core/serverSentEvents.gen'; +import type { HttpMethod } from '../core/types.gen'; +import { getValidRequestBody } from '../core/utils.gen'; +import type { + Client, + Config, + RequestOptions, + ResolvedRequestOptions, +} from './types.gen'; +import { + buildUrl, + createConfig, + createInterceptors, + getParseAs, + mergeConfigs, + mergeHeaders, + setAuthParams, +} from './utils.gen'; + +type ReqInit = Omit & { + body?: any; + headers: ReturnType; +}; + +export const createClient = (config: Config = {}): Client => { + let _config = mergeConfigs(createConfig(), config); + + const getConfig = (): Config => ({ ..._config }); + + const setConfig = (config: Config): Config => { + _config = mergeConfigs(_config, config); + return getConfig(); + }; + + const interceptors = createInterceptors< + Request, + Response, + unknown, + ResolvedRequestOptions + >(); + + const beforeRequest = async (options: RequestOptions) => { + const opts = { + ..._config, + ...options, + fetch: options.fetch ?? _config.fetch ?? globalThis.fetch, + headers: mergeHeaders(_config.headers, options.headers), + serializedBody: undefined, + }; + + if (opts.security) { + await setAuthParams({ + ...opts, + security: opts.security, + }); + } + + if (opts.requestValidator) { + await opts.requestValidator(opts); + } + + if (opts.body !== undefined && opts.bodySerializer) { + opts.serializedBody = opts.bodySerializer(opts.body); + } + + // remove Content-Type header if body is empty to avoid sending invalid requests + if (opts.body === undefined || opts.serializedBody === '') { + opts.headers.delete('Content-Type'); + } + + const url = buildUrl(opts); + + return { opts, url }; + }; + + const request: Client['request'] = async (options) => { + // @ts-expect-error + const { opts, url } = await beforeRequest(options); + const requestInit: ReqInit = { + redirect: 'follow', + ...opts, + body: getValidRequestBody(opts), + }; + + let request = new Request(url, requestInit); + + for (const fn of interceptors.request.fns) { + if (fn) { + request = await fn(request, opts); + } + } + + // fetch must be assigned here, otherwise it would throw the error: + // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation + const _fetch = opts.fetch!; + let response: Response; + + try { + response = await _fetch(request); + } catch (error) { + // Handle fetch exceptions (AbortError, network errors, etc.) + let finalError = error; + + for (const fn of interceptors.error.fns) { + if (fn) { + finalError = (await fn( + error, + undefined as any, + request, + opts, + )) as unknown; + } + } + + finalError = finalError || ({} as unknown); + + if (opts.throwOnError) { + throw finalError; + } + + // Return error response + return opts.responseStyle === 'data' + ? undefined + : { + error: finalError, + request, + response: undefined as any, + }; + } + + for (const fn of interceptors.response.fns) { + if (fn) { + response = await fn(response, request, opts); + } + } + + const result = { + request, + response, + }; + + if (response.ok) { + const parseAs = + (opts.parseAs === 'auto' + ? getParseAs(response.headers.get('Content-Type')) + : opts.parseAs) ?? 'json'; + + if ( + response.status === 204 || + response.headers.get('Content-Length') === '0' + ) { + let emptyData: any; + switch (parseAs) { + case 'arrayBuffer': + case 'blob': + case 'text': + emptyData = await response[parseAs](); + break; + case 'formData': + emptyData = new FormData(); + break; + case 'stream': + emptyData = response.body; + break; + case 'json': + default: + emptyData = {}; + break; + } + return opts.responseStyle === 'data' + ? emptyData + : { + data: emptyData, + ...result, + }; + } + + let data: any; + switch (parseAs) { + case 'arrayBuffer': + case 'blob': + case 'formData': + case 'json': + case 'text': + data = await response[parseAs](); + break; + case 'stream': + return opts.responseStyle === 'data' + ? response.body + : { + data: response.body, + ...result, + }; + } + + if (parseAs === 'json') { + if (opts.responseValidator) { + await opts.responseValidator(data); + } + + if (opts.responseTransformer) { + data = await opts.responseTransformer(data); + } + } + + return opts.responseStyle === 'data' + ? data + : { + data, + ...result, + }; + } + + const textError = await response.text(); + let jsonError: unknown; + + try { + jsonError = JSON.parse(textError); + } catch { + // noop + } + + const error = jsonError ?? textError; + let finalError = error; + + for (const fn of interceptors.error.fns) { + if (fn) { + finalError = (await fn(error, response, request, opts)) as string; + } + } + + finalError = finalError || ({} as string); + + if (opts.throwOnError) { + throw finalError; + } + + // TODO: we probably want to return error and improve types + return opts.responseStyle === 'data' + ? undefined + : { + error: finalError, + ...result, + }; + }; + + const makeMethodFn = + (method: Uppercase) => (options: RequestOptions) => + request({ ...options, method }); + + const makeSseFn = + (method: Uppercase) => async (options: RequestOptions) => { + const { opts, url } = await beforeRequest(options); + return createSseClient({ + ...opts, + body: opts.body as BodyInit | null | undefined, + headers: opts.headers as unknown as Record, + method, + onRequest: async (url, init) => { + let request = new Request(url, init); + for (const fn of interceptors.request.fns) { + if (fn) { + request = await fn(request, opts); + } + } + return request; + }, + url, + }); + }; + + return { + buildUrl, + connect: makeMethodFn('CONNECT'), + delete: makeMethodFn('DELETE'), + get: makeMethodFn('GET'), + getConfig, + head: makeMethodFn('HEAD'), + interceptors, + options: makeMethodFn('OPTIONS'), + patch: makeMethodFn('PATCH'), + post: makeMethodFn('POST'), + put: makeMethodFn('PUT'), + request, + setConfig, + sse: { + connect: makeSseFn('CONNECT'), + delete: makeSseFn('DELETE'), + get: makeSseFn('GET'), + head: makeSseFn('HEAD'), + options: makeSseFn('OPTIONS'), + patch: makeSseFn('PATCH'), + post: makeSseFn('POST'), + put: makeSseFn('PUT'), + trace: makeSseFn('TRACE'), + }, + trace: makeMethodFn('TRACE'), + } as Client; +}; diff --git a/src/clientsdk/client/index.ts b/src/clientsdk/client/index.ts new file mode 100644 index 0000000..b295ede --- /dev/null +++ b/src/clientsdk/client/index.ts @@ -0,0 +1,25 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type { Auth } from '../core/auth.gen'; +export type { QuerySerializerOptions } from '../core/bodySerializer.gen'; +export { + formDataBodySerializer, + jsonBodySerializer, + urlSearchParamsBodySerializer, +} from '../core/bodySerializer.gen'; +export { buildClientParams } from '../core/params.gen'; +export { serializeQueryKeyValue } from '../core/queryKeySerializer.gen'; +export { createClient } from './client.gen'; +export type { + Client, + ClientOptions, + Config, + CreateClientConfig, + Options, + RequestOptions, + RequestResult, + ResolvedRequestOptions, + ResponseStyle, + TDataShape, +} from './types.gen'; +export { createConfig, mergeHeaders } from './utils.gen'; diff --git a/src/clientsdk/client/types.gen.ts b/src/clientsdk/client/types.gen.ts new file mode 100644 index 0000000..b4a499c --- /dev/null +++ b/src/clientsdk/client/types.gen.ts @@ -0,0 +1,241 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth } from '../core/auth.gen'; +import type { + ServerSentEventsOptions, + ServerSentEventsResult, +} from '../core/serverSentEvents.gen'; +import type { + Client as CoreClient, + Config as CoreConfig, +} from '../core/types.gen'; +import type { Middleware } from './utils.gen'; + +export type ResponseStyle = 'data' | 'fields'; + +export interface Config + extends Omit, + CoreConfig { + /** + * Base URL for all requests made by this client. + */ + baseUrl?: T['baseUrl']; + /** + * Fetch API implementation. You can use this option to provide a custom + * fetch instance. + * + * @default globalThis.fetch + */ + fetch?: typeof fetch; + /** + * Please don't use the Fetch client for Next.js applications. The `next` + * options won't have any effect. + * + * Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead. + */ + next?: never; + /** + * Return the response data parsed in a specified format. By default, `auto` + * will infer the appropriate method from the `Content-Type` response header. + * You can override this behavior with any of the {@link Body} methods. + * Select `stream` if you don't want to parse response data at all. + * + * @default 'auto' + */ + parseAs?: + | 'arrayBuffer' + | 'auto' + | 'blob' + | 'formData' + | 'json' + | 'stream' + | 'text'; + /** + * Should we return only data or multiple fields (data, error, response, etc.)? + * + * @default 'fields' + */ + responseStyle?: ResponseStyle; + /** + * Throw an error instead of returning it in the response? + * + * @default false + */ + throwOnError?: T['throwOnError']; +} + +export interface RequestOptions< + TData = unknown, + TResponseStyle extends ResponseStyle = 'fields', + ThrowOnError extends boolean = boolean, + Url extends string = string, +> extends Config<{ + responseStyle: TResponseStyle; + throwOnError: ThrowOnError; + }>, + Pick< + ServerSentEventsOptions, + | 'onSseError' + | 'onSseEvent' + | 'sseDefaultRetryDelay' + | 'sseMaxRetryAttempts' + | 'sseMaxRetryDelay' + > { + /** + * Any body that you want to add to your request. + * + * {@link https://developer.mozilla.org/docs/Web/API/fetch#body} + */ + body?: unknown; + path?: Record; + query?: Record; + /** + * Security mechanism(s) to use for the request. + */ + security?: ReadonlyArray; + url: Url; +} + +export interface ResolvedRequestOptions< + TResponseStyle extends ResponseStyle = 'fields', + ThrowOnError extends boolean = boolean, + Url extends string = string, +> extends RequestOptions { + serializedBody?: string; +} + +export type RequestResult< + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = boolean, + TResponseStyle extends ResponseStyle = 'fields', +> = ThrowOnError extends true + ? Promise< + TResponseStyle extends 'data' + ? TData extends Record + ? TData[keyof TData] + : TData + : { + data: TData extends Record + ? TData[keyof TData] + : TData; + request: Request; + response: Response; + } + > + : Promise< + TResponseStyle extends 'data' + ? + | (TData extends Record + ? TData[keyof TData] + : TData) + | undefined + : ( + | { + data: TData extends Record + ? TData[keyof TData] + : TData; + error: undefined; + } + | { + data: undefined; + error: TError extends Record + ? TError[keyof TError] + : TError; + } + ) & { + request: Request; + response: Response; + } + >; + +export interface ClientOptions { + baseUrl?: string; + responseStyle?: ResponseStyle; + throwOnError?: boolean; +} + +type MethodFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'>, +) => RequestResult; + +type SseFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'>, +) => Promise>; + +type RequestFn = < + TData = unknown, + TError = unknown, + ThrowOnError extends boolean = false, + TResponseStyle extends ResponseStyle = 'fields', +>( + options: Omit, 'method'> & + Pick< + Required>, + 'method' + >, +) => RequestResult; + +type BuildUrlFn = < + TData extends { + body?: unknown; + path?: Record; + query?: Record; + url: string; + }, +>( + options: TData & Options, +) => string; + +export type Client = CoreClient< + RequestFn, + Config, + MethodFn, + BuildUrlFn, + SseFn +> & { + interceptors: Middleware; +}; + +/** + * The `createClientConfig()` function will be called on client initialization + * and the returned object will become the client's initial configuration. + * + * You may want to initialize your client this way instead of calling + * `setConfig()`. This is useful for example if you're using Next.js + * to ensure your client always has the correct values. + */ +export type CreateClientConfig = ( + override?: Config, +) => Config & T>; + +export interface TDataShape { + body?: unknown; + headers?: unknown; + path?: unknown; + query?: unknown; + url: string; +} + +type OmitKeys = Pick>; + +export type Options< + TData extends TDataShape = TDataShape, + ThrowOnError extends boolean = boolean, + TResponse = unknown, + TResponseStyle extends ResponseStyle = 'fields', +> = OmitKeys< + RequestOptions, + 'body' | 'path' | 'query' | 'url' +> & + ([TData] extends [never] ? unknown : Omit); diff --git a/src/clientsdk/client/utils.gen.ts b/src/clientsdk/client/utils.gen.ts new file mode 100644 index 0000000..4c48a9e --- /dev/null +++ b/src/clientsdk/client/utils.gen.ts @@ -0,0 +1,332 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { getAuthToken } from '../core/auth.gen'; +import type { QuerySerializerOptions } from '../core/bodySerializer.gen'; +import { jsonBodySerializer } from '../core/bodySerializer.gen'; +import { + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from '../core/pathSerializer.gen'; +import { getUrl } from '../core/utils.gen'; +import type { Client, ClientOptions, Config, RequestOptions } from './types.gen'; + +export const createQuerySerializer = ({ + parameters = {}, + ...args +}: QuerySerializerOptions = {}) => { + const querySerializer = (queryParams: T) => { + const search: string[] = []; + if (queryParams && typeof queryParams === 'object') { + for (const name in queryParams) { + const value = queryParams[name]; + + if (value === undefined || value === null) { + continue; + } + + const options = parameters[name] || args; + + if (Array.isArray(value)) { + const serializedArray = serializeArrayParam({ + allowReserved: options.allowReserved, + explode: true, + name, + style: 'form', + value, + ...options.array, + }); + if (serializedArray) search.push(serializedArray); + } else if (typeof value === 'object') { + const serializedObject = serializeObjectParam({ + allowReserved: options.allowReserved, + explode: true, + name, + style: 'deepObject', + value: value as Record, + ...options.object, + }); + if (serializedObject) search.push(serializedObject); + } else { + const serializedPrimitive = serializePrimitiveParam({ + allowReserved: options.allowReserved, + name, + value: value as string, + }); + if (serializedPrimitive) search.push(serializedPrimitive); + } + } + } + return search.join('&'); + }; + return querySerializer; +}; + +/** + * Infers parseAs value from provided Content-Type header. + */ +export const getParseAs = ( + contentType: string | null, +): Exclude => { + if (!contentType) { + // If no Content-Type header is provided, the best we can do is return the raw response body, + // which is effectively the same as the 'stream' option. + return 'stream'; + } + + const cleanContent = contentType.split(';')[0]?.trim(); + + if (!cleanContent) { + return; + } + + if ( + cleanContent.startsWith('application/json') || + cleanContent.endsWith('+json') + ) { + return 'json'; + } + + if (cleanContent === 'multipart/form-data') { + return 'formData'; + } + + if ( + ['application/', 'audio/', 'image/', 'video/'].some((type) => + cleanContent.startsWith(type), + ) + ) { + return 'blob'; + } + + if (cleanContent.startsWith('text/')) { + return 'text'; + } + + return; +}; + +const checkForExistence = ( + options: Pick & { + headers: Headers; + }, + name?: string, +): boolean => { + if (!name) { + return false; + } + if ( + options.headers.has(name) || + options.query?.[name] || + options.headers.get('Cookie')?.includes(`${name}=`) + ) { + return true; + } + return false; +}; + +export const setAuthParams = async ({ + security, + ...options +}: Pick, 'security'> & + Pick & { + headers: Headers; + }) => { + for (const auth of security) { + if (checkForExistence(options, auth.name)) { + continue; + } + + const token = await getAuthToken(auth, options.auth); + + if (!token) { + continue; + } + + const name = auth.name ?? 'Authorization'; + + switch (auth.in) { + case 'query': + if (!options.query) { + options.query = {}; + } + options.query[name] = token; + break; + case 'cookie': + options.headers.append('Cookie', `${name}=${token}`); + break; + case 'header': + default: + options.headers.set(name, token); + break; + } + } +}; + +export const buildUrl: Client['buildUrl'] = (options) => + getUrl({ + baseUrl: options.baseUrl as string, + path: options.path, + query: options.query, + querySerializer: + typeof options.querySerializer === 'function' + ? options.querySerializer + : createQuerySerializer(options.querySerializer), + url: options.url, + }); + +export const mergeConfigs = (a: Config, b: Config): Config => { + const config = { ...a, ...b }; + if (config.baseUrl?.endsWith('/')) { + config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1); + } + config.headers = mergeHeaders(a.headers, b.headers); + return config; +}; + +const headersEntries = (headers: Headers): Array<[string, string]> => { + const entries: Array<[string, string]> = []; + headers.forEach((value, key) => { + entries.push([key, value]); + }); + return entries; +}; + +export const mergeHeaders = ( + ...headers: Array['headers'] | undefined> +): Headers => { + const mergedHeaders = new Headers(); + for (const header of headers) { + if (!header) { + continue; + } + + const iterator = + header instanceof Headers + ? headersEntries(header) + : Object.entries(header); + + for (const [key, value] of iterator) { + if (value === null) { + mergedHeaders.delete(key); + } else if (Array.isArray(value)) { + for (const v of value) { + mergedHeaders.append(key, v as string); + } + } else if (value !== undefined) { + // assume object headers are meant to be JSON stringified, i.e. their + // content value in OpenAPI specification is 'application/json' + mergedHeaders.set( + key, + typeof value === 'object' ? JSON.stringify(value) : (value as string), + ); + } + } + } + return mergedHeaders; +}; + +type ErrInterceptor = ( + error: Err, + response: Res, + request: Req, + options: Options, +) => Err | Promise; + +type ReqInterceptor = ( + request: Req, + options: Options, +) => Req | Promise; + +type ResInterceptor = ( + response: Res, + request: Req, + options: Options, +) => Res | Promise; + +class Interceptors { + fns: Array = []; + + clear(): void { + this.fns = []; + } + + eject(id: number | Interceptor): void { + const index = this.getInterceptorIndex(id); + if (this.fns[index]) { + this.fns[index] = null; + } + } + + exists(id: number | Interceptor): boolean { + const index = this.getInterceptorIndex(id); + return Boolean(this.fns[index]); + } + + getInterceptorIndex(id: number | Interceptor): number { + if (typeof id === 'number') { + return this.fns[id] ? id : -1; + } + return this.fns.indexOf(id); + } + + update( + id: number | Interceptor, + fn: Interceptor, + ): number | Interceptor | false { + const index = this.getInterceptorIndex(id); + if (this.fns[index]) { + this.fns[index] = fn; + return id; + } + return false; + } + + use(fn: Interceptor): number { + this.fns.push(fn); + return this.fns.length - 1; + } +} + +export interface Middleware { + error: Interceptors>; + request: Interceptors>; + response: Interceptors>; +} + +export const createInterceptors = (): Middleware< + Req, + Res, + Err, + Options +> => ({ + error: new Interceptors>(), + request: new Interceptors>(), + response: new Interceptors>(), +}); + +const defaultQuerySerializer = createQuerySerializer({ + allowReserved: false, + array: { + explode: true, + style: 'form', + }, + object: { + explode: true, + style: 'deepObject', + }, +}); + +const defaultHeaders = { + 'Content-Type': 'application/json', +}; + +export const createConfig = ( + override: Config & T> = {}, +): Config & T> => ({ + ...jsonBodySerializer, + headers: defaultHeaders, + parseAs: 'auto', + querySerializer: defaultQuerySerializer, + ...override, +}); diff --git a/src/clientsdk/core/auth.gen.ts b/src/clientsdk/core/auth.gen.ts new file mode 100644 index 0000000..f8a7326 --- /dev/null +++ b/src/clientsdk/core/auth.gen.ts @@ -0,0 +1,42 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type AuthToken = string | undefined; + +export interface Auth { + /** + * Which part of the request do we use to send the auth? + * + * @default 'header' + */ + in?: 'header' | 'query' | 'cookie'; + /** + * Header or query parameter name. + * + * @default 'Authorization' + */ + name?: string; + scheme?: 'basic' | 'bearer'; + type: 'apiKey' | 'http'; +} + +export const getAuthToken = async ( + auth: Auth, + callback: ((auth: Auth) => Promise | AuthToken) | AuthToken, +): Promise => { + const token = + typeof callback === 'function' ? await callback(auth) : callback; + + if (!token) { + return; + } + + if (auth.scheme === 'bearer') { + return `Bearer ${token}`; + } + + if (auth.scheme === 'basic') { + return `Basic ${btoa(token)}`; + } + + return token; +}; diff --git a/src/clientsdk/core/bodySerializer.gen.ts b/src/clientsdk/core/bodySerializer.gen.ts new file mode 100644 index 0000000..552b50f --- /dev/null +++ b/src/clientsdk/core/bodySerializer.gen.ts @@ -0,0 +1,100 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { + ArrayStyle, + ObjectStyle, + SerializerOptions, +} from './pathSerializer.gen'; + +export type QuerySerializer = (query: Record) => string; + +export type BodySerializer = (body: any) => any; + +type QuerySerializerOptionsObject = { + allowReserved?: boolean; + array?: Partial>; + object?: Partial>; +}; + +export type QuerySerializerOptions = QuerySerializerOptionsObject & { + /** + * Per-parameter serialization overrides. When provided, these settings + * override the global array/object settings for specific parameter names. + */ + parameters?: Record; +}; + +const serializeFormDataPair = ( + data: FormData, + key: string, + value: unknown, +): void => { + if (typeof value === 'string' || value instanceof Blob) { + data.append(key, value); + } else if (value instanceof Date) { + data.append(key, value.toISOString()); + } else { + data.append(key, JSON.stringify(value)); + } +}; + +const serializeUrlSearchParamsPair = ( + data: URLSearchParams, + key: string, + value: unknown, +): void => { + if (typeof value === 'string') { + data.append(key, value); + } else { + data.append(key, JSON.stringify(value)); + } +}; + +export const formDataBodySerializer = { + bodySerializer: | Array>>( + body: T, + ): FormData => { + const data = new FormData(); + + Object.entries(body).forEach(([key, value]) => { + if (value === undefined || value === null) { + return; + } + if (Array.isArray(value)) { + value.forEach((v) => serializeFormDataPair(data, key, v)); + } else { + serializeFormDataPair(data, key, value); + } + }); + + return data; + }, +}; + +export const jsonBodySerializer = { + bodySerializer: (body: T): string => + JSON.stringify(body, (_key, value) => + typeof value === 'bigint' ? value.toString() : value, + ), +}; + +export const urlSearchParamsBodySerializer = { + bodySerializer: | Array>>( + body: T, + ): string => { + const data = new URLSearchParams(); + + Object.entries(body).forEach(([key, value]) => { + if (value === undefined || value === null) { + return; + } + if (Array.isArray(value)) { + value.forEach((v) => serializeUrlSearchParamsPair(data, key, v)); + } else { + serializeUrlSearchParamsPair(data, key, value); + } + }); + + return data.toString(); + }, +}; diff --git a/src/clientsdk/core/params.gen.ts b/src/clientsdk/core/params.gen.ts new file mode 100644 index 0000000..602715c --- /dev/null +++ b/src/clientsdk/core/params.gen.ts @@ -0,0 +1,176 @@ +// This file is auto-generated by @hey-api/openapi-ts + +type Slot = 'body' | 'headers' | 'path' | 'query'; + +export type Field = + | { + in: Exclude; + /** + * Field name. This is the name we want the user to see and use. + */ + key: string; + /** + * Field mapped name. This is the name we want to use in the request. + * If omitted, we use the same value as `key`. + */ + map?: string; + } + | { + in: Extract; + /** + * Key isn't required for bodies. + */ + key?: string; + map?: string; + } + | { + /** + * Field name. This is the name we want the user to see and use. + */ + key: string; + /** + * Field mapped name. This is the name we want to use in the request. + * If `in` is omitted, `map` aliases `key` to the transport layer. + */ + map: Slot; + }; + +export interface Fields { + allowExtra?: Partial>; + args?: ReadonlyArray; +} + +export type FieldsConfig = ReadonlyArray; + +const extraPrefixesMap: Record = { + $body_: 'body', + $headers_: 'headers', + $path_: 'path', + $query_: 'query', +}; +const extraPrefixes = Object.entries(extraPrefixesMap); + +type KeyMap = Map< + string, + | { + in: Slot; + map?: string; + } + | { + in?: never; + map: Slot; + } +>; + +const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => { + if (!map) { + map = new Map(); + } + + for (const config of fields) { + if ('in' in config) { + if (config.key) { + map.set(config.key, { + in: config.in, + map: config.map, + }); + } + } else if ('key' in config) { + map.set(config.key, { + map: config.map, + }); + } else if (config.args) { + buildKeyMap(config.args, map); + } + } + + return map; +}; + +interface Params { + body: unknown; + headers: Record; + path: Record; + query: Record; +} + +const stripEmptySlots = (params: Params) => { + for (const [slot, value] of Object.entries(params)) { + if (value && typeof value === 'object' && !Object.keys(value).length) { + delete params[slot as Slot]; + } + } +}; + +export const buildClientParams = ( + args: ReadonlyArray, + fields: FieldsConfig, +) => { + const params: Params = { + body: {}, + headers: {}, + path: {}, + query: {}, + }; + + const map = buildKeyMap(fields); + + let config: FieldsConfig[number] | undefined; + + for (const [index, arg] of args.entries()) { + if (fields[index]) { + config = fields[index]; + } + + if (!config) { + continue; + } + + if ('in' in config) { + if (config.key) { + const field = map.get(config.key)!; + const name = field.map || config.key; + if (field.in) { + (params[field.in] as Record)[name] = arg; + } + } else { + params.body = arg; + } + } else { + for (const [key, value] of Object.entries(arg ?? {})) { + const field = map.get(key); + + if (field) { + if (field.in) { + const name = field.map || key; + (params[field.in] as Record)[name] = value; + } else { + params[field.map] = value; + } + } else { + const extra = extraPrefixes.find(([prefix]) => + key.startsWith(prefix), + ); + + if (extra) { + const [prefix, slot] = extra; + (params[slot] as Record)[ + key.slice(prefix.length) + ] = value; + } else if ('allowExtra' in config && config.allowExtra) { + for (const [slot, allowed] of Object.entries(config.allowExtra)) { + if (allowed) { + (params[slot as Slot] as Record)[key] = value; + break; + } + } + } + } + } + } + } + + stripEmptySlots(params); + + return params; +}; diff --git a/src/clientsdk/core/pathSerializer.gen.ts b/src/clientsdk/core/pathSerializer.gen.ts new file mode 100644 index 0000000..8d99931 --- /dev/null +++ b/src/clientsdk/core/pathSerializer.gen.ts @@ -0,0 +1,181 @@ +// This file is auto-generated by @hey-api/openapi-ts + +interface SerializeOptions + extends SerializePrimitiveOptions, + SerializerOptions {} + +interface SerializePrimitiveOptions { + allowReserved?: boolean; + name: string; +} + +export interface SerializerOptions { + /** + * @default true + */ + explode: boolean; + style: T; +} + +export type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited'; +export type ArraySeparatorStyle = ArrayStyle | MatrixStyle; +type MatrixStyle = 'label' | 'matrix' | 'simple'; +export type ObjectStyle = 'form' | 'deepObject'; +type ObjectSeparatorStyle = ObjectStyle | MatrixStyle; + +interface SerializePrimitiveParam extends SerializePrimitiveOptions { + value: string; +} + +export const separatorArrayExplode = (style: ArraySeparatorStyle) => { + switch (style) { + case 'label': + return '.'; + case 'matrix': + return ';'; + case 'simple': + return ','; + default: + return '&'; + } +}; + +export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => { + switch (style) { + case 'form': + return ','; + case 'pipeDelimited': + return '|'; + case 'spaceDelimited': + return '%20'; + default: + return ','; + } +}; + +export const separatorObjectExplode = (style: ObjectSeparatorStyle) => { + switch (style) { + case 'label': + return '.'; + case 'matrix': + return ';'; + case 'simple': + return ','; + default: + return '&'; + } +}; + +export const serializeArrayParam = ({ + allowReserved, + explode, + name, + style, + value, +}: SerializeOptions & { + value: unknown[]; +}) => { + if (!explode) { + const joinedValues = ( + allowReserved ? value : value.map((v) => encodeURIComponent(v as string)) + ).join(separatorArrayNoExplode(style)); + switch (style) { + case 'label': + return `.${joinedValues}`; + case 'matrix': + return `;${name}=${joinedValues}`; + case 'simple': + return joinedValues; + default: + return `${name}=${joinedValues}`; + } + } + + const separator = separatorArrayExplode(style); + const joinedValues = value + .map((v) => { + if (style === 'label' || style === 'simple') { + return allowReserved ? v : encodeURIComponent(v as string); + } + + return serializePrimitiveParam({ + allowReserved, + name, + value: v as string, + }); + }) + .join(separator); + return style === 'label' || style === 'matrix' + ? separator + joinedValues + : joinedValues; +}; + +export const serializePrimitiveParam = ({ + allowReserved, + name, + value, +}: SerializePrimitiveParam) => { + if (value === undefined || value === null) { + return ''; + } + + if (typeof value === 'object') { + throw new Error( + 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.', + ); + } + + return `${name}=${allowReserved ? value : encodeURIComponent(value)}`; +}; + +export const serializeObjectParam = ({ + allowReserved, + explode, + name, + style, + value, + valueOnly, +}: SerializeOptions & { + value: Record | Date; + valueOnly?: boolean; +}) => { + if (value instanceof Date) { + return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`; + } + + if (style !== 'deepObject' && !explode) { + let values: string[] = []; + Object.entries(value).forEach(([key, v]) => { + values = [ + ...values, + key, + allowReserved ? (v as string) : encodeURIComponent(v as string), + ]; + }); + const joinedValues = values.join(','); + switch (style) { + case 'form': + return `${name}=${joinedValues}`; + case 'label': + return `.${joinedValues}`; + case 'matrix': + return `;${name}=${joinedValues}`; + default: + return joinedValues; + } + } + + const separator = separatorObjectExplode(style); + const joinedValues = Object.entries(value) + .map(([key, v]) => + serializePrimitiveParam({ + allowReserved, + name: style === 'deepObject' ? `${name}[${key}]` : key, + value: v as string, + }), + ) + .join(separator); + return style === 'label' || style === 'matrix' + ? separator + joinedValues + : joinedValues; +}; diff --git a/src/clientsdk/core/queryKeySerializer.gen.ts b/src/clientsdk/core/queryKeySerializer.gen.ts new file mode 100644 index 0000000..d3bb683 --- /dev/null +++ b/src/clientsdk/core/queryKeySerializer.gen.ts @@ -0,0 +1,136 @@ +// This file is auto-generated by @hey-api/openapi-ts + +/** + * JSON-friendly union that mirrors what Pinia Colada can hash. + */ +export type JsonValue = + | null + | string + | number + | boolean + | JsonValue[] + | { [key: string]: JsonValue }; + +/** + * Replacer that converts non-JSON values (bigint, Date, etc.) to safe substitutes. + */ +export const queryKeyJsonReplacer = (_key: string, value: unknown) => { + if ( + value === undefined || + typeof value === 'function' || + typeof value === 'symbol' + ) { + return undefined; + } + if (typeof value === 'bigint') { + return value.toString(); + } + if (value instanceof Date) { + return value.toISOString(); + } + return value; +}; + +/** + * Safely stringifies a value and parses it back into a JsonValue. + */ +export const stringifyToJsonValue = (input: unknown): JsonValue | undefined => { + try { + const json = JSON.stringify(input, queryKeyJsonReplacer); + if (json === undefined) { + return undefined; + } + return JSON.parse(json) as JsonValue; + } catch { + return undefined; + } +}; + +/** + * Detects plain objects (including objects with a null prototype). + */ +const isPlainObject = (value: unknown): value is Record => { + if (value === null || typeof value !== 'object') { + return false; + } + const prototype = Object.getPrototypeOf(value as object); + return prototype === Object.prototype || prototype === null; +}; + +/** + * Turns URLSearchParams into a sorted JSON object for deterministic keys. + */ +const serializeSearchParams = (params: URLSearchParams): JsonValue => { + const entries = Array.from(params.entries()).sort(([a], [b]) => + a.localeCompare(b), + ); + const result: Record = {}; + + for (const [key, value] of entries) { + const existing = result[key]; + if (existing === undefined) { + result[key] = value; + continue; + } + + if (Array.isArray(existing)) { + (existing as string[]).push(value); + } else { + result[key] = [existing, value]; + } + } + + return result; +}; + +/** + * Normalizes any accepted value into a JSON-friendly shape for query keys. + */ +export const serializeQueryKeyValue = ( + value: unknown, +): JsonValue | undefined => { + if (value === null) { + return null; + } + + if ( + typeof value === 'string' || + typeof value === 'number' || + typeof value === 'boolean' + ) { + return value; + } + + if ( + value === undefined || + typeof value === 'function' || + typeof value === 'symbol' + ) { + return undefined; + } + + if (typeof value === 'bigint') { + return value.toString(); + } + + if (value instanceof Date) { + return value.toISOString(); + } + + if (Array.isArray(value)) { + return stringifyToJsonValue(value); + } + + if ( + typeof URLSearchParams !== 'undefined' && + value instanceof URLSearchParams + ) { + return serializeSearchParams(value); + } + + if (isPlainObject(value)) { + return stringifyToJsonValue(value); + } + + return undefined; +}; diff --git a/src/clientsdk/core/serverSentEvents.gen.ts b/src/clientsdk/core/serverSentEvents.gen.ts new file mode 100644 index 0000000..343d25a --- /dev/null +++ b/src/clientsdk/core/serverSentEvents.gen.ts @@ -0,0 +1,266 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Config } from './types.gen'; + +export type ServerSentEventsOptions = Omit< + RequestInit, + 'method' +> & + Pick & { + /** + * Fetch API implementation. You can use this option to provide a custom + * fetch instance. + * + * @default globalThis.fetch + */ + fetch?: typeof fetch; + /** + * Implementing clients can call request interceptors inside this hook. + */ + onRequest?: (url: string, init: RequestInit) => Promise; + /** + * Callback invoked when a network or parsing error occurs during streaming. + * + * This option applies only if the endpoint returns a stream of events. + * + * @param error The error that occurred. + */ + onSseError?: (error: unknown) => void; + /** + * Callback invoked when an event is streamed from the server. + * + * This option applies only if the endpoint returns a stream of events. + * + * @param event Event streamed from the server. + * @returns Nothing (void). + */ + onSseEvent?: (event: StreamEvent) => void; + serializedBody?: RequestInit['body']; + /** + * Default retry delay in milliseconds. + * + * This option applies only if the endpoint returns a stream of events. + * + * @default 3000 + */ + sseDefaultRetryDelay?: number; + /** + * Maximum number of retry attempts before giving up. + */ + sseMaxRetryAttempts?: number; + /** + * Maximum retry delay in milliseconds. + * + * Applies only when exponential backoff is used. + * + * This option applies only if the endpoint returns a stream of events. + * + * @default 30000 + */ + sseMaxRetryDelay?: number; + /** + * Optional sleep function for retry backoff. + * + * Defaults to using `setTimeout`. + */ + sseSleepFn?: (ms: number) => Promise; + url: string; + }; + +export interface StreamEvent { + data: TData; + event?: string; + id?: string; + retry?: number; +} + +export type ServerSentEventsResult< + TData = unknown, + TReturn = void, + TNext = unknown, +> = { + stream: AsyncGenerator< + TData extends Record ? TData[keyof TData] : TData, + TReturn, + TNext + >; +}; + +export const createSseClient = ({ + onRequest, + onSseError, + onSseEvent, + responseTransformer, + responseValidator, + sseDefaultRetryDelay, + sseMaxRetryAttempts, + sseMaxRetryDelay, + sseSleepFn, + url, + ...options +}: ServerSentEventsOptions): ServerSentEventsResult => { + let lastEventId: string | undefined; + + const sleep = + sseSleepFn ?? + ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms))); + + const createStream = async function* () { + let retryDelay: number = sseDefaultRetryDelay ?? 3000; + let attempt = 0; + const signal = options.signal ?? new AbortController().signal; + + while (true) { + if (signal.aborted) break; + + attempt++; + + const headers = + options.headers instanceof Headers + ? options.headers + : new Headers(options.headers as Record | undefined); + + if (lastEventId !== undefined) { + headers.set('Last-Event-ID', lastEventId); + } + + try { + const requestInit: RequestInit = { + redirect: 'follow', + ...options, + body: options.serializedBody, + headers, + signal, + }; + let request = new Request(url, requestInit); + if (onRequest) { + request = await onRequest(url, requestInit); + } + // fetch must be assigned here, otherwise it would throw the error: + // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation + const _fetch = options.fetch ?? globalThis.fetch; + const response = await _fetch(request); + + if (!response.ok) + throw new Error( + `SSE failed: ${response.status} ${response.statusText}`, + ); + + if (!response.body) throw new Error('No body in SSE response'); + + const reader = response.body + .pipeThrough(new TextDecoderStream()) + .getReader(); + + let buffer = ''; + + const abortHandler = () => { + try { + reader.cancel(); + } catch { + // noop + } + }; + + signal.addEventListener('abort', abortHandler); + + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + buffer += value; + // Normalize line endings: CRLF -> LF, then CR -> LF + buffer = buffer.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); + + const chunks = buffer.split('\n\n'); + buffer = chunks.pop() ?? ''; + + for (const chunk of chunks) { + const lines = chunk.split('\n'); + const dataLines: Array = []; + let eventName: string | undefined; + + for (const line of lines) { + if (line.startsWith('data:')) { + dataLines.push(line.replace(/^data:\s*/, '')); + } else if (line.startsWith('event:')) { + eventName = line.replace(/^event:\s*/, ''); + } else if (line.startsWith('id:')) { + lastEventId = line.replace(/^id:\s*/, ''); + } else if (line.startsWith('retry:')) { + const parsed = Number.parseInt( + line.replace(/^retry:\s*/, ''), + 10, + ); + if (!Number.isNaN(parsed)) { + retryDelay = parsed; + } + } + } + + let data: unknown; + let parsedJson = false; + + if (dataLines.length) { + const rawData = dataLines.join('\n'); + try { + data = JSON.parse(rawData); + parsedJson = true; + } catch { + data = rawData; + } + } + + if (parsedJson) { + if (responseValidator) { + await responseValidator(data); + } + + if (responseTransformer) { + data = await responseTransformer(data); + } + } + + onSseEvent?.({ + data, + event: eventName, + id: lastEventId, + retry: retryDelay, + }); + + if (dataLines.length) { + yield data as any; + } + } + } + } finally { + signal.removeEventListener('abort', abortHandler); + reader.releaseLock(); + } + + break; // exit loop on normal completion + } catch (error) { + // connection failed or aborted; retry after delay + onSseError?.(error); + + if ( + sseMaxRetryAttempts !== undefined && + attempt >= sseMaxRetryAttempts + ) { + break; // stop after firing error + } + + // exponential backoff: double retry each attempt, cap at 30s + const backoff = Math.min( + retryDelay * 2 ** (attempt - 1), + sseMaxRetryDelay ?? 30000, + ); + await sleep(backoff); + } + } + }; + + const stream = createStream(); + + return { stream }; +}; diff --git a/src/clientsdk/core/types.gen.ts b/src/clientsdk/core/types.gen.ts new file mode 100644 index 0000000..643c070 --- /dev/null +++ b/src/clientsdk/core/types.gen.ts @@ -0,0 +1,118 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Auth, AuthToken } from './auth.gen'; +import type { + BodySerializer, + QuerySerializer, + QuerySerializerOptions, +} from './bodySerializer.gen'; + +export type HttpMethod = + | 'connect' + | 'delete' + | 'get' + | 'head' + | 'options' + | 'patch' + | 'post' + | 'put' + | 'trace'; + +export type Client< + RequestFn = never, + Config = unknown, + MethodFn = never, + BuildUrlFn = never, + SseFn = never, +> = { + /** + * Returns the final request URL. + */ + buildUrl: BuildUrlFn; + getConfig: () => Config; + request: RequestFn; + setConfig: (config: Config) => Config; +} & { + [K in HttpMethod]: MethodFn; +} & ([SseFn] extends [never] + ? { sse?: never } + : { sse: { [K in HttpMethod]: SseFn } }); + +export interface Config { + /** + * Auth token or a function returning auth token. The resolved value will be + * added to the request payload as defined by its `security` array. + */ + auth?: ((auth: Auth) => Promise | AuthToken) | AuthToken; + /** + * A function for serializing request body parameter. By default, + * {@link JSON.stringify()} will be used. + */ + bodySerializer?: BodySerializer | null; + /** + * An object containing any HTTP headers that you want to pre-populate your + * `Headers` object with. + * + * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more} + */ + headers?: + | RequestInit['headers'] + | Record< + string, + | string + | number + | boolean + | (string | number | boolean)[] + | null + | undefined + | unknown + >; + /** + * The request method. + * + * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more} + */ + method?: Uppercase; + /** + * A function for serializing request query parameters. By default, arrays + * will be exploded in form style, objects will be exploded in deepObject + * style, and reserved characters are percent-encoded. + * + * This method will have no effect if the native `paramsSerializer()` Axios + * API function is used. + * + * {@link https://swagger.io/docs/specification/serialization/#query View examples} + */ + querySerializer?: QuerySerializer | QuerySerializerOptions; + /** + * A function validating request data. This is useful if you want to ensure + * the request conforms to the desired shape, so it can be safely sent to + * the server. + */ + requestValidator?: (data: unknown) => Promise; + /** + * A function transforming response data before it's returned. This is useful + * for post-processing data, e.g. converting ISO strings into Date objects. + */ + responseTransformer?: (data: unknown) => Promise; + /** + * A function validating response data. This is useful if you want to ensure + * the response conforms to the desired shape, so it can be safely passed to + * the transformers and returned to the user. + */ + responseValidator?: (data: unknown) => Promise; +} + +type IsExactlyNeverOrNeverUndefined = [T] extends [never] + ? true + : [T] extends [never | undefined] + ? [undefined] extends [T] + ? false + : true + : false; + +export type OmitNever> = { + [K in keyof T as IsExactlyNeverOrNeverUndefined extends true + ? never + : K]: T[K]; +}; diff --git a/src/clientsdk/core/utils.gen.ts b/src/clientsdk/core/utils.gen.ts new file mode 100644 index 0000000..0b5389d --- /dev/null +++ b/src/clientsdk/core/utils.gen.ts @@ -0,0 +1,143 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { BodySerializer, QuerySerializer } from './bodySerializer.gen'; +import { + type ArraySeparatorStyle, + serializeArrayParam, + serializeObjectParam, + serializePrimitiveParam, +} from './pathSerializer.gen'; + +export interface PathSerializer { + path: Record; + url: string; +} + +export const PATH_PARAM_RE = /\{[^{}]+\}/g; + +export const defaultPathSerializer = ({ path, url: _url }: PathSerializer) => { + let url = _url; + const matches = _url.match(PATH_PARAM_RE); + if (matches) { + for (const match of matches) { + let explode = false; + let name = match.substring(1, match.length - 1); + let style: ArraySeparatorStyle = 'simple'; + + if (name.endsWith('*')) { + explode = true; + name = name.substring(0, name.length - 1); + } + + if (name.startsWith('.')) { + name = name.substring(1); + style = 'label'; + } else if (name.startsWith(';')) { + name = name.substring(1); + style = 'matrix'; + } + + const value = path[name]; + + if (value === undefined || value === null) { + continue; + } + + if (Array.isArray(value)) { + url = url.replace( + match, + serializeArrayParam({ explode, name, style, value }), + ); + continue; + } + + if (typeof value === 'object') { + url = url.replace( + match, + serializeObjectParam({ + explode, + name, + style, + value: value as Record, + valueOnly: true, + }), + ); + continue; + } + + if (style === 'matrix') { + url = url.replace( + match, + `;${serializePrimitiveParam({ + name, + value: value as string, + })}`, + ); + continue; + } + + const replaceValue = encodeURIComponent( + style === 'label' ? `.${value as string}` : (value as string), + ); + url = url.replace(match, replaceValue); + } + } + return url; +}; + +export const getUrl = ({ + baseUrl, + path, + query, + querySerializer, + url: _url, +}: { + baseUrl?: string; + path?: Record; + query?: Record; + querySerializer: QuerySerializer; + url: string; +}) => { + const pathUrl = _url.startsWith('/') ? _url : `/${_url}`; + let url = (baseUrl ?? '') + pathUrl; + if (path) { + url = defaultPathSerializer({ path, url }); + } + let search = query ? querySerializer(query) : ''; + if (search.startsWith('?')) { + search = search.substring(1); + } + if (search) { + url += `?${search}`; + } + return url; +}; + +export function getValidRequestBody(options: { + body?: unknown; + bodySerializer?: BodySerializer | null; + serializedBody?: unknown; +}) { + const hasBody = options.body !== undefined; + const isSerializedBody = hasBody && options.bodySerializer; + + if (isSerializedBody) { + if ('serializedBody' in options) { + const hasSerializedBody = + options.serializedBody !== undefined && options.serializedBody !== ''; + + return hasSerializedBody ? options.serializedBody : null; + } + + // not all clients implement a serializedBody property (i.e. client-axios) + return options.body !== '' ? options.body : null; + } + + // plain/text body + if (hasBody) { + return options.body; + } + + // no body was provided + return undefined; +} diff --git a/src/clientsdk/index.ts b/src/clientsdk/index.ts new file mode 100644 index 0000000..e7c8690 --- /dev/null +++ b/src/clientsdk/index.ts @@ -0,0 +1,4 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export { Categories, Folders, Forms, FormSubmissions, type Options, Pages, PayloadJobs, PayloadKvs, PayloadLockedDocuments, PayloadMigrations, PayloadPreferences, Posts, Redirects, SearchResults, Tenants, Users } from './sdk.gen'; +export { type Category, type CategoryPatchRequestBody, type CategoryQueryOperations, type CategoryQueryOperationsAnd, type CategoryQueryOperationsOr, type CategoryRequestBody, type ClientOptions, type CreateCategoryData, type CreateCategoryResponse, type CreateCategoryResponses, type CreateFolderData, type CreateFolderResponse, type CreateFolderResponses, type CreateFormData, type CreateFormResponse, type CreateFormResponses, type CreateFormSubmissionData, type CreateFormSubmissionResponse, type CreateFormSubmissionResponses, type CreateMediaData, type CreateMediaResponse, type CreateMediaResponses, type CreatePageData, type CreatePageResponse, type CreatePageResponses, type CreatePayloadJobData, type CreatePayloadJobResponse, type CreatePayloadJobResponses, type CreatePayloadKvData, type CreatePayloadKvResponse, type CreatePayloadKvResponses, type CreatePayloadLockedDocumentData, type CreatePayloadLockedDocumentResponse, type CreatePayloadLockedDocumentResponses, type CreatePayloadMigrationData, type CreatePayloadMigrationResponse, type CreatePayloadMigrationResponses, type CreatePayloadPreferenceData, type CreatePayloadPreferenceResponse, type CreatePayloadPreferenceResponses, type CreatePostData, type CreatePostResponse, type CreatePostResponses, type CreateRedirectData, type CreateRedirectResponse, type CreateRedirectResponses, type CreateSearchResultData, type CreateSearchResultResponse, type CreateSearchResultResponses, type CreateTenantData, type CreateTenantResponse, type CreateTenantResponses, type CreateUserData, type CreateUserResponse, type CreateUserResponses, type DeleteCategoryData, type DeleteCategoryErrors, type DeleteCategoryResponse, type DeleteCategoryResponses, type DeleteFolderData, type DeleteFolderErrors, type DeleteFolderResponse, type DeleteFolderResponses, type DeleteFormData, type DeleteFormErrors, type DeleteFormResponse, type DeleteFormResponses, type DeleteFormSubmissionData, type DeleteFormSubmissionErrors, type DeleteFormSubmissionResponse, type DeleteFormSubmissionResponses, type DeleteMediaData, type DeleteMediaErrors, type DeleteMediaResponse, type DeleteMediaResponses, type DeletePageData, type DeletePageErrors, type DeletePageResponse, type DeletePageResponses, type DeletePayloadJobData, type DeletePayloadJobErrors, type DeletePayloadJobResponse, type DeletePayloadJobResponses, type DeletePayloadKvData, type DeletePayloadKvErrors, type DeletePayloadKvResponse, type DeletePayloadKvResponses, type DeletePayloadLockedDocumentData, type DeletePayloadLockedDocumentErrors, type DeletePayloadLockedDocumentResponse, type DeletePayloadLockedDocumentResponses, type DeletePayloadMigrationData, type DeletePayloadMigrationErrors, type DeletePayloadMigrationResponse, type DeletePayloadMigrationResponses, type DeletePayloadPreferenceData, type DeletePayloadPreferenceErrors, type DeletePayloadPreferenceResponse, type DeletePayloadPreferenceResponses, type DeletePostData, type DeletePostErrors, type DeletePostResponse, type DeletePostResponses, type DeleteRedirectData, type DeleteRedirectErrors, type DeleteRedirectResponse, type DeleteRedirectResponses, type DeleteSearchResultData, type DeleteSearchResultErrors, type DeleteSearchResultResponse, type DeleteSearchResultResponses, type DeleteTenantData, type DeleteTenantErrors, type DeleteTenantResponse, type DeleteTenantResponses, type DeleteUserData, type DeleteUserErrors, type DeleteUserResponse, type DeleteUserResponses, type FindCategoryByIdData, type FindCategoryByIdErrors, type FindCategoryByIdResponse, type FindCategoryByIdResponses, type FindFolderByIdData, type FindFolderByIdErrors, type FindFolderByIdResponse, type FindFolderByIdResponses, type FindFormByIdData, type FindFormByIdErrors, type FindFormByIdResponse, type FindFormByIdResponses, type FindFormSubmissionByIdData, type FindFormSubmissionByIdErrors, type FindFormSubmissionByIdResponse, type FindFormSubmissionByIdResponses, type FindMediaByIdData, type FindMediaByIdErrors, type FindMediaByIdResponse, type FindMediaByIdResponses, type FindPageByIdData, type FindPageByIdErrors, type FindPageByIdResponse, type FindPageByIdResponses, type FindPayloadJobByIdData, type FindPayloadJobByIdErrors, type FindPayloadJobByIdResponse, type FindPayloadJobByIdResponses, type FindPayloadKvByIdData, type FindPayloadKvByIdErrors, type FindPayloadKvByIdResponse, type FindPayloadKvByIdResponses, type FindPayloadLockedDocumentByIdData, type FindPayloadLockedDocumentByIdErrors, type FindPayloadLockedDocumentByIdResponse, type FindPayloadLockedDocumentByIdResponses, type FindPayloadMigrationByIdData, type FindPayloadMigrationByIdErrors, type FindPayloadMigrationByIdResponse, type FindPayloadMigrationByIdResponses, type FindPayloadPreferenceByIdData, type FindPayloadPreferenceByIdErrors, type FindPayloadPreferenceByIdResponse, type FindPayloadPreferenceByIdResponses, type FindPostByIdData, type FindPostByIdErrors, type FindPostByIdResponse, type FindPostByIdResponses, type FindRedirectByIdData, type FindRedirectByIdErrors, type FindRedirectByIdResponse, type FindRedirectByIdResponses, type FindSearchResultByIdData, type FindSearchResultByIdErrors, type FindSearchResultByIdResponse, type FindSearchResultByIdResponses, type FindTenantByIdData, type FindTenantByIdErrors, type FindTenantByIdResponse, type FindTenantByIdResponses, type FindUserByIdData, type FindUserByIdErrors, type FindUserByIdResponse, type FindUserByIdResponses, type Folder, type FolderPatchRequestBody, type FolderQueryOperations, type FolderQueryOperationsAnd, type FolderQueryOperationsOr, type FolderRequestBody, Footer, type FooterRead, type FooterRequestBody, type FooterWrite, type Form, type FormPatchRequestBody, type FormQueryOperations, type FormQueryOperationsAnd, type FormQueryOperationsOr, type FormRequestBody, type FormSubmission, type FormSubmissionPatchRequestBody, type FormSubmissionQueryOperations, type FormSubmissionQueryOperationsAnd, type FormSubmissionQueryOperationsOr, type FormSubmissionRequestBody, type GetApiGlobalsFooterData, type GetApiGlobalsFooterResponse, type GetApiGlobalsFooterResponses, type GetApiGlobalsHeaderData, type GetApiGlobalsHeaderResponse, type GetApiGlobalsHeaderResponses, Header, type HeaderRead, type HeaderRequestBody, type HeaderWrite, type ListCategoriesData, type ListCategoriesResponse, type ListCategoriesResponses, type ListFoldersData, type ListFoldersResponse, type ListFoldersResponses, type ListFormsData, type ListFormsResponse, type ListFormsResponses, type ListFormSubmissionsData, type ListFormSubmissionsResponse, type ListFormSubmissionsResponses, type ListMediaData, type ListMediaResponse, type ListMediaResponses, type ListPagesData, type ListPagesResponse, type ListPagesResponses, type ListPayloadJobsData, type ListPayloadJobsResponse, type ListPayloadJobsResponses, type ListPayloadKvsData, type ListPayloadKvsResponse, type ListPayloadKvsResponses, type ListPayloadLockedDocumentsData, type ListPayloadLockedDocumentsResponse, type ListPayloadLockedDocumentsResponses, type ListPayloadMigrationsData, type ListPayloadMigrationsResponse, type ListPayloadMigrationsResponses, type ListPayloadPreferencesData, type ListPayloadPreferencesResponse, type ListPayloadPreferencesResponses, type ListPostsData, type ListPostsResponse, type ListPostsResponses, type ListRedirectsData, type ListRedirectsResponse, type ListRedirectsResponses, type ListSearchResultsData, type ListSearchResultsResponse, type ListSearchResultsResponses, type ListTenantsData, type ListTenantsResponse, type ListTenantsResponses, type ListUsersData, type ListUsersResponse, type ListUsersResponses, Media, type MediaPatchRequestBody, type MediaQueryOperations, type MediaQueryOperationsAnd, type MediaQueryOperationsOr, type MediaRequestBody, type Page, type PagePatchRequestBody, type PageQueryOperations, type PageQueryOperationsAnd, type PageQueryOperationsOr, type PageRequestBody, type PayloadJob, type PayloadJobPatchRequestBody, type PayloadJobQueryOperations, type PayloadJobQueryOperationsAnd, type PayloadJobQueryOperationsOr, type PayloadJobRequestBody, type PayloadKv, type PayloadKvPatchRequestBody, type PayloadKvQueryOperations, type PayloadKvQueryOperationsAnd, type PayloadKvQueryOperationsOr, type PayloadKvRequestBody, type PayloadLockedDocument, type PayloadLockedDocumentPatchRequestBody, type PayloadLockedDocumentQueryOperations, type PayloadLockedDocumentQueryOperationsAnd, type PayloadLockedDocumentQueryOperationsOr, type PayloadLockedDocumentRequestBody, type PayloadMigration, type PayloadMigrationPatchRequestBody, type PayloadMigrationQueryOperations, type PayloadMigrationQueryOperationsAnd, type PayloadMigrationQueryOperationsOr, type PayloadMigrationRequestBody, type PayloadPreference, type PayloadPreferencePatchRequestBody, type PayloadPreferenceQueryOperations, type PayloadPreferenceQueryOperationsAnd, type PayloadPreferenceQueryOperationsOr, type PayloadPreferenceRequestBody, type Post, type PostApiGlobalsFooterData, type PostApiGlobalsFooterResponse, type PostApiGlobalsFooterResponses, type PostApiGlobalsHeaderData, type PostApiGlobalsHeaderResponse, type PostApiGlobalsHeaderResponses, type PostPatchRequestBody, type PostQueryOperations, type PostQueryOperationsAnd, type PostQueryOperationsOr, type PostRequestBody, type Redirect, type RedirectPatchRequestBody, type RedirectQueryOperations, type RedirectQueryOperationsAnd, type RedirectQueryOperationsOr, type RedirectRequestBody, type SearchResult, type SearchResultPatchRequestBody, type SearchResultQueryOperations, type SearchResultQueryOperationsAnd, type SearchResultQueryOperationsOr, type SearchResultRequestBody, type SupportedTimezones, type Tenant, type TenantPatchRequestBody, type TenantQueryOperations, type TenantQueryOperationsAnd, type TenantQueryOperationsOr, type TenantRequestBody, type UpdateCategoryData, type UpdateCategoryErrors, type UpdateCategoryResponse, type UpdateCategoryResponses, type UpdateFolderData, type UpdateFolderErrors, type UpdateFolderResponse, type UpdateFolderResponses, type UpdateFormData, type UpdateFormErrors, type UpdateFormResponse, type UpdateFormResponses, type UpdateFormSubmissionData, type UpdateFormSubmissionErrors, type UpdateFormSubmissionResponse, type UpdateFormSubmissionResponses, type UpdateMediaData, type UpdateMediaErrors, type UpdateMediaResponse, type UpdateMediaResponses, type UpdatePageData, type UpdatePageErrors, type UpdatePageResponse, type UpdatePageResponses, type UpdatePayloadJobData, type UpdatePayloadJobErrors, type UpdatePayloadJobResponse, type UpdatePayloadJobResponses, type UpdatePayloadKvData, type UpdatePayloadKvErrors, type UpdatePayloadKvResponse, type UpdatePayloadKvResponses, type UpdatePayloadLockedDocumentData, type UpdatePayloadLockedDocumentErrors, type UpdatePayloadLockedDocumentResponse, type UpdatePayloadLockedDocumentResponses, type UpdatePayloadMigrationData, type UpdatePayloadMigrationErrors, type UpdatePayloadMigrationResponse, type UpdatePayloadMigrationResponses, type UpdatePayloadPreferenceData, type UpdatePayloadPreferenceErrors, type UpdatePayloadPreferenceResponse, type UpdatePayloadPreferenceResponses, type UpdatePostData, type UpdatePostErrors, type UpdatePostResponse, type UpdatePostResponses, type UpdateRedirectData, type UpdateRedirectErrors, type UpdateRedirectResponse, type UpdateRedirectResponses, type UpdateSearchResultData, type UpdateSearchResultErrors, type UpdateSearchResultResponse, type UpdateSearchResultResponses, type UpdateTenantData, type UpdateTenantErrors, type UpdateTenantResponse, type UpdateTenantResponses, type UpdateUserData, type UpdateUserErrors, type UpdateUserResponse, type UpdateUserResponses, type User, type UserPatchRequestBody, type UserQueryOperations, type UserQueryOperationsAnd, type UserQueryOperationsOr, type UserRequestBody } from './types.gen'; diff --git a/src/clientsdk/querySerializer.ts b/src/clientsdk/querySerializer.ts new file mode 100644 index 0000000..b938868 --- /dev/null +++ b/src/clientsdk/querySerializer.ts @@ -0,0 +1,28 @@ +export const customQuerySerializer = (queryParams: any) => { + const search: string[] = []; + + const serialize = (name: string, value: any) => { + if (value === undefined || value === null) return; + + if (Array.isArray(value)) { + value.forEach((v, i) => { + serialize(`${name}[${i}]`, v); + }); + } else if (typeof value === 'object' && value !== null && !(value instanceof Date)) { + Object.entries(value).forEach(([key, v]) => { + serialize(`${name}[${key}]`, v); + }); + } else { + const val = value instanceof Date ? value.toISOString() : String(value); + search.push(`${encodeURIComponent(name)}=${encodeURIComponent(val)}`); + } + }; + + if (queryParams && typeof queryParams === 'object') { + for (const key in queryParams) { + serialize(key, queryParams[key]); + } + } + + return search.join('&'); +}; diff --git a/src/clientsdk/sdk.gen.ts b/src/clientsdk/sdk.gen.ts new file mode 100644 index 0000000..d3d199f --- /dev/null +++ b/src/clientsdk/sdk.gen.ts @@ -0,0 +1,1098 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import type { Client, Options as Options2, TDataShape } from './client'; +import { client } from './client.gen'; +import type { CreateCategoryData, CreateCategoryResponses, CreateFolderData, CreateFolderResponses, CreateFormData, CreateFormResponses, CreateFormSubmissionData, CreateFormSubmissionResponses, CreateMediaData, CreateMediaResponses, CreatePageData, CreatePageResponses, CreatePayloadJobData, CreatePayloadJobResponses, CreatePayloadKvData, CreatePayloadKvResponses, CreatePayloadLockedDocumentData, CreatePayloadLockedDocumentResponses, CreatePayloadMigrationData, CreatePayloadMigrationResponses, CreatePayloadPreferenceData, CreatePayloadPreferenceResponses, CreatePostData, CreatePostResponses, CreateRedirectData, CreateRedirectResponses, CreateSearchResultData, CreateSearchResultResponses, CreateTenantData, CreateTenantResponses, CreateUserData, CreateUserResponses, DeleteCategoryData, DeleteCategoryErrors, DeleteCategoryResponses, DeleteFolderData, DeleteFolderErrors, DeleteFolderResponses, DeleteFormData, DeleteFormErrors, DeleteFormResponses, DeleteFormSubmissionData, DeleteFormSubmissionErrors, DeleteFormSubmissionResponses, DeleteMediaData, DeleteMediaErrors, DeleteMediaResponses, DeletePageData, DeletePageErrors, DeletePageResponses, DeletePayloadJobData, DeletePayloadJobErrors, DeletePayloadJobResponses, DeletePayloadKvData, DeletePayloadKvErrors, DeletePayloadKvResponses, DeletePayloadLockedDocumentData, DeletePayloadLockedDocumentErrors, DeletePayloadLockedDocumentResponses, DeletePayloadMigrationData, DeletePayloadMigrationErrors, DeletePayloadMigrationResponses, DeletePayloadPreferenceData, DeletePayloadPreferenceErrors, DeletePayloadPreferenceResponses, DeletePostData, DeletePostErrors, DeletePostResponses, DeleteRedirectData, DeleteRedirectErrors, DeleteRedirectResponses, DeleteSearchResultData, DeleteSearchResultErrors, DeleteSearchResultResponses, DeleteTenantData, DeleteTenantErrors, DeleteTenantResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponses, FindCategoryByIdData, FindCategoryByIdErrors, FindCategoryByIdResponses, FindFolderByIdData, FindFolderByIdErrors, FindFolderByIdResponses, FindFormByIdData, FindFormByIdErrors, FindFormByIdResponses, FindFormSubmissionByIdData, FindFormSubmissionByIdErrors, FindFormSubmissionByIdResponses, FindMediaByIdData, FindMediaByIdErrors, FindMediaByIdResponses, FindPageByIdData, FindPageByIdErrors, FindPageByIdResponses, FindPayloadJobByIdData, FindPayloadJobByIdErrors, FindPayloadJobByIdResponses, FindPayloadKvByIdData, FindPayloadKvByIdErrors, FindPayloadKvByIdResponses, FindPayloadLockedDocumentByIdData, FindPayloadLockedDocumentByIdErrors, FindPayloadLockedDocumentByIdResponses, FindPayloadMigrationByIdData, FindPayloadMigrationByIdErrors, FindPayloadMigrationByIdResponses, FindPayloadPreferenceByIdData, FindPayloadPreferenceByIdErrors, FindPayloadPreferenceByIdResponses, FindPostByIdData, FindPostByIdErrors, FindPostByIdResponses, FindRedirectByIdData, FindRedirectByIdErrors, FindRedirectByIdResponses, FindSearchResultByIdData, FindSearchResultByIdErrors, FindSearchResultByIdResponses, FindTenantByIdData, FindTenantByIdErrors, FindTenantByIdResponses, FindUserByIdData, FindUserByIdErrors, FindUserByIdResponses, GetApiGlobalsFooterData, GetApiGlobalsFooterResponses, GetApiGlobalsHeaderData, GetApiGlobalsHeaderResponses, ListCategoriesData, ListCategoriesResponses, ListFoldersData, ListFoldersResponses, ListFormsData, ListFormsResponses, ListFormSubmissionsData, ListFormSubmissionsResponses, ListMediaData, ListMediaResponses, ListPagesData, ListPagesResponses, ListPayloadJobsData, ListPayloadJobsResponses, ListPayloadKvsData, ListPayloadKvsResponses, ListPayloadLockedDocumentsData, ListPayloadLockedDocumentsResponses, ListPayloadMigrationsData, ListPayloadMigrationsResponses, ListPayloadPreferencesData, ListPayloadPreferencesResponses, ListPostsData, ListPostsResponses, ListRedirectsData, ListRedirectsResponses, ListSearchResultsData, ListSearchResultsResponses, ListTenantsData, ListTenantsResponses, ListUsersData, ListUsersResponses, PostApiGlobalsFooterData, PostApiGlobalsFooterResponses, PostApiGlobalsHeaderData, PostApiGlobalsHeaderResponses, UpdateCategoryData, UpdateCategoryErrors, UpdateCategoryResponses, UpdateFolderData, UpdateFolderErrors, UpdateFolderResponses, UpdateFormData, UpdateFormErrors, UpdateFormResponses, UpdateFormSubmissionData, UpdateFormSubmissionErrors, UpdateFormSubmissionResponses, UpdateMediaData, UpdateMediaErrors, UpdateMediaResponses, UpdatePageData, UpdatePageErrors, UpdatePageResponses, UpdatePayloadJobData, UpdatePayloadJobErrors, UpdatePayloadJobResponses, UpdatePayloadKvData, UpdatePayloadKvErrors, UpdatePayloadKvResponses, UpdatePayloadLockedDocumentData, UpdatePayloadLockedDocumentErrors, UpdatePayloadLockedDocumentResponses, UpdatePayloadMigrationData, UpdatePayloadMigrationErrors, UpdatePayloadMigrationResponses, UpdatePayloadPreferenceData, UpdatePayloadPreferenceErrors, UpdatePayloadPreferenceResponses, UpdatePostData, UpdatePostErrors, UpdatePostResponses, UpdateRedirectData, UpdateRedirectErrors, UpdateRedirectResponses, UpdateSearchResultData, UpdateSearchResultErrors, UpdateSearchResultResponses, UpdateTenantData, UpdateTenantErrors, UpdateTenantResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses } from './types.gen'; + +export type Options = Options2 & { + /** + * You can provide a client instance returned by `createClient()` instead of + * individual options. This might be also useful if you want to implement a + * custom client. + */ + client?: Client; + /** + * You can pass arbitrary values through the `meta` object. This can be + * used to access values that aren't defined as part of the SDK function. + */ + meta?: Record; +}; + +export class Pages { + /** + * Retrieve a list of Pages + */ + public static listPages(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/pages', + ...options + }); + } + + /** + * Create a new Page + */ + public static createPage(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/pages', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Page + */ + public static deletePage(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/pages/{id}', + ...options + }); + } + + /** + * Find a Page by ID + */ + public static findPageById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/pages/{id}', + ...options + }); + } + + /** + * Update a Page + */ + public static updatePage(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/pages/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class Posts { + /** + * Retrieve a list of Posts + */ + public static listPosts(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/posts', + ...options + }); + } + + /** + * Create a new Post + */ + public static createPost(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/posts', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Post + */ + public static deletePost(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/posts/{id}', + ...options + }); + } + + /** + * Find a Post by ID + */ + public static findPostById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/posts/{id}', + ...options + }); + } + + /** + * Update a Post + */ + public static updatePost(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/posts/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class Media { + /** + * Retrieve a list of Media + */ + public static listMedia(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/media', + ...options + }); + } + + /** + * Create a new Media + */ + public static createMedia(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/media', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Media + */ + public static deleteMedia(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/media/{id}', + ...options + }); + } + + /** + * Find a Media by ID + */ + public static findMediaById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/media/{id}', + ...options + }); + } + + /** + * Update a Media + */ + public static updateMedia(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/media/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class Categories { + /** + * Retrieve a list of Categories + */ + public static listCategories(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/categories', + ...options + }); + } + + /** + * Create a new Category + */ + public static createCategory(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/categories', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Category + */ + public static deleteCategory(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/categories/{id}', + ...options + }); + } + + /** + * Find a Category by ID + */ + public static findCategoryById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/categories/{id}', + ...options + }); + } + + /** + * Update a Category + */ + public static updateCategory(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/categories/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class Users { + /** + * Retrieve a list of Users + */ + public static listUsers(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/users', + ...options + }); + } + + /** + * Create a new User + */ + public static createUser(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/users', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a User + */ + public static deleteUser(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/users/{id}', + ...options + }); + } + + /** + * Find a User by ID + */ + public static findUserById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/users/{id}', + ...options + }); + } + + /** + * Update a User + */ + public static updateUser(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/users/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class Tenants { + /** + * Retrieve a list of Tenants + */ + public static listTenants(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/tenants', + ...options + }); + } + + /** + * Create a new Tenant + */ + public static createTenant(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/tenants', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Tenant + */ + public static deleteTenant(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/tenants/{id}', + ...options + }); + } + + /** + * Find a Tenant by ID + */ + public static findTenantById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/tenants/{id}', + ...options + }); + } + + /** + * Update a Tenant + */ + public static updateTenant(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/tenants/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class Redirects { + /** + * Retrieve a list of Redirects + */ + public static listRedirects(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/redirects', + ...options + }); + } + + /** + * Create a new Redirect + */ + public static createRedirect(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/redirects', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Redirect + */ + public static deleteRedirect(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/redirects/{id}', + ...options + }); + } + + /** + * Find a Redirect by ID + */ + public static findRedirectById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/redirects/{id}', + ...options + }); + } + + /** + * Update a Redirect + */ + public static updateRedirect(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/redirects/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class Forms { + /** + * Retrieve a list of Forms + */ + public static listForms(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/forms', + ...options + }); + } + + /** + * Create a new Form + */ + public static createForm(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/forms', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Form + */ + public static deleteForm(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/forms/{id}', + ...options + }); + } + + /** + * Find a Form by ID + */ + public static findFormById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/forms/{id}', + ...options + }); + } + + /** + * Update a Form + */ + public static updateForm(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/forms/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class FormSubmissions { + /** + * Retrieve a list of Form Submissions + */ + public static listFormSubmissions(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/form-submissions', + ...options + }); + } + + /** + * Create a new Form Submission + */ + public static createFormSubmission(options?: Options) { + return (options?.client ?? client).post({ + url: '/api/form-submissions', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Form Submission + */ + public static deleteFormSubmission(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/form-submissions/{id}', + ...options + }); + } + + /** + * Find a Form Submission by ID + */ + public static findFormSubmissionById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/form-submissions/{id}', + ...options + }); + } + + /** + * Update a Form Submission + */ + public static updateFormSubmission(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/form-submissions/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class SearchResults { + /** + * Retrieve a list of Search Results + */ + public static listSearchResults(options?: Options) { + return (options?.client ?? client).get({ url: '/api/search', ...options }); + } + + /** + * Create a new Search Result + */ + public static createSearchResult(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/search', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Search Result + */ + public static deleteSearchResult(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/search/{id}', + ...options + }); + } + + /** + * Find a Search Result by ID + */ + public static findSearchResultById(options: Options) { + return (options.client ?? client).get({ url: '/api/search/{id}', ...options }); + } + + /** + * Update a Search Result + */ + public static updateSearchResult(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/search/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class PayloadKvs { + /** + * Retrieve a list of Payload Kvs + */ + public static listPayloadKvs(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-kv', + ...options + }); + } + + /** + * Create a new Payload Kv + */ + public static createPayloadKv(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-kv', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Payload Kv + */ + public static deletePayloadKv(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-kv/{id}', + ...options + }); + } + + /** + * Find a Payload Kv by ID + */ + public static findPayloadKvById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-kv/{id}', + ...options + }); + } + + /** + * Update a Payload Kv + */ + public static updatePayloadKv(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-kv/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class PayloadJobs { + /** + * Retrieve a list of Payload Jobs + */ + public static listPayloadJobs(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-jobs', + ...options + }); + } + + /** + * Create a new Payload Job + */ + public static createPayloadJob(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-jobs', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Payload Job + */ + public static deletePayloadJob(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-jobs/{id}', + ...options + }); + } + + /** + * Find a Payload Job by ID + */ + public static findPayloadJobById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-jobs/{id}', + ...options + }); + } + + /** + * Update a Payload Job + */ + public static updatePayloadJob(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-jobs/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class Folders { + /** + * Retrieve a list of Folders + */ + public static listFolders(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-folders', + ...options + }); + } + + /** + * Create a new Folder + */ + public static createFolder(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-folders', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Folder + */ + public static deleteFolder(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-folders/{id}', + ...options + }); + } + + /** + * Find a Folder by ID + */ + public static findFolderById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-folders/{id}', + ...options + }); + } + + /** + * Update a Folder + */ + public static updateFolder(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-folders/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class PayloadLockedDocuments { + /** + * Retrieve a list of Payload Locked Documents + */ + public static listPayloadLockedDocuments(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-locked-documents', + ...options + }); + } + + /** + * Create a new Payload Locked Document + */ + public static createPayloadLockedDocument(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-locked-documents', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Payload Locked Document + */ + public static deletePayloadLockedDocument(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-locked-documents/{id}', + ...options + }); + } + + /** + * Find a Payload Locked Document by ID + */ + public static findPayloadLockedDocumentById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-locked-documents/{id}', + ...options + }); + } + + /** + * Update a Payload Locked Document + */ + public static updatePayloadLockedDocument(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-locked-documents/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class PayloadPreferences { + /** + * Retrieve a list of Payload Preferences + */ + public static listPayloadPreferences(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-preferences', + ...options + }); + } + + /** + * Create a new Payload Preference + */ + public static createPayloadPreference(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-preferences', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Payload Preference + */ + public static deletePayloadPreference(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-preferences/{id}', + ...options + }); + } + + /** + * Find a Payload Preference by ID + */ + public static findPayloadPreferenceById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-preferences/{id}', + ...options + }); + } + + /** + * Update a Payload Preference + */ + public static updatePayloadPreference(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-preferences/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class PayloadMigrations { + /** + * Retrieve a list of Payload Migrations + */ + public static listPayloadMigrations(options?: Options) { + return (options?.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-migrations', + ...options + }); + } + + /** + * Create a new Payload Migration + */ + public static createPayloadMigration(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-migrations', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } + + /** + * Delete a Payload Migration + */ + public static deletePayloadMigration(options: Options) { + return (options.client ?? client).delete({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-migrations/{id}', + ...options + }); + } + + /** + * Find a Payload Migration by ID + */ + public static findPayloadMigrationById(options: Options) { + return (options.client ?? client).get({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-migrations/{id}', + ...options + }); + } + + /** + * Update a Payload Migration + */ + public static updatePayloadMigration(options: Options) { + return (options.client ?? client).patch({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/payload-migrations/{id}', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } + }); + } +} + +export class Header { + /** + * Get the Header + */ + public static getApiGlobalsHeader(options?: Options) { + return (options?.client ?? client).get({ url: '/api/globals/header', ...options }); + } + + /** + * Update the Header + */ + public static postApiGlobalsHeader(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/globals/header', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } +} + +export class Footer { + /** + * Get the Footer + */ + public static getApiGlobalsFooter(options?: Options) { + return (options?.client ?? client).get({ url: '/api/globals/footer', ...options }); + } + + /** + * Update the Footer + */ + public static postApiGlobalsFooter(options?: Options) { + return (options?.client ?? client).post({ + security: [{ scheme: 'bearer', type: 'http' }], + url: '/api/globals/footer', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options?.headers + } + }); + } +} diff --git a/src/clientsdk/types.gen.ts b/src/clientsdk/types.gen.ts new file mode 100644 index 0000000..b87491f --- /dev/null +++ b/src/clientsdk/types.gen.ts @@ -0,0 +1,6179 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type ClientOptions = { + baseUrl: 'http://localhost:3000' | (string & {}); +}; + +export type SupportedTimezones = string; + +/** + * Page + */ +export type Page = { + id: string; + tenant?: string | null | Tenant; + title: string; + hero: { + type: 'none' | 'highImpact' | 'mediumImpact' | 'lowImpact'; + richText?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + links?: Array<{ + link: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + /** + * Choose how the link should be rendered. + */ + appearance?: 'default' | 'outline'; + }; + id?: string | null; + }> | null; + media?: string | null | Media; + }; + layout: Array<{ + richText?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + links?: Array<{ + link: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + /** + * Choose how the link should be rendered. + */ + appearance?: 'default' | 'outline'; + }; + id?: string | null; + }> | null; + id?: string | null; + blockName?: string | null; + blockType: 'cta'; + } | { + columns?: Array<{ + size?: 'oneThird' | 'half' | 'twoThirds' | 'full'; + richText?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + enableLink?: boolean | null; + link?: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + /** + * Choose how the link should be rendered. + */ + appearance?: 'default' | 'outline'; + }; + id?: string | null; + }> | null; + id?: string | null; + blockName?: string | null; + blockType: 'content'; + } | { + media: string | Media; + id?: string | null; + blockName?: string | null; + blockType: 'mediaBlock'; + } | { + introContent?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + populateBy?: 'collection' | 'selection'; + relationTo?: 'posts'; + categories?: Array | null; + limit?: number | null; + selectedDocs?: Array<{ + relationTo: 'posts'; + value: string | Post; + }> | null; + id?: string | null; + blockName?: string | null; + blockType: 'archive'; + } | { + form: string | Form; + enableIntro?: boolean | null; + introContent?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + id?: string | null; + blockName?: string | null; + blockType: 'formBlock'; + }>; + meta?: { + title?: string | null; + /** + * Maximum upload file size: 12MB. Recommended file size for images is <500KB. + */ + image?: string | null | Media; + description?: string | null; + }; + publishedAt?: string | null; + /** + * When enabled, the slug will auto-generate from the title field on save and autosave. + */ + generateSlug?: boolean | null; + slug: string; + updatedAt: string; + createdAt: string; + _status?: 'draft' | 'published'; +}; + +/** + * Post + */ +export type Post = { + id: string; + tenant?: string | null | Tenant; + title: string; + heroImage?: string | null | Media; + content: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + }; + content_html?: string | null; + relatedPosts?: Array | null; + categories?: Array | null; + meta?: { + title?: string | null; + /** + * Maximum upload file size: 12MB. Recommended file size for images is <500KB. + */ + image?: string | null | Media; + description?: string | null; + }; + publishedAt?: string | null; + authors?: Array | null; + populatedAuthors?: Array<{ + id?: string | null; + name?: string | null; + }> | null; + /** + * When enabled, the slug will auto-generate from the title field on save and autosave. + */ + generateSlug?: boolean | null; + slug: string; + updatedAt: string; + createdAt: string; + _status?: 'draft' | 'published'; +}; + +/** + * Media + */ +export type Media = { + id: string; + tenant?: string | null | Tenant; + alt?: string | null; + caption?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + folder?: string | null | Folder; + updatedAt: string; + createdAt: string; + url?: string | null; + thumbnailURL?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + focalX?: number | null; + focalY?: number | null; + sizes?: { + thumbnail?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + square?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + small?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + medium?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + large?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + xlarge?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + og?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + }; +}; + +/** + * Category + */ +export type Category = { + id: string; + tenant?: string | null | Tenant; + title: string; + /** + * When enabled, the slug will auto-generate from the title field on save and autosave. + */ + generateSlug?: boolean | null; + slug: string; + parent?: string | null | Category; + breadcrumbs?: Array<{ + doc?: string | null | Category; + url?: string | null; + label?: string | null; + id?: string | null; + }> | null; + updatedAt: string; + createdAt: string; +}; + +/** + * User + */ +export type User = { + id: string; + email: string; + emailVerified?: string | null; + name?: string | null; + image?: string | null; + displayName?: string | null; + tenants?: Array<{ + tenant: string | Tenant; + id?: string | null; + }> | null; + accounts?: Array<{ + provider: string; + providerAccountId: string; + type: 'oidc' | 'oauth' | 'email' | 'webauthn'; + id?: string | null; + }> | null; + updatedAt: string; + createdAt: string; +}; + +/** + * Tenant + * + * 租户基本信息管理 + */ +export type Tenant = { + id: string; + /** + * 租户显示名称 + */ + name?: string | null; + /** + * 租户标识符(用于 API 认证时的 X-Tenant-Slug 请求头) + */ + slug: string; + apiKeyEncrypted?: string | null; + /** + * 这是该租户的主 API Key。 + */ + apiKeyDisplay?: string | null; + updatedAt: string; + createdAt: string; +}; + +/** + * Redirect + */ +export type Redirect = { + id: string; + tenant?: string | null | Tenant; + /** + * You will need to rebuild the website when changing this field. + */ + from: string; + to?: { + type?: 'reference' | 'custom'; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + }; + updatedAt: string; + createdAt: string; +}; + +/** + * Form + */ +export type Form = { + id: string; + tenant?: string | null | Tenant; + title: string; + fields?: Array<{ + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + defaultValue?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'checkbox'; + } | { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'country'; + } | { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'email'; + } | { + message?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + id?: string | null; + blockName?: string | null; + blockType: 'message'; + } | { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'number'; + } | { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: string | null; + placeholder?: string | null; + options?: Array<{ + label: string; + value: string; + id?: string | null; + }> | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'select'; + } | { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'state'; + } | { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: string | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'text'; + } | { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: string | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'textarea'; + }> | null; + submitButtonLabel?: string | null; + /** + * Choose whether to display an on-page message or redirect to a different page after they submit the form. + */ + confirmationType?: 'message' | 'redirect'; + confirmationMessage?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + redirect?: { + url: string; + }; + /** + * Send custom emails when the form submits. Use comma separated lists to send the same email to multiple recipients. To reference a value from this form, wrap that field's name with double curly brackets, i.e. {{firstName}}. You can use a wildcard {{*}} to output all data and {{*:table}} to format it as an HTML table in the email. + */ + emails?: Array<{ + emailTo?: string | null; + cc?: string | null; + bcc?: string | null; + replyTo?: string | null; + emailFrom?: string | null; + subject: string; + /** + * Enter the message that should be sent in this email. + */ + message?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + id?: string | null; + }> | null; + updatedAt: string; + createdAt: string; +}; + +/** + * Form Submission + */ +export type FormSubmission = { + id: string; + form: string | Form; + submissionData?: Array<{ + field: string; + value: string; + id?: string | null; + }> | null; + updatedAt: string; + createdAt: string; +}; + +/** + * Search Result + * + * This is a collection of automatically created search results. These results are used by the global site search and will be updated automatically as documents in the CMS are created or updated. + */ +export type SearchResult = { + id: string; + title?: string | null; + priority?: number | null; + doc: { + relationTo: 'posts'; + value: string | Post; + }; + slug?: string | null; + meta?: { + title?: string | null; + description?: string | null; + image?: string | null | Media; + }; + categories?: Array<{ + relationTo?: string | null; + categoryID?: string | null; + title?: string | null; + id?: string | null; + }> | null; + updatedAt: string; + createdAt: string; +}; + +/** + * Payload Kv + */ +export type PayloadKv = { + id: string; + key: string; + data: { + [key: string]: unknown; + } | Array | string | number | boolean | null; +}; + +/** + * Payload Job + */ +export type PayloadJob = { + id: string; + /** + * Input data provided to the job + */ + input?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + taskStatus?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + completedAt?: string | null; + totalTried?: number | null; + /** + * If hasError is true this job will not be retried + */ + hasError?: boolean | null; + /** + * If hasError is true, this is the error that caused it + */ + error?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + /** + * Task execution log + */ + log?: Array<{ + executedAt: string; + completedAt: string; + taskSlug: 'inline' | 'schedulePublish'; + taskID: string; + input?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + output?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + state: 'failed' | 'succeeded'; + error?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + id?: string | null; + }> | null; + taskSlug?: 'inline' | 'schedulePublish'; + queue?: string | null; + waitUntil?: string | null; + processing?: boolean | null; + updatedAt: string; + createdAt: string; +}; + +/** + * Folder + */ +export type Folder = { + id: string; + name: string; + folder?: string | null | Folder; + documentsAndFolders?: { + docs?: Array<{ + relationTo?: 'payload-folders'; + value: string | Folder; + } | { + relationTo?: 'media'; + value: string | Media; + }>; + hasNextPage?: boolean; + totalDocs?: number; + }; + folderType?: Array<'media'> | null; + updatedAt: string; + createdAt: string; +}; + +/** + * Payload Locked Document + */ +export type PayloadLockedDocument = { + id: string; + document?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + } | { + relationTo: 'media'; + value: string | Media; + } | { + relationTo: 'categories'; + value: string | Category; + } | { + relationTo: 'users'; + value: string | User; + } | { + relationTo: 'tenants'; + value: string | Tenant; + } | { + relationTo: 'redirects'; + value: string | Redirect; + } | { + relationTo: 'forms'; + value: string | Form; + } | { + relationTo: 'form-submissions'; + value: string | FormSubmission; + } | { + relationTo: 'search'; + value: string | SearchResult; + } | { + relationTo: 'payload-folders'; + value: string | Folder; + }; + globalSlug?: string | null; + user: { + relationTo: 'users'; + value: string | User; + }; + updatedAt: string; + createdAt: string; +}; + +/** + * Payload Preference + */ +export type PayloadPreference = { + id: string; + user: { + relationTo: 'users'; + value: string | User; + }; + key?: string | null; + value?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + updatedAt: string; + createdAt: string; +}; + +/** + * Payload Migration + */ +export type PayloadMigration = { + id: string; + name?: string | null; + batch?: number | null; + updatedAt: string; + createdAt: string; +}; + +/** + * Page query operations + */ +export type PageQueryOperations = { + title?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + publishedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + _status?: { + equals?: 'draft' | 'published'; + not_equals?: 'draft' | 'published'; + in?: string; + not_in?: string; + }; +}; + +/** + * Page query conjunction + */ +export type PageQueryOperationsAnd = { + and: Array; +}; + +/** + * Page query disjunction + */ +export type PageQueryOperationsOr = { + or: Array; +}; + +/** + * Post query operations + */ +export type PostQueryOperations = { + title?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + publishedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + _status?: { + equals?: 'draft' | 'published'; + not_equals?: 'draft' | 'published'; + in?: string; + not_in?: string; + }; +}; + +/** + * Post query conjunction + */ +export type PostQueryOperationsAnd = { + and: Array; +}; + +/** + * Post query disjunction + */ +export type PostQueryOperationsOr = { + or: Array; +}; + +/** + * Media query operations + */ +export type MediaQueryOperations = { + alt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + url?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + thumbnailURL?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + filename?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + mimeType?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + filesize?: { + equals?: number; + not_equals?: number; + in?: string; + not_in?: string; + greater_than?: number; + greater_than_equal?: number; + less_than?: number; + less_than_equal?: number; + }; + width?: { + equals?: number; + not_equals?: number; + in?: string; + not_in?: string; + greater_than?: number; + greater_than_equal?: number; + less_than?: number; + less_than_equal?: number; + }; + height?: { + equals?: number; + not_equals?: number; + in?: string; + not_in?: string; + greater_than?: number; + greater_than_equal?: number; + less_than?: number; + less_than_equal?: number; + }; + focalX?: { + equals?: number; + not_equals?: number; + in?: string; + not_in?: string; + greater_than?: number; + greater_than_equal?: number; + less_than?: number; + less_than_equal?: number; + }; + focalY?: { + equals?: number; + not_equals?: number; + in?: string; + not_in?: string; + greater_than?: number; + greater_than_equal?: number; + less_than?: number; + less_than_equal?: number; + }; +}; + +/** + * Media query conjunction + */ +export type MediaQueryOperationsAnd = { + and: Array; +}; + +/** + * Media query disjunction + */ +export type MediaQueryOperationsOr = { + or: Array; +}; + +/** + * Category query operations + */ +export type CategoryQueryOperations = { + title?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; +}; + +/** + * Category query conjunction + */ +export type CategoryQueryOperationsAnd = { + and: Array; +}; + +/** + * Category query disjunction + */ +export type CategoryQueryOperationsOr = { + or: Array; +}; + +/** + * User query operations + */ +export type UserQueryOperations = { + id?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; +}; + +/** + * User query conjunction + */ +export type UserQueryOperationsAnd = { + and: Array; +}; + +/** + * User query disjunction + */ +export type UserQueryOperationsOr = { + or: Array; +}; + +/** + * Tenant query operations + */ +export type TenantQueryOperations = { + name?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + slug?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; +}; + +/** + * Tenant query conjunction + */ +export type TenantQueryOperationsAnd = { + and: Array; +}; + +/** + * Tenant query disjunction + */ +export type TenantQueryOperationsOr = { + or: Array; +}; + +/** + * Redirect query operations + */ +export type RedirectQueryOperations = { + from?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; +}; + +/** + * Redirect query conjunction + */ +export type RedirectQueryOperationsAnd = { + and: Array; +}; + +/** + * Redirect query disjunction + */ +export type RedirectQueryOperationsOr = { + or: Array; +}; + +/** + * Form query operations + */ +export type FormQueryOperations = { + title?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + submitButtonLabel?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + confirmationType?: { + equals?: 'message' | 'redirect'; + not_equals?: 'message' | 'redirect'; + in?: string; + not_in?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; +}; + +/** + * Form query conjunction + */ +export type FormQueryOperationsAnd = { + and: Array; +}; + +/** + * Form query disjunction + */ +export type FormQueryOperationsOr = { + or: Array; +}; + +/** + * Form Submission query operations + */ +export type FormSubmissionQueryOperations = { + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; +}; + +/** + * Form Submission query conjunction + */ +export type FormSubmissionQueryOperationsAnd = { + and: Array; +}; + +/** + * Form Submission query disjunction + */ +export type FormSubmissionQueryOperationsOr = { + or: Array; +}; + +/** + * Search Result query operations + */ +export type SearchResultQueryOperations = { + title?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + priority?: { + equals?: number; + not_equals?: number; + in?: string; + not_in?: string; + greater_than?: number; + greater_than_equal?: number; + less_than?: number; + less_than_equal?: number; + }; + slug?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; +}; + +/** + * Search Result query conjunction + */ +export type SearchResultQueryOperationsAnd = { + and: Array; +}; + +/** + * Search Result query disjunction + */ +export type SearchResultQueryOperationsOr = { + or: Array; +}; + +/** + * Payload Kv query operations + */ +export type PayloadKvQueryOperations = { + key?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; +}; + +/** + * Payload Kv query conjunction + */ +export type PayloadKvQueryOperationsAnd = { + and: Array; +}; + +/** + * Payload Kv query disjunction + */ +export type PayloadKvQueryOperationsOr = { + or: Array; +}; + +/** + * Payload Job query operations + */ +export type PayloadJobQueryOperations = { + taskSlug?: { + equals?: 'inline' | 'schedulePublish'; + not_equals?: 'inline' | 'schedulePublish'; + in?: string; + not_in?: string; + }; + queue?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + waitUntil?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + processing?: { + equals?: boolean; + not_equals?: boolean; + in?: string; + not_in?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; +}; + +/** + * Payload Job query conjunction + */ +export type PayloadJobQueryOperationsAnd = { + and: Array; +}; + +/** + * Payload Job query disjunction + */ +export type PayloadJobQueryOperationsOr = { + or: Array; +}; + +/** + * Folder query operations + */ +export type FolderQueryOperations = { + name?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + folderType?: { + equals?: 'media'; + not_equals?: 'media'; + in?: string; + not_in?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; +}; + +/** + * Folder query conjunction + */ +export type FolderQueryOperationsAnd = { + and: Array; +}; + +/** + * Folder query disjunction + */ +export type FolderQueryOperationsOr = { + or: Array; +}; + +/** + * Payload Locked Document query operations + */ +export type PayloadLockedDocumentQueryOperations = { + globalSlug?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; +}; + +/** + * Payload Locked Document query conjunction + */ +export type PayloadLockedDocumentQueryOperationsAnd = { + and: Array; +}; + +/** + * Payload Locked Document query disjunction + */ +export type PayloadLockedDocumentQueryOperationsOr = { + or: Array; +}; + +/** + * Payload Preference query operations + */ +export type PayloadPreferenceQueryOperations = { + key?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; +}; + +/** + * Payload Preference query conjunction + */ +export type PayloadPreferenceQueryOperationsAnd = { + and: Array; +}; + +/** + * Payload Preference query disjunction + */ +export type PayloadPreferenceQueryOperationsOr = { + or: Array; +}; + +/** + * Payload Migration query operations + */ +export type PayloadMigrationQueryOperations = { + name?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + like?: string; + contains?: string; + }; + batch?: { + equals?: number; + not_equals?: number; + in?: string; + not_in?: string; + greater_than?: number; + greater_than_equal?: number; + less_than?: number; + less_than_equal?: number; + }; + updatedAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; + createdAt?: { + equals?: string; + not_equals?: string; + in?: string; + not_in?: string; + greater_than?: string; + greater_than_equal?: string; + less_than?: string; + less_than_equal?: string; + }; +}; + +/** + * Payload Migration query conjunction + */ +export type PayloadMigrationQueryOperationsAnd = { + and: Array; +}; + +/** + * Payload Migration query disjunction + */ +export type PayloadMigrationQueryOperationsOr = { + or: Array; +}; + +/** + * Header + */ +export type Header = { + id: string; + navItems?: Array<{ + link: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + }; + id?: string | null; + }> | null; + updatedAt?: string | null; + createdAt?: string | null; +}; + +/** + * Header (if present) + */ +export type HeaderRead = { + id: string; + navItems?: Array<{ + link: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + }; + id?: string | null; + }> | null; + updatedAt?: string | null; + createdAt?: string | null; +} | { + [key: string]: unknown; +}; + +/** + * Header (writable fields) + */ +export type HeaderWrite = { + id: string; + navItems?: Array<{ + link: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + }; + id?: string | null; + }> | null; + updatedAt?: string | null; + createdAt?: string | null; +}; + +/** + * Footer + */ +export type Footer = { + id: string; + navItems?: Array<{ + link: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + }; + id?: string | null; + }> | null; + updatedAt?: string | null; + createdAt?: string | null; +}; + +/** + * Footer (if present) + */ +export type FooterRead = { + id: string; + navItems?: Array<{ + link: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + }; + id?: string | null; + }> | null; + updatedAt?: string | null; + createdAt?: string | null; +} | { + [key: string]: unknown; +}; + +/** + * Footer (writable fields) + */ +export type FooterWrite = { + id: string; + navItems?: Array<{ + link: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + }; + id?: string | null; + }> | null; + updatedAt?: string | null; + createdAt?: string | null; +}; + +/** + * Page + * + * Page + */ +export type PageRequestBody = { + /** + * ID of the tenants + */ + tenant?: string; + title: string; + hero: { + type: 'none' | 'highImpact' | 'mediumImpact' | 'lowImpact'; + richText?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + links?: Array<{ + link: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + /** + * Choose how the link should be rendered. + */ + appearance?: 'default' | 'outline'; + }; + id?: string | null; + }> | null; + media?: string | null | Media; + }; + layout: Array<{ + richText?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + links?: Array<{ + link: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + /** + * Choose how the link should be rendered. + */ + appearance?: 'default' | 'outline'; + }; + id?: string | null; + }> | null; + id?: string | null; + blockName?: string | null; + blockType: 'cta'; + } | { + columns?: Array<{ + size?: 'oneThird' | 'half' | 'twoThirds' | 'full'; + richText?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + enableLink?: boolean | null; + link?: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + /** + * Choose how the link should be rendered. + */ + appearance?: 'default' | 'outline'; + }; + id?: string | null; + }> | null; + id?: string | null; + blockName?: string | null; + blockType: 'content'; + } | { + media: string | Media; + id?: string | null; + blockName?: string | null; + blockType: 'mediaBlock'; + } | { + introContent?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + populateBy?: 'collection' | 'selection'; + relationTo?: 'posts'; + categories?: Array | null; + limit?: number | null; + selectedDocs?: Array<{ + relationTo: 'posts'; + value: string | Post; + }> | null; + id?: string | null; + blockName?: string | null; + blockType: 'archive'; + } | { + form: string | Form; + enableIntro?: boolean | null; + introContent?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + id?: string | null; + blockName?: string | null; + blockType: 'formBlock'; + }>; + meta?: { + title?: string | null; + /** + * Maximum upload file size: 12MB. Recommended file size for images is <500KB. + */ + image?: string | null | Media; + description?: string | null; + }; + publishedAt?: string | null; + /** + * When enabled, the slug will auto-generate from the title field on save and autosave. + */ + generateSlug?: boolean | null; + slug: string; + _status?: 'draft' | 'published'; +}; + +/** + * Page + * + * Page + */ +export type PagePatchRequestBody = { + /** + * ID of the tenants + */ + tenant?: string; + title?: string; + hero?: { + type: 'none' | 'highImpact' | 'mediumImpact' | 'lowImpact'; + richText?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + links?: Array<{ + link: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + /** + * Choose how the link should be rendered. + */ + appearance?: 'default' | 'outline'; + }; + id?: string | null; + }> | null; + media?: string | null | Media; + }; + layout?: Array<{ + richText?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + links?: Array<{ + link: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + /** + * Choose how the link should be rendered. + */ + appearance?: 'default' | 'outline'; + }; + id?: string | null; + }> | null; + id?: string | null; + blockName?: string | null; + blockType: 'cta'; + } | { + columns?: Array<{ + size?: 'oneThird' | 'half' | 'twoThirds' | 'full'; + richText?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + enableLink?: boolean | null; + link?: { + type?: 'reference' | 'custom'; + newTab?: boolean | null; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + label: string; + /** + * Choose how the link should be rendered. + */ + appearance?: 'default' | 'outline'; + }; + id?: string | null; + }> | null; + id?: string | null; + blockName?: string | null; + blockType: 'content'; + } | { + media: string | Media; + id?: string | null; + blockName?: string | null; + blockType: 'mediaBlock'; + } | { + introContent?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + populateBy?: 'collection' | 'selection'; + relationTo?: 'posts'; + categories?: Array | null; + limit?: number | null; + selectedDocs?: Array<{ + relationTo: 'posts'; + value: string | Post; + }> | null; + id?: string | null; + blockName?: string | null; + blockType: 'archive'; + } | { + form: string | Form; + enableIntro?: boolean | null; + introContent?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + id?: string | null; + blockName?: string | null; + blockType: 'formBlock'; + }>; + meta?: { + title?: string | null; + /** + * Maximum upload file size: 12MB. Recommended file size for images is <500KB. + */ + image?: string | null | Media; + description?: string | null; + }; + publishedAt?: string | null; + /** + * When enabled, the slug will auto-generate from the title field on save and autosave. + */ + generateSlug?: boolean | null; + slug?: string; + _status?: 'draft' | 'published'; +}; + +/** + * Post + * + * Post + */ +export type PostRequestBody = { + /** + * ID of the tenants + */ + tenant?: string; + title: string; + heroImage?: string | null | Media; + content: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + }; + content_html?: string | null; + relatedPosts?: Array | null; + categories?: Array | null; + meta?: { + title?: string | null; + /** + * Maximum upload file size: 12MB. Recommended file size for images is <500KB. + */ + image?: string | null | Media; + description?: string | null; + }; + publishedAt?: string | null; + /** + * ID of the users + */ + authors?: string; + populatedAuthors?: Array<{ + id?: string | null; + name?: string | null; + }> | null; + /** + * When enabled, the slug will auto-generate from the title field on save and autosave. + */ + generateSlug?: boolean | null; + slug: string; + _status?: 'draft' | 'published'; +}; + +/** + * Post + * + * Post + */ +export type PostPatchRequestBody = { + /** + * ID of the tenants + */ + tenant?: string; + title?: string; + heroImage?: string | null | Media; + content?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + }; + content_html?: string | null; + relatedPosts?: Array | null; + categories?: Array | null; + meta?: { + title?: string | null; + /** + * Maximum upload file size: 12MB. Recommended file size for images is <500KB. + */ + image?: string | null | Media; + description?: string | null; + }; + publishedAt?: string | null; + /** + * ID of the users + */ + authors?: string; + populatedAuthors?: Array<{ + id?: string | null; + name?: string | null; + }> | null; + /** + * When enabled, the slug will auto-generate from the title field on save and autosave. + */ + generateSlug?: boolean | null; + slug?: string; + _status?: 'draft' | 'published'; +}; + +/** + * Media + * + * Media + */ +export type MediaRequestBody = { + /** + * ID of the tenants + */ + tenant?: string; + alt?: string | null; + caption?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + /** + * ID of the payload-folders + */ + folder?: string; + url?: string | null; + thumbnailURL?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + focalX?: number | null; + focalY?: number | null; + sizes?: { + thumbnail?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + square?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + small?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + medium?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + large?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + xlarge?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + og?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + }; +}; + +/** + * Media + * + * Media + */ +export type MediaPatchRequestBody = { + /** + * ID of the tenants + */ + tenant?: string; + alt?: string | null; + caption?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + /** + * ID of the payload-folders + */ + folder?: string; + url?: string | null; + thumbnailURL?: string | null; + filename?: string | null; + mimeType?: string | null; + filesize?: number | null; + width?: number | null; + height?: number | null; + focalX?: number | null; + focalY?: number | null; + sizes?: { + thumbnail?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + square?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + small?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + medium?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + large?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + xlarge?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + og?: { + url?: string | null; + width?: number | null; + height?: number | null; + mimeType?: string | null; + filesize?: number | null; + filename?: string | null; + }; + }; +}; + +/** + * Category + * + * Category + */ +export type CategoryRequestBody = { + /** + * ID of the tenants + */ + tenant?: string; + title: string; + /** + * When enabled, the slug will auto-generate from the title field on save and autosave. + */ + generateSlug?: boolean | null; + slug: string; + /** + * ID of the categories + */ + parent?: string; + breadcrumbs?: Array<{ + doc?: string | null | Category; + url?: string | null; + label?: string | null; + id?: string | null; + }> | null; +}; + +/** + * Category + * + * Category + */ +export type CategoryPatchRequestBody = { + /** + * ID of the tenants + */ + tenant?: string; + title?: string; + /** + * When enabled, the slug will auto-generate from the title field on save and autosave. + */ + generateSlug?: boolean | null; + slug?: string; + /** + * ID of the categories + */ + parent?: string; + breadcrumbs?: Array<{ + doc?: string | null | Category; + url?: string | null; + label?: string | null; + id?: string | null; + }> | null; +}; + +/** + * User + * + * User + */ +export type UserRequestBody = { + email: string; + emailVerified?: string | null; + name?: string | null; + image?: string | null; + displayName?: string | null; + tenants?: Array<{ + tenant: string | Tenant; + id?: string | null; + }> | null; + accounts?: Array<{ + provider: string; + providerAccountId: string; + type: 'oidc' | 'oauth' | 'email' | 'webauthn'; + id?: string | null; + }> | null; +}; + +/** + * User + * + * User + */ +export type UserPatchRequestBody = { + email?: string; + emailVerified?: string | null; + name?: string | null; + image?: string | null; + displayName?: string | null; + tenants?: Array<{ + tenant: string | Tenant; + id?: string | null; + }> | null; + accounts?: Array<{ + provider: string; + providerAccountId: string; + type: 'oidc' | 'oauth' | 'email' | 'webauthn'; + id?: string | null; + }> | null; +}; + +/** + * Tenant + * + * 租户基本信息管理 + */ +export type TenantRequestBody = { + /** + * 租户显示名称 + */ + name?: string | null; + /** + * 租户标识符(用于 API 认证时的 X-Tenant-Slug 请求头) + */ + slug: string; + apiKeyEncrypted?: string | null; + /** + * 这是该租户的主 API Key。 + */ + apiKeyDisplay?: string | null; +}; + +/** + * Tenant + * + * 租户基本信息管理 + */ +export type TenantPatchRequestBody = { + /** + * 租户显示名称 + */ + name?: string | null; + /** + * 租户标识符(用于 API 认证时的 X-Tenant-Slug 请求头) + */ + slug?: string; + apiKeyEncrypted?: string | null; + /** + * 这是该租户的主 API Key。 + */ + apiKeyDisplay?: string | null; +}; + +/** + * Redirect + * + * Redirect + */ +export type RedirectRequestBody = { + /** + * ID of the tenants + */ + tenant?: string; + /** + * You will need to rebuild the website when changing this field. + */ + from: string; + to?: { + type?: 'reference' | 'custom'; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + }; +}; + +/** + * Redirect + * + * Redirect + */ +export type RedirectPatchRequestBody = { + /** + * ID of the tenants + */ + tenant?: string; + /** + * You will need to rebuild the website when changing this field. + */ + from?: string; + to?: { + type?: 'reference' | 'custom'; + reference?: { + relationTo: 'pages'; + value: string | Page; + } | null | { + relationTo: 'posts'; + value: string | Post; + }; + url?: string | null; + }; +}; + +/** + * Form + * + * Form + */ +export type FormRequestBody = { + /** + * ID of the tenants + */ + tenant?: string; + title: string; + fields?: Array<{ + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + defaultValue?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'checkbox'; + } | { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'country'; + } | { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'email'; + } | { + message?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + id?: string | null; + blockName?: string | null; + blockType: 'message'; + } | { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'number'; + } | { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: string | null; + placeholder?: string | null; + options?: Array<{ + label: string; + value: string; + id?: string | null; + }> | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'select'; + } | { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'state'; + } | { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: string | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'text'; + } | { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: string | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'textarea'; + }> | null; + submitButtonLabel?: string | null; + /** + * Choose whether to display an on-page message or redirect to a different page after they submit the form. + */ + confirmationType?: 'message' | 'redirect'; + confirmationMessage?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + redirect?: { + url: string; + }; + /** + * Send custom emails when the form submits. Use comma separated lists to send the same email to multiple recipients. To reference a value from this form, wrap that field's name with double curly brackets, i.e. {{firstName}}. You can use a wildcard {{*}} to output all data and {{*:table}} to format it as an HTML table in the email. + */ + emails?: Array<{ + emailTo?: string | null; + cc?: string | null; + bcc?: string | null; + replyTo?: string | null; + emailFrom?: string | null; + subject: string; + /** + * Enter the message that should be sent in this email. + */ + message?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + id?: string | null; + }> | null; +}; + +/** + * Form + * + * Form + */ +export type FormPatchRequestBody = { + /** + * ID of the tenants + */ + tenant?: string; + title?: string; + fields?: Array<{ + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + defaultValue?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'checkbox'; + } | { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'country'; + } | { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'email'; + } | { + message?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + id?: string | null; + blockName?: string | null; + blockType: 'message'; + } | { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'number'; + } | { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: string | null; + placeholder?: string | null; + options?: Array<{ + label: string; + value: string; + id?: string | null; + }> | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'select'; + } | { + name: string; + label?: string | null; + width?: number | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'state'; + } | { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: string | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'text'; + } | { + name: string; + label?: string | null; + width?: number | null; + defaultValue?: string | null; + required?: boolean | null; + id?: string | null; + blockName?: string | null; + blockType: 'textarea'; + }> | null; + submitButtonLabel?: string | null; + /** + * Choose whether to display an on-page message or redirect to a different page after they submit the form. + */ + confirmationType?: 'message' | 'redirect'; + confirmationMessage?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + redirect?: { + url: string; + }; + /** + * Send custom emails when the form submits. Use comma separated lists to send the same email to multiple recipients. To reference a value from this form, wrap that field's name with double curly brackets, i.e. {{firstName}}. You can use a wildcard {{*}} to output all data and {{*:table}} to format it as an HTML table in the email. + */ + emails?: Array<{ + emailTo?: string | null; + cc?: string | null; + bcc?: string | null; + replyTo?: string | null; + emailFrom?: string | null; + subject: string; + /** + * Enter the message that should be sent in this email. + */ + message?: { + root: { + type: string; + children: Array<{ + type: string; + version: number; + [key: string]: unknown | string | number; + }>; + direction: 'ltr' | 'rtl' | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + } | null; + id?: string | null; + }> | null; +}; + +/** + * FormSubmission + * + * Form Submission + */ +export type FormSubmissionRequestBody = { + /** + * ID of the forms + */ + form: string; + submissionData?: Array<{ + field: string; + value: string; + id?: string | null; + }> | null; +}; + +/** + * FormSubmission + * + * Form Submission + */ +export type FormSubmissionPatchRequestBody = { + /** + * ID of the forms + */ + form?: string; + submissionData?: Array<{ + field: string; + value: string; + id?: string | null; + }> | null; +}; + +/** + * Search + * + * This is a collection of automatically created search results. These results are used by the global site search and will be updated automatically as documents in the CMS are created or updated. + */ +export type SearchResultRequestBody = { + title?: string | null; + priority?: number | null; + /** + * ID of the posts + */ + doc: string; + slug?: string | null; + meta?: { + title?: string | null; + description?: string | null; + image?: string | null | Media; + }; + categories?: Array<{ + relationTo?: string | null; + categoryID?: string | null; + title?: string | null; + id?: string | null; + }> | null; +}; + +/** + * Search + * + * This is a collection of automatically created search results. These results are used by the global site search and will be updated automatically as documents in the CMS are created or updated. + */ +export type SearchResultPatchRequestBody = { + title?: string | null; + priority?: number | null; + /** + * ID of the posts + */ + doc?: string; + slug?: string | null; + meta?: { + title?: string | null; + description?: string | null; + image?: string | null | Media; + }; + categories?: Array<{ + relationTo?: string | null; + categoryID?: string | null; + title?: string | null; + id?: string | null; + }> | null; +}; + +/** + * PayloadKv + * + * Payload Kv + */ +export type PayloadKvRequestBody = { + key: string; + data: { + [key: string]: unknown; + } | Array | string | number | boolean | null; +}; + +/** + * PayloadKv + * + * Payload Kv + */ +export type PayloadKvPatchRequestBody = { + key?: string; + data?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; +}; + +/** + * PayloadJob + * + * Payload Job + */ +export type PayloadJobRequestBody = { + /** + * Input data provided to the job + */ + input?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + taskStatus?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + completedAt?: string | null; + totalTried?: number | null; + /** + * If hasError is true this job will not be retried + */ + hasError?: boolean | null; + /** + * If hasError is true, this is the error that caused it + */ + error?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + /** + * Task execution log + */ + log?: Array<{ + executedAt: string; + completedAt: string; + taskSlug: 'inline' | 'schedulePublish'; + taskID: string; + input?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + output?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + state: 'failed' | 'succeeded'; + error?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + id?: string | null; + }> | null; + taskSlug?: 'inline' | 'schedulePublish'; + queue?: string | null; + waitUntil?: string | null; + processing?: boolean | null; +}; + +/** + * PayloadJob + * + * Payload Job + */ +export type PayloadJobPatchRequestBody = { + /** + * Input data provided to the job + */ + input?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + taskStatus?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + completedAt?: string | null; + totalTried?: number | null; + /** + * If hasError is true this job will not be retried + */ + hasError?: boolean | null; + /** + * If hasError is true, this is the error that caused it + */ + error?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + /** + * Task execution log + */ + log?: Array<{ + executedAt: string; + completedAt: string; + taskSlug: 'inline' | 'schedulePublish'; + taskID: string; + input?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + output?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + state: 'failed' | 'succeeded'; + error?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; + id?: string | null; + }> | null; + taskSlug?: 'inline' | 'schedulePublish'; + queue?: string | null; + waitUntil?: string | null; + processing?: boolean | null; +}; + +/** + * FolderInterface + * + * Folder + */ +export type FolderRequestBody = { + name: string; + /** + * ID of the payload-folders + */ + folder?: string; + documentsAndFolders?: { + docs?: Array<{ + relationTo?: 'payload-folders'; + value: string | Folder; + } | { + relationTo?: 'media'; + value: string | Media; + }>; + hasNextPage?: boolean; + totalDocs?: number; + }; + folderType?: Array<'media'> | null; +}; + +/** + * FolderInterface + * + * Folder + */ +export type FolderPatchRequestBody = { + name?: string; + /** + * ID of the payload-folders + */ + folder?: string; + documentsAndFolders?: { + docs?: Array<{ + relationTo?: 'payload-folders'; + value: string | Folder; + } | { + relationTo?: 'media'; + value: string | Media; + }>; + hasNextPage?: boolean; + totalDocs?: number; + }; + folderType?: Array<'media'> | null; +}; + +/** + * PayloadLockedDocument + * + * Payload Locked Document + */ +export type PayloadLockedDocumentRequestBody = { + /** + * ID of the pages/posts/media/categories/users/tenants/redirects/forms/form-submissions/search/payload-folders + */ + document?: string; + globalSlug?: string | null; + /** + * ID of the users + */ + user: string; +}; + +/** + * PayloadLockedDocument + * + * Payload Locked Document + */ +export type PayloadLockedDocumentPatchRequestBody = { + /** + * ID of the pages/posts/media/categories/users/tenants/redirects/forms/form-submissions/search/payload-folders + */ + document?: string; + globalSlug?: string | null; + /** + * ID of the users + */ + user?: string; +}; + +/** + * PayloadPreference + * + * Payload Preference + */ +export type PayloadPreferenceRequestBody = { + /** + * ID of the users + */ + user: string; + key?: string | null; + value?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; +}; + +/** + * PayloadPreference + * + * Payload Preference + */ +export type PayloadPreferencePatchRequestBody = { + /** + * ID of the users + */ + user?: string; + key?: string | null; + value?: { + [key: string]: unknown; + } | Array | string | number | boolean | null; +}; + +/** + * PayloadMigration + * + * Payload Migration + */ +export type PayloadMigrationRequestBody = { + name?: string | null; + batch?: number | null; +}; + +/** + * PayloadMigration + * + * Payload Migration + */ +export type PayloadMigrationPatchRequestBody = { + name?: string | null; + batch?: number | null; +}; + +/** + * Header + */ +export type HeaderRequestBody = HeaderWrite; + +/** + * Footer + */ +export type FooterRequestBody = FooterWrite; + +export type ListPagesData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'title' | '-title' | 'publishedAt' | '-publishedAt' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (PageQueryOperations | PageQueryOperationsAnd | PageQueryOperationsOr); + }; + url: '/api/pages'; +}; + +export type ListPagesResponses = { + /** + * List of Pages + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListPagesResponse = ListPagesResponses[keyof ListPagesResponses]; + +export type CreatePageData = { + /** + * Page + */ + body?: PageRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/pages'; +}; + +export type CreatePageResponses = { + /** + * Page object + */ + 201: { + message: string; + doc: Page & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreatePageResponse = CreatePageResponses[keyof CreatePageResponses]; + +export type DeletePageData = { + body?: never; + path: { + /** + * ID of the Page + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/pages/{id}'; +}; + +export type DeletePageErrors = { + /** + * Page not found + */ + 404: unknown; +}; + +export type DeletePageResponses = { + /** + * Page object + */ + 200: Page; +}; + +export type DeletePageResponse = DeletePageResponses[keyof DeletePageResponses]; + +export type FindPageByIdData = { + body?: never; + path: { + /** + * ID of the Page + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/pages/{id}'; +}; + +export type FindPageByIdErrors = { + /** + * Page not found + */ + 404: unknown; +}; + +export type FindPageByIdResponses = { + /** + * Page object + */ + 200: Page; +}; + +export type FindPageByIdResponse = FindPageByIdResponses[keyof FindPageByIdResponses]; + +export type UpdatePageData = { + /** + * Page + */ + body?: PagePatchRequestBody; + path: { + /** + * ID of the Page + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/pages/{id}'; +}; + +export type UpdatePageErrors = { + /** + * Page not found + */ + 404: unknown; +}; + +export type UpdatePageResponses = { + /** + * Page object + */ + 200: Page; +}; + +export type UpdatePageResponse = UpdatePageResponses[keyof UpdatePageResponses]; + +export type ListPostsData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'title' | '-title' | 'publishedAt' | '-publishedAt' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (PostQueryOperations | PostQueryOperationsAnd | PostQueryOperationsOr); + }; + url: '/api/posts'; +}; + +export type ListPostsResponses = { + /** + * List of Posts + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListPostsResponse = ListPostsResponses[keyof ListPostsResponses]; + +export type CreatePostData = { + /** + * Post + */ + body?: PostRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/posts'; +}; + +export type CreatePostResponses = { + /** + * Post object + */ + 201: { + message: string; + doc: Post & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreatePostResponse = CreatePostResponses[keyof CreatePostResponses]; + +export type DeletePostData = { + body?: never; + path: { + /** + * ID of the Post + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/posts/{id}'; +}; + +export type DeletePostErrors = { + /** + * Post not found + */ + 404: unknown; +}; + +export type DeletePostResponses = { + /** + * Post object + */ + 200: Post; +}; + +export type DeletePostResponse = DeletePostResponses[keyof DeletePostResponses]; + +export type FindPostByIdData = { + body?: never; + path: { + /** + * ID of the Post + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/posts/{id}'; +}; + +export type FindPostByIdErrors = { + /** + * Post not found + */ + 404: unknown; +}; + +export type FindPostByIdResponses = { + /** + * Post object + */ + 200: Post; +}; + +export type FindPostByIdResponse = FindPostByIdResponses[keyof FindPostByIdResponses]; + +export type UpdatePostData = { + /** + * Post + */ + body?: PostPatchRequestBody; + path: { + /** + * ID of the Post + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/posts/{id}'; +}; + +export type UpdatePostErrors = { + /** + * Post not found + */ + 404: unknown; +}; + +export type UpdatePostResponses = { + /** + * Post object + */ + 200: Post; +}; + +export type UpdatePostResponse = UpdatePostResponses[keyof UpdatePostResponses]; + +export type ListMediaData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'alt' | '-alt' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt' | 'url' | '-url' | 'thumbnailURL' | '-thumbnailURL' | 'filename' | '-filename' | 'mimeType' | '-mimeType' | 'filesize' | '-filesize' | 'width' | '-width' | 'height' | '-height' | 'focalX' | '-focalX' | 'focalY' | '-focalY'; + where?: { + [key: string]: unknown; + } & (MediaQueryOperations | MediaQueryOperationsAnd | MediaQueryOperationsOr); + }; + url: '/api/media'; +}; + +export type ListMediaResponses = { + /** + * List of Media + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListMediaResponse = ListMediaResponses[keyof ListMediaResponses]; + +export type CreateMediaData = { + /** + * Media + */ + body?: MediaRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/media'; +}; + +export type CreateMediaResponses = { + /** + * Media object + */ + 201: { + message: string; + doc: Media & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreateMediaResponse = CreateMediaResponses[keyof CreateMediaResponses]; + +export type DeleteMediaData = { + body?: never; + path: { + /** + * ID of the Media + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/media/{id}'; +}; + +export type DeleteMediaErrors = { + /** + * Media not found + */ + 404: unknown; +}; + +export type DeleteMediaResponses = { + /** + * Media object + */ + 200: Media; +}; + +export type DeleteMediaResponse = DeleteMediaResponses[keyof DeleteMediaResponses]; + +export type FindMediaByIdData = { + body?: never; + path: { + /** + * ID of the Media + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/media/{id}'; +}; + +export type FindMediaByIdErrors = { + /** + * Media not found + */ + 404: unknown; +}; + +export type FindMediaByIdResponses = { + /** + * Media object + */ + 200: Media; +}; + +export type FindMediaByIdResponse = FindMediaByIdResponses[keyof FindMediaByIdResponses]; + +export type UpdateMediaData = { + /** + * Media + */ + body?: MediaPatchRequestBody; + path: { + /** + * ID of the Media + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/media/{id}'; +}; + +export type UpdateMediaErrors = { + /** + * Media not found + */ + 404: unknown; +}; + +export type UpdateMediaResponses = { + /** + * Media object + */ + 200: Media; +}; + +export type UpdateMediaResponse = UpdateMediaResponses[keyof UpdateMediaResponses]; + +export type ListCategoriesData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'title' | '-title' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (CategoryQueryOperations | CategoryQueryOperationsAnd | CategoryQueryOperationsOr); + }; + url: '/api/categories'; +}; + +export type ListCategoriesResponses = { + /** + * List of Categories + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListCategoriesResponse = ListCategoriesResponses[keyof ListCategoriesResponses]; + +export type CreateCategoryData = { + /** + * Category + */ + body?: CategoryRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/categories'; +}; + +export type CreateCategoryResponses = { + /** + * Category object + */ + 201: { + message: string; + doc: Category & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreateCategoryResponse = CreateCategoryResponses[keyof CreateCategoryResponses]; + +export type DeleteCategoryData = { + body?: never; + path: { + /** + * ID of the Category + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/categories/{id}'; +}; + +export type DeleteCategoryErrors = { + /** + * Category not found + */ + 404: unknown; +}; + +export type DeleteCategoryResponses = { + /** + * Category object + */ + 200: Category; +}; + +export type DeleteCategoryResponse = DeleteCategoryResponses[keyof DeleteCategoryResponses]; + +export type FindCategoryByIdData = { + body?: never; + path: { + /** + * ID of the Category + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/categories/{id}'; +}; + +export type FindCategoryByIdErrors = { + /** + * Category not found + */ + 404: unknown; +}; + +export type FindCategoryByIdResponses = { + /** + * Category object + */ + 200: Category; +}; + +export type FindCategoryByIdResponse = FindCategoryByIdResponses[keyof FindCategoryByIdResponses]; + +export type UpdateCategoryData = { + /** + * Category + */ + body?: CategoryPatchRequestBody; + path: { + /** + * ID of the Category + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/categories/{id}'; +}; + +export type UpdateCategoryErrors = { + /** + * Category not found + */ + 404: unknown; +}; + +export type UpdateCategoryResponses = { + /** + * Category object + */ + 200: Category; +}; + +export type UpdateCategoryResponse = UpdateCategoryResponses[keyof UpdateCategoryResponses]; + +export type ListUsersData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'id' | '-id' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (UserQueryOperations | UserQueryOperationsAnd | UserQueryOperationsOr); + }; + url: '/api/users'; +}; + +export type ListUsersResponses = { + /** + * List of Users + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListUsersResponse = ListUsersResponses[keyof ListUsersResponses]; + +export type CreateUserData = { + /** + * User + */ + body?: UserRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/users'; +}; + +export type CreateUserResponses = { + /** + * User object + */ + 201: { + message: string; + doc: User & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreateUserResponse = CreateUserResponses[keyof CreateUserResponses]; + +export type DeleteUserData = { + body?: never; + path: { + /** + * ID of the User + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/users/{id}'; +}; + +export type DeleteUserErrors = { + /** + * User not found + */ + 404: unknown; +}; + +export type DeleteUserResponses = { + /** + * User object + */ + 200: User; +}; + +export type DeleteUserResponse = DeleteUserResponses[keyof DeleteUserResponses]; + +export type FindUserByIdData = { + body?: never; + path: { + /** + * ID of the User + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/users/{id}'; +}; + +export type FindUserByIdErrors = { + /** + * User not found + */ + 404: unknown; +}; + +export type FindUserByIdResponses = { + /** + * User object + */ + 200: User; +}; + +export type FindUserByIdResponse = FindUserByIdResponses[keyof FindUserByIdResponses]; + +export type UpdateUserData = { + /** + * User + */ + body?: UserPatchRequestBody; + path: { + /** + * ID of the User + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/users/{id}'; +}; + +export type UpdateUserErrors = { + /** + * User not found + */ + 404: unknown; +}; + +export type UpdateUserResponses = { + /** + * User object + */ + 200: User; +}; + +export type UpdateUserResponse = UpdateUserResponses[keyof UpdateUserResponses]; + +export type ListTenantsData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'name' | '-name' | 'slug' | '-slug' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (TenantQueryOperations | TenantQueryOperationsAnd | TenantQueryOperationsOr); + }; + url: '/api/tenants'; +}; + +export type ListTenantsResponses = { + /** + * List of Tenants + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListTenantsResponse = ListTenantsResponses[keyof ListTenantsResponses]; + +export type CreateTenantData = { + /** + * Tenant + */ + body?: TenantRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/tenants'; +}; + +export type CreateTenantResponses = { + /** + * Tenant object + */ + 201: { + message: string; + doc: Tenant & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreateTenantResponse = CreateTenantResponses[keyof CreateTenantResponses]; + +export type DeleteTenantData = { + body?: never; + path: { + /** + * ID of the Tenant + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/tenants/{id}'; +}; + +export type DeleteTenantErrors = { + /** + * Tenant not found + */ + 404: unknown; +}; + +export type DeleteTenantResponses = { + /** + * Tenant object + */ + 200: Tenant; +}; + +export type DeleteTenantResponse = DeleteTenantResponses[keyof DeleteTenantResponses]; + +export type FindTenantByIdData = { + body?: never; + path: { + /** + * ID of the Tenant + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/tenants/{id}'; +}; + +export type FindTenantByIdErrors = { + /** + * Tenant not found + */ + 404: unknown; +}; + +export type FindTenantByIdResponses = { + /** + * Tenant object + */ + 200: Tenant; +}; + +export type FindTenantByIdResponse = FindTenantByIdResponses[keyof FindTenantByIdResponses]; + +export type UpdateTenantData = { + /** + * Tenant + */ + body?: TenantPatchRequestBody; + path: { + /** + * ID of the Tenant + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/tenants/{id}'; +}; + +export type UpdateTenantErrors = { + /** + * Tenant not found + */ + 404: unknown; +}; + +export type UpdateTenantResponses = { + /** + * Tenant object + */ + 200: Tenant; +}; + +export type UpdateTenantResponse = UpdateTenantResponses[keyof UpdateTenantResponses]; + +export type ListRedirectsData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'from' | '-from' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (RedirectQueryOperations | RedirectQueryOperationsAnd | RedirectQueryOperationsOr); + }; + url: '/api/redirects'; +}; + +export type ListRedirectsResponses = { + /** + * List of Redirects + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListRedirectsResponse = ListRedirectsResponses[keyof ListRedirectsResponses]; + +export type CreateRedirectData = { + /** + * Redirect + */ + body?: RedirectRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/redirects'; +}; + +export type CreateRedirectResponses = { + /** + * Redirect object + */ + 201: { + message: string; + doc: Redirect & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreateRedirectResponse = CreateRedirectResponses[keyof CreateRedirectResponses]; + +export type DeleteRedirectData = { + body?: never; + path: { + /** + * ID of the Redirect + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/redirects/{id}'; +}; + +export type DeleteRedirectErrors = { + /** + * Redirect not found + */ + 404: unknown; +}; + +export type DeleteRedirectResponses = { + /** + * Redirect object + */ + 200: Redirect; +}; + +export type DeleteRedirectResponse = DeleteRedirectResponses[keyof DeleteRedirectResponses]; + +export type FindRedirectByIdData = { + body?: never; + path: { + /** + * ID of the Redirect + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/redirects/{id}'; +}; + +export type FindRedirectByIdErrors = { + /** + * Redirect not found + */ + 404: unknown; +}; + +export type FindRedirectByIdResponses = { + /** + * Redirect object + */ + 200: Redirect; +}; + +export type FindRedirectByIdResponse = FindRedirectByIdResponses[keyof FindRedirectByIdResponses]; + +export type UpdateRedirectData = { + /** + * Redirect + */ + body?: RedirectPatchRequestBody; + path: { + /** + * ID of the Redirect + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/redirects/{id}'; +}; + +export type UpdateRedirectErrors = { + /** + * Redirect not found + */ + 404: unknown; +}; + +export type UpdateRedirectResponses = { + /** + * Redirect object + */ + 200: Redirect; +}; + +export type UpdateRedirectResponse = UpdateRedirectResponses[keyof UpdateRedirectResponses]; + +export type ListFormsData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'title' | '-title' | 'submitButtonLabel' | '-submitButtonLabel' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (FormQueryOperations | FormQueryOperationsAnd | FormQueryOperationsOr); + }; + url: '/api/forms'; +}; + +export type ListFormsResponses = { + /** + * List of Forms + */ + 200: { + docs: Array
; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListFormsResponse = ListFormsResponses[keyof ListFormsResponses]; + +export type CreateFormData = { + /** + * Form + */ + body?: FormRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/forms'; +}; + +export type CreateFormResponses = { + /** + * Form object + */ + 201: { + message: string; + doc: Form & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreateFormResponse = CreateFormResponses[keyof CreateFormResponses]; + +export type DeleteFormData = { + body?: never; + path: { + /** + * ID of the Form + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/forms/{id}'; +}; + +export type DeleteFormErrors = { + /** + * Form not found + */ + 404: unknown; +}; + +export type DeleteFormResponses = { + /** + * Form object + */ + 200: Form; +}; + +export type DeleteFormResponse = DeleteFormResponses[keyof DeleteFormResponses]; + +export type FindFormByIdData = { + body?: never; + path: { + /** + * ID of the Form + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/forms/{id}'; +}; + +export type FindFormByIdErrors = { + /** + * Form not found + */ + 404: unknown; +}; + +export type FindFormByIdResponses = { + /** + * Form object + */ + 200: Form; +}; + +export type FindFormByIdResponse = FindFormByIdResponses[keyof FindFormByIdResponses]; + +export type UpdateFormData = { + /** + * Form + */ + body?: FormPatchRequestBody; + path: { + /** + * ID of the Form + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/forms/{id}'; +}; + +export type UpdateFormErrors = { + /** + * Form not found + */ + 404: unknown; +}; + +export type UpdateFormResponses = { + /** + * Form object + */ + 200: Form; +}; + +export type UpdateFormResponse = UpdateFormResponses[keyof UpdateFormResponses]; + +export type ListFormSubmissionsData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (FormSubmissionQueryOperations | FormSubmissionQueryOperationsAnd | FormSubmissionQueryOperationsOr); + }; + url: '/api/form-submissions'; +}; + +export type ListFormSubmissionsResponses = { + /** + * List of Form Submissions + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListFormSubmissionsResponse = ListFormSubmissionsResponses[keyof ListFormSubmissionsResponses]; + +export type CreateFormSubmissionData = { + /** + * Form Submission + */ + body?: FormSubmissionRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/form-submissions'; +}; + +export type CreateFormSubmissionResponses = { + /** + * Form Submission object + */ + 201: { + message: string; + doc: FormSubmission & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreateFormSubmissionResponse = CreateFormSubmissionResponses[keyof CreateFormSubmissionResponses]; + +export type DeleteFormSubmissionData = { + body?: never; + path: { + /** + * ID of the Form Submission + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/form-submissions/{id}'; +}; + +export type DeleteFormSubmissionErrors = { + /** + * Form Submission not found + */ + 404: unknown; +}; + +export type DeleteFormSubmissionResponses = { + /** + * Form Submission object + */ + 200: FormSubmission; +}; + +export type DeleteFormSubmissionResponse = DeleteFormSubmissionResponses[keyof DeleteFormSubmissionResponses]; + +export type FindFormSubmissionByIdData = { + body?: never; + path: { + /** + * ID of the Form Submission + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/form-submissions/{id}'; +}; + +export type FindFormSubmissionByIdErrors = { + /** + * Form Submission not found + */ + 404: unknown; +}; + +export type FindFormSubmissionByIdResponses = { + /** + * Form Submission object + */ + 200: FormSubmission; +}; + +export type FindFormSubmissionByIdResponse = FindFormSubmissionByIdResponses[keyof FindFormSubmissionByIdResponses]; + +export type UpdateFormSubmissionData = { + /** + * Form Submission + */ + body?: FormSubmissionPatchRequestBody; + path: { + /** + * ID of the Form Submission + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/form-submissions/{id}'; +}; + +export type UpdateFormSubmissionErrors = { + /** + * Form Submission not found + */ + 404: unknown; +}; + +export type UpdateFormSubmissionResponses = { + /** + * Form Submission object + */ + 200: FormSubmission; +}; + +export type UpdateFormSubmissionResponse = UpdateFormSubmissionResponses[keyof UpdateFormSubmissionResponses]; + +export type ListSearchResultsData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'title' | '-title' | 'priority' | '-priority' | 'slug' | '-slug' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (SearchResultQueryOperations | SearchResultQueryOperationsAnd | SearchResultQueryOperationsOr); + }; + url: '/api/search'; +}; + +export type ListSearchResultsResponses = { + /** + * List of Search Results + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListSearchResultsResponse = ListSearchResultsResponses[keyof ListSearchResultsResponses]; + +export type CreateSearchResultData = { + /** + * Search Result + */ + body?: SearchResultRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/search'; +}; + +export type CreateSearchResultResponses = { + /** + * Search Result object + */ + 201: { + message: string; + doc: SearchResult & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreateSearchResultResponse = CreateSearchResultResponses[keyof CreateSearchResultResponses]; + +export type DeleteSearchResultData = { + body?: never; + path: { + /** + * ID of the Search Result + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/search/{id}'; +}; + +export type DeleteSearchResultErrors = { + /** + * Search Result not found + */ + 404: unknown; +}; + +export type DeleteSearchResultResponses = { + /** + * Search Result object + */ + 200: SearchResult; +}; + +export type DeleteSearchResultResponse = DeleteSearchResultResponses[keyof DeleteSearchResultResponses]; + +export type FindSearchResultByIdData = { + body?: never; + path: { + /** + * ID of the Search Result + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/search/{id}'; +}; + +export type FindSearchResultByIdErrors = { + /** + * Search Result not found + */ + 404: unknown; +}; + +export type FindSearchResultByIdResponses = { + /** + * Search Result object + */ + 200: SearchResult; +}; + +export type FindSearchResultByIdResponse = FindSearchResultByIdResponses[keyof FindSearchResultByIdResponses]; + +export type UpdateSearchResultData = { + /** + * Search Result + */ + body?: SearchResultPatchRequestBody; + path: { + /** + * ID of the Search Result + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/search/{id}'; +}; + +export type UpdateSearchResultErrors = { + /** + * Search Result not found + */ + 404: unknown; +}; + +export type UpdateSearchResultResponses = { + /** + * Search Result object + */ + 200: SearchResult; +}; + +export type UpdateSearchResultResponse = UpdateSearchResultResponses[keyof UpdateSearchResultResponses]; + +export type ListPayloadKvsData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'key' | '-key'; + where?: { + [key: string]: unknown; + } & (PayloadKvQueryOperations | PayloadKvQueryOperationsAnd | PayloadKvQueryOperationsOr); + }; + url: '/api/payload-kv'; +}; + +export type ListPayloadKvsResponses = { + /** + * List of Payload Kvs + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListPayloadKvsResponse = ListPayloadKvsResponses[keyof ListPayloadKvsResponses]; + +export type CreatePayloadKvData = { + /** + * Payload Kv + */ + body?: PayloadKvRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/payload-kv'; +}; + +export type CreatePayloadKvResponses = { + /** + * Payload Kv object + */ + 201: { + message: string; + doc: PayloadKv & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreatePayloadKvResponse = CreatePayloadKvResponses[keyof CreatePayloadKvResponses]; + +export type DeletePayloadKvData = { + body?: never; + path: { + /** + * ID of the Payload Kv + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-kv/{id}'; +}; + +export type DeletePayloadKvErrors = { + /** + * Payload Kv not found + */ + 404: unknown; +}; + +export type DeletePayloadKvResponses = { + /** + * Payload Kv object + */ + 200: PayloadKv; +}; + +export type DeletePayloadKvResponse = DeletePayloadKvResponses[keyof DeletePayloadKvResponses]; + +export type FindPayloadKvByIdData = { + body?: never; + path: { + /** + * ID of the Payload Kv + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-kv/{id}'; +}; + +export type FindPayloadKvByIdErrors = { + /** + * Payload Kv not found + */ + 404: unknown; +}; + +export type FindPayloadKvByIdResponses = { + /** + * Payload Kv object + */ + 200: PayloadKv; +}; + +export type FindPayloadKvByIdResponse = FindPayloadKvByIdResponses[keyof FindPayloadKvByIdResponses]; + +export type UpdatePayloadKvData = { + /** + * Payload Kv + */ + body?: PayloadKvPatchRequestBody; + path: { + /** + * ID of the Payload Kv + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-kv/{id}'; +}; + +export type UpdatePayloadKvErrors = { + /** + * Payload Kv not found + */ + 404: unknown; +}; + +export type UpdatePayloadKvResponses = { + /** + * Payload Kv object + */ + 200: PayloadKv; +}; + +export type UpdatePayloadKvResponse = UpdatePayloadKvResponses[keyof UpdatePayloadKvResponses]; + +export type ListPayloadJobsData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'queue' | '-queue' | 'waitUntil' | '-waitUntil' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (PayloadJobQueryOperations | PayloadJobQueryOperationsAnd | PayloadJobQueryOperationsOr); + }; + url: '/api/payload-jobs'; +}; + +export type ListPayloadJobsResponses = { + /** + * List of Payload Jobs + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListPayloadJobsResponse = ListPayloadJobsResponses[keyof ListPayloadJobsResponses]; + +export type CreatePayloadJobData = { + /** + * Payload Job + */ + body?: PayloadJobRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/payload-jobs'; +}; + +export type CreatePayloadJobResponses = { + /** + * Payload Job object + */ + 201: { + message: string; + doc: PayloadJob & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreatePayloadJobResponse = CreatePayloadJobResponses[keyof CreatePayloadJobResponses]; + +export type DeletePayloadJobData = { + body?: never; + path: { + /** + * ID of the Payload Job + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-jobs/{id}'; +}; + +export type DeletePayloadJobErrors = { + /** + * Payload Job not found + */ + 404: unknown; +}; + +export type DeletePayloadJobResponses = { + /** + * Payload Job object + */ + 200: PayloadJob; +}; + +export type DeletePayloadJobResponse = DeletePayloadJobResponses[keyof DeletePayloadJobResponses]; + +export type FindPayloadJobByIdData = { + body?: never; + path: { + /** + * ID of the Payload Job + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-jobs/{id}'; +}; + +export type FindPayloadJobByIdErrors = { + /** + * Payload Job not found + */ + 404: unknown; +}; + +export type FindPayloadJobByIdResponses = { + /** + * Payload Job object + */ + 200: PayloadJob; +}; + +export type FindPayloadJobByIdResponse = FindPayloadJobByIdResponses[keyof FindPayloadJobByIdResponses]; + +export type UpdatePayloadJobData = { + /** + * Payload Job + */ + body?: PayloadJobPatchRequestBody; + path: { + /** + * ID of the Payload Job + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-jobs/{id}'; +}; + +export type UpdatePayloadJobErrors = { + /** + * Payload Job not found + */ + 404: unknown; +}; + +export type UpdatePayloadJobResponses = { + /** + * Payload Job object + */ + 200: PayloadJob; +}; + +export type UpdatePayloadJobResponse = UpdatePayloadJobResponses[keyof UpdatePayloadJobResponses]; + +export type ListFoldersData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'name' | '-name' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (FolderQueryOperations | FolderQueryOperationsAnd | FolderQueryOperationsOr); + }; + url: '/api/payload-folders'; +}; + +export type ListFoldersResponses = { + /** + * List of Folders + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListFoldersResponse = ListFoldersResponses[keyof ListFoldersResponses]; + +export type CreateFolderData = { + /** + * Folder + */ + body?: FolderRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/payload-folders'; +}; + +export type CreateFolderResponses = { + /** + * Folder object + */ + 201: { + message: string; + doc: Folder & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreateFolderResponse = CreateFolderResponses[keyof CreateFolderResponses]; + +export type DeleteFolderData = { + body?: never; + path: { + /** + * ID of the Folder + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-folders/{id}'; +}; + +export type DeleteFolderErrors = { + /** + * Folder not found + */ + 404: unknown; +}; + +export type DeleteFolderResponses = { + /** + * Folder object + */ + 200: Folder; +}; + +export type DeleteFolderResponse = DeleteFolderResponses[keyof DeleteFolderResponses]; + +export type FindFolderByIdData = { + body?: never; + path: { + /** + * ID of the Folder + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-folders/{id}'; +}; + +export type FindFolderByIdErrors = { + /** + * Folder not found + */ + 404: unknown; +}; + +export type FindFolderByIdResponses = { + /** + * Folder object + */ + 200: Folder; +}; + +export type FindFolderByIdResponse = FindFolderByIdResponses[keyof FindFolderByIdResponses]; + +export type UpdateFolderData = { + /** + * Folder + */ + body?: FolderPatchRequestBody; + path: { + /** + * ID of the Folder + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-folders/{id}'; +}; + +export type UpdateFolderErrors = { + /** + * Folder not found + */ + 404: unknown; +}; + +export type UpdateFolderResponses = { + /** + * Folder object + */ + 200: Folder; +}; + +export type UpdateFolderResponse = UpdateFolderResponses[keyof UpdateFolderResponses]; + +export type ListPayloadLockedDocumentsData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'globalSlug' | '-globalSlug' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (PayloadLockedDocumentQueryOperations | PayloadLockedDocumentQueryOperationsAnd | PayloadLockedDocumentQueryOperationsOr); + }; + url: '/api/payload-locked-documents'; +}; + +export type ListPayloadLockedDocumentsResponses = { + /** + * List of Payload Locked Documents + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListPayloadLockedDocumentsResponse = ListPayloadLockedDocumentsResponses[keyof ListPayloadLockedDocumentsResponses]; + +export type CreatePayloadLockedDocumentData = { + /** + * Payload Locked Document + */ + body?: PayloadLockedDocumentRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/payload-locked-documents'; +}; + +export type CreatePayloadLockedDocumentResponses = { + /** + * Payload Locked Document object + */ + 201: { + message: string; + doc: PayloadLockedDocument & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreatePayloadLockedDocumentResponse = CreatePayloadLockedDocumentResponses[keyof CreatePayloadLockedDocumentResponses]; + +export type DeletePayloadLockedDocumentData = { + body?: never; + path: { + /** + * ID of the Payload Locked Document + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-locked-documents/{id}'; +}; + +export type DeletePayloadLockedDocumentErrors = { + /** + * Payload Locked Document not found + */ + 404: unknown; +}; + +export type DeletePayloadLockedDocumentResponses = { + /** + * Payload Locked Document object + */ + 200: PayloadLockedDocument; +}; + +export type DeletePayloadLockedDocumentResponse = DeletePayloadLockedDocumentResponses[keyof DeletePayloadLockedDocumentResponses]; + +export type FindPayloadLockedDocumentByIdData = { + body?: never; + path: { + /** + * ID of the Payload Locked Document + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-locked-documents/{id}'; +}; + +export type FindPayloadLockedDocumentByIdErrors = { + /** + * Payload Locked Document not found + */ + 404: unknown; +}; + +export type FindPayloadLockedDocumentByIdResponses = { + /** + * Payload Locked Document object + */ + 200: PayloadLockedDocument; +}; + +export type FindPayloadLockedDocumentByIdResponse = FindPayloadLockedDocumentByIdResponses[keyof FindPayloadLockedDocumentByIdResponses]; + +export type UpdatePayloadLockedDocumentData = { + /** + * Payload Locked Document + */ + body?: PayloadLockedDocumentPatchRequestBody; + path: { + /** + * ID of the Payload Locked Document + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-locked-documents/{id}'; +}; + +export type UpdatePayloadLockedDocumentErrors = { + /** + * Payload Locked Document not found + */ + 404: unknown; +}; + +export type UpdatePayloadLockedDocumentResponses = { + /** + * Payload Locked Document object + */ + 200: PayloadLockedDocument; +}; + +export type UpdatePayloadLockedDocumentResponse = UpdatePayloadLockedDocumentResponses[keyof UpdatePayloadLockedDocumentResponses]; + +export type ListPayloadPreferencesData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'key' | '-key' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (PayloadPreferenceQueryOperations | PayloadPreferenceQueryOperationsAnd | PayloadPreferenceQueryOperationsOr); + }; + url: '/api/payload-preferences'; +}; + +export type ListPayloadPreferencesResponses = { + /** + * List of Payload Preferences + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListPayloadPreferencesResponse = ListPayloadPreferencesResponses[keyof ListPayloadPreferencesResponses]; + +export type CreatePayloadPreferenceData = { + /** + * Payload Preference + */ + body?: PayloadPreferenceRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/payload-preferences'; +}; + +export type CreatePayloadPreferenceResponses = { + /** + * Payload Preference object + */ + 201: { + message: string; + doc: PayloadPreference & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreatePayloadPreferenceResponse = CreatePayloadPreferenceResponses[keyof CreatePayloadPreferenceResponses]; + +export type DeletePayloadPreferenceData = { + body?: never; + path: { + /** + * ID of the Payload Preference + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-preferences/{id}'; +}; + +export type DeletePayloadPreferenceErrors = { + /** + * Payload Preference not found + */ + 404: unknown; +}; + +export type DeletePayloadPreferenceResponses = { + /** + * Payload Preference object + */ + 200: PayloadPreference; +}; + +export type DeletePayloadPreferenceResponse = DeletePayloadPreferenceResponses[keyof DeletePayloadPreferenceResponses]; + +export type FindPayloadPreferenceByIdData = { + body?: never; + path: { + /** + * ID of the Payload Preference + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-preferences/{id}'; +}; + +export type FindPayloadPreferenceByIdErrors = { + /** + * Payload Preference not found + */ + 404: unknown; +}; + +export type FindPayloadPreferenceByIdResponses = { + /** + * Payload Preference object + */ + 200: PayloadPreference; +}; + +export type FindPayloadPreferenceByIdResponse = FindPayloadPreferenceByIdResponses[keyof FindPayloadPreferenceByIdResponses]; + +export type UpdatePayloadPreferenceData = { + /** + * Payload Preference + */ + body?: PayloadPreferencePatchRequestBody; + path: { + /** + * ID of the Payload Preference + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-preferences/{id}'; +}; + +export type UpdatePayloadPreferenceErrors = { + /** + * Payload Preference not found + */ + 404: unknown; +}; + +export type UpdatePayloadPreferenceResponses = { + /** + * Payload Preference object + */ + 200: PayloadPreference; +}; + +export type UpdatePayloadPreferenceResponse = UpdatePayloadPreferenceResponses[keyof UpdatePayloadPreferenceResponses]; + +export type ListPayloadMigrationsData = { + body?: never; + path?: never; + query?: { + page?: number; + limit?: number; + depth?: number; + locale?: string; + 'fallback-locale'?: string; + sort?: 'name' | '-name' | 'batch' | '-batch' | 'updatedAt' | '-updatedAt' | 'createdAt' | '-createdAt'; + where?: { + [key: string]: unknown; + } & (PayloadMigrationQueryOperations | PayloadMigrationQueryOperationsAnd | PayloadMigrationQueryOperationsOr); + }; + url: '/api/payload-migrations'; +}; + +export type ListPayloadMigrationsResponses = { + /** + * List of Payload Migrations + */ + 200: { + docs: Array; + totalDocs: number; + limit: number; + totalPages: number; + page: number; + pagingCounter: number; + hasPrevPage: boolean; + hasNextPage: boolean; + prevPage: number | null; + nextPage: number | null; + }; +}; + +export type ListPayloadMigrationsResponse = ListPayloadMigrationsResponses[keyof ListPayloadMigrationsResponses]; + +export type CreatePayloadMigrationData = { + /** + * Payload Migration + */ + body?: PayloadMigrationRequestBody; + path?: never; + query?: { + depth?: number; + locale?: string; + }; + url: '/api/payload-migrations'; +}; + +export type CreatePayloadMigrationResponses = { + /** + * Payload Migration object + */ + 201: { + message: string; + doc: PayloadMigration & { + id: string; + createdAt: string; + updatedAt: string; + }; + }; +}; + +export type CreatePayloadMigrationResponse = CreatePayloadMigrationResponses[keyof CreatePayloadMigrationResponses]; + +export type DeletePayloadMigrationData = { + body?: never; + path: { + /** + * ID of the Payload Migration + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-migrations/{id}'; +}; + +export type DeletePayloadMigrationErrors = { + /** + * Payload Migration not found + */ + 404: unknown; +}; + +export type DeletePayloadMigrationResponses = { + /** + * Payload Migration object + */ + 200: PayloadMigration; +}; + +export type DeletePayloadMigrationResponse = DeletePayloadMigrationResponses[keyof DeletePayloadMigrationResponses]; + +export type FindPayloadMigrationByIdData = { + body?: never; + path: { + /** + * ID of the Payload Migration + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-migrations/{id}'; +}; + +export type FindPayloadMigrationByIdErrors = { + /** + * Payload Migration not found + */ + 404: unknown; +}; + +export type FindPayloadMigrationByIdResponses = { + /** + * Payload Migration object + */ + 200: PayloadMigration; +}; + +export type FindPayloadMigrationByIdResponse = FindPayloadMigrationByIdResponses[keyof FindPayloadMigrationByIdResponses]; + +export type UpdatePayloadMigrationData = { + /** + * Payload Migration + */ + body?: PayloadMigrationPatchRequestBody; + path: { + /** + * ID of the Payload Migration + */ + id: string; + }; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/payload-migrations/{id}'; +}; + +export type UpdatePayloadMigrationErrors = { + /** + * Payload Migration not found + */ + 404: unknown; +}; + +export type UpdatePayloadMigrationResponses = { + /** + * Payload Migration object + */ + 200: PayloadMigration; +}; + +export type UpdatePayloadMigrationResponse = UpdatePayloadMigrationResponses[keyof UpdatePayloadMigrationResponses]; + +export type GetApiGlobalsHeaderData = { + body?: never; + path?: never; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/globals/header'; +}; + +export type GetApiGlobalsHeaderResponses = { + /** + * Header + */ + 200: HeaderRead; +}; + +export type GetApiGlobalsHeaderResponse = GetApiGlobalsHeaderResponses[keyof GetApiGlobalsHeaderResponses]; + +export type PostApiGlobalsHeaderData = { + /** + * Header + */ + body?: HeaderRequestBody; + path?: never; + query?: never; + url: '/api/globals/header'; +}; + +export type PostApiGlobalsHeaderResponses = { + /** + * Header + */ + 200: HeaderRead; +}; + +export type PostApiGlobalsHeaderResponse = PostApiGlobalsHeaderResponses[keyof PostApiGlobalsHeaderResponses]; + +export type GetApiGlobalsFooterData = { + body?: never; + path?: never; + query?: { + depth?: number; + locale?: string; + 'fallback-locale'?: string; + }; + url: '/api/globals/footer'; +}; + +export type GetApiGlobalsFooterResponses = { + /** + * Footer + */ + 200: FooterRead; +}; + +export type GetApiGlobalsFooterResponse = GetApiGlobalsFooterResponses[keyof GetApiGlobalsFooterResponses]; + +export type PostApiGlobalsFooterData = { + /** + * Footer + */ + body?: FooterRequestBody; + path?: never; + query?: never; + url: '/api/globals/footer'; +}; + +export type PostApiGlobalsFooterResponses = { + /** + * Footer + */ + 200: FooterRead; +}; + +export type PostApiGlobalsFooterResponse = PostApiGlobalsFooterResponses[keyof PostApiGlobalsFooterResponses]; diff --git a/src/components/Footer.astro b/src/components/Footer.astro new file mode 100644 index 0000000..d6c92ec --- /dev/null +++ b/src/components/Footer.astro @@ -0,0 +1,10 @@ +--- +--- +
+
+

Powered by TenantCMS

+

+ Using X-Tenant-Slug for multi-tenant authentication +

+
+
diff --git a/src/components/Header.astro b/src/components/Header.astro new file mode 100644 index 0000000..054f52e --- /dev/null +++ b/src/components/Header.astro @@ -0,0 +1,15 @@ +--- +--- +
+
+
+

+ TenantCMS Demo +

+ +
+
+
diff --git a/src/components/PostCard.astro b/src/components/PostCard.astro new file mode 100644 index 0000000..6a2844b --- /dev/null +++ b/src/components/PostCard.astro @@ -0,0 +1,30 @@ +--- +interface Props { + title: string + excerpt: string + category?: string + date: string + slug: string +} + +const { title, excerpt, category, date, slug } = Astro.props +--- + + +
+ {category && ( + + {category} + + )} + {date} +
+

{title}

+

{excerpt}

+
+ 阅读更多 + + + +
+
diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..7c818df --- /dev/null +++ b/src/config.ts @@ -0,0 +1,3 @@ +export const TENANT_SLUG = "zitadel-example" +export const TENANT_API_KEY = "tenant_new-tenant_jau52FifQXXfnPufibP4NXXu54tHbWRQ5cEdh27j" +export const API_URL = "http://localhost:3000" diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro new file mode 100644 index 0000000..99d1fa5 --- /dev/null +++ b/src/layouts/Layout.astro @@ -0,0 +1,22 @@ +--- +import '../styles/global.css' + +interface Props { + title: string +} + +const { title } = Astro.props +--- + + + + + + + + {title} + + + + + diff --git a/src/pages/categories/[slug].astro b/src/pages/categories/[slug].astro new file mode 100644 index 0000000..6e8481b --- /dev/null +++ b/src/pages/categories/[slug].astro @@ -0,0 +1,101 @@ +--- +export const prerender = false + +import Layout from '../../layouts/Layout.astro' +import Header from '../../components/Header.astro' +import Footer from '../../components/Footer.astro' +import PostCard from '../../components/PostCard.astro' +import { Posts, Categories as CategoriesAPI } from '../../clientsdk/sdk.gen' +import { createClient } from '../../clientsdk/client' +import { customQuerySerializer } from '../../clientsdk/querySerializer' +import { TENANT_SLUG, TENANT_API_KEY, API_URL } from '../../config' +import type { Post } from '../../clientsdk/types.gen' + +const { slug } = Astro.params + +const client = createClient({ + baseUrl: API_URL, + querySerializer: customQuerySerializer, + headers: { + 'X-Tenant-Slug': TENANT_SLUG, + 'X-API-Key': TENANT_API_KEY, + }, +}) + +const [categoriesRes, postsRes] = await Promise.all([ + // Use listCategories with where filter since findCategoryById doesn't support slug lookup + CategoriesAPI.listCategories({ + client, + query: { + where: { + slug: { + equals: slug, + }, + }, + limit: 1, + }, + }), + Posts.listPosts({ + client, + query: { + limit: 100, + sort: '-createdAt', + }, + }), +]) + +const category = (categoriesRes as any)?.data?.docs?.[0] +const allDocs = (postsRes as any)?.data?.docs || [] +// categories is an array, check if any category in the array matches the slug +const categoryPosts = allDocs.filter((post: any) => + post.categories?.some((cat: any) => cat.slug === slug) +) + +const error = categoryPosts.length === 0 ? '该分类下暂无文章' : null + +const stripHtml = (html: string): string => { + if (!html) return '' + return html.replace(/<[^>]*>/g, '').trim() +} + +const formatDate = (dateString: string): string => { + const date = new Date(dateString) + return date.toLocaleDateString('zh-CN', { + year: 'numeric', + month: 'long', + day: 'numeric', + }) +} +--- + +
+ +
+
+

+ 📂 {category?.title || '分类'} +

+

探索该分类下的所有内容

+
+ + {error && ( +
+

{error}

+
+ )} + +
+ {categoryPosts.map((post: Post) => ( + + ))} +
+
+ +