build: include production build artifacts in repo

This commit is contained in:
S. Esmaeili
2026-10-24 10:11:05 +03:30
parent dfd8a82809
commit 7399812d0e
213 changed files with 65702 additions and 2 deletions
+60
View File
@@ -0,0 +1,60 @@
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { createParamDecorator, ForbiddenException, Injectable, SetMetadata, UnauthorizedException, UseGuards, applyDecorators, } from "@nestjs/common";
import { Reflector } from "@nestjs/core";
import { JwtService } from "@nestjs/jwt";
import { PrismaService } from "../prisma/prisma.service.js";
const ROLES_KEY = "roles";
let JwtAuthGuard = class JwtAuthGuard {
jwt;
reflector;
prisma;
constructor(jwt, reflector, prisma) {
this.jwt = jwt;
this.reflector = reflector;
this.prisma = prisma;
}
async canActivate(ctx) {
const req = ctx.switchToHttp().getRequest();
const [scheme, token] = (req.headers.authorization ?? "").split(" ");
if (scheme !== "Bearer" || !token)
throw new UnauthorizedException("ابتدا وارد شوید");
let payload;
try {
payload = await this.jwt.verifyAsync(token);
}
catch {
throw new UnauthorizedException("نشست شما منقضی شده است");
}
const user = await this.prisma.adminUser.findUnique({ where: { id: payload.sub } });
if (!user?.isActive)
throw new UnauthorizedException("حساب کاربری غیرفعال است");
req.user = { id: user.id, phone: user.phone, name: user.name, role: user.role };
const roles = this.reflector.getAllAndOverride(ROLES_KEY, [
ctx.getHandler(),
ctx.getClass(),
]);
if (roles?.length && !roles.includes(user.role)) {
throw new ForbiddenException("برای این کار دسترسی ندارید");
}
return true;
}
};
JwtAuthGuard = __decorate([
Injectable(),
__metadata("design:paramtypes", [JwtService,
Reflector,
PrismaService])
], JwtAuthGuard);
export { JwtAuthGuard };
export const AdminAuth = (...roles) => applyDecorators(SetMetadata(ROLES_KEY, roles), UseGuards(JwtAuthGuard));
export const Roles = (...roles) => SetMetadata(ROLES_KEY, roles);
export const CurrentUser = createParamDecorator((_, ctx) => ctx.switchToHttp().getRequest().user);
//# sourceMappingURL=auth.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/common/auth.ts"],"names":[],"mappings":"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"}
+70
View File
@@ -0,0 +1,70 @@
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var AuditService_1, RevalidateService_1;
import { Global, Injectable, Logger, Module } from "@nestjs/common";
import { env } from "../config/env.js";
import { PrismaService } from "../prisma/prisma.service.js";
let AuditService = AuditService_1 = class AuditService {
prisma;
logger = new Logger(AuditService_1.name);
constructor(prisma) {
this.prisma = prisma;
}
log(userId, action, entity, entityId = "", summary = "") {
this.prisma.auditLog
.create({ data: { userId, action, entity, entityId: String(entityId), summary } })
.catch((e) => this.logger.warn(`audit log failed: ${String(e)}`));
}
};
AuditService = AuditService_1 = __decorate([
Injectable(),
__metadata("design:paramtypes", [PrismaService])
], AuditService);
export { AuditService };
let RevalidateService = RevalidateService_1 = class RevalidateService {
logger = new Logger(RevalidateService_1.name);
timer;
trigger() {
if (!env.WEB_REVALIDATE_URL)
return;
clearTimeout(this.timer);
this.timer = setTimeout(() => void this.run(), 1500);
this.timer.unref();
}
async run() {
try {
const res = await fetch(env.WEB_REVALIDATE_URL, {
method: "POST",
headers: { "x-revalidate-secret": env.REVALIDATE_SECRET ?? "" },
signal: AbortSignal.timeout(5000),
});
if (!res.ok)
this.logger.warn(`site revalidation returned ${res.status}`);
}
catch (e) {
this.logger.warn(`site revalidation failed: ${String(e)}`);
}
}
};
RevalidateService = RevalidateService_1 = __decorate([
Injectable()
], RevalidateService);
export { RevalidateService };
let CommonModule = class CommonModule {
};
CommonModule = __decorate([
Global(),
Module({
providers: [AuditService, RevalidateService],
exports: [AuditService, RevalidateService],
})
], CommonModule);
export { CommonModule };
//# sourceMappingURL=common.module.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"common.module.js","sourceRoot":"","sources":["../../src/common/common.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAIrD,IAAM,YAAY,oBAAlB,MAAM,YAAY;IAGM;IAFZ,MAAM,GAAG,IAAI,MAAM,CAAC,cAAY,CAAC,IAAI,CAAC,CAAC;IAExD,YAA6B,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;IAAG,CAAC;IAEtD,GAAG,CACD,MAAqB,EACrB,MAAc,EACd,MAAc,EACd,WAA4B,EAAE,EAC9B,OAAO,GAAG,EAAE;QAEZ,IAAI,CAAC,MAAM,CAAC,QAAQ;aACjB,MAAM,CAAC,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC;aACjF,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAqB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/E,CAAC;CACF,CAAA;AAhBY,YAAY;IADxB,UAAU,EAAE;qCAI0B,aAAa;GAHvC,YAAY,CAgBxB;;AAOM,IAAM,iBAAiB,yBAAvB,MAAM,iBAAiB;IACX,MAAM,GAAG,IAAI,MAAM,CAAC,mBAAiB,CAAC,IAAI,CAAC,CAAC;IACrD,KAAK,CAA6B;IAE1C,OAAO;QACL,IAAI,CAAC,GAAG,CAAC,kBAAkB;YAAE,OAAO;QACpC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,GAAG;QACf,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,kBAAmB,EAAE;gBAC/C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,qBAAqB,EAAE,GAAG,CAAC,iBAAiB,IAAI,EAAE,EAAE;gBAC/D,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;aAClC,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5E,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,6BAA6B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;CACF,CAAA;AAvBY,iBAAiB;IAD7B,UAAU,EAAE;GACA,iBAAiB,CAuB7B;;AAOM,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,YAAY;IALxB,MAAM,EAAE;IACR,MAAM,CAAC;QACN,SAAS,EAAE,CAAC,YAAY,EAAE,iBAAiB,CAAC;QAC5C,OAAO,EAAE,CAAC,YAAY,EAAE,iBAAiB,CAAC;KAC3C,CAAC;GACW,YAAY,CAAG"}
+59
View File
@@ -0,0 +1,59 @@
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { Catch, HttpStatus } from "@nestjs/common";
import { Prisma } from "../generated/prisma/client.js";
const FIELD_LABELS = {
slug: "اسلاگ",
code: "کد",
email: "ایمیل",
phone: "شماره موبایل",
};
function uniqueFields(meta) {
if (meta?.target)
return Array.isArray(meta.target) ? meta.target : [meta.target];
const constraint = meta?.driverAdapterError?.cause?.constraint;
if (constraint?.fields)
return constraint.fields;
const match = constraint?.index?.match(/^[^_]+_(.+)_key$/);
return match ? match[1].split("_") : [];
}
let PrismaExceptionFilter = class PrismaExceptionFilter {
catch(error, host) {
const res = host.switchToHttp().getResponse();
switch (error.code) {
case "P2002": {
const fields = uniqueFields(error.meta)
.filter((f) => !f.endsWith("Id"))
.map((f) => FIELD_LABELS[f] ?? f)
.join("، ");
return res.status(HttpStatus.CONFLICT).json({
statusCode: HttpStatus.CONFLICT,
message: fields ? `مقدار «${fields}» تکراری است` : "مقدار تکراری است",
});
}
case "P2003":
return res.status(HttpStatus.CONFLICT).json({
statusCode: HttpStatus.CONFLICT,
message: "این مورد به داده‌های دیگری وابسته است",
});
case "P2025":
return res
.status(HttpStatus.NOT_FOUND)
.json({ statusCode: HttpStatus.NOT_FOUND, message: "مورد پیدا نشد" });
default:
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
message: "خطای پایگاه داده",
});
}
}
};
PrismaExceptionFilter = __decorate([
Catch(Prisma.PrismaClientKnownRequestError)
], PrismaExceptionFilter);
export { PrismaExceptionFilter };
//# sourceMappingURL=prisma-exception.filter.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"prisma-exception.filter.js","sourceRoot":"","sources":["../../src/common/prisma-exception.filter.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAsB,KAAK,EAAwB,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE7F,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAEvD,MAAM,YAAY,GAA2B;IAC3C,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,cAAc;CACtB,CAAC;AAQF,SAAS,YAAY,CAAC,IAA4B;IAChD,IAAI,IAAI,EAAE,MAAM;QAAE,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClF,MAAM,UAAU,GAAG,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,UAAU,CAAC;IAC/D,IAAI,UAAU,EAAE,MAAM;QAAE,OAAO,UAAU,CAAC,MAAM,CAAC;IAEjD,MAAM,KAAK,GAAG,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3C,CAAC;AAIM,IAAM,qBAAqB,GAA3B,MAAM,qBAAqB;IAChC,KAAK,CAAC,KAA2C,EAAE,IAAmB;QACpE,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,WAAW,EAAY,CAAC;QAExD,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,IAA8B,CAAC;qBAC9D,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;qBAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;qBAChC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,OAAO,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;oBAC1C,UAAU,EAAE,UAAU,CAAC,QAAQ;oBAC/B,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,MAAM,cAAc,CAAC,CAAC,CAAC,kBAAkB;iBACtE,CAAC,CAAC;YACL,CAAC;YACD,KAAK,OAAO;gBACV,OAAO,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;oBAC1C,UAAU,EAAE,UAAU,CAAC,QAAQ;oBAC/B,OAAO,EAAE,uCAAuC;iBACjD,CAAC,CAAC;YACL,KAAK,OAAO;gBACV,OAAO,GAAG;qBACP,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC;qBAC5B,IAAI,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;YAC1E;gBACE,OAAO,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC;oBACvD,UAAU,EAAE,UAAU,CAAC,qBAAqB;oBAC5C,OAAO,EAAE,kBAAkB;iBAC5B,CAAC,CAAC;QACP,CAAC;IACH,CAAC;CACF,CAAA;AA/BY,qBAAqB;IADjC,KAAK,CAAC,MAAM,CAAC,6BAA6B,CAAC;GAC/B,qBAAqB,CA+BjC"}
+23
View File
@@ -0,0 +1,23 @@
import { BadRequestException } from "@nestjs/common";
import { toIssues } from "@imen/shared";
import { z } from "zod";
z.config(z.locales.fa());
export class ZodPipe {
schema;
constructor(schema) {
this.schema = schema;
}
transform(value) {
const result = this.schema.safeParse(value);
if (!result.success) {
throw new BadRequestException({
statusCode: 400,
message: "اطلاعات واردشده معتبر نیست",
issues: toIssues(result.error),
});
}
return result.data;
}
}
export const IdPipe = new ZodPipe(z.coerce.number().int().positive());
//# sourceMappingURL=zod.pipe.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"zod.pipe.js","sourceRoot":"","sources":["../../src/common/zod.pipe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAsB,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;AAGzB,MAAM,OAAO,OAAO;IACW;IAA7B,YAA6B,MAAS;QAAT,WAAM,GAAN,MAAM,CAAG;IAAG,CAAC;IAE1C,SAAS,CAAC,KAAc;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,mBAAmB,CAAC;gBAC5B,UAAU,EAAE,GAAG;gBACf,OAAO,EAAE,4BAA4B;gBACrC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC;aAC/B,CAAC,CAAC;QACL,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;CACF;AAGD,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC"}