محمود سعداوي2 نشر 9 يوليو أرسل تقرير نشر 9 يوليو السلام عليكم. أواجه مشكل في رفع التطبيق التالي على render. package.json { "name": "chat-app-backend", "version": "1.0.0", "main": "index.js", "type": "module", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node dist/index.js", "server": "tsx watch index.ts", "build": "prisma generate && tsc", "postinstall": "prisma generate" }, "author": "Mahmoud Saadaoui", "license": "ISC", "description": "", "dependencies": { "@prisma/client": "^6.6.0", "bcrypt": "^5.1.1", "cloudinary": "^2.6.1", "cors": "^2.8.5", "dotenv": "^16.5.0", "express": "^4.21.2", "express-async-errors": "^3.1.1", "jsonwebtoken": "^9.0.2", "multer": "^2.0.0", "nodemailer": "^7.0.3", "socket.io": "^4.8.1", "zod": "^3.24.4" }, "devDependencies": { "@types/bcrypt": "^5.0.2", "@types/express": "^5.0.1", "@types/jsonwebtoken": "^9.0.9", "@types/multer": "^1.4.12", "@types/node": "^22.16.0", "@types/nodemailer": "^6.4.17", "@types/web-push": "^3.6.4", "prisma": "^6.6.0", "ts-node": "^10.9.2", "tsx": "^4.19.3", "typescript": "^5.8.3" } } tsconfig.json { "compilerOptions": { "outDir": "dist", "target": "esnext", "lib": ["dom", "dom.iterable", "esnext"], // "module": "commonjs", "module": "esnext", "moduleResolution": "node", "strict": true, "forceConsistentCasingInFileNames": true, "esModuleInterop": true, "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "baseUrl": ".", "paths": { "@/*": ["src/*"] }, "incremental": true, "skipLibCheck": true }, "include": ["index.ts", "**/*.ts"], "exclude": ["node_modules"] } تنظيم الملفات الخطأ اقتباس node:internal/modules/esm/resolve:275 Jul 9 08:17:22 AM throw new ERR_MODULE_NOT_FOUND( Jul 9 08:17:22 AM ^ Jul 9 08:17:22 AM Jul 9 08:17:22 AM Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/opt/render/project/src/backend/dist/routes/userRoute' imported from /opt/render/project/src/backend/dist/index.js Jul 9 08:17:22 AM at finalizeResolution (node:internal/modules/esm/resolve:275:11) Jul 9 08:17:22 AM at moduleResolve (node:internal/modules/esm/resolve:860:10) Jul 9 08:17:22 AM at defaultResolve (node:internal/modules/esm/resolve:984:11) Jul 9 08:17:22 AM at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:780:12) Jul 9 08:17:22 AM at #cachedDefaultResolve (node:internal/modules/esm/loader:704:25) Jul 9 08:17:22 AM at ModuleLoader.resolve (node:internal/modules/esm/loader:687:38) Jul 9 08:17:22 AM at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:305:38) Jul 9 08:17:22 AM at ModuleJob._link (node:internal/modules/esm/module_job:137:49) { Jul 9 08:17:22 AM code: 'ERR_MODULE_NOT_FOUND', Jul 9 08:17:22 AM url: 'file:///opt/render/project/src/backend/dist/routes/userRoute' Jul 9 08:17:22 AM } Jul 9 08:17:22 AM Jul 9 08:17:22 AM Node.js v22.16.0 ملاحظة عندما أقوم بـ اقتباس npm run build يظهر بوضوح الملف اقتباس backend/dist/controllers/userRoute.js شكرا لكم. 1 اقتباس
0 Mustafa Suleiman نشر 9 يوليو أرسل تقرير نشر 9 يوليو بسبب "type": "module" في package.json، والتي تفرض عليك تضمين امتداد الملف .js في جميع عبارات الاستيراد، أي عليك تحديث جميع عبارات الاستيراد في مشروعك لتتضمن .js 1 اقتباس
0 محمود سعداوي2 نشر 9 يوليو الكاتب أرسل تقرير نشر 9 يوليو بتاريخ 1 ساعة قال Mustafa Suleiman: بسبب "type": "module" في package.json، والتي تفرض عليك تضمين امتداد الملف .js في جميع عبارات الاستيراد، أي عليك تحديث جميع عبارات الاستيراد في مشروعك لتتضمن .js شكرا. المشكل الحالي: بعد رفع المشروع إلى البيئة الإنتاجية، لم أعد قادرًا على تغيير صورة الملف الشخصي للمستخدم، بالرغم من أن العملية تعمل بشكل سليم تمامًا في بيئة التطوير (development). ✅ لا تظهر أي أخطاء سواء في الواجهة الأمامية (frontend) أو الخلفية (backend). ✅ نفس الكود المستخدم في التطوير تم رفعه كما هو إلى الإنتاج. الكود كاملا الواجهة الخلفية: profile.ts /** * @method PUT * @route /api/profile/:id/profile-photo * @desc Update user profile (name & bio) * @access private (only user himself) */ export const updateProfilePhoto = async ( req: Request, res: Response ): Promise<void> => { try { // Check if the user is authorized to update this profile if (req.user.id !== req.params.id) { res.status(403).json({ message: "Unauthorized: You are not allowed to update this profile." }); return } // Check if an image file was uploaded if (!req.file) { res.status(400).json({ message: "No image file uploaded." }) return } // Build the local path to the uploaded image const imagePath = path.join(__dirname, ../images/${req.file.filename}) // Upload the image to Cloudinary const uploadResult = await cloudinaryUploadImage(imagePath) // Remove the local image file after upload await fs.unlink(imagePath); // Retrieve the user from the database const profile = await prisma.user.findUnique({ where: { id: req.user.id } }) if (!profile) { res.status(404).json({ message: "User not found" }); return } // If the user already has a profile picture, remove it from Cloudinary const profilePicture = profile.profilePicture as { publicId: string; secureUrl: string }; if (profilePicture?.publicId) { await cloudinaryRemoveImage(profilePicture.publicId); } // Update the user's profile with the new profile picture const updatedProfilePhoto = await prisma.user.update({ where: { id: req.user.id }, data: { profilePicture: { publicId: uploadResult.public_id, secureUrl: uploadResult.secure_url } }, select: { id: true, name: true, profilePicture: true } }); // Return a success response with updated user info res.status(200).json({ updatedProfilePhoto, message: "Profile photo updated successfully." }); } catch (err) { handleError(res, err as Error); } }; middlewares/cloudinary.ts *************************** import { v2 as cloudinary } from 'cloudinary'; cloudinary.config({ cloud_name: process.env.CLOUDINARY_CLOUD_NAME, api_key: process.env.CLOUDINARY_API_KEY, api_secret: process.env.CLOUDINARY_API_SECRET }) export const cloudinaryUploadImage = async(fileToUpload: string) => { try { const data = await cloudinary.uploader.upload(fileToUpload, { resource_type: 'auto', }) return data } catch (error) { console.log(error) throw new Error('Internal Server Error (cloudinary)') } } export const cloudinaryRemoveImage = async(imagePublicId: string ) => { try { const result = await cloudinary.uploader.destroy(imagePublicId) return result } catch (error) { console.log(error) throw new Error('Internal Server Error (cloudinary)') } } middlewares/upload.ts ********************* import path from "path"; import multer from "multer"; import { fileURLToPath } from "url"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Photo Storage const photoStorage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, path.join(__dirname, "../images")); }, filename: function (req, file, cb) { if (file) { cb(null, new Date().toISOString().replace(/:/g, "-") + file.originalname); } else { cb(new Error("File upload error"), "") } }, }); // Photo Upload Middleware export const photoUpload = multer({ storage: photoStorage, fileFilter: function(req, file, cb) { if (file.mimetype.startsWith("image")) { cb(null, true) } else { cb(new Error("Unsupported File Format")) } }, limits: { fieldSize: 1024 * 1024 * 5 } }) الواجهة الأمامية EditProfileImage.tsx ********************* import { FaCamera } from "react-icons/fa"; import { useUpdateProfilePhoto } from "../../hooks/useProfile"; import { useAuthStore } from "../../store/auth.store"; import { toast } from "react-toastify"; import Spinner from "../Spinner"; import { defaultAvatar } from "../../utils/constantes"; const EditProfileImage = () => { const { user, token, setUser } = useAuthStore(); const { mutate, isPending } = useUpdateProfilePhoto(); const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => { if (e.target.files?.[0]) { updateProfilePhoto(e.target.files[0]); } }; const updateProfilePhoto = (selectedFile: File) => { if (!token || !user) return mutate( {file: selectedFile, token, id:user?.id}, { onSuccess: (data) => { setUser({ ...user, photoProfile: data?.updatedProfilePhoto.profilePicture.secureUrl, }); toast.success(data?.message) }, onError: (err) => { console.log(err) toast.error('An unexpected error occurred.') } }) }; if (isPending) { return ( <Spinner /> ); } return ( ....... ); }; export default EditProfileImage; ****************************** hooks/useUpdateProfilePhoto ****************************** export const useUpdateProfilePhoto = () => { return useMutation({ mutationFn: ({ file, token, id, }: { file: File; token: string; id: string; }) => updateProfilePhotoApi(file, token, id), }); }; ************************ api/profile.api.ts *********************** export const updateProfilePhotoApi = async ( file: File, token: string, id: string ) => { try { const formData = new FormData() formData.append("image", file) const res = await axios.put( ${process.env.REACT_APP_API_URL}/profile/${id}/profile-photo, formData, { headers: { Authorization: Bearer ${token}, }, withCredentials: true, } ); return res.data } catch (error) { console.log(error) } }; اقتباس
السؤال
محمود سعداوي2
السلام عليكم.
أواجه مشكل في رفع التطبيق التالي على render.
package.json
{ "name": "chat-app-backend", "version": "1.0.0", "main": "index.js", "type": "module", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node dist/index.js", "server": "tsx watch index.ts", "build": "prisma generate && tsc", "postinstall": "prisma generate" }, "author": "Mahmoud Saadaoui", "license": "ISC", "description": "", "dependencies": { "@prisma/client": "^6.6.0", "bcrypt": "^5.1.1", "cloudinary": "^2.6.1", "cors": "^2.8.5", "dotenv": "^16.5.0", "express": "^4.21.2", "express-async-errors": "^3.1.1", "jsonwebtoken": "^9.0.2", "multer": "^2.0.0", "nodemailer": "^7.0.3", "socket.io": "^4.8.1", "zod": "^3.24.4" }, "devDependencies": { "@types/bcrypt": "^5.0.2", "@types/express": "^5.0.1", "@types/jsonwebtoken": "^9.0.9", "@types/multer": "^1.4.12", "@types/node": "^22.16.0", "@types/nodemailer": "^6.4.17", "@types/web-push": "^3.6.4", "prisma": "^6.6.0", "ts-node": "^10.9.2", "tsx": "^4.19.3", "typescript": "^5.8.3" } }
tsconfig.json
{ "compilerOptions": { "outDir": "dist", "target": "esnext", "lib": ["dom", "dom.iterable", "esnext"], // "module": "commonjs", "module": "esnext", "moduleResolution": "node", "strict": true, "forceConsistentCasingInFileNames": true, "esModuleInterop": true, "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "baseUrl": ".", "paths": { "@/*": ["src/*"] }, "incremental": true, "skipLibCheck": true }, "include": ["index.ts", "**/*.ts"], "exclude": ["node_modules"] }
تنظيم الملفات
الخطأ
ملاحظة
عندما أقوم بـ
يظهر بوضوح الملف
شكرا لكم.
2 أجوبة على هذا السؤال
Recommended Posts
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.