<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Amir_zpr</title>
        <link>https://virgool.io/feed/@amir_zpr</link>
        <description>مشک آن است که خود ببوید نه آنکه عطار بگوید :))))) RNNE =&gt; React+Next+Node+Express اینو خودم ساختم :))</description>
        <language>fa</language>
        <pubDate>2026-06-07 11:47:26</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/57494/avatar/mC50sZ.png?height=120&amp;width=120</url>
            <title>Amir_zpr</title>
            <link>https://virgool.io/@amir_zpr</link>
        </image>

                    <item>
                <title>جلد یک تجربگی : پیاده سازی ورود و ثبت نام با نود جی اس</title>
                <link>https://virgool.io/@amir_zpr/%D8%AC%D9%84%D8%AF-%DB%8C%DA%A9-%D8%AA%D8%AC%D8%B1%D8%A8%DA%AF%DB%8C-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D9%88%D8%B1%D9%88%D8%AF-%D9%88-%D8%AB%D8%A8%D8%AA-%D9%86%D8%A7%D9%85-%D8%A8%D8%A7-%D9%86%D9%88%D8%AF-%D8%AC%DB%8C-%D8%A7%D8%B3-uftxnxapjjxt</link>
                <description>سلام بعد از سه سال دوباره با یه پست شاید مفید اومدم خدمتتون. صرفا دوس دارم یاد گرفته هامو اشتراک بذارم تا خودمم یه محکی زده باشم.حرف بسه بریم سراغ کار.خب اول همه توضیح بدیم که چه کاری قراره انجام بدیم.قراره که روند ثبت نام و ورود کاربر رو کار کنیم با نود جی اس ، اکسپرس صد البته Mongoose . چیا کلا قراره پیاده سازی بشه ثبت نام کاربر و لاگین کاربر ، ریست کردن پسورد ، ریست کردن توکن ، ایمیل کردن ریست پسورد ، محافظت از مسیر های یوزر ، نقش کاربر ادمین یا restrict  کردن ها و کار با توکن و کوکی و ذخیره سازی کلی چیز میز.البته فک نکنم همش توی یه مقاله حوصله سر بر نشه و تقسیمش میکنم به سلسله ای از مقالات.:))هشدار که شاید کامنت گذاری ها توی متن و اسم گذاری ها باب میل سنیور ها نباشه.و اینکه ارور هندلینگم خودتون هندل کنید دیگه .:))چیزایی که فعلا احتیاج داریم ایناس که با npm نصب شن : ,bcryptjs ,express ,jsonwebtoken ,mongoose ,validator, nodemailerیه سری فایل هم باید ساخته بشه که بخش بخش باهاش میریم جلو : فایل اول فایل userModel.js  که قرار مدل اسکیمای یوزر رو توش بسازیم: به این شکل با کد زیر: const mongoose = require(&amp;quotmongoose&amp;quot);
const validator = require(&amp;quotvalidator&amp;quot);
const bcrypt = require(&amp;quotbcryptjs&amp;quot);
const userSchema = new mongoose.Schema({
 name: {
    type: String,
     required: [true, &amp;quotPlease tell us your name!&amp;quot],  },
  email: {  type: String,
       required: [true, &amp;quotPlease provide your email&amp;quot],
       unique: true,
        lowercase: true,
       validate: [validator.isEmail, &amp;quotPlease provide a valid email&amp;quot],
 },
photo: String,
role: {
       type: String,
        enum: [&amp;quotadmin&amp;quot, &amp;quotuser&amp;quot, &amp;quottour-lead&amp;quot, &amp;quottour-guied&amp;quot],
         default: &amp;quotuser&amp;quot, },
password: {
       type: String,
       required: [true, &amp;quotPlease provide a password&amp;quot],
       minlength: 8,
       select: false,
},
passwordConfirm: {
        type: String,
        required: [true, &amp;quotPlease confirm your password&amp;quot],
 validate: {
    validator: function (el) {
            return el ==this.password},
            message: &amp;quotconfirm password is incorrect&amp;quot, }  }
    passwordChangeAt: Date}); خب راجع به مدل بگم که 7 تا فیلده :  نام ،ایمیل ، پسورد ، تایید پسورد،نقش کاربر، عکس پروفایل و تاریخ تغییر پسورد فعلا البته بعدا باز اضافه میشه بهشون.از validator  توی ایمیل استفاده کردیم برای صحتش. و توی تایید ایمیل هم یه فانکشنی برای ولیدیت نوشتیم.خب حالا که مدل رو ساختیم میریم سراغ فایل server.js  شروع برنامه .چیز خاصی توش نیست که بخوام کدش رو بذارم فقط کانفیگ سرور و منگو دی بی و پورت و اینا همین.توی فایل app.js  هم همون چیزایی که برای شروع هست فقط روت یوزر رو ست میکنیم: app.use(&amp;quot/api/v1/users&amp;quot, userRouter);خب حالا باید دوتا فایل بسازیم اولی برای احراز یوزر کنترلر  authController و دومی برای یوزر روترuserRouter.توی فایل اول یعنی authController دوتا میدلور داریم. یکی برای ثبت نام به اسم signUp و دیگری برای ورود کاربر.فعلا خالی خالی بسازیم و اکسپورت کنیم چون توی یوزر روتر کار داریم .بعد تک تک هرکودوم رو میریم جلو.میدلور هارو که توی کنترلر ساختیم توی فایل یوزر روتر ست میکنیم.یوزر روتر:::const express = require(&amp;quotexpress&amp;quot);
const authController = require(&amp;quot../controllers/authController&amp;quot);
const router = express.Router();
router.post(&amp;quot/signup&amp;quot, authController.signUp);            ایناهاش
router.post(&amp;quot/login&amp;quot, authController.logIn);                    ایناهاش 
module.exports = router;خب حالا همه چی آمادس بریم سر وقت فایل کنترلر مون:مدل و jwt رو ایمپورت میکنیم تا ازش استفاده کنیم اسمه مدلمون هم User  هست.onst User = require(&amp;quot../model/userModel&amp;quot);
const jwt = require(&amp;quotjsonwebtoken&amp;quot);یه فانکشنی مینویسیم برای ایجاد توکن نا برامون توکن تولید کنه آیدی کاربر رو به عنوان ورودی میگیره.const signToken = (id) =&gt; {
   return jwt.sign({ id }, &amp;quotnew_secret_key_foobar&amp;quot, {
         expiresIn: &amp;quot30d&amp;quot,                                  });};سه تا مقدار میتونیم به این متد sign بدیم . یکیش آی دی که از پارامترمون گرفتیم دومی کلید سکرت که من اینجا اینو گذاشتم ولی شما اینو نذارید :))  سومی هم مدت زمان ماندگاری توکنه .که به روز و دقیقه وساعت اینا میتونید وارد کنید که من اینجا دادم 30 روز.خیلی بهتره که کلید سکرت و اینجور موارد رو توی فایل config.env وارد کنید و بعد با دات انو ازش استفاده کنید.مرحله بعدی ساخت فانکشن ثبت نام هست : کدو ببین و بعد توضیحات رو ببین : exports.signUp = async (req, res) =&gt; {
const newUser = await User.create({
 name: req.body.name,
 email: req.body.email,
  password: req.body.password,
 passwordConfirm: req.body.passwordConfirm,
 passwordChangeAt: req.body.passwordChangeAt,
  role: req.body.role,});
const token = signToken(newUser._id);
res.status(201).json({
   status: &amp;quotok&amp;quot,
    token,
    data: {
       newUser,
},});};از مدل User و متد create  استفاده میکنیم و با استفاده از req.body یه کاربر جدید میسازیم. بعد یه ثابت میسازیم به اسم توکن و فانکشن sign ور صدا میزنیم و حالا که آی دی کاربر رو داریم آی دی رو بهش میدیم.بعد هم یوزر جدید و توکن رو به آبجکت جیسون میدیم.توجه کنید که ارور هندلینگ رو پیاده سازی کنید حتما.خب حالا مرحله بعدی که داریم اینکه قبل از اینکه پسورد توی دیتابیس ذخیره بشه اونو رمزنگاری کنیم.چطوری اینکارو بکنیم؟ میتونیم از متد توی فایل مدل یوزر استفاده کنیم. و از قلاب .pre توی فایل مدل یوزرمون که اول همین مقاله هست این کد رو اضافه میکنیم : //encrypt password with bcrypt hash
userSchema.pre(&amp;quotsave&amp;quot, async function (next) {
    if (!this.isModified(&amp;quotpassword&amp;quot)) return next();
    this.password = await bcrypt.hash(this.password, 12);
this.passwordConfirm = undefined;
next();
});بی کریپت جی اس  bcryptjs  رو قبلا نصب کردیم از هوک .pre  و save  استفاده می کنیم و یک عدد کالبک فانکشن : اول بررسی میکنم ببینم که تغییری توی داکیومنت داده شده یا نه با this.isModified بعد پسوردم رو مقدار جدیدی میدم که مقدار جدیدش همون پسورده که با بی کریپت هش کردیم.در آخر هم نمیخوام که تایید پسوردم توی دیتابیس ذخیره بشه من فقط برای ولیدیت کردن احتیاجش دارم برای همین مقدارش رو آندیفاین میذارم.قبلا توی خود مدل من با یه فانکشن ولیدتش کردم. خب حالا اگر کد رو سیو کنیم میبینیم که به راحتی میره توی دیتابیس ذخیره میشه.نکته دیگه که فعلا به role یوزر کاری نداریم بعدا برای محدودیت ایجاد کردن ازش استفاده میکنیم.البته فعلا به صورت دیفالت نقش رو user تعیین میکنه.بعدا با ادمین کار میکنیم.به نظرم برای این قسمت کافیه.توی قسمت بعد لاگین یا ورود رو پیاده سازی کنیم.با توکن بیشتر کار کنیم و ببینیم داستان توکن و پسورد و لاگین چطوریه.باز نکته اینکه اگر اشتباهات املایی داشتم یا جایی از ه کسره استفاده کردم یا فانکشنی رو کال بک گفتم یا برعکس یا چیزی باشد که اصلاح شود.</description>
                <category>Amir_zpr</category>
                <author>Amir_zpr</author>
                <pubDate>Tue, 02 Aug 2022 18:30:27 +0430</pubDate>
            </item>
                    <item>
                <title>تجربه من از کار با PWA(بخش دوم)</title>
                <link>https://virgool.io/@amir_zpr/%D8%AA%D8%AC%D8%B1%D8%A8%D9%87-%D9%85%D9%86-%D8%A7%D8%B2-%DA%A9%D8%A7%D8%B1-%D8%A8%D8%A7-pwa%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-c9bsxqkzifr2</link>
                <description> عکس از سایت appinventiv.comاگر قسمت اول تجربه من با PWA رو مطالعه کرده باشید احتمالا میدونید که قراره درباره فایل serviceWorker صحبت کنم.وب اپلیکیشن ها به چند فایل ضروری احتیاج دارن که یکیش manifest  بود که توی جلسه قبل توضیح دادم راجع به اون.یکی دیگه از فایل های مهم فایل service worker  هستش که یک فایله جاوا اسکریپته.این فایل کارش اینه که وقتی کاربر برای اولین بار اپلیکیشن ما رو اجرا میکنه منابع مورد نیاز رو در حافظه پنهان ذخیره میکنه و دفعه بعدی که کاربر اپ رو اجرا میکنه قبل از اینکه اتصال به اینترنت چک بشه به کاربر جواب میده.این باعث میشه که اگر اتصال به اینترنت کاربر قطع شد بازم بتونه با اپ کارکنه.(کلماتی که من برای راحتی کار به فارسی مینویسم. سرویس ورکر :Service Worker  و کنسول : console )خب برای شروع من یک فایل میسازم به اسمه app.js که وظیفه این فایل رجیستر کردن سرویس ورکر هست. این فایل رو من داخل تمام صفحات html خودم باید لینک کنم.(که اینجا ما فعلا یک صفحه داریم).فایل app.js برای رجیستر  اولین گام اینه که ما چک کنیم که اصلا آیا مرورگر از سرویس ورکر پشتیبانی میکنه یا نه؟توی این تیکه کد من اومدم گفتم اگر سرویس ورکر داخل مرورگر وجود داشت (یعنی توی این نسخه مرورگر ازش پشتیبانی میشد) اونو برام رجیستر کن.حالا توی بخش 1 میگم سپس برام توی کنسول بگو رجیستر شده در غیر اینصورت بگو که رجیستر نشده و مشکلی وجود داره.همونطوری که توی عکس زیر میبینید توی کنسولم سرویس ورکر برام رجیستر شده.خب توی این مرحله باید رویداد های سرویس ورکر خودمون رو داخل فایل sw.jsکد کنیم.(این فایل باید حتما داخله روت اصلی پروژمون قرار گرفته باشه)اولین رویدادمون install هست که قراره سرویس ورکر رو برای ما نصب کنه.رویداد install برای نصب سرویس ورکر
خب فعلا در حد یک لاگ سادس که به ما میگه که اون به خوبی نصب شده ولی بعدا ازش استفاده های بیشتری میکنیم.(وظیفه این متد کش کردن اطلاعاتی هست که من بهش میدم و اونارو توی حافظه پنهان ذخیره میکنه.)خب همونطوری که میبینیم اون به خوبی نصب شده اگر من صفحه رو یک بار رفرش کنم دیگه پیام نصب سرویس ورکر رو نمیبینم و فقط پیام رجیستر سرویس ورکر رو میبینم.این دلیلش اینه که در حاله حاضر اون نصب هست ولی اگر من توی فایل تغییری بدم و اونو سیو کنم دوباره سرویس ورکر برای من اول رجیستر و بعد نصب میشه. اگر من بیام توی مرورگر و از صفحه ام inspect  بگیرم درونه تب اپلیکیشن و داخل serviceWorker میبینم که برام اکتیو شده .خب ما به یک متد دیگه احتیاج داریم که وظیفه ایجاد تغییرات در کش رو داره که این متد هم فعلا یک لاگ سادس.متد activateاین متد بلافاصله بعد از اینکه متد install فراخوانی شد فراخوانی میشه در اصل متد install وظیفه کش کردن مواردی رو داره که ما به اون میگیم تا برامون ذخیره کنه.متد activate وظیفه این رو داره تا در صورتی که در فایل هامون تغییراتی ایجاد کردیم ورژن جدید کش مارو جایگزین ورژن قبلی کنه تا تغییرات جدید توی سایت اعمال بشن.اگر این متد فراخوانی نشه اونوقت تغییراتی رو که توی سایت شاید بعدا اعمال کنیم رو نمیبینیم چون توی مرورگر کش شده از قبل(توسط متد install).اگر این جلسه رو بخوام توی یک عکس خلاصه کنم به شکله زیر میشه:فک کنم یکم طولانی و حوصله سر بر شد:)) توی جلسه آینده میخوام طریقه کش کردن اطلاعات رو توسط متد install بگم  و اینکه چطور از اطلاعات کش شده توسط یک متد دیگه استفاده کنیم و راجع به متد activate و خوبیاش  بیشتر براتون میگم:))</description>
                <category>Amir_zpr</category>
                <author>Amir_zpr</author>
                <pubDate>Tue, 06 Aug 2019 10:49:56 +0430</pubDate>
            </item>
                    <item>
                <title>تجربه من از شروع کار با PWA(بخش اول)</title>
                <link>https://virgool.io/JavaScript8/%D8%AA%D8%AC%D8%B1%D8%A8%D9%87-%D9%85%D9%86-%D8%A7%D8%B2-%D8%B4%D8%B1%D9%88%D8%B9-%DA%A9%D8%A7%D8%B1-%D8%A8%D8%A7-pwa-mg9oclugl0ae</link>
                <description>سلام این نوشته فقط تجربه شروع من با PWA هست و صدر در صد چون تجربه است و شروعه اولیه برای یادگیری هست شاید دارای اشکالاتی باشه.خب اصلا PWAچیه؟ Progressive Web Applicationیا PWA یک وب اپلیکیشنه که با مرورگرهای مدرن سازگاری داره البته با مرورگرهای قدیمی هم کار میکنه ولی قابلیت هاش توی مرورگر های جدید بیشتره.حالا مزایاش چیه؟ اول اینکه برای نصب به مارکت ها احتیاج نداره نصبش خیلی آسونه کاربر اونو به homeScreen گوشیش اضافه میکنه.دوم اینکه به صورت آفلاین هم میتونه کار کنه و محتوایی رو به کاربر نشون بده در صورتی که کاربر اینترنتش قطع شد از محتوای آفلاین استفاده میکنه.سوم اینکه کاملا رسپانسیو هستش و سرعت خوبی داره.خب برای شروع من یک پوشه جدید ساختم و یک پروژه htmlجدید ساختم که از materialize برای css استفاده کردم.هیچ ایده ای برای ساخت نداشتم برای همین یه پروژه ساده ایجاد کردم تا کم کم ببرمش جلو.قیافه اولیه اش هم این شکلیه زیاد چیز جالبی نیست :))خب بعد اینکه پروژه خودمونو با HTML و CSS ساختیم ( البته من برای باز بسته شدن منو سمت راست از جاوا اسکریپت استفاده کردم) چندتا کار باید انجام بدیم.اولیش اینه که شما برای اجرا گرفتن احتیاج به یک سرور مجازی دارین که از هرکدوم که باهاش راحتین میتونین استفاده کنین.اگر از vs code استفاده میکنید میتونید  (live server extension) نصب کنید.دومیش هم یک شبیه ساز برای اجرا گرفتن روی گوشی.که بازم بستگی به سلیقه خودتون داره که از کودوم استفاده میکنین من از شبیه ساز nox استفاده میکنم ولی شما اگر اندروید استودیو دارید میتونید از شبیه ساز اندروید استودیو استفاده کنید.سومین کار اینکه من دو تا فایل به پروژه ام اضافه میکنم.اولیش فایل manifest.json هستش. حالا وظیفه این فایل چیه؟یک سری ویژگی رو داخل خودش داره که نحوه نمایش وب اپلیکیشن رو کنترل میکنه.فایل manifest.jsonخب اما این ویژگی ها چیه:(انگلیسی ها رو آخر پاراگراف نوشتم برای اینکه بهم میریخت:))) خباماتعریفاینویژگیها: اسم کوتاهی هست که برای اپلیکیشن انتخاب میشه: Shortnameصفحه شروع اپلیکیشن ما یا همون صفحه خانه: Start_urlدیسپلی: حالت نمایش اپلیکیشن هست (standalone:به صورت اپلیکیشن نمایش میده و fullscreen : به صورت کامل نمایش میده  و browser :  که به صورت پیشفرض این حالت رو میگیره )تا زمانی که اپلیکیشن در حال لود شدنه از این رنگ استفاده میشه در پس زمینه : Background_colorاین هم مثله رنگ پس زمینه اس کارش فقط رنگ نوار بالایی رو مشخص میکنه : Theme_colorنوع نمایش اپلیکیشن هست که من روی عمودی گذاشتم بقیه مقدارهاشو از این لینک میتونید ببینید : Orientationاین آیکونه برنامه اس.البته برای اسپلش اسکرین برنامه هم ازین استفاده میکنه.یعنی زمانی که کاربر روی آیکون برنامه کلیک میکنه اولین صفحه ای که نمایش میده اسپلش اسکرینی هست که از همین آیکون میسازه و نمایش میده من توی یک آرایه اندازه های مختلفشو ست کردم تا خودش براساس اندازه صفحه نمایش از اونا استفاده کنه : Icons البته ویژگی های دیگه ام داره که فعلا ازشون استفاده نکردم و نمیدونم چی هستن میتونید شما به این &amp;amp;lt;لینک&amp;amp;gt; برید و مستنداتشو بخونید.خب کارمون با این فایل تموم شد فقط کافیه که بریم داخل تگ head فایل index.html خودمون و manifest  رو لینک کنیم.&lt;link href=&quot;/manifest.json&quot; rel=&quot;manifest&quot;&gt;خب اگر من به inspect برم  و در تب اپلیکیشن روی manifest کلیک کنم میبینیم که فایلم به صفحه ام اضافه شده و ویژگی های manifest رو داره میخونه.مرحله آخرم هم میام و روی گوشی اونو تست میکنم.خروجی که من داخل گوشی از اپلیکیشن ام گرفتم به شکله زیره:یک فایل ضروریه دیگه که وب اپلیکیشن بهش احتیاج داره فایل service worker هست.وظیفه این فایل جاوا اسکریپت اینه که اطلاعات مارو بگیره تا زمانی که ما آفلاین هستیم هم بتونیم از اپلیکیشن استفاده کنیم که توی پست آینده هم راجع به اون از چیزایی که فهمیدم می نویسم. خب همین .تو پست بعدی میگم که چطوری آیکون برنامه رو به هوم اسکرین گوشی منتقل کنیم تا با لمس کردنه آیکون، برنامه برامون اجرا بشه و نیازی به مرورگر نداشته باشیم.</description>
                <category>Amir_zpr</category>
                <author>Amir_zpr</author>
                <pubDate>Wed, 17 Jul 2019 14:37:58 +0430</pubDate>
            </item>
            </channel>
</rss>