@forge-ts/cli 0.13.0 → 0.15.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-7UPSAG3L.js +44 -0
- package/dist/chunk-7UPSAG3L.js.map +1 -0
- package/dist/chunk-CINQWGH7.js +344 -0
- package/dist/chunk-CINQWGH7.js.map +1 -0
- package/dist/chunk-ZFFY4AQX.js +73 -0
- package/dist/chunk-ZFFY4AQX.js.map +1 -0
- package/dist/index.d.ts +246 -1
- package/dist/index.js +646 -161
- package/dist/index.js.map +1 -1
- package/dist/init-project-5DESIZ73.js +14 -0
- package/dist/init-project-5DESIZ73.js.map +1 -0
- package/dist/logger-MMBBZG6U.js +8 -0
- package/dist/logger-MMBBZG6U.js.map +1 -0
- package/dist/output-OSCHMPOX.js +10 -0
- package/dist/output-OSCHMPOX.js.map +1 -0
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
initProjectCommand,
|
|
4
|
+
runInitProject
|
|
5
|
+
} from "./chunk-CINQWGH7.js";
|
|
6
|
+
import {
|
|
7
|
+
emitResult,
|
|
8
|
+
resolveExitCode
|
|
9
|
+
} from "./chunk-ZFFY4AQX.js";
|
|
10
|
+
import {
|
|
11
|
+
createLogger
|
|
12
|
+
} from "./chunk-7UPSAG3L.js";
|
|
2
13
|
|
|
3
14
|
// src/index.ts
|
|
4
15
|
import { createRequire } from "module";
|
|
5
|
-
import { defineCommand as
|
|
16
|
+
import { defineCommand as defineCommand13, runMain } from "citty";
|
|
6
17
|
|
|
7
18
|
// src/commands/audit.ts
|
|
8
19
|
import {
|
|
@@ -10,74 +21,6 @@ import {
|
|
|
10
21
|
readAuditLog
|
|
11
22
|
} from "@forge-ts/core";
|
|
12
23
|
import { defineCommand } from "citty";
|
|
13
|
-
|
|
14
|
-
// src/output.ts
|
|
15
|
-
import { randomUUID } from "crypto";
|
|
16
|
-
import {
|
|
17
|
-
createEnvelope,
|
|
18
|
-
resolveFlags
|
|
19
|
-
} from "@cleocode/lafs-protocol";
|
|
20
|
-
function emitResult(output, flags, humanFormatter) {
|
|
21
|
-
const flagInput = {
|
|
22
|
-
json: flags.json,
|
|
23
|
-
human: flags.human,
|
|
24
|
-
quiet: flags.quiet,
|
|
25
|
-
mvi: flags.mvi,
|
|
26
|
-
// LAFS 1.8.0: TTY detection drives the default format.
|
|
27
|
-
// Terminals get human output, pipes/agents get JSON.
|
|
28
|
-
tty: process.stdout.isTTY ?? false
|
|
29
|
-
};
|
|
30
|
-
const resolved = resolveFlags(flagInput);
|
|
31
|
-
const format = resolved.format.format;
|
|
32
|
-
const quiet = resolved.format.quiet;
|
|
33
|
-
if (quiet) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
const meta = {
|
|
37
|
-
operation: `forge-ts.${output.operation}`,
|
|
38
|
-
requestId: randomUUID(),
|
|
39
|
-
transport: "cli",
|
|
40
|
-
mvi: flags.mvi ?? "full"
|
|
41
|
-
};
|
|
42
|
-
const resultData = output.data;
|
|
43
|
-
if (output.warnings && output.warnings.length > 0) {
|
|
44
|
-
resultData._warnings = output.warnings.map((w) => ({
|
|
45
|
-
code: w.code,
|
|
46
|
-
message: w.message
|
|
47
|
-
}));
|
|
48
|
-
}
|
|
49
|
-
const envelope = output.success ? createEnvelope({
|
|
50
|
-
success: true,
|
|
51
|
-
result: resultData,
|
|
52
|
-
meta
|
|
53
|
-
}) : createEnvelope({
|
|
54
|
-
success: false,
|
|
55
|
-
result: resultData,
|
|
56
|
-
error: {
|
|
57
|
-
code: output.errors?.[0]?.code ?? "FORGE_CHECK_FAILED",
|
|
58
|
-
message: output.errors?.[0]?.message ?? "Check failed \u2014 see result for actionable fixes",
|
|
59
|
-
category: "VALIDATION",
|
|
60
|
-
retryable: true,
|
|
61
|
-
retryAfterMs: null
|
|
62
|
-
},
|
|
63
|
-
meta
|
|
64
|
-
});
|
|
65
|
-
if (format === "json") {
|
|
66
|
-
process.stdout.write(`${JSON.stringify(envelope, null, 2)}
|
|
67
|
-
`);
|
|
68
|
-
} else {
|
|
69
|
-
const formatted = humanFormatter(output.data, output);
|
|
70
|
-
if (formatted) {
|
|
71
|
-
console.log(formatted);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
function resolveExitCode(output) {
|
|
76
|
-
if (output.success) return 0;
|
|
77
|
-
return 1;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// src/commands/audit.ts
|
|
81
24
|
function runAudit(args) {
|
|
82
25
|
const rootDir = args.cwd ?? process.cwd();
|
|
83
26
|
const limit = args.limit ?? 20;
|
|
@@ -178,46 +121,6 @@ import { generateApi } from "@forge-ts/api";
|
|
|
178
121
|
import { loadConfig } from "@forge-ts/core";
|
|
179
122
|
import { generate } from "@forge-ts/gen";
|
|
180
123
|
import { defineCommand as defineCommand2 } from "citty";
|
|
181
|
-
|
|
182
|
-
// src/logger.ts
|
|
183
|
-
var GREEN = "\x1B[32m";
|
|
184
|
-
var YELLOW = "\x1B[33m";
|
|
185
|
-
var RED = "\x1B[31m";
|
|
186
|
-
var BOLD = "\x1B[1m";
|
|
187
|
-
var RESET = "\x1B[0m";
|
|
188
|
-
function createLogger(options) {
|
|
189
|
-
const useColors = options?.colors ?? process.stdout.isTTY ?? false;
|
|
190
|
-
function colorize(text, code) {
|
|
191
|
-
return useColors ? `${code}${text}${RESET}` : text;
|
|
192
|
-
}
|
|
193
|
-
function bold(text) {
|
|
194
|
-
return useColors ? `${BOLD}${text}${RESET}` : text;
|
|
195
|
-
}
|
|
196
|
-
return {
|
|
197
|
-
info(msg) {
|
|
198
|
-
console.log(msg);
|
|
199
|
-
},
|
|
200
|
-
success(msg) {
|
|
201
|
-
const prefix = colorize("\u2713", GREEN);
|
|
202
|
-
console.log(`${prefix} ${msg}`);
|
|
203
|
-
},
|
|
204
|
-
warn(msg) {
|
|
205
|
-
const prefix = colorize("warn", YELLOW);
|
|
206
|
-
console.warn(`${bold(prefix)} ${msg}`);
|
|
207
|
-
},
|
|
208
|
-
error(msg) {
|
|
209
|
-
const prefix = colorize("error", RED);
|
|
210
|
-
console.error(`${bold(prefix)} ${msg}`);
|
|
211
|
-
},
|
|
212
|
-
step(label, detail, duration) {
|
|
213
|
-
const check = colorize("\u2713", GREEN);
|
|
214
|
-
const durationStr = duration !== void 0 ? ` (${duration}ms)` : "";
|
|
215
|
-
console.log(` ${check} ${bold(label)}: ${detail}${durationStr}`);
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// src/commands/build.ts
|
|
221
124
|
async function runBuild(args) {
|
|
222
125
|
const config = await loadConfig(args.cwd);
|
|
223
126
|
const buildStart = Date.now();
|
|
@@ -917,12 +820,486 @@ var checkCommand = defineCommand4({
|
|
|
917
820
|
}
|
|
918
821
|
});
|
|
919
822
|
|
|
823
|
+
// src/commands/doctor.ts
|
|
824
|
+
import { existsSync, readFileSync } from "fs";
|
|
825
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
826
|
+
import { join } from "path";
|
|
827
|
+
import { defineCommand as defineCommand5 } from "citty";
|
|
828
|
+
function readJsonSafe(filePath) {
|
|
829
|
+
if (!existsSync(filePath)) {
|
|
830
|
+
return null;
|
|
831
|
+
}
|
|
832
|
+
try {
|
|
833
|
+
const raw = readFileSync(filePath, "utf8");
|
|
834
|
+
return JSON.parse(raw);
|
|
835
|
+
} catch {
|
|
836
|
+
return null;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
var DEFAULT_CONFIG_CONTENT = `import { defineConfig } from "@forge-ts/core";
|
|
840
|
+
|
|
841
|
+
export default defineConfig({
|
|
842
|
+
rootDir: ".",
|
|
843
|
+
tsconfig: "tsconfig.json",
|
|
844
|
+
outDir: "docs/generated",
|
|
845
|
+
enforce: {
|
|
846
|
+
enabled: true,
|
|
847
|
+
minVisibility: "public",
|
|
848
|
+
strict: false,
|
|
849
|
+
},
|
|
850
|
+
gen: {
|
|
851
|
+
enabled: true,
|
|
852
|
+
formats: ["mdx"],
|
|
853
|
+
llmsTxt: true,
|
|
854
|
+
readmeSync: false,
|
|
855
|
+
ssgTarget: "mintlify",
|
|
856
|
+
},
|
|
857
|
+
});
|
|
858
|
+
`;
|
|
859
|
+
var DEFAULT_TSDOC_CONTENT = JSON.stringify(
|
|
860
|
+
{
|
|
861
|
+
$schema: "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
|
|
862
|
+
extends: ["@forge-ts/tsdoc-config/tsdoc.json"]
|
|
863
|
+
},
|
|
864
|
+
null,
|
|
865
|
+
" "
|
|
866
|
+
);
|
|
867
|
+
async function runDoctor(args) {
|
|
868
|
+
const start = Date.now();
|
|
869
|
+
const rootDir = args.cwd ?? process.cwd();
|
|
870
|
+
const fix = args.fix ?? false;
|
|
871
|
+
const checks = [];
|
|
872
|
+
const fixed = [];
|
|
873
|
+
const configPath = join(rootDir, "forge-ts.config.ts");
|
|
874
|
+
const configJsPath = join(rootDir, "forge-ts.config.js");
|
|
875
|
+
if (existsSync(configPath) || existsSync(configJsPath)) {
|
|
876
|
+
const which = existsSync(configPath) ? "forge-ts.config.ts" : "forge-ts.config.js";
|
|
877
|
+
checks.push({
|
|
878
|
+
name: "forge-ts.config",
|
|
879
|
+
status: "pass",
|
|
880
|
+
message: `${which} \u2014 found`,
|
|
881
|
+
fixable: false
|
|
882
|
+
});
|
|
883
|
+
} else if (fix) {
|
|
884
|
+
await mkdir(rootDir, { recursive: true });
|
|
885
|
+
await writeFile(configPath, DEFAULT_CONFIG_CONTENT, "utf8");
|
|
886
|
+
fixed.push("forge-ts.config.ts");
|
|
887
|
+
checks.push({
|
|
888
|
+
name: "forge-ts.config",
|
|
889
|
+
status: "pass",
|
|
890
|
+
message: "forge-ts.config.ts \u2014 created by --fix",
|
|
891
|
+
fixable: true
|
|
892
|
+
});
|
|
893
|
+
} else {
|
|
894
|
+
checks.push({
|
|
895
|
+
name: "forge-ts.config",
|
|
896
|
+
status: "error",
|
|
897
|
+
message: "forge-ts.config.ts \u2014 MISSING (run forge-ts init or forge-ts doctor --fix)",
|
|
898
|
+
fixable: true
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
const tsdocPath = join(rootDir, "tsdoc.json");
|
|
902
|
+
if (existsSync(tsdocPath)) {
|
|
903
|
+
const tsdoc = readJsonSafe(tsdocPath);
|
|
904
|
+
if (tsdoc?.extends && tsdoc.extends.includes("@forge-ts/tsdoc-config/tsdoc.json")) {
|
|
905
|
+
checks.push({
|
|
906
|
+
name: "tsdoc.json",
|
|
907
|
+
status: "pass",
|
|
908
|
+
message: "tsdoc.json \u2014 extends @forge-ts/tsdoc-config",
|
|
909
|
+
fixable: false
|
|
910
|
+
});
|
|
911
|
+
} else {
|
|
912
|
+
checks.push({
|
|
913
|
+
name: "tsdoc.json",
|
|
914
|
+
status: "warn",
|
|
915
|
+
message: "tsdoc.json \u2014 does not extend @forge-ts/tsdoc-config",
|
|
916
|
+
fixable: false
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
} else if (fix) {
|
|
920
|
+
await writeFile(tsdocPath, `${DEFAULT_TSDOC_CONTENT}
|
|
921
|
+
`, "utf8");
|
|
922
|
+
fixed.push("tsdoc.json");
|
|
923
|
+
checks.push({
|
|
924
|
+
name: "tsdoc.json",
|
|
925
|
+
status: "pass",
|
|
926
|
+
message: "tsdoc.json \u2014 created by --fix",
|
|
927
|
+
fixable: true
|
|
928
|
+
});
|
|
929
|
+
} else {
|
|
930
|
+
checks.push({
|
|
931
|
+
name: "tsdoc.json",
|
|
932
|
+
status: "error",
|
|
933
|
+
message: "tsdoc.json \u2014 MISSING (run forge-ts init or forge-ts doctor --fix)",
|
|
934
|
+
fixable: true
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
const tsdocConfigModulePath = join(
|
|
938
|
+
rootDir,
|
|
939
|
+
"node_modules",
|
|
940
|
+
"@forge-ts",
|
|
941
|
+
"tsdoc-config",
|
|
942
|
+
"package.json"
|
|
943
|
+
);
|
|
944
|
+
if (existsSync(tsdocConfigModulePath)) {
|
|
945
|
+
const tsdocPkg = readJsonSafe(
|
|
946
|
+
tsdocConfigModulePath
|
|
947
|
+
);
|
|
948
|
+
const version = tsdocPkg?.version ?? "unknown";
|
|
949
|
+
checks.push({
|
|
950
|
+
name: "@forge-ts/tsdoc-config",
|
|
951
|
+
status: "pass",
|
|
952
|
+
message: `@forge-ts/tsdoc-config \u2014 installed (${version})`,
|
|
953
|
+
fixable: false
|
|
954
|
+
});
|
|
955
|
+
} else {
|
|
956
|
+
checks.push({
|
|
957
|
+
name: "@forge-ts/tsdoc-config",
|
|
958
|
+
status: "warn",
|
|
959
|
+
message: "@forge-ts/tsdoc-config \u2014 MISSING (run npm install @forge-ts/tsdoc-config)",
|
|
960
|
+
fixable: false
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
const tsPkgPath = join(
|
|
964
|
+
rootDir,
|
|
965
|
+
"node_modules",
|
|
966
|
+
"typescript",
|
|
967
|
+
"package.json"
|
|
968
|
+
);
|
|
969
|
+
if (existsSync(tsPkgPath)) {
|
|
970
|
+
const tsPkg = readJsonSafe(tsPkgPath);
|
|
971
|
+
const version = tsPkg?.version ?? "unknown";
|
|
972
|
+
checks.push({
|
|
973
|
+
name: "TypeScript",
|
|
974
|
+
status: "pass",
|
|
975
|
+
message: `TypeScript \u2014 ${version}`,
|
|
976
|
+
fixable: false
|
|
977
|
+
});
|
|
978
|
+
} else {
|
|
979
|
+
const pkgPath = join(rootDir, "package.json");
|
|
980
|
+
const pkg2 = readJsonSafe(pkgPath);
|
|
981
|
+
const allDeps = {
|
|
982
|
+
...pkg2?.dependencies,
|
|
983
|
+
...pkg2?.devDependencies
|
|
984
|
+
};
|
|
985
|
+
if ("typescript" in allDeps) {
|
|
986
|
+
checks.push({
|
|
987
|
+
name: "TypeScript",
|
|
988
|
+
status: "warn",
|
|
989
|
+
message: `TypeScript \u2014 in package.json (${allDeps.typescript}) but not in node_modules`,
|
|
990
|
+
fixable: false
|
|
991
|
+
});
|
|
992
|
+
} else {
|
|
993
|
+
checks.push({
|
|
994
|
+
name: "TypeScript",
|
|
995
|
+
status: "error",
|
|
996
|
+
message: "TypeScript \u2014 MISSING (run npm install -D typescript)",
|
|
997
|
+
fixable: false
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
const tsconfigPath = join(rootDir, "tsconfig.json");
|
|
1002
|
+
if (existsSync(tsconfigPath)) {
|
|
1003
|
+
const tsconfig = readJsonSafe(tsconfigPath);
|
|
1004
|
+
if (tsconfig?.compilerOptions?.strict === true) {
|
|
1005
|
+
checks.push({
|
|
1006
|
+
name: "tsconfig.json",
|
|
1007
|
+
status: "pass",
|
|
1008
|
+
message: "tsconfig.json \u2014 strict mode enabled",
|
|
1009
|
+
fixable: false
|
|
1010
|
+
});
|
|
1011
|
+
} else {
|
|
1012
|
+
const missingFlags = ["strict"];
|
|
1013
|
+
if (!tsconfig?.compilerOptions?.strictNullChecks) {
|
|
1014
|
+
missingFlags.push("strictNullChecks");
|
|
1015
|
+
}
|
|
1016
|
+
if (!tsconfig?.compilerOptions?.noImplicitAny) {
|
|
1017
|
+
missingFlags.push("noImplicitAny");
|
|
1018
|
+
}
|
|
1019
|
+
checks.push({
|
|
1020
|
+
name: "tsconfig.json",
|
|
1021
|
+
status: "warn",
|
|
1022
|
+
message: `tsconfig.json \u2014 strict mode not fully enabled (missing ${missingFlags.join(", ")})`,
|
|
1023
|
+
fixable: false
|
|
1024
|
+
});
|
|
1025
|
+
}
|
|
1026
|
+
} else {
|
|
1027
|
+
checks.push({
|
|
1028
|
+
name: "tsconfig.json",
|
|
1029
|
+
status: "warn",
|
|
1030
|
+
message: "tsconfig.json \u2014 not found",
|
|
1031
|
+
fixable: false
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
const biomePath = join(rootDir, "biome.json");
|
|
1035
|
+
const biomecPath = join(rootDir, "biome.jsonc");
|
|
1036
|
+
if (existsSync(biomePath) || existsSync(biomecPath)) {
|
|
1037
|
+
checks.push({
|
|
1038
|
+
name: "biome.json",
|
|
1039
|
+
status: "pass",
|
|
1040
|
+
message: "biome.json \u2014 found",
|
|
1041
|
+
fixable: false
|
|
1042
|
+
});
|
|
1043
|
+
} else {
|
|
1044
|
+
checks.push({
|
|
1045
|
+
name: "biome.json",
|
|
1046
|
+
status: "info",
|
|
1047
|
+
message: "biome.json \u2014 not found (optional)",
|
|
1048
|
+
fixable: false
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
const lockPath = join(rootDir, ".forge-lock.json");
|
|
1052
|
+
if (existsSync(lockPath)) {
|
|
1053
|
+
const lock = readJsonSafe(lockPath);
|
|
1054
|
+
if (lock?.lockedAt) {
|
|
1055
|
+
checks.push({
|
|
1056
|
+
name: ".forge-lock.json",
|
|
1057
|
+
status: "pass",
|
|
1058
|
+
message: `.forge-lock.json \u2014 locked at ${lock.lockedAt}`,
|
|
1059
|
+
fixable: false
|
|
1060
|
+
});
|
|
1061
|
+
} else {
|
|
1062
|
+
checks.push({
|
|
1063
|
+
name: ".forge-lock.json",
|
|
1064
|
+
status: "warn",
|
|
1065
|
+
message: ".forge-lock.json \u2014 invalid format (run forge-ts lock to regenerate)",
|
|
1066
|
+
fixable: false
|
|
1067
|
+
});
|
|
1068
|
+
}
|
|
1069
|
+
} else {
|
|
1070
|
+
checks.push({
|
|
1071
|
+
name: ".forge-lock.json",
|
|
1072
|
+
status: "warn",
|
|
1073
|
+
message: ".forge-lock.json \u2014 not locked (run forge-ts lock)",
|
|
1074
|
+
fixable: false
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
1077
|
+
const auditPath = join(rootDir, ".forge-audit.jsonl");
|
|
1078
|
+
if (existsSync(auditPath)) {
|
|
1079
|
+
try {
|
|
1080
|
+
const raw = readFileSync(auditPath, "utf8");
|
|
1081
|
+
const lines = raw.split("\n").filter((line) => line.trim().length > 0);
|
|
1082
|
+
checks.push({
|
|
1083
|
+
name: ".forge-audit.jsonl",
|
|
1084
|
+
status: "info",
|
|
1085
|
+
message: `.forge-audit.jsonl \u2014 ${lines.length} event${lines.length !== 1 ? "s" : ""}`,
|
|
1086
|
+
fixable: false
|
|
1087
|
+
});
|
|
1088
|
+
} catch {
|
|
1089
|
+
checks.push({
|
|
1090
|
+
name: ".forge-audit.jsonl",
|
|
1091
|
+
status: "warn",
|
|
1092
|
+
message: ".forge-audit.jsonl \u2014 exists but unreadable",
|
|
1093
|
+
fixable: false
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
} else {
|
|
1097
|
+
checks.push({
|
|
1098
|
+
name: ".forge-audit.jsonl",
|
|
1099
|
+
status: "info",
|
|
1100
|
+
message: ".forge-audit.jsonl \u2014 no audit trail",
|
|
1101
|
+
fixable: false
|
|
1102
|
+
});
|
|
1103
|
+
}
|
|
1104
|
+
const bypassPath = join(rootDir, ".forge-bypass.json");
|
|
1105
|
+
if (existsSync(bypassPath)) {
|
|
1106
|
+
const records = readJsonSafe(bypassPath);
|
|
1107
|
+
if (records && Array.isArray(records)) {
|
|
1108
|
+
const now = /* @__PURE__ */ new Date();
|
|
1109
|
+
const active = records.filter(
|
|
1110
|
+
(r) => r.expiresAt && new Date(r.expiresAt) > now
|
|
1111
|
+
);
|
|
1112
|
+
const expired = records.length - active.length;
|
|
1113
|
+
if (active.length > 0) {
|
|
1114
|
+
checks.push({
|
|
1115
|
+
name: ".forge-bypass.json",
|
|
1116
|
+
status: "info",
|
|
1117
|
+
message: `.forge-bypass.json \u2014 ${active.length} active bypass${active.length !== 1 ? "es" : ""}`,
|
|
1118
|
+
fixable: false
|
|
1119
|
+
});
|
|
1120
|
+
} else if (expired > 0) {
|
|
1121
|
+
checks.push({
|
|
1122
|
+
name: ".forge-bypass.json",
|
|
1123
|
+
status: "info",
|
|
1124
|
+
message: `.forge-bypass.json \u2014 ${expired} expired bypass${expired !== 1 ? "es" : ""} (run cleanup)`,
|
|
1125
|
+
fixable: false
|
|
1126
|
+
});
|
|
1127
|
+
} else {
|
|
1128
|
+
checks.push({
|
|
1129
|
+
name: ".forge-bypass.json",
|
|
1130
|
+
status: "pass",
|
|
1131
|
+
message: ".forge-bypass.json \u2014 no active bypasses",
|
|
1132
|
+
fixable: false
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
} else {
|
|
1136
|
+
checks.push({
|
|
1137
|
+
name: ".forge-bypass.json",
|
|
1138
|
+
status: "warn",
|
|
1139
|
+
message: ".forge-bypass.json \u2014 invalid format",
|
|
1140
|
+
fixable: false
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
} else {
|
|
1144
|
+
checks.push({
|
|
1145
|
+
name: ".forge-bypass.json",
|
|
1146
|
+
status: "pass",
|
|
1147
|
+
message: ".forge-bypass.json \u2014 no active bypasses",
|
|
1148
|
+
fixable: false
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
const huskyPreCommit = join(rootDir, ".husky", "pre-commit");
|
|
1152
|
+
const lefthookYml = join(rootDir, "lefthook.yml");
|
|
1153
|
+
let hookConfigured = false;
|
|
1154
|
+
let hookLocation = "";
|
|
1155
|
+
if (existsSync(huskyPreCommit)) {
|
|
1156
|
+
try {
|
|
1157
|
+
const content = readFileSync(huskyPreCommit, "utf8");
|
|
1158
|
+
if (content.includes("forge-ts check")) {
|
|
1159
|
+
hookConfigured = true;
|
|
1160
|
+
hookLocation = "husky pre-commit";
|
|
1161
|
+
}
|
|
1162
|
+
} catch {
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
if (!hookConfigured && existsSync(lefthookYml)) {
|
|
1166
|
+
try {
|
|
1167
|
+
const content = readFileSync(lefthookYml, "utf8");
|
|
1168
|
+
if (content.includes("forge-ts check")) {
|
|
1169
|
+
hookConfigured = true;
|
|
1170
|
+
hookLocation = "lefthook";
|
|
1171
|
+
}
|
|
1172
|
+
} catch {
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
if (hookConfigured) {
|
|
1176
|
+
checks.push({
|
|
1177
|
+
name: "Git hooks",
|
|
1178
|
+
status: "pass",
|
|
1179
|
+
message: `Git hooks \u2014 forge-ts check in ${hookLocation}`,
|
|
1180
|
+
fixable: false
|
|
1181
|
+
});
|
|
1182
|
+
} else {
|
|
1183
|
+
checks.push({
|
|
1184
|
+
name: "Git hooks",
|
|
1185
|
+
status: "warn",
|
|
1186
|
+
message: "Git hooks \u2014 forge-ts check not in pre-commit (run forge-ts init hooks)",
|
|
1187
|
+
fixable: false
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
const summary = {
|
|
1191
|
+
passed: checks.filter((c) => c.status === "pass").length,
|
|
1192
|
+
warnings: checks.filter((c) => c.status === "warn").length,
|
|
1193
|
+
errors: checks.filter((c) => c.status === "error").length,
|
|
1194
|
+
info: checks.filter((c) => c.status === "info").length
|
|
1195
|
+
};
|
|
1196
|
+
const data = {
|
|
1197
|
+
success: summary.errors === 0,
|
|
1198
|
+
checks,
|
|
1199
|
+
summary,
|
|
1200
|
+
fixed
|
|
1201
|
+
};
|
|
1202
|
+
return {
|
|
1203
|
+
operation: "doctor",
|
|
1204
|
+
success: summary.errors === 0,
|
|
1205
|
+
data,
|
|
1206
|
+
duration: Date.now() - start
|
|
1207
|
+
};
|
|
1208
|
+
}
|
|
1209
|
+
var STATUS_LABELS = {
|
|
1210
|
+
pass: "[PASS]",
|
|
1211
|
+
warn: "[WARN]",
|
|
1212
|
+
error: "[FAIL]",
|
|
1213
|
+
info: "[INFO]"
|
|
1214
|
+
};
|
|
1215
|
+
function formatDoctorHuman(result) {
|
|
1216
|
+
const lines = [];
|
|
1217
|
+
lines.push("\nforge-ts doctor: project health check\n");
|
|
1218
|
+
for (const check of result.checks) {
|
|
1219
|
+
const label = STATUS_LABELS[check.status];
|
|
1220
|
+
lines.push(` ${label} ${check.message}`);
|
|
1221
|
+
}
|
|
1222
|
+
if (result.fixed.length > 0) {
|
|
1223
|
+
lines.push("");
|
|
1224
|
+
lines.push(" Fixed:");
|
|
1225
|
+
for (const file of result.fixed) {
|
|
1226
|
+
lines.push(` ${file}`);
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
lines.push("");
|
|
1230
|
+
lines.push(
|
|
1231
|
+
` Summary: ${result.summary.passed} passed, ${result.summary.warnings} warning${result.summary.warnings !== 1 ? "s" : ""}, ${result.summary.errors} error${result.summary.errors !== 1 ? "s" : ""}`
|
|
1232
|
+
);
|
|
1233
|
+
if (result.summary.errors > 0 || result.summary.warnings > 0) {
|
|
1234
|
+
lines.push(
|
|
1235
|
+
" Run: forge-ts doctor --fix to auto-fix resolvable issues"
|
|
1236
|
+
);
|
|
1237
|
+
}
|
|
1238
|
+
return lines.join("\n");
|
|
1239
|
+
}
|
|
1240
|
+
var doctorCommand = defineCommand5({
|
|
1241
|
+
meta: {
|
|
1242
|
+
name: "doctor",
|
|
1243
|
+
description: "Project integrity check and repair"
|
|
1244
|
+
},
|
|
1245
|
+
args: {
|
|
1246
|
+
cwd: {
|
|
1247
|
+
type: "string",
|
|
1248
|
+
description: "Project root directory"
|
|
1249
|
+
},
|
|
1250
|
+
fix: {
|
|
1251
|
+
type: "boolean",
|
|
1252
|
+
description: "Auto-fix resolvable issues",
|
|
1253
|
+
default: false
|
|
1254
|
+
},
|
|
1255
|
+
json: {
|
|
1256
|
+
type: "boolean",
|
|
1257
|
+
description: "Output as LAFS JSON envelope",
|
|
1258
|
+
default: false
|
|
1259
|
+
},
|
|
1260
|
+
human: {
|
|
1261
|
+
type: "boolean",
|
|
1262
|
+
description: "Output as formatted text",
|
|
1263
|
+
default: false
|
|
1264
|
+
},
|
|
1265
|
+
quiet: {
|
|
1266
|
+
type: "boolean",
|
|
1267
|
+
description: "Suppress non-essential output",
|
|
1268
|
+
default: false
|
|
1269
|
+
},
|
|
1270
|
+
mvi: {
|
|
1271
|
+
type: "string",
|
|
1272
|
+
description: "MVI verbosity level: minimal, standard, full"
|
|
1273
|
+
}
|
|
1274
|
+
},
|
|
1275
|
+
async run({ args }) {
|
|
1276
|
+
const output = await runDoctor({
|
|
1277
|
+
cwd: args.cwd,
|
|
1278
|
+
fix: args.fix,
|
|
1279
|
+
mvi: args.mvi
|
|
1280
|
+
});
|
|
1281
|
+
const flags = {
|
|
1282
|
+
json: args.json,
|
|
1283
|
+
human: args.human,
|
|
1284
|
+
quiet: args.quiet,
|
|
1285
|
+
mvi: args.mvi
|
|
1286
|
+
};
|
|
1287
|
+
emitResult(output, flags, (data, cmd) => {
|
|
1288
|
+
if (!cmd.success) {
|
|
1289
|
+
return formatDoctorHuman(data);
|
|
1290
|
+
}
|
|
1291
|
+
return formatDoctorHuman(data);
|
|
1292
|
+
});
|
|
1293
|
+
process.exit(resolveExitCode(output));
|
|
1294
|
+
}
|
|
1295
|
+
});
|
|
1296
|
+
|
|
920
1297
|
// src/commands/docs-dev.ts
|
|
921
1298
|
import { spawn } from "child_process";
|
|
922
1299
|
import { resolve } from "path";
|
|
923
1300
|
import { loadConfig as loadConfig4 } from "@forge-ts/core";
|
|
924
1301
|
import { DEFAULT_TARGET, getAdapter } from "@forge-ts/gen";
|
|
925
|
-
import { defineCommand as
|
|
1302
|
+
import { defineCommand as defineCommand6 } from "citty";
|
|
926
1303
|
async function runDocsDev(args) {
|
|
927
1304
|
const logger = createLogger();
|
|
928
1305
|
const config = await loadConfig4(args.cwd);
|
|
@@ -955,7 +1332,7 @@ async function runDocsDev(args) {
|
|
|
955
1332
|
proc.on("error", reject);
|
|
956
1333
|
});
|
|
957
1334
|
}
|
|
958
|
-
var docsDevCommand =
|
|
1335
|
+
var docsDevCommand = defineCommand6({
|
|
959
1336
|
meta: {
|
|
960
1337
|
name: "dev",
|
|
961
1338
|
description: "Start a local doc preview server"
|
|
@@ -980,16 +1357,16 @@ var docsDevCommand = defineCommand5({
|
|
|
980
1357
|
});
|
|
981
1358
|
|
|
982
1359
|
// src/commands/init-docs.ts
|
|
983
|
-
import { existsSync } from "fs";
|
|
984
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
985
|
-
import { join, resolve as resolve2 } from "path";
|
|
1360
|
+
import { existsSync as existsSync2 } from "fs";
|
|
1361
|
+
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
1362
|
+
import { join as join2, resolve as resolve2 } from "path";
|
|
986
1363
|
import { loadConfig as loadConfig5 } from "@forge-ts/core";
|
|
987
1364
|
import {
|
|
988
1365
|
DEFAULT_TARGET as DEFAULT_TARGET2,
|
|
989
1366
|
getAdapter as getAdapter2,
|
|
990
1367
|
getAvailableTargets
|
|
991
1368
|
} from "@forge-ts/gen";
|
|
992
|
-
import { defineCommand as
|
|
1369
|
+
import { defineCommand as defineCommand7 } from "citty";
|
|
993
1370
|
async function runInitDocs(args) {
|
|
994
1371
|
const start = Date.now();
|
|
995
1372
|
const rawTarget = args.target ?? DEFAULT_TARGET2;
|
|
@@ -1060,15 +1437,15 @@ async function runInitDocs(args) {
|
|
|
1060
1437
|
const manifest = adapter.scaffold(context);
|
|
1061
1438
|
const writtenFiles = [];
|
|
1062
1439
|
for (const file of manifest.files) {
|
|
1063
|
-
const filePath =
|
|
1440
|
+
const filePath = join2(outDir, file.path);
|
|
1064
1441
|
const fileDir = filePath.substring(0, filePath.lastIndexOf("/"));
|
|
1065
|
-
await
|
|
1066
|
-
await
|
|
1442
|
+
await mkdir2(fileDir, { recursive: true });
|
|
1443
|
+
await writeFile2(filePath, file.content, "utf8");
|
|
1067
1444
|
writtenFiles.push(file.path);
|
|
1068
1445
|
}
|
|
1069
1446
|
if (config.tsdoc.writeConfig) {
|
|
1070
|
-
const tsdocPath =
|
|
1071
|
-
if (
|
|
1447
|
+
const tsdocPath = join2(config.rootDir, "tsdoc.json");
|
|
1448
|
+
if (existsSync2(tsdocPath)) {
|
|
1072
1449
|
warnings.push({
|
|
1073
1450
|
code: "INIT_TSDOC_EXISTS",
|
|
1074
1451
|
message: "tsdoc.json already exists \u2014 skipping. Remove it and re-run to regenerate."
|
|
@@ -1082,8 +1459,8 @@ async function runInitDocs(args) {
|
|
|
1082
1459
|
null,
|
|
1083
1460
|
" "
|
|
1084
1461
|
);
|
|
1085
|
-
await
|
|
1086
|
-
await
|
|
1462
|
+
await mkdir2(config.rootDir, { recursive: true });
|
|
1463
|
+
await writeFile2(tsdocPath, `${tsdocContent}
|
|
1087
1464
|
`, "utf8");
|
|
1088
1465
|
writtenFiles.push("tsdoc.json");
|
|
1089
1466
|
}
|
|
@@ -1145,7 +1522,7 @@ function formatInitDocsHuman(result) {
|
|
|
1145
1522
|
);
|
|
1146
1523
|
return lines.join("\n");
|
|
1147
1524
|
}
|
|
1148
|
-
var initDocsCommand =
|
|
1525
|
+
var initDocsCommand = defineCommand7({
|
|
1149
1526
|
meta: {
|
|
1150
1527
|
name: "init",
|
|
1151
1528
|
description: "Scaffold a documentation site"
|
|
@@ -1214,7 +1591,7 @@ var initDocsCommand = defineCommand6({
|
|
|
1214
1591
|
process.exit(resolveExitCode(output));
|
|
1215
1592
|
}
|
|
1216
1593
|
});
|
|
1217
|
-
var initCommand =
|
|
1594
|
+
var initCommand = defineCommand7({
|
|
1218
1595
|
meta: {
|
|
1219
1596
|
name: "init",
|
|
1220
1597
|
description: "Scaffold project artefacts"
|
|
@@ -1225,23 +1602,23 @@ var initCommand = defineCommand6({
|
|
|
1225
1602
|
});
|
|
1226
1603
|
|
|
1227
1604
|
// src/commands/init-hooks.ts
|
|
1228
|
-
import { existsSync as
|
|
1229
|
-
import { mkdir as
|
|
1230
|
-
import { join as
|
|
1231
|
-
import { defineCommand as
|
|
1605
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
1606
|
+
import { mkdir as mkdir3, readFile, writeFile as writeFile3 } from "fs/promises";
|
|
1607
|
+
import { join as join3 } from "path";
|
|
1608
|
+
import { defineCommand as defineCommand8 } from "citty";
|
|
1232
1609
|
function detectHookManager(rootDir) {
|
|
1233
|
-
const huskyDir =
|
|
1234
|
-
if (
|
|
1610
|
+
const huskyDir = join3(rootDir, ".husky");
|
|
1611
|
+
if (existsSync3(huskyDir)) {
|
|
1235
1612
|
return "husky";
|
|
1236
1613
|
}
|
|
1237
|
-
const lefthookYml =
|
|
1238
|
-
if (
|
|
1614
|
+
const lefthookYml = join3(rootDir, "lefthook.yml");
|
|
1615
|
+
if (existsSync3(lefthookYml)) {
|
|
1239
1616
|
return "lefthook";
|
|
1240
1617
|
}
|
|
1241
|
-
const pkgJsonPath =
|
|
1242
|
-
if (
|
|
1618
|
+
const pkgJsonPath = join3(rootDir, "package.json");
|
|
1619
|
+
if (existsSync3(pkgJsonPath)) {
|
|
1243
1620
|
try {
|
|
1244
|
-
const raw =
|
|
1621
|
+
const raw = readFileSync2(pkgJsonPath, "utf8");
|
|
1245
1622
|
const pkg2 = JSON.parse(raw);
|
|
1246
1623
|
const allDeps = { ...pkg2.dependencies, ...pkg2.devDependencies };
|
|
1247
1624
|
if ("husky" in allDeps) return "husky";
|
|
@@ -1270,10 +1647,10 @@ async function runInitHooks(args) {
|
|
|
1270
1647
|
const warnings = [];
|
|
1271
1648
|
const instructions = [];
|
|
1272
1649
|
if (hookManager === "husky" || hookManager === "none") {
|
|
1273
|
-
const huskyDir =
|
|
1274
|
-
const hookPath =
|
|
1650
|
+
const huskyDir = join3(rootDir, ".husky");
|
|
1651
|
+
const hookPath = join3(huskyDir, "pre-commit");
|
|
1275
1652
|
const relativePath = ".husky/pre-commit";
|
|
1276
|
-
if (
|
|
1653
|
+
if (existsSync3(hookPath) && !args.force) {
|
|
1277
1654
|
const existing = await readFile(hookPath, "utf8");
|
|
1278
1655
|
if (existing.includes("forge-ts check")) {
|
|
1279
1656
|
skippedFiles.push(relativePath);
|
|
@@ -1286,12 +1663,12 @@ async function runInitHooks(args) {
|
|
|
1286
1663
|
|
|
1287
1664
|
npx forge-ts check
|
|
1288
1665
|
`;
|
|
1289
|
-
await
|
|
1666
|
+
await writeFile3(hookPath, appended, { mode: 493 });
|
|
1290
1667
|
writtenFiles.push(relativePath);
|
|
1291
1668
|
}
|
|
1292
1669
|
} else {
|
|
1293
|
-
await
|
|
1294
|
-
await
|
|
1670
|
+
await mkdir3(huskyDir, { recursive: true });
|
|
1671
|
+
await writeFile3(hookPath, HUSKY_PRE_COMMIT, { mode: 493 });
|
|
1295
1672
|
writtenFiles.push(relativePath);
|
|
1296
1673
|
}
|
|
1297
1674
|
if (hookManager === "none") {
|
|
@@ -1303,9 +1680,9 @@ npx forge-ts check
|
|
|
1303
1680
|
instructions.push("Husky pre-commit hook configured to run forge-ts check.");
|
|
1304
1681
|
}
|
|
1305
1682
|
} else if (hookManager === "lefthook") {
|
|
1306
|
-
const lefthookPath =
|
|
1683
|
+
const lefthookPath = join3(rootDir, "lefthook.yml");
|
|
1307
1684
|
const relativePath = "lefthook.yml";
|
|
1308
|
-
if (
|
|
1685
|
+
if (existsSync3(lefthookPath)) {
|
|
1309
1686
|
const existing = await readFile(lefthookPath, "utf8");
|
|
1310
1687
|
if (existing.includes("forge-ts check") && !args.force) {
|
|
1311
1688
|
skippedFiles.push(relativePath);
|
|
@@ -1318,17 +1695,17 @@ npx forge-ts check
|
|
|
1318
1695
|
forge-ts-check:
|
|
1319
1696
|
run: npx forge-ts check
|
|
1320
1697
|
`;
|
|
1321
|
-
await
|
|
1698
|
+
await writeFile3(lefthookPath, appended, "utf8");
|
|
1322
1699
|
writtenFiles.push(relativePath);
|
|
1323
1700
|
} else {
|
|
1324
1701
|
const appended = `${existing.trimEnd()}
|
|
1325
1702
|
|
|
1326
1703
|
${LEFTHOOK_BLOCK}`;
|
|
1327
|
-
await
|
|
1704
|
+
await writeFile3(lefthookPath, appended, "utf8");
|
|
1328
1705
|
writtenFiles.push(relativePath);
|
|
1329
1706
|
}
|
|
1330
1707
|
} else {
|
|
1331
|
-
await
|
|
1708
|
+
await writeFile3(lefthookPath, LEFTHOOK_BLOCK, "utf8");
|
|
1332
1709
|
writtenFiles.push(relativePath);
|
|
1333
1710
|
}
|
|
1334
1711
|
instructions.push("Lefthook pre-commit hook configured to run forge-ts check.");
|
|
@@ -1373,7 +1750,7 @@ function formatInitHooksHuman(result) {
|
|
|
1373
1750
|
${result.summary.filesWritten} file(s) written.`);
|
|
1374
1751
|
return lines.join("\n");
|
|
1375
1752
|
}
|
|
1376
|
-
var initHooksCommand =
|
|
1753
|
+
var initHooksCommand = defineCommand8({
|
|
1377
1754
|
meta: {
|
|
1378
1755
|
name: "hooks",
|
|
1379
1756
|
description: "Scaffold git hook integration (husky/lefthook)"
|
|
@@ -1441,7 +1818,7 @@ import {
|
|
|
1441
1818
|
readLockFile,
|
|
1442
1819
|
writeLockFile
|
|
1443
1820
|
} from "@forge-ts/core";
|
|
1444
|
-
import { defineCommand as
|
|
1821
|
+
import { defineCommand as defineCommand9 } from "citty";
|
|
1445
1822
|
async function runLock(args) {
|
|
1446
1823
|
const config = await loadConfig6(args.cwd);
|
|
1447
1824
|
const rootDir = config.rootDir;
|
|
@@ -1500,7 +1877,7 @@ function formatLockHuman(result) {
|
|
|
1500
1877
|
To modify locked settings, run: forge-ts unlock --reason="..."`);
|
|
1501
1878
|
return lines.join("\n");
|
|
1502
1879
|
}
|
|
1503
|
-
var lockCommand =
|
|
1880
|
+
var lockCommand = defineCommand9({
|
|
1504
1881
|
meta: {
|
|
1505
1882
|
name: "lock",
|
|
1506
1883
|
description: "Lock current config to prevent silent weakening"
|
|
@@ -1539,7 +1916,7 @@ var lockCommand = defineCommand8({
|
|
|
1539
1916
|
});
|
|
1540
1917
|
|
|
1541
1918
|
// src/commands/prepublish.ts
|
|
1542
|
-
import { defineCommand as
|
|
1919
|
+
import { defineCommand as defineCommand10 } from "citty";
|
|
1543
1920
|
async function runPrepublish(args) {
|
|
1544
1921
|
const start = Date.now();
|
|
1545
1922
|
const allErrors = [];
|
|
@@ -1643,7 +2020,7 @@ function formatPrepublishHuman(result) {
|
|
|
1643
2020
|
}
|
|
1644
2021
|
return lines.join("\n");
|
|
1645
2022
|
}
|
|
1646
|
-
var prepublishCommand =
|
|
2023
|
+
var prepublishCommand = defineCommand10({
|
|
1647
2024
|
meta: {
|
|
1648
2025
|
name: "prepublish",
|
|
1649
2026
|
description: "Safety gate: check + build before npm publish"
|
|
@@ -1704,7 +2081,7 @@ var prepublishCommand = defineCommand9({
|
|
|
1704
2081
|
// src/commands/test.ts
|
|
1705
2082
|
import { loadConfig as loadConfig7 } from "@forge-ts/core";
|
|
1706
2083
|
import { doctest } from "@forge-ts/doctest";
|
|
1707
|
-
import { defineCommand as
|
|
2084
|
+
import { defineCommand as defineCommand11 } from "citty";
|
|
1708
2085
|
async function runTest(args) {
|
|
1709
2086
|
const config = await loadConfig7(args.cwd);
|
|
1710
2087
|
const result = await doctest(config);
|
|
@@ -1747,7 +2124,7 @@ async function runTest(args) {
|
|
|
1747
2124
|
duration: result.duration
|
|
1748
2125
|
};
|
|
1749
2126
|
}
|
|
1750
|
-
var testCommand =
|
|
2127
|
+
var testCommand = defineCommand11({
|
|
1751
2128
|
meta: {
|
|
1752
2129
|
name: "test",
|
|
1753
2130
|
description: "Run @example blocks as doctests"
|
|
@@ -1808,7 +2185,7 @@ import {
|
|
|
1808
2185
|
readLockFile as readLockFile2,
|
|
1809
2186
|
removeLockFile
|
|
1810
2187
|
} from "@forge-ts/core";
|
|
1811
|
-
import { defineCommand as
|
|
2188
|
+
import { defineCommand as defineCommand12 } from "citty";
|
|
1812
2189
|
async function runUnlock(args) {
|
|
1813
2190
|
const config = await loadConfig8(args.cwd);
|
|
1814
2191
|
const rootDir = config.rootDir;
|
|
@@ -1893,7 +2270,7 @@ function formatUnlockHuman(result) {
|
|
|
1893
2270
|
lines.push(" Run `forge-ts lock` to re-lock after changes.");
|
|
1894
2271
|
return lines.join("\n");
|
|
1895
2272
|
}
|
|
1896
|
-
var unlockCommand =
|
|
2273
|
+
var unlockCommand = defineCommand12({
|
|
1897
2274
|
meta: {
|
|
1898
2275
|
name: "unlock",
|
|
1899
2276
|
description: "Remove config lock (requires --reason)"
|
|
@@ -1948,7 +2325,7 @@ var unlockCommand = defineCommand11({
|
|
|
1948
2325
|
// src/index.ts
|
|
1949
2326
|
var require2 = createRequire(import.meta.url);
|
|
1950
2327
|
var pkg = require2("../package.json");
|
|
1951
|
-
var docsCommand =
|
|
2328
|
+
var docsCommand = defineCommand13({
|
|
1952
2329
|
meta: {
|
|
1953
2330
|
name: "docs",
|
|
1954
2331
|
description: "Documentation site management"
|
|
@@ -1958,17 +2335,120 @@ var docsCommand = defineCommand12({
|
|
|
1958
2335
|
dev: docsDevCommand
|
|
1959
2336
|
}
|
|
1960
2337
|
});
|
|
1961
|
-
var initCommand2 =
|
|
2338
|
+
var initCommand2 = defineCommand13({
|
|
1962
2339
|
meta: {
|
|
1963
2340
|
name: "init",
|
|
1964
|
-
description: "
|
|
2341
|
+
description: "Full project setup (bare) or scaffold artefacts (with subcommand)"
|
|
2342
|
+
},
|
|
2343
|
+
args: {
|
|
2344
|
+
cwd: {
|
|
2345
|
+
type: "string",
|
|
2346
|
+
description: "Project root directory"
|
|
2347
|
+
},
|
|
2348
|
+
json: {
|
|
2349
|
+
type: "boolean",
|
|
2350
|
+
description: "Output as LAFS JSON envelope",
|
|
2351
|
+
default: false
|
|
2352
|
+
},
|
|
2353
|
+
human: {
|
|
2354
|
+
type: "boolean",
|
|
2355
|
+
description: "Output as formatted text",
|
|
2356
|
+
default: false
|
|
2357
|
+
},
|
|
2358
|
+
quiet: {
|
|
2359
|
+
type: "boolean",
|
|
2360
|
+
description: "Suppress non-essential output",
|
|
2361
|
+
default: false
|
|
2362
|
+
},
|
|
2363
|
+
mvi: {
|
|
2364
|
+
type: "string",
|
|
2365
|
+
description: "MVI verbosity level: minimal, standard, full"
|
|
2366
|
+
}
|
|
1965
2367
|
},
|
|
1966
2368
|
subCommands: {
|
|
1967
2369
|
docs: initDocsCommand,
|
|
1968
|
-
hooks: initHooksCommand
|
|
2370
|
+
hooks: initHooksCommand,
|
|
2371
|
+
setup: initProjectCommand
|
|
2372
|
+
},
|
|
2373
|
+
async run({ rawArgs, args }) {
|
|
2374
|
+
const subCommandNames = /* @__PURE__ */ new Set(["docs", "hooks", "setup"]);
|
|
2375
|
+
const hasSubCommand = rawArgs.some((arg) => subCommandNames.has(arg));
|
|
2376
|
+
if (hasSubCommand) {
|
|
2377
|
+
return;
|
|
2378
|
+
}
|
|
2379
|
+
const { runInitProject: runInitProject2 } = await import("./init-project-5DESIZ73.js");
|
|
2380
|
+
const { emitResult: emitResult2, resolveExitCode: resolveExitCode2 } = await import("./output-OSCHMPOX.js");
|
|
2381
|
+
const { createLogger: createLogger3 } = await import("./logger-MMBBZG6U.js");
|
|
2382
|
+
const output = await runInitProject2({
|
|
2383
|
+
cwd: args.cwd,
|
|
2384
|
+
mvi: args.mvi
|
|
2385
|
+
});
|
|
2386
|
+
const flags = {
|
|
2387
|
+
json: args.json,
|
|
2388
|
+
human: args.human,
|
|
2389
|
+
quiet: args.quiet,
|
|
2390
|
+
mvi: args.mvi
|
|
2391
|
+
};
|
|
2392
|
+
emitResult2(output, flags, (data, cmd) => {
|
|
2393
|
+
if (!cmd.success) {
|
|
2394
|
+
const logger = createLogger3();
|
|
2395
|
+
const msg = cmd.errors?.[0]?.message ?? "Init failed";
|
|
2396
|
+
logger.error(msg);
|
|
2397
|
+
return "";
|
|
2398
|
+
}
|
|
2399
|
+
const lines = [];
|
|
2400
|
+
lines.push("\nforge-ts init: project setup complete\n");
|
|
2401
|
+
if (data.created.length > 0) {
|
|
2402
|
+
lines.push(" Created:");
|
|
2403
|
+
for (const file of data.created) {
|
|
2404
|
+
lines.push(` ${file}`);
|
|
2405
|
+
}
|
|
2406
|
+
}
|
|
2407
|
+
if (data.skipped.length > 0) {
|
|
2408
|
+
lines.push("");
|
|
2409
|
+
lines.push(" Already exists (skipped):");
|
|
2410
|
+
for (const file of data.skipped) {
|
|
2411
|
+
lines.push(` ${file}`);
|
|
2412
|
+
}
|
|
2413
|
+
} else if (data.created.length > 0) {
|
|
2414
|
+
lines.push("");
|
|
2415
|
+
lines.push(" Already exists (skipped):");
|
|
2416
|
+
lines.push(" (none)");
|
|
2417
|
+
}
|
|
2418
|
+
if (data.warnings.length > 0) {
|
|
2419
|
+
lines.push("");
|
|
2420
|
+
lines.push(" Warnings:");
|
|
2421
|
+
for (const warning of data.warnings) {
|
|
2422
|
+
lines.push(` ${warning}`);
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
const env = data.environment;
|
|
2426
|
+
lines.push("");
|
|
2427
|
+
lines.push(" Environment:");
|
|
2428
|
+
lines.push(` TypeScript: ${env.typescriptVersion ?? "not detected"}`);
|
|
2429
|
+
lines.push(` Biome: ${env.biomeDetected ? "detected" : "not detected"}`);
|
|
2430
|
+
const hookLabel = env.hookManager === "none" ? "not detected" : `${env.hookManager} detected`;
|
|
2431
|
+
lines.push(` Git hooks: ${hookLabel}`);
|
|
2432
|
+
if (env.monorepo) {
|
|
2433
|
+
lines.push(
|
|
2434
|
+
` Monorepo: ${env.monorepoType === "pnpm" ? "pnpm workspaces" : "npm/yarn workspaces"}`
|
|
2435
|
+
);
|
|
2436
|
+
} else {
|
|
2437
|
+
lines.push(" Monorepo: no");
|
|
2438
|
+
}
|
|
2439
|
+
if (data.nextSteps.length > 0) {
|
|
2440
|
+
lines.push("");
|
|
2441
|
+
lines.push(" Next steps:");
|
|
2442
|
+
for (const [idx, step] of data.nextSteps.entries()) {
|
|
2443
|
+
lines.push(` ${idx + 1}. ${step}`);
|
|
2444
|
+
}
|
|
2445
|
+
}
|
|
2446
|
+
return lines.join("\n");
|
|
2447
|
+
});
|
|
2448
|
+
process.exit(resolveExitCode2(output));
|
|
1969
2449
|
}
|
|
1970
2450
|
});
|
|
1971
|
-
var main =
|
|
2451
|
+
var main = defineCommand13({
|
|
1972
2452
|
meta: {
|
|
1973
2453
|
name: "forge-ts",
|
|
1974
2454
|
version: pkg.version,
|
|
@@ -1984,7 +2464,8 @@ var main = defineCommand12({
|
|
|
1984
2464
|
unlock: unlockCommand,
|
|
1985
2465
|
bypass: bypassCommand,
|
|
1986
2466
|
audit: auditCommand,
|
|
1987
|
-
prepublish: prepublishCommand
|
|
2467
|
+
prepublish: prepublishCommand,
|
|
2468
|
+
doctor: doctorCommand
|
|
1988
2469
|
}
|
|
1989
2470
|
});
|
|
1990
2471
|
runMain(main);
|
|
@@ -1995,16 +2476,20 @@ export {
|
|
|
1995
2476
|
checkCommand,
|
|
1996
2477
|
createLogger,
|
|
1997
2478
|
docsDevCommand,
|
|
2479
|
+
doctorCommand,
|
|
1998
2480
|
emitResult,
|
|
1999
2481
|
initDocsCommand,
|
|
2000
2482
|
initHooksCommand,
|
|
2483
|
+
initProjectCommand,
|
|
2001
2484
|
lockCommand,
|
|
2002
2485
|
prepublishCommand,
|
|
2003
2486
|
resolveExitCode,
|
|
2004
2487
|
runBypassCreate,
|
|
2005
2488
|
runBypassStatus,
|
|
2006
2489
|
runDocsDev,
|
|
2490
|
+
runDoctor,
|
|
2007
2491
|
runInitHooks,
|
|
2492
|
+
runInitProject,
|
|
2008
2493
|
runLock,
|
|
2009
2494
|
runPrepublish,
|
|
2010
2495
|
runUnlock,
|