Files
S. EsmaeiliandClaude Haiku 5.5 10e453e4be build: ship pre-built API bundle; images copy output instead of installing
- API: `pnpm build` bundles dist/ into apps/api/.output (esbuild), with
  Linux musl native packages for sharp and argon2 kept alongside
- docker/api.Dockerfile copies that output; no pnpm install on the server
- add dist/migrate.js (prisma migrate deploy equivalent, same
  _prisma_migrations table and lock) so the Prisma CLI is not needed at runtime
- pnpm-workspace: supportedArchitectures for linux/x64/musl
- admin: apps/admin/.env.production sets VITE_SITE_URL for the production build
- drop NPM_REGISTRY / SITE_URL build args from compose and .env.example
- gitignore: anchor node_modules rules so pre-built node_modules are committed
- README: describe the pre-built deploy flow

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
2026-10-24 14:41:31 +03:30

3596 lines
138 KiB
JavaScript

import { createRequire as __bundleCreateRequire } from "node:module"; const require = __bundleCreateRequire(import.meta.url);
import {
ACCEPTED_IMAGE_TYPES,
AuditService,
AuthService,
CommonModule,
JwtModule,
JwtService,
MESSAGE_STATUSES,
PrismaModule,
PrismaService,
RevalidateService,
S3Storage,
SECTION_KEYS,
categoryInputSchema,
changePasswordSchema,
contactInputSchema,
env,
external_exports,
hashPassword,
isProd,
isSectionKey,
loginSchema,
mediaUpdateSchema,
messageUpdateSchema,
prismaNamespace_exports,
productInputSchema,
productListQuerySchema,
reorderSchema,
sectionSchemas,
toIssues,
toUserDto,
toWebp,
userCreateSchema,
userUpdateSchema
} from "./chunks/chunk-TXBARIZB.js";
import "./chunks/chunk-KIUJQ22G.js";
import {
APP_FILTER,
APP_GUARD,
FileInterceptor,
NestFactory,
Reflector,
core_exports,
init_core,
init_platform_express,
require_cookie
} from "./chunks/chunk-XSOBN2CI.js";
import {
BadRequestException,
Body,
Catch,
ConflictException,
Controller,
Delete,
ForbiddenException,
Get,
HttpCode,
HttpStatus,
Injectable,
Logger,
Module,
NotFoundException,
Param,
Patch,
Post,
Put,
Query,
Req,
Res,
ServiceUnavailableException,
SetMetadata,
UnauthorizedException,
UploadedFile,
UseGuards,
UseInterceptors,
applyDecorators,
common_exports,
createParamDecorator,
init_common
} from "./chunks/chunk-BX2ML7LW.js";
import "./chunks/chunk-C4DYPKAN.js";
import "./chunks/chunk-A34KYKJP.js";
import "./chunks/chunk-6UPY3HEI.js";
import {
__commonJS,
__name,
__require,
__toCommonJS,
__toESM
} from "./chunks/chunk-T6GW54FI.js";
// ../../node_modules/.pnpm/cookie-signature@1.0.6/node_modules/cookie-signature/index.js
var require_cookie_signature = __commonJS({
"../../node_modules/.pnpm/cookie-signature@1.0.6/node_modules/cookie-signature/index.js"(exports) {
var crypto = __require("crypto");
exports.sign = function(val, secret) {
if ("string" != typeof val) throw new TypeError("Cookie value must be provided as a string.");
if ("string" != typeof secret) throw new TypeError("Secret string must be provided.");
return val + "." + crypto.createHmac("sha256", secret).update(val).digest("base64").replace(/\=+$/, "");
};
exports.unsign = function(val, secret) {
if ("string" != typeof val) throw new TypeError("Signed cookie string must be provided.");
if ("string" != typeof secret) throw new TypeError("Secret string must be provided.");
var str = val.slice(0, val.lastIndexOf(".")), mac = exports.sign(str, secret);
return sha1(mac) == sha1(val) ? str : false;
};
function sha1(str) {
return crypto.createHash("sha1").update(str).digest("hex");
}
__name(sha1, "sha1");
}
});
// ../../node_modules/.pnpm/cookie-parser@1.4.7/node_modules/cookie-parser/index.js
var require_cookie_parser = __commonJS({
"../../node_modules/.pnpm/cookie-parser@1.4.7/node_modules/cookie-parser/index.js"(exports, module) {
"use strict";
var cookie = require_cookie();
var signature = require_cookie_signature();
module.exports = cookieParser2;
module.exports.JSONCookie = JSONCookie;
module.exports.JSONCookies = JSONCookies;
module.exports.signedCookie = signedCookie;
module.exports.signedCookies = signedCookies;
function cookieParser2(secret, options) {
var secrets = !secret || Array.isArray(secret) ? secret || [] : [secret];
return /* @__PURE__ */ __name(function cookieParser3(req, res, next) {
if (req.cookies) {
return next();
}
var cookies = req.headers.cookie;
req.secret = secrets[0];
req.cookies = /* @__PURE__ */ Object.create(null);
req.signedCookies = /* @__PURE__ */ Object.create(null);
if (!cookies) {
return next();
}
req.cookies = cookie.parse(cookies, options);
if (secrets.length !== 0) {
req.signedCookies = signedCookies(req.cookies, secrets);
req.signedCookies = JSONCookies(req.signedCookies);
}
req.cookies = JSONCookies(req.cookies);
next();
}, "cookieParser");
}
__name(cookieParser2, "cookieParser");
function JSONCookie(str) {
if (typeof str !== "string" || str.substr(0, 2) !== "j:") {
return void 0;
}
try {
return JSON.parse(str.slice(2));
} catch (err) {
return void 0;
}
}
__name(JSONCookie, "JSONCookie");
function JSONCookies(obj) {
var cookies = Object.keys(obj);
var key;
var val;
for (var i = 0; i < cookies.length; i++) {
key = cookies[i];
val = JSONCookie(obj[key]);
if (val) {
obj[key] = val;
}
}
return obj;
}
__name(JSONCookies, "JSONCookies");
function signedCookie(str, secret) {
if (typeof str !== "string") {
return void 0;
}
if (str.substr(0, 2) !== "s:") {
return str;
}
var secrets = !secret || Array.isArray(secret) ? secret || [] : [secret];
for (var i = 0; i < secrets.length; i++) {
var val = signature.unsign(str.slice(2), secrets[i]);
if (val !== false) {
return val;
}
}
return false;
}
__name(signedCookie, "signedCookie");
function signedCookies(obj, secret) {
var cookies = Object.keys(obj);
var dec;
var key;
var ret = /* @__PURE__ */ Object.create(null);
var val;
for (var i = 0; i < cookies.length; i++) {
key = cookies[i];
val = obj[key];
dec = signedCookie(val, secret);
if (val !== dec) {
ret[key] = dec;
delete obj[key];
}
}
return ret;
}
__name(signedCookies, "signedCookies");
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/ip.js
var require_ip = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/ip.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_IPV6_SUBNET_PREFIX = void 0;
exports.normalizeIp = normalizeIp;
var net_1 = __require("net");
exports.DEFAULT_IPV6_SUBNET_PREFIX = 64;
function toHextets(address) {
let head = address;
const lastColon = head.lastIndexOf(":");
const tail = head.slice(lastColon + 1);
if (tail.includes(".")) {
const octets = tail.split(".").map(Number);
if (octets.length !== 4 || octets.some((o) => !Number.isInteger(o) || o < 0 || o > 255)) {
return null;
}
const high = (octets[0] << 8 | octets[1]).toString(16);
const low = (octets[2] << 8 | octets[3]).toString(16);
head = `${head.slice(0, lastColon + 1)}${high}:${low}`;
}
const sides = head.split("::");
if (sides.length > 2) {
return null;
}
const left = sides[0] ? sides[0].split(":") : [];
const right = sides.length === 2 && sides[1] ? sides[1].split(":") : [];
const fill = sides.length === 2 ? 8 - left.length - right.length : 0;
if (fill < 0 || left.length + fill + right.length !== 8) {
return null;
}
const groups = [...left, ...new Array(fill).fill("0"), ...right];
const hextets = groups.map((group) => parseInt(group, 16));
if (hextets.some((hextet) => !Number.isInteger(hextet) || hextet < 0 || hextet > 65535)) {
return null;
}
return hextets;
}
__name(toHextets, "toHextets");
function maskHextets(hextets, prefix) {
return hextets.map((hextet, index) => {
const bitsBefore = index * 16;
if (prefix >= bitsBefore + 16) {
return hextet;
}
if (prefix <= bitsBefore) {
return 0;
}
const keep = prefix - bitsBefore;
return hextet & (65535 << 16 - keep & 65535);
});
}
__name(maskHextets, "maskHextets");
function formatIpv6(hextets) {
let bestStart = -1;
let bestLength = 0;
let runStart = -1;
let runLength = 0;
for (let index = 0; index < hextets.length; index++) {
if (hextets[index] !== 0) {
runStart = -1;
runLength = 0;
continue;
}
if (runStart === -1) {
runStart = index;
}
runLength++;
if (runLength > bestLength) {
bestStart = runStart;
bestLength = runLength;
}
}
const groups = hextets.map((hextet) => hextet.toString(16));
if (bestLength < 2) {
return groups.join(":");
}
return `${groups.slice(0, bestStart).join(":")}::${groups.slice(bestStart + bestLength).join(":")}`;
}
__name(formatIpv6, "formatIpv6");
function normalizeIp(ip, ipv6SubnetPrefix = exports.DEFAULT_IPV6_SUBNET_PREFIX) {
if (typeof ip !== "string" || ip.length === 0) {
return ip;
}
const zoneIndex = ip.indexOf("%");
const bare = zoneIndex === -1 ? ip : ip.slice(0, zoneIndex);
const version = (0, net_1.isIP)(bare);
if (version === 4) {
return bare;
}
if (version !== 6) {
return ip;
}
const hextets = toHextets(bare.toLowerCase());
if (!hextets) {
return ip;
}
const isLoopback = hextets[7] === 1 && hextets.slice(0, 7).every((hextet) => hextet === 0);
if (isLoopback) {
return "::1";
}
const isIpv4Mapped = hextets[0] === 0 && hextets[1] === 0 && hextets[2] === 0 && hextets[3] === 0 && hextets[4] === 0 && hextets[5] === 65535;
if (isIpv4Mapped) {
return [hextets[6] >> 8, hextets[6] & 255, hextets[7] >> 8, hextets[7] & 255].join(".");
}
const prefix = Number.isFinite(ipv6SubnetPrefix) ? Math.min(Math.max(Math.trunc(ipv6SubnetPrefix), 0), 128) : exports.DEFAULT_IPV6_SUBNET_PREFIX;
return `${formatIpv6(maskHextets(hextets, prefix))}/${prefix}`;
}
__name(normalizeIp, "normalizeIp");
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler-module-options.interface.js
var require_throttler_module_options_interface = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler-module-options.interface.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler-storage.interface.js
var require_throttler_storage_interface = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler-storage.interface.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ThrottlerStorage = void 0;
exports.ThrottlerStorage = /* @__PURE__ */ Symbol("ThrottlerStorage");
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.constants.js
var require_throttler_constants = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.constants.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.THROTTLER_SKIP = exports.THROTTLER_OPTIONS = exports.THROTTLER_KEY_GENERATOR = exports.THROTTLER_BLOCK_DURATION = exports.THROTTLER_TRACKER = exports.THROTTLER_TTL = exports.THROTTLER_LIMIT = void 0;
exports.THROTTLER_LIMIT = "THROTTLER:LIMIT";
exports.THROTTLER_TTL = "THROTTLER:TTL";
exports.THROTTLER_TRACKER = "THROTTLER:TRACKER";
exports.THROTTLER_BLOCK_DURATION = "THROTTLER:BLOCK_DURATION";
exports.THROTTLER_KEY_GENERATOR = "THROTTLER:KEY_GENERATOR";
exports.THROTTLER_OPTIONS = "THROTTLER:MODULE_OPTIONS";
exports.THROTTLER_SKIP = "THROTTLER:SKIP";
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.service.js
var require_throttler_service = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.service.js"(exports) {
"use strict";
var __decorate15 = exports && exports.__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;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ThrottlerStorageService = exports.DEFAULT_SWEEP_INTERVAL = void 0;
var common_1 = (init_common(), __toCommonJS(common_exports));
var async_hooks_1 = __require("async_hooks");
exports.DEFAULT_SWEEP_INTERVAL = 6e4;
var ThrottlerStorageService = class ThrottlerStorageService {
static {
__name(this, "ThrottlerStorageService");
}
constructor() {
this._storage = /* @__PURE__ */ new Map();
this.hitExpirations = /* @__PURE__ */ new Map();
this.sweepIntervalMs = exports.DEFAULT_SWEEP_INTERVAL;
this.startSweep = async_hooks_1.AsyncResource.bind(() => {
var _a, _b;
this.sweepInterval = setInterval(() => this.evictIdleRecords(), this.sweepIntervalMs);
(_b = (_a = this.sweepInterval).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
});
}
ensureSweep() {
if (this.sweepInterval) {
return;
}
this.startSweep();
}
get storage() {
return this._storage;
}
evictIdleRecords(now = Date.now()) {
for (const [key, record] of this._storage) {
if (record.isBlocked && record.blockExpiresAt > now) {
continue;
}
if (record.expiresAt > now) {
continue;
}
if (this.hasLiveHits(key, now)) {
continue;
}
this.hitExpirations.delete(key);
this._storage.delete(key);
}
}
hasLiveHits(key, now) {
const expirations = this.hitExpirations.get(key);
if (!expirations) {
return false;
}
for (const hits of expirations.values()) {
if (hits.some((expiresAt) => expiresAt > now)) {
return true;
}
}
return false;
}
getHitExpirations(key, throttlerName) {
let expirations = this.hitExpirations.get(key);
if (!expirations) {
expirations = /* @__PURE__ */ new Map();
this.hitExpirations.set(key, expirations);
}
let hits = expirations.get(throttlerName);
if (!hits) {
hits = [];
expirations.set(throttlerName, hits);
}
return hits;
}
pruneExpiredHits(key, throttlerName, now = Date.now()) {
const hits = this.getHitExpirations(key, throttlerName).filter((expiresAt) => expiresAt > now);
this.hitExpirations.get(key).set(throttlerName, hits);
this.storage.get(key).totalHits.set(throttlerName, hits.length);
}
getExpirationTime(key) {
return Math.ceil((this.storage.get(key).expiresAt - Date.now()) / 1e3);
}
getBlockExpirationTime(key) {
return Math.ceil((this.storage.get(key).blockExpiresAt - Date.now()) / 1e3);
}
resetBlockedRequest(key, throttlerName) {
this.storage.get(key).isBlocked = false;
this.storage.get(key).totalHits.set(throttlerName, 0);
this.hitExpirations.get(key).set(throttlerName, []);
}
fireHitCount(key, throttlerName, ttl) {
const { totalHits } = this.storage.get(key);
totalHits.set(throttlerName, totalHits.get(throttlerName) + 1);
this.getHitExpirations(key, throttlerName).push(Date.now() + ttl);
}
incrementWithoutBlock(key, ttlMilliseconds, limit, throttlerName, timeToExpire) {
const { totalHits } = this.storage.get(key);
const isBlocked = totalHits.get(throttlerName) >= limit;
if (!isBlocked) {
this.fireHitCount(key, throttlerName, ttlMilliseconds);
}
const hits = this.getHitExpirations(key, throttlerName);
const timeToBlockExpire = hits.length ? Math.ceil((Math.min(...hits) - Date.now()) / 1e3) : timeToExpire;
return {
totalHits: totalHits.get(throttlerName) + (isBlocked ? 1 : 0),
timeToExpire,
isBlocked,
timeToBlockExpire: isBlocked ? timeToBlockExpire : 0
};
}
async increment(key, ttl, limit, blockDuration, throttlerName) {
const ttlMilliseconds = ttl;
const blockDurationMilliseconds = blockDuration;
this.ensureSweep();
if (!this.storage.has(key)) {
this.storage.set(key, {
totalHits: /* @__PURE__ */ new Map([[throttlerName, 0]]),
expiresAt: Date.now() + ttlMilliseconds,
blockExpiresAt: 0,
isBlocked: false
});
}
this.pruneExpiredHits(key, throttlerName);
let timeToExpire = this.getExpirationTime(key);
if (timeToExpire <= 0) {
this.storage.get(key).expiresAt = Date.now() + ttlMilliseconds;
timeToExpire = this.getExpirationTime(key);
}
if (blockDurationMilliseconds <= 0) {
return this.incrementWithoutBlock(key, ttlMilliseconds, limit, throttlerName, timeToExpire);
}
if (!this.storage.get(key).isBlocked) {
this.fireHitCount(key, throttlerName, ttlMilliseconds);
}
if (this.storage.get(key).totalHits.get(throttlerName) > limit && !this.storage.get(key).isBlocked) {
this.storage.get(key).isBlocked = true;
this.storage.get(key).blockExpiresAt = Date.now() + blockDurationMilliseconds;
}
const timeToBlockExpire = this.getBlockExpirationTime(key);
if (timeToBlockExpire <= 0 && this.storage.get(key).isBlocked) {
this.resetBlockedRequest(key, throttlerName);
this.fireHitCount(key, throttlerName, ttlMilliseconds);
}
return {
totalHits: this.storage.get(key).totalHits.get(throttlerName),
timeToExpire,
isBlocked: this.storage.get(key).isBlocked,
timeToBlockExpire
};
}
onApplicationShutdown() {
if (this.sweepInterval) {
clearInterval(this.sweepInterval);
this.sweepInterval = void 0;
}
this.hitExpirations.clear();
this._storage.clear();
}
};
exports.ThrottlerStorageService = ThrottlerStorageService;
exports.ThrottlerStorageService = ThrottlerStorageService = __decorate15([
(0, common_1.Injectable)()
], ThrottlerStorageService);
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.providers.js
var require_throttler_providers = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.providers.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStorageToken = exports.getOptionsToken = exports.ThrottlerStorageProvider = void 0;
exports.createThrottlerProviders = createThrottlerProviders;
var throttler_storage_interface_1 = require_throttler_storage_interface();
var throttler_constants_1 = require_throttler_constants();
var throttler_service_1 = require_throttler_service();
function createThrottlerProviders(options) {
return [
{
provide: throttler_constants_1.THROTTLER_OPTIONS,
useValue: options
}
];
}
__name(createThrottlerProviders, "createThrottlerProviders");
exports.ThrottlerStorageProvider = {
provide: throttler_storage_interface_1.ThrottlerStorage,
useFactory: /* @__PURE__ */ __name((options) => {
return !Array.isArray(options) && options.storage ? options.storage : new throttler_service_1.ThrottlerStorageService();
}, "useFactory"),
inject: [throttler_constants_1.THROTTLER_OPTIONS]
};
var getOptionsToken = /* @__PURE__ */ __name(() => throttler_constants_1.THROTTLER_OPTIONS, "getOptionsToken");
exports.getOptionsToken = getOptionsToken;
var getStorageToken = /* @__PURE__ */ __name(() => throttler_storage_interface_1.ThrottlerStorage, "getStorageToken");
exports.getStorageToken = getStorageToken;
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.decorator.js
var require_throttler_decorator = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.decorator.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InjectThrottlerStorage = exports.InjectThrottlerOptions = exports.SkipThrottle = exports.Throttle = void 0;
var common_1 = (init_common(), __toCommonJS(common_exports));
var throttler_constants_1 = require_throttler_constants();
var throttler_providers_1 = require_throttler_providers();
function setThrottlerMetadata(target, options) {
for (const name in options) {
Reflect.defineMetadata(throttler_constants_1.THROTTLER_TTL + name, options[name].ttl, target);
Reflect.defineMetadata(throttler_constants_1.THROTTLER_LIMIT + name, options[name].limit, target);
Reflect.defineMetadata(throttler_constants_1.THROTTLER_BLOCK_DURATION + name, options[name].blockDuration, target);
Reflect.defineMetadata(throttler_constants_1.THROTTLER_TRACKER + name, options[name].getTracker, target);
Reflect.defineMetadata(throttler_constants_1.THROTTLER_KEY_GENERATOR + name, options[name].generateKey, target);
}
}
__name(setThrottlerMetadata, "setThrottlerMetadata");
var Throttle3 = /* @__PURE__ */ __name((options) => {
return (target, propertyKey, descriptor) => {
if (descriptor) {
setThrottlerMetadata(descriptor.value, options);
return descriptor;
}
setThrottlerMetadata(target, options);
return target;
};
}, "Throttle");
exports.Throttle = Throttle3;
var SkipThrottle = /* @__PURE__ */ __name((skip = { default: true }) => {
return (target, propertyKey, descriptor) => {
var _a;
const reflectionTarget = (_a = descriptor === null || descriptor === void 0 ? void 0 : descriptor.value) !== null && _a !== void 0 ? _a : target;
for (const key in skip) {
Reflect.defineMetadata(throttler_constants_1.THROTTLER_SKIP + key, skip[key], reflectionTarget);
}
return descriptor !== null && descriptor !== void 0 ? descriptor : target;
};
}, "SkipThrottle");
exports.SkipThrottle = SkipThrottle;
var InjectThrottlerOptions = /* @__PURE__ */ __name(() => (0, common_1.Inject)((0, throttler_providers_1.getOptionsToken)()), "InjectThrottlerOptions");
exports.InjectThrottlerOptions = InjectThrottlerOptions;
var InjectThrottlerStorage = /* @__PURE__ */ __name(() => (0, common_1.Inject)((0, throttler_providers_1.getStorageToken)()), "InjectThrottlerStorage");
exports.InjectThrottlerStorage = InjectThrottlerStorage;
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.exception.js
var require_throttler_exception = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.exception.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ThrottlerException = exports.throttlerMessage = void 0;
var common_1 = (init_common(), __toCommonJS(common_exports));
exports.throttlerMessage = "ThrottlerException: Too Many Requests";
var ThrottlerException = class extends common_1.HttpException {
static {
__name(this, "ThrottlerException");
}
constructor(message) {
super(`${message || exports.throttlerMessage}`, common_1.HttpStatus.TOO_MANY_REQUESTS);
}
};
exports.ThrottlerException = ThrottlerException;
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/hash.js
var require_hash = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/hash.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sha256 = sha256;
var crypto = __require("node:crypto");
function sha256(text) {
return crypto.createHash("sha256").update(text).digest("hex");
}
__name(sha256, "sha256");
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.guard.js
var require_throttler_guard = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.guard.js"(exports) {
"use strict";
var __decorate15 = exports && exports.__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 __metadata14 = exports && exports.__metadata || function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param8 = exports && exports.__param || function(paramIndex, decorator) {
return function(target, key) {
decorator(target, key, paramIndex);
};
};
var ThrottlerGuard_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ThrottlerGuard = void 0;
var common_1 = (init_common(), __toCommonJS(common_exports));
var core_1 = (init_core(), __toCommonJS(core_exports));
var hash_1 = require_hash();
var ip_1 = require_ip();
var throttler_storage_interface_1 = require_throttler_storage_interface();
var throttler_constants_1 = require_throttler_constants();
var throttler_decorator_1 = require_throttler_decorator();
var throttler_exception_1 = require_throttler_exception();
var ThrottlerGuard2 = ThrottlerGuard_1 = class ThrottlerGuard {
static {
__name(this, "ThrottlerGuard");
}
constructor(options, storageService, reflector) {
this.options = options;
this.storageService = storageService;
this.reflector = reflector;
this.headerPrefix = "X-RateLimit";
this.logger = new common_1.Logger(ThrottlerGuard_1.name);
this.errorMessage = throttler_exception_1.throttlerMessage;
this.ipv6SubnetPrefix = ip_1.DEFAULT_IPV6_SUBNET_PREFIX;
}
async onModuleInit() {
var _a, _b, _c;
var _d, _e;
this.throttlers = (Array.isArray(this.options) ? this.options : this.options.throttlers).sort((first, second) => {
if (typeof first.ttl === "function") {
return 1;
}
if (typeof second.ttl === "function") {
return 0;
}
return first.ttl - second.ttl;
}).map((opt) => {
var _a2;
return Object.assign(Object.assign({}, opt), { name: (_a2 = opt.name) !== null && _a2 !== void 0 ? _a2 : "default" });
});
if (!this.throttlers.length) {
this.logger.warn("No throttlers are configured, so no request is limited. Provide at least one entry to ThrottlerModule.forRoot() or return one from ThrottlerModule.forRootAsync().");
}
if (Array.isArray(this.options)) {
this.commonOptions = {};
} else {
this.commonOptions = {
skipIf: this.options.skipIf,
ignoreUserAgents: this.options.ignoreUserAgents,
getTracker: this.options.getTracker,
generateKey: this.options.generateKey,
setHeaders: this.options.setHeaders
};
this.ipv6SubnetPrefix = (_a = this.options.ipv6SubnetPrefix) !== null && _a !== void 0 ? _a : ip_1.DEFAULT_IPV6_SUBNET_PREFIX;
}
(_b = (_d = this.commonOptions).getTracker) !== null && _b !== void 0 ? _b : _d.getTracker = this.getTracker.bind(this);
(_c = (_e = this.commonOptions).generateKey) !== null && _c !== void 0 ? _c : _e.generateKey = this.generateKey.bind(this);
}
async canActivate(context) {
var _a;
const handler = context.getHandler();
const classRef = context.getClass();
if (await this.shouldSkip(context)) {
return true;
}
const continues = [];
for (const namedThrottler of this.throttlers) {
const skip = this.reflector.getAllAndOverride(throttler_constants_1.THROTTLER_SKIP + namedThrottler.name, [
handler,
classRef
]);
const skipIf = namedThrottler.skipIf || this.commonOptions.skipIf;
if (skip || (skipIf === null || skipIf === void 0 ? void 0 : skipIf(context))) {
continues.push(true);
continue;
}
const routeOrClassLimit = this.reflector.getAllAndOverride(throttler_constants_1.THROTTLER_LIMIT + namedThrottler.name, [handler, classRef]);
const routeOrClassTtl = this.reflector.getAllAndOverride(throttler_constants_1.THROTTLER_TTL + namedThrottler.name, [handler, classRef]);
const routeOrClassBlockDuration = this.reflector.getAllAndOverride(throttler_constants_1.THROTTLER_BLOCK_DURATION + namedThrottler.name, [handler, classRef]);
const routeOrClassGetTracker = this.reflector.getAllAndOverride(throttler_constants_1.THROTTLER_TRACKER + namedThrottler.name, [handler, classRef]);
const routeOrClassGetKeyGenerator = this.reflector.getAllAndOverride(throttler_constants_1.THROTTLER_KEY_GENERATOR + namedThrottler.name, [handler, classRef]);
const limit = this.toNumber(await this.resolveValue(context, routeOrClassLimit !== null && routeOrClassLimit !== void 0 ? routeOrClassLimit : namedThrottler.limit), "limit", namedThrottler.name);
const ttl = this.toNumber(await this.resolveValue(context, routeOrClassTtl !== null && routeOrClassTtl !== void 0 ? routeOrClassTtl : namedThrottler.ttl), "ttl", namedThrottler.name);
const blockDuration = this.toNumber(await this.resolveValue(context, (_a = routeOrClassBlockDuration !== null && routeOrClassBlockDuration !== void 0 ? routeOrClassBlockDuration : namedThrottler.blockDuration) !== null && _a !== void 0 ? _a : ttl), "blockDuration", namedThrottler.name);
const getTracker = routeOrClassGetTracker || namedThrottler.getTracker || this.commonOptions.getTracker;
const generateKey = routeOrClassGetKeyGenerator || namedThrottler.generateKey || this.commonOptions.generateKey;
continues.push(await this.handleRequest({
context,
limit,
ttl,
throttler: namedThrottler,
blockDuration,
getTracker,
generateKey
}));
}
return continues.every((cont) => cont);
}
async shouldSkip(_context) {
return false;
}
async handleRequest(requestProps) {
var _a, _b, _c;
const { context, limit, ttl, throttler, blockDuration, getTracker, generateKey } = requestProps;
const { req, res } = this.getRequestResponse(context);
const ignoreUserAgents = (_a = throttler.ignoreUserAgents) !== null && _a !== void 0 ? _a : this.commonOptions.ignoreUserAgents;
if (Array.isArray(ignoreUserAgents)) {
for (const pattern of ignoreUserAgents) {
if (pattern.test(req.headers["user-agent"])) {
return true;
}
}
}
const tracker = await getTracker(req, context);
const key = generateKey(context, tracker, throttler.name);
const { totalHits, timeToExpire, isBlocked, timeToBlockExpire } = await this.storageService.increment(key, ttl, limit, blockDuration, throttler.name);
const getThrottlerSuffix = /* @__PURE__ */ __name((name) => name === "default" ? "" : `-${name}`, "getThrottlerSuffix");
const setHeaders = (_c = (_b = throttler.setHeaders) !== null && _b !== void 0 ? _b : this.commonOptions.setHeaders) !== null && _c !== void 0 ? _c : true;
if (isBlocked) {
if (setHeaders) {
this.setResponseHeader(res, `Retry-After${getThrottlerSuffix(throttler.name)}`, timeToBlockExpire);
}
await this.throwThrottlingException(context, {
limit,
ttl,
key,
tracker,
totalHits,
timeToExpire,
isBlocked,
timeToBlockExpire
});
}
if (setHeaders) {
this.setResponseHeader(res, `${this.headerPrefix}-Limit${getThrottlerSuffix(throttler.name)}`, limit);
this.setResponseHeader(res, `${this.headerPrefix}-Remaining${getThrottlerSuffix(throttler.name)}`, Math.max(0, limit - totalHits));
this.setResponseHeader(res, `${this.headerPrefix}-Reset${getThrottlerSuffix(throttler.name)}`, timeToExpire);
}
return true;
}
async getTracker(req) {
return (0, ip_1.normalizeIp)(req.ip, this.ipv6SubnetPrefix);
}
setResponseHeader(res, name, value) {
if (typeof res.header === "function") {
res.header(name, value);
} else if (typeof res.setHeader === "function") {
res.setHeader(name, value);
}
}
getRequestResponse(context) {
const http = context.switchToHttp();
return { req: http.getRequest(), res: http.getResponse() };
}
generateKey(context, suffix, name) {
const prefix = `${context.getClass().name}-${context.getHandler().name}-${name}`;
return (0, hash_1.sha256)(`${prefix}-${suffix}`);
}
async throwThrottlingException(context, throttlerLimitDetail) {
throw new throttler_exception_1.ThrottlerException(await this.getErrorMessage(context, throttlerLimitDetail));
}
async getErrorMessage(context, throttlerLimitDetail) {
if (!Array.isArray(this.options)) {
if (!this.options.errorMessage)
return this.errorMessage;
return typeof this.options.errorMessage === "function" ? this.options.errorMessage(context, throttlerLimitDetail) : this.options.errorMessage;
}
return this.errorMessage;
}
toNumber(value, option, throttlerName) {
const number = typeof value === "string" && value.trim() !== "" ? Number(value) : value;
if (typeof number !== "number" || Number.isNaN(number)) {
throw new Error(`Invalid "${option}" for the "${throttlerName}" throttler: expected a number, got ${JSON.stringify(value)}.`);
}
return number;
}
async resolveValue(context, resolvableValue) {
return typeof resolvableValue === "function" ? resolvableValue(context) : resolvableValue;
}
};
exports.ThrottlerGuard = ThrottlerGuard2;
exports.ThrottlerGuard = ThrottlerGuard2 = ThrottlerGuard_1 = __decorate15([
(0, common_1.Injectable)(),
__param8(0, (0, throttler_decorator_1.InjectThrottlerOptions)()),
__param8(1, (0, throttler_decorator_1.InjectThrottlerStorage)()),
__metadata14("design:paramtypes", [Object, Object, core_1.Reflector])
], ThrottlerGuard2);
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.guard.interface.js
var require_throttler_guard_interface = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.guard.interface.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.module.js
var require_throttler_module = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/throttler.module.js"(exports) {
"use strict";
var __decorate15 = exports && exports.__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 ThrottlerModule_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ThrottlerModule = void 0;
var common_1 = (init_common(), __toCommonJS(common_exports));
var throttler_constants_1 = require_throttler_constants();
var throttler_providers_1 = require_throttler_providers();
var ThrottlerModule2 = ThrottlerModule_1 = class ThrottlerModule {
static {
__name(this, "ThrottlerModule");
}
static forRoot(options = []) {
const providers = [...(0, throttler_providers_1.createThrottlerProviders)(options), throttler_providers_1.ThrottlerStorageProvider];
return {
module: ThrottlerModule_1,
providers,
exports: providers
};
}
static forRootAsync(options) {
const providers = [...this.createAsyncProviders(options), throttler_providers_1.ThrottlerStorageProvider];
return {
module: ThrottlerModule_1,
imports: options.imports || [],
providers,
exports: providers
};
}
static createAsyncProviders(options) {
if (options.useExisting || options.useFactory) {
return [this.createAsyncOptionsProvider(options)];
}
return [
this.createAsyncOptionsProvider(options),
{
provide: options.useClass,
useClass: options.useClass
}
];
}
static createAsyncOptionsProvider(options) {
if (options.useFactory) {
return {
provide: throttler_constants_1.THROTTLER_OPTIONS,
useFactory: options.useFactory,
inject: options.inject || []
};
}
return {
provide: throttler_constants_1.THROTTLER_OPTIONS,
useFactory: /* @__PURE__ */ __name(async (optionsFactory) => await optionsFactory.createThrottlerOptions(), "useFactory"),
inject: [options.useExisting || options.useClass]
};
}
};
exports.ThrottlerModule = ThrottlerModule2;
exports.ThrottlerModule = ThrottlerModule2 = ThrottlerModule_1 = __decorate15([
(0, common_1.Global)(),
(0, common_1.Module)({})
], ThrottlerModule2);
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/utilities.js
var require_utilities = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/utilities.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.weeks = exports.days = exports.hours = exports.minutes = exports.seconds = void 0;
var seconds = /* @__PURE__ */ __name((howMany) => howMany * 1e3, "seconds");
exports.seconds = seconds;
var minutes = /* @__PURE__ */ __name((howMany) => 60 * howMany * (0, exports.seconds)(1), "minutes");
exports.minutes = minutes;
var hours = /* @__PURE__ */ __name((howMany) => 60 * howMany * (0, exports.minutes)(1), "hours");
exports.hours = hours;
var days = /* @__PURE__ */ __name((howMany) => 24 * howMany * (0, exports.hours)(1), "days");
exports.days = days;
var weeks = /* @__PURE__ */ __name((howMany) => 7 * howMany * (0, exports.days)(1), "weeks");
exports.weeks = weeks;
}
});
// ../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/index.js
var require_dist = __commonJS({
"../../node_modules/.pnpm/@nestjs+throttler@6.7.1_@ne_8947d8974bd7ad1fe5135dd2888a680f/node_modules/@nestjs/throttler/dist/index.js"(exports) {
"use strict";
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
if (k2 === void 0) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: /* @__PURE__ */ __name(function() {
return m[k];
}, "get") };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === void 0) k2 = k;
o[k2] = m[k];
}));
var __exportStar = exports && exports.__exportStar || function(m, exports2) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStorageToken = exports.getOptionsToken = void 0;
__exportStar(require_ip(), exports);
__exportStar(require_throttler_module_options_interface(), exports);
__exportStar(require_throttler_storage_interface(), exports);
__exportStar(require_throttler_decorator(), exports);
__exportStar(require_throttler_exception(), exports);
__exportStar(require_throttler_guard(), exports);
__exportStar(require_throttler_guard_interface(), exports);
__exportStar(require_throttler_module(), exports);
var throttler_providers_1 = require_throttler_providers();
Object.defineProperty(exports, "getOptionsToken", { enumerable: true, get: /* @__PURE__ */ __name(function() {
return throttler_providers_1.getOptionsToken;
}, "get") });
Object.defineProperty(exports, "getStorageToken", { enumerable: true, get: /* @__PURE__ */ __name(function() {
return throttler_providers_1.getStorageToken;
}, "get") });
__exportStar(require_throttler_service(), exports);
__exportStar(require_utilities(), exports);
}
});
// dist/main.js
init_core();
var import_cookie_parser = __toESM(require_cookie_parser(), 1);
// ../../node_modules/.pnpm/helmet@8.3.0/node_modules/helmet/index.mjs
var dashify = /* @__PURE__ */ __name((str) => str.replace(/[A-Z]/g, (capitalLetter) => "-" + capitalLetter.toLowerCase()), "dashify");
var errify = /* @__PURE__ */ __name((err) => err instanceof Error ? err : new Error(String(err)), "errify");
var isString = /* @__PURE__ */ __name((value) => typeof value === "string", "isString");
var throwErrorIfExists = /* @__PURE__ */ __name((err) => {
if (err) throw err;
}, "throwErrorIfExists");
var dangerouslyDisableDefaultSrc = /* @__PURE__ */ Symbol("dangerouslyDisableDefaultSrc");
var SHOULD_BE_QUOTED = /* @__PURE__ */ new Set(["none", "self", "strict-dynamic", "report-sample", "inline-speculation-rules", "unsafe-inline", "unsafe-eval", "unsafe-hashes", "wasm-unsafe-eval"]);
var getDefaultDirectives = /* @__PURE__ */ __name(() => ({
"default-src": ["'self'"],
"base-uri": ["'self'"],
"font-src": ["'self'", "https:", "data:"],
"form-action": ["'self'"],
"frame-ancestors": ["'self'"],
"img-src": ["'self'", "data:"],
"object-src": ["'none'"],
"script-src": ["'self'"],
"script-src-attr": ["'none'"],
"style-src": ["'self'", "https:", "'unsafe-inline'"],
"upgrade-insecure-requests": []
}), "getDefaultDirectives");
var parseDirectiveName = /* @__PURE__ */ __name((rawDirectiveName) => {
if (rawDirectiveName.length === 0 || !/^[a-z](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(rawDirectiveName)) {
throw new Error(`Content-Security-Policy received an invalid directive name ${JSON.stringify(rawDirectiveName)}`);
}
return dashify(rawDirectiveName);
}, "parseDirectiveName");
var getDirectiveValueValidationError = /* @__PURE__ */ __name((directiveName, directiveValue) => /;|,/.test(directiveValue) ? new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}`) : null, "getDirectiveValueValidationError");
var getDirectiveValueEntryValidationError = /* @__PURE__ */ __name((directiveName, directiveValueEntry) => SHOULD_BE_QUOTED.has(directiveValueEntry) || directiveValueEntry.startsWith("nonce-") || directiveValueEntry.startsWith("sha256-") || directiveValueEntry.startsWith("sha384-") || directiveValueEntry.startsWith("sha512-") ? new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}. ${JSON.stringify(directiveValueEntry)} should be quoted`) : null, "getDirectiveValueEntryValidationError");
var stringifyDirectiveValue = /* @__PURE__ */ __name((directiveValue) => {
if (Array.isArray(directiveValue)) {
return directiveValue.every(isString) ? directiveValue.join(" ") : null;
}
if (directiveValue instanceof Set) {
return stringifyDirectiveValue(Array.from(directiveValue));
}
return null;
}, "stringifyDirectiveValue");
var parseDirectives = /* @__PURE__ */ __name(({ useDefaults = true, directives: rawDirectives = {} }) => {
const result = new Map(useDefaults ? Object.entries(getDefaultDirectives()) : []);
let hasDisabledDefaultSrc = false;
const directiveNamesSeen = /* @__PURE__ */ new Set();
for (const rawDirectiveName in rawDirectives) {
if (!Object.hasOwn(rawDirectives, rawDirectiveName)) {
continue;
}
const directiveName = parseDirectiveName(rawDirectiveName);
if (directiveNamesSeen.has(directiveName)) {
throw new Error(`Content-Security-Policy received a duplicate directive ${JSON.stringify(directiveName)}`);
}
directiveNamesSeen.add(directiveName);
const rawDirectiveValue = rawDirectives[rawDirectiveName];
let directiveValue;
if (rawDirectiveValue === null) {
if (directiveName === "default-src") {
throw new Error("Content-Security-Policy needs a default-src but it was set to `null`. If you really want to disable it, set it to `contentSecurityPolicy.dangerouslyDisableDefaultSrc`.");
}
result.delete(directiveName);
continue;
} else if (typeof rawDirectiveValue === "string") {
directiveValue = [rawDirectiveValue];
} else if (rawDirectiveValue === dangerouslyDisableDefaultSrc) {
if (directiveName === "default-src") {
hasDisabledDefaultSrc = true;
result.delete(directiveName);
continue;
} else {
throw new Error(`Content-Security-Policy: tried to disable ${JSON.stringify(directiveName)} as if it were default-src; simply omit the key`);
}
} else if (rawDirectiveValue) {
directiveValue = rawDirectiveValue;
} else {
throw new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}`);
}
for (const element of directiveValue) {
if (typeof element !== "string") continue;
throwErrorIfExists(getDirectiveValueValidationError(directiveName, element) ?? getDirectiveValueEntryValidationError(directiveName, element));
}
result.set(directiveName, directiveValue);
}
if (!result.size) {
throw new Error("Content-Security-Policy has no directives. Either set some or disable the header");
}
if (!result.has("default-src") && !hasDisabledDefaultSrc) {
throw new Error("Content-Security-Policy needs a default-src but none was provided. If you really want to disable it, set it to `contentSecurityPolicy.dangerouslyDisableDefaultSrc`.");
}
let stringResult = "";
let shouldUseStringResult = true;
for (const [directiveName, directiveValue] of result) {
const directiveValueString = stringifyDirectiveValue(directiveValue);
if (directiveValueString === null) {
shouldUseStringResult = false;
break;
} else {
if (stringResult) stringResult += ";";
stringResult += directiveValueString ? `${directiveName} ${directiveValueString}` : directiveName;
}
}
return shouldUseStringResult ? stringResult : result;
}, "parseDirectives");
function getHeaderValue(req, res, normalizedDirectives) {
const result = [];
for (const [directiveName, rawDirectiveValue] of normalizedDirectives) {
let directiveValue = "";
for (const element of rawDirectiveValue) {
if (typeof element === "function") {
let newElement;
try {
newElement = element(req, res);
} catch (err2) {
return errify(err2);
}
const err = getDirectiveValueEntryValidationError(directiveName, newElement);
if (err) return err;
directiveValue += " " + newElement;
} else {
directiveValue += " " + element;
}
}
if (directiveValue) {
const err = getDirectiveValueValidationError(directiveName, directiveValue);
if (err) return err;
result.push(`${directiveName}${directiveValue}`);
} else {
result.push(directiveName);
}
}
return result.join(";");
}
__name(getHeaderValue, "getHeaderValue");
var contentSecurityPolicy = /* @__PURE__ */ __name(function contentSecurityPolicy2(options = {}) {
const headerName = options.reportOnly ? "Content-Security-Policy-Report-Only" : "Content-Security-Policy";
const parsedDirectives = parseDirectives(options);
if (typeof parsedDirectives === "string") {
return /* @__PURE__ */ __name(function contentSecurityPolicyMiddleware(_req, res, next) {
res.setHeader(headerName, parsedDirectives);
next();
}, "contentSecurityPolicyMiddleware");
}
return /* @__PURE__ */ __name(function contentSecurityPolicyMiddleware(req, res, next) {
const result = getHeaderValue(req, res, parsedDirectives);
if (result instanceof Error) {
next(result);
} else {
res.setHeader(headerName, result);
next();
}
}, "contentSecurityPolicyMiddleware");
}, "contentSecurityPolicy");
contentSecurityPolicy.getDefaultDirectives = getDefaultDirectives;
contentSecurityPolicy.dangerouslyDisableDefaultSrc = dangerouslyDisableDefaultSrc;
var ALLOWED_POLICIES$2 = /* @__PURE__ */ new Set(["require-corp", "credentialless", "unsafe-none"]);
function getHeaderValueFromOptions$6({ policy = "require-corp" }) {
if (ALLOWED_POLICIES$2.has(policy)) {
return policy;
} else {
throw new Error(`Cross-Origin-Embedder-Policy does not support the ${JSON.stringify(policy)} policy`);
}
}
__name(getHeaderValueFromOptions$6, "getHeaderValueFromOptions$6");
function crossOriginEmbedderPolicy(options = {}) {
const headerValue = getHeaderValueFromOptions$6(options);
return /* @__PURE__ */ __name(function crossOriginEmbedderPolicyMiddleware(_req, res, next) {
res.setHeader("Cross-Origin-Embedder-Policy", headerValue);
next();
}, "crossOriginEmbedderPolicyMiddleware");
}
__name(crossOriginEmbedderPolicy, "crossOriginEmbedderPolicy");
var ALLOWED_POLICIES$1 = /* @__PURE__ */ new Set(["same-origin", "same-origin-allow-popups", "noopener-allow-popups", "unsafe-none"]);
function getHeaderValueFromOptions$5({ policy = "same-origin" }) {
if (ALLOWED_POLICIES$1.has(policy)) {
return policy;
} else {
throw new Error(`Cross-Origin-Opener-Policy does not support the ${JSON.stringify(policy)} policy`);
}
}
__name(getHeaderValueFromOptions$5, "getHeaderValueFromOptions$5");
function crossOriginOpenerPolicy(options = {}) {
const headerValue = getHeaderValueFromOptions$5(options);
return /* @__PURE__ */ __name(function crossOriginOpenerPolicyMiddleware(_req, res, next) {
res.setHeader("Cross-Origin-Opener-Policy", headerValue);
next();
}, "crossOriginOpenerPolicyMiddleware");
}
__name(crossOriginOpenerPolicy, "crossOriginOpenerPolicy");
var ALLOWED_POLICIES = /* @__PURE__ */ new Set(["same-origin", "same-site", "cross-origin"]);
function getHeaderValueFromOptions$4({ policy = "same-origin" }) {
if (ALLOWED_POLICIES.has(policy)) {
return policy;
} else {
throw new Error(`Cross-Origin-Resource-Policy does not support the ${JSON.stringify(policy)} policy`);
}
}
__name(getHeaderValueFromOptions$4, "getHeaderValueFromOptions$4");
function crossOriginResourcePolicy(options = {}) {
const headerValue = getHeaderValueFromOptions$4(options);
return /* @__PURE__ */ __name(function crossOriginResourcePolicyMiddleware(_req, res, next) {
res.setHeader("Cross-Origin-Resource-Policy", headerValue);
next();
}, "crossOriginResourcePolicyMiddleware");
}
__name(crossOriginResourcePolicy, "crossOriginResourcePolicy");
function originAgentCluster() {
return /* @__PURE__ */ __name(function originAgentClusterMiddleware(_req, res, next) {
res.setHeader("Origin-Agent-Cluster", "?1");
next();
}, "originAgentClusterMiddleware");
}
__name(originAgentCluster, "originAgentCluster");
var ALLOWED_TOKENS = /* @__PURE__ */ new Set(["no-referrer", "no-referrer-when-downgrade", "same-origin", "origin", "strict-origin", "origin-when-cross-origin", "strict-origin-when-cross-origin", "unsafe-url", ""]);
function getHeaderValueFromOptions$3({ policy = ["no-referrer"] }) {
const tokens = typeof policy === "string" ? [policy] : policy;
if (tokens.length === 0) {
throw new Error("Referrer-Policy received no policy tokens");
}
const tokensSeen = /* @__PURE__ */ new Set();
tokens.forEach((token) => {
if (!ALLOWED_TOKENS.has(token)) {
throw new Error(`Referrer-Policy received an unexpected policy token ${JSON.stringify(token)}`);
} else if (tokensSeen.has(token)) {
throw new Error(`Referrer-Policy received a duplicate policy token ${JSON.stringify(token)}`);
}
tokensSeen.add(token);
});
return tokens.join(",");
}
__name(getHeaderValueFromOptions$3, "getHeaderValueFromOptions$3");
function referrerPolicy(options = {}) {
const headerValue = getHeaderValueFromOptions$3(options);
return /* @__PURE__ */ __name(function referrerPolicyMiddleware(_req, res, next) {
res.setHeader("Referrer-Policy", headerValue);
next();
}, "referrerPolicyMiddleware");
}
__name(referrerPolicy, "referrerPolicy");
var DEFAULT_MAX_AGE = 365 * 24 * 60 * 60;
function parseMaxAge(value = DEFAULT_MAX_AGE) {
if (value >= 0 && Number.isFinite(value)) {
return Math.floor(value);
} else {
throw new Error(`Strict-Transport-Security: ${JSON.stringify(value)} is not a valid value for maxAge. Please choose a positive integer.`);
}
}
__name(parseMaxAge, "parseMaxAge");
function getHeaderValueFromOptions$2(options) {
if ("maxage" in options) {
throw new Error("Strict-Transport-Security received an unsupported property, `maxage`. Did you mean to pass `maxAge`?");
}
if ("includeSubdomains" in options) {
throw new Error('Strict-Transport-Security middleware should use `includeSubDomains` instead of `includeSubdomains`. (The correct one has an uppercase "D".)');
}
const directives = [`max-age=${parseMaxAge(options.maxAge)}`];
if (options.includeSubDomains === void 0 || options.includeSubDomains) {
directives.push("includeSubDomains");
}
if (options.preload) {
directives.push("preload");
}
return directives.join("; ");
}
__name(getHeaderValueFromOptions$2, "getHeaderValueFromOptions$2");
function strictTransportSecurity(options = {}) {
const headerValue = getHeaderValueFromOptions$2(options);
return /* @__PURE__ */ __name(function strictTransportSecurityMiddleware(_req, res, next) {
res.setHeader("Strict-Transport-Security", headerValue);
next();
}, "strictTransportSecurityMiddleware");
}
__name(strictTransportSecurity, "strictTransportSecurity");
function xContentTypeOptions() {
return /* @__PURE__ */ __name(function xContentTypeOptionsMiddleware(_req, res, next) {
res.setHeader("X-Content-Type-Options", "nosniff");
next();
}, "xContentTypeOptionsMiddleware");
}
__name(xContentTypeOptions, "xContentTypeOptions");
function xDnsPrefetchControl(options = {}) {
const headerValue = options.allow ? "on" : "off";
return /* @__PURE__ */ __name(function xDnsPrefetchControlMiddleware(_req, res, next) {
res.setHeader("X-DNS-Prefetch-Control", headerValue);
next();
}, "xDnsPrefetchControlMiddleware");
}
__name(xDnsPrefetchControl, "xDnsPrefetchControl");
function xDownloadOptions() {
return /* @__PURE__ */ __name(function xDownloadOptionsMiddleware(_req, res, next) {
res.setHeader("X-Download-Options", "noopen");
next();
}, "xDownloadOptionsMiddleware");
}
__name(xDownloadOptions, "xDownloadOptions");
function getHeaderValueFromOptions$1({ action = "sameorigin" }) {
const normalizedAction = typeof action === "string" ? action.toUpperCase() : action;
switch (normalizedAction) {
case "SAME-ORIGIN":
return "SAMEORIGIN";
case "DENY":
case "SAMEORIGIN":
return normalizedAction;
default:
throw new Error(`X-Frame-Options received an invalid action ${JSON.stringify(action)}`);
}
}
__name(getHeaderValueFromOptions$1, "getHeaderValueFromOptions$1");
function xFrameOptions(options = {}) {
const headerValue = getHeaderValueFromOptions$1(options);
return /* @__PURE__ */ __name(function xFrameOptionsMiddleware(_req, res, next) {
res.setHeader("X-Frame-Options", headerValue);
next();
}, "xFrameOptionsMiddleware");
}
__name(xFrameOptions, "xFrameOptions");
var ALLOWED_PERMITTED_POLICIES = /* @__PURE__ */ new Set(["none", "master-only", "by-content-type", "all"]);
function getHeaderValueFromOptions({ permittedPolicies = "none" }) {
if (ALLOWED_PERMITTED_POLICIES.has(permittedPolicies)) {
return permittedPolicies;
} else {
throw new Error(`X-Permitted-Cross-Domain-Policies does not support ${JSON.stringify(permittedPolicies)}`);
}
}
__name(getHeaderValueFromOptions, "getHeaderValueFromOptions");
function xPermittedCrossDomainPolicies(options = {}) {
const headerValue = getHeaderValueFromOptions(options);
return /* @__PURE__ */ __name(function xPermittedCrossDomainPoliciesMiddleware(_req, res, next) {
res.setHeader("X-Permitted-Cross-Domain-Policies", headerValue);
next();
}, "xPermittedCrossDomainPoliciesMiddleware");
}
__name(xPermittedCrossDomainPolicies, "xPermittedCrossDomainPolicies");
function xPoweredBy() {
return /* @__PURE__ */ __name(function xPoweredByMiddleware(_req, res, next) {
res.removeHeader("X-Powered-By");
next();
}, "xPoweredByMiddleware");
}
__name(xPoweredBy, "xPoweredBy");
function xXssProtection() {
return /* @__PURE__ */ __name(function xXssProtectionMiddleware(_req, res, next) {
res.setHeader("X-XSS-Protection", "0");
next();
}, "xXssProtectionMiddleware");
}
__name(xXssProtection, "xXssProtection");
function getMiddlewareFunctionsFromOptions(options) {
const result = [];
switch (options.contentSecurityPolicy) {
case void 0:
case true:
result.push(contentSecurityPolicy());
break;
case false:
break;
default:
result.push(contentSecurityPolicy(options.contentSecurityPolicy));
break;
}
switch (options.crossOriginEmbedderPolicy) {
case void 0:
case false:
break;
case true:
result.push(crossOriginEmbedderPolicy());
break;
default:
result.push(crossOriginEmbedderPolicy(options.crossOriginEmbedderPolicy));
break;
}
switch (options.crossOriginOpenerPolicy) {
case void 0:
case true:
result.push(crossOriginOpenerPolicy());
break;
case false:
break;
default:
result.push(crossOriginOpenerPolicy(options.crossOriginOpenerPolicy));
break;
}
switch (options.crossOriginResourcePolicy) {
case void 0:
case true:
result.push(crossOriginResourcePolicy());
break;
case false:
break;
default:
result.push(crossOriginResourcePolicy(options.crossOriginResourcePolicy));
break;
}
switch (options.originAgentCluster) {
case void 0:
case true:
result.push(originAgentCluster());
break;
case false:
break;
default:
console.warn("Origin-Agent-Cluster does not take options. Remove the property to silence this warning.");
result.push(originAgentCluster());
break;
}
switch (options.referrerPolicy) {
case void 0:
case true:
result.push(referrerPolicy());
break;
case false:
break;
default:
result.push(referrerPolicy(options.referrerPolicy));
break;
}
if ("strictTransportSecurity" in options && "hsts" in options) {
throw new Error("Strict-Transport-Security option was specified twice. Remove the `hsts` option to fix this error.");
}
const strictTransportSecurityOption = options.strictTransportSecurity ?? options.hsts;
switch (strictTransportSecurityOption) {
case void 0:
case true:
result.push(strictTransportSecurity());
break;
case false:
break;
default:
result.push(strictTransportSecurity(strictTransportSecurityOption));
break;
}
if ("xContentTypeOptions" in options && "noSniff" in options) {
throw new Error("X-Content-Type-Options option was specified twice. Remove the `noSniff` option to fix this error.");
}
const xContentTypeOptionsOption = options.xContentTypeOptions ?? options.noSniff;
switch (xContentTypeOptionsOption) {
case void 0:
case true:
result.push(xContentTypeOptions());
break;
case false:
break;
default:
console.warn("X-Content-Type-Options does not take options. Remove the property to silence this warning.");
result.push(xContentTypeOptions());
break;
}
if ("xDnsPrefetchControl" in options && "dnsPrefetchControl" in options) {
throw new Error("X-DNS-Prefetch-Control option was specified twice. Remove the `dnsPrefetchControl` option to fix this error.");
}
const xDnsPrefetchControlOption = options.xDnsPrefetchControl ?? options.dnsPrefetchControl;
switch (xDnsPrefetchControlOption) {
case void 0:
case true:
result.push(xDnsPrefetchControl());
break;
case false:
break;
default:
result.push(xDnsPrefetchControl(xDnsPrefetchControlOption));
break;
}
if ("xDownloadOptions" in options && "ieNoOpen" in options) {
throw new Error("X-Download-Options option was specified twice. Remove the `ieNoOpen` option to fix this error.");
}
const xDownloadOptionsOption = options.xDownloadOptions ?? options.ieNoOpen;
switch (xDownloadOptionsOption) {
case void 0:
case true:
result.push(xDownloadOptions());
break;
case false:
break;
default:
console.warn("X-Download-Options does not take options. Remove the property to silence this warning.");
result.push(xDownloadOptions());
break;
}
if ("xFrameOptions" in options && "frameguard" in options) {
throw new Error("X-Frame-Options option was specified twice. Remove the `frameguard` option to fix this error.");
}
const xFrameOptionsOption = options.xFrameOptions ?? options.frameguard;
switch (xFrameOptionsOption) {
case void 0:
case true:
result.push(xFrameOptions());
break;
case false:
break;
default:
result.push(xFrameOptions(xFrameOptionsOption));
break;
}
if ("xPermittedCrossDomainPolicies" in options && "permittedCrossDomainPolicies" in options) {
throw new Error("X-Permitted-Cross-Domain-Policies option was specified twice. Remove the `permittedCrossDomainPolicies` option to fix this error.");
}
const xPermittedCrossDomainPoliciesOption = options.xPermittedCrossDomainPolicies ?? options.permittedCrossDomainPolicies;
switch (xPermittedCrossDomainPoliciesOption) {
case void 0:
case true:
result.push(xPermittedCrossDomainPolicies());
break;
case false:
break;
default:
result.push(xPermittedCrossDomainPolicies(xPermittedCrossDomainPoliciesOption));
break;
}
if ("xPoweredBy" in options && "hidePoweredBy" in options) {
throw new Error("X-Powered-By option was specified twice. Remove the `hidePoweredBy` option to fix this error.");
}
const xPoweredByOption = options.xPoweredBy ?? options.hidePoweredBy;
switch (xPoweredByOption) {
case void 0:
case true:
result.push(xPoweredBy());
break;
case false:
break;
default:
console.warn("X-Powered-By does not take options. Remove the property to silence this warning.");
result.push(xPoweredBy());
break;
}
if ("xXssProtection" in options && "xssFilter" in options) {
throw new Error("X-XSS-Protection option was specified twice. Remove the `xssFilter` option to fix this error.");
}
const xXssProtectionOption = options.xXssProtection ?? options.xssFilter;
switch (xXssProtectionOption) {
case void 0:
case true:
result.push(xXssProtection());
break;
case false:
break;
default:
console.warn("X-XSS-Protection does not take options. Remove the property to silence this warning.");
result.push(xXssProtection());
break;
}
return result;
}
__name(getMiddlewareFunctionsFromOptions, "getMiddlewareFunctionsFromOptions");
var helmet = Object.assign(
/* @__PURE__ */ __name(function helmet2(options = {}) {
if (options.constructor?.name === "IncomingMessage") {
throw new Error("It appears you have done something like `app.use(helmet)`, but it should be `app.use(helmet())`.");
}
const middlewareFunctions = getMiddlewareFunctionsFromOptions(options);
return /* @__PURE__ */ __name(function helmetMiddleware(req, res, next) {
let middlewareIndex = 0;
(/* @__PURE__ */ __name((function internalNext(err) {
if (err) {
next(err);
return;
}
const middlewareFunction = middlewareFunctions[middlewareIndex];
if (middlewareFunction) {
middlewareIndex++;
middlewareFunction(req, res, internalNext);
} else {
next();
}
}), "internalNext"))();
}, "helmetMiddleware");
}, "helmet"),
{
contentSecurityPolicy,
crossOriginEmbedderPolicy,
crossOriginOpenerPolicy,
crossOriginResourcePolicy,
originAgentCluster,
referrerPolicy,
strictTransportSecurity,
xContentTypeOptions,
xDnsPrefetchControl,
xDownloadOptions,
xFrameOptions,
xPermittedCrossDomainPolicies,
xPoweredBy,
xXssProtection,
// Legacy aliases
dnsPrefetchControl: xDnsPrefetchControl,
xssFilter: xXssProtection,
permittedCrossDomainPolicies: xPermittedCrossDomainPolicies,
ieNoOpen: xDownloadOptions,
noSniff: xContentTypeOptions,
frameguard: xFrameOptions,
hidePoweredBy: xPoweredBy,
hsts: strictTransportSecurity
}
);
// dist/app.module.js
init_common();
init_core();
var import_throttler3 = __toESM(require_dist(), 1);
// dist/auth/auth.controller.js
init_common();
var import_throttler = __toESM(require_dist(), 1);
// dist/common/auth.js
init_common();
init_core();
var __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 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var ROLES_KEY = "roles";
var JwtAuthGuard = class JwtAuthGuard2 {
static {
__name(this, "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("\u0627\u0628\u062A\u062F\u0627 \u0648\u0627\u0631\u062F \u0634\u0648\u06CC\u062F");
let payload;
try {
payload = await this.jwt.verifyAsync(token);
} catch {
throw new UnauthorizedException("\u0646\u0634\u0633\u062A \u0634\u0645\u0627 \u0645\u0646\u0642\u0636\u06CC \u0634\u062F\u0647 \u0627\u0633\u062A");
}
const user = await this.prisma.adminUser.findUnique({ where: { id: payload.sub } });
if (!user?.isActive)
throw new UnauthorizedException("\u062D\u0633\u0627\u0628 \u06A9\u0627\u0631\u0628\u0631\u06CC \u063A\u06CC\u0631\u0641\u0639\u0627\u0644 \u0627\u0633\u062A");
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("\u0628\u0631\u0627\u06CC \u0627\u06CC\u0646 \u06A9\u0627\u0631 \u062F\u0633\u062A\u0631\u0633\u06CC \u0646\u062F\u0627\u0631\u06CC\u062F");
}
return true;
}
};
JwtAuthGuard = __decorate([
Injectable(),
__metadata("design:paramtypes", [
JwtService,
Reflector,
PrismaService
])
], JwtAuthGuard);
var AdminAuth = /* @__PURE__ */ __name((...roles) => applyDecorators(SetMetadata(ROLES_KEY, roles), UseGuards(JwtAuthGuard)), "AdminAuth");
var Roles = /* @__PURE__ */ __name((...roles) => SetMetadata(ROLES_KEY, roles), "Roles");
var CurrentUser = createParamDecorator((_, ctx) => ctx.switchToHttp().getRequest().user);
// dist/common/zod.pipe.js
init_common();
external_exports.config(external_exports.locales.fa());
var ZodPipe = class {
static {
__name(this, "ZodPipe");
}
schema;
constructor(schema) {
this.schema = schema;
}
transform(value) {
const result = this.schema.safeParse(value);
if (!result.success) {
throw new BadRequestException({
statusCode: 400,
message: "\u0627\u0637\u0644\u0627\u0639\u0627\u062A \u0648\u0627\u0631\u062F\u0634\u062F\u0647 \u0645\u0639\u062A\u0628\u0631 \u0646\u06CC\u0633\u062A",
issues: toIssues(result.error)
});
}
return result.data;
}
};
var IdPipe = new ZodPipe(external_exports.coerce.number().int().positive());
// dist/auth/auth.controller.js
var __decorate2 = 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 __metadata2 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = function(paramIndex, decorator) {
return function(target, key) {
decorator(target, key, paramIndex);
};
};
var COOKIE = "imen_rt";
var COOKIE_PATH = "/api/admin/auth";
var ua = /* @__PURE__ */ __name((req) => req.headers["user-agent"] ?? "", "ua");
var readCookie = /* @__PURE__ */ __name((req) => req.cookies?.[COOKIE], "readCookie");
var AuthController = class AuthController2 {
static {
__name(this, "AuthController");
}
auth;
constructor(auth) {
this.auth = auth;
}
async login(body, req, res) {
return this.respond(res, await this.auth.login(body, ua(req)));
}
async refresh(req, res) {
try {
return this.respond(res, await this.auth.refresh(readCookie(req), ua(req)));
} catch (e) {
res.clearCookie(COOKIE, { path: COOKIE_PATH });
throw e;
}
}
async logout(req, res) {
await this.auth.logout(readCookie(req));
res.clearCookie(COOKIE, { path: COOKIE_PATH });
}
me(user) {
return this.auth.me(user.id);
}
async changePassword(body, user) {
await this.auth.changePassword(user.id, body);
}
respond(res, t) {
res.cookie(COOKIE, t.refreshToken, {
httpOnly: true,
secure: isProd && env.COOKIE_SECURE,
sameSite: "strict",
path: COOKIE_PATH,
expires: t.refreshExpiresAt
});
return { accessToken: t.accessToken, user: t.user };
}
};
__decorate2([
Post("login"),
HttpCode(200),
(0, import_throttler.Throttle)({ default: { limit: 8, ttl: 6e4 } }),
__param(0, Body(new ZodPipe(loginSchema))),
__param(1, Req()),
__param(2, Res({ passthrough: true })),
__metadata2("design:type", Function),
__metadata2("design:paramtypes", [Object, Object, Object]),
__metadata2("design:returntype", Promise)
], AuthController.prototype, "login", null);
__decorate2([
Post("refresh"),
HttpCode(200),
(0, import_throttler.Throttle)({ default: { limit: 30, ttl: 6e4 } }),
__param(0, Req()),
__param(1, Res({ passthrough: true })),
__metadata2("design:type", Function),
__metadata2("design:paramtypes", [Object, Object]),
__metadata2("design:returntype", Promise)
], AuthController.prototype, "refresh", null);
__decorate2([
Post("logout"),
HttpCode(204),
__param(0, Req()),
__param(1, Res({ passthrough: true })),
__metadata2("design:type", Function),
__metadata2("design:paramtypes", [Object, Object]),
__metadata2("design:returntype", Promise)
], AuthController.prototype, "logout", null);
__decorate2([
Get("me"),
AdminAuth(),
__param(0, CurrentUser()),
__metadata2("design:type", Function),
__metadata2("design:paramtypes", [Object]),
__metadata2("design:returntype", void 0)
], AuthController.prototype, "me", null);
__decorate2([
Post("change-password"),
HttpCode(204),
AdminAuth(),
__param(0, Body(new ZodPipe(changePasswordSchema))),
__param(1, CurrentUser()),
__metadata2("design:type", Function),
__metadata2("design:paramtypes", [Object, Object]),
__metadata2("design:returntype", Promise)
], AuthController.prototype, "changePassword", null);
AuthController = __decorate2([
Controller("admin/auth"),
__metadata2("design:paramtypes", [AuthService])
], AuthController);
var AuthModule = class AuthModule2 {
static {
__name(this, "AuthModule");
}
};
AuthModule = __decorate2([
Module({
imports: [
JwtModule.register({
global: true,
secret: env.JWT_SECRET,
signOptions: { expiresIn: env.JWT_ACCESS_TTL }
})
],
controllers: [AuthController],
providers: [AuthService],
exports: [AuthService]
})
], AuthModule);
// dist/catalog/catalog.module.js
init_common();
// dist/media/media.controller.js
init_common();
init_platform_express();
// dist/media/media.service.js
init_common();
import { randomUUID } from "node:crypto";
var __decorate3 = 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 __metadata3 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var MediaService_1;
var MediaService = MediaService_1 = class MediaService2 {
static {
__name(this, "MediaService");
}
prisma;
audit;
revalidate;
logger = new Logger(MediaService_1.name);
storage = new S3Storage();
constructor(prisma, audit, revalidate) {
this.prisma = prisma;
this.audit = audit;
this.revalidate = revalidate;
}
async onModuleInit() {
if (!env.S3_ENSURE_BUCKET)
return;
try {
await this.storage.ensureBucket();
} catch (e) {
this.logger.error(`could not prepare bucket "${env.S3_BUCKET}": ${String(e)}`);
}
}
url(key) {
return this.storage.publicUrl(key);
}
toDto(m) {
return {
id: m.id,
url: this.url(m.key),
alt: m.alt,
mime: m.mime,
size: m.size,
width: m.width,
height: m.height,
originalName: m.originalName,
createdAt: m.createdAt.toISOString()
};
}
async list(page, pageSize, q) {
const where = q ? {
OR: [
{ originalName: { contains: q, mode: "insensitive" } },
{ alt: { contains: q, mode: "insensitive" } }
]
} : {};
const [items, total] = await this.prisma.$transaction([
this.prisma.media.findMany({
where,
orderBy: { id: "desc" },
skip: (page - 1) * pageSize,
take: pageSize
}),
this.prisma.media.count({ where })
]);
return { items: items.map((m) => this.toDto(m)), total, page, pageSize };
}
async upload(file, alt, userId) {
if (!file)
throw new BadRequestException("\u0641\u0627\u06CC\u0644\u06CC \u0627\u0631\u0633\u0627\u0644 \u0646\u0634\u062F\u0647 \u0627\u0633\u062A");
if (!ACCEPTED_IMAGE_TYPES.includes(file.mimetype)) {
throw new BadRequestException("\u0641\u0642\u0637 \u062A\u0635\u0627\u0648\u06CC\u0631 JPG\u060C PNG\u060C WebP\u060C AVIF \u0648 GIF \u067E\u0630\u06CC\u0631\u0641\u062A\u0647 \u0645\u06CC\u200C\u0634\u0648\u0646\u062F");
}
let image;
try {
image = await toWebp(file.buffer);
} catch {
throw new BadRequestException("\u0641\u0627\u06CC\u0644 \u062A\u0635\u0648\u06CC\u0631 \u0642\u0627\u0628\u0644 \u067E\u0631\u062F\u0627\u0632\u0634 \u0646\u06CC\u0633\u062A");
}
const now = /* @__PURE__ */ new Date();
const month = String(now.getMonth() + 1).padStart(2, "0");
const key = `uploads/${now.getFullYear()}/${month}/${randomUUID()}.webp`;
await this.storage.put(key, image.data, "image/webp");
const media = await this.prisma.media.create({
data: {
key,
mime: "image/webp",
size: image.size,
width: image.width,
height: image.height,
alt: alt.trim().slice(0, 200),
originalName: Buffer.from(file.originalname, "latin1").toString("utf8").slice(0, 200)
}
});
this.audit.log(userId, "upload", "media", media.id, media.originalName);
return this.toDto(media);
}
async updateAlt(id, alt, userId) {
const media = await this.prisma.media.update({ where: { id }, data: { alt } });
this.audit.log(userId, "update", "media", id, media.originalName);
this.revalidate.trigger();
return this.toDto(media);
}
async remove(id, userId) {
const media = await this.prisma.media.findUnique({
where: { id },
include: { _count: { select: { categoryCovers: true, productImages: true, productGallery: true } } }
});
if (!media)
throw new NotFoundException("\u0641\u0627\u06CC\u0644 \u067E\u06CC\u062F\u0627 \u0646\u0634\u062F");
const { categoryCovers, productImages, productGallery } = media._count;
const sections = await this.prisma.$queryRaw`
SELECT key FROM "SiteSection" WHERE data::text LIKE ${"%" + media.key + "%"}`;
if (categoryCovers + productImages + productGallery + sections.length > 0) {
throw new ConflictException("\u0627\u06CC\u0646 \u062A\u0635\u0648\u06CC\u0631 \u062F\u0631 \u0645\u062D\u0635\u0648\u0644\u0627\u062A\u060C \u062F\u0633\u062A\u0647\u200C\u0647\u0627 \u06CC\u0627 \u0628\u062E\u0634\u200C\u0647\u0627\u06CC \u0633\u0627\u06CC\u062A \u0627\u0633\u062A\u0641\u0627\u062F\u0647 \u0634\u062F\u0647 \u0648 \u0642\u0627\u0628\u0644 \u062D\u0630\u0641 \u0646\u06CC\u0633\u062A");
}
await this.prisma.media.delete({ where: { id } });
await this.storage.remove(media.key).catch((e) => {
this.logger.warn(`could not delete object ${media.key}: ${String(e)}`);
});
this.audit.log(userId, "delete", "media", id, media.originalName);
}
};
MediaService = MediaService_1 = __decorate3([
Injectable(),
__metadata3("design:paramtypes", [
PrismaService,
AuditService,
RevalidateService
])
], MediaService);
// dist/media/media.controller.js
var __decorate4 = 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 __metadata4 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param2 = function(paramIndex, decorator) {
return function(target, key) {
decorator(target, key, paramIndex);
};
};
var listQuery = external_exports.object({
page: external_exports.coerce.number().int().min(1).default(1),
pageSize: external_exports.coerce.number().int().min(1).max(100).default(40),
q: external_exports.string().trim().max(100).optional()
});
var MediaController = class MediaController2 {
static {
__name(this, "MediaController");
}
media;
constructor(media) {
this.media = media;
}
list(q) {
return this.media.list(q.page, q.pageSize, q.q);
}
upload(file, alt, user) {
return this.media.upload(file, typeof alt === "string" ? alt : "", user.id);
}
update(id, body, user) {
return this.media.updateAlt(id, body.alt, user.id);
}
async remove(id, user) {
await this.media.remove(id, user.id);
}
};
__decorate4([
Get(),
__param2(0, Query(new ZodPipe(listQuery))),
__metadata4("design:type", Function),
__metadata4("design:paramtypes", [Object]),
__metadata4("design:returntype", void 0)
], MediaController.prototype, "list", null);
__decorate4([
Post(),
UseInterceptors(FileInterceptor("file", { limits: { fileSize: 15 * 1024 * 1024 } })),
__param2(0, UploadedFile()),
__param2(1, Body("alt")),
__param2(2, CurrentUser()),
__metadata4("design:type", Function),
__metadata4("design:paramtypes", [Object, Object, Object]),
__metadata4("design:returntype", void 0)
], MediaController.prototype, "upload", null);
__decorate4([
Patch(":id"),
__param2(0, Param("id", IdPipe)),
__param2(1, Body(new ZodPipe(mediaUpdateSchema))),
__param2(2, CurrentUser()),
__metadata4("design:type", Function),
__metadata4("design:paramtypes", [Number, Object, Object]),
__metadata4("design:returntype", void 0)
], MediaController.prototype, "update", null);
__decorate4([
Roles("ADMIN"),
Delete(":id"),
HttpCode(204),
__param2(0, Param("id", IdPipe)),
__param2(1, CurrentUser()),
__metadata4("design:type", Function),
__metadata4("design:paramtypes", [Number, Object]),
__metadata4("design:returntype", Promise)
], MediaController.prototype, "remove", null);
MediaController = __decorate4([
AdminAuth(),
Controller("admin/media"),
__metadata4("design:paramtypes", [MediaService])
], MediaController);
var MediaModule = class MediaModule2 {
static {
__name(this, "MediaModule");
}
};
MediaModule = __decorate4([
Module({
controllers: [MediaController],
providers: [MediaService],
exports: [MediaService]
})
], MediaModule);
// dist/catalog/categories.service.js
init_common();
var __decorate5 = 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 __metadata5 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var withCover = { coverImage: true };
var CategoriesService = class CategoriesService2 {
static {
__name(this, "CategoriesService");
}
prisma;
media;
audit;
revalidate;
constructor(prisma, media, audit, revalidate) {
this.prisma = prisma;
this.media = media;
this.audit = audit;
this.revalidate = revalidate;
}
async list() {
const rows = await this.prisma.category.findMany({
orderBy: [{ sortOrder: "asc" }, { id: "asc" }],
include: { ...withCover, _count: { select: { products: true, groups: true } } }
});
return rows.map(({ coverImage, _count, ...c }) => ({
...c,
coverImage: coverImage && this.media.toDto(coverImage),
productCount: _count.products,
groupCount: _count.groups
}));
}
async get(id) {
const { coverImage, ...c } = await this.prisma.category.findUniqueOrThrow({
where: { id },
include: {
...withCover,
groups: {
orderBy: { sortOrder: "asc" },
include: { _count: { select: { products: true } } }
}
}
});
return {
...c,
coverImage: coverImage && this.media.toDto(coverImage),
groups: c.groups.map(({ _count, ...g }) => ({ ...g, productCount: _count.products }))
};
}
async create(input, userId) {
this.assertUniqueGroupSlugs(input);
const { groups, ...data } = input;
const last = await this.prisma.category.aggregate({ _max: { sortOrder: true } });
const category = await this.prisma.category.create({
data: {
...data,
sortOrder: (last._max.sortOrder ?? -1) + 1,
groups: {
create: groups.map((g, i) => ({ slug: g.slug, name: g.name, desc: g.desc, sortOrder: i }))
}
}
});
this.audit.log(userId, "create", "category", category.id, category.name);
this.revalidate.trigger();
return this.get(category.id);
}
async update(id, input, userId) {
this.assertUniqueGroupSlugs(input);
const { groups, ...data } = input;
await this.prisma.$transaction(async (tx) => {
const category = await tx.category.update({ where: { id }, data });
const keepIds = groups.flatMap((g) => g.id ? [g.id] : []);
await tx.productGroup.deleteMany({ where: { categoryId: id, id: { notIn: keepIds } } });
for (const g of groups) {
if (g.id) {
await tx.productGroup.update({
where: { id: g.id, categoryId: id },
data: { slug: `__tmp-${g.id}` }
});
}
}
for (const [i, g] of groups.entries()) {
const fields = { slug: g.slug, name: g.name, desc: g.desc, sortOrder: i };
if (g.id) {
await tx.productGroup.update({ where: { id: g.id, categoryId: id }, data: fields });
} else {
await tx.productGroup.create({ data: { ...fields, categoryId: id } });
}
}
this.audit.log(userId, "update", "category", id, category.name);
});
this.revalidate.trigger();
return this.get(id);
}
async remove(id, userId) {
const category = await this.prisma.category.findUniqueOrThrow({
where: { id },
include: { _count: { select: { products: true } } }
});
if (category._count.products > 0) {
throw new ConflictException(`\u0627\u06CC\u0646 \u062F\u0633\u062A\u0647 ${category._count.products} \u0645\u062D\u0635\u0648\u0644 \u062F\u0627\u0631\u062F\u061B \u0627\u0628\u062A\u062F\u0627 \u0645\u062D\u0635\u0648\u0644\u0627\u062A \u0631\u0627 \u062D\u0630\u0641 \u06CC\u0627 \u062C\u0627\u0628\u0647\u200C\u062C\u0627 \u06A9\u0646\u06CC\u062F`);
}
await this.prisma.category.delete({ where: { id } });
this.audit.log(userId, "delete", "category", id, category.name);
this.revalidate.trigger();
}
async reorder(ids, userId) {
await this.prisma.$transaction(ids.map((id, i) => this.prisma.category.update({ where: { id }, data: { sortOrder: i } })));
this.audit.log(userId, "reorder", "category", "", `${ids.length} \u062F\u0633\u062A\u0647`);
this.revalidate.trigger();
}
assertUniqueGroupSlugs(input) {
const slugs = input.groups.map((g) => g.slug);
if (new Set(slugs).size !== slugs.length) {
throw new ConflictException("\u0627\u0633\u0644\u0627\u06AF \u0632\u06CC\u0631\u06AF\u0631\u0648\u0647\u200C\u0647\u0627 \u0628\u0627\u06CC\u062F \u06CC\u06A9\u062A\u0627 \u0628\u0627\u0634\u062F");
}
}
};
CategoriesService = __decorate5([
Injectable(),
__metadata5("design:paramtypes", [
PrismaService,
MediaService,
AuditService,
RevalidateService
])
], CategoriesService);
// dist/catalog/products.service.js
init_common();
var __decorate6 = 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 __metadata6 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var ProductsService = class ProductsService2 {
static {
__name(this, "ProductsService");
}
prisma;
media;
audit;
revalidate;
constructor(prisma, media, audit, revalidate) {
this.prisma = prisma;
this.media = media;
this.audit = audit;
this.revalidate = revalidate;
}
async list(q) {
const where = {
...q.categoryId && { categoryId: q.categoryId },
...q.groupId && { groupId: q.groupId },
...q.status && { isPublished: q.status === "published" },
...q.q && {
OR: [
{ name: { contains: q.q, mode: "insensitive" } },
{ nameEn: { contains: q.q, mode: "insensitive" } },
{ code: { contains: q.q, mode: "insensitive" } }
]
}
};
const [rows, total] = await this.prisma.$transaction([
this.prisma.product.findMany({
where,
orderBy: [{ category: { sortOrder: "asc" } }, { sortOrder: "asc" }, { id: "asc" }],
skip: (q.page - 1) * q.pageSize,
take: q.pageSize,
include: {
image: true,
category: { select: { id: true, name: true } },
group: { select: { id: true, name: true } }
}
}),
this.prisma.product.count({ where })
]);
return {
items: rows.map(({ image, ...p }) => ({ ...p, image: image && this.media.toDto(image) })),
total,
page: q.page,
pageSize: q.pageSize
};
}
async get(id) {
const { image, gallery, ...p } = await this.prisma.product.findUniqueOrThrow({
where: { id },
include: { image: true, gallery: { orderBy: { sortOrder: "asc" }, include: { media: true } } }
});
return {
...p,
image: image && this.media.toDto(image),
gallery: gallery.map((g) => this.media.toDto(g.media))
};
}
async create(input, userId) {
await this.assertGroup(input);
const { galleryIds, ...data } = input;
const last = await this.prisma.product.aggregate({
where: { categoryId: input.categoryId },
_max: { sortOrder: true }
});
const product = await this.prisma.product.create({
data: {
...data,
sortOrder: (last._max.sortOrder ?? -1) + 1,
gallery: { create: unique(galleryIds).map((mediaId, i) => ({ mediaId, sortOrder: i })) }
}
});
this.audit.log(userId, "create", "product", product.id, product.name);
this.revalidate.trigger();
return this.get(product.id);
}
async update(id, input, userId) {
await this.assertGroup(input);
const { galleryIds, ...data } = input;
const product = await this.prisma.product.update({
where: { id },
data: {
...data,
gallery: {
deleteMany: {},
create: unique(galleryIds).map((mediaId, i) => ({ mediaId, sortOrder: i }))
}
}
});
this.audit.log(userId, "update", "product", id, product.name);
this.revalidate.trigger();
return this.get(id);
}
async setPublished(id, isPublished, userId) {
const product = await this.prisma.product.update({ where: { id }, data: { isPublished } });
this.audit.log(userId, isPublished ? "publish" : "unpublish", "product", id, product.name);
this.revalidate.trigger();
return { id, isPublished };
}
async duplicate(id, userId) {
const src = await this.prisma.product.findUniqueOrThrow({
where: { id },
include: { gallery: true }
});
let n = 1;
const taken = /* @__PURE__ */ __name(async (code, slug) => await this.prisma.product.count({ where: { OR: [{ code }, { slug }] } }) > 0, "taken");
while (await taken(`${src.code}-${n}`, `${src.slug}-copy-${n}`))
n++;
const copy = await this.prisma.product.create({
data: {
categoryId: src.categoryId,
groupId: src.groupId,
code: `${src.code}-${n}`,
slug: `${src.slug}-copy-${n}`,
name: `${src.name} (\u06A9\u067E\u06CC)`,
nameEn: src.nameEn,
desc: src.desc,
specs: src.specs,
variants: src.variants,
details: src.details,
brand: src.brand,
origin: src.origin,
sizes: src.sizes,
standards: src.standards,
features: src.features,
applications: src.applications,
attributes: src.attributes ?? [],
packaging: src.packaging,
minOrder: src.minOrder,
seoTitle: src.seoTitle,
seoDescription: src.seoDescription,
imageId: src.imageId,
sortOrder: src.sortOrder + 1,
isPublished: false,
gallery: {
create: src.gallery.map((g) => ({ mediaId: g.mediaId, sortOrder: g.sortOrder }))
}
}
});
this.audit.log(userId, "duplicate", "product", copy.id, copy.name);
return this.get(copy.id);
}
async remove(id, userId) {
const product = await this.prisma.product.delete({ where: { id } });
this.audit.log(userId, "delete", "product", id, product.name);
this.revalidate.trigger();
}
async reorder(ids, userId) {
await this.prisma.$transaction(ids.map((id, i) => this.prisma.product.update({ where: { id }, data: { sortOrder: i } })));
this.audit.log(userId, "reorder", "product", "", `${ids.length} \u0645\u062D\u0635\u0648\u0644`);
this.revalidate.trigger();
}
async assertGroup(input) {
if (!input.groupId)
return;
const group = await this.prisma.productGroup.findUnique({ where: { id: input.groupId } });
if (group?.categoryId !== input.categoryId) {
throw new BadRequestException("\u0632\u06CC\u0631\u06AF\u0631\u0648\u0647 \u0627\u0646\u062A\u062E\u0627\u0628\u200C\u0634\u062F\u0647 \u0645\u062A\u0639\u0644\u0642 \u0628\u0647 \u0627\u06CC\u0646 \u062F\u0633\u062A\u0647 \u0646\u06CC\u0633\u062A");
}
}
};
ProductsService = __decorate6([
Injectable(),
__metadata6("design:paramtypes", [
PrismaService,
MediaService,
AuditService,
RevalidateService
])
], ProductsService);
var unique = /* @__PURE__ */ __name((ids) => [...new Set(ids)], "unique");
// dist/catalog/catalog.module.js
var __decorate7 = 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 __metadata7 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param3 = function(paramIndex, decorator) {
return function(target, key) {
decorator(target, key, paramIndex);
};
};
var publishSchema = external_exports.object({ isPublished: external_exports.boolean() });
var CategoriesController = class CategoriesController2 {
static {
__name(this, "CategoriesController");
}
categories;
constructor(categories) {
this.categories = categories;
}
list() {
return this.categories.list();
}
get(id) {
return this.categories.get(id);
}
create(body, user) {
return this.categories.create(body, user.id);
}
async reorder(body, user) {
await this.categories.reorder(body.ids, user.id);
}
update(id, body, user) {
return this.categories.update(id, body, user.id);
}
async remove(id, user) {
await this.categories.remove(id, user.id);
}
};
__decorate7([
Get(),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", []),
__metadata7("design:returntype", void 0)
], CategoriesController.prototype, "list", null);
__decorate7([
Get(":id"),
__param3(0, Param("id", IdPipe)),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Number]),
__metadata7("design:returntype", void 0)
], CategoriesController.prototype, "get", null);
__decorate7([
Post(),
__param3(0, Body(new ZodPipe(categoryInputSchema))),
__param3(1, CurrentUser()),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Object, Object]),
__metadata7("design:returntype", void 0)
], CategoriesController.prototype, "create", null);
__decorate7([
Post("reorder"),
HttpCode(204),
__param3(0, Body(new ZodPipe(reorderSchema))),
__param3(1, CurrentUser()),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Object, Object]),
__metadata7("design:returntype", Promise)
], CategoriesController.prototype, "reorder", null);
__decorate7([
Put(":id"),
__param3(0, Param("id", IdPipe)),
__param3(1, Body(new ZodPipe(categoryInputSchema))),
__param3(2, CurrentUser()),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Number, Object, Object]),
__metadata7("design:returntype", void 0)
], CategoriesController.prototype, "update", null);
__decorate7([
Roles("ADMIN"),
Delete(":id"),
HttpCode(204),
__param3(0, Param("id", IdPipe)),
__param3(1, CurrentUser()),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Number, Object]),
__metadata7("design:returntype", Promise)
], CategoriesController.prototype, "remove", null);
CategoriesController = __decorate7([
AdminAuth(),
Controller("admin/categories"),
__metadata7("design:paramtypes", [CategoriesService])
], CategoriesController);
var ProductsController = class ProductsController2 {
static {
__name(this, "ProductsController");
}
products;
constructor(products) {
this.products = products;
}
list(q) {
return this.products.list(q);
}
get(id) {
return this.products.get(id);
}
create(body, user) {
return this.products.create(body, user.id);
}
async reorder(body, user) {
await this.products.reorder(body.ids, user.id);
}
duplicate(id, user) {
return this.products.duplicate(id, user.id);
}
publish(id, body, user) {
return this.products.setPublished(id, body.isPublished, user.id);
}
update(id, body, user) {
return this.products.update(id, body, user.id);
}
async remove(id, user) {
await this.products.remove(id, user.id);
}
};
__decorate7([
Get(),
__param3(0, Query(new ZodPipe(productListQuerySchema))),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Object]),
__metadata7("design:returntype", void 0)
], ProductsController.prototype, "list", null);
__decorate7([
Get(":id"),
__param3(0, Param("id", IdPipe)),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Number]),
__metadata7("design:returntype", void 0)
], ProductsController.prototype, "get", null);
__decorate7([
Post(),
__param3(0, Body(new ZodPipe(productInputSchema))),
__param3(1, CurrentUser()),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Object, Object]),
__metadata7("design:returntype", void 0)
], ProductsController.prototype, "create", null);
__decorate7([
Post("reorder"),
HttpCode(204),
__param3(0, Body(new ZodPipe(reorderSchema))),
__param3(1, CurrentUser()),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Object, Object]),
__metadata7("design:returntype", Promise)
], ProductsController.prototype, "reorder", null);
__decorate7([
Post(":id/duplicate"),
__param3(0, Param("id", IdPipe)),
__param3(1, CurrentUser()),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Number, Object]),
__metadata7("design:returntype", void 0)
], ProductsController.prototype, "duplicate", null);
__decorate7([
Patch(":id/publish"),
__param3(0, Param("id", IdPipe)),
__param3(1, Body(new ZodPipe(publishSchema))),
__param3(2, CurrentUser()),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Number, Object, Object]),
__metadata7("design:returntype", void 0)
], ProductsController.prototype, "publish", null);
__decorate7([
Put(":id"),
__param3(0, Param("id", IdPipe)),
__param3(1, Body(new ZodPipe(productInputSchema))),
__param3(2, CurrentUser()),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Number, Object, Object]),
__metadata7("design:returntype", void 0)
], ProductsController.prototype, "update", null);
__decorate7([
Roles("ADMIN"),
Delete(":id"),
HttpCode(204),
__param3(0, Param("id", IdPipe)),
__param3(1, CurrentUser()),
__metadata7("design:type", Function),
__metadata7("design:paramtypes", [Number, Object]),
__metadata7("design:returntype", Promise)
], ProductsController.prototype, "remove", null);
ProductsController = __decorate7([
AdminAuth(),
Controller("admin/products"),
__metadata7("design:paramtypes", [ProductsService])
], ProductsController);
var CatalogModule = class CatalogModule2 {
static {
__name(this, "CatalogModule");
}
};
CatalogModule = __decorate7([
Module({
imports: [MediaModule],
controllers: [CategoriesController, ProductsController],
providers: [CategoriesService, ProductsService]
})
], CatalogModule);
// dist/common/prisma-exception.filter.js
init_common();
var __decorate8 = 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 FIELD_LABELS = {
slug: "\u0627\u0633\u0644\u0627\u06AF",
code: "\u06A9\u062F",
email: "\u0627\u06CC\u0645\u06CC\u0644",
phone: "\u0634\u0645\u0627\u0631\u0647 \u0645\u0648\u0628\u0627\u06CC\u0644"
};
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("_") : [];
}
__name(uniqueFields, "uniqueFields");
var PrismaExceptionFilter = class PrismaExceptionFilter2 {
static {
__name(this, "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("\u060C ");
return res.status(HttpStatus.CONFLICT).json({
statusCode: HttpStatus.CONFLICT,
message: fields ? `\u0645\u0642\u062F\u0627\u0631 \xAB${fields}\xBB \u062A\u06A9\u0631\u0627\u0631\u06CC \u0627\u0633\u062A` : "\u0645\u0642\u062F\u0627\u0631 \u062A\u06A9\u0631\u0627\u0631\u06CC \u0627\u0633\u062A"
});
}
case "P2003":
return res.status(HttpStatus.CONFLICT).json({
statusCode: HttpStatus.CONFLICT,
message: "\u0627\u06CC\u0646 \u0645\u0648\u0631\u062F \u0628\u0647 \u062F\u0627\u062F\u0647\u200C\u0647\u0627\u06CC \u062F\u06CC\u06AF\u0631\u06CC \u0648\u0627\u0628\u0633\u062A\u0647 \u0627\u0633\u062A"
});
case "P2025":
return res.status(HttpStatus.NOT_FOUND).json({ statusCode: HttpStatus.NOT_FOUND, message: "\u0645\u0648\u0631\u062F \u067E\u06CC\u062F\u0627 \u0646\u0634\u062F" });
default:
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
message: "\u062E\u0637\u0627\u06CC \u067E\u0627\u06CC\u06AF\u0627\u0647 \u062F\u0627\u062F\u0647"
});
}
}
};
PrismaExceptionFilter = __decorate8([
Catch(prismaNamespace_exports.PrismaClientKnownRequestError)
], PrismaExceptionFilter);
// dist/contact/contact.module.js
init_common();
var import_throttler2 = __toESM(require_dist(), 1);
var __decorate9 = 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 __metadata8 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param4 = function(paramIndex, decorator) {
return function(target, key) {
decorator(target, key, paramIndex);
};
};
var listQuery2 = external_exports.object({
status: external_exports.enum(MESSAGE_STATUSES).optional(),
page: external_exports.coerce.number().int().min(1).default(1),
pageSize: external_exports.coerce.number().int().min(1).max(100).default(20)
});
var toMessageDto = /* @__PURE__ */ __name((m) => ({
id: m.id,
name: m.name,
org: m.org,
phone: m.phone,
message: m.message,
status: m.status,
createdAt: m.createdAt.toISOString()
}), "toMessageDto");
var ContactService = class ContactService2 {
static {
__name(this, "ContactService");
}
prisma;
audit;
constructor(prisma, audit) {
this.prisma = prisma;
this.audit = audit;
}
async submit(input, ip, userAgent) {
if (input.website)
return;
await this.prisma.contactMessage.create({
data: {
name: input.name,
org: input.org,
phone: input.phone,
message: input.message,
ip: ip.slice(0, 64),
userAgent: userAgent.slice(0, 300)
}
});
}
async list(q) {
const where = q.status ? { status: q.status } : {};
const [items, total] = await this.prisma.$transaction([
this.prisma.contactMessage.findMany({
where,
orderBy: { id: "desc" },
skip: (q.page - 1) * q.pageSize,
take: q.pageSize
}),
this.prisma.contactMessage.count({ where })
]);
return { items: items.map(toMessageDto), total, page: q.page, pageSize: q.pageSize };
}
async setStatus(id, status) {
return toMessageDto(await this.prisma.contactMessage.update({ where: { id }, data: { status } }));
}
async remove(id, userId) {
const m = await this.prisma.contactMessage.delete({ where: { id } });
this.audit.log(userId, "delete", "message", id, m.name);
}
};
ContactService = __decorate9([
Injectable(),
__metadata8("design:paramtypes", [
PrismaService,
AuditService
])
], ContactService);
var PublicContactController = class PublicContactController2 {
static {
__name(this, "PublicContactController");
}
contact;
constructor(contact) {
this.contact = contact;
}
async submit(body, req) {
await this.contact.submit(body, req.ip ?? "", req.headers["user-agent"] ?? "");
return { ok: true };
}
};
__decorate9([
Post(),
HttpCode(201),
(0, import_throttler2.Throttle)({ default: { limit: 5, ttl: 10 * 6e4 } }),
__param4(0, Body(new ZodPipe(contactInputSchema))),
__param4(1, Req()),
__metadata8("design:type", Function),
__metadata8("design:paramtypes", [Object, Object]),
__metadata8("design:returntype", Promise)
], PublicContactController.prototype, "submit", null);
PublicContactController = __decorate9([
Controller("public/contact"),
__metadata8("design:paramtypes", [ContactService])
], PublicContactController);
var MessagesController = class MessagesController2 {
static {
__name(this, "MessagesController");
}
contact;
constructor(contact) {
this.contact = contact;
}
list(q) {
return this.contact.list(q);
}
update(id, body) {
return this.contact.setStatus(id, body.status);
}
async remove(id, user) {
await this.contact.remove(id, user.id);
}
};
__decorate9([
Get(),
__param4(0, Query(new ZodPipe(listQuery2))),
__metadata8("design:type", Function),
__metadata8("design:paramtypes", [Object]),
__metadata8("design:returntype", void 0)
], MessagesController.prototype, "list", null);
__decorate9([
Patch(":id"),
__param4(0, Param("id", IdPipe)),
__param4(1, Body(new ZodPipe(messageUpdateSchema))),
__metadata8("design:type", Function),
__metadata8("design:paramtypes", [Number, Object]),
__metadata8("design:returntype", void 0)
], MessagesController.prototype, "update", null);
__decorate9([
Roles("ADMIN"),
Delete(":id"),
HttpCode(204),
__param4(0, Param("id", IdPipe)),
__param4(1, CurrentUser()),
__metadata8("design:type", Function),
__metadata8("design:paramtypes", [Number, Object]),
__metadata8("design:returntype", Promise)
], MessagesController.prototype, "remove", null);
MessagesController = __decorate9([
AdminAuth(),
Controller("admin/messages"),
__metadata8("design:paramtypes", [ContactService])
], MessagesController);
var ContactModule = class ContactModule2 {
static {
__name(this, "ContactModule");
}
};
ContactModule = __decorate9([
Module({
controllers: [PublicContactController, MessagesController],
providers: [ContactService]
})
], ContactModule);
// dist/dashboard/dashboard.module.js
init_common();
var __decorate10 = 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 __metadata9 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var DAY_NAMES = ["\u06CC\u06A9\u0634\u0646\u0628\u0647", "\u062F\u0648\u0634\u0646\u0628\u0647", "\u0633\u0647\u200C\u0634\u0646\u0628\u0647", "\u0686\u0647\u0627\u0631\u0634\u0646\u0628\u0647", "\u067E\u0646\u062C\u200C\u0634\u0646\u0628\u0647", "\u062C\u0645\u0639\u0647", "\u0634\u0646\u0628\u0647"];
var DashboardController = class DashboardController2 {
static {
__name(this, "DashboardController");
}
prisma;
constructor(prisma) {
this.prisma = prisma;
}
async get() {
const [categories, products, draftProducts, newMessages, readMessages, archivedMessages, media, messages, activity, categoryRows, sectionRows] = await Promise.all([
this.prisma.category.count(),
this.prisma.product.count(),
this.prisma.product.count({ where: { isPublished: false } }),
this.prisma.contactMessage.count({ where: { status: "NEW" } }),
this.prisma.contactMessage.count({ where: { status: "READ" } }),
this.prisma.contactMessage.count({ where: { status: "ARCHIVED" } }),
this.prisma.media.count(),
this.prisma.contactMessage.findMany({ orderBy: { id: "desc" }, take: 6 }),
this.prisma.auditLog.findMany({
orderBy: { id: "desc" },
take: 10,
include: { user: { select: { name: true } } }
}),
this.prisma.category.findMany({
select: { id: true, name: true, _count: { select: { products: true } } },
orderBy: { products: { _count: "desc" } },
take: 7
}),
this.prisma.siteSection.findMany()
]);
let hiddenCount = 0;
for (const s of sectionRows) {
if (s.data && typeof s.data === "object" && s.data.enabled === false) {
hiddenCount++;
}
}
const now = /* @__PURE__ */ new Date();
const trend = [];
for (let i = 6; i >= 0; i--) {
const start = new Date(now.getFullYear(), now.getMonth(), now.getDate() - i, 0, 0, 0);
const end = new Date(now.getFullYear(), now.getMonth(), now.getDate() - i, 23, 59, 59, 999);
const count = await this.prisma.contactMessage.count({
where: { createdAt: { gte: start, lte: end } }
});
trend.push({
date: start.toISOString().slice(0, 10),
dayName: DAY_NAMES[start.getDay()],
messages: count
});
}
return {
categories,
products,
draftProducts,
newMessages,
media,
recentMessages: messages.map(toMessageDto),
recentActivity: activity.map((a) => ({
id: a.id,
action: a.action,
entity: a.entity,
summary: a.summary,
user: a.user?.name ?? null,
createdAt: a.createdAt.toISOString()
})),
categoryStats: categoryRows.map((c) => ({
id: c.id,
name: c.name,
count: c._count.products
})),
messageBreakdown: {
new: newMessages,
read: readMessages,
archived: archivedMessages,
total: newMessages + readMessages + archivedMessages
},
sectionsSummary: {
total: SECTION_KEYS.length,
visible: SECTION_KEYS.length - hiddenCount,
hidden: hiddenCount
},
trend
};
}
};
__decorate10([
Get(),
__metadata9("design:type", Function),
__metadata9("design:paramtypes", []),
__metadata9("design:returntype", Promise)
], DashboardController.prototype, "get", null);
DashboardController = __decorate10([
AdminAuth(),
Controller("admin/dashboard"),
__metadata9("design:paramtypes", [PrismaService])
], DashboardController);
var DashboardModule = class DashboardModule2 {
static {
__name(this, "DashboardModule");
}
};
DashboardModule = __decorate10([
Module({ controllers: [DashboardController] })
], DashboardModule);
// dist/public/public.module.js
init_common();
// dist/sections/sections.module.js
init_common();
var __decorate11 = 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 __metadata10 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param5 = function(paramIndex, decorator) {
return function(target, key) {
decorator(target, key, paramIndex);
};
};
var SectionsService = class SectionsService2 {
static {
__name(this, "SectionsService");
}
prisma;
audit;
revalidate;
constructor(prisma, audit, revalidate) {
this.prisma = prisma;
this.audit = audit;
this.revalidate = revalidate;
}
async getAll() {
const rows = await this.prisma.siteSection.findMany();
const byKey = new Map(rows.map((r) => [r.key, r.data]));
const missing = SECTION_KEYS.filter((k) => !byKey.has(k));
if (missing.length) {
throw new ServiceUnavailableException(`\u0645\u062D\u062A\u0648\u0627\u06CC \u0633\u0627\u06CC\u062A \u0645\u0642\u062F\u0627\u0631\u062F\u0647\u06CC \u0646\u0634\u062F\u0647 \u0627\u0633\u062A (${missing.join(", ")}) \u2014 pnpm db:seed \u0631\u0627 \u0627\u062C\u0631\u0627 \u06A9\u0646\u06CC\u062F`);
}
return Object.fromEntries(SECTION_KEYS.map((k) => [k, sectionSchemas[k].parse(byKey.get(k))]));
}
async get(key) {
if (!isSectionKey(key))
throw new NotFoundException("\u0628\u062E\u0634 \u067E\u06CC\u062F\u0627 \u0646\u0634\u062F");
const row = await this.prisma.siteSection.findUnique({ where: { key } });
if (!row)
throw new NotFoundException("\u0628\u062E\u0634 \u067E\u06CC\u062F\u0627 \u0646\u0634\u062F");
return { key, data: sectionSchemas[key].parse(row.data), updatedAt: row.updatedAt };
}
async update(key, body, user) {
if (!isSectionKey(key))
throw new NotFoundException("\u0628\u062E\u0634 \u067E\u06CC\u062F\u0627 \u0646\u0634\u062F");
if (key === "settings" && user.role !== "ADMIN") {
throw new ForbiddenException("\u0641\u0642\u0637 \u0645\u062F\u06CC\u0631 \u06A9\u0644 \u0645\u06CC\u200C\u062A\u0648\u0627\u0646\u062F \u062A\u0646\u0638\u06CC\u0645\u0627\u062A \u0633\u0627\u06CC\u062A \u0631\u0627 \u062A\u063A\u06CC\u06CC\u0631 \u062F\u0647\u062F");
}
const parsed = sectionSchemas[key].safeParse(body);
if (!parsed.success) {
throw new BadRequestException({
statusCode: 400,
message: "\u0627\u0637\u0644\u0627\u0639\u0627\u062A \u0648\u0627\u0631\u062F\u0634\u062F\u0647 \u0645\u0639\u062A\u0628\u0631 \u0646\u06CC\u0633\u062A",
issues: toIssues(parsed.error)
});
}
const row = await this.prisma.siteSection.upsert({
where: { key },
create: { key, data: parsed.data, updatedById: user.id },
update: { data: parsed.data, updatedById: user.id }
});
this.audit.log(user.id, "update", "section", key, key);
this.revalidate.trigger();
return { key, data: parsed.data, updatedAt: row.updatedAt };
}
async listAdmin() {
const rows = await this.prisma.siteSection.findMany();
const byKey = new Map(rows.map((r) => [r.key, r]));
return SECTION_KEYS.map((key) => {
const row = byKey.get(key);
let data = null;
if (row) {
const parsed = sectionSchemas[key].safeParse(row.data);
data = parsed.success ? parsed.data : row.data;
}
return {
key,
updatedAt: row?.updatedAt?.toISOString() ?? null,
enabled: data && typeof data === "object" && "enabled" in data ? data.enabled !== false : true
};
});
}
async setVisibility(key, enabled, user) {
if (!isSectionKey(key))
throw new NotFoundException("\u0628\u062E\u0634 \u067E\u06CC\u062F\u0627 \u0646\u0634\u062F");
if (key === "settings") {
throw new BadRequestException("\u062A\u0646\u0638\u06CC\u0645\u0627\u062A \u0633\u0627\u06CC\u062A \u0642\u0627\u0628\u0644\u06CC\u062A \u062A\u063A\u06CC\u06CC\u0631 \u0648\u0636\u0639\u06CC\u062A \u0646\u0645\u0627\u06CC\u0634 \u0646\u062F\u0627\u0631\u062F");
}
const row = await this.prisma.siteSection.findUnique({ where: { key } });
if (!row)
throw new NotFoundException("\u0628\u062E\u0634 \u067E\u06CC\u062F\u0627 \u0646\u0634\u062F");
const currentData = row.data && typeof row.data === "object" ? { ...row.data } : {};
currentData.enabled = enabled;
const parsed = sectionSchemas[key].safeParse(currentData);
if (!parsed.success) {
throw new BadRequestException({
statusCode: 400,
message: "\u0627\u0637\u0644\u0627\u0639\u0627\u062A \u0628\u062E\u0634 \u0645\u0639\u062A\u0628\u0631 \u0646\u06CC\u0633\u062A",
issues: toIssues(parsed.error)
});
}
const updated = await this.prisma.siteSection.update({
where: { key },
data: { data: parsed.data, updatedById: user.id }
});
this.audit.log(user.id, "update", "section", key, `\u062A\u063A\u06CC\u06CC\u0631 \u0648\u0636\u0639\u06CC\u062A \u0646\u0645\u0627\u06CC\u0634 \u0628\u0647 ${enabled ? "\u0646\u0645\u0627\u06CC\u0634" : "\u0639\u062F\u0645 \u0646\u0645\u0627\u06CC\u0634"}`);
this.revalidate.trigger();
return {
key,
enabled: parsed.data.enabled !== false,
updatedAt: updated.updatedAt.toISOString()
};
}
};
SectionsService = __decorate11([
Injectable(),
__metadata10("design:paramtypes", [
PrismaService,
AuditService,
RevalidateService
])
], SectionsService);
var SectionsController = class SectionsController2 {
static {
__name(this, "SectionsController");
}
sections;
constructor(sections) {
this.sections = sections;
}
list() {
return this.sections.listAdmin();
}
get(key) {
return this.sections.get(key);
}
update(key, body, user) {
return this.sections.update(key, body, user);
}
setVisibility(key, body, user) {
const enabled = body && typeof body.enabled === "boolean" ? body.enabled : Boolean(body?.enabled);
return this.sections.setVisibility(key, enabled, user);
}
};
__decorate11([
Get(),
__metadata10("design:type", Function),
__metadata10("design:paramtypes", []),
__metadata10("design:returntype", void 0)
], SectionsController.prototype, "list", null);
__decorate11([
Get(":key"),
__param5(0, Param("key")),
__metadata10("design:type", Function),
__metadata10("design:paramtypes", [String]),
__metadata10("design:returntype", void 0)
], SectionsController.prototype, "get", null);
__decorate11([
Put(":key"),
__param5(0, Param("key")),
__param5(1, Body()),
__param5(2, CurrentUser()),
__metadata10("design:type", Function),
__metadata10("design:paramtypes", [String, Object, Object]),
__metadata10("design:returntype", void 0)
], SectionsController.prototype, "update", null);
__decorate11([
Patch(":key/visibility"),
__param5(0, Param("key")),
__param5(1, Body()),
__param5(2, CurrentUser()),
__metadata10("design:type", Function),
__metadata10("design:paramtypes", [String, Object, Object]),
__metadata10("design:returntype", void 0)
], SectionsController.prototype, "setVisibility", null);
SectionsController = __decorate11([
AdminAuth(),
Controller("admin/sections"),
__metadata10("design:paramtypes", [SectionsService])
], SectionsController);
var SectionsModule = class SectionsModule2 {
static {
__name(this, "SectionsModule");
}
};
SectionsModule = __decorate11([
Module({
controllers: [SectionsController],
providers: [SectionsService],
exports: [SectionsService]
})
], SectionsModule);
// dist/public/public.module.js
var __decorate12 = 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 __metadata11 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param6 = function(paramIndex, decorator) {
return function(target, key) {
decorator(target, key, paramIndex);
};
};
var visible = { isPublished: true, category: { isPublished: true } };
var RELATED_LIMIT = 4;
var isAttribute = /* @__PURE__ */ __name((a) => !!a && typeof a === "object" && typeof a.name === "string" && typeof a.value === "string", "isAttribute");
var PublicService = class PublicService2 {
static {
__name(this, "PublicService");
}
prisma;
media;
sections;
constructor(prisma, media, sections) {
this.prisma = prisma;
this.media = media;
this.sections = sections;
}
async site() {
const [sections, categories] = await Promise.all([this.sections.getAll(), this.categories()]);
return { sections, categories };
}
async categories() {
const rows = await this.prisma.category.findMany({
where: { isPublished: true },
orderBy: [{ sortOrder: "asc" }, { id: "asc" }],
include: {
coverImage: true,
_count: { select: { products: { where: { isPublished: true } } } }
}
});
return rows.map((c) => ({
slug: c.slug,
code: c.code,
name: c.name,
nameEn: c.nameEn,
shortDesc: c.shortDesc,
icon: c.icon,
coverImage: c.coverImage && this.media.url(c.coverImage.key),
productCount: c._count.products
}));
}
async category(slug) {
const c = await this.prisma.category.findFirst({
where: { slug, isPublished: true },
include: {
coverImage: true,
groups: { orderBy: { sortOrder: "asc" } },
products: {
where: { isPublished: true },
orderBy: [{ sortOrder: "asc" }, { id: "asc" }],
include: { image: true, group: { select: { slug: true } } }
}
}
});
if (!c)
throw new NotFoundException("\u062F\u0633\u062A\u0647\u200C\u0628\u0646\u062F\u06CC \u06CC\u0627\u0641\u062A \u0646\u0634\u062F");
const products = c.products.map((p) => this.toPublicProduct(p));
const usedGroups = new Set(products.map((p) => p.group));
return {
slug: c.slug,
code: c.code,
name: c.name,
nameEn: c.nameEn,
shortDesc: c.shortDesc,
fullDesc: c.fullDesc,
icon: c.icon,
seoTitle: c.seoTitle,
seoDescription: c.seoDescription,
coverImage: c.coverImage && this.media.url(c.coverImage.key),
productCount: products.length,
groups: c.groups.filter((g) => usedGroups.has(g.slug)).map((g) => ({ slug: g.slug, name: g.name, desc: g.desc })),
products
};
}
async product(slug) {
const p = await this.prisma.product.findFirst({
where: { slug, ...visible },
include: {
image: true,
gallery: { orderBy: { sortOrder: "asc" }, include: { media: true } },
group: true,
category: { include: { coverImage: true } }
}
});
if (!p)
throw new NotFoundException("\u0645\u062D\u0635\u0648\u0644 \u06CC\u0627\u0641\u062A \u0646\u0634\u062F");
const media = /* @__PURE__ */ new Map();
for (const m of [p.image, ...p.gallery.map((g) => g.media)])
if (m)
media.set(m.id, m);
const siblings = await this.prisma.product.findMany({
where: { categoryId: p.categoryId, isPublished: true, id: { not: p.id } },
orderBy: [{ sortOrder: "asc" }, { id: "asc" }],
include: { image: true, group: { select: { slug: true } } }
});
const sameGroup = /* @__PURE__ */ __name((s) => p.groupId !== null && s.groupId === p.groupId, "sameGroup");
const related = [...siblings.filter(sameGroup), ...siblings.filter((s) => !sameGroup(s))].slice(0, RELATED_LIMIT).map((s) => this.toPublicProduct(s));
return {
...this.toPublicProduct(p),
details: p.details,
brand: p.brand,
origin: p.origin,
sizes: p.sizes,
standards: p.standards,
features: p.features,
applications: p.applications,
attributes: Array.isArray(p.attributes) ? p.attributes.filter(isAttribute) : [],
packaging: p.packaging,
minOrder: p.minOrder,
seoTitle: p.seoTitle,
seoDescription: p.seoDescription,
images: [...media.values()].map((m) => ({
url: this.media.url(m.key),
alt: m.alt || p.name,
width: m.width,
height: m.height
})),
groupName: p.group?.name ?? null,
category: {
slug: p.category.slug,
code: p.category.code,
name: p.category.name,
nameEn: p.category.nameEn,
fullDesc: p.category.fullDesc,
coverImage: p.category.coverImage && this.media.url(p.category.coverImage.key)
},
related,
updatedAt: p.updatedAt.toISOString()
};
}
async productRefs() {
const rows = await this.prisma.product.findMany({
where: visible,
orderBy: [{ category: { sortOrder: "asc" } }, { sortOrder: "asc" }],
select: { slug: true, updatedAt: true }
});
return rows.map((r) => ({ slug: r.slug, updatedAt: r.updatedAt.toISOString() }));
}
toPublicProduct(p) {
return {
code: p.code,
slug: p.slug,
name: p.name,
nameEn: p.nameEn,
desc: p.desc,
specs: p.specs,
variants: p.variants,
image: p.image && this.media.url(p.image.key),
group: p.group?.slug ?? null
};
}
};
PublicService = __decorate12([
Injectable(),
__metadata11("design:paramtypes", [
PrismaService,
MediaService,
SectionsService
])
], PublicService);
var PublicController = class PublicController2 {
static {
__name(this, "PublicController");
}
publicData;
constructor(publicData) {
this.publicData = publicData;
}
site() {
return this.publicData.site();
}
categories() {
return this.publicData.categories();
}
category(slug) {
return this.publicData.category(slug);
}
products() {
return this.publicData.productRefs();
}
product(slug) {
return this.publicData.product(slug);
}
};
__decorate12([
Get("site"),
__metadata11("design:type", Function),
__metadata11("design:paramtypes", []),
__metadata11("design:returntype", void 0)
], PublicController.prototype, "site", null);
__decorate12([
Get("categories"),
__metadata11("design:type", Function),
__metadata11("design:paramtypes", []),
__metadata11("design:returntype", void 0)
], PublicController.prototype, "categories", null);
__decorate12([
Get("categories/:slug"),
__param6(0, Param("slug")),
__metadata11("design:type", Function),
__metadata11("design:paramtypes", [String]),
__metadata11("design:returntype", void 0)
], PublicController.prototype, "category", null);
__decorate12([
Get("products"),
__metadata11("design:type", Function),
__metadata11("design:paramtypes", []),
__metadata11("design:returntype", void 0)
], PublicController.prototype, "products", null);
__decorate12([
Get("products/:slug"),
__param6(0, Param("slug")),
__metadata11("design:type", Function),
__metadata11("design:paramtypes", [String]),
__metadata11("design:returntype", void 0)
], PublicController.prototype, "product", null);
PublicController = __decorate12([
Controller("public"),
__metadata11("design:paramtypes", [PublicService])
], PublicController);
var PublicModule = class PublicModule2 {
static {
__name(this, "PublicModule");
}
};
PublicModule = __decorate12([
Module({
imports: [MediaModule, SectionsModule],
controllers: [PublicController],
providers: [PublicService]
})
], PublicModule);
// dist/users/users.controller.js
init_common();
var __decorate13 = 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 __metadata12 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param7 = function(paramIndex, decorator) {
return function(target, key) {
decorator(target, key, paramIndex);
};
};
var UsersService = class UsersService2 {
static {
__name(this, "UsersService");
}
prisma;
auth;
audit;
constructor(prisma, auth, audit) {
this.prisma = prisma;
this.auth = auth;
this.audit = audit;
}
async list() {
const users = await this.prisma.adminUser.findMany({ orderBy: { id: "asc" } });
return users.map(toUserDto);
}
async create(input, actor) {
const user = await this.prisma.adminUser.create({
data: {
phone: input.phone,
name: input.name,
role: input.role,
passwordHash: await hashPassword(input.password)
}
});
this.audit.log(actor.id, "create", "user", user.id, user.phone);
return toUserDto(user);
}
async update(id, input, actor) {
if (id === actor.id && (input.role !== "ADMIN" || !input.isActive)) {
throw new BadRequestException("\u0646\u0645\u06CC\u200C\u062A\u0648\u0627\u0646\u06CC\u062F \u0646\u0642\u0634 \u06CC\u0627 \u0648\u0636\u0639\u06CC\u062A \u062D\u0633\u0627\u0628 \u062E\u0648\u062F\u062A\u0627\u0646 \u0631\u0627 \u062A\u063A\u06CC\u06CC\u0631 \u062F\u0647\u06CC\u062F");
}
const user = await this.prisma.adminUser.update({
where: { id },
data: {
name: input.name,
role: input.role,
isActive: input.isActive,
...input.password ? { passwordHash: await hashPassword(input.password) } : {}
}
});
if (input.password || !input.isActive)
await this.auth.revokeAll(id);
this.audit.log(actor.id, "update", "user", id, user.phone);
return toUserDto(user);
}
async remove(id, actor) {
if (id === actor.id)
throw new BadRequestException("\u0646\u0645\u06CC\u200C\u062A\u0648\u0627\u0646\u06CC\u062F \u062D\u0633\u0627\u0628 \u062E\u0648\u062F\u062A\u0627\u0646 \u0631\u0627 \u062D\u0630\u0641 \u06A9\u0646\u06CC\u062F");
const user = await this.prisma.adminUser.delete({ where: { id } });
this.audit.log(actor.id, "delete", "user", id, user.phone);
}
};
UsersService = __decorate13([
Injectable(),
__metadata12("design:paramtypes", [
PrismaService,
AuthService,
AuditService
])
], UsersService);
var UsersController = class UsersController2 {
static {
__name(this, "UsersController");
}
users;
constructor(users) {
this.users = users;
}
list() {
return this.users.list();
}
create(body, actor) {
return this.users.create(body, actor);
}
update(id, body, actor) {
return this.users.update(id, body, actor);
}
async remove(id, actor) {
await this.users.remove(id, actor);
}
};
__decorate13([
Get(),
__metadata12("design:type", Function),
__metadata12("design:paramtypes", []),
__metadata12("design:returntype", void 0)
], UsersController.prototype, "list", null);
__decorate13([
Post(),
__param7(0, Body(new ZodPipe(userCreateSchema))),
__param7(1, CurrentUser()),
__metadata12("design:type", Function),
__metadata12("design:paramtypes", [Object, Object]),
__metadata12("design:returntype", void 0)
], UsersController.prototype, "create", null);
__decorate13([
Put(":id"),
__param7(0, Param("id", IdPipe)),
__param7(1, Body(new ZodPipe(userUpdateSchema))),
__param7(2, CurrentUser()),
__metadata12("design:type", Function),
__metadata12("design:paramtypes", [Number, Object, Object]),
__metadata12("design:returntype", void 0)
], UsersController.prototype, "update", null);
__decorate13([
Delete(":id"),
HttpCode(204),
__param7(0, Param("id", IdPipe)),
__param7(1, CurrentUser()),
__metadata12("design:type", Function),
__metadata12("design:paramtypes", [Number, Object]),
__metadata12("design:returntype", Promise)
], UsersController.prototype, "remove", null);
UsersController = __decorate13([
AdminAuth("ADMIN"),
Controller("admin/users"),
__metadata12("design:paramtypes", [UsersService])
], UsersController);
var UsersModule = class UsersModule2 {
static {
__name(this, "UsersModule");
}
};
UsersModule = __decorate13([
Module({
imports: [AuthModule],
controllers: [UsersController],
providers: [UsersService]
})
], UsersModule);
// dist/app.module.js
var __decorate14 = 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 __metadata13 = function(k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var HealthController = class HealthController2 {
static {
__name(this, "HealthController");
}
prisma;
constructor(prisma) {
this.prisma = prisma;
}
async health() {
await this.prisma.$queryRaw`SELECT 1`;
return { ok: true };
}
};
__decorate14([
Get(),
__metadata13("design:type", Function),
__metadata13("design:paramtypes", []),
__metadata13("design:returntype", Promise)
], HealthController.prototype, "health", null);
HealthController = __decorate14([
Controller("health"),
__metadata13("design:paramtypes", [PrismaService])
], HealthController);
var AppModule = class AppModule2 {
static {
__name(this, "AppModule");
}
};
AppModule = __decorate14([
Module({
imports: [
import_throttler3.ThrottlerModule.forRoot([{ ttl: 6e4, limit: 300 }]),
PrismaModule,
CommonModule,
AuthModule,
UsersModule,
MediaModule,
CatalogModule,
SectionsModule,
ContactModule,
PublicModule,
DashboardModule
],
controllers: [HealthController],
providers: [
{ provide: APP_GUARD, useClass: import_throttler3.ThrottlerGuard },
{ provide: APP_FILTER, useClass: PrismaExceptionFilter }
]
})
], AppModule);
// dist/main.js
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.set("trust proxy", env.TRUST_PROXY);
app.setGlobalPrefix("api");
app.use(helmet());
app.use((0, import_cookie_parser.default)());
const origins = env.CORS_ORIGINS.split(",").map((o) => o.trim()).filter(Boolean);
if (origins.length)
app.enableCors({ origin: origins, credentials: true });
app.enableShutdownHooks();
await app.listen(env.PORT);
}
__name(bootstrap, "bootstrap");
await bootstrap();