chore: first commit
This commit is contained in:
Executable
+22
@@ -0,0 +1,22 @@
|
||||
import { ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { Type } from "class-transformer";
|
||||
import { IsNotEmpty, IsNumber, IsOptional, Max, Min } from "class-validator";
|
||||
|
||||
export class PaginationDto {
|
||||
@IsOptional()
|
||||
@IsNotEmpty()
|
||||
@IsNumber()
|
||||
@Min(1)
|
||||
@Type(() => Number)
|
||||
@ApiPropertyOptional({ type: "number", required: false })
|
||||
page?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsNotEmpty()
|
||||
@IsNumber()
|
||||
@Min(1)
|
||||
@Max(50)
|
||||
@Type(() => Number)
|
||||
@ApiPropertyOptional({ type: "number", required: false })
|
||||
limit?: number;
|
||||
}
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
import { ApiProperty, PartialType } from "@nestjs/swagger";
|
||||
import { IsNotEmpty, IsUUID } from "class-validator";
|
||||
|
||||
import { CommonMessage } from "../enums/message.enum";
|
||||
|
||||
export class ParamDto {
|
||||
@IsNotEmpty({ message: CommonMessage.ID_REQUIRED })
|
||||
@IsUUID("7", { message: CommonMessage.ID_SHOULD_BE_UUID })
|
||||
@ApiProperty({ description: "Id of the entity", example: "8b1e8b1e-8b1e-8b1e-8b1e-8b1e8b1e8b1e" })
|
||||
id: string;
|
||||
}
|
||||
|
||||
export class OptionalParamDto extends PartialType(ParamDto) {}
|
||||
|
||||
export class ParamNumberIdDto {
|
||||
@IsNotEmpty({ message: CommonMessage.ID_REQUIRED })
|
||||
@ApiProperty({ description: "Id of the entity", example: "20" })
|
||||
id: string;
|
||||
}
|
||||
Executable
+15
@@ -0,0 +1,15 @@
|
||||
// export const AUTH_THROTTLE = "AUTH_THROTTLE";
|
||||
export const AUTH_THROTTLE_TTL = 5 * 60 * 1000;
|
||||
export const AUTH_THROTTLE_LIMIT = 5;
|
||||
export const AUTH__REFRESH_THROTTLE_TTL = 10 * 60 * 1000;
|
||||
export const AUTH__REFRESH_THROTTLE_LIMIT = 10;
|
||||
//
|
||||
export const CONSOLE_JWT_STRATEGY_NAME = "console_jwt_strategy";
|
||||
export const LOCAL_JWT_STRATEGY_NAME = "local_jwt_strategy";
|
||||
|
||||
export const DANAK_IMAPS_SERVER = "imaps.danakcorp.com";
|
||||
export const DANAK_SMTPS_SERVER = "smtps.danakcorp.com";
|
||||
export const DANAK_IMAPS_PORT = 993;
|
||||
export const DANAK_SMTPS_PORT = 465;
|
||||
export const DANAK_IMAPS_ENCRYPTION = "TLS";
|
||||
export const DANAK_SMTPS_ENCRYPTION = "TLS";
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
export const ADMIN_ROUTE = "shouldAdmin";
|
||||
import { SetMetadata } from "@nestjs/common";
|
||||
|
||||
export const AdminRoute = (isAdminRoute: boolean = true) => SetMetadata(ADMIN_ROUTE, isAdminRoute);
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { UseGuards, applyDecorators } from "@nestjs/common";
|
||||
import { ApiBearerAuth } from "@nestjs/swagger";
|
||||
|
||||
import { JwtAuthGuard } from "../../modules/auth/guards/auth.guard";
|
||||
|
||||
export function AuthGuards() {
|
||||
return applyDecorators(UseGuards(JwtAuthGuard), ApiBearerAuth("authorization"));
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { ExecutionContext, createParamDecorator } from "@nestjs/common";
|
||||
import { FastifyRequest } from "fastify";
|
||||
|
||||
/**
|
||||
* Extracts the business ID from the request header
|
||||
* @example
|
||||
* ```typescript
|
||||
* @Get()
|
||||
* findAll(@BusinessIdHeader() businessId: string) {
|
||||
* // Use businessId
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export const BusinessIdHeader = createParamDecorator((headerName: string = "X-Business-Id", ctx: ExecutionContext) => {
|
||||
const req = ctx.switchToHttp().getRequest<FastifyRequest>();
|
||||
return req.headers[headerName.toLocaleLowerCase()];
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
import { ExecutionContext, createParamDecorator } from "@nestjs/common";
|
||||
import { FastifyRequest } from "fastify";
|
||||
|
||||
import { Business } from "../../modules/businesses/entities/business.entity";
|
||||
|
||||
export const BusinessDec = createParamDecorator((data: keyof Business | undefined, ctx: ExecutionContext) => {
|
||||
const req = ctx.switchToHttp().getRequest<FastifyRequest>();
|
||||
const business = req.business;
|
||||
|
||||
return data ? business?.[data] : business;
|
||||
});
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import { ValidationArguments, ValidationOptions, ValidatorConstraint, ValidatorConstraintInterface, registerDecorator } from "class-validator";
|
||||
|
||||
export function isValidIranianNationalCode(nationalCode: string): boolean {
|
||||
if (!/^\d{10}$/.test(nationalCode)) return false;
|
||||
|
||||
const digits = nationalCode.split("").map(Number);
|
||||
const controlDigit = digits[9];
|
||||
const sum = digits.slice(0, 9).reduce((acc, digit, index) => acc + digit * (10 - index), 0);
|
||||
const remainder = sum % 11;
|
||||
|
||||
return (remainder < 2 && controlDigit === remainder) || (remainder >= 2 && controlDigit === 11 - remainder);
|
||||
}
|
||||
|
||||
@ValidatorConstraint({ async: false })
|
||||
export class IsNationalCodeConstraint implements ValidatorConstraintInterface {
|
||||
validate(value: unknown, _args: ValidationArguments) {
|
||||
return typeof value === "string" && isValidIranianNationalCode(value);
|
||||
}
|
||||
|
||||
defaultMessage(_args: ValidationArguments) {
|
||||
return `Invalid Iranian national code :${_args.value}`;
|
||||
}
|
||||
}
|
||||
|
||||
export function IsNationalCode(validationOptions?: ValidationOptions) {
|
||||
return function (object: object, propertyName: string) {
|
||||
registerDecorator({
|
||||
target: object.constructor,
|
||||
propertyName: propertyName,
|
||||
options: validationOptions,
|
||||
constraints: [],
|
||||
validator: IsNationalCodeConstraint,
|
||||
});
|
||||
};
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { applyDecorators } from "@nestjs/common";
|
||||
import { ApiQuery } from "@nestjs/swagger";
|
||||
|
||||
export function Pagination() {
|
||||
return applyDecorators(
|
||||
ApiQuery({ name: "page", example: 1, required: false, type: "number" }),
|
||||
ApiQuery({ name: "limit", example: 10, required: false, type: "number" }),
|
||||
);
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// import { SetMetadata } from "@nestjs/common";
|
||||
|
||||
// import { PermissionEnum } from "../../modules/users/enums/permission.enum";
|
||||
|
||||
// export const PERMISSION_KEY = "permissions";
|
||||
// export const PermissionsDec = (...permissions: PermissionEnum[]) => SetMetadata(PERMISSION_KEY, permissions);
|
||||
@@ -0,0 +1,12 @@
|
||||
import { UseGuards, applyDecorators } from "@nestjs/common";
|
||||
import { Throttle, ThrottlerGuard } from "@nestjs/throttler";
|
||||
|
||||
import { AUTH__REFRESH_THROTTLE_LIMIT, AUTH__REFRESH_THROTTLE_TTL } from "../constants";
|
||||
|
||||
export const RateLimit = (limit: number, ttl: number) => applyDecorators(Throttle({ default: { limit, ttl } }), UseGuards(ThrottlerGuard));
|
||||
|
||||
// Predefined rate limits for common scenarios
|
||||
export const StrictRateLimit = () => RateLimit(5, 60000); // 5 requests per minute
|
||||
export const StandardRateLimit = () => RateLimit(30, 60000); // 30 requests per minute
|
||||
export const MailSendRateLimit = () => RateLimit(10, 60000); // 10 emails per minute
|
||||
export const RefreshTokenRateLimit = () => RateLimit(AUTH__REFRESH_THROTTLE_LIMIT, AUTH__REFRESH_THROTTLE_TTL); // 10 emails per minute
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
// import { SetMetadata } from "@nestjs/common";
|
||||
|
||||
// export const ROLES_KEY = "roles";
|
||||
// export const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles);
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
import { SetMetadata } from "@nestjs/common";
|
||||
|
||||
export const SKIP_AUTH_KEY = "skipAuth";
|
||||
|
||||
export const SkipAuth = () => SetMetadata(SKIP_AUTH_KEY, true);
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
import { ExecutionContext, createParamDecorator } from "@nestjs/common";
|
||||
import { FastifyRequest } from "fastify";
|
||||
|
||||
import { ITokenPayload } from "../../modules/auth/interfaces/IToken-payload";
|
||||
|
||||
declare module "fastify" {
|
||||
interface FastifyRequest {
|
||||
user?: ITokenPayload;
|
||||
}
|
||||
}
|
||||
|
||||
export const UserDec = createParamDecorator((data: keyof ITokenPayload | undefined, ctx: ExecutionContext) => {
|
||||
const req = ctx.switchToHttp().getRequest<FastifyRequest>();
|
||||
const user = req.user;
|
||||
|
||||
return data ? user?.[data] : user;
|
||||
});
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
import { Opt, PrimaryKey, Property, sql } from "@mikro-orm/core";
|
||||
import { v7 } from "uuid";
|
||||
|
||||
export abstract class BaseEntity {
|
||||
@PrimaryKey({ type: "uuid" })
|
||||
id = v7();
|
||||
|
||||
@Property({ default: sql.now(), type: "timestamptz" })
|
||||
createdAt: Date & Opt;
|
||||
|
||||
@Property({ default: sql.now(), type: "timestamptz" })
|
||||
updatedAt: Date & Opt;
|
||||
|
||||
@Property({ nullable: true })
|
||||
deletedAt?: Date;
|
||||
}
|
||||
Executable
+222
@@ -0,0 +1,222 @@
|
||||
export const enum AuthMessage {
|
||||
UNAUTHORIZED_ACCESS = "شما دسترسی لازم برای این عملیات را ندارید.",
|
||||
PHONE_REGISTERED = "شماره ثبت شد",
|
||||
INVALID_PHONE_FORMAT = "فرمت شماره تلفن صحیح نیست",
|
||||
OTP_SENT = "کد یکبار مصرف به شماره شما ارسال شد.",
|
||||
INVALID_PHONE = "شماره موبایل اشتباه می باشد",
|
||||
INVALID_CREDENTIAL = "شماره موبایل یا رمز عبور اشتباه می باشد",
|
||||
OTP_FAILED = "کد یا شماره موبایل اشتباه است",
|
||||
LOGIN_SUCCESS = "ورود با موفقیت انجام شد",
|
||||
PASSWORD_LOGIN_SUCCESS = "با موفقیت وارد شدید",
|
||||
FORGOT_PASSWORD_SUCCESS = "درخواست فراموشی رمز عبور با موفقیت ثبت شد",
|
||||
PASSWORD_SET_SUCCESS = "پسورد با موفقیت تنظیم شد",
|
||||
PASSWORD_UPDATE_SUCCESS = "رمز عبور شما تغییر کرد",
|
||||
INVALID_OTP = "کد صحیح نمیباشد یا منقضی شده است",
|
||||
PASSWORD_MISMATCH = "رمز عبور یکسان نیست",
|
||||
INVALID_PASSWORD = "ایمیل یا رمز عبور اشتباه است",
|
||||
INVALID_REPEAT_PASSWORD = "تکرار رمز عبور اشتباه است",
|
||||
EMAIL_NOT_EMPTY = "ایمیل نمیتواند خالی باشد.",
|
||||
INVALID_EMAIL_FORMAT = "فرمت ایمیل صحیح نیست",
|
||||
PasswordNotEmpty = "پسورد نمیتواند خالی باشد.",
|
||||
USER_NOT_FOUND = "کاربری با این شماره وجود ندارد",
|
||||
USER_EXISTS = "با این شماره قبلا ثبت نام شده است",
|
||||
USER_REGISTER_SUCCESS = "ثبت نام موفقیت آمیز بود",
|
||||
INVALID_USER = "کاربری با این مشخصات یافت نشد",
|
||||
PHONE_NOT_FOUND = "کاربری با این شماره یافت نشد",
|
||||
TOKEN_EXPIRED = "توکن منقضی شده است",
|
||||
TOKEN_INVALID = "توکن نامعتبر است",
|
||||
BANNED = "در حال حاضر شما امکان دسترسی به این سرویس را ندارید",
|
||||
PHONE_EXISTS = "شماره تلفن قبلا ثبت شده است",
|
||||
ADMIN_CREATED = "ادمین با موفقیت ایجاد شد",
|
||||
PERM_NOT_FOUND = "دسترسی یافت نشد",
|
||||
INVALID_PASS_FORMAT = "فرمت رمز عبور صحیح نیست",
|
||||
PHONE_NOT_EMPTY = "شماره تلفن نمیتواند خالی باشد",
|
||||
PASSWORD_FORMAT_INVALID = "رمز عبور باید به صورت رشته باشد",
|
||||
OTP_FORMAT_INVALID = "کد یکبار مصرف باید عددی و ۵ رقمی باشد",
|
||||
PHONE_FORMAT_INVALID = "شماره تلفن باید معتبر و به فرمت ایران باشد",
|
||||
TOKEN_NOT_EMPTY = "توکن نمیتواند خالی باشد",
|
||||
PASSWORD_NOT_EMPTY = "رمز عبور نمیتواند خالی باشد",
|
||||
PASSWORD_CHANGED_SUCCESSFULLY = "رمز عبور با موفقیت تغییر کرد",
|
||||
PASSWORD_CONFIRMATION_NOT_EMPTY = "تایید رمز عبور نمیتواند خالی باشد",
|
||||
PASSWORD_LENGTH = "رمز عبور باید حداقل ۸ کاراکتر باشد",
|
||||
OTP_NOT_EMPTY = "کد یکبار مصرف نمیتواند خالی باشد",
|
||||
LAST_PASSWORD_NOT_EMPTY = "رمز عبور قبلی نمیتواند خالی باشد",
|
||||
FIRST_NAME_NOT_EMPTY = "نام نمیتواند خالی باشد",
|
||||
LAST_NAME_NOT_EMPTY = "نام خانوادگی نمیتواند خالی باشد",
|
||||
FIRST_NAME_SHOULD_BE_BETWEEN_2_AND_50 = "نام باید بین ۲ تا ۵۰ کاراکتر باشد",
|
||||
LAST_NAME_SHOULD_BE_BETWEEN_2_AND_50 = "نام خانوادگی باید بین ۲ تا ۵۰ کاراکتر باشد",
|
||||
BIRTH_DATE_NOT_EMPTY = "تاریخ تولد نمیتواند خالی باشد",
|
||||
NATIONAL_CODE_INCORRECT = "کد ملی باید ۱۰ رقمی باشد",
|
||||
NATIONAL_NOT_EMPTY = "کد ملی نمیتواند خالی باشد",
|
||||
OTP_ALREADY_SENT = "کد یکبار مصرف قبلا ارسال شده است",
|
||||
TOO_MANY_REQUESTS = "تعداد درخواست های شما بیش از حد مجاز است",
|
||||
NOT_ADMIN = "شما دسترسی به بخش ادمین ندارید",
|
||||
PHONE_SHOULD_BE_11_DIGIT = "شماره تلفن باید ۱۱ رقم باشد",
|
||||
TIMESTAMP_NOT_EMPTY = "زمان نمیتواند خالی باشد",
|
||||
ADMIN_CAN_NOT_LOGIN = "ادمین نمیتواند وارد شود",
|
||||
NATIONAL_CODE_INVALID = "کد ملی نامعتبر است",
|
||||
INVALID_REFRESH_TOKEN = "توکن رفرش نامعتبر است",
|
||||
REFRESH_TOKEN_EXPIRED = "توکن رفرش منقضی شده است",
|
||||
LOGOUT_SUCCESS = "خروج با موفقیت انجام شد",
|
||||
CURRENT_PASSWORD_INVALID = "رمز عبور فعلی نامعتبر است",
|
||||
TOKEN_EXPIRED_OR_INVALID = "توکن منقضی شده یا نامعتبر است",
|
||||
ACCESS_DENIED = "دسترسی شما محدود شده است",
|
||||
USER_ACCOUNT_INACTIVE = "حساب کاربری شما غیر فعال است",
|
||||
}
|
||||
|
||||
export const enum UserMessage {
|
||||
USER_NOT_FOUND = "کاربری با این شماره وجود ندارد",
|
||||
USER_EXISTS = "با این شماره قبلا ثبت نام شده است",
|
||||
USER_REGISTER_SUCCESS = "ثبت نام موفقیت آمیز بود",
|
||||
INVALID_USER = "کاربری با این مشخصات یافت نشد",
|
||||
EMAIL_ADDRESS_ALREADY_EXISTS = "ایمیل قبلا ثبت شده است",
|
||||
EMAIL_USER_NOT_FOUND = "ایمیل یافت نشد",
|
||||
EMAIL_USER_DELETED_SUCCESSFULLY = "ایمیل با موفقیت حذف شد",
|
||||
FAILED_TO_DELETE_EMAIL_USER = "خطا در حذف ایمیل",
|
||||
EMAIL_USER_QUOTA_UPDATED_SUCCESSFULLY = "ایمیل با موفقیت به روز رسانی شد",
|
||||
FAILED_TO_UPDATE_EMAIL_USER_QUOTA = "خطا در به روز رسانی حجم ایمیل",
|
||||
}
|
||||
|
||||
export const enum CommonMessage {
|
||||
VALIDITY_TYPE_REQUIRED = "نوع اعتبار سنجی مورد نیاز است",
|
||||
THIS_FILED_IS_REQUIRED = "این فیلد الزامی است",
|
||||
VALID_FOR_CHOOSE = "معتبر برای انتخاب",
|
||||
UPDATE_SUCCESS = "با موفقیت به روز رسانی شد",
|
||||
CREATED = "با موفقیت ایجاد شد",
|
||||
DELETED = "با موفقیت حذف شد",
|
||||
ID_REQUIRED = "شناسه مورد نیاز است",
|
||||
ID_SHOULD_BE_UUID = "شناسه باید یک یو یو آی دی باشد",
|
||||
PaymentTypeQueryNotEmpty = "نوع پرداخت نمیتواند خالی باشد",
|
||||
SEARCH_QUERY_STRING = "رشته جستجو باید یک رشته باشد",
|
||||
UPDATED = "با موفقیت آپدیت شد",
|
||||
IS_ACTIVE_SHOULD_BE_1_0 = "وضعیت باید یکی از مقادیر ۰ و ۱ باشد",
|
||||
DATE_MUST_BE_DATE = "تاریخ باید یک تاریخ معتبر به صورت رشته باشد",
|
||||
}
|
||||
|
||||
export const enum UploaderMessage {
|
||||
UPLOAD_FILE_INVALID = "فایل معتبر نیست",
|
||||
}
|
||||
|
||||
export const enum EmailMessage {
|
||||
EMAIL_VERIFICATION = "تایید ایمیل",
|
||||
EMAIL_SENDING_FAILED = "ارسال ایمیل با خطا مواجه شد",
|
||||
LOGIN = "ورود به سیستم",
|
||||
INVOICE = "فاکتور",
|
||||
WALLET = "اعلان کیف پول",
|
||||
TICKET = "تیکت پشتیبانی",
|
||||
ANNOUNCEMENT = "اعلان",
|
||||
PAYMENT_REMINDER = "یادآوری پرداخت",
|
||||
PAYMENT_CANCELLATION = "لغو پرداخت",
|
||||
}
|
||||
|
||||
export const enum SmsMessage {
|
||||
SEND_SMS_ERROR = "خطا در ارسال پیامک",
|
||||
}
|
||||
|
||||
export const enum BusinessMessage {
|
||||
NOT_FOUND = "کسب و کار یافت نشد",
|
||||
BUSINESS_ID_REQUIRED = "شناسه کسب و کار مورد نیاز است",
|
||||
SLUG_REQUIRED = "اسلاگ مورد نیاز است",
|
||||
SLUG_MUST_BE_STRING = "اسلاگ باید یک رشته باشد",
|
||||
DOMAIN_INVALID = "دامنه وارد شده معتبر نیست",
|
||||
DOMAIN_UPDATED = "دامنه با موفقیت بهروزرسانی شد",
|
||||
DOMAIN_VERIFICATION_INITIATED = "فرآیند تایید دامنه آغاز شد",
|
||||
DOMAIN_VERIFICATION_FAILED = "تایید دامنه با خطا مواجه شد",
|
||||
DOMAIN_VERIFICATION_SUCCESS = "دامنه با موفقیت تایید شد",
|
||||
DOMAIN_VERIFICATION_METHOD_INVALID = "روش تایید دامنه نامعتبر است",
|
||||
DOMAIN_ALREADY_VERIFIED = "این دامنه قبلا تایید شده است",
|
||||
DOMAIN_REQUIRED = "دامنه مورد نیاز است",
|
||||
DOMAIN_MUST_BE_STRING = "دامنه باید یک رشته باشد",
|
||||
STAFF_NOT_FOUND = "کاربر ادمین یافت نشد",
|
||||
ZARINPAL_MERCHANT_ID_REQUIRED = "شناسه مرچنت زرین پال مورد نیاز است",
|
||||
ZARINPAL_MERCHANT_ID_STRING = "شناسه مرچنت زرین پال باید یک رشته باشد",
|
||||
LOGO_URL_REQUIRED = "آدرس تصویر لوگو مورد نیاز است",
|
||||
LOGO_URL_STRING = "آدرس تصویر لوگو باید یک رشته باشد",
|
||||
LOGO_URL_INVALID = "آدرس تصویر لوگو معتبر نیست",
|
||||
BUSINESS_SETTINGS_UPDATED = "تنظیمات کسب و کار با موفقیت به روز رسانی شد",
|
||||
NAME_REQUIRED = "نام کسب و کار مورد نیاز است",
|
||||
NAME_STRING = "نام کسب و کار باید یک رشته باشد",
|
||||
DOMAIN_CONNECTED = "دامنه با موفقیت متصل شد",
|
||||
DOMAIN_NOT_CONNECTED = "دامنه به سرور ما متصل نشد",
|
||||
DOMAIN_NOT_FOUND = "دامنه یافت نشد",
|
||||
DOMAIN_VERIFICATION_TOKEN_REQUIRED = "توکن تایید دامنه مورد نیاز است",
|
||||
}
|
||||
|
||||
export const enum DomainMessage {
|
||||
// Domain Ownership & Verification
|
||||
NOT_BELONG_TO_BUSINESS = "دامنه به این کسب و کار تعلق ندارد",
|
||||
NOT_VERIFIED = "دامنه باید تایید شده باشد",
|
||||
DOMAIN_NOT_FOUND = "دامنه یافت نشد",
|
||||
DOMAIN_ALREADY_EXISTS = "دامنه [name] قبلا ثبت شده است",
|
||||
DOMAIN_DELETED_SUCCESSFULLY = "دامنه با موفقیت حذف شد",
|
||||
VERIFICATION_NOT_FOUND = "تایید دامنه یافت نشد",
|
||||
NO_DOMAIN_FOUND = "دامنه ای یافت نشد",
|
||||
DOMAIN_CHECKED = "دامنه با موفقیت بررسی شد",
|
||||
|
||||
// Domain Creation & Setup
|
||||
DOMAIN_CREATED_WITH_RECORDS = "دامنه [name] با موفقیت ایجاد شد و تمام رکوردهای مورد نیاز تولید گردید",
|
||||
ALL_REQUIRED_RECORDS_GENERATED = "تمام رکوردهای مورد نیاز (MX, SPF, DMARC, DKIM) به طور خودکار برای شما تولید شدهاند",
|
||||
ESTIMATED_PROPAGATION_TIME = "تغییرات DNS معمولاً ۱۵ دقیقه تا ۴۸ ساعت در سراسر جهان منتشر میشود",
|
||||
|
||||
// DNS Records Instructions
|
||||
ADD_MX_RECORD = "یک رکورد MX با نام [name] که به [value] با اولویت [priority] اشاره کند اضافه کنید",
|
||||
ADD_TXT_RECORD = "یک رکورد TXT با نام [name] و مقدار [value] اضافه کنید",
|
||||
ADD_DKIM_RECORD = "یک رکورد TXT با نام [name] و مقدار [value] اضافه کنید (کلید عمومی DKIM)",
|
||||
ADD_DMARC_RECORD = "یک رکورد TXT با نام [name] و مقدار [value] اضافه کنید (سیاست DMARC)",
|
||||
ADD_CNAME_RECORD = "یک رکورد CNAME با نام [name] که به [value] اشاره کند اضافه کنید",
|
||||
ADD_GENERIC_RECORD = "یک رکورد [type] با نام [name] و مقدار [value] اضافه کنید",
|
||||
|
||||
// Domain Setup Steps
|
||||
STEP_LOGIN_DNS_PANEL = "وارد پنل مدیریت DNS ثبت کننده دامنه خود شوید",
|
||||
STEP_ADD_ALL_RECORDS = "تمام رکوردهای DNS مورد نیاز لیست شده در بالا را به زون DNS دامنه خود اضافه کنید",
|
||||
STEP_INCLUDE_ALL_TYPES = "مطمئن شوید که رکوردهای MX، SPF، DMARC و DKIM را برای عملکرد کامل ایمیل شامل کردهاید",
|
||||
STEP_WAIT_PROPAGATION = "منتظر انتشار DNS بمانید (معمولاً ۱۵ دقیقه تا ۴۸ ساعت)",
|
||||
STEP_USE_CHECK_ENDPOINT = "از نقطه پایانی 'بررسی DNS' برای تایید تنظیم صحیح رکوردهای خود استفاده کنید",
|
||||
STEP_DOMAIN_READY = "پس از تایید، دامنه شما برای سرویسهای ایمیل آماده خواهد بود!",
|
||||
|
||||
// Status Messages
|
||||
RECORDS_PENDING_VERIFICATION = "[count] رکورد DNS هنوز در انتظار تایید هستند",
|
||||
ALL_REQUIRED_RECORDS_MUST_BE_CONFIGURED = "تمام [count] رکورد مورد نیاز باید برای کار درست ایمیل تنظیم شوند",
|
||||
DOMAIN_FULLY_VERIFIED = "دامنه شما به طور کامل تایید شده و برای ایمیل آماده است!",
|
||||
EMAIL_ACCOUNTS_READY = "اکنون میتوانید حسابهای ایمیل ایجاد کرده و شروع به ارسال/دریافت ایمیل کنید",
|
||||
|
||||
// Verification Status
|
||||
DOMAIN_VERIFICATION_INITIATED = "فرآیند تایید دامنه آغاز شد",
|
||||
DOMAIN_VERIFICATION_FAILED = "تایید دامنه با خطا مواجه شد",
|
||||
DOMAIN_VERIFICATION_SUCCESS = "دامنه با موفقیت تایید شد",
|
||||
DOMAIN_VERIFICATION_PENDING = "تایید دامنه در انتظار است",
|
||||
|
||||
// DNS Record Status
|
||||
DNS_RECORD_VERIFIED = "رکورد DNS تایید شد",
|
||||
DNS_RECORD_FAILED = "رکورد DNS تایید نشد",
|
||||
DNS_RECORD_NOT_FOUND_OR_MISMATCH = "رکورد DNS یافت نشد یا مقدار مطابقت ندارد",
|
||||
|
||||
// DKIM Messages
|
||||
DKIM_ENABLED_AUTOMATICALLY = "DKIM به طور خودکار برای دامنه [name] فعال شد",
|
||||
DKIM_FAILED_TO_CREATE = "ایجاد DKIM برای دامنه [name] ناموفق بود",
|
||||
DKIM_ENABLED_SUCCESSFULLY = "DKIM برای دامنه [name] با موفقیت فعال شد",
|
||||
|
||||
// Error Messages
|
||||
FAILED_TO_VERIFY_DOMAIN = "تایید دامنه [name] ناموفق بود",
|
||||
FAILED_TO_SETUP_MAIL_SERVER = "راهاندازی دامنه [name] در سرور ایمیل ناموفق بود",
|
||||
DOMAIN_CREATION_FAILED = "ایجاد دامنه ناموفق بود",
|
||||
DNS_VERIFICATION_ATTEMPTS_EXCEEDED = "تعداد تلاشهای تایید DNS از حد مجاز بیشتر شد",
|
||||
|
||||
// Service Messages
|
||||
DOMAIN_UPDATED_SUCCESSFULLY = "دامنه بروزرسانی شد",
|
||||
VERIFICATION_TOKEN_PREFIX = "توکن تایید: [token]",
|
||||
RECORD_NEEDS_FIXING = "رکورد [type] برای [name] نیاز به اصلاح دارد: [error]",
|
||||
RECORD_PENDING_VERIFICATION_DETAIL = "رکورد [type] برای [name] هنوز در انتظار تایید است. لطفا مطمئن شوید که انتشار DNS کامل شده است.",
|
||||
RECORD_DESCRIPTION_EMAIL_FUNCTIONALITY = "رکورد [type] برای عملکرد ایمیل",
|
||||
BUSINESS_ALREADY_HAS_DOMAIN = "این کسب و کار قبلا دامنه ای دارد",
|
||||
}
|
||||
|
||||
export const enum MailServerMessage {
|
||||
FAILED_TO_CREATE_ACCOUNT = "خطا در ایجاد ایمیل",
|
||||
FAILED_TO_CREATE_DKIM_KEY = "FAILED_TO_CREATE_DKIM_KEY",
|
||||
}
|
||||
|
||||
export const enum DnsRecordMessage {
|
||||
DNS_RECORD_NOT_FOUND = "رکورد DNS یافت نشد",
|
||||
DNS_RECORD_DELETED = "رکورد DNS با موفقیت حذف شد",
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export interface ErrorResponse {
|
||||
statusCode: number;
|
||||
success: boolean;
|
||||
error: {
|
||||
message: string | string[];
|
||||
timestamp?: string;
|
||||
path?: string;
|
||||
};
|
||||
}
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
export interface IPageFormat {
|
||||
page: number;
|
||||
limit: number;
|
||||
totalItems: number;
|
||||
totalPages: number;
|
||||
prevPage: string | boolean;
|
||||
nextPage: string | boolean;
|
||||
}
|
||||
|
||||
export interface PaginationQuery {
|
||||
page?: string;
|
||||
limit?: string;
|
||||
}
|
||||
|
||||
export interface PaginatedResponse {
|
||||
paginate?: boolean;
|
||||
count?: number;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { ValueProvider } from "@nestjs/common";
|
||||
import { Logger } from "@nestjs/common";
|
||||
|
||||
export const MIKRO_ORM_QUERY_LOGGER = "MikroOrmQueryLogger";
|
||||
|
||||
export const MikroOrmQueryLogger: ValueProvider = {
|
||||
provide: MIKRO_ORM_QUERY_LOGGER,
|
||||
useValue: new Logger("mikro-orm"),
|
||||
};
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
import { OnWorkerEvent, WorkerHost } from "@nestjs/bullmq";
|
||||
import { Logger } from "@nestjs/common";
|
||||
import { Job } from "bullmq";
|
||||
|
||||
export abstract class WorkerProcessor extends WorkerHost {
|
||||
protected readonly logger = new Logger(WorkerProcessor.name);
|
||||
|
||||
@OnWorkerEvent("completed")
|
||||
onCompleted(job: Job) {
|
||||
const { id, name, queueName, finishedOn, returnvalue } = job;
|
||||
const completionTime = finishedOn ? new Date(finishedOn).toISOString() : "";
|
||||
this.logger.log(`Job id: ${id}, name: ${name} completed in queue ${queueName} on ${completionTime}. Result: ${returnvalue}`);
|
||||
}
|
||||
|
||||
@OnWorkerEvent("progress")
|
||||
onProgress(job: Job) {
|
||||
const { id, name, progress } = job;
|
||||
this.logger.log(`Job id: ${id}, name: ${name} completes ${progress}%`);
|
||||
}
|
||||
|
||||
@OnWorkerEvent("failed")
|
||||
onFailed(job: Job) {
|
||||
const { id, name, queueName, failedReason } = job;
|
||||
this.logger.error(`Job id: ${id}, name: ${name} failed in queue ${queueName}. Failed reason: ${failedReason}`);
|
||||
}
|
||||
|
||||
@OnWorkerEvent("active")
|
||||
onActive(job: Job) {
|
||||
const { id, name, queueName, timestamp } = job;
|
||||
const startTime = timestamp ? new Date(timestamp).toISOString() : "";
|
||||
this.logger.log(`Job id: ${id}, name: ${name} starts in queue ${queueName} on ${startTime}.`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user