@lazy-node/semver-ampersand 3.0.11 → 3.0.12

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.
Files changed (80) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +61 -20
  3. package/lib/Range.d.ts +111 -0
  4. package/lib/Range.js +136 -0
  5. package/lib/Range.js.map +1 -1
  6. package/lib/comparator/detect.d.ts +14 -0
  7. package/lib/comparator/detect.js +14 -0
  8. package/lib/comparator/detect.js.map +1 -1
  9. package/lib/const.d.ts +38 -0
  10. package/lib/const.js +38 -0
  11. package/lib/const.js.map +1 -1
  12. package/lib/handleAmpersandAndSpaces.d.ts +16 -0
  13. package/lib/handleAmpersandAndSpaces.js +16 -0
  14. package/lib/handleAmpersandAndSpaces.js.map +1 -1
  15. package/lib/internal/parseOptionsOrLoose.d.ts +20 -0
  16. package/lib/internal/parseOptionsOrLoose.js +20 -0
  17. package/lib/internal/parseOptionsOrLoose.js.map +1 -1
  18. package/lib/maxSatisfying.d.ts +15 -0
  19. package/lib/maxSatisfying.js +15 -0
  20. package/lib/maxSatisfying.js.map +1 -1
  21. package/lib/minSatisfying.d.ts +15 -0
  22. package/lib/minSatisfying.js +15 -0
  23. package/lib/minSatisfying.js.map +1 -1
  24. package/lib/range/buildRangeSet.d.ts +13 -0
  25. package/lib/range/buildRangeSet.js +15 -0
  26. package/lib/range/buildRangeSet.js.map +1 -1
  27. package/lib/range/cache.d.ts +10 -0
  28. package/lib/range/cache.js +10 -0
  29. package/lib/range/cache.js.map +1 -1
  30. package/lib/range/fixComparatorSet.d.ts +50 -0
  31. package/lib/range/fixComparatorSet.js +50 -0
  32. package/lib/range/fixComparatorSet.js.map +1 -1
  33. package/lib/range/normalizeRangeInput.d.ts +14 -0
  34. package/lib/range/normalizeRangeInput.js +16 -0
  35. package/lib/range/normalizeRangeInput.js.map +1 -1
  36. package/lib/range/options.d.ts +38 -0
  37. package/lib/range/options.js +38 -0
  38. package/lib/range/options.js.map +1 -1
  39. package/lib/range/parseRange.d.ts +67 -0
  40. package/lib/range/parseRange.js +84 -0
  41. package/lib/range/parseRange.js.map +1 -1
  42. package/lib/range/stringifyRangeSet.d.ts +12 -0
  43. package/lib/range/stringifyRangeSet.js +12 -0
  44. package/lib/range/stringifyRangeSet.js.map +1 -1
  45. package/lib/range/toRangeString.d.ts +12 -0
  46. package/lib/range/toRangeString.js +12 -0
  47. package/lib/range/toRangeString.js.map +1 -1
  48. package/lib/range/util.d.ts +133 -0
  49. package/lib/range/util.js +213 -0
  50. package/lib/range/util.js.map +1 -1
  51. package/lib/satisfies.d.ts +17 -0
  52. package/lib/satisfies.js +17 -0
  53. package/lib/satisfies.js.map +1 -1
  54. package/lib/simplifyRange.d.ts +15 -0
  55. package/lib/simplifyRange.js +15 -0
  56. package/lib/simplifyRange.js.map +1 -1
  57. package/lib/types.d.ts +30 -0
  58. package/lib/types.js.map +1 -1
  59. package/lib/util/array.d.ts +14 -0
  60. package/lib/util/array.js +14 -0
  61. package/lib/util/array.js.map +1 -1
  62. package/lib/util/assert.d.ts +42 -0
  63. package/lib/util/assert.js +42 -0
  64. package/lib/util/assert.js.map +1 -1
  65. package/lib/util/fixBooleanProperty.d.ts +15 -0
  66. package/lib/util/fixBooleanProperty.js +18 -0
  67. package/lib/util/fixBooleanProperty.js.map +1 -1
  68. package/lib/util/index.d.ts +24 -0
  69. package/lib/util/index.js +24 -0
  70. package/lib/util/index.js.map +1 -1
  71. package/lib/util/split.d.ts +17 -0
  72. package/lib/util/split.js +17 -0
  73. package/lib/util/split.js.map +1 -1
  74. package/lib/util/stringifyComparators.d.ts +18 -0
  75. package/lib/util/stringifyComparators.js +18 -0
  76. package/lib/util/stringifyComparators.js.map +1 -1
  77. package/lib/validRange.d.ts +15 -1
  78. package/lib/validRange.js +15 -1
  79. package/lib/validRange.js.map +1 -1
  80. package/package.json +7 -5
package/CHANGELOG.md CHANGED
@@ -3,6 +3,41 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.0.12](https://github.com/bluelovers/ws-yarn-workspaces/compare/@lazy-node/semver-ampersand@3.0.11...@lazy-node/semver-ampersand@3.0.12) (2026-10-12)
7
+
8
+
9
+
10
+ ### 📚 Documentation
11
+
12
+ * add jsdoc ([9cb9b13](https://github.com/bluelovers/ws-yarn-workspaces/commit/9cb9b13eda8c357221ad1b754458aa9916eada22))
13
+
14
+
15
+ ### 🚨 Tests
16
+
17
+ * **all:** 完善 node:test 遷移與測試案例優化 ([e38f263](https://github.com/bluelovers/ws-yarn-workspaces/commit/e38f26376a03520b39a54fea5794f27aecc4f424))
18
+ * **snap:** update snapshots ([c9945a5](https://github.com/bluelovers/ws-yarn-workspaces/commit/c9945a5b9cd723d38ded2a69b83e2e83ecc3b524))
19
+ * **test:** 將測試框架從 jest 遷移至 node:test ([3af9774](https://github.com/bluelovers/ws-yarn-workspaces/commit/3af9774964abc48083ec60b2021c1cec08874803))
20
+
21
+
22
+ ### 🛠 Build System
23
+
24
+ * update build ([3186340](https://github.com/bluelovers/ws-yarn-workspaces/commit/3186340758172427cb1e9b8955f6fd677abac625))
25
+ * **deps:** 更新測試腳本與依賴以支援 node:test ([f9c71c7](https://github.com/bluelovers/ws-yarn-workspaces/commit/f9c71c795c792c5c7ed9d613ce7e9c3c726c39d5))
26
+
27
+
28
+ ### ♻️ Chores
29
+
30
+ * **deps:** 更新依賴版本並清理 npm-init2 腳本 ([82bf1e5](https://github.com/bluelovers/ws-yarn-workspaces/commit/82bf1e5d229759aa285205d81cf0651e4d3d9792))
31
+ * **deps:** 更新各套件依賴版本 ([569f075](https://github.com/bluelovers/ws-yarn-workspaces/commit/569f0756189cdadf69955d8e388ac0a6a8988056))
32
+ * **workspace:** 更新測試指令路徑與新增工作區搜尋選項 ([a80039d](https://github.com/bluelovers/ws-yarn-workspaces/commit/a80039dd8c691e047466966ffc8f8a4e2e31c03f))
33
+
34
+
35
+ ### 🔖 Miscellaneous
36
+
37
+ * . ([e5788f8](https://github.com/bluelovers/ws-yarn-workspaces/commit/e5788f84551b870490a96d0a5d67d8d542481373))
38
+
39
+
40
+
6
41
  ## [3.0.11](https://github.com/bluelovers/ws-yarn-workspaces/compare/@lazy-node/semver-ampersand@3.0.10...@lazy-node/semver-ampersand@3.0.11) (2026-09-06)
7
42
 
8
43
 
package/README.md CHANGED
@@ -11,6 +11,15 @@
11
11
 
12
12
  This module extends the standard `semver` package's range handling with support for the `&` symbol to represent "AND" conditions. This is particularly useful when handling dependency versions in yarn or npm workspaces, where more explicit version range expressions are sometimes needed.
13
13
 
14
+ ## 功能特色 / Features
15
+
16
+ - 🔗 **Ampersand 支援** - 使用 `&` 符號組合多個版本條件 / Use `&` symbol to combine multiple version conditions
17
+ - ✅ **satisfies** - 檢查版本是否符合範圍 / Check if version satisfies range
18
+ - 🔍 **maxSatisfying / minSatisfying** - 找出最大/最小符合版本 / Find max/min satisfying version
19
+ - 📝 **validRange** - 驗證範圍字串是否有效 / Validate if range string is valid
20
+ - 🔄 **simplifyRange** - 簡化版本範圍 / Simplify version range
21
+ - 🏗️ **Range 類別** - 類似 semver.Range 的增強版 / Enhanced Range class similar to semver.Range
22
+
14
23
  ## 安裝 / Installation
15
24
 
16
25
  ```bash
@@ -24,14 +33,26 @@ yarn-tool add @lazy-node/semver-ampersand
24
33
  npm install @lazy-node/semver-ampersand
25
34
  ```
26
35
 
27
- ## 功能特色 / Features
36
+ ## 使用方式 / Usage
28
37
 
29
- - 🔗 **Ampersand 支援** - 使用 `&` 符號組合多個版本條件 / Use `&` symbol to combine multiple version conditions
30
- - ✅ **satisfies** - 檢查版本是否符合範圍 / Check if version satisfies range
31
- - 🔍 **maxSatisfying / minSatisfying** - 找出最大/最小符合版本 / Find max/min satisfying version
32
- - 📝 **validRange** - 驗證範圍字串是否有效 / Validate if range string is valid
33
- - 🔄 **simplifyRange** - 簡化版本範圍 / Simplify version range
34
- - 🏗️ **Range 類別** - 類似 semver.Range 的增強版 / Enhanced Range class similar to semver.Range
38
+ ```typescript
39
+ import { satisfies, validRange, maxSatisfying, Range } from '@lazy-node/semver-ampersand';
40
+
41
+ // 標準 semver 與 ampersand 語法皆可 / Both standard and ampersand syntax work
42
+ satisfies('1.2.3', '>=1.0.0 <2.0.0'); // true
43
+ satisfies('1.2.3', '>=1.0.0 & <2.0.0'); // true
44
+
45
+ // 驗證範圍是否有效 / Validate the range string
46
+ validRange('>=1.0.0 & <2.0.0'); // 回傳規範化後的範圍字串 / returns the normalized range string
47
+ validRange('>=1.0.0 & invalid'); // null
48
+
49
+ // 從版本清單挑選符合的版本 / Pick a satisfying version from a list
50
+ maxSatisfying(['1.0.0', '1.2.3', '2.0.0'], '>=1.0.0 & <2.0.0'); // '1.2.3'
51
+
52
+ // 重複使用同一個範圍 / Reuse one range instance
53
+ const range = new Range('>=1.0.0 & <2.0.0');
54
+ range.test('1.5.0'); // true
55
+ ```
35
56
 
36
57
  ## Ampersand (`&`) 語法說明 / Ampersand (`&`) Syntax Explanation
37
58
 
@@ -79,7 +100,7 @@ Validate if a range string is valid, returns normalized range or `null`.
79
100
  ```typescript
80
101
  import { validRange } from '@lazy-node/semver-ampersand';
81
102
 
82
- validRange('>=1.0.0 & <2.0.0'); // true (返回規範化的範圍)
103
+ validRange('>=1.0.0 & <2.0.0'); // 回傳規範化後的範圍字串 / Returns the normalized range string
83
104
  validRange('invalid-range'); // null
84
105
  validRange('>=1.0.0 & invalid'); // null
85
106
  ```
@@ -160,22 +181,38 @@ console.log(range.set); // 比較器集合
160
181
  console.log(range.toString()); // '>=1.0.0 <2.0.0'
161
182
  ```
162
183
 
163
- ### 選項 / Options
184
+ ## 組態設定 / Configuration
185
+
186
+ 此套件沒有設定檔 (Config File),所有選項皆透過各函數的 `options` 參數傳遞,型別為 `IOptions`(繼承 `semver.Options` 與 `semver.RangeOptions`)。
187
+
188
+ This package has no config file; all options are passed through the `options` parameter of each function, typed as `IOptions` (extending `semver.Options` and `semver.RangeOptions`).
189
+
190
+ | 選項 / Option | 型別 / Type | 預設 / Default | 說明 / Description |
191
+ | --- | --- | --- | --- |
192
+ | `loose` | `boolean` | `false` | 寬鬆模式 (Loose Mode),放寬版本字串解析規則 / Relax version string parsing rules |
193
+ | `includePrerelease` | `boolean` | `false` | 將預發布版本 (Pre-release) 視為候選 / Include pre-release versions as candidates |
194
+ | `noAmpersand` | `boolean` | `false` | 停用 ampersand (`&`) 支援,此時 `&` 會被視為無效字元 / Disable ampersand (`&`) support; `&` is then treated as an invalid character |
195
+ | `unsafeOptimize` | `boolean` | `false` | 啟用不安全的比較器集合優化,可能改變邊界行為,請謹慎使用 / Enable unsafe comparator-set optimization; may alter edge behavior, use with caution |
164
196
 
165
197
  ```typescript
166
- interface IOptions extends semver.Options, semver.RangeOptions {
167
- /**
168
- * 停用 ampersand 處理 / Disable ampersand handling
169
- */
170
- noAmpersand?: boolean;
171
-
172
- /**
173
- * 啟用不安全優化 / Enable unsafe optimization
174
- */
175
- unsafeOptimize?: boolean;
176
- }
198
+ import { satisfies, validRange } from '@lazy-node/semver-ampersand';
199
+
200
+ // noAmpersand: true → `&` 被視為無效字元,範圍回傳 null / `&` becomes an invalid character, so the range returns null
201
+ validRange('>=1.0.0 & <2.0.0', { noAmpersand: true }); // null
202
+ validRange('>=1.0.0 & <2.0.0'); // 回傳規範化後的範圍字串 / returns the normalized range string
203
+
204
+ // 允許預發布版本 / Include pre-release versions
205
+ satisfies('1.0.1-beta.1', '^1.0.0', { includePrerelease: true }); // true
206
+ satisfies('1.0.1-beta.1', '^1.0.0'); // false
207
+
208
+ // 布林值簡寫等同於 { loose: true } / Boolean shorthand equals `{ loose: true }`
209
+ satisfies('1.2.3', '>=1.0.0', true);
177
210
  ```
178
211
 
212
+ > ⚠️ `noAmpersand` 只在有傳遞選項的路徑(如 `Range`、`validRange`)生效;`satisfies()`、`maxSatisfying()` 等函式一律會先把 `&` 視為「且」處理。
213
+ >
214
+ > ⚠️ `noAmpersand` only takes effect on paths that forward options (such as `Range` and `validRange`); `satisfies()`, `maxSatisfying()`, etc. always treat `&` as "AND".
215
+
179
216
  ## 使用案例 / Use Cases
180
217
 
181
218
  ### 1. Workspaces 版本管理 / Workspace Version Management
@@ -272,6 +309,10 @@ const range = new Range(complexRange);
272
309
  - [`@lazy-node/semver-parse`](../semver-parse) - semver 解析工具 / Semver parsing utilities
273
310
  - [`semver`](https://www.npmjs.com/package/semver) - 語義化版本處理 / Semantic versioning
274
311
 
312
+ ### 延伸閱讀 / Further Reading
313
+
314
+ - [docs/semver-packages.md](../../../docs/semver-packages.md) - `@lazy-node/semver-*` 系列套件總覽 / Overview of the `@lazy-node/semver-*` package series
315
+
275
316
  ## 授權 / License
276
317
 
277
318
  ISC © bluelovers
package/lib/Range.d.ts CHANGED
@@ -1,27 +1,138 @@
1
+ /**
2
+ * 增強版 semver Range 類別
3
+ * Enhanced semver Range class
4
+ *
5
+ * 繼承 semver 的 Range,但刻意略過父層建構函式(super() 不帶參數),
6
+ * 改由 _inherit 自行正規化輸入,才能同時接受字串、Comparator、SemVer
7
+ * 與原生 Range 作為來源,並在搬移時保留原有的比較器集合以避免重複解析。
8
+ * Extends semver's Range but deliberately skips the parent constructor
9
+ * (`super()` takes no arguments), letting `_inherit` normalize the input so a
10
+ * string, Comparator, SemVer, or native Range can all serve as the source while
11
+ * an existing comparator set is carried over instead of re-parsed.
12
+ *
13
+ * @packageDocumentation
14
+ */
1
15
  import semverRange from 'semver/classes/range';
2
16
  import { IComparatorSet, IComparatorSetInput, IOptions, IOptionsOrLoose, ISemverRangeInput } from './types';
3
17
  import { Comparator } from 'semver';
4
18
  declare const SemverRange_base: typeof semverRange & (new () => semverRange);
19
+ /**
20
+ * SemverRange 類別(對外以 Range 匯出)
21
+ * The SemverRange class (exported as `Range`)
22
+ *
23
+ * 特點:來源可為多種型別、支援 ampersand 語法、可重用既有比較器集合。
24
+ * Highlights: accepts several source types, supports ampersand syntax, and
25
+ * can reuse an existing comparator set.
26
+ *
27
+ * @template RAW - 原始輸入的型別 / Type of the raw input
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const range = new Range('>=1.0.0 & <2.0.0');
32
+ * range.test('1.5.0'); // true
33
+ * range.toString(); // '>=1.0.0 <2.0.0'
34
+ * ```
35
+ */
5
36
  export declare class SemverRange<RAW extends ISemverRangeInput> extends SemverRange_base {
37
+ /** 呼叫端傳入的原始值,保留供除錯 / The original value passed in, kept for debugging */
6
38
  readonly rawSource?: RAW;
39
+ /** 規範化後的範圍字串 / Normalized range string */
7
40
  readonly raw: string;
41
+ /** 二維比較器集合(外層為 `||` 分隔的集合)/ Two-dimensional comparator set (outer level = `||` groups) */
8
42
  readonly set: IComparatorSet;
43
+ /** 解析後的選項 / Normalized options */
9
44
  readonly options: IOptions;
45
+ /** 是否為寬鬆模式 / Whether loose mode is on */
10
46
  readonly loose: boolean;
47
+ /** 是否納入預發布版本 / Whether pre-releases are included */
11
48
  readonly includePrerelease: boolean;
49
+ /** 快取的格式化結果,由 range getter 每次重算後寫入 / Cached formatted result, rewritten by the `range` getter on every access */
12
50
  protected readonly formatted: string;
51
+ /**
52
+ * 建立 Range 實例
53
+ * Create a Range instance
54
+ *
55
+ * @param rawSource - 範圍來源(字串、Comparator、SemVer、原生 Range)/ Range source (string, Comparator, SemVer, native Range)
56
+ * @param optionsOrLoose - 選項或寬鬆旗標 / Options or loose flag
57
+ * @throws {TypeError} 當比較器集合為空(整個範圍無效)時 / When the comparator set is empty (the whole range is invalid)
58
+ */
13
59
  constructor(rawSource: RAW, optionsOrLoose?: IOptionsOrLoose<IOptions>);
60
+ /**
61
+ * 把範圍字串切成二維比較器集合
62
+ * Turn a range string into a two-dimensional comparator set
63
+ *
64
+ * 以 `||` 分割成多個集合,各集合再解析為比較器;
65
+ * 空集合會被過濾(loose 模式下允許個別條件無效),
66
+ * 但若整個範圍都無效,外層的 assert 仍會拋錯。
67
+ * Split on `||` into groups, then parse each group into comparators; empty
68
+ * groups are dropped (loose mode tolerates invalid individual conditions),
69
+ * while a wholly invalid range still throws at the outer assert.
70
+ *
71
+ * @param range - 範圍字串 / Range string
72
+ * @param options - 選項 / Options
73
+ * @returns 比較器集合 / Comparator set
74
+ */
14
75
  protected _buildComparatorsSet(range: string, options: IOptions): IComparatorSetInput;
76
+ /**
77
+ * 解析單一(不含 `||`)的範圍字串
78
+ * Parse a single range string (without `||`)
79
+ *
80
+ * 這裡帶入 this.options,確保 ampersand 與空格的處理與建構時一致。
81
+ * Options are threaded through here so ampersand/space handling matches
82
+ * what the constructor did.
83
+ *
84
+ * @param range - 範圍字串 / Range string
85
+ * @returns 比較器陣列 / Comparator array
86
+ */
15
87
  parseRange(range: string): readonly Comparator[];
88
+ /**
89
+ * 從各種來源繼承範圍與選項
90
+ * Inherit range and options from any supported source
91
+ *
92
+ * 輸入為原生 semver Range 時:合併兩側選項,且僅在選項完全相同的情況下
93
+ * 直接沿用其 set;否則會重新解析(選項不同可能產生不同結果)。
94
+ * When the input is a native semver Range: options from both sides are
95
+ * merged, and its `set` is reused only when the merged options match
96
+ * exactly — otherwise it is re-parsed, since differing options can produce
97
+ * a different set.
98
+ *
99
+ * @param range - 範圍來源 / Range source
100
+ * @param options - 已正規化的選項 / Normalized options
101
+ * @returns 正規化後的 range、options 與(可能存在的)set / Normalized range, options, and (possibly) set
102
+ */
16
103
  protected _inherit(range: ISemverRangeInput, options: IOptions): {
17
104
  range: string;
18
105
  options: IOptions;
19
106
  set: readonly (readonly Comparator[])[];
20
107
  };
108
+ /**
109
+ * 把選項同步到實例上
110
+ * Sync options onto the instance
111
+ *
112
+ * options 寫入父層欄位後,再以 _copyOptions 複製 loose / includePrerelease
113
+ * 兩個常用欄位,避免每次取值都要翻閱 options 物件。
114
+ * After writing `options` to the parent field, `_copyOptions` mirrors the
115
+ * frequently used `loose` / `includePrerelease` fields so readers do not
116
+ * have to dig into the options object.
117
+ *
118
+ * @param options - 已正規化的選項 / Normalized options
119
+ */
21
120
  protected _inheritOptions(options: IOptions): void;
121
+ /**
122
+ * 取得格式化後的範圍字串
123
+ * Get the formatted range string
124
+ *
125
+ * 每次存取都從 set 重新組字串(而非取快取),因為 set 可能已被外部修改。
126
+ * The string is rebuilt from `set` on every access instead of being cached,
127
+ * because `set` may have been mutated externally.
128
+ */
22
129
  get range(): string;
23
130
  /**
24
131
  * Return '*' instead of '' so that truthiness works.
132
+ *
133
+ * 回傳 `*` 而非空字串,可讓 `if (range.toRangeString())` 這類真值判斷成立。
134
+ * Returning `*` instead of an empty string keeps truthiness checks such as
135
+ * `if (range.toRangeString())` working.
25
136
  */
26
137
  toRangeString(): string;
27
138
  }
package/lib/Range.js CHANGED
@@ -2,6 +2,20 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Range = exports.SemverRange = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ /**
6
+ * 增強版 semver Range 類別
7
+ * Enhanced semver Range class
8
+ *
9
+ * 繼承 semver 的 Range,但刻意略過父層建構函式(super() 不帶參數),
10
+ * 改由 _inherit 自行正規化輸入,才能同時接受字串、Comparator、SemVer
11
+ * 與原生 Range 作為來源,並在搬移時保留原有的比較器集合以避免重複解析。
12
+ * Extends semver's Range but deliberately skips the parent constructor
13
+ * (`super()` takes no arguments), letting `_inherit` normalize the input so a
14
+ * string, Comparator, SemVer, or native Range can all serve as the source while
15
+ * an existing comparator set is carried over instead of re-parsed.
16
+ *
17
+ * @packageDocumentation
18
+ */
5
19
  const range_1 = tslib_1.__importDefault(require("semver/classes/range"));
6
20
  const handleAmpersandAndSpaces_1 = require("./handleAmpersandAndSpaces");
7
21
  const stringifyComparators_1 = require("./util/stringifyComparators");
@@ -15,26 +29,83 @@ const fixComparatorSet_1 = require("./range/fixComparatorSet");
15
29
  const parseOptionsOrLoose_1 = require("./internal/parseOptionsOrLoose");
16
30
  const split_1 = require("./util/split");
17
31
  const parseRange_1 = require("./range/parseRange");
32
+ /**
33
+ * SemverRange 類別(對外以 Range 匯出)
34
+ * The SemverRange class (exported as `Range`)
35
+ *
36
+ * 特點:來源可為多種型別、支援 ampersand 語法、可重用既有比較器集合。
37
+ * Highlights: accepts several source types, supports ampersand syntax, and
38
+ * can reuse an existing comparator set.
39
+ *
40
+ * @template RAW - 原始輸入的型別 / Type of the raw input
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * const range = new Range('>=1.0.0 & <2.0.0');
45
+ * range.test('1.5.0'); // true
46
+ * range.toString(); // '>=1.0.0 <2.0.0'
47
+ * ```
48
+ */
18
49
  class SemverRange extends (0, class_without_call_parent_constructor_1.classWithoutCallParentConstructor)(range_1.default) {
50
+ /**
51
+ * 建立 Range 實例
52
+ * Create a Range instance
53
+ *
54
+ * @param rawSource - 範圍來源(字串、Comparator、SemVer、原生 Range)/ Range source (string, Comparator, SemVer, native Range)
55
+ * @param optionsOrLoose - 選項或寬鬆旗標 / Options or loose flag
56
+ * @throws {TypeError} 當比較器集合為空(整個範圍無效)時 / When the comparator set is empty (the whole range is invalid)
57
+ */
19
58
  constructor(rawSource, optionsOrLoose) {
20
59
  // skip original semverRange constructor
21
60
  super();
61
+ // 統一選項格式,讓後續一律拿到物件形態的選項
62
+ // Normalize option shape so everything downstream sees an object
22
63
  optionsOrLoose = (0, parseOptionsOrLoose_1.parseOptionsOrLoose)(optionsOrLoose);
23
64
  let { range, options, set } = this._inherit(rawSource, optionsOrLoose);
65
+ /**
66
+ * 只有當正規化後的字串與呼叫端輸入不同時才記錄 rawSource,
67
+ * 否則保留 undefined,避免不必要的記憶體佔用。
68
+ * Record rawSource only when normalization changed the string;
69
+ * otherwise leave it undefined to avoid needless memory use.
70
+ */
24
71
  if (typeof rawSource === 'string' && range !== rawSource) {
25
72
  this.rawSource = rawSource;
26
73
  }
27
74
  this._inheritOptions(options);
75
+ /**
76
+ * 來源若已帶有比較器集合(例如搬移另一個 Range),
77
+ * 直接沿用,省下重新解析的成本。
78
+ * When the source already carries a comparator set (e.g. another
79
+ * Range being copied), reuse it instead of paying for a re-parse.
80
+ */
28
81
  if (!set) {
29
82
  set = this._buildComparatorsSet(range, options);
30
83
  }
31
84
  (0, assert_1.assertInvalidComparatorSet)(set, `Invalid SemVer Range: ${range}`);
85
+ // unsafeOptimize 才會真的做集合簡化,預設保持原樣以確保行為一致
86
+ // The set is only simplified under unsafeOptimize; by default it is kept
87
+ // as-is so behavior stays predictable
32
88
  set = (0, fixComparatorSet_1.fixComparatorSet)(set, options.unsafeOptimize);
33
89
  (0, assert_1.assertInvalidComparatorSet)(set);
34
90
  this.raw = range;
35
91
  this.set = set;
36
92
  this.format();
37
93
  }
94
+ /**
95
+ * 把範圍字串切成二維比較器集合
96
+ * Turn a range string into a two-dimensional comparator set
97
+ *
98
+ * 以 `||` 分割成多個集合,各集合再解析為比較器;
99
+ * 空集合會被過濾(loose 模式下允許個別條件無效),
100
+ * 但若整個範圍都無效,外層的 assert 仍會拋錯。
101
+ * Split on `||` into groups, then parse each group into comparators; empty
102
+ * groups are dropped (loose mode tolerates invalid individual conditions),
103
+ * while a wholly invalid range still throws at the outer assert.
104
+ *
105
+ * @param range - 範圍字串 / Range string
106
+ * @param options - 選項 / Options
107
+ * @returns 比較器集合 / Comparator set
108
+ */
38
109
  _buildComparatorsSet(range, options) {
39
110
  let comparatorsSet = (0, split_1.splitDoubleVerticalBar)(range)
40
111
  // map the range to a 2d array of comparators
@@ -45,9 +116,35 @@ class SemverRange extends (0, class_without_call_parent_constructor_1.classWitho
45
116
  .filter(c => c.length);
46
117
  return comparatorsSet;
47
118
  }
119
+ /**
120
+ * 解析單一(不含 `||`)的範圍字串
121
+ * Parse a single range string (without `||`)
122
+ *
123
+ * 這裡帶入 this.options,確保 ampersand 與空格的處理與建構時一致。
124
+ * Options are threaded through here so ampersand/space handling matches
125
+ * what the constructor did.
126
+ *
127
+ * @param range - 範圍字串 / Range string
128
+ * @returns 比較器陣列 / Comparator array
129
+ */
48
130
  parseRange(range) {
49
131
  return (0, parseRange_1.parseRange)(range, this.options);
50
132
  }
133
+ /**
134
+ * 從各種來源繼承範圍與選項
135
+ * Inherit range and options from any supported source
136
+ *
137
+ * 輸入為原生 semver Range 時:合併兩側選項,且僅在選項完全相同的情況下
138
+ * 直接沿用其 set;否則會重新解析(選項不同可能產生不同結果)。
139
+ * When the input is a native semver Range: options from both sides are
140
+ * merged, and its `set` is reused only when the merged options match
141
+ * exactly — otherwise it is re-parsed, since differing options can produce
142
+ * a different set.
143
+ *
144
+ * @param range - 範圍來源 / Range source
145
+ * @param options - 已正規化的選項 / Normalized options
146
+ * @returns 正規化後的 range、options 與(可能存在的)set / Normalized range, options, and (possibly) set
147
+ */
51
148
  _inherit(range, options) {
52
149
  let set;
53
150
  if (range instanceof range_1.default) {
@@ -58,11 +155,21 @@ class SemverRange extends (0, class_without_call_parent_constructor_1.classWitho
58
155
  ...options,
59
156
  };
60
157
  options = (0, options_1._normalizeOptions)(options);
158
+ // 選項一致才可安全搬移 set,否則可能與新選項不相符
159
+ // The set may only be moved when options agree, otherwise it might
160
+ // not match the new options
61
161
  if ((0, options_1._isSameOptions)(range, options)) {
62
162
  set = range.set;
63
163
  }
64
164
  range = range.raw;
65
165
  }
166
+ /**
167
+ * Comparator / SemVer 這兩種來源各自轉成可繼續解析的形態:
168
+ * Comparator 直接包成單元素集合,SemVer 則取其格式化字串。
169
+ * Comparator and SemVer sources are each converted into something
170
+ * parseable: a Comparator becomes a single-element set, a SemVer is
171
+ * reduced to its formatted string.
172
+ */
66
173
  if (range instanceof semver_2.Comparator) {
67
174
  set = [[range]];
68
175
  range = range.value;
@@ -70,10 +177,15 @@ class SemverRange extends (0, class_without_call_parent_constructor_1.classWitho
70
177
  else if (range instanceof semver_1.default) {
71
178
  range = range.format();
72
179
  }
180
+ // 有 set 但為空集合代表來源無效,提早拋錯避免帶到後續流程
181
+ // An existing-but-empty set means the source is invalid; fail fast
182
+ // instead of letting it travel further downstream
73
183
  if ((set === null || set === void 0 ? void 0 : set.length) === 0) {
74
184
  (0, assert_1.assertInvalidComparatorSet)(set);
75
185
  }
76
186
  options = (0, options_1._normalizeOptions)(options);
187
+ // 依選項決定是否把 & 視為「且」並整理空白
188
+ // Decide per options whether `&` means "AND" and tidy the whitespace
77
189
  range = (0, handleAmpersandAndSpaces_1.handleAmpersandAndSpaces)(range, options);
78
190
  return {
79
191
  range,
@@ -81,10 +193,30 @@ class SemverRange extends (0, class_without_call_parent_constructor_1.classWitho
81
193
  set,
82
194
  };
83
195
  }
196
+ /**
197
+ * 把選項同步到實例上
198
+ * Sync options onto the instance
199
+ *
200
+ * options 寫入父層欄位後,再以 _copyOptions 複製 loose / includePrerelease
201
+ * 兩個常用欄位,避免每次取值都要翻閱 options 物件。
202
+ * After writing `options` to the parent field, `_copyOptions` mirrors the
203
+ * frequently used `loose` / `includePrerelease` fields so readers do not
204
+ * have to dig into the options object.
205
+ *
206
+ * @param options - 已正規化的選項 / Normalized options
207
+ */
84
208
  _inheritOptions(options) {
85
209
  this.options = options;
86
210
  (0, options_1._copyOptions)(this, options);
87
211
  }
212
+ /**
213
+ * 取得格式化後的範圍字串
214
+ * Get the formatted range string
215
+ *
216
+ * 每次存取都從 set 重新組字串(而非取快取),因為 set 可能已被外部修改。
217
+ * The string is rebuilt from `set` on every access instead of being cached,
218
+ * because `set` may have been mutated externally.
219
+ */
88
220
  // @ts-ignore
89
221
  get range() {
90
222
  // @ts-ignore
@@ -97,6 +229,10 @@ class SemverRange extends (0, class_without_call_parent_constructor_1.classWitho
97
229
  // }
98
230
  /**
99
231
  * Return '*' instead of '' so that truthiness works.
232
+ *
233
+ * 回傳 `*` 而非空字串,可讓 `if (range.toRangeString())` 這類真值判斷成立。
234
+ * Returning `*` instead of an empty string keeps truthiness checks such as
235
+ * `if (range.toRangeString())` working.
100
236
  */
101
237
  toRangeString() {
102
238
  return (0, toRangeString_1.toRangeString)(this.range);
package/lib/Range.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Range.js","sourceRoot":"","sources":["Range.ts"],"names":[],"mappings":"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","sourcesContent":["import semverRange from 'semver/classes/range';\nimport { handleAmpersandAndSpaces } from './handleAmpersandAndSpaces';\nimport {\n\tIComparatorSet,\n\tIComparatorSetInput,\n\tIOptions,\n\tIOptionsOrLoose,\n\tISemverRangeInput,\n} from './types';\nimport { stringifyComparatorsSet } from './util/stringifyComparators';\nimport SemVer from 'semver/classes/semver';\nimport { classWithoutCallParentConstructor } from 'class-without-call-parent-constructor';\nimport { Comparator } from 'semver';\nimport { _copyOptions, _isSameOptions, _normalizeOptions } from './range/options';\nimport { toRangeString } from './range/toRangeString';\nimport { assertInvalidComparatorSet } from './util/assert';\nimport { fixComparatorSet } from './range/fixComparatorSet';\nimport { parseOptionsOrLoose } from './internal/parseOptionsOrLoose';\nimport { splitDoubleVerticalBar } from './util/split';\nimport { parseRange } from './range/parseRange';\n\nexport class SemverRange<RAW extends ISemverRangeInput> extends classWithoutCallParentConstructor(semverRange)\n{\n\treadonly rawSource?: RAW;\n\n\toverride readonly raw: string;\n\toverride readonly set: IComparatorSet;\n\n\toverride readonly options: IOptions;\n\toverride readonly loose: boolean;\n\toverride readonly includePrerelease: boolean;\n\n\tprotected readonly formatted: string;\n\n\tconstructor(rawSource: RAW, optionsOrLoose?: IOptionsOrLoose<IOptions>)\n\t{\n\t\t// skip original semverRange constructor\n\t\tsuper();\n\n\t\toptionsOrLoose = parseOptionsOrLoose(optionsOrLoose);\n\n\t\tlet { range, options, set } = this._inherit(rawSource, optionsOrLoose);\n\n\t\tif (typeof rawSource === 'string' && range !== rawSource)\n\t\t{\n\t\t\tthis.rawSource = rawSource;\n\t\t}\n\n\t\tthis._inheritOptions(options);\n\n\t\tif (!set)\n\t\t{\n\n\t\t\tset = this._buildComparatorsSet(range, options);\n\t\t}\n\n\t\tassertInvalidComparatorSet(set, `Invalid SemVer Range: ${range}`);\n\n\t\tset = fixComparatorSet(set, options.unsafeOptimize);\n\n\t\tassertInvalidComparatorSet(set);\n\n\t\tthis.raw = range;\n\t\tthis.set = set;\n\n\t\tthis.format()\n\t}\n\n\tprotected _buildComparatorsSet(range: string, options: IOptions): IComparatorSetInput\n\t{\n\t\tlet comparatorsSet = splitDoubleVerticalBar(range)\n\t\t\t// map the range to a 2d array of comparators\n\t\t\t.map(range => this.parseRange(range))\n\t\t\t// throw out any comparator lists that are empty\n\t\t\t// this generally means that it was not a valid range, which is allowed\n\t\t\t// in loose mode, but will still throw if the WHOLE range is invalid.\n\t\t\t.filter(c => c.length)\n\t\t;\n\n\t\treturn comparatorsSet\n\t}\n\n\toverride parseRange(range: string)\n\t{\n\t\treturn parseRange(range, this.options)\n\t}\n\n\tprotected _inherit(range: ISemverRangeInput, options: IOptions)\n\t{\n\t\tlet set: IComparatorSet;\n\n\t\tif (range instanceof semverRange)\n\t\t{\n\t\t\toptions = {\n\t\t\t\tloose: range.loose,\n\t\t\t\tincludePrerelease: range.includePrerelease,\n\t\t\t\t...range.options,\n\t\t\t\t...options,\n\t\t\t}\n\n\t\t\toptions = _normalizeOptions(options);\n\n\t\t\tif (_isSameOptions(range, options))\n\t\t\t{\n\t\t\t\tset = range.set;\n\t\t\t}\n\n\t\t\trange = range.raw;\n\t\t}\n\n\t\tif (range instanceof Comparator)\n\t\t{\n\t\t\tset = [[range]];\n\t\t\trange = range.value\n\t\t}\n\t\telse if (range instanceof SemVer)\n\t\t{\n\t\t\trange = range.format();\n\t\t}\n\n\t\tif (set?.length === 0)\n\t\t{\n\t\t\tassertInvalidComparatorSet(set);\n\t\t}\n\n\t\toptions = _normalizeOptions(options);\n\n\t\trange = handleAmpersandAndSpaces(range, options);\n\n\t\treturn {\n\t\t\trange,\n\t\t\toptions,\n\t\t\tset,\n\t\t}\n\t}\n\n\tprotected _inheritOptions(options: IOptions)\n\t{\n\t\t(this as any as semverRange).options = options;\n\t\t_copyOptions(this, options);\n\t}\n\n\t// @ts-ignore\n\toverride get range()\n\t{\n\t\t// @ts-ignore\n\t\tthis.formatted = stringifyComparatorsSet(this.set);\n\t\treturn this.formatted\n\t}\n\n//\toverride format()\n//\t{\n//\t\treturn this.range\n//\t}\n\n\t/**\n\t * Return '*' instead of '' so that truthiness works.\n\t */\n\ttoRangeString()\n\t{\n\t\treturn toRangeString(this.range)\n\t}\n\n}\n\nexport { SemverRange as Range }\n\nexport default SemverRange\n"]}
1
+ {"version":3,"file":"Range.js","sourceRoot":"","sources":["Range.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 增強版 semver Range 類別\n * Enhanced semver Range class\n *\n * 繼承 semver 的 Range,但刻意略過父層建構函式(super() 不帶參數),\n * 改由 _inherit 自行正規化輸入,才能同時接受字串、Comparator、SemVer\n * 與原生 Range 作為來源,並在搬移時保留原有的比較器集合以避免重複解析。\n * Extends semver's Range but deliberately skips the parent constructor\n * (`super()` takes no arguments), letting `_inherit` normalize the input so a\n * string, Comparator, SemVer, or native Range can all serve as the source while\n * an existing comparator set is carried over instead of re-parsed.\n *\n * @packageDocumentation\n */\nimport semverRange from 'semver/classes/range';\nimport { handleAmpersandAndSpaces } from './handleAmpersandAndSpaces';\nimport {\n\tIComparatorSet,\n\tIComparatorSetInput,\n\tIOptions,\n\tIOptionsOrLoose,\n\tISemverRangeInput,\n} from './types';\nimport { stringifyComparatorsSet } from './util/stringifyComparators';\nimport SemVer from 'semver/classes/semver';\nimport { classWithoutCallParentConstructor } from 'class-without-call-parent-constructor';\nimport { Comparator } from 'semver';\nimport { _copyOptions, _isSameOptions, _normalizeOptions } from './range/options';\nimport { toRangeString } from './range/toRangeString';\nimport { assertInvalidComparatorSet } from './util/assert';\nimport { fixComparatorSet } from './range/fixComparatorSet';\nimport { parseOptionsOrLoose } from './internal/parseOptionsOrLoose';\nimport { splitDoubleVerticalBar } from './util/split';\nimport { parseRange } from './range/parseRange';\n\n/**\n * SemverRange 類別(對外以 Range 匯出)\n * The SemverRange class (exported as `Range`)\n *\n * 特點:來源可為多種型別、支援 ampersand 語法、可重用既有比較器集合。\n * Highlights: accepts several source types, supports ampersand syntax, and\n * can reuse an existing comparator set.\n *\n * @template RAW - 原始輸入的型別 / Type of the raw input\n *\n * @example\n * ```typescript\n * const range = new Range('>=1.0.0 & <2.0.0');\n * range.test('1.5.0'); // true\n * range.toString(); // '>=1.0.0 <2.0.0'\n * ```\n */\nexport class SemverRange<RAW extends ISemverRangeInput> extends classWithoutCallParentConstructor(semverRange)\n{\n\t/** 呼叫端傳入的原始值,保留供除錯 / The original value passed in, kept for debugging */\n\treadonly rawSource?: RAW;\n\n\t/** 規範化後的範圍字串 / Normalized range string */\n\toverride readonly raw: string;\n\n\t/** 二維比較器集合(外層為 `||` 分隔的集合)/ Two-dimensional comparator set (outer level = `||` groups) */\n\toverride readonly set: IComparatorSet;\n\n\t/** 解析後的選項 / Normalized options */\n\toverride readonly options: IOptions;\n\n\t/** 是否為寬鬆模式 / Whether loose mode is on */\n\toverride readonly loose: boolean;\n\n\t/** 是否納入預發布版本 / Whether pre-releases are included */\n\toverride readonly includePrerelease: boolean;\n\n\t/** 快取的格式化結果,由 range getter 每次重算後寫入 / Cached formatted result, rewritten by the `range` getter on every access */\n\tprotected readonly formatted: string;\n\n\t/**\n\t * 建立 Range 實例\n\t * Create a Range instance\n\t *\n\t * @param rawSource - 範圍來源(字串、Comparator、SemVer、原生 Range)/ Range source (string, Comparator, SemVer, native Range)\n\t * @param optionsOrLoose - 選項或寬鬆旗標 / Options or loose flag\n\t * @throws {TypeError} 當比較器集合為空(整個範圍無效)時 / When the comparator set is empty (the whole range is invalid)\n\t */\n\tconstructor(rawSource: RAW, optionsOrLoose?: IOptionsOrLoose<IOptions>)\n\t{\n\t\t// skip original semverRange constructor\n\t\tsuper();\n\n\t\t// 統一選項格式,讓後續一律拿到物件形態的選項\n\t\t// Normalize option shape so everything downstream sees an object\n\t\toptionsOrLoose = parseOptionsOrLoose(optionsOrLoose);\n\n\t\tlet { range, options, set } = this._inherit(rawSource, optionsOrLoose);\n\n\t\t/**\n\t\t * 只有當正規化後的字串與呼叫端輸入不同時才記錄 rawSource,\n\t\t * 否則保留 undefined,避免不必要的記憶體佔用。\n\t\t * Record rawSource only when normalization changed the string;\n\t\t * otherwise leave it undefined to avoid needless memory use.\n\t\t */\n\t\tif (typeof rawSource === 'string' && range !== rawSource)\n\t\t{\n\t\t\tthis.rawSource = rawSource;\n\t\t}\n\n\t\tthis._inheritOptions(options);\n\n\t\t/**\n\t\t * 來源若已帶有比較器集合(例如搬移另一個 Range),\n\t\t * 直接沿用,省下重新解析的成本。\n\t\t * When the source already carries a comparator set (e.g. another\n\t\t * Range being copied), reuse it instead of paying for a re-parse.\n\t\t */\n\t\tif (!set)\n\t\t{\n\n\t\t\tset = this._buildComparatorsSet(range, options);\n\t\t}\n\n\t\tassertInvalidComparatorSet(set, `Invalid SemVer Range: ${range}`);\n\n\t\t// unsafeOptimize 才會真的做集合簡化,預設保持原樣以確保行為一致\n\t\t// The set is only simplified under unsafeOptimize; by default it is kept\n\t\t// as-is so behavior stays predictable\n\t\tset = fixComparatorSet(set, options.unsafeOptimize);\n\n\t\tassertInvalidComparatorSet(set);\n\n\t\tthis.raw = range;\n\t\tthis.set = set;\n\n\t\tthis.format()\n\t}\n\n\t/**\n\t * 把範圍字串切成二維比較器集合\n\t * Turn a range string into a two-dimensional comparator set\n\t *\n\t * 以 `||` 分割成多個集合,各集合再解析為比較器;\n\t * 空集合會被過濾(loose 模式下允許個別條件無效),\n\t * 但若整個範圍都無效,外層的 assert 仍會拋錯。\n\t * Split on `||` into groups, then parse each group into comparators; empty\n\t * groups are dropped (loose mode tolerates invalid individual conditions),\n\t * while a wholly invalid range still throws at the outer assert.\n\t *\n\t * @param range - 範圍字串 / Range string\n\t * @param options - 選項 / Options\n\t * @returns 比較器集合 / Comparator set\n\t */\n\tprotected _buildComparatorsSet(range: string, options: IOptions): IComparatorSetInput\n\t{\n\t\tlet comparatorsSet = splitDoubleVerticalBar(range)\n\t\t\t// map the range to a 2d array of comparators\n\t\t\t.map(range => this.parseRange(range))\n\t\t\t// throw out any comparator lists that are empty\n\t\t\t// this generally means that it was not a valid range, which is allowed\n\t\t\t// in loose mode, but will still throw if the WHOLE range is invalid.\n\t\t\t.filter(c => c.length)\n\t\t;\n\n\t\treturn comparatorsSet\n\t}\n\n\t/**\n\t * 解析單一(不含 `||`)的範圍字串\n\t * Parse a single range string (without `||`)\n\t *\n\t * 這裡帶入 this.options,確保 ampersand 與空格的處理與建構時一致。\n\t * Options are threaded through here so ampersand/space handling matches\n\t * what the constructor did.\n\t *\n\t * @param range - 範圍字串 / Range string\n\t * @returns 比較器陣列 / Comparator array\n\t */\n\toverride parseRange(range: string)\n\t{\n\t\treturn parseRange(range, this.options)\n\t}\n\n\t/**\n\t * 從各種來源繼承範圍與選項\n\t * Inherit range and options from any supported source\n\t *\n\t * 輸入為原生 semver Range 時:合併兩側選項,且僅在選項完全相同的情況下\n\t * 直接沿用其 set;否則會重新解析(選項不同可能產生不同結果)。\n\t * When the input is a native semver Range: options from both sides are\n\t * merged, and its `set` is reused only when the merged options match\n\t * exactly — otherwise it is re-parsed, since differing options can produce\n\t * a different set.\n\t *\n\t * @param range - 範圍來源 / Range source\n\t * @param options - 已正規化的選項 / Normalized options\n\t * @returns 正規化後的 range、options 與(可能存在的)set / Normalized range, options, and (possibly) set\n\t */\n\tprotected _inherit(range: ISemverRangeInput, options: IOptions)\n\t{\n\t\tlet set: IComparatorSet;\n\n\t\tif (range instanceof semverRange)\n\t\t{\n\t\t\toptions = {\n\t\t\t\tloose: range.loose,\n\t\t\t\tincludePrerelease: range.includePrerelease,\n\t\t\t\t...range.options,\n\t\t\t\t...options,\n\t\t\t}\n\n\t\t\toptions = _normalizeOptions(options);\n\n\t\t\t// 選項一致才可安全搬移 set,否則可能與新選項不相符\n\t\t\t// The set may only be moved when options agree, otherwise it might\n\t\t\t// not match the new options\n\t\t\tif (_isSameOptions(range, options))\n\t\t\t{\n\t\t\t\tset = range.set;\n\t\t\t}\n\n\t\t\trange = range.raw;\n\t\t}\n\n\t\t/**\n\t\t * Comparator / SemVer 這兩種來源各自轉成可繼續解析的形態:\n\t\t * Comparator 直接包成單元素集合,SemVer 則取其格式化字串。\n\t\t * Comparator and SemVer sources are each converted into something\n\t\t * parseable: a Comparator becomes a single-element set, a SemVer is\n\t\t * reduced to its formatted string.\n\t\t */\n\t\tif (range instanceof Comparator)\n\t\t{\n\t\t\tset = [[range]];\n\t\t\trange = range.value\n\t\t}\n\t\telse if (range instanceof SemVer)\n\t\t{\n\t\t\trange = range.format();\n\t\t}\n\n\t\t// 有 set 但為空集合代表來源無效,提早拋錯避免帶到後續流程\n\t\t// An existing-but-empty set means the source is invalid; fail fast\n\t\t// instead of letting it travel further downstream\n\t\tif (set?.length === 0)\n\t\t{\n\t\t\tassertInvalidComparatorSet(set);\n\t\t}\n\n\t\toptions = _normalizeOptions(options);\n\n\t\t// 依選項決定是否把 & 視為「且」並整理空白\n\t\t// Decide per options whether `&` means \"AND\" and tidy the whitespace\n\t\trange = handleAmpersandAndSpaces(range, options);\n\n\t\treturn {\n\t\t\trange,\n\t\t\toptions,\n\t\t\tset,\n\t\t}\n\t}\n\n\t/**\n\t * 把選項同步到實例上\n\t * Sync options onto the instance\n\t *\n\t * options 寫入父層欄位後,再以 _copyOptions 複製 loose / includePrerelease\n\t * 兩個常用欄位,避免每次取值都要翻閱 options 物件。\n\t * After writing `options` to the parent field, `_copyOptions` mirrors the\n\t * frequently used `loose` / `includePrerelease` fields so readers do not\n\t * have to dig into the options object.\n\t *\n\t * @param options - 已正規化的選項 / Normalized options\n\t */\n\tprotected _inheritOptions(options: IOptions)\n\t{\n\t\t(this as any as semverRange).options = options;\n\t\t_copyOptions(this, options);\n\t}\n\n\t/**\n\t * 取得格式化後的範圍字串\n\t * Get the formatted range string\n\t *\n\t * 每次存取都從 set 重新組字串(而非取快取),因為 set 可能已被外部修改。\n\t * The string is rebuilt from `set` on every access instead of being cached,\n\t * because `set` may have been mutated externally.\n\t */\n\t// @ts-ignore\n\toverride get range()\n\t{\n\t\t// @ts-ignore\n\t\tthis.formatted = stringifyComparatorsSet(this.set);\n\t\treturn this.formatted\n\t}\n\n//\toverride format()\n//\t{\n//\t\treturn this.range\n//\t}\n\n\t/**\n\t * Return '*' instead of '' so that truthiness works.\n\t *\n\t * 回傳 `*` 而非空字串,可讓 `if (range.toRangeString())` 這類真值判斷成立。\n\t * Returning `*` instead of an empty string keeps truthiness checks such as\n\t * `if (range.toRangeString())` working.\n\t */\n\ttoRangeString()\n\t{\n\t\treturn toRangeString(this.range)\n\t}\n\n}\n\nexport { SemverRange as Range }\n\nexport default SemverRange\n"]}
@@ -1,7 +1,21 @@
1
1
  import Comparator from 'semver/classes/comparator';
2
+ /**
3
+ * 是否為 Null Set(<0.0.0-0,代表沒有任何版本符合)
4
+ * Whether it is a null set (<0.0.0-0, nothing can match)
5
+ *
6
+ * @param c - 比較器 / Comparator
7
+ * @returns 是否為 Null Set / Whether it is a null set
8
+ */
2
9
  export declare function isNullSet<T extends Comparator>(c: T): c is T & {
3
10
  value: '<0.0.0-0';
4
11
  };
12
+ /**
13
+ * 是否為任意版本比較器(`*`,值為空字串)
14
+ * Whether it is an "any" comparator (`*`, empty-string value)
15
+ *
16
+ * @param c - 比較器 / Comparator
17
+ * @returns 是否為任意版本 / Whether it matches any version
18
+ */
5
19
  export declare function isAny<T extends Comparator>(c: T): c is T & {
6
20
  value: '';
7
21
  };
@@ -2,9 +2,23 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isNullSet = isNullSet;
4
4
  exports.isAny = isAny;
5
+ /**
6
+ * 是否為 Null Set(<0.0.0-0,代表沒有任何版本符合)
7
+ * Whether it is a null set (<0.0.0-0, nothing can match)
8
+ *
9
+ * @param c - 比較器 / Comparator
10
+ * @returns 是否為 Null Set / Whether it is a null set
11
+ */
5
12
  function isNullSet(c) {
6
13
  return c.value === "<0.0.0-0" /* EnumSemverVersion.NULL */;
7
14
  }
15
+ /**
16
+ * 是否為任意版本比較器(`*`,值為空字串)
17
+ * Whether it is an "any" comparator (`*`, empty-string value)
18
+ *
19
+ * @param c - 比較器 / Comparator
20
+ * @returns 是否為任意版本 / Whether it matches any version
21
+ */
8
22
  function isAny(c) {
9
23
  return c.value === "" /* EnumSemverVersion.ANY */;
10
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"detect.js","sourceRoot":"","sources":["detect.ts"],"names":[],"mappings":";;AAGA,8BAKC;AAED,sBAKC;AAZD,SAAgB,SAAS,CAAuB,CAAI;IAInD,OAAO,CAAC,CAAC,KAAK,4CAA2B,CAAC;AAC3C,CAAC;AAED,SAAgB,KAAK,CAAuB,CAAI;IAI/C,OAAO,CAAC,CAAC,KAAK,mCAA0B,CAAC;AAC1C,CAAC","sourcesContent":["import Comparator from 'semver/classes/comparator';\nimport { EnumSemverVersion } from '../const';\n\nexport function isNullSet<T extends Comparator>(c: T): c is T & {\n\tvalue: '<0.0.0-0'\n}\n{\n\treturn c.value === EnumSemverVersion.NULL;\n}\n\nexport function isAny<T extends Comparator>(c: T): c is T & {\n\tvalue: ''\n}\n{\n\treturn c.value === EnumSemverVersion.ANY;\n}\n"]}
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["detect.ts"],"names":[],"mappings":";;AAUA,8BAKC;AASD,sBAKC;AA1BD;;;;;;GAMG;AACH,SAAgB,SAAS,CAAuB,CAAI;IAInD,OAAO,CAAC,CAAC,KAAK,4CAA2B,CAAC;AAC3C,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,KAAK,CAAuB,CAAI;IAI/C,OAAO,CAAC,CAAC,KAAK,mCAA0B,CAAC;AAC1C,CAAC","sourcesContent":["import Comparator from 'semver/classes/comparator';\nimport { EnumSemverVersion } from '../const';\n\n/**\n * 是否為 Null Set(<0.0.0-0,代表沒有任何版本符合)\n * Whether it is a null set (<0.0.0-0, nothing can match)\n *\n * @param c - 比較器 / Comparator\n * @returns 是否為 Null Set / Whether it is a null set\n */\nexport function isNullSet<T extends Comparator>(c: T): c is T & {\n\tvalue: '<0.0.0-0'\n}\n{\n\treturn c.value === EnumSemverVersion.NULL;\n}\n\n/**\n * 是否為任意版本比較器(`*`,值為空字串)\n * Whether it is an \"any\" comparator (`*`, empty-string value)\n *\n * @param c - 比較器 / Comparator\n * @returns 是否為任意版本 / Whether it matches any version\n */\nexport function isAny<T extends Comparator>(c: T): c is T & {\n\tvalue: ''\n}\n{\n\treturn c.value === EnumSemverVersion.ANY;\n}\n"]}