@forge-ts/cli 0.17.0 → 0.19.0
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/{chunk-57QAENSK.js → chunk-JVI2NAXX.js} +83 -58
- package/dist/chunk-JVI2NAXX.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +278 -47
- package/dist/index.js.map +1 -1
- package/dist/{init-project-PT4XOWV2.js → init-project-6CWF4CCX.js} +2 -2
- package/package.json +6 -6
- package/dist/chunk-57QAENSK.js.map +0 -1
- /package/dist/{init-project-PT4XOWV2.js.map → init-project-6CWF4CCX.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
addScripts,
|
|
3
4
|
initProjectCommand,
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
readPkgJson,
|
|
6
|
+
runInitProject,
|
|
7
|
+
writePkgJson
|
|
8
|
+
} from "./chunk-JVI2NAXX.js";
|
|
6
9
|
import {
|
|
7
10
|
configureLogger,
|
|
8
11
|
forgeLogger
|
|
@@ -473,9 +476,22 @@ var bypassCommand = defineCommand3({
|
|
|
473
476
|
});
|
|
474
477
|
|
|
475
478
|
// src/commands/check.ts
|
|
479
|
+
import { execSync } from "child_process";
|
|
476
480
|
import { loadConfig as loadConfig3 } from "@forge-ts/core";
|
|
477
481
|
import { enforce } from "@forge-ts/enforcer";
|
|
478
482
|
import { defineCommand as defineCommand4 } from "citty";
|
|
483
|
+
function getStagedFiles(cwd) {
|
|
484
|
+
try {
|
|
485
|
+
const output = execSync("git diff --cached --name-only --diff-filter=d", {
|
|
486
|
+
cwd,
|
|
487
|
+
encoding: "utf8",
|
|
488
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
489
|
+
});
|
|
490
|
+
return output.split("\n").map((f) => f.trim()).filter((f) => f.length > 0 && (f.endsWith(".ts") || f.endsWith(".tsx")));
|
|
491
|
+
} catch {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
479
495
|
var RULE_NAMES = {
|
|
480
496
|
E001: "require-summary",
|
|
481
497
|
E002: "require-param",
|
|
@@ -634,27 +650,66 @@ async function runCheck(args) {
|
|
|
634
650
|
if (args.strict !== void 0) {
|
|
635
651
|
config.enforce.strict = args.strict;
|
|
636
652
|
}
|
|
653
|
+
const fileFilter = args.file;
|
|
654
|
+
let stagedPaths;
|
|
655
|
+
if (args.staged) {
|
|
656
|
+
const rootDir = config.rootDir;
|
|
657
|
+
const staged = getStagedFiles(rootDir);
|
|
658
|
+
if (staged !== null && staged.length > 0) {
|
|
659
|
+
stagedPaths = staged;
|
|
660
|
+
} else {
|
|
661
|
+
const data2 = {
|
|
662
|
+
success: true,
|
|
663
|
+
summary: { errors: 0, warnings: 0, files: 0, symbols: 0, duration: 0 }
|
|
664
|
+
};
|
|
665
|
+
return { operation: "check", success: true, data: data2, duration: 0 };
|
|
666
|
+
}
|
|
667
|
+
}
|
|
637
668
|
const result = await enforce(config);
|
|
638
669
|
const mviLevel = args.mvi ?? "standard";
|
|
639
670
|
const limit = args.limit ?? 20;
|
|
640
671
|
const offset = args.offset ?? 0;
|
|
641
|
-
const filters = { rule: args.rule, file:
|
|
672
|
+
const filters = { rule: args.rule, file: fileFilter };
|
|
673
|
+
const CROSS_FILE_RULES = /* @__PURE__ */ new Set([
|
|
674
|
+
"E005",
|
|
675
|
+
"E008",
|
|
676
|
+
"E009",
|
|
677
|
+
"E010",
|
|
678
|
+
"E011",
|
|
679
|
+
"E012",
|
|
680
|
+
"W007",
|
|
681
|
+
"W008",
|
|
682
|
+
"W009"
|
|
683
|
+
]);
|
|
684
|
+
let filteredErrors = result.errors;
|
|
685
|
+
let filteredWarnings = result.warnings;
|
|
686
|
+
if (stagedPaths && stagedPaths.length > 0) {
|
|
687
|
+
const stagedSet = new Set(stagedPaths);
|
|
688
|
+
const matchesStaged = (filePath) => stagedPaths?.some((sp) => filePath.endsWith(sp)) ?? false;
|
|
689
|
+
filteredErrors = result.errors.filter(
|
|
690
|
+
(e) => CROSS_FILE_RULES.has(e.code) || stagedSet.has(e.filePath) || matchesStaged(e.filePath)
|
|
691
|
+
);
|
|
692
|
+
filteredWarnings = result.warnings.filter(
|
|
693
|
+
(w) => CROSS_FILE_RULES.has(w.code) || stagedSet.has(w.filePath) || matchesStaged(w.filePath)
|
|
694
|
+
);
|
|
695
|
+
}
|
|
642
696
|
const exportedSymbolCount = result.symbols.filter((s) => s.exported).length;
|
|
643
697
|
const data = buildCheckResult(
|
|
644
|
-
|
|
645
|
-
|
|
698
|
+
filteredErrors,
|
|
699
|
+
filteredWarnings,
|
|
646
700
|
exportedSymbolCount,
|
|
647
701
|
result.duration,
|
|
648
|
-
|
|
702
|
+
filteredErrors.length === 0,
|
|
649
703
|
mviLevel,
|
|
650
704
|
filters,
|
|
651
705
|
limit,
|
|
652
706
|
offset
|
|
653
707
|
);
|
|
654
|
-
const
|
|
708
|
+
const checkSuccess = filteredErrors.length === 0;
|
|
709
|
+
const cliErrors = checkSuccess ? void 0 : [
|
|
655
710
|
{
|
|
656
711
|
code: "FORGE_CHECK_FAILED",
|
|
657
|
-
message: `TSDoc coverage check failed: ${
|
|
712
|
+
message: `TSDoc coverage check failed: ${filteredErrors.length} error(s), ${filteredWarnings.length} warning(s) across ${data.summary.files} file(s)`
|
|
658
713
|
}
|
|
659
714
|
];
|
|
660
715
|
const cliWarnings = config._configWarnings?.map((msg) => ({
|
|
@@ -666,7 +721,7 @@ async function runCheck(args) {
|
|
|
666
721
|
}));
|
|
667
722
|
return {
|
|
668
723
|
operation: "check",
|
|
669
|
-
success:
|
|
724
|
+
success: checkSuccess,
|
|
670
725
|
data,
|
|
671
726
|
errors: cliErrors,
|
|
672
727
|
warnings: cliWarnings,
|
|
@@ -769,6 +824,11 @@ var checkCommand = defineCommand4({
|
|
|
769
824
|
type: "string",
|
|
770
825
|
description: "Filter by file path (substring match)"
|
|
771
826
|
},
|
|
827
|
+
staged: {
|
|
828
|
+
type: "boolean",
|
|
829
|
+
description: "Only check symbols from git-staged .ts/.tsx files",
|
|
830
|
+
default: false
|
|
831
|
+
},
|
|
772
832
|
limit: {
|
|
773
833
|
type: "string",
|
|
774
834
|
description: "Max file groups in output (default: 20)"
|
|
@@ -805,6 +865,7 @@ var checkCommand = defineCommand4({
|
|
|
805
865
|
mvi: args.mvi,
|
|
806
866
|
rule: args.rule,
|
|
807
867
|
file: args.file,
|
|
868
|
+
staged: args.staged,
|
|
808
869
|
limit: args.limit ? parseInt(args.limit, 10) : void 0,
|
|
809
870
|
offset: args.offset ? parseInt(args.offset, 10) : void 0
|
|
810
871
|
});
|
|
@@ -880,6 +941,7 @@ var docsDevCommand = defineCommand5({
|
|
|
880
941
|
});
|
|
881
942
|
|
|
882
943
|
// src/commands/doctor.ts
|
|
944
|
+
import { execSync as execSync2 } from "child_process";
|
|
883
945
|
import { existsSync, readFileSync } from "fs";
|
|
884
946
|
import { mkdir, writeFile } from "fs/promises";
|
|
885
947
|
import { join } from "path";
|
|
@@ -1183,43 +1245,136 @@ async function runDoctor(args) {
|
|
|
1183
1245
|
});
|
|
1184
1246
|
}
|
|
1185
1247
|
const huskyPreCommit = join(rootDir, ".husky", "pre-commit");
|
|
1248
|
+
const huskyPrePush = join(rootDir, ".husky", "pre-push");
|
|
1186
1249
|
const lefthookYml = join(rootDir, "lefthook.yml");
|
|
1187
|
-
let
|
|
1188
|
-
let
|
|
1250
|
+
let hookManagerType = "none";
|
|
1251
|
+
let preCommitConfigured = false;
|
|
1252
|
+
let prePushConfigured = false;
|
|
1189
1253
|
if (existsSync(huskyPreCommit)) {
|
|
1254
|
+
hookManagerType = "husky";
|
|
1190
1255
|
try {
|
|
1191
1256
|
const content = readFileSync(huskyPreCommit, "utf8");
|
|
1192
1257
|
if (content.includes("forge-ts check")) {
|
|
1193
|
-
|
|
1194
|
-
|
|
1258
|
+
preCommitConfigured = true;
|
|
1259
|
+
}
|
|
1260
|
+
} catch {
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
if (hookManagerType === "husky" && existsSync(huskyPrePush)) {
|
|
1264
|
+
try {
|
|
1265
|
+
const content = readFileSync(huskyPrePush, "utf8");
|
|
1266
|
+
if (content.includes("forge-ts prepublish")) {
|
|
1267
|
+
prePushConfigured = true;
|
|
1195
1268
|
}
|
|
1196
1269
|
} catch {
|
|
1197
1270
|
}
|
|
1198
1271
|
}
|
|
1199
|
-
if (
|
|
1272
|
+
if (hookManagerType === "none" && existsSync(lefthookYml)) {
|
|
1273
|
+
hookManagerType = "lefthook";
|
|
1200
1274
|
try {
|
|
1201
1275
|
const content = readFileSync(lefthookYml, "utf8");
|
|
1202
1276
|
if (content.includes("forge-ts check")) {
|
|
1203
|
-
|
|
1204
|
-
|
|
1277
|
+
preCommitConfigured = true;
|
|
1278
|
+
}
|
|
1279
|
+
if (content.includes("forge-ts prepublish")) {
|
|
1280
|
+
prePushConfigured = true;
|
|
1205
1281
|
}
|
|
1206
1282
|
} catch {
|
|
1207
1283
|
}
|
|
1208
1284
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1285
|
+
let huskyInstalled = false;
|
|
1286
|
+
if (hookManagerType === "husky" || hookManagerType === "none") {
|
|
1287
|
+
const huskyBin = join(rootDir, "node_modules", ".bin", "husky");
|
|
1288
|
+
if (existsSync(huskyBin)) {
|
|
1289
|
+
huskyInstalled = true;
|
|
1290
|
+
} else {
|
|
1291
|
+
const pkgPathHooks = join(rootDir, "package.json");
|
|
1292
|
+
const hooksPkg = readJsonSafe(pkgPathHooks);
|
|
1293
|
+
if (hooksPkg) {
|
|
1294
|
+
const allDeps = { ...hooksPkg.dependencies, ...hooksPkg.devDependencies };
|
|
1295
|
+
if ("husky" in allDeps) {
|
|
1296
|
+
huskyInstalled = true;
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
let prepareScriptExists = false;
|
|
1302
|
+
{
|
|
1303
|
+
const pkgPathPrep = join(rootDir, "package.json");
|
|
1304
|
+
const prepPkg = readJsonSafe(pkgPathPrep);
|
|
1305
|
+
if (prepPkg?.scripts?.prepare) {
|
|
1306
|
+
prepareScriptExists = true;
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
if (hookManagerType === "husky") {
|
|
1310
|
+
try {
|
|
1311
|
+
execSync2("git config core.hooksPath", {
|
|
1312
|
+
cwd: rootDir,
|
|
1313
|
+
encoding: "utf8",
|
|
1314
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1315
|
+
});
|
|
1316
|
+
} catch {
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
if (hookManagerType === "none" && !preCommitConfigured && !prePushConfigured) {
|
|
1217
1320
|
checks.push({
|
|
1218
1321
|
name: "Git hooks",
|
|
1219
1322
|
status: "warn",
|
|
1220
|
-
message: "Git hooks \u2014
|
|
1323
|
+
message: "Git hooks \u2014 no hook manager detected (run forge-ts init hooks)",
|
|
1221
1324
|
fixable: false
|
|
1222
1325
|
});
|
|
1326
|
+
} else if (hookManagerType === "husky") {
|
|
1327
|
+
if (!huskyInstalled) {
|
|
1328
|
+
checks.push({
|
|
1329
|
+
name: "Git hooks (husky)",
|
|
1330
|
+
status: "warn",
|
|
1331
|
+
message: "Git hooks \u2014 hook files exist but husky is not installed (run: npm install -D husky)",
|
|
1332
|
+
fixable: false
|
|
1333
|
+
});
|
|
1334
|
+
} else if (!prepareScriptExists) {
|
|
1335
|
+
checks.push({
|
|
1336
|
+
name: "Git hooks (husky)",
|
|
1337
|
+
status: "warn",
|
|
1338
|
+
message: 'Git hooks \u2014 husky installed but "prepare" script missing in package.json',
|
|
1339
|
+
fixable: false
|
|
1340
|
+
});
|
|
1341
|
+
} else if (preCommitConfigured && prePushConfigured) {
|
|
1342
|
+
checks.push({
|
|
1343
|
+
name: "Git hooks (husky)",
|
|
1344
|
+
status: "pass",
|
|
1345
|
+
message: "Git hooks \u2014 husky installed, prepare script wired, pre-commit and pre-push configured",
|
|
1346
|
+
fixable: false
|
|
1347
|
+
});
|
|
1348
|
+
} else {
|
|
1349
|
+
const missing = [];
|
|
1350
|
+
if (!preCommitConfigured) missing.push("pre-commit (forge-ts check)");
|
|
1351
|
+
if (!prePushConfigured) missing.push("pre-push (forge-ts prepublish)");
|
|
1352
|
+
checks.push({
|
|
1353
|
+
name: "Git hooks (husky)",
|
|
1354
|
+
status: "warn",
|
|
1355
|
+
message: `Git hooks \u2014 husky installed but missing: ${missing.join(", ")}`,
|
|
1356
|
+
fixable: false
|
|
1357
|
+
});
|
|
1358
|
+
}
|
|
1359
|
+
} else if (hookManagerType === "lefthook") {
|
|
1360
|
+
if (preCommitConfigured && prePushConfigured) {
|
|
1361
|
+
checks.push({
|
|
1362
|
+
name: "Git hooks (lefthook)",
|
|
1363
|
+
status: "pass",
|
|
1364
|
+
message: "Git hooks \u2014 lefthook pre-commit and pre-push configured",
|
|
1365
|
+
fixable: false
|
|
1366
|
+
});
|
|
1367
|
+
} else {
|
|
1368
|
+
const missing = [];
|
|
1369
|
+
if (!preCommitConfigured) missing.push("pre-commit (forge-ts check)");
|
|
1370
|
+
if (!prePushConfigured) missing.push("pre-push (forge-ts prepublish)");
|
|
1371
|
+
checks.push({
|
|
1372
|
+
name: "Git hooks (lefthook)",
|
|
1373
|
+
status: "warn",
|
|
1374
|
+
message: `Git hooks \u2014 lefthook detected but missing: ${missing.join(", ")}`,
|
|
1375
|
+
fixable: false
|
|
1376
|
+
});
|
|
1377
|
+
}
|
|
1223
1378
|
}
|
|
1224
1379
|
const summary = {
|
|
1225
1380
|
passed: checks.filter((c) => c.status === "pass").length,
|
|
@@ -1597,15 +1752,19 @@ function detectHookManager(rootDir) {
|
|
|
1597
1752
|
}
|
|
1598
1753
|
return "none";
|
|
1599
1754
|
}
|
|
1600
|
-
var HUSKY_PRE_COMMIT =
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
npx forge-ts check
|
|
1755
|
+
var HUSKY_PRE_COMMIT = `npx forge-ts check
|
|
1756
|
+
`;
|
|
1757
|
+
var HUSKY_PRE_PUSH = `npx forge-ts prepublish
|
|
1604
1758
|
`;
|
|
1605
1759
|
var LEFTHOOK_BLOCK = `pre-commit:
|
|
1606
1760
|
commands:
|
|
1607
1761
|
forge-ts-check:
|
|
1608
1762
|
run: npx forge-ts check
|
|
1763
|
+
|
|
1764
|
+
pre-push:
|
|
1765
|
+
commands:
|
|
1766
|
+
forge-ts-prepublish:
|
|
1767
|
+
run: npx forge-ts prepublish
|
|
1609
1768
|
`;
|
|
1610
1769
|
async function runInitHooks(args) {
|
|
1611
1770
|
const start = Date.now();
|
|
@@ -1616,54 +1775,125 @@ async function runInitHooks(args) {
|
|
|
1616
1775
|
const warnings = [];
|
|
1617
1776
|
const instructions = [];
|
|
1618
1777
|
if (hookManager === "husky" || hookManager === "none") {
|
|
1778
|
+
const huskyBin = join3(rootDir, "node_modules", ".bin", "husky");
|
|
1779
|
+
const pkg2 = readPkgJson(rootDir);
|
|
1780
|
+
const huskyInDeps = pkg2 !== null && ("husky" in (pkg2.obj.devDependencies ?? {}) || "husky" in (pkg2.obj.dependencies ?? {}));
|
|
1781
|
+
const huskyInstalled = existsSync3(huskyBin) || huskyInDeps;
|
|
1782
|
+
if (!huskyInstalled) {
|
|
1783
|
+
warnings.push({
|
|
1784
|
+
code: "HOOKS_HUSKY_NOT_INSTALLED",
|
|
1785
|
+
message: "husky not installed. Run: npm install -D husky"
|
|
1786
|
+
});
|
|
1787
|
+
instructions.push("husky is not installed. Run: npm install -D husky (or pnpm add -D husky)");
|
|
1788
|
+
}
|
|
1619
1789
|
const huskyDir = join3(rootDir, ".husky");
|
|
1620
|
-
const
|
|
1621
|
-
const
|
|
1622
|
-
if (existsSync3(
|
|
1623
|
-
const existing = await readFile(
|
|
1790
|
+
const preCommitPath = join3(huskyDir, "pre-commit");
|
|
1791
|
+
const preCommitRel = ".husky/pre-commit";
|
|
1792
|
+
if (existsSync3(preCommitPath) && !args.force) {
|
|
1793
|
+
const existing = await readFile(preCommitPath, "utf8");
|
|
1624
1794
|
if (existing.includes("forge-ts check")) {
|
|
1625
|
-
skippedFiles.push(
|
|
1795
|
+
skippedFiles.push(preCommitRel);
|
|
1626
1796
|
warnings.push({
|
|
1627
1797
|
code: "HOOKS_ALREADY_EXISTS",
|
|
1628
|
-
message: `${
|
|
1798
|
+
message: `${preCommitRel} already contains forge-ts check \u2014 skipping. Use --force to overwrite.`
|
|
1629
1799
|
});
|
|
1630
1800
|
} else {
|
|
1631
1801
|
const appended = `${existing.trimEnd()}
|
|
1632
1802
|
|
|
1633
1803
|
npx forge-ts check
|
|
1634
1804
|
`;
|
|
1635
|
-
await writeFile3(
|
|
1636
|
-
writtenFiles.push(
|
|
1805
|
+
await writeFile3(preCommitPath, appended, { mode: 493 });
|
|
1806
|
+
writtenFiles.push(preCommitRel);
|
|
1637
1807
|
}
|
|
1638
1808
|
} else {
|
|
1639
1809
|
await mkdir3(huskyDir, { recursive: true });
|
|
1640
|
-
await writeFile3(
|
|
1641
|
-
writtenFiles.push(
|
|
1810
|
+
await writeFile3(preCommitPath, HUSKY_PRE_COMMIT, { mode: 493 });
|
|
1811
|
+
writtenFiles.push(preCommitRel);
|
|
1812
|
+
}
|
|
1813
|
+
const prePushPath = join3(huskyDir, "pre-push");
|
|
1814
|
+
const prePushRel = ".husky/pre-push";
|
|
1815
|
+
if (existsSync3(prePushPath) && !args.force) {
|
|
1816
|
+
const existing = await readFile(prePushPath, "utf8");
|
|
1817
|
+
if (existing.includes("forge-ts prepublish")) {
|
|
1818
|
+
skippedFiles.push(prePushRel);
|
|
1819
|
+
warnings.push({
|
|
1820
|
+
code: "HOOKS_ALREADY_EXISTS",
|
|
1821
|
+
message: `${prePushRel} already contains forge-ts prepublish \u2014 skipping. Use --force to overwrite.`
|
|
1822
|
+
});
|
|
1823
|
+
} else {
|
|
1824
|
+
const appended = `${existing.trimEnd()}
|
|
1825
|
+
|
|
1826
|
+
npx forge-ts prepublish
|
|
1827
|
+
`;
|
|
1828
|
+
await writeFile3(prePushPath, appended, { mode: 493 });
|
|
1829
|
+
writtenFiles.push(prePushRel);
|
|
1830
|
+
}
|
|
1831
|
+
} else {
|
|
1832
|
+
await mkdir3(huskyDir, { recursive: true });
|
|
1833
|
+
await writeFile3(prePushPath, HUSKY_PRE_PUSH, { mode: 493 });
|
|
1834
|
+
writtenFiles.push(prePushRel);
|
|
1835
|
+
}
|
|
1836
|
+
const pkgData = readPkgJson(rootDir);
|
|
1837
|
+
if (pkgData) {
|
|
1838
|
+
const added = addScripts(pkgData, { prepare: "husky" });
|
|
1839
|
+
if (added.length > 0) {
|
|
1840
|
+
await writePkgJson(pkgData);
|
|
1841
|
+
writtenFiles.push("package.json (prepare script)");
|
|
1842
|
+
instructions.push('Added "prepare": "husky" script to package.json.');
|
|
1843
|
+
} else {
|
|
1844
|
+
skippedFiles.push("package.json (prepare script already exists)");
|
|
1845
|
+
}
|
|
1642
1846
|
}
|
|
1643
1847
|
if (hookManager === "none") {
|
|
1644
1848
|
instructions.push(
|
|
1645
|
-
"No hook manager detected. Wrote .husky/pre-commit as a starting point.",
|
|
1646
|
-
"Install husky to activate:
|
|
1849
|
+
"No hook manager detected. Wrote .husky/pre-commit and .husky/pre-push as a starting point.",
|
|
1850
|
+
"Install husky to activate: npm install -D husky && npx husky (or pnpm add -D husky && pnpm exec husky)"
|
|
1647
1851
|
);
|
|
1648
1852
|
} else {
|
|
1649
1853
|
instructions.push("Husky pre-commit hook configured to run forge-ts check.");
|
|
1854
|
+
instructions.push("Husky pre-push hook configured to run forge-ts prepublish.");
|
|
1650
1855
|
}
|
|
1651
1856
|
} else if (hookManager === "lefthook") {
|
|
1652
1857
|
const lefthookPath = join3(rootDir, "lefthook.yml");
|
|
1653
1858
|
const relativePath = "lefthook.yml";
|
|
1654
1859
|
if (existsSync3(lefthookPath)) {
|
|
1655
1860
|
const existing = await readFile(lefthookPath, "utf8");
|
|
1656
|
-
|
|
1861
|
+
const hasCheck = existing.includes("forge-ts check");
|
|
1862
|
+
const hasPrepublish = existing.includes("forge-ts prepublish");
|
|
1863
|
+
if (hasCheck && hasPrepublish && !args.force) {
|
|
1657
1864
|
skippedFiles.push(relativePath);
|
|
1658
1865
|
warnings.push({
|
|
1659
1866
|
code: "HOOKS_ALREADY_EXISTS",
|
|
1660
|
-
message: `${relativePath} already contains forge-ts check \u2014 skipping. Use --force to overwrite.`
|
|
1867
|
+
message: `${relativePath} already contains forge-ts check and prepublish \u2014 skipping. Use --force to overwrite.`
|
|
1661
1868
|
});
|
|
1662
|
-
} else if (
|
|
1869
|
+
} else if (hasCheck && !hasPrepublish && !args.force) {
|
|
1870
|
+
const prePushBlock = `
|
|
1871
|
+
pre-push:
|
|
1872
|
+
commands:
|
|
1873
|
+
forge-ts-prepublish:
|
|
1874
|
+
run: npx forge-ts prepublish
|
|
1875
|
+
`;
|
|
1663
1876
|
const appended = `${existing.trimEnd()}
|
|
1664
|
-
|
|
1665
|
-
|
|
1877
|
+
${prePushBlock}`;
|
|
1878
|
+
await writeFile3(lefthookPath, appended, "utf8");
|
|
1879
|
+
writtenFiles.push(relativePath);
|
|
1880
|
+
} else if (existing.includes("pre-commit:") && !args.force) {
|
|
1881
|
+
let appended = existing.trimEnd();
|
|
1882
|
+
if (!hasCheck) {
|
|
1883
|
+
appended += "\n forge-ts-check:\n run: npx forge-ts check";
|
|
1884
|
+
}
|
|
1885
|
+
if (!existing.includes("pre-push:")) {
|
|
1886
|
+
appended += `
|
|
1887
|
+
|
|
1888
|
+
pre-push:
|
|
1889
|
+
commands:
|
|
1890
|
+
forge-ts-prepublish:
|
|
1891
|
+
run: npx forge-ts prepublish
|
|
1666
1892
|
`;
|
|
1893
|
+
} else if (!hasPrepublish) {
|
|
1894
|
+
appended += "\n forge-ts-prepublish:\n run: npx forge-ts prepublish";
|
|
1895
|
+
}
|
|
1896
|
+
appended += "\n";
|
|
1667
1897
|
await writeFile3(lefthookPath, appended, "utf8");
|
|
1668
1898
|
writtenFiles.push(relativePath);
|
|
1669
1899
|
} else {
|
|
@@ -1678,6 +1908,7 @@ ${LEFTHOOK_BLOCK}`;
|
|
|
1678
1908
|
writtenFiles.push(relativePath);
|
|
1679
1909
|
}
|
|
1680
1910
|
instructions.push("Lefthook pre-commit hook configured to run forge-ts check.");
|
|
1911
|
+
instructions.push("Lefthook pre-push hook configured to run forge-ts prepublish.");
|
|
1681
1912
|
}
|
|
1682
1913
|
const data = {
|
|
1683
1914
|
success: true,
|
|
@@ -2341,7 +2572,7 @@ var initCommand2 = defineCommand13({
|
|
|
2341
2572
|
if (hasSubCommand) {
|
|
2342
2573
|
return;
|
|
2343
2574
|
}
|
|
2344
|
-
const { runInitProject: runInitProject2 } = await import("./init-project-
|
|
2575
|
+
const { runInitProject: runInitProject2 } = await import("./init-project-6CWF4CCX.js");
|
|
2345
2576
|
const { emitResult: emitResult2, resolveExitCode: resolveExitCode2 } = await import("./output-OSCHMPOX.js");
|
|
2346
2577
|
const { forgeLogger: forgeLogger2 } = await import("./forge-logger-RTOBEKWH.js");
|
|
2347
2578
|
const output = await runInitProject2({
|