Initial Mento CRM: portal OTP, reports, SMS, and deploy for crm.montzar.ir.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-29 21:06:30 +03:30
co-authored by Cursor
commit 29a040c21d
195 changed files with 39430 additions and 0 deletions
@@ -0,0 +1,48 @@
import { Injectable, OnModuleInit } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { createReadStream, promises as fs } from 'fs';
import * as path from 'path';
import type { Readable } from 'stream';
@Injectable()
export class LocalFileStorage implements OnModuleInit {
private readonly root: string;
constructor(private readonly config: ConfigService) {
this.root =
this.config.get<string>('UPLOAD_DIR')?.trim() ||
path.join(process.cwd(), 'uploads');
}
async onModuleInit() {
await fs.mkdir(this.root, { recursive: true });
}
absolutePath(storageKey: string): string {
const resolved = path.resolve(this.root, storageKey);
if (!resolved.startsWith(path.resolve(this.root))) {
throw new Error('Invalid storage key');
}
return resolved;
}
async save(storageKey: string, buffer: Buffer): Promise<void> {
const abs = this.absolutePath(storageKey);
await fs.mkdir(path.dirname(abs), { recursive: true });
await fs.writeFile(abs, buffer);
}
async remove(storageKey: string): Promise<void> {
const abs = this.absolutePath(storageKey);
try {
await fs.unlink(abs);
} catch (err) {
const code = (err as NodeJS.ErrnoException).code;
if (code !== 'ENOENT') throw err;
}
}
openReadStream(storageKey: string): Readable {
return createReadStream(this.absolutePath(storageKey));
}
}
+9
View File
@@ -0,0 +1,9 @@
import { Global, Module } from '@nestjs/common';
import { LocalFileStorage } from './local-file.storage';
@Global()
@Module({
providers: [LocalFileStorage],
exports: [LocalFileStorage],
})
export class StorageModule {}