Compare commits

...

11 Commits

Author SHA1 Message Date
parsa aghaei
897b4d61ec fix(docker): configure official Iran TIC national DNS servers (217.218.127.127)
All checks were successful
Deploy Canina / deploy (push) Successful in 42s
2026-08-16 15:50:51 +03:30
parsa aghaei
45359eb2fa revert(docker): remove external DNS to use host internal Iran DNS
All checks were successful
Deploy Canina / deploy (push) Successful in 50s
2026-08-16 15:40:55 +03:30
parsa aghaei
e1f471c978 fix(auth): normalize mobile digits and whitespace in login, register, and admin user creation
All checks were successful
Deploy Canina / deploy (push) Successful in 1m43s
2026-08-16 15:31:28 +03:30
parsa aghaei
2984b9f637 fix(settings): add validated SmsLogQueryDto to allow pagination and filter queries on sms logs
All checks were successful
Deploy Canina / deploy (push) Successful in 1m42s
2026-08-16 15:22:10 +03:30
parsa aghaei
e82d2b88c1 fix(docker): configure public DNS servers in compose to resolve external API hostnames
All checks were successful
Deploy Canina / deploy (push) Successful in 50s
2026-08-16 15:19:28 +03:30
parsa aghaei
ad854a717b feat(admin): implement complete User CRUD with create, edit, delete, and direct wallet adjust capabilities
All checks were successful
Deploy Canina / deploy (push) Successful in 1m53s
2026-08-16 15:16:47 +03:30
parsa aghaei
6ae35efb3e fix(filter): preserve custom Persian error messages in HttpExceptionFilter
All checks were successful
Deploy Canina / deploy (push) Successful in 1m43s
2026-08-16 15:12:18 +03:30
parsa aghaei
0c32985ce2 fix(auth): centralize JWT secret with registerAsync to ensure consistent signing and verification 2026-08-16 15:11:05 +03:30
parsa aghaei
1a21c4c642 fix(auth): add refresh & logout endpoints and ensure UsersService.findById handles fallback admin
All checks were successful
Deploy Canina / deploy (push) Successful in 1m53s
2026-08-16 15:07:07 +03:30
parsa aghaei
28fc660f69 chore(graphify): update knowledge graph artifacts
All checks were successful
Deploy Canina / deploy (push) Successful in 1m41s
2026-08-16 15:01:26 +03:30
parsa aghaei
9b7a9e363d fix(auth): add reliable fallback for JWT secrets to prevent login signing crashes in production
Some checks failed
Deploy Canina / deploy (push) Has been cancelled
2026-08-16 14:59:44 +03:30
37 changed files with 12230 additions and 9751 deletions

1
backend/scripts/generate-openapi.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,68 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@nestjs/core");
const app_module_1 = require("../src/app.module");
const swagger_1 = require("@nestjs/swagger");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const yaml = __importStar(require("js-yaml"));
async function generateOpenApi() {
process.env.JWT_ACCESS_SECRET =
process.env.JWT_ACCESS_SECRET ||
'test_access_secret_32_characters_minimum_entropy';
process.env.JWT_REFRESH_SECRET =
process.env.JWT_REFRESH_SECRET ||
'test_refresh_secret_32_characters_minimum_entropy';
const app = await core_1.NestFactory.create(app_module_1.AppModule, { logger: false });
app.setGlobalPrefix('api');
const config = new swagger_1.DocumentBuilder()
.setTitle('Canino Iran API')
.setDescription('API Documentation for Canino Iran Pet Health & Supplement Platform')
.setVersion('1.0.0')
.addBearerAuth()
.build();
const document = swagger_1.SwaggerModule.createDocument(app, config);
const yamlContent = yaml.dump(document, { noRefs: true, lineWidth: -1 });
const rootSwaggerPath = path.resolve(__dirname, '../../swagger.yml');
fs.writeFileSync(rootSwaggerPath, yamlContent, 'utf8');
console.log(`OpenAPI documentation successfully synchronized to ${rootSwaggerPath}`);
await app.close();
}
generateOpenApi().catch((err) => {
console.error('Error generating OpenAPI spec:', err);
process.exit(1);
});
//# sourceMappingURL=generate-openapi.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"generate-openapi.js","sourceRoot":"","sources":["generate-openapi.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAA2C;AAC3C,kDAA8C;AAC9C,6CAAiE;AACjE,uCAAyB;AACzB,2CAA6B;AAC7B,8CAAgC;AAEhC,KAAK,UAAU,eAAe;IAC5B,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAC3B,OAAO,CAAC,GAAG,CAAC,iBAAiB;YAC7B,kDAAkD,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,kBAAkB;QAC5B,OAAO,CAAC,GAAG,CAAC,kBAAkB;YAC9B,mDAAmD,CAAC;IAEtD,MAAM,GAAG,GAAG,MAAM,kBAAW,CAAC,MAAM,CAAC,sBAAS,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAEnE,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAE3B,MAAM,MAAM,GAAG,IAAI,yBAAe,EAAE;SACjC,QAAQ,CAAC,iBAAiB,CAAC;SAC3B,cAAc,CACb,oEAAoE,CACrE;SACA,UAAU,CAAC,OAAO,CAAC;SACnB,aAAa,EAAE;SACf,KAAK,EAAE,CAAC;IAEX,MAAM,QAAQ,GAAG,uBAAa,CAAC,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAE3D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAEzE,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IACrE,EAAE,CAAC,aAAa,CAAC,eAAe,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IAEvD,OAAO,CAAC,GAAG,CACT,sDAAsD,eAAe,EAAE,CACxE,CAAC;IAEF,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;AACpB,CAAC;AAED,eAAe,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC9B,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,GAAG,CAAC,CAAC;IACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}

View File

@ -19,6 +19,8 @@ import {
ApiQuery, ApiQuery,
} from '@nestjs/swagger'; } from '@nestjs/swagger';
import { CreateUserDto, UpdateUserDto } from './dto/user.dto';
@ApiTags('Admin - مدیریت سیستم') @ApiTags('Admin - مدیریت سیستم')
@ApiBearerAuth() @ApiBearerAuth()
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)
@ -43,6 +45,17 @@ export class AdminController {
return { success: true, ...result }; return { success: true, ...result };
} }
@Post('users')
@ApiOperation({ summary: 'ایجاد کاربر جدید توسط ادمین' })
async createUser(@Body() dto: CreateUserDto) {
const user = await this.adminService.createUser(dto);
return {
success: true,
message: 'کاربر جدید با موفقیت ایجاد شد',
data: user,
};
}
@Get('users/:id') @Get('users/:id')
@ApiOperation({ summary: 'جزئیات کاربر' }) @ApiOperation({ summary: 'جزئیات کاربر' })
async getUserDetails(@Param('id') id: string) { async getUserDetails(@Param('id') id: string) {
@ -50,6 +63,30 @@ export class AdminController {
return { success: true, data }; return { success: true, data };
} }
@Put('users/:id')
@ApiOperation({ summary: 'ویرایش مشخصات کامل کاربر' })
async updateUser(
@Param('id') id: string,
@Body() dto: UpdateUserDto,
) {
const user = await this.adminService.updateUser(id, dto);
return {
success: true,
message: 'اطلاعات کاربر با موفقیت ویرایش شد',
data: user,
};
}
@Delete('users/:id')
@ApiOperation({ summary: 'حذف کاربر و داده‌های مرتبط' })
async deleteUser(@Param('id') id: string) {
await this.adminService.deleteUser(id);
return {
success: true,
message: 'کاربر با موفقیت از سیستم حذف شد',
};
}
@Put('users/:id/role') @Put('users/:id/role')
@ApiOperation({ summary: 'تغییر نقش کاربر' }) @ApiOperation({ summary: 'تغییر نقش کاربر' })
async updateUserRole(@Param('id') id: string, @Body('role') role: string) { async updateUserRole(@Param('id') id: string, @Body('role') role: string) {

View File

@ -1,7 +1,15 @@
import { Injectable, HttpException, NotFoundException } from '@nestjs/common'; import {
Injectable,
HttpException,
NotFoundException,
BadRequestException,
} from '@nestjs/common';
import { Prisma } from '@prisma/client'; import { Prisma } from '@prisma/client';
import { PrismaService } from '../prisma/prisma.service'; import { PrismaService } from '../prisma/prisma.service';
import { RedisService } from '../redis/redis.service'; import { RedisService } from '../redis/redis.service';
import * as bcrypt from 'bcryptjs';
import { CreateUserDto, UpdateUserDto } from './dto/user.dto';
import { normalizeMobile } from '../common/utils/phone.utils';
export class PaginationQuery { export class PaginationQuery {
page?: number | string; page?: number | string;
@ -169,6 +177,92 @@ export class AdminService {
return user; return user;
} }
async createUser(dto: CreateUserDto) {
const mobile = normalizeMobile(dto.mobile);
const existingMobile = await this.prisma.user.findUnique({
where: { mobile },
});
if (existingMobile) {
throw new BadRequestException('کاربری با این شماره موبایل قبلاً در سیستم ثبت شده است');
}
if (dto.email) {
const existingEmail = await this.prisma.user.findUnique({
where: { email: dto.email.trim().toLowerCase() },
});
if (existingEmail) {
throw new BadRequestException('کاربری با این آدرس ایمیل قبلاً در سیستم ثبت شده است');
}
}
const passwordToHash = dto.password?.trim();
const hashedPassword = passwordToHash ? await bcrypt.hash(passwordToHash, 10) : '';
return this.prisma.user.create({
data: {
firstName: dto.firstName.trim(),
lastName: dto.lastName.trim(),
mobile,
email: dto.email ? dto.email.trim().toLowerCase() : null,
password: hashedPassword,
role: dto.role || 'User_PetOwner',
walletBalance:
dto.walletBalance !== undefined
? new Prisma.Decimal(dto.walletBalance)
: new Prisma.Decimal(0),
},
});
}
async updateUser(id: string, dto: UpdateUserDto) {
if (id === '12345678-1234-1234-1234-123456789012') {
throw new BadRequestException('امکان ویرایش حساب ادمین پیش‌فرض وجود ندارد');
}
const user = await this.prisma.user.findUnique({ where: { id } });
if (!user) {
throw new NotFoundException(`کاربری با شناسه ${id} یافت نشد`);
}
const normalizedMobile = dto.mobile ? normalizeMobile(dto.mobile) : undefined;
if (normalizedMobile && normalizedMobile !== user.mobile) {
const existingMobile = await this.prisma.user.findUnique({
where: { mobile: normalizedMobile },
});
if (existingMobile && existingMobile.id !== id) {
throw new BadRequestException('این شماره موبایل متعلق به کاربر دیگری است');
}
}
const normalizedEmail = dto.email ? dto.email.trim().toLowerCase() : undefined;
if (normalizedEmail && normalizedEmail !== user.email) {
const existingEmail = await this.prisma.user.findUnique({
where: { email: normalizedEmail },
});
if (existingEmail && existingEmail.id !== id) {
throw new BadRequestException('این آدرس ایمیل متعلق به کاربر دیگری است');
}
}
const updateData: Prisma.UserUpdateInput = {};
if (dto.firstName !== undefined) updateData.firstName = dto.firstName.trim();
if (dto.lastName !== undefined) updateData.lastName = dto.lastName.trim();
if (normalizedMobile !== undefined) updateData.mobile = normalizedMobile;
if (normalizedEmail !== undefined) updateData.email = normalizedEmail || null;
if (dto.role !== undefined) updateData.role = dto.role;
if (dto.walletBalance !== undefined) {
updateData.walletBalance = new Prisma.Decimal(dto.walletBalance);
}
if (dto.password && dto.password.trim().length >= 6) {
updateData.password = await bcrypt.hash(dto.password.trim(), 10);
}
return this.prisma.user.update({
where: { id },
data: updateData,
});
}
async updateUserRole(id: string, role: string) { async updateUserRole(id: string, role: string) {
return this.prisma.user.update({ return this.prisma.user.update({
where: { id }, where: { id },
@ -176,6 +270,29 @@ export class AdminService {
}); });
} }
async deleteUser(id: string) {
if (id === '12345678-1234-1234-1234-123456789012') {
throw new BadRequestException('امکان حذف حساب ادمین پیش‌فرض وجود ندارد');
}
const user = await this.prisma.user.findUnique({ where: { id } });
if (!user) {
throw new NotFoundException(`کاربری با شناسه ${id} یافت نشد`);
}
return this.prisma.$transaction(async (tx) => {
await tx.userAddress.deleteMany({ where: { userId: id } });
await tx.walletTransaction.deleteMany({ where: { userId: id } });
await tx.pet.deleteMany({ where: { userId: id } });
await tx.prescription.deleteMany({ where: { userId: id } });
await tx.paymentTransaction.deleteMany({ where: { userId: id } });
await tx.partnerAccount.deleteMany({ where: { userId: id } });
await tx.blog.deleteMany({ where: { authorId: id } });
await tx.order.deleteMany({ where: { userId: id } });
return tx.user.delete({ where: { id } });
});
}
async getProducts(query: PaginationQuery = {}) { async getProducts(query: PaginationQuery = {}) {
try { try {
const page = Number(query.page) || 1; const page = Number(query.page) || 1;

View File

@ -0,0 +1,78 @@
import { IsNotEmpty, IsString, IsOptional, IsEmail, MinLength, IsNumber } from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class CreateUserDto {
@ApiProperty({ description: 'نام کاربر', example: 'علی' })
@IsNotEmpty({ message: 'نام الزامی است' })
@IsString()
firstName!: string;
@ApiProperty({ description: 'نام خانوادگی کاربر', example: 'محمدی' })
@IsNotEmpty({ message: 'نام خانوادگی الزامی است' })
@IsString()
lastName!: string;
@ApiProperty({ description: 'شماره موبایل', example: '09123456789' })
@IsNotEmpty({ message: 'شماره موبایل الزامی است' })
@IsString()
mobile!: string;
@ApiPropertyOptional({ description: 'ایمیل کاربر', example: 'ali@example.com' })
@IsOptional()
@IsEmail({}, { message: 'فرمت ایمیل نامعتبر است' })
email?: string;
@ApiPropertyOptional({ description: 'رمز عبور', example: 'Password123' })
@IsOptional()
@IsString()
@MinLength(6, { message: 'رمز عبور باید حداقل ۶ کاراکتر باشد' })
password?: string;
@ApiPropertyOptional({ description: 'نقش کاربر', example: 'User_PetOwner' })
@IsOptional()
@IsString()
role?: string;
@ApiPropertyOptional({ description: 'موجودی اولیه کیف پول', example: 0 })
@IsOptional()
@IsNumber({}, { message: 'موجودی کیف پول باید عدد باشد' })
walletBalance?: number;
}
export class UpdateUserDto {
@ApiPropertyOptional({ description: 'نام کاربر', example: 'علی' })
@IsOptional()
@IsString()
firstName?: string;
@ApiPropertyOptional({ description: 'نام خانوادگی کاربر', example: 'محمدی' })
@IsOptional()
@IsString()
lastName?: string;
@ApiPropertyOptional({ description: 'شماره موبایل', example: '09123456789' })
@IsOptional()
@IsString()
mobile?: string;
@ApiPropertyOptional({ description: 'ایمیل کاربر', example: 'ali@example.com' })
@IsOptional()
@IsEmail({}, { message: 'فرمت ایمیل نامعتبر است' })
email?: string;
@ApiPropertyOptional({ description: 'رمز عبور جدید', example: 'NewPassword123' })
@IsOptional()
@IsString()
@MinLength(6, { message: 'رمز عبور باید حداقل ۶ کاراکتر باشد' })
password?: string;
@ApiPropertyOptional({ description: 'نقش کاربر', example: 'User_PetOwner' })
@IsOptional()
@IsString()
role?: string;
@ApiPropertyOptional({ description: 'موجودی کیف پول', example: 500000 })
@IsOptional()
@IsNumber({}, { message: 'موجودی کیف پول باید عدد باشد' })
walletBalance?: number;
}

View File

@ -0,0 +1,14 @@
export const DEFAULT_JWT_SECRET =
'canina_jwt_fallback_access_secret_32_characters_minimum_len_2026';
export const DEFAULT_JWT_REFRESH_SECRET =
'canina_jwt_fallback_refresh_secret_32_characters_minimum_len_2026';
export const getJwtSecret = (): string =>
process.env.JWT_ACCESS_SECRET ||
process.env.JWT_SECRET ||
DEFAULT_JWT_SECRET;
export const getJwtRefreshSecret = (): string =>
process.env.JWT_REFRESH_SECRET ||
DEFAULT_JWT_REFRESH_SECRET;

View File

@ -1,15 +1,17 @@
import { Controller, Post, Body, HttpCode, HttpStatus } from '@nestjs/common'; import { Controller, Post, Body, HttpCode, HttpStatus, UseGuards, Req } from '@nestjs/common';
import { AuthService } from './auth.service'; import { AuthService } from './auth.service';
import { SendOtpDto } from './dto/send-otp.dto'; import { SendOtpDto } from './dto/send-otp.dto';
import { VerifyOtpDto } from './dto/verify-otp.dto'; import { VerifyOtpDto } from './dto/verify-otp.dto';
import { RegisterDto } from './dto/register.dto'; import { RegisterDto } from './dto/register.dto';
import { LoginDto } from './dto/login.dto'; import { LoginDto } from './dto/login.dto';
import { JwtAuthGuard } from './jwt-auth.guard';
import { import {
ApiTags, ApiTags,
ApiOperation, ApiOperation,
ApiResponse, ApiResponse,
ApiOkResponse, ApiOkResponse,
ApiBadRequestResponse, ApiBadRequestResponse,
ApiBearerAuth,
} from '@nestjs/swagger'; } from '@nestjs/swagger';
import { AdminLoginDto } from './dto/admin-login.dto'; import { AdminLoginDto } from './dto/admin-login.dto';
@ -43,59 +45,17 @@ export class AuthController {
}, },
}, },
}) })
@ApiBadRequestResponse({ @ApiBadRequestResponse({ description: 'شماره تلفن همراه نامعتبر است' })
description: 'فرمت شماره تلفن همراه نامعتبر است',
schema: {
example: {
success: false,
message: 'شماره موبایل نامعتبر است',
code: 'BAD_REQUEST',
details: {
message: ['شماره موبایل نامعتبر است'],
},
},
},
})
sendOtp(@Body() sendOtpDto: SendOtpDto) { sendOtp(@Body() sendOtpDto: SendOtpDto) {
return this.authService.sendOtp(sendOtpDto); return this.authService.sendOtp(sendOtpDto);
} }
@Post('verify-otp') @Post('verify-otp')
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'تایید کد پیامکی و ورود/ثبت‌نام کاربر' }) @ApiOperation({ summary: 'تایید کد پیامکی و ورود به سیستم' })
@ApiOkResponse({ @ApiOkResponse({ description: 'کد تایید شد و ورود با موفقیت انجام گردید' })
description: 'ورود موفق به همراه توکن دسترسی JWT و اطلاعات کاربر',
schema: {
example: {
success: true,
data: {
user: {
id: 'd8c4e428-cd2f-4c55-bfa3-dfa312bb6480',
firstName: 'کاربر',
lastName: 'جدید',
email: '09123456789@temp.local',
mobile: '09123456789',
role: 'User_PetOwner',
walletBalance: '0.00',
charityDonationTotal: '0.00',
createdAt: '2026-05-26T15:20:00.000Z',
updatedAt: '2026-05-26T15:20:00.000Z',
},
accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
},
},
},
})
@ApiBadRequestResponse({ @ApiBadRequestResponse({
description: 'کد تایید اشتباه یا منقضی شده است', description: 'کد تایید اشتباه است یا منقضی شده است',
schema: {
example: {
success: false,
message: 'کد تایید اشتباه است',
code: 'OTP_INVALID',
details: {},
},
},
}) })
verifyOtp(@Body() verifyOtpDto: VerifyOtpDto) { verifyOtp(@Body() verifyOtpDto: VerifyOtpDto) {
return this.authService.verifyOtp(verifyOtpDto); return this.authService.verifyOtp(verifyOtpDto);
@ -129,4 +89,22 @@ export class AuthController {
adminLogin(@Body() body: AdminLoginDto) { adminLogin(@Body() body: AdminLoginDto) {
return this.authService.adminLogin(body); return this.authService.adminLogin(body);
} }
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Post('refresh')
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'تازه‌سازی توکن دسترسی (Refresh Token)' })
@ApiOkResponse({ description: 'توکن جدید با موفقیت صادر شد' })
refresh(@Req() req: { user: { id: string; email?: string; role?: string; mobile?: string } }) {
return this.authService.refresh(req.user);
}
@Post('logout')
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'خروج از حساب کاربری' })
@ApiOkResponse({ description: 'با موفقیت خارج شدید' })
logout() {
return { success: true, message: 'با موفقیت خارج شدید' };
}
} }

View File

@ -5,18 +5,22 @@ import { AuthService } from './auth.service';
import { AuthController } from './auth.controller'; import { AuthController } from './auth.controller';
import { JwtStrategy } from './jwt.strategy'; import { JwtStrategy } from './jwt.strategy';
import { UsersModule } from '../users/users.module'; import { UsersModule } from '../users/users.module';
import { getJwtSecret } from './auth.constants';
@Module({ @Module({
imports: [ imports: [
UsersModule, UsersModule,
PassportModule, PassportModule,
JwtModule.register({ JwtModule.registerAsync({
secret: process.env.JWT_ACCESS_SECRET, useFactory: () => ({
secret: getJwtSecret(),
signOptions: { expiresIn: '7d' }, signOptions: { expiresIn: '7d' },
}), }),
}),
], ],
controllers: [AuthController], controllers: [AuthController],
providers: [AuthService, JwtStrategy], providers: [AuthService, JwtStrategy],
exports: [AuthService], exports: [AuthService],
}) })
export class AuthModule {} export class AuthModule {}

View File

@ -7,6 +7,7 @@ import { VerifyOtpDto } from './dto/verify-otp.dto';
import { SmsService } from '../common/services/sms.service'; import { SmsService } from '../common/services/sms.service';
import * as bcrypt from 'bcryptjs'; import * as bcrypt from 'bcryptjs';
import * as crypto from 'crypto'; import * as crypto from 'crypto';
import { normalizeMobile } from '../common/utils/phone.utils';
export class RegisterInput { export class RegisterInput {
firstName!: string; firstName!: string;
@ -36,7 +37,7 @@ export class AuthService {
) {} ) {}
async sendOtp(sendOtpDto: SendOtpDto) { async sendOtp(sendOtpDto: SendOtpDto) {
const { phoneNumber } = sendOtpDto; const phoneNumber = normalizeMobile(sendOtpDto.phoneNumber);
const code = crypto.randomInt(10000, 100000).toString(); const code = crypto.randomInt(10000, 100000).toString();
@ -62,7 +63,8 @@ export class AuthService {
} }
async verifyOtp(verifyOtpDto: VerifyOtpDto) { async verifyOtp(verifyOtpDto: VerifyOtpDto) {
const { phoneNumber, code } = verifyOtpDto; const phoneNumber = normalizeMobile(verifyOtpDto.phoneNumber);
const code = String(verifyOtpDto.code).trim();
const savedCode = await this.redisService.get(`otp:${phoneNumber}`); const savedCode = await this.redisService.get(`otp:${phoneNumber}`);
@ -102,7 +104,11 @@ export class AuthService {
} }
async register(registerDto: RegisterInput) { async register(registerDto: RegisterInput) {
const { firstName, lastName, email, mobile, password } = registerDto; const firstName = registerDto.firstName.trim();
const lastName = registerDto.lastName.trim();
const mobile = normalizeMobile(registerDto.mobile);
const email = registerDto.email ? registerDto.email.trim().toLowerCase() : null;
const password = registerDto.password?.trim();
const existingUser = await this.prisma.user.findUnique({ const existingUser = await this.prisma.user.findUnique({
where: { mobile }, where: { mobile },
@ -132,7 +138,7 @@ export class AuthService {
data: { data: {
firstName, firstName,
lastName, lastName,
email: email || null, email,
mobile, mobile,
password: hashedPassword, password: hashedPassword,
}, },
@ -151,7 +157,8 @@ export class AuthService {
} }
async login(loginDto: LoginInput) { async login(loginDto: LoginInput) {
const { mobile, password } = loginDto; const mobile = normalizeMobile(loginDto.mobile);
const password = loginDto.password ? loginDto.password.trim() : '';
const user = await this.prisma.user.findUnique({ where: { mobile } }); const user = await this.prisma.user.findUnique({ where: { mobile } });
if (!user) { if (!user) {
@ -245,4 +252,21 @@ export class AuthService {
error: 'INVALID_ADMIN_CREDENTIALS', error: 'INVALID_ADMIN_CREDENTIALS',
}); });
} }
async refresh(user: { id: string; email?: string; role?: string; mobile?: string }) {
const payload = {
sub: user.id,
email: user.email,
role: user.role,
phoneNumber: user.mobile,
};
return {
success: true,
data: {
user,
accessToken: this.jwtService.sign(payload),
},
};
}
} }

View File

@ -2,6 +2,7 @@ import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport'; import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common'; import { Injectable, UnauthorizedException } from '@nestjs/common';
import { UsersService } from '../users/users.service'; import { UsersService } from '../users/users.service';
import { getJwtSecret } from './auth.constants';
export interface JwtPayload { export interface JwtPayload {
sub: string; sub: string;
@ -16,7 +17,7 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
super({ super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false, ignoreExpiration: false,
secretOrKey: process.env.JWT_ACCESS_SECRET!, secretOrKey: getJwtSecret(),
}); });
} }

View File

@ -92,19 +92,19 @@ export class CustomHttpExceptionFilter implements ExceptionFilter {
if (!msg) return 'خطای نامشخص رخ داده است.'; if (!msg) return 'خطای نامشخص رخ داده است.';
const lower = msg.toLowerCase(); const lower = msg.toLowerCase();
if (lower.includes('unauthorized') || status === 401) { if (lower === 'unauthorized' || msg === 'Unauthorized') {
return 'شما دسترسی لازم برای این عملیات را ندارید. لطفاً ابتدا وارد حساب کاربری خود شوید.'; return 'شما دسترسی لازم برای این عملیات را ندارید. لطفاً ابتدا وارد حساب کاربری خود شوید.';
} }
if (lower.includes('forbidden') || status === 403) { if (lower === 'forbidden' || msg === 'Forbidden') {
return 'دسترسی شما به این بخش یا منبع محدود شده است.'; return 'دسترسی شما به این بخش یا منبع محدود شده است.';
} }
if (lower.includes('not found') || status === 404) { if (lower === 'not found' || msg === 'Not Found') {
return 'مورد یا صفحه درخواستی یافت نشد.'; return 'مورد یا صفحه درخواستی یافت نشد.';
} }
if (status === 400) { if (lower === 'bad request' || msg === 'Bad Request') {
return 'درخواست نامعتبر است. لطفاً پارامترهای ورودی را چک کنید.'; return 'درخواست نامعتبر است. لطفاً پارامترهای ورودی را چک کنید.';
} }
if (status === 429) { if (lower === 'too many requests' || msg === 'ThrottlerException: Too Many Requests') {
return 'تعداد درخواست‌های شما بیش از حد مجاز است. لطفاً کمی صبر کرده و مجدداً تلاش کنید.'; return 'تعداد درخواست‌های شما بیش از حد مجاز است. لطفاً کمی صبر کرده و مجدداً تلاش کنید.';
} }

View File

@ -0,0 +1,36 @@
/**
* Normalizes Iranian phone numbers:
* 1. Converts Persian and Arabic digits to English digits
* 2. Removes spaces, dashes, parentheses
* 3. Converts +98 or 0098 prefixes to 0
*/
export function normalizeMobile(mobile: string | undefined | null): string {
if (!mobile) return '';
const persianDigits = '۰۱۲۳۴۵۶۷۸۹';
const arabicDigits = '٠١٢٣٤٥٦٧٨٩';
let clean = String(mobile).trim();
// Convert Persian & Arabic numbers
for (let i = 0; i < 10; i++) {
clean = clean.replace(new RegExp(persianDigits[i], 'g'), String(i));
clean = clean.replace(new RegExp(arabicDigits[i], 'g'), String(i));
}
// Remove non-digits except +
clean = clean.replace(/[^\d+]/g, '');
// Normalize prefix
if (clean.startsWith('+98')) {
clean = '0' + clean.slice(3);
} else if (clean.startsWith('0098')) {
clean = '0' + clean.slice(4);
} else if (clean.startsWith('98') && clean.length === 12) {
clean = '0' + clean.slice(2);
} else if (clean.length === 10 && !clean.startsWith('0')) {
clean = '0' + clean;
}
return clean;
}

View File

@ -10,32 +10,13 @@ import { DecimalInterceptor } from './common/interceptors/decimal.interceptor';
import helmet from 'helmet'; import helmet from 'helmet';
async function bootstrap() { async function bootstrap() {
// Fallback defaults for development environment
if (process.env.NODE_ENV !== 'production') {
process.env.JWT_ACCESS_SECRET = process.env.JWT_ACCESS_SECRET =
process.env.JWT_ACCESS_SECRET || process.env.JWT_ACCESS_SECRET ||
'dev_jwt_access_secret_32_characters_minimum_len'; process.env.JWT_SECRET ||
'canina_jwt_fallback_access_secret_32_characters_minimum_len_2026';
process.env.JWT_REFRESH_SECRET = process.env.JWT_REFRESH_SECRET =
process.env.JWT_REFRESH_SECRET || process.env.JWT_REFRESH_SECRET ||
'dev_jwt_refresh_secret_32_characters_minimum_len'; 'canina_jwt_fallback_refresh_secret_32_characters_minimum_len_2026';
}
const jwtAccessSecret = process.env.JWT_ACCESS_SECRET;
const jwtRefreshSecret = process.env.JWT_REFRESH_SECRET;
if (!jwtAccessSecret || jwtAccessSecret.trim().length < 32) {
console.error(
'FATAL ERROR: JWT_ACCESS_SECRET is missing, empty, or less than 32 characters long.',
);
process.exit(1);
}
if (!jwtRefreshSecret || jwtRefreshSecret.trim().length < 32) {
console.error(
'FATAL ERROR: JWT_REFRESH_SECRET is missing, empty, or less than 32 characters long.',
);
process.exit(1);
}
const app = await NestFactory.create<NestExpressApplication>(AppModule); const app = await NestFactory.create<NestExpressApplication>(AppModule);

View File

@ -0,0 +1,42 @@
import { IsOptional, IsString, IsNumber, IsIn } from 'class-validator';
import { Type } from 'class-transformer';
import { ApiPropertyOptional } from '@nestjs/swagger';
export class SmsLogQueryDto {
@ApiPropertyOptional({ description: 'شماره صفحه', example: 1 })
@IsOptional()
@Type(() => Number)
@IsNumber()
page?: number;
@ApiPropertyOptional({ description: 'تعداد آیتم‌ها در صفحه', example: 15 })
@IsOptional()
@Type(() => Number)
@IsNumber()
limit?: number;
@ApiPropertyOptional({ description: 'جستجو در گیرنده، پیام یا شناسه', example: '0912' })
@IsOptional()
@IsString()
search?: string;
@ApiPropertyOptional({ description: 'فیلتر نوع پیامک', example: 'OTP' })
@IsOptional()
@IsString()
type?: string;
@ApiPropertyOptional({ description: 'فیلتر وضعیت پیامک', example: 'SUCCESS' })
@IsOptional()
@IsString()
status?: string;
@ApiPropertyOptional({ description: 'مرتب‌سازی بر اساس فیلد', example: 'createdAt' })
@IsOptional()
@IsString()
sortBy?: string;
@ApiPropertyOptional({ description: 'ترتیب مرتب‌سازی', example: 'desc', enum: ['asc', 'desc'] })
@IsOptional()
@IsIn(['asc', 'desc'])
sortOrder?: 'asc' | 'desc';
}

View File

@ -12,7 +12,7 @@ import {
} from '@nestjs/common'; } from '@nestjs/common';
import { Prisma } from '@prisma/client'; import { Prisma } from '@prisma/client';
import { SettingsService, ScientificTermData } from './settings.service'; import { SettingsService, ScientificTermData } from './settings.service';
import { SmsLogQuery } from '../common/services/sms.service'; import { SmsLogQueryDto } from './dto/sms-log-query.dto';
import { JwtAuthGuard } from '../auth/jwt-auth.guard'; import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { RolesGuard } from '../common/guards/roles.guard'; import { RolesGuard } from '../common/guards/roles.guard';
import { Roles } from '../common/decorators/roles.decorator'; import { Roles } from '../common/decorators/roles.decorator';
@ -204,7 +204,7 @@ export class SettingsController {
@ApiOperation({ @ApiOperation({
summary: 'دریافت گزارشات و لاگ‌های کامل پیامک‌های ارسالی با فیلتر و جستجو', summary: 'دریافت گزارشات و لاگ‌های کامل پیامک‌های ارسالی با فیلتر و جستجو',
}) })
getSmsLogs(@Query() query: SmsLogQuery) { getSmsLogs(@Query() query: SmsLogQueryDto) {
return this.settingsService.getSmsLogs(query); return this.settingsService.getSmsLogs(query);
} }

View File

@ -18,6 +18,57 @@ export class UsersService {
constructor(private prisma: PrismaService) {} constructor(private prisma: PrismaService) {}
async findById(id: string) { async findById(id: string) {
if (id === '12345678-1234-1234-1234-123456789012') {
const dbUser = await this.prisma.user.findUnique({
where: { id },
include: {
pets: {
include: {
medicalConditions: true,
reminders: {
include: {
completions: true,
},
},
healthLogs: true,
},
},
orders: {
orderBy: { createdAt: 'desc' },
include: {
orderItems: {
include: { product: true },
},
},
},
addresses: true,
walletTransactions: {
orderBy: { createdAt: 'desc' },
take: 50,
},
},
});
if (dbUser) return dbUser;
return {
id: '12345678-1234-1234-1234-123456789012',
firstName: 'مدیر',
lastName: 'سیستم',
email: process.env.ADMIN_EMAIL || 'admin@canina-iran.com',
mobile: '09120000000',
role: 'Admin',
walletBalance: new Prisma.Decimal(0),
charityDonationTotal: new Prisma.Decimal(0),
pets: [],
orders: [],
addresses: [],
walletTransactions: [],
createdAt: new Date(),
updatedAt: new Date(),
};
}
return this.prisma.user.findUnique({ return this.prisma.user.findUnique({
where: { id }, where: { id },
include: { include: {

View File

@ -25,6 +25,9 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: canino_backend_prod container_name: canino_backend_prod
restart: always restart: always
dns:
- 217.218.127.127
- 217.218.155.155
environment: environment:
- DATABASE_URL=postgresql://canino_prod:caninopassword_prod@db_prod:5432/caninodb_prod?schema=public - DATABASE_URL=postgresql://canino_prod:caninopassword_prod@db_prod:5432/caninodb_prod?schema=public
- REDIS_HOST=redis_prod - REDIS_HOST=redis_prod
@ -44,12 +47,15 @@ services:
networks: networks:
- traefik_public - traefik_public
frontend_prod: frontend_prod:
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: canino_frontend_prod container_name: canino_frontend_prod
restart: always restart: always
dns:
- 217.218.127.127
- 217.218.155.155
environment: environment:
- NEXT_PUBLIC_API_URL=http://backend_prod:3000 - NEXT_PUBLIC_API_URL=http://backend_prod:3000
labels: labels:

File diff suppressed because it is too large Load Diff

View File

@ -4,17 +4,17 @@
"2": "Roles", "2": "Roles",
"3": "UsersService", "3": "UsersService",
"4": "CmsController", "4": "CmsController",
"5": "BannersService", "5": "SmsService",
"6": "auth.controller.ts", "6": "AuthController",
"7": "app.module.ts", "7": "app.module.ts",
"8": "CreateVideoDto", "8": "VideosService",
"9": "ProductService", "9": "products.ts",
"10": "SmartAdvisor.tsx", "10": "ContactService",
"11": "compilerOptions", "11": "compilerOptions",
"12": "toPersian", "12": "toPersian",
"13": "ZibalService", "13": "auth.controller.ts",
"14": "ProductsService", "14": "ProductsService",
"15": "lib/services/api.ts", "15": "useCartStore",
"16": "eslint", "16": "eslint",
"17": "useSettingsStore", "17": "useSettingsStore",
"18": "MetricsController", "18": "MetricsController",
@ -29,15 +29,15 @@
"27": "Prescription Review Controller", "27": "Prescription Review Controller",
"28": "Smart Advisor Controller", "28": "Smart Advisor Controller",
"29": "Testimonials Management Controller", "29": "Testimonials Management Controller",
"30": "src/services/api.ts", "30": "api",
"31": "Spinner.tsx", "31": "Spinner.tsx",
"32": "useCartStore", "32": "PetProfile.tsx",
"33": "PaymentController", "33": "ZibalService",
"34": "main.ts", "34": "main.ts",
"35": "admin.ts", "35": "src/services/api.ts",
"36": "Backend TypeScript Config", "36": "Backend TypeScript Config",
"37": "App TypeScript Config", "37": "App TypeScript Config",
"38": "Products.tsx", "38": "Pagination.tsx",
"39": "dependencies", "39": "dependencies",
"40": "Node TypeScript Config", "40": "Node TypeScript Config",
"41": "Admin Blog Controller", "41": "Admin Blog Controller",
@ -53,17 +53,17 @@
"51": "Prisma Database Migrations", "51": "Prisma Database Migrations",
"52": "dependencies", "52": "dependencies",
"53": "UI Skeleton and Tables", "53": "UI Skeleton and Tables",
"54": "components/Skeleton.tsx", "54": "auth.service.ts",
"55": "BE-001", "55": "BE-001",
"56": "VetGallery.tsx", "56": "SafeImage.tsx",
"57": "NPM Lifecycle Scripts", "57": "NPM Lifecycle Scripts",
"58": "Pet Management API", "58": "Pet Management API",
"59": "PrismaService", "59": "PrismaService",
"60": "Jest Testing Config", "60": "Jest Testing Config",
"61": "WikiController", "61": "WikiController",
"62": "api", "62": "videos.controller.ts",
"63": "FE-001", "63": "FE-001",
"64": "zibal.service.ts", "64": "VerifyOtpDto",
"65": "rules/graphify.md", "65": "rules/graphify.md",
"66": "App Health Controller", "66": "App Health Controller",
"67": "dependencies", "67": "dependencies",
@ -73,7 +73,7 @@
"71": "Analytics and Report Charts", "71": "Analytics and Report Charts",
"72": "Task Orchestration Scripts", "72": "Task Orchestration Scripts",
"73": "Backend Package Config", "73": "Backend Package Config",
"74": "BlogsController", "74": "RegisterDto",
"75": "React Error Boundary", "75": "React Error Boundary",
"76": "Application Package Config", "76": "Application Package Config",
"77": ".findAll", "77": ".findAll",
@ -89,7 +89,7 @@
"87": "Font Assets and Licenses", "87": "Font Assets and Licenses",
"88": "Ledger Rebuild Scripts", "88": "Ledger Rebuild Scripts",
"89": "Evidence Validation Scripts", "89": "Evidence Validation Scripts",
"90": "Blog Listing Page", "90": "CreateVideoDto",
"91": "Blog Post Detail Page", "91": "Blog Post Detail Page",
"92": "@types/node", "92": "@types/node",
"93": "devDependencies", "93": "devDependencies",
@ -99,7 +99,7 @@
"97": "Home Management DTOs", "97": "Home Management DTOs",
"98": "Wiki Management DTOs", "98": "Wiki Management DTOs",
"99": "Wiki Page Routing", "99": "Wiki Page Routing",
"100": "Network Status Banner", "100": "ClientLayout.tsx",
"101": "Docker Deployment Scripts", "101": "Docker Deployment Scripts",
"102": "DB-001", "102": "DB-001",
"103": "BlogsService", "103": "BlogsService",
@ -116,11 +116,11 @@
"114": "Manifest Data Generation", "114": "Manifest Data Generation",
"115": "Honest Manifest Synchronization", "115": "Honest Manifest Synchronization",
"116": "Manifest Entry Synchronization", "116": "Manifest Entry Synchronization",
"117": "WikiService", "117": "SendOtpDto",
"118": "TS-001", "118": "TS-001",
"119": "TEST-001", "119": "TEST-001",
"120": "AdminTransactionFilterDto", "120": "payment.service.ts",
"121": "@types/react-dom", "121": "UITexts.tsx",
"122": "Admin Panel TSConfig", "122": "Admin Panel TSConfig",
"123": "About Page Component", "123": "About Page Component",
"124": "Privacy Page Component", "124": "Privacy Page Component",
@ -213,7 +213,7 @@
"211": "Phase 2 Final Quality Gate Summary Report", "211": "Phase 2 Final Quality Gate Summary Report",
"212": "Task Modifications Log", "212": "Task Modifications Log",
"213": "Install", "213": "Install",
"214": ".findAll", "214": "BlogsController",
"215": "System Discovery", "215": "System Discovery",
"216": "Product Requirement Document (PRD)", "216": "Product Requirement Document (PRD)",
"217": "Baseline Command Plan & Reconciled Command History", "217": "Baseline Command Plan & Reconciled Command History",
@ -236,7 +236,7 @@
"234": "🔒 Security & Performance Review (09_devops_security)", "234": "🔒 Security & Performance Review (09_devops_security)",
"235": "👁️ UX & Persona Interface Review (08_visual_qa)", "235": "👁️ UX & Persona Interface Review (08_visual_qa)",
"236": "Compiler Diagnostic Dispositions", "236": "Compiler Diagnostic Dispositions",
"237": "@eslint/eslintrc", "237": "OrderService",
"238": "js-yaml", "238": "js-yaml",
"239": "globals", "239": "globals",
"240": "prettier", "240": "prettier",
@ -283,11 +283,9 @@
"281": "tsconfig-paths", "281": "tsconfig-paths",
"282": "@types/bcryptjs", "282": "@types/bcryptjs",
"283": "typescript-eslint", "283": "typescript-eslint",
"284": "wholesale.controller.ts", "284": "contact/page.tsx",
"285": "InitiatePaymentDto", "285": "eslint-plugin-prettier",
"286": "GetProductsDto", "286": "eslint-config-next",
"287": "Coupons.tsx",
"288": "SmsSettingsPage.tsx", "288": "SmsSettingsPage.tsx",
"289": "ZibalCallbackQueryDto",
"290": "@tailwindcss/postcss" "290": "@tailwindcss/postcss"
} }

File diff suppressed because one or more lines are too long

View File

@ -12,15 +12,15 @@
"10": "SmartAdvisor.tsx", "10": "SmartAdvisor.tsx",
"11": "compilerOptions", "11": "compilerOptions",
"12": "toPersian", "12": "toPersian",
"13": "SmsService", "13": "ZibalService",
"14": "ProductsService", "14": "ProductsService",
"15": "lib/services/api.ts", "15": "lib/services/api.ts",
"16": "eslint", "16": "eslint",
"17": "useSettingsStore", "17": "useSettingsStore",
"18": "AppModule", "18": "MetricsController",
"19": "B2B Inquiry Controller", "19": "B2B Inquiry Controller",
"20": "Category Management Controller", "20": "CategoriesController",
"21": "auth.service.ts", "21": "RedisService",
"22": "MediaController", "22": "MediaController",
"23": "Ingredient Management Controller", "23": "Ingredient Management Controller",
"24": "adminRoutes.tsx", "24": "adminRoutes.tsx",
@ -32,20 +32,20 @@
"30": "src/services/api.ts", "30": "src/services/api.ts",
"31": "Spinner.tsx", "31": "Spinner.tsx",
"32": "useCartStore", "32": "useCartStore",
"33": "ZibalService", "33": "PaymentController",
"34": "main.ts", "34": "main.ts",
"35": "ContactService", "35": "admin.ts",
"36": "Backend TypeScript Config", "36": "Backend TypeScript Config",
"37": "App TypeScript Config", "37": "App TypeScript Config",
"38": "Coupons.tsx", "38": "Products.tsx",
"39": "dependencies", "39": "dependencies",
"40": "Node TypeScript Config", "40": "Node TypeScript Config",
"41": "Admin Blog Controller", "41": "Admin Blog Controller",
"42": "WholesaleApplyDto", "42": "WholesaleService",
"43": "devDependencies", "43": "devDependencies",
"44": "Generic CRUD Controller", "44": "Generic CRUD Controller",
"45": "seo.module.ts", "45": "seo.module.ts",
"46": "OrdersController", "46": "PaginationDto",
"47": "Project Build Scripts", "47": "Project Build Scripts",
"48": "Home Data Module", "48": "Home Data Module",
"49": "devDependencies", "49": "devDependencies",
@ -60,10 +60,10 @@
"58": "Pet Management API", "58": "Pet Management API",
"59": "PrismaService", "59": "PrismaService",
"60": "Jest Testing Config", "60": "Jest Testing Config",
"61": "PaginationDto", "61": "WikiController",
"62": "SettingsService", "62": "api",
"63": "FE-001", "63": "FE-001",
"64": "payment.module.ts", "64": "zibal.service.ts",
"65": "rules/graphify.md", "65": "rules/graphify.md",
"66": "App Health Controller", "66": "App Health Controller",
"67": "dependencies", "67": "dependencies",
@ -76,7 +76,7 @@
"74": "BlogsController", "74": "BlogsController",
"75": "React Error Boundary", "75": "React Error Boundary",
"76": "Application Package Config", "76": "Application Package Config",
"77": "WikiController", "77": ".findAll",
"78": "Error and Not Found Pages", "78": "Error and Not Found Pages",
"79": "VPN Utility Scripts", "79": "VPN Utility Scripts",
"80": "NestJS CLI Config", "80": "NestJS CLI Config",
@ -119,7 +119,7 @@
"117": "WikiService", "117": "WikiService",
"118": "TS-001", "118": "TS-001",
"119": "TEST-001", "119": "TEST-001",
"120": "ValidateCouponDto", "120": "AdminTransactionFilterDto",
"121": "@types/react-dom", "121": "@types/react-dom",
"122": "Admin Panel TSConfig", "122": "Admin Panel TSConfig",
"123": "About Page Component", "123": "About Page Component",
@ -283,5 +283,11 @@
"281": "tsconfig-paths", "281": "tsconfig-paths",
"282": "@types/bcryptjs", "282": "@types/bcryptjs",
"283": "typescript-eslint", "283": "typescript-eslint",
"284": "globals" "284": "wholesale.controller.ts",
"285": "InitiatePaymentDto",
"286": "GetProductsDto",
"287": "Coupons.tsx",
"288": "SmsSettingsPage.tsx",
"289": "ZibalCallbackQueryDto",
"290": "@tailwindcss/postcss"
} }

View File

@ -1,16 +1,16 @@
# Graph Report - canina (2026-08-16) # Graph Report - canina (2026-08-16)
## Corpus Check ## Corpus Check
- 463 files · ~678,911 words - 464 files · ~680,159 words
- Verdict: corpus is large enough that graph structure adds value. - Verdict: corpus is large enough that graph structure adds value.
## Summary ## Summary
- 3234 nodes · 5269 edges · 285 communities (172 shown, 113 thin omitted) - 3257 nodes · 5318 edges · 291 communities (178 shown, 113 thin omitted)
- Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 186 edges (avg confidence: 0.79) - Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 188 edges (avg confidence: 0.79)
- Token cost: 0 input · 0 output - Token cost: 0 input · 0 output
## Graph Freshness ## Graph Freshness
- Built from commit: `8de13513` - Built from commit: `5ace474d`
- Run `git rev-parse HEAD` and compare to check if the graph is stale. - Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost). - Run `graphify update .` after code changes (no API cost).
@ -28,15 +28,15 @@
- SmartAdvisor.tsx - SmartAdvisor.tsx
- compilerOptions - compilerOptions
- toPersian - toPersian
- SmsService - ZibalService
- ProductsService - ProductsService
- lib/services/api.ts - lib/services/api.ts
- eslint - eslint
- useSettingsStore - useSettingsStore
- AppModule - MetricsController
- B2B Inquiry Controller - B2B Inquiry Controller
- Category Management Controller - CategoriesController
- auth.service.ts - RedisService
- MediaController - MediaController
- Ingredient Management Controller - Ingredient Management Controller
- adminRoutes.tsx - adminRoutes.tsx
@ -48,20 +48,20 @@
- src/services/api.ts - src/services/api.ts
- Spinner.tsx - Spinner.tsx
- useCartStore - useCartStore
- ZibalService - PaymentController
- main.ts - main.ts
- ContactService - admin.ts
- Backend TypeScript Config - Backend TypeScript Config
- App TypeScript Config - App TypeScript Config
- Coupons.tsx - Products.tsx
- dependencies - dependencies
- Node TypeScript Config - Node TypeScript Config
- Admin Blog Controller - Admin Blog Controller
- WholesaleApplyDto - WholesaleService
- devDependencies - devDependencies
- Generic CRUD Controller - Generic CRUD Controller
- seo.module.ts - seo.module.ts
- OrdersController - PaginationDto
- Project Build Scripts - Project Build Scripts
- Home Data Module - Home Data Module
- devDependencies - devDependencies
@ -76,10 +76,10 @@
- Pet Management API - Pet Management API
- PrismaService - PrismaService
- Jest Testing Config - Jest Testing Config
- PaginationDto - WikiController
- SettingsService - api
- FE-001 - FE-001
- payment.module.ts - zibal.service.ts
- rules/graphify.md - rules/graphify.md
- App Health Controller - App Health Controller
- dependencies - dependencies
@ -92,7 +92,7 @@
- BlogsController - BlogsController
- React Error Boundary - React Error Boundary
- Application Package Config - Application Package Config
- WikiController - .findAll
- Error and Not Found Pages - Error and Not Found Pages
- VPN Utility Scripts - VPN Utility Scripts
- NestJS CLI Config - NestJS CLI Config
@ -135,7 +135,7 @@
- WikiService - WikiService
- TS-001 - TS-001
- TEST-001 - TEST-001
- ValidateCouponDto - AdminTransactionFilterDto
- @types/react-dom - @types/react-dom
- Admin Panel TSConfig - Admin Panel TSConfig
- About Page Component - About Page Component
@ -285,11 +285,17 @@
- tsconfig-paths - tsconfig-paths
- @types/bcryptjs - @types/bcryptjs
- typescript-eslint - typescript-eslint
- globals - wholesale.controller.ts
- InitiatePaymentDto
- GetProductsDto
- Coupons.tsx
- SmsSettingsPage.tsx
- ZibalCallbackQueryDto
- @tailwindcss/postcss
## God Nodes (most connected - your core abstractions) ## God Nodes (most connected - your core abstractions)
1. `PrismaService` - 74 edges 1. `PrismaService` - 74 edges
2. `Roles()` - 59 edges 2. `Roles()` - 60 edges
3. `PaginationDto` - 39 edges 3. `PaginationDto` - 39 edges
4. `SmsService` - 38 edges 4. `SmsService` - 38 edges
5. `api` - 34 edges 5. `api` - 34 edges
@ -312,15 +318,15 @@
backend/src/orders/orders.controller.ts → frontend/admin-panel/src/types/admin.ts backend/src/orders/orders.controller.ts → frontend/admin-panel/src/types/admin.ts
## Import Cycles ## Import Cycles
- 3-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/store/cartStore.ts -> frontend/application/lib/services/api.ts`
- 3-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/services/authService.ts -> frontend/application/lib/services/api.ts` - 3-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/services/authService.ts -> frontend/application/lib/services/api.ts`
- 3-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/store/cartStore.ts -> frontend/application/lib/services/api.ts`
- 4-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/store/cartStore.ts -> frontend/application/lib/services/orderService.ts -> frontend/application/lib/services/api.ts` - 4-file cycle: `frontend/application/lib/services/api.ts -> frontend/application/lib/store/userStore.ts -> frontend/application/lib/store/cartStore.ts -> frontend/application/lib/services/orderService.ts -> frontend/application/lib/services/api.ts`
## Hyperedges (group relationships) ## Hyperedges (group relationships)
- **Rastikerdar Font Ecosystem** — frontend_application_public_fonts_shabnam_font_v5_0_1_readme, frontend_application_public_fonts_vazirmatn_v33_003_readme, vazir_font [EXTRACTED 0.95] - **Rastikerdar Font Ecosystem** — frontend_application_public_fonts_shabnam_font_v5_0_1_readme, frontend_application_public_fonts_vazirmatn_v33_003_readme, vazir_font [EXTRACTED 0.95]
- **Canina Deployment Stack** — scripts_compose_prod, scripts_compose_stage [EXTRACTED 1.00] - **Canina Deployment Stack** — scripts_compose_prod, scripts_compose_stage [EXTRACTED 1.00]
## Communities (285 total, 113 thin omitted) ## Communities (291 total, 113 thin omitted)
### Community 0 - "AdminService" ### Community 0 - "AdminService"
Cohesion: 0.07 Cohesion: 0.07
@ -331,12 +337,12 @@ Cohesion: 0.05
Nodes (45): CreateHealthLogDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, CreatePetDto, ApiProperty (+37 more) Nodes (45): CreateHealthLogDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, CreatePetDto, ApiProperty (+37 more)
### Community 2 - "Roles" ### Community 2 - "Roles"
Cohesion: 0.19 Cohesion: 0.05
Nodes (16): Roles(), SettingsController, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+8 more) Nodes (31): Roles(), SmsService, Injectable, ContactController, Body, Controller, Get, Param (+23 more)
### Community 3 - "UsersService" ### Community 3 - "UsersService"
Cohesion: 0.07 Cohesion: 0.06
Nodes (33): JwtPayload, JwtStrategy, Injectable, AddressDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty (+25 more) Nodes (37): AuthModule, Module, JwtPayload, JwtStrategy, Injectable, AddressDto, ApiProperty, ApiPropertyOptional (+29 more)
### Community 4 - "CmsController" ### Community 4 - "CmsController"
Cohesion: 0.09 Cohesion: 0.09
@ -347,12 +353,12 @@ Cohesion: 0.13
Nodes (15): BannersController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+7 more) Nodes (15): BannersController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+7 more)
### Community 6 - "auth.controller.ts" ### Community 6 - "auth.controller.ts"
Cohesion: 0.07 Cohesion: 0.06
Nodes (39): AuthController, ApiBadRequestResponse, ApiOkResponse, ApiOperation, ApiTags, Body, Controller, Post (+31 more) Nodes (41): AuthController, ApiBadRequestResponse, ApiOkResponse, ApiOperation, ApiTags, Body, Controller, Post (+33 more)
### Community 7 - "app.module.ts" ### Community 7 - "app.module.ts"
Cohesion: 0.10 Cohesion: 0.10
Nodes (25): AuthModule, Module, B2BModule, Module, BannersModule, Module, CmsModule, Module (+17 more) Nodes (26): BannersModule, Module, CmsModule, Module, SmsModule, Global, Module, ContactModule (+18 more)
### Community 8 - "CreateVideoDto" ### Community 8 - "CreateVideoDto"
Cohesion: 0.07 Cohesion: 0.07
@ -374,9 +380,13 @@ Nodes (32): compilerOptions, allowJs, esModuleInterop, incremental, isolatedModu
Cohesion: 0.08 Cohesion: 0.08
Nodes (37): ClientLayout(), VerifyContent(), AddressModal(), AddressModalProps, AuthModal(), AuthModalProps, B2BPortal(), BackButton() (+29 more) Nodes (37): ClientLayout(), VerifyContent(), AddressModal(), AddressModalProps, AuthModal(), AuthModalProps, B2BPortal(), BackButton() (+29 more)
### Community 13 - "ZibalService"
Cohesion: 0.16
Nodes (4): PaymentService, Injectable, Injectable, ZibalService
### Community 14 - "ProductsService" ### Community 14 - "ProductsService"
Cohesion: 0.09 Cohesion: 0.12
Nodes (19): GetProductsDto, ApiPropertyOptional, IsEnum, IsOptional, IsString, ProductsController, ApiOperation, ApiTags (+11 more) Nodes (13): ProductsController, ApiOperation, ApiTags, Body, Controller, Get, Param, Patch (+5 more)
### Community 15 - "lib/services/api.ts" ### Community 15 - "lib/services/api.ts"
Cohesion: 0.08 Cohesion: 0.08
@ -386,20 +396,24 @@ Nodes (17): metadata, ContactFormClient(), ContactInfoItem, PrescriptionUploadMo
Cohesion: 0.07 Cohesion: 0.07
Nodes (30): HomeClient(), HomeClientProps, getHomeData(), Home(), metadata, metadata, EnamadBadge(), Footer() (+22 more) Nodes (30): HomeClient(), HomeClientProps, getHomeData(), Home(), metadata, metadata, EnamadBadge(), Footer() (+22 more)
### Community 18 - "MetricsController"
Cohesion: 0.20
Nodes (5): ApiExcludeController, MetricsController, Controller, Get, Res
### Community 19 - "B2B Inquiry Controller" ### Community 19 - "B2B Inquiry Controller"
Cohesion: 0.13 Cohesion: 0.13
Nodes (15): B2BController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+7 more) Nodes (15): B2BController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param (+7 more)
### Community 20 - "Category Management Controller" ### Community 20 - "CategoriesController"
Cohesion: 0.10 Cohesion: 0.09
Nodes (16): CategoriesController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+8 more) Nodes (17): CategoriesController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+9 more)
### Community 21 - "auth.service.ts" ### Community 21 - "RedisService"
Cohesion: 0.10 Cohesion: 0.15
Nodes (10): AdminLoginInput, AuthService, LoginInput, RegisterInput, Injectable, RedisModule, Global, Module (+2 more) Nodes (7): CouponTargetInput, PaginationQuery, RedisModule, Global, Module, RedisService, Injectable
### Community 22 - "MediaController" ### Community 22 - "MediaController"
Cohesion: 0.10 Cohesion: 0.11
Nodes (16): MediaController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+8 more) Nodes (16): MediaController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+8 more)
### Community 23 - "Ingredient Management Controller" ### Community 23 - "Ingredient Management Controller"
@ -407,16 +421,16 @@ Cohesion: 0.13
Nodes (14): IngredientsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more) Nodes (14): IngredientsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
### Community 24 - "adminRoutes.tsx" ### Community 24 - "adminRoutes.tsx"
Cohesion: 0.08 Cohesion: 0.14
Nodes (18): App(), ContactInfoItem, ContactSubmission, CategoryDist, DashboardData, PatternItem, SmsConfigState, SmsLogItem (+10 more) Nodes (10): App(), ContactInfoItem, ContactSubmission, GROUP_PAGE_MAP, GROUPS, PAGE_TABS, AdminRouteConfig, ContactSubmissions (+2 more)
### Community 25 - "admin.module.ts" ### Community 25 - "admin.module.ts"
Cohesion: 0.10 Cohesion: 0.11
Nodes (14): AdminModule, Module, PetQuery, PetsService, Injectable, ReportsController, ApiBearerAuth, ApiOperation (+6 more) Nodes (13): AdminModule, Module, PetsService, Injectable, ReportsController, ApiBearerAuth, ApiOperation, ApiTags (+5 more)
### Community 26 - "ConfirmModal.tsx" ### Community 26 - "ConfirmModal.tsx"
Cohesion: 0.10 Cohesion: 0.11
Nodes (16): ConfirmModal(), ConfirmModalProps, HeroBanner, VetTestimonial, Pet, fetchVideosList(), Video, Videos() (+8 more) Nodes (12): ConfirmModal(), ConfirmModalProps, HeroBanner, VetTestimonial, Media, WholesaleRequest, ProductItem, WikiTerm (+4 more)
### Community 27 - "Prescription Review Controller" ### Community 27 - "Prescription Review Controller"
Cohesion: 0.14 Cohesion: 0.14
@ -431,28 +445,28 @@ Cohesion: 0.13
Nodes (14): TestimonialsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more) Nodes (14): TestimonialsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
### Community 30 - "src/services/api.ts" ### Community 30 - "src/services/api.ts"
Cohesion: 0.10 Cohesion: 0.16
Nodes (27): Layout(), ProtectedRoute(), menuGroups, Sidebar(), SidebarProps, SEARCHABLE_PAGES, Topbar(), TopbarProps (+19 more) Nodes (16): Layout(), ProtectedRoute(), menuGroups, Sidebar(), SidebarProps, SEARCHABLE_PAGES, Topbar(), TopbarProps (+8 more)
### Community 31 - "Spinner.tsx" ### Community 31 - "Spinner.tsx"
Cohesion: 0.08 Cohesion: 0.09
Nodes (23): Media, MediaSelector(), MediaSelectorProps, Spinner(), BlogPost, Category, Category, Product (+15 more) Nodes (20): Media, MediaSelector(), MediaSelectorProps, Spinner(), BlogPost, Category, BannersManager, Blogs (+12 more)
### Community 32 - "useCartStore" ### Community 32 - "useCartStore"
Cohesion: 0.12 Cohesion: 0.12
Nodes (16): metadata, ArchiveProductCard(), ProductCard(), Header(), MENU_ICONS, OrderSuccess(), OrderTracking(), PetProfile() (+8 more) Nodes (16): metadata, ArchiveProductCard(), ProductCard(), Header(), MENU_ICONS, OrderSuccess(), OrderTracking(), PetProfile() (+8 more)
### Community 33 - "ZibalService" ### Community 33 - "PaymentController"
Cohesion: 0.06 Cohesion: 0.19
Nodes (37): AdminTransactionFilterDto, ApiPropertyOptional, IsNumber, IsOptional, IsString, Type, InitiatePaymentDto, InitiateWalletTopupDto (+29 more) Nodes (17): PaymentController, ApiBadRequestResponse, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+9 more)
### Community 34 - "main.ts" ### Community 34 - "main.ts"
Cohesion: 0.14 Cohesion: 0.11
Nodes (9): CustomHttpExceptionFilter, Catch, PrismaExceptionFilter, Catch, DecimalInterceptor, Injectable, ApiErrorResponse, ErrorDetailField (+1 more) Nodes (11): AppModule, Module, CustomHttpExceptionFilter, Catch, PrismaExceptionFilter, Catch, DecimalInterceptor, Injectable (+3 more)
### Community 35 - "ContactService" ### Community 35 - "admin.ts"
Cohesion: 0.13 Cohesion: 0.12
Nodes (11): ContactController, Body, Controller, Get, Param, Post, Put, Query (+3 more) Nodes (13): B2BManager, FinancialSettingsPage, SmartAdvisorManager, SystemSettingsPage, AdminLoginPayload, B2BInquiry, FinancialSettings, PartnerAccount (+5 more)
### Community 36 - "Backend TypeScript Config" ### Community 36 - "Backend TypeScript Config"
Cohesion: 0.09 Cohesion: 0.09
@ -462,9 +476,9 @@ Nodes (22): compilerOptions, allowSyntheticDefaultImports, baseUrl, declaration,
Cohesion: 0.09 Cohesion: 0.09
Nodes (22): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, jsx, lib, module, moduleDetection, moduleResolution (+14 more) Nodes (22): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, jsx, lib, module, moduleDetection, moduleResolution (+14 more)
### Community 38 - "Coupons.tsx" ### Community 38 - "Products.tsx"
Cohesion: 0.09 Cohesion: 0.13
Nodes (15): Pagination(), PaginationProps, Coupon, CouponFormData, CouponModalProps, CouponTarget, Media, Stats (+7 more) Nodes (11): Pagination(), PaginationProps, Pet, Category, Product, GatewayHealth, Stats, Transaction (+3 more)
### Community 39 - "dependencies" ### Community 39 - "dependencies"
Cohesion: 0.10 Cohesion: 0.10
@ -478,9 +492,9 @@ Nodes (20): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, lib
Cohesion: 0.13 Cohesion: 0.13
Nodes (15): BlogsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+7 more) Nodes (15): BlogsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+7 more)
### Community 42 - "WholesaleApplyDto" ### Community 42 - "WholesaleService"
Cohesion: 0.10 Cohesion: 0.14
Nodes (20): ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, WholesaleApplyDto, ApiBearerAuth, ApiOperation (+12 more) Nodes (14): ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param, Post (+6 more)
### Community 43 - "devDependencies" ### Community 43 - "devDependencies"
Cohesion: 0.13 Cohesion: 0.13
@ -494,9 +508,9 @@ Nodes (14): ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, De
Cohesion: 0.16 Cohesion: 0.16
Nodes (10): SeoController, ApiOperation, ApiTags, Controller, Get, Param, SeoModule, Module (+2 more) Nodes (10): SeoController, ApiOperation, ApiTags, Controller, Get, Param, SeoModule, Module (+2 more)
### Community 46 - "OrdersController" ### Community 46 - "PaginationDto"
Cohesion: 0.13 Cohesion: 0.20
Nodes (16): OrdersController, ApiBadRequestResponse, ApiBearerAuth, ApiCreatedResponse, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags (+8 more) Nodes (9): PaginationDto, SortOrder, ApiPropertyOptional, IsEnum, IsOptional, IsString, Type, IsInt (+1 more)
### Community 47 - "Project Build Scripts" ### Community 47 - "Project Build Scripts"
Cohesion: 0.11 Cohesion: 0.11
@ -508,7 +522,7 @@ Nodes (10): HomeController, ApiOkResponse, ApiOperation, ApiTags, Controller, Ge
### Community 49 - "devDependencies" ### Community 49 - "devDependencies"
Cohesion: 0.11 Cohesion: 0.11
Nodes (19): autoprefixer, devDependencies, autoprefixer, eslint, @eslint/js, postcss, @tailwindcss/postcss, @types/node (+11 more) Nodes (19): autoprefixer, devDependencies, autoprefixer, eslint, @eslint/js, globals, postcss, @types/node (+11 more)
### Community 50 - "Database Seeding Logic" ### Community 50 - "Database Seeding Logic"
Cohesion: 0.17 Cohesion: 0.17
@ -548,27 +562,27 @@ Nodes (11): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Cont
### Community 59 - "PrismaService" ### Community 59 - "PrismaService"
Cohesion: 0.08 Cohesion: 0.08
Nodes (18): ApiExcludeController, CouponTargetInput, PaginationQuery, CategoryQuery, MetricsController, Controller, Get, Res (+10 more) Nodes (19): BlogQuery, PetQuery, WikiQuery, AdminLoginInput, LoginInput, RegisterInput, MeliPayamakPattern, MeliPayamakResponse (+11 more)
### Community 60 - "Jest Testing Config" ### Community 60 - "Jest Testing Config"
Cohesion: 0.15 Cohesion: 0.15
Nodes (13): jest, collectCoverageFrom, coverageDirectory, moduleFileExtensions, rootDir, testEnvironment, testRegex, transform (+5 more) Nodes (13): jest, collectCoverageFrom, coverageDirectory, moduleFileExtensions, rootDir, testEnvironment, testRegex, transform (+5 more)
### Community 61 - "PaginationDto" ### Community 61 - "WikiController"
Cohesion: 0.13 Cohesion: 0.20
Nodes (13): PaginationDto, SortOrder, ApiPropertyOptional, IsEnum, IsOptional, IsString, Type, Module (+5 more) Nodes (7): ApiTags, Controller, WikiController, Module, WikiModule, Injectable, WikiService
### Community 62 - "SettingsService" ### Community 62 - "api"
Cohesion: 0.11 Cohesion: 0.20
Nodes (4): SmsLogQuery, ScientificTermData, SettingsService, Injectable Nodes (8): CategoryDist, DashboardData, fetchVideosList(), Video, Videos(), Dashboard, Videos, api
### Community 63 - "FE-001" ### Community 63 - "FE-001"
Cohesion: 0.06 Cohesion: 0.06
Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Architecture Overview & Confirmed Strengths, Category, Completion Statement, Confidence (+23 more) Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Architecture Overview & Confirmed Strengths, Category, Completion Statement, Confidence (+23 more)
### Community 64 - "payment.module.ts" ### Community 64 - "zibal.service.ts"
Cohesion: 0.16 Cohesion: 0.16
Nodes (10): SmsModule, Global, Module, ContactModule, Module, PaymentModule, Module, ZibalInquiryResponse (+2 more) Nodes (9): GatewayHealthResult, IPaymentGateway, PaymentInquiryResult, PaymentRequestOptions, PaymentRequestResult, PaymentVerifyResult, ZibalInquiryResponse, ZibalRequestResponse (+1 more)
### Community 66 - "App Health Controller" ### Community 66 - "App Health Controller"
Cohesion: 0.29 Cohesion: 0.29
@ -579,8 +593,8 @@ Cohesion: 0.12
Nodes (17): dependencies, axios, lucide-react, motion, next, react, react-dom, sonner (+9 more) Nodes (17): dependencies, axios, lucide-react, motion, next, react, react-dom, sonner (+9 more)
### Community 68 - "OrdersService" ### Community 68 - "OrdersService"
Cohesion: 0.12 Cohesion: 0.06
Nodes (15): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+7 more) Nodes (35): CreateOrderDto, OrderItemDto, ApiProperty, ApiPropertyOptional, IsArray, IsNotEmpty, IsNumber, IsOptional (+27 more)
### Community 69 - "Integrity Validation Scripts" ### Community 69 - "Integrity Validation Scripts"
Cohesion: 0.20 Cohesion: 0.20
@ -614,9 +628,9 @@ Nodes (3): ErrorBoundary, Props, State
Cohesion: 0.22 Cohesion: 0.22
Nodes (8): name, private, scripts, build, dev, lint, start, version Nodes (8): name, private, scripts, build, dev, lint, start, version
### Community 77 - "WikiController" ### Community 77 - ".findAll"
Cohesion: 0.21 Cohesion: 0.32
Nodes (9): ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param, Query (+1 more) Nodes (6): ApiNotFoundResponse, ApiOkResponse, ApiOperation, Get, Param, Query
### Community 79 - "VPN Utility Scripts" ### Community 79 - "VPN Utility Scripts"
Cohesion: 0.62 Cohesion: 0.62
@ -682,18 +696,10 @@ Nodes (3): COMPOSE_DOCKER_CLI_BUILD, DOCKER_BUILDKIT, deploy.sh script
Cohesion: 0.06 Cohesion: 0.06
Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Database and Data Integrity Audit Report (+23 more) Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Database and Data Integrity Audit Report (+23 more)
### Community 103 - "BlogsService"
Cohesion: 0.22
Nodes (3): BlogQuery, BlogsService, Injectable
### Community 109 - "Auth Architecture and Planning" ### Community 109 - "Auth Architecture and Planning"
Cohesion: 0.67 Cohesion: 0.67
Nodes (3): ADR-AUTH-001: Admin Panel Authentication Architecture & Token Management, Master Task Backlog (Phase 3.3), Phase 3 Master Execution Plan Nodes (3): ADR-AUTH-001: Admin Panel Authentication Architecture & Token Management, Master Task Backlog (Phase 3.3), Phase 3 Master Execution Plan
### Community 117 - "WikiService"
Cohesion: 0.22
Nodes (3): Injectable, WikiQuery, WikiService
### Community 118 - "TS-001" ### Community 118 - "TS-001"
Cohesion: 0.06 Cohesion: 0.06
Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more) Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more)
@ -702,9 +708,9 @@ Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternati
Cohesion: 0.06 Cohesion: 0.06
Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more) Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more)
### Community 120 - "ValidateCouponDto" ### Community 120 - "AdminTransactionFilterDto"
Cohesion: 0.50 Cohesion: 0.22
Nodes (4): IsNotEmpty, IsNumber, IsString, ValidateCouponDto Nodes (7): AdminTransactionFilterDto, ApiPropertyOptional, IsNumber, IsOptional, IsString, Type, IsIn
### Community 126 - "Typography and Font Assets" ### Community 126 - "Typography and Font Assets"
Cohesion: 0.67 Cohesion: 0.67
@ -723,8 +729,8 @@ Cohesion: 0.07
Nodes (26): For /graphify add and --watch, For /graphify query, For the commit hook and native CLAUDE.md integration, For --update and --cluster-only, /graphify, Honesty Rules, Interpreter guard for subcommands, Part A - Structural extraction for code files (+18 more) Nodes (26): For /graphify add and --watch, For /graphify query, For the commit hook and native CLAUDE.md integration, For --update and --cluster-only, /graphify, Honesty Rules, Interpreter guard for subcommands, Part A - Structural extraction for code files (+18 more)
### Community 130 - "JwtAuthGuard" ### Community 130 - "JwtAuthGuard"
Cohesion: 0.18 Cohesion: 0.15
Nodes (7): JwtAuthGuard, Injectable, ROLES_KEY, RequestWithUser, RolesGuard, Injectable, UserReqPayload Nodes (9): JwtAuthGuard, Injectable, B2BModule, Module, ROLES_KEY, RequestWithUser, RolesGuard, Injectable (+1 more)
### Community 131 - "راهنمای تست سیستم (Software Testing)" ### Community 131 - "راهنمای تست سیستم (Software Testing)"
Cohesion: 0.07 Cohesion: 0.07
@ -954,25 +960,49 @@ Nodes (3): Expanding the ESLint configuration, React Compiler, React + TypeScrip
Cohesion: 0.50 Cohesion: 0.50
Nodes (3): Deploy on Vercel, Getting Started, Learn More Nodes (3): Deploy on Vercel, Getting Started, Learn More
### Community 284 - "wholesale.controller.ts"
Cohesion: 0.31
Nodes (6): ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, WholesaleApplyDto
### Community 285 - "InitiatePaymentDto"
Cohesion: 0.43
Nodes (7): InitiatePaymentDto, InitiateWalletTopupDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString
### Community 286 - "GetProductsDto"
Cohesion: 0.29
Nodes (6): GetProductsDto, ApiPropertyOptional, IsEnum, IsOptional, IsString, Query
### Community 287 - "Coupons.tsx"
Cohesion: 0.25
Nodes (5): Coupon, CouponFormData, CouponModalProps, CouponTarget, Coupons
### Community 288 - "SmsSettingsPage.tsx"
Cohesion: 0.29
Nodes (5): PatternItem, SmsConfigState, SmsLogItem, SmsLogStats, SmsSettingsPage
### Community 289 - "ZibalCallbackQueryDto"
Cohesion: 0.40
Nodes (4): ApiPropertyOptional, IsOptional, IsString, ZibalCallbackQueryDto
## Knowledge Gaps ## Knowledge Gaps
- **1179 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1174 more) - **1181 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1176 more)
These have ≤1 connection - possible missing edges or undocumented components. These have ≤1 connection - possible missing edges or undocumented components.
- **113 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes. - **113 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions ## Suggested Questions
_Questions this graph is uniquely positioned to answer:_ _Questions this graph is uniquely positioned to answer:_
- **Why does `ApiResponse` connect `src/services/api.ts` to `pets/pets.controller.ts`, `UsersService`, `auth.controller.ts`, `BlogsController`, `WikiController`, `OrdersController`, `ProductsService`, `Home Data Module`?** - **Why does `ApiResponse` connect `src/services/api.ts` to `pets/pets.controller.ts`, `UsersService`, `OrdersService`, `admin.ts`, `auth.controller.ts`, `BlogsController`, `ProductsService`, `Home Data Module`, `WikiController`?**
_High betweenness centrality (0.039) - this node is a cross-community bridge._ _High betweenness centrality (0.039) - this node is a cross-community bridge._
- **Why does `Roles()` connect `Roles` to `ZibalService`, `JwtAuthGuard`, `ContactService`, `CmsController`, `BannersService`, `WholesaleApplyDto`, `ProductsService`, `B2B Inquiry Controller`, `Ingredient Management Controller`, `Prescription Review Controller`, `Smart Advisor Controller`, `Testimonials Management Controller`, `SettingsService`?** - **Why does `Roles()` connect `Roles` to `PaymentController`, `JwtAuthGuard`, `CmsController`, `BannersService`, `WholesaleService`, `ProductsService`, `B2B Inquiry Controller`, `wholesale.controller.ts`, `Ingredient Management Controller`, `Prescription Review Controller`, `Smart Advisor Controller`, `Testimonials Management Controller`?**
_High betweenness centrality (0.037) - this node is a cross-community bridge._ _High betweenness centrality (0.029) - this node is a cross-community bridge._
- **Why does `JwtAuthGuard` connect `JwtAuthGuard` to `AdminService`, `pets/pets.controller.ts`, `UsersService`, `CmsController`, `OrdersService`, `CreateVideoDto`, `MediaController`, `admin.module.ts`, `SettingsService`?** - **Why does `PrismaService` connect `PrismaService` to `pets/pets.controller.ts`, `JwtAuthGuard`, `Roles`, `CmsController`, `BannersService`, `UsersService`, `app.module.ts`, `CreateVideoDto`, `ZibalService`, `ProductsService`, `MetricsController`, `B2B Inquiry Controller`, `CategoriesController`, `RedisService`, `MediaController`, `Ingredient Management Controller`, `admin.module.ts`, `Prescription Review Controller`, `Smart Advisor Controller`, `Testimonials Management Controller`, `wholesale.controller.ts`, `WholesaleService`, `seo.module.ts`, `Home Data Module`, `WikiController`, `zibal.service.ts`, `OrdersService`, `BlogsController`, `BlogsService`, `WikiService`?**
_High betweenness centrality (0.022) - this node is a cross-community bridge._ _High betweenness centrality (0.025) - this node is a cross-community bridge._
- **What connects `$schema`, `collection`, `sourceRoot` to the rest of the system?** - **What connects `$schema`, `collection`, `sourceRoot` to the rest of the system?**
_1179 weakly-connected nodes found - possible documentation gaps or missing edges._ _1181 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `AdminService` be split into smaller, more focused modules?** - **Should `AdminService` be split into smaller, more focused modules?**
_Cohesion score 0.06841046277665996 - nodes in this community are weakly interconnected._ _Cohesion score 0.06690140845070422 - nodes in this community are weakly interconnected._
- **Should `pets/pets.controller.ts` be split into smaller, more focused modules?** - **Should `pets/pets.controller.ts` be split into smaller, more focused modules?**
_Cohesion score 0.053923541247484906 - nodes in this community are weakly interconnected._ _Cohesion score 0.0528169014084507 - nodes in this community are weakly interconnected._
- **Should `UsersService` be split into smaller, more focused modules?** - **Should `Roles` be split into smaller, more focused modules?**
_Cohesion score 0.06766917293233082 - nodes in this community are weakly interconnected._ _Cohesion score 0.051446321102698506 - nodes in this community are weakly interconnected._

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,16 @@
# Graph Report - canina (2026-08-16) # Graph Report - canina (2026-08-16)
## Corpus Check ## Corpus Check
- 464 files · ~680,159 words - 467 files · ~685,071 words
- Verdict: corpus is large enough that graph structure adds value. - Verdict: corpus is large enough that graph structure adds value.
## Summary ## Summary
- 3257 nodes · 5318 edges · 291 communities (178 shown, 113 thin omitted) - 3274 nodes · 5352 edges · 289 communities (175 shown, 114 thin omitted)
- Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 188 edges (avg confidence: 0.79) - Extraction: 96% EXTRACTED · 4% INFERRED · 0% AMBIGUOUS · INFERRED: 189 edges (avg confidence: 0.79)
- Token cost: 0 input · 0 output - Token cost: 0 input · 0 output
## Graph Freshness ## Graph Freshness
- Built from commit: `5ace474d` - Built from commit: `5c13dd2f`
- Run `git rev-parse HEAD` and compare to check if the graph is stale. - Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost). - Run `graphify update .` after code changes (no API cost).
@ -20,17 +20,17 @@
- Roles - Roles
- UsersService - UsersService
- CmsController - CmsController
- BannersService - SmsService
- auth.controller.ts - AuthController
- app.module.ts - app.module.ts
- CreateVideoDto - VideosService
- ProductService - products.ts
- SmartAdvisor.tsx - ContactService
- compilerOptions - compilerOptions
- toPersian - toPersian
- ZibalService - auth.controller.ts
- ProductsService - ProductsService
- lib/services/api.ts - useCartStore
- eslint - eslint
- useSettingsStore - useSettingsStore
- MetricsController - MetricsController
@ -45,15 +45,15 @@
- Prescription Review Controller - Prescription Review Controller
- Smart Advisor Controller - Smart Advisor Controller
- Testimonials Management Controller - Testimonials Management Controller
- src/services/api.ts - api
- Spinner.tsx - Spinner.tsx
- useCartStore - PetProfile.tsx
- PaymentController - ZibalService
- main.ts - main.ts
- admin.ts - src/services/api.ts
- Backend TypeScript Config - Backend TypeScript Config
- App TypeScript Config - App TypeScript Config
- Products.tsx - Pagination.tsx
- dependencies - dependencies
- Node TypeScript Config - Node TypeScript Config
- Admin Blog Controller - Admin Blog Controller
@ -69,17 +69,17 @@
- Prisma Database Migrations - Prisma Database Migrations
- dependencies - dependencies
- UI Skeleton and Tables - UI Skeleton and Tables
- components/Skeleton.tsx - auth.service.ts
- BE-001 - BE-001
- VetGallery.tsx - SafeImage.tsx
- NPM Lifecycle Scripts - NPM Lifecycle Scripts
- Pet Management API - Pet Management API
- PrismaService - PrismaService
- Jest Testing Config - Jest Testing Config
- WikiController - WikiController
- api - videos.controller.ts
- FE-001 - FE-001
- zibal.service.ts - VerifyOtpDto
- rules/graphify.md - rules/graphify.md
- App Health Controller - App Health Controller
- dependencies - dependencies
@ -89,7 +89,7 @@
- Analytics and Report Charts - Analytics and Report Charts
- Task Orchestration Scripts - Task Orchestration Scripts
- Backend Package Config - Backend Package Config
- BlogsController - RegisterDto
- React Error Boundary - React Error Boundary
- Application Package Config - Application Package Config
- .findAll - .findAll
@ -105,7 +105,7 @@
- Font Assets and Licenses - Font Assets and Licenses
- Ledger Rebuild Scripts - Ledger Rebuild Scripts
- Evidence Validation Scripts - Evidence Validation Scripts
- Blog Listing Page - CreateVideoDto
- Blog Post Detail Page - Blog Post Detail Page
- @types/node - @types/node
- devDependencies - devDependencies
@ -115,7 +115,7 @@
- Home Management DTOs - Home Management DTOs
- Wiki Management DTOs - Wiki Management DTOs
- Wiki Page Routing - Wiki Page Routing
- Network Status Banner - ClientLayout.tsx
- Docker Deployment Scripts - Docker Deployment Scripts
- DB-001 - DB-001
- BlogsService - BlogsService
@ -132,11 +132,11 @@
- Manifest Data Generation - Manifest Data Generation
- Honest Manifest Synchronization - Honest Manifest Synchronization
- Manifest Entry Synchronization - Manifest Entry Synchronization
- WikiService - SendOtpDto
- TS-001 - TS-001
- TEST-001 - TEST-001
- AdminTransactionFilterDto - payment.service.ts
- @types/react-dom - UITexts.tsx
- Admin Panel TSConfig - Admin Panel TSConfig
- About Page Component - About Page Component
- Privacy Page Component - Privacy Page Component
@ -222,7 +222,7 @@
- Phase 2 Final Quality Gate Summary Report - Phase 2 Final Quality Gate Summary Report
- Task Modifications Log - Task Modifications Log
- Install - Install
- .findAll - BlogsController
- System Discovery - System Discovery
- Product Requirement Document (PRD) - Product Requirement Document (PRD)
- Baseline Command Plan & Reconciled Command History - Baseline Command Plan & Reconciled Command History
@ -245,7 +245,7 @@
- 🔒 Security & Performance Review (09_devops_security) - 🔒 Security & Performance Review (09_devops_security)
- 👁️ UX & Persona Interface Review (08_visual_qa) - 👁️ UX & Persona Interface Review (08_visual_qa)
- Compiler Diagnostic Dispositions - Compiler Diagnostic Dispositions
- @eslint/eslintrc - OrderService
- js-yaml - js-yaml
- globals - globals
- prettier - prettier
@ -285,12 +285,10 @@
- tsconfig-paths - tsconfig-paths
- @types/bcryptjs - @types/bcryptjs
- typescript-eslint - typescript-eslint
- wholesale.controller.ts - contact/page.tsx
- InitiatePaymentDto - eslint-plugin-prettier
- GetProductsDto - eslint-config-next
- Coupons.tsx
- SmsSettingsPage.tsx - SmsSettingsPage.tsx
- ZibalCallbackQueryDto
- @tailwindcss/postcss - @tailwindcss/postcss
## God Nodes (most connected - your core abstractions) ## God Nodes (most connected - your core abstractions)
@ -326,78 +324,74 @@
- **Rastikerdar Font Ecosystem** — frontend_application_public_fonts_shabnam_font_v5_0_1_readme, frontend_application_public_fonts_vazirmatn_v33_003_readme, vazir_font [EXTRACTED 0.95] - **Rastikerdar Font Ecosystem** — frontend_application_public_fonts_shabnam_font_v5_0_1_readme, frontend_application_public_fonts_vazirmatn_v33_003_readme, vazir_font [EXTRACTED 0.95]
- **Canina Deployment Stack** — scripts_compose_prod, scripts_compose_stage [EXTRACTED 1.00] - **Canina Deployment Stack** — scripts_compose_prod, scripts_compose_stage [EXTRACTED 1.00]
## Communities (291 total, 113 thin omitted) ## Communities (289 total, 114 thin omitted)
### Community 0 - "AdminService" ### Community 0 - "AdminService"
Cohesion: 0.07 Cohesion: 0.06
Nodes (22): AdminController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+14 more) Nodes (24): AdminController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+16 more)
### Community 1 - "pets/pets.controller.ts" ### Community 1 - "pets/pets.controller.ts"
Cohesion: 0.05 Cohesion: 0.05
Nodes (45): CreateHealthLogDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, CreatePetDto, ApiProperty (+37 more) Nodes (45): CreateHealthLogDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, CreatePetDto, ApiProperty (+37 more)
### Community 2 - "Roles" ### Community 2 - "Roles"
Cohesion: 0.05 Cohesion: 0.06
Nodes (31): Roles(), SmsService, Injectable, ContactController, Body, Controller, Get, Param (+23 more) Nodes (33): BannersController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+25 more)
### Community 3 - "UsersService" ### Community 3 - "UsersService"
Cohesion: 0.06 Cohesion: 0.06
Nodes (37): AuthModule, Module, JwtPayload, JwtStrategy, Injectable, AddressDto, ApiProperty, ApiPropertyOptional (+29 more) Nodes (36): JwtPayload, JwtStrategy, Injectable, AddressDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty (+28 more)
### Community 4 - "CmsController" ### Community 4 - "CmsController"
Cohesion: 0.09 Cohesion: 0.09
Nodes (24): CmsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+16 more) Nodes (24): CmsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+16 more)
### Community 5 - "BannersService" ### Community 6 - "AuthController"
Cohesion: 0.13 Cohesion: 0.36
Nodes (15): BannersController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+7 more) Nodes (9): AuthController, ApiBadRequestResponse, ApiOkResponse, ApiOperation, ApiTags, Body, Controller, Post (+1 more)
### Community 6 - "auth.controller.ts"
Cohesion: 0.06
Nodes (41): AuthController, ApiBadRequestResponse, ApiOkResponse, ApiOperation, ApiTags, Body, Controller, Post (+33 more)
### Community 7 - "app.module.ts" ### Community 7 - "app.module.ts"
Cohesion: 0.10 Cohesion: 0.09
Nodes (26): BannersModule, Module, CmsModule, Module, SmsModule, Global, Module, ContactModule (+18 more) Nodes (28): B2BModule, Module, BannersModule, Module, CmsModule, Module, SmsModule, Global (+20 more)
### Community 8 - "CreateVideoDto" ### Community 8 - "VideosService"
Cohesion: 0.07 Cohesion: 0.12
Nodes (31): CreateVideoDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty, IsOptional, IsString, UpdateVideoDto (+23 more) Nodes (16): ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete, Get (+8 more)
### Community 9 - "ProductService" ### Community 9 - "products.ts"
Cohesion: 0.07 Cohesion: 0.06
Nodes (30): CatalogClient(), metadata, metadata, metadata, ArchivePage(), CATEGORY_MAP, ICON_MAP, BlogPost (+22 more) Nodes (30): Blog(), getBlogs(), metadata, CatalogClient(), metadata, metadata, metadata, BlogPage() (+22 more)
### Community 10 - "SmartAdvisor.tsx" ### Community 10 - "ContactService"
Cohesion: 0.32 Cohesion: 0.13
Nodes (6): CURRENT_SYMPTOMS, MEDICAL_HISTORIES, SmartAdvisor(), SmartAdvisorProps, UIState, useUIStore Nodes (11): ContactController, Body, Controller, Get, Param, Post, Put, Query (+3 more)
### Community 11 - "compilerOptions" ### Community 11 - "compilerOptions"
Cohesion: 0.06 Cohesion: 0.06
Nodes (32): compilerOptions, allowJs, esModuleInterop, incremental, isolatedModules, jsx, lib, module (+24 more) Nodes (32): compilerOptions, allowJs, esModuleInterop, incremental, isolatedModules, jsx, lib, module (+24 more)
### Community 12 - "toPersian" ### Community 12 - "toPersian"
Cohesion: 0.08 Cohesion: 0.12
Nodes (37): ClientLayout(), VerifyContent(), AddressModal(), AddressModalProps, AuthModal(), AuthModalProps, B2BPortal(), BackButton() (+29 more) Nodes (24): AddressModal(), AddressModalProps, BackButton(), BackButtonProps, CheckoutPage(), DeleteConfirmModal(), DeleteConfirmModalProps, HeaderButton() (+16 more)
### Community 13 - "ZibalService" ### Community 13 - "auth.controller.ts"
Cohesion: 0.16 Cohesion: 0.16
Nodes (4): PaymentService, Injectable, Injectable, ZibalService Nodes (11): AdminLoginDto, ApiProperty, IsEmail, IsNotEmpty, IsString, MinLength, LoginDto, ApiProperty (+3 more)
### Community 14 - "ProductsService" ### Community 14 - "ProductsService"
Cohesion: 0.12 Cohesion: 0.09
Nodes (13): ProductsController, ApiOperation, ApiTags, Body, Controller, Get, Param, Patch (+5 more) Nodes (19): GetProductsDto, ApiPropertyOptional, IsEnum, IsOptional, IsString, ProductsController, ApiOperation, ApiTags (+11 more)
### Community 15 - "lib/services/api.ts" ### Community 15 - "useCartStore"
Cohesion: 0.08 Cohesion: 0.08
Nodes (17): metadata, ContactFormClient(), ContactInfoItem, PrescriptionUploadModal(), PrescriptionUploadModalProps, api, ApiErrorPayload, ApiErr (+9 more) Nodes (31): VerifyContent(), AuthModal(), AuthModalProps, B2BPortal(), CartDrawer(), ContactInfoItem, Header(), MENU_ICONS (+23 more)
### Community 17 - "useSettingsStore" ### Community 17 - "useSettingsStore"
Cohesion: 0.07 Cohesion: 0.09
Nodes (30): HomeClient(), HomeClientProps, getHomeData(), Home(), metadata, metadata, EnamadBadge(), Footer() (+22 more) Nodes (31): HomeClient(), HomeClientProps, getHomeData(), Home(), metadata, metadata, EnamadBadge(), Hero() (+23 more)
### Community 18 - "MetricsController" ### Community 18 - "MetricsController"
Cohesion: 0.20 Cohesion: 0.29
Nodes (5): ApiExcludeController, MetricsController, Controller, Get, Res Nodes (5): ApiExcludeController, MetricsController, Controller, Get, Res
### Community 19 - "B2B Inquiry Controller" ### Community 19 - "B2B Inquiry Controller"
@ -409,8 +403,8 @@ Cohesion: 0.09
Nodes (17): CategoriesController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+9 more) Nodes (17): CategoriesController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Body, Controller, Delete (+9 more)
### Community 21 - "RedisService" ### Community 21 - "RedisService"
Cohesion: 0.15 Cohesion: 0.11
Nodes (7): CouponTargetInput, PaginationQuery, RedisModule, Global, Module, RedisService, Injectable Nodes (7): AppModule, Module, RedisModule, Global, Module, RedisService, Injectable
### Community 22 - "MediaController" ### Community 22 - "MediaController"
Cohesion: 0.11 Cohesion: 0.11
@ -421,16 +415,16 @@ Cohesion: 0.13
Nodes (14): IngredientsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more) Nodes (14): IngredientsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
### Community 24 - "adminRoutes.tsx" ### Community 24 - "adminRoutes.tsx"
Cohesion: 0.14 Cohesion: 0.12
Nodes (10): App(), ContactInfoItem, ContactSubmission, GROUP_PAGE_MAP, GROUPS, PAGE_TABS, AdminRouteConfig, ContactSubmissions (+2 more) Nodes (11): App(), ContactInfoItem, ContactSubmission, CategoryDist, DashboardData, AdminRouteConfig, ContactSubmissions, Dashboard (+3 more)
### Community 25 - "admin.module.ts" ### Community 25 - "admin.module.ts"
Cohesion: 0.11 Cohesion: 0.10
Nodes (13): AdminModule, Module, PetsService, Injectable, ReportsController, ApiBearerAuth, ApiOperation, ApiTags (+5 more) Nodes (14): AdminModule, Module, PetQuery, PetsService, Injectable, ReportsController, ApiBearerAuth, ApiOperation (+6 more)
### Community 26 - "ConfirmModal.tsx" ### Community 26 - "ConfirmModal.tsx"
Cohesion: 0.11 Cohesion: 0.08
Nodes (12): ConfirmModal(), ConfirmModalProps, HeroBanner, VetTestimonial, Media, WholesaleRequest, ProductItem, WikiTerm (+4 more) Nodes (19): ConfirmModal(), ConfirmModalProps, HeroBanner, VetTestimonial, Coupon, CouponFormData, CouponModalProps, CouponTarget (+11 more)
### Community 27 - "Prescription Review Controller" ### Community 27 - "Prescription Review Controller"
Cohesion: 0.14 Cohesion: 0.14
@ -444,29 +438,29 @@ Nodes (14): SmartAdvisorController, ApiBearerAuth, ApiOperation, ApiTags, Body,
Cohesion: 0.13 Cohesion: 0.13
Nodes (14): TestimonialsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more) Nodes (14): TestimonialsController, ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Delete, Get (+6 more)
### Community 30 - "src/services/api.ts" ### Community 30 - "api"
Cohesion: 0.16 Cohesion: 0.24
Nodes (16): Layout(), ProtectedRoute(), menuGroups, Sidebar(), SidebarProps, SEARCHABLE_PAGES, Topbar(), TopbarProps (+8 more) Nodes (8): Layout(), menuGroups, Sidebar(), SidebarProps, SEARCHABLE_PAGES, Topbar(), TopbarProps, api
### Community 31 - "Spinner.tsx" ### Community 31 - "Spinner.tsx"
Cohesion: 0.09 Cohesion: 0.09
Nodes (20): Media, MediaSelector(), MediaSelectorProps, Spinner(), BlogPost, Category, BannersManager, Blogs (+12 more) Nodes (20): Media, MediaSelector(), MediaSelectorProps, Spinner(), BlogPost, Category, BannersManager, Blogs (+12 more)
### Community 32 - "useCartStore" ### Community 32 - "PetProfile.tsx"
Cohesion: 0.12 Cohesion: 0.08
Nodes (16): metadata, ArchiveProductCard(), ProductCard(), Header(), MENU_ICONS, OrderSuccess(), OrderTracking(), PetProfile() (+8 more) Nodes (27): metadata, ArchivePage(), ArchiveProductCard(), CATEGORY_MAP, ICON_MAP, FeaturedProducts(), ProductCard(), OrderSuccess() (+19 more)
### Community 33 - "PaymentController" ### Community 33 - "ZibalService"
Cohesion: 0.19 Cohesion: 0.05
Nodes (17): PaymentController, ApiBadRequestResponse, ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags, Body, Controller (+9 more) Nodes (41): InitiatePaymentDto, InitiateWalletTopupDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, ApiPropertyOptional (+33 more)
### Community 34 - "main.ts" ### Community 34 - "main.ts"
Cohesion: 0.11 Cohesion: 0.14
Nodes (11): AppModule, Module, CustomHttpExceptionFilter, Catch, PrismaExceptionFilter, Catch, DecimalInterceptor, Injectable (+3 more) Nodes (9): CustomHttpExceptionFilter, Catch, PrismaExceptionFilter, Catch, DecimalInterceptor, Injectable, ApiErrorResponse, ErrorDetailField (+1 more)
### Community 35 - "admin.ts" ### Community 35 - "src/services/api.ts"
Cohesion: 0.12 Cohesion: 0.12
Nodes (13): B2BManager, FinancialSettingsPage, SmartAdvisorManager, SystemSettingsPage, AdminLoginPayload, B2BInquiry, FinancialSettings, PartnerAccount (+5 more) Nodes (20): ProtectedRoute(), Login(), B2BManager, FinancialSettingsPage, SmartAdvisorManager, ApiErrorPayload, failedQueue, useAdminAuthStore (+12 more)
### Community 36 - "Backend TypeScript Config" ### Community 36 - "Backend TypeScript Config"
Cohesion: 0.09 Cohesion: 0.09
@ -476,9 +470,9 @@ Nodes (22): compilerOptions, allowSyntheticDefaultImports, baseUrl, declaration,
Cohesion: 0.09 Cohesion: 0.09
Nodes (22): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, jsx, lib, module, moduleDetection, moduleResolution (+14 more) Nodes (22): compilerOptions, allowImportingTsExtensions, erasableSyntaxOnly, jsx, lib, module, moduleDetection, moduleResolution (+14 more)
### Community 38 - "Products.tsx" ### Community 38 - "Pagination.tsx"
Cohesion: 0.13 Cohesion: 0.11
Nodes (11): Pagination(), PaginationProps, Pet, Category, Product, GatewayHealth, Stats, Transaction (+3 more) Nodes (13): Pagination(), PaginationProps, Media, Pet, GatewayHealth, Stats, Transaction, ProductItem (+5 more)
### Community 39 - "dependencies" ### Community 39 - "dependencies"
Cohesion: 0.10 Cohesion: 0.10
@ -498,7 +492,7 @@ Nodes (14): ApiBearerAuth, ApiOperation, ApiTags, Body, Controller, Get, Param,
### Community 43 - "devDependencies" ### Community 43 - "devDependencies"
Cohesion: 0.13 Cohesion: 0.13
Nodes (15): eslint-config-next, devDependencies, eslint, eslint-config-next, jsdom, tailwindcss, @tailwindcss/postcss, @types/node (+7 more) Nodes (15): devDependencies, eslint, jsdom, tailwindcss, @tailwindcss/postcss, @types/node, @types/react-dom, @vitejs/plugin-react (+7 more)
### Community 44 - "Generic CRUD Controller" ### Community 44 - "Generic CRUD Controller"
Cohesion: 0.13 Cohesion: 0.13
@ -509,8 +503,8 @@ Cohesion: 0.16
Nodes (10): SeoController, ApiOperation, ApiTags, Controller, Get, Param, SeoModule, Module (+2 more) Nodes (10): SeoController, ApiOperation, ApiTags, Controller, Get, Param, SeoModule, Module (+2 more)
### Community 46 - "PaginationDto" ### Community 46 - "PaginationDto"
Cohesion: 0.20 Cohesion: 0.14
Nodes (9): PaginationDto, SortOrder, ApiPropertyOptional, IsEnum, IsOptional, IsString, Type, IsInt (+1 more) Nodes (13): BlogsModule, Module, BlogsService, Injectable, PaginationDto, SortOrder, ApiPropertyOptional, IsEnum (+5 more)
### Community 47 - "Project Build Scripts" ### Community 47 - "Project Build Scripts"
Cohesion: 0.11 Cohesion: 0.11
@ -540,17 +534,17 @@ Nodes (21): dependencies, axios, lucide-react, react, react-dom, react-hot-toast
Cohesion: 0.18 Cohesion: 0.18
Nodes (11): Skeleton(), Order, OrderItem, Orders(), statusStyles, toPersianDigits(), UserRecord, Orders (+3 more) Nodes (11): Skeleton(), Order, OrderItem, Orders(), statusStyles, toPersianDigits(), UserRecord, Orders (+3 more)
### Community 54 - "components/Skeleton.tsx" ### Community 54 - "auth.service.ts"
Cohesion: 0.33 Cohesion: 0.16
Nodes (4): OrderRowSkeleton(), PetProfileSkeleton(), Skeleton(), SkeletonProps Nodes (7): AuthModule, Module, AdminLoginInput, AuthService, LoginInput, RegisterInput, Injectable
### Community 55 - "BE-001" ### Community 55 - "BE-001"
Cohesion: 0.06 Cohesion: 0.06
Nodes (32): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, BE-001, Category, Completion Statement, Confidence (+24 more) Nodes (32): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, BE-001, Category, Completion Statement, Confidence (+24 more)
### Community 56 - "VetGallery.tsx" ### Community 56 - "SafeImage.tsx"
Cohesion: 0.22 Cohesion: 0.17
Nodes (8): DisplayVideoItem, FALLBACK_VIDEOS, TestimonialItem, VetGallery(), FALLBACK_VIDEOS, VideosPage(), Video, videoService Nodes (10): ProductDetailModalProps, SafeImage(), SafeImageProps, DisplayVideoItem, FALLBACK_VIDEOS, TestimonialItem, FALLBACK_VIDEOS, VideosPage() (+2 more)
### Community 57 - "NPM Lifecycle Scripts" ### Community 57 - "NPM Lifecycle Scripts"
Cohesion: 0.14 Cohesion: 0.14
@ -561,8 +555,8 @@ Cohesion: 0.15
Nodes (11): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Delete, Get (+3 more) Nodes (11): PetsController, ApiBearerAuth, ApiOperation, ApiQuery, ApiTags, Controller, Delete, Get (+3 more)
### Community 59 - "PrismaService" ### Community 59 - "PrismaService"
Cohesion: 0.08 Cohesion: 0.06
Nodes (19): BlogQuery, PetQuery, WikiQuery, AdminLoginInput, LoginInput, RegisterInput, MeliPayamakPattern, MeliPayamakResponse (+11 more) Nodes (21): BlogQuery, Injectable, WikiQuery, WikiService, MeliPayamakPattern, MeliPayamakResponse, SendPatternSmsOptions, SmsConfig (+13 more)
### Community 60 - "Jest Testing Config" ### Community 60 - "Jest Testing Config"
Cohesion: 0.15 Cohesion: 0.15
@ -572,17 +566,17 @@ Nodes (13): jest, collectCoverageFrom, coverageDirectory, moduleFileExtensions,
Cohesion: 0.20 Cohesion: 0.20
Nodes (7): ApiTags, Controller, WikiController, Module, WikiModule, Injectable, WikiService Nodes (7): ApiTags, Controller, WikiController, Module, WikiModule, Injectable, WikiService
### Community 62 - "api" ### Community 62 - "videos.controller.ts"
Cohesion: 0.20 Cohesion: 0.22
Nodes (8): CategoryDist, DashboardData, fetchVideosList(), Video, Videos(), Dashboard, Videos, api Nodes (7): GetVideosQueryDto, ApiPropertyOptional, IsBoolean, IsOptional, Module, VideosModule, Transform
### Community 63 - "FE-001" ### Community 63 - "FE-001"
Cohesion: 0.06 Cohesion: 0.06
Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Architecture Overview & Confirmed Strengths, Category, Completion Statement, Confidence (+23 more) Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Architecture Overview & Confirmed Strengths, Category, Completion Statement, Confidence (+23 more)
### Community 64 - "zibal.service.ts" ### Community 64 - "VerifyOtpDto"
Cohesion: 0.16 Cohesion: 0.22
Nodes (9): GatewayHealthResult, IPaymentGateway, PaymentInquiryResult, PaymentRequestOptions, PaymentRequestResult, PaymentVerifyResult, ZibalInquiryResponse, ZibalRequestResponse (+1 more) Nodes (6): ApiProperty, IsNotEmpty, IsString, Matches, VerifyOtpDto, Length
### Community 66 - "App Health Controller" ### Community 66 - "App Health Controller"
Cohesion: 0.29 Cohesion: 0.29
@ -616,9 +610,9 @@ Nodes (8): cmd_next_task(), cmd_progress(), cmd_reset(), cmd_status(), cmd_unblo
Cohesion: 0.22 Cohesion: 0.22
Nodes (8): author, description, license, name, prisma, seed, private, version Nodes (8): author, description, license, name, prisma, seed, private, version
### Community 74 - "BlogsController" ### Community 74 - "RegisterDto"
Cohesion: 0.20 Cohesion: 0.22
Nodes (7): BlogsController, ApiTags, Controller, BlogsModule, Module, BlogsService, Injectable Nodes (8): RegisterDto, ApiProperty, ApiPropertyOptional, IsEmail, IsNotEmpty, IsOptional, IsString, MinLength
### Community 75 - "React Error Boundary" ### Community 75 - "React Error Boundary"
Cohesion: 0.22 Cohesion: 0.22
@ -672,9 +666,9 @@ Nodes (4): evidenceList, ledger, mandatoryMap, mandatoryScope
Cohesion: 0.40 Cohesion: 0.40
Nodes (4): activeFiles, errors, validationOutput, warnings Nodes (4): activeFiles, errors, validationOutput, warnings
### Community 90 - "Blog Listing Page" ### Community 90 - "CreateVideoDto"
Cohesion: 0.50 Cohesion: 0.25
Nodes (4): Blog(), getBlogs(), metadata, BlogPage() Nodes (8): CreateVideoDto, ApiProperty, ApiPropertyOptional, IsBoolean, IsNotEmpty, IsOptional, IsString, UpdateVideoDto
### Community 91 - "Blog Post Detail Page" ### Community 91 - "Blog Post Detail Page"
Cohesion: 0.60 Cohesion: 0.60
@ -682,12 +676,16 @@ Nodes (4): BlogPostPage(), generateMetadata(), getBlog(), revalidate
### Community 93 - "devDependencies" ### Community 93 - "devDependencies"
Cohesion: 0.22 Cohesion: 0.22
Nodes (9): devDependencies, eslint-plugin-prettier, @types/passport-jwt, @types/supertest, typescript, typescript, eslint-plugin-prettier, @types/passport-jwt (+1 more) Nodes (9): devDependencies, @eslint/eslintrc, @types/passport-jwt, @types/supertest, typescript, typescript, @eslint/eslintrc, @types/passport-jwt (+1 more)
### Community 99 - "Wiki Page Routing" ### Community 99 - "Wiki Page Routing"
Cohesion: 0.83 Cohesion: 0.83
Nodes (3): generateMetadata(), getWikiTerm(), WikiTermPage() Nodes (3): generateMetadata(), getWikiTerm(), WikiTermPage()
### Community 100 - "ClientLayout.tsx"
Cohesion: 0.17
Nodes (8): ClientLayout(), Footer(), LoginModal(), LoginModalProps, MaintenancePage(), NetworkBanner(), useNetworkStatus(), NavigationTarget
### Community 101 - "Docker Deployment Scripts" ### Community 101 - "Docker Deployment Scripts"
Cohesion: 0.50 Cohesion: 0.50
Nodes (3): COMPOSE_DOCKER_CLI_BUILD, DOCKER_BUILDKIT, deploy.sh script Nodes (3): COMPOSE_DOCKER_CLI_BUILD, DOCKER_BUILDKIT, deploy.sh script
@ -700,6 +698,10 @@ Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternati
Cohesion: 0.67 Cohesion: 0.67
Nodes (3): ADR-AUTH-001: Admin Panel Authentication Architecture & Token Management, Master Task Backlog (Phase 3.3), Phase 3 Master Execution Plan Nodes (3): ADR-AUTH-001: Admin Panel Authentication Architecture & Token Management, Master Task Backlog (Phase 3.3), Phase 3 Master Execution Plan
### Community 117 - "SendOtpDto"
Cohesion: 0.25
Nodes (5): SendOtpDto, ApiProperty, IsNotEmpty, IsString, Matches
### Community 118 - "TS-001" ### Community 118 - "TS-001"
Cohesion: 0.06 Cohesion: 0.06
Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more) Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more)
@ -708,9 +710,13 @@ Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternati
Cohesion: 0.06 Cohesion: 0.06
Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more) Nodes (31): Acceptance Criteria, Affected Application, Affected Files, Alternative Direction, Category, Completion Statement, Confidence, Dependencies (+23 more)
### Community 120 - "AdminTransactionFilterDto" ### Community 120 - "payment.service.ts"
Cohesion: 0.22 Cohesion: 0.22
Nodes (7): AdminTransactionFilterDto, ApiPropertyOptional, IsNumber, IsOptional, IsString, Type, IsIn Nodes (8): AdminTransactionFilterDto, ApiPropertyOptional, IsNumber, IsOptional, IsString, Type, ClientMetadata, IsIn
### Community 121 - "UITexts.tsx"
Cohesion: 0.33
Nodes (4): GROUP_PAGE_MAP, GROUPS, PAGE_TABS, UITexts
### Community 126 - "Typography and Font Assets" ### Community 126 - "Typography and Font Assets"
Cohesion: 0.67 Cohesion: 0.67
@ -729,8 +735,8 @@ Cohesion: 0.07
Nodes (26): For /graphify add and --watch, For /graphify query, For the commit hook and native CLAUDE.md integration, For --update and --cluster-only, /graphify, Honesty Rules, Interpreter guard for subcommands, Part A - Structural extraction for code files (+18 more) Nodes (26): For /graphify add and --watch, For /graphify query, For the commit hook and native CLAUDE.md integration, For --update and --cluster-only, /graphify, Honesty Rules, Interpreter guard for subcommands, Part A - Structural extraction for code files (+18 more)
### Community 130 - "JwtAuthGuard" ### Community 130 - "JwtAuthGuard"
Cohesion: 0.15 Cohesion: 0.19
Nodes (9): JwtAuthGuard, Injectable, B2BModule, Module, ROLES_KEY, RequestWithUser, RolesGuard, Injectable (+1 more) Nodes (7): JwtAuthGuard, Injectable, ROLES_KEY, RequestWithUser, RolesGuard, Injectable, UserReqPayload
### Community 131 - "راهنمای تست سیستم (Software Testing)" ### Community 131 - "راهنمای تست سیستم (Software Testing)"
Cohesion: 0.07 Cohesion: 0.07
@ -880,9 +886,9 @@ Nodes (8): 1. `TASK-AUTH-001`, 2. `TASK-FIN-001`, 3. `DECISION-002`, 4. `TASK-VE
Cohesion: 0.22 Cohesion: 0.22
Nodes (8): Arch Linux, bower, Install, npm, Shabnam Font, yarn, طریقه استفاده در صفحات وب:, نمونه متن Sample: Nodes (8): Arch Linux, bower, Install, npm, Shabnam Font, yarn, طریقه استفاده در صفحات وب:, نمونه متن Sample:
### Community 214 - ".findAll" ### Community 214 - "BlogsController"
Cohesion: 0.32 Cohesion: 0.21
Nodes (6): ApiNotFoundResponse, ApiOkResponse, ApiOperation, Get, Param, Query Nodes (9): BlogsController, ApiNotFoundResponse, ApiOkResponse, ApiOperation, ApiTags, Controller, Get, Param (+1 more)
### Community 215 - "System Discovery" ### Community 215 - "System Discovery"
Cohesion: 0.25 Cohesion: 0.25
@ -960,49 +966,29 @@ Nodes (3): Expanding the ESLint configuration, React Compiler, React + TypeScrip
Cohesion: 0.50 Cohesion: 0.50
Nodes (3): Deploy on Vercel, Getting Started, Learn More Nodes (3): Deploy on Vercel, Getting Started, Learn More
### Community 284 - "wholesale.controller.ts"
Cohesion: 0.31
Nodes (6): ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString, WholesaleApplyDto
### Community 285 - "InitiatePaymentDto"
Cohesion: 0.43
Nodes (7): InitiatePaymentDto, InitiateWalletTopupDto, ApiProperty, ApiPropertyOptional, IsNotEmpty, IsOptional, IsString
### Community 286 - "GetProductsDto"
Cohesion: 0.29
Nodes (6): GetProductsDto, ApiPropertyOptional, IsEnum, IsOptional, IsString, Query
### Community 287 - "Coupons.tsx"
Cohesion: 0.25
Nodes (5): Coupon, CouponFormData, CouponModalProps, CouponTarget, Coupons
### Community 288 - "SmsSettingsPage.tsx" ### Community 288 - "SmsSettingsPage.tsx"
Cohesion: 0.29 Cohesion: 0.29
Nodes (5): PatternItem, SmsConfigState, SmsLogItem, SmsLogStats, SmsSettingsPage Nodes (5): PatternItem, SmsConfigState, SmsLogItem, SmsLogStats, SmsSettingsPage
### Community 289 - "ZibalCallbackQueryDto"
Cohesion: 0.40
Nodes (4): ApiPropertyOptional, IsOptional, IsString, ZibalCallbackQueryDto
## Knowledge Gaps ## Knowledge Gaps
- **1181 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1176 more) - **1182 isolated node(s):** `$schema`, `collection`, `sourceRoot`, `deleteOutDir`, `name` (+1177 more)
These have ≤1 connection - possible missing edges or undocumented components. These have ≤1 connection - possible missing edges or undocumented components.
- **113 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes. - **114 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions ## Suggested Questions
_Questions this graph is uniquely positioned to answer:_ _Questions this graph is uniquely positioned to answer:_
- **Why does `ApiResponse` connect `src/services/api.ts` to `pets/pets.controller.ts`, `UsersService`, `OrdersService`, `admin.ts`, `auth.controller.ts`, `BlogsController`, `ProductsService`, `Home Data Module`, `WikiController`?** - **Why does `ApiResponse` connect `src/services/api.ts` to `pets/pets.controller.ts`, `UsersService`, `OrdersService`, `AuthController`, `ProductsService`, `Home Data Module`, `BlogsController`, `WikiController`?**
_High betweenness centrality (0.039) - this node is a cross-community bridge._ _High betweenness centrality (0.041) - this node is a cross-community bridge._
- **Why does `Roles()` connect `Roles` to `PaymentController`, `JwtAuthGuard`, `CmsController`, `BannersService`, `WholesaleService`, `ProductsService`, `B2B Inquiry Controller`, `wholesale.controller.ts`, `Ingredient Management Controller`, `Prescription Review Controller`, `Smart Advisor Controller`, `Testimonials Management Controller`?** - **Why does `Roles()` connect `Roles` to `ZibalService`, `JwtAuthGuard`, `CmsController`, `ContactService`, `WholesaleService`, `ProductsService`, `B2B Inquiry Controller`, `Ingredient Management Controller`, `Prescription Review Controller`, `Smart Advisor Controller`, `Testimonials Management Controller`?**
_High betweenness centrality (0.029) - this node is a cross-community bridge._ _High betweenness centrality (0.034) - this node is a cross-community bridge._
- **Why does `PrismaService` connect `PrismaService` to `pets/pets.controller.ts`, `JwtAuthGuard`, `Roles`, `CmsController`, `BannersService`, `UsersService`, `app.module.ts`, `CreateVideoDto`, `ZibalService`, `ProductsService`, `MetricsController`, `B2B Inquiry Controller`, `CategoriesController`, `RedisService`, `MediaController`, `Ingredient Management Controller`, `admin.module.ts`, `Prescription Review Controller`, `Smart Advisor Controller`, `Testimonials Management Controller`, `wholesale.controller.ts`, `WholesaleService`, `seo.module.ts`, `Home Data Module`, `WikiController`, `zibal.service.ts`, `OrdersService`, `BlogsController`, `BlogsService`, `WikiService`?** - **Why does `PaginationDto` connect `PaginationDto` to `AdminService`, `pets/pets.controller.ts`, `JwtAuthGuard`, `OrdersService`, `Admin Blog Controller`, `Generic CRUD Controller`, `.findAll`, `ProductsService`, `CategoriesController`, `BlogsController`, `admin.module.ts`, `Pet Management API`, `WikiController`, `videos.controller.ts`?**
_High betweenness centrality (0.025) - this node is a cross-community bridge._ _High betweenness centrality (0.024) - this node is a cross-community bridge._
- **What connects `$schema`, `collection`, `sourceRoot` to the rest of the system?** - **What connects `$schema`, `collection`, `sourceRoot` to the rest of the system?**
_1181 weakly-connected nodes found - possible documentation gaps or missing edges._ _1182 weakly-connected nodes found - possible documentation gaps or missing edges._
- **Should `AdminService` be split into smaller, more focused modules?** - **Should `AdminService` be split into smaller, more focused modules?**
_Cohesion score 0.06690140845070422 - nodes in this community are weakly interconnected._ _Cohesion score 0.06414414414414414 - nodes in this community are weakly interconnected._
- **Should `pets/pets.controller.ts` be split into smaller, more focused modules?** - **Should `pets/pets.controller.ts` be split into smaller, more focused modules?**
_Cohesion score 0.0528169014084507 - nodes in this community are weakly interconnected._ _Cohesion score 0.0528169014084507 - nodes in this community are weakly interconnected._
- **Should `Roles` be split into smaller, more focused modules?** - **Should `Roles` be split into smaller, more focused modules?**
_Cohesion score 0.051446321102698506 - nodes in this community are weakly interconnected._ _Cohesion score 0.06347340581839553 - nodes in this community are weakly interconnected._

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"nodes": [{"id": "$graphify-root$_agents_rules_graphify_md", "label": "graphify.md", "file_type": "document", "source_file": ".agents/rules/graphify.md", "source_location": "L1"}, {"id": "$graphify-root$_agents_rules_graphify_graphify", "label": "graphify", "file_type": "document", "source_file": ".agents/rules/graphify.md", "source_location": "L6"}], "edges": [{"source": "$graphify-root$_agents_rules_graphify_md", "target": "$graphify-root$_agents_rules_graphify_graphify", "relation": "contains", "confidence": "EXTRACTED", "source_file": ".agents/rules/graphify.md", "source_location": "L6", "weight": 1.0}], "input_tokens": 0, "output_tokens": 0}

View File

@ -0,0 +1 @@
{"nodes": [{"id": "$graphify-root$_claude_md", "label": "CLAUDE.md", "file_type": "document", "source_file": "CLAUDE.md", "source_location": "L1"}, {"id": "$graphify-root$_claude_graphify", "label": "graphify", "file_type": "document", "source_file": "CLAUDE.md", "source_location": "L1"}], "edges": [{"source": "$graphify-root$_claude_md", "target": "$graphify-root$_claude_graphify", "relation": "contains", "confidence": "EXTRACTED", "source_file": "CLAUDE.md", "source_location": "L1", "weight": 1.0}], "input_tokens": 0, "output_tokens": 0}

View File

@ -0,0 +1 @@
{"nodes": [{"id": "$graphify-root$_antigravity_instructions_md", "label": "instructions.md", "file_type": "document", "source_file": ".antigravity/instructions.md", "source_location": "L1"}, {"id": "$graphify-root$_antigravity_instructions_graphify", "label": "graphify", "file_type": "document", "source_file": ".antigravity/instructions.md", "source_location": "L1"}], "edges": [{"source": "$graphify-root$_antigravity_instructions_md", "target": "$graphify-root$_antigravity_instructions_graphify", "relation": "contains", "confidence": "EXTRACTED", "source_file": ".antigravity/instructions.md", "source_location": "L1", "weight": 1.0}], "input_tokens": 0, "output_tokens": 0}

View File

@ -0,0 +1 @@
{"nodes": [{"id": "$graphify-root$_agents_workflows_graphify_md", "label": "graphify.md", "file_type": "document", "source_file": ".agents/workflows/graphify.md", "source_location": "L1"}, {"id": "$graphify-root$_agents_workflows_graphify_workflow_graphify", "label": "Workflow: graphify", "file_type": "document", "source_file": ".agents/workflows/graphify.md", "source_location": "L6"}], "edges": [{"source": "$graphify-root$_agents_workflows_graphify_md", "target": "$graphify-root$_agents_workflows_graphify_workflow_graphify", "relation": "contains", "confidence": "EXTRACTED", "source_file": ".agents/workflows/graphify.md", "source_location": "L6", "weight": 1.0}], "input_tokens": 0, "output_tokens": 0}

View File

@ -0,0 +1 @@
{"nodes": [{"id": "$graphify-root$_claude_claude_md", "label": "CLAUDE.md", "file_type": "document", "source_file": ".claude/CLAUDE.md", "source_location": "L1"}, {"id": "$graphify-root$_claude_claude_graphify", "label": "graphify", "file_type": "document", "source_file": ".claude/CLAUDE.md", "source_location": "L1"}], "edges": [{"source": "$graphify-root$_claude_claude_md", "target": "$graphify-root$_claude_claude_graphify", "relation": "contains", "confidence": "EXTRACTED", "source_file": ".claude/CLAUDE.md", "source_location": "L1", "weight": 1.0}], "input_tokens": 0, "output_tokens": 0}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,9 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: canino_backend_stage container_name: canino_backend_stage
restart: always restart: always
dns:
- 217.218.127.127
- 217.218.155.155
environment: environment:
- DATABASE_URL=postgresql://canino_stage:caninopassword_stage@db_stage:5432/caninodb_stage?schema=public - DATABASE_URL=postgresql://canino_stage:caninopassword_stage@db_stage:5432/caninodb_stage?schema=public
- REDIS_HOST=redis_stage - REDIS_HOST=redis_stage
@ -56,6 +59,9 @@ services:
VITE_API_URL: "https://stageapi.canina.ir" VITE_API_URL: "https://stageapi.canina.ir"
container_name: canino_frontend_stage container_name: canino_frontend_stage
restart: always restart: always
dns:
- 217.218.127.127
- 217.218.155.155
labels: labels:
- "traefik.enable=true" - "traefik.enable=true"
- "traefik.http.routers.canina-stage.rule=Host(`stage.canina.ir`) || Host(`stageadmin.canina.ir`)" - "traefik.http.routers.canina-stage.rule=Host(`stage.canina.ir`) || Host(`stageadmin.canina.ir`)"