@mi-avalon/libs 0.0.20 → 0.0.22

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,192 @@
1
+ /**
2
+ * 版本号工具类
3
+ * 支持语义化版本 (SemVer) 和基本版本号比较
4
+ */
5
+ export class VersionUtil {
6
+ /**
7
+ * 验证版本号格式是否有效
8
+ * @param version 版本号字符串
9
+ * @returns 是否有效
10
+ */
11
+ static isValid(version) {
12
+ const semverRegex = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/i;
13
+ return semverRegex.test(version);
14
+ }
15
+ /**
16
+ * 比较两个版本号
17
+ * @param v1 版本号1
18
+ * @param v2 版本号2
19
+ * @returns 比较结果: 1(v1>v2), 0(v1=v2), -1(v1<v2)
20
+ */
21
+ static compare(v1, v2) {
22
+ if (!this.isValid(v1) || !this.isValid(v2)) {
23
+ throw new Error('Invalid version format');
24
+ }
25
+ // 去除前缀v并分割版本号
26
+ const normalize = (v) => v.replace(/^v/, '').split(/[-+]/)[0].split('.');
27
+ const parts1 = normalize(v1);
28
+ const parts2 = normalize(v2);
29
+ for (let i = 0; i < 3; i++) {
30
+ const num1 = parseInt(parts1[i] || '0', 10);
31
+ const num2 = parseInt(parts2[i] || '0', 10);
32
+ if (num1 > num2)
33
+ return 1;
34
+ if (num1 < num2)
35
+ return -1;
36
+ }
37
+ // 比较预发布版本
38
+ const preRelease1 = v1.match(/-(.+)/);
39
+ const preRelease2 = v2.match(/-(.+)/);
40
+ if (preRelease1 && !preRelease2)
41
+ return -1;
42
+ if (!preRelease1 && preRelease2)
43
+ return 1;
44
+ if (preRelease1 && preRelease2) {
45
+ return preRelease1[1].localeCompare(preRelease2[1]);
46
+ }
47
+ return 0;
48
+ }
49
+ /**
50
+ * 检查版本号是否满足范围要求
51
+ * @param version 要检查的版本
52
+ * @param range 版本范围 (如 ">=1.0.0 <2.0.0") 支持: >, >=, <, <=, ^, ~, ==, =
53
+ * @returns 是否满足
54
+ */
55
+ static satisfies(version, range) {
56
+ if (!this.isValid(version))
57
+ return false;
58
+ const rangeRegex = /([<>]=?|==?|\^|~)?\s*v?([0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+)?)/g;
59
+ const ranges = range.match(rangeRegex);
60
+ if (!ranges || ranges.length === 0)
61
+ return false;
62
+ return ranges.every(r => {
63
+ const match = r.match(/([<>]=?|==?|\^|~)?\s*(v?[0-9].*)/);
64
+ if (!match)
65
+ return false;
66
+ const operator = match[1] || '==';
67
+ const rangeVersion = match[2];
68
+ if (!this.isValid(rangeVersion))
69
+ return false;
70
+ const comparison = this.compare(version, rangeVersion);
71
+ switch (operator) {
72
+ case '>':
73
+ return comparison > 0;
74
+ case '>=':
75
+ return comparison >= 0;
76
+ case '<':
77
+ return comparison < 0;
78
+ case '<=':
79
+ return comparison <= 0;
80
+ case '^':
81
+ return this.caretRange(version, rangeVersion);
82
+ case '~':
83
+ return this.tildeRange(version, rangeVersion);
84
+ case '=':
85
+ case '==':
86
+ default:
87
+ return comparison === 0;
88
+ }
89
+ });
90
+ }
91
+ /**
92
+ * 处理 ^ 范围 (允许不修改最左边的非零数字)
93
+ * @param version 版本号
94
+ * @param range 范围版本
95
+ * @returns 是否匹配
96
+ */
97
+ static caretRange(version, range) {
98
+ const normalize = (v) => v.replace(/^v/, '').split(/[-+]/)[0].split('.');
99
+ const vParts = normalize(version);
100
+ const rParts = normalize(range);
101
+ // 找到第一个非零部分
102
+ let firstNonZero = 0;
103
+ for (let i = 0; i < rParts.length; i++) {
104
+ if (parseInt(rParts[i], 10) !== 0) {
105
+ firstNonZero = i;
106
+ break;
107
+ }
108
+ }
109
+ for (let i = 0; i <= firstNonZero; i++) {
110
+ const vNum = parseInt(vParts[i] || '0', 10);
111
+ const rNum = parseInt(rParts[i] || '0', 10);
112
+ if (vNum !== rNum)
113
+ return false;
114
+ }
115
+ return this.compare(version, range) >= 0;
116
+ }
117
+ /**
118
+ * 处理 ~ 范围 (允许修改最后一位数字)
119
+ * @param version 版本号
120
+ * @param range 范围版本
121
+ * @returns 是否匹配
122
+ */
123
+ static tildeRange(version, range) {
124
+ const normalize = (v) => v.replace(/^v/, '').split(/[-+]/)[0].split('.');
125
+ const vParts = normalize(version);
126
+ const rParts = normalize(range);
127
+ for (let i = 0; i < rParts.length - 1; i++) {
128
+ const vNum = parseInt(vParts[i] || '0', 10);
129
+ const rNum = parseInt(rParts[i] || '0', 10);
130
+ if (vNum !== rNum)
131
+ return false;
132
+ }
133
+ const lastVNum = parseInt(vParts[rParts.length - 1] || '0', 10);
134
+ const lastRNum = parseInt(rParts[rParts.length - 1] || '0', 10);
135
+ return lastVNum >= lastRNum;
136
+ }
137
+ /**
138
+ * 获取主版本号 (major)
139
+ * @param version 版本号
140
+ * @returns 主版本号
141
+ */
142
+ static getMajor(version) {
143
+ if (!this.isValid(version))
144
+ throw new Error('Invalid version format');
145
+ const parts = version.replace(/^v/, '').split('.');
146
+ return parseInt(parts[0], 10);
147
+ }
148
+ /**
149
+ * 获取次版本号 (minor)
150
+ * @param version 版本号
151
+ * @returns 次版本号
152
+ */
153
+ static getMinor(version) {
154
+ if (!this.isValid(version))
155
+ throw new Error('Invalid version format');
156
+ const parts = version.replace(/^v/, '').split('.');
157
+ return parseInt(parts[1] || '0', 10);
158
+ }
159
+ /**
160
+ * 获取修订号 (patch)
161
+ * @param version 版本号
162
+ * @returns 修订号
163
+ */
164
+ static getPatch(version) {
165
+ if (!this.isValid(version))
166
+ throw new Error('Invalid version format');
167
+ const parts = version.replace(/^v/, '').split('.');
168
+ return parseInt(parts[2] || '0', 10);
169
+ }
170
+ /**
171
+ * 获取预发布版本标识
172
+ * @param version 版本号
173
+ * @returns 预发布标识 (无则返回null)
174
+ */
175
+ static getPrerelease(version) {
176
+ if (!this.isValid(version))
177
+ throw new Error('Invalid version format');
178
+ const match = version.match(/-([^+]+)/);
179
+ return match ? match[1] : null;
180
+ }
181
+ /**
182
+ * 获取构建元数据
183
+ * @param version 版本号
184
+ * @returns 构建元数据 (无则返回null)
185
+ */
186
+ static getBuildMetadata(version) {
187
+ if (!this.isValid(version))
188
+ throw new Error('Invalid version format');
189
+ const match = version.match(/\+([^]+)/);
190
+ return match ? match[1] : null;
191
+ }
192
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mi-avalon/libs",
3
3
  "private": false,
4
- "version": "0.0.20",
4
+ "version": "0.0.22",
5
5
  "type": "module",
6
6
  "main": "./dist/index.umd.js",
7
7
  "module": "./dist/index.es.js",
@@ -9,10 +9,14 @@
9
9
  "files": [
10
10
  "dist"
11
11
  ],
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
12
15
  "scripts": {
13
16
  "dev": "vite",
14
17
  "build": "vite build && tsc",
15
- "preview": "vite preview"
18
+ "preview": "vite preview",
19
+ "pub": "npm run build && npm publish"
16
20
  },
17
21
  "devDependencies": {
18
22
  "@types/node": "^20.0.0",
@@ -1 +0,0 @@
1
- export declare const getClassName: (key1: string, key2: string) => string;
@@ -1,16 +0,0 @@
1
- // 生成类名
2
- export const getClassName = (key1, key2) => {
3
- const cn = key1;
4
- let str = key1;
5
- if (key2.includes(' ')) {
6
- str = '';
7
- const nArr = key2?.split(' ');
8
- for (const i of nArr) {
9
- str += ` ${cn}-${i}`;
10
- }
11
- }
12
- else if (key2) {
13
- str = `${key1}-${key2}`;
14
- }
15
- return str;
16
- };