C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\fields\config\sanitize.js:52
throw new _errors.InvalidFieldRelationship(field, relationship);
^
InvalidFieldRelationship: Field Product file(s) has invalid relationship 'product_files'.
at C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\fields\config\sanitize.js:52:31
at Array.forEach ()
at C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\fields\config\sanitize.js:50:31
at Array.map ()
at sanitizeFields (C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\fields\config\sanitize.js:25:19)
at sanitizeCollection (C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\collections\config\sanitize.js:135:53)
at C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\config\sanitize.js:81:85
at Array.map ()
at sanitizeConfig (C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\config\sanitize.js:81:45)
at buildConfig (C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\config\build.js:21:41) {
data: null,
isOperational: true,
isPublic: false,
status: 500
}
Node.js v20.10.0
my ProductFile.ts :
import { User } from "../payload-types";
import { BeforeChangeHook } from "payload/dist/collections/config/types";
import { Access, CollectionConfig } from "payload/types";
const addUser: BeforeChangeHook = ({ req, data }) => {
const user = req.user as User | null
return {...data, user: user?.id}
}
const yourOwnAndPurchased: Access = async ({ req }) => {
const user = req.user as User | null
Hello,
so i am having troubles with running generate:types from json. The code is exactly the same as in the video.
if i run npm run generate:types i get this error : PS C:\Users\hacke\complete_fullstack_digital_marketplace_app> npm run generate:types
C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\fields\config\sanitize.js:52 throw new _errors.InvalidFieldRelationship(field, relationship); ^
InvalidFieldRelationship: Field Product file(s) has invalid relationship 'product_files'. at C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\fields\config\sanitize.js:52:31 at Array.forEach ()
at C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\fields\config\sanitize.js:50:31
at Array.map ()
at sanitizeFields (C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\fields\config\sanitize.js:25:19)
at sanitizeCollection (C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\collections\config\sanitize.js:135:53)
at C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\config\sanitize.js:81:85
at Array.map ()
at sanitizeConfig (C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\config\sanitize.js:81:45)
at buildConfig (C:\Users\hacke\complete_fullstack_digital_marketplace_app\node_modules\payload\dist\config\build.js:21:41) {
data: null,
isOperational: true,
isPublic: false,
status: 500
}
Node.js v20.10.0
my ProductFile.ts :
import { User } from "../payload-types"; import { BeforeChangeHook } from "payload/dist/collections/config/types"; import { Access, CollectionConfig } from "payload/types";
const addUser: BeforeChangeHook = ({ req, data }) => { const user = req.user as User | null return {...data, user: user?.id} }
const yourOwnAndPurchased: Access = async ({ req }) => { const user = req.user as User | null
}
export const ProductFiles: CollectionConfig = { slug: "product_files", admin: { hidden: ({ user }) => user.role !== "admin", }, hooks: { beforeChange: [addUser] }, access: { read: yourOwnAndPurchased }, upload: { staticURL: "/product_files", staticDir: "product_files", mimeTypes: ["image/", "font/", "application/postscript"], }, fields: [ { name: "user", type: "relationship", relationTo: "users", admin: { condition: () => false }, hasMany: false, required: true, }, ], }
my payload.config.ts :
import { mongooseAdapter } from "@payloadcms/db-mongodb"; import { slateEditor } from "@payloadcms/richtext-slate"; import { buildConfig } from "payload/config"; import { webpackBundler } from "@payloadcms/bundler-webpack"; import path from "path"; import { Users } from "./collections/Users"; import dotenv from "dotenv"; import { Products } from "./collections/Products/Products"; import { Media } from "./collections/Media"; //*IMPORTS*****
dotenv.config({ path: path.resolve(__dirname, "../.env"), })
export default buildConfig({ serverURL: process.env.NEXT_PUBLIC_SERVER_URL || '', collections: [Users, Products, Media], routes: { admin: '/sell' }, admin: { user: "users", bundler: webpackBundler(), meta: { titleSuffix: "- HippoHub", favicon: "/favicon.ico", ogImage: "/thumbnail.jpg", }, }, rateLimit: { max: 2000, }, editor: slateEditor({}), db: mongooseAdapter({ url: process.env.MONGODB_URL!, }), typescript: { outputFile: path.resolve(__dirname, 'payload-types.ts'), }, })
my Products.ts :
import { PRODUCT_CATEGORIES } from "../../config"; import { CollectionConfig } from "payload/types";
export const Products: CollectionConfig = { slug: "products", admin: { useAsTitle: "name" }, access: {}, fields: [ { name: "user", type: "relationship", relationTo: "users", required: true, hasMany: false, admin: { condition: () => false }, }, { name: "name", label: "Name", type: "text", required: true, }, { name: "description", type: "textarea", label: "Product details", }, { name: "price", label: "Price in USD", min: 0, max: 1000, type: "number", required: true, }, { name: "category", label: "Category", type: "select", options: PRODUCT_CATEGORIES.map(({ label, value }) => ({ label, value }) ), required: true, }, { name: "product_files", label: "Product file(s)", type: "relationship", required: true, relationTo: "product_files", hasMany: false, }, { name: "approvedForSale", label: "Product Status", type: "select", defaultValue: "pending", access: { create: ({ req }) => req.user.role === "admin", read: ({ req }) => req.user.role === "admin", update: ({ req }) => req.user.role === "admin", }, options: [ { label: "Pending verification", value: "pending", }, { label: "Approved", value: "approved", }, { label: "Denied", value: "denied", }, ], }, { name: "priceId", access: { create: () => false, read: () => false, update: () => false, }, type: "text", admin: { hidden: true, }, }, { name: "stripeId", access: { create: () => false, read: () => false, update: () => false, }, type: "text", admin: { hidden: true, }, }, { name: "images", type: "array", label: "Product images", minRows: 1, maxRows: 4, required: true, labels: { singular: "Image", plural: "Images", }, fields: [ { name: "image", type: "upload", relationTo: "media", required: true, }, ], }, ], }
my package.json :
{ "name": "complete_fullstack_digital_marketplace_app", "version": "0.1.0", "private": true, "scripts": { "dev": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts nodemon", "generate:types": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:types", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "@hookform/resolvers": "^3.3.2", "@payloadcms/bundler-webpack": "^1.0.5", "@payloadcms/db-mongodb": "^1.0.8", "@payloadcms/richtext-slate": "^1.2.0", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", "@tanstack/react-query": "^4.36.1", "@trpc/client": "^10.44.1", "@trpc/next": "^10.44.1", "@trpc/react-query": "^10.44.1", "@trpc/server": "^10.44.1", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", "cross-env": "^7.0.3", "dotenv": "^16.3.1", "express": "^4.18.2", "lucide-react": "^0.292.0", "next": "14.0.3", "nodemailer": "^6.9.7", "payload": "^2.2.2", "react": "^18", "react-dom": "^18", "react-hook-form": "^7.48.2", "sonner": "^1.2.4", "tailwind-merge": "^2.0.0", "tailwindcss-animate": "^1.0.7", "zod": "^3.22.4" }, "devDependencies": { "@types/express": "^4.17.21", "@types/node": "^20", "@types/nodemailer": "^6.4.14", "@types/react": "^18", "@types/react-dom": "^18", "autoprefixer": "^10.0.1", "eslint": "^8", "eslint-config-next": "14.0.3", "nodemon": "^3.0.1", "postcss": "^8", "tailwindcss": "^3.3.0", "typescript": "^5" } }
i cant figure this out already spent few days debugging this.