You are a senior NestJS architect. Generate a production-ready data layer for an eCommerce backend using NestJS v10 + TypeORM + MySQL 8+.

Global requirements

Use TypeORM with MySQL.

synchronize: false (mandatory).a

Use DataSource API and place migrations under src/migrations.

Provide entities (.entity.ts) for each table with proper relations, indexes, and column types tuned for MySQL.

Generate an initial migration creating all tables, FKs, unique constraints, indexes, and enums (as MySQL check-enums or varchar with union type).

All timestamps: created_at, updated_at as datetime(6) with onUpdate for updated_at. Use soft delete where specified.

for dto validation will use class validator and transforma

Use snake_case for table/column names; add @Index() where helpful.

IDs: use @PrimaryGeneratedColumn('uuid') or 'increment' where appropriate (you may choose uuid for external-facing objects; increment ok for junctions).

Set appropriate cascade and onDelete behaviors:

Images/variants → ON DELETE CASCADE.

User → addresses/tokens/reviews/activity → ON DELETE CASCADE.

Product → images/variants/product_categories/product_tags/related_products/reviews → ON DELETE CASCADE.

Numeric money fields: int in cents (e.g., price_cents int unsigned).

Text HTML: longtext for big descriptions; short strings: varchar(255).

JSON: use json type for MySQL.

Add seed placeholders (optional).

Environment & Config (just outline)

.env: DB_HOST, DB_PORT, DB_USER, DB_PASS, DB_NAME

credential:
DB_HOST:localhost
DB_PORT: default
DB_USER:root
DB_PASS:123456
DB_NAME:grocery

TypeOrmModule.forRootAsync(...) using ConfigService.

data-source.ts must export a DataSource using same env; migrations: ['src/migrations/*.ts'].

and write well api documentation by swagger for all modules

Entities to implement (exactly these columns)
🧑‍💻 Users — users

id, name, email (unique), password_hash,

role enum: customer | admin | seller,

avatar_url, phone, is_active (bool),

created_at, updated_at.

🔐 Refresh Tokens — refresh_tokens

id, user_id (FK → users), token (unique),

expires_at (datetime), revoked (bool), created_at.

🛍️ Products — products

id, title, slug (unique), subtitle, description_html,

product_code (SKU, unique), brand_id (nullable FK → brands if present; else keep nullable),

status enum: active | draft | archived,

visibility enum: public | private,

price_cents, compare_at_price_cents (nullable), currency (char(3)),

stock_qty, low_stock_threshold (nullable), allow_backorder (bool),

shipping_note (text), return_policy_note (text), warranty_months (int, nullable),

weight_g, length_mm, width_mm, height_mm (nullable ints),

country_of_origin (varchar(64), nullable), hs_code (varchar(32), nullable),

cover_image_url, thumbnail_url, media_count (int default 0),

tags_text (text, nullable), rating_avg (decimal(3,1) default 0), review_count (int default 0), sold_count (int default 0), badge_label (varchar(32), nullable),

publish_at, start_sale_at, end_sale_at (nullable datetime),

seo_title (varchar(255), nullable), seo_description (varchar(300), nullable),

meta_json (json),

created_by (nullable FK → users), updated_by (nullable FK → users),

created_at, updated_at, deleted_at (soft delete).

🎨 Product Variants — product_variants

id, product_id (FK → products), sku (unique), barcode (nullable),

option_values (json) e.g. { "color": "Blue", "size": "42" },

price_cents, compare_at_price_cents (nullable), currency,

cost_cents (nullable), stock_qty, allow_backorder (bool),

weight_g, length_mm, width_mm, height_mm (nullable),

image_url (nullable), status enum: active | inactive,

created_at, updated_at.

⚙️ Product Options — product_options

id, product_id (FK → products), name (e.g., Color/Size), position (int).

⚙️ Product Option Values — product_option_values

id, product_option_id (FK → product_options), value, hex_code (nullable), position.

🖼️ Product Images — product_images

id, product_id (FK → products), variant_id (nullable FK → product_variants),

url, alt_text (nullable), position (int).

🧾 Categories — categories

id, name, slug (unique), description (text, nullable),

parent_id (nullable self-FK), thumbnail_url (nullable),

is_active (bool), created_at, updated_at.

Junction: Product ↔ Category — product_categories

product_id (FK), category_id (FK), PK on both.

🏷️ Tags — tags

id, name, slug (unique).

Junction: Product ↔ Tag — product_tags

product_id (FK), tag_id (FK), PK on both.

🏠 Addresses — addresses

id, user_id (FK → users), label (varchar(64)),

full_name, phone,

address_line1, address_line2 (nullable), city, state, postal_code, country,

is_default_shipping (bool), is_default_billing (bool),

created_at, updated_at.

💳 Payments — payments

id, order_id (FK → orders), provider (varchar(32), e.g., stripe, paypal),

transaction_id (unique), amount_cents, currency,

status enum: pending | succeeded | failed | refunded,

payment_method (varchar(64)), payload_json (json),

created_at, updated_at.

⭐ Product Reviews — product_reviews

id, product_id (FK), user_id (FK),

rating (tinyint unsigned 1–5), title (nullable), comment (text),

status enum: pending | approved | rejected,

created_at.

🔁 Related Products — related_products
zz
product_id (FK → products), related_product_id (FK → products), position (int).

Composite PK on (product_id, related_product_id).

⚙️ Activity Logs (optional) — activity_logs

id, user_id (FK → users, nullable),

action (varchar(64)), target_type (varchar(64)), target_id (varchar(64)),

meta_json (json), ip_address (varchar(64), nullable),

created_at.

Type & Index guidance (MySQL)

Email, slug, SKU: @Index({ unique: true }).

Search helpers: add non-unique indexes on (title), (status), (product_id), (category_id), (tag_id), (user_id), (order_id).

Use @Column({ type: 'json' }) for meta_json, option_values, payload_json.

Money: @Column({ type: 'int', unsigned: true }) for *_cents.

Soft delete on products: @DeleteDateColumn({ type: 'datetime', nullable: true }).

Deliverables

All Entity classes as described above (folders per domain).

A single initial migration that creates every table, FKs, indexes, uniques, and enums for MySQL 8+.

data-source.ts configured for MySQL and pointing to src/migrations/*.ts.

and must be check hole module type error and others error

package.json scripts:

{
  "scripts": {
    "typeorm:generate": "ts-node -r tsconfig-paths/register src/database/data-source.ts migration:generate src/migrations/InitMySQL",
    "typeorm:run": "ts-node -r tsconfig-paths/register src/database/data-source.ts migration:run",
    "typeorm:revert": "ts-node -r tsconfig-paths/register src/database/data-source.ts migration:revert"
  }
}
