@forge-ts/cli 0.4.0 → 0.6.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/index.d.ts +146 -1
- package/dist/index.js +313 -9
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as citty from 'citty';
|
|
2
|
+
import { SSGTarget } from '@forge-ts/gen';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Central output layer for forge-ts CLI.
|
|
@@ -146,6 +147,11 @@ declare const buildCommand: citty.CommandDef<{
|
|
|
146
147
|
readonly description: "Skip doc generation";
|
|
147
148
|
readonly default: false;
|
|
148
149
|
};
|
|
150
|
+
readonly "force-stubs": {
|
|
151
|
+
readonly type: "boolean";
|
|
152
|
+
readonly description: "Overwrite stub pages even if they exist (reset to scaffolding)";
|
|
153
|
+
readonly default: false;
|
|
154
|
+
};
|
|
149
155
|
readonly json: {
|
|
150
156
|
readonly type: "boolean";
|
|
151
157
|
readonly description: "Output as LAFS JSON envelope (agent-friendly)";
|
|
@@ -278,6 +284,145 @@ declare const checkCommand: citty.CommandDef<{
|
|
|
278
284
|
};
|
|
279
285
|
}>;
|
|
280
286
|
|
|
287
|
+
/**
|
|
288
|
+
* The `forge-ts docs dev` command — starts a local doc preview server.
|
|
289
|
+
*
|
|
290
|
+
* Reads the ssgTarget from forge-ts config, looks up the adapter,
|
|
291
|
+
* and spawns the correct dev server automatically.
|
|
292
|
+
*
|
|
293
|
+
* @packageDocumentation
|
|
294
|
+
* @public
|
|
295
|
+
*/
|
|
296
|
+
/**
|
|
297
|
+
* Starts the local dev server for the configured SSG target.
|
|
298
|
+
*
|
|
299
|
+
* Reads `gen.ssgTarget` from the forge-ts config, resolves the adapter,
|
|
300
|
+
* and spawns the platform's dev server in the output directory.
|
|
301
|
+
*
|
|
302
|
+
* @param args - Command arguments.
|
|
303
|
+
* @returns A promise that resolves when the server exits.
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* ```typescript
|
|
307
|
+
* import { runDocsDev } from "@forge-ts/cli";
|
|
308
|
+
* await runDocsDev({ cwd: "./my-project" });
|
|
309
|
+
* ```
|
|
310
|
+
* @public
|
|
311
|
+
*/
|
|
312
|
+
declare function runDocsDev(args: {
|
|
313
|
+
/** Project root directory. */
|
|
314
|
+
cwd?: string;
|
|
315
|
+
/** Override the SSG target from config. */
|
|
316
|
+
target?: string;
|
|
317
|
+
/** Port to run the dev server on. */
|
|
318
|
+
port?: string;
|
|
319
|
+
}): Promise<void>;
|
|
320
|
+
/**
|
|
321
|
+
* Citty command definition for `forge-ts docs dev`.
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* ```typescript
|
|
325
|
+
* import { docsDevCommand } from "@forge-ts/cli";
|
|
326
|
+
* ```
|
|
327
|
+
* @public
|
|
328
|
+
*/
|
|
329
|
+
declare const docsDevCommand: citty.CommandDef<{
|
|
330
|
+
readonly cwd: {
|
|
331
|
+
readonly type: "string";
|
|
332
|
+
readonly description: "Project root directory";
|
|
333
|
+
};
|
|
334
|
+
readonly target: {
|
|
335
|
+
readonly type: "string";
|
|
336
|
+
readonly description: "SSG target override (reads from config by default)";
|
|
337
|
+
};
|
|
338
|
+
readonly port: {
|
|
339
|
+
readonly type: "string";
|
|
340
|
+
readonly description: "Port for the dev server";
|
|
341
|
+
};
|
|
342
|
+
}>;
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Result of the `init docs` command.
|
|
346
|
+
*
|
|
347
|
+
* @example
|
|
348
|
+
* ```typescript
|
|
349
|
+
* import { runInitDocs } from "@forge-ts/cli/commands/init-docs";
|
|
350
|
+
* const output = await runInitDocs({ target: "mintlify" });
|
|
351
|
+
* console.log(output.data.summary.filesCreated); // number of files written
|
|
352
|
+
* ```
|
|
353
|
+
* @public
|
|
354
|
+
*/
|
|
355
|
+
interface InitDocsResult {
|
|
356
|
+
/** Whether the scaffold succeeded. */
|
|
357
|
+
success: boolean;
|
|
358
|
+
/** The SSG target that was scaffolded. */
|
|
359
|
+
target: SSGTarget;
|
|
360
|
+
/** Summary of what was created. */
|
|
361
|
+
summary: {
|
|
362
|
+
/** Number of files written to disk. */
|
|
363
|
+
filesCreated: number;
|
|
364
|
+
/** Number of npm dependencies declared by the adapter. */
|
|
365
|
+
dependencies: number;
|
|
366
|
+
/** Number of package.json scripts declared by the adapter. */
|
|
367
|
+
scripts: number;
|
|
368
|
+
};
|
|
369
|
+
/** Relative paths of all files created. */
|
|
370
|
+
files: string[];
|
|
371
|
+
/** Post-scaffold instructions for the user. */
|
|
372
|
+
instructions: string[];
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Citty command definition for `forge-ts init docs`.
|
|
376
|
+
*
|
|
377
|
+
* Scaffolds a complete documentation site for the target SSG platform.
|
|
378
|
+
* Use `--json` for LAFS JSON envelope output (agent/CI-friendly).
|
|
379
|
+
*
|
|
380
|
+
* @example
|
|
381
|
+
* ```typescript
|
|
382
|
+
* import { initDocsCommand } from "@forge-ts/cli/commands/init-docs";
|
|
383
|
+
* // Registered automatically as a subcommand of `forge-ts init`
|
|
384
|
+
* ```
|
|
385
|
+
* @public
|
|
386
|
+
*/
|
|
387
|
+
declare const initDocsCommand: citty.CommandDef<{
|
|
388
|
+
readonly target: {
|
|
389
|
+
readonly type: "string";
|
|
390
|
+
readonly description: `SSG target: ${string} (default: mintlify)` | `SSG target: ${string} (default: docusaurus)` | `SSG target: ${string} (default: nextra)` | `SSG target: ${string} (default: vitepress)`;
|
|
391
|
+
};
|
|
392
|
+
readonly cwd: {
|
|
393
|
+
readonly type: "string";
|
|
394
|
+
readonly description: "Project root directory";
|
|
395
|
+
};
|
|
396
|
+
readonly "out-dir": {
|
|
397
|
+
readonly type: "string";
|
|
398
|
+
readonly description: "Output directory for doc site (default: ./docs)";
|
|
399
|
+
};
|
|
400
|
+
readonly force: {
|
|
401
|
+
readonly type: "boolean";
|
|
402
|
+
readonly description: "Overwrite existing scaffold";
|
|
403
|
+
readonly default: false;
|
|
404
|
+
};
|
|
405
|
+
readonly json: {
|
|
406
|
+
readonly type: "boolean";
|
|
407
|
+
readonly description: "Output as LAFS JSON envelope";
|
|
408
|
+
readonly default: false;
|
|
409
|
+
};
|
|
410
|
+
readonly human: {
|
|
411
|
+
readonly type: "boolean";
|
|
412
|
+
readonly description: "Output as formatted text";
|
|
413
|
+
readonly default: false;
|
|
414
|
+
};
|
|
415
|
+
readonly quiet: {
|
|
416
|
+
readonly type: "boolean";
|
|
417
|
+
readonly description: "Suppress non-essential output";
|
|
418
|
+
readonly default: false;
|
|
419
|
+
};
|
|
420
|
+
readonly mvi: {
|
|
421
|
+
readonly type: "string";
|
|
422
|
+
readonly description: "MVI verbosity level: minimal, standard, full";
|
|
423
|
+
};
|
|
424
|
+
}>;
|
|
425
|
+
|
|
281
426
|
/**
|
|
282
427
|
* A single test failure entry, included at standard and full MVI levels.
|
|
283
428
|
* @public
|
|
@@ -385,4 +530,4 @@ declare function createLogger(options?: {
|
|
|
385
530
|
colors?: boolean;
|
|
386
531
|
}): Logger;
|
|
387
532
|
|
|
388
|
-
export { type BuildResult, type BuildStep, type CheckFileError, type CheckFileGroup, type CheckFileWarning, type CheckResult, type CommandOutput, type ForgeCliError, type ForgeCliWarning, type Logger, type OutputFlags, type TestFailure, type TestResult, buildCommand, checkCommand, createLogger, emitResult, resolveExitCode, testCommand };
|
|
533
|
+
export { type BuildResult, type BuildStep, type CheckFileError, type CheckFileGroup, type CheckFileWarning, type CheckResult, type CommandOutput, type ForgeCliError, type ForgeCliWarning, type InitDocsResult, type Logger, type OutputFlags, type TestFailure, type TestResult, buildCommand, checkCommand, createLogger, docsDevCommand, emitResult, initDocsCommand, resolveExitCode, runDocsDev, testCommand };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { defineCommand as
|
|
4
|
+
import { defineCommand as defineCommand6, runMain } from "citty";
|
|
5
5
|
|
|
6
6
|
// src/commands/build.ts
|
|
7
7
|
import { join } from "path";
|
|
@@ -157,7 +157,7 @@ async function runBuild(args) {
|
|
|
157
157
|
steps.push({ name: "api", status: "skipped" });
|
|
158
158
|
}
|
|
159
159
|
if (config.gen.enabled && !args.skipGen) {
|
|
160
|
-
const result = await generate(config);
|
|
160
|
+
const result = await generate(config, { forceStubs: args.forceStubs });
|
|
161
161
|
if (!result.success) {
|
|
162
162
|
const errors = result.errors.map((e) => ({
|
|
163
163
|
code: e.code,
|
|
@@ -236,6 +236,11 @@ var buildCommand = defineCommand({
|
|
|
236
236
|
description: "Skip doc generation",
|
|
237
237
|
default: false
|
|
238
238
|
},
|
|
239
|
+
"force-stubs": {
|
|
240
|
+
type: "boolean",
|
|
241
|
+
description: "Overwrite stub pages even if they exist (reset to scaffolding)",
|
|
242
|
+
default: false
|
|
243
|
+
},
|
|
239
244
|
json: {
|
|
240
245
|
type: "boolean",
|
|
241
246
|
description: "Output as LAFS JSON envelope (agent-friendly)",
|
|
@@ -261,6 +266,7 @@ var buildCommand = defineCommand({
|
|
|
261
266
|
cwd: args.cwd,
|
|
262
267
|
skipApi: args["skip-api"],
|
|
263
268
|
skipGen: args["skip-gen"],
|
|
269
|
+
forceStubs: args["force-stubs"],
|
|
264
270
|
mvi: args.mvi
|
|
265
271
|
});
|
|
266
272
|
const flags = {
|
|
@@ -468,12 +474,296 @@ var checkCommand = defineCommand2({
|
|
|
468
474
|
}
|
|
469
475
|
});
|
|
470
476
|
|
|
471
|
-
// src/commands/
|
|
477
|
+
// src/commands/docs-dev.ts
|
|
478
|
+
import { spawn } from "child_process";
|
|
479
|
+
import { resolve } from "path";
|
|
472
480
|
import { loadConfig as loadConfig3 } from "@forge-ts/core";
|
|
473
|
-
import {
|
|
481
|
+
import { DEFAULT_TARGET, getAdapter } from "@forge-ts/gen";
|
|
474
482
|
import { defineCommand as defineCommand3 } from "citty";
|
|
475
|
-
async function
|
|
483
|
+
async function runDocsDev(args) {
|
|
484
|
+
const logger = createLogger();
|
|
476
485
|
const config = await loadConfig3(args.cwd);
|
|
486
|
+
const target = args.target ?? config.gen.ssgTarget ?? DEFAULT_TARGET;
|
|
487
|
+
const adapter = getAdapter(target);
|
|
488
|
+
const outDir = resolve(config.outDir);
|
|
489
|
+
const devCmd = adapter.getDevCommand(outDir);
|
|
490
|
+
logger.info(`Starting ${devCmd.label}...`);
|
|
491
|
+
logger.info(` Target: ${target}`);
|
|
492
|
+
logger.info(` Directory: ${outDir}`);
|
|
493
|
+
logger.info(` URL: ${devCmd.url}`);
|
|
494
|
+
logger.info("");
|
|
495
|
+
const spawnArgs = [...devCmd.args];
|
|
496
|
+
if (args.port) {
|
|
497
|
+
spawnArgs.push("--port", args.port);
|
|
498
|
+
}
|
|
499
|
+
const proc = spawn(devCmd.bin, spawnArgs, {
|
|
500
|
+
cwd: devCmd.cwd,
|
|
501
|
+
stdio: "inherit",
|
|
502
|
+
shell: true
|
|
503
|
+
});
|
|
504
|
+
return new Promise((_resolve, reject) => {
|
|
505
|
+
proc.on("close", (code) => {
|
|
506
|
+
if (code === 0) {
|
|
507
|
+
_resolve();
|
|
508
|
+
} else {
|
|
509
|
+
reject(new Error(`${devCmd.label} exited with code ${code}`));
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
proc.on("error", reject);
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
var docsDevCommand = defineCommand3({
|
|
516
|
+
meta: {
|
|
517
|
+
name: "dev",
|
|
518
|
+
description: "Start a local doc preview server"
|
|
519
|
+
},
|
|
520
|
+
args: {
|
|
521
|
+
cwd: {
|
|
522
|
+
type: "string",
|
|
523
|
+
description: "Project root directory"
|
|
524
|
+
},
|
|
525
|
+
target: {
|
|
526
|
+
type: "string",
|
|
527
|
+
description: "SSG target override (reads from config by default)"
|
|
528
|
+
},
|
|
529
|
+
port: {
|
|
530
|
+
type: "string",
|
|
531
|
+
description: "Port for the dev server"
|
|
532
|
+
}
|
|
533
|
+
},
|
|
534
|
+
async run({ args }) {
|
|
535
|
+
await runDocsDev(args);
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
// src/commands/init-docs.ts
|
|
540
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
541
|
+
import { join as join2, resolve as resolve2 } from "path";
|
|
542
|
+
import { loadConfig as loadConfig4 } from "@forge-ts/core";
|
|
543
|
+
import {
|
|
544
|
+
DEFAULT_TARGET as DEFAULT_TARGET2,
|
|
545
|
+
getAdapter as getAdapter2,
|
|
546
|
+
getAvailableTargets
|
|
547
|
+
} from "@forge-ts/gen";
|
|
548
|
+
import { defineCommand as defineCommand4 } from "citty";
|
|
549
|
+
async function runInitDocs(args) {
|
|
550
|
+
const start = Date.now();
|
|
551
|
+
const rawTarget = args.target ?? DEFAULT_TARGET2;
|
|
552
|
+
const available = getAvailableTargets();
|
|
553
|
+
if (!available.includes(rawTarget)) {
|
|
554
|
+
const err = {
|
|
555
|
+
code: "INIT_UNKNOWN_TARGET",
|
|
556
|
+
message: `Unknown SSG target "${rawTarget}". Available targets: ${available.join(", ")}`
|
|
557
|
+
};
|
|
558
|
+
return {
|
|
559
|
+
operation: "init.docs",
|
|
560
|
+
success: false,
|
|
561
|
+
data: {
|
|
562
|
+
success: false,
|
|
563
|
+
target: DEFAULT_TARGET2,
|
|
564
|
+
summary: { filesCreated: 0, dependencies: 0, scripts: 0 },
|
|
565
|
+
files: [],
|
|
566
|
+
instructions: []
|
|
567
|
+
},
|
|
568
|
+
errors: [err],
|
|
569
|
+
duration: Date.now() - start
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
const target = rawTarget;
|
|
573
|
+
const adapter = getAdapter2(target);
|
|
574
|
+
const config = await loadConfig4(args.cwd);
|
|
575
|
+
const outDir = args.outDir ? resolve2(args.outDir) : config.outDir;
|
|
576
|
+
const alreadyExists = await adapter.detectExisting(outDir);
|
|
577
|
+
if (alreadyExists && !args.force) {
|
|
578
|
+
const err = {
|
|
579
|
+
code: "INIT_ALREADY_EXISTS",
|
|
580
|
+
message: `Docs already scaffolded for ${target}. Use --force to overwrite.`
|
|
581
|
+
};
|
|
582
|
+
return {
|
|
583
|
+
operation: "init.docs",
|
|
584
|
+
success: false,
|
|
585
|
+
data: {
|
|
586
|
+
success: false,
|
|
587
|
+
target,
|
|
588
|
+
summary: { filesCreated: 0, dependencies: 0, scripts: 0 },
|
|
589
|
+
files: [],
|
|
590
|
+
instructions: []
|
|
591
|
+
},
|
|
592
|
+
errors: [err],
|
|
593
|
+
duration: Date.now() - start
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
const warnings = [];
|
|
597
|
+
for (const otherTarget of available) {
|
|
598
|
+
if (otherTarget === target) continue;
|
|
599
|
+
const otherAdapter = getAdapter2(otherTarget);
|
|
600
|
+
const otherExists = await otherAdapter.detectExisting(outDir);
|
|
601
|
+
if (otherExists) {
|
|
602
|
+
warnings.push({
|
|
603
|
+
code: "INIT_TARGET_MISMATCH",
|
|
604
|
+
message: `Existing scaffold detected for ${otherTarget} but scaffolding for ${target}. Remove conflicting files to avoid issues.`
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
const projectName = config.rootDir.split("/").pop() ?? "Project";
|
|
609
|
+
const context = {
|
|
610
|
+
config,
|
|
611
|
+
projectName,
|
|
612
|
+
pages: [],
|
|
613
|
+
symbols: [],
|
|
614
|
+
outDir
|
|
615
|
+
};
|
|
616
|
+
const manifest = adapter.scaffold(context);
|
|
617
|
+
const writtenFiles = [];
|
|
618
|
+
for (const file of manifest.files) {
|
|
619
|
+
const filePath = join2(outDir, file.path);
|
|
620
|
+
const fileDir = filePath.substring(0, filePath.lastIndexOf("/"));
|
|
621
|
+
await mkdir(fileDir, { recursive: true });
|
|
622
|
+
await writeFile(filePath, file.content, "utf8");
|
|
623
|
+
writtenFiles.push(file.path);
|
|
624
|
+
}
|
|
625
|
+
const depCount = Object.keys(manifest.dependencies).length + Object.keys(manifest.devDependencies).length;
|
|
626
|
+
const scriptCount = Object.keys(manifest.scripts).length;
|
|
627
|
+
const data = {
|
|
628
|
+
success: true,
|
|
629
|
+
target,
|
|
630
|
+
summary: {
|
|
631
|
+
filesCreated: writtenFiles.length,
|
|
632
|
+
dependencies: depCount,
|
|
633
|
+
scripts: scriptCount
|
|
634
|
+
},
|
|
635
|
+
files: writtenFiles,
|
|
636
|
+
instructions: manifest.instructions
|
|
637
|
+
};
|
|
638
|
+
return {
|
|
639
|
+
operation: "init.docs",
|
|
640
|
+
success: true,
|
|
641
|
+
data,
|
|
642
|
+
warnings: warnings.length > 0 ? warnings.map((w) => ({
|
|
643
|
+
code: w.code,
|
|
644
|
+
message: w.message,
|
|
645
|
+
filePath: "",
|
|
646
|
+
line: 0,
|
|
647
|
+
column: 0
|
|
648
|
+
})) : void 0,
|
|
649
|
+
duration: Date.now() - start
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
function formatInitDocsHuman(result) {
|
|
653
|
+
const lines = [];
|
|
654
|
+
if (!result.success) {
|
|
655
|
+
return "";
|
|
656
|
+
}
|
|
657
|
+
const targetName = result.target.charAt(0).toUpperCase() + result.target.slice(1);
|
|
658
|
+
lines.push(`
|
|
659
|
+
Scaffolding ${targetName} documentation site...
|
|
660
|
+
`);
|
|
661
|
+
const MAX_INLINE = 5;
|
|
662
|
+
const shown = result.files.slice(0, MAX_INLINE);
|
|
663
|
+
const remaining = result.files.length - shown.length;
|
|
664
|
+
for (const file of shown) {
|
|
665
|
+
lines.push(` \u2713 Created ${file}`);
|
|
666
|
+
}
|
|
667
|
+
if (remaining > 0) {
|
|
668
|
+
lines.push(` ... (${remaining} more file${remaining !== 1 ? "s" : ""})`);
|
|
669
|
+
}
|
|
670
|
+
if (result.instructions.length > 0) {
|
|
671
|
+
lines.push("\n Next steps:");
|
|
672
|
+
result.instructions.forEach((inst, idx) => {
|
|
673
|
+
lines.push(` ${idx + 1}. ${inst}`);
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
lines.push(
|
|
677
|
+
`
|
|
678
|
+
${result.summary.filesCreated} file${result.summary.filesCreated !== 1 ? "s" : ""} created for ${targetName} doc site.`
|
|
679
|
+
);
|
|
680
|
+
return lines.join("\n");
|
|
681
|
+
}
|
|
682
|
+
var initDocsCommand = defineCommand4({
|
|
683
|
+
meta: {
|
|
684
|
+
name: "docs",
|
|
685
|
+
description: "Scaffold a documentation site"
|
|
686
|
+
},
|
|
687
|
+
args: {
|
|
688
|
+
target: {
|
|
689
|
+
type: "string",
|
|
690
|
+
description: `SSG target: ${getAvailableTargets().join(", ")} (default: ${DEFAULT_TARGET2})`
|
|
691
|
+
},
|
|
692
|
+
cwd: {
|
|
693
|
+
type: "string",
|
|
694
|
+
description: "Project root directory"
|
|
695
|
+
},
|
|
696
|
+
"out-dir": {
|
|
697
|
+
type: "string",
|
|
698
|
+
description: "Output directory for doc site (default: ./docs)"
|
|
699
|
+
},
|
|
700
|
+
force: {
|
|
701
|
+
type: "boolean",
|
|
702
|
+
description: "Overwrite existing scaffold",
|
|
703
|
+
default: false
|
|
704
|
+
},
|
|
705
|
+
json: {
|
|
706
|
+
type: "boolean",
|
|
707
|
+
description: "Output as LAFS JSON envelope",
|
|
708
|
+
default: false
|
|
709
|
+
},
|
|
710
|
+
human: {
|
|
711
|
+
type: "boolean",
|
|
712
|
+
description: "Output as formatted text",
|
|
713
|
+
default: false
|
|
714
|
+
},
|
|
715
|
+
quiet: {
|
|
716
|
+
type: "boolean",
|
|
717
|
+
description: "Suppress non-essential output",
|
|
718
|
+
default: false
|
|
719
|
+
},
|
|
720
|
+
mvi: {
|
|
721
|
+
type: "string",
|
|
722
|
+
description: "MVI verbosity level: minimal, standard, full"
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
async run({ args }) {
|
|
726
|
+
const output = await runInitDocs({
|
|
727
|
+
target: args.target,
|
|
728
|
+
cwd: args.cwd,
|
|
729
|
+
outDir: args["out-dir"],
|
|
730
|
+
force: args.force,
|
|
731
|
+
mvi: args.mvi
|
|
732
|
+
});
|
|
733
|
+
const flags = {
|
|
734
|
+
json: args.json,
|
|
735
|
+
human: args.human,
|
|
736
|
+
quiet: args.quiet,
|
|
737
|
+
mvi: args.mvi
|
|
738
|
+
};
|
|
739
|
+
emitResult(output, flags, (data, cmd) => {
|
|
740
|
+
if (!cmd.success) {
|
|
741
|
+
const logger = createLogger();
|
|
742
|
+
const msg = cmd.errors?.[0]?.message ?? "Scaffold failed";
|
|
743
|
+
logger.error(msg);
|
|
744
|
+
return "";
|
|
745
|
+
}
|
|
746
|
+
return formatInitDocsHuman(data);
|
|
747
|
+
});
|
|
748
|
+
process.exit(resolveExitCode(output));
|
|
749
|
+
}
|
|
750
|
+
});
|
|
751
|
+
var initCommand = defineCommand4({
|
|
752
|
+
meta: {
|
|
753
|
+
name: "init",
|
|
754
|
+
description: "Scaffold project artefacts"
|
|
755
|
+
},
|
|
756
|
+
subCommands: {
|
|
757
|
+
docs: initDocsCommand
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
// src/commands/test.ts
|
|
762
|
+
import { loadConfig as loadConfig5 } from "@forge-ts/core";
|
|
763
|
+
import { doctest } from "@forge-ts/doctest";
|
|
764
|
+
import { defineCommand as defineCommand5 } from "citty";
|
|
765
|
+
async function runTest(args) {
|
|
766
|
+
const config = await loadConfig5(args.cwd);
|
|
477
767
|
const result = await doctest(config);
|
|
478
768
|
const mviLevel = args.mvi ?? "standard";
|
|
479
769
|
const failCount = result.errors.length;
|
|
@@ -501,7 +791,7 @@ async function runTest(args) {
|
|
|
501
791
|
duration: result.duration
|
|
502
792
|
};
|
|
503
793
|
}
|
|
504
|
-
var testCommand =
|
|
794
|
+
var testCommand = defineCommand5({
|
|
505
795
|
meta: {
|
|
506
796
|
name: "test",
|
|
507
797
|
description: "Run @example blocks as doctests"
|
|
@@ -555,16 +845,27 @@ var testCommand = defineCommand3({
|
|
|
555
845
|
});
|
|
556
846
|
|
|
557
847
|
// src/index.ts
|
|
558
|
-
var
|
|
848
|
+
var docsCommand = defineCommand6({
|
|
849
|
+
meta: {
|
|
850
|
+
name: "docs",
|
|
851
|
+
description: "Documentation site management"
|
|
852
|
+
},
|
|
853
|
+
subCommands: {
|
|
854
|
+
init: initDocsCommand,
|
|
855
|
+
dev: docsDevCommand
|
|
856
|
+
}
|
|
857
|
+
});
|
|
858
|
+
var main = defineCommand6({
|
|
559
859
|
meta: {
|
|
560
860
|
name: "forge-ts",
|
|
561
|
-
version: "0.
|
|
861
|
+
version: "0.5.0",
|
|
562
862
|
description: "Universal TypeScript Documentation Compiler"
|
|
563
863
|
},
|
|
564
864
|
subCommands: {
|
|
565
865
|
check: checkCommand,
|
|
566
866
|
test: testCommand,
|
|
567
|
-
build: buildCommand
|
|
867
|
+
build: buildCommand,
|
|
868
|
+
docs: docsCommand
|
|
568
869
|
}
|
|
569
870
|
});
|
|
570
871
|
runMain(main);
|
|
@@ -572,8 +873,11 @@ export {
|
|
|
572
873
|
buildCommand,
|
|
573
874
|
checkCommand,
|
|
574
875
|
createLogger,
|
|
876
|
+
docsDevCommand,
|
|
575
877
|
emitResult,
|
|
878
|
+
initDocsCommand,
|
|
576
879
|
resolveExitCode,
|
|
880
|
+
runDocsDev,
|
|
577
881
|
testCommand
|
|
578
882
|
};
|
|
579
883
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/build.ts","../src/logger.ts","../src/output.ts","../src/commands/check.ts","../src/commands/test.ts"],"sourcesContent":["/**\n * @forge-ts/cli — Command-line interface for the forge-ts toolchain.\n *\n * Usage:\n * forge-ts check [--cwd <dir>] [--strict] [--verbose]\n * forge-ts test [--cwd <dir>]\n * forge-ts build [--cwd <dir>] [--skip-api] [--skip-gen]\n *\n * @packageDocumentation\n * @public\n */\n\nimport { defineCommand, runMain } from \"citty\";\nimport { buildCommand } from \"./commands/build.js\";\nimport { checkCommand } from \"./commands/check.js\";\nimport { testCommand } from \"./commands/test.js\";\n\nexport { type BuildResult, type BuildStep, buildCommand } from \"./commands/build.js\";\nexport {\n\ttype CheckFileError,\n\ttype CheckFileGroup,\n\ttype CheckFileWarning,\n\ttype CheckResult,\n\tcheckCommand,\n} from \"./commands/check.js\";\nexport { type TestFailure, type TestResult, testCommand } from \"./commands/test.js\";\nexport { createLogger, type Logger } from \"./logger.js\";\nexport {\n\ttype CommandOutput,\n\temitResult,\n\ttype ForgeCliError,\n\ttype ForgeCliWarning,\n\ttype OutputFlags,\n\tresolveExitCode,\n} from \"./output.js\";\n\nconst main = defineCommand({\n\tmeta: {\n\t\tname: \"forge-ts\",\n\t\tversion: \"0.1.0\",\n\t\tdescription: \"Universal TypeScript Documentation Compiler\",\n\t},\n\tsubCommands: {\n\t\tcheck: checkCommand,\n\t\ttest: testCommand,\n\t\tbuild: buildCommand,\n\t},\n});\n\nrunMain(main);\n","import { join } from \"node:path\";\nimport { generateApi } from \"@forge-ts/api\";\nimport { loadConfig } from \"@forge-ts/core\";\nimport { generate } from \"@forge-ts/gen\";\nimport { defineCommand } from \"citty\";\nimport { createLogger } from \"../logger.js\";\nimport {\n\ttype CommandOutput,\n\temitResult,\n\ttype ForgeCliError,\n\ttype OutputFlags,\n\tresolveExitCode,\n} from \"../output.js\";\n\n/**\n * Arguments for the `build` command.\n * @internal\n */\nexport interface BuildArgs {\n\t/** Project root directory (default: cwd). */\n\tcwd?: string;\n\t/** Skip API generation even if enabled in config. */\n\tskipApi?: boolean;\n\t/** Skip doc generation even if enabled in config. */\n\tskipGen?: boolean;\n\t/** MVI verbosity level for structured output. */\n\tmvi?: string;\n}\n\n/**\n * A single step in the build pipeline.\n * @public\n */\nexport interface BuildStep {\n\t/** Internal step name, e.g. \"api\" or \"gen\". */\n\tname: string;\n\t/** Outcome of this step. */\n\tstatus: \"success\" | \"skipped\" | \"failed\";\n\t/** Path to the primary output file produced by this step, if applicable. */\n\toutputPath?: string;\n\t/** Wall-clock duration of this step in milliseconds. */\n\tduration?: number;\n\t/** Errors produced by this step when status is \"failed\". */\n\terrors?: ForgeCliError[];\n}\n\n/**\n * Typed result for the `build` command.\n * @public\n */\nexport interface BuildResult {\n\t/** Whether the build succeeded. */\n\tsuccess: boolean;\n\t/** Aggregate pipeline counts — always present. */\n\tsummary: {\n\t\t/** Total number of pipeline steps. */\n\t\tsteps: number;\n\t\t/** Steps that completed successfully. */\n\t\tsucceeded: number;\n\t\t/** Steps that failed. */\n\t\tfailed: number;\n\t\t/** Wall-clock duration in milliseconds. */\n\t\tduration: number;\n\t};\n\t/** Per-step details. */\n\tsteps: BuildStep[];\n\t/** Files written during the build — present at standard and full MVI levels. */\n\tgeneratedFiles?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Runs the full build pipeline and returns a typed command output.\n *\n * @param args - CLI arguments for the build command.\n * @returns A typed `CommandOutput<BuildResult>`.\n * @example\n * ```typescript\n * import { runBuild } from \"@forge-ts/cli/commands/build\";\n * const output = await runBuild({ cwd: process.cwd() });\n * console.log(output.success); // true if all steps succeeded\n * ```\n * @public\n */\nexport async function runBuild(args: BuildArgs): Promise<CommandOutput<BuildResult>> {\n\tconst config = await loadConfig(args.cwd);\n\tconst buildStart = Date.now();\n\tconst mviLevel = args.mvi ?? \"standard\";\n\n\tconst steps: BuildStep[] = [];\n\tconst allErrors: ForgeCliError[] = [];\n\tconst generatedFiles: string[] = [];\n\tlet success = true;\n\n\tif (config.api.enabled && !args.skipApi) {\n\t\tconst result = await generateApi(config);\n\t\tif (!result.success) {\n\t\t\tconst errors: ForgeCliError[] = result.errors.map((e) => ({\n\t\t\t\tcode: e.code,\n\t\t\t\tmessage: e.message,\n\t\t\t\tfilePath: e.filePath,\n\t\t\t\tline: e.line,\n\t\t\t\tcolumn: e.column,\n\t\t\t}));\n\t\t\tallErrors.push(...errors);\n\t\t\tsuccess = false;\n\t\t\tsteps.push({\n\t\t\t\tname: \"api\",\n\t\t\t\tstatus: \"failed\",\n\t\t\t\toutputPath: config.api.openapiPath,\n\t\t\t\tduration: result.duration,\n\t\t\t\terrors,\n\t\t\t});\n\t\t} else {\n\t\t\tsteps.push({\n\t\t\t\tname: \"api\",\n\t\t\t\tstatus: \"success\",\n\t\t\t\toutputPath: config.api.openapiPath,\n\t\t\t\tduration: result.duration,\n\t\t\t});\n\t\t\tgeneratedFiles.push(config.api.openapiPath);\n\t\t}\n\t} else if (!config.api.enabled || args.skipApi) {\n\t\tsteps.push({ name: \"api\", status: \"skipped\" });\n\t}\n\n\tif (config.gen.enabled && !args.skipGen) {\n\t\tconst result = await generate(config);\n\t\tif (!result.success) {\n\t\t\tconst errors: ForgeCliError[] = result.errors.map((e) => ({\n\t\t\t\tcode: e.code,\n\t\t\t\tmessage: e.message,\n\t\t\t\tfilePath: e.filePath,\n\t\t\t\tline: e.line,\n\t\t\t\tcolumn: e.column,\n\t\t\t}));\n\t\t\tallErrors.push(...errors);\n\t\t\tsuccess = false;\n\t\t\tsteps.push({\n\t\t\t\tname: \"gen\",\n\t\t\t\tstatus: \"failed\",\n\t\t\t\tduration: result.duration,\n\t\t\t\terrors,\n\t\t\t});\n\t\t} else {\n\t\t\tsteps.push({\n\t\t\t\tname: \"gen\",\n\t\t\t\tstatus: \"success\",\n\t\t\t\tduration: result.duration,\n\t\t\t});\n\t\t\t// Track the generated output directory and standard files\n\t\t\tfor (const format of config.gen.formats) {\n\t\t\t\tconst ext = format === \"mdx\" ? \"mdx\" : \"md\";\n\t\t\t\tgeneratedFiles.push(join(config.outDir, `api-reference.${ext}`));\n\t\t\t}\n\t\t\tif (config.gen.llmsTxt) {\n\t\t\t\tgeneratedFiles.push(join(config.outDir, \"llms.txt\"));\n\t\t\t\tgeneratedFiles.push(join(config.outDir, \"llms-full.txt\"));\n\t\t\t}\n\t\t}\n\t} else if (!config.gen.enabled || args.skipGen) {\n\t\tsteps.push({ name: \"gen\", status: \"skipped\" });\n\t}\n\n\tconst totalMs = Date.now() - buildStart;\n\n\tconst succeededCount = steps.filter((s) => s.status === \"success\").length;\n\tconst failedCount = steps.filter((s) => s.status === \"failed\").length;\n\n\tconst data: BuildResult = {\n\t\tsuccess,\n\t\tsummary: {\n\t\t\tsteps: steps.length,\n\t\t\tsucceeded: succeededCount,\n\t\t\tfailed: failedCount,\n\t\t\tduration: totalMs,\n\t\t},\n\t\tsteps,\n\t};\n\n\tif (mviLevel !== \"minimal\") {\n\t\tdata.generatedFiles = generatedFiles;\n\t}\n\n\treturn {\n\t\toperation: \"build\",\n\t\tsuccess,\n\t\tdata,\n\t\terrors: allErrors,\n\t\tduration: totalMs,\n\t};\n}\n\n/**\n * Citty command definition for `forge-ts build`.\n * @public\n */\nexport const buildCommand = defineCommand({\n\tmeta: {\n\t\tname: \"build\",\n\t\tdescription: \"Generate API reference and documentation\",\n\t},\n\targs: {\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Project root directory\",\n\t\t},\n\t\t\"skip-api\": {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Skip OpenAPI generation\",\n\t\t\tdefault: false,\n\t\t},\n\t\t\"skip-gen\": {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Skip doc generation\",\n\t\t\tdefault: false,\n\t\t},\n\t\tjson: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as LAFS JSON envelope (agent-friendly)\",\n\t\t\tdefault: false,\n\t\t},\n\t\thuman: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as formatted text (default for TTY)\",\n\t\t\tdefault: false,\n\t\t},\n\t\tquiet: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Suppress non-essential output\",\n\t\t\tdefault: false,\n\t\t},\n\t\tmvi: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"MVI verbosity level: minimal, standard, full\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst output = await runBuild({\n\t\t\tcwd: args.cwd,\n\t\t\tskipApi: args[\"skip-api\"],\n\t\t\tskipGen: args[\"skip-gen\"],\n\t\t\tmvi: args.mvi,\n\t\t});\n\n\t\tconst flags: OutputFlags = {\n\t\t\tjson: args.json,\n\t\t\thuman: args.human,\n\t\t\tquiet: args.quiet,\n\t\t\tmvi: args.mvi,\n\t\t};\n\n\t\temitResult(output, flags, (data) => {\n\t\t\tconst logger = createLogger();\n\t\t\tfor (const step of data.steps) {\n\t\t\t\tif (step.status === \"failed\") {\n\t\t\t\t\tfor (const err of step.errors ?? []) {\n\t\t\t\t\t\tlogger.error(`[${step.name}] ${err.message}`);\n\t\t\t\t\t}\n\t\t\t\t} else if (step.status === \"success\") {\n\t\t\t\t\tconst detail =\n\t\t\t\t\t\tstep.name === \"api\" && step.outputPath != null\n\t\t\t\t\t\t\t? `Generated OpenAPI spec \\u2192 ${step.outputPath}`\n\t\t\t\t\t\t\t: `Step complete`;\n\t\t\t\t\tlogger.step(step.name.toUpperCase(), detail, step.duration);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (output.success) {\n\t\t\t\treturn ` Done in ${data.summary.duration}ms`;\n\t\t\t}\n\t\t\treturn \"\";\n\t\t});\n\n\t\tprocess.exit(resolveExitCode(output));\n\t},\n});\n","/**\n * Simple TTY-aware logger for forge-ts CLI output.\n *\n * Uses ANSI escape codes directly — no external colour library.\n *\n * @packageDocumentation\n * @internal\n */\n\n// ---------------------------------------------------------------------------\n// ANSI constants\n// ---------------------------------------------------------------------------\n\nconst GREEN = \"\\x1b[32m\";\nconst YELLOW = \"\\x1b[33m\";\nconst RED = \"\\x1b[31m\";\nconst BOLD = \"\\x1b[1m\";\nconst RESET = \"\\x1b[0m\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * A minimal structured logger used throughout the CLI commands.\n * @internal\n */\nexport interface Logger {\n\t/** Print an informational message. */\n\tinfo(msg: string): void;\n\t/** Print a success message (green ✓ prefix when colours are on). */\n\tsuccess(msg: string): void;\n\t/** Print a warning message (yellow prefix when colours are on). */\n\twarn(msg: string): void;\n\t/** Print an error message (red ✗ prefix when colours are on). */\n\terror(msg: string): void;\n\t/**\n\t * Print a build-step line.\n\t *\n\t * @param label - Short category label (e.g. \"API\", \"Gen\").\n\t * @param detail - Description of what was produced.\n\t * @param duration - Optional wall-clock time in milliseconds.\n\t */\n\tstep(label: string, detail: string, duration?: number): void;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a {@link Logger} instance.\n *\n * @param options - Optional configuration.\n * @param options.colors - Emit ANSI colour codes. Defaults to `process.stdout.isTTY`.\n * @returns A configured logger.\n * @internal\n */\nexport function createLogger(options?: { colors?: boolean }): Logger {\n\tconst useColors = options?.colors ?? process.stdout.isTTY ?? false;\n\n\tfunction colorize(text: string, code: string): string {\n\t\treturn useColors ? `${code}${text}${RESET}` : text;\n\t}\n\n\tfunction bold(text: string): string {\n\t\treturn useColors ? `${BOLD}${text}${RESET}` : text;\n\t}\n\n\treturn {\n\t\tinfo(msg: string): void {\n\t\t\tconsole.log(msg);\n\t\t},\n\n\t\tsuccess(msg: string): void {\n\t\t\tconst prefix = colorize(\"✓\", GREEN);\n\t\t\tconsole.log(`${prefix} ${msg}`);\n\t\t},\n\n\t\twarn(msg: string): void {\n\t\t\tconst prefix = colorize(\"warn\", YELLOW);\n\t\t\tconsole.warn(`${bold(prefix)} ${msg}`);\n\t\t},\n\n\t\terror(msg: string): void {\n\t\t\tconst prefix = colorize(\"error\", RED);\n\t\t\tconsole.error(`${bold(prefix)} ${msg}`);\n\t\t},\n\n\t\tstep(label: string, detail: string, duration?: number): void {\n\t\t\tconst check = colorize(\"✓\", GREEN);\n\t\t\tconst durationStr = duration !== undefined ? ` (${duration}ms)` : \"\";\n\t\t\tconsole.log(` ${check} ${bold(label)}: ${detail}${durationStr}`);\n\t\t},\n\t};\n}\n","/**\n * Central output layer for forge-ts CLI.\n *\n * Wraps all command results in LAFS envelopes for agent-first output, while\n * preserving human-readable formatting for TTY consumers.\n *\n * @packageDocumentation\n * @internal\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport {\n\tcreateEnvelope,\n\ttype MVILevel,\n\tprojectEnvelope,\n\tresolveFlags,\n\ttype UnifiedFlagInput,\n} from \"@cleocode/lafs-protocol\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/** Typed result from a forge-ts command. */\nexport interface CommandOutput<T> {\n\t/** Name of the command that produced this output (e.g., \"check\", \"build\"). */\n\toperation: string;\n\t/** Whether the command completed successfully. */\n\tsuccess: boolean;\n\t/** Strongly-typed command-specific result payload. */\n\tdata: T;\n\t/** Structured errors produced by the command, if any. */\n\terrors?: ForgeCliError[];\n\t/** Structured warnings produced by the command, if any. */\n\twarnings?: ForgeCliWarning[];\n\t/** Wall-clock duration of the command in milliseconds. */\n\tduration?: number;\n}\n\n/** Structured error for CLI commands. */\nexport interface ForgeCliError {\n\t/** Machine-readable error code (e.g., \"E004\"). */\n\tcode: string;\n\t/** Human-readable error description. */\n\tmessage: string;\n\t/** Absolute path to the source file containing the error, if applicable. */\n\tfilePath?: string;\n\t/** 1-based line number of the error, if applicable. */\n\tline?: number;\n\t/** 0-based column number of the error, if applicable. */\n\tcolumn?: number;\n}\n\n/** Structured warning for CLI commands. */\nexport interface ForgeCliWarning {\n\t/** Machine-readable warning code. */\n\tcode: string;\n\t/** Human-readable warning description. */\n\tmessage: string;\n\t/** Absolute path to the source file containing the warning, if applicable. */\n\tfilePath?: string;\n\t/** 1-based line number of the warning, if applicable. */\n\tline?: number;\n\t/** 0-based column number of the warning, if applicable. */\n\tcolumn?: number;\n}\n\n/** Output format flags passed through from citty args. */\nexport interface OutputFlags {\n\t/** Emit output as a LAFS JSON envelope instead of human-readable text. */\n\tjson?: boolean;\n\t/** Emit output as formatted human-readable text. */\n\thuman?: boolean;\n\t/** Suppress all output regardless of format. */\n\tquiet?: boolean;\n\t/** MVI verbosity level: \"minimal\", \"standard\", or \"full\". */\n\tmvi?: string;\n}\n\n// ---------------------------------------------------------------------------\n// emitResult\n// ---------------------------------------------------------------------------\n\n/**\n * Wraps a command result in a LAFS envelope and emits it.\n *\n * - JSON mode: writes the projected envelope to stdout as JSON.\n * - Human mode: calls the provided formatter function.\n * - Quiet mode: suppresses all output regardless of format.\n *\n * @param output - Typed result from the command.\n * @param flags - Output format flags from citty args.\n * @param humanFormatter - Produces a human-readable string for TTY consumers.\n * @example\n * ```typescript\n * import { emitResult } from \"@forge-ts/cli/output\";\n * emitResult(output, { human: true }, (data) => `Done: ${data.summary.duration}ms`);\n * ```\n * @internal\n */\nexport function emitResult<T>(\n\toutput: CommandOutput<T>,\n\tflags: OutputFlags,\n\thumanFormatter: (data: T, output: CommandOutput<T>) => string,\n): void {\n\tconst flagInput: UnifiedFlagInput = {\n\t\tjson: flags.json,\n\t\thuman: flags.human,\n\t\tquiet: flags.quiet,\n\t\tmvi: flags.mvi,\n\t};\n\n\tconst resolved = resolveFlags(flagInput);\n\tconst format = resolved.format.format;\n\tconst quiet = resolved.format.quiet;\n\n\t// Quiet mode: suppress all output, just let exit code speak.\n\tif (quiet) {\n\t\treturn;\n\t}\n\n\t// Build the LAFS envelope\n\tconst envelope = createEnvelope(\n\t\toutput.success\n\t\t\t? {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tresult: output.data as Record<string, unknown>,\n\t\t\t\t\tmeta: {\n\t\t\t\t\t\toperation: `forge-ts.${output.operation}`,\n\t\t\t\t\t\trequestId: randomUUID(),\n\t\t\t\t\t\ttransport: \"cli\",\n\t\t\t\t\t\tmvi: (flags.mvi as MVILevel) ?? \"standard\",\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: output.errors?.[0]?.code ?? \"FORGE_ERROR\",\n\t\t\t\t\t\tmessage: output.errors?.[0]?.message ?? \"Command failed\",\n\t\t\t\t\t\tcategory: \"VALIDATION\",\n\t\t\t\t\t\tretryable: false,\n\t\t\t\t\t\tretryAfterMs: null,\n\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\terrors: output.errors ?? [],\n\t\t\t\t\t\t\twarnings: output.warnings ?? [],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tmeta: {\n\t\t\t\t\t\toperation: `forge-ts.${output.operation}`,\n\t\t\t\t\t\trequestId: randomUUID(),\n\t\t\t\t\t\ttransport: \"cli\",\n\t\t\t\t\t\tmvi: (flags.mvi as MVILevel) ?? \"standard\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t);\n\n\tif (format === \"json\") {\n\t\t// MVI projection reduces token cost for agents\n\t\tconst mviLevel: MVILevel = (flags.mvi as MVILevel) ?? \"standard\";\n\t\tconst projected = projectEnvelope(envelope, mviLevel);\n\t\tprocess.stdout.write(`${JSON.stringify(projected, null, 2)}\\n`);\n\t} else {\n\t\t// Human-readable output\n\t\tconst formatted = humanFormatter(output.data, output);\n\t\tif (formatted) {\n\t\t\tconsole.log(formatted);\n\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// resolveExitCode\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the LAFS-compliant exit code for a command output.\n *\n * @param output - Typed result from the command.\n * @returns `0` on success, `1` on validation/check failure.\n * @internal\n */\nexport function resolveExitCode(output: CommandOutput<unknown>): number {\n\tif (output.success) return 0;\n\treturn 1;\n}\n","import { type ForgeError, type ForgeWarning, loadConfig } from \"@forge-ts/core\";\nimport { enforce } from \"@forge-ts/enforcer\";\nimport { defineCommand } from \"citty\";\nimport { type CommandOutput, emitResult, type OutputFlags, resolveExitCode } from \"../output.js\";\n\n/**\n * Arguments for the `check` command.\n * @internal\n */\nexport interface CheckArgs {\n\t/** Project root directory (default: cwd). */\n\tcwd?: string;\n\t/** Exit with non-zero code on warnings as well as errors. */\n\tstrict?: boolean;\n\t/** Include symbol signatures alongside diagnostics. */\n\tverbose?: boolean;\n\t/** MVI verbosity level for structured output. */\n\tmvi?: string;\n}\n\n/**\n * A single error entry within a file group, included at standard and full MVI levels.\n * @public\n */\nexport interface CheckFileError {\n\t/** Machine-readable error code. */\n\tcode: string;\n\t/** Symbol name that needs fixing. */\n\tsymbol: string;\n\t/** Symbol kind (function, class, interface, etc.). */\n\tkind: string;\n\t/** 1-based line number of the error. */\n\tline: number;\n\t/** Human-readable description. */\n\tmessage: string;\n\t/** Exact TSDoc block to add (full MVI level only). */\n\tsuggestedFix?: string;\n\t/** Recommended agent action (full MVI level only). */\n\tagentAction?: string;\n}\n\n/**\n * A single warning entry within a file group, included at standard and full MVI levels.\n * @public\n */\nexport interface CheckFileWarning {\n\t/** Machine-readable warning code. */\n\tcode: string;\n\t/** Symbol name that generated the warning. */\n\tsymbol: string;\n\t/** Symbol kind (function, class, interface, etc.). */\n\tkind: string;\n\t/** 1-based line number of the warning. */\n\tline: number;\n\t/** Human-readable description. */\n\tmessage: string;\n}\n\n/**\n * Errors and warnings grouped by file, included at standard and full MVI levels.\n * @public\n */\nexport interface CheckFileGroup {\n\t/** Absolute path to the source file. */\n\tfile: string;\n\t/** Errors in this file. */\n\terrors: CheckFileError[];\n\t/** Warnings in this file. */\n\twarnings: CheckFileWarning[];\n}\n\n/**\n * Typed result for the `check` command.\n * @public\n */\nexport interface CheckResult {\n\t/** Whether the check passed without errors. */\n\tsuccess: boolean;\n\t/** Aggregate counts — always present regardless of MVI level. */\n\tsummary: {\n\t\t/** Total number of errors. */\n\t\terrors: number;\n\t\t/** Total number of warnings. */\n\t\twarnings: number;\n\t\t/** Number of unique files with diagnostics. */\n\t\tfiles: number;\n\t\t/** Number of exported symbols checked. */\n\t\tsymbols: number;\n\t\t/** Wall-clock duration in milliseconds. */\n\t\tduration: number;\n\t};\n\t/** Per-file breakdown — present at standard and full MVI levels. */\n\tbyFile?: CheckFileGroup[];\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Determines the recommended agent action given a ForgeError.\n * @internal\n */\nfunction resolveAgentAction(_error: ForgeError): string {\n\treturn \"retry_modified\";\n}\n\n/**\n * Groups errors and warnings by file path.\n * @internal\n */\nfunction groupByFile(\n\terrors: ForgeError[],\n\twarnings: ForgeWarning[],\n\tincludeFix: boolean,\n): CheckFileGroup[] {\n\tconst fileMap = new Map<string, CheckFileGroup>();\n\n\tfor (const e of errors) {\n\t\tconst fp = e.filePath ?? \"\";\n\t\tif (!fileMap.has(fp)) {\n\t\t\tfileMap.set(fp, { file: fp, errors: [], warnings: [] });\n\t\t}\n\t\tconst entry: CheckFileError = {\n\t\t\tcode: e.code,\n\t\t\tsymbol: e.symbolName ?? \"\",\n\t\t\tkind: e.symbolKind ?? \"\",\n\t\t\tline: e.line,\n\t\t\tmessage: e.message,\n\t\t};\n\t\tif (includeFix) {\n\t\t\tif (e.suggestedFix !== undefined) {\n\t\t\t\tentry.suggestedFix = e.suggestedFix;\n\t\t\t}\n\t\t\tentry.agentAction = resolveAgentAction(e);\n\t\t}\n\t\tfileMap.get(fp)?.errors.push(entry);\n\t}\n\n\tfor (const w of warnings) {\n\t\tconst fp = w.filePath ?? \"\";\n\t\tif (!fileMap.has(fp)) {\n\t\t\tfileMap.set(fp, { file: fp, errors: [], warnings: [] });\n\t\t}\n\t\tfileMap.get(fp)?.warnings.push({\n\t\t\tcode: w.code,\n\t\t\tsymbol: \"\",\n\t\t\tkind: \"\",\n\t\t\tline: w.line,\n\t\t\tmessage: w.message,\n\t\t});\n\t}\n\n\treturn Array.from(fileMap.values());\n}\n\n/**\n * Builds an MVI-projected CheckResult from raw enforcer output.\n * @internal\n */\nfunction buildCheckResult(\n\trawErrors: ForgeError[],\n\trawWarnings: ForgeWarning[],\n\t_symbolCount: number,\n\texportedSymbolCount: number,\n\tduration: number,\n\tsuccess: boolean,\n\tmviLevel: string,\n): CheckResult {\n\tconst uniqueFiles = new Set([\n\t\t...rawErrors.map((e) => e.filePath),\n\t\t...rawWarnings.map((w) => w.filePath),\n\t]);\n\n\tconst summary = {\n\t\terrors: rawErrors.length,\n\t\twarnings: rawWarnings.length,\n\t\tfiles: uniqueFiles.size,\n\t\tsymbols: exportedSymbolCount,\n\t\tduration,\n\t};\n\n\tif (mviLevel === \"minimal\") {\n\t\treturn { success, summary };\n\t}\n\n\tconst byFile = groupByFile(rawErrors, rawWarnings, mviLevel === \"full\");\n\treturn { success, summary, byFile };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Runs the TSDoc enforcement pass and returns a typed command output.\n *\n * @param args - CLI arguments for the check command.\n * @returns A typed `CommandOutput<CheckResult>`.\n * @example\n * ```typescript\n * import { runCheck } from \"@forge-ts/cli/commands/check\";\n * const output = await runCheck({ cwd: process.cwd() });\n * console.log(output.data.summary.errors); // number of TSDoc errors found\n * ```\n * @public\n */\nexport async function runCheck(args: CheckArgs): Promise<CommandOutput<CheckResult>> {\n\tconst config = await loadConfig(args.cwd);\n\tif (args.strict !== undefined) {\n\t\tconfig.enforce.strict = args.strict;\n\t}\n\n\tconst result = await enforce(config);\n\tconst mviLevel = args.mvi ?? \"standard\";\n\n\tconst exportedSymbolCount = result.symbols.filter((s) => s.exported).length;\n\n\tconst data = buildCheckResult(\n\t\tresult.errors,\n\t\tresult.warnings,\n\t\tresult.symbols.length,\n\t\texportedSymbolCount,\n\t\tresult.duration,\n\t\tresult.success,\n\t\tmviLevel,\n\t);\n\n\treturn {\n\t\toperation: \"check\",\n\t\tsuccess: result.success,\n\t\tdata,\n\t\tduration: result.duration,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Human formatter\n// ---------------------------------------------------------------------------\n\n/**\n * Formats a CheckResult as human-readable text.\n * @internal\n */\nfunction formatCheckHuman(result: CheckResult): string {\n\tconst lines: string[] = [];\n\n\tif (result.success) {\n\t\tlines.push(\n\t\t\t`forge-ts check: OK (${result.summary.symbols} symbol(s) checked, ${result.summary.duration}ms)`,\n\t\t);\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\tlines.push(\"forge-ts check: FAILED\\n\");\n\tlines.push(\n\t\t` ${result.summary.errors} error(s), ${result.summary.warnings} warning(s) across ${result.summary.files} file(s) (${result.summary.symbols} symbols checked)\\n`,\n\t);\n\n\tif (result.byFile && result.byFile.length > 0) {\n\t\tfor (const group of result.byFile) {\n\t\t\tif (group.errors.length > 0) {\n\t\t\t\tlines.push(` ${group.file} (${group.errors.length} error(s)):`);\n\t\t\t\tfor (const err of group.errors) {\n\t\t\t\t\tconst symbolPart = err.symbol\n\t\t\t\t\t\t? `${err.symbol} (${err.kind}:${err.line})`\n\t\t\t\t\t\t: `line ${err.line}`;\n\t\t\t\t\tlines.push(` ${err.code} ${symbolPart} — ${err.message}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (group.warnings.length > 0) {\n\t\t\t\tlines.push(` ${group.file} (${group.warnings.length} warning(s)):`);\n\t\t\t\tfor (const w of group.warnings) {\n\t\t\t\t\tlines.push(` ${w.code} line ${w.line} — ${w.message}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlines.push(\"\");\n\t}\n\n\tlines.push(\" Run with --json --mvi full for exact fix suggestions.\");\n\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Citty command definition for `forge-ts check`.\n * @public\n */\nexport const checkCommand = defineCommand({\n\tmeta: {\n\t\tname: \"check\",\n\t\tdescription: \"Lint TSDoc coverage on exported symbols\",\n\t},\n\targs: {\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Project root directory\",\n\t\t},\n\t\tstrict: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Treat warnings as errors\",\n\t\t\tdefault: false,\n\t\t},\n\t\tverbose: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Show detailed output\",\n\t\t\tdefault: false,\n\t\t},\n\t\tjson: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as LAFS JSON envelope (agent-friendly)\",\n\t\t\tdefault: false,\n\t\t},\n\t\thuman: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as formatted text (default for TTY)\",\n\t\t\tdefault: false,\n\t\t},\n\t\tquiet: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Suppress non-essential output\",\n\t\t\tdefault: false,\n\t\t},\n\t\tmvi: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"MVI verbosity level: minimal, standard, full\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst output = await runCheck({\n\t\t\tcwd: args.cwd,\n\t\t\tstrict: args.strict,\n\t\t\tverbose: args.verbose,\n\t\t\tmvi: args.mvi,\n\t\t});\n\n\t\tconst flags: OutputFlags = {\n\t\t\tjson: args.json,\n\t\t\thuman: args.human,\n\t\t\tquiet: args.quiet,\n\t\t\tmvi: args.mvi,\n\t\t};\n\n\t\temitResult(output, flags, (data) => formatCheckHuman(data));\n\n\t\tprocess.exit(resolveExitCode(output));\n\t},\n});\n","import { loadConfig } from \"@forge-ts/core\";\nimport { doctest } from \"@forge-ts/doctest\";\nimport { defineCommand } from \"citty\";\nimport { type CommandOutput, emitResult, type OutputFlags, resolveExitCode } from \"../output.js\";\n\n/**\n * Arguments for the `test` command.\n * @internal\n */\nexport interface TestArgs {\n\t/** Project root directory (default: cwd). */\n\tcwd?: string;\n\t/** MVI verbosity level for structured output. */\n\tmvi?: string;\n}\n\n/**\n * A single test failure entry, included at standard and full MVI levels.\n * @public\n */\nexport interface TestFailure {\n\t/** Symbol name where the doctest failed. */\n\tsymbol: string;\n\t/** Absolute path to the source file. */\n\tfile: string;\n\t/** 1-based line number of the failing example. */\n\tline: number;\n\t/** Human-readable failure message. */\n\tmessage: string;\n}\n\n/**\n * Typed result for the `test` command.\n * @public\n */\nexport interface TestResult {\n\t/** Whether all doctests passed. */\n\tsuccess: boolean;\n\t/** Aggregate counts — always present regardless of MVI level. */\n\tsummary: {\n\t\t/** Number of passing doctests. */\n\t\tpassed: number;\n\t\t/** Number of failing doctests. */\n\t\tfailed: number;\n\t\t/** Total doctests run. */\n\t\ttotal: number;\n\t\t/** Wall-clock duration in milliseconds. */\n\t\tduration: number;\n\t};\n\t/** Per-failure details — present at standard and full MVI levels. */\n\tfailures?: TestFailure[];\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Runs the doctest pipeline and returns a typed command output.\n *\n * @param args - CLI arguments for the test command.\n * @returns A typed `CommandOutput<TestResult>`.\n * @example\n * ```typescript\n * import { runTest } from \"@forge-ts/cli/commands/test\";\n * const output = await runTest({ cwd: process.cwd() });\n * console.log(output.data.summary.passed); // number of passing doctests\n * ```\n * @public\n */\nexport async function runTest(args: TestArgs): Promise<CommandOutput<TestResult>> {\n\tconst config = await loadConfig(args.cwd);\n\tconst result = await doctest(config);\n\tconst mviLevel = args.mvi ?? \"standard\";\n\n\tconst failCount = result.errors.length;\n\tconst totalSymbols = result.symbols.length;\n\tconst passCount = totalSymbols - failCount > 0 ? totalSymbols - failCount : 0;\n\n\tconst summary = {\n\t\tpassed: passCount,\n\t\tfailed: failCount,\n\t\ttotal: totalSymbols,\n\t\tduration: result.duration,\n\t};\n\n\tconst data: TestResult = { success: result.success, summary };\n\n\tif (mviLevel !== \"minimal\") {\n\t\tdata.failures = result.errors.map((e) => ({\n\t\t\tsymbol: e.symbolName ?? \"\",\n\t\t\tfile: e.filePath ?? \"\",\n\t\t\tline: e.line,\n\t\t\tmessage: e.message,\n\t\t}));\n\t}\n\n\treturn {\n\t\toperation: \"test\",\n\t\tsuccess: result.success,\n\t\tdata,\n\t\tduration: result.duration,\n\t};\n}\n\n/**\n * Citty command definition for `forge-ts test`.\n * @public\n */\nexport const testCommand = defineCommand({\n\tmeta: {\n\t\tname: \"test\",\n\t\tdescription: \"Run @example blocks as doctests\",\n\t},\n\targs: {\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Project root directory\",\n\t\t},\n\t\tjson: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as LAFS JSON envelope (agent-friendly)\",\n\t\t\tdefault: false,\n\t\t},\n\t\thuman: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as formatted text (default for TTY)\",\n\t\t\tdefault: false,\n\t\t},\n\t\tquiet: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Suppress non-essential output\",\n\t\t\tdefault: false,\n\t\t},\n\t\tmvi: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"MVI verbosity level: minimal, standard, full\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst output = await runTest({ cwd: args.cwd, mvi: args.mvi });\n\n\t\tconst flags: OutputFlags = {\n\t\t\tjson: args.json,\n\t\t\thuman: args.human,\n\t\t\tquiet: args.quiet,\n\t\t\tmvi: args.mvi,\n\t\t};\n\n\t\temitResult(output, flags, (data) => {\n\t\t\tif (output.success) {\n\t\t\t\treturn `forge-ts test: all doctests passed. (${data.summary.duration}ms)`;\n\t\t\t}\n\t\t\tconst lines: string[] = [];\n\t\t\tfor (const f of data.failures ?? []) {\n\t\t\t\tlines.push(f.message);\n\t\t\t}\n\t\t\tlines.push(`forge-ts test: ${data.summary.failed} failure(s). (${data.summary.duration}ms)`);\n\t\t\treturn lines.join(\"\\n\");\n\t\t});\n\n\t\tprocess.exit(resolveExitCode(output));\n\t},\n});\n"],"mappings":"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","names":["defineCommand","loadConfig","defineCommand","loadConfig","defineCommand","loadConfig","defineCommand","loadConfig","defineCommand","defineCommand"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/build.ts","../src/logger.ts","../src/output.ts","../src/commands/check.ts","../src/commands/docs-dev.ts","../src/commands/init-docs.ts","../src/commands/test.ts"],"sourcesContent":["/**\n * @forge-ts/cli — Command-line interface for the forge-ts toolchain.\n *\n * Usage:\n * forge-ts check [--cwd <dir>] [--strict] [--verbose]\n * forge-ts test [--cwd <dir>]\n * forge-ts build [--cwd <dir>] [--skip-api] [--skip-gen]\n * forge-ts docs init [--target <ssg>] [--out-dir <dir>] [--force]\n * forge-ts docs dev [--target <ssg>] [--port <port>]\n *\n * @packageDocumentation\n * @public\n */\n\nimport { defineCommand, runMain } from \"citty\";\nimport { buildCommand } from \"./commands/build.js\";\nimport { checkCommand } from \"./commands/check.js\";\nimport { docsDevCommand } from \"./commands/docs-dev.js\";\nimport { initDocsCommand } from \"./commands/init-docs.js\";\nimport { testCommand } from \"./commands/test.js\";\n\nexport { type BuildResult, type BuildStep, buildCommand } from \"./commands/build.js\";\nexport {\n\ttype CheckFileError,\n\ttype CheckFileGroup,\n\ttype CheckFileWarning,\n\ttype CheckResult,\n\tcheckCommand,\n} from \"./commands/check.js\";\nexport { docsDevCommand, runDocsDev } from \"./commands/docs-dev.js\";\nexport {\n\ttype InitDocsResult,\n\tinitDocsCommand,\n} from \"./commands/init-docs.js\";\nexport { type TestFailure, type TestResult, testCommand } from \"./commands/test.js\";\nexport { createLogger, type Logger } from \"./logger.js\";\nexport {\n\ttype CommandOutput,\n\temitResult,\n\ttype ForgeCliError,\n\ttype ForgeCliWarning,\n\ttype OutputFlags,\n\tresolveExitCode,\n} from \"./output.js\";\n\n/**\n * The `docs` parent command with `init` and `dev` subcommands.\n *\n * @example\n * ```typescript\n * // forge-ts docs init --target mintlify\n * // forge-ts docs dev\n * ```\n * @public\n */\nconst docsCommand = defineCommand({\n\tmeta: {\n\t\tname: \"docs\",\n\t\tdescription: \"Documentation site management\",\n\t},\n\tsubCommands: {\n\t\tinit: initDocsCommand,\n\t\tdev: docsDevCommand,\n\t},\n});\n\nconst main = defineCommand({\n\tmeta: {\n\t\tname: \"forge-ts\",\n\t\tversion: \"0.5.0\",\n\t\tdescription: \"Universal TypeScript Documentation Compiler\",\n\t},\n\tsubCommands: {\n\t\tcheck: checkCommand,\n\t\ttest: testCommand,\n\t\tbuild: buildCommand,\n\t\tdocs: docsCommand,\n\t},\n});\n\nrunMain(main);\n","import { join } from \"node:path\";\nimport { generateApi } from \"@forge-ts/api\";\nimport { loadConfig } from \"@forge-ts/core\";\nimport { generate, type GenerateOptions } from \"@forge-ts/gen\";\nimport { defineCommand } from \"citty\";\nimport { createLogger } from \"../logger.js\";\nimport {\n\ttype CommandOutput,\n\temitResult,\n\ttype ForgeCliError,\n\ttype OutputFlags,\n\tresolveExitCode,\n} from \"../output.js\";\n\n/**\n * Arguments for the `build` command.\n * @internal\n */\nexport interface BuildArgs {\n\t/** Project root directory (default: cwd). */\n\tcwd?: string;\n\t/** Skip API generation even if enabled in config. */\n\tskipApi?: boolean;\n\t/** Skip doc generation even if enabled in config. */\n\tskipGen?: boolean;\n\t/**\n\t * Overwrite stub pages even if they already exist on disk.\n\t * Normally stub pages (concepts, guides, faq, contributing, changelog)\n\t * are only created on the first build to preserve manual edits.\n\t * Use this to reset stubs to their scaffolding state.\n\t */\n\tforceStubs?: boolean;\n\t/** MVI verbosity level for structured output. */\n\tmvi?: string;\n}\n\n/**\n * A single step in the build pipeline.\n * @public\n */\nexport interface BuildStep {\n\t/** Internal step name, e.g. \"api\" or \"gen\". */\n\tname: string;\n\t/** Outcome of this step. */\n\tstatus: \"success\" | \"skipped\" | \"failed\";\n\t/** Path to the primary output file produced by this step, if applicable. */\n\toutputPath?: string;\n\t/** Wall-clock duration of this step in milliseconds. */\n\tduration?: number;\n\t/** Errors produced by this step when status is \"failed\". */\n\terrors?: ForgeCliError[];\n}\n\n/**\n * Typed result for the `build` command.\n * @public\n */\nexport interface BuildResult {\n\t/** Whether the build succeeded. */\n\tsuccess: boolean;\n\t/** Aggregate pipeline counts — always present. */\n\tsummary: {\n\t\t/** Total number of pipeline steps. */\n\t\tsteps: number;\n\t\t/** Steps that completed successfully. */\n\t\tsucceeded: number;\n\t\t/** Steps that failed. */\n\t\tfailed: number;\n\t\t/** Wall-clock duration in milliseconds. */\n\t\tduration: number;\n\t};\n\t/** Per-step details. */\n\tsteps: BuildStep[];\n\t/** Files written during the build — present at standard and full MVI levels. */\n\tgeneratedFiles?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Runs the full build pipeline and returns a typed command output.\n *\n * @param args - CLI arguments for the build command.\n * @returns A typed `CommandOutput<BuildResult>`.\n * @example\n * ```typescript\n * import { runBuild } from \"@forge-ts/cli/commands/build\";\n * const output = await runBuild({ cwd: process.cwd() });\n * console.log(output.success); // true if all steps succeeded\n * ```\n * @public\n */\nexport async function runBuild(args: BuildArgs): Promise<CommandOutput<BuildResult>> {\n\tconst config = await loadConfig(args.cwd);\n\tconst buildStart = Date.now();\n\tconst mviLevel = args.mvi ?? \"standard\";\n\n\tconst steps: BuildStep[] = [];\n\tconst allErrors: ForgeCliError[] = [];\n\tconst generatedFiles: string[] = [];\n\tlet success = true;\n\n\tif (config.api.enabled && !args.skipApi) {\n\t\tconst result = await generateApi(config);\n\t\tif (!result.success) {\n\t\t\tconst errors: ForgeCliError[] = result.errors.map((e) => ({\n\t\t\t\tcode: e.code,\n\t\t\t\tmessage: e.message,\n\t\t\t\tfilePath: e.filePath,\n\t\t\t\tline: e.line,\n\t\t\t\tcolumn: e.column,\n\t\t\t}));\n\t\t\tallErrors.push(...errors);\n\t\t\tsuccess = false;\n\t\t\tsteps.push({\n\t\t\t\tname: \"api\",\n\t\t\t\tstatus: \"failed\",\n\t\t\t\toutputPath: config.api.openapiPath,\n\t\t\t\tduration: result.duration,\n\t\t\t\terrors,\n\t\t\t});\n\t\t} else {\n\t\t\tsteps.push({\n\t\t\t\tname: \"api\",\n\t\t\t\tstatus: \"success\",\n\t\t\t\toutputPath: config.api.openapiPath,\n\t\t\t\tduration: result.duration,\n\t\t\t});\n\t\t\tgeneratedFiles.push(config.api.openapiPath);\n\t\t}\n\t} else if (!config.api.enabled || args.skipApi) {\n\t\tsteps.push({ name: \"api\", status: \"skipped\" });\n\t}\n\n\tif (config.gen.enabled && !args.skipGen) {\n\t\tconst result = await generate(config, { forceStubs: args.forceStubs });\n\t\tif (!result.success) {\n\t\t\tconst errors: ForgeCliError[] = result.errors.map((e) => ({\n\t\t\t\tcode: e.code,\n\t\t\t\tmessage: e.message,\n\t\t\t\tfilePath: e.filePath,\n\t\t\t\tline: e.line,\n\t\t\t\tcolumn: e.column,\n\t\t\t}));\n\t\t\tallErrors.push(...errors);\n\t\t\tsuccess = false;\n\t\t\tsteps.push({\n\t\t\t\tname: \"gen\",\n\t\t\t\tstatus: \"failed\",\n\t\t\t\tduration: result.duration,\n\t\t\t\terrors,\n\t\t\t});\n\t\t} else {\n\t\t\tsteps.push({\n\t\t\t\tname: \"gen\",\n\t\t\t\tstatus: \"success\",\n\t\t\t\tduration: result.duration,\n\t\t\t});\n\t\t\t// Track the generated output directory and standard files\n\t\t\tfor (const format of config.gen.formats) {\n\t\t\t\tconst ext = format === \"mdx\" ? \"mdx\" : \"md\";\n\t\t\t\tgeneratedFiles.push(join(config.outDir, `api-reference.${ext}`));\n\t\t\t}\n\t\t\tif (config.gen.llmsTxt) {\n\t\t\t\tgeneratedFiles.push(join(config.outDir, \"llms.txt\"));\n\t\t\t\tgeneratedFiles.push(join(config.outDir, \"llms-full.txt\"));\n\t\t\t}\n\t\t}\n\t} else if (!config.gen.enabled || args.skipGen) {\n\t\tsteps.push({ name: \"gen\", status: \"skipped\" });\n\t}\n\n\tconst totalMs = Date.now() - buildStart;\n\n\tconst succeededCount = steps.filter((s) => s.status === \"success\").length;\n\tconst failedCount = steps.filter((s) => s.status === \"failed\").length;\n\n\tconst data: BuildResult = {\n\t\tsuccess,\n\t\tsummary: {\n\t\t\tsteps: steps.length,\n\t\t\tsucceeded: succeededCount,\n\t\t\tfailed: failedCount,\n\t\t\tduration: totalMs,\n\t\t},\n\t\tsteps,\n\t};\n\n\tif (mviLevel !== \"minimal\") {\n\t\tdata.generatedFiles = generatedFiles;\n\t}\n\n\treturn {\n\t\toperation: \"build\",\n\t\tsuccess,\n\t\tdata,\n\t\terrors: allErrors,\n\t\tduration: totalMs,\n\t};\n}\n\n/**\n * Citty command definition for `forge-ts build`.\n * @public\n */\nexport const buildCommand = defineCommand({\n\tmeta: {\n\t\tname: \"build\",\n\t\tdescription: \"Generate API reference and documentation\",\n\t},\n\targs: {\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Project root directory\",\n\t\t},\n\t\t\"skip-api\": {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Skip OpenAPI generation\",\n\t\t\tdefault: false,\n\t\t},\n\t\t\"skip-gen\": {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Skip doc generation\",\n\t\t\tdefault: false,\n\t\t},\n\t\t\"force-stubs\": {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Overwrite stub pages even if they exist (reset to scaffolding)\",\n\t\t\tdefault: false,\n\t\t},\n\t\tjson: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as LAFS JSON envelope (agent-friendly)\",\n\t\t\tdefault: false,\n\t\t},\n\t\thuman: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as formatted text (default for TTY)\",\n\t\t\tdefault: false,\n\t\t},\n\t\tquiet: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Suppress non-essential output\",\n\t\t\tdefault: false,\n\t\t},\n\t\tmvi: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"MVI verbosity level: minimal, standard, full\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst output = await runBuild({\n\t\t\tcwd: args.cwd,\n\t\t\tskipApi: args[\"skip-api\"],\n\t\t\tskipGen: args[\"skip-gen\"],\n\t\t\tforceStubs: args[\"force-stubs\"],\n\t\t\tmvi: args.mvi,\n\t\t});\n\n\t\tconst flags: OutputFlags = {\n\t\t\tjson: args.json,\n\t\t\thuman: args.human,\n\t\t\tquiet: args.quiet,\n\t\t\tmvi: args.mvi,\n\t\t};\n\n\t\temitResult(output, flags, (data) => {\n\t\t\tconst logger = createLogger();\n\t\t\tfor (const step of data.steps) {\n\t\t\t\tif (step.status === \"failed\") {\n\t\t\t\t\tfor (const err of step.errors ?? []) {\n\t\t\t\t\t\tlogger.error(`[${step.name}] ${err.message}`);\n\t\t\t\t\t}\n\t\t\t\t} else if (step.status === \"success\") {\n\t\t\t\t\tconst detail =\n\t\t\t\t\t\tstep.name === \"api\" && step.outputPath != null\n\t\t\t\t\t\t\t? `Generated OpenAPI spec \\u2192 ${step.outputPath}`\n\t\t\t\t\t\t\t: `Step complete`;\n\t\t\t\t\tlogger.step(step.name.toUpperCase(), detail, step.duration);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (output.success) {\n\t\t\t\treturn ` Done in ${data.summary.duration}ms`;\n\t\t\t}\n\t\t\treturn \"\";\n\t\t});\n\n\t\tprocess.exit(resolveExitCode(output));\n\t},\n});\n","/**\n * Simple TTY-aware logger for forge-ts CLI output.\n *\n * Uses ANSI escape codes directly — no external colour library.\n *\n * @packageDocumentation\n * @internal\n */\n\n// ---------------------------------------------------------------------------\n// ANSI constants\n// ---------------------------------------------------------------------------\n\nconst GREEN = \"\\x1b[32m\";\nconst YELLOW = \"\\x1b[33m\";\nconst RED = \"\\x1b[31m\";\nconst BOLD = \"\\x1b[1m\";\nconst RESET = \"\\x1b[0m\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * A minimal structured logger used throughout the CLI commands.\n * @internal\n */\nexport interface Logger {\n\t/** Print an informational message. */\n\tinfo(msg: string): void;\n\t/** Print a success message (green ✓ prefix when colours are on). */\n\tsuccess(msg: string): void;\n\t/** Print a warning message (yellow prefix when colours are on). */\n\twarn(msg: string): void;\n\t/** Print an error message (red ✗ prefix when colours are on). */\n\terror(msg: string): void;\n\t/**\n\t * Print a build-step line.\n\t *\n\t * @param label - Short category label (e.g. \"API\", \"Gen\").\n\t * @param detail - Description of what was produced.\n\t * @param duration - Optional wall-clock time in milliseconds.\n\t */\n\tstep(label: string, detail: string, duration?: number): void;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a {@link Logger} instance.\n *\n * @param options - Optional configuration.\n * @param options.colors - Emit ANSI colour codes. Defaults to `process.stdout.isTTY`.\n * @returns A configured logger.\n * @internal\n */\nexport function createLogger(options?: { colors?: boolean }): Logger {\n\tconst useColors = options?.colors ?? process.stdout.isTTY ?? false;\n\n\tfunction colorize(text: string, code: string): string {\n\t\treturn useColors ? `${code}${text}${RESET}` : text;\n\t}\n\n\tfunction bold(text: string): string {\n\t\treturn useColors ? `${BOLD}${text}${RESET}` : text;\n\t}\n\n\treturn {\n\t\tinfo(msg: string): void {\n\t\t\tconsole.log(msg);\n\t\t},\n\n\t\tsuccess(msg: string): void {\n\t\t\tconst prefix = colorize(\"✓\", GREEN);\n\t\t\tconsole.log(`${prefix} ${msg}`);\n\t\t},\n\n\t\twarn(msg: string): void {\n\t\t\tconst prefix = colorize(\"warn\", YELLOW);\n\t\t\tconsole.warn(`${bold(prefix)} ${msg}`);\n\t\t},\n\n\t\terror(msg: string): void {\n\t\t\tconst prefix = colorize(\"error\", RED);\n\t\t\tconsole.error(`${bold(prefix)} ${msg}`);\n\t\t},\n\n\t\tstep(label: string, detail: string, duration?: number): void {\n\t\t\tconst check = colorize(\"✓\", GREEN);\n\t\t\tconst durationStr = duration !== undefined ? ` (${duration}ms)` : \"\";\n\t\t\tconsole.log(` ${check} ${bold(label)}: ${detail}${durationStr}`);\n\t\t},\n\t};\n}\n","/**\n * Central output layer for forge-ts CLI.\n *\n * Wraps all command results in LAFS envelopes for agent-first output, while\n * preserving human-readable formatting for TTY consumers.\n *\n * @packageDocumentation\n * @internal\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport {\n\tcreateEnvelope,\n\ttype MVILevel,\n\tprojectEnvelope,\n\tresolveFlags,\n\ttype UnifiedFlagInput,\n} from \"@cleocode/lafs-protocol\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/** Typed result from a forge-ts command. */\nexport interface CommandOutput<T> {\n\t/** Name of the command that produced this output (e.g., \"check\", \"build\"). */\n\toperation: string;\n\t/** Whether the command completed successfully. */\n\tsuccess: boolean;\n\t/** Strongly-typed command-specific result payload. */\n\tdata: T;\n\t/** Structured errors produced by the command, if any. */\n\terrors?: ForgeCliError[];\n\t/** Structured warnings produced by the command, if any. */\n\twarnings?: ForgeCliWarning[];\n\t/** Wall-clock duration of the command in milliseconds. */\n\tduration?: number;\n}\n\n/** Structured error for CLI commands. */\nexport interface ForgeCliError {\n\t/** Machine-readable error code (e.g., \"E004\"). */\n\tcode: string;\n\t/** Human-readable error description. */\n\tmessage: string;\n\t/** Absolute path to the source file containing the error, if applicable. */\n\tfilePath?: string;\n\t/** 1-based line number of the error, if applicable. */\n\tline?: number;\n\t/** 0-based column number of the error, if applicable. */\n\tcolumn?: number;\n}\n\n/** Structured warning for CLI commands. */\nexport interface ForgeCliWarning {\n\t/** Machine-readable warning code. */\n\tcode: string;\n\t/** Human-readable warning description. */\n\tmessage: string;\n\t/** Absolute path to the source file containing the warning, if applicable. */\n\tfilePath?: string;\n\t/** 1-based line number of the warning, if applicable. */\n\tline?: number;\n\t/** 0-based column number of the warning, if applicable. */\n\tcolumn?: number;\n}\n\n/** Output format flags passed through from citty args. */\nexport interface OutputFlags {\n\t/** Emit output as a LAFS JSON envelope instead of human-readable text. */\n\tjson?: boolean;\n\t/** Emit output as formatted human-readable text. */\n\thuman?: boolean;\n\t/** Suppress all output regardless of format. */\n\tquiet?: boolean;\n\t/** MVI verbosity level: \"minimal\", \"standard\", or \"full\". */\n\tmvi?: string;\n}\n\n// ---------------------------------------------------------------------------\n// emitResult\n// ---------------------------------------------------------------------------\n\n/**\n * Wraps a command result in a LAFS envelope and emits it.\n *\n * - JSON mode: writes the projected envelope to stdout as JSON.\n * - Human mode: calls the provided formatter function.\n * - Quiet mode: suppresses all output regardless of format.\n *\n * @param output - Typed result from the command.\n * @param flags - Output format flags from citty args.\n * @param humanFormatter - Produces a human-readable string for TTY consumers.\n * @example\n * ```typescript\n * import { emitResult } from \"@forge-ts/cli/output\";\n * emitResult(output, { human: true }, (data) => `Done: ${data.summary.duration}ms`);\n * ```\n * @internal\n */\nexport function emitResult<T>(\n\toutput: CommandOutput<T>,\n\tflags: OutputFlags,\n\thumanFormatter: (data: T, output: CommandOutput<T>) => string,\n): void {\n\tconst flagInput: UnifiedFlagInput = {\n\t\tjson: flags.json,\n\t\thuman: flags.human,\n\t\tquiet: flags.quiet,\n\t\tmvi: flags.mvi,\n\t};\n\n\tconst resolved = resolveFlags(flagInput);\n\tconst format = resolved.format.format;\n\tconst quiet = resolved.format.quiet;\n\n\t// Quiet mode: suppress all output, just let exit code speak.\n\tif (quiet) {\n\t\treturn;\n\t}\n\n\t// Build the LAFS envelope\n\tconst envelope = createEnvelope(\n\t\toutput.success\n\t\t\t? {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tresult: output.data as Record<string, unknown>,\n\t\t\t\t\tmeta: {\n\t\t\t\t\t\toperation: `forge-ts.${output.operation}`,\n\t\t\t\t\t\trequestId: randomUUID(),\n\t\t\t\t\t\ttransport: \"cli\",\n\t\t\t\t\t\tmvi: (flags.mvi as MVILevel) ?? \"standard\",\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: output.errors?.[0]?.code ?? \"FORGE_ERROR\",\n\t\t\t\t\t\tmessage: output.errors?.[0]?.message ?? \"Command failed\",\n\t\t\t\t\t\tcategory: \"VALIDATION\",\n\t\t\t\t\t\tretryable: false,\n\t\t\t\t\t\tretryAfterMs: null,\n\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\terrors: output.errors ?? [],\n\t\t\t\t\t\t\twarnings: output.warnings ?? [],\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tmeta: {\n\t\t\t\t\t\toperation: `forge-ts.${output.operation}`,\n\t\t\t\t\t\trequestId: randomUUID(),\n\t\t\t\t\t\ttransport: \"cli\",\n\t\t\t\t\t\tmvi: (flags.mvi as MVILevel) ?? \"standard\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t);\n\n\tif (format === \"json\") {\n\t\t// MVI projection reduces token cost for agents\n\t\tconst mviLevel: MVILevel = (flags.mvi as MVILevel) ?? \"standard\";\n\t\tconst projected = projectEnvelope(envelope, mviLevel);\n\t\tprocess.stdout.write(`${JSON.stringify(projected, null, 2)}\\n`);\n\t} else {\n\t\t// Human-readable output\n\t\tconst formatted = humanFormatter(output.data, output);\n\t\tif (formatted) {\n\t\t\tconsole.log(formatted);\n\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// resolveExitCode\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the LAFS-compliant exit code for a command output.\n *\n * @param output - Typed result from the command.\n * @returns `0` on success, `1` on validation/check failure.\n * @internal\n */\nexport function resolveExitCode(output: CommandOutput<unknown>): number {\n\tif (output.success) return 0;\n\treturn 1;\n}\n","import { type ForgeError, type ForgeWarning, loadConfig } from \"@forge-ts/core\";\nimport { enforce } from \"@forge-ts/enforcer\";\nimport { defineCommand } from \"citty\";\nimport { type CommandOutput, emitResult, type OutputFlags, resolveExitCode } from \"../output.js\";\n\n/**\n * Arguments for the `check` command.\n * @internal\n */\nexport interface CheckArgs {\n\t/** Project root directory (default: cwd). */\n\tcwd?: string;\n\t/** Exit with non-zero code on warnings as well as errors. */\n\tstrict?: boolean;\n\t/** Include symbol signatures alongside diagnostics. */\n\tverbose?: boolean;\n\t/** MVI verbosity level for structured output. */\n\tmvi?: string;\n}\n\n/**\n * A single error entry within a file group, included at standard and full MVI levels.\n * @public\n */\nexport interface CheckFileError {\n\t/** Machine-readable error code. */\n\tcode: string;\n\t/** Symbol name that needs fixing. */\n\tsymbol: string;\n\t/** Symbol kind (function, class, interface, etc.). */\n\tkind: string;\n\t/** 1-based line number of the error. */\n\tline: number;\n\t/** Human-readable description. */\n\tmessage: string;\n\t/** Exact TSDoc block to add (full MVI level only). */\n\tsuggestedFix?: string;\n\t/** Recommended agent action (full MVI level only). */\n\tagentAction?: string;\n}\n\n/**\n * A single warning entry within a file group, included at standard and full MVI levels.\n * @public\n */\nexport interface CheckFileWarning {\n\t/** Machine-readable warning code. */\n\tcode: string;\n\t/** Symbol name that generated the warning. */\n\tsymbol: string;\n\t/** Symbol kind (function, class, interface, etc.). */\n\tkind: string;\n\t/** 1-based line number of the warning. */\n\tline: number;\n\t/** Human-readable description. */\n\tmessage: string;\n}\n\n/**\n * Errors and warnings grouped by file, included at standard and full MVI levels.\n * @public\n */\nexport interface CheckFileGroup {\n\t/** Absolute path to the source file. */\n\tfile: string;\n\t/** Errors in this file. */\n\terrors: CheckFileError[];\n\t/** Warnings in this file. */\n\twarnings: CheckFileWarning[];\n}\n\n/**\n * Typed result for the `check` command.\n * @public\n */\nexport interface CheckResult {\n\t/** Whether the check passed without errors. */\n\tsuccess: boolean;\n\t/** Aggregate counts — always present regardless of MVI level. */\n\tsummary: {\n\t\t/** Total number of errors. */\n\t\terrors: number;\n\t\t/** Total number of warnings. */\n\t\twarnings: number;\n\t\t/** Number of unique files with diagnostics. */\n\t\tfiles: number;\n\t\t/** Number of exported symbols checked. */\n\t\tsymbols: number;\n\t\t/** Wall-clock duration in milliseconds. */\n\t\tduration: number;\n\t};\n\t/** Per-file breakdown — present at standard and full MVI levels. */\n\tbyFile?: CheckFileGroup[];\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Determines the recommended agent action given a ForgeError.\n * @internal\n */\nfunction resolveAgentAction(_error: ForgeError): string {\n\treturn \"retry_modified\";\n}\n\n/**\n * Groups errors and warnings by file path.\n * @internal\n */\nfunction groupByFile(\n\terrors: ForgeError[],\n\twarnings: ForgeWarning[],\n\tincludeFix: boolean,\n): CheckFileGroup[] {\n\tconst fileMap = new Map<string, CheckFileGroup>();\n\n\tfor (const e of errors) {\n\t\tconst fp = e.filePath ?? \"\";\n\t\tif (!fileMap.has(fp)) {\n\t\t\tfileMap.set(fp, { file: fp, errors: [], warnings: [] });\n\t\t}\n\t\tconst entry: CheckFileError = {\n\t\t\tcode: e.code,\n\t\t\tsymbol: e.symbolName ?? \"\",\n\t\t\tkind: e.symbolKind ?? \"\",\n\t\t\tline: e.line,\n\t\t\tmessage: e.message,\n\t\t};\n\t\tif (includeFix) {\n\t\t\tif (e.suggestedFix !== undefined) {\n\t\t\t\tentry.suggestedFix = e.suggestedFix;\n\t\t\t}\n\t\t\tentry.agentAction = resolveAgentAction(e);\n\t\t}\n\t\tfileMap.get(fp)?.errors.push(entry);\n\t}\n\n\tfor (const w of warnings) {\n\t\tconst fp = w.filePath ?? \"\";\n\t\tif (!fileMap.has(fp)) {\n\t\t\tfileMap.set(fp, { file: fp, errors: [], warnings: [] });\n\t\t}\n\t\tfileMap.get(fp)?.warnings.push({\n\t\t\tcode: w.code,\n\t\t\tsymbol: \"\",\n\t\t\tkind: \"\",\n\t\t\tline: w.line,\n\t\t\tmessage: w.message,\n\t\t});\n\t}\n\n\treturn Array.from(fileMap.values());\n}\n\n/**\n * Builds an MVI-projected CheckResult from raw enforcer output.\n * @internal\n */\nfunction buildCheckResult(\n\trawErrors: ForgeError[],\n\trawWarnings: ForgeWarning[],\n\t_symbolCount: number,\n\texportedSymbolCount: number,\n\tduration: number,\n\tsuccess: boolean,\n\tmviLevel: string,\n): CheckResult {\n\tconst uniqueFiles = new Set([\n\t\t...rawErrors.map((e) => e.filePath),\n\t\t...rawWarnings.map((w) => w.filePath),\n\t]);\n\n\tconst summary = {\n\t\terrors: rawErrors.length,\n\t\twarnings: rawWarnings.length,\n\t\tfiles: uniqueFiles.size,\n\t\tsymbols: exportedSymbolCount,\n\t\tduration,\n\t};\n\n\tif (mviLevel === \"minimal\") {\n\t\treturn { success, summary };\n\t}\n\n\tconst byFile = groupByFile(rawErrors, rawWarnings, mviLevel === \"full\");\n\treturn { success, summary, byFile };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Runs the TSDoc enforcement pass and returns a typed command output.\n *\n * @param args - CLI arguments for the check command.\n * @returns A typed `CommandOutput<CheckResult>`.\n * @example\n * ```typescript\n * import { runCheck } from \"@forge-ts/cli/commands/check\";\n * const output = await runCheck({ cwd: process.cwd() });\n * console.log(output.data.summary.errors); // number of TSDoc errors found\n * ```\n * @public\n */\nexport async function runCheck(args: CheckArgs): Promise<CommandOutput<CheckResult>> {\n\tconst config = await loadConfig(args.cwd);\n\tif (args.strict !== undefined) {\n\t\tconfig.enforce.strict = args.strict;\n\t}\n\n\tconst result = await enforce(config);\n\tconst mviLevel = args.mvi ?? \"standard\";\n\n\tconst exportedSymbolCount = result.symbols.filter((s) => s.exported).length;\n\n\tconst data = buildCheckResult(\n\t\tresult.errors,\n\t\tresult.warnings,\n\t\tresult.symbols.length,\n\t\texportedSymbolCount,\n\t\tresult.duration,\n\t\tresult.success,\n\t\tmviLevel,\n\t);\n\n\treturn {\n\t\toperation: \"check\",\n\t\tsuccess: result.success,\n\t\tdata,\n\t\tduration: result.duration,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Human formatter\n// ---------------------------------------------------------------------------\n\n/**\n * Formats a CheckResult as human-readable text.\n * @internal\n */\nfunction formatCheckHuman(result: CheckResult): string {\n\tconst lines: string[] = [];\n\n\tif (result.success) {\n\t\tlines.push(\n\t\t\t`forge-ts check: OK (${result.summary.symbols} symbol(s) checked, ${result.summary.duration}ms)`,\n\t\t);\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\tlines.push(\"forge-ts check: FAILED\\n\");\n\tlines.push(\n\t\t` ${result.summary.errors} error(s), ${result.summary.warnings} warning(s) across ${result.summary.files} file(s) (${result.summary.symbols} symbols checked)\\n`,\n\t);\n\n\tif (result.byFile && result.byFile.length > 0) {\n\t\tfor (const group of result.byFile) {\n\t\t\tif (group.errors.length > 0) {\n\t\t\t\tlines.push(` ${group.file} (${group.errors.length} error(s)):`);\n\t\t\t\tfor (const err of group.errors) {\n\t\t\t\t\tconst symbolPart = err.symbol\n\t\t\t\t\t\t? `${err.symbol} (${err.kind}:${err.line})`\n\t\t\t\t\t\t: `line ${err.line}`;\n\t\t\t\t\tlines.push(` ${err.code} ${symbolPart} — ${err.message}`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (group.warnings.length > 0) {\n\t\t\t\tlines.push(` ${group.file} (${group.warnings.length} warning(s)):`);\n\t\t\t\tfor (const w of group.warnings) {\n\t\t\t\t\tlines.push(` ${w.code} line ${w.line} — ${w.message}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlines.push(\"\");\n\t}\n\n\tlines.push(\" Run with --json --mvi full for exact fix suggestions.\");\n\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Citty command definition for `forge-ts check`.\n * @public\n */\nexport const checkCommand = defineCommand({\n\tmeta: {\n\t\tname: \"check\",\n\t\tdescription: \"Lint TSDoc coverage on exported symbols\",\n\t},\n\targs: {\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Project root directory\",\n\t\t},\n\t\tstrict: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Treat warnings as errors\",\n\t\t\tdefault: false,\n\t\t},\n\t\tverbose: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Show detailed output\",\n\t\t\tdefault: false,\n\t\t},\n\t\tjson: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as LAFS JSON envelope (agent-friendly)\",\n\t\t\tdefault: false,\n\t\t},\n\t\thuman: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as formatted text (default for TTY)\",\n\t\t\tdefault: false,\n\t\t},\n\t\tquiet: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Suppress non-essential output\",\n\t\t\tdefault: false,\n\t\t},\n\t\tmvi: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"MVI verbosity level: minimal, standard, full\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst output = await runCheck({\n\t\t\tcwd: args.cwd,\n\t\t\tstrict: args.strict,\n\t\t\tverbose: args.verbose,\n\t\t\tmvi: args.mvi,\n\t\t});\n\n\t\tconst flags: OutputFlags = {\n\t\t\tjson: args.json,\n\t\t\thuman: args.human,\n\t\t\tquiet: args.quiet,\n\t\t\tmvi: args.mvi,\n\t\t};\n\n\t\temitResult(output, flags, (data) => formatCheckHuman(data));\n\n\t\tprocess.exit(resolveExitCode(output));\n\t},\n});\n","/**\n * The `forge-ts docs dev` command — starts a local doc preview server.\n *\n * Reads the ssgTarget from forge-ts config, looks up the adapter,\n * and spawns the correct dev server automatically.\n *\n * @packageDocumentation\n * @public\n */\n\nimport { spawn } from \"node:child_process\";\nimport { resolve } from \"node:path\";\nimport { loadConfig } from \"@forge-ts/core\";\nimport { DEFAULT_TARGET, getAdapter, type SSGTarget } from \"@forge-ts/gen\";\nimport { defineCommand } from \"citty\";\nimport { createLogger } from \"../logger.js\";\n\n/**\n * Starts the local dev server for the configured SSG target.\n *\n * Reads `gen.ssgTarget` from the forge-ts config, resolves the adapter,\n * and spawns the platform's dev server in the output directory.\n *\n * @param args - Command arguments.\n * @returns A promise that resolves when the server exits.\n *\n * @example\n * ```typescript\n * import { runDocsDev } from \"@forge-ts/cli\";\n * await runDocsDev({ cwd: \"./my-project\" });\n * ```\n * @public\n */\nexport async function runDocsDev(args: {\n\t/** Project root directory. */\n\tcwd?: string;\n\t/** Override the SSG target from config. */\n\ttarget?: string;\n\t/** Port to run the dev server on. */\n\tport?: string;\n}): Promise<void> {\n\tconst logger = createLogger();\n\tconst config = await loadConfig(args.cwd);\n\tconst target = (args.target ?? config.gen.ssgTarget ?? DEFAULT_TARGET) as SSGTarget;\n\tconst adapter = getAdapter(target);\n\tconst outDir = resolve(config.outDir);\n\tconst devCmd = adapter.getDevCommand(outDir);\n\n\tlogger.info(`Starting ${devCmd.label}...`);\n\tlogger.info(` Target: ${target}`);\n\tlogger.info(` Directory: ${outDir}`);\n\tlogger.info(` URL: ${devCmd.url}`);\n\tlogger.info(\"\");\n\n\tconst spawnArgs = [...devCmd.args];\n\tif (args.port) {\n\t\tspawnArgs.push(\"--port\", args.port);\n\t}\n\n\tconst proc = spawn(devCmd.bin, spawnArgs, {\n\t\tcwd: devCmd.cwd,\n\t\tstdio: \"inherit\",\n\t\tshell: true,\n\t});\n\n\treturn new Promise<void>((_resolve, reject) => {\n\t\tproc.on(\"close\", (code) => {\n\t\t\tif (code === 0) {\n\t\t\t\t_resolve();\n\t\t\t} else {\n\t\t\t\treject(new Error(`${devCmd.label} exited with code ${code}`));\n\t\t\t}\n\t\t});\n\t\tproc.on(\"error\", reject);\n\t});\n}\n\n/**\n * Citty command definition for `forge-ts docs dev`.\n *\n * @example\n * ```typescript\n * import { docsDevCommand } from \"@forge-ts/cli\";\n * ```\n * @public\n */\nexport const docsDevCommand = defineCommand({\n\tmeta: {\n\t\tname: \"dev\",\n\t\tdescription: \"Start a local doc preview server\",\n\t},\n\targs: {\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Project root directory\",\n\t\t},\n\t\ttarget: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"SSG target override (reads from config by default)\",\n\t\t},\n\t\tport: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Port for the dev server\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tawait runDocsDev(args);\n\t},\n});\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { loadConfig } from \"@forge-ts/core\";\nimport {\n\ttype AdapterContext,\n\tDEFAULT_TARGET,\n\tgetAdapter,\n\tgetAvailableTargets,\n\ttype SSGTarget,\n} from \"@forge-ts/gen\";\nimport { defineCommand } from \"citty\";\nimport { createLogger } from \"../logger.js\";\nimport {\n\ttype CommandOutput,\n\temitResult,\n\ttype ForgeCliError,\n\ttype OutputFlags,\n\tresolveExitCode,\n} from \"../output.js\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * Result of the `init docs` command.\n *\n * @example\n * ```typescript\n * import { runInitDocs } from \"@forge-ts/cli/commands/init-docs\";\n * const output = await runInitDocs({ target: \"mintlify\" });\n * console.log(output.data.summary.filesCreated); // number of files written\n * ```\n * @public\n */\nexport interface InitDocsResult {\n\t/** Whether the scaffold succeeded. */\n\tsuccess: boolean;\n\t/** The SSG target that was scaffolded. */\n\ttarget: SSGTarget;\n\t/** Summary of what was created. */\n\tsummary: {\n\t\t/** Number of files written to disk. */\n\t\tfilesCreated: number;\n\t\t/** Number of npm dependencies declared by the adapter. */\n\t\tdependencies: number;\n\t\t/** Number of package.json scripts declared by the adapter. */\n\t\tscripts: number;\n\t};\n\t/** Relative paths of all files created. */\n\tfiles: string[];\n\t/** Post-scaffold instructions for the user. */\n\tinstructions: string[];\n}\n\n/**\n * Arguments for the `init docs` command.\n * @internal\n */\nexport interface InitDocsArgs {\n\t/** SSG target to scaffold. Defaults to {@link DEFAULT_TARGET}. */\n\ttarget?: string;\n\t/** Project root directory (default: cwd). */\n\tcwd?: string;\n\t/** Output directory for the doc site (default: outDir from config or ./docs). */\n\toutDir?: string;\n\t/** Overwrite an existing scaffold without prompting. */\n\tforce?: boolean;\n\t/** MVI verbosity level for structured output. */\n\tmvi?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Scaffolds a documentation site for the target SSG platform.\n *\n * Resolves the target from args, validates it, checks for an existing\n * scaffold, calls the adapter's `scaffold()` method, and writes all files\n * produced by the manifest to `outDir`.\n *\n * @param args - CLI arguments for the init docs command.\n * @returns A typed `CommandOutput<InitDocsResult>`.\n * @example\n * ```typescript\n * import { runInitDocs } from \"@forge-ts/cli/commands/init-docs\";\n * const output = await runInitDocs({ target: \"mintlify\", cwd: process.cwd() });\n * console.log(output.data.files); // list of created file paths\n * ```\n * @public\n */\nexport async function runInitDocs(args: InitDocsArgs): Promise<CommandOutput<InitDocsResult>> {\n\tconst start = Date.now();\n\n\t// 1. Resolve target\n\tconst rawTarget = args.target ?? DEFAULT_TARGET;\n\tconst available = getAvailableTargets();\n\tif (!available.includes(rawTarget as SSGTarget)) {\n\t\tconst err: ForgeCliError = {\n\t\t\tcode: \"INIT_UNKNOWN_TARGET\",\n\t\t\tmessage: `Unknown SSG target \"${rawTarget}\". Available targets: ${available.join(\", \")}`,\n\t\t};\n\t\treturn {\n\t\t\toperation: \"init.docs\",\n\t\t\tsuccess: false,\n\t\t\tdata: {\n\t\t\t\tsuccess: false,\n\t\t\t\ttarget: DEFAULT_TARGET,\n\t\t\t\tsummary: { filesCreated: 0, dependencies: 0, scripts: 0 },\n\t\t\t\tfiles: [],\n\t\t\t\tinstructions: [],\n\t\t\t},\n\t\t\terrors: [err],\n\t\t\tduration: Date.now() - start,\n\t\t};\n\t}\n\n\tconst target = rawTarget as SSGTarget;\n\tconst adapter = getAdapter(target);\n\n\t// 2. Load config to resolve outDir\n\tconst config = await loadConfig(args.cwd);\n\tconst outDir = args.outDir ? resolve(args.outDir) : config.outDir;\n\n\t// 3. Safety check: detect existing scaffold\n\tconst alreadyExists = await adapter.detectExisting(outDir);\n\tif (alreadyExists && !args.force) {\n\t\tconst err: ForgeCliError = {\n\t\t\tcode: \"INIT_ALREADY_EXISTS\",\n\t\t\tmessage: `Docs already scaffolded for ${target}. Use --force to overwrite.`,\n\t\t};\n\t\treturn {\n\t\t\toperation: \"init.docs\",\n\t\t\tsuccess: false,\n\t\t\tdata: {\n\t\t\t\tsuccess: false,\n\t\t\t\ttarget,\n\t\t\t\tsummary: { filesCreated: 0, dependencies: 0, scripts: 0 },\n\t\t\t\tfiles: [],\n\t\t\t\tinstructions: [],\n\t\t\t},\n\t\t\terrors: [err],\n\t\t\tduration: Date.now() - start,\n\t\t};\n\t}\n\n\t// 4. Check for cross-target collision (any other adapter already scaffolded)\n\tconst warnings: Array<{ code: string; message: string }> = [];\n\tfor (const otherTarget of available) {\n\t\tif (otherTarget === target) continue;\n\t\tconst otherAdapter = getAdapter(otherTarget as SSGTarget);\n\t\tconst otherExists = await otherAdapter.detectExisting(outDir);\n\t\tif (otherExists) {\n\t\t\twarnings.push({\n\t\t\t\tcode: \"INIT_TARGET_MISMATCH\",\n\t\t\t\tmessage: `Existing scaffold detected for ${otherTarget} but scaffolding for ${target}. Remove conflicting files to avoid issues.`,\n\t\t\t});\n\t\t}\n\t}\n\n\t// 5. Build AdapterContext — use an empty pages/symbols array for init\n\tconst projectName = config.rootDir.split(\"/\").pop() ?? \"Project\";\n\tconst context: AdapterContext = {\n\t\tconfig,\n\t\tprojectName,\n\t\tpages: [],\n\t\tsymbols: [],\n\t\toutDir,\n\t};\n\n\t// 6. Call adapter.scaffold() to get the ScaffoldManifest\n\tconst manifest = adapter.scaffold(context);\n\n\t// 7. Write all files from the manifest\n\tconst writtenFiles: string[] = [];\n\tfor (const file of manifest.files) {\n\t\tconst filePath = join(outDir, file.path);\n\t\tconst fileDir = filePath.substring(0, filePath.lastIndexOf(\"/\"));\n\t\tawait mkdir(fileDir, { recursive: true });\n\t\tawait writeFile(filePath, file.content, \"utf8\");\n\t\twrittenFiles.push(file.path);\n\t}\n\n\tconst depCount =\n\t\tObject.keys(manifest.dependencies).length + Object.keys(manifest.devDependencies).length;\n\tconst scriptCount = Object.keys(manifest.scripts).length;\n\n\tconst data: InitDocsResult = {\n\t\tsuccess: true,\n\t\ttarget,\n\t\tsummary: {\n\t\t\tfilesCreated: writtenFiles.length,\n\t\t\tdependencies: depCount,\n\t\t\tscripts: scriptCount,\n\t\t},\n\t\tfiles: writtenFiles,\n\t\tinstructions: manifest.instructions,\n\t};\n\n\treturn {\n\t\toperation: \"init.docs\",\n\t\tsuccess: true,\n\t\tdata,\n\t\twarnings:\n\t\t\twarnings.length > 0\n\t\t\t\t? warnings.map((w) => ({\n\t\t\t\t\t\tcode: w.code,\n\t\t\t\t\t\tmessage: w.message,\n\t\t\t\t\t\tfilePath: \"\",\n\t\t\t\t\t\tline: 0,\n\t\t\t\t\t\tcolumn: 0,\n\t\t\t\t\t}))\n\t\t\t\t: undefined,\n\t\tduration: Date.now() - start,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Human formatter\n// ---------------------------------------------------------------------------\n\n/**\n * Formats an InitDocsResult as human-readable text.\n * @internal\n */\nfunction formatInitDocsHuman(result: InitDocsResult): string {\n\tconst lines: string[] = [];\n\n\tif (!result.success) {\n\t\treturn \"\";\n\t}\n\n\tconst targetName = result.target.charAt(0).toUpperCase() + result.target.slice(1);\n\tlines.push(`\\n Scaffolding ${targetName} documentation site...\\n`);\n\n\tconst MAX_INLINE = 5;\n\tconst shown = result.files.slice(0, MAX_INLINE);\n\tconst remaining = result.files.length - shown.length;\n\n\tfor (const file of shown) {\n\t\tlines.push(` \\u2713 Created ${file}`);\n\t}\n\n\tif (remaining > 0) {\n\t\tlines.push(` ... (${remaining} more file${remaining !== 1 ? \"s\" : \"\"})`);\n\t}\n\n\tif (result.instructions.length > 0) {\n\t\tlines.push(\"\\n Next steps:\");\n\t\tresult.instructions.forEach((inst, idx) => {\n\t\t\tlines.push(` ${idx + 1}. ${inst}`);\n\t\t});\n\t}\n\n\tlines.push(\n\t\t`\\n ${result.summary.filesCreated} file${result.summary.filesCreated !== 1 ? \"s\" : \"\"} created for ${targetName} doc site.`,\n\t);\n\n\treturn lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// Citty command definition\n// ---------------------------------------------------------------------------\n\n/**\n * Citty command definition for `forge-ts init docs`.\n *\n * Scaffolds a complete documentation site for the target SSG platform.\n * Use `--json` for LAFS JSON envelope output (agent/CI-friendly).\n *\n * @example\n * ```typescript\n * import { initDocsCommand } from \"@forge-ts/cli/commands/init-docs\";\n * // Registered automatically as a subcommand of `forge-ts init`\n * ```\n * @public\n */\nexport const initDocsCommand = defineCommand({\n\tmeta: {\n\t\tname: \"docs\",\n\t\tdescription: \"Scaffold a documentation site\",\n\t},\n\targs: {\n\t\ttarget: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: `SSG target: ${getAvailableTargets().join(\", \")} (default: ${DEFAULT_TARGET})`,\n\t\t},\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Project root directory\",\n\t\t},\n\t\t\"out-dir\": {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Output directory for doc site (default: ./docs)\",\n\t\t},\n\t\tforce: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Overwrite existing scaffold\",\n\t\t\tdefault: false,\n\t\t},\n\t\tjson: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as LAFS JSON envelope\",\n\t\t\tdefault: false,\n\t\t},\n\t\thuman: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as formatted text\",\n\t\t\tdefault: false,\n\t\t},\n\t\tquiet: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Suppress non-essential output\",\n\t\t\tdefault: false,\n\t\t},\n\t\tmvi: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"MVI verbosity level: minimal, standard, full\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst output = await runInitDocs({\n\t\t\ttarget: args.target,\n\t\t\tcwd: args.cwd,\n\t\t\toutDir: args[\"out-dir\"],\n\t\t\tforce: args.force,\n\t\t\tmvi: args.mvi,\n\t\t});\n\n\t\tconst flags: OutputFlags = {\n\t\t\tjson: args.json,\n\t\t\thuman: args.human,\n\t\t\tquiet: args.quiet,\n\t\t\tmvi: args.mvi,\n\t\t};\n\n\t\temitResult(output, flags, (data, cmd) => {\n\t\t\tif (!cmd.success) {\n\t\t\t\tconst logger = createLogger();\n\t\t\t\tconst msg = cmd.errors?.[0]?.message ?? \"Scaffold failed\";\n\t\t\t\tlogger.error(msg);\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t\treturn formatInitDocsHuman(data);\n\t\t});\n\n\t\tprocess.exit(resolveExitCode(output));\n\t},\n});\n\n// ---------------------------------------------------------------------------\n// Parent \"init\" command that exposes `forge-ts init docs`\n// ---------------------------------------------------------------------------\n\n/**\n * Citty command definition for `forge-ts init`.\n *\n * Exposes subcommands for scaffolding project artefacts.\n *\n * @example\n * ```typescript\n * import { initCommand } from \"@forge-ts/cli/commands/init-docs\";\n * // Registered automatically as a subcommand of `forge-ts`\n * ```\n * @public\n */\nexport const initCommand = defineCommand({\n\tmeta: {\n\t\tname: \"init\",\n\t\tdescription: \"Scaffold project artefacts\",\n\t},\n\tsubCommands: {\n\t\tdocs: initDocsCommand,\n\t},\n});\n","import { loadConfig } from \"@forge-ts/core\";\nimport { doctest } from \"@forge-ts/doctest\";\nimport { defineCommand } from \"citty\";\nimport { type CommandOutput, emitResult, type OutputFlags, resolveExitCode } from \"../output.js\";\n\n/**\n * Arguments for the `test` command.\n * @internal\n */\nexport interface TestArgs {\n\t/** Project root directory (default: cwd). */\n\tcwd?: string;\n\t/** MVI verbosity level for structured output. */\n\tmvi?: string;\n}\n\n/**\n * A single test failure entry, included at standard and full MVI levels.\n * @public\n */\nexport interface TestFailure {\n\t/** Symbol name where the doctest failed. */\n\tsymbol: string;\n\t/** Absolute path to the source file. */\n\tfile: string;\n\t/** 1-based line number of the failing example. */\n\tline: number;\n\t/** Human-readable failure message. */\n\tmessage: string;\n}\n\n/**\n * Typed result for the `test` command.\n * @public\n */\nexport interface TestResult {\n\t/** Whether all doctests passed. */\n\tsuccess: boolean;\n\t/** Aggregate counts — always present regardless of MVI level. */\n\tsummary: {\n\t\t/** Number of passing doctests. */\n\t\tpassed: number;\n\t\t/** Number of failing doctests. */\n\t\tfailed: number;\n\t\t/** Total doctests run. */\n\t\ttotal: number;\n\t\t/** Wall-clock duration in milliseconds. */\n\t\tduration: number;\n\t};\n\t/** Per-failure details — present at standard and full MVI levels. */\n\tfailures?: TestFailure[];\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Runs the doctest pipeline and returns a typed command output.\n *\n * @param args - CLI arguments for the test command.\n * @returns A typed `CommandOutput<TestResult>`.\n * @example\n * ```typescript\n * import { runTest } from \"@forge-ts/cli/commands/test\";\n * const output = await runTest({ cwd: process.cwd() });\n * console.log(output.data.summary.passed); // number of passing doctests\n * ```\n * @public\n */\nexport async function runTest(args: TestArgs): Promise<CommandOutput<TestResult>> {\n\tconst config = await loadConfig(args.cwd);\n\tconst result = await doctest(config);\n\tconst mviLevel = args.mvi ?? \"standard\";\n\n\tconst failCount = result.errors.length;\n\tconst totalSymbols = result.symbols.length;\n\tconst passCount = totalSymbols - failCount > 0 ? totalSymbols - failCount : 0;\n\n\tconst summary = {\n\t\tpassed: passCount,\n\t\tfailed: failCount,\n\t\ttotal: totalSymbols,\n\t\tduration: result.duration,\n\t};\n\n\tconst data: TestResult = { success: result.success, summary };\n\n\tif (mviLevel !== \"minimal\") {\n\t\tdata.failures = result.errors.map((e) => ({\n\t\t\tsymbol: e.symbolName ?? \"\",\n\t\t\tfile: e.filePath ?? \"\",\n\t\t\tline: e.line,\n\t\t\tmessage: e.message,\n\t\t}));\n\t}\n\n\treturn {\n\t\toperation: \"test\",\n\t\tsuccess: result.success,\n\t\tdata,\n\t\tduration: result.duration,\n\t};\n}\n\n/**\n * Citty command definition for `forge-ts test`.\n * @public\n */\nexport const testCommand = defineCommand({\n\tmeta: {\n\t\tname: \"test\",\n\t\tdescription: \"Run @example blocks as doctests\",\n\t},\n\targs: {\n\t\tcwd: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"Project root directory\",\n\t\t},\n\t\tjson: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as LAFS JSON envelope (agent-friendly)\",\n\t\t\tdefault: false,\n\t\t},\n\t\thuman: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Output as formatted text (default for TTY)\",\n\t\t\tdefault: false,\n\t\t},\n\t\tquiet: {\n\t\t\ttype: \"boolean\",\n\t\t\tdescription: \"Suppress non-essential output\",\n\t\t\tdefault: false,\n\t\t},\n\t\tmvi: {\n\t\t\ttype: \"string\",\n\t\t\tdescription: \"MVI verbosity level: minimal, standard, full\",\n\t\t},\n\t},\n\tasync run({ args }) {\n\t\tconst output = await runTest({ cwd: args.cwd, mvi: args.mvi });\n\n\t\tconst flags: OutputFlags = {\n\t\t\tjson: args.json,\n\t\t\thuman: args.human,\n\t\t\tquiet: args.quiet,\n\t\t\tmvi: args.mvi,\n\t\t};\n\n\t\temitResult(output, flags, (data) => {\n\t\t\tif (output.success) {\n\t\t\t\treturn `forge-ts test: all doctests passed. (${data.summary.duration}ms)`;\n\t\t\t}\n\t\t\tconst lines: string[] = [];\n\t\t\tfor (const f of data.failures ?? []) {\n\t\t\t\tlines.push(f.message);\n\t\t\t}\n\t\t\tlines.push(`forge-ts test: ${data.summary.failed} failure(s). (${data.summary.duration}ms)`);\n\t\t\treturn lines.join(\"\\n\");\n\t\t});\n\n\t\tprocess.exit(resolveExitCode(output));\n\t},\n});\n"],"mappings":"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","names":["defineCommand","loadConfig","defineCommand","loadConfig","defineCommand","loadConfig","defineCommand","loadConfig","defineCommand","join","resolve","loadConfig","DEFAULT_TARGET","getAdapter","defineCommand","DEFAULT_TARGET","getAdapter","loadConfig","resolve","join","defineCommand","loadConfig","defineCommand","loadConfig","defineCommand","defineCommand"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forge-ts/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI entry point for forge-ts",
|
|
6
6
|
"license": "MIT",
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@cleocode/lafs-protocol": "^1.7.0",
|
|
31
31
|
"citty": "^0.2.1",
|
|
32
|
-
"@forge-ts/api": "0.
|
|
33
|
-
"@forge-ts/
|
|
34
|
-
"@forge-ts/
|
|
35
|
-
"@forge-ts/
|
|
36
|
-
"@forge-ts/gen": "0.
|
|
32
|
+
"@forge-ts/api": "0.6.0",
|
|
33
|
+
"@forge-ts/doctest": "0.6.0",
|
|
34
|
+
"@forge-ts/core": "0.6.0",
|
|
35
|
+
"@forge-ts/enforcer": "0.6.0",
|
|
36
|
+
"@forge-ts/gen": "0.6.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"tsup": "^8.3.5",
|