@forge-ts/cli 0.2.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/LICENSE +21 -0
- package/dist/index.d.ts +218 -0
- package/dist/index.js +488 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 forge-ts contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import * as citty from 'citty';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Central output layer for forge-ts CLI.
|
|
5
|
+
*
|
|
6
|
+
* Wraps all command results in LAFS envelopes for agent-first output, while
|
|
7
|
+
* preserving human-readable formatting for TTY consumers.
|
|
8
|
+
*
|
|
9
|
+
* @packageDocumentation
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
/** Typed result from a forge-ts command. */
|
|
13
|
+
interface CommandOutput<T> {
|
|
14
|
+
operation: string;
|
|
15
|
+
success: boolean;
|
|
16
|
+
data: T;
|
|
17
|
+
errors?: ForgeCliError[];
|
|
18
|
+
warnings?: ForgeCliWarning[];
|
|
19
|
+
duration?: number;
|
|
20
|
+
}
|
|
21
|
+
/** Structured error for CLI commands. */
|
|
22
|
+
interface ForgeCliError {
|
|
23
|
+
code: string;
|
|
24
|
+
message: string;
|
|
25
|
+
filePath?: string;
|
|
26
|
+
line?: number;
|
|
27
|
+
column?: number;
|
|
28
|
+
}
|
|
29
|
+
/** Structured warning for CLI commands. */
|
|
30
|
+
interface ForgeCliWarning {
|
|
31
|
+
code: string;
|
|
32
|
+
message: string;
|
|
33
|
+
filePath?: string;
|
|
34
|
+
line?: number;
|
|
35
|
+
column?: number;
|
|
36
|
+
}
|
|
37
|
+
/** Output format flags passed through from citty args. */
|
|
38
|
+
interface OutputFlags {
|
|
39
|
+
json?: boolean;
|
|
40
|
+
human?: boolean;
|
|
41
|
+
quiet?: boolean;
|
|
42
|
+
mvi?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Wraps a command result in a LAFS envelope and emits it.
|
|
46
|
+
*
|
|
47
|
+
* - JSON mode: writes the projected envelope to stdout as JSON.
|
|
48
|
+
* - Human mode: calls the provided formatter function.
|
|
49
|
+
* - Quiet mode: suppresses all output regardless of format.
|
|
50
|
+
*
|
|
51
|
+
* @param output - Typed result from the command.
|
|
52
|
+
* @param flags - Output format flags from citty args.
|
|
53
|
+
* @param humanFormatter - Produces a human-readable string for TTY consumers.
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
declare function emitResult<T>(output: CommandOutput<T>, flags: OutputFlags, humanFormatter: (data: T, output: CommandOutput<T>) => string): void;
|
|
57
|
+
/**
|
|
58
|
+
* Returns the LAFS-compliant exit code for a command output.
|
|
59
|
+
*
|
|
60
|
+
* @param output - Typed result from the command.
|
|
61
|
+
* @returns `0` on success, `1` on validation/check failure.
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
declare function resolveExitCode(output: CommandOutput<unknown>): number;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Citty command definition for `forge-ts build`.
|
|
68
|
+
* @public
|
|
69
|
+
*/
|
|
70
|
+
declare const buildCommand: citty.CommandDef<{
|
|
71
|
+
readonly cwd: {
|
|
72
|
+
readonly type: "string";
|
|
73
|
+
readonly description: "Project root directory";
|
|
74
|
+
};
|
|
75
|
+
readonly "skip-api": {
|
|
76
|
+
readonly type: "boolean";
|
|
77
|
+
readonly description: "Skip OpenAPI generation";
|
|
78
|
+
readonly default: false;
|
|
79
|
+
};
|
|
80
|
+
readonly "skip-gen": {
|
|
81
|
+
readonly type: "boolean";
|
|
82
|
+
readonly description: "Skip doc generation";
|
|
83
|
+
readonly default: false;
|
|
84
|
+
};
|
|
85
|
+
readonly json: {
|
|
86
|
+
readonly type: "boolean";
|
|
87
|
+
readonly description: "Output as LAFS JSON envelope (agent-friendly)";
|
|
88
|
+
readonly default: false;
|
|
89
|
+
};
|
|
90
|
+
readonly human: {
|
|
91
|
+
readonly type: "boolean";
|
|
92
|
+
readonly description: "Output as formatted text (default for TTY)";
|
|
93
|
+
readonly default: false;
|
|
94
|
+
};
|
|
95
|
+
readonly quiet: {
|
|
96
|
+
readonly type: "boolean";
|
|
97
|
+
readonly description: "Suppress non-essential output";
|
|
98
|
+
readonly default: false;
|
|
99
|
+
};
|
|
100
|
+
readonly mvi: {
|
|
101
|
+
readonly type: "string";
|
|
102
|
+
readonly description: "MVI verbosity level: minimal, standard, full";
|
|
103
|
+
};
|
|
104
|
+
}>;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Citty command definition for `forge-ts check`.
|
|
108
|
+
* @public
|
|
109
|
+
*/
|
|
110
|
+
declare const checkCommand: citty.CommandDef<{
|
|
111
|
+
readonly cwd: {
|
|
112
|
+
readonly type: "string";
|
|
113
|
+
readonly description: "Project root directory";
|
|
114
|
+
};
|
|
115
|
+
readonly strict: {
|
|
116
|
+
readonly type: "boolean";
|
|
117
|
+
readonly description: "Treat warnings as errors";
|
|
118
|
+
readonly default: false;
|
|
119
|
+
};
|
|
120
|
+
readonly verbose: {
|
|
121
|
+
readonly type: "boolean";
|
|
122
|
+
readonly description: "Show detailed output";
|
|
123
|
+
readonly default: false;
|
|
124
|
+
};
|
|
125
|
+
readonly json: {
|
|
126
|
+
readonly type: "boolean";
|
|
127
|
+
readonly description: "Output as LAFS JSON envelope (agent-friendly)";
|
|
128
|
+
readonly default: false;
|
|
129
|
+
};
|
|
130
|
+
readonly human: {
|
|
131
|
+
readonly type: "boolean";
|
|
132
|
+
readonly description: "Output as formatted text (default for TTY)";
|
|
133
|
+
readonly default: false;
|
|
134
|
+
};
|
|
135
|
+
readonly quiet: {
|
|
136
|
+
readonly type: "boolean";
|
|
137
|
+
readonly description: "Suppress non-essential output";
|
|
138
|
+
readonly default: false;
|
|
139
|
+
};
|
|
140
|
+
readonly mvi: {
|
|
141
|
+
readonly type: "string";
|
|
142
|
+
readonly description: "MVI verbosity level: minimal, standard, full";
|
|
143
|
+
};
|
|
144
|
+
}>;
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Citty command definition for `forge-ts test`.
|
|
148
|
+
* @public
|
|
149
|
+
*/
|
|
150
|
+
declare const testCommand: citty.CommandDef<{
|
|
151
|
+
readonly cwd: {
|
|
152
|
+
readonly type: "string";
|
|
153
|
+
readonly description: "Project root directory";
|
|
154
|
+
};
|
|
155
|
+
readonly json: {
|
|
156
|
+
readonly type: "boolean";
|
|
157
|
+
readonly description: "Output as LAFS JSON envelope (agent-friendly)";
|
|
158
|
+
readonly default: false;
|
|
159
|
+
};
|
|
160
|
+
readonly human: {
|
|
161
|
+
readonly type: "boolean";
|
|
162
|
+
readonly description: "Output as formatted text (default for TTY)";
|
|
163
|
+
readonly default: false;
|
|
164
|
+
};
|
|
165
|
+
readonly quiet: {
|
|
166
|
+
readonly type: "boolean";
|
|
167
|
+
readonly description: "Suppress non-essential output";
|
|
168
|
+
readonly default: false;
|
|
169
|
+
};
|
|
170
|
+
readonly mvi: {
|
|
171
|
+
readonly type: "string";
|
|
172
|
+
readonly description: "MVI verbosity level: minimal, standard, full";
|
|
173
|
+
};
|
|
174
|
+
}>;
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Simple TTY-aware logger for forge-ts CLI output.
|
|
178
|
+
*
|
|
179
|
+
* Uses ANSI escape codes directly — no external colour library.
|
|
180
|
+
*
|
|
181
|
+
* @packageDocumentation
|
|
182
|
+
* @internal
|
|
183
|
+
*/
|
|
184
|
+
/**
|
|
185
|
+
* A minimal structured logger used throughout the CLI commands.
|
|
186
|
+
* @internal
|
|
187
|
+
*/
|
|
188
|
+
interface Logger {
|
|
189
|
+
/** Print an informational message. */
|
|
190
|
+
info(msg: string): void;
|
|
191
|
+
/** Print a success message (green ✓ prefix when colours are on). */
|
|
192
|
+
success(msg: string): void;
|
|
193
|
+
/** Print a warning message (yellow prefix when colours are on). */
|
|
194
|
+
warn(msg: string): void;
|
|
195
|
+
/** Print an error message (red ✗ prefix when colours are on). */
|
|
196
|
+
error(msg: string): void;
|
|
197
|
+
/**
|
|
198
|
+
* Print a build-step line.
|
|
199
|
+
*
|
|
200
|
+
* @param label - Short category label (e.g. "API", "Gen").
|
|
201
|
+
* @param detail - Description of what was produced.
|
|
202
|
+
* @param duration - Optional wall-clock time in milliseconds.
|
|
203
|
+
*/
|
|
204
|
+
step(label: string, detail: string, duration?: number): void;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Creates a {@link Logger} instance.
|
|
208
|
+
*
|
|
209
|
+
* @param options - Optional configuration.
|
|
210
|
+
* @param options.colors - Emit ANSI colour codes. Defaults to `process.stdout.isTTY`.
|
|
211
|
+
* @returns A configured logger.
|
|
212
|
+
* @internal
|
|
213
|
+
*/
|
|
214
|
+
declare function createLogger(options?: {
|
|
215
|
+
colors?: boolean;
|
|
216
|
+
}): Logger;
|
|
217
|
+
|
|
218
|
+
export { type CommandOutput, type ForgeCliError, type ForgeCliWarning, type Logger, type OutputFlags, buildCommand, checkCommand, createLogger, emitResult, resolveExitCode, testCommand };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { defineCommand as defineCommand4, runMain } from "citty";
|
|
5
|
+
|
|
6
|
+
// src/commands/build.ts
|
|
7
|
+
import { generateApi } from "@codluv/forge-api";
|
|
8
|
+
import { loadConfig } from "@codluv/forge-core";
|
|
9
|
+
import { generate } from "@codluv/forge-gen";
|
|
10
|
+
import { defineCommand } from "citty";
|
|
11
|
+
|
|
12
|
+
// src/logger.ts
|
|
13
|
+
var GREEN = "\x1B[32m";
|
|
14
|
+
var YELLOW = "\x1B[33m";
|
|
15
|
+
var RED = "\x1B[31m";
|
|
16
|
+
var BOLD = "\x1B[1m";
|
|
17
|
+
var RESET = "\x1B[0m";
|
|
18
|
+
function createLogger(options) {
|
|
19
|
+
const useColors = options?.colors ?? process.stdout.isTTY ?? false;
|
|
20
|
+
function colorize(text, code) {
|
|
21
|
+
return useColors ? `${code}${text}${RESET}` : text;
|
|
22
|
+
}
|
|
23
|
+
function bold(text) {
|
|
24
|
+
return useColors ? `${BOLD}${text}${RESET}` : text;
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
info(msg) {
|
|
28
|
+
console.log(msg);
|
|
29
|
+
},
|
|
30
|
+
success(msg) {
|
|
31
|
+
const prefix = colorize("\u2713", GREEN);
|
|
32
|
+
console.log(`${prefix} ${msg}`);
|
|
33
|
+
},
|
|
34
|
+
warn(msg) {
|
|
35
|
+
const prefix = colorize("warn", YELLOW);
|
|
36
|
+
console.warn(`${bold(prefix)} ${msg}`);
|
|
37
|
+
},
|
|
38
|
+
error(msg) {
|
|
39
|
+
const prefix = colorize("error", RED);
|
|
40
|
+
console.error(`${bold(prefix)} ${msg}`);
|
|
41
|
+
},
|
|
42
|
+
step(label, detail, duration) {
|
|
43
|
+
const check = colorize("\u2713", GREEN);
|
|
44
|
+
const durationStr = duration !== void 0 ? ` (${duration}ms)` : "";
|
|
45
|
+
console.log(` ${check} ${bold(label)}: ${detail}${durationStr}`);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/output.ts
|
|
51
|
+
import { randomUUID } from "crypto";
|
|
52
|
+
import {
|
|
53
|
+
createEnvelope,
|
|
54
|
+
projectEnvelope,
|
|
55
|
+
resolveFlags
|
|
56
|
+
} from "@cleocode/lafs-protocol";
|
|
57
|
+
function emitResult(output, flags, humanFormatter) {
|
|
58
|
+
const flagInput = {
|
|
59
|
+
json: flags.json,
|
|
60
|
+
human: flags.human,
|
|
61
|
+
quiet: flags.quiet,
|
|
62
|
+
mvi: flags.mvi
|
|
63
|
+
};
|
|
64
|
+
const resolved = resolveFlags(flagInput);
|
|
65
|
+
const format = resolved.format.format;
|
|
66
|
+
const quiet = resolved.format.quiet;
|
|
67
|
+
if (quiet) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const envelope = createEnvelope(
|
|
71
|
+
output.success ? {
|
|
72
|
+
success: true,
|
|
73
|
+
result: output.data,
|
|
74
|
+
meta: {
|
|
75
|
+
operation: `forge-ts.${output.operation}`,
|
|
76
|
+
requestId: randomUUID(),
|
|
77
|
+
transport: "cli",
|
|
78
|
+
mvi: flags.mvi ?? "standard"
|
|
79
|
+
}
|
|
80
|
+
} : {
|
|
81
|
+
success: false,
|
|
82
|
+
error: {
|
|
83
|
+
code: output.errors?.[0]?.code ?? "FORGE_ERROR",
|
|
84
|
+
message: output.errors?.[0]?.message ?? "Command failed",
|
|
85
|
+
category: "VALIDATION",
|
|
86
|
+
retryable: false,
|
|
87
|
+
retryAfterMs: null,
|
|
88
|
+
details: {
|
|
89
|
+
errors: output.errors ?? [],
|
|
90
|
+
warnings: output.warnings ?? []
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
meta: {
|
|
94
|
+
operation: `forge-ts.${output.operation}`,
|
|
95
|
+
requestId: randomUUID(),
|
|
96
|
+
transport: "cli",
|
|
97
|
+
mvi: flags.mvi ?? "standard"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
if (format === "json") {
|
|
102
|
+
const mviLevel = flags.mvi ?? "standard";
|
|
103
|
+
const projected = projectEnvelope(envelope, mviLevel);
|
|
104
|
+
process.stdout.write(`${JSON.stringify(projected, null, 2)}
|
|
105
|
+
`);
|
|
106
|
+
} else {
|
|
107
|
+
const formatted = humanFormatter(output.data, output);
|
|
108
|
+
if (formatted) {
|
|
109
|
+
console.log(formatted);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function resolveExitCode(output) {
|
|
114
|
+
if (output.success) return 0;
|
|
115
|
+
return 1;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/commands/build.ts
|
|
119
|
+
async function runBuild(args) {
|
|
120
|
+
const config = await loadConfig(args.cwd);
|
|
121
|
+
const buildStart = Date.now();
|
|
122
|
+
const steps = [];
|
|
123
|
+
const allErrors = [];
|
|
124
|
+
let success = true;
|
|
125
|
+
if (config.api.enabled && !args.skipApi) {
|
|
126
|
+
const result = await generateApi(config);
|
|
127
|
+
if (!result.success) {
|
|
128
|
+
const errors = result.errors.map((e) => ({
|
|
129
|
+
code: e.code,
|
|
130
|
+
message: e.message,
|
|
131
|
+
filePath: e.filePath,
|
|
132
|
+
line: e.line,
|
|
133
|
+
column: e.column
|
|
134
|
+
}));
|
|
135
|
+
allErrors.push(...errors);
|
|
136
|
+
success = false;
|
|
137
|
+
steps.push({
|
|
138
|
+
name: "api",
|
|
139
|
+
status: "failed",
|
|
140
|
+
outputPath: config.api.openapiPath,
|
|
141
|
+
duration: result.duration,
|
|
142
|
+
errors
|
|
143
|
+
});
|
|
144
|
+
} else {
|
|
145
|
+
steps.push({
|
|
146
|
+
name: "api",
|
|
147
|
+
status: "success",
|
|
148
|
+
outputPath: config.api.openapiPath,
|
|
149
|
+
duration: result.duration
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
} else if (!config.api.enabled || args.skipApi) {
|
|
153
|
+
steps.push({ name: "api", status: "skipped" });
|
|
154
|
+
}
|
|
155
|
+
if (config.gen.enabled && !args.skipGen) {
|
|
156
|
+
const result = await generate(config);
|
|
157
|
+
if (!result.success) {
|
|
158
|
+
const errors = result.errors.map((e) => ({
|
|
159
|
+
code: e.code,
|
|
160
|
+
message: e.message,
|
|
161
|
+
filePath: e.filePath,
|
|
162
|
+
line: e.line,
|
|
163
|
+
column: e.column
|
|
164
|
+
}));
|
|
165
|
+
allErrors.push(...errors);
|
|
166
|
+
success = false;
|
|
167
|
+
steps.push({
|
|
168
|
+
name: "gen",
|
|
169
|
+
status: "failed",
|
|
170
|
+
duration: result.duration,
|
|
171
|
+
errors
|
|
172
|
+
});
|
|
173
|
+
} else {
|
|
174
|
+
steps.push({
|
|
175
|
+
name: "gen",
|
|
176
|
+
status: "success",
|
|
177
|
+
duration: result.duration
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
} else if (!config.gen.enabled || args.skipGen) {
|
|
181
|
+
steps.push({ name: "gen", status: "skipped" });
|
|
182
|
+
}
|
|
183
|
+
const totalMs = Date.now() - buildStart;
|
|
184
|
+
const data = { steps, duration: totalMs };
|
|
185
|
+
return {
|
|
186
|
+
operation: "build",
|
|
187
|
+
success,
|
|
188
|
+
data,
|
|
189
|
+
errors: allErrors,
|
|
190
|
+
duration: totalMs
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
var buildCommand = defineCommand({
|
|
194
|
+
meta: {
|
|
195
|
+
name: "build",
|
|
196
|
+
description: "Generate API reference and documentation"
|
|
197
|
+
},
|
|
198
|
+
args: {
|
|
199
|
+
cwd: {
|
|
200
|
+
type: "string",
|
|
201
|
+
description: "Project root directory"
|
|
202
|
+
},
|
|
203
|
+
"skip-api": {
|
|
204
|
+
type: "boolean",
|
|
205
|
+
description: "Skip OpenAPI generation",
|
|
206
|
+
default: false
|
|
207
|
+
},
|
|
208
|
+
"skip-gen": {
|
|
209
|
+
type: "boolean",
|
|
210
|
+
description: "Skip doc generation",
|
|
211
|
+
default: false
|
|
212
|
+
},
|
|
213
|
+
json: {
|
|
214
|
+
type: "boolean",
|
|
215
|
+
description: "Output as LAFS JSON envelope (agent-friendly)",
|
|
216
|
+
default: false
|
|
217
|
+
},
|
|
218
|
+
human: {
|
|
219
|
+
type: "boolean",
|
|
220
|
+
description: "Output as formatted text (default for TTY)",
|
|
221
|
+
default: false
|
|
222
|
+
},
|
|
223
|
+
quiet: {
|
|
224
|
+
type: "boolean",
|
|
225
|
+
description: "Suppress non-essential output",
|
|
226
|
+
default: false
|
|
227
|
+
},
|
|
228
|
+
mvi: {
|
|
229
|
+
type: "string",
|
|
230
|
+
description: "MVI verbosity level: minimal, standard, full"
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
async run({ args }) {
|
|
234
|
+
const output = await runBuild({
|
|
235
|
+
cwd: args.cwd,
|
|
236
|
+
skipApi: args["skip-api"],
|
|
237
|
+
skipGen: args["skip-gen"]
|
|
238
|
+
});
|
|
239
|
+
const flags = {
|
|
240
|
+
json: args.json,
|
|
241
|
+
human: args.human,
|
|
242
|
+
quiet: args.quiet,
|
|
243
|
+
mvi: args.mvi
|
|
244
|
+
};
|
|
245
|
+
emitResult(output, flags, (data) => {
|
|
246
|
+
const logger = createLogger();
|
|
247
|
+
for (const step of data.steps) {
|
|
248
|
+
if (step.status === "failed") {
|
|
249
|
+
for (const err of step.errors ?? []) {
|
|
250
|
+
logger.error(`[${step.name}] ${err.message}`);
|
|
251
|
+
}
|
|
252
|
+
} else if (step.status === "success") {
|
|
253
|
+
const detail = step.name === "api" && step.outputPath != null ? `Generated OpenAPI spec \u2192 ${step.outputPath}` : `Step complete`;
|
|
254
|
+
logger.step(step.name.toUpperCase(), detail, step.duration);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (output.success) {
|
|
258
|
+
return ` Done in ${data.duration}ms`;
|
|
259
|
+
}
|
|
260
|
+
return "";
|
|
261
|
+
});
|
|
262
|
+
process.exit(resolveExitCode(output));
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// src/commands/check.ts
|
|
267
|
+
import { loadConfig as loadConfig2 } from "@codluv/forge-core";
|
|
268
|
+
import { enforce } from "@codluv/forge-enforcer";
|
|
269
|
+
import { defineCommand as defineCommand2 } from "citty";
|
|
270
|
+
async function runCheck(args) {
|
|
271
|
+
const config = await loadConfig2(args.cwd);
|
|
272
|
+
if (args.strict !== void 0) {
|
|
273
|
+
config.enforce.strict = args.strict;
|
|
274
|
+
}
|
|
275
|
+
const result = await enforce(config);
|
|
276
|
+
const errors = result.errors.map((e) => ({
|
|
277
|
+
code: e.code,
|
|
278
|
+
message: e.message,
|
|
279
|
+
filePath: e.filePath,
|
|
280
|
+
line: e.line,
|
|
281
|
+
column: e.column
|
|
282
|
+
}));
|
|
283
|
+
const warnings = result.warnings.map((w) => ({
|
|
284
|
+
code: w.code,
|
|
285
|
+
message: w.message,
|
|
286
|
+
filePath: w.filePath,
|
|
287
|
+
line: w.line,
|
|
288
|
+
column: w.column
|
|
289
|
+
}));
|
|
290
|
+
const data = {
|
|
291
|
+
symbolCount: result.symbols.length,
|
|
292
|
+
errorCount: errors.length,
|
|
293
|
+
warningCount: warnings.length,
|
|
294
|
+
errors,
|
|
295
|
+
warnings,
|
|
296
|
+
duration: result.duration
|
|
297
|
+
};
|
|
298
|
+
return {
|
|
299
|
+
operation: "check",
|
|
300
|
+
success: result.success,
|
|
301
|
+
data,
|
|
302
|
+
errors,
|
|
303
|
+
warnings,
|
|
304
|
+
duration: result.duration
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
var checkCommand = defineCommand2({
|
|
308
|
+
meta: {
|
|
309
|
+
name: "check",
|
|
310
|
+
description: "Lint TSDoc coverage on exported symbols"
|
|
311
|
+
},
|
|
312
|
+
args: {
|
|
313
|
+
cwd: {
|
|
314
|
+
type: "string",
|
|
315
|
+
description: "Project root directory"
|
|
316
|
+
},
|
|
317
|
+
strict: {
|
|
318
|
+
type: "boolean",
|
|
319
|
+
description: "Treat warnings as errors",
|
|
320
|
+
default: false
|
|
321
|
+
},
|
|
322
|
+
verbose: {
|
|
323
|
+
type: "boolean",
|
|
324
|
+
description: "Show detailed output",
|
|
325
|
+
default: false
|
|
326
|
+
},
|
|
327
|
+
json: {
|
|
328
|
+
type: "boolean",
|
|
329
|
+
description: "Output as LAFS JSON envelope (agent-friendly)",
|
|
330
|
+
default: false
|
|
331
|
+
},
|
|
332
|
+
human: {
|
|
333
|
+
type: "boolean",
|
|
334
|
+
description: "Output as formatted text (default for TTY)",
|
|
335
|
+
default: false
|
|
336
|
+
},
|
|
337
|
+
quiet: {
|
|
338
|
+
type: "boolean",
|
|
339
|
+
description: "Suppress non-essential output",
|
|
340
|
+
default: false
|
|
341
|
+
},
|
|
342
|
+
mvi: {
|
|
343
|
+
type: "string",
|
|
344
|
+
description: "MVI verbosity level: minimal, standard, full"
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
async run({ args }) {
|
|
348
|
+
const output = await runCheck({
|
|
349
|
+
cwd: args.cwd,
|
|
350
|
+
strict: args.strict,
|
|
351
|
+
verbose: args.verbose
|
|
352
|
+
});
|
|
353
|
+
const flags = {
|
|
354
|
+
json: args.json,
|
|
355
|
+
human: args.human,
|
|
356
|
+
quiet: args.quiet,
|
|
357
|
+
mvi: args.mvi
|
|
358
|
+
};
|
|
359
|
+
emitResult(output, flags, (_data, cmd) => {
|
|
360
|
+
const lines = [];
|
|
361
|
+
for (const err of cmd.errors ?? []) {
|
|
362
|
+
const loc = err.filePath != null ? `${err.filePath}:${err.line ?? 0}:${err.column ?? 0}` : "";
|
|
363
|
+
lines.push(loc ? `${loc} \u2014 ${err.message}` : err.message);
|
|
364
|
+
}
|
|
365
|
+
if (lines.length > 0) {
|
|
366
|
+
lines.push(
|
|
367
|
+
`
|
|
368
|
+
${cmd.data.errorCount} error(s), ${cmd.data.warningCount} warning(s) in ${cmd.data.duration}ms`
|
|
369
|
+
);
|
|
370
|
+
} else {
|
|
371
|
+
lines.push(
|
|
372
|
+
`forge-ts check: ${cmd.data.symbolCount} symbol(s) checked. (${cmd.data.duration}ms)`
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
return lines.join("\n");
|
|
376
|
+
});
|
|
377
|
+
process.exit(resolveExitCode(output));
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// src/commands/test.ts
|
|
382
|
+
import { loadConfig as loadConfig3 } from "@codluv/forge-core";
|
|
383
|
+
import { doctest } from "@codluv/forge-doctest";
|
|
384
|
+
import { defineCommand as defineCommand3 } from "citty";
|
|
385
|
+
async function runTest(args) {
|
|
386
|
+
const config = await loadConfig3(args.cwd);
|
|
387
|
+
const result = await doctest(config);
|
|
388
|
+
const failures = result.errors.map((e) => ({
|
|
389
|
+
code: e.code,
|
|
390
|
+
message: e.message,
|
|
391
|
+
filePath: e.filePath,
|
|
392
|
+
line: e.line,
|
|
393
|
+
column: e.column
|
|
394
|
+
}));
|
|
395
|
+
const failCount = failures.length;
|
|
396
|
+
const totalSymbols = result.symbols.length;
|
|
397
|
+
const passCount = totalSymbols - failCount > 0 ? totalSymbols - failCount : 0;
|
|
398
|
+
const data = {
|
|
399
|
+
passed: passCount,
|
|
400
|
+
failed: failCount,
|
|
401
|
+
total: totalSymbols,
|
|
402
|
+
duration: result.duration,
|
|
403
|
+
failures
|
|
404
|
+
};
|
|
405
|
+
return {
|
|
406
|
+
operation: "test",
|
|
407
|
+
success: result.success,
|
|
408
|
+
data,
|
|
409
|
+
errors: failures,
|
|
410
|
+
duration: result.duration
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
var testCommand = defineCommand3({
|
|
414
|
+
meta: {
|
|
415
|
+
name: "test",
|
|
416
|
+
description: "Run @example blocks as doctests"
|
|
417
|
+
},
|
|
418
|
+
args: {
|
|
419
|
+
cwd: {
|
|
420
|
+
type: "string",
|
|
421
|
+
description: "Project root directory"
|
|
422
|
+
},
|
|
423
|
+
json: {
|
|
424
|
+
type: "boolean",
|
|
425
|
+
description: "Output as LAFS JSON envelope (agent-friendly)",
|
|
426
|
+
default: false
|
|
427
|
+
},
|
|
428
|
+
human: {
|
|
429
|
+
type: "boolean",
|
|
430
|
+
description: "Output as formatted text (default for TTY)",
|
|
431
|
+
default: false
|
|
432
|
+
},
|
|
433
|
+
quiet: {
|
|
434
|
+
type: "boolean",
|
|
435
|
+
description: "Suppress non-essential output",
|
|
436
|
+
default: false
|
|
437
|
+
},
|
|
438
|
+
mvi: {
|
|
439
|
+
type: "string",
|
|
440
|
+
description: "MVI verbosity level: minimal, standard, full"
|
|
441
|
+
}
|
|
442
|
+
},
|
|
443
|
+
async run({ args }) {
|
|
444
|
+
const output = await runTest({ cwd: args.cwd });
|
|
445
|
+
const flags = {
|
|
446
|
+
json: args.json,
|
|
447
|
+
human: args.human,
|
|
448
|
+
quiet: args.quiet,
|
|
449
|
+
mvi: args.mvi
|
|
450
|
+
};
|
|
451
|
+
emitResult(output, flags, (data) => {
|
|
452
|
+
if (output.success) {
|
|
453
|
+
return `forge-ts test: all doctests passed. (${data.duration}ms)`;
|
|
454
|
+
}
|
|
455
|
+
const lines = [];
|
|
456
|
+
for (const err of data.failures) {
|
|
457
|
+
lines.push(err.message);
|
|
458
|
+
}
|
|
459
|
+
lines.push(`forge-ts test: ${data.failed} failure(s). (${data.duration}ms)`);
|
|
460
|
+
return lines.join("\n");
|
|
461
|
+
});
|
|
462
|
+
process.exit(resolveExitCode(output));
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
// src/index.ts
|
|
467
|
+
var main = defineCommand4({
|
|
468
|
+
meta: {
|
|
469
|
+
name: "forge-ts",
|
|
470
|
+
version: "0.1.0",
|
|
471
|
+
description: "Universal TypeScript Documentation Compiler"
|
|
472
|
+
},
|
|
473
|
+
subCommands: {
|
|
474
|
+
check: checkCommand,
|
|
475
|
+
test: testCommand,
|
|
476
|
+
build: buildCommand
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
runMain(main);
|
|
480
|
+
export {
|
|
481
|
+
buildCommand,
|
|
482
|
+
checkCommand,
|
|
483
|
+
createLogger,
|
|
484
|
+
emitResult,
|
|
485
|
+
resolveExitCode,
|
|
486
|
+
testCommand
|
|
487
|
+
};
|
|
488
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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 * @codluv/forge-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 { buildCommand } from \"./commands/build.js\";\nexport { checkCommand } from \"./commands/check.js\";\nexport { 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 { generateApi } from \"@codluv/forge-api\";\nimport { loadConfig } from \"@codluv/forge-core\";\nimport { generate } from \"@codluv/forge-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}\n\n/**\n * A single step in the build pipeline.\n * @public\n */\nexport interface BuildStep {\n\tname: string;\n\tstatus: \"success\" | \"skipped\" | \"failed\";\n\toutputPath?: string;\n\tduration?: number;\n\terrors?: ForgeCliError[];\n}\n\n/**\n * Typed result for the `build` command.\n * @public\n */\nexport interface BuildResult {\n\tsteps: BuildStep[];\n\tduration: number;\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 * @public\n */\nexport async function runBuild(args: BuildArgs): Promise<CommandOutput<BuildResult>> {\n\tconst config = await loadConfig(args.cwd);\n\tconst buildStart = Date.now();\n\n\tconst steps: BuildStep[] = [];\n\tconst allErrors: ForgeCliError[] = [];\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}\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}\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\tconst data: BuildResult = { steps, duration: totalMs };\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});\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.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\toperation: string;\n\tsuccess: boolean;\n\tdata: T;\n\terrors?: ForgeCliError[];\n\twarnings?: ForgeCliWarning[];\n\tduration?: number;\n}\n\n/** Structured error for CLI commands. */\nexport interface ForgeCliError {\n\tcode: string;\n\tmessage: string;\n\tfilePath?: string;\n\tline?: number;\n\tcolumn?: number;\n}\n\n/** Structured warning for CLI commands. */\nexport interface ForgeCliWarning {\n\tcode: string;\n\tmessage: string;\n\tfilePath?: string;\n\tline?: number;\n\tcolumn?: number;\n}\n\n/** Output format flags passed through from citty args. */\nexport interface OutputFlags {\n\tjson?: boolean;\n\thuman?: boolean;\n\tquiet?: boolean;\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 * @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 { loadConfig } from \"@codluv/forge-core\";\nimport { enforce } from \"@codluv/forge-enforcer\";\nimport { defineCommand } from \"citty\";\nimport {\n\ttype CommandOutput,\n\temitResult,\n\ttype ForgeCliError,\n\ttype ForgeCliWarning,\n\ttype OutputFlags,\n\tresolveExitCode,\n} 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}\n\n/**\n * Typed result for the `check` command.\n * @public\n */\nexport interface CheckResult {\n\tsymbolCount: number;\n\terrorCount: number;\n\twarningCount: number;\n\terrors: ForgeCliError[];\n\twarnings: ForgeCliWarning[];\n\tduration: number;\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 * @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\n\tconst errors: ForgeCliError[] = result.errors.map((e) => ({\n\t\tcode: e.code,\n\t\tmessage: e.message,\n\t\tfilePath: e.filePath,\n\t\tline: e.line,\n\t\tcolumn: e.column,\n\t}));\n\n\tconst warnings: ForgeCliWarning[] = result.warnings.map((w) => ({\n\t\tcode: w.code,\n\t\tmessage: w.message,\n\t\tfilePath: w.filePath,\n\t\tline: w.line,\n\t\tcolumn: w.column,\n\t}));\n\n\tconst data: CheckResult = {\n\t\tsymbolCount: result.symbols.length,\n\t\terrorCount: errors.length,\n\t\twarningCount: warnings.length,\n\t\terrors,\n\t\twarnings,\n\t\tduration: result.duration,\n\t};\n\n\treturn {\n\t\toperation: \"check\",\n\t\tsuccess: result.success,\n\t\tdata,\n\t\terrors,\n\t\twarnings,\n\t\tduration: result.duration,\n\t};\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});\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\t// Delegate to enforcer's own formatter for human output.\n\t\t\t// Re-run enforce is not needed — we have the raw result embedded.\n\t\t\t// However formatResults needs the ForgeResult shape; we reconstruct\n\t\t\t// just enough to call it by printing the errors inline.\n\t\t\tconst lines: string[] = [];\n\t\t\tfor (const err of cmd.errors ?? []) {\n\t\t\t\tconst loc =\n\t\t\t\t\terr.filePath != null ? `${err.filePath}:${err.line ?? 0}:${err.column ?? 0}` : \"\";\n\t\t\t\tlines.push(loc ? `${loc} — ${err.message}` : err.message);\n\t\t\t}\n\t\t\tif (lines.length > 0) {\n\t\t\t\tlines.push(\n\t\t\t\t\t`\\n${cmd.data.errorCount} error(s), ${cmd.data.warningCount} warning(s) in ${cmd.data.duration}ms`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tlines.push(\n\t\t\t\t\t`forge-ts check: ${cmd.data.symbolCount} symbol(s) checked. (${cmd.data.duration}ms)`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn lines.join(\"\\n\");\n\t\t});\n\n\t\tprocess.exit(resolveExitCode(output));\n\t},\n});\n","import { loadConfig } from \"@codluv/forge-core\";\nimport { doctest } from \"@codluv/forge-doctest\";\nimport { defineCommand } from \"citty\";\nimport {\n\ttype CommandOutput,\n\temitResult,\n\ttype ForgeCliError,\n\ttype OutputFlags,\n\tresolveExitCode,\n} 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}\n\n/**\n * Typed result for the `test` command.\n * @public\n */\nexport interface TestResult {\n\tpassed: number;\n\tfailed: number;\n\ttotal: number;\n\tduration: number;\n\tfailures: ForgeCliError[];\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 * @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\n\tconst failures: ForgeCliError[] = result.errors.map((e) => ({\n\t\tcode: e.code,\n\t\tmessage: e.message,\n\t\tfilePath: e.filePath,\n\t\tline: e.line,\n\t\tcolumn: e.column,\n\t}));\n\n\tconst failCount = failures.length;\n\tconst totalSymbols = result.symbols.length;\n\tconst passCount = totalSymbols - failCount > 0 ? totalSymbols - failCount : 0;\n\n\tconst data: TestResult = {\n\t\tpassed: passCount,\n\t\tfailed: failCount,\n\t\ttotal: totalSymbols,\n\t\tduration: result.duration,\n\t\tfailures,\n\t};\n\n\treturn {\n\t\toperation: \"test\",\n\t\tsuccess: result.success,\n\t\tdata,\n\t\terrors: failures,\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 });\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.duration}ms)`;\n\t\t\t}\n\t\t\tconst lines: string[] = [];\n\t\t\tfor (const err of data.failures) {\n\t\t\t\tlines.push(err.message);\n\t\t\t}\n\t\t\tlines.push(`forge-ts test: ${data.failed} failure(s). (${data.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"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@forge-ts/cli",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "CLI entry point for forge-ts",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/codluv/forge-ts"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"main": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"bin": {
|
|
21
|
+
"forge-ts": "./dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"import": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@cleocode/lafs-protocol": "^1.7.0",
|
|
31
|
+
"citty": "^0.2.1",
|
|
32
|
+
"@codluv/forge-api": "npm:@forge-ts/api@0.2.0",
|
|
33
|
+
"@codluv/forge-core": "npm:@forge-ts/core@0.2.0",
|
|
34
|
+
"@codluv/forge-enforcer": "npm:@forge-ts/enforcer@0.2.0",
|
|
35
|
+
"@codluv/forge-doctest": "npm:@forge-ts/doctest@0.2.0",
|
|
36
|
+
"@codluv/forge-gen": "npm:@forge-ts/gen@0.2.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"tsup": "^8.3.5",
|
|
40
|
+
"typescript": "^5.8.2"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsup",
|
|
44
|
+
"dev": "tsup --watch",
|
|
45
|
+
"typecheck": "tsc --noEmit"
|
|
46
|
+
}
|
|
47
|
+
}
|