create-yss-spec 2.1.1 → 2.1.2
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/README.md +1 -1
- package/package.json +1 -1
- package/src/cli.js +1 -29
- package/src/template-hash.js +44 -0
- package/template.snapshot.json +2 -2
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ npx create-yss-spec@latest
|
|
|
33
33
|
- 旧、新资产内容冲突或清单 schema / mode 非法时 fail closed
|
|
34
34
|
- 保留模板的共享 skill 投影;生成实例可在尚未 `git init` 时运行模板校验
|
|
35
35
|
|
|
36
|
-
本次新增能力按 `2.1.
|
|
36
|
+
本次新增能力按 `2.1.2` 发布。`templateCommit` 会写入实例 metadata;“最新模板”指用户执行的 `npx create-yss-spec@latest` 所携带的最新已发布快照,CLI 运行时不会拉取模板仓库。
|
|
37
37
|
|
|
38
38
|
## 接管已有项目
|
|
39
39
|
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ const os = require("node:os");
|
|
|
4
4
|
const path = require("node:path");
|
|
5
5
|
const readline = require("node:readline/promises");
|
|
6
6
|
const { spawnSync } = require("node:child_process");
|
|
7
|
+
const { treeHash } = require("./template-hash");
|
|
7
8
|
|
|
8
9
|
const PACKAGE_ROOT = path.resolve(__dirname, "..");
|
|
9
10
|
const PACKAGE_MANIFEST = JSON.parse(
|
|
@@ -489,35 +490,6 @@ function fileHash(filePath) {
|
|
|
489
490
|
return sha256(fs.readFileSync(filePath));
|
|
490
491
|
}
|
|
491
492
|
|
|
492
|
-
function treeHash(rootPath) {
|
|
493
|
-
const digest = crypto.createHash("sha256");
|
|
494
|
-
|
|
495
|
-
function visit(currentPath, relativeDir = "") {
|
|
496
|
-
for (const entry of fs
|
|
497
|
-
.readdirSync(currentPath, { withFileTypes: true })
|
|
498
|
-
.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
499
|
-
if (entry.name === ".DS_Store") {
|
|
500
|
-
continue;
|
|
501
|
-
}
|
|
502
|
-
const relativePath = relativeDir
|
|
503
|
-
? `${relativeDir}/${entry.name}`
|
|
504
|
-
: entry.name;
|
|
505
|
-
const absolutePath = path.join(currentPath, entry.name);
|
|
506
|
-
if (entry.isDirectory()) {
|
|
507
|
-
digest.update(`dir:${relativePath}\0`);
|
|
508
|
-
visit(absolutePath, relativePath);
|
|
509
|
-
} else if (entry.isFile()) {
|
|
510
|
-
digest.update(`file:${relativePath}\0`);
|
|
511
|
-
digest.update(fs.readFileSync(absolutePath));
|
|
512
|
-
digest.update("\0");
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
visit(rootPath);
|
|
518
|
-
return digest.digest("hex");
|
|
519
|
-
}
|
|
520
|
-
|
|
521
493
|
function pathKind(absolutePath) {
|
|
522
494
|
let stat;
|
|
523
495
|
try {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const crypto = require("node:crypto");
|
|
2
|
+
const fs = require("node:fs");
|
|
3
|
+
const path = require("node:path");
|
|
4
|
+
|
|
5
|
+
function compareNames(left, right) {
|
|
6
|
+
if (left < right) {
|
|
7
|
+
return -1;
|
|
8
|
+
}
|
|
9
|
+
if (left > right) {
|
|
10
|
+
return 1;
|
|
11
|
+
}
|
|
12
|
+
return 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function treeHash(rootPath) {
|
|
16
|
+
const digest = crypto.createHash("sha256");
|
|
17
|
+
|
|
18
|
+
function visit(currentPath, relativeDir = "") {
|
|
19
|
+
for (const entry of fs
|
|
20
|
+
.readdirSync(currentPath, { withFileTypes: true })
|
|
21
|
+
.sort((left, right) => compareNames(left.name, right.name))) {
|
|
22
|
+
if (entry.name === ".DS_Store") {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const relativePath = relativeDir
|
|
26
|
+
? `${relativeDir}/${entry.name}`
|
|
27
|
+
: entry.name;
|
|
28
|
+
const absolutePath = path.join(currentPath, entry.name);
|
|
29
|
+
if (entry.isDirectory()) {
|
|
30
|
+
digest.update(`dir:${relativePath}\0`);
|
|
31
|
+
visit(absolutePath, relativePath);
|
|
32
|
+
} else if (entry.isFile()) {
|
|
33
|
+
digest.update(`file:${relativePath}\0`);
|
|
34
|
+
digest.update(fs.readFileSync(absolutePath));
|
|
35
|
+
digest.update("\0");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
visit(rootPath);
|
|
41
|
+
return digest.digest("hex");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = { treeHash };
|
package/template.snapshot.json
CHANGED
|
@@ -32,6 +32,6 @@
|
|
|
32
32
|
".trae/skills/drawio-academic-skills/.gitignore": ".trae/skills/drawio-academic-skills/__yss_dotfile__.gitignore",
|
|
33
33
|
".trae/skills/excalidraw-diagram-generator/scripts/.gitignore": ".trae/skills/excalidraw-diagram-generator/scripts/__yss_dotfile__.gitignore"
|
|
34
34
|
},
|
|
35
|
-
"snapshotHash": "
|
|
36
|
-
"generatedAt": "2026-08-13T05:
|
|
35
|
+
"snapshotHash": "93231767f7b762d0247e2db3f075c620b15a2820382e16d6d5e424d50ff922f4",
|
|
36
|
+
"generatedAt": "2026-08-13T05:40:01.242Z"
|
|
37
37
|
}
|