@atlas-id/contracts 0.1.0

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.
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Esquemas de validación en runtime usando Zod.
3
+ * Estos esquemas permiten validar datos en tiempo de ejecución,
4
+ * no solo en tiempo de compilación con TypeScript.
5
+ *
6
+ * Nota: Requiere instalar zod como dependencia.
7
+ */
8
+
9
+ import { z } from 'zod';
10
+ import { isValidSemanticVersion } from '../versioning';
11
+
12
+ /**
13
+ * Esquema para validar versiones semánticas.
14
+ */
15
+ export const semanticVersionSchema = z.string().refine(
16
+ isValidSemanticVersion,
17
+ { message: 'Debe ser una versión semántica válida (MAJOR.MINOR.PATCH)' }
18
+ );
19
+
20
+ /**
21
+ * Esquema para validar metadata de eventos.
22
+ */
23
+ export const eventMetaSchema = z.object({
24
+ traceId: z.string().optional(),
25
+ spanId: z.string().optional(),
26
+ correlationId: z.string().optional(),
27
+ causationId: z.string().optional(),
28
+ tenantId: z.string().optional(),
29
+ projectId: z.string().optional(),
30
+ source: z.string().min(1),
31
+ });
32
+
33
+ /**
34
+ * Esquema genérico para validar envelopes de eventos.
35
+ *
36
+ * @template TPayload - Tipo del payload (debe ser un esquema Zod)
37
+ */
38
+ export function createEventEnvelopeSchema<TPayload extends z.ZodTypeAny>(
39
+ payloadSchema: TPayload
40
+ ) {
41
+ return z.object({
42
+ id: z.string().min(1),
43
+ type: z.string().min(1),
44
+ version: semanticVersionSchema,
45
+ occurredAt: z.string().datetime(),
46
+ payload: payloadSchema,
47
+ meta: eventMetaSchema,
48
+ });
49
+ }
50
+
51
+ /**
52
+ * Esquema para validar solicitudes de notificación por email.
53
+ */
54
+ export const emailNotificationRequestSchema = z.object({
55
+ channel: z.literal('email'),
56
+ projectId: z.string().min(1),
57
+ tenantId: z.string().optional(),
58
+ locale: z.string().optional(),
59
+ deduplicationKey: z.string().optional(),
60
+ expiresAt: z.string().datetime().optional(),
61
+ metadata: z.record(z.string()).optional(),
62
+ to: z.string().email(),
63
+ templateId: z.string().min(1),
64
+ variables: z.record(z.union([z.string(), z.number(), z.boolean(), z.null()])).optional(),
65
+ cc: z.array(z.string().email()).optional(),
66
+ bcc: z.array(z.string().email()).optional(),
67
+ replyTo: z.string().email().optional(),
68
+ });
69
+
70
+ /**
71
+ * Esquema para validar solicitudes de notificación por SMS.
72
+ */
73
+ export const smsNotificationRequestSchema = z.object({
74
+ channel: z.literal('sms'),
75
+ projectId: z.string().min(1),
76
+ tenantId: z.string().optional(),
77
+ locale: z.string().optional(),
78
+ deduplicationKey: z.string().optional(),
79
+ expiresAt: z.string().datetime().optional(),
80
+ metadata: z.record(z.string()).optional(),
81
+ to: z.string().min(1),
82
+ templateId: z.string().min(1),
83
+ variables: z.record(z.union([z.string(), z.number(), z.boolean(), z.null()])).optional(),
84
+ });
85
+
86
+ /**
87
+ * Esquema para validar solicitudes de notificación por webhook.
88
+ */
89
+ export const webhookNotificationRequestSchema = z.object({
90
+ channel: z.literal('webhook'),
91
+ projectId: z.string().min(1),
92
+ tenantId: z.string().optional(),
93
+ locale: z.string().optional(),
94
+ deduplicationKey: z.string().optional(),
95
+ expiresAt: z.string().datetime().optional(),
96
+ metadata: z.record(z.string()).optional(),
97
+ url: z.string().url(),
98
+ signatureVersion: semanticVersionSchema,
99
+ body: z.unknown(),
100
+ });
101
+
102
+ /**
103
+ * Esquema para validar cualquier solicitud de notificación.
104
+ */
105
+ export const notificationRequestSchema = z.discriminatedUnion('channel', [
106
+ emailNotificationRequestSchema,
107
+ smsNotificationRequestSchema,
108
+ webhookNotificationRequestSchema,
109
+ ]);
110
+
111
+ /**
112
+ * Esquema para validar conexiones OAuth.
113
+ */
114
+ export const oauthConnectionSchema = z.object({
115
+ id: z.string().min(1),
116
+ providerId: z.string().min(1),
117
+ projectId: z.string().min(1),
118
+ tenantId: z.string().optional(),
119
+ userId: z.string().min(1),
120
+ scope: z.array(z.string()),
121
+ expiresAt: z.string().datetime().optional(),
122
+ createdAt: z.string().datetime(),
123
+ updatedAt: z.string().datetime(),
124
+ status: z.enum(['active', 'refreshing', 'revoked', 'expired']),
125
+ });
126
+
127
+ /**
128
+ * Esquema para validar conjuntos de tokens OAuth.
129
+ */
130
+ export const tokenSetSchema = z.object({
131
+ accessToken: z.string().min(1),
132
+ refreshToken: z.string().optional(),
133
+ expiresIn: z.number().positive().optional(),
134
+ tokenType: z.string().optional(),
135
+ issuedAt: z.string().datetime(),
136
+ expiresAt: z.string().datetime().optional(),
137
+ idToken: z.string().optional(),
138
+ });
@@ -0,0 +1 @@
1
+ export * from './validation';
@@ -0,0 +1,96 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import {
3
+ isValidUuid,
4
+ isValidEmail,
5
+ isValidUrl,
6
+ isValidE164Phone,
7
+ isValidIso8601,
8
+ hasRequiredKeys,
9
+ } from './validation';
10
+
11
+ describe('validation utils', () => {
12
+ describe('isValidUuid', () => {
13
+ it('debe validar UUIDs v4 correctos', () => {
14
+ expect(isValidUuid('550e8400-e29b-41d4-a716-446655440000')).toBe(true);
15
+ // UUID v4 válido (el segundo ejemplo es UUID v1, no v4)
16
+ expect(isValidUuid('f47ac10b-58cc-4372-a567-0e02b2c3d479')).toBe(true);
17
+ expect(isValidUuid('a1b2c3d4-e5f6-4789-a012-3456789abcde')).toBe(true);
18
+ });
19
+
20
+ it('debe rechazar UUIDs inválidos', () => {
21
+ expect(isValidUuid('invalid')).toBe(false);
22
+ expect(isValidUuid('550e8400-e29b-41d4-a716')).toBe(false);
23
+ expect(isValidUuid('')).toBe(false);
24
+ });
25
+ });
26
+
27
+ describe('isValidEmail', () => {
28
+ it('debe validar emails correctos', () => {
29
+ expect(isValidEmail('user@example.com')).toBe(true);
30
+ expect(isValidEmail('test.user+tag@example.co.uk')).toBe(true);
31
+ });
32
+
33
+ it('debe rechazar emails inválidos', () => {
34
+ expect(isValidEmail('invalid')).toBe(false);
35
+ expect(isValidEmail('@example.com')).toBe(false);
36
+ expect(isValidEmail('user@')).toBe(false);
37
+ expect(isValidEmail('')).toBe(false);
38
+ });
39
+ });
40
+
41
+ describe('isValidUrl', () => {
42
+ it('debe validar URLs correctas', () => {
43
+ expect(isValidUrl('https://example.com')).toBe(true);
44
+ expect(isValidUrl('http://example.com/path?query=1')).toBe(true);
45
+ expect(isValidUrl('https://subdomain.example.com:8080/path')).toBe(true);
46
+ });
47
+
48
+ it('debe rechazar URLs inválidas', () => {
49
+ expect(isValidUrl('not-a-url')).toBe(false);
50
+ expect(isValidUrl('://invalid')).toBe(false);
51
+ expect(isValidUrl('')).toBe(false);
52
+ });
53
+ });
54
+
55
+ describe('isValidE164Phone', () => {
56
+ it('debe validar números E.164 correctos', () => {
57
+ expect(isValidE164Phone('+1234567890')).toBe(true);
58
+ expect(isValidE164Phone('+34612345678')).toBe(true);
59
+ });
60
+
61
+ it('debe rechazar números inválidos', () => {
62
+ expect(isValidE164Phone('1234567890')).toBe(false);
63
+ expect(isValidE164Phone('+123')).toBe(false);
64
+ expect(isValidE164Phone('')).toBe(false);
65
+ });
66
+ });
67
+
68
+ describe('isValidIso8601', () => {
69
+ it('debe validar timestamps ISO 8601 correctos', () => {
70
+ expect(isValidIso8601('2024-01-01T00:00:00.000Z')).toBe(true);
71
+ expect(isValidIso8601('2024-12-31T23:59:59.999Z')).toBe(true);
72
+ });
73
+
74
+ it('debe rechazar timestamps inválidos', () => {
75
+ expect(isValidIso8601('2024-01-01')).toBe(false);
76
+ expect(isValidIso8601('invalid')).toBe(false);
77
+ expect(isValidIso8601('')).toBe(false);
78
+ });
79
+ });
80
+
81
+ describe('hasRequiredKeys', () => {
82
+ it('debe validar que un objeto tiene todas las claves requeridas', () => {
83
+ const obj1: Record<string, number> = { a: 1, b: 2 };
84
+ const obj2: Record<string, number> = { a: 1, b: 2, c: 3 };
85
+ expect(hasRequiredKeys(obj1, ['a', 'b'])).toBe(true);
86
+ expect(hasRequiredKeys(obj2, ['a', 'b'])).toBe(true);
87
+ });
88
+
89
+ it('debe retornar false si faltan claves requeridas', () => {
90
+ const obj1: Record<string, number> = { a: 1 };
91
+ const obj2: Record<string, unknown> = {};
92
+ expect(hasRequiredKeys(obj1, ['a', 'b'])).toBe(false);
93
+ expect(hasRequiredKeys(obj2, ['a'])).toBe(false);
94
+ });
95
+ });
96
+ });
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Utilidades de validación para formatos comunes utilizados en los contratos.
3
+ */
4
+
5
+ /**
6
+ * Expresión regular para validar formato UUID v4.
7
+ */
8
+ const UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
9
+
10
+ /**
11
+ * Expresión regular básica para validar formato de email.
12
+ * Nota: Esta es una validación básica. Para validación estricta, usar una biblioteca especializada.
13
+ */
14
+ const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
15
+
16
+ /**
17
+ * Expresión regular para validar formato de teléfono E.164.
18
+ * E.164 requiere: + seguido de 1-3 dígitos del código de país, luego 1-14 dígitos adicionales.
19
+ * Mínimo total: + seguido de al menos 7 dígitos (código de país + número local).
20
+ */
21
+ const E164_PHONE_REGEX = /^\+[1-9]\d{6,14}$/;
22
+
23
+ /**
24
+ * Valida si una cadena tiene formato UUID v4.
25
+ *
26
+ * @param value - Cadena a validar
27
+ * @returns true si es un UUID v4 válido
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * isValidUuid('550e8400-e29b-41d4-a716-446655440000'); // true
32
+ * isValidUuid('invalid'); // false
33
+ * ```
34
+ */
35
+ export function isValidUuid(value: string): boolean {
36
+ return UUID_V4_REGEX.test(value);
37
+ }
38
+
39
+ /**
40
+ * Valida si una cadena tiene formato de email básico.
41
+ *
42
+ * @param value - Cadena a validar
43
+ * @returns true si tiene formato de email válido
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * isValidEmail('user@example.com'); // true
48
+ * isValidEmail('invalid'); // false
49
+ * ```
50
+ */
51
+ export function isValidEmail(value: string): boolean {
52
+ return EMAIL_REGEX.test(value);
53
+ }
54
+
55
+ /**
56
+ * Valida si una cadena tiene formato de URL válido.
57
+ *
58
+ * @param value - Cadena a validar
59
+ * @returns true si es una URL válida
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * isValidUrl('https://example.com'); // true
64
+ * isValidUrl('not-a-url'); // false
65
+ * ```
66
+ */
67
+ export function isValidUrl(value: string): boolean {
68
+ try {
69
+ // URL está disponible en Node.js 18+ y navegadores modernos
70
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
71
+ const URLConstructor = (globalThis as unknown as { URL?: new (url: string) => unknown }).URL;
72
+
73
+ if (URLConstructor) {
74
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call
75
+ new URLConstructor(value);
76
+ return true;
77
+ }
78
+ // Fallback para entornos sin URL global
79
+ return /^https?:\/\/.+\..+/.test(value);
80
+ } catch {
81
+ return false;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Valida si una cadena tiene formato de teléfono E.164.
87
+ *
88
+ * @param value - Cadena a validar
89
+ * @returns true si tiene formato E.164 válido
90
+ *
91
+ * @example
92
+ * ```typescript
93
+ * isValidE164Phone('+1234567890'); // true
94
+ * isValidE164Phone('1234567890'); // false
95
+ * ```
96
+ */
97
+ export function isValidE164Phone(value: string): boolean {
98
+ return E164_PHONE_REGEX.test(value);
99
+ }
100
+
101
+ /**
102
+ * Valida si una cadena es un timestamp ISO 8601 válido.
103
+ *
104
+ * @param value - Cadena a validar
105
+ * @returns true si es un timestamp ISO 8601 válido
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * isValidIso8601('2024-01-01T00:00:00.000Z'); // true
110
+ * isValidIso8601('invalid'); // false
111
+ * ```
112
+ */
113
+ export function isValidIso8601(value: string): boolean {
114
+ const date = new Date(value);
115
+ return !isNaN(date.getTime()) && value === date.toISOString();
116
+ }
117
+
118
+ /**
119
+ * Valida si un objeto tiene todas las propiedades requeridas.
120
+ *
121
+ * @param obj - Objeto a validar
122
+ * @param requiredKeys - Array de claves requeridas
123
+ * @returns true si todas las claves están presentes
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * hasRequiredKeys({ a: 1, b: 2 }, ['a', 'b']); // true
128
+ * hasRequiredKeys({ a: 1 }, ['a', 'b']); // false
129
+ * ```
130
+ */
131
+ export function hasRequiredKeys<T extends Record<string, unknown>>(
132
+ obj: T,
133
+ requiredKeys: (keyof T)[]
134
+ ): boolean {
135
+ return requiredKeys.every((key) => key in obj);
136
+ }
@@ -0,0 +1,112 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import {
3
+ isValidSemanticVersion,
4
+ parseSemanticVersion,
5
+ compareSemanticVersions,
6
+ isVersionGreaterThan,
7
+ isVersionLessThan,
8
+ isVersionGreaterOrEqual,
9
+ isVersionLessOrEqual,
10
+ type SemanticVersion,
11
+ } from './versioning';
12
+
13
+ describe('versioning', () => {
14
+ describe('isValidSemanticVersion', () => {
15
+ it('debe validar versiones semánticas correctas', () => {
16
+ expect(isValidSemanticVersion('1.0.0')).toBe(true);
17
+ expect(isValidSemanticVersion('0.1.0')).toBe(true);
18
+ expect(isValidSemanticVersion('10.20.30')).toBe(true);
19
+ });
20
+
21
+ it('debe rechazar versiones inválidas', () => {
22
+ expect(isValidSemanticVersion('1.0')).toBe(false);
23
+ expect(isValidSemanticVersion('1.0.0.0')).toBe(false);
24
+ expect(isValidSemanticVersion('1.0.0-beta')).toBe(false);
25
+ expect(isValidSemanticVersion('invalid')).toBe(false);
26
+ expect(isValidSemanticVersion('')).toBe(false);
27
+ });
28
+ });
29
+
30
+ describe('parseSemanticVersion', () => {
31
+ it('debe parsear versiones válidas correctamente', () => {
32
+ expect(parseSemanticVersion('1.2.3')).toEqual({
33
+ major: 1,
34
+ minor: 2,
35
+ patch: 3,
36
+ });
37
+ expect(parseSemanticVersion('10.20.30')).toEqual({
38
+ major: 10,
39
+ minor: 20,
40
+ patch: 30,
41
+ });
42
+ });
43
+
44
+ it('debe retornar null para versiones inválidas', () => {
45
+ expect(parseSemanticVersion('1.0')).toBeNull();
46
+ expect(parseSemanticVersion('invalid')).toBeNull();
47
+ expect(parseSemanticVersion('')).toBeNull();
48
+ });
49
+ });
50
+
51
+ describe('compareSemanticVersions', () => {
52
+ it('debe comparar versiones correctamente', () => {
53
+ expect(compareSemanticVersions('1.0.0', '1.0.0')).toBe(0);
54
+ expect(compareSemanticVersions('1.0.0', '1.0.1')).toBe(-1);
55
+ expect(compareSemanticVersions('1.0.1', '1.0.0')).toBe(1);
56
+ expect(compareSemanticVersions('1.1.0', '1.0.0')).toBe(1);
57
+ expect(compareSemanticVersions('2.0.0', '1.9.9')).toBe(1);
58
+ });
59
+
60
+ it('debe lanzar error para versiones inválidas', () => {
61
+ expect(() => compareSemanticVersions('invalid', '1.0.0')).toThrow();
62
+ expect(() => compareSemanticVersions('1.0.0', 'invalid')).toThrow();
63
+ });
64
+ });
65
+
66
+ describe('isVersionGreaterThan', () => {
67
+ it('debe retornar true cuando version1 > version2', () => {
68
+ expect(isVersionGreaterThan('2.0.0', '1.9.9')).toBe(true);
69
+ expect(isVersionGreaterThan('1.1.0', '1.0.9')).toBe(true);
70
+ expect(isVersionGreaterThan('1.0.1', '1.0.0')).toBe(true);
71
+ });
72
+
73
+ it('debe retornar false cuando version1 <= version2', () => {
74
+ expect(isVersionGreaterThan('1.0.0', '1.0.0')).toBe(false);
75
+ expect(isVersionGreaterThan('1.0.0', '2.0.0')).toBe(false);
76
+ });
77
+ });
78
+
79
+ describe('isVersionLessThan', () => {
80
+ it('debe retornar true cuando version1 < version2', () => {
81
+ expect(isVersionLessThan('1.0.0', '2.0.0')).toBe(true);
82
+ expect(isVersionLessThan('1.0.0', '1.1.0')).toBe(true);
83
+ });
84
+
85
+ it('debe retornar false cuando version1 >= version2', () => {
86
+ expect(isVersionLessThan('1.0.0', '1.0.0')).toBe(false);
87
+ expect(isVersionLessThan('2.0.0', '1.0.0')).toBe(false);
88
+ });
89
+ });
90
+
91
+ describe('isVersionGreaterOrEqual', () => {
92
+ it('debe retornar true cuando version1 >= version2', () => {
93
+ expect(isVersionGreaterOrEqual('2.0.0', '1.0.0')).toBe(true);
94
+ expect(isVersionGreaterOrEqual('1.0.0', '1.0.0')).toBe(true);
95
+ });
96
+
97
+ it('debe retornar false cuando version1 < version2', () => {
98
+ expect(isVersionGreaterOrEqual('1.0.0', '2.0.0')).toBe(false);
99
+ });
100
+ });
101
+
102
+ describe('isVersionLessOrEqual', () => {
103
+ it('debe retornar true cuando version1 <= version2', () => {
104
+ expect(isVersionLessOrEqual('1.0.0', '2.0.0')).toBe(true);
105
+ expect(isVersionLessOrEqual('1.0.0', '1.0.0')).toBe(true);
106
+ });
107
+
108
+ it('debe retornar false cuando version1 > version2', () => {
109
+ expect(isVersionLessOrEqual('2.0.0', '1.0.0')).toBe(false);
110
+ });
111
+ });
112
+ });
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Representa una versión semántica en formato MAJOR.MINOR.PATCH
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * const version: SemanticVersion = '1.2.3';
7
+ * ```
8
+ */
9
+ export type SemanticVersion = `${number}.${number}.${number}`;
10
+
11
+ /**
12
+ * Estructura que contiene un payload con su versión asociada.
13
+ * Útil para versionado de datos y compatibilidad entre versiones.
14
+ *
15
+ * @template TPayload - Tipo del payload versionado
16
+ */
17
+ export type Versioned<TPayload> = {
18
+ version: SemanticVersion;
19
+ payload: TPayload;
20
+ };
21
+
22
+ /**
23
+ * Valida si una cadena de texto cumple con el formato de versión semántica.
24
+ *
25
+ * @param version - Cadena a validar
26
+ * @returns true si es una versión semántica válida, false en caso contrario
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * isValidSemanticVersion('1.2.3'); // true
31
+ * isValidSemanticVersion('1.2'); // false
32
+ * isValidSemanticVersion('invalid'); // false
33
+ * ```
34
+ */
35
+ export function isValidSemanticVersion(version: string): version is SemanticVersion {
36
+ return /^\d+\.\d+\.\d+$/.test(version);
37
+ }
38
+
39
+ /**
40
+ * Parsea una versión semántica y retorna sus componentes numéricos.
41
+ *
42
+ * @param version - Versión semántica a parsear
43
+ * @returns Objeto con major, minor y patch, o null si la versión es inválida
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * parseSemanticVersion('1.2.3'); // { major: 1, minor: 2, patch: 3 }
48
+ * parseSemanticVersion('invalid'); // null
49
+ * ```
50
+ */
51
+ export function parseSemanticVersion(version: string): {
52
+ major: number;
53
+ minor: number;
54
+ patch: number;
55
+ } | null {
56
+ const match = version.match(/^(\d+)\.(\d+)\.(\d+)$/);
57
+ if (!match) return null;
58
+
59
+ return {
60
+ major: parseInt(match[1], 10),
61
+ minor: parseInt(match[2], 10),
62
+ patch: parseInt(match[3], 10),
63
+ };
64
+ }
65
+
66
+ /**
67
+ * Compara dos versiones semánticas.
68
+ *
69
+ * @param version1 - Primera versión a comparar
70
+ * @param version2 - Segunda versión a comparar
71
+ * @returns -1 si version1 < version2, 0 si son iguales, 1 si version1 > version2
72
+ * @throws Error si alguna de las versiones es inválida
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * compareSemanticVersions('1.2.3', '1.2.4'); // -1
77
+ * compareSemanticVersions('2.0.0', '1.9.9'); // 1
78
+ * compareSemanticVersions('1.0.0', '1.0.0'); // 0
79
+ * ```
80
+ */
81
+ export function compareSemanticVersions(
82
+ version1: string,
83
+ version2: string
84
+ ): number {
85
+ const v1 = parseSemanticVersion(version1);
86
+ const v2 = parseSemanticVersion(version2);
87
+
88
+ if (!v1 || !v2) {
89
+ throw new Error(`Invalid semantic version: ${!v1 ? version1 : version2}`);
90
+ }
91
+
92
+ if (v1.major !== v2.major) {
93
+ return v1.major - v2.major;
94
+ }
95
+
96
+ if (v1.minor !== v2.minor) {
97
+ return v1.minor - v2.minor;
98
+ }
99
+
100
+ return v1.patch - v2.patch;
101
+ }
102
+
103
+ /**
104
+ * Verifica si una versión es mayor que otra.
105
+ *
106
+ * @param version1 - Versión a comparar
107
+ * @param version2 - Versión de referencia
108
+ * @returns true si version1 > version2
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * isVersionGreaterThan('2.0.0', '1.9.9'); // true
113
+ * isVersionGreaterThan('1.0.0', '1.0.0'); // false
114
+ * ```
115
+ */
116
+ export function isVersionGreaterThan(version1: string, version2: string): boolean {
117
+ return compareSemanticVersions(version1, version2) > 0;
118
+ }
119
+
120
+ /**
121
+ * Verifica si una versión es menor que otra.
122
+ *
123
+ * @param version1 - Versión a comparar
124
+ * @param version2 - Versión de referencia
125
+ * @returns true si version1 < version2
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * isVersionLessThan('1.0.0', '2.0.0'); // true
130
+ * ```
131
+ */
132
+ export function isVersionLessThan(version1: string, version2: string): boolean {
133
+ return compareSemanticVersions(version1, version2) < 0;
134
+ }
135
+
136
+ /**
137
+ * Verifica si una versión es mayor o igual que otra.
138
+ *
139
+ * @param version1 - Versión a comparar
140
+ * @param version2 - Versión de referencia
141
+ * @returns true si version1 >= version2
142
+ */
143
+ export function isVersionGreaterOrEqual(version1: string, version2: string): boolean {
144
+ return compareSemanticVersions(version1, version2) >= 0;
145
+ }
146
+
147
+ /**
148
+ * Verifica si una versión es menor o igual que otra.
149
+ *
150
+ * @param version1 - Versión a comparar
151
+ * @param version2 - Versión de referencia
152
+ * @returns true si version1 <= version2
153
+ */
154
+ export function isVersionLessOrEqual(version1: string, version2: string): boolean {
155
+ return compareSemanticVersions(version1, version2) <= 0;
156
+ }