{
  "title": "قراردادهای نام‌گذاری",
  "slug": "team/platform/standards/naming-conventions",
  "url": "/docs/team/platform/standards/naming-conventions",
  "frontmatter": {
    "layout": "doc",
    "title": "قراردادهای نام‌گذاری",
    "description": "استاندارد نام‌گذاری فایل‌ها، دیتابیس، متغیرهای محیط، Docker، NATS، API و کد",
    "version": "1.0.0",
    "status": "PRIVATE",
    "author": "xoxxel",
    "owner": "xoxxel",
    "created_at": "2026-06-07",
    "updated_at": "2026-06-15",
    "tags": "",
    "reviewers": ""
  },
  "sections": [
    {
      "level": 1,
      "heading": "قراردادهای نام‌گذاری",
      "content": "**Naming Conventions**\n\nنسخه 1.0 | الزامی برای همه سرویس‌ها، پکیج‌ها و مشارکت‌کنندگان\n\n---"
    },
    {
      "level": 2,
      "heading": "1. فایل‌ها و پوشه‌ها",
      "content": "| زمینه | قرارداد | مثال |\n|---|---|---|\n| پوشه‌ها | `kebab-case` | `order-service/`, `auth-service/` |\n| فایل‌های TypeScript | `kebab-case` | `order.controller.ts`, `create-order.dto.ts` |\n| فایل‌های Go | `snake_case` | `order_handler.go`, `create_order.go` |\n| فایل‌های Python | `snake_case` | `order_service.py`, `create_order.py` |\n| فایل‌های تنظیمات | `kebab-case` | `tsconfig.json`, `jest.config.ts` |\n| فایل‌های محیطی | `.env.{environment}` | `.env.development`, `.env.test` |\n| فایل‌های تست | `{name}.test/spec.{ext}` | `order.service.test.ts` |\n| فایل‌های مهاجرت | `{timestamp}_{description}` | `20240101_create_orders_table.sql` |\n\n> **نکته:** نام فایل‌ها و پوشه‌ها همیشه انگلیسی و ترجیحاً تک‌کلمه‌ای یا با خط تیره هستند.\n\n---"
    },
    {
      "level": 2,
      "heading": "2. پایگاه داده",
      "content": "| زمینه | قرارداد | مثال |\n|---|---|---|\n| نام دیتابیس | `{service}_db` | `auth_db`, `order_db`, `payment_db` |\n| نام جدول | `snake_case` جمع | `orders`, `product_versions`, `escrow_holds` |\n| نام ستون | `snake_case` | `created_at`, `seller_id`, `escrow_amount_cents` |\n| نام ایندکس | `idx_{table}_{column}` | `idx_orders_seller_id` |\n| کلید خارجی | `fk_{table}_{ref_table}` | `fk_orders_products` |\n| کلید اصلی | همیشه `id` | `id UUID PRIMARY KEY` |\n| کلید یکتا | `uq_{table}_{column}` | `uq_users_email` |\n| ستون زمان | `{action}_at` | `created_at`, `updated_at`, `deleted_at` |\n\n```sql\n-- ✅ درست\nCREATE TABLE order_snapshots (\n    id UUID PRIMARY KEY,\n    order_id UUID NOT NULL,\n    product_version_id UUID NOT NULL,\n    escrow_amount_cents BIGINT NOT NULL,\n    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n);\n\nCREATE INDEX idx_order_snapshots_order_id ON order_snapshots(order_id);\nALTER TABLE order_snapshots ADD CONSTRAINT fk_order_snapshots_orders\n    FOREIGN KEY (order_id) REFERENCES orders(id);\n\n-- ❌ غلط\nCREATE TABLE OrderSnapshot (\n    OrderID uuid,\n    productVersion uuid,\n    createdAt timestamp\n);\n```\n\n---"
    },
    {
      "level": 2,
      "heading": "3. متغیرهای محیطی (Environment Variables)",
      "content": "فرمت: `{SERVICE}_{CATEGORY}_{NAME}` — همیشه `SCREAMING_SNAKE_CASE`\n\n```bash"
    },
    {
      "level": 1,
      "heading": "✅ درست",
      "content": "AUTH_DB_URL=postgres://localhost:5432/auth_db\nAUTH_JWT_SECRET=my-secret-key\nAUTH_JWT_EXPIRY=15m\nAUTH_REFRESH_TOKEN_EXPIRY=7d\nORDER_DB_URL=postgres://localhost:5432/order_db\nORDER_REDIS_URL=redis://localhost:6379\nORDER_GUARANTEE_TIMEOUT_HOURS=24\nPAYMENT_DB_URL=postgres://localhost:5432/payment_db\nPAYMENT_ESCROW_RELEASE_DELAY_MS=5000\nNATS_URL=nats://localhost:4222\nNATS_CLUSTER_ID=nons-cluster"
    },
    {
      "level": 1,
      "heading": "❌ غلط",
      "content": "DATABASE_URL=                    # مشخص نیست متعلق به کدام سرویس است\njwtSecret=my-secret-key          # فرمت اشتباه\ndb_url=postgres://localhost:5432 # فرمت اشتباه\nPAYMENT_escrow_url=              # فرمت ترکیبی\n```\n\n**قوانین:**\n- همه متغیرها با نام سرویس شروع می‌شوند\n- از زیرخط (`_`) برای جداکننده استفاده کنید\n- مقدار پیش‌فرض در `.env.example` قرار می‌گیرد\n- هیچوقت مقدار واقعی در `.env.example` نگذارید\n\n---"
    },
    {
      "level": 2,
      "heading": "4. ایمیج‌های داکر (Docker Images)",
      "content": "فرمت: `nons/{service-name}:{version}`\n\n```\nnons/auth:1.0.0\nnons/marketplace:1.0.0\nnons/order:1.0.0\nnons/payment:1.0.0\nnons/chat:1.0.0\nnons/dispute:1.0.0\nnons/notification:1.0.0\n```\n\n**قوانین:**\n- همیشه از `nons/` به عنوان namespace استفاده کنید\n- تگ `latest` ممنوع — همیشه از نسخه دقیق استفاده کنید\n- برای پیش‌نمایش از تگ `{version}-alpha` یا `{version}-rc` استفاده کنید\n\n---"
    },
    {
      "level": 2,
      "heading": "5. موضوعات NATS (رویدادها)",
      "content": "فرمت: `nons.<domain>.<entity>.<past_action>`\n\n```\nnons.auth.user.registered\nnons.auth.user.logged_in\nnons.auth.user.password_changed\nnons.iam.user.suspended\nnons.order.created\nnons.order.fulfillment.completed\nnons.payment.escrow.held\nnons.payment.released\nnons.product.published\nnons.wallet.credit.posted\nnons.dispute.opened\nnons.dispute.resolved\nnons.review.submitted\nnons.moderation.user.flagged\nnons.zone.score_updated\nnons.boost.activated\nnons.kyc.verified\n```\n\n**قوانین:**\n- همیشه با `nons.` شروع شود\n- domain و entity به صورت مفرد (`order` نه `orders`, `user` نه `users`)\n- فعل در زمان گذشته ساده (`created` نه `create`)\n- برای چندکلمه‌ای از زیرخط استفاده کنید (`score_updated`, `password_changed`)\n- entity اختیاری است — برای domainهای ساده حذف می‌شود (`nons.order.completed`)\n- sub-entity با dot اضافه می‌شود (`nons.payment.escrow.held`)\n- حداکثر عمق: ۴ بخش بعد از `nons.`\n- domain جدید فقط با ADR جدید قابل اضافه شدن است\n\n> **نکته:** استاندارد کامل در `ADR-EVENT-001` ثبت شده است. این بخش خلاصه‌ای از آن تصمیم است.\n\n---"
    },
    {
      "level": 2,
      "heading": "6. مسیرهای API",
      "content": "فرمت: `/v{n}/{resource}/{id?}/{sub-resource?}`\n\n```\nGET    /v1/products\nGET    /v1/products/:id\nPOST   /v1/products\nPATCH  /v1/products/:id\nDELETE /v1/products/:id\nGET    /v1/orders/:id\nPOST   /v1/orders\nPATCH  /v1/orders/:id/status\nPOST   /v1/disputes\nGET    /v1/disputes/:id\nPOST   /v1/disputes/:id/verdict\n```\n\n**قوانین:**\n| قانون | ✅ درست | ❌ غلط |\n|---|---|---|\n| اسم جمع | `/products` | `/product` |\n| خط تیره برای چندکلمه‌ای | `/product-versions` | `/productVersions` |\n| بدون فعل | `/orders/:id/status` | `/orders/:id/updateStatus` |\n| زیر-منبع برای اقدامات خاص | `/orders/:id/dispute` | `/orders/:id/createDispute` |\n| نسخه‌بندی | `/v1/products` | `/api/products` |\n\n---"
    },
    {
      "level": 2,
      "heading": "7. کدهای خطا (Error Codes)",
      "content": "فرمت: `SCREAMING_SNAKE_CASE` — Platform Error Codes از `nons-api/contracts/errors.proto`، Domain Error Codes از هر سرویس\n\n```\nORDER_NOT_FOUND\nORDER_INVALID_STATUS\nORDER_PAYMENT_TIMEOUT\nPAYMENT_ESCROW_LOCK_FAILED\nPAYMENT_INSUFFICIENT_BALANCE\nAUTH_TOKEN_EXPIRED\nAUTH_INVALID_CREDENTIALS\nUSER_NOT_FOUND\nUSER_ALREADY_EXISTS\nPRODUCT_NOT_FOUND\nPRODUCT_INSUFFICIENT_STOCK\nDISPUTE_ALREADY_RESOLVED\nRATE_LIMIT_EXCEEDED\nVALIDATION_ERROR\nINTERNAL_ERROR\n```\n\n---"
    },
    {
      "level": 2,
      "heading": "8. ساختار کلی",
      "content": "| موجودیت | قرارداد | مثال |\n|---|---|---|\n| پکیج / ماجول | `kebab-case` | `@nons/contracts`, `@nons/events` |\n| فایل Proto | `snake_case` | `envelope.proto`, `registry.proto` |\n| Proto package name | `reverse_domain.team.component` | `nons.platform.contracts.v1` |\n| کلاس | `PascalCase` | `OrderService`, `PaymentGateway` |\n| تابع | `camelCase` | `createOrder()`, `getUserById()` |\n| متغیر | `camelCase` | `orderId`, `sellerWallet` |\n| ثابت | `SCREAMING_SNAKE_CASE` | `MAX_RETRY_COUNT`, `DEFAULT_TIMEOUT` |\n| اینترفیس TypeScript | `PascalCase` | `Order`, `UserPayload` |\n| تایپ TypeScript | `PascalCase` | `OrderStatus`, `ApiResponse` |\n| enum | `PascalCase` با مقادیر `snake_case` | `OrderStatus.PENDING` |\n| فایل تست | `{name}.test.{ext}` | `order.service.test.ts` |"
    }
  ]
}