- 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>
3596 lines
138 KiB
JavaScript
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();
|