@avelardelarosa/core-util 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.prettierrc ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "singleQuote": true,
3
+ "trailingComma": "all"
4
+ }
package/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # 🧱 core-util
2
+
3
+ **core-util** es una librería personal de utilidades para proyectos **NestJS**, diseñada para centralizar componentes clave y facilitar el desarrollo backend mediante recursos reutilizables y estructurados.
4
+
5
+ ---
6
+
7
+ ## 🔍 Propósito
8
+
9
+ Este proyecto actúa como una **capa base** para múltiples servicios NestJS, ofreciendo:
10
+
11
+ - ✅ **Clases abstractas comunes**
12
+ Por ejemplo, entidades base con campos de auditoría o herencia reutilizable.
13
+
14
+ - 📦 **Modelos de respuesta estándar**
15
+ Para mantener consistencia en las respuestas de tus APIs.
16
+
17
+ - 🛡️ **Decoradores y validaciones personalizadas**
18
+ Para mejorar la legibilidad y control de tus DTOs.
19
+
20
+ - 🔧 **Funciones utilitarias**
21
+ Manejo de fechas, formateo de datos, utilidades comunes, etc.
22
+
23
+ - 🧪 **DTOs, constantes y helpers compartidos**
24
+ Que se pueden reutilizar entre distintos microservicios.
25
+
26
+ ---
27
+
28
+ ## 🚀 Beneficios
29
+
30
+ - 🔁 **Reduce el código repetitivo**
31
+ - 🧩 **Aporta consistencia entre proyectos**
32
+ - 📈 **Mejora la escalabilidad y mantenimiento**
33
+ - ♻️ **Fácil de extender y reutilizar**
34
+
35
+ ---
36
+
37
+ > Este proyecto forma parte de una arquitectura modular para uso personal, y está pensado para integrarse fácilmente en cualquier backend desarrollado con NestJS.
@@ -0,0 +1,34 @@
1
+ // @ts-check
2
+ import eslint from '@eslint/js';
3
+ import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
4
+ import globals from 'globals';
5
+ import tseslint from 'typescript-eslint';
6
+
7
+ export default tseslint.config(
8
+ {
9
+ ignores: ['eslint.config.mjs'],
10
+ },
11
+ eslint.configs.recommended,
12
+ ...tseslint.configs.recommendedTypeChecked,
13
+ eslintPluginPrettierRecommended,
14
+ {
15
+ languageOptions: {
16
+ globals: {
17
+ ...globals.node,
18
+ ...globals.jest,
19
+ },
20
+ sourceType: 'commonjs',
21
+ parserOptions: {
22
+ projectService: true,
23
+ tsconfigRootDir: import.meta.dirname,
24
+ },
25
+ },
26
+ },
27
+ {
28
+ rules: {
29
+ '@typescript-eslint/no-explicit-any': 'off',
30
+ '@typescript-eslint/no-floating-promises': 'warn',
31
+ '@typescript-eslint/no-unsafe-argument': 'warn'
32
+ },
33
+ },
34
+ );
package/nest-cli.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/nest-cli",
3
+ "collection": "@nestjs/schematics",
4
+ "sourceRoot": "src",
5
+ "compilerOptions": {
6
+ "deleteOutDir": true
7
+ }
8
+ }
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "@avelardelarosa/core-util",
3
+ "version": "0.0.3",
4
+ "description": "Librería de utilidades comunes para servicios backend desarrollados con NestJS",
5
+ "author": "Alexander Junior Velarde La Rosa <avelardelarosa@gmail.com>",
6
+ "private": false,
7
+ "license": "UNLICENSED",
8
+ "publishConfig": {
9
+ "registry": "https://registry.npmjs.org/"
10
+ },
11
+ "scripts": {
12
+ "build": "nest build",
13
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
14
+ "start": "nest start",
15
+ "start:dev": "nest start --watch",
16
+ "start:debug": "nest start --debug --watch",
17
+ "start:prod": "node dist/main",
18
+ "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
19
+ "test": "jest",
20
+ "test:watch": "jest --watch",
21
+ "test:cov": "jest --coverage",
22
+ "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
23
+ "test:e2e": "jest --config ./test/jest-e2e.json"
24
+ },
25
+ "dependencies": {
26
+ "@nestjs/common": "^11.0.1",
27
+ "@nestjs/core": "^11.0.1",
28
+ "@nestjs/platform-express": "^11.0.1",
29
+ "@nestjs/typeorm": "^11.0.0",
30
+ "class-transformer": "^0.5.1",
31
+ "class-validator": "^0.14.2",
32
+ "mysql2": "^3.14.2",
33
+ "reflect-metadata": "^0.2.2",
34
+ "rxjs": "^7.8.1",
35
+ "typeorm": "^0.3.25"
36
+ },
37
+ "devDependencies": {
38
+ "@eslint/eslintrc": "^3.2.0",
39
+ "@eslint/js": "^9.18.0",
40
+ "@nestjs/cli": "^11.0.0",
41
+ "@nestjs/schematics": "^11.0.0",
42
+ "@nestjs/testing": "^11.0.1",
43
+ "@swc/cli": "^0.6.0",
44
+ "@swc/core": "^1.10.7",
45
+ "@types/express": "^5.0.0",
46
+ "@types/jest": "^29.5.14",
47
+ "@types/node": "^22.10.7",
48
+ "@types/supertest": "^6.0.2",
49
+ "eslint": "^9.18.0",
50
+ "eslint-config-prettier": "^10.0.1",
51
+ "eslint-plugin-prettier": "^5.2.2",
52
+ "globals": "^16.0.0",
53
+ "jest": "^29.7.0",
54
+ "prettier": "^3.4.2",
55
+ "source-map-support": "^0.5.21",
56
+ "supertest": "^7.0.0",
57
+ "ts-jest": "^29.2.5",
58
+ "ts-loader": "^9.5.2",
59
+ "ts-node": "^10.9.2",
60
+ "tsconfig-paths": "^4.2.0",
61
+ "typescript": "^5.7.3",
62
+ "typescript-eslint": "^8.20.0"
63
+ },
64
+ "jest": {
65
+ "moduleFileExtensions": [
66
+ "js",
67
+ "json",
68
+ "ts"
69
+ ],
70
+ "rootDir": "src",
71
+ "testRegex": ".*\\.spec\\.ts$",
72
+ "transform": {
73
+ "^.+\\.(t|j)s$": "ts-jest"
74
+ },
75
+ "collectCoverageFrom": [
76
+ "**/*.(t|j)s"
77
+ ],
78
+ "coverageDirectory": "../coverage",
79
+ "testEnvironment": "node"
80
+ }
81
+ }
@@ -0,0 +1,40 @@
1
+ export class Pagination<T> {
2
+ pageNumber: number;
3
+ pageSize: number;
4
+ body: T[];
5
+ totalElements: number;
6
+ totalPages: number;
7
+ lastRow: boolean;
8
+
9
+ constructor(init?: Partial<Pagination<T>>) {
10
+ Object.assign(this, init);
11
+ }
12
+ }
13
+
14
+ export class ApiResponse<T> {
15
+ successful: boolean;
16
+ code: string;
17
+ message: string;
18
+ data: T;
19
+
20
+ constructor(init?: Partial<ApiResponse<T>>) {
21
+ Object.assign(this, init);
22
+ }
23
+
24
+ success(message: string, data: T) {
25
+ this.successful = true;
26
+ this.message = message;
27
+ this.data = data;
28
+ }
29
+
30
+ error(code: string, message: string) {
31
+ this.successful = false;
32
+ this.code = code;
33
+ this.message = message;
34
+ }
35
+
36
+ msg(message: string) {
37
+ this.successful = true;
38
+ this.message = message;
39
+ }
40
+ }
@@ -0,0 +1,22 @@
1
+ import { Test, TestingModule } from '@nestjs/testing';
2
+ import { AppController } from './app.controller';
3
+ import { AppService } from './app.service';
4
+
5
+ describe('AppController', () => {
6
+ let appController: AppController;
7
+
8
+ beforeEach(async () => {
9
+ const app: TestingModule = await Test.createTestingModule({
10
+ controllers: [AppController],
11
+ providers: [AppService],
12
+ }).compile();
13
+
14
+ appController = app.get<AppController>(AppController);
15
+ });
16
+
17
+ describe('root', () => {
18
+ it('should return "Hello World!"', () => {
19
+ expect(appController.getHello()).toBe('Hello World!');
20
+ });
21
+ });
22
+ });
@@ -0,0 +1,12 @@
1
+ import { Controller, Get } from '@nestjs/common';
2
+ import { AppService } from './app.service';
3
+
4
+ @Controller()
5
+ export class AppController {
6
+ constructor(private readonly appService: AppService) {}
7
+
8
+ @Get()
9
+ getHello(): string {
10
+ return this.appService.getHello();
11
+ }
12
+ }
@@ -0,0 +1,10 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { AppController } from './app.controller';
3
+ import { AppService } from './app.service';
4
+
5
+ @Module({
6
+ imports: [],
7
+ controllers: [AppController],
8
+ providers: [AppService],
9
+ })
10
+ export class AppModule {}
@@ -0,0 +1,8 @@
1
+ import { Injectable } from '@nestjs/common';
2
+
3
+ @Injectable()
4
+ export class AppService {
5
+ getHello(): string {
6
+ return 'Hello World!';
7
+ }
8
+ }
@@ -0,0 +1,8 @@
1
+ export class AuditoryDTO {
2
+ createUser: string;
3
+ createDate: string;
4
+ updateUser: string;
5
+ updateDate: string;
6
+ deleteUser: string;
7
+ deleteDate: string;
8
+ }
@@ -0,0 +1,25 @@
1
+ import { Column, Entity } from 'typeorm';
2
+ import { IsDate } from 'class-validator';
3
+ import { Type } from 'class-transformer';
4
+
5
+ @Entity()
6
+ export class Auditory {
7
+ @Column({ nullable: false })
8
+ createUser: string;
9
+ @Column({ type: 'timestamp', nullable: false })
10
+ @IsDate()
11
+ @Type(() => Date)
12
+ createDate: Date;
13
+ @Column({ nullable: false })
14
+ updateUser: string;
15
+ @Column({ type: 'timestamp', nullable: false })
16
+ @IsDate()
17
+ @Type(() => Date)
18
+ updateDate: string;
19
+ @Column({ nullable: false })
20
+ deleteUser: string;
21
+ @Column({ type: 'timestamp', nullable: false })
22
+ @IsDate()
23
+ @Type(() => Date)
24
+ deleteDate: string;
25
+ }
@@ -0,0 +1,11 @@
1
+ import { ApiResponse, Pagination } from '../api/response/ApiResponse';
2
+
3
+ export interface IGenericCrud<T> {
4
+ pagination(): Promise<ApiResponse<Pagination<T>>>;
5
+
6
+ create(t: T): Promise<ApiResponse<T>>;
7
+
8
+ update(t: T): Promise<ApiResponse<T>>;
9
+
10
+ delete(id: string): Promise<ApiResponse<T>>;
11
+ }
package/src/main.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { NestFactory } from '@nestjs/core';
2
+ import { AppModule } from './app.module';
3
+
4
+ async function bootstrap() {
5
+ const app = await NestFactory.create(AppModule);
6
+ await app.listen(process.env.PORT ?? 3000);
7
+ }
8
+ bootstrap();
@@ -0,0 +1,63 @@
1
+ export class Validation<T> {
2
+ isNull(obj: T) {
3
+ return obj === null;
4
+ }
5
+
6
+ isUndefined(obj: T) {
7
+ return obj === undefined;
8
+ }
9
+
10
+ isEmpty(obj: T) {
11
+ return obj === '' || obj === null;
12
+ }
13
+
14
+ sString(obj: unknown): boolean {
15
+ return typeof obj === 'string';
16
+ }
17
+
18
+ isNumber(obj: unknown): boolean {
19
+ return typeof obj === 'number' && !isNaN(obj);
20
+ }
21
+
22
+ isBoolean(obj: unknown): boolean {
23
+ return typeof obj === 'boolean';
24
+ }
25
+
26
+ isPositiveNumber(obj: T) {
27
+ return this.isNumber(obj) && (obj as number) > 0;
28
+ }
29
+
30
+ isNegativeNumber(obj: T) {
31
+ return this.isNumber(obj) && (obj as number) < 0;
32
+ }
33
+
34
+ isDate(obj: unknown): boolean {
35
+ return obj instanceof Date && !isNaN(obj.getTime());
36
+ }
37
+
38
+ isFutureDate(obj: unknown): boolean {
39
+ return this.isDate(obj) && (obj as Date).getTime() > Date.now();
40
+ }
41
+
42
+ isPastDate(obj: unknown): boolean {
43
+ return this.isDate(obj) && (obj as Date).getTime() < Date.now();
44
+ }
45
+
46
+ isInArray(value: unknown, array: unknown[]): boolean {
47
+ return array.includes(value);
48
+ }
49
+
50
+ hasMinLength(obj: T, length: number): boolean {
51
+ if (typeof obj === 'string' || Array.isArray(obj)) {
52
+ return (obj as any).length >= length;
53
+ }
54
+ return false;
55
+ }
56
+
57
+ hasMaxLength(obj: T, length: number): boolean {
58
+ if (typeof obj === 'string' || Array.isArray(obj)) {
59
+ return (obj as any).length <= length;
60
+ }
61
+ return false;
62
+ }
63
+ }
@@ -0,0 +1,25 @@
1
+ import { Test, TestingModule } from '@nestjs/testing';
2
+ import { INestApplication } from '@nestjs/common';
3
+ import * as request from 'supertest';
4
+ import { App } from 'supertest/types';
5
+ import { AppModule } from './../src/app.module';
6
+
7
+ describe('AppController (e2e)', () => {
8
+ let app: INestApplication<App>;
9
+
10
+ beforeEach(async () => {
11
+ const moduleFixture: TestingModule = await Test.createTestingModule({
12
+ imports: [AppModule],
13
+ }).compile();
14
+
15
+ app = moduleFixture.createNestApplication();
16
+ await app.init();
17
+ });
18
+
19
+ it('/ (GET)', () => {
20
+ return request(app.getHttpServer())
21
+ .get('/')
22
+ .expect(200)
23
+ .expect('Hello World!');
24
+ });
25
+ });
@@ -0,0 +1,9 @@
1
+ {
2
+ "moduleFileExtensions": ["js", "json", "ts"],
3
+ "rootDir": ".",
4
+ "testEnvironment": "node",
5
+ "testRegex": ".e2e-spec.ts$",
6
+ "transform": {
7
+ "^.+\\.(t|j)s$": "ts-jest"
8
+ }
9
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "commonjs",
4
+ "declaration": true,
5
+ "removeComments": true,
6
+ "emitDecoratorMetadata": true,
7
+ "experimentalDecorators": true,
8
+ "allowSyntheticDefaultImports": true,
9
+ "target": "ES2023",
10
+ "sourceMap": true,
11
+ "outDir": "./dist",
12
+ "baseUrl": "./",
13
+ "incremental": true,
14
+ "skipLibCheck": true,
15
+ "strictNullChecks": true,
16
+ "forceConsistentCasingInFileNames": true,
17
+ "noImplicitAny": false,
18
+ "strictBindCallApply": false,
19
+ "noFallthroughCasesInSwitch": false
20
+ }
21
+ }