create-yarn-workspaces 3.0.34 → 3.0.36

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/index.js CHANGED
@@ -1,337 +1,77 @@
1
1
  "use strict";
2
2
  /**
3
- * 創建 Yarn Workspaces 工具模組
4
- * Yarn Workspaces Creation Tool Module
3
+ * 創建 Workspaces 工具模組
5
4
  *
6
- * 提供初始化 Yarn Workspaces 專案結構的功能,包含 package.json 設定、
7
- * Lerna 整合、目錄創建與靜態檔案複製等功能。
8
- * Provides functionality to initialize Yarn Workspaces project structure,
9
- * including package.json configuration, Lerna integration, directory creation,
10
- * and static file copying.
11
- *
12
- * @author user
13
- * @since 2018/5/13/013
5
+ * 提供初始化 Workspaces 專案結構的功能,
6
+ * 包含 package.json 設定、
7
+ * Lerna 整合、
8
+ * 目錄創建與靜態檔案複製等功能。
14
9
  */
15
10
  Object.defineProperty(exports, "__esModule", { value: true });
16
11
  exports.createYarnWorkspaces = createYarnWorkspaces;
17
- exports._createYarnWorkspaces = _createYarnWorkspaces;
18
- exports.createDirByPackages = createDirByPackages;
12
+ exports.createYarnWorkspacesAsync = createYarnWorkspacesAsync;
19
13
  const tslib_1 = require("tslib");
20
- const upath2_1 = require("upath2");
21
- const logger_1 = require("debug-color2/logger");
22
- const static_file_1 = require("@yarn-tool/static-file");
23
- const fs_extra_1 = require("fs-extra");
24
- const sort_package_json3_1 = require("sort-package-json3");
25
- const lib_1 = require("./lib");
26
- const util_1 = require("./lib/util");
27
- const wsCopyStaticFiles_1 = require("@yarn-tool/static-file/lib/ws/wsCopyStaticFiles");
28
- const find_root_1 = require("@yarn-tool/find-root");
29
- const upath2_2 = require("upath2");
30
- const staticFiles_1 = require("@yarn-tool/fix-all/lib/file/staticFiles");
14
+ const core_1 = require("./lib/core");
15
+ const check_env_1 = require("./lib/check-env");
31
16
  tslib_1.__exportStar(require("./lib/index"), exports);
32
17
  tslib_1.__exportStar(require("./lib/util"), exports);
33
18
  /**
34
- * 創建 Yarn Workspaces 主函式
35
- * Main function to create Yarn Workspaces
19
+ * 創建 Workspaces 主函式(同步)
20
+ *
21
+ * 檢查並創建 Workspaces 專案結構,處理已存在 Package 與父層 Workspaces 的情況。
22
+ * 不支援互動介面:環境檢查發現疑似錯誤路徑時僅印出警告並繼續執行。
36
23
  *
37
- * 檢查並創建 Workspaces 專案結構,處理已存在 Package 與父層 Workspaces 的情況
38
- * Checks and creates workspace project structure, handling existing packages
39
- * and parent workspaces
24
+ * @param cwd - 工作目錄路徑
25
+ * @param options - 配置選項
26
+ * @returns 是否成功創建
40
27
  *
41
- * @param cwd - 工作目錄路徑 / Working directory path
42
- * @param options - 配置選項 / Configuration options
43
- * @returns 是否成功創建 / Whether creation was successful
28
+ * @deprecated 請改用 `createYarnWorkspacesAsync` 以獲得更好的互動體驗
44
29
  */
45
30
  function createYarnWorkspaces(cwd, options = {}) {
46
- var _a;
47
- // 處理第一個參數可能是選項物件的情況
48
- // Handle case where first argument might be options object
49
- if (cwd && typeof cwd != 'string') {
50
- options = cwd;
51
- cwd = options.cwd;
52
- }
53
- // 預設使用當前工作目錄 / Default to current working directory
54
- cwd !== null && cwd !== void 0 ? cwd : (cwd = process.cwd());
55
- // 尋找專案根目錄資訊 / Find project root information
56
- const rootData = (0, find_root_1.findRootLazy)({
57
- cwd,
58
- });
59
- // 標準化路徑 / Normalize path
60
- cwd = (0, upath2_2.normalize)((_a = rootData === null || rootData === void 0 ? void 0 : rootData.cwd) !== null && _a !== void 0 ? _a : cwd);
61
- // 取得 Package 根目錄與 Workspaces 路徑
62
- // Get package root directory and workspace path
63
- let root = rootData === null || rootData === void 0 ? void 0 : rootData.pkg;
64
- let ws = rootData === null || rootData === void 0 ? void 0 : rootData.ws;
65
- // 實際要初始化的目標路徑:優先採用既有 package 根目錄,否則退回 cwd。
66
- // The actual init target: prefer an existing package root, otherwise fall back to `cwd`.
67
- let targetPath = (0, upath2_1.resolve)(root || cwd);
68
- // 除錯輸出 / Debug output
69
- options.debug && logger_1.consoleLogger.debug({
70
- targetPath,
71
- ws,
72
- options,
73
- });
74
- /**
75
- * 檢查是否已存在 Package
76
- * Check if package already exists
77
- */
78
- if (!options.ignoreExistsPackage && root) {
79
- logger_1.consoleLogger.error(`already have package at "${root}", or use ignoreExistsPackage for overwrite it`);
31
+ const precheck = (0, core_1._precheckYarnWorkspaces)(cwd, options);
32
+ if (!precheck.ok) {
80
33
  return false;
81
34
  }
82
- else if (root) {
83
- // 忽略已存在的 Package / Ignore existing package
84
- logger_1.consoleLogger.warn(`ignore exists package "${root}"`);
35
+ const report = (0, check_env_1._checkEnv)(precheck.targetPath, precheck.options);
36
+ if (report.suspicious) {
37
+ /** sync 版本不支援互動介面:印出警告後繼續執行(原有邏輯機制)。 */
38
+ (0, check_env_1._warnCheckEnv)(report);
85
39
  }
86
- /**
87
- * 檢查是否已存在 Workspaces
88
- * Check if workspace already exists
89
- */
90
- if (ws) {
91
- // 檢查目標路徑是否與現有 Workspace 相同
92
- // Check if target path is same as existing workspace
93
- let bool = !(0, util_1.isSamePath)(targetPath, ws);
94
- logger_1.consoleLogger.warn(`detect exists workspace "${ws}"`);
95
- if (bool) {
96
- // 根據選項決定是否忽略父層 Workspaces
97
- // Decide whether to ignore parent workspaces based on options
98
- if (options.ignoreParentWorkspaces) {
99
- logger_1.consoleLogger.warn(`ignoreParentWorkspaces = true`);
100
- bool = false;
101
- }
102
- else {
103
- logger_1.consoleLogger.error(`target path already is workspace`);
104
- }
105
- }
106
- if (bool) {
107
- return false;
108
- }
109
- }
110
- return _createYarnWorkspaces(targetPath, options);
40
+ return (0, core_1._createYarnWorkspaces)(precheck.targetPath, precheck.options);
111
41
  }
112
42
  /**
113
- * 內部創建 Workspaces 實作函式
114
- * Internal implementation function for creating workspaces
115
- *
116
- * 執行實際的 Workspaces 初始化工作,包含:
117
- * - 讀取並更新 Lerna 配置
118
- * - 創建或更新 package.json
119
- * - 複製靜態範本檔案
120
- * - 創建 packages 目錄
43
+ * 創建 Workspaces 主函式(非同步)
121
44
  *
122
- * Performs actual workspace initialization including:
123
- * - Reading and updating Lerna configuration
124
- * - Creating or updating package.json
125
- * - Copying static template files
126
- * - Creating packages directory
45
+ * 與 {@link createYarnWorkspaces} 相同,但當 `options.interactive` 啟用且環境具備 TTY 時,
46
+ * 會依環境檢查報告透過互動介面詢問是否繼續;
47
+ * 未啟用互動介面(或不具備 TTY)時與同步版本相同,僅印出警告並繼續執行。
127
48
  *
128
- * @param targetPath - 目標路徑 / Target path
129
- * @param options - 配置選項 / Configuration options
130
- * @returns 是否成功 / Whether successful
49
+ * @param cwd - 工作目錄路徑
50
+ * @param options - 配置選項
51
+ * @returns 是否成功創建;使用者在互動介面取消時回傳 false
131
52
  */
132
- function _createYarnWorkspaces(targetPath, options = {}) {
133
- var _a;
134
- logger_1.consoleLogger.info(`create in target path "${targetPath}"`);
135
- let pkg;
136
- let lerna;
137
- /**
138
- * 嘗試讀取現有的 lerna.json 配置
139
- * Try to read existing lerna.json configuration
140
- */
141
- {
142
- let file = (0, upath2_1.join)(targetPath, 'lerna.json');
143
- if ((0, fs_extra_1.existsSync)(file)) {
144
- let json = JSON.parse((0, fs_extra_1.readFileSync)(file).toString());
145
- /**
146
- * 清理空的 packages 陣列
147
- * Clean up empty packages array
148
- */
149
- if (json.packages && !Object.keys(json.packages).length) {
150
- json.packages = undefined;
151
- }
152
- lerna = json;
153
- }
53
+ async function createYarnWorkspacesAsync(cwd, options = {}) {
54
+ const precheck = (0, core_1._precheckYarnWorkspaces)(cwd, options);
55
+ if (!precheck.ok) {
56
+ return false;
154
57
  }
155
- /**
156
- * 預設 packages 目錄模式
157
- * Default packages directory pattern
158
- */
159
- let packages = lerna && lerna.packages || [
160
- "packages/*",
161
- ];
162
- let file = (0, upath2_1.join)(targetPath, 'package.json');
163
- /**
164
- * 處理 package.json 不存在的情況
165
- * Handle case when package.json does not exist
166
- */
167
- if (!(0, fs_extra_1.existsSync)(file)) {
168
- // 使用目錄名作為預設 Package 名稱
169
- // Use directory name as default package name
170
- let name = (0, upath2_1.basename)(targetPath);
171
- // 創建目標目錄(如果不存在)
172
- // Create target directory if it doesn't exist
173
- if (!(0, fs_extra_1.existsSync)(targetPath)) {
174
- (0, fs_extra_1.mkdirSync)(targetPath);
175
- }
176
- // 合併預設配置與基本資訊
177
- // Merge default configuration with basic info
178
- pkg = Object.assign((0, lib_1.getDefaultPackageJson)(name), {
179
- name,
180
- workspaces: packages,
181
- });
182
- /**
183
- * 執行自定義初始化回呼
184
- * Execute custom initialization callback
185
- */
186
- if (options.initPackageJson) {
187
- let ret = options.initPackageJson(pkg);
188
- if (ret) {
189
- pkg = ret;
58
+ const report = (0, check_env_1._checkEnv)(precheck.targetPath, precheck.options);
59
+ if (report.suspicious) {
60
+ if (precheck.options.interactive && (0, check_env_1._checkInteractive)()) {
61
+ /** 依 _checkEnv 結果詢問是否疑似在錯誤路徑執行、仍要繼續 */
62
+ if (!await (0, check_env_1._confirmCheckEnv)(report)) {
63
+ return false;
190
64
  }
191
65
  }
192
- }
193
- else {
194
- /**
195
- * 處理已存在的 package.json
196
- * Handle existing package.json
197
- */
198
- let json = JSON.parse((0, fs_extra_1.readFileSync)(file).toString());
199
- let workspaces;
200
- /**
201
- * 解析現有的 workspaces 配置
202
- * Parse existing workspaces configuration
203
- */
204
- if (json.workspaces && Object.keys(json.workspaces).length) {
205
- workspaces = json.workspaces;
206
- /**
207
- * 支援 nohoist 配置格式
208
- * Support nohoist configuration format
209
- * @see https://yarnpkg.com/blog/2018/02/15/nohoist/
210
- */
211
- // @ts-ignore
212
- packages = workspaces.packages || workspaces;
213
- }
214
66
  else {
215
- workspaces = packages;
67
+ /** 未啟用互動介面:印出警告但繼續執行(原有邏輯機制) */
68
+ (0, check_env_1._warnCheckEnv)(report);
216
69
  }
217
- /**
218
- * 更新 Package.json 內容
219
- * Update package.json content
220
- */
221
- pkg = Object.assign(json, {
222
- "private": true,
223
- "workspaces": workspaces,
224
- });
225
- /**
226
- * 合併預設腳本與欄位
227
- * Merge default scripts and fields
228
- */
229
- Object.entries((0, lib_1.getDefaultPackageJson)(json.name))
230
- .forEach(([field, value]) => {
231
- var _a, _b;
232
- /**
233
- * 特殊處理 scripts 欄位:合併而非覆蓋
234
- * Special handling for scripts field: merge instead of overwrite
235
- */
236
- if (field === 'scripts') {
237
- (_a = pkg.scripts) !== null && _a !== void 0 ? _a : (pkg.scripts = {});
238
- pkg.scripts = {
239
- // @ts-ignore
240
- ...value,
241
- ...pkg.scripts,
242
- };
243
- }
244
- else {
245
- // 使用空值合併運算子設置預設值
246
- // Use nullish coalescing operator for default values
247
- (_b = pkg[field]) !== null && _b !== void 0 ? _b : (pkg[field] = value);
248
- }
249
- });
250
70
  }
251
- /**
252
- * 寫入格式化後的 package.json
253
- * Write formatted package.json
254
- */
255
- let s = JSON.stringify((0, sort_package_json3_1.sortPackageJson)(pkg), null, 2);
256
- (0, fs_extra_1.writeFileSync)(file, s);
257
- logger_1.consoleLogger.success(`create workspace package.json`);
258
- /**
259
- * 更新 Lerna 配置(如果存在且需要更新)
260
- * Update Lerna configuration if exists and needs updating
261
- */
262
- if (lerna && (packages != lerna.packages || lerna.npmClient !== 'yarn' || lerna['useWorkspaces'] !== true)) {
263
- let file = (0, upath2_1.join)(targetPath, 'lerna.json');
264
- // 更新為 Yarn Workspaces 模式
265
- // Update to Yarn Workspaces mode
266
- lerna.packages = packages;
267
- (_a = lerna.npmClient) !== null && _a !== void 0 ? _a : (lerna.npmClient = 'pnpm');
268
- // lerna['useWorkspaces'] = true;
269
- let s = JSON.stringify((0, sort_package_json3_1.sortPackageJson)(lerna), null, 2);
270
- (0, fs_extra_1.writeFileSync)(file, s);
271
- logger_1.consoleLogger.info(`update lerna.json`);
272
- }
273
- /**
274
- * 複製靜態範本檔案
275
- * Copy static template files
276
- */
277
- const file_map = (0, wsCopyStaticFiles_1.getWsCopyStaticFiles)();
278
- /**
279
- * 複製靜態範本檔案
280
- * Copy static template files
281
- *
282
- * 此呼叫點 addStaticFiles 預設為 true,可用 noStaticFiles 關閉
283
- * addStaticFiles defaults to true at this call site; disable it with noStaticFiles
284
- */
285
- if ((0, staticFiles_1._isAddStaticFilesOrReset)(options, true)) {
286
- (0, static_file_1.copyStaticFiles)({
287
- cwd: targetPath,
288
- file_map,
289
- });
290
- }
291
- /**
292
- * 根據 packages 模式創建目錄
293
- * Create directories based on packages pattern
294
- */
295
- createDirByPackages(targetPath, packages);
296
- return true;
297
- }
298
- /**
299
- * 根據 packages 模式創建目錄
300
- * Create directories based on packages pattern
301
- *
302
- * 解析 packages 陣列中的目錄模式(如 "packages/*"),
303
- * 並創建對應的實體目錄。
304
- * Parses directory patterns from packages array (e.g., "packages/*")
305
- * and creates corresponding physical directories.
306
- *
307
- * @param cwd - 當前工作目錄 / Current working directory
308
- * @param packages - packages 模式陣列 / Array of package patterns
309
- * @returns 是否有創建任何目錄 / Whether any directories were created
310
- */
311
- function createDirByPackages(cwd, packages) {
312
- return packages.some(function (value) {
313
- let bool;
314
- // 提取路徑的第一個部分(目錄名稱)
315
- // Extract first part of path (directory name)
316
- let s = value.split(/[\/\\]/)[0];
317
- /**
318
- * 只處理不包含 glob 模式的純目錄路徑
319
- * Only handle pure directory paths without glob patterns
320
- */
321
- if (!/[!?\*{}\[\]]/.test(s)) {
322
- let dir = (0, upath2_1.join)(cwd, s);
323
- // 目錄不存在時創建 / Create directory if it doesn't exist
324
- if (!(0, fs_extra_1.existsSync)(dir)) {
325
- (0, fs_extra_1.mkdirSync)(dir);
326
- }
327
- return true;
328
- }
329
- return bool;
330
- });
71
+ return (0, core_1._createYarnWorkspaces)(precheck.targetPath, precheck.options);
331
72
  }
332
73
  /**
333
74
  * 預設導出創建函式
334
- * Default export of creation function
335
75
  */
336
76
  exports.default = createYarnWorkspaces;
337
77
  //# 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":["/**\n * 創建 Yarn Workspaces 工具模組\n * Yarn Workspaces Creation Tool Module\n *\n * 提供初始化 Yarn Workspaces 專案結構的功能,包含 package.json 設定、\n * Lerna 整合、目錄創建與靜態檔案複製等功能。\n * Provides functionality to initialize Yarn Workspaces project structure,\n * including package.json configuration, Lerna integration, directory creation,\n * and static file copying.\n *\n * @author user\n * @since 2018/5/13/013\n */\n\nimport findYarnWorkspaceRoot from 'find-yarn-workspace-root2/core';\nimport { resolve, join, basename } from 'upath2';\nimport pkgDir from 'pkg-dir';\nimport { consoleLogger as console } from 'debug-color2/logger';\nimport { copyStaticFiles } from '@yarn-tool/static-file';\nimport { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs-extra';\nimport { sortPackageJson } from 'sort-package-json3';\nimport { getDefaultPackageJson } from './lib';\nimport { isSamePath } from './lib/util';\nimport { ILernaJson } from '@ts-type/package-dts/lerna-json';\nimport { IPackageJson } from '@ts-type/package-dts/package-json';\nimport { getWsCopyStaticFiles } from '@yarn-tool/static-file/lib/ws/wsCopyStaticFiles';\nimport { findRootLazy } from '@yarn-tool/find-root';\nimport { normalize as pathNormalize } from 'upath2';\nimport { _isAddStaticFilesOrReset } from '@yarn-tool/fix-all/lib/file/staticFiles';\nimport { INpmAutoFixAll } from '@yarn-tool/fix-all';\n\nexport * from './lib/index';\nexport * from './lib/util';\n\n/**\n * 創建 Workspaces 的選項介面\n * Interface for creating workspaces options\n */\nexport interface IOptions extends Pick<INpmAutoFixAll, 'addStaticFiles' | 'noStaticFiles'>\n{\n\t/**\n\t * 工作目錄路徑 / Working directory path\n\t */\n\tcwd?: string,\n\n\t/**\n\t * 忽略父層 Workspaces / Ignore parent workspaces\n\t */\n\tignoreParentWorkspaces?: boolean,\n\n\t/**\n\t * 忽略已存在的 Package / Ignore existing package\n\t */\n\tignoreExistsPackage?: boolean,\n\n\t/**\n\t * 初始化 Package.json 的回呼函式\n\t * Callback function to initialize package.json\n\t * @template T - 擴展屬性類型 / Extended property type\n\t * @param current - 當前的 package.json / Current package.json\n\t * @returns 修改後的 package.json / Modified package.json\n\t */\n\tinitPackageJson?<T extends Record<string, any> = {}>(current: IPackageJson): IPackageJson & T,\n\n\t/**\n\t * 啟用除錯模式 / Enable debug mode\n\t */\n\tdebug?: boolean,\n}\n\n/**\n * 創建 Yarn Workspaces 主函式\n * Main function to create Yarn Workspaces\n *\n * 檢查並創建 Workspaces 專案結構,處理已存在 Package 與父層 Workspaces 的情況\n * Checks and creates workspace project structure, handling existing packages\n * and parent workspaces\n *\n * @param cwd - 工作目錄路徑 / Working directory path\n * @param options - 配置選項 / Configuration options\n * @returns 是否成功創建 / Whether creation was successful\n */\nexport function createYarnWorkspaces(cwd?: string, options: IOptions = {})\n{\n\t// 處理第一個參數可能是選項物件的情況\n\t// Handle case where first argument might be options object\n\tif (cwd && typeof cwd != 'string')\n\t{\n\t\toptions = cwd;\n\t\tcwd = options.cwd;\n\t}\n\n\t// 預設使用當前工作目錄 / Default to current working directory\n\tcwd ??= process.cwd();\n\n\t// 尋找專案根目錄資訊 / Find project root information\n\tconst rootData = findRootLazy({\n\t\tcwd,\n\t});\n\n\t// 標準化路徑 / Normalize path\n\tcwd = pathNormalize(rootData?.cwd ?? cwd);\n\n\t// 取得 Package 根目錄與 Workspaces 路徑\n\t// Get package root directory and workspace path\n\tlet root: string = rootData?.pkg;\n\tlet ws: string = rootData?.ws;\n\n\t// 實際要初始化的目標路徑:優先採用既有 package 根目錄,否則退回 cwd。\n\t// The actual init target: prefer an existing package root, otherwise fall back to `cwd`.\n\tlet targetPath = resolve(root || cwd);\n\n\t// 除錯輸出 / Debug output\n\toptions.debug && console.debug({\n\t\ttargetPath,\n\t\tws,\n\t\toptions,\n\t});\n\n\t/**\n\t * 檢查是否已存在 Package\n\t * Check if package already exists\n\t */\n\tif (!options.ignoreExistsPackage && root)\n\t{\n\t\tconsole.error(`already have package at \"${root}\", or use ignoreExistsPackage for overwrite it`);\n\n\t\treturn false;\n\t}\n\telse if (root)\n\t{\n\t\t// 忽略已存在的 Package / Ignore existing package\n\t\tconsole.warn(`ignore exists package \"${root}\"`);\n\t}\n\n\t/**\n\t * 檢查是否已存在 Workspaces\n\t * Check if workspace already exists\n\t */\n\tif (ws)\n\t{\n\t\t// 檢查目標路徑是否與現有 Workspace 相同\n\t\t// Check if target path is same as existing workspace\n\t\tlet bool: boolean = !isSamePath(targetPath, ws);\n\n\t\tconsole.warn(`detect exists workspace \"${ws}\"`);\n\n\t\tif (bool)\n\t\t{\n\t\t\t// 根據選項決定是否忽略父層 Workspaces\n\t\t\t// Decide whether to ignore parent workspaces based on options\n\t\t\tif (options.ignoreParentWorkspaces)\n\t\t\t{\n\t\t\t\tconsole.warn(`ignoreParentWorkspaces = true`);\n\t\t\t\tbool = false;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tconsole.error(`target path already is workspace`);\n\t\t\t}\n\t\t}\n\n\t\tif (bool)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn _createYarnWorkspaces(targetPath, options);\n}\n\n/**\n * 內部創建 Workspaces 實作函式\n * Internal implementation function for creating workspaces\n *\n * 執行實際的 Workspaces 初始化工作,包含:\n * - 讀取並更新 Lerna 配置\n * - 創建或更新 package.json\n * - 複製靜態範本檔案\n * - 創建 packages 目錄\n *\n * Performs actual workspace initialization including:\n * - Reading and updating Lerna configuration\n * - Creating or updating package.json\n * - Copying static template files\n * - Creating packages directory\n *\n * @param targetPath - 目標路徑 / Target path\n * @param options - 配置選項 / Configuration options\n * @returns 是否成功 / Whether successful\n */\nexport function _createYarnWorkspaces(targetPath: string, options: IOptions = {})\n{\n\tconsole.info(`create in target path \"${targetPath}\"`);\n\n\tlet pkg: IPackageJson;\n\n\tlet lerna: ILernaJson;\n\n\t/**\n\t * 嘗試讀取現有的 lerna.json 配置\n\t * Try to read existing lerna.json configuration\n\t */\n\t{\n\t\tlet file = join(targetPath, 'lerna.json');\n\n\t\tif (existsSync(file))\n\t\t{\n\t\t\tlet json: ILernaJson = JSON.parse(readFileSync(file).toString());\n\n\t\t\t/**\n\t\t\t * 清理空的 packages 陣列\n\t\t\t * Clean up empty packages array\n\t\t\t */\n\t\t\tif (json.packages && !Object.keys(json.packages).length)\n\t\t\t{\n\t\t\t\tjson.packages = undefined;\n\t\t\t}\n\n\t\t\tlerna = json;\n\t\t}\n\t}\n\n\t/**\n\t * 預設 packages 目錄模式\n\t * Default packages directory pattern\n\t */\n\tlet packages = lerna && lerna.packages || [\n\t\t\"packages/*\",\n\t];\n\n\tlet file = join(targetPath, 'package.json');\n\n\t/**\n\t * 處理 package.json 不存在的情況\n\t * Handle case when package.json does not exist\n\t */\n\tif (!existsSync(file))\n\t{\n\t\t// 使用目錄名作為預設 Package 名稱\n\t\t// Use directory name as default package name\n\t\tlet name = basename(targetPath);\n\n\t\t// 創建目標目錄(如果不存在)\n\t\t// Create target directory if it doesn't exist\n\t\tif (!existsSync(targetPath))\n\t\t{\n\t\t\tmkdirSync(targetPath);\n\t\t}\n\n\t\t// 合併預設配置與基本資訊\n\t\t// Merge default configuration with basic info\n\t\tpkg = Object.assign(getDefaultPackageJson(name), {\n\t\t\tname,\n\t\t\tworkspaces: packages,\n\t\t});\n\n\t\t/**\n\t\t * 執行自定義初始化回呼\n\t\t * Execute custom initialization callback\n\t\t */\n\t\tif (options.initPackageJson)\n\t\t{\n\t\t\tlet ret = options.initPackageJson(pkg);\n\n\t\t\tif (ret)\n\t\t\t{\n\t\t\t\tpkg = ret;\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t/**\n\t\t * 處理已存在的 package.json\n\t\t * Handle existing package.json\n\t\t */\n\t\tlet json: IPackageJson = JSON.parse(readFileSync(file).toString());\n\n\t\tlet workspaces: ILernaJson['packages'];\n\n\t\t/**\n\t\t * 解析現有的 workspaces 配置\n\t\t * Parse existing workspaces configuration\n\t\t */\n\t\tif (json.workspaces && Object.keys(json.workspaces).length)\n\t\t{\n\t\t\tworkspaces = json.workspaces;\n\n\t\t\t/**\n\t\t\t * 支援 nohoist 配置格式\n\t\t\t * Support nohoist configuration format\n\t\t\t * @see https://yarnpkg.com/blog/2018/02/15/nohoist/\n\t\t\t */\n\t\t\t// @ts-ignore\n\t\t\tpackages = workspaces.packages || workspaces;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tworkspaces = packages;\n\t\t}\n\n\t\t/**\n\t\t * 更新 Package.json 內容\n\t\t * Update package.json content\n\t\t */\n\t\tpkg = Object.assign(json, {\n\t\t\t\"private\": true,\n\t\t\t\"workspaces\": workspaces,\n\t\t});\n\n\t\t/**\n\t\t * 合併預設腳本與欄位\n\t\t * Merge default scripts and fields\n\t\t */\n\t\tObject.entries(getDefaultPackageJson(json.name))\n\t\t\t.forEach(([field, value]) => {\n\n\t\t\t\t/**\n\t\t\t\t * 特殊處理 scripts 欄位:合併而非覆蓋\n\t\t\t\t * Special handling for scripts field: merge instead of overwrite\n\t\t\t\t */\n\t\t\t\tif (field === 'scripts')\n\t\t\t\t{\n\t\t\t\t\tpkg.scripts ??= {};\n\t\t\t\t\tpkg.scripts = {\n\t\t\t\t\t\t// @ts-ignore\n\t\t\t\t\t\t...value,\n\t\t\t\t\t\t...pkg.scripts,\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// 使用空值合併運算子設置預設值\n\t\t\t\t\t// Use nullish coalescing operator for default values\n\t\t\t\t\tpkg[field] ??= value\n\t\t\t\t}\n\n\t\t\t})\n\t\t;\n\n\t}\n\n\t/**\n\t * 寫入格式化後的 package.json\n\t * Write formatted package.json\n\t */\n\tlet s = JSON.stringify(sortPackageJson(pkg), null, 2);\n\twriteFileSync(file, s);\n\n\tconsole.success(`create workspace package.json`);\n\n\t/**\n\t * 更新 Lerna 配置(如果存在且需要更新)\n\t * Update Lerna configuration if exists and needs updating\n\t */\n\tif (lerna && (packages != lerna.packages || lerna.npmClient !== 'yarn' || lerna['useWorkspaces'] !== true))\n\t{\n\t\tlet file = join(targetPath, 'lerna.json');\n\n\t\t// 更新為 Yarn Workspaces 模式\n\t\t// Update to Yarn Workspaces mode\n\t\tlerna.packages = packages;\n\t\tlerna.npmClient ??= 'pnpm';\n\t\t// lerna['useWorkspaces'] = true;\n\n\t\tlet s = JSON.stringify(sortPackageJson(lerna), null, 2);\n\t\twriteFileSync(file, s);\n\n\t\tconsole.info(`update lerna.json`);\n\t}\n\n\t/**\n\t * 複製靜態範本檔案\n\t * Copy static template files\n\t */\n\tconst file_map = getWsCopyStaticFiles();\n\n\t/**\n\t * 複製靜態範本檔案\n\t * Copy static template files\n\t *\n\t * 此呼叫點 addStaticFiles 預設為 true,可用 noStaticFiles 關閉\n\t * addStaticFiles defaults to true at this call site; disable it with noStaticFiles\n\t */\n\tif (_isAddStaticFilesOrReset(options, true))\n\t{\n\t\tcopyStaticFiles({\n\t\t\tcwd: targetPath,\n\t\t\tfile_map,\n\t\t});\n\t}\n\n\t/**\n\t * 根據 packages 模式創建目錄\n\t * Create directories based on packages pattern\n\t */\n\tcreateDirByPackages(targetPath, packages);\n\n\treturn true;\n}\n\n/**\n * 根據 packages 模式創建目錄\n * Create directories based on packages pattern\n *\n * 解析 packages 陣列中的目錄模式(如 \"packages/*\"),\n * 並創建對應的實體目錄。\n * Parses directory patterns from packages array (e.g., \"packages/*\")\n * and creates corresponding physical directories.\n *\n * @param cwd - 當前工作目錄 / Current working directory\n * @param packages - packages 模式陣列 / Array of package patterns\n * @returns 是否有創建任何目錄 / Whether any directories were created\n */\nexport function createDirByPackages(cwd: string, packages: string[])\n{\n\treturn packages.some(function (value)\n\t{\n\t\tlet bool: boolean;\n\n\t\t// 提取路徑的第一個部分(目錄名稱)\n\t\t// Extract first part of path (directory name)\n\t\tlet s = value.split(/[\\/\\\\]/)[0];\n\n\t\t/**\n\t\t * 只處理不包含 glob 模式的純目錄路徑\n\t\t * Only handle pure directory paths without glob patterns\n\t\t */\n\t\tif (!/[!?\\*{}\\[\\]]/.test(s))\n\t\t{\n\t\t\tlet dir = join(cwd, s);\n\n\t\t\t// 目錄不存在時創建 / Create directory if it doesn't exist\n\t\t\tif (!existsSync(dir))\n\t\t\t{\n\t\t\t\tmkdirSync(dir);\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\n\t\treturn bool;\n\t})\n}\n\n/**\n * 預設導出創建函式\n * Default export of creation function\n */\nexport default createYarnWorkspaces;\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;AAoBH,oDAkBC;AAaD,8DA6BC;;AA9ED,qCAAsF;AACtF,+CAAgG;AAEhG,sDAA4B;AAC5B,qDAA2B;AAE3B;;;;;;;;;;;GAWG;AACH,SAAgB,oBAAoB,CAAC,GAAY,EAAE,UAAoB,EAAE;IAExE,MAAM,QAAQ,GAAG,IAAA,8BAAuB,EAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAEvD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAChB,CAAC;QACA,OAAO,KAAK,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,IAAA,qBAAS,EAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEhE,IAAI,MAAM,CAAC,UAAU,EACrB,CAAC;QACA,wCAAwC;QACxC,IAAA,yBAAa,EAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,IAAA,4BAAqB,EAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;AACrE,CAAC;AAED;;;;;;;;;;GAUG;AACI,KAAK,UAAU,yBAAyB,CAAC,GAAY,EAAE,UAAoB,EAAE;IAEnF,MAAM,QAAQ,GAAG,IAAA,8BAAuB,EAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAEvD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAChB,CAAC;QACA,OAAO,KAAK,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,IAAA,qBAAS,EAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEhE,IAAI,MAAM,CAAC,UAAU,EACrB,CAAC;QACA,IAAI,QAAQ,CAAC,OAAO,CAAC,WAAW,IAAI,IAAA,6BAAiB,GAAE,EACvD,CAAC;YACA,uCAAuC;YACvC,IAAI,CAAC,MAAM,IAAA,4BAAgB,EAAC,MAAM,CAAC,EACnC,CAAC;gBACA,OAAO,KAAK,CAAC;YACd,CAAC;QACF,CAAC;aAED,CAAC;YACA,gCAAgC;YAChC,IAAA,yBAAa,EAAC,MAAM,CAAC,CAAC;QACvB,CAAC;IACF,CAAC;IAED,OAAO,IAAA,4BAAqB,EAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;AACrE,CAAC;AAED;;GAEG;AACH,kBAAe,oBAAoB,CAAC","sourcesContent":["/**\n * 創建 Workspaces 工具模組\n *\n * 提供初始化 Workspaces 專案結構的功能,\n * 包含 package.json 設定、\n * Lerna 整合、\n * 目錄創建與靜態檔案複製等功能。\n */\n\nimport { _createYarnWorkspaces, _precheckYarnWorkspaces, IOptions } from './lib/core';\nimport { _checkEnv, _checkInteractive, _confirmCheckEnv, _warnCheckEnv } from './lib/check-env';\n\nexport * from './lib/index';\nexport * from './lib/util';\n\n/**\n * 創建 Workspaces 主函式(同步)\n *\n * 檢查並創建 Workspaces 專案結構,處理已存在 Package 與父層 Workspaces 的情況。\n * 不支援互動介面:環境檢查發現疑似錯誤路徑時僅印出警告並繼續執行。\n *\n * @param cwd - 工作目錄路徑\n * @param options - 配置選項\n * @returns 是否成功創建\n *\n * @deprecated 請改用 `createYarnWorkspacesAsync` 以獲得更好的互動體驗\n */\nexport function createYarnWorkspaces(cwd?: string, options: IOptions = {})\n{\n\tconst precheck = _precheckYarnWorkspaces(cwd, options);\n\n\tif (!precheck.ok)\n\t{\n\t\treturn false;\n\t}\n\n\tconst report = _checkEnv(precheck.targetPath, precheck.options);\n\n\tif (report.suspicious)\n\t{\n\t\t/** sync 版本不支援互動介面:印出警告後繼續執行(原有邏輯機制)。 */\n\t\t_warnCheckEnv(report);\n\t}\n\n\treturn _createYarnWorkspaces(precheck.targetPath, precheck.options);\n}\n\n/**\n * 創建 Workspaces 主函式(非同步)\n *\n * 與 {@link createYarnWorkspaces} 相同,但當 `options.interactive` 啟用且環境具備 TTY 時,\n * 會依環境檢查報告透過互動介面詢問是否繼續;\n * 未啟用互動介面(或不具備 TTY)時與同步版本相同,僅印出警告並繼續執行。\n *\n * @param cwd - 工作目錄路徑\n * @param options - 配置選項\n * @returns 是否成功創建;使用者在互動介面取消時回傳 false\n */\nexport async function createYarnWorkspacesAsync(cwd?: string, options: IOptions = {})\n{\n\tconst precheck = _precheckYarnWorkspaces(cwd, options);\n\n\tif (!precheck.ok)\n\t{\n\t\treturn false;\n\t}\n\n\tconst report = _checkEnv(precheck.targetPath, precheck.options);\n\n\tif (report.suspicious)\n\t{\n\t\tif (precheck.options.interactive && _checkInteractive())\n\t\t{\n\t\t\t/** 依 _checkEnv 結果詢問是否疑似在錯誤路徑執行、仍要繼續 */\n\t\t\tif (!await _confirmCheckEnv(report))\n\t\t\t{\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t/** 未啟用互動介面:印出警告但繼續執行(原有邏輯機制) */\n\t\t\t_warnCheckEnv(report);\n\t\t}\n\t}\n\n\treturn _createYarnWorkspaces(precheck.targetPath, precheck.options);\n}\n\n/**\n * 預設導出創建函式\n */\nexport default createYarnWorkspaces;\n"]}
@@ -0,0 +1,42 @@
1
+ import type { IOptions } from './core';
2
+ /**
3
+ * `_checkEnv` 的環境檢查報告
4
+ */
5
+ export interface ICheckEnvReport {
6
+ /** 被檢查的工作目錄 */
7
+ cwd: string;
8
+ /** 已存在的 package.json 相對路徑(cwd 根目錄與第一層子目錄) */
9
+ files: string[];
10
+ /** 是否疑似在錯誤的路徑執行(任一處已存在 package.json) */
11
+ suspicious: boolean;
12
+ }
13
+ /**
14
+ * 檢查目標目錄與其子目錄是否已存在 package.json
15
+ *
16
+ * 掃描 cwd 根目錄與第一層子目錄(排除 node_modules),
17
+ * 產出可供警告輸出或互動介面顯示的報告。
18
+ *
19
+ * @param cwd - 要檢查的目錄
20
+ * @param options - 配置選項(保留供呼叫端傳遞,目前未使用)
21
+ * @returns 環境檢查報告
22
+ */
23
+ export declare function _checkEnv(cwd: string, options?: IOptions): ICheckEnvReport;
24
+ /**
25
+ * 以警告方式列出環境檢查報告並繼續執行
26
+ *
27
+ * 未啟用互動介面時的路徑:只印出警告,維持原有邏輯機制繼續創建。
28
+ *
29
+ * @param report - 環境檢查報告
30
+ */
31
+ export declare function _warnCheckEnv(report: ICheckEnvReport): void;
32
+ /**
33
+ * 列出環境檢查報告,並透過 @clack/prompts 詢問是否繼續
34
+ *
35
+ * @param report - 環境檢查報告
36
+ * @returns 使用者選擇繼續時回傳 true;取消或非布林回應(如 Ctrl+C)回傳 false
37
+ */
38
+ export declare function _confirmCheckEnv(report: ICheckEnvReport): Promise<boolean>;
39
+ /**
40
+ * 檢測是否具備互動能力
41
+ */
42
+ export declare function _checkInteractive(): boolean;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports._checkEnv = _checkEnv;
4
+ exports._warnCheckEnv = _warnCheckEnv;
5
+ exports._confirmCheckEnv = _confirmCheckEnv;
6
+ exports._checkInteractive = _checkInteractive;
7
+ const tslib_1 = require("tslib");
8
+ const fast_glob_1 = require("fast-glob");
9
+ const logger_1 = require("debug-color2/logger");
10
+ const p = tslib_1.__importStar(require("@clack/prompts"));
11
+ /**
12
+ * 檢查目標目錄與其子目錄是否已存在 package.json
13
+ *
14
+ * 掃描 cwd 根目錄與第一層子目錄(排除 node_modules),
15
+ * 產出可供警告輸出或互動介面顯示的報告。
16
+ *
17
+ * @param cwd - 要檢查的目錄
18
+ * @param options - 配置選項(保留供呼叫端傳遞,目前未使用)
19
+ * @returns 環境檢查報告
20
+ */
21
+ function _checkEnv(cwd, options = {}) {
22
+ const files = (0, fast_glob_1.sync)([
23
+ 'package.json',
24
+ '*/package.json',
25
+ '!node_modules/**',
26
+ '!node_modules',
27
+ ], {
28
+ cwd,
29
+ onlyFiles: true,
30
+ objectMode: false,
31
+ deep: 2,
32
+ }).sort();
33
+ return {
34
+ cwd,
35
+ files,
36
+ /** 任一處已存在 package.json 即視為疑似在錯誤的路徑執行 */
37
+ suspicious: !!files.length,
38
+ };
39
+ }
40
+ /**
41
+ * 以警告方式列出環境檢查報告並繼續執行
42
+ *
43
+ * 未啟用互動介面時的路徑:只印出警告,維持原有邏輯機制繼續創建。
44
+ *
45
+ * @param report - 環境檢查報告
46
+ */
47
+ function _warnCheckEnv(report) {
48
+ _printCheckEnvReport(report);
49
+ logger_1.consoleLogger.warn(`continue anyway`);
50
+ }
51
+ /**
52
+ * 列出環境檢查報告,並透過 @clack/prompts 詢問是否繼續
53
+ *
54
+ * @param report - 環境檢查報告
55
+ * @returns 使用者選擇繼續時回傳 true;取消或非布林回應(如 Ctrl+C)回傳 false
56
+ */
57
+ async function _confirmCheckEnv(report) {
58
+ p.intro(`create-yarn-workspaces`);
59
+ _printCheckEnvReport(report);
60
+ const ret = await p.confirm({
61
+ message: `detected existing package.json, continue anyway?`,
62
+ initialValue: false,
63
+ });
64
+ /** 取消(Ctrl+C / 非布林回應)時不繼續創建 */
65
+ if (typeof ret !== 'boolean') {
66
+ p.outro(`cancelled`);
67
+ return false;
68
+ }
69
+ p.outro(ret ? `continue` : `cancelled`);
70
+ return ret;
71
+ }
72
+ /**
73
+ * 列出報告中的既有 package.json,供警告與互動介面共用同一份輸出
74
+ */
75
+ function _printCheckEnvReport(report) {
76
+ logger_1.consoleLogger.warn(`detected existing package.json in "${report.cwd}", possible wrong path`);
77
+ report.files.forEach(function (file) {
78
+ logger_1.consoleLogger.warn(` - ${file}`);
79
+ });
80
+ }
81
+ /**
82
+ * 檢測是否具備互動能力
83
+ */
84
+ function _checkInteractive() {
85
+ return process.stdout.isTTY && process.stdin.isTTY;
86
+ }
87
+ //# sourceMappingURL=check-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check-env.js","sourceRoot":"","sources":["check-env.ts"],"names":[],"mappings":";;AA8BA,8BAoBC;AASD,sCAKC;AAQD,4CAsBC;AAkBD,8CAGC;;AAnHD,yCAA6C;AAC7C,gDAA+D;AAC/D,0DAAoC;AAkBpC;;;;;;;;;GASG;AACH,SAAgB,SAAS,CAAC,GAAW,EAAE,UAAoB,EAAE;IAE5D,MAAM,KAAK,GAAG,IAAA,gBAAQ,EAAC;QACtB,cAAc;QACd,gBAAgB;QAChB,kBAAkB;QAClB,eAAe;KACf,EAAE;QACF,GAAG;QACH,SAAS,EAAE,IAAI;QACf,UAAU,EAAE,KAAK;QACjB,IAAI,EAAE,CAAC;KACP,CAAC,CAAC,IAAI,EAAE,CAAC;IAEV,OAAO;QACN,GAAG;QACH,KAAK;QACL,wCAAwC;QACxC,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM;KAC1B,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,aAAa,CAAC,MAAuB;IAEpD,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAE7B,sBAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;AACjC,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,gBAAgB,CAAC,MAAuB;IAE7D,CAAC,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAElC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAE7B,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC;QAC3B,OAAO,EAAE,kDAAkD;QAC3D,YAAY,EAAE,KAAK;KACnB,CAAC,CAAC;IAEH,+BAA+B;IAC/B,IAAI,OAAO,GAAG,KAAK,SAAS,EAC5B,CAAC;QACA,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAErB,OAAO,KAAK,CAAC;IACd,CAAC;IAED,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAExC,OAAO,GAAG,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,MAAuB;IAEpD,sBAAO,CAAC,IAAI,CAAC,sCAAsC,MAAM,CAAC,GAAG,wBAAwB,CAAC,CAAC;IAEvF,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,IAAI;QAElC,sBAAO,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB;IAEhC,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;AACpD,CAAC","sourcesContent":["import { sync as globSync } from 'fast-glob';\nimport { consoleLogger as console } from 'debug-color2/logger';\nimport * as p from '@clack/prompts';\nimport type { IOptions } from './core';\n\n/**\n * `_checkEnv` 的環境檢查報告\n */\nexport interface ICheckEnvReport\n{\n\t/** 被檢查的工作目錄 */\n\tcwd: string,\n\n\t/** 已存在的 package.json 相對路徑(cwd 根目錄與第一層子目錄) */\n\tfiles: string[],\n\n\t/** 是否疑似在錯誤的路徑執行(任一處已存在 package.json) */\n\tsuspicious: boolean,\n}\n\n/**\n * 檢查目標目錄與其子目錄是否已存在 package.json\n *\n * 掃描 cwd 根目錄與第一層子目錄(排除 node_modules),\n * 產出可供警告輸出或互動介面顯示的報告。\n *\n * @param cwd - 要檢查的目錄\n * @param options - 配置選項(保留供呼叫端傳遞,目前未使用)\n * @returns 環境檢查報告\n */\nexport function _checkEnv(cwd: string, options: IOptions = {}): ICheckEnvReport\n{\n\tconst files = globSync([\n\t\t'package.json',\n\t\t'*/package.json',\n\t\t'!node_modules/**',\n\t\t'!node_modules',\n\t], {\n\t\tcwd,\n\t\tonlyFiles: true,\n\t\tobjectMode: false,\n\t\tdeep: 2,\n\t}).sort();\n\n\treturn {\n\t\tcwd,\n\t\tfiles,\n\t\t/** 任一處已存在 package.json 即視為疑似在錯誤的路徑執行 */\n\t\tsuspicious: !!files.length,\n\t};\n}\n\n/**\n * 以警告方式列出環境檢查報告並繼續執行\n *\n * 未啟用互動介面時的路徑:只印出警告,維持原有邏輯機制繼續創建。\n *\n * @param report - 環境檢查報告\n */\nexport function _warnCheckEnv(report: ICheckEnvReport)\n{\n\t_printCheckEnvReport(report);\n\n\tconsole.warn(`continue anyway`);\n}\n\n/**\n * 列出環境檢查報告,並透過 @clack/prompts 詢問是否繼續\n *\n * @param report - 環境檢查報告\n * @returns 使用者選擇繼續時回傳 true;取消或非布林回應(如 Ctrl+C)回傳 false\n */\nexport async function _confirmCheckEnv(report: ICheckEnvReport): Promise<boolean>\n{\n\tp.intro(`create-yarn-workspaces`);\n\n\t_printCheckEnvReport(report);\n\n\tconst ret = await p.confirm({\n\t\tmessage: `detected existing package.json, continue anyway?`,\n\t\tinitialValue: false,\n\t});\n\n\t/** 取消(Ctrl+C / 非布林回應)時不繼續創建 */\n\tif (typeof ret !== 'boolean')\n\t{\n\t\tp.outro(`cancelled`);\n\n\t\treturn false;\n\t}\n\n\tp.outro(ret ? `continue` : `cancelled`);\n\n\treturn ret;\n}\n\n/**\n * 列出報告中的既有 package.json,供警告與互動介面共用同一份輸出\n */\nfunction _printCheckEnvReport(report: ICheckEnvReport)\n{\n\tconsole.warn(`detected existing package.json in \"${report.cwd}\", possible wrong path`);\n\n\treport.files.forEach(function (file)\n\t{\n\t\tconsole.warn(` - ${file}`);\n\t});\n}\n\n/**\n * 檢測是否具備互動能力\n */\nexport function _checkInteractive()\n{\n\treturn process.stdout.isTTY && process.stdin.isTTY;\n}\n"]}
package/lib/core.d.ts ADDED
@@ -0,0 +1,85 @@
1
+ import { INpmAutoFixAll } from '@yarn-tool/fix-all';
2
+ import { IPackageJson } from '@ts-type/package-dts/package-json';
3
+ /**
4
+ * 創建 Workspaces 的選項介面
5
+ */
6
+ export interface IOptions extends Pick<INpmAutoFixAll, 'addStaticFiles' | 'noStaticFiles'> {
7
+ /**
8
+ * 工作目錄路徑
9
+ */
10
+ cwd?: string;
11
+ /**
12
+ * 忽略父層 Workspaces
13
+ */
14
+ ignoreParentWorkspaces?: boolean;
15
+ /**
16
+ * 忽略已存在的 Package
17
+ */
18
+ ignoreExistsPackage?: boolean;
19
+ /**
20
+ * 初始化 Package.json 的回呼函式
21
+ * @template T - 擴展屬性類型
22
+ * @param current - 當前的 package.json
23
+ * @returns 修改後的 package.json
24
+ */
25
+ initPackageJson?<T extends Record<string, any> = {}>(current: IPackageJson): IPackageJson & T;
26
+ /**
27
+ * 啟用除錯模式
28
+ */
29
+ debug?: boolean;
30
+ /**
31
+ * 啟用互動介面
32
+ *
33
+ * 僅 `createYarnWorkspacesAsync` 支援,sync 版本會忽略此選項;
34
+ * 需環境具備 TTY,且在 `_checkEnv` 判定疑似錯誤路徑時才會詢問是否繼續。
35
+ */
36
+ interactive?: boolean;
37
+ }
38
+ /**
39
+ * `createYarnWorkspaces` 的前置檢查結果
40
+ */
41
+ export interface IPrecheckResult {
42
+ /** 是否可繼續執行創建流程 */
43
+ ok: boolean;
44
+ /** 實際要初始化的目標路徑:優先採用既有 package 根目錄,否則退回 cwd。 */
45
+ targetPath: string;
46
+ /** 經參數正規化後的配置選項(第一個參數可能直接傳入選項物件) */
47
+ options: IOptions;
48
+ }
49
+ /**
50
+ * 創建 Workspaces 的核心前置檢查邏輯
51
+ *
52
+ * 處理參數正規化、尋找專案根目錄,並檢查:
53
+ * - 是否已存在 Package
54
+ * - 是否已存在(父層)Workspaces
55
+ *
56
+ * @param cwd - 工作目錄路徑;也可直接傳入 IOptions
57
+ * @param options - 配置選項
58
+ * @returns 前置檢查結果;`ok` 為 false 時不應繼續創建
59
+ */
60
+ export declare function _precheckYarnWorkspaces(cwd?: string, options?: IOptions): IPrecheckResult;
61
+ /**
62
+ * 內部創建 Workspaces 實作函式
63
+ *
64
+ * 執行實際的 Workspaces 初始化工作,包含:
65
+ * - 讀取並更新 Lerna 配置
66
+ * - 創建或更新 package.json
67
+ * - 複製靜態範本檔案
68
+ * - 創建 packages 目錄
69
+ *
70
+ * @param targetPath - 目標路徑
71
+ * @param options - 配置選項
72
+ * @returns 是否成功
73
+ */
74
+ export declare function _createYarnWorkspaces(targetPath: string, options?: IOptions): boolean;
75
+ /**
76
+ * 根據 packages 模式創建目錄
77
+ *
78
+ * 解析 packages 陣列中的目錄模式(如 "packages/*"),
79
+ * 並創建對應的實體目錄。
80
+ *
81
+ * @param cwd - 當前工作目錄
82
+ * @param packages - packages 模式陣列
83
+ * @returns 是否有創建任何目錄
84
+ */
85
+ export declare function createDirByPackages(cwd: string, packages: string[]): boolean;