@yarn-tool/detect-package-manager 1.0.9 → 1.0.11

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/CHANGELOG.md CHANGED
@@ -3,6 +3,64 @@
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
+ ## [1.0.11](https://github.com/bluelovers/ws-yarn-workspaces/compare/@yarn-tool/detect-package-manager@1.0.10...@yarn-tool/detect-package-manager@1.0.11) (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
+ * **snap:** update snapshots ([c9945a5](https://github.com/bluelovers/ws-yarn-workspaces/commit/c9945a5b9cd723d38ded2a69b83e2e83ecc3b524))
18
+ * **test:** 將測試框架從 jest 遷移至 node:test ([3af9774](https://github.com/bluelovers/ws-yarn-workspaces/commit/3af9774964abc48083ec60b2021c1cec08874803))
19
+
20
+
21
+ ### 🛠 Build System
22
+
23
+ * update build ([3186340](https://github.com/bluelovers/ws-yarn-workspaces/commit/3186340758172427cb1e9b8955f6fd677abac625))
24
+ * **deps:** 更新測試腳本與依賴以支援 node:test ([f9c71c7](https://github.com/bluelovers/ws-yarn-workspaces/commit/f9c71c795c792c5c7ed9d613ce7e9c3c726c39d5))
25
+
26
+
27
+ ### ♻️ Chores
28
+
29
+ * **workspace:** 更新測試指令路徑與新增工作區搜尋選項 ([a80039d](https://github.com/bluelovers/ws-yarn-workspaces/commit/a80039dd8c691e047466966ffc8f8a4e2e31c03f))
30
+
31
+
32
+ ### 🔖 Miscellaneous
33
+
34
+ * . ([e5788f8](https://github.com/bluelovers/ws-yarn-workspaces/commit/e5788f84551b870490a96d0a5d67d8d542481373))
35
+
36
+
37
+
38
+ ## [1.0.10](https://github.com/bluelovers/ws-yarn-workspaces/compare/@yarn-tool/detect-package-manager@1.0.9...@yarn-tool/detect-package-manager@1.0.10) (2026-09-06)
39
+
40
+
41
+
42
+ ### 🚨 Tests
43
+
44
+ * **@yarn-tool/detect-package-manager:** 將測試驗證方式從 snapshot 改為內容比對 ([ee6f231](https://github.com/bluelovers/ws-yarn-workspaces/commit/ee6f2311f1caa4ffac16ca7c8069a4f31fb4ef09))
45
+ * **tests:** 新增與更新多個套件的單元測試快照 ([11628a4](https://github.com/bluelovers/ws-yarn-workspaces/commit/11628a47aa48be30829cf615a52d7b2b1b273d43))
46
+
47
+
48
+ ### 🛠 Build System
49
+
50
+ * update Static Files ([b2f5d72](https://github.com/bluelovers/ws-yarn-workspaces/commit/b2f5d7216773c53eb35f267ba34f8788543d46a1))
51
+
52
+
53
+ ### ♻️ Chores
54
+
55
+ * **workspace:** 將所有套件的指令從 yarn 改為 pnpm 並更新依賴版本 ([0505892](https://github.com/bluelovers/ws-yarn-workspaces/commit/0505892e5e7c356f8cf59495fefda1aa681499c6))
56
+
57
+
58
+ ### 🔖 Miscellaneous
59
+
60
+ * . ([b545589](https://github.com/bluelovers/ws-yarn-workspaces/commit/b54558925d67304019e2b4f9bb3c4671c429a96e))
61
+
62
+
63
+
6
64
  ## [1.0.9](https://github.com/bluelovers/ws-yarn-workspaces/compare/@yarn-tool/detect-package-manager@1.0.8...@yarn-tool/detect-package-manager@1.0.9) (2026-04-26)
7
65
 
8
66
 
package/README.md CHANGED
@@ -54,7 +54,7 @@ _runtime 選項輸入類型 - 可接受布林值或 IOptionsWhichPackageManager
54
54
  type IRuntimeOptionInput = boolean | IOptionsWhichPackageManager;
55
55
  ```
56
56
 
57
- ## API (API)
57
+ ## API 文件 (API Documentation)
58
58
 
59
59
  ### whichPackageManagerSync(npmClients?: IPackageManager[], returnDefaultOrOptions?: IRuntimeOptionInput): IPackageManager | undefined
60
60
 
@@ -116,6 +116,19 @@ type IRuntimeOptionInput = boolean | IOptionsWhichPackageManager;
116
116
 
117
117
  **回傳 (Returns):** AsyncGenerator yields `[packageManager, commandPath]` tuples
118
118
 
119
+ ## 組態設定 (Configuration)
120
+
121
+ 所有偵測函式共用同一組選項,可透過 `IRuntimeOptionInput`(布林值或 `IOptionsWhichPackageManager` 物件)傳入:
122
+
123
+ | 選項 (Option) | 型別 (Type) | 預設值 (Default) | 說明 (Description) |
124
+ | --- | --- | --- | --- |
125
+ | `returnDefault` | `boolean` | `false` | 找不到任何套件管理器時,是否回傳優先順序中的第一個作為預設值 / Whether to return the first entry of the priority order as fallback when none is found |
126
+ | `noUseDefaultClients` | `boolean` | `false` | 只使用使用者指定的套件管理器,不合併預設優先順序 / Only use user-specified package managers; do not merge the default priority order |
127
+
128
+ - 預設優先順序 (Default priority):`pnpm` → `yarn` → `npm`
129
+ - 直接傳入 `true` 等同於 `{ returnDefault: true }` / Passing `true` directly is equivalent to `{ returnDefault: true }`
130
+ - 若完全未指定套件管理器列表,則依預設優先順序檢查 / When no package manager list is given, detection follows the default priority order
131
+
119
132
  ## 安裝 (Installation)
120
133
 
121
134
  ```bash
@@ -134,7 +147,9 @@ pnpm add @yarn-tool/detect-package-manager
134
147
  npm install @yarn-tool/detect-package-manager
135
148
  ```
136
149
 
137
- ## 範例 (Examples)
150
+ ## 用法 (Usage)
151
+
152
+ 以下範例展示常見的使用方式 (The following examples show common usage):
138
153
 
139
154
  ```typescript
140
155
  import {
package/index.d.ts CHANGED
@@ -13,6 +13,12 @@ export declare const enum EnumPackageManager {
13
13
  * Supported package manager types
14
14
  */
15
15
  export type IPackageManager = ITSTypeAndStringLiteral<EnumPackageManager>;
16
+ /**
17
+ * 支援的套件管理器型別,並允許擴充額外的自訂字串
18
+ * Supported package manager type, extended with extra custom string literals
19
+ *
20
+ * @typeParam T - 額外允許的自訂型別 / Additional custom literal type allowed
21
+ */
16
22
  export type IPackageManager2<T extends string> = IPackageManager | T;
17
23
  /**
18
24
  * 偵測結果類型 - 包含套件管理器名稱和命令路徑
@@ -80,13 +86,6 @@ export declare function handleOptionsWhichPackageManager<T extends string = IPac
80
86
  * Merge user-specified priority with default order
81
87
  */
82
88
  export declare function _handleClientsToCheck<T extends string = IPackageManager>(npmClients?: ITSArrayListMaybeReadonly<T> | undefined, options?: IOptionsWhichPackageManager): readonly IPackageManager2<T>[];
83
- /**
84
- * 使用 which 依序檢查套件管理器列表,返回第一個可用的
85
- * Sequentially check package managers using which, return the first available one
86
- *
87
- * @param npmClients - 套件管理器列表 / Package manager list
88
- * @returns 可用的套件管理器名稱 / Available package manager name
89
- */
90
89
  /**
91
90
  * 非同步生成器 - 使用 which 依序檢查套件管理器列表
92
91
  * Async generator - sequentially check package managers using which
@@ -122,13 +121,6 @@ export declare function whichPackageManagerAsync(npmClients?: ITSArrayListMaybeR
122
121
  * @returns 所有可用的套件管理器陣列 / Array of all available package managers
123
122
  */
124
123
  export declare function whichPackageManagerAsyncAll(npmClients?: ITSArrayListMaybeReadonly<IPackageManager> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): Promise<IPackageManager[]>;
125
- /**
126
- * 使用 which 依序檢查套件管理器列表,以同步生成器方式 yield 所有可用的套件管理器
127
- * Sequentially check package managers using which, yield all available package managers via sync generator
128
- *
129
- * @param npmClients - 套件管理器列表 / Package manager list
130
- * @returns 可用的套件管理器(透過 yield)/ Available package manager (via yield)
131
- */
132
124
  /**
133
125
  * 同步生成器 - 使用 which 依序檢查套件管理器列表
134
126
  * Sync generator - sequentially check package managers using which
@@ -164,4 +156,8 @@ export declare function whichPackageManagerSyncAll(npmClients?: ITSArrayListMayb
164
156
  * @returns 可用的套件管理器名稱 / Available package manager name
165
157
  */
166
158
  export declare function whichPackageManagerSync(npmClients?: ITSArrayListMaybeReadonly<IPackageManager> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): IPackageManager;
159
+ /**
160
+ * 預設匯出:同步偵測第一個可用的套件管理器
161
+ * Default export: synchronously detect the first available package manager
162
+ */
167
163
  export default whichPackageManagerSync;
package/index.js CHANGED
@@ -46,10 +46,22 @@ const _whichOptions = {
46
46
  */
47
47
  function _handleOptionsWhichPackageManagerCore(returnDefaultOrOptions) {
48
48
  if (typeof returnDefaultOrOptions === 'boolean') {
49
+ /**
50
+ * 布林值是 `returnDefault` 的簡寫形式,
51
+ * 正規化成物件後,後續程式只需處理單一型別
52
+ * A boolean is shorthand for `returnDefault`;
53
+ * normalizing to an object keeps downstream code single-typed
54
+ */
49
55
  returnDefaultOrOptions = {
50
56
  returnDefault: returnDefaultOrOptions,
51
57
  };
52
58
  }
59
+ /**
60
+ * 未傳入任何選項時以空物件代替 undefined,
61
+ * 讓呼叫端不必額外處理 null/undefined 分支
62
+ * When no option is given, return an empty object instead of undefined
63
+ * so callers never have to handle a null/undefined branch
64
+ */
53
65
  return returnDefaultOrOptions !== null && returnDefaultOrOptions !== void 0 ? returnDefaultOrOptions : {};
54
66
  }
55
67
  /**
@@ -81,21 +93,30 @@ function _handleClientsToCheck(npmClients, options) {
81
93
  * Merge user-specified priority with default order
82
94
  */
83
95
  if (npmClients === null || npmClients === void 0 ? void 0 : npmClients.length) {
84
- // 過濾不合法的名稱
96
+ /**
97
+ * 過濾不合法的名稱(空字串或 undefined)
98
+ * Filter out invalid names (empty string or undefined)
99
+ */
85
100
  npmClients = npmClients.filter(v => v === null || v === void 0 ? void 0 : v.length);
101
+ /**
102
+ * `noUseDefaultClients` 時只保留使用者清單,否則追加預設順序;
103
+ * 以 Set 去重,避免使用者重複指定同一個套件管理器時重複檢查
104
+ * With `noUseDefaultClients` only the user list is kept, otherwise the
105
+ * default order is appended; Set de-duplicates so an entry specified
106
+ * twice by the user is not checked twice
107
+ */
86
108
  return (options === null || options === void 0 ? void 0 : options.noUseDefaultClients)
87
109
  ? [...new Set([...npmClients])]
88
110
  : [...new Set([...npmClients, ...defaultClients])];
89
111
  }
112
+ /**
113
+ * 使用者未指定任何套件管理器(或清單經篩選後為空)時,
114
+ * 直接以預設優先順序作為檢查清單
115
+ * When the user specified nothing (or the list became empty after filtering),
116
+ * fall back to the default priority order as the check list
117
+ */
90
118
  return [...defaultClients];
91
119
  }
92
- /**
93
- * 使用 which 依序檢查套件管理器列表,返回第一個可用的
94
- * Sequentially check package managers using which, return the first available one
95
- *
96
- * @param npmClients - 套件管理器列表 / Package manager list
97
- * @returns 可用的套件管理器名稱 / Available package manager name
98
- */
99
120
  /**
100
121
  * 非同步生成器 - 使用 which 依序檢查套件管理器列表
101
122
  * Async generator - sequentially check package managers using which
@@ -119,18 +140,40 @@ async function* _whichPackageManagerAsyncGenerator(npmClients, returnDefaultOrOp
119
140
  * @yield - 可用的套件管理器元組 [名稱, 路徑] / Available package manager tuple [name, path]
120
141
  */
121
142
  async function* _whichAsyncGeneratorCore(clientsToCheck, options) {
143
+ /**
144
+ * 追蹤是否會有任何套件管理器被找到,
145
+ * 供最後判斷是否需要回傳預設值
146
+ * Tracks whether any package manager was found,
147
+ * used at the end to decide if the default should be returned
148
+ */
122
149
  let notFound = true;
123
150
  /**
124
151
  * 依序檢查每個套件管理器是否可用
125
152
  * Check each package manager sequentially for availability
126
153
  */
127
154
  for (const client of clientsToCheck) {
155
+ /**
156
+ * `nothrow: true` 使找不到命令時回傳 null 而非丟出例外,
157
+ * `.catch(() => null)` 則涵蓋其他非預期錯誤,讓檢查能繼續下一個候選者
158
+ * `nothrow: true` makes a missing command resolve to null instead of throwing,
159
+ * and `.catch(() => null)` swallows unexpected errors so checking continues to the next candidate
160
+ */
128
161
  const commandPath = await (0, which_1.default)(client, _whichOptions).catch(() => null);
162
+ /**
163
+ * 只有找到可執行檔時才 yield,避免把不存在的套件管理器當成可用結果
164
+ * Only yield when the executable exists, so missing package managers are never reported as available
165
+ */
129
166
  if (commandPath) {
130
167
  yield [client, commandPath];
131
168
  notFound = false;
132
169
  }
133
170
  }
171
+ /**
172
+ * 全部都找不到時,若允許回傳預設值,
173
+ * 則以檢查清單的第一個作為回報(即使它並未安裝)
174
+ * When nothing was found, if defaults are allowed, report the first
175
+ * entry of the check list (even if it is not installed)
176
+ */
134
177
  if (options.returnDefault && notFound)
135
178
  return [clientsToCheck[0]];
136
179
  }
@@ -142,6 +185,12 @@ async function* _whichAsyncGeneratorCore(clientsToCheck, options) {
142
185
  * @returns 可用的套件管理器名稱 / Available package manager name
143
186
  */
144
187
  async function whichPackageManagerAsync(npmClients, returnDefaultOrOptions) {
188
+ /**
189
+ * 只取生成器第一次 yield 的結果,
190
+ * 找不到時 `next.value` 為 undefined,回傳 undefined
191
+ * Take only the first value yielded by the generator;
192
+ * when nothing is found `next.value` is undefined, so undefined is returned
193
+ */
145
194
  return _whichPackageManagerAsyncGenerator(npmClients, returnDefaultOrOptions).next().then(next => { var _a; return (_a = next.value) === null || _a === void 0 ? void 0 : _a[0]; });
146
195
  }
147
196
  /**
@@ -153,18 +202,15 @@ async function whichPackageManagerAsync(npmClients, returnDefaultOrOptions) {
153
202
  */
154
203
  async function whichPackageManagerAsyncAll(npmClients, returnDefaultOrOptions) {
155
204
  const result = [];
205
+ /**
206
+ * 逐一收集生成器 yield 的結果,只保留名稱、捨棄路徑
207
+ * Collect each value yielded by the generator, keeping only the name and discarding the path
208
+ */
156
209
  for await (const client of _whichPackageManagerAsyncGenerator(npmClients, returnDefaultOrOptions)) {
157
210
  result.push(client[0]);
158
211
  }
159
212
  return result;
160
213
  }
161
- /**
162
- * 使用 which 依序檢查套件管理器列表,以同步生成器方式 yield 所有可用的套件管理器
163
- * Sequentially check package managers using which, yield all available package managers via sync generator
164
- *
165
- * @param npmClients - 套件管理器列表 / Package manager list
166
- * @returns 可用的套件管理器(透過 yield)/ Available package manager (via yield)
167
- */
168
214
  /**
169
215
  * 同步生成器 - 使用 which 依序檢查套件管理器列表
170
216
  * Sync generator - sequentially check package managers using which
@@ -188,18 +234,40 @@ function* _whichPackageManagerSyncGenerator(npmClients, returnDefaultOrOptions)
188
234
  * @yield - 可用的套件管理器元組 [名稱, 路徑] / Available package manager tuple [name, path]
189
235
  */
190
236
  function* _whichSyncGeneratorCore(clientsToCheck, options) {
237
+ /**
238
+ * 追蹤是否會有任何套件管理器被找到,
239
+ * 供最後判斷是否需要回傳預設值
240
+ * Tracks whether any package manager was found,
241
+ * used at the end to decide if the default should be returned
242
+ */
191
243
  let notFound = true;
192
244
  /**
193
245
  * 依序檢查每個套件管理器是否可用
194
246
  * Check each package manager sequentially for availability
195
247
  */
196
248
  for (const client of clientsToCheck) {
249
+ /**
250
+ * `nothrow: true` 使找不到命令時回傳 null 而非丟出例外,
251
+ * 因此可直接以 truthy 判斷是否找到可執行檔
252
+ * `nothrow: true` makes a missing command return null instead of throwing,
253
+ * so a simple truthy check tells us whether the executable was found
254
+ */
197
255
  const commandPath = (0, which_1.sync)(client, _whichOptions);
256
+ /**
257
+ * 只有找到可執行檔時才 yield,避免把不存在的套件管理器當成可用結果
258
+ * Only yield when the executable exists, so missing package managers are never reported as available
259
+ */
198
260
  if (commandPath) {
199
261
  yield [client, commandPath];
200
262
  notFound = false;
201
263
  }
202
264
  }
265
+ /**
266
+ * 全部都找不到時,若允許回傳預設值,
267
+ * 則以檢查清單的第一個作為回報(即使它並未安裝)
268
+ * When nothing was found, if defaults are allowed, report the first
269
+ * entry of the check list (even if it is not installed)
270
+ */
203
271
  if (options.returnDefault && notFound)
204
272
  return [clientsToCheck[0]];
205
273
  }
@@ -212,6 +280,10 @@ function* _whichSyncGeneratorCore(clientsToCheck, options) {
212
280
  */
213
281
  function whichPackageManagerSyncAll(npmClients, returnDefaultOrOptions) {
214
282
  const result = [];
283
+ /**
284
+ * 逐一收集生成器 yield 的結果,只保留名稱、捨棄路徑
285
+ * Collect each value yielded by the generator, keeping only the name and discarding the path
286
+ */
215
287
  for (const client of _whichPackageManagerSyncGenerator(npmClients, returnDefaultOrOptions)) {
216
288
  result.push(client[0]);
217
289
  }
@@ -226,7 +298,17 @@ function whichPackageManagerSyncAll(npmClients, returnDefaultOrOptions) {
226
298
  */
227
299
  function whichPackageManagerSync(npmClients, returnDefaultOrOptions) {
228
300
  var _a;
301
+ /**
302
+ * 只取生成器第一次 yield 的結果,
303
+ * 找不到時 `next.value` 為 undefined,回傳 undefined
304
+ * Take only the first value yielded by the generator;
305
+ * when nothing is found `next.value` is undefined, so undefined is returned
306
+ */
229
307
  return (_a = _whichPackageManagerSyncGenerator(npmClients, returnDefaultOrOptions).next().value) === null || _a === void 0 ? void 0 : _a[0];
230
308
  }
309
+ /**
310
+ * 預設匯出:同步偵測第一個可用的套件管理器
311
+ * Default export: synchronously detect the first available package manager
312
+ */
231
313
  exports.default = whichPackageManagerSync;
232
314
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import _ from 'lodash';\nimport { ITSAsyncGenerator, ITSGenerator, ITSTypeAndStringLiteral, ITSArrayListMaybeReadonly } from 'ts-type';\nimport which, { sync as whichSync } from 'which';\n\n/**\n * 支援的套件管理器類型\n * Supported package manager types\n */\nexport const enum EnumPackageManager\n{\n\t'yarn' = 'yarn',\n\t'npm' = 'npm',\n\t'pnpm' = 'pnpm',\n};\n\n/**\n * 支援的套件管理器類型\n * Supported package manager types\n */\nexport type IPackageManager = ITSTypeAndStringLiteral<EnumPackageManager>;\nexport type IPackageManager2<T extends string> = IPackageManager | T;\n\n/**\n * 預設的套件管理器優先順序\n * Default package manager priority order\n */\nconst defaultClients: readonly IPackageManager[] = [EnumPackageManager.pnpm, EnumPackageManager.yarn, EnumPackageManager.npm];\n\n/**\n * 偵測結果類型 - 包含套件管理器名稱和命令路徑\n * Detection result type - contains package manager name and command path\n *\n * @typeParam T - 套件管理器類型 / Package manager type\n */\nexport type IResultDetectPackageManagerRaw<T extends IPackageManager = IPackageManager> = IResultDetectRawCore<T>;\n\n/**\n * 偵測結果核心類型 - 元組 [名稱, 路徑?]\n * Detection result core type - tuple [name, path?]\n *\n * @typeParam T - 字串類型 / String type\n */\nexport type IResultDetectRawCore<T extends string = IPackageManager> = readonly [T, string?];\n\n/**\n * which 命令選項配置\n * which command options configuration\n */\nconst _whichOptions: which.Options = {\n\tnothrow: true,\n}\n\n/**\n * 選項配置介面\n * Options configuration interface\n */\nexport interface IOptionsWhichPackageManager\n{\n\t/**\n\t * 當找不到時是否返回預設值\n\t * Whether to return default when not found\n\t */\n\treturnDefault?: boolean;\n\t/**\n\t * 只使用使用者指定的套件管理器\n\t * 不合併使用者指定的優先順序與預設順序\n\t * Only use user-specified package managers\n\t * Do not merge user-specified priority with default order\n\t */\n\tnoUseDefaultClients?: boolean;\n}\n\n/**\n * 選項輸入類型 - 可接受布林值或選項物件\n * Options input type - accepts boolean or options object\n */\nexport type IRuntimeOptionInput = boolean | IOptionsWhichPackageManager;\n\n/**\n * 核心選項處理函數 - 將輸入轉換為標準選項物件\n * Core options handler function - converts input to standard options object\n *\n * @param returnDefaultOrOptions - 布林值或選項物件 / Boolean or options object\n * @returns 標準選項物件 / Standard options object\n */\nexport function _handleOptionsWhichPackageManagerCore(returnDefaultOrOptions?: IRuntimeOptionInput): IOptionsWhichPackageManager\n{\n\tif (typeof returnDefaultOrOptions === 'boolean')\n\t{\n\t\treturnDefaultOrOptions = {\n\t\t\treturnDefault: returnDefaultOrOptions,\n\t\t}\n\t}\n\n\treturn returnDefaultOrOptions ?? {};\n}\n\n/**\n * 處理套件管理器選項與客戶端列表\n * Handle package manager options and client list\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @param returnDefaultOrOptions - 選項輸入 / Options input\n * @returns 包含選項與檢查列表的物件 / Object containing options and check list\n */\nexport function handleOptionsWhichPackageManager<T extends string = IPackageManager>(npmClients?: ITSArrayListMaybeReadonly<IPackageManager2<T>> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput)\n{\n\treturnDefaultOrOptions = _handleOptionsWhichPackageManagerCore(returnDefaultOrOptions);\n\n\treturn {\n\t\toptions: returnDefaultOrOptions,\n\t\t/**\n\t\t * 合併使用者指定的優先順序與預設順序\n\t\t * Merge user-specified priority with default order\n\t\t */\n\t\tclientsToCheck: _handleClientsToCheck<T>(npmClients as T[], returnDefaultOrOptions),\n\t};\n}\n\n/**\n * 合併使用者指定的優先順序與預設順序\n * Merge user-specified priority with default order\n */\nexport function _handleClientsToCheck<T extends string = IPackageManager>(npmClients?: ITSArrayListMaybeReadonly<T> | undefined, options?: IOptionsWhichPackageManager): readonly IPackageManager2<T>[]\n{\n\t/**\n\t * 合併使用者指定的優先順序與預設順序\n\t * Merge user-specified priority with default order\n\t */\n\tif (npmClients?.length)\n\t{\n\t\t// 過濾不合法的名稱\n\t\tnpmClients = npmClients.filter(v => v?.length);\n\n\t\treturn options?.noUseDefaultClients\n\t\t\t? [...new Set([...npmClients])]\n\t\t\t: [...new Set([...npmClients, ...defaultClients])];\n\t}\n\n\treturn [...defaultClients];\n}\n\n/**\n * 使用 which 依序檢查套件管理器列表,返回第一個可用的\n * Sequentially check package managers using which, return the first available one\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @returns 可用的套件管理器名稱 / Available package manager name\n */\n/**\n * 非同步生成器 - 使用 which 依序檢查套件管理器列表\n * Async generator - sequentially check package managers using which\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @param returnDefaultOrOptions - 選項輸入 (布林值或 IOptionsWhichPackageManager) / Options input (boolean or IOptionsWhichPackageManager)\n * @yield - 可用的套件管理器元組 [名稱, 路徑] / Available package manager tuple [name, path]\n */\n// @ts-ignore\nexport async function* _whichPackageManagerAsyncGenerator<T extends string = IPackageManager>(npmClients?: ITSArrayListMaybeReadonly<IPackageManager2<T>> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): ITSAsyncGenerator<IResultDetectPackageManagerRaw<IPackageManager2<T>>>\n{\n\n\tconst { clientsToCheck, options } = handleOptionsWhichPackageManager(npmClients, returnDefaultOrOptions);\n\n\tyield* _whichAsyncGeneratorCore(clientsToCheck, options) as any;\n}\n\n/**\n * 非同步生成器核心實作 - 依序檢查每個套件管理器是否可用\n * Async generator core implementation - sequentially check each package manager for availability\n *\n * @typeParam T - 套件管理器類型 / Package manager type\n * @param clientsToCheck - 要檢查的套件管理器列表 / List of package managers to check\n * @param options - 選項 / Options\n * @yield - 可用的套件管理器元組 [名稱, 路徑] / Available package manager tuple [name, path]\n */\nexport async function* _whichAsyncGeneratorCore<T extends string = IPackageManager>(clientsToCheck: ITSArrayListMaybeReadonly<T>, options: IOptionsWhichPackageManager): ITSAsyncGenerator<IResultDetectRawCore<T>>\n{\n\tlet notFound = true;\n\n\t/**\n\t * 依序檢查每個套件管理器是否可用\n\t * Check each package manager sequentially for availability\n\t */\n\tfor (const client of clientsToCheck)\n\t{\n\t\tconst commandPath = await which(client, _whichOptions).catch(() => null);\n\t\tif (commandPath)\n\t\t{\n\t\t\tyield [client, commandPath as string] as IResultDetectRawCore<T>;\n\t\t\tnotFound = false;\n\t\t}\n\t}\n\n\tif (options.returnDefault && notFound) return [clientsToCheck[0]] as IResultDetectRawCore<T>;\n}\n\n/**\n * 使用 which 依序檢查套件管理器列表,返回第一個可用的\n * Sequentially check package managers using which, return the first available one\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @returns 可用的套件管理器名稱 / Available package manager name\n */\nexport async function whichPackageManagerAsync(npmClients?: ITSArrayListMaybeReadonly<IPackageManager> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): Promise<IPackageManager>\n{\n\treturn _whichPackageManagerAsyncGenerator(npmClients, returnDefaultOrOptions).next().then(next => next.value?.[0]);\n}\n\n/**\n * 使用 which 依序檢查套件管理器列表,返回所有可用的套件管理器陣列\n * Sequentially check package managers using which, return all available package managers as array\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @returns 所有可用的套件管理器陣列 / Array of all available package managers\n */\nexport async function whichPackageManagerAsyncAll(npmClients?: ITSArrayListMaybeReadonly<IPackageManager> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): Promise<IPackageManager[]>\n{\n\tconst result: IPackageManager[] = [];\n\n\tfor await (const client of _whichPackageManagerAsyncGenerator(npmClients, returnDefaultOrOptions))\n\t{\n\t\tresult.push(client[0]);\n\t}\n\n\treturn result;\n}\n\n/**\n * 使用 which 依序檢查套件管理器列表,以同步生成器方式 yield 所有可用的套件管理器\n * Sequentially check package managers using which, yield all available package managers via sync generator\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @returns 可用的套件管理器(透過 yield)/ Available package manager (via yield)\n */\n/**\n * 同步生成器 - 使用 which 依序檢查套件管理器列表\n * Sync generator - sequentially check package managers using which\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @param returnDefaultOrOptions - 選項輸入 (布林值或 IOptionsWhichPackageManager) / Options input (boolean or IOptionsWhichPackageManager)\n * @yield - 可用的套件管理器元組 [名稱, 路徑] / Available package manager tuple [name, path]\n */\n// @ts-ignore\nexport function* _whichPackageManagerSyncGenerator<T extends string = IPackageManager>(npmClients?: ITSArrayListMaybeReadonly<IPackageManager2<T>> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): ITSGenerator<IResultDetectPackageManagerRaw<IPackageManager2<T>>>\n{\n\tconst { clientsToCheck, options } = handleOptionsWhichPackageManager(npmClients, returnDefaultOrOptions);\n\n\tyield* _whichSyncGeneratorCore(clientsToCheck, options) as any;\n}\n\n/**\n * 同步生成器核心實作 - 依序檢查每個套件管理器是否可用\n * Sync generator core implementation - sequentially check each package manager for availability\n *\n * @typeParam T - 套件管理器類型 / Package manager type\n * @param clientsToCheck - 要檢查的套件管理器列表 / List of package managers to check\n * @param options - 選項 / Options\n * @yield - 可用的套件管理器元組 [名稱, 路徑] / Available package manager tuple [name, path]\n */\nexport function* _whichSyncGeneratorCore<T extends string = IPackageManager>(clientsToCheck: ITSArrayListMaybeReadonly<T>, options: IOptionsWhichPackageManager): ITSGenerator<IResultDetectRawCore<T>>\n{\n\tlet notFound = true;\n\n\t/**\n\t * 依序檢查每個套件管理器是否可用\n\t * Check each package manager sequentially for availability\n\t */\n\tfor (const client of clientsToCheck)\n\t{\n\t\tconst commandPath = whichSync(client, _whichOptions);\n\t\tif (commandPath)\n\t\t{\n\t\t\tyield [client, commandPath as string] as IResultDetectRawCore<T>;\n\t\t\tnotFound = false;\n\t\t}\n\t}\n\n\tif (options.returnDefault && notFound) return [clientsToCheck[0]] as IResultDetectRawCore<T>;\n}\n\n/**\n * 使用 which 依序檢查套件管理器列表,返回所有可用的套件管理器陣列(同步版本)\n * Sequentially check package managers using which, return all available package managers as array (sync version)\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @returns 所有可用的套件管理器陣列 / Array of all available package managers\n */\nexport function whichPackageManagerSyncAll(npmClients?: ITSArrayListMaybeReadonly<IPackageManager> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): IPackageManager[]\n{\n\tconst result: IPackageManager[] = [];\n\n\tfor (const client of _whichPackageManagerSyncGenerator(npmClients, returnDefaultOrOptions))\n\t{\n\t\tresult.push(client[0]);\n\t}\n\n\treturn result;\n}\n\n/**\n * 使用 which 依序檢查套件管理器列表,返回第一個可用的\n * Sequentially check package managers using which, return the first available one\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @returns 可用的套件管理器名稱 / Available package manager name\n */\nexport function whichPackageManagerSync(npmClients?: ITSArrayListMaybeReadonly<IPackageManager> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): IPackageManager\n{\n\treturn _whichPackageManagerSyncGenerator(npmClients, returnDefaultOrOptions).next().value?.[0]\n}\n\nexport default whichPackageManagerSync\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import _ from 'lodash';\nimport { ITSAsyncGenerator, ITSGenerator, ITSTypeAndStringLiteral, ITSArrayListMaybeReadonly } from 'ts-type';\nimport which, { sync as whichSync } from 'which';\n\n/**\n * 支援的套件管理器類型\n * Supported package manager types\n */\nexport const enum EnumPackageManager\n{\n\t'yarn' = 'yarn',\n\t'npm' = 'npm',\n\t'pnpm' = 'pnpm',\n};\n\n/**\n * 支援的套件管理器類型\n * Supported package manager types\n */\nexport type IPackageManager = ITSTypeAndStringLiteral<EnumPackageManager>;\n/**\n * 支援的套件管理器型別,並允許擴充額外的自訂字串\n * Supported package manager type, extended with extra custom string literals\n *\n * @typeParam T - 額外允許的自訂型別 / Additional custom literal type allowed\n */\nexport type IPackageManager2<T extends string> = IPackageManager | T;\n\n/**\n * 預設的套件管理器優先順序\n * Default package manager priority order\n */\nconst defaultClients: readonly IPackageManager[] = [EnumPackageManager.pnpm, EnumPackageManager.yarn, EnumPackageManager.npm];\n\n/**\n * 偵測結果類型 - 包含套件管理器名稱和命令路徑\n * Detection result type - contains package manager name and command path\n *\n * @typeParam T - 套件管理器類型 / Package manager type\n */\nexport type IResultDetectPackageManagerRaw<T extends IPackageManager = IPackageManager> = IResultDetectRawCore<T>;\n\n/**\n * 偵測結果核心類型 - 元組 [名稱, 路徑?]\n * Detection result core type - tuple [name, path?]\n *\n * @typeParam T - 字串類型 / String type\n */\nexport type IResultDetectRawCore<T extends string = IPackageManager> = readonly [T, string?];\n\n/**\n * which 命令選項配置\n * which command options configuration\n */\nconst _whichOptions: which.Options = {\n\tnothrow: true,\n}\n\n/**\n * 選項配置介面\n * Options configuration interface\n */\nexport interface IOptionsWhichPackageManager\n{\n\t/**\n\t * 當找不到時是否返回預設值\n\t * Whether to return default when not found\n\t */\n\treturnDefault?: boolean;\n\t/**\n\t * 只使用使用者指定的套件管理器\n\t * 不合併使用者指定的優先順序與預設順序\n\t * Only use user-specified package managers\n\t * Do not merge user-specified priority with default order\n\t */\n\tnoUseDefaultClients?: boolean;\n}\n\n/**\n * 選項輸入類型 - 可接受布林值或選項物件\n * Options input type - accepts boolean or options object\n */\nexport type IRuntimeOptionInput = boolean | IOptionsWhichPackageManager;\n\n/**\n * 核心選項處理函數 - 將輸入轉換為標準選項物件\n * Core options handler function - converts input to standard options object\n *\n * @param returnDefaultOrOptions - 布林值或選項物件 / Boolean or options object\n * @returns 標準選項物件 / Standard options object\n */\nexport function _handleOptionsWhichPackageManagerCore(returnDefaultOrOptions?: IRuntimeOptionInput): IOptionsWhichPackageManager\n{\n\tif (typeof returnDefaultOrOptions === 'boolean')\n\t{\n\t\t/**\n\t\t * 布林值是 `returnDefault` 的簡寫形式,\n\t\t * 正規化成物件後,後續程式只需處理單一型別\n\t\t * A boolean is shorthand for `returnDefault`;\n\t\t * normalizing to an object keeps downstream code single-typed\n\t\t */\n\t\treturnDefaultOrOptions = {\n\t\t\treturnDefault: returnDefaultOrOptions,\n\t\t}\n\t}\n\n\t/**\n\t * 未傳入任何選項時以空物件代替 undefined,\n\t * 讓呼叫端不必額外處理 null/undefined 分支\n\t * When no option is given, return an empty object instead of undefined\n\t * so callers never have to handle a null/undefined branch\n\t */\n\treturn returnDefaultOrOptions ?? {};\n}\n\n/**\n * 處理套件管理器選項與客戶端列表\n * Handle package manager options and client list\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @param returnDefaultOrOptions - 選項輸入 / Options input\n * @returns 包含選項與檢查列表的物件 / Object containing options and check list\n */\nexport function handleOptionsWhichPackageManager<T extends string = IPackageManager>(npmClients?: ITSArrayListMaybeReadonly<IPackageManager2<T>> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput)\n{\n\treturnDefaultOrOptions = _handleOptionsWhichPackageManagerCore(returnDefaultOrOptions);\n\n\treturn {\n\t\toptions: returnDefaultOrOptions,\n\t\t/**\n\t\t * 合併使用者指定的優先順序與預設順序\n\t\t * Merge user-specified priority with default order\n\t\t */\n\t\tclientsToCheck: _handleClientsToCheck<T>(npmClients as T[], returnDefaultOrOptions),\n\t};\n}\n\n/**\n * 合併使用者指定的優先順序與預設順序\n * Merge user-specified priority with default order\n */\nexport function _handleClientsToCheck<T extends string = IPackageManager>(npmClients?: ITSArrayListMaybeReadonly<T> | undefined, options?: IOptionsWhichPackageManager): readonly IPackageManager2<T>[]\n{\n\t/**\n\t * 合併使用者指定的優先順序與預設順序\n\t * Merge user-specified priority with default order\n\t */\n\tif (npmClients?.length)\n\t{\n\t\t/**\n\t\t * 過濾不合法的名稱(空字串或 undefined)\n\t\t * Filter out invalid names (empty string or undefined)\n\t\t */\n\t\tnpmClients = npmClients.filter(v => v?.length);\n\n\t\t/**\n\t\t * `noUseDefaultClients` 時只保留使用者清單,否則追加預設順序;\n\t\t * 以 Set 去重,避免使用者重複指定同一個套件管理器時重複檢查\n\t\t * With `noUseDefaultClients` only the user list is kept, otherwise the\n\t\t * default order is appended; Set de-duplicates so an entry specified\n\t\t * twice by the user is not checked twice\n\t\t */\n\t\treturn options?.noUseDefaultClients\n\t\t\t? [...new Set([...npmClients])]\n\t\t\t: [...new Set([...npmClients, ...defaultClients])];\n\t}\n\n\t/**\n\t * 使用者未指定任何套件管理器(或清單經篩選後為空)時,\n\t * 直接以預設優先順序作為檢查清單\n\t * When the user specified nothing (or the list became empty after filtering),\n\t * fall back to the default priority order as the check list\n\t */\n\treturn [...defaultClients];\n}\n\n/**\n * 非同步生成器 - 使用 which 依序檢查套件管理器列表\n * Async generator - sequentially check package managers using which\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @param returnDefaultOrOptions - 選項輸入 (布林值或 IOptionsWhichPackageManager) / Options input (boolean or IOptionsWhichPackageManager)\n * @yield - 可用的套件管理器元組 [名稱, 路徑] / Available package manager tuple [name, path]\n */\n// @ts-ignore\nexport async function* _whichPackageManagerAsyncGenerator<T extends string = IPackageManager>(npmClients?: ITSArrayListMaybeReadonly<IPackageManager2<T>> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): ITSAsyncGenerator<IResultDetectPackageManagerRaw<IPackageManager2<T>>>\n{\n\n\tconst { clientsToCheck, options } = handleOptionsWhichPackageManager(npmClients, returnDefaultOrOptions);\n\n\tyield* _whichAsyncGeneratorCore(clientsToCheck, options) as any;\n}\n\n/**\n * 非同步生成器核心實作 - 依序檢查每個套件管理器是否可用\n * Async generator core implementation - sequentially check each package manager for availability\n *\n * @typeParam T - 套件管理器類型 / Package manager type\n * @param clientsToCheck - 要檢查的套件管理器列表 / List of package managers to check\n * @param options - 選項 / Options\n * @yield - 可用的套件管理器元組 [名稱, 路徑] / Available package manager tuple [name, path]\n */\nexport async function* _whichAsyncGeneratorCore<T extends string = IPackageManager>(clientsToCheck: ITSArrayListMaybeReadonly<T>, options: IOptionsWhichPackageManager): ITSAsyncGenerator<IResultDetectRawCore<T>>\n{\n\t/**\n\t * 追蹤是否會有任何套件管理器被找到,\n\t * 供最後判斷是否需要回傳預設值\n\t * Tracks whether any package manager was found,\n\t * used at the end to decide if the default should be returned\n\t */\n\tlet notFound = true;\n\n\t/**\n\t * 依序檢查每個套件管理器是否可用\n\t * Check each package manager sequentially for availability\n\t */\n\tfor (const client of clientsToCheck)\n\t{\n\t\t/**\n\t\t * `nothrow: true` 使找不到命令時回傳 null 而非丟出例外,\n\t\t * `.catch(() => null)` 則涵蓋其他非預期錯誤,讓檢查能繼續下一個候選者\n\t\t * `nothrow: true` makes a missing command resolve to null instead of throwing,\n\t\t * and `.catch(() => null)` swallows unexpected errors so checking continues to the next candidate\n\t\t */\n\t\tconst commandPath = await which(client, _whichOptions).catch(() => null);\n\t\t/**\n\t\t * 只有找到可執行檔時才 yield,避免把不存在的套件管理器當成可用結果\n\t\t * Only yield when the executable exists, so missing package managers are never reported as available\n\t\t */\n\t\tif (commandPath)\n\t\t{\n\t\t\tyield [client, commandPath as string] as IResultDetectRawCore<T>;\n\t\t\tnotFound = false;\n\t\t}\n\t}\n\n\t/**\n\t * 全部都找不到時,若允許回傳預設值,\n\t * 則以檢查清單的第一個作為回報(即使它並未安裝)\n\t * When nothing was found, if defaults are allowed, report the first\n\t * entry of the check list (even if it is not installed)\n\t */\n\tif (options.returnDefault && notFound) return [clientsToCheck[0]] as IResultDetectRawCore<T>;\n}\n\n/**\n * 使用 which 依序檢查套件管理器列表,返回第一個可用的\n * Sequentially check package managers using which, return the first available one\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @returns 可用的套件管理器名稱 / Available package manager name\n */\nexport async function whichPackageManagerAsync(npmClients?: ITSArrayListMaybeReadonly<IPackageManager> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): Promise<IPackageManager>\n{\n\t/**\n\t * 只取生成器第一次 yield 的結果,\n\t * 找不到時 `next.value` 為 undefined,回傳 undefined\n\t * Take only the first value yielded by the generator;\n\t * when nothing is found `next.value` is undefined, so undefined is returned\n\t */\n\treturn _whichPackageManagerAsyncGenerator(npmClients, returnDefaultOrOptions).next().then(next => next.value?.[0]);\n}\n\n/**\n * 使用 which 依序檢查套件管理器列表,返回所有可用的套件管理器陣列\n * Sequentially check package managers using which, return all available package managers as array\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @returns 所有可用的套件管理器陣列 / Array of all available package managers\n */\nexport async function whichPackageManagerAsyncAll(npmClients?: ITSArrayListMaybeReadonly<IPackageManager> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): Promise<IPackageManager[]>\n{\n\tconst result: IPackageManager[] = [];\n\n\t/**\n\t * 逐一收集生成器 yield 的結果,只保留名稱、捨棄路徑\n\t * Collect each value yielded by the generator, keeping only the name and discarding the path\n\t */\n\tfor await (const client of _whichPackageManagerAsyncGenerator(npmClients, returnDefaultOrOptions))\n\t{\n\t\tresult.push(client[0]);\n\t}\n\n\treturn result;\n}\n\n/**\n * 同步生成器 - 使用 which 依序檢查套件管理器列表\n * Sync generator - sequentially check package managers using which\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @param returnDefaultOrOptions - 選項輸入 (布林值或 IOptionsWhichPackageManager) / Options input (boolean or IOptionsWhichPackageManager)\n * @yield - 可用的套件管理器元組 [名稱, 路徑] / Available package manager tuple [name, path]\n */\n// @ts-ignore\nexport function* _whichPackageManagerSyncGenerator<T extends string = IPackageManager>(npmClients?: ITSArrayListMaybeReadonly<IPackageManager2<T>> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): ITSGenerator<IResultDetectPackageManagerRaw<IPackageManager2<T>>>\n{\n\tconst { clientsToCheck, options } = handleOptionsWhichPackageManager(npmClients, returnDefaultOrOptions);\n\n\tyield* _whichSyncGeneratorCore(clientsToCheck, options) as any;\n}\n\n/**\n * 同步生成器核心實作 - 依序檢查每個套件管理器是否可用\n * Sync generator core implementation - sequentially check each package manager for availability\n *\n * @typeParam T - 套件管理器類型 / Package manager type\n * @param clientsToCheck - 要檢查的套件管理器列表 / List of package managers to check\n * @param options - 選項 / Options\n * @yield - 可用的套件管理器元組 [名稱, 路徑] / Available package manager tuple [name, path]\n */\nexport function* _whichSyncGeneratorCore<T extends string = IPackageManager>(clientsToCheck: ITSArrayListMaybeReadonly<T>, options: IOptionsWhichPackageManager): ITSGenerator<IResultDetectRawCore<T>>\n{\n\t/**\n\t * 追蹤是否會有任何套件管理器被找到,\n\t * 供最後判斷是否需要回傳預設值\n\t * Tracks whether any package manager was found,\n\t * used at the end to decide if the default should be returned\n\t */\n\tlet notFound = true;\n\n\t/**\n\t * 依序檢查每個套件管理器是否可用\n\t * Check each package manager sequentially for availability\n\t */\n\tfor (const client of clientsToCheck)\n\t{\n\t\t/**\n\t\t * `nothrow: true` 使找不到命令時回傳 null 而非丟出例外,\n\t\t * 因此可直接以 truthy 判斷是否找到可執行檔\n\t\t * `nothrow: true` makes a missing command return null instead of throwing,\n\t\t * so a simple truthy check tells us whether the executable was found\n\t\t */\n\t\tconst commandPath = whichSync(client, _whichOptions);\n\t\t/**\n\t\t * 只有找到可執行檔時才 yield,避免把不存在的套件管理器當成可用結果\n\t\t * Only yield when the executable exists, so missing package managers are never reported as available\n\t\t */\n\t\tif (commandPath)\n\t\t{\n\t\t\tyield [client, commandPath as string] as IResultDetectRawCore<T>;\n\t\t\tnotFound = false;\n\t\t}\n\t}\n\n\t/**\n\t * 全部都找不到時,若允許回傳預設值,\n\t * 則以檢查清單的第一個作為回報(即使它並未安裝)\n\t * When nothing was found, if defaults are allowed, report the first\n\t * entry of the check list (even if it is not installed)\n\t */\n\tif (options.returnDefault && notFound) return [clientsToCheck[0]] as IResultDetectRawCore<T>;\n}\n\n/**\n * 使用 which 依序檢查套件管理器列表,返回所有可用的套件管理器陣列(同步版本)\n * Sequentially check package managers using which, return all available package managers as array (sync version)\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @returns 所有可用的套件管理器陣列 / Array of all available package managers\n */\nexport function whichPackageManagerSyncAll(npmClients?: ITSArrayListMaybeReadonly<IPackageManager> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): IPackageManager[]\n{\n\tconst result: IPackageManager[] = [];\n\n\t/**\n\t * 逐一收集生成器 yield 的結果,只保留名稱、捨棄路徑\n\t * Collect each value yielded by the generator, keeping only the name and discarding the path\n\t */\n\tfor (const client of _whichPackageManagerSyncGenerator(npmClients, returnDefaultOrOptions))\n\t{\n\t\tresult.push(client[0]);\n\t}\n\n\treturn result;\n}\n\n/**\n * 使用 which 依序檢查套件管理器列表,返回第一個可用的\n * Sequentially check package managers using which, return the first available one\n *\n * @param npmClients - 套件管理器列表 / Package manager list\n * @returns 可用的套件管理器名稱 / Available package manager name\n */\nexport function whichPackageManagerSync(npmClients?: ITSArrayListMaybeReadonly<IPackageManager> | undefined, returnDefaultOrOptions?: IRuntimeOptionInput): IPackageManager\n{\n\t/**\n\t * 只取生成器第一次 yield 的結果,\n\t * 找不到時 `next.value` 為 undefined,回傳 undefined\n\t * Take only the first value yielded by the generator;\n\t * when nothing is found `next.value` is undefined, so undefined is returned\n\t */\n\treturn _whichPackageManagerSyncGenerator(npmClients, returnDefaultOrOptions).next().value?.[0]\n}\n\n/**\n * 預設匯出:同步偵測第一個可用的套件管理器\n * Default export: synchronously detect the first available package manager\n */\nexport default whichPackageManagerSync\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yarn-tool/detect-package-manager",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "Detect available package manager (yarn, npm, pnpm) using which command",
5
5
  "keywords": [
6
6
  "detect",
@@ -36,18 +36,20 @@
36
36
  "main": "index.js",
37
37
  "scripts": {
38
38
  "review": "node --run review:coverage",
39
- "review:coverage": "yarn run lint && yarn run coverage",
40
- "review:test": "yarn run lint && yarn run test",
41
- "coverage": "yarn run test -- --coverage",
39
+ "review:coverage": "pnpm run lint && pnpm run coverage",
40
+ "review:test": "pnpm run lint && pnpm run test",
41
+ "coverage": "pnpm run test -- --coverage",
42
42
  "lint": "node --run lint:eslint",
43
43
  "lint:eslint": "ynpx eslint --ext .ts,.tsx,.mts,.cts ./",
44
44
  "pretest": "echo pretest",
45
- "test": "jest --passWithNoTests",
45
+ "test": "node --run test:node",
46
46
  "test:jest": "jest --passWithNoTests",
47
47
  "test:jest:coverage": "node --run test:jest -- --coverage",
48
48
  "test:jest:snapshot": "node --run test:jest -- -u",
49
49
  "test:mocha": "ynpx --quiet -p ts-node -p mocha mocha -- --require ts-node/register \"!(node_modules)/**/*.{test,spec}.{ts,tsx}\"",
50
- "test:snapshot": "yarn run test -- -u",
50
+ "test:node": "tsx --test --test-update-snapshots **/*.node-spec.ts **/*.node-test.ts **/*.spec.ts **/*.test.ts",
51
+ "test:snapshot": "pnpm run test -u",
52
+ "test:tsc": "tsc --noEmit & echo typescript check done",
51
53
  "test:tsd": "ynpx tsd",
52
54
  "test:tsdx": "ynpx @bluelovers/tsdx test --passWithNoTests",
53
55
  "build:dts:bundle": "ynpx @bluelovers/dts-bundle-generator -o ./dist/index.d.ts ./src/index.ts --no-banner --inline-declare-global & echo build:dts:bundle",
@@ -58,11 +60,10 @@
58
60
  "build:tsdx": "ynpx @bluelovers/tsdx build --target node --name index",
59
61
  "ci:install": "echo ci:install",
60
62
  "ci:build": "echo ci:build",
61
- "preversion": "echo preversion && yarn run test",
63
+ "preversion": "echo preversion && pnpm run test",
62
64
  "version": "echo version",
63
65
  "postversion": "echo postversion",
64
66
  "prepublish": "echo prepublish",
65
- "prepare": "echo prepare",
66
67
  "prepublishOnly": "echo prepublishOnly",
67
68
  "prepack": "echo prepack",
68
69
  "pack": "echo pack",
@@ -78,10 +79,10 @@
78
79
  "dependencies": {
79
80
  "@types/which": "^3.0.4",
80
81
  "tslib": ">=2.8.1",
81
- "which": "^6.0.1"
82
+ "which": "^7.0.0"
82
83
  },
83
84
  "publishConfig": {
84
85
  "access": "public"
85
86
  },
86
- "gitHead": "8c939a673ef0f088d4a3aa8a240ed6c28d390f98"
87
+ "gitHead": "471c63ee11851f0ac3487f23d1c472936f99b460"
87
88
  }