@icebreakers/monorepo 3.2.14 → 3.2.16
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/dist/cli.cjs +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/index.cjs +15 -1
- package/dist/index.d.cts +26 -5
- package/dist/index.d.mts +27 -6
- package/dist/index.mjs +2 -2
- package/dist/{upgrade-BGgjWFfq.mjs → upgrade-C0Gz88iI.mjs} +219 -355
- package/dist/{upgrade-C2M-cSL9.cjs → upgrade-C9HSrDIr.cjs} +363 -394
- package/package.json +5 -10
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
//#region \0rolldown/runtime.js
|
|
2
2
|
var __create = Object.create;
|
|
3
|
-
var __defProp
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
9
8
|
var __copyProps = (to, from, except, desc) => {
|
|
10
9
|
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
10
|
key = keys[i];
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
12
|
get: ((k) => from[k]).bind(null, key),
|
|
14
13
|
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
14
|
});
|
|
16
15
|
}
|
|
17
16
|
return to;
|
|
18
17
|
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
19
|
value: mod,
|
|
21
20
|
enumerable: true
|
|
22
21
|
}) : target, mod));
|
|
@@ -31,10 +30,13 @@ let pathe = require("pathe");
|
|
|
31
30
|
pathe = __toESM(pathe);
|
|
32
31
|
let node_process = require("node:process");
|
|
33
32
|
node_process = __toESM(node_process);
|
|
34
|
-
let
|
|
35
|
-
fs_extra = __toESM(fs_extra);
|
|
33
|
+
let node_fs_promises = require("node:fs/promises");
|
|
36
34
|
let consola = require("consola");
|
|
37
35
|
let _icebreakers_monorepo_templates = require("@icebreakers/monorepo-templates");
|
|
36
|
+
let yaml = require("yaml");
|
|
37
|
+
yaml = __toESM(yaml);
|
|
38
|
+
let node_crypto = require("node:crypto");
|
|
39
|
+
node_crypto = __toESM(node_crypto);
|
|
38
40
|
let c12 = require("c12");
|
|
39
41
|
let node_os = require("node:os");
|
|
40
42
|
node_os = __toESM(node_os);
|
|
@@ -44,10 +46,6 @@ let node_url = require("node:url");
|
|
|
44
46
|
let picocolors = require("picocolors");
|
|
45
47
|
picocolors = __toESM(picocolors);
|
|
46
48
|
require("@pnpm/types");
|
|
47
|
-
let yaml = require("yaml");
|
|
48
|
-
yaml = __toESM(yaml);
|
|
49
|
-
let node_crypto = require("node:crypto");
|
|
50
|
-
node_crypto = __toESM(node_crypto);
|
|
51
49
|
let comment_json = require("comment-json");
|
|
52
50
|
let p_queue = require("p-queue");
|
|
53
51
|
p_queue = __toESM(p_queue);
|
|
@@ -55,73 +53,6 @@ let klaw = require("klaw");
|
|
|
55
53
|
klaw = __toESM(klaw);
|
|
56
54
|
let node_buffer = require("node:buffer");
|
|
57
55
|
let semver = require("semver");
|
|
58
|
-
//#region ../../node_modules/.pnpm/get-value@4.0.1/node_modules/get-value/dist/index.mjs
|
|
59
|
-
var __defProp = Object.defineProperty;
|
|
60
|
-
var __name = (target, value) => __defProp(target, "name", {
|
|
61
|
-
value,
|
|
62
|
-
configurable: true
|
|
63
|
-
});
|
|
64
|
-
var isObject = /* @__PURE__ */ __name((v) => v !== null && typeof v === "object", "isObject");
|
|
65
|
-
var join = /* @__PURE__ */ __name((segs, joinChar, options) => {
|
|
66
|
-
if (typeof options.join === "function") return options.join(segs);
|
|
67
|
-
return segs[0] + joinChar + segs[1];
|
|
68
|
-
}, "join");
|
|
69
|
-
var split = /* @__PURE__ */ __name((path, splitChar, options) => {
|
|
70
|
-
if (typeof options.split === "function") return options.split(path);
|
|
71
|
-
return path.split(splitChar);
|
|
72
|
-
}, "split");
|
|
73
|
-
var isValid = /* @__PURE__ */ __name((key, target = {}, options) => {
|
|
74
|
-
if (typeof options?.isValid === "function") return options.isValid(key, target);
|
|
75
|
-
return true;
|
|
76
|
-
}, "isValid");
|
|
77
|
-
var isValidObject = /* @__PURE__ */ __name((v) => {
|
|
78
|
-
return isObject(v) || typeof v === "function";
|
|
79
|
-
}, "isValidObject");
|
|
80
|
-
var index_default = /* @__PURE__ */ __name((target, path, options = {}) => {
|
|
81
|
-
if (!isObject(options)) options = { default: options };
|
|
82
|
-
if (!isValidObject(target)) return typeof options.default !== "undefined" ? options.default : target;
|
|
83
|
-
if (typeof path === "number") path = String(path);
|
|
84
|
-
const pathIsArray = Array.isArray(path);
|
|
85
|
-
const pathIsString = typeof path === "string";
|
|
86
|
-
const splitChar = options.separator || ".";
|
|
87
|
-
const joinChar = options.joinChar || (typeof splitChar === "string" ? splitChar : ".");
|
|
88
|
-
if (!pathIsString && !pathIsArray) return target;
|
|
89
|
-
if (target[path] !== void 0) return isValid(path, target, options) ? target[path] : options.default;
|
|
90
|
-
const segs = pathIsArray ? path : split(path, splitChar, options);
|
|
91
|
-
const len = segs.length;
|
|
92
|
-
let idx = 0;
|
|
93
|
-
do {
|
|
94
|
-
let prop = segs[idx];
|
|
95
|
-
if (typeof prop !== "string") prop = String(prop);
|
|
96
|
-
while (prop && prop.slice(-1) === "\\") prop = join([prop.slice(0, -1), segs[++idx] || ""], joinChar, options);
|
|
97
|
-
if (target[prop] !== void 0) {
|
|
98
|
-
if (!isValid(prop, target, options)) return options.default;
|
|
99
|
-
target = target[prop];
|
|
100
|
-
} else {
|
|
101
|
-
let hasProp = false;
|
|
102
|
-
let n = idx + 1;
|
|
103
|
-
while (n < len) {
|
|
104
|
-
prop = join([prop, segs[n++]], joinChar, options);
|
|
105
|
-
if (hasProp = target[prop] !== void 0) {
|
|
106
|
-
if (!isValid(prop, target, options)) return options.default;
|
|
107
|
-
target = target[prop];
|
|
108
|
-
idx = n - 1;
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (!hasProp) return options.default;
|
|
113
|
-
}
|
|
114
|
-
} while (++idx < len && isValidObject(target));
|
|
115
|
-
if (idx === len) return target;
|
|
116
|
-
return options.default;
|
|
117
|
-
}, "getValue");
|
|
118
|
-
/*!
|
|
119
|
-
* get-value <https://github.com/jonschlinkert/get-value>
|
|
120
|
-
*
|
|
121
|
-
* Copyright (c) 2014-present, Jon Schlinkert.
|
|
122
|
-
* Released under the MIT License.
|
|
123
|
-
*/
|
|
124
|
-
//#endregion
|
|
125
56
|
//#region src/core/git.ts
|
|
126
57
|
/**
|
|
127
58
|
* 对 simple-git 的轻量封装,集中处理配置缓存与常用查询。
|
|
@@ -156,8 +87,8 @@ var GitClient = class {
|
|
|
156
87
|
* 解析 remote.origin.url,返回 git-url-parse 的结构,便于获取仓库元信息。
|
|
157
88
|
*/
|
|
158
89
|
async getGitUrl() {
|
|
159
|
-
const x =
|
|
160
|
-
if (x) return (0, git_url_parse.default)(x);
|
|
90
|
+
const x = (await this.getConfig())["remote.origin.url"];
|
|
91
|
+
if (typeof x === "string") return (0, git_url_parse.default)(x);
|
|
161
92
|
}
|
|
162
93
|
/**
|
|
163
94
|
* 组合 owner/name,生成常用的仓库名表达。
|
|
@@ -172,8 +103,8 @@ var GitClient = class {
|
|
|
172
103
|
async getUser() {
|
|
173
104
|
const config = await this.getConfig();
|
|
174
105
|
return {
|
|
175
|
-
name:
|
|
176
|
-
email:
|
|
106
|
+
name: config["user.name"],
|
|
107
|
+
email: config["user.email"]
|
|
177
108
|
};
|
|
178
109
|
}
|
|
179
110
|
/**
|
|
@@ -267,6 +198,90 @@ async function getWorkspaceData(cwd, options) {
|
|
|
267
198
|
};
|
|
268
199
|
}
|
|
269
200
|
//#endregion
|
|
201
|
+
//#region src/utils/fs.ts
|
|
202
|
+
function stringifyJson(data, options) {
|
|
203
|
+
return JSON.stringify(data, void 0, options?.spaces);
|
|
204
|
+
}
|
|
205
|
+
async function ensureParentDir(targetPath) {
|
|
206
|
+
await (0, node_fs_promises.mkdir)(pathe.default.dirname(targetPath), { recursive: true });
|
|
207
|
+
}
|
|
208
|
+
async function pathExists(targetPath) {
|
|
209
|
+
try {
|
|
210
|
+
await (0, node_fs_promises.access)(targetPath);
|
|
211
|
+
return true;
|
|
212
|
+
} catch {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const exists = pathExists;
|
|
217
|
+
async function ensureDir(targetPath) {
|
|
218
|
+
await (0, node_fs_promises.mkdir)(targetPath, { recursive: true });
|
|
219
|
+
}
|
|
220
|
+
async function ensureFile(targetPath) {
|
|
221
|
+
await ensureParentDir(targetPath);
|
|
222
|
+
await (await (0, node_fs_promises.open)(targetPath, "a")).close();
|
|
223
|
+
}
|
|
224
|
+
async function remove(targetPath) {
|
|
225
|
+
await (0, node_fs_promises.rm)(targetPath, {
|
|
226
|
+
recursive: true,
|
|
227
|
+
force: true,
|
|
228
|
+
maxRetries: 3,
|
|
229
|
+
retryDelay: 100
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
async function copy(sourcePath, targetPath) {
|
|
233
|
+
await (0, node_fs_promises.cp)(sourcePath, targetPath, {
|
|
234
|
+
recursive: true,
|
|
235
|
+
force: true
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
async function outputFile(targetPath, data, options) {
|
|
239
|
+
await ensureParentDir(targetPath);
|
|
240
|
+
await (0, node_fs_promises.writeFile)(targetPath, data, options);
|
|
241
|
+
}
|
|
242
|
+
async function readJson(targetPath) {
|
|
243
|
+
return JSON.parse(await (0, node_fs_promises.readFile)(targetPath, "utf8"));
|
|
244
|
+
}
|
|
245
|
+
const readJSON = readJson;
|
|
246
|
+
async function writeJson(targetPath, data, options) {
|
|
247
|
+
await (0, node_fs_promises.writeFile)(targetPath, stringifyJson(data, options), "utf8");
|
|
248
|
+
}
|
|
249
|
+
const writeJSON = writeJson;
|
|
250
|
+
async function outputJson(targetPath, data, options) {
|
|
251
|
+
await ensureParentDir(targetPath);
|
|
252
|
+
await writeJson(targetPath, data, options);
|
|
253
|
+
}
|
|
254
|
+
const outputJSON = outputJson;
|
|
255
|
+
/**
|
|
256
|
+
* 判断是否为可忽略的文件系统错误。
|
|
257
|
+
* - ENOENT: 文件已被删除
|
|
258
|
+
* - EBUSY: Windows 中资源被系统占用
|
|
259
|
+
*/
|
|
260
|
+
function isIgnorableFsError(error) {
|
|
261
|
+
if (!error) return false;
|
|
262
|
+
const code = error.code;
|
|
263
|
+
return code === "ENOENT" || code === "EBUSY" || code === "EEXIST";
|
|
264
|
+
}
|
|
265
|
+
const fs = {
|
|
266
|
+
copy,
|
|
267
|
+
ensureDir,
|
|
268
|
+
ensureFile,
|
|
269
|
+
exists,
|
|
270
|
+
mkdtemp: node_fs_promises.mkdtemp,
|
|
271
|
+
outputFile,
|
|
272
|
+
outputJSON,
|
|
273
|
+
outputJson,
|
|
274
|
+
pathExists,
|
|
275
|
+
readFile: node_fs_promises.readFile,
|
|
276
|
+
readJSON,
|
|
277
|
+
readJson,
|
|
278
|
+
remove,
|
|
279
|
+
stat: node_fs_promises.stat,
|
|
280
|
+
writeFile: node_fs_promises.writeFile,
|
|
281
|
+
writeJSON,
|
|
282
|
+
writeJson
|
|
283
|
+
};
|
|
284
|
+
//#endregion
|
|
270
285
|
//#region src/core/logger.ts
|
|
271
286
|
/**
|
|
272
287
|
* 统一的日志实例,便于在命令行中输出带有前缀和颜色的消息。
|
|
@@ -314,17 +329,17 @@ async function generateAgenticTemplate(options = {}) {
|
|
|
314
329
|
}
|
|
315
330
|
const targetPath = pathe.default.resolve(cwd, outputPath);
|
|
316
331
|
const targetDir = pathe.default.dirname(targetPath);
|
|
317
|
-
await
|
|
318
|
-
const exists = await
|
|
332
|
+
await fs.ensureDir(targetDir);
|
|
333
|
+
const exists = await fs.pathExists(targetPath);
|
|
319
334
|
if (exists && !options.force) throw new Error(`目标文件已存在:${pathe.default.relative(cwd, targetPath)}`);
|
|
320
|
-
await
|
|
335
|
+
await fs.outputFile(targetPath, template, "utf8");
|
|
321
336
|
const actionLabel = exists ? "已覆盖模板" : "已生成模板";
|
|
322
337
|
logger.success(`${actionLabel}:${pathe.default.relative(cwd, targetPath)}`);
|
|
323
338
|
return template;
|
|
324
339
|
}
|
|
325
340
|
async function loadAgenticTasks(filePath, cwd) {
|
|
326
341
|
const fullPath = pathe.default.resolve(cwd, filePath);
|
|
327
|
-
const tasks = await
|
|
342
|
+
const tasks = await fs.readJson(fullPath);
|
|
328
343
|
if (!Array.isArray(tasks)) throw new TypeError("任务清单需要是数组");
|
|
329
344
|
return tasks;
|
|
330
345
|
}
|
|
@@ -343,169 +358,126 @@ async function generateAgenticTemplates(tasks, defaults = {}) {
|
|
|
343
358
|
return results;
|
|
344
359
|
}
|
|
345
360
|
//#endregion
|
|
346
|
-
//#region
|
|
347
|
-
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
* Copyright (c) 2014-present, Jon Schlinkert.
|
|
351
|
-
* Released under the MIT License.
|
|
361
|
+
//#region src/utils/github.ts
|
|
362
|
+
/**
|
|
363
|
+
* 将 Issue 模版里的 discussions 链接同步为当前仓库的 discussions 地址。
|
|
352
364
|
*/
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
365
|
+
function updateIssueTemplateConfig(source, repoName) {
|
|
366
|
+
if (!repoName) return source;
|
|
367
|
+
let doc;
|
|
368
|
+
try {
|
|
369
|
+
doc = (0, yaml.parseDocument)(source);
|
|
370
|
+
} catch {
|
|
371
|
+
return source;
|
|
372
|
+
}
|
|
373
|
+
const contactLinks = doc.get("contact_links");
|
|
374
|
+
if (!(0, yaml.isSeq)(contactLinks)) return source;
|
|
375
|
+
const nextUrl = `https://github.com/${repoName}/discussions`;
|
|
376
|
+
let changed = false;
|
|
377
|
+
contactLinks.items.forEach((_, index) => {
|
|
378
|
+
const url = doc.getIn([
|
|
379
|
+
"contact_links",
|
|
380
|
+
index,
|
|
381
|
+
"url"
|
|
382
|
+
]);
|
|
383
|
+
if (typeof url !== "string") return;
|
|
384
|
+
if (!url.includes("/discussions")) return;
|
|
385
|
+
if (url === nextUrl) return;
|
|
386
|
+
doc.setIn([
|
|
387
|
+
"contact_links",
|
|
388
|
+
index,
|
|
389
|
+
"url"
|
|
390
|
+
], nextUrl);
|
|
391
|
+
changed = true;
|
|
392
|
+
});
|
|
393
|
+
if (!changed) return source;
|
|
394
|
+
return doc.toString();
|
|
395
|
+
}
|
|
359
396
|
//#endregion
|
|
360
|
-
//#region
|
|
361
|
-
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
* Copyright (c) 2014-2017, Jon Schlinkert.
|
|
365
|
-
* Released under the MIT License.
|
|
397
|
+
//#region src/utils/hash.ts
|
|
398
|
+
/**
|
|
399
|
+
* 生成给定二进制内容的 md5 摘要,用于快速比较文件内容。
|
|
366
400
|
*/
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
/*!
|
|
375
|
-
* is-plain-object <https://github.com/jonschlinkert/is-plain-object>
|
|
376
|
-
*
|
|
377
|
-
* Copyright (c) 2014-2017, Jon Schlinkert.
|
|
378
|
-
* Released under the MIT License.
|
|
401
|
+
function getFileHash(data) {
|
|
402
|
+
const hashSum = node_crypto.default.createHash("md5");
|
|
403
|
+
hashSum.update(data);
|
|
404
|
+
return hashSum.digest("hex");
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* 对比两个文件的 md5,如果不一致则认为内容有变化。
|
|
379
408
|
*/
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
ctor = o.constructor;
|
|
389
|
-
if (typeof ctor !== "function") return false;
|
|
390
|
-
prot = ctor.prototype;
|
|
391
|
-
if (isObjectObject(prot) === false) return false;
|
|
392
|
-
if (prot.hasOwnProperty("isPrototypeOf") === false) return false;
|
|
393
|
-
return true;
|
|
394
|
-
};
|
|
395
|
-
}));
|
|
409
|
+
function isFileChanged(src, dest) {
|
|
410
|
+
try {
|
|
411
|
+
return getFileHash(src) !== getFileHash(dest);
|
|
412
|
+
} catch (err) {
|
|
413
|
+
logger.error("Error calculating file hash:", err);
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
396
417
|
//#endregion
|
|
397
|
-
//#region
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
const isUnsafeKey = (key) => {
|
|
412
|
-
return key === "__proto__" || key === "constructor" || key === "prototype";
|
|
413
|
-
};
|
|
414
|
-
const validateKey = (key) => {
|
|
415
|
-
if (!isPrimitive(key)) throw new TypeError("Object keys must be strings or symbols");
|
|
416
|
-
if (isUnsafeKey(key)) throw new Error(`Cannot set unsafe key: "${key}"`);
|
|
417
|
-
};
|
|
418
|
-
const toStringKey = (input) => {
|
|
419
|
-
return Array.isArray(input) ? input.flat().map(String).join(",") : input;
|
|
420
|
-
};
|
|
421
|
-
const createMemoKey = (input, options) => {
|
|
422
|
-
if (typeof input !== "string" || !options) return input;
|
|
423
|
-
let key = input + ";";
|
|
424
|
-
if (options.arrays !== void 0) key += `arrays=${options.arrays};`;
|
|
425
|
-
if (options.separator !== void 0) key += `separator=${options.separator};`;
|
|
426
|
-
if (options.split !== void 0) key += `split=${options.split};`;
|
|
427
|
-
if (options.merge !== void 0) key += `merge=${options.merge};`;
|
|
428
|
-
if (options.preservePaths !== void 0) key += `preservePaths=${options.preservePaths};`;
|
|
429
|
-
return key;
|
|
430
|
-
};
|
|
431
|
-
const memoize = (input, options, fn) => {
|
|
432
|
-
const key = toStringKey(options ? createMemoKey(input, options) : input);
|
|
433
|
-
validateKey(key);
|
|
434
|
-
const value = setValue.cache.get(key) || fn();
|
|
435
|
-
setValue.cache.set(key, value);
|
|
436
|
-
return value;
|
|
437
|
-
};
|
|
438
|
-
const splitString = (input, options = {}) => {
|
|
439
|
-
const sep = options.separator || ".";
|
|
440
|
-
const preserve = sep === "/" ? false : options.preservePaths;
|
|
441
|
-
if (typeof input === "string" && preserve !== false && /\//.test(input)) return [input];
|
|
442
|
-
const parts = [];
|
|
443
|
-
let part = "";
|
|
444
|
-
const push = (part) => {
|
|
445
|
-
let number;
|
|
446
|
-
if (part.trim() !== "" && Number.isInteger(number = Number(part))) parts.push(number);
|
|
447
|
-
else parts.push(part);
|
|
448
|
-
};
|
|
449
|
-
for (let i = 0; i < input.length; i++) {
|
|
450
|
-
const value = input[i];
|
|
451
|
-
if (value === "\\") {
|
|
452
|
-
part += input[++i];
|
|
453
|
-
continue;
|
|
454
|
-
}
|
|
455
|
-
if (value === sep) {
|
|
456
|
-
push(part);
|
|
457
|
-
part = "";
|
|
458
|
-
continue;
|
|
459
|
-
}
|
|
460
|
-
part += value;
|
|
418
|
+
//#region src/utils/object.ts
|
|
419
|
+
const arrayIndexPattern = /^\d+$/;
|
|
420
|
+
function isArrayIndex(value) {
|
|
421
|
+
return arrayIndexPattern.test(value);
|
|
422
|
+
}
|
|
423
|
+
function parsePath(input) {
|
|
424
|
+
const segments = [];
|
|
425
|
+
let current = "";
|
|
426
|
+
let escaped = false;
|
|
427
|
+
for (const char of input) {
|
|
428
|
+
if (escaped) {
|
|
429
|
+
current += char;
|
|
430
|
+
escaped = false;
|
|
431
|
+
continue;
|
|
461
432
|
}
|
|
462
|
-
if (
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
const split = (input, options) => {
|
|
466
|
-
if (options && typeof options.split === "function") return options.split(input);
|
|
467
|
-
if (typeof input === "symbol") return [input];
|
|
468
|
-
if (Array.isArray(input)) return input;
|
|
469
|
-
return memoize(input, options, () => splitString(input, options));
|
|
470
|
-
};
|
|
471
|
-
const assignProp = (obj, prop, value, options) => {
|
|
472
|
-
validateKey(prop);
|
|
473
|
-
if (value === void 0) deleteProperty(obj, prop);
|
|
474
|
-
else if (options && options.merge) {
|
|
475
|
-
const merge = options.merge === "function" ? options.merge : Object.assign;
|
|
476
|
-
if (merge && isPlainObject(obj[prop]) && isPlainObject(value)) obj[prop] = merge(obj[prop], value);
|
|
477
|
-
else obj[prop] = value;
|
|
478
|
-
} else obj[prop] = value;
|
|
479
|
-
return obj;
|
|
480
|
-
};
|
|
481
|
-
const setValue = (target, path, value, options) => {
|
|
482
|
-
if (!path || !isObject(target)) return target;
|
|
483
|
-
const keys = split(path, options);
|
|
484
|
-
let obj = target;
|
|
485
|
-
for (let i = 0; i < keys.length; i++) {
|
|
486
|
-
const key = keys[i];
|
|
487
|
-
const next = keys[i + 1];
|
|
488
|
-
validateKey(key);
|
|
489
|
-
if (next === void 0) {
|
|
490
|
-
assignProp(obj, key, value, options);
|
|
491
|
-
break;
|
|
492
|
-
}
|
|
493
|
-
if (typeof next === "number" && !Array.isArray(obj[key])) {
|
|
494
|
-
obj = obj[key] = [];
|
|
495
|
-
continue;
|
|
496
|
-
}
|
|
497
|
-
if (!isObject(obj[key])) obj[key] = {};
|
|
498
|
-
obj = obj[key];
|
|
433
|
+
if (char === "\\") {
|
|
434
|
+
escaped = true;
|
|
435
|
+
continue;
|
|
499
436
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
|
|
437
|
+
if (char === ".") {
|
|
438
|
+
segments.push(current);
|
|
439
|
+
current = "";
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
current += char;
|
|
443
|
+
}
|
|
444
|
+
segments.push(current);
|
|
445
|
+
return segments;
|
|
446
|
+
}
|
|
447
|
+
function setByPath(target, path, value) {
|
|
448
|
+
const segments = typeof path === "string" ? parsePath(path) : [...path];
|
|
449
|
+
if (!segments.length) return target;
|
|
450
|
+
let current = target;
|
|
451
|
+
for (let index = 0; index < segments.length - 1; index++) {
|
|
452
|
+
const segment = segments[index];
|
|
453
|
+
const nextSegment = segments[index + 1];
|
|
454
|
+
const key = Array.isArray(current) && isArrayIndex(segment) ? Number(segment) : segment;
|
|
455
|
+
const existing = current[key];
|
|
456
|
+
if (typeof existing !== "object" || existing === null) current[key] = isArrayIndex(nextSegment) ? [] : {};
|
|
457
|
+
current = current[key];
|
|
458
|
+
}
|
|
459
|
+
const lastSegment = segments.at(-1);
|
|
460
|
+
const lastKey = Array.isArray(current) && isArrayIndex(lastSegment) ? Number(lastSegment) : lastSegment;
|
|
461
|
+
current[lastKey] = value;
|
|
462
|
+
return target;
|
|
463
|
+
}
|
|
464
|
+
//#endregion
|
|
465
|
+
//#region src/utils/regexp.ts
|
|
466
|
+
const regexpSpecialCharacterPattern = /[|\\{}()[\]^$+*?.]/g;
|
|
467
|
+
const hyphenPattern = /-/g;
|
|
468
|
+
/**
|
|
469
|
+
* 逃逸正则表达式中所有特殊字符,避免被当做模式解析。
|
|
470
|
+
*/
|
|
471
|
+
function escapeStringRegexp(str) {
|
|
472
|
+
return str.replace(regexpSpecialCharacterPattern, "\\$&").replace(hyphenPattern, "\\x2d");
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* 判断字符串是否命中任意一个正则,用于过滤要同步的资产文件。
|
|
476
|
+
*/
|
|
477
|
+
function isMatch(str, arr) {
|
|
478
|
+
for (const reg of arr) if (reg.test(str)) return true;
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
509
481
|
//#endregion
|
|
510
482
|
//#region src/core/config.ts
|
|
511
483
|
/**
|
|
@@ -553,7 +525,7 @@ async function resolveCommandConfig(name, cwd) {
|
|
|
553
525
|
//#endregion
|
|
554
526
|
//#region package.json
|
|
555
527
|
var name = "@icebreakers/monorepo";
|
|
556
|
-
var version = "3.2.
|
|
528
|
+
var version = "3.2.16";
|
|
557
529
|
//#endregion
|
|
558
530
|
//#region src/constants.ts
|
|
559
531
|
/**
|
|
@@ -585,7 +557,7 @@ function normalizeTargets(values) {
|
|
|
585
557
|
}
|
|
586
558
|
async function syncSkills(options = {}) {
|
|
587
559
|
const cwd = options.cwd ?? node_process.default.cwd();
|
|
588
|
-
if (!await
|
|
560
|
+
if (!await fs.pathExists(skillSourceDir)) {
|
|
589
561
|
const relative = pathe.default.relative(cwd, skillSourceDir);
|
|
590
562
|
throw new Error(`未找到技能目录:${relative || skillSourceDir}`);
|
|
591
563
|
}
|
|
@@ -603,9 +575,9 @@ async function syncSkills(options = {}) {
|
|
|
603
575
|
const results = [];
|
|
604
576
|
for (const target of targets) {
|
|
605
577
|
const dest = targetPaths[target];
|
|
606
|
-
await
|
|
607
|
-
await
|
|
608
|
-
await
|
|
578
|
+
await fs.remove(dest);
|
|
579
|
+
await fs.ensureDir(pathe.default.dirname(dest));
|
|
580
|
+
await fs.copy(skillSourceDir, dest);
|
|
609
581
|
results.push({
|
|
610
582
|
target,
|
|
611
583
|
dest
|
|
@@ -615,7 +587,6 @@ async function syncSkills(options = {}) {
|
|
|
615
587
|
}
|
|
616
588
|
//#endregion
|
|
617
589
|
//#region src/commands/clean.ts
|
|
618
|
-
var import_set_value = /* @__PURE__ */ __toESM(require_set_value(), 1);
|
|
619
590
|
function mergeCleanConfig(base, overrides) {
|
|
620
591
|
const normalizedBase = base ?? {};
|
|
621
592
|
if (!overrides) return normalizedBase;
|
|
@@ -665,12 +636,12 @@ async function cleanProjects(cwd, overrides) {
|
|
|
665
636
|
...skillTargets
|
|
666
637
|
])];
|
|
667
638
|
await Promise.all(candidates.map(async (dir) => {
|
|
668
|
-
if (await
|
|
639
|
+
if (await fs.pathExists(dir)) await fs.remove(dir);
|
|
669
640
|
}));
|
|
670
641
|
const name = pathe.default.resolve(workspaceDir, "package.json");
|
|
671
|
-
const pkgJson = await
|
|
672
|
-
(
|
|
673
|
-
await
|
|
642
|
+
const pkgJson = await fs.readJson(name);
|
|
643
|
+
setByPath(pkgJson, "devDependencies.@icebreakers/monorepo", cleanConfig?.pinnedVersion ?? "latest");
|
|
644
|
+
await fs.outputJson(name, pkgJson, { spaces: 2 });
|
|
674
645
|
}
|
|
675
646
|
//#endregion
|
|
676
647
|
//#region src/commands/create.ts
|
|
@@ -776,7 +747,7 @@ async function applyGitMetadata(pkgJson, repoDir, targetDir) {
|
|
|
776
747
|
const git = new GitClient({ baseDir: repoDir });
|
|
777
748
|
const repoName = await git.getRepoName();
|
|
778
749
|
if (!repoName) return;
|
|
779
|
-
(
|
|
750
|
+
setByPath(pkgJson, ["bugs", "url"], `https://github.com/${repoName}/issues`);
|
|
780
751
|
const repository = {
|
|
781
752
|
type: "git",
|
|
782
753
|
url: `git+https://github.com/${repoName}.git`
|
|
@@ -784,9 +755,9 @@ async function applyGitMetadata(pkgJson, repoDir, targetDir) {
|
|
|
784
755
|
const directoryBase = await git.getRepoRoot() ?? repoDir;
|
|
785
756
|
const relative = pathe.default.relative(directoryBase, targetDir);
|
|
786
757
|
if (relative && relative !== ".") repository.directory = relative.split(pathe.default.sep).join("/");
|
|
787
|
-
(
|
|
758
|
+
setByPath(pkgJson, "repository", repository);
|
|
788
759
|
const gitUser = await git.getUser();
|
|
789
|
-
if (gitUser?.name && gitUser?.email) (
|
|
760
|
+
if (gitUser?.name && gitUser?.email) setByPath(pkgJson, "author", `${gitUser.name} <${gitUser.email}>`);
|
|
790
761
|
} catch {}
|
|
791
762
|
}
|
|
792
763
|
/**
|
|
@@ -808,21 +779,21 @@ async function createNewProject(options) {
|
|
|
808
779
|
const from = pathe.default.join(templatesRoot, templateDefinition.source);
|
|
809
780
|
const targetName = name && name.length > 0 ? name : templateDefinition.target;
|
|
810
781
|
const to = pathe.default.join(cwd, targetName);
|
|
811
|
-
if (await
|
|
812
|
-
await
|
|
782
|
+
if (await fs.pathExists(to)) throw new Error(`${picocolors.default.red("目标目录已存在")}: ${pathe.default.relative(cwd, to)}`);
|
|
783
|
+
await fs.ensureDir(to);
|
|
813
784
|
const sourceJsonPath = pathe.default.resolve(from, "package.json");
|
|
814
|
-
const hasPackageJson = await
|
|
785
|
+
const hasPackageJson = await fs.pathExists(sourceJsonPath);
|
|
815
786
|
await (0, _icebreakers_monorepo_templates.scaffoldTemplate)({
|
|
816
787
|
sourceDir: from,
|
|
817
788
|
targetDir: to,
|
|
818
789
|
skipRootBasenames: ["package.json"]
|
|
819
790
|
});
|
|
820
791
|
if (hasPackageJson) {
|
|
821
|
-
const sourceJson = await
|
|
822
|
-
(
|
|
823
|
-
(
|
|
792
|
+
const sourceJson = await fs.readJson(sourceJsonPath);
|
|
793
|
+
setByPath(sourceJson, "version", "0.0.0");
|
|
794
|
+
setByPath(sourceJson, "name", name?.startsWith("@") ? name : pathe.default.basename(targetName));
|
|
824
795
|
await applyGitMetadata(sourceJson, cwd, to);
|
|
825
|
-
await
|
|
796
|
+
await fs.outputJson(pathe.default.resolve(to, renameJson ? "package.mock.json" : "package.json"), sourceJson, { spaces: 2 });
|
|
826
797
|
}
|
|
827
798
|
logger.success(`${picocolors.default.bgGreenBright(picocolors.default.white(`[${bundlerName}]`))} ${targetName} 项目创建成功!`);
|
|
828
799
|
}
|
|
@@ -853,104 +824,18 @@ async function createContext(cwd) {
|
|
|
853
824
|
*/
|
|
854
825
|
async function setChangeset_default(ctx) {
|
|
855
826
|
const { gitUrl, workspaceFilepath } = ctx;
|
|
856
|
-
if (gitUrl && await
|
|
827
|
+
if (gitUrl && await fs.exists(workspaceFilepath)) {
|
|
857
828
|
const changesetConfigPath = pathe.default.resolve(pathe.default.dirname(workspaceFilepath), ".changeset/config.json");
|
|
858
|
-
if (await
|
|
859
|
-
const changesetConfig = await
|
|
829
|
+
if (await fs.exists(changesetConfigPath)) {
|
|
830
|
+
const changesetConfig = await fs.readJson(changesetConfigPath);
|
|
860
831
|
if (gitUrl.full_name) {
|
|
861
|
-
(
|
|
862
|
-
await
|
|
832
|
+
setByPath(changesetConfig, "changelog.1.repo", gitUrl.full_name);
|
|
833
|
+
await fs.outputJson(changesetConfigPath, changesetConfig, { spaces: 2 });
|
|
863
834
|
}
|
|
864
835
|
}
|
|
865
836
|
}
|
|
866
837
|
}
|
|
867
838
|
//#endregion
|
|
868
|
-
//#region src/utils/fs.ts
|
|
869
|
-
/**
|
|
870
|
-
* 判断是否为可忽略的文件系统错误。
|
|
871
|
-
* - ENOENT: 文件已被删除
|
|
872
|
-
* - EBUSY: Windows 中资源被系统占用
|
|
873
|
-
*/
|
|
874
|
-
function isIgnorableFsError(error) {
|
|
875
|
-
if (!error) return false;
|
|
876
|
-
const code = error.code;
|
|
877
|
-
return code === "ENOENT" || code === "EBUSY" || code === "EEXIST";
|
|
878
|
-
}
|
|
879
|
-
//#endregion
|
|
880
|
-
//#region src/utils/github.ts
|
|
881
|
-
/**
|
|
882
|
-
* 将 Issue 模版里的 discussions 链接同步为当前仓库的 discussions 地址。
|
|
883
|
-
*/
|
|
884
|
-
function updateIssueTemplateConfig(source, repoName) {
|
|
885
|
-
if (!repoName) return source;
|
|
886
|
-
let doc;
|
|
887
|
-
try {
|
|
888
|
-
doc = (0, yaml.parseDocument)(source);
|
|
889
|
-
} catch {
|
|
890
|
-
return source;
|
|
891
|
-
}
|
|
892
|
-
const contactLinks = doc.get("contact_links");
|
|
893
|
-
if (!(0, yaml.isSeq)(contactLinks)) return source;
|
|
894
|
-
const nextUrl = `https://github.com/${repoName}/discussions`;
|
|
895
|
-
let changed = false;
|
|
896
|
-
contactLinks.items.forEach((_, index) => {
|
|
897
|
-
const url = doc.getIn([
|
|
898
|
-
"contact_links",
|
|
899
|
-
index,
|
|
900
|
-
"url"
|
|
901
|
-
]);
|
|
902
|
-
if (typeof url !== "string") return;
|
|
903
|
-
if (!url.includes("/discussions")) return;
|
|
904
|
-
if (url === nextUrl) return;
|
|
905
|
-
doc.setIn([
|
|
906
|
-
"contact_links",
|
|
907
|
-
index,
|
|
908
|
-
"url"
|
|
909
|
-
], nextUrl);
|
|
910
|
-
changed = true;
|
|
911
|
-
});
|
|
912
|
-
if (!changed) return source;
|
|
913
|
-
return doc.toString();
|
|
914
|
-
}
|
|
915
|
-
//#endregion
|
|
916
|
-
//#region src/utils/hash.ts
|
|
917
|
-
/**
|
|
918
|
-
* 生成给定二进制内容的 md5 摘要,用于快速比较文件内容。
|
|
919
|
-
*/
|
|
920
|
-
function getFileHash(data) {
|
|
921
|
-
const hashSum = node_crypto.default.createHash("md5");
|
|
922
|
-
hashSum.update(data);
|
|
923
|
-
return hashSum.digest("hex");
|
|
924
|
-
}
|
|
925
|
-
/**
|
|
926
|
-
* 对比两个文件的 md5,如果不一致则认为内容有变化。
|
|
927
|
-
*/
|
|
928
|
-
function isFileChanged(src, dest) {
|
|
929
|
-
try {
|
|
930
|
-
return getFileHash(src) !== getFileHash(dest);
|
|
931
|
-
} catch (err) {
|
|
932
|
-
logger.error("Error calculating file hash:", err);
|
|
933
|
-
return false;
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
//#endregion
|
|
937
|
-
//#region src/utils/regexp.ts
|
|
938
|
-
const regexpSpecialCharacterPattern = /[|\\{}()[\]^$+*?.]/g;
|
|
939
|
-
const hyphenPattern = /-/g;
|
|
940
|
-
/**
|
|
941
|
-
* 逃逸正则表达式中所有特殊字符,避免被当做模式解析。
|
|
942
|
-
*/
|
|
943
|
-
function escapeStringRegexp(str) {
|
|
944
|
-
return str.replace(regexpSpecialCharacterPattern, "\\$&").replace(hyphenPattern, "\\x2d");
|
|
945
|
-
}
|
|
946
|
-
/**
|
|
947
|
-
* 判断字符串是否命中任意一个正则,用于过滤要同步的资产文件。
|
|
948
|
-
*/
|
|
949
|
-
function isMatch(str, arr) {
|
|
950
|
-
for (const reg of arr) if (reg.test(str)) return true;
|
|
951
|
-
return false;
|
|
952
|
-
}
|
|
953
|
-
//#endregion
|
|
954
839
|
//#region src/commands/init/setIssueTemplateConfig.ts
|
|
955
840
|
/**
|
|
956
841
|
* 同步 Issue 模版里的 discussions 链接到当前仓库。
|
|
@@ -959,10 +844,10 @@ async function setIssueTemplateConfig_default(ctx) {
|
|
|
959
844
|
const repoName = ctx.gitUrl?.full_name;
|
|
960
845
|
if (!repoName) return;
|
|
961
846
|
const configPath = pathe.default.resolve(ctx.cwd, ".github/ISSUE_TEMPLATE/config.yml");
|
|
962
|
-
if (!await
|
|
963
|
-
const source = await
|
|
847
|
+
if (!await fs.pathExists(configPath)) return;
|
|
848
|
+
const source = await fs.readFile(configPath, "utf8");
|
|
964
849
|
const next = updateIssueTemplateConfig(source, repoName);
|
|
965
|
-
if (next !== source) await
|
|
850
|
+
if (next !== source) await fs.writeFile(configPath, next, "utf8");
|
|
966
851
|
}
|
|
967
852
|
//#endregion
|
|
968
853
|
//#region src/commands/init/setPkgJson.ts
|
|
@@ -971,21 +856,21 @@ async function setIssueTemplateConfig_default(ctx) {
|
|
|
971
856
|
*/
|
|
972
857
|
async function setPkgJson_default(ctx) {
|
|
973
858
|
const { gitUrl, gitUser, packages, cwd, workspaceFilepath } = ctx;
|
|
974
|
-
const workspaceExists = await
|
|
859
|
+
const workspaceExists = await fs.pathExists(workspaceFilepath);
|
|
975
860
|
if (gitUrl && workspaceExists) await Promise.all(packages.map(async (pkg) => {
|
|
976
|
-
if (!await
|
|
861
|
+
if (!await fs.pathExists(pkg.pkgJsonPath)) return;
|
|
977
862
|
const pkgJson = JSON.parse(JSON.stringify(pkg.manifest));
|
|
978
863
|
const directory = pathe.default.relative(cwd, pkg.rootDir);
|
|
979
|
-
(
|
|
864
|
+
setByPath(pkgJson, ["bugs", "url"], `https://github.com/${gitUrl.full_name}/issues`);
|
|
980
865
|
const repository = {
|
|
981
866
|
type: "git",
|
|
982
867
|
url: `git+https://github.com/${gitUrl.full_name}.git`
|
|
983
868
|
};
|
|
984
869
|
if (directory) repository.directory = directory;
|
|
985
|
-
(
|
|
986
|
-
if (gitUser?.name && gitUser?.email) (
|
|
870
|
+
setByPath(pkgJson, "repository", repository);
|
|
871
|
+
if (gitUser?.name && gitUser?.email) setByPath(pkgJson, "author", `${gitUser.name} <${gitUser.email}>`);
|
|
987
872
|
const nextContent = `${JSON.stringify(pkgJson, void 0, 2)}\n`;
|
|
988
|
-
if (await
|
|
873
|
+
if (await fs.readFile(pkg.pkgJsonPath, "utf8") !== nextContent) await fs.writeFile(pkg.pkgJsonPath, nextContent, "utf8");
|
|
989
874
|
}));
|
|
990
875
|
}
|
|
991
876
|
//#endregion
|
|
@@ -1032,7 +917,7 @@ async function getRows(ctx) {
|
|
|
1032
917
|
*/
|
|
1033
918
|
async function setReadme_default(ctx) {
|
|
1034
919
|
const rows = await getRows(ctx);
|
|
1035
|
-
await
|
|
920
|
+
await fs.writeFile(pathe.default.resolve(ctx.cwd, "README.md"), `${rows.join("\n")}\n`);
|
|
1036
921
|
}
|
|
1037
922
|
//#endregion
|
|
1038
923
|
//#region src/commands/init/index.ts
|
|
@@ -1089,7 +974,7 @@ function setMirror(obj, envs = chinaMirrorsEnvs) {
|
|
|
1089
974
|
"osx"
|
|
1090
975
|
];
|
|
1091
976
|
const prefix = "terminal.integrated.env";
|
|
1092
|
-
if (typeof obj === "object" && obj) for (const platform of platforms) (
|
|
977
|
+
if (typeof obj === "object" && obj) for (const platform of platforms) setByPath(obj, [prefix, platform].join(".").replaceAll(".", "\\."), envs);
|
|
1093
978
|
}
|
|
1094
979
|
//#endregion
|
|
1095
980
|
//#region src/commands/mirror/binaryMirror.ts
|
|
@@ -1099,14 +984,14 @@ function setMirror(obj, envs = chinaMirrorsEnvs) {
|
|
|
1099
984
|
async function setVscodeBinaryMirror(cwd) {
|
|
1100
985
|
const mirrorConfig = await resolveCommandConfig("mirror", cwd);
|
|
1101
986
|
const targetJsonPath = pathe.default.resolve(cwd, ".vscode/settings.json");
|
|
1102
|
-
await
|
|
1103
|
-
const json = (0, comment_json.parse)(await
|
|
987
|
+
await fs.ensureFile(targetJsonPath);
|
|
988
|
+
const json = (0, comment_json.parse)(await fs.readFile(targetJsonPath, "utf8"), void 0, false);
|
|
1104
989
|
const env = mirrorConfig?.env ? {
|
|
1105
990
|
...chinaMirrorsEnvs,
|
|
1106
991
|
...mirrorConfig.env
|
|
1107
992
|
} : chinaMirrorsEnvs;
|
|
1108
993
|
json && typeof json === "object" && setMirror(json, env);
|
|
1109
|
-
await
|
|
994
|
+
await fs.writeFile(targetJsonPath, `${(0, comment_json.stringify)(json, void 0, 2)}\n`, "utf8");
|
|
1110
995
|
}
|
|
1111
996
|
//#endregion
|
|
1112
997
|
//#region src/commands/sync.ts
|
|
@@ -1245,7 +1130,7 @@ function asBuffer(data) {
|
|
|
1245
1130
|
}
|
|
1246
1131
|
async function evaluateWriteIntent(targetPath, options) {
|
|
1247
1132
|
const { skipOverwrite, source } = options;
|
|
1248
|
-
if (!await
|
|
1133
|
+
if (!await fs.pathExists(targetPath)) return {
|
|
1249
1134
|
type: "write",
|
|
1250
1135
|
reason: "missing"
|
|
1251
1136
|
};
|
|
@@ -1256,7 +1141,7 @@ async function evaluateWriteIntent(targetPath, options) {
|
|
|
1256
1141
|
const src = asBuffer(source);
|
|
1257
1142
|
let destSize = 0;
|
|
1258
1143
|
try {
|
|
1259
|
-
destSize = (await
|
|
1144
|
+
destSize = (await fs.stat(targetPath)).size;
|
|
1260
1145
|
} catch {
|
|
1261
1146
|
return {
|
|
1262
1147
|
type: "write",
|
|
@@ -1267,7 +1152,7 @@ async function evaluateWriteIntent(targetPath, options) {
|
|
|
1267
1152
|
type: "prompt",
|
|
1268
1153
|
reason: "changed"
|
|
1269
1154
|
};
|
|
1270
|
-
if (!isFileChanged(src, await
|
|
1155
|
+
if (!isFileChanged(src, await fs.readFile(targetPath))) return {
|
|
1271
1156
|
type: "skip",
|
|
1272
1157
|
reason: "identical"
|
|
1273
1158
|
};
|
|
@@ -1512,14 +1397,14 @@ async function upgradeMonorepo(opts) {
|
|
|
1512
1397
|
const targetPath = pathe.default.resolve(absOutDir, relPath);
|
|
1513
1398
|
try {
|
|
1514
1399
|
if (relPath === "package.json") {
|
|
1515
|
-
if (!await
|
|
1516
|
-
const sourcePkgJson = await
|
|
1517
|
-
const targetPkgJson = await
|
|
1400
|
+
if (!await fs.pathExists(targetPath)) continue;
|
|
1401
|
+
const sourcePkgJson = await fs.readJson(file.path);
|
|
1402
|
+
const targetPkgJson = await fs.readJson(targetPath);
|
|
1518
1403
|
setPkgJson(sourcePkgJson, targetPkgJson, scriptOverrides ? { scripts: scriptOverrides } : void 0);
|
|
1519
1404
|
const data = `${JSON.stringify(targetPkgJson, void 0, 2)}\n`;
|
|
1520
1405
|
const intent = await evaluateWriteIntent(targetPath, buildWriteIntentOptions(data));
|
|
1521
1406
|
const action = async () => {
|
|
1522
|
-
await
|
|
1407
|
+
await fs.outputFile(targetPath, data, "utf8");
|
|
1523
1408
|
logger.success(targetPath);
|
|
1524
1409
|
};
|
|
1525
1410
|
await scheduleOverwrite(intent, {
|
|
@@ -1531,14 +1416,14 @@ async function upgradeMonorepo(opts) {
|
|
|
1531
1416
|
continue;
|
|
1532
1417
|
}
|
|
1533
1418
|
if (relPath === "pnpm-workspace.yaml") {
|
|
1534
|
-
const sourceManifest = normalizeWorkspaceManifest(yaml.default.parse(await
|
|
1535
|
-
const exists = await
|
|
1536
|
-
const targetManifest = exists ? normalizeWorkspaceManifest(yaml.default.parse(await
|
|
1419
|
+
const sourceManifest = normalizeWorkspaceManifest(yaml.default.parse(await fs.readFile(file.path, "utf8")));
|
|
1420
|
+
const exists = await fs.pathExists(targetPath);
|
|
1421
|
+
const targetManifest = exists ? normalizeWorkspaceManifest(yaml.default.parse(await fs.readFile(targetPath, "utf8"))) : normalizeWorkspaceManifest({});
|
|
1537
1422
|
const mergedManifest = exists ? mergeWorkspaceManifest(sourceManifest, targetManifest) : sourceManifest;
|
|
1538
1423
|
const data = yaml.default.stringify(mergedManifest, { singleQuote: true });
|
|
1539
1424
|
const intent = await evaluateWriteIntent(targetPath, buildWriteIntentOptions(data));
|
|
1540
1425
|
const action = async () => {
|
|
1541
|
-
await
|
|
1426
|
+
await fs.outputFile(targetPath, data, "utf8");
|
|
1542
1427
|
logger.success(targetPath);
|
|
1543
1428
|
};
|
|
1544
1429
|
await scheduleOverwrite(intent, {
|
|
@@ -1550,14 +1435,14 @@ async function upgradeMonorepo(opts) {
|
|
|
1550
1435
|
continue;
|
|
1551
1436
|
}
|
|
1552
1437
|
if (relPath === ".gitignore") {
|
|
1553
|
-
const source = await
|
|
1554
|
-
const exists = await
|
|
1555
|
-
const target = exists ? await
|
|
1438
|
+
const source = await fs.readFile(file.path, "utf8");
|
|
1439
|
+
const exists = await fs.pathExists(targetPath);
|
|
1440
|
+
const target = exists ? await fs.readFile(targetPath, "utf8") : "";
|
|
1556
1441
|
const data = exists ? mergeGitignore(source, target) : source;
|
|
1557
1442
|
if (exists && isTextEquivalent(target, data)) continue;
|
|
1558
1443
|
const intent = await evaluateWriteIntent(targetPath, buildWriteIntentOptions(data));
|
|
1559
1444
|
const action = async () => {
|
|
1560
|
-
await
|
|
1445
|
+
await fs.outputFile(targetPath, data, "utf8");
|
|
1561
1446
|
logger.success(targetPath);
|
|
1562
1447
|
};
|
|
1563
1448
|
await scheduleOverwrite(intent, {
|
|
@@ -1569,14 +1454,14 @@ async function upgradeMonorepo(opts) {
|
|
|
1569
1454
|
continue;
|
|
1570
1455
|
}
|
|
1571
1456
|
if (relPath === "AGENTS.md") {
|
|
1572
|
-
const source = await
|
|
1573
|
-
const exists = await
|
|
1574
|
-
const target = exists ? await
|
|
1457
|
+
const source = await fs.readFile(file.path, "utf8");
|
|
1458
|
+
const exists = await fs.pathExists(targetPath);
|
|
1459
|
+
const target = exists ? await fs.readFile(targetPath, "utf8") : "";
|
|
1575
1460
|
const data = exists ? mergeAgentsMarkdown(source, target) : source;
|
|
1576
1461
|
if (exists && isAgentsMarkdownEquivalent(target, data)) continue;
|
|
1577
1462
|
const intent = await evaluateWriteIntent(targetPath, buildWriteIntentOptions(data));
|
|
1578
1463
|
const action = async () => {
|
|
1579
|
-
await
|
|
1464
|
+
await fs.outputFile(targetPath, data, "utf8");
|
|
1580
1465
|
logger.success(targetPath);
|
|
1581
1466
|
};
|
|
1582
1467
|
await scheduleOverwrite(intent, {
|
|
@@ -1588,12 +1473,12 @@ async function upgradeMonorepo(opts) {
|
|
|
1588
1473
|
continue;
|
|
1589
1474
|
}
|
|
1590
1475
|
if (relPath === ".changeset/config.json" && repoName) {
|
|
1591
|
-
const changesetJson = await
|
|
1592
|
-
(
|
|
1476
|
+
const changesetJson = await fs.readJson(file.path);
|
|
1477
|
+
setByPath(changesetJson, "changelog.1.repo", repoName);
|
|
1593
1478
|
const data = `${JSON.stringify(changesetJson, void 0, 2)}\n`;
|
|
1594
1479
|
const intent = await evaluateWriteIntent(targetPath, buildWriteIntentOptions(data));
|
|
1595
1480
|
const action = async () => {
|
|
1596
|
-
await
|
|
1481
|
+
await fs.outputFile(targetPath, data, "utf8");
|
|
1597
1482
|
logger.success(targetPath);
|
|
1598
1483
|
};
|
|
1599
1484
|
await scheduleOverwrite(intent, {
|
|
@@ -1605,13 +1490,13 @@ async function upgradeMonorepo(opts) {
|
|
|
1605
1490
|
continue;
|
|
1606
1491
|
}
|
|
1607
1492
|
if (relPath === "LICENSE") {
|
|
1608
|
-
const source = await
|
|
1493
|
+
const source = await fs.readFile(file.path);
|
|
1609
1494
|
const intent = await evaluateWriteIntent(targetPath, {
|
|
1610
1495
|
skipOverwrite: true,
|
|
1611
1496
|
source
|
|
1612
1497
|
});
|
|
1613
1498
|
const action = async () => {
|
|
1614
|
-
await
|
|
1499
|
+
await fs.outputFile(targetPath, source);
|
|
1615
1500
|
logger.success(targetPath);
|
|
1616
1501
|
};
|
|
1617
1502
|
await scheduleOverwrite(intent, {
|
|
@@ -1623,10 +1508,10 @@ async function upgradeMonorepo(opts) {
|
|
|
1623
1508
|
continue;
|
|
1624
1509
|
}
|
|
1625
1510
|
if (relPath === ".github/ISSUE_TEMPLATE/config.yml") {
|
|
1626
|
-
const data = updateIssueTemplateConfig(await
|
|
1511
|
+
const data = updateIssueTemplateConfig(await fs.readFile(file.path, "utf8"), repoName);
|
|
1627
1512
|
const intent = await evaluateWriteIntent(targetPath, buildWriteIntentOptions(data));
|
|
1628
1513
|
const action = async () => {
|
|
1629
|
-
await
|
|
1514
|
+
await fs.outputFile(targetPath, data);
|
|
1630
1515
|
logger.success(targetPath);
|
|
1631
1516
|
};
|
|
1632
1517
|
await scheduleOverwrite(intent, {
|
|
@@ -1637,10 +1522,10 @@ async function upgradeMonorepo(opts) {
|
|
|
1637
1522
|
});
|
|
1638
1523
|
continue;
|
|
1639
1524
|
}
|
|
1640
|
-
const source = await
|
|
1525
|
+
const source = await fs.readFile(file.path);
|
|
1641
1526
|
const intent = await evaluateWriteIntent(targetPath, buildWriteIntentOptions(source));
|
|
1642
1527
|
const action = async () => {
|
|
1643
|
-
await
|
|
1528
|
+
await fs.outputFile(targetPath, source);
|
|
1644
1529
|
logger.success(targetPath);
|
|
1645
1530
|
};
|
|
1646
1531
|
await scheduleOverwrite(intent, {
|
|
@@ -1675,6 +1560,12 @@ Object.defineProperty(exports, "cleanProjects", {
|
|
|
1675
1560
|
return cleanProjects;
|
|
1676
1561
|
}
|
|
1677
1562
|
});
|
|
1563
|
+
Object.defineProperty(exports, "copy", {
|
|
1564
|
+
enumerable: true,
|
|
1565
|
+
get: function() {
|
|
1566
|
+
return copy;
|
|
1567
|
+
}
|
|
1568
|
+
});
|
|
1678
1569
|
Object.defineProperty(exports, "createContext", {
|
|
1679
1570
|
enumerable: true,
|
|
1680
1571
|
get: function() {
|
|
@@ -1711,12 +1602,30 @@ Object.defineProperty(exports, "defineMonorepoConfig", {
|
|
|
1711
1602
|
return defineMonorepoConfig;
|
|
1712
1603
|
}
|
|
1713
1604
|
});
|
|
1605
|
+
Object.defineProperty(exports, "ensureDir", {
|
|
1606
|
+
enumerable: true,
|
|
1607
|
+
get: function() {
|
|
1608
|
+
return ensureDir;
|
|
1609
|
+
}
|
|
1610
|
+
});
|
|
1611
|
+
Object.defineProperty(exports, "ensureFile", {
|
|
1612
|
+
enumerable: true,
|
|
1613
|
+
get: function() {
|
|
1614
|
+
return ensureFile;
|
|
1615
|
+
}
|
|
1616
|
+
});
|
|
1714
1617
|
Object.defineProperty(exports, "escapeStringRegexp", {
|
|
1715
1618
|
enumerable: true,
|
|
1716
1619
|
get: function() {
|
|
1717
1620
|
return escapeStringRegexp;
|
|
1718
1621
|
}
|
|
1719
1622
|
});
|
|
1623
|
+
Object.defineProperty(exports, "exists", {
|
|
1624
|
+
enumerable: true,
|
|
1625
|
+
get: function() {
|
|
1626
|
+
return exists;
|
|
1627
|
+
}
|
|
1628
|
+
});
|
|
1720
1629
|
Object.defineProperty(exports, "generateAgenticTemplate", {
|
|
1721
1630
|
enumerable: true,
|
|
1722
1631
|
get: function() {
|
|
@@ -1813,12 +1722,54 @@ Object.defineProperty(exports, "name", {
|
|
|
1813
1722
|
return name;
|
|
1814
1723
|
}
|
|
1815
1724
|
});
|
|
1725
|
+
Object.defineProperty(exports, "outputFile", {
|
|
1726
|
+
enumerable: true,
|
|
1727
|
+
get: function() {
|
|
1728
|
+
return outputFile;
|
|
1729
|
+
}
|
|
1730
|
+
});
|
|
1731
|
+
Object.defineProperty(exports, "outputJSON", {
|
|
1732
|
+
enumerable: true,
|
|
1733
|
+
get: function() {
|
|
1734
|
+
return outputJSON;
|
|
1735
|
+
}
|
|
1736
|
+
});
|
|
1737
|
+
Object.defineProperty(exports, "outputJson", {
|
|
1738
|
+
enumerable: true,
|
|
1739
|
+
get: function() {
|
|
1740
|
+
return outputJson;
|
|
1741
|
+
}
|
|
1742
|
+
});
|
|
1816
1743
|
Object.defineProperty(exports, "packageDir", {
|
|
1817
1744
|
enumerable: true,
|
|
1818
1745
|
get: function() {
|
|
1819
1746
|
return packageDir;
|
|
1820
1747
|
}
|
|
1821
1748
|
});
|
|
1749
|
+
Object.defineProperty(exports, "pathExists", {
|
|
1750
|
+
enumerable: true,
|
|
1751
|
+
get: function() {
|
|
1752
|
+
return pathExists;
|
|
1753
|
+
}
|
|
1754
|
+
});
|
|
1755
|
+
Object.defineProperty(exports, "readJSON", {
|
|
1756
|
+
enumerable: true,
|
|
1757
|
+
get: function() {
|
|
1758
|
+
return readJSON;
|
|
1759
|
+
}
|
|
1760
|
+
});
|
|
1761
|
+
Object.defineProperty(exports, "readJson", {
|
|
1762
|
+
enumerable: true,
|
|
1763
|
+
get: function() {
|
|
1764
|
+
return readJson;
|
|
1765
|
+
}
|
|
1766
|
+
});
|
|
1767
|
+
Object.defineProperty(exports, "remove", {
|
|
1768
|
+
enumerable: true,
|
|
1769
|
+
get: function() {
|
|
1770
|
+
return remove;
|
|
1771
|
+
}
|
|
1772
|
+
});
|
|
1822
1773
|
Object.defineProperty(exports, "resolveCommandConfig", {
|
|
1823
1774
|
enumerable: true,
|
|
1824
1775
|
get: function() {
|
|
@@ -1831,6 +1782,12 @@ Object.defineProperty(exports, "rootDir", {
|
|
|
1831
1782
|
return rootDir;
|
|
1832
1783
|
}
|
|
1833
1784
|
});
|
|
1785
|
+
Object.defineProperty(exports, "setByPath", {
|
|
1786
|
+
enumerable: true,
|
|
1787
|
+
get: function() {
|
|
1788
|
+
return setByPath;
|
|
1789
|
+
}
|
|
1790
|
+
});
|
|
1834
1791
|
Object.defineProperty(exports, "setVscodeBinaryMirror", {
|
|
1835
1792
|
enumerable: true,
|
|
1836
1793
|
get: function() {
|
|
@@ -1879,3 +1836,15 @@ Object.defineProperty(exports, "version", {
|
|
|
1879
1836
|
return version;
|
|
1880
1837
|
}
|
|
1881
1838
|
});
|
|
1839
|
+
Object.defineProperty(exports, "writeJSON", {
|
|
1840
|
+
enumerable: true,
|
|
1841
|
+
get: function() {
|
|
1842
|
+
return writeJSON;
|
|
1843
|
+
}
|
|
1844
|
+
});
|
|
1845
|
+
Object.defineProperty(exports, "writeJson", {
|
|
1846
|
+
enumerable: true,
|
|
1847
|
+
get: function() {
|
|
1848
|
+
return writeJson;
|
|
1849
|
+
}
|
|
1850
|
+
});
|