├── src ├── app │ ├── (payload) │ │ ├── custom.scss │ │ ├── api │ │ │ ├── graphql │ │ │ │ └── route.ts │ │ │ ├── graphql-playground │ │ │ │ └── route.ts │ │ │ └── [...slug] │ │ │ │ └── route.ts │ │ ├── layout.tsx │ │ └── admin │ │ │ └── [[...segments]] │ │ │ ├── page.tsx │ │ │ └── not-found.tsx │ └── (app) │ │ ├── api │ │ └── search │ │ │ └── route.ts │ │ ├── layout.tsx │ │ ├── Header.tsx │ │ ├── page.tsx │ │ ├── movie │ │ └── [slug] │ │ │ └── page.tsx │ │ ├── globals.scss │ │ ├── MovieCards.tsx │ │ └── add │ │ └── page.tsx ├── movies │ ├── utils.ts │ └── index.ts ├── lib │ └── utils.ts ├── cms │ └── collections │ │ ├── Users │ │ └── index.ts │ │ ├── Media │ │ └── index.ts │ │ └── Movies │ │ └── index.ts ├── components │ └── ui │ │ ├── input.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ └── carousel.tsx └── migrations │ ├── 20240712_231319_initial.ts │ └── 20240712_231319_initial.json ├── .eslintrc.json ├── public ├── blur.png ├── gradient.webp └── crosshair.svg ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── .prettierrc.json ├── postcss.config.mjs ├── .env.example ├── .github └── ISSUE_TEMPLATE │ └── config.yml ├── components.json ├── next.config.mjs ├── .gitignore ├── .idea └── runConfigurations │ └── Run_Dev__pnpm_.xml ├── start-database.sh ├── tsconfig.json ├── README.md ├── payload.config.ts ├── tailwind.config.js ├── package.json ├── payload-types.ts └── schema.graphql /src/app/(payload)/custom.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /public/blur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/payload-3.0-movies/HEAD/public/blur.png -------------------------------------------------------------------------------- /public/gradient.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jherr/payload-3.0-movies/HEAD/public/gradient.webp -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["esbenp.prettier-vscode", "dbaeumer.vscode-eslint"] 3 | } 4 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "printWidth": 100, 5 | "semi": false 6 | } 7 | -------------------------------------------------------------------------------- /src/movies/utils.ts: -------------------------------------------------------------------------------- 1 | export function posterURL(poster_path: string) { 2 | return `https://image.tmdb.org/t/p/w600_and_h900_bestv2${poster_path}` 3 | } 4 | -------------------------------------------------------------------------------- /postcss.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('postcss-load-config').Config} */ 2 | const config = { 3 | plugins: { 4 | tailwindcss: {}, 5 | }, 6 | }; 7 | 8 | export default config; 9 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # PAYLOAD_SECRET=jawliejfilwajefSEANlawefawfewag349jwgo3gj4w 2 | # POSTGRES_URL=postgresql://postgres:password123@127.0.0.1:5432/next-payload-3 3 | # TMDB_API_KEY= -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /public/crosshair.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Beta Issues 4 | url: https://github.com/payloadcms/payload/issues/new/choose 5 | about: Any issues should be opened on the main repository 6 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "command": "pnpm run dev", 5 | "cwd": "${workspaceFolder}", 6 | "name": "Run Dev (pnpm)", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ], 11 | "version": "0.2.0" 12 | } 13 | -------------------------------------------------------------------------------- /src/cms/collections/Users/index.ts: -------------------------------------------------------------------------------- 1 | import { CollectionConfig } from 'payload' 2 | 3 | export const UsersCollection: CollectionConfig = { 4 | slug: 'users', 5 | auth: true, 6 | access: { 7 | delete: () => false, 8 | update: () => false, 9 | }, 10 | fields: [], 11 | } 12 | -------------------------------------------------------------------------------- /src/app/(payload)/api/graphql/route.ts: -------------------------------------------------------------------------------- 1 | /* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ 2 | /* DO NOT MODIFY it because it could be re-written at any time. */ 3 | import config from '@payload-config' 4 | import { GRAPHQL_POST } from '@payloadcms/next/routes' 5 | 6 | export const POST = GRAPHQL_POST(config) 7 | -------------------------------------------------------------------------------- /src/app/(payload)/api/graphql-playground/route.ts: -------------------------------------------------------------------------------- 1 | /* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ 2 | /* DO NOT MODIFY it because it could be re-written at any time. */ 3 | import config from '@payload-config' 4 | import { GRAPHQL_PLAYGROUND_GET } from '@payloadcms/next/routes' 5 | 6 | export const GET = GRAPHQL_PLAYGROUND_GET(config) 7 | -------------------------------------------------------------------------------- /src/cms/collections/Media/index.ts: -------------------------------------------------------------------------------- 1 | import { CollectionConfig } from 'payload' 2 | 3 | export const MediaCollection: CollectionConfig = { 4 | slug: 'media', 5 | upload: true, 6 | access: { 7 | create: () => true, 8 | read: () => true, 9 | }, 10 | fields: [ 11 | { 12 | name: 'text', 13 | type: 'text', 14 | }, 15 | ], 16 | } 17 | -------------------------------------------------------------------------------- /src/app/(app)/api/search/route.ts: -------------------------------------------------------------------------------- 1 | import { NextRequest, NextResponse } from 'next/server' 2 | 3 | import { searchMovies } from '@/movies' 4 | 5 | export async function GET(request: NextRequest) { 6 | const searchParams = request.nextUrl.searchParams 7 | const query = searchParams.get('query') ?? '' 8 | 9 | return NextResponse.json(await searchMovies(query)) 10 | } 11 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "src/app/(app)/globals.scss", 9 | "baseColor": "slate", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils" 16 | } 17 | } -------------------------------------------------------------------------------- /next.config.mjs: -------------------------------------------------------------------------------- 1 | import { withPayload } from '@payloadcms/next/withPayload' 2 | 3 | /** @type {import('next').NextConfig} */ 4 | const nextConfig = { 5 | // Your Next.js config here 6 | experimental: { 7 | reactCompiler: false, 8 | }, 9 | images: { 10 | unoptimized: true, 11 | remotePatterns: [ 12 | { 13 | protocol: 'https', 14 | hostname: 'image.tmdb.org', 15 | }, 16 | ], 17 | }, 18 | } 19 | 20 | export default withPayload(nextConfig) 21 | -------------------------------------------------------------------------------- /src/app/(app)/layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './globals.scss' 3 | 4 | import Header from './Header' 5 | 6 | /* Our app sits here to not cause any conflicts with payload's root layout */ 7 | const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) => { 8 | return ( 9 | 10 | 11 |
12 | {children} 13 | 14 | 15 | ) 16 | } 17 | 18 | export default Layout 19 | -------------------------------------------------------------------------------- /src/app/(payload)/api/[...slug]/route.ts: -------------------------------------------------------------------------------- 1 | /* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ 2 | /* DO NOT MODIFY it because it could be re-written at any time. */ 3 | import config from '@payload-config' 4 | import { REST_DELETE, REST_GET, REST_OPTIONS, REST_PATCH, REST_POST } from '@payloadcms/next/routes' 5 | 6 | export const GET = REST_GET(config) 7 | export const POST = REST_POST(config) 8 | export const DELETE = REST_DELETE(config) 9 | export const PATCH = REST_PATCH(config) 10 | export const OPTIONS = REST_OPTIONS(config) 11 | -------------------------------------------------------------------------------- /src/app/(app)/Header.tsx: -------------------------------------------------------------------------------- 1 | import { FilmIcon } from 'lucide-react' 2 | import Link from 'next/link' 3 | 4 | export default function Header() { 5 | return ( 6 |
7 | 8 | 9 |

Our Favorite Movies

10 | {' '} 11 | | 12 | 13 | Add A Movie 14 | 15 |
16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /src/app/(payload)/layout.tsx: -------------------------------------------------------------------------------- 1 | /* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ 2 | import configPromise from '@payload-config' 3 | import '@payloadcms/next/css' 4 | import { RootLayout } from '@payloadcms/next/layouts' 5 | /* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ 6 | import React from 'react' 7 | 8 | import './custom.scss' 9 | 10 | type Args = { 11 | children: React.ReactNode 12 | } 13 | 14 | const Layout = ({ children }: Args) => {children} 15 | 16 | export default Layout 17 | -------------------------------------------------------------------------------- /src/app/(app)/page.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { getPayloadHMR } from '@payloadcms/next/utilities' 4 | import configPromise from '@payload-config' 5 | 6 | import MovieCards from './MovieCards' 7 | 8 | 9 | const Page = async () => { 10 | const payload = await getPayloadHMR({ config: configPromise }) 11 | 12 | const movies = await payload.find({ 13 | collection: 'movies', 14 | sort: '-votes', 15 | }) 16 | 17 | return ( 18 | <> 19 |
20 | 21 |
22 | 23 | ) 24 | } 25 | 26 | export default Page 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | .env.production.local 9 | .env.production 10 | 11 | /.idea/* 12 | !/.idea/runConfigurations 13 | 14 | # testing 15 | /coverage 16 | 17 | # next.js 18 | /.next/ 19 | /out/ 20 | 21 | # production 22 | /build 23 | 24 | # misc 25 | .DS_Store 26 | *.pem 27 | 28 | # debug 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | 33 | # local env files 34 | .env*.local 35 | 36 | # vercel 37 | .vercel 38 | 39 | # typescript 40 | *.tsbuildinfo 41 | next-env.d.ts 42 | 43 | .env 44 | 45 | /media 46 | -------------------------------------------------------------------------------- /src/app/(payload)/admin/[[...segments]]/page.tsx: -------------------------------------------------------------------------------- 1 | /* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ 2 | import type { Metadata } from 'next' 3 | 4 | import config from '@payload-config' 5 | /* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ 6 | import { RootPage, generatePageMetadata } from '@payloadcms/next/views' 7 | 8 | type Args = { 9 | params: { 10 | segments: string[] 11 | } 12 | searchParams: { 13 | [key: string]: string | string[] 14 | } 15 | } 16 | 17 | export const generateMetadata = ({ params, searchParams }: Args): Promise => 18 | generatePageMetadata({ config, params, searchParams }) 19 | 20 | const Page = ({ params, searchParams }: Args) => RootPage({ config, params, searchParams }) 21 | 22 | export default Page 23 | -------------------------------------------------------------------------------- /src/app/(payload)/admin/[[...segments]]/not-found.tsx: -------------------------------------------------------------------------------- 1 | /* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */ 2 | import type { Metadata } from 'next' 3 | 4 | import config from '@payload-config' 5 | /* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */ 6 | import { NotFoundPage, generatePageMetadata } from '@payloadcms/next/views' 7 | 8 | type Args = { 9 | params: { 10 | segments: string[] 11 | } 12 | searchParams: { 13 | [key: string]: string | string[] 14 | } 15 | } 16 | 17 | export const generateMetadata = ({ params, searchParams }: Args): Promise => 18 | generatePageMetadata({ config, params, searchParams }) 19 | 20 | const NotFound = ({ params, searchParams }: Args) => NotFoundPage({ config, params, searchParams }) 21 | 22 | export default NotFound 23 | -------------------------------------------------------------------------------- /.idea/runConfigurations/Run_Dev__pnpm_.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | -------------------------------------------------------------------------------- /start-database.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DB_CONTAINER_NAME="next-payload-3" 4 | 5 | if ! [ -x "$(command -v docker)" ]; then 6 | echo "Docker is not installed. Please install docker and try again.\nDocker install guide: https://docs.docker.com/engine/install/" 7 | exit 1 8 | fi 9 | 10 | if [ "$(docker ps -q -f name=$DB_CONTAINER_NAME)" ]; then 11 | docker start $DB_CONTAINER_NAME 12 | echo "Database container started" 13 | exit 0 14 | fi 15 | 16 | set -a 17 | source .env 18 | 19 | DB_PASSWORD=$(echo $DATABASE_URL | awk -F':' '{print $3}' | awk -F'@' '{print $1}') 20 | 21 | if [ "$DB_PASSWORD" = "password" ]; then 22 | echo "You are using the default database password" 23 | fi 24 | 25 | docker run --name $DB_CONTAINER_NAME -e POSTGRES_PASSWORD=$DB_PASSWORD -e POSTGRES_HOST_AUTH_METHOD=trust -e POSTGRES_DB=next-payload-3 -d -p 5432:5432 docker.io/postgres 26 | 27 | echo "Database container was successfully created" 28 | 29 | -------------------------------------------------------------------------------- /src/components/ui/input.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | export interface InputProps 6 | extends React.InputHTMLAttributes {} 7 | 8 | const Input = React.forwardRef( 9 | ({ className, type, ...props }, ref) => { 10 | return ( 11 | 20 | ) 21 | } 22 | ) 23 | Input.displayName = "Input" 24 | 25 | export { Input } 26 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "strict": true, 12 | "noEmit": true, 13 | "esModuleInterop": true, 14 | "module": "esnext", 15 | "moduleResolution": "bundler", 16 | "resolveJsonModule": true, 17 | "isolatedModules": true, 18 | "jsx": "preserve", 19 | "incremental": true, 20 | "plugins": [ 21 | { 22 | "name": "next" 23 | } 24 | ], 25 | "paths": { 26 | "@/*": [ 27 | "./src/*" 28 | ], 29 | "@payload-config": [ 30 | "./payload.config.ts" 31 | ] 32 | }, 33 | "target": "ES2017" 34 | }, 35 | "include": [ 36 | "next-env.d.ts", 37 | "**/*.ts", 38 | "**/*.tsx", 39 | ".next/types/**/*.ts" 40 | ], 41 | "exclude": [ 42 | "node_modules" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "npm.packageManager": "pnpm", 3 | "editor.defaultFormatter": "esbenp.prettier-vscode", 4 | "[typescript]": { 5 | "editor.defaultFormatter": "esbenp.prettier-vscode", 6 | "editor.formatOnSave": true, 7 | "editor.codeActionsOnSave": { 8 | "source.fixAll.eslint": "explicit" 9 | } 10 | }, 11 | "[typescriptreact]": { 12 | "editor.defaultFormatter": "esbenp.prettier-vscode", 13 | "editor.formatOnSave": true, 14 | "editor.codeActionsOnSave": { 15 | "source.fixAll.eslint": "explicit" 16 | } 17 | }, 18 | "[javascript]": { 19 | "editor.defaultFormatter": "esbenp.prettier-vscode", 20 | "editor.formatOnSave": true, 21 | "editor.codeActionsOnSave": { 22 | "source.fixAll.eslint": "explicit" 23 | } 24 | }, 25 | "[json]": { 26 | "editor.defaultFormatter": "esbenp.prettier-vscode", 27 | "editor.formatOnSave": true 28 | }, 29 | "[jsonc]": { 30 | "editor.defaultFormatter": "esbenp.prettier-vscode", 31 | "editor.formatOnSave": true 32 | }, 33 | "editor.formatOnSaveMode": "file", 34 | "eslint.rules.customizations": [{ "rule": "*", "severity": "warn" }], 35 | "typescript.tsdk": "node_modules/typescript/lib", 36 | "[javascript][typescript][typescriptreact]": { 37 | "editor.codeActionsOnSave": { 38 | "source.fixAll.eslint": "explicit" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/app/(app)/movie/[slug]/page.tsx: -------------------------------------------------------------------------------- 1 | import Image from 'next/image' 2 | import { notFound } from 'next/navigation' 3 | 4 | import type { Media } from 'payload-types' 5 | import { getPayloadHMR } from '@payloadcms/next/utilities' 6 | import configPromise from '@payload-config' 7 | 8 | 9 | export default async function MovieDetails({ params }: { params: { slug: string } }) { 10 | const { slug } = params 11 | const payload = await getPayloadHMR({ config: configPromise }) 12 | 13 | const movies = await payload.find({ 14 | collection: 'movies', 15 | where: { 16 | slug: { equals: slug }, 17 | }, 18 | }) 19 | 20 | if (movies.docs.length === 0) { 21 | return notFound() 22 | } 23 | 24 | const movie = movies.docs[0] 25 | 26 | return ( 27 |
28 | {(movie.poster 35 |
36 |

{movie.name}

37 | {movie.tagline &&

{movie.tagline}

} 38 |

39 | {movie.genres.map(({ name }) => name).join(', ')} 40 |

41 |

{movie.overview}

42 |
43 |
44 | ) 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Payload 3.0 Movies Example 2 | 3 | This repo showcases Payload 3.0, its support for Postgres (as well as MongoDB), its asset management system and admin dashboard, as well as simple deployment to Vercel. 4 | 5 | ### Quick Start 6 | 7 | [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fjherr%2Fpayload-3.0-movies&project-name=our-favorite-movies&env=PAYLOAD_SECRET,TMDB_API_KEY&build-command=pnpm%20run%20ci&stores=%5B%7B%22type%22%3A%22postgres%22%7D%2C%7B%22type%22%3A%22blob%22%7D%5D) 8 | 9 | ### Local Development 10 | 11 | #### Create the local development environment file. 12 | 13 | ```bash 14 | cp .env.example .env.development.local 15 | ``` 16 | 17 | #### Run the script start database script, which uses docker to spin up Postgres. 18 | 19 | ```bash 20 | ./start-database.sh 21 | ``` 22 | 23 | _Note: You can change the connection string in the .env.development.local file to point to a different database, you will also want to change it in the start-database.sh script._ 24 | 25 | #### Create a payload secret, perhaps using `openssl rand -base64 32` and set that value in the .env.development.local file. 26 | 27 | Get a [TMBD API key](https://www.themoviedb.org/settings/api) and add it to the .env.development.local file. You will need an account on TMDB. It's all free. 28 | 29 | #### Install the dependencies. 30 | 31 | ```bash 32 | pnpm i 33 | ``` 34 | 35 | #### Create the database migration file. 36 | 37 | ```bash 38 | pnpm run payload migrate:create initial 39 | ``` 40 | 41 | #### Run the migration to create the database tables. 42 | 43 | ```bash 44 | pnpm run payload migrate 45 | ``` 46 | 47 | #### Start up the development server. 48 | 49 | ```bash 50 | pnpm dev 51 | ``` 52 | -------------------------------------------------------------------------------- /src/app/(app)/globals.scss: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | @layer base { 6 | :root { 7 | --background: 0 0% 100%; 8 | --foreground: 222.2 84% 4.9%; 9 | 10 | --card: 0 0% 100%; 11 | --card-foreground: 222.2 84% 4.9%; 12 | 13 | --popover: 0 0% 100%; 14 | --popover-foreground: 222.2 84% 4.9%; 15 | 16 | --primary: 222.2 47.4% 11.2%; 17 | --primary-foreground: 210 40% 98%; 18 | 19 | --secondary: 210 40% 96.1%; 20 | --secondary-foreground: 222.2 47.4% 11.2%; 21 | 22 | --muted: 210 40% 96.1%; 23 | --muted-foreground: 215.4 16.3% 46.9%; 24 | 25 | --accent: 210 40% 96.1%; 26 | --accent-foreground: 222.2 47.4% 11.2%; 27 | 28 | --destructive: 0 84.2% 60.2%; 29 | --destructive-foreground: 210 40% 98%; 30 | 31 | --border: 214.3 31.8% 91.4%; 32 | --input: 214.3 31.8% 91.4%; 33 | --ring: 222.2 84% 4.9%; 34 | 35 | --radius: 0.5rem; 36 | } 37 | 38 | .dark { 39 | --background: 222.2 84% 4.9%; 40 | --foreground: 210 40% 98%; 41 | 42 | --card: 222.2 84% 4.9%; 43 | --card-foreground: 210 40% 98%; 44 | 45 | --popover: 222.2 84% 4.9%; 46 | --popover-foreground: 210 40% 98%; 47 | 48 | --primary: 210 40% 98%; 49 | --primary-foreground: 222.2 47.4% 11.2%; 50 | 51 | --secondary: 217.2 32.6% 17.5%; 52 | --secondary-foreground: 210 40% 98%; 53 | 54 | --muted: 217.2 32.6% 17.5%; 55 | --muted-foreground: 215 20.2% 65.1%; 56 | 57 | --accent: 217.2 32.6% 17.5%; 58 | --accent-foreground: 210 40% 98%; 59 | 60 | --destructive: 0 62.8% 30.6%; 61 | --destructive-foreground: 210 40% 98%; 62 | 63 | --border: 217.2 32.6% 17.5%; 64 | --input: 217.2 32.6% 17.5%; 65 | --ring: 212.7 26.8% 83.9%; 66 | } 67 | } 68 | 69 | @layer base { 70 | * { 71 | @apply border-border; 72 | } 73 | body { 74 | @apply bg-background text-foreground; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/app/(app)/MovieCards.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | import React, { useState } from 'react' 3 | import Image from 'next/image' 4 | import Link from 'next/link' 5 | 6 | import type { Movie, Media } from 'payload-types' 7 | import { VoteIcon, ThumbsUpIcon } from 'lucide-react' 8 | 9 | import { Button } from '@/components/ui/button' 10 | import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' 11 | import { addVote } from '@/movies' 12 | 13 | export default function MovieCards({ movies: initialMovies }: { movies: Movie[] }) { 14 | const [movies, setMovies] = useState(initialMovies) 15 | 16 | return ( 17 |
18 | {movies.map((movie) => ( 19 | 20 | 21 | 22 | {movie.name} 23 | 24 | 25 | 26 | {(movie.poster 32 | 33 |
34 |
35 | 36 |
{movie.votes}
37 |
38 | 45 |
46 |
47 |
48 |
49 | ))} 50 |
51 | ) 52 | } 53 | -------------------------------------------------------------------------------- /src/cms/collections/Movies/index.ts: -------------------------------------------------------------------------------- 1 | import { CollectionConfig, FieldHook } from 'payload' 2 | 3 | const format = (val: string): string => 4 | val 5 | .replace(/ /g, '-') 6 | .replace(/[^\w-/]+/g, '') 7 | .toLowerCase() 8 | 9 | const formatSlug = 10 | (fallback: string): FieldHook => 11 | ({ value, originalDoc, data }) => { 12 | if (typeof value === 'string') { 13 | return format(value) 14 | } 15 | const fallbackData = data?.[fallback] || originalDoc?.[fallback] 16 | 17 | if (fallbackData && typeof fallbackData === 'string') { 18 | return format(fallbackData) 19 | } 20 | 21 | return value 22 | } 23 | 24 | export const MoviesCollection: CollectionConfig = { 25 | slug: 'movies', 26 | admin: { 27 | useAsTitle: 'name', 28 | }, 29 | access: { 30 | create: () => true, 31 | read: () => true, 32 | }, 33 | fields: [ 34 | { 35 | name: 'name', 36 | type: 'text', 37 | required: true, 38 | }, 39 | { 40 | name: 'url', 41 | type: 'text', 42 | required: true, 43 | }, 44 | { 45 | name: 'votes', 46 | type: 'number', 47 | required: true, 48 | }, 49 | { 50 | name: 'poster', 51 | type: 'upload', 52 | relationTo: 'media', // required 53 | required: true, 54 | }, 55 | { 56 | name: 'overview', 57 | type: 'text', 58 | required: true, 59 | }, 60 | { 61 | name: 'tagline', 62 | type: 'text', 63 | required: false, // Some movies in tmd have no tagline 64 | }, 65 | { 66 | name: 'genres', 67 | type: 'array', 68 | fields: [ 69 | { 70 | name: 'name', 71 | type: 'text', 72 | }, 73 | ], 74 | required: true, 75 | }, 76 | { 77 | name: 'slug', 78 | label: 'Slug', 79 | type: 'text', 80 | admin: { 81 | position: 'sidebar', 82 | }, 83 | hooks: { 84 | beforeValidate: [formatSlug('name')], 85 | }, 86 | }, 87 | ], 88 | } 89 | -------------------------------------------------------------------------------- /src/components/ui/button.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import { Slot } from "@radix-ui/react-slot" 3 | import { cva, type VariantProps } from "class-variance-authority" 4 | 5 | import { cn } from "@/lib/utils" 6 | 7 | const buttonVariants = cva( 8 | "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", 9 | { 10 | variants: { 11 | variant: { 12 | default: "bg-primary text-primary-foreground hover:bg-primary/90", 13 | destructive: 14 | "bg-destructive text-destructive-foreground hover:bg-destructive/90", 15 | outline: 16 | "border border-input bg-background hover:bg-accent hover:text-accent-foreground", 17 | secondary: 18 | "bg-secondary text-secondary-foreground hover:bg-secondary/80", 19 | ghost: "hover:bg-accent hover:text-accent-foreground", 20 | link: "text-primary underline-offset-4 hover:underline", 21 | }, 22 | size: { 23 | default: "h-10 px-4 py-2", 24 | sm: "h-9 rounded-md px-3", 25 | lg: "h-11 rounded-md px-8", 26 | icon: "h-10 w-10", 27 | }, 28 | }, 29 | defaultVariants: { 30 | variant: "default", 31 | size: "default", 32 | }, 33 | } 34 | ) 35 | 36 | export interface ButtonProps 37 | extends React.ButtonHTMLAttributes, 38 | VariantProps { 39 | asChild?: boolean 40 | } 41 | 42 | const Button = React.forwardRef( 43 | ({ className, variant, size, asChild = false, ...props }, ref) => { 44 | const Comp = asChild ? Slot : "button" 45 | return ( 46 | 51 | ) 52 | } 53 | ) 54 | Button.displayName = "Button" 55 | 56 | export { Button, buttonVariants } 57 | -------------------------------------------------------------------------------- /src/app/(app)/add/page.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | import { useState, useEffect } from 'react' 3 | import Image from 'next/image' 4 | import { useRouter } from 'next/navigation' 5 | 6 | import { Input } from '@/components/ui/input' 7 | import { Button } from '@/components/ui/button' 8 | import { 9 | Carousel, 10 | CarouselContent, 11 | CarouselItem, 12 | CarouselNext, 13 | CarouselPrevious, 14 | } from '@/components/ui/carousel' 15 | 16 | import { posterURL } from '@/movies/utils' 17 | import { addMovieAction } from '@/movies' 18 | 19 | export default function Page() { 20 | const [query, setQuery] = useState('') 21 | const [movies, setMovies] = useState<{ id: number; poster_path: string; title: string }[]>([]) 22 | 23 | useEffect(() => { 24 | fetch(`/api/search?query=${encodeURIComponent(query)}`) 25 | .then((res) => res.json()) 26 | .then(setMovies) 27 | }, [query]) 28 | 29 | const router = useRouter() 30 | 31 | async function addMovie(id: number) { 32 | await addMovieAction(id) 33 | router.push(`/`) 34 | } 35 | 36 | return ( 37 |
38 |
39 | setQuery(e.target.value)} /> 40 |
41 | {movies.length > 0 ? ( 42 | 43 | 44 | {movies.map(({ id, poster_path, title }) => ( 45 | 46 | {title 53 |

{title}

54 | 55 |
56 | ))} 57 |
58 | 59 | 60 |
61 | ) : ( 62 |

Type in a query to find movies

63 | )} 64 |
65 | ) 66 | } 67 | -------------------------------------------------------------------------------- /src/components/ui/card.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | const Card = React.forwardRef< 6 | HTMLDivElement, 7 | React.HTMLAttributes 8 | >(({ className, ...props }, ref) => ( 9 |
17 | )) 18 | Card.displayName = "Card" 19 | 20 | const CardHeader = React.forwardRef< 21 | HTMLDivElement, 22 | React.HTMLAttributes 23 | >(({ className, ...props }, ref) => ( 24 |
29 | )) 30 | CardHeader.displayName = "CardHeader" 31 | 32 | const CardTitle = React.forwardRef< 33 | HTMLParagraphElement, 34 | React.HTMLAttributes 35 | >(({ className, ...props }, ref) => ( 36 |

44 | )) 45 | CardTitle.displayName = "CardTitle" 46 | 47 | const CardDescription = React.forwardRef< 48 | HTMLParagraphElement, 49 | React.HTMLAttributes 50 | >(({ className, ...props }, ref) => ( 51 |

56 | )) 57 | CardDescription.displayName = "CardDescription" 58 | 59 | const CardContent = React.forwardRef< 60 | HTMLDivElement, 61 | React.HTMLAttributes 62 | >(({ className, ...props }, ref) => ( 63 |

64 | )) 65 | CardContent.displayName = "CardContent" 66 | 67 | const CardFooter = React.forwardRef< 68 | HTMLDivElement, 69 | React.HTMLAttributes 70 | >(({ className, ...props }, ref) => ( 71 |
76 | )) 77 | CardFooter.displayName = "CardFooter" 78 | 79 | export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } 80 | -------------------------------------------------------------------------------- /payload.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { postgresAdapter } from '@payloadcms/db-postgres' 3 | import { en } from 'payload/i18n/en' 4 | import { 5 | lexicalEditor, 6 | } from '@payloadcms/richtext-lexical' 7 | import { vercelBlobStorage } from '@payloadcms/storage-vercel-blob' 8 | 9 | import { buildConfig } from 'payload' 10 | import sharp from 'sharp' 11 | import { fileURLToPath } from 'url' 12 | 13 | const filename = fileURLToPath(import.meta.url) 14 | const dirname = path.dirname(filename) 15 | 16 | import { UsersCollection } from '@/cms/collections/Users' 17 | import { MoviesCollection } from '@/cms/collections/Movies' 18 | import { MediaCollection } from '@/cms/collections/Media' 19 | 20 | export default buildConfig({ 21 | secret: process.env.PAYLOAD_SECRET || 'set-a-secret-in-your-env', 22 | collections: [UsersCollection, MoviesCollection, MediaCollection], 23 | admin: { 24 | autoLogin: { 25 | email: 'dev@payloadcms.com', 26 | password: 'test', 27 | prefillOnly: true, 28 | }, 29 | }, 30 | // the type of DB you would like to use 31 | db: postgresAdapter({ 32 | pool: { 33 | connectionString: process.env.POSTGRES_URL, 34 | }, 35 | }), 36 | plugins: process.env.BLOB_READ_WRITE_TOKEN 37 | ? [ 38 | vercelBlobStorage({ 39 | collections: { 40 | [MediaCollection.slug]: true, 41 | }, 42 | token: process.env.BLOB_READ_WRITE_TOKEN || '', 43 | }), 44 | ] 45 | : [], 46 | // richText editor 47 | editor: lexicalEditor(), 48 | typescript: { 49 | outputFile: path.resolve(dirname, 'payload-types.ts'), 50 | }, 51 | i18n: { 52 | supportedLanguages: { en }, 53 | }, 54 | async onInit(payload) { 55 | const existingUsers = await payload.find({ 56 | collection: 'users', 57 | limit: 1, 58 | }) 59 | 60 | // This is useful for local development 61 | // so you do not need to create a first-user every time 62 | if (existingUsers.docs.length === 0) { 63 | await payload.create({ 64 | collection: 'users', 65 | data: { 66 | email: 'dev@payloadcms.com', 67 | password: 'test', 68 | }, 69 | }) 70 | } 71 | }, 72 | // Sharp is now an optional dependency - 73 | // if you want to resize images, crop, set focal point, etc. 74 | // make sure to install it and pass it to the config. 75 | sharp, 76 | }) 77 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | darkMode: ['class'], 4 | content: [ 5 | './pages/**/*.{ts,tsx}', 6 | './components/**/*.{ts,tsx}', 7 | './app/**/*.{ts,tsx}', 8 | './src/**/*.{ts,tsx}', 9 | ], 10 | prefix: '', 11 | theme: { 12 | container: { 13 | center: true, 14 | padding: '2rem', 15 | screens: { 16 | '2xl': '1400px', 17 | }, 18 | }, 19 | extend: { 20 | colors: { 21 | border: 'hsl(var(--border))', 22 | input: 'hsl(var(--input))', 23 | ring: 'hsl(var(--ring))', 24 | background: 'hsl(var(--background))', 25 | foreground: 'hsl(var(--foreground))', 26 | primary: { 27 | DEFAULT: 'hsl(var(--primary))', 28 | foreground: 'hsl(var(--primary-foreground))', 29 | }, 30 | secondary: { 31 | DEFAULT: 'hsl(var(--secondary))', 32 | foreground: 'hsl(var(--secondary-foreground))', 33 | }, 34 | destructive: { 35 | DEFAULT: 'hsl(var(--destructive))', 36 | foreground: 'hsl(var(--destructive-foreground))', 37 | }, 38 | muted: { 39 | DEFAULT: 'hsl(var(--muted))', 40 | foreground: 'hsl(var(--muted-foreground))', 41 | }, 42 | accent: { 43 | DEFAULT: 'hsl(var(--accent))', 44 | foreground: 'hsl(var(--accent-foreground))', 45 | }, 46 | popover: { 47 | DEFAULT: 'hsl(var(--popover))', 48 | foreground: 'hsl(var(--popover-foreground))', 49 | }, 50 | card: { 51 | DEFAULT: 'hsl(var(--card))', 52 | foreground: 'hsl(var(--card-foreground))', 53 | }, 54 | }, 55 | borderRadius: { 56 | lg: 'var(--radius)', 57 | md: 'calc(var(--radius) - 2px)', 58 | sm: 'calc(var(--radius) - 4px)', 59 | }, 60 | keyframes: { 61 | 'accordion-down': { 62 | from: { height: '0' }, 63 | to: { height: 'var(--radix-accordion-content-height)' }, 64 | }, 65 | 'accordion-up': { 66 | from: { height: 'var(--radix-accordion-content-height)' }, 67 | to: { height: '0' }, 68 | }, 69 | }, 70 | animation: { 71 | 'accordion-down': 'accordion-down 0.2s ease-out', 72 | 'accordion-up': 'accordion-up 0.2s ease-out', 73 | }, 74 | }, 75 | }, 76 | plugins: [require('tailwindcss-animate')], 77 | } 78 | -------------------------------------------------------------------------------- /src/movies/index.ts: -------------------------------------------------------------------------------- 1 | 'use server' 2 | import { getPayloadHMR } from '@payloadcms/next/utilities' 3 | import configPromise from '@payload-config' 4 | import { revalidatePath } from 'next/cache' 5 | 6 | import { posterURL } from './utils' 7 | 8 | export async function searchMovies(query: string) { 9 | const response = await fetch( 10 | `https://api.themoviedb.org/3/search/movie?query=${encodeURIComponent( 11 | query, 12 | )}&include_adult=false&language=en-US&page=1&api_key=${process.env.TMDB_API_KEY}`, 13 | ) 14 | const { results } = await response.json() 15 | return results 16 | .map(({ id, poster_path, title }: { id: string; poster_path: string; title: string }) => ({ 17 | id, 18 | poster_path, 19 | title, 20 | })) 21 | .filter(({ poster_path }: { poster_path: string }) => !!poster_path) 22 | } 23 | 24 | export async function addMovieAction(movieId: number) { 25 | const payload = await getPayloadHMR({ config: configPromise }) 26 | 27 | const movieDataReq = await fetch( 28 | `https://api.themoviedb.org/3/movie/${movieId}?language=en-US&api_key=${process.env.TMDB_API_KEY}`, 29 | ) 30 | const { title, poster_path, overview, tagline, genres: genreObjects } = await movieDataReq.json() 31 | const genres = genreObjects.map(({ name }: { name: string }) => ({ name })) 32 | 33 | const response = await fetch(posterURL(poster_path)) 34 | const arrayBuffer = await response.arrayBuffer() 35 | const posterBuffer = Buffer.from(arrayBuffer) 36 | 37 | const posterMedia = await payload.create({ 38 | collection: 'media', 39 | data: { 40 | text: `${title} Poster`, 41 | }, 42 | file: { 43 | data: posterBuffer, 44 | name: `${movieId}.jpg`, 45 | mimetype: 'image/jpeg', 46 | size: posterBuffer.byteLength, 47 | }, 48 | }) 49 | 50 | const movie = await payload.create({ 51 | collection: 'movies', 52 | data: { 53 | name: title, 54 | url: `https://www.themoviedb.org/movie/${movieId}`, 55 | votes: 0, 56 | poster: posterMedia.id, 57 | overview, 58 | tagline, 59 | genres, 60 | }, 61 | }) 62 | 63 | revalidatePath('/') 64 | 65 | return movie 66 | } 67 | 68 | export async function addVote(movieId: number) { 69 | const payload = await getPayloadHMR({ config: configPromise }) 70 | 71 | const movie = await payload.findByID({ 72 | collection: 'movies', 73 | id: movieId, 74 | }) 75 | 76 | await payload.update({ 77 | collection: 'movies', 78 | id: movieId, 79 | data: { 80 | votes: movie.votes + 1, 81 | }, 82 | }) 83 | 84 | const movies = await payload.find({ 85 | collection: 'movies', 86 | sort: '-votes', 87 | }) 88 | return movies.docs 89 | } 90 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "our-favorite-movies", 3 | "version": "0.1.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "cross-env NODE_OPTIONS=--no-deprecation next dev", 8 | "devturbo": "cross-env NODE_OPTIONS=--no-deprecation next dev --turbo", 9 | "devsafe": "rm -rf .next && cross-env NODE_OPTIONS=--no-deprecation next dev", 10 | "build": "cross-env NODE_OPTIONS=--no-deprecation next build", 11 | "payload": "cross-env NODE_OPTIONS=--no-deprecation payload", 12 | "start": "cross-env NODE_OPTIONS=--no-deprecation next start", 13 | "lint": "cross-env NODE_OPTIONS=--no-deprecation next lint", 14 | "ci": "payload migrate && pnpm build", 15 | "generate:types": "payload generate:types", 16 | "generate:schema": "payload-graphql generate:schema" 17 | }, 18 | "engines": { 19 | "node": "^18.20.2 || >=20.9.0" 20 | }, 21 | "dependencies": { 22 | "@payloadcms/db-postgres": "3.0.0-beta.63", 23 | "@payloadcms/next": "3.0.0-beta.63", 24 | "@payloadcms/plugin-cloud-storage": "3.0.0-beta.63", 25 | "@payloadcms/richtext-lexical": "3.0.0-beta.63", 26 | "@payloadcms/richtext-slate": "3.0.0-beta.63", 27 | "@payloadcms/ui": "3.0.0-beta.63", 28 | "@payloadcms/storage-vercel-blob": "3.0.0-beta.63", 29 | "@vercel/blob": "^0.22.3", 30 | "@radix-ui/react-slot": "^1.0.2", 31 | "babel-plugin-react-compiler": "^0.0.0-experimental-592953e-20240517", 32 | "class-variance-authority": "^0.7.0", 33 | "clsx": "^2.1.1", 34 | "cross-env": "^7.0.3", 35 | "embla-carousel-react": "^8.1.5", 36 | "graphql": "^16.8.1", 37 | "lucide-react": "^0.395.0", 38 | "next": "15.0.0-canary.53", 39 | "payload": "3.0.0-beta.63", 40 | "react": "19.0.0-rc-6230622a1a-20240610", 41 | "react-dom": "19.0.0-rc-6230622a1a-20240610", 42 | "sharp": "0.32.6", 43 | "tailwind-merge": "^2.3.0", 44 | "tailwindcss-animate": "^1.0.7" 45 | }, 46 | "devDependencies": { 47 | "@types/node": "^20.12.12", 48 | "@types/react": "npm:types-react@19.0.0-rc.0", 49 | "@types/react-dom": "npm:types-react-dom@19.0.0-rc.0", 50 | "autoprefixer": "^10.4.19", 51 | "eslint": "^8.57.0", 52 | "eslint-config-next": "15.0.0-canary.53", 53 | "postcss": "^8.4.38", 54 | "tailwindcss": "^3.4.4", 55 | "typescript": "5.5.3" 56 | }, 57 | "pnpm": { 58 | "overrides": { 59 | "@types/react": "npm:types-react@19.0.0-rc.0", 60 | "@types/react-dom": "npm:types-react-dom@19.0.0-rc.0" 61 | } 62 | }, 63 | "overrides": { 64 | "@types/react": "npm:types-react@19.0.0-rc.0", 65 | "@types/react-dom": "npm:types-react-dom@19.0.0-rc.0" 66 | }, 67 | "packageManager": "pnpm@8.15.7+sha256.50783dd0fa303852de2dd1557cd4b9f07cb5b018154a6e76d0f40635d6cee019" 68 | } 69 | -------------------------------------------------------------------------------- /payload-types.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * This file was automatically generated by Payload. 5 | * DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config, 6 | * and re-run `payload generate:types` to regenerate this file. 7 | */ 8 | 9 | export interface Config { 10 | auth: { 11 | users: UserAuthOperations; 12 | }; 13 | collections: { 14 | users: User; 15 | movies: Movie; 16 | media: Media; 17 | 'payload-preferences': PayloadPreference; 18 | 'payload-migrations': PayloadMigration; 19 | }; 20 | globals: {}; 21 | locale: null; 22 | user: User & { 23 | collection: 'users'; 24 | }; 25 | } 26 | export interface UserAuthOperations { 27 | forgotPassword: { 28 | email: string; 29 | }; 30 | login: { 31 | password: string; 32 | email: string; 33 | }; 34 | registerFirstUser: { 35 | email: string; 36 | password: string; 37 | }; 38 | } 39 | /** 40 | * This interface was referenced by `Config`'s JSON-Schema 41 | * via the `definition` "users". 42 | */ 43 | export interface User { 44 | id: number; 45 | updatedAt: string; 46 | createdAt: string; 47 | email: string; 48 | resetPasswordToken?: string | null; 49 | resetPasswordExpiration?: string | null; 50 | salt?: string | null; 51 | hash?: string | null; 52 | loginAttempts?: number | null; 53 | lockUntil?: string | null; 54 | password?: string | null; 55 | } 56 | /** 57 | * This interface was referenced by `Config`'s JSON-Schema 58 | * via the `definition` "movies". 59 | */ 60 | export interface Movie { 61 | id: number; 62 | name: string; 63 | url: string; 64 | votes: number; 65 | poster: number | Media; 66 | overview: string; 67 | tagline?: string | null; 68 | genres: { 69 | name?: string | null; 70 | id?: string | null; 71 | }[]; 72 | slug?: string | null; 73 | updatedAt: string; 74 | createdAt: string; 75 | } 76 | /** 77 | * This interface was referenced by `Config`'s JSON-Schema 78 | * via the `definition` "media". 79 | */ 80 | export interface Media { 81 | id: number; 82 | text?: string | null; 83 | updatedAt: string; 84 | createdAt: string; 85 | url?: string | null; 86 | thumbnailURL?: string | null; 87 | filename?: string | null; 88 | mimeType?: string | null; 89 | filesize?: number | null; 90 | width?: number | null; 91 | height?: number | null; 92 | focalX?: number | null; 93 | focalY?: number | null; 94 | } 95 | /** 96 | * This interface was referenced by `Config`'s JSON-Schema 97 | * via the `definition` "payload-preferences". 98 | */ 99 | export interface PayloadPreference { 100 | id: number; 101 | user: { 102 | relationTo: 'users'; 103 | value: number | User; 104 | }; 105 | key?: string | null; 106 | value?: 107 | | { 108 | [k: string]: unknown; 109 | } 110 | | unknown[] 111 | | string 112 | | number 113 | | boolean 114 | | null; 115 | updatedAt: string; 116 | createdAt: string; 117 | } 118 | /** 119 | * This interface was referenced by `Config`'s JSON-Schema 120 | * via the `definition` "payload-migrations". 121 | */ 122 | export interface PayloadMigration { 123 | id: number; 124 | name?: string | null; 125 | batch?: number | null; 126 | updatedAt: string; 127 | createdAt: string; 128 | } 129 | /** 130 | * This interface was referenced by `Config`'s JSON-Schema 131 | * via the `definition` "auth". 132 | */ 133 | export interface Auth { 134 | [k: string]: unknown; 135 | } 136 | 137 | 138 | declare module 'payload' { 139 | export interface GeneratedTypes extends Config {} 140 | } -------------------------------------------------------------------------------- /src/migrations/20240712_231319_initial.ts: -------------------------------------------------------------------------------- 1 | import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres' 2 | 3 | export async function up({ payload, req }: MigrateUpArgs): Promise { 4 | await payload.db.drizzle.execute(sql` 5 | CREATE TABLE IF NOT EXISTS "users" ( 6 | "id" serial PRIMARY KEY NOT NULL, 7 | "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, 8 | "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL, 9 | "email" varchar NOT NULL, 10 | "reset_password_token" varchar, 11 | "reset_password_expiration" timestamp(3) with time zone, 12 | "salt" varchar, 13 | "hash" varchar, 14 | "login_attempts" numeric, 15 | "lock_until" timestamp(3) with time zone 16 | ); 17 | 18 | CREATE TABLE IF NOT EXISTS "movies_genres" ( 19 | "_order" integer NOT NULL, 20 | "_parent_id" integer NOT NULL, 21 | "id" varchar PRIMARY KEY NOT NULL, 22 | "name" varchar 23 | ); 24 | 25 | CREATE TABLE IF NOT EXISTS "movies" ( 26 | "id" serial PRIMARY KEY NOT NULL, 27 | "name" varchar NOT NULL, 28 | "url" varchar NOT NULL, 29 | "votes" numeric NOT NULL, 30 | "poster_id" integer NOT NULL, 31 | "overview" varchar NOT NULL, 32 | "tagline" varchar, 33 | "slug" varchar, 34 | "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, 35 | "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL 36 | ); 37 | 38 | CREATE TABLE IF NOT EXISTS "media" ( 39 | "id" serial PRIMARY KEY NOT NULL, 40 | "text" varchar, 41 | "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, 42 | "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL, 43 | "url" varchar, 44 | "thumbnail_u_r_l" varchar, 45 | "filename" varchar, 46 | "mime_type" varchar, 47 | "filesize" numeric, 48 | "width" numeric, 49 | "height" numeric, 50 | "focal_x" numeric, 51 | "focal_y" numeric 52 | ); 53 | 54 | CREATE TABLE IF NOT EXISTS "payload_preferences" ( 55 | "id" serial PRIMARY KEY NOT NULL, 56 | "key" varchar, 57 | "value" jsonb, 58 | "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, 59 | "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL 60 | ); 61 | 62 | CREATE TABLE IF NOT EXISTS "payload_preferences_rels" ( 63 | "id" serial PRIMARY KEY NOT NULL, 64 | "order" integer, 65 | "parent_id" integer NOT NULL, 66 | "path" varchar NOT NULL, 67 | "users_id" integer 68 | ); 69 | 70 | CREATE TABLE IF NOT EXISTS "payload_migrations" ( 71 | "id" serial PRIMARY KEY NOT NULL, 72 | "name" varchar, 73 | "batch" numeric, 74 | "updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL, 75 | "created_at" timestamp(3) with time zone DEFAULT now() NOT NULL 76 | ); 77 | 78 | CREATE INDEX IF NOT EXISTS "users_created_at_idx" ON "users" ("created_at"); 79 | CREATE UNIQUE INDEX IF NOT EXISTS "users_email_idx" ON "users" ("email"); 80 | CREATE INDEX IF NOT EXISTS "movies_genres_order_idx" ON "movies_genres" ("_order"); 81 | CREATE INDEX IF NOT EXISTS "movies_genres_parent_id_idx" ON "movies_genres" ("_parent_id"); 82 | CREATE INDEX IF NOT EXISTS "movies_created_at_idx" ON "movies" ("created_at"); 83 | CREATE INDEX IF NOT EXISTS "media_created_at_idx" ON "media" ("created_at"); 84 | CREATE UNIQUE INDEX IF NOT EXISTS "media_filename_idx" ON "media" ("filename"); 85 | CREATE INDEX IF NOT EXISTS "payload_preferences_key_idx" ON "payload_preferences" ("key"); 86 | CREATE INDEX IF NOT EXISTS "payload_preferences_created_at_idx" ON "payload_preferences" ("created_at"); 87 | CREATE INDEX IF NOT EXISTS "payload_preferences_rels_order_idx" ON "payload_preferences_rels" ("order"); 88 | CREATE INDEX IF NOT EXISTS "payload_preferences_rels_parent_idx" ON "payload_preferences_rels" ("parent_id"); 89 | CREATE INDEX IF NOT EXISTS "payload_preferences_rels_path_idx" ON "payload_preferences_rels" ("path"); 90 | CREATE INDEX IF NOT EXISTS "payload_migrations_created_at_idx" ON "payload_migrations" ("created_at"); 91 | DO $$ BEGIN 92 | ALTER TABLE "movies_genres" ADD CONSTRAINT "movies_genres_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "movies"("id") ON DELETE cascade ON UPDATE no action; 93 | EXCEPTION 94 | WHEN duplicate_object THEN null; 95 | END $$; 96 | 97 | DO $$ BEGIN 98 | ALTER TABLE "movies" ADD CONSTRAINT "movies_poster_id_media_id_fk" FOREIGN KEY ("poster_id") REFERENCES "media"("id") ON DELETE set null ON UPDATE no action; 99 | EXCEPTION 100 | WHEN duplicate_object THEN null; 101 | END $$; 102 | 103 | DO $$ BEGIN 104 | ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "payload_preferences"("id") ON DELETE cascade ON UPDATE no action; 105 | EXCEPTION 106 | WHEN duplicate_object THEN null; 107 | END $$; 108 | 109 | DO $$ BEGIN 110 | ALTER TABLE "payload_preferences_rels" ADD CONSTRAINT "payload_preferences_rels_users_fk" FOREIGN KEY ("users_id") REFERENCES "users"("id") ON DELETE cascade ON UPDATE no action; 111 | EXCEPTION 112 | WHEN duplicate_object THEN null; 113 | END $$; 114 | `) 115 | }; 116 | 117 | export async function down({ payload, req }: MigrateDownArgs): Promise { 118 | await payload.db.drizzle.execute(sql` 119 | DROP TABLE "users"; 120 | DROP TABLE "movies_genres"; 121 | DROP TABLE "movies"; 122 | DROP TABLE "media"; 123 | DROP TABLE "payload_preferences"; 124 | DROP TABLE "payload_preferences_rels"; 125 | DROP TABLE "payload_migrations";`) 126 | }; 127 | -------------------------------------------------------------------------------- /src/components/ui/carousel.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import useEmblaCarousel, { 5 | type UseEmblaCarouselType, 6 | } from "embla-carousel-react" 7 | import { ArrowLeft, ArrowRight } from "lucide-react" 8 | 9 | import { cn } from "@/lib/utils" 10 | import { Button } from "@/components/ui/button" 11 | 12 | type CarouselApi = UseEmblaCarouselType[1] 13 | type UseCarouselParameters = Parameters 14 | type CarouselOptions = UseCarouselParameters[0] 15 | type CarouselPlugin = UseCarouselParameters[1] 16 | 17 | type CarouselProps = { 18 | opts?: CarouselOptions 19 | plugins?: CarouselPlugin 20 | orientation?: "horizontal" | "vertical" 21 | setApi?: (api: CarouselApi) => void 22 | } 23 | 24 | type CarouselContextProps = { 25 | carouselRef: ReturnType[0] 26 | api: ReturnType[1] 27 | scrollPrev: () => void 28 | scrollNext: () => void 29 | canScrollPrev: boolean 30 | canScrollNext: boolean 31 | } & CarouselProps 32 | 33 | const CarouselContext = React.createContext(null) 34 | 35 | function useCarousel() { 36 | const context = React.useContext(CarouselContext) 37 | 38 | if (!context) { 39 | throw new Error("useCarousel must be used within a ") 40 | } 41 | 42 | return context 43 | } 44 | 45 | const Carousel = React.forwardRef< 46 | HTMLDivElement, 47 | React.HTMLAttributes & CarouselProps 48 | >( 49 | ( 50 | { 51 | orientation = "horizontal", 52 | opts, 53 | setApi, 54 | plugins, 55 | className, 56 | children, 57 | ...props 58 | }, 59 | ref 60 | ) => { 61 | const [carouselRef, api] = useEmblaCarousel( 62 | { 63 | ...opts, 64 | axis: orientation === "horizontal" ? "x" : "y", 65 | }, 66 | plugins 67 | ) 68 | const [canScrollPrev, setCanScrollPrev] = React.useState(false) 69 | const [canScrollNext, setCanScrollNext] = React.useState(false) 70 | 71 | const onSelect = React.useCallback((api: CarouselApi) => { 72 | if (!api) { 73 | return 74 | } 75 | 76 | setCanScrollPrev(api.canScrollPrev()) 77 | setCanScrollNext(api.canScrollNext()) 78 | }, []) 79 | 80 | const scrollPrev = React.useCallback(() => { 81 | api?.scrollPrev() 82 | }, [api]) 83 | 84 | const scrollNext = React.useCallback(() => { 85 | api?.scrollNext() 86 | }, [api]) 87 | 88 | const handleKeyDown = React.useCallback( 89 | (event: React.KeyboardEvent) => { 90 | if (event.key === "ArrowLeft") { 91 | event.preventDefault() 92 | scrollPrev() 93 | } else if (event.key === "ArrowRight") { 94 | event.preventDefault() 95 | scrollNext() 96 | } 97 | }, 98 | [scrollPrev, scrollNext] 99 | ) 100 | 101 | React.useEffect(() => { 102 | if (!api || !setApi) { 103 | return 104 | } 105 | 106 | setApi(api) 107 | }, [api, setApi]) 108 | 109 | React.useEffect(() => { 110 | if (!api) { 111 | return 112 | } 113 | 114 | onSelect(api) 115 | api.on("reInit", onSelect) 116 | api.on("select", onSelect) 117 | 118 | return () => { 119 | api?.off("select", onSelect) 120 | } 121 | }, [api, onSelect]) 122 | 123 | return ( 124 | 137 |
145 | {children} 146 |
147 |
148 | ) 149 | } 150 | ) 151 | Carousel.displayName = "Carousel" 152 | 153 | const CarouselContent = React.forwardRef< 154 | HTMLDivElement, 155 | React.HTMLAttributes 156 | >(({ className, ...props }, ref) => { 157 | const { carouselRef, orientation } = useCarousel() 158 | 159 | return ( 160 |
161 |
170 |
171 | ) 172 | }) 173 | CarouselContent.displayName = "CarouselContent" 174 | 175 | const CarouselItem = React.forwardRef< 176 | HTMLDivElement, 177 | React.HTMLAttributes 178 | >(({ className, ...props }, ref) => { 179 | const { orientation } = useCarousel() 180 | 181 | return ( 182 |
193 | ) 194 | }) 195 | CarouselItem.displayName = "CarouselItem" 196 | 197 | const CarouselPrevious = React.forwardRef< 198 | HTMLButtonElement, 199 | React.ComponentProps 200 | >(({ className, variant = "outline", size = "icon", ...props }, ref) => { 201 | const { orientation, scrollPrev, canScrollPrev } = useCarousel() 202 | 203 | return ( 204 | 222 | ) 223 | }) 224 | CarouselPrevious.displayName = "CarouselPrevious" 225 | 226 | const CarouselNext = React.forwardRef< 227 | HTMLButtonElement, 228 | React.ComponentProps 229 | >(({ className, variant = "outline", size = "icon", ...props }, ref) => { 230 | const { orientation, scrollNext, canScrollNext } = useCarousel() 231 | 232 | return ( 233 | 251 | ) 252 | }) 253 | CarouselNext.displayName = "CarouselNext" 254 | 255 | export { 256 | type CarouselApi, 257 | Carousel, 258 | CarouselContent, 259 | CarouselItem, 260 | CarouselPrevious, 261 | CarouselNext, 262 | } 263 | -------------------------------------------------------------------------------- /src/migrations/20240712_231319_initial.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "47eb685a-0a82-4942-9f46-9c636072b779", 3 | "prevId": "00000000-0000-0000-0000-000000000000", 4 | "version": "5", 5 | "dialect": "pg", 6 | "tables": { 7 | "users": { 8 | "name": "users", 9 | "schema": "", 10 | "columns": { 11 | "id": { 12 | "name": "id", 13 | "type": "serial", 14 | "primaryKey": true, 15 | "notNull": true 16 | }, 17 | "updated_at": { 18 | "name": "updated_at", 19 | "type": "timestamp(3) with time zone", 20 | "primaryKey": false, 21 | "notNull": true, 22 | "default": "now()" 23 | }, 24 | "created_at": { 25 | "name": "created_at", 26 | "type": "timestamp(3) with time zone", 27 | "primaryKey": false, 28 | "notNull": true, 29 | "default": "now()" 30 | }, 31 | "email": { 32 | "name": "email", 33 | "type": "varchar", 34 | "primaryKey": false, 35 | "notNull": true 36 | }, 37 | "reset_password_token": { 38 | "name": "reset_password_token", 39 | "type": "varchar", 40 | "primaryKey": false, 41 | "notNull": false 42 | }, 43 | "reset_password_expiration": { 44 | "name": "reset_password_expiration", 45 | "type": "timestamp(3) with time zone", 46 | "primaryKey": false, 47 | "notNull": false 48 | }, 49 | "salt": { 50 | "name": "salt", 51 | "type": "varchar", 52 | "primaryKey": false, 53 | "notNull": false 54 | }, 55 | "hash": { 56 | "name": "hash", 57 | "type": "varchar", 58 | "primaryKey": false, 59 | "notNull": false 60 | }, 61 | "login_attempts": { 62 | "name": "login_attempts", 63 | "type": "numeric", 64 | "primaryKey": false, 65 | "notNull": false 66 | }, 67 | "lock_until": { 68 | "name": "lock_until", 69 | "type": "timestamp(3) with time zone", 70 | "primaryKey": false, 71 | "notNull": false 72 | } 73 | }, 74 | "indexes": { 75 | "users_created_at_idx": { 76 | "name": "users_created_at_idx", 77 | "columns": [ 78 | "created_at" 79 | ], 80 | "isUnique": false 81 | }, 82 | "users_email_idx": { 83 | "name": "users_email_idx", 84 | "columns": [ 85 | "email" 86 | ], 87 | "isUnique": true 88 | } 89 | }, 90 | "foreignKeys": {}, 91 | "compositePrimaryKeys": {}, 92 | "uniqueConstraints": {} 93 | }, 94 | "movies_genres": { 95 | "name": "movies_genres", 96 | "schema": "", 97 | "columns": { 98 | "_order": { 99 | "name": "_order", 100 | "type": "integer", 101 | "primaryKey": false, 102 | "notNull": true 103 | }, 104 | "_parent_id": { 105 | "name": "_parent_id", 106 | "type": "integer", 107 | "primaryKey": false, 108 | "notNull": true 109 | }, 110 | "id": { 111 | "name": "id", 112 | "type": "varchar", 113 | "primaryKey": true, 114 | "notNull": true 115 | }, 116 | "name": { 117 | "name": "name", 118 | "type": "varchar", 119 | "primaryKey": false, 120 | "notNull": false 121 | } 122 | }, 123 | "indexes": { 124 | "movies_genres_order_idx": { 125 | "name": "movies_genres_order_idx", 126 | "columns": [ 127 | "_order" 128 | ], 129 | "isUnique": false 130 | }, 131 | "movies_genres_parent_id_idx": { 132 | "name": "movies_genres_parent_id_idx", 133 | "columns": [ 134 | "_parent_id" 135 | ], 136 | "isUnique": false 137 | } 138 | }, 139 | "foreignKeys": { 140 | "movies_genres_parent_id_fk": { 141 | "name": "movies_genres_parent_id_fk", 142 | "tableFrom": "movies_genres", 143 | "tableTo": "movies", 144 | "columnsFrom": [ 145 | "_parent_id" 146 | ], 147 | "columnsTo": [ 148 | "id" 149 | ], 150 | "onDelete": "cascade", 151 | "onUpdate": "no action" 152 | } 153 | }, 154 | "compositePrimaryKeys": {}, 155 | "uniqueConstraints": {} 156 | }, 157 | "movies": { 158 | "name": "movies", 159 | "schema": "", 160 | "columns": { 161 | "id": { 162 | "name": "id", 163 | "type": "serial", 164 | "primaryKey": true, 165 | "notNull": true 166 | }, 167 | "name": { 168 | "name": "name", 169 | "type": "varchar", 170 | "primaryKey": false, 171 | "notNull": true 172 | }, 173 | "url": { 174 | "name": "url", 175 | "type": "varchar", 176 | "primaryKey": false, 177 | "notNull": true 178 | }, 179 | "votes": { 180 | "name": "votes", 181 | "type": "numeric", 182 | "primaryKey": false, 183 | "notNull": true 184 | }, 185 | "poster_id": { 186 | "name": "poster_id", 187 | "type": "integer", 188 | "primaryKey": false, 189 | "notNull": true 190 | }, 191 | "overview": { 192 | "name": "overview", 193 | "type": "varchar", 194 | "primaryKey": false, 195 | "notNull": true 196 | }, 197 | "tagline": { 198 | "name": "tagline", 199 | "type": "varchar", 200 | "primaryKey": false, 201 | "notNull": false 202 | }, 203 | "slug": { 204 | "name": "slug", 205 | "type": "varchar", 206 | "primaryKey": false, 207 | "notNull": false 208 | }, 209 | "updated_at": { 210 | "name": "updated_at", 211 | "type": "timestamp(3) with time zone", 212 | "primaryKey": false, 213 | "notNull": true, 214 | "default": "now()" 215 | }, 216 | "created_at": { 217 | "name": "created_at", 218 | "type": "timestamp(3) with time zone", 219 | "primaryKey": false, 220 | "notNull": true, 221 | "default": "now()" 222 | } 223 | }, 224 | "indexes": { 225 | "movies_created_at_idx": { 226 | "name": "movies_created_at_idx", 227 | "columns": [ 228 | "created_at" 229 | ], 230 | "isUnique": false 231 | } 232 | }, 233 | "foreignKeys": { 234 | "movies_poster_id_media_id_fk": { 235 | "name": "movies_poster_id_media_id_fk", 236 | "tableFrom": "movies", 237 | "tableTo": "media", 238 | "columnsFrom": [ 239 | "poster_id" 240 | ], 241 | "columnsTo": [ 242 | "id" 243 | ], 244 | "onDelete": "set null", 245 | "onUpdate": "no action" 246 | } 247 | }, 248 | "compositePrimaryKeys": {}, 249 | "uniqueConstraints": {} 250 | }, 251 | "media": { 252 | "name": "media", 253 | "schema": "", 254 | "columns": { 255 | "id": { 256 | "name": "id", 257 | "type": "serial", 258 | "primaryKey": true, 259 | "notNull": true 260 | }, 261 | "text": { 262 | "name": "text", 263 | "type": "varchar", 264 | "primaryKey": false, 265 | "notNull": false 266 | }, 267 | "updated_at": { 268 | "name": "updated_at", 269 | "type": "timestamp(3) with time zone", 270 | "primaryKey": false, 271 | "notNull": true, 272 | "default": "now()" 273 | }, 274 | "created_at": { 275 | "name": "created_at", 276 | "type": "timestamp(3) with time zone", 277 | "primaryKey": false, 278 | "notNull": true, 279 | "default": "now()" 280 | }, 281 | "url": { 282 | "name": "url", 283 | "type": "varchar", 284 | "primaryKey": false, 285 | "notNull": false 286 | }, 287 | "thumbnail_u_r_l": { 288 | "name": "thumbnail_u_r_l", 289 | "type": "varchar", 290 | "primaryKey": false, 291 | "notNull": false 292 | }, 293 | "filename": { 294 | "name": "filename", 295 | "type": "varchar", 296 | "primaryKey": false, 297 | "notNull": false 298 | }, 299 | "mime_type": { 300 | "name": "mime_type", 301 | "type": "varchar", 302 | "primaryKey": false, 303 | "notNull": false 304 | }, 305 | "filesize": { 306 | "name": "filesize", 307 | "type": "numeric", 308 | "primaryKey": false, 309 | "notNull": false 310 | }, 311 | "width": { 312 | "name": "width", 313 | "type": "numeric", 314 | "primaryKey": false, 315 | "notNull": false 316 | }, 317 | "height": { 318 | "name": "height", 319 | "type": "numeric", 320 | "primaryKey": false, 321 | "notNull": false 322 | }, 323 | "focal_x": { 324 | "name": "focal_x", 325 | "type": "numeric", 326 | "primaryKey": false, 327 | "notNull": false 328 | }, 329 | "focal_y": { 330 | "name": "focal_y", 331 | "type": "numeric", 332 | "primaryKey": false, 333 | "notNull": false 334 | } 335 | }, 336 | "indexes": { 337 | "media_created_at_idx": { 338 | "name": "media_created_at_idx", 339 | "columns": [ 340 | "created_at" 341 | ], 342 | "isUnique": false 343 | }, 344 | "media_filename_idx": { 345 | "name": "media_filename_idx", 346 | "columns": [ 347 | "filename" 348 | ], 349 | "isUnique": true 350 | } 351 | }, 352 | "foreignKeys": {}, 353 | "compositePrimaryKeys": {}, 354 | "uniqueConstraints": {} 355 | }, 356 | "payload_preferences": { 357 | "name": "payload_preferences", 358 | "schema": "", 359 | "columns": { 360 | "id": { 361 | "name": "id", 362 | "type": "serial", 363 | "primaryKey": true, 364 | "notNull": true 365 | }, 366 | "key": { 367 | "name": "key", 368 | "type": "varchar", 369 | "primaryKey": false, 370 | "notNull": false 371 | }, 372 | "value": { 373 | "name": "value", 374 | "type": "jsonb", 375 | "primaryKey": false, 376 | "notNull": false 377 | }, 378 | "updated_at": { 379 | "name": "updated_at", 380 | "type": "timestamp(3) with time zone", 381 | "primaryKey": false, 382 | "notNull": true, 383 | "default": "now()" 384 | }, 385 | "created_at": { 386 | "name": "created_at", 387 | "type": "timestamp(3) with time zone", 388 | "primaryKey": false, 389 | "notNull": true, 390 | "default": "now()" 391 | } 392 | }, 393 | "indexes": { 394 | "payload_preferences_key_idx": { 395 | "name": "payload_preferences_key_idx", 396 | "columns": [ 397 | "key" 398 | ], 399 | "isUnique": false 400 | }, 401 | "payload_preferences_created_at_idx": { 402 | "name": "payload_preferences_created_at_idx", 403 | "columns": [ 404 | "created_at" 405 | ], 406 | "isUnique": false 407 | } 408 | }, 409 | "foreignKeys": {}, 410 | "compositePrimaryKeys": {}, 411 | "uniqueConstraints": {} 412 | }, 413 | "payload_preferences_rels": { 414 | "name": "payload_preferences_rels", 415 | "schema": "", 416 | "columns": { 417 | "id": { 418 | "name": "id", 419 | "type": "serial", 420 | "primaryKey": true, 421 | "notNull": true 422 | }, 423 | "order": { 424 | "name": "order", 425 | "type": "integer", 426 | "primaryKey": false, 427 | "notNull": false 428 | }, 429 | "parent_id": { 430 | "name": "parent_id", 431 | "type": "integer", 432 | "primaryKey": false, 433 | "notNull": true 434 | }, 435 | "path": { 436 | "name": "path", 437 | "type": "varchar", 438 | "primaryKey": false, 439 | "notNull": true 440 | }, 441 | "users_id": { 442 | "name": "users_id", 443 | "type": "integer", 444 | "primaryKey": false, 445 | "notNull": false 446 | } 447 | }, 448 | "indexes": { 449 | "payload_preferences_rels_order_idx": { 450 | "name": "payload_preferences_rels_order_idx", 451 | "columns": [ 452 | "order" 453 | ], 454 | "isUnique": false 455 | }, 456 | "payload_preferences_rels_parent_idx": { 457 | "name": "payload_preferences_rels_parent_idx", 458 | "columns": [ 459 | "parent_id" 460 | ], 461 | "isUnique": false 462 | }, 463 | "payload_preferences_rels_path_idx": { 464 | "name": "payload_preferences_rels_path_idx", 465 | "columns": [ 466 | "path" 467 | ], 468 | "isUnique": false 469 | } 470 | }, 471 | "foreignKeys": { 472 | "payload_preferences_rels_parent_fk": { 473 | "name": "payload_preferences_rels_parent_fk", 474 | "tableFrom": "payload_preferences_rels", 475 | "tableTo": "payload_preferences", 476 | "columnsFrom": [ 477 | "parent_id" 478 | ], 479 | "columnsTo": [ 480 | "id" 481 | ], 482 | "onDelete": "cascade", 483 | "onUpdate": "no action" 484 | }, 485 | "payload_preferences_rels_users_fk": { 486 | "name": "payload_preferences_rels_users_fk", 487 | "tableFrom": "payload_preferences_rels", 488 | "tableTo": "users", 489 | "columnsFrom": [ 490 | "users_id" 491 | ], 492 | "columnsTo": [ 493 | "id" 494 | ], 495 | "onDelete": "cascade", 496 | "onUpdate": "no action" 497 | } 498 | }, 499 | "compositePrimaryKeys": {}, 500 | "uniqueConstraints": {} 501 | }, 502 | "payload_migrations": { 503 | "name": "payload_migrations", 504 | "schema": "", 505 | "columns": { 506 | "id": { 507 | "name": "id", 508 | "type": "serial", 509 | "primaryKey": true, 510 | "notNull": true 511 | }, 512 | "name": { 513 | "name": "name", 514 | "type": "varchar", 515 | "primaryKey": false, 516 | "notNull": false 517 | }, 518 | "batch": { 519 | "name": "batch", 520 | "type": "numeric", 521 | "primaryKey": false, 522 | "notNull": false 523 | }, 524 | "updated_at": { 525 | "name": "updated_at", 526 | "type": "timestamp(3) with time zone", 527 | "primaryKey": false, 528 | "notNull": true, 529 | "default": "now()" 530 | }, 531 | "created_at": { 532 | "name": "created_at", 533 | "type": "timestamp(3) with time zone", 534 | "primaryKey": false, 535 | "notNull": true, 536 | "default": "now()" 537 | } 538 | }, 539 | "indexes": { 540 | "payload_migrations_created_at_idx": { 541 | "name": "payload_migrations_created_at_idx", 542 | "columns": [ 543 | "created_at" 544 | ], 545 | "isUnique": false 546 | } 547 | }, 548 | "foreignKeys": {}, 549 | "compositePrimaryKeys": {}, 550 | "uniqueConstraints": {} 551 | } 552 | }, 553 | "enums": {}, 554 | "schemas": {}, 555 | "_meta": { 556 | "schemas": {}, 557 | "tables": {}, 558 | "columns": {} 559 | } 560 | } -------------------------------------------------------------------------------- /schema.graphql: -------------------------------------------------------------------------------- 1 | type Query { 2 | User(id: String!, draft: Boolean): User 3 | Users(draft: Boolean, where: User_where, limit: Int, page: Int, sort: String): Users 4 | countUsers(draft: Boolean, where: User_where): countUsers 5 | docAccessUser(id: String!): usersDocAccess 6 | meUser: usersMe 7 | initializedUser: Boolean 8 | Page(id: String!, draft: Boolean): Page 9 | Pages(draft: Boolean, where: Page_where, limit: Int, page: Int, sort: String): Pages 10 | countPages(draft: Boolean, where: Page_where): countPages 11 | docAccessPage(id: String!): pagesDocAccess 12 | Media(id: String!, draft: Boolean): Media 13 | allMedia(draft: Boolean, where: Media_where, limit: Int, page: Int, sort: String): allMedia 14 | countallMedia(draft: Boolean, where: Media_where): countallMedia 15 | docAccessMedia(id: String!): mediaDocAccess 16 | PayloadPreference(id: String!, draft: Boolean): PayloadPreference 17 | PayloadPreferences(draft: Boolean, where: PayloadPreference_where, limit: Int, page: Int, sort: String): PayloadPreferences 18 | countPayloadPreferences(draft: Boolean, where: PayloadPreference_where): countPayloadPreferences 19 | docAccessPayloadPreference(id: String!): payload_preferencesDocAccess 20 | Access: Access 21 | } 22 | 23 | type User { 24 | id: String 25 | updatedAt: DateTime 26 | createdAt: DateTime 27 | email: EmailAddress! 28 | resetPasswordToken: String 29 | resetPasswordExpiration: DateTime 30 | salt: String 31 | hash: String 32 | loginAttempts: Float 33 | lockUntil: DateTime 34 | password: String! 35 | } 36 | 37 | """ 38 | A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. 39 | """ 40 | scalar DateTime 41 | 42 | """ 43 | A field whose value conforms to the standard internet email address format as specified in HTML Spec: https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address. 44 | """ 45 | scalar EmailAddress @specifiedBy(url: "https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address") 46 | 47 | type Users { 48 | docs: [User] 49 | hasNextPage: Boolean 50 | hasPrevPage: Boolean 51 | limit: Int 52 | nextPage: Int 53 | offset: Int 54 | page: Int 55 | pagingCounter: Int 56 | prevPage: Int 57 | totalDocs: Int 58 | totalPages: Int 59 | } 60 | 61 | input User_where { 62 | updatedAt: User_updatedAt_operator 63 | createdAt: User_createdAt_operator 64 | email: User_email_operator 65 | id: User_id_operator 66 | AND: [User_where_and] 67 | OR: [User_where_or] 68 | } 69 | 70 | input User_updatedAt_operator { 71 | equals: DateTime 72 | not_equals: DateTime 73 | greater_than_equal: DateTime 74 | greater_than: DateTime 75 | less_than_equal: DateTime 76 | less_than: DateTime 77 | like: DateTime 78 | exists: Boolean 79 | } 80 | 81 | input User_createdAt_operator { 82 | equals: DateTime 83 | not_equals: DateTime 84 | greater_than_equal: DateTime 85 | greater_than: DateTime 86 | less_than_equal: DateTime 87 | less_than: DateTime 88 | like: DateTime 89 | exists: Boolean 90 | } 91 | 92 | input User_email_operator { 93 | equals: EmailAddress 94 | not_equals: EmailAddress 95 | like: EmailAddress 96 | contains: EmailAddress 97 | in: [EmailAddress] 98 | not_in: [EmailAddress] 99 | all: [EmailAddress] 100 | } 101 | 102 | input User_id_operator { 103 | equals: String 104 | not_equals: String 105 | like: String 106 | contains: String 107 | in: [String] 108 | not_in: [String] 109 | all: [String] 110 | exists: Boolean 111 | } 112 | 113 | input User_where_and { 114 | updatedAt: User_updatedAt_operator 115 | createdAt: User_createdAt_operator 116 | email: User_email_operator 117 | id: User_id_operator 118 | AND: [User_where_and] 119 | OR: [User_where_or] 120 | } 121 | 122 | input User_where_or { 123 | updatedAt: User_updatedAt_operator 124 | createdAt: User_createdAt_operator 125 | email: User_email_operator 126 | id: User_id_operator 127 | AND: [User_where_and] 128 | OR: [User_where_or] 129 | } 130 | 131 | type countUsers { 132 | totalDocs: Int 133 | } 134 | 135 | type usersDocAccess { 136 | fields: UsersDocAccessFields 137 | create: UsersCreateDocAccess 138 | read: UsersReadDocAccess 139 | update: UsersUpdateDocAccess 140 | delete: UsersDeleteDocAccess 141 | unlock: UsersUnlockDocAccess 142 | } 143 | 144 | type UsersDocAccessFields { 145 | updatedAt: UsersDocAccessFields_updatedAt 146 | createdAt: UsersDocAccessFields_createdAt 147 | email: UsersDocAccessFields_email 148 | password: UsersDocAccessFields_password 149 | } 150 | 151 | type UsersDocAccessFields_updatedAt { 152 | create: UsersDocAccessFields_updatedAt_Create 153 | read: UsersDocAccessFields_updatedAt_Read 154 | update: UsersDocAccessFields_updatedAt_Update 155 | delete: UsersDocAccessFields_updatedAt_Delete 156 | } 157 | 158 | type UsersDocAccessFields_updatedAt_Create { 159 | permission: Boolean! 160 | } 161 | 162 | type UsersDocAccessFields_updatedAt_Read { 163 | permission: Boolean! 164 | } 165 | 166 | type UsersDocAccessFields_updatedAt_Update { 167 | permission: Boolean! 168 | } 169 | 170 | type UsersDocAccessFields_updatedAt_Delete { 171 | permission: Boolean! 172 | } 173 | 174 | type UsersDocAccessFields_createdAt { 175 | create: UsersDocAccessFields_createdAt_Create 176 | read: UsersDocAccessFields_createdAt_Read 177 | update: UsersDocAccessFields_createdAt_Update 178 | delete: UsersDocAccessFields_createdAt_Delete 179 | } 180 | 181 | type UsersDocAccessFields_createdAt_Create { 182 | permission: Boolean! 183 | } 184 | 185 | type UsersDocAccessFields_createdAt_Read { 186 | permission: Boolean! 187 | } 188 | 189 | type UsersDocAccessFields_createdAt_Update { 190 | permission: Boolean! 191 | } 192 | 193 | type UsersDocAccessFields_createdAt_Delete { 194 | permission: Boolean! 195 | } 196 | 197 | type UsersDocAccessFields_email { 198 | create: UsersDocAccessFields_email_Create 199 | read: UsersDocAccessFields_email_Read 200 | update: UsersDocAccessFields_email_Update 201 | delete: UsersDocAccessFields_email_Delete 202 | } 203 | 204 | type UsersDocAccessFields_email_Create { 205 | permission: Boolean! 206 | } 207 | 208 | type UsersDocAccessFields_email_Read { 209 | permission: Boolean! 210 | } 211 | 212 | type UsersDocAccessFields_email_Update { 213 | permission: Boolean! 214 | } 215 | 216 | type UsersDocAccessFields_email_Delete { 217 | permission: Boolean! 218 | } 219 | 220 | type UsersDocAccessFields_password { 221 | create: UsersDocAccessFields_password_Create 222 | read: UsersDocAccessFields_password_Read 223 | update: UsersDocAccessFields_password_Update 224 | delete: UsersDocAccessFields_password_Delete 225 | } 226 | 227 | type UsersDocAccessFields_password_Create { 228 | permission: Boolean! 229 | } 230 | 231 | type UsersDocAccessFields_password_Read { 232 | permission: Boolean! 233 | } 234 | 235 | type UsersDocAccessFields_password_Update { 236 | permission: Boolean! 237 | } 238 | 239 | type UsersDocAccessFields_password_Delete { 240 | permission: Boolean! 241 | } 242 | 243 | type UsersCreateDocAccess { 244 | permission: Boolean! 245 | where: JSONObject 246 | } 247 | 248 | """ 249 | The `JSONObject` scalar type represents JSON objects as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). 250 | """ 251 | scalar JSONObject @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf") 252 | 253 | type UsersReadDocAccess { 254 | permission: Boolean! 255 | where: JSONObject 256 | } 257 | 258 | type UsersUpdateDocAccess { 259 | permission: Boolean! 260 | where: JSONObject 261 | } 262 | 263 | type UsersDeleteDocAccess { 264 | permission: Boolean! 265 | where: JSONObject 266 | } 267 | 268 | type UsersUnlockDocAccess { 269 | permission: Boolean! 270 | where: JSONObject 271 | } 272 | 273 | type usersMe { 274 | collection: String 275 | exp: Int 276 | token: String 277 | user: User 278 | } 279 | 280 | type Page { 281 | id: String 282 | title: String 283 | content(depth: Int): JSON 284 | updatedAt: DateTime 285 | createdAt: DateTime 286 | } 287 | 288 | """ 289 | The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). 290 | """ 291 | scalar JSON @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf") 292 | 293 | type Pages { 294 | docs: [Page] 295 | hasNextPage: Boolean 296 | hasPrevPage: Boolean 297 | limit: Int 298 | nextPage: Int 299 | offset: Int 300 | page: Int 301 | pagingCounter: Int 302 | prevPage: Int 303 | totalDocs: Int 304 | totalPages: Int 305 | } 306 | 307 | input Page_where { 308 | title: Page_title_operator 309 | content: Page_content_operator 310 | updatedAt: Page_updatedAt_operator 311 | createdAt: Page_createdAt_operator 312 | id: Page_id_operator 313 | AND: [Page_where_and] 314 | OR: [Page_where_or] 315 | } 316 | 317 | input Page_title_operator { 318 | equals: String 319 | not_equals: String 320 | like: String 321 | contains: String 322 | in: [String] 323 | not_in: [String] 324 | all: [String] 325 | exists: Boolean 326 | } 327 | 328 | input Page_content_operator { 329 | equals: JSON 330 | not_equals: JSON 331 | like: JSON 332 | contains: JSON 333 | exists: Boolean 334 | } 335 | 336 | input Page_updatedAt_operator { 337 | equals: DateTime 338 | not_equals: DateTime 339 | greater_than_equal: DateTime 340 | greater_than: DateTime 341 | less_than_equal: DateTime 342 | less_than: DateTime 343 | like: DateTime 344 | exists: Boolean 345 | } 346 | 347 | input Page_createdAt_operator { 348 | equals: DateTime 349 | not_equals: DateTime 350 | greater_than_equal: DateTime 351 | greater_than: DateTime 352 | less_than_equal: DateTime 353 | less_than: DateTime 354 | like: DateTime 355 | exists: Boolean 356 | } 357 | 358 | input Page_id_operator { 359 | equals: String 360 | not_equals: String 361 | like: String 362 | contains: String 363 | in: [String] 364 | not_in: [String] 365 | all: [String] 366 | exists: Boolean 367 | } 368 | 369 | input Page_where_and { 370 | title: Page_title_operator 371 | content: Page_content_operator 372 | updatedAt: Page_updatedAt_operator 373 | createdAt: Page_createdAt_operator 374 | id: Page_id_operator 375 | AND: [Page_where_and] 376 | OR: [Page_where_or] 377 | } 378 | 379 | input Page_where_or { 380 | title: Page_title_operator 381 | content: Page_content_operator 382 | updatedAt: Page_updatedAt_operator 383 | createdAt: Page_createdAt_operator 384 | id: Page_id_operator 385 | AND: [Page_where_and] 386 | OR: [Page_where_or] 387 | } 388 | 389 | type countPages { 390 | totalDocs: Int 391 | } 392 | 393 | type pagesDocAccess { 394 | fields: PagesDocAccessFields 395 | create: PagesCreateDocAccess 396 | read: PagesReadDocAccess 397 | update: PagesUpdateDocAccess 398 | delete: PagesDeleteDocAccess 399 | } 400 | 401 | type PagesDocAccessFields { 402 | title: PagesDocAccessFields_title 403 | content: PagesDocAccessFields_content 404 | updatedAt: PagesDocAccessFields_updatedAt 405 | createdAt: PagesDocAccessFields_createdAt 406 | } 407 | 408 | type PagesDocAccessFields_title { 409 | create: PagesDocAccessFields_title_Create 410 | read: PagesDocAccessFields_title_Read 411 | update: PagesDocAccessFields_title_Update 412 | delete: PagesDocAccessFields_title_Delete 413 | } 414 | 415 | type PagesDocAccessFields_title_Create { 416 | permission: Boolean! 417 | } 418 | 419 | type PagesDocAccessFields_title_Read { 420 | permission: Boolean! 421 | } 422 | 423 | type PagesDocAccessFields_title_Update { 424 | permission: Boolean! 425 | } 426 | 427 | type PagesDocAccessFields_title_Delete { 428 | permission: Boolean! 429 | } 430 | 431 | type PagesDocAccessFields_content { 432 | create: PagesDocAccessFields_content_Create 433 | read: PagesDocAccessFields_content_Read 434 | update: PagesDocAccessFields_content_Update 435 | delete: PagesDocAccessFields_content_Delete 436 | } 437 | 438 | type PagesDocAccessFields_content_Create { 439 | permission: Boolean! 440 | } 441 | 442 | type PagesDocAccessFields_content_Read { 443 | permission: Boolean! 444 | } 445 | 446 | type PagesDocAccessFields_content_Update { 447 | permission: Boolean! 448 | } 449 | 450 | type PagesDocAccessFields_content_Delete { 451 | permission: Boolean! 452 | } 453 | 454 | type PagesDocAccessFields_updatedAt { 455 | create: PagesDocAccessFields_updatedAt_Create 456 | read: PagesDocAccessFields_updatedAt_Read 457 | update: PagesDocAccessFields_updatedAt_Update 458 | delete: PagesDocAccessFields_updatedAt_Delete 459 | } 460 | 461 | type PagesDocAccessFields_updatedAt_Create { 462 | permission: Boolean! 463 | } 464 | 465 | type PagesDocAccessFields_updatedAt_Read { 466 | permission: Boolean! 467 | } 468 | 469 | type PagesDocAccessFields_updatedAt_Update { 470 | permission: Boolean! 471 | } 472 | 473 | type PagesDocAccessFields_updatedAt_Delete { 474 | permission: Boolean! 475 | } 476 | 477 | type PagesDocAccessFields_createdAt { 478 | create: PagesDocAccessFields_createdAt_Create 479 | read: PagesDocAccessFields_createdAt_Read 480 | update: PagesDocAccessFields_createdAt_Update 481 | delete: PagesDocAccessFields_createdAt_Delete 482 | } 483 | 484 | type PagesDocAccessFields_createdAt_Create { 485 | permission: Boolean! 486 | } 487 | 488 | type PagesDocAccessFields_createdAt_Read { 489 | permission: Boolean! 490 | } 491 | 492 | type PagesDocAccessFields_createdAt_Update { 493 | permission: Boolean! 494 | } 495 | 496 | type PagesDocAccessFields_createdAt_Delete { 497 | permission: Boolean! 498 | } 499 | 500 | type PagesCreateDocAccess { 501 | permission: Boolean! 502 | where: JSONObject 503 | } 504 | 505 | type PagesReadDocAccess { 506 | permission: Boolean! 507 | where: JSONObject 508 | } 509 | 510 | type PagesUpdateDocAccess { 511 | permission: Boolean! 512 | where: JSONObject 513 | } 514 | 515 | type PagesDeleteDocAccess { 516 | permission: Boolean! 517 | where: JSONObject 518 | } 519 | 520 | type Media { 521 | id: String 522 | text: String 523 | updatedAt: DateTime 524 | createdAt: DateTime 525 | url: String 526 | thumbnailURL: String 527 | filename: String 528 | mimeType: String 529 | filesize: Float 530 | width: Float 531 | height: Float 532 | focalX: Float 533 | focalY: Float 534 | } 535 | 536 | type allMedia { 537 | docs: [Media] 538 | hasNextPage: Boolean 539 | hasPrevPage: Boolean 540 | limit: Int 541 | nextPage: Int 542 | offset: Int 543 | page: Int 544 | pagingCounter: Int 545 | prevPage: Int 546 | totalDocs: Int 547 | totalPages: Int 548 | } 549 | 550 | input Media_where { 551 | text: Media_text_operator 552 | updatedAt: Media_updatedAt_operator 553 | createdAt: Media_createdAt_operator 554 | url: Media_url_operator 555 | thumbnailURL: Media_thumbnailURL_operator 556 | filename: Media_filename_operator 557 | mimeType: Media_mimeType_operator 558 | filesize: Media_filesize_operator 559 | width: Media_width_operator 560 | height: Media_height_operator 561 | focalX: Media_focalX_operator 562 | focalY: Media_focalY_operator 563 | id: Media_id_operator 564 | AND: [Media_where_and] 565 | OR: [Media_where_or] 566 | } 567 | 568 | input Media_text_operator { 569 | equals: String 570 | not_equals: String 571 | like: String 572 | contains: String 573 | in: [String] 574 | not_in: [String] 575 | all: [String] 576 | exists: Boolean 577 | } 578 | 579 | input Media_updatedAt_operator { 580 | equals: DateTime 581 | not_equals: DateTime 582 | greater_than_equal: DateTime 583 | greater_than: DateTime 584 | less_than_equal: DateTime 585 | less_than: DateTime 586 | like: DateTime 587 | exists: Boolean 588 | } 589 | 590 | input Media_createdAt_operator { 591 | equals: DateTime 592 | not_equals: DateTime 593 | greater_than_equal: DateTime 594 | greater_than: DateTime 595 | less_than_equal: DateTime 596 | less_than: DateTime 597 | like: DateTime 598 | exists: Boolean 599 | } 600 | 601 | input Media_url_operator { 602 | equals: String 603 | not_equals: String 604 | like: String 605 | contains: String 606 | in: [String] 607 | not_in: [String] 608 | all: [String] 609 | exists: Boolean 610 | } 611 | 612 | input Media_thumbnailURL_operator { 613 | equals: String 614 | not_equals: String 615 | like: String 616 | contains: String 617 | in: [String] 618 | not_in: [String] 619 | all: [String] 620 | exists: Boolean 621 | } 622 | 623 | input Media_filename_operator { 624 | equals: String 625 | not_equals: String 626 | like: String 627 | contains: String 628 | in: [String] 629 | not_in: [String] 630 | all: [String] 631 | exists: Boolean 632 | } 633 | 634 | input Media_mimeType_operator { 635 | equals: String 636 | not_equals: String 637 | like: String 638 | contains: String 639 | in: [String] 640 | not_in: [String] 641 | all: [String] 642 | exists: Boolean 643 | } 644 | 645 | input Media_filesize_operator { 646 | equals: Float 647 | not_equals: Float 648 | greater_than_equal: Float 649 | greater_than: Float 650 | less_than_equal: Float 651 | less_than: Float 652 | exists: Boolean 653 | } 654 | 655 | input Media_width_operator { 656 | equals: Float 657 | not_equals: Float 658 | greater_than_equal: Float 659 | greater_than: Float 660 | less_than_equal: Float 661 | less_than: Float 662 | exists: Boolean 663 | } 664 | 665 | input Media_height_operator { 666 | equals: Float 667 | not_equals: Float 668 | greater_than_equal: Float 669 | greater_than: Float 670 | less_than_equal: Float 671 | less_than: Float 672 | exists: Boolean 673 | } 674 | 675 | input Media_focalX_operator { 676 | equals: Float 677 | not_equals: Float 678 | greater_than_equal: Float 679 | greater_than: Float 680 | less_than_equal: Float 681 | less_than: Float 682 | exists: Boolean 683 | } 684 | 685 | input Media_focalY_operator { 686 | equals: Float 687 | not_equals: Float 688 | greater_than_equal: Float 689 | greater_than: Float 690 | less_than_equal: Float 691 | less_than: Float 692 | exists: Boolean 693 | } 694 | 695 | input Media_id_operator { 696 | equals: String 697 | not_equals: String 698 | like: String 699 | contains: String 700 | in: [String] 701 | not_in: [String] 702 | all: [String] 703 | exists: Boolean 704 | } 705 | 706 | input Media_where_and { 707 | text: Media_text_operator 708 | updatedAt: Media_updatedAt_operator 709 | createdAt: Media_createdAt_operator 710 | url: Media_url_operator 711 | thumbnailURL: Media_thumbnailURL_operator 712 | filename: Media_filename_operator 713 | mimeType: Media_mimeType_operator 714 | filesize: Media_filesize_operator 715 | width: Media_width_operator 716 | height: Media_height_operator 717 | focalX: Media_focalX_operator 718 | focalY: Media_focalY_operator 719 | id: Media_id_operator 720 | AND: [Media_where_and] 721 | OR: [Media_where_or] 722 | } 723 | 724 | input Media_where_or { 725 | text: Media_text_operator 726 | updatedAt: Media_updatedAt_operator 727 | createdAt: Media_createdAt_operator 728 | url: Media_url_operator 729 | thumbnailURL: Media_thumbnailURL_operator 730 | filename: Media_filename_operator 731 | mimeType: Media_mimeType_operator 732 | filesize: Media_filesize_operator 733 | width: Media_width_operator 734 | height: Media_height_operator 735 | focalX: Media_focalX_operator 736 | focalY: Media_focalY_operator 737 | id: Media_id_operator 738 | AND: [Media_where_and] 739 | OR: [Media_where_or] 740 | } 741 | 742 | type countallMedia { 743 | totalDocs: Int 744 | } 745 | 746 | type mediaDocAccess { 747 | fields: MediaDocAccessFields 748 | create: MediaCreateDocAccess 749 | read: MediaReadDocAccess 750 | update: MediaUpdateDocAccess 751 | delete: MediaDeleteDocAccess 752 | } 753 | 754 | type MediaDocAccessFields { 755 | text: MediaDocAccessFields_text 756 | updatedAt: MediaDocAccessFields_updatedAt 757 | createdAt: MediaDocAccessFields_createdAt 758 | url: MediaDocAccessFields_url 759 | thumbnailURL: MediaDocAccessFields_thumbnailURL 760 | filename: MediaDocAccessFields_filename 761 | mimeType: MediaDocAccessFields_mimeType 762 | filesize: MediaDocAccessFields_filesize 763 | width: MediaDocAccessFields_width 764 | height: MediaDocAccessFields_height 765 | focalX: MediaDocAccessFields_focalX 766 | focalY: MediaDocAccessFields_focalY 767 | } 768 | 769 | type MediaDocAccessFields_text { 770 | create: MediaDocAccessFields_text_Create 771 | read: MediaDocAccessFields_text_Read 772 | update: MediaDocAccessFields_text_Update 773 | delete: MediaDocAccessFields_text_Delete 774 | } 775 | 776 | type MediaDocAccessFields_text_Create { 777 | permission: Boolean! 778 | } 779 | 780 | type MediaDocAccessFields_text_Read { 781 | permission: Boolean! 782 | } 783 | 784 | type MediaDocAccessFields_text_Update { 785 | permission: Boolean! 786 | } 787 | 788 | type MediaDocAccessFields_text_Delete { 789 | permission: Boolean! 790 | } 791 | 792 | type MediaDocAccessFields_updatedAt { 793 | create: MediaDocAccessFields_updatedAt_Create 794 | read: MediaDocAccessFields_updatedAt_Read 795 | update: MediaDocAccessFields_updatedAt_Update 796 | delete: MediaDocAccessFields_updatedAt_Delete 797 | } 798 | 799 | type MediaDocAccessFields_updatedAt_Create { 800 | permission: Boolean! 801 | } 802 | 803 | type MediaDocAccessFields_updatedAt_Read { 804 | permission: Boolean! 805 | } 806 | 807 | type MediaDocAccessFields_updatedAt_Update { 808 | permission: Boolean! 809 | } 810 | 811 | type MediaDocAccessFields_updatedAt_Delete { 812 | permission: Boolean! 813 | } 814 | 815 | type MediaDocAccessFields_createdAt { 816 | create: MediaDocAccessFields_createdAt_Create 817 | read: MediaDocAccessFields_createdAt_Read 818 | update: MediaDocAccessFields_createdAt_Update 819 | delete: MediaDocAccessFields_createdAt_Delete 820 | } 821 | 822 | type MediaDocAccessFields_createdAt_Create { 823 | permission: Boolean! 824 | } 825 | 826 | type MediaDocAccessFields_createdAt_Read { 827 | permission: Boolean! 828 | } 829 | 830 | type MediaDocAccessFields_createdAt_Update { 831 | permission: Boolean! 832 | } 833 | 834 | type MediaDocAccessFields_createdAt_Delete { 835 | permission: Boolean! 836 | } 837 | 838 | type MediaDocAccessFields_url { 839 | create: MediaDocAccessFields_url_Create 840 | read: MediaDocAccessFields_url_Read 841 | update: MediaDocAccessFields_url_Update 842 | delete: MediaDocAccessFields_url_Delete 843 | } 844 | 845 | type MediaDocAccessFields_url_Create { 846 | permission: Boolean! 847 | } 848 | 849 | type MediaDocAccessFields_url_Read { 850 | permission: Boolean! 851 | } 852 | 853 | type MediaDocAccessFields_url_Update { 854 | permission: Boolean! 855 | } 856 | 857 | type MediaDocAccessFields_url_Delete { 858 | permission: Boolean! 859 | } 860 | 861 | type MediaDocAccessFields_thumbnailURL { 862 | create: MediaDocAccessFields_thumbnailURL_Create 863 | read: MediaDocAccessFields_thumbnailURL_Read 864 | update: MediaDocAccessFields_thumbnailURL_Update 865 | delete: MediaDocAccessFields_thumbnailURL_Delete 866 | } 867 | 868 | type MediaDocAccessFields_thumbnailURL_Create { 869 | permission: Boolean! 870 | } 871 | 872 | type MediaDocAccessFields_thumbnailURL_Read { 873 | permission: Boolean! 874 | } 875 | 876 | type MediaDocAccessFields_thumbnailURL_Update { 877 | permission: Boolean! 878 | } 879 | 880 | type MediaDocAccessFields_thumbnailURL_Delete { 881 | permission: Boolean! 882 | } 883 | 884 | type MediaDocAccessFields_filename { 885 | create: MediaDocAccessFields_filename_Create 886 | read: MediaDocAccessFields_filename_Read 887 | update: MediaDocAccessFields_filename_Update 888 | delete: MediaDocAccessFields_filename_Delete 889 | } 890 | 891 | type MediaDocAccessFields_filename_Create { 892 | permission: Boolean! 893 | } 894 | 895 | type MediaDocAccessFields_filename_Read { 896 | permission: Boolean! 897 | } 898 | 899 | type MediaDocAccessFields_filename_Update { 900 | permission: Boolean! 901 | } 902 | 903 | type MediaDocAccessFields_filename_Delete { 904 | permission: Boolean! 905 | } 906 | 907 | type MediaDocAccessFields_mimeType { 908 | create: MediaDocAccessFields_mimeType_Create 909 | read: MediaDocAccessFields_mimeType_Read 910 | update: MediaDocAccessFields_mimeType_Update 911 | delete: MediaDocAccessFields_mimeType_Delete 912 | } 913 | 914 | type MediaDocAccessFields_mimeType_Create { 915 | permission: Boolean! 916 | } 917 | 918 | type MediaDocAccessFields_mimeType_Read { 919 | permission: Boolean! 920 | } 921 | 922 | type MediaDocAccessFields_mimeType_Update { 923 | permission: Boolean! 924 | } 925 | 926 | type MediaDocAccessFields_mimeType_Delete { 927 | permission: Boolean! 928 | } 929 | 930 | type MediaDocAccessFields_filesize { 931 | create: MediaDocAccessFields_filesize_Create 932 | read: MediaDocAccessFields_filesize_Read 933 | update: MediaDocAccessFields_filesize_Update 934 | delete: MediaDocAccessFields_filesize_Delete 935 | } 936 | 937 | type MediaDocAccessFields_filesize_Create { 938 | permission: Boolean! 939 | } 940 | 941 | type MediaDocAccessFields_filesize_Read { 942 | permission: Boolean! 943 | } 944 | 945 | type MediaDocAccessFields_filesize_Update { 946 | permission: Boolean! 947 | } 948 | 949 | type MediaDocAccessFields_filesize_Delete { 950 | permission: Boolean! 951 | } 952 | 953 | type MediaDocAccessFields_width { 954 | create: MediaDocAccessFields_width_Create 955 | read: MediaDocAccessFields_width_Read 956 | update: MediaDocAccessFields_width_Update 957 | delete: MediaDocAccessFields_width_Delete 958 | } 959 | 960 | type MediaDocAccessFields_width_Create { 961 | permission: Boolean! 962 | } 963 | 964 | type MediaDocAccessFields_width_Read { 965 | permission: Boolean! 966 | } 967 | 968 | type MediaDocAccessFields_width_Update { 969 | permission: Boolean! 970 | } 971 | 972 | type MediaDocAccessFields_width_Delete { 973 | permission: Boolean! 974 | } 975 | 976 | type MediaDocAccessFields_height { 977 | create: MediaDocAccessFields_height_Create 978 | read: MediaDocAccessFields_height_Read 979 | update: MediaDocAccessFields_height_Update 980 | delete: MediaDocAccessFields_height_Delete 981 | } 982 | 983 | type MediaDocAccessFields_height_Create { 984 | permission: Boolean! 985 | } 986 | 987 | type MediaDocAccessFields_height_Read { 988 | permission: Boolean! 989 | } 990 | 991 | type MediaDocAccessFields_height_Update { 992 | permission: Boolean! 993 | } 994 | 995 | type MediaDocAccessFields_height_Delete { 996 | permission: Boolean! 997 | } 998 | 999 | type MediaDocAccessFields_focalX { 1000 | create: MediaDocAccessFields_focalX_Create 1001 | read: MediaDocAccessFields_focalX_Read 1002 | update: MediaDocAccessFields_focalX_Update 1003 | delete: MediaDocAccessFields_focalX_Delete 1004 | } 1005 | 1006 | type MediaDocAccessFields_focalX_Create { 1007 | permission: Boolean! 1008 | } 1009 | 1010 | type MediaDocAccessFields_focalX_Read { 1011 | permission: Boolean! 1012 | } 1013 | 1014 | type MediaDocAccessFields_focalX_Update { 1015 | permission: Boolean! 1016 | } 1017 | 1018 | type MediaDocAccessFields_focalX_Delete { 1019 | permission: Boolean! 1020 | } 1021 | 1022 | type MediaDocAccessFields_focalY { 1023 | create: MediaDocAccessFields_focalY_Create 1024 | read: MediaDocAccessFields_focalY_Read 1025 | update: MediaDocAccessFields_focalY_Update 1026 | delete: MediaDocAccessFields_focalY_Delete 1027 | } 1028 | 1029 | type MediaDocAccessFields_focalY_Create { 1030 | permission: Boolean! 1031 | } 1032 | 1033 | type MediaDocAccessFields_focalY_Read { 1034 | permission: Boolean! 1035 | } 1036 | 1037 | type MediaDocAccessFields_focalY_Update { 1038 | permission: Boolean! 1039 | } 1040 | 1041 | type MediaDocAccessFields_focalY_Delete { 1042 | permission: Boolean! 1043 | } 1044 | 1045 | type MediaCreateDocAccess { 1046 | permission: Boolean! 1047 | where: JSONObject 1048 | } 1049 | 1050 | type MediaReadDocAccess { 1051 | permission: Boolean! 1052 | where: JSONObject 1053 | } 1054 | 1055 | type MediaUpdateDocAccess { 1056 | permission: Boolean! 1057 | where: JSONObject 1058 | } 1059 | 1060 | type MediaDeleteDocAccess { 1061 | permission: Boolean! 1062 | where: JSONObject 1063 | } 1064 | 1065 | type PayloadPreference { 1066 | id: String 1067 | user: PayloadPreference_User_Relationship! 1068 | key: String 1069 | value: JSON 1070 | updatedAt: DateTime 1071 | createdAt: DateTime 1072 | } 1073 | 1074 | type PayloadPreference_User_Relationship { 1075 | relationTo: PayloadPreference_User_RelationTo 1076 | value: PayloadPreference_User 1077 | } 1078 | 1079 | enum PayloadPreference_User_RelationTo { 1080 | users 1081 | } 1082 | 1083 | union PayloadPreference_User = User 1084 | 1085 | type PayloadPreferences { 1086 | docs: [PayloadPreference] 1087 | hasNextPage: Boolean 1088 | hasPrevPage: Boolean 1089 | limit: Int 1090 | nextPage: Int 1091 | offset: Int 1092 | page: Int 1093 | pagingCounter: Int 1094 | prevPage: Int 1095 | totalDocs: Int 1096 | totalPages: Int 1097 | } 1098 | 1099 | input PayloadPreference_where { 1100 | user: PayloadPreference_user_Relation 1101 | key: PayloadPreference_key_operator 1102 | value: PayloadPreference_value_operator 1103 | updatedAt: PayloadPreference_updatedAt_operator 1104 | createdAt: PayloadPreference_createdAt_operator 1105 | id: PayloadPreference_id_operator 1106 | AND: [PayloadPreference_where_and] 1107 | OR: [PayloadPreference_where_or] 1108 | } 1109 | 1110 | input PayloadPreference_user_Relation { 1111 | relationTo: PayloadPreference_user_Relation_RelationTo 1112 | value: JSON 1113 | } 1114 | 1115 | enum PayloadPreference_user_Relation_RelationTo { 1116 | users 1117 | } 1118 | 1119 | input PayloadPreference_key_operator { 1120 | equals: String 1121 | not_equals: String 1122 | like: String 1123 | contains: String 1124 | in: [String] 1125 | not_in: [String] 1126 | all: [String] 1127 | exists: Boolean 1128 | } 1129 | 1130 | input PayloadPreference_value_operator { 1131 | equals: JSON 1132 | not_equals: JSON 1133 | like: JSON 1134 | contains: JSON 1135 | within: JSON 1136 | intersects: JSON 1137 | exists: Boolean 1138 | } 1139 | 1140 | input PayloadPreference_updatedAt_operator { 1141 | equals: DateTime 1142 | not_equals: DateTime 1143 | greater_than_equal: DateTime 1144 | greater_than: DateTime 1145 | less_than_equal: DateTime 1146 | less_than: DateTime 1147 | like: DateTime 1148 | exists: Boolean 1149 | } 1150 | 1151 | input PayloadPreference_createdAt_operator { 1152 | equals: DateTime 1153 | not_equals: DateTime 1154 | greater_than_equal: DateTime 1155 | greater_than: DateTime 1156 | less_than_equal: DateTime 1157 | less_than: DateTime 1158 | like: DateTime 1159 | exists: Boolean 1160 | } 1161 | 1162 | input PayloadPreference_id_operator { 1163 | equals: String 1164 | not_equals: String 1165 | like: String 1166 | contains: String 1167 | in: [String] 1168 | not_in: [String] 1169 | all: [String] 1170 | exists: Boolean 1171 | } 1172 | 1173 | input PayloadPreference_where_and { 1174 | user: PayloadPreference_user_Relation 1175 | key: PayloadPreference_key_operator 1176 | value: PayloadPreference_value_operator 1177 | updatedAt: PayloadPreference_updatedAt_operator 1178 | createdAt: PayloadPreference_createdAt_operator 1179 | id: PayloadPreference_id_operator 1180 | AND: [PayloadPreference_where_and] 1181 | OR: [PayloadPreference_where_or] 1182 | } 1183 | 1184 | input PayloadPreference_where_or { 1185 | user: PayloadPreference_user_Relation 1186 | key: PayloadPreference_key_operator 1187 | value: PayloadPreference_value_operator 1188 | updatedAt: PayloadPreference_updatedAt_operator 1189 | createdAt: PayloadPreference_createdAt_operator 1190 | id: PayloadPreference_id_operator 1191 | AND: [PayloadPreference_where_and] 1192 | OR: [PayloadPreference_where_or] 1193 | } 1194 | 1195 | type countPayloadPreferences { 1196 | totalDocs: Int 1197 | } 1198 | 1199 | type payload_preferencesDocAccess { 1200 | fields: PayloadPreferencesDocAccessFields 1201 | create: PayloadPreferencesCreateDocAccess 1202 | read: PayloadPreferencesReadDocAccess 1203 | update: PayloadPreferencesUpdateDocAccess 1204 | delete: PayloadPreferencesDeleteDocAccess 1205 | } 1206 | 1207 | type PayloadPreferencesDocAccessFields { 1208 | user: PayloadPreferencesDocAccessFields_user 1209 | key: PayloadPreferencesDocAccessFields_key 1210 | value: PayloadPreferencesDocAccessFields_value 1211 | updatedAt: PayloadPreferencesDocAccessFields_updatedAt 1212 | createdAt: PayloadPreferencesDocAccessFields_createdAt 1213 | } 1214 | 1215 | type PayloadPreferencesDocAccessFields_user { 1216 | create: PayloadPreferencesDocAccessFields_user_Create 1217 | read: PayloadPreferencesDocAccessFields_user_Read 1218 | update: PayloadPreferencesDocAccessFields_user_Update 1219 | delete: PayloadPreferencesDocAccessFields_user_Delete 1220 | } 1221 | 1222 | type PayloadPreferencesDocAccessFields_user_Create { 1223 | permission: Boolean! 1224 | } 1225 | 1226 | type PayloadPreferencesDocAccessFields_user_Read { 1227 | permission: Boolean! 1228 | } 1229 | 1230 | type PayloadPreferencesDocAccessFields_user_Update { 1231 | permission: Boolean! 1232 | } 1233 | 1234 | type PayloadPreferencesDocAccessFields_user_Delete { 1235 | permission: Boolean! 1236 | } 1237 | 1238 | type PayloadPreferencesDocAccessFields_key { 1239 | create: PayloadPreferencesDocAccessFields_key_Create 1240 | read: PayloadPreferencesDocAccessFields_key_Read 1241 | update: PayloadPreferencesDocAccessFields_key_Update 1242 | delete: PayloadPreferencesDocAccessFields_key_Delete 1243 | } 1244 | 1245 | type PayloadPreferencesDocAccessFields_key_Create { 1246 | permission: Boolean! 1247 | } 1248 | 1249 | type PayloadPreferencesDocAccessFields_key_Read { 1250 | permission: Boolean! 1251 | } 1252 | 1253 | type PayloadPreferencesDocAccessFields_key_Update { 1254 | permission: Boolean! 1255 | } 1256 | 1257 | type PayloadPreferencesDocAccessFields_key_Delete { 1258 | permission: Boolean! 1259 | } 1260 | 1261 | type PayloadPreferencesDocAccessFields_value { 1262 | create: PayloadPreferencesDocAccessFields_value_Create 1263 | read: PayloadPreferencesDocAccessFields_value_Read 1264 | update: PayloadPreferencesDocAccessFields_value_Update 1265 | delete: PayloadPreferencesDocAccessFields_value_Delete 1266 | } 1267 | 1268 | type PayloadPreferencesDocAccessFields_value_Create { 1269 | permission: Boolean! 1270 | } 1271 | 1272 | type PayloadPreferencesDocAccessFields_value_Read { 1273 | permission: Boolean! 1274 | } 1275 | 1276 | type PayloadPreferencesDocAccessFields_value_Update { 1277 | permission: Boolean! 1278 | } 1279 | 1280 | type PayloadPreferencesDocAccessFields_value_Delete { 1281 | permission: Boolean! 1282 | } 1283 | 1284 | type PayloadPreferencesDocAccessFields_updatedAt { 1285 | create: PayloadPreferencesDocAccessFields_updatedAt_Create 1286 | read: PayloadPreferencesDocAccessFields_updatedAt_Read 1287 | update: PayloadPreferencesDocAccessFields_updatedAt_Update 1288 | delete: PayloadPreferencesDocAccessFields_updatedAt_Delete 1289 | } 1290 | 1291 | type PayloadPreferencesDocAccessFields_updatedAt_Create { 1292 | permission: Boolean! 1293 | } 1294 | 1295 | type PayloadPreferencesDocAccessFields_updatedAt_Read { 1296 | permission: Boolean! 1297 | } 1298 | 1299 | type PayloadPreferencesDocAccessFields_updatedAt_Update { 1300 | permission: Boolean! 1301 | } 1302 | 1303 | type PayloadPreferencesDocAccessFields_updatedAt_Delete { 1304 | permission: Boolean! 1305 | } 1306 | 1307 | type PayloadPreferencesDocAccessFields_createdAt { 1308 | create: PayloadPreferencesDocAccessFields_createdAt_Create 1309 | read: PayloadPreferencesDocAccessFields_createdAt_Read 1310 | update: PayloadPreferencesDocAccessFields_createdAt_Update 1311 | delete: PayloadPreferencesDocAccessFields_createdAt_Delete 1312 | } 1313 | 1314 | type PayloadPreferencesDocAccessFields_createdAt_Create { 1315 | permission: Boolean! 1316 | } 1317 | 1318 | type PayloadPreferencesDocAccessFields_createdAt_Read { 1319 | permission: Boolean! 1320 | } 1321 | 1322 | type PayloadPreferencesDocAccessFields_createdAt_Update { 1323 | permission: Boolean! 1324 | } 1325 | 1326 | type PayloadPreferencesDocAccessFields_createdAt_Delete { 1327 | permission: Boolean! 1328 | } 1329 | 1330 | type PayloadPreferencesCreateDocAccess { 1331 | permission: Boolean! 1332 | where: JSONObject 1333 | } 1334 | 1335 | type PayloadPreferencesReadDocAccess { 1336 | permission: Boolean! 1337 | where: JSONObject 1338 | } 1339 | 1340 | type PayloadPreferencesUpdateDocAccess { 1341 | permission: Boolean! 1342 | where: JSONObject 1343 | } 1344 | 1345 | type PayloadPreferencesDeleteDocAccess { 1346 | permission: Boolean! 1347 | where: JSONObject 1348 | } 1349 | 1350 | type Access { 1351 | canAccessAdmin: Boolean! 1352 | users: usersAccess 1353 | pages: pagesAccess 1354 | media: mediaAccess 1355 | payload_preferences: payload_preferencesAccess 1356 | } 1357 | 1358 | type usersAccess { 1359 | fields: UsersFields 1360 | create: UsersCreateAccess 1361 | read: UsersReadAccess 1362 | update: UsersUpdateAccess 1363 | delete: UsersDeleteAccess 1364 | unlock: UsersUnlockAccess 1365 | } 1366 | 1367 | type UsersFields { 1368 | updatedAt: UsersFields_updatedAt 1369 | createdAt: UsersFields_createdAt 1370 | email: UsersFields_email 1371 | password: UsersFields_password 1372 | } 1373 | 1374 | type UsersFields_updatedAt { 1375 | create: UsersFields_updatedAt_Create 1376 | read: UsersFields_updatedAt_Read 1377 | update: UsersFields_updatedAt_Update 1378 | delete: UsersFields_updatedAt_Delete 1379 | } 1380 | 1381 | type UsersFields_updatedAt_Create { 1382 | permission: Boolean! 1383 | } 1384 | 1385 | type UsersFields_updatedAt_Read { 1386 | permission: Boolean! 1387 | } 1388 | 1389 | type UsersFields_updatedAt_Update { 1390 | permission: Boolean! 1391 | } 1392 | 1393 | type UsersFields_updatedAt_Delete { 1394 | permission: Boolean! 1395 | } 1396 | 1397 | type UsersFields_createdAt { 1398 | create: UsersFields_createdAt_Create 1399 | read: UsersFields_createdAt_Read 1400 | update: UsersFields_createdAt_Update 1401 | delete: UsersFields_createdAt_Delete 1402 | } 1403 | 1404 | type UsersFields_createdAt_Create { 1405 | permission: Boolean! 1406 | } 1407 | 1408 | type UsersFields_createdAt_Read { 1409 | permission: Boolean! 1410 | } 1411 | 1412 | type UsersFields_createdAt_Update { 1413 | permission: Boolean! 1414 | } 1415 | 1416 | type UsersFields_createdAt_Delete { 1417 | permission: Boolean! 1418 | } 1419 | 1420 | type UsersFields_email { 1421 | create: UsersFields_email_Create 1422 | read: UsersFields_email_Read 1423 | update: UsersFields_email_Update 1424 | delete: UsersFields_email_Delete 1425 | } 1426 | 1427 | type UsersFields_email_Create { 1428 | permission: Boolean! 1429 | } 1430 | 1431 | type UsersFields_email_Read { 1432 | permission: Boolean! 1433 | } 1434 | 1435 | type UsersFields_email_Update { 1436 | permission: Boolean! 1437 | } 1438 | 1439 | type UsersFields_email_Delete { 1440 | permission: Boolean! 1441 | } 1442 | 1443 | type UsersFields_password { 1444 | create: UsersFields_password_Create 1445 | read: UsersFields_password_Read 1446 | update: UsersFields_password_Update 1447 | delete: UsersFields_password_Delete 1448 | } 1449 | 1450 | type UsersFields_password_Create { 1451 | permission: Boolean! 1452 | } 1453 | 1454 | type UsersFields_password_Read { 1455 | permission: Boolean! 1456 | } 1457 | 1458 | type UsersFields_password_Update { 1459 | permission: Boolean! 1460 | } 1461 | 1462 | type UsersFields_password_Delete { 1463 | permission: Boolean! 1464 | } 1465 | 1466 | type UsersCreateAccess { 1467 | permission: Boolean! 1468 | where: JSONObject 1469 | } 1470 | 1471 | type UsersReadAccess { 1472 | permission: Boolean! 1473 | where: JSONObject 1474 | } 1475 | 1476 | type UsersUpdateAccess { 1477 | permission: Boolean! 1478 | where: JSONObject 1479 | } 1480 | 1481 | type UsersDeleteAccess { 1482 | permission: Boolean! 1483 | where: JSONObject 1484 | } 1485 | 1486 | type UsersUnlockAccess { 1487 | permission: Boolean! 1488 | where: JSONObject 1489 | } 1490 | 1491 | type pagesAccess { 1492 | fields: PagesFields 1493 | create: PagesCreateAccess 1494 | read: PagesReadAccess 1495 | update: PagesUpdateAccess 1496 | delete: PagesDeleteAccess 1497 | } 1498 | 1499 | type PagesFields { 1500 | title: PagesFields_title 1501 | content: PagesFields_content 1502 | updatedAt: PagesFields_updatedAt 1503 | createdAt: PagesFields_createdAt 1504 | } 1505 | 1506 | type PagesFields_title { 1507 | create: PagesFields_title_Create 1508 | read: PagesFields_title_Read 1509 | update: PagesFields_title_Update 1510 | delete: PagesFields_title_Delete 1511 | } 1512 | 1513 | type PagesFields_title_Create { 1514 | permission: Boolean! 1515 | } 1516 | 1517 | type PagesFields_title_Read { 1518 | permission: Boolean! 1519 | } 1520 | 1521 | type PagesFields_title_Update { 1522 | permission: Boolean! 1523 | } 1524 | 1525 | type PagesFields_title_Delete { 1526 | permission: Boolean! 1527 | } 1528 | 1529 | type PagesFields_content { 1530 | create: PagesFields_content_Create 1531 | read: PagesFields_content_Read 1532 | update: PagesFields_content_Update 1533 | delete: PagesFields_content_Delete 1534 | } 1535 | 1536 | type PagesFields_content_Create { 1537 | permission: Boolean! 1538 | } 1539 | 1540 | type PagesFields_content_Read { 1541 | permission: Boolean! 1542 | } 1543 | 1544 | type PagesFields_content_Update { 1545 | permission: Boolean! 1546 | } 1547 | 1548 | type PagesFields_content_Delete { 1549 | permission: Boolean! 1550 | } 1551 | 1552 | type PagesFields_updatedAt { 1553 | create: PagesFields_updatedAt_Create 1554 | read: PagesFields_updatedAt_Read 1555 | update: PagesFields_updatedAt_Update 1556 | delete: PagesFields_updatedAt_Delete 1557 | } 1558 | 1559 | type PagesFields_updatedAt_Create { 1560 | permission: Boolean! 1561 | } 1562 | 1563 | type PagesFields_updatedAt_Read { 1564 | permission: Boolean! 1565 | } 1566 | 1567 | type PagesFields_updatedAt_Update { 1568 | permission: Boolean! 1569 | } 1570 | 1571 | type PagesFields_updatedAt_Delete { 1572 | permission: Boolean! 1573 | } 1574 | 1575 | type PagesFields_createdAt { 1576 | create: PagesFields_createdAt_Create 1577 | read: PagesFields_createdAt_Read 1578 | update: PagesFields_createdAt_Update 1579 | delete: PagesFields_createdAt_Delete 1580 | } 1581 | 1582 | type PagesFields_createdAt_Create { 1583 | permission: Boolean! 1584 | } 1585 | 1586 | type PagesFields_createdAt_Read { 1587 | permission: Boolean! 1588 | } 1589 | 1590 | type PagesFields_createdAt_Update { 1591 | permission: Boolean! 1592 | } 1593 | 1594 | type PagesFields_createdAt_Delete { 1595 | permission: Boolean! 1596 | } 1597 | 1598 | type PagesCreateAccess { 1599 | permission: Boolean! 1600 | where: JSONObject 1601 | } 1602 | 1603 | type PagesReadAccess { 1604 | permission: Boolean! 1605 | where: JSONObject 1606 | } 1607 | 1608 | type PagesUpdateAccess { 1609 | permission: Boolean! 1610 | where: JSONObject 1611 | } 1612 | 1613 | type PagesDeleteAccess { 1614 | permission: Boolean! 1615 | where: JSONObject 1616 | } 1617 | 1618 | type mediaAccess { 1619 | fields: MediaFields 1620 | create: MediaCreateAccess 1621 | read: MediaReadAccess 1622 | update: MediaUpdateAccess 1623 | delete: MediaDeleteAccess 1624 | } 1625 | 1626 | type MediaFields { 1627 | text: MediaFields_text 1628 | updatedAt: MediaFields_updatedAt 1629 | createdAt: MediaFields_createdAt 1630 | url: MediaFields_url 1631 | thumbnailURL: MediaFields_thumbnailURL 1632 | filename: MediaFields_filename 1633 | mimeType: MediaFields_mimeType 1634 | filesize: MediaFields_filesize 1635 | width: MediaFields_width 1636 | height: MediaFields_height 1637 | focalX: MediaFields_focalX 1638 | focalY: MediaFields_focalY 1639 | } 1640 | 1641 | type MediaFields_text { 1642 | create: MediaFields_text_Create 1643 | read: MediaFields_text_Read 1644 | update: MediaFields_text_Update 1645 | delete: MediaFields_text_Delete 1646 | } 1647 | 1648 | type MediaFields_text_Create { 1649 | permission: Boolean! 1650 | } 1651 | 1652 | type MediaFields_text_Read { 1653 | permission: Boolean! 1654 | } 1655 | 1656 | type MediaFields_text_Update { 1657 | permission: Boolean! 1658 | } 1659 | 1660 | type MediaFields_text_Delete { 1661 | permission: Boolean! 1662 | } 1663 | 1664 | type MediaFields_updatedAt { 1665 | create: MediaFields_updatedAt_Create 1666 | read: MediaFields_updatedAt_Read 1667 | update: MediaFields_updatedAt_Update 1668 | delete: MediaFields_updatedAt_Delete 1669 | } 1670 | 1671 | type MediaFields_updatedAt_Create { 1672 | permission: Boolean! 1673 | } 1674 | 1675 | type MediaFields_updatedAt_Read { 1676 | permission: Boolean! 1677 | } 1678 | 1679 | type MediaFields_updatedAt_Update { 1680 | permission: Boolean! 1681 | } 1682 | 1683 | type MediaFields_updatedAt_Delete { 1684 | permission: Boolean! 1685 | } 1686 | 1687 | type MediaFields_createdAt { 1688 | create: MediaFields_createdAt_Create 1689 | read: MediaFields_createdAt_Read 1690 | update: MediaFields_createdAt_Update 1691 | delete: MediaFields_createdAt_Delete 1692 | } 1693 | 1694 | type MediaFields_createdAt_Create { 1695 | permission: Boolean! 1696 | } 1697 | 1698 | type MediaFields_createdAt_Read { 1699 | permission: Boolean! 1700 | } 1701 | 1702 | type MediaFields_createdAt_Update { 1703 | permission: Boolean! 1704 | } 1705 | 1706 | type MediaFields_createdAt_Delete { 1707 | permission: Boolean! 1708 | } 1709 | 1710 | type MediaFields_url { 1711 | create: MediaFields_url_Create 1712 | read: MediaFields_url_Read 1713 | update: MediaFields_url_Update 1714 | delete: MediaFields_url_Delete 1715 | } 1716 | 1717 | type MediaFields_url_Create { 1718 | permission: Boolean! 1719 | } 1720 | 1721 | type MediaFields_url_Read { 1722 | permission: Boolean! 1723 | } 1724 | 1725 | type MediaFields_url_Update { 1726 | permission: Boolean! 1727 | } 1728 | 1729 | type MediaFields_url_Delete { 1730 | permission: Boolean! 1731 | } 1732 | 1733 | type MediaFields_thumbnailURL { 1734 | create: MediaFields_thumbnailURL_Create 1735 | read: MediaFields_thumbnailURL_Read 1736 | update: MediaFields_thumbnailURL_Update 1737 | delete: MediaFields_thumbnailURL_Delete 1738 | } 1739 | 1740 | type MediaFields_thumbnailURL_Create { 1741 | permission: Boolean! 1742 | } 1743 | 1744 | type MediaFields_thumbnailURL_Read { 1745 | permission: Boolean! 1746 | } 1747 | 1748 | type MediaFields_thumbnailURL_Update { 1749 | permission: Boolean! 1750 | } 1751 | 1752 | type MediaFields_thumbnailURL_Delete { 1753 | permission: Boolean! 1754 | } 1755 | 1756 | type MediaFields_filename { 1757 | create: MediaFields_filename_Create 1758 | read: MediaFields_filename_Read 1759 | update: MediaFields_filename_Update 1760 | delete: MediaFields_filename_Delete 1761 | } 1762 | 1763 | type MediaFields_filename_Create { 1764 | permission: Boolean! 1765 | } 1766 | 1767 | type MediaFields_filename_Read { 1768 | permission: Boolean! 1769 | } 1770 | 1771 | type MediaFields_filename_Update { 1772 | permission: Boolean! 1773 | } 1774 | 1775 | type MediaFields_filename_Delete { 1776 | permission: Boolean! 1777 | } 1778 | 1779 | type MediaFields_mimeType { 1780 | create: MediaFields_mimeType_Create 1781 | read: MediaFields_mimeType_Read 1782 | update: MediaFields_mimeType_Update 1783 | delete: MediaFields_mimeType_Delete 1784 | } 1785 | 1786 | type MediaFields_mimeType_Create { 1787 | permission: Boolean! 1788 | } 1789 | 1790 | type MediaFields_mimeType_Read { 1791 | permission: Boolean! 1792 | } 1793 | 1794 | type MediaFields_mimeType_Update { 1795 | permission: Boolean! 1796 | } 1797 | 1798 | type MediaFields_mimeType_Delete { 1799 | permission: Boolean! 1800 | } 1801 | 1802 | type MediaFields_filesize { 1803 | create: MediaFields_filesize_Create 1804 | read: MediaFields_filesize_Read 1805 | update: MediaFields_filesize_Update 1806 | delete: MediaFields_filesize_Delete 1807 | } 1808 | 1809 | type MediaFields_filesize_Create { 1810 | permission: Boolean! 1811 | } 1812 | 1813 | type MediaFields_filesize_Read { 1814 | permission: Boolean! 1815 | } 1816 | 1817 | type MediaFields_filesize_Update { 1818 | permission: Boolean! 1819 | } 1820 | 1821 | type MediaFields_filesize_Delete { 1822 | permission: Boolean! 1823 | } 1824 | 1825 | type MediaFields_width { 1826 | create: MediaFields_width_Create 1827 | read: MediaFields_width_Read 1828 | update: MediaFields_width_Update 1829 | delete: MediaFields_width_Delete 1830 | } 1831 | 1832 | type MediaFields_width_Create { 1833 | permission: Boolean! 1834 | } 1835 | 1836 | type MediaFields_width_Read { 1837 | permission: Boolean! 1838 | } 1839 | 1840 | type MediaFields_width_Update { 1841 | permission: Boolean! 1842 | } 1843 | 1844 | type MediaFields_width_Delete { 1845 | permission: Boolean! 1846 | } 1847 | 1848 | type MediaFields_height { 1849 | create: MediaFields_height_Create 1850 | read: MediaFields_height_Read 1851 | update: MediaFields_height_Update 1852 | delete: MediaFields_height_Delete 1853 | } 1854 | 1855 | type MediaFields_height_Create { 1856 | permission: Boolean! 1857 | } 1858 | 1859 | type MediaFields_height_Read { 1860 | permission: Boolean! 1861 | } 1862 | 1863 | type MediaFields_height_Update { 1864 | permission: Boolean! 1865 | } 1866 | 1867 | type MediaFields_height_Delete { 1868 | permission: Boolean! 1869 | } 1870 | 1871 | type MediaFields_focalX { 1872 | create: MediaFields_focalX_Create 1873 | read: MediaFields_focalX_Read 1874 | update: MediaFields_focalX_Update 1875 | delete: MediaFields_focalX_Delete 1876 | } 1877 | 1878 | type MediaFields_focalX_Create { 1879 | permission: Boolean! 1880 | } 1881 | 1882 | type MediaFields_focalX_Read { 1883 | permission: Boolean! 1884 | } 1885 | 1886 | type MediaFields_focalX_Update { 1887 | permission: Boolean! 1888 | } 1889 | 1890 | type MediaFields_focalX_Delete { 1891 | permission: Boolean! 1892 | } 1893 | 1894 | type MediaFields_focalY { 1895 | create: MediaFields_focalY_Create 1896 | read: MediaFields_focalY_Read 1897 | update: MediaFields_focalY_Update 1898 | delete: MediaFields_focalY_Delete 1899 | } 1900 | 1901 | type MediaFields_focalY_Create { 1902 | permission: Boolean! 1903 | } 1904 | 1905 | type MediaFields_focalY_Read { 1906 | permission: Boolean! 1907 | } 1908 | 1909 | type MediaFields_focalY_Update { 1910 | permission: Boolean! 1911 | } 1912 | 1913 | type MediaFields_focalY_Delete { 1914 | permission: Boolean! 1915 | } 1916 | 1917 | type MediaCreateAccess { 1918 | permission: Boolean! 1919 | where: JSONObject 1920 | } 1921 | 1922 | type MediaReadAccess { 1923 | permission: Boolean! 1924 | where: JSONObject 1925 | } 1926 | 1927 | type MediaUpdateAccess { 1928 | permission: Boolean! 1929 | where: JSONObject 1930 | } 1931 | 1932 | type MediaDeleteAccess { 1933 | permission: Boolean! 1934 | where: JSONObject 1935 | } 1936 | 1937 | type payload_preferencesAccess { 1938 | fields: PayloadPreferencesFields 1939 | create: PayloadPreferencesCreateAccess 1940 | read: PayloadPreferencesReadAccess 1941 | update: PayloadPreferencesUpdateAccess 1942 | delete: PayloadPreferencesDeleteAccess 1943 | } 1944 | 1945 | type PayloadPreferencesFields { 1946 | user: PayloadPreferencesFields_user 1947 | key: PayloadPreferencesFields_key 1948 | value: PayloadPreferencesFields_value 1949 | updatedAt: PayloadPreferencesFields_updatedAt 1950 | createdAt: PayloadPreferencesFields_createdAt 1951 | } 1952 | 1953 | type PayloadPreferencesFields_user { 1954 | create: PayloadPreferencesFields_user_Create 1955 | read: PayloadPreferencesFields_user_Read 1956 | update: PayloadPreferencesFields_user_Update 1957 | delete: PayloadPreferencesFields_user_Delete 1958 | } 1959 | 1960 | type PayloadPreferencesFields_user_Create { 1961 | permission: Boolean! 1962 | } 1963 | 1964 | type PayloadPreferencesFields_user_Read { 1965 | permission: Boolean! 1966 | } 1967 | 1968 | type PayloadPreferencesFields_user_Update { 1969 | permission: Boolean! 1970 | } 1971 | 1972 | type PayloadPreferencesFields_user_Delete { 1973 | permission: Boolean! 1974 | } 1975 | 1976 | type PayloadPreferencesFields_key { 1977 | create: PayloadPreferencesFields_key_Create 1978 | read: PayloadPreferencesFields_key_Read 1979 | update: PayloadPreferencesFields_key_Update 1980 | delete: PayloadPreferencesFields_key_Delete 1981 | } 1982 | 1983 | type PayloadPreferencesFields_key_Create { 1984 | permission: Boolean! 1985 | } 1986 | 1987 | type PayloadPreferencesFields_key_Read { 1988 | permission: Boolean! 1989 | } 1990 | 1991 | type PayloadPreferencesFields_key_Update { 1992 | permission: Boolean! 1993 | } 1994 | 1995 | type PayloadPreferencesFields_key_Delete { 1996 | permission: Boolean! 1997 | } 1998 | 1999 | type PayloadPreferencesFields_value { 2000 | create: PayloadPreferencesFields_value_Create 2001 | read: PayloadPreferencesFields_value_Read 2002 | update: PayloadPreferencesFields_value_Update 2003 | delete: PayloadPreferencesFields_value_Delete 2004 | } 2005 | 2006 | type PayloadPreferencesFields_value_Create { 2007 | permission: Boolean! 2008 | } 2009 | 2010 | type PayloadPreferencesFields_value_Read { 2011 | permission: Boolean! 2012 | } 2013 | 2014 | type PayloadPreferencesFields_value_Update { 2015 | permission: Boolean! 2016 | } 2017 | 2018 | type PayloadPreferencesFields_value_Delete { 2019 | permission: Boolean! 2020 | } 2021 | 2022 | type PayloadPreferencesFields_updatedAt { 2023 | create: PayloadPreferencesFields_updatedAt_Create 2024 | read: PayloadPreferencesFields_updatedAt_Read 2025 | update: PayloadPreferencesFields_updatedAt_Update 2026 | delete: PayloadPreferencesFields_updatedAt_Delete 2027 | } 2028 | 2029 | type PayloadPreferencesFields_updatedAt_Create { 2030 | permission: Boolean! 2031 | } 2032 | 2033 | type PayloadPreferencesFields_updatedAt_Read { 2034 | permission: Boolean! 2035 | } 2036 | 2037 | type PayloadPreferencesFields_updatedAt_Update { 2038 | permission: Boolean! 2039 | } 2040 | 2041 | type PayloadPreferencesFields_updatedAt_Delete { 2042 | permission: Boolean! 2043 | } 2044 | 2045 | type PayloadPreferencesFields_createdAt { 2046 | create: PayloadPreferencesFields_createdAt_Create 2047 | read: PayloadPreferencesFields_createdAt_Read 2048 | update: PayloadPreferencesFields_createdAt_Update 2049 | delete: PayloadPreferencesFields_createdAt_Delete 2050 | } 2051 | 2052 | type PayloadPreferencesFields_createdAt_Create { 2053 | permission: Boolean! 2054 | } 2055 | 2056 | type PayloadPreferencesFields_createdAt_Read { 2057 | permission: Boolean! 2058 | } 2059 | 2060 | type PayloadPreferencesFields_createdAt_Update { 2061 | permission: Boolean! 2062 | } 2063 | 2064 | type PayloadPreferencesFields_createdAt_Delete { 2065 | permission: Boolean! 2066 | } 2067 | 2068 | type PayloadPreferencesCreateAccess { 2069 | permission: Boolean! 2070 | where: JSONObject 2071 | } 2072 | 2073 | type PayloadPreferencesReadAccess { 2074 | permission: Boolean! 2075 | where: JSONObject 2076 | } 2077 | 2078 | type PayloadPreferencesUpdateAccess { 2079 | permission: Boolean! 2080 | where: JSONObject 2081 | } 2082 | 2083 | type PayloadPreferencesDeleteAccess { 2084 | permission: Boolean! 2085 | where: JSONObject 2086 | } 2087 | 2088 | type Mutation { 2089 | createUser(data: mutationUserInput!, draft: Boolean): User 2090 | updateUser(id: String!, autosave: Boolean, data: mutationUserUpdateInput!, draft: Boolean): User 2091 | deleteUser(id: String!): User 2092 | refreshTokenUser(token: String): usersRefreshedUser 2093 | logoutUser: String 2094 | unlockUser(email: String!): Boolean! 2095 | loginUser(email: String, password: String): usersLoginResult 2096 | forgotPasswordUser(disableEmail: Boolean, email: String!, expiration: Int): Boolean! 2097 | resetPasswordUser(password: String, token: String): usersResetPassword 2098 | verifyEmailUser(token: String): Boolean 2099 | createPage(data: mutationPageInput!, draft: Boolean): Page 2100 | updatePage(id: String!, autosave: Boolean, data: mutationPageUpdateInput!, draft: Boolean): Page 2101 | deletePage(id: String!): Page 2102 | duplicatePage(id: String!): Page 2103 | createMedia(data: mutationMediaInput!, draft: Boolean): Media 2104 | updateMedia(id: String!, autosave: Boolean, data: mutationMediaUpdateInput!, draft: Boolean): Media 2105 | deleteMedia(id: String!): Media 2106 | createPayloadPreference(data: mutationPayloadPreferenceInput!, draft: Boolean): PayloadPreference 2107 | updatePayloadPreference(id: String!, autosave: Boolean, data: mutationPayloadPreferenceUpdateInput!, draft: Boolean): PayloadPreference 2108 | deletePayloadPreference(id: String!): PayloadPreference 2109 | duplicatePayloadPreference(id: String!): PayloadPreference 2110 | } 2111 | 2112 | input mutationUserInput { 2113 | updatedAt: String 2114 | createdAt: String 2115 | email: String! 2116 | resetPasswordToken: String 2117 | resetPasswordExpiration: String 2118 | salt: String 2119 | hash: String 2120 | loginAttempts: Float 2121 | lockUntil: String 2122 | password: String! 2123 | } 2124 | 2125 | input mutationUserUpdateInput { 2126 | updatedAt: String 2127 | createdAt: String 2128 | email: String 2129 | resetPasswordToken: String 2130 | resetPasswordExpiration: String 2131 | salt: String 2132 | hash: String 2133 | loginAttempts: Float 2134 | lockUntil: String 2135 | password: String 2136 | } 2137 | 2138 | type usersRefreshedUser { 2139 | exp: Int 2140 | refreshedToken: String 2141 | user: usersJWT 2142 | } 2143 | 2144 | type usersJWT { 2145 | email: EmailAddress! 2146 | collection: String! 2147 | } 2148 | 2149 | type usersLoginResult { 2150 | exp: Int 2151 | token: String 2152 | user: User 2153 | } 2154 | 2155 | type usersResetPassword { 2156 | token: String 2157 | user: User 2158 | } 2159 | 2160 | input mutationPageInput { 2161 | title: String 2162 | content: JSON 2163 | updatedAt: String 2164 | createdAt: String 2165 | } 2166 | 2167 | input mutationPageUpdateInput { 2168 | title: String 2169 | content: JSON 2170 | updatedAt: String 2171 | createdAt: String 2172 | } 2173 | 2174 | input mutationMediaInput { 2175 | text: String 2176 | updatedAt: String 2177 | createdAt: String 2178 | url: String 2179 | thumbnailURL: String 2180 | filename: String 2181 | mimeType: String 2182 | filesize: Float 2183 | width: Float 2184 | height: Float 2185 | focalX: Float 2186 | focalY: Float 2187 | } 2188 | 2189 | input mutationMediaUpdateInput { 2190 | text: String 2191 | updatedAt: String 2192 | createdAt: String 2193 | url: String 2194 | thumbnailURL: String 2195 | filename: String 2196 | mimeType: String 2197 | filesize: Float 2198 | width: Float 2199 | height: Float 2200 | focalX: Float 2201 | focalY: Float 2202 | } 2203 | 2204 | input mutationPayloadPreferenceInput { 2205 | user: PayloadPreference_UserRelationshipInput 2206 | key: String 2207 | value: JSON 2208 | updatedAt: String 2209 | createdAt: String 2210 | } 2211 | 2212 | input PayloadPreference_UserRelationshipInput { 2213 | relationTo: PayloadPreference_UserRelationshipInputRelationTo 2214 | value: JSON 2215 | } 2216 | 2217 | enum PayloadPreference_UserRelationshipInputRelationTo { 2218 | users 2219 | } 2220 | 2221 | input mutationPayloadPreferenceUpdateInput { 2222 | user: PayloadPreferenceUpdate_UserRelationshipInput 2223 | key: String 2224 | value: JSON 2225 | updatedAt: String 2226 | createdAt: String 2227 | } 2228 | 2229 | input PayloadPreferenceUpdate_UserRelationshipInput { 2230 | relationTo: PayloadPreferenceUpdate_UserRelationshipInputRelationTo 2231 | value: JSON 2232 | } 2233 | 2234 | enum PayloadPreferenceUpdate_UserRelationshipInputRelationTo { 2235 | users 2236 | } --------------------------------------------------------------------------------