diff --git a/templates/blank/src/payload-types.ts b/templates/blank/src/payload-types.ts index a9606af9af0..0669f6e0ae9 100644 --- a/templates/blank/src/payload-types.ts +++ b/templates/blank/src/payload-types.ts @@ -69,6 +69,7 @@ export interface Config { collections: { users: User; media: Media; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,6 +78,7 @@ export interface Config { collectionsSelect: { users: UsersSelect | UsersSelect; media: MediaSelect | MediaSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -156,6 +158,23 @@ export interface Media { focalX?: number | null; focalY?: number | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -170,6 +189,10 @@ export interface PayloadLockedDocument { | ({ relationTo: 'media'; value: string | Media; + } | null) + | ({ + relationTo: 'payload-kv'; + value: string | PayloadKv; } | null); globalSlug?: string | null; user: { @@ -253,6 +276,14 @@ export interface MediaSelect { focalX?: T; focalY?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/templates/ecommerce/src/payload-types.ts b/templates/ecommerce/src/payload-types.ts index 27d68abead3..50c369ce73f 100644 --- a/templates/ecommerce/src/payload-types.ts +++ b/templates/ecommerce/src/payload-types.ts @@ -86,6 +86,7 @@ export interface Config { carts: Cart; orders: Order; transactions: Transaction; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -118,6 +119,7 @@ export interface Config { carts: CartsSelect | CartsSelect; orders: OrdersSelect | OrdersSelect; transactions: TransactionsSelect | TransactionsSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -1030,6 +1032,23 @@ export interface FormSubmission { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -1092,6 +1111,10 @@ export interface PayloadLockedDocument { | ({ relationTo: 'transactions'; value: string | Transaction; + } | null) + | ({ + relationTo: 'payload-kv'; + value: string | PayloadKv; } | null); globalSlug?: string | null; user: { @@ -1720,6 +1743,14 @@ export interface TransactionsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/templates/website/src/payload-types.ts b/templates/website/src/payload-types.ts index 671e5bf622c..98216c7235f 100644 --- a/templates/website/src/payload-types.ts +++ b/templates/website/src/payload-types.ts @@ -76,6 +76,7 @@ export interface Config { forms: Form; 'form-submissions': FormSubmission; search: Search; + 'payload-kv': PayloadKv; 'payload-jobs': PayloadJob; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -92,6 +93,7 @@ export interface Config { forms: FormsSelect | FormsSelect; 'form-submissions': FormSubmissionsSelect | FormSubmissionsSelect; search: SearchSelect | SearchSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-jobs': PayloadJobsSelect | PayloadJobsSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -817,6 +819,23 @@ export interface Search { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-jobs". @@ -952,6 +971,10 @@ export interface PayloadLockedDocument { relationTo: 'search'; value: string | Search; } | null) + | ({ + relationTo: 'payload-kv'; + value: string | PayloadKv; + } | null) | ({ relationTo: 'payload-jobs'; value: string | PayloadJob; @@ -1492,6 +1515,14 @@ export interface SearchSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-jobs_select". diff --git a/templates/with-cloudflare-d1/package.json b/templates/with-cloudflare-d1/package.json index 126bd27cf07..d3b376f2817 100644 --- a/templates/with-cloudflare-d1/package.json +++ b/templates/with-cloudflare-d1/package.json @@ -26,16 +26,16 @@ }, "dependencies": { "@opennextjs/cloudflare": "^1.6.5", - "@payloadcms/db-d1-sqlite": "3.59.1", - "@payloadcms/next": "3.59.1", - "@payloadcms/richtext-lexical": "3.59.1", - "@payloadcms/storage-r2": "3.59.1", - "@payloadcms/ui": "3.59.1", + "@payloadcms/db-d1-sqlite": "3.62.0", + "@payloadcms/next": "3.62.0", + "@payloadcms/richtext-lexical": "3.62.0", + "@payloadcms/storage-r2": "3.62.0", + "@payloadcms/ui": "3.62.0", "cross-env": "^7.0.3", "dotenv": "16.4.7", "graphql": "^16.8.1", "next": "15.4.4", - "payload": "3.59.1", + "payload": "3.62.0", "react": "19.1.0", "react-dom": "19.1.0" }, diff --git a/templates/with-cloudflare-d1/src/payload-types.ts b/templates/with-cloudflare-d1/src/payload-types.ts index 49bbd88913f..5365beaa3c9 100644 --- a/templates/with-cloudflare-d1/src/payload-types.ts +++ b/templates/with-cloudflare-d1/src/payload-types.ts @@ -69,6 +69,7 @@ export interface Config { collections: { users: User; media: Media; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,6 +78,7 @@ export interface Config { collectionsSelect: { users: UsersSelect | UsersSelect; media: MediaSelect | MediaSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -154,6 +156,23 @@ export interface Media { width?: number | null; height?: number | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: number; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -168,6 +187,10 @@ export interface PayloadLockedDocument { | ({ relationTo: 'media'; value: number | Media; + } | null) + | ({ + relationTo: 'payload-kv'; + value: number | PayloadKv; } | null); globalSlug?: string | null; user: { @@ -249,6 +272,14 @@ export interface MediaSelect { width?: T; height?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/templates/with-postgres/package.json b/templates/with-postgres/package.json index 380d9578dbb..4e082fa96c0 100644 --- a/templates/with-postgres/package.json +++ b/templates/with-postgres/package.json @@ -19,15 +19,15 @@ "test:int": "cross-env NODE_OPTIONS=--no-deprecation vitest run --config ./vitest.config.mts" }, "dependencies": { - "@payloadcms/db-postgres": "3.59.1", - "@payloadcms/next": "3.59.1", - "@payloadcms/payload-cloud": "3.59.1", - "@payloadcms/richtext-lexical": "3.59.1", - "@payloadcms/ui": "3.59.1", + "@payloadcms/db-postgres": "3.62.0", + "@payloadcms/next": "3.62.0", + "@payloadcms/payload-cloud": "3.62.0", + "@payloadcms/richtext-lexical": "3.62.0", + "@payloadcms/ui": "3.62.0", "cross-env": "^7.0.3", "graphql": "^16.8.1", "next": "15.4.4", - "payload": "3.59.1", + "payload": "3.62.0", "react": "19.1.0", "react-dom": "19.1.0", "sharp": "0.34.2" diff --git a/templates/with-postgres/src/migrations/20251009_155521_initial.json b/templates/with-postgres/src/migrations/20251030_181618_initial.json similarity index 91% rename from templates/with-postgres/src/migrations/20251009_155521_initial.json rename to templates/with-postgres/src/migrations/20251030_181618_initial.json index 33b12ccbd01..edc76a45828 100644 --- a/templates/with-postgres/src/migrations/20251009_155521_initial.json +++ b/templates/with-postgres/src/migrations/20251030_181618_initial.json @@ -1,5 +1,5 @@ { - "id": "26587b23-7412-4cee-88bc-555f1511ca75", + "id": "4481a010-73af-4719-ac12-529e9b4b55e6", "prevId": "00000000-0000-0000-0000-000000000000", "version": "7", "dialect": "postgresql", @@ -349,6 +349,53 @@ "checkConstraints": {}, "isRLSEnabled": false }, + "public.payload_kv": { + "name": "payload_kv", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "payload_kv_key_idx": { + "name": "payload_kv_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, "public.payload_locked_documents": { "name": "payload_locked_documents", "schema": "", @@ -473,6 +520,12 @@ "type": "integer", "primaryKey": false, "notNull": false + }, + "payload_kv_id": { + "name": "payload_kv_id", + "type": "integer", + "primaryKey": false, + "notNull": false } }, "indexes": { @@ -550,6 +603,21 @@ "concurrently": false, "method": "btree", "with": {} + }, + "payload_locked_documents_rels_payload_kv_id_idx": { + "name": "payload_locked_documents_rels_payload_kv_id_idx", + "columns": [ + { + "expression": "payload_kv_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} } }, "foreignKeys": { @@ -579,6 +647,15 @@ "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" + }, + "payload_locked_documents_rels_payload_kv_fk": { + "name": "payload_locked_documents_rels_payload_kv_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "payload_kv", + "columnsFrom": ["payload_kv_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" } }, "compositePrimaryKeys": {}, diff --git a/templates/with-postgres/src/migrations/20251009_155521_initial.ts b/templates/with-postgres/src/migrations/20251030_181618_initial.ts similarity index 91% rename from templates/with-postgres/src/migrations/20251009_155521_initial.ts rename to templates/with-postgres/src/migrations/20251030_181618_initial.ts index ebe2acf7d07..7b56c122e01 100644 --- a/templates/with-postgres/src/migrations/20251009_155521_initial.ts +++ b/templates/with-postgres/src/migrations/20251030_181618_initial.ts @@ -39,6 +39,12 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { "focal_y" numeric ); + CREATE TABLE "payload_kv" ( + "id" serial PRIMARY KEY NOT NULL, + "key" varchar NOT NULL, + "data" jsonb NOT NULL + ); + CREATE TABLE "payload_locked_documents" ( "id" serial PRIMARY KEY NOT NULL, "global_slug" varchar, @@ -52,7 +58,8 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { "parent_id" integer NOT NULL, "path" varchar NOT NULL, "users_id" integer, - "media_id" integer + "media_id" integer, + "payload_kv_id" integer ); CREATE TABLE "payload_preferences" ( @@ -83,6 +90,7 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."payload_locked_documents"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_users_fk" FOREIGN KEY ("users_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_media_fk" FOREIGN KEY ("media_id") REFERENCES "public"."media"("id") ON DELETE cascade ON UPDATE no action; + ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_payload_kv_fk" FOREIGN KEY ("payload_kv_id") REFERENCES "public"."payload_kv"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."payload_preferences"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_users_fk" FOREIGN KEY ("users_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; CREATE INDEX "users_sessions_order_idx" ON "users_sessions" USING btree ("_order"); @@ -93,6 +101,7 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { CREATE INDEX "media_updated_at_idx" ON "media" USING btree ("updated_at"); CREATE INDEX "media_created_at_idx" ON "media" USING btree ("created_at"); CREATE UNIQUE INDEX "media_filename_idx" ON "media" USING btree ("filename"); + CREATE UNIQUE INDEX "payload_kv_key_idx" ON "payload_kv" USING btree ("key"); CREATE INDEX "payload_locked_documents_global_slug_idx" ON "payload_locked_documents" USING btree ("global_slug"); CREATE INDEX "payload_locked_documents_updated_at_idx" ON "payload_locked_documents" USING btree ("updated_at"); CREATE INDEX "payload_locked_documents_created_at_idx" ON "payload_locked_documents" USING btree ("created_at"); @@ -101,6 +110,7 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { CREATE INDEX "payload_locked_documents_rels_path_idx" ON "payload_locked_documents_rels" USING btree ("path"); CREATE INDEX "payload_locked_documents_rels_users_id_idx" ON "payload_locked_documents_rels" USING btree ("users_id"); CREATE INDEX "payload_locked_documents_rels_media_id_idx" ON "payload_locked_documents_rels" USING btree ("media_id"); + CREATE INDEX "payload_locked_documents_rels_payload_kv_id_idx" ON "payload_locked_documents_rels" USING btree ("payload_kv_id"); CREATE INDEX "payload_preferences_key_idx" ON "payload_preferences" USING btree ("key"); CREATE INDEX "payload_preferences_updated_at_idx" ON "payload_preferences" USING btree ("updated_at"); CREATE INDEX "payload_preferences_created_at_idx" ON "payload_preferences" USING btree ("created_at"); @@ -117,6 +127,7 @@ export async function down({ db, payload, req }: MigrateDownArgs): Promise DROP TABLE "users_sessions" CASCADE; DROP TABLE "users" CASCADE; DROP TABLE "media" CASCADE; + DROP TABLE "payload_kv" CASCADE; DROP TABLE "payload_locked_documents" CASCADE; DROP TABLE "payload_locked_documents_rels" CASCADE; DROP TABLE "payload_preferences" CASCADE; diff --git a/templates/with-postgres/src/migrations/index.ts b/templates/with-postgres/src/migrations/index.ts index de5b1457cac..36b2ffa58b3 100644 --- a/templates/with-postgres/src/migrations/index.ts +++ b/templates/with-postgres/src/migrations/index.ts @@ -1,9 +1,9 @@ -import * as migration_20251009_155521_initial from './20251009_155521_initial' +import * as migration_20251030_181618_initial from './20251030_181618_initial' export const migrations = [ { - up: migration_20251009_155521_initial.up, - down: migration_20251009_155521_initial.down, - name: '20251009_155521_initial', + up: migration_20251030_181618_initial.up, + down: migration_20251030_181618_initial.down, + name: '20251030_181618_initial', }, ] diff --git a/templates/with-postgres/src/payload-types.ts b/templates/with-postgres/src/payload-types.ts index 72b7ce4b6b6..a932549213d 100644 --- a/templates/with-postgres/src/payload-types.ts +++ b/templates/with-postgres/src/payload-types.ts @@ -69,6 +69,7 @@ export interface Config { collections: { users: User; media: Media; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,6 +78,7 @@ export interface Config { collectionsSelect: { users: UsersSelect | UsersSelect; media: MediaSelect | MediaSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -156,6 +158,23 @@ export interface Media { focalX?: number | null; focalY?: number | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: number; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -170,6 +189,10 @@ export interface PayloadLockedDocument { | ({ relationTo: 'media'; value: number | Media; + } | null) + | ({ + relationTo: 'payload-kv'; + value: number | PayloadKv; } | null); globalSlug?: string | null; user: { @@ -253,6 +276,14 @@ export interface MediaSelect { focalX?: T; focalY?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/templates/with-vercel-mongodb/package.json b/templates/with-vercel-mongodb/package.json index d1742631971..67ef07cabc4 100644 --- a/templates/with-vercel-mongodb/package.json +++ b/templates/with-vercel-mongodb/package.json @@ -18,16 +18,16 @@ "test:int": "cross-env NODE_OPTIONS=--no-deprecation vitest run --config ./vitest.config.mts" }, "dependencies": { - "@payloadcms/db-mongodb": "3.59.1", - "@payloadcms/next": "3.59.1", - "@payloadcms/payload-cloud": "3.59.1", - "@payloadcms/richtext-lexical": "3.59.1", - "@payloadcms/storage-vercel-blob": "3.59.1", - "@payloadcms/ui": "3.59.1", + "@payloadcms/db-mongodb": "3.62.0", + "@payloadcms/next": "3.62.0", + "@payloadcms/payload-cloud": "3.62.0", + "@payloadcms/richtext-lexical": "3.62.0", + "@payloadcms/storage-vercel-blob": "3.62.0", + "@payloadcms/ui": "3.62.0", "cross-env": "^7.0.3", "graphql": "^16.8.1", "next": "15.4.4", - "payload": "3.59.1", + "payload": "3.62.0", "react": "19.1.0", "react-dom": "19.1.0" }, @@ -49,7 +49,7 @@ "vite-tsconfig-paths": "5.1.4", "vitest": "3.2.3" }, - "packageManager": "pnpm@10.18.1", + "packageManager": "pnpm@10.20.0", "engines": { "node": "^18.20.2 || >=20.9.0" }, diff --git a/templates/with-vercel-mongodb/src/payload-types.ts b/templates/with-vercel-mongodb/src/payload-types.ts index a9606af9af0..0669f6e0ae9 100644 --- a/templates/with-vercel-mongodb/src/payload-types.ts +++ b/templates/with-vercel-mongodb/src/payload-types.ts @@ -69,6 +69,7 @@ export interface Config { collections: { users: User; media: Media; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,6 +78,7 @@ export interface Config { collectionsSelect: { users: UsersSelect | UsersSelect; media: MediaSelect | MediaSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -156,6 +158,23 @@ export interface Media { focalX?: number | null; focalY?: number | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: string; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -170,6 +189,10 @@ export interface PayloadLockedDocument { | ({ relationTo: 'media'; value: string | Media; + } | null) + | ({ + relationTo: 'payload-kv'; + value: string | PayloadKv; } | null); globalSlug?: string | null; user: { @@ -253,6 +276,14 @@ export interface MediaSelect { focalX?: T; focalY?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/templates/with-vercel-postgres/package.json b/templates/with-vercel-postgres/package.json index c294c79279a..1975b9ace1a 100644 --- a/templates/with-vercel-postgres/package.json +++ b/templates/with-vercel-postgres/package.json @@ -19,16 +19,16 @@ "test:int": "cross-env NODE_OPTIONS=--no-deprecation vitest run --config ./vitest.config.mts" }, "dependencies": { - "@payloadcms/db-vercel-postgres": "3.59.1", - "@payloadcms/next": "3.59.1", - "@payloadcms/payload-cloud": "3.59.1", - "@payloadcms/richtext-lexical": "3.59.1", - "@payloadcms/storage-vercel-blob": "3.59.1", - "@payloadcms/ui": "3.59.1", + "@payloadcms/db-vercel-postgres": "3.62.0", + "@payloadcms/next": "3.62.0", + "@payloadcms/payload-cloud": "3.62.0", + "@payloadcms/richtext-lexical": "3.62.0", + "@payloadcms/storage-vercel-blob": "3.62.0", + "@payloadcms/ui": "3.62.0", "cross-env": "^7.0.3", "graphql": "^16.8.1", "next": "15.4.4", - "payload": "3.59.1", + "payload": "3.62.0", "react": "19.1.0", "react-dom": "19.1.0" }, @@ -50,7 +50,7 @@ "vite-tsconfig-paths": "5.1.4", "vitest": "3.2.3" }, - "packageManager": "pnpm@10.18.1", + "packageManager": "pnpm@10.20.0", "engines": { "node": "^18.20.2 || >=20.9.0" }, diff --git a/templates/with-vercel-postgres/src/migrations/20251009_155439_initial.json b/templates/with-vercel-postgres/src/migrations/20251030_181538_initial.json similarity index 91% rename from templates/with-vercel-postgres/src/migrations/20251009_155439_initial.json rename to templates/with-vercel-postgres/src/migrations/20251030_181538_initial.json index 5826bce92b1..d7525347f65 100644 --- a/templates/with-vercel-postgres/src/migrations/20251009_155439_initial.json +++ b/templates/with-vercel-postgres/src/migrations/20251030_181538_initial.json @@ -1,5 +1,5 @@ { - "id": "69900809-28b8-4674-a3d3-21bbb98f3e2e", + "id": "85775a6d-7355-4386-94c0-cfd0c76a10e2", "prevId": "00000000-0000-0000-0000-000000000000", "version": "7", "dialect": "postgresql", @@ -349,6 +349,53 @@ "checkConstraints": {}, "isRLSEnabled": false }, + "public.payload_kv": { + "name": "payload_kv", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "payload_kv_key_idx": { + "name": "payload_kv_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, "public.payload_locked_documents": { "name": "payload_locked_documents", "schema": "", @@ -473,6 +520,12 @@ "type": "integer", "primaryKey": false, "notNull": false + }, + "payload_kv_id": { + "name": "payload_kv_id", + "type": "integer", + "primaryKey": false, + "notNull": false } }, "indexes": { @@ -550,6 +603,21 @@ "concurrently": false, "method": "btree", "with": {} + }, + "payload_locked_documents_rels_payload_kv_id_idx": { + "name": "payload_locked_documents_rels_payload_kv_id_idx", + "columns": [ + { + "expression": "payload_kv_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} } }, "foreignKeys": { @@ -579,6 +647,15 @@ "columnsTo": ["id"], "onDelete": "cascade", "onUpdate": "no action" + }, + "payload_locked_documents_rels_payload_kv_fk": { + "name": "payload_locked_documents_rels_payload_kv_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "payload_kv", + "columnsFrom": ["payload_kv_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" } }, "compositePrimaryKeys": {}, diff --git a/templates/with-vercel-postgres/src/migrations/20251009_155439_initial.ts b/templates/with-vercel-postgres/src/migrations/20251030_181538_initial.ts similarity index 91% rename from templates/with-vercel-postgres/src/migrations/20251009_155439_initial.ts rename to templates/with-vercel-postgres/src/migrations/20251030_181538_initial.ts index 4d73fb6f487..be72c7c8633 100644 --- a/templates/with-vercel-postgres/src/migrations/20251009_155439_initial.ts +++ b/templates/with-vercel-postgres/src/migrations/20251030_181538_initial.ts @@ -39,6 +39,12 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { "focal_y" numeric ); + CREATE TABLE "payload_kv" ( + "id" serial PRIMARY KEY NOT NULL, + "key" varchar NOT NULL, + "data" jsonb NOT NULL + ); + CREATE TABLE "payload_locked_documents" ( "id" serial PRIMARY KEY NOT NULL, "global_slug" varchar, @@ -52,7 +58,8 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { "parent_id" integer NOT NULL, "path" varchar NOT NULL, "users_id" integer, - "media_id" integer + "media_id" integer, + "payload_kv_id" integer ); CREATE TABLE "payload_preferences" ( @@ -83,6 +90,7 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."payload_locked_documents"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_users_fk" FOREIGN KEY ("users_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_media_fk" FOREIGN KEY ("media_id") REFERENCES "public"."media"("id") ON DELETE cascade ON UPDATE no action; + ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_payload_kv_fk" FOREIGN KEY ("payload_kv_id") REFERENCES "public"."payload_kv"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."payload_preferences"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_users_fk" FOREIGN KEY ("users_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; CREATE INDEX "users_sessions_order_idx" ON "users_sessions" USING btree ("_order"); @@ -93,6 +101,7 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { CREATE INDEX "media_updated_at_idx" ON "media" USING btree ("updated_at"); CREATE INDEX "media_created_at_idx" ON "media" USING btree ("created_at"); CREATE UNIQUE INDEX "media_filename_idx" ON "media" USING btree ("filename"); + CREATE UNIQUE INDEX "payload_kv_key_idx" ON "payload_kv" USING btree ("key"); CREATE INDEX "payload_locked_documents_global_slug_idx" ON "payload_locked_documents" USING btree ("global_slug"); CREATE INDEX "payload_locked_documents_updated_at_idx" ON "payload_locked_documents" USING btree ("updated_at"); CREATE INDEX "payload_locked_documents_created_at_idx" ON "payload_locked_documents" USING btree ("created_at"); @@ -101,6 +110,7 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { CREATE INDEX "payload_locked_documents_rels_path_idx" ON "payload_locked_documents_rels" USING btree ("path"); CREATE INDEX "payload_locked_documents_rels_users_id_idx" ON "payload_locked_documents_rels" USING btree ("users_id"); CREATE INDEX "payload_locked_documents_rels_media_id_idx" ON "payload_locked_documents_rels" USING btree ("media_id"); + CREATE INDEX "payload_locked_documents_rels_payload_kv_id_idx" ON "payload_locked_documents_rels" USING btree ("payload_kv_id"); CREATE INDEX "payload_preferences_key_idx" ON "payload_preferences" USING btree ("key"); CREATE INDEX "payload_preferences_updated_at_idx" ON "payload_preferences" USING btree ("updated_at"); CREATE INDEX "payload_preferences_created_at_idx" ON "payload_preferences" USING btree ("created_at"); @@ -117,6 +127,7 @@ export async function down({ db, payload, req }: MigrateDownArgs): Promise DROP TABLE "users_sessions" CASCADE; DROP TABLE "users" CASCADE; DROP TABLE "media" CASCADE; + DROP TABLE "payload_kv" CASCADE; DROP TABLE "payload_locked_documents" CASCADE; DROP TABLE "payload_locked_documents_rels" CASCADE; DROP TABLE "payload_preferences" CASCADE; diff --git a/templates/with-vercel-postgres/src/migrations/index.ts b/templates/with-vercel-postgres/src/migrations/index.ts index 7f1651c7f83..3c084e71873 100644 --- a/templates/with-vercel-postgres/src/migrations/index.ts +++ b/templates/with-vercel-postgres/src/migrations/index.ts @@ -1,9 +1,9 @@ -import * as migration_20251009_155439_initial from './20251009_155439_initial' +import * as migration_20251030_181538_initial from './20251030_181538_initial' export const migrations = [ { - up: migration_20251009_155439_initial.up, - down: migration_20251009_155439_initial.down, - name: '20251009_155439_initial', + up: migration_20251030_181538_initial.up, + down: migration_20251030_181538_initial.down, + name: '20251030_181538_initial', }, ] diff --git a/templates/with-vercel-postgres/src/payload-types.ts b/templates/with-vercel-postgres/src/payload-types.ts index 72b7ce4b6b6..a932549213d 100644 --- a/templates/with-vercel-postgres/src/payload-types.ts +++ b/templates/with-vercel-postgres/src/payload-types.ts @@ -69,6 +69,7 @@ export interface Config { collections: { users: User; media: Media; + 'payload-kv': PayloadKv; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; @@ -77,6 +78,7 @@ export interface Config { collectionsSelect: { users: UsersSelect | UsersSelect; media: MediaSelect | MediaSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; 'payload-migrations': PayloadMigrationsSelect | PayloadMigrationsSelect; @@ -156,6 +158,23 @@ export interface Media { focalX?: number | null; focalY?: number | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: number; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents". @@ -170,6 +189,10 @@ export interface PayloadLockedDocument { | ({ relationTo: 'media'; value: number | Media; + } | null) + | ({ + relationTo: 'payload-kv'; + value: number | PayloadKv; } | null); globalSlug?: string | null; user: { @@ -253,6 +276,14 @@ export interface MediaSelect { focalX?: T; focalY?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-locked-documents_select". diff --git a/templates/with-vercel-website/package.json b/templates/with-vercel-website/package.json index d65f5ee7f49..c10d6c4a734 100644 --- a/templates/with-vercel-website/package.json +++ b/templates/with-vercel-website/package.json @@ -23,19 +23,19 @@ "test:int": "cross-env NODE_OPTIONS=--no-deprecation vitest run --config ./vitest.config.mts" }, "dependencies": { - "@payloadcms/admin-bar": "3.59.1", - "@payloadcms/db-vercel-postgres": "3.59.1", - "@payloadcms/live-preview-react": "3.59.1", - "@payloadcms/next": "3.59.1", - "@payloadcms/payload-cloud": "3.59.1", - "@payloadcms/plugin-form-builder": "3.59.1", - "@payloadcms/plugin-nested-docs": "3.59.1", - "@payloadcms/plugin-redirects": "3.59.1", - "@payloadcms/plugin-search": "3.59.1", - "@payloadcms/plugin-seo": "3.59.1", - "@payloadcms/richtext-lexical": "3.59.1", - "@payloadcms/storage-vercel-blob": "3.59.1", - "@payloadcms/ui": "3.59.1", + "@payloadcms/admin-bar": "3.62.0", + "@payloadcms/db-vercel-postgres": "3.62.0", + "@payloadcms/live-preview-react": "3.62.0", + "@payloadcms/next": "3.62.0", + "@payloadcms/payload-cloud": "3.62.0", + "@payloadcms/plugin-form-builder": "3.62.0", + "@payloadcms/plugin-nested-docs": "3.62.0", + "@payloadcms/plugin-redirects": "3.62.0", + "@payloadcms/plugin-search": "3.62.0", + "@payloadcms/plugin-seo": "3.62.0", + "@payloadcms/richtext-lexical": "3.62.0", + "@payloadcms/storage-vercel-blob": "3.62.0", + "@payloadcms/ui": "3.62.0", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-select": "^2.0.0", @@ -49,7 +49,7 @@ "lucide-react": "^0.378.0", "next": "15.4.4", "next-sitemap": "^4.2.3", - "payload": "3.59.1", + "payload": "3.62.0", "prism-react-renderer": "^2.3.1", "react": "19.1.0", "react-dom": "19.1.0", @@ -82,7 +82,7 @@ "vite-tsconfig-paths": "5.1.4", "vitest": "3.2.3" }, - "packageManager": "pnpm@10.18.1", + "packageManager": "pnpm@10.20.0", "engines": { "node": "^18.20.2 || >=20.9.0" }, diff --git a/templates/with-vercel-website/src/app/(frontend)/[slug]/page.tsx b/templates/with-vercel-website/src/app/(frontend)/[slug]/page.tsx index 7a8d1037e85..1e274ff3e9f 100644 --- a/templates/with-vercel-website/src/app/(frontend)/[slug]/page.tsx +++ b/templates/with-vercel-website/src/app/(frontend)/[slug]/page.tsx @@ -46,12 +46,13 @@ type Args = { export default async function Page({ params: paramsPromise }: Args) { const { isEnabled: draft } = await draftMode() const { slug = 'home' } = await paramsPromise - const url = '/' + slug - + // Decode to support slugs with special characters + const decodedSlug = decodeURIComponent(slug) + const url = '/' + decodedSlug let page: RequiredDataFromCollectionSlug<'pages'> | null page = await queryPageBySlug({ - slug, + slug: decodedSlug, }) // Remove this code once your website is seeded @@ -81,8 +82,10 @@ export default async function Page({ params: paramsPromise }: Args) { export async function generateMetadata({ params: paramsPromise }: Args): Promise { const { slug = 'home' } = await paramsPromise + // Decode to support slugs with special characters + const decodedSlug = decodeURIComponent(slug) const page = await queryPageBySlug({ - slug, + slug: decodedSlug, }) return generateMeta({ doc: page }) diff --git a/templates/with-vercel-website/src/app/(frontend)/posts/[slug]/page.tsx b/templates/with-vercel-website/src/app/(frontend)/posts/[slug]/page.tsx index ab6ab19a31f..160bbbf0ac8 100644 --- a/templates/with-vercel-website/src/app/(frontend)/posts/[slug]/page.tsx +++ b/templates/with-vercel-website/src/app/(frontend)/posts/[slug]/page.tsx @@ -44,8 +44,10 @@ type Args = { export default async function Post({ params: paramsPromise }: Args) { const { isEnabled: draft } = await draftMode() const { slug = '' } = await paramsPromise - const url = '/posts/' + slug - const post = await queryPostBySlug({ slug }) + // Decode to support slugs with special characters + const decodedSlug = decodeURIComponent(slug) + const url = '/posts/' + decodedSlug + const post = await queryPostBySlug({ slug: decodedSlug }) if (!post) return @@ -77,7 +79,9 @@ export default async function Post({ params: paramsPromise }: Args) { export async function generateMetadata({ params: paramsPromise }: Args): Promise { const { slug = '' } = await paramsPromise - const post = await queryPostBySlug({ slug }) + // Decode to support slugs with special characters + const decodedSlug = decodeURIComponent(slug) + const post = await queryPostBySlug({ slug: decodedSlug }) return generateMeta({ doc: post }) } diff --git a/templates/with-vercel-website/src/migrations/20251009_155501_initial.json b/templates/with-vercel-website/src/migrations/20251030_181558_initial.json similarity index 99% rename from templates/with-vercel-website/src/migrations/20251009_155501_initial.json rename to templates/with-vercel-website/src/migrations/20251030_181558_initial.json index f4f7923a2f9..80d1c409ae8 100644 --- a/templates/with-vercel-website/src/migrations/20251009_155501_initial.json +++ b/templates/with-vercel-website/src/migrations/20251030_181558_initial.json @@ -1,5 +1,5 @@ { - "id": "61df5806-88a9-45d6-b81d-9f1316d50fa8", + "id": "6116b1f9-abbd-4517-a0a4-6949b9825791", "prevId": "00000000-0000-0000-0000-000000000000", "version": "7", "dialect": "postgresql", @@ -7055,6 +7055,53 @@ "checkConstraints": {}, "isRLSEnabled": false }, + "public.payload_kv": { + "name": "payload_kv", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "key": { + "name": "key", + "type": "varchar", + "primaryKey": false, + "notNull": true + }, + "data": { + "name": "data", + "type": "jsonb", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "payload_kv_key_idx": { + "name": "payload_kv_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, "public.payload_jobs_log": { "name": "payload_jobs_log", "schema": "", @@ -7572,6 +7619,12 @@ "primaryKey": false, "notNull": false }, + "payload_kv_id": { + "name": "payload_kv_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, "payload_jobs_id": { "name": "payload_jobs_id", "type": "integer", @@ -7760,6 +7813,21 @@ "method": "btree", "with": {} }, + "payload_locked_documents_rels_payload_kv_id_idx": { + "name": "payload_locked_documents_rels_payload_kv_id_idx", + "columns": [ + { + "expression": "payload_kv_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, "payload_locked_documents_rels_payload_jobs_id_idx": { "name": "payload_locked_documents_rels_payload_jobs_id_idx", "columns": [ @@ -7867,6 +7935,15 @@ "onDelete": "cascade", "onUpdate": "no action" }, + "payload_locked_documents_rels_payload_kv_fk": { + "name": "payload_locked_documents_rels_payload_kv_fk", + "tableFrom": "payload_locked_documents_rels", + "tableTo": "payload_kv", + "columnsFrom": ["payload_kv_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, "payload_locked_documents_rels_payload_jobs_fk": { "name": "payload_locked_documents_rels_payload_jobs_fk", "tableFrom": "payload_locked_documents_rels", diff --git a/templates/with-vercel-website/src/migrations/20251009_155501_initial.ts b/templates/with-vercel-website/src/migrations/20251030_181558_initial.ts similarity index 99% rename from templates/with-vercel-website/src/migrations/20251009_155501_initial.ts rename to templates/with-vercel-website/src/migrations/20251030_181558_initial.ts index 9ad4bb178ff..91a0f34a3ef 100644 --- a/templates/with-vercel-website/src/migrations/20251009_155501_initial.ts +++ b/templates/with-vercel-website/src/migrations/20251030_181558_initial.ts @@ -647,6 +647,12 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { "posts_id" integer ); + CREATE TABLE "payload_kv" ( + "id" serial PRIMARY KEY NOT NULL, + "key" varchar NOT NULL, + "data" jsonb NOT NULL + ); + CREATE TABLE "payload_jobs_log" ( "_order" integer NOT NULL, "_parent_id" integer NOT NULL, @@ -697,6 +703,7 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { "forms_id" integer, "form_submissions_id" integer, "search_id" integer, + "payload_kv_id" integer, "payload_jobs_id" integer ); @@ -857,6 +864,7 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_forms_fk" FOREIGN KEY ("forms_id") REFERENCES "public"."forms"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_form_submissions_fk" FOREIGN KEY ("form_submissions_id") REFERENCES "public"."form_submissions"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_search_fk" FOREIGN KEY ("search_id") REFERENCES "public"."search"("id") ON DELETE cascade ON UPDATE no action; + ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_payload_kv_fk" FOREIGN KEY ("payload_kv_id") REFERENCES "public"."payload_kv"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_payload_jobs_fk" FOREIGN KEY ("payload_jobs_id") REFERENCES "public"."payload_jobs"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."payload_preferences"("id") ON DELETE cascade ON UPDATE no action; ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_users_fk" FOREIGN KEY ("users_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action; @@ -1054,6 +1062,7 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { CREATE INDEX "search_rels_parent_idx" ON "search_rels" USING btree ("parent_id"); CREATE INDEX "search_rels_path_idx" ON "search_rels" USING btree ("path"); CREATE INDEX "search_rels_posts_id_idx" ON "search_rels" USING btree ("posts_id"); + CREATE UNIQUE INDEX "payload_kv_key_idx" ON "payload_kv" USING btree ("key"); CREATE INDEX "payload_jobs_log_order_idx" ON "payload_jobs_log" USING btree ("_order"); CREATE INDEX "payload_jobs_log_parent_id_idx" ON "payload_jobs_log" USING btree ("_parent_id"); CREATE INDEX "payload_jobs_completed_at_idx" ON "payload_jobs" USING btree ("completed_at"); @@ -1080,6 +1089,7 @@ export async function up({ db, payload, req }: MigrateUpArgs): Promise { CREATE INDEX "payload_locked_documents_rels_forms_id_idx" ON "payload_locked_documents_rels" USING btree ("forms_id"); CREATE INDEX "payload_locked_documents_rels_form_submissions_id_idx" ON "payload_locked_documents_rels" USING btree ("form_submissions_id"); CREATE INDEX "payload_locked_documents_rels_search_id_idx" ON "payload_locked_documents_rels" USING btree ("search_id"); + CREATE INDEX "payload_locked_documents_rels_payload_kv_id_idx" ON "payload_locked_documents_rels" USING btree ("payload_kv_id"); CREATE INDEX "payload_locked_documents_rels_payload_jobs_id_idx" ON "payload_locked_documents_rels" USING btree ("payload_jobs_id"); CREATE INDEX "payload_preferences_key_idx" ON "payload_preferences" USING btree ("key"); CREATE INDEX "payload_preferences_updated_at_idx" ON "payload_preferences" USING btree ("updated_at"); @@ -1158,6 +1168,7 @@ export async function down({ db, payload, req }: MigrateDownArgs): Promise DROP TABLE "search_categories" CASCADE; DROP TABLE "search" CASCADE; DROP TABLE "search_rels" CASCADE; + DROP TABLE "payload_kv" CASCADE; DROP TABLE "payload_jobs_log" CASCADE; DROP TABLE "payload_jobs" CASCADE; DROP TABLE "payload_locked_documents" CASCADE; diff --git a/templates/with-vercel-website/src/migrations/index.ts b/templates/with-vercel-website/src/migrations/index.ts index 228ab3ebeda..eb980e098ba 100644 --- a/templates/with-vercel-website/src/migrations/index.ts +++ b/templates/with-vercel-website/src/migrations/index.ts @@ -1,9 +1,9 @@ -import * as migration_20251009_155501_initial from './20251009_155501_initial' +import * as migration_20251030_181558_initial from './20251030_181558_initial' export const migrations = [ { - up: migration_20251009_155501_initial.up, - down: migration_20251009_155501_initial.down, - name: '20251009_155501_initial', + up: migration_20251030_181558_initial.up, + down: migration_20251030_181558_initial.down, + name: '20251030_181558_initial', }, ] diff --git a/templates/with-vercel-website/src/payload-types.ts b/templates/with-vercel-website/src/payload-types.ts index 7e4c57c4c7a..9d4b20b5dbf 100644 --- a/templates/with-vercel-website/src/payload-types.ts +++ b/templates/with-vercel-website/src/payload-types.ts @@ -76,6 +76,7 @@ export interface Config { forms: Form; 'form-submissions': FormSubmission; search: Search; + 'payload-kv': PayloadKv; 'payload-jobs': PayloadJob; 'payload-locked-documents': PayloadLockedDocument; 'payload-preferences': PayloadPreference; @@ -92,6 +93,7 @@ export interface Config { forms: FormsSelect | FormsSelect; 'form-submissions': FormSubmissionsSelect | FormSubmissionsSelect; search: SearchSelect | SearchSelect; + 'payload-kv': PayloadKvSelect | PayloadKvSelect; 'payload-jobs': PayloadJobsSelect | PayloadJobsSelect; 'payload-locked-documents': PayloadLockedDocumentsSelect | PayloadLockedDocumentsSelect; 'payload-preferences': PayloadPreferencesSelect | PayloadPreferencesSelect; @@ -817,6 +819,23 @@ export interface Search { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv". + */ +export interface PayloadKv { + id: number; + key: string; + data: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-jobs". @@ -952,6 +971,10 @@ export interface PayloadLockedDocument { relationTo: 'search'; value: number | Search; } | null) + | ({ + relationTo: 'payload-kv'; + value: number | PayloadKv; + } | null) | ({ relationTo: 'payload-jobs'; value: number | PayloadJob; @@ -1492,6 +1515,14 @@ export interface SearchSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "payload-kv_select". + */ +export interface PayloadKvSelect { + key?: T; + data?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "payload-jobs_select". diff --git a/templates/with-vercel-website/src/utilities/generatePreviewPath.ts b/templates/with-vercel-website/src/utilities/generatePreviewPath.ts index df95ecc0d2e..e6e1130bb57 100644 --- a/templates/with-vercel-website/src/utilities/generatePreviewPath.ts +++ b/templates/with-vercel-website/src/utilities/generatePreviewPath.ts @@ -17,10 +17,13 @@ export const generatePreviewPath = ({ collection, slug }: Props) => { return null } + // Encode to support slugs with special characters + const encodedSlug = encodeURIComponent(slug) + const encodedParams = new URLSearchParams({ - slug, + slug: encodedSlug, collection, - path: `${collectionPrefixMap[collection]}/${slug}`, + path: `${collectionPrefixMap[collection]}/${encodedSlug}`, previewSecret: process.env.PREVIEW_SECRET || '', })