templates: add support for scheduled publish to the website template [no lint] (#10455)
Adds configuration for vercel cron jobs and scheduled publish/unpublish in website templates
This commit is contained in:
@@ -95,7 +95,7 @@ async function main() {
|
|||||||
encodeURI(
|
encodeURI(
|
||||||
`${templateRepoUrlBase}/with-vercel-website` +
|
`${templateRepoUrlBase}/with-vercel-website` +
|
||||||
'&project-name=payload-project' +
|
'&project-name=payload-project' +
|
||||||
'&env=PAYLOAD_SECRET' +
|
'&env=PAYLOAD_SECRET%2CCRON_SECRET' +
|
||||||
'&build-command=pnpm run ci' +
|
'&build-command=pnpm run ci' +
|
||||||
'&stores=[{"type":"postgres"},{"type":"blob"}]', // Postgres and Vercel Blob Storage
|
'&stores=[{"type":"postgres"},{"type":"blob"}]', // Postgres and Vercel Blob Storage
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -9,3 +9,6 @@ PAYLOAD_SECRET=YOUR_SECRET_HERE
|
|||||||
|
|
||||||
# Used to configure CORS, format links and more. No trailing slash
|
# Used to configure CORS, format links and more. No trailing slash
|
||||||
NEXT_PUBLIC_SERVER_URL=http://localhost:3000
|
NEXT_PUBLIC_SERVER_URL=http://localhost:3000
|
||||||
|
|
||||||
|
# Secret used to authenticate cron jobs
|
||||||
|
CRON_SECRET=YOUR_CRON_SECRET_HERE
|
||||||
|
|||||||
@@ -179,6 +179,38 @@ Although Next.js includes a robust set of caching strategies out of the box, Pay
|
|||||||
|
|
||||||
To spin up this example locally, follow the [Quick Start](#quick-start). Then [Seed](#seed) the database with a few pages, posts, and projects.
|
To spin up this example locally, follow the [Quick Start](#quick-start). Then [Seed](#seed) the database with a few pages, posts, and projects.
|
||||||
|
|
||||||
|
### Working with Postgres
|
||||||
|
|
||||||
|
Postgres and other SQL-based databases follow a strict schema for managing your data. In comparison to our MongoDB adapter, this means that there's a few extra steps to working with Postgres.
|
||||||
|
|
||||||
|
Note that often times when making big schema changes you can run the risk of losing data if you're not manually migrating it.
|
||||||
|
|
||||||
|
#### Local development
|
||||||
|
|
||||||
|
Ideally we recommend running a local copy of your database so that schema updates are as fast as possible. By default the Postgres adapter has `push: true` for development environments. This will let you add, modify and remove fields and collections without needing to run any data migrations.
|
||||||
|
|
||||||
|
If your database is pointed to production you will want to set `push: false` otherwise you will risk losing data or having your migrations out of sync.
|
||||||
|
|
||||||
|
#### Migrations
|
||||||
|
|
||||||
|
[Migrations](https://payloadcms.com/docs/database/migrations) are essentially SQL code versions that keeps track of your schema. When deploy with Postgres you will need to make sure you create and then run your migrations.
|
||||||
|
|
||||||
|
Locally create a migration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm payload migrate:create
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates the migration files you will need to push alongside with your new configuration.
|
||||||
|
|
||||||
|
On the server after building and before running `pnpm start` you will want to run your migrations
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm payload migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
This command will check for any migrations that have not yet been run and try to run them and it will keep a record of migrations that have been run in the database.
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
Alternatively, you can use [Docker](https://www.docker.com) to spin up this template locally. To do so, follow these steps:
|
Alternatively, you can use [Docker](https://www.docker.com) to spin up this template locally. To do so, follow these steps:
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ export const Pages: CollectionConfig<'pages'> = {
|
|||||||
autosave: {
|
autosave: {
|
||||||
interval: 100, // We set this interval for optimal live preview
|
interval: 100, // We set this interval for optimal live preview
|
||||||
},
|
},
|
||||||
|
schedulePublish: true,
|
||||||
},
|
},
|
||||||
maxPerDoc: 50,
|
maxPerDoc: 50,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ export const Posts: CollectionConfig<'posts'> = {
|
|||||||
autosave: {
|
autosave: {
|
||||||
interval: 100, // We set this interval for optimal live preview
|
interval: 100, // We set this interval for optimal live preview
|
||||||
},
|
},
|
||||||
|
schedulePublish: true,
|
||||||
},
|
},
|
||||||
maxPerDoc: 50,
|
maxPerDoc: 50,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export interface Config {
|
|||||||
forms: Form;
|
forms: Form;
|
||||||
'form-submissions': FormSubmission;
|
'form-submissions': FormSubmission;
|
||||||
search: Search;
|
search: Search;
|
||||||
|
'payload-jobs': PayloadJob;
|
||||||
'payload-locked-documents': PayloadLockedDocument;
|
'payload-locked-documents': PayloadLockedDocument;
|
||||||
'payload-preferences': PayloadPreference;
|
'payload-preferences': PayloadPreference;
|
||||||
'payload-migrations': PayloadMigration;
|
'payload-migrations': PayloadMigration;
|
||||||
@@ -35,6 +36,7 @@ export interface Config {
|
|||||||
forms: FormsSelect<false> | FormsSelect<true>;
|
forms: FormsSelect<false> | FormsSelect<true>;
|
||||||
'form-submissions': FormSubmissionsSelect<false> | FormSubmissionsSelect<true>;
|
'form-submissions': FormSubmissionsSelect<false> | FormSubmissionsSelect<true>;
|
||||||
search: SearchSelect<false> | SearchSelect<true>;
|
search: SearchSelect<false> | SearchSelect<true>;
|
||||||
|
'payload-jobs': PayloadJobsSelect<false> | PayloadJobsSelect<true>;
|
||||||
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
||||||
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
|
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
|
||||||
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
|
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
|
||||||
@@ -55,7 +57,13 @@ export interface Config {
|
|||||||
collection: 'users';
|
collection: 'users';
|
||||||
};
|
};
|
||||||
jobs: {
|
jobs: {
|
||||||
tasks: unknown;
|
tasks: {
|
||||||
|
schedulePublish: TaskSchedulePublish;
|
||||||
|
inline: {
|
||||||
|
input: unknown;
|
||||||
|
output: unknown;
|
||||||
|
};
|
||||||
|
};
|
||||||
workflows: unknown;
|
workflows: unknown;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -735,6 +743,98 @@ export interface Search {
|
|||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "payload-jobs".
|
||||||
|
*/
|
||||||
|
export interface PayloadJob {
|
||||||
|
id: string;
|
||||||
|
/**
|
||||||
|
* Input data provided to the job
|
||||||
|
*/
|
||||||
|
input?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
taskStatus?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| 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?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
/**
|
||||||
|
* Task execution log
|
||||||
|
*/
|
||||||
|
log?:
|
||||||
|
| {
|
||||||
|
executedAt: string;
|
||||||
|
completedAt: string;
|
||||||
|
taskSlug: 'inline' | 'schedulePublish';
|
||||||
|
taskID: string;
|
||||||
|
input?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
output?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
state: 'failed' | 'succeeded';
|
||||||
|
error?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
|
taskSlug?: ('inline' | 'schedulePublish') | null;
|
||||||
|
queue?: string | null;
|
||||||
|
waitUntil?: string | null;
|
||||||
|
processing?: boolean | null;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-locked-documents".
|
* via the `definition` "payload-locked-documents".
|
||||||
@@ -777,6 +877,10 @@ export interface PayloadLockedDocument {
|
|||||||
| ({
|
| ({
|
||||||
relationTo: 'search';
|
relationTo: 'search';
|
||||||
value: string | Search;
|
value: string | Search;
|
||||||
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: 'payload-jobs';
|
||||||
|
value: string | PayloadJob;
|
||||||
} | null);
|
} | null);
|
||||||
globalSlug?: string | null;
|
globalSlug?: string | null;
|
||||||
user: {
|
user: {
|
||||||
@@ -1305,6 +1409,37 @@ export interface SearchSelect<T extends boolean = true> {
|
|||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "payload-jobs_select".
|
||||||
|
*/
|
||||||
|
export interface PayloadJobsSelect<T extends boolean = true> {
|
||||||
|
input?: T;
|
||||||
|
taskStatus?: T;
|
||||||
|
completedAt?: T;
|
||||||
|
totalTried?: T;
|
||||||
|
hasError?: T;
|
||||||
|
error?: T;
|
||||||
|
log?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
executedAt?: T;
|
||||||
|
completedAt?: T;
|
||||||
|
taskSlug?: T;
|
||||||
|
taskID?: T;
|
||||||
|
input?: T;
|
||||||
|
output?: T;
|
||||||
|
state?: T;
|
||||||
|
error?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
taskSlug?: T;
|
||||||
|
queue?: T;
|
||||||
|
waitUntil?: T;
|
||||||
|
processing?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-locked-documents_select".
|
* via the `definition` "payload-locked-documents_select".
|
||||||
@@ -1441,6 +1576,28 @@ export interface FooterSelect<T extends boolean = true> {
|
|||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
globalType?: T;
|
globalType?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "TaskSchedulePublish".
|
||||||
|
*/
|
||||||
|
export interface TaskSchedulePublish {
|
||||||
|
input: {
|
||||||
|
type?: ('publish' | 'unpublish') | null;
|
||||||
|
locale?: string | null;
|
||||||
|
doc?:
|
||||||
|
| ({
|
||||||
|
relationTo: 'pages';
|
||||||
|
value: string | Page;
|
||||||
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: 'posts';
|
||||||
|
value: string | Post;
|
||||||
|
} | null);
|
||||||
|
global?: string | null;
|
||||||
|
user?: (string | null) | User;
|
||||||
|
};
|
||||||
|
output?: unknown;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "BannerBlock".
|
* via the `definition` "BannerBlock".
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { mongooseAdapter } from '@payloadcms/db-mongodb' // database-adapter-imp
|
|||||||
|
|
||||||
import sharp from 'sharp' // sharp-import
|
import sharp from 'sharp' // sharp-import
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { buildConfig } from 'payload'
|
import { buildConfig, PayloadRequest } from 'payload'
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
|
|
||||||
import { Categories } from './collections/Categories'
|
import { Categories } from './collections/Categories'
|
||||||
@@ -76,4 +76,19 @@ export default buildConfig({
|
|||||||
typescript: {
|
typescript: {
|
||||||
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||||
},
|
},
|
||||||
|
jobs: {
|
||||||
|
access: {
|
||||||
|
run: ({ req }: { req: PayloadRequest }): boolean => {
|
||||||
|
// Allow logged in users to execute this endpoint (default)
|
||||||
|
if (req.user) return true
|
||||||
|
|
||||||
|
// If there is no logged in user, then check
|
||||||
|
// for the Vercel Cron secret to be present as an
|
||||||
|
// Authorization header:
|
||||||
|
const authHeader = req.headers.get('authorization')
|
||||||
|
return authHeader === `Bearer ${process.env.CRON_SECRET}`
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tasks: []
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,4 +3,6 @@ POSTGRES_URL=postgresql://127.0.0.1:5432/your-database-name
|
|||||||
# Used to encrypt JWT tokens
|
# Used to encrypt JWT tokens
|
||||||
PAYLOAD_SECRET=YOUR_SECRET_HERE
|
PAYLOAD_SECRET=YOUR_SECRET_HERE
|
||||||
# Used to configure CORS, format links and more. No trailing slash
|
# Used to configure CORS, format links and more. No trailing slash
|
||||||
NEXT_PUBLIC_SERVER_URL=http://localhost:3000
|
NEXT_PUBLIC_SERVER_URL=http://localhost:3000
|
||||||
|
# Secret used to authenticate cron jobs
|
||||||
|
CRON_SECRET=YOUR_CRON_SECRET_HERE
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ This is the official [Payload Website Template](https://github.com/payloadcms/pa
|
|||||||
|
|
||||||
You can deploy to Vercel, using Neon and Vercel Blob Storage with one click:
|
You can deploy to Vercel, using Neon and Vercel Blob Storage with one click:
|
||||||
|
|
||||||
[](https://vercel.com/new/clone?repository-url=https://github.com/payloadcms/payload/tree/main/templates/with-vercel-website&project-name=payload-project&env=PAYLOAD_SECRET&build-command=pnpm%20run%20ci&stores=%5B%7B%22type%22:%22postgres%22%7D,%7B%22type%22:%22blob%22%7D%5D)
|
[](https://vercel.com/new/clone?repository-url=https://github.com/payloadcms/payload/tree/main/templates/with-vercel-website&project-name=payload-project&env=PAYLOAD_SECRET%2CCRON_SECRET&build-command=pnpm%20run%20ci&stores=%5B%7B%22type%22:%22postgres%22%7D,%7B%22type%22:%22blob%22%7D%5D)
|
||||||
|
|
||||||
This template is right for you if you are working on:
|
This template is right for you if you are working on:
|
||||||
|
|
||||||
@@ -172,6 +172,38 @@ Core features:
|
|||||||
|
|
||||||
To spin up this example locally, follow the [Quick Start](#quick-start). Then [Seed](#seed) the database with a few pages, posts, and projects.
|
To spin up this example locally, follow the [Quick Start](#quick-start). Then [Seed](#seed) the database with a few pages, posts, and projects.
|
||||||
|
|
||||||
|
### Working with Postgres
|
||||||
|
|
||||||
|
Postgres and other SQL-based databases follow a strict schema for managing your data. In comparison to our MongoDB adapter, this means that there's a few extra steps to working with Postgres.
|
||||||
|
|
||||||
|
Note that often times when making big schema changes you can run the risk of losing data if you're not manually migrating it.
|
||||||
|
|
||||||
|
#### Local development
|
||||||
|
|
||||||
|
Ideally we recommend running a local copy of your database so that schema updates are as fast as possible. By default the Postgres adapter has `push: true` for development environments. This will let you add, modify and remove fields and collections without needing to run any data migrations.
|
||||||
|
|
||||||
|
If your database is pointed to production you will want to set `push: false` otherwise you will risk losing data or having your migrations out of sync.
|
||||||
|
|
||||||
|
#### Migrations
|
||||||
|
|
||||||
|
[Migrations](https://payloadcms.com/docs/database/migrations) are essentially SQL code versions that keeps track of your schema. When deploy with Postgres you will need to make sure you create and then run your migrations.
|
||||||
|
|
||||||
|
Locally create a migration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm payload migrate:create
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates the migration files you will need to push alongside with your new configuration.
|
||||||
|
|
||||||
|
On the server after building and before running `pnpm start` you will want to run your migrations
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm payload migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
This command will check for any migrations that have not yet been run and try to run them and it will keep a record of migrations that have been run in the database.
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
Alternatively, you can use [Docker](https://www.docker.com) to spin up this template locally. To do so, follow these steps:
|
Alternatively, you can use [Docker](https://www.docker.com) to spin up this template locally. To do so, follow these steps:
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ export const Pages: CollectionConfig<'pages'> = {
|
|||||||
autosave: {
|
autosave: {
|
||||||
interval: 100, // We set this interval for optimal live preview
|
interval: 100, // We set this interval for optimal live preview
|
||||||
},
|
},
|
||||||
|
schedulePublish: true,
|
||||||
},
|
},
|
||||||
maxPerDoc: 50,
|
maxPerDoc: 50,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -229,6 +229,7 @@ export const Posts: CollectionConfig<'posts'> = {
|
|||||||
autosave: {
|
autosave: {
|
||||||
interval: 100, // We set this interval for optimal live preview
|
interval: 100, // We set this interval for optimal live preview
|
||||||
},
|
},
|
||||||
|
schedulePublish: true,
|
||||||
},
|
},
|
||||||
maxPerDoc: 50,
|
maxPerDoc: 50,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export interface Config {
|
|||||||
forms: Form;
|
forms: Form;
|
||||||
'form-submissions': FormSubmission;
|
'form-submissions': FormSubmission;
|
||||||
search: Search;
|
search: Search;
|
||||||
|
'payload-jobs': PayloadJob;
|
||||||
'payload-locked-documents': PayloadLockedDocument;
|
'payload-locked-documents': PayloadLockedDocument;
|
||||||
'payload-preferences': PayloadPreference;
|
'payload-preferences': PayloadPreference;
|
||||||
'payload-migrations': PayloadMigration;
|
'payload-migrations': PayloadMigration;
|
||||||
@@ -35,6 +36,7 @@ export interface Config {
|
|||||||
forms: FormsSelect<false> | FormsSelect<true>;
|
forms: FormsSelect<false> | FormsSelect<true>;
|
||||||
'form-submissions': FormSubmissionsSelect<false> | FormSubmissionsSelect<true>;
|
'form-submissions': FormSubmissionsSelect<false> | FormSubmissionsSelect<true>;
|
||||||
search: SearchSelect<false> | SearchSelect<true>;
|
search: SearchSelect<false> | SearchSelect<true>;
|
||||||
|
'payload-jobs': PayloadJobsSelect<false> | PayloadJobsSelect<true>;
|
||||||
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
||||||
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
|
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
|
||||||
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
|
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
|
||||||
@@ -55,7 +57,13 @@ export interface Config {
|
|||||||
collection: 'users';
|
collection: 'users';
|
||||||
};
|
};
|
||||||
jobs: {
|
jobs: {
|
||||||
tasks: unknown;
|
tasks: {
|
||||||
|
schedulePublish: TaskSchedulePublish;
|
||||||
|
inline: {
|
||||||
|
input: unknown;
|
||||||
|
output: unknown;
|
||||||
|
};
|
||||||
|
};
|
||||||
workflows: unknown;
|
workflows: unknown;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -735,6 +743,98 @@ export interface Search {
|
|||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "payload-jobs".
|
||||||
|
*/
|
||||||
|
export interface PayloadJob {
|
||||||
|
id: number;
|
||||||
|
/**
|
||||||
|
* Input data provided to the job
|
||||||
|
*/
|
||||||
|
input?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
taskStatus?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| 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?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
/**
|
||||||
|
* Task execution log
|
||||||
|
*/
|
||||||
|
log?:
|
||||||
|
| {
|
||||||
|
executedAt: string;
|
||||||
|
completedAt: string;
|
||||||
|
taskSlug: 'inline' | 'schedulePublish';
|
||||||
|
taskID: string;
|
||||||
|
input?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
output?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
state: 'failed' | 'succeeded';
|
||||||
|
error?:
|
||||||
|
| {
|
||||||
|
[k: string]: unknown;
|
||||||
|
}
|
||||||
|
| unknown[]
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| null;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
|
taskSlug?: ('inline' | 'schedulePublish') | null;
|
||||||
|
queue?: string | null;
|
||||||
|
waitUntil?: string | null;
|
||||||
|
processing?: boolean | null;
|
||||||
|
updatedAt: string;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-locked-documents".
|
* via the `definition` "payload-locked-documents".
|
||||||
@@ -777,6 +877,10 @@ export interface PayloadLockedDocument {
|
|||||||
| ({
|
| ({
|
||||||
relationTo: 'search';
|
relationTo: 'search';
|
||||||
value: number | Search;
|
value: number | Search;
|
||||||
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: 'payload-jobs';
|
||||||
|
value: number | PayloadJob;
|
||||||
} | null);
|
} | null);
|
||||||
globalSlug?: string | null;
|
globalSlug?: string | null;
|
||||||
user: {
|
user: {
|
||||||
@@ -1305,6 +1409,37 @@ export interface SearchSelect<T extends boolean = true> {
|
|||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "payload-jobs_select".
|
||||||
|
*/
|
||||||
|
export interface PayloadJobsSelect<T extends boolean = true> {
|
||||||
|
input?: T;
|
||||||
|
taskStatus?: T;
|
||||||
|
completedAt?: T;
|
||||||
|
totalTried?: T;
|
||||||
|
hasError?: T;
|
||||||
|
error?: T;
|
||||||
|
log?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
executedAt?: T;
|
||||||
|
completedAt?: T;
|
||||||
|
taskSlug?: T;
|
||||||
|
taskID?: T;
|
||||||
|
input?: T;
|
||||||
|
output?: T;
|
||||||
|
state?: T;
|
||||||
|
error?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
taskSlug?: T;
|
||||||
|
queue?: T;
|
||||||
|
waitUntil?: T;
|
||||||
|
processing?: T;
|
||||||
|
updatedAt?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "payload-locked-documents_select".
|
* via the `definition` "payload-locked-documents_select".
|
||||||
@@ -1441,6 +1576,28 @@ export interface FooterSelect<T extends boolean = true> {
|
|||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
globalType?: T;
|
globalType?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "TaskSchedulePublish".
|
||||||
|
*/
|
||||||
|
export interface TaskSchedulePublish {
|
||||||
|
input: {
|
||||||
|
type?: ('publish' | 'unpublish') | null;
|
||||||
|
locale?: string | null;
|
||||||
|
doc?:
|
||||||
|
| ({
|
||||||
|
relationTo: 'pages';
|
||||||
|
value: number | Page;
|
||||||
|
} | null)
|
||||||
|
| ({
|
||||||
|
relationTo: 'posts';
|
||||||
|
value: number | Post;
|
||||||
|
} | null);
|
||||||
|
global?: string | null;
|
||||||
|
user?: (number | null) | User;
|
||||||
|
};
|
||||||
|
output?: unknown;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "BannerBlock".
|
* via the `definition` "BannerBlock".
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { vercelPostgresAdapter } from '@payloadcms/db-vercel-postgres'
|
|||||||
|
|
||||||
import sharp from 'sharp' // sharp-import
|
import sharp from 'sharp' // sharp-import
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { buildConfig } from 'payload'
|
import { buildConfig, PayloadRequest } from 'payload'
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
|
|
||||||
import { Categories } from './collections/Categories'
|
import { Categories } from './collections/Categories'
|
||||||
@@ -81,4 +81,19 @@ export default buildConfig({
|
|||||||
typescript: {
|
typescript: {
|
||||||
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||||
},
|
},
|
||||||
|
jobs: {
|
||||||
|
access: {
|
||||||
|
run: ({ req }: { req: PayloadRequest }): boolean => {
|
||||||
|
// Allow logged in users to execute this endpoint (default)
|
||||||
|
if (req.user) return true
|
||||||
|
|
||||||
|
// If there is no logged in user, then check
|
||||||
|
// for the Vercel Cron secret to be present as an
|
||||||
|
// Authorization header:
|
||||||
|
const authHeader = req.headers.get('authorization')
|
||||||
|
return authHeader === `Bearer ${process.env.CRON_SECRET}`
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tasks: [],
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
8
templates/with-vercel-website/vercel.json
Normal file
8
templates/with-vercel-website/vercel.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"crons": [
|
||||||
|
{
|
||||||
|
"path": "/api/payload-jobs/run",
|
||||||
|
"schedule": "*/5 * * * *"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user