Update: nueva version Horux Despachos

This commit is contained in:
consultoria-as
2026-04-27 22:09:36 -06:00
commit 6b36db1403
614 changed files with 125926 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
export * from './token';
export * from './password';

View File

@@ -0,0 +1,11 @@
import bcrypt from 'bcryptjs';
const SALT_ROUNDS = 12;
export async function hashPassword(password: string): Promise<string> {
return bcrypt.hash(password, SALT_ROUNDS);
}
export async function verifyPassword(password: string, hash: string): Promise<boolean> {
return bcrypt.compare(password, hash);
}

View File

@@ -0,0 +1,37 @@
import jwt, { type SignOptions } from 'jsonwebtoken';
import { randomBytes } from 'crypto';
import type { JWTPayload } from '@horux/shared';
export interface TokenConfig {
secret: string;
accessExpiresIn: string;
refreshExpiresIn: string;
}
export function generateAccessToken(payload: Omit<JWTPayload, 'iat' | 'exp'>, config: TokenConfig): string {
const options: SignOptions = {
expiresIn: config.accessExpiresIn as SignOptions['expiresIn'],
jwtid: randomBytes(8).toString('hex'),
};
return jwt.sign(payload, config.secret, options);
}
export function generateRefreshToken(payload: Omit<JWTPayload, 'iat' | 'exp'>, config: TokenConfig): string {
const options: SignOptions = {
expiresIn: config.refreshExpiresIn as SignOptions['expiresIn'],
jwtid: randomBytes(8).toString('hex'),
};
return jwt.sign(payload, config.secret, options);
}
export function verifyToken(token: string, secret: string): JWTPayload {
return jwt.verify(token, secret) as JWTPayload;
}
export function decodeToken(token: string): JWTPayload | null {
try {
return jwt.decode(token) as JWTPayload;
} catch {
return null;
}
}

View File

@@ -0,0 +1,30 @@
import { createCipheriv, createDecipheriv, randomBytes, createHash } from 'crypto';
const ALGORITHM = 'aes-256-gcm';
const IV_LENGTH = 16;
export function deriveAesKey(secret: string): Buffer {
return createHash('sha256').update(secret).digest();
}
export function encryptAesGcm(data: Buffer, key: Buffer): { encrypted: Buffer; iv: Buffer; tag: Buffer } {
const iv = randomBytes(IV_LENGTH);
const cipher = createCipheriv(ALGORITHM, key, iv);
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
const tag = cipher.getAuthTag();
return { encrypted, iv, tag };
}
export function decryptAesGcm(encrypted: Buffer, iv: Buffer, tag: Buffer, key: Buffer): Buffer {
const decipher = createDecipheriv(ALGORITHM, key, iv);
decipher.setAuthTag(tag);
return Buffer.concat([decipher.update(encrypted), decipher.final()]);
}
export function encryptStringAesGcm(text: string, key: Buffer): { encrypted: Buffer; iv: Buffer; tag: Buffer } {
return encryptAesGcm(Buffer.from(text, 'utf-8'), key);
}
export function decryptToStringAesGcm(encrypted: Buffer, iv: Buffer, tag: Buffer, key: Buffer): string {
return decryptAesGcm(encrypted, iv, tag, key).toString('utf-8');
}

View File

@@ -0,0 +1 @@
export * from './aes-gcm';

View File

@@ -0,0 +1 @@
export * from './transport';

View File

@@ -0,0 +1,60 @@
import { createTransport, type Transporter } from 'nodemailer';
export interface SmtpConfig {
host: string;
port: number;
user: string;
pass: string;
from: string;
}
export interface EmailTransport {
send(to: string, subject: string, html: string): Promise<void>;
}
export function createEmailTransport(config: SmtpConfig | null): EmailTransport {
let transporter: Transporter | null = null;
function getTransporter(): Transporter {
if (!transporter) {
if (!config || !config.user || !config.pass) {
console.warn('[EMAIL] SMTP not configured. Emails will be logged to console.');
return {
sendMail: async (opts: any) => {
console.log('[EMAIL] Would send:', { to: opts.to, subject: opts.subject });
return { messageId: 'mock' };
},
} as any;
}
transporter = createTransport({
host: config.host,
port: config.port,
secure: false,
requireTLS: true,
auth: {
user: config.user,
pass: config.pass,
},
});
}
return transporter;
}
return {
async send(to: string, subject: string, html: string) {
const transport = getTransporter();
try {
await transport.sendMail({
from: config?.from ?? 'noreply@example.com',
to,
subject,
html,
text: html.replace(/<[^>]*>/g, ''),
});
} catch (error) {
console.error('[EMAIL] Error sending email:', error);
}
},
};
}

View File

@@ -0,0 +1,3 @@
export * from './auth';
export * from './email';
export * from './crypto';