0

▼Environment (taken from packege.json)

"@prisma/client": "^4.11.0"

"@supabase/supabase-js": "^2.12.1"

"next":"^12.2.5",.

"next-auth": "^4.20.1",.

"react": "17.0.2", "next".

"typescript": "4.5.5"

The framework is nextjs

Database is supabase

Image storage is supabase storage

ORM is prisma

The form is react hook form

typescript is used.

I can register, update, and retrieve images without problems during local development with npm run dev.

If I run npm run build locally instead of vercel, I can build without any problem, npm run start works without any problem.

The column type of the image to be stored in the DB is string.

I think the error is because the type defined in next.js does not match the type when saving in prisma, but I am inexperienced and it is difficult to identify the cause and solve the problem.

Translated with www.DeepL.com/Translator (free version)


The following error message is output only when building with vercel, and I cannot build.

// Error output in vercel log
./pages/api/user/index.tsx:19:9
Type error: Type '{ name: any; email: any; password: any; image: any; }' is not assignable to type '(Without<UserCreateInput, UserUncheckedCreateInput> & UserUncheckedCreateInput) | (Without<...> & UserCreateInput)'.
  Object literal may only specify known properties, and 'image' does not exist in type '(Without<UserCreateInput, UserUncheckedCreateInput> & UserUncheckedCreateInput) | (Without<...> & UserCreateInput)'.

Error api

  • pages/api/user/index.tsx
import prisma from "../../../lib/prisma";
import type { NextApiRequest, NextApiResponse } from "next";
import { hash } from "bcrypt";

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  if (req.method === "POST") {
    const { name, email, password, image } = req.body;
    console.log(req.body);

    const hash_password = await hash(password, 10);
    const data = await prisma.user.create({
      data: {
        name: name,
        email: email,
        password: hash_password,
        image: image,
      },
    });
    return res.status(200).json(data);
  } else if (req.method === "GET") {
    const data = await prisma.user.findMany({});
    return res.status(200).json(data);
  }
}

component that calls the above API

  • pages/user/index.tsx

// pages/user/index.tsx
import { useForm } from "react-hook-form";
import { useRouter } from "next/router";
import Link from "next/link";
import { signIn } from "next-auth/react";
import Image, { StaticImageData } from "next/image";
import { useState, useRef } from "react";
import { supabase } from "../../lib/supabase";
// ユーザのデフォルト画像
const defaultImg = process.env.NEXT_PUBLIC_DEFAULT_IMG;
interface UserInput {
  name: string;
  email: string;
  password: string;
  image?: string | StaticImageData;
}

type uploadImageUrl = string;

export default function UserForm() {
  const [uploadImageUrl, setUploadImageUrl] = useState<uploadImageUrl>();
  const [uploadImageFile, setUploadImageFile] = useState<File>();
  const router = useRouter();
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<UserInput>({
    defaultValues: {
      name: "",
      email: "",
      password: "",
      image: defaultImg,
    },
  });

  // const inputRef = useRef<HTMLInputElement>();
  // 画像が選択されたら、プレビュー
  const onChangeFile = (e: React.ChangeEvent<HTMLInputElement>) => {
    const { files } = e.target;
    setUploadImageUrl(URL.createObjectURL(files[0]));
    setUploadImageFile(files[0]);
  };

  const submitUserRegister = async (input: UserInput) => {
    //supabaseに画像をアップロード
    const { data, error } = await supabase.storage
      .from("photos")
      .upload("user/" + uploadImageFile.name, uploadImageFile);

    //supabaseから画像のURLをDL
    const url = await supabase.storage
      .from("photos")
      .getPublicUrl(JSON.stringify(data));
    const { publicUrl } = url.data;

    // DLしたURLをimageに格納
    const formData = {
      name: input.name,
      email: input.email,
      password: input.password,
      image: publicUrl,
    };

    try {
      const res = await fetch("/api/user", {
        method: "POST",
        body: JSON.stringify(formData),
        headers: {
          "Content-Type": "application/json",
        },
      });
      // json形式で返す
      const data = await res.json();
      const email = data.email;
      //登録済みのデータを使用するとhash化したpasswordを利用してしまうため、formに入力されたpasswordを使用
      const password = formData.password;
      //sign In()でそのままログイン

      await signIn("credentials", {
        email,
        password,
        callbackUrl: "/",
        redirect: true,
      });
    } catch (error) {
      console.error("Error registering user:", error);
    }
  };

  return (
    <div>
      <h3>ユーザー登録</h3>

      <form
        onSubmit={handleSubmit(submitUserRegister)}
        className="w-full max-w-sm"
      >
---
不要部分の為省略
---
        <Image
          src={uploadImageUrl ? uploadImageUrl : defaultImg}
          width={100}
          height={100}
        ></Image>
        <label className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
          Upload file
        </label>
        <input
          className="block w-full text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-none dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400"
          id="file_input"
          type="file"
          onChange={onChangeFile}
        />

        <div className="md:flex md:items-center">
          <div className="md:w-2/3">
            <button className="shadow bg-blue-500 hover:bg-blue-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded">
              <Link href={`/`}>Home</Link>
            </button>
          </div>
          <div className="md:w-2/3">
            <button
              className="shadow bg-blue-500 hover:bg-blue-400 focus:shadow-outline focus:outline-none text-white font-bold py-2 px-4 rounded"
              type="submit"
            >
              Sign Up
            </button>
          </div>
        </div>
      </form>
    </div>
  );
}

schema.prisma

model User {
  id            String       @default(cuid()) @id
  name          String?
  email         String?   @unique
  emailVerified DateTime?
  image         String?
  password      String
  createdAt     DateTime  @default(now()) @map(name: "created_at")
  updatedAt     DateTime  @updatedAt @map(name: "updated_at")
  posts         Post[]
  @@map(name: "users")
}

If you need any other information, please let us know. Thank you in advance.

1 Answer 1

0

Error: "image" field not found. Ensure your Prisma schema is up-to-date. For development, try prisma db push. For production or MongoDB, use prisma migrate (or prisma db push for MongoDB).

Sign up to request clarification or add additional context in comments.

10 Comments

i recommend you to take to another place the code that use the prisma client and export a functions like "createUser"
I specified the type in the api update statement, but the error did not change.
else if (req.method === "PUT") { const { name, email, password, image } = req.body as { name?: string; email?: string; password: string; image?: string; }; const hash_password = await hash(password, 10); const { id } = req.query; const user = await prisma.user.update({ where: { id: String(id), }, data: { name: name, email: email, password: hash_password, image: image, }, }); return res.status(200).json(user); }
the error say that the image field is not know. Maybe you need to update the model. try "prisma db push"
if you are in production you need to use prisma migrate to update the model
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.