@thebassclef/lite 1.9.11 → 1.9.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.cjs +79 -1
- package/dist/cli.js +80 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ your browser.
|
|
|
67
67
|
|
|
68
68
|
## Current release
|
|
69
69
|
|
|
70
|
-
<!-- version-start -->1.9.
|
|
70
|
+
<!-- version-start -->1.9.12<!-- version-end -->
|
|
71
71
|
|
|
72
72
|
See [CHANGELOG.md](CHANGELOG.md) for the full changelog. Adopter-facing
|
|
73
73
|
release notes live at [docs.bassclef.dev/docs/whats-new/releases](https://docs.bassclef.dev/docs/whats-new/releases).
|
package/dist/cli.cjs
CHANGED
|
@@ -272,6 +272,47 @@ function hashContent(content) {
|
|
|
272
272
|
normalized = normalized.replace(/\r\n/g, "\n");
|
|
273
273
|
return node_crypto.createHash("sha256").update(normalized, "utf8").digest("hex");
|
|
274
274
|
}
|
|
275
|
+
const SCHEMA_VERSION = "1.0.0";
|
|
276
|
+
const WRITER_SLUG = "bassclef-init-npm";
|
|
277
|
+
function registerInstallWrittenPaths(targetDir, paths, now = /* @__PURE__ */ new Date()) {
|
|
278
|
+
if (paths.length === 0) return;
|
|
279
|
+
const manifestPath = node_path.join(targetDir, "state", "install-written-paths.json");
|
|
280
|
+
let manifest = {
|
|
281
|
+
schema_version: SCHEMA_VERSION,
|
|
282
|
+
entries: []
|
|
283
|
+
};
|
|
284
|
+
if (node_fs.existsSync(manifestPath)) {
|
|
285
|
+
try {
|
|
286
|
+
const parsed = JSON.parse(node_fs.readFileSync(manifestPath, "utf8"));
|
|
287
|
+
if (parsed && typeof parsed === "object" && "entries" in parsed && Array.isArray(parsed.entries)) {
|
|
288
|
+
manifest = parsed;
|
|
289
|
+
manifest.schema_version = SCHEMA_VERSION;
|
|
290
|
+
}
|
|
291
|
+
} catch {
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const writtenAt = now.toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
295
|
+
const uniqueInputs = /* @__PURE__ */ new Map();
|
|
296
|
+
for (const p of paths) {
|
|
297
|
+
uniqueInputs.set(p.relativePath, p);
|
|
298
|
+
}
|
|
299
|
+
const incomingPaths = new Set(uniqueInputs.keys());
|
|
300
|
+
manifest.entries = manifest.entries.filter((e) => !incomingPaths.has(e.path));
|
|
301
|
+
for (const p of uniqueInputs.values()) {
|
|
302
|
+
manifest.entries.push({
|
|
303
|
+
path: p.relativePath,
|
|
304
|
+
writer: WRITER_SLUG,
|
|
305
|
+
written_at: writtenAt,
|
|
306
|
+
content_hash: `sha256:${p.contentHashSha256}`
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
node_fs.mkdirSync(node_path.dirname(manifestPath), { recursive: true });
|
|
310
|
+
node_fs.writeFileSync(
|
|
311
|
+
manifestPath,
|
|
312
|
+
JSON.stringify(manifest, null, 2) + "\n",
|
|
313
|
+
"utf8"
|
|
314
|
+
);
|
|
315
|
+
}
|
|
275
316
|
const SUBSTRATE_CONFIG_TEMPLATE_VERSION = "0.0.1";
|
|
276
317
|
function substrateConfigMdTemplate(pkgVersion) {
|
|
277
318
|
return [
|
|
@@ -549,6 +590,7 @@ function copySubstrate(targetDir, options = {}) {
|
|
|
549
590
|
copied: [],
|
|
550
591
|
copiedEntries: [],
|
|
551
592
|
refused: [],
|
|
593
|
+
unchanged: [],
|
|
552
594
|
errored: [],
|
|
553
595
|
erroredMessages: [],
|
|
554
596
|
hookCount: 0,
|
|
@@ -736,6 +778,16 @@ function copyOne(relPath, bundleRoot, options, result, scopeDecision) {
|
|
|
736
778
|
} catch (e) {
|
|
737
779
|
if (e instanceof WriteError) {
|
|
738
780
|
if (e.kind === "AlreadyExists") {
|
|
781
|
+
if (scope === "user") {
|
|
782
|
+
try {
|
|
783
|
+
const existing = node_fs.readFileSync(targetPath, "utf8");
|
|
784
|
+
if (hashContent(existing) === hashContent(outputContent)) {
|
|
785
|
+
result.unchanged.push(adopterRelPath);
|
|
786
|
+
return "unchanged";
|
|
787
|
+
}
|
|
788
|
+
} catch {
|
|
789
|
+
}
|
|
790
|
+
}
|
|
739
791
|
result.refused.push(adopterRelPath);
|
|
740
792
|
return "refused";
|
|
741
793
|
}
|
|
@@ -1079,13 +1131,14 @@ function buildInitReport(input) {
|
|
|
1079
1131
|
else project += 1;
|
|
1080
1132
|
}
|
|
1081
1133
|
const refused = input.refused.length;
|
|
1134
|
+
const unchanged = input.unchanged?.length ?? 0;
|
|
1082
1135
|
const errored = input.errored.length;
|
|
1083
1136
|
const written = input.configs.length + input.entries.length;
|
|
1084
1137
|
return {
|
|
1085
1138
|
schema_version: 3,
|
|
1086
1139
|
tier: input.tier,
|
|
1087
1140
|
totals: {
|
|
1088
|
-
files: written + refused + errored,
|
|
1141
|
+
files: written + refused + unchanged + errored,
|
|
1089
1142
|
written,
|
|
1090
1143
|
project,
|
|
1091
1144
|
user,
|
|
@@ -1098,6 +1151,7 @@ function buildInitReport(input) {
|
|
|
1098
1151
|
files: catalog.hooks
|
|
1099
1152
|
},
|
|
1100
1153
|
refused,
|
|
1154
|
+
unchanged,
|
|
1101
1155
|
errored,
|
|
1102
1156
|
failed: refused + errored
|
|
1103
1157
|
};
|
|
@@ -1203,6 +1257,7 @@ function runInit(argv) {
|
|
|
1203
1257
|
entries: outcome.result?.wouldCopyEntries ?? [],
|
|
1204
1258
|
configs: plans.map((pl) => ({ path: pl.relativePath })),
|
|
1205
1259
|
refused: outcome.result?.refused ?? [],
|
|
1260
|
+
unchanged: outcome.result?.unchanged ?? [],
|
|
1206
1261
|
// A dry run still reads every source file, so it can still fail
|
|
1207
1262
|
// to read one. Hard-coding this empty hid those failures from
|
|
1208
1263
|
// the JSON (RFC-0005 A-3).
|
|
@@ -1301,6 +1356,7 @@ function dispatchSubstrateCopy(targetDir, force, verbose, dryRun, allowRoot, say
|
|
|
1301
1356
|
}
|
|
1302
1357
|
const parts = [];
|
|
1303
1358
|
if (result.copied.length > 0) parts.push(`${result.copied.length} substrate files copied`);
|
|
1359
|
+
if (result.unchanged.length > 0) parts.push(`${result.unchanged.length} already-present`);
|
|
1304
1360
|
if (result.refused.length > 0) parts.push(`${result.refused.length} refused`);
|
|
1305
1361
|
if (result.errored.length > 0) parts.push(`${result.errored.length} error(s)`);
|
|
1306
1362
|
say(`bassclef init: ${parts.join(", ")}.
|
|
@@ -1531,12 +1587,25 @@ function runReal$1(plans, force, verbose, targetDir, allowRoot, json, skipStatus
|
|
|
1531
1587
|
entries: walker.result?.copiedEntries ?? [],
|
|
1532
1588
|
configs: results.map((r) => ({ path: r.plan.relativePath })),
|
|
1533
1589
|
refused: walker.result?.refused ?? [],
|
|
1590
|
+
unchanged: walker.result?.unchanged ?? [],
|
|
1534
1591
|
errored: walker.result?.errored ?? [],
|
|
1535
1592
|
hookCount: walker.result?.hookCount ?? 0,
|
|
1536
1593
|
declaredHooksCopied,
|
|
1537
1594
|
tier: RESOLVED_TIER
|
|
1538
1595
|
});
|
|
1539
1596
|
writeManifest(targetDir, results, walker.result);
|
|
1597
|
+
const createdConfigPaths = results.filter((r) => r.outcome === "created").map((r) => ({
|
|
1598
|
+
relativePath: r.plan.relativePath,
|
|
1599
|
+
contentHashSha256: hashContent(r.plan.content)
|
|
1600
|
+
}));
|
|
1601
|
+
const createdBundlePaths = (walker.result?.copiedEntries ?? []).filter((e) => typeof e.content_hash_sha256 === "string").map((e) => ({
|
|
1602
|
+
relativePath: e.path,
|
|
1603
|
+
contentHashSha256: e.content_hash_sha256
|
|
1604
|
+
}));
|
|
1605
|
+
registerInstallWrittenPaths(targetDir, [
|
|
1606
|
+
...createdConfigPaths,
|
|
1607
|
+
...createdBundlePaths
|
|
1608
|
+
]);
|
|
1540
1609
|
if (walker.code === 0) {
|
|
1541
1610
|
say(
|
|
1542
1611
|
`bassclef init: your substrate lives under .claude/. Add .claude/ to .gitignore if you have not.
|
|
@@ -1606,6 +1675,15 @@ function writeManifest(targetDir, results, walkerResult) {
|
|
|
1606
1675
|
source: "bundle"
|
|
1607
1676
|
});
|
|
1608
1677
|
}
|
|
1678
|
+
for (const path of walkerResult.unchanged) {
|
|
1679
|
+
entries.push({
|
|
1680
|
+
path,
|
|
1681
|
+
template: `bundle:${path}`,
|
|
1682
|
+
template_version: index.version,
|
|
1683
|
+
outcome: "unchanged",
|
|
1684
|
+
source: "bundle"
|
|
1685
|
+
});
|
|
1686
|
+
}
|
|
1609
1687
|
for (const path of walkerResult.errored) {
|
|
1610
1688
|
entries.push({
|
|
1611
1689
|
path,
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { version } from "./index.js";
|
|
3
|
-
import { realpathSync, statSync, constants, lstatSync, mkdirSync, accessSync, unlinkSync, openSync, writeSync, closeSync, readlinkSync,
|
|
3
|
+
import { realpathSync, statSync, constants, lstatSync, mkdirSync, accessSync, unlinkSync, openSync, writeSync, closeSync, readlinkSync, existsSync, readFileSync, writeFileSync, chmodSync, readdirSync, renameSync } from "node:fs";
|
|
4
4
|
import { isAbsolute, resolve, dirname, join, normalize, relative, basename as basename$1 } from "node:path";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import { createHash } from "node:crypto";
|
|
@@ -249,6 +249,47 @@ function hashContent(content) {
|
|
|
249
249
|
normalized = normalized.replace(/\r\n/g, "\n");
|
|
250
250
|
return createHash("sha256").update(normalized, "utf8").digest("hex");
|
|
251
251
|
}
|
|
252
|
+
const SCHEMA_VERSION = "1.0.0";
|
|
253
|
+
const WRITER_SLUG = "bassclef-init-npm";
|
|
254
|
+
function registerInstallWrittenPaths(targetDir, paths, now = /* @__PURE__ */ new Date()) {
|
|
255
|
+
if (paths.length === 0) return;
|
|
256
|
+
const manifestPath = join(targetDir, "state", "install-written-paths.json");
|
|
257
|
+
let manifest = {
|
|
258
|
+
schema_version: SCHEMA_VERSION,
|
|
259
|
+
entries: []
|
|
260
|
+
};
|
|
261
|
+
if (existsSync(manifestPath)) {
|
|
262
|
+
try {
|
|
263
|
+
const parsed = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
264
|
+
if (parsed && typeof parsed === "object" && "entries" in parsed && Array.isArray(parsed.entries)) {
|
|
265
|
+
manifest = parsed;
|
|
266
|
+
manifest.schema_version = SCHEMA_VERSION;
|
|
267
|
+
}
|
|
268
|
+
} catch {
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
const writtenAt = now.toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
272
|
+
const uniqueInputs = /* @__PURE__ */ new Map();
|
|
273
|
+
for (const p of paths) {
|
|
274
|
+
uniqueInputs.set(p.relativePath, p);
|
|
275
|
+
}
|
|
276
|
+
const incomingPaths = new Set(uniqueInputs.keys());
|
|
277
|
+
manifest.entries = manifest.entries.filter((e) => !incomingPaths.has(e.path));
|
|
278
|
+
for (const p of uniqueInputs.values()) {
|
|
279
|
+
manifest.entries.push({
|
|
280
|
+
path: p.relativePath,
|
|
281
|
+
writer: WRITER_SLUG,
|
|
282
|
+
written_at: writtenAt,
|
|
283
|
+
content_hash: `sha256:${p.contentHashSha256}`
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
mkdirSync(dirname(manifestPath), { recursive: true });
|
|
287
|
+
writeFileSync(
|
|
288
|
+
manifestPath,
|
|
289
|
+
JSON.stringify(manifest, null, 2) + "\n",
|
|
290
|
+
"utf8"
|
|
291
|
+
);
|
|
292
|
+
}
|
|
252
293
|
const SUBSTRATE_CONFIG_TEMPLATE_VERSION = "0.0.1";
|
|
253
294
|
function substrateConfigMdTemplate(pkgVersion) {
|
|
254
295
|
return [
|
|
@@ -526,6 +567,7 @@ function copySubstrate(targetDir, options = {}) {
|
|
|
526
567
|
copied: [],
|
|
527
568
|
copiedEntries: [],
|
|
528
569
|
refused: [],
|
|
570
|
+
unchanged: [],
|
|
529
571
|
errored: [],
|
|
530
572
|
erroredMessages: [],
|
|
531
573
|
hookCount: 0,
|
|
@@ -713,6 +755,16 @@ function copyOne(relPath, bundleRoot, options, result, scopeDecision) {
|
|
|
713
755
|
} catch (e) {
|
|
714
756
|
if (e instanceof WriteError) {
|
|
715
757
|
if (e.kind === "AlreadyExists") {
|
|
758
|
+
if (scope === "user") {
|
|
759
|
+
try {
|
|
760
|
+
const existing = readFileSync(targetPath, "utf8");
|
|
761
|
+
if (hashContent(existing) === hashContent(outputContent)) {
|
|
762
|
+
result.unchanged.push(adopterRelPath);
|
|
763
|
+
return "unchanged";
|
|
764
|
+
}
|
|
765
|
+
} catch {
|
|
766
|
+
}
|
|
767
|
+
}
|
|
716
768
|
result.refused.push(adopterRelPath);
|
|
717
769
|
return "refused";
|
|
718
770
|
}
|
|
@@ -1056,13 +1108,14 @@ function buildInitReport(input) {
|
|
|
1056
1108
|
else project += 1;
|
|
1057
1109
|
}
|
|
1058
1110
|
const refused = input.refused.length;
|
|
1111
|
+
const unchanged = input.unchanged?.length ?? 0;
|
|
1059
1112
|
const errored = input.errored.length;
|
|
1060
1113
|
const written = input.configs.length + input.entries.length;
|
|
1061
1114
|
return {
|
|
1062
1115
|
schema_version: 3,
|
|
1063
1116
|
tier: input.tier,
|
|
1064
1117
|
totals: {
|
|
1065
|
-
files: written + refused + errored,
|
|
1118
|
+
files: written + refused + unchanged + errored,
|
|
1066
1119
|
written,
|
|
1067
1120
|
project,
|
|
1068
1121
|
user,
|
|
@@ -1075,6 +1128,7 @@ function buildInitReport(input) {
|
|
|
1075
1128
|
files: catalog.hooks
|
|
1076
1129
|
},
|
|
1077
1130
|
refused,
|
|
1131
|
+
unchanged,
|
|
1078
1132
|
errored,
|
|
1079
1133
|
failed: refused + errored
|
|
1080
1134
|
};
|
|
@@ -1180,6 +1234,7 @@ function runInit(argv) {
|
|
|
1180
1234
|
entries: outcome.result?.wouldCopyEntries ?? [],
|
|
1181
1235
|
configs: plans.map((pl) => ({ path: pl.relativePath })),
|
|
1182
1236
|
refused: outcome.result?.refused ?? [],
|
|
1237
|
+
unchanged: outcome.result?.unchanged ?? [],
|
|
1183
1238
|
// A dry run still reads every source file, so it can still fail
|
|
1184
1239
|
// to read one. Hard-coding this empty hid those failures from
|
|
1185
1240
|
// the JSON (RFC-0005 A-3).
|
|
@@ -1278,6 +1333,7 @@ function dispatchSubstrateCopy(targetDir, force, verbose, dryRun, allowRoot, say
|
|
|
1278
1333
|
}
|
|
1279
1334
|
const parts = [];
|
|
1280
1335
|
if (result.copied.length > 0) parts.push(`${result.copied.length} substrate files copied`);
|
|
1336
|
+
if (result.unchanged.length > 0) parts.push(`${result.unchanged.length} already-present`);
|
|
1281
1337
|
if (result.refused.length > 0) parts.push(`${result.refused.length} refused`);
|
|
1282
1338
|
if (result.errored.length > 0) parts.push(`${result.errored.length} error(s)`);
|
|
1283
1339
|
say(`bassclef init: ${parts.join(", ")}.
|
|
@@ -1508,12 +1564,25 @@ function runReal$1(plans, force, verbose, targetDir, allowRoot, json, skipStatus
|
|
|
1508
1564
|
entries: walker.result?.copiedEntries ?? [],
|
|
1509
1565
|
configs: results.map((r) => ({ path: r.plan.relativePath })),
|
|
1510
1566
|
refused: walker.result?.refused ?? [],
|
|
1567
|
+
unchanged: walker.result?.unchanged ?? [],
|
|
1511
1568
|
errored: walker.result?.errored ?? [],
|
|
1512
1569
|
hookCount: walker.result?.hookCount ?? 0,
|
|
1513
1570
|
declaredHooksCopied,
|
|
1514
1571
|
tier: RESOLVED_TIER
|
|
1515
1572
|
});
|
|
1516
1573
|
writeManifest(targetDir, results, walker.result);
|
|
1574
|
+
const createdConfigPaths = results.filter((r) => r.outcome === "created").map((r) => ({
|
|
1575
|
+
relativePath: r.plan.relativePath,
|
|
1576
|
+
contentHashSha256: hashContent(r.plan.content)
|
|
1577
|
+
}));
|
|
1578
|
+
const createdBundlePaths = (walker.result?.copiedEntries ?? []).filter((e) => typeof e.content_hash_sha256 === "string").map((e) => ({
|
|
1579
|
+
relativePath: e.path,
|
|
1580
|
+
contentHashSha256: e.content_hash_sha256
|
|
1581
|
+
}));
|
|
1582
|
+
registerInstallWrittenPaths(targetDir, [
|
|
1583
|
+
...createdConfigPaths,
|
|
1584
|
+
...createdBundlePaths
|
|
1585
|
+
]);
|
|
1517
1586
|
if (walker.code === 0) {
|
|
1518
1587
|
say(
|
|
1519
1588
|
`bassclef init: your substrate lives under .claude/. Add .claude/ to .gitignore if you have not.
|
|
@@ -1583,6 +1652,15 @@ function writeManifest(targetDir, results, walkerResult) {
|
|
|
1583
1652
|
source: "bundle"
|
|
1584
1653
|
});
|
|
1585
1654
|
}
|
|
1655
|
+
for (const path of walkerResult.unchanged) {
|
|
1656
|
+
entries.push({
|
|
1657
|
+
path,
|
|
1658
|
+
template: `bundle:${path}`,
|
|
1659
|
+
template_version: version,
|
|
1660
|
+
outcome: "unchanged",
|
|
1661
|
+
source: "bundle"
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1586
1664
|
for (const path of walkerResult.errored) {
|
|
1587
1665
|
entries.push({
|
|
1588
1666
|
path,
|
package/dist/index.cjs
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version: "1.9.
|
|
1
|
+
export declare const version: "1.9.12";
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED