@nu-art/ts-common 0.401.4 → 0.401.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nu-art/ts-common",
3
- "version": "0.401.4",
3
+ "version": "0.401.6",
4
4
  "description": "Core TypeScript infrastructure library for building modular applications with lifecycle management, logging, validation, and utilities",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -37,8 +37,8 @@
37
37
  "run-tests": "ts-mocha --timeout 50000 -p src/test/tsconfig.json src/test/run-all-tests.ts"
38
38
  },
39
39
  "dependencies": {
40
- "@nu-art/testalot": "0.401.4",
41
- "@nu-art/logger": "0.401.4",
40
+ "@nu-art/testalot": "0.401.6",
41
+ "@nu-art/logger": "0.401.6",
42
42
  "fast-csv": "^5.0.2",
43
43
  "export-to-csv": "0.2.1",
44
44
  "moment": "^2.29.4",
@@ -1,26 +1,34 @@
1
1
  /**
2
2
  * Compares two semantic version strings.
3
3
  *
4
- * Extracts the major.minor.patch pattern from each version string and compares
5
- * them numerically. Only the first matching pattern is used (e.g., "1.2.3-beta"
6
- * becomes "1.2.3").
4
+ * Normalizes version strings by replacing non-numeric characters with dots,
5
+ * then compares them numerically segment by segment. Supports versions with
6
+ * any number of segments (e.g., "1.0.0", "1.0.0--rc.17", "1.2.3.4.5").
7
+ *
8
+ * **Normalization process**:
9
+ * - Replaces all non-numeric characters (letters, dashes, etc.) with dots
10
+ * - Collapses multiple consecutive dots into a single dot
11
+ * - Extracts numeric segments for comparison
7
12
  *
8
13
  * **Comparison logic**:
9
- * - Compares major, then minor, then patch numbers
14
+ * - Compares segments from left to right numerically
15
+ * - If all segments are equal up to the minimum length, the version with more segments is considered greater
10
16
  * - Returns -1 if first version is greater
11
17
  * - Returns 0 if versions are equal
12
18
  * - Returns 1 if second version is greater
13
19
  *
14
- * @param firstVersion - First version string (must contain X.Y.Z pattern)
15
- * @param secondVersion - Second version string (must contain X.Y.Z pattern)
20
+ * @param firstVersion - First version string (must contain at least one numeric segment)
21
+ * @param secondVersion - Second version string (must contain at least one numeric segment)
16
22
  * @returns Comparison result: -1, 0, or 1
17
- * @throws BadImplementationException if versions are undefined or don't contain X.Y.Z pattern
23
+ * @throws BadImplementationException if versions are undefined or don't contain numeric segments
18
24
  *
19
25
  * @example
20
26
  * ```typescript
21
27
  * compareVersions('1.2.3', '1.2.4') // Returns 1 (second is greater)
22
28
  * compareVersions('2.0.0', '1.9.9') // Returns -1 (first is greater)
23
29
  * compareVersions('1.0.0', '1.0.0') // Returns 0 (equal)
30
+ * compareVersions('1.0.0--rc.17', '1.0.0--rc.18') // Returns 1 (second is greater)
31
+ * compareVersions('1.0.0', '1.0.0.1') // Returns 1 (second has more segments)
24
32
  * ```
25
33
  */
26
34
  export declare function compareVersions(firstVersion: string, secondVersion: string): 0 | 1 | -1;
@@ -18,29 +18,64 @@
18
18
  import { BadImplementationException } from '../core/exceptions/exceptions.js';
19
19
  import { tsValidateResult } from '../validator/validator-core.js';
20
20
  import { tsValidateVersion } from '../validator/validators.js';
21
+ /**
22
+ * Normalizes a version string by converting non-numeric characters to dots,
23
+ * collapsing multiple consecutive dots, and extracting numeric segments.
24
+ *
25
+ * @param version - Version string to normalize
26
+ * @returns Array of numeric segments
27
+ * @throws BadImplementationException if version contains no numeric segments
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * normalizeVersion('1.0.0--rc.17') // Returns [1, 0, 0, 17]
32
+ * normalizeVersion('2.3.4-suffix') // Returns [2, 3, 4]
33
+ * normalizeVersion('1.2.3.4.5') // Returns [1, 2, 3, 4, 5]
34
+ * ```
35
+ */
36
+ function normalizeVersion(version) {
37
+ // Replace all non-numeric characters with dots
38
+ let normalized = version.replace(/[^\d]/g, '.');
39
+ // Replace multiple consecutive dots with single dot
40
+ normalized = normalized.replace(/\.+/g, '.');
41
+ // Trim leading/trailing dots
42
+ normalized = normalized.replace(/^\.+|\.+$/g, '');
43
+ if (!normalized)
44
+ throw new BadImplementationException(`Unable to extract calculable version from '${version}' - no numeric segments found`);
45
+ // Split and convert to numbers
46
+ return normalized.split('.').map(Number);
47
+ }
21
48
  /**
22
49
  * Compares two semantic version strings.
23
50
  *
24
- * Extracts the major.minor.patch pattern from each version string and compares
25
- * them numerically. Only the first matching pattern is used (e.g., "1.2.3-beta"
26
- * becomes "1.2.3").
51
+ * Normalizes version strings by replacing non-numeric characters with dots,
52
+ * then compares them numerically segment by segment. Supports versions with
53
+ * any number of segments (e.g., "1.0.0", "1.0.0--rc.17", "1.2.3.4.5").
54
+ *
55
+ * **Normalization process**:
56
+ * - Replaces all non-numeric characters (letters, dashes, etc.) with dots
57
+ * - Collapses multiple consecutive dots into a single dot
58
+ * - Extracts numeric segments for comparison
27
59
  *
28
60
  * **Comparison logic**:
29
- * - Compares major, then minor, then patch numbers
61
+ * - Compares segments from left to right numerically
62
+ * - If all segments are equal up to the minimum length, the version with more segments is considered greater
30
63
  * - Returns -1 if first version is greater
31
64
  * - Returns 0 if versions are equal
32
65
  * - Returns 1 if second version is greater
33
66
  *
34
- * @param firstVersion - First version string (must contain X.Y.Z pattern)
35
- * @param secondVersion - Second version string (must contain X.Y.Z pattern)
67
+ * @param firstVersion - First version string (must contain at least one numeric segment)
68
+ * @param secondVersion - Second version string (must contain at least one numeric segment)
36
69
  * @returns Comparison result: -1, 0, or 1
37
- * @throws BadImplementationException if versions are undefined or don't contain X.Y.Z pattern
70
+ * @throws BadImplementationException if versions are undefined or don't contain numeric segments
38
71
  *
39
72
  * @example
40
73
  * ```typescript
41
74
  * compareVersions('1.2.3', '1.2.4') // Returns 1 (second is greater)
42
75
  * compareVersions('2.0.0', '1.9.9') // Returns -1 (first is greater)
43
76
  * compareVersions('1.0.0', '1.0.0') // Returns 0 (equal)
77
+ * compareVersions('1.0.0--rc.17', '1.0.0--rc.18') // Returns 1 (second is greater)
78
+ * compareVersions('1.0.0', '1.0.0.1') // Returns 1 (second has more segments)
44
79
  * ```
45
80
  */
46
81
  export function compareVersions(firstVersion, secondVersion) {
@@ -48,26 +83,23 @@ export function compareVersions(firstVersion, secondVersion) {
48
83
  throw new BadImplementationException('First version is undefined');
49
84
  if (!secondVersion)
50
85
  throw new BadImplementationException('Second version is undefined');
51
- const extractedFirstVersion = firstVersion.match(/\d+\.\d+\.\d+/)?.[0];
52
- if (!extractedFirstVersion)
53
- throw new BadImplementationException(`Unable to extract calculable version from '${firstVersion}'`);
54
- firstVersion = extractedFirstVersion;
55
- const extractedSecondVersion = secondVersion.match(/\d+\.\d+\.\d+/)?.[0];
56
- if (!extractedSecondVersion)
57
- throw new BadImplementationException(`Unable to extract calculable version from '${secondVersion}'`);
58
- secondVersion = extractedSecondVersion;
59
- const firstVersionAsArray = firstVersion.split('\.');
60
- const secondVersionAsArray = secondVersion.split('\.');
61
- for (let i = 0; i < firstVersionAsArray.length; i++) {
62
- const secondVal = +secondVersionAsArray[i];
63
- const firstVal = +firstVersionAsArray[i];
86
+ const firstVersionAsArray = normalizeVersion(firstVersion);
87
+ const secondVersionAsArray = normalizeVersion(secondVersion);
88
+ const minLength = Math.min(firstVersionAsArray.length, secondVersionAsArray.length);
89
+ // Compare segments up to the minimum length
90
+ for (let i = 0; i < minLength; i++) {
91
+ const firstVal = firstVersionAsArray[i];
92
+ const secondVal = secondVersionAsArray[i];
64
93
  if (secondVal > firstVal)
65
94
  return 1;
66
- if (secondVal === firstVal)
67
- continue;
68
95
  if (secondVal < firstVal)
69
96
  return -1;
70
97
  }
98
+ // If all segments are equal up to minimum length, compare by length
99
+ if (firstVersionAsArray.length > secondVersionAsArray.length)
100
+ return -1;
101
+ if (firstVersionAsArray.length < secondVersionAsArray.length)
102
+ return 1;
71
103
  return 0;
72
104
  }
73
105
  /**