@forge-ts/cli 0.19.1 → 0.19.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-JVI2NAXX.js → chunk-LIEBLWZO.js} +24 -8
- package/dist/chunk-LIEBLWZO.js.map +1 -0
- package/dist/index.js +20 -27
- package/dist/index.js.map +1 -1
- package/dist/{init-project-6CWF4CCX.js → init-project-GEZLDJOY.js} +4 -2
- package/package.json +6 -6
- package/dist/chunk-JVI2NAXX.js.map +0 -1
- /package/dist/{init-project-6CWF4CCX.js.map → init-project-GEZLDJOY.js.map} +0 -0
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
12
12
|
import { mkdir, writeFile as writeFile2 } from "fs/promises";
|
|
13
13
|
import { join as join2 } from "path";
|
|
14
|
+
import { loadConfig } from "@forge-ts/core";
|
|
14
15
|
import { defineCommand } from "citty";
|
|
15
16
|
|
|
16
17
|
// src/pkg-json.ts
|
|
@@ -131,14 +132,21 @@ export default defineConfig({
|
|
|
131
132
|
},
|
|
132
133
|
});
|
|
133
134
|
`;
|
|
134
|
-
|
|
135
|
-
{
|
|
135
|
+
function buildTsdocContent(customTags = []) {
|
|
136
|
+
const tsdoc = {
|
|
136
137
|
$schema: "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
|
|
137
138
|
extends: ["@forge-ts/core/tsdoc-preset/tsdoc.json"]
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
};
|
|
140
|
+
if (customTags.length > 0) {
|
|
141
|
+
tsdoc.tagDefinitions = customTags;
|
|
142
|
+
const supportForTags = {};
|
|
143
|
+
for (const tag of customTags) {
|
|
144
|
+
supportForTags[tag.tagName] = true;
|
|
145
|
+
}
|
|
146
|
+
tsdoc.supportForTags = supportForTags;
|
|
147
|
+
}
|
|
148
|
+
return JSON.stringify(tsdoc, null, " ");
|
|
149
|
+
}
|
|
142
150
|
var FORGE_SCRIPTS = {
|
|
143
151
|
"forge:check": "forge-ts check",
|
|
144
152
|
"forge:test": "forge-ts test",
|
|
@@ -192,11 +200,18 @@ async function runInitProject(args) {
|
|
|
192
200
|
await writeFile2(configPath, DEFAULT_CONFIG_CONTENT, "utf8");
|
|
193
201
|
created.push("forge-ts.config.ts");
|
|
194
202
|
}
|
|
203
|
+
let customTags = [];
|
|
204
|
+
try {
|
|
205
|
+
const config = await loadConfig(rootDir);
|
|
206
|
+
customTags = config.tsdoc.customTags;
|
|
207
|
+
} catch {
|
|
208
|
+
}
|
|
195
209
|
const tsdocPath = join2(rootDir, "tsdoc.json");
|
|
196
210
|
if (existsSync2(tsdocPath)) {
|
|
197
211
|
skipped.push("tsdoc.json");
|
|
198
212
|
} else {
|
|
199
|
-
|
|
213
|
+
const tsdocContent = buildTsdocContent(customTags);
|
|
214
|
+
await writeFile2(tsdocPath, `${tsdocContent}
|
|
200
215
|
`, "utf8");
|
|
201
216
|
created.push("tsdoc.json");
|
|
202
217
|
}
|
|
@@ -395,7 +410,8 @@ export {
|
|
|
395
410
|
writePkgJson,
|
|
396
411
|
addScripts,
|
|
397
412
|
detectEnvironment,
|
|
413
|
+
buildTsdocContent,
|
|
398
414
|
runInitProject,
|
|
399
415
|
initProjectCommand
|
|
400
416
|
};
|
|
401
|
-
//# sourceMappingURL=chunk-
|
|
417
|
+
//# sourceMappingURL=chunk-LIEBLWZO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/init-project.ts","../src/pkg-json.ts"],"sourcesContent":["/**\n * `forge-ts init` command — full project setup.\n *\n * Detects the project environment, writes default config files, validates\n * tsconfig/package.json, and prints a summary with next steps.\n *\n * @packageDocumentation\n * @internal\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { loadConfig } from \"@forge-ts/core\";\nimport { defineCommand } from \"citty\";\nimport { forgeLogger } from \"../forge-logger.js\";\nimport {\n\ttype CommandOutput,\n\temitResult,\n\ttype ForgeCliError,\n\ttype ForgeCliWarning,\n\ttype OutputFlags,\n\tresolveExitCode,\n} from \"../output.js\";\nimport { addScripts, readPkgJson, writePkgJson } from \"../pkg-json.js\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * Detected project environment from Step 1 of the init flow.\n *\n * @public\n */\nexport interface InitProjectEnvironment {\n\t/** Whether package.json exists. */\n\tpackageJsonExists: boolean;\n\t/** Whether tsconfig.json exists. */\n\ttsconfigExists: boolean;\n\t/** Whether biome.json or biome.jsonc exists. */\n\tbiomeDetected: boolean;\n\t/** TypeScript version from dependencies, or null if not found. */\n\ttypescriptVersion: string | null;\n\t/** Detected hook manager. */\n\thookManager: \"husky\" | \"lefthook\" | \"none\";\n\t/** Whether the project is a monorepo. */\n\tmonorepo: boolean;\n\t/** Monorepo type if detected. */\n\tmonorepoType: \"pnpm\" | \"npm/yarn\" | null;\n}\n\n/**\n * Result of the `init` (project setup) command.\n *\n * @example\n * ```typescript\n * import { runInitProject } from \"@forge-ts/cli/commands/init-project\";\n * const output = await runInitProject({ cwd: process.cwd() });\n * console.log(output.data.created); // list of created files\n * ```\n * @public\n */\nexport interface InitProjectResult {\n\t/** Whether the init succeeded. */\n\tsuccess: boolean;\n\t/** Files that were created. */\n\tcreated: string[];\n\t/** Files that already existed and were skipped. */\n\tskipped: string[];\n\t/** Warning messages collected during init. */\n\twarnings: string[];\n\t/** Detected project environment. */\n\tenvironment: InitProjectEnvironment;\n\t/** Next steps for the user. */\n\tnextSteps: string[];\n\t/** Scripts that were added to package.json (empty if none were added). */\n\tscriptsAdded: string[];\n}\n\n/**\n * Arguments for the `init` (project setup) command.\n * @internal\n */\nexport interface InitProjectArgs {\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// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Reads and parses a package.json file.\n * @internal\n */\ninterface PackageJsonShape {\n\ttype?: string;\n\tengines?: { node?: string };\n\tdependencies?: Record<string, string>;\n\tdevDependencies?: Record<string, string>;\n\tscripts?: Record<string, string>;\n\tworkspaces?: string[] | { packages: string[] };\n}\n\n/**\n * Safely reads and parses a JSON file.\n * @internal\n */\nfunction readJsonSafe<T>(filePath: string): T | null {\n\tif (!existsSync(filePath)) {\n\t\treturn null;\n\t}\n\ttry {\n\t\tconst raw = readFileSync(filePath, \"utf8\");\n\t\treturn JSON.parse(raw) as T;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Environment detection\n// ---------------------------------------------------------------------------\n\n/**\n * Detects the project environment by checking for files and dependencies.\n *\n * @param rootDir - Absolute path to the project root.\n * @returns The detected environment.\n * @internal\n */\nexport function detectEnvironment(rootDir: string): InitProjectEnvironment {\n\tconst packageJsonPath = join(rootDir, \"package.json\");\n\tconst tsconfigPath = join(rootDir, \"tsconfig.json\");\n\tconst biomePath = join(rootDir, \"biome.json\");\n\tconst biomecPath = join(rootDir, \"biome.jsonc\");\n\tconst pnpmWorkspacePath = join(rootDir, \"pnpm-workspace.yaml\");\n\tconst huskyDir = join(rootDir, \".husky\");\n\tconst lefthookYml = join(rootDir, \"lefthook.yml\");\n\n\tconst packageJsonExists = existsSync(packageJsonPath);\n\tconst tsconfigExists = existsSync(tsconfigPath);\n\tconst biomeDetected = existsSync(biomePath) || existsSync(biomecPath);\n\n\t// TypeScript version detection\n\tlet typescriptVersion: string | null = null;\n\tif (packageJsonExists) {\n\t\tconst pkg = readJsonSafe<PackageJsonShape>(packageJsonPath);\n\t\tif (pkg) {\n\t\t\tconst tsVersion = pkg.devDependencies?.typescript ?? pkg.dependencies?.typescript ?? null;\n\t\t\ttypescriptVersion = tsVersion;\n\t\t}\n\t}\n\n\t// Hook manager detection\n\tlet hookManager: \"husky\" | \"lefthook\" | \"none\" = \"none\";\n\tif (existsSync(huskyDir)) {\n\t\thookManager = \"husky\";\n\t} else if (existsSync(lefthookYml)) {\n\t\thookManager = \"lefthook\";\n\t} else if (packageJsonExists) {\n\t\tconst pkg = readJsonSafe<PackageJsonShape>(packageJsonPath);\n\t\tif (pkg) {\n\t\t\tconst allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n\t\t\tif (\"husky\" in allDeps) {\n\t\t\t\thookManager = \"husky\";\n\t\t\t} else if (\"lefthook\" in allDeps) {\n\t\t\t\thookManager = \"lefthook\";\n\t\t\t}\n\t\t}\n\t}\n\n\t// Monorepo detection\n\tlet monorepo = false;\n\tlet monorepoType: \"pnpm\" | \"npm/yarn\" | null = null;\n\tif (existsSync(pnpmWorkspacePath)) {\n\t\tmonorepo = true;\n\t\tmonorepoType = \"pnpm\";\n\t} else if (packageJsonExists) {\n\t\tconst pkg = readJsonSafe<PackageJsonShape>(packageJsonPath);\n\t\tif (pkg?.workspaces) {\n\t\t\tmonorepo = true;\n\t\t\tmonorepoType = \"npm/yarn\";\n\t\t}\n\t}\n\n\treturn {\n\t\tpackageJsonExists,\n\t\ttsconfigExists,\n\t\tbiomeDetected,\n\t\ttypescriptVersion,\n\t\thookManager,\n\t\tmonorepo,\n\t\tmonorepoType,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Config file content\n// ---------------------------------------------------------------------------\n\n/**\n * Default forge-ts.config.ts content for new projects.\n *\n * Only overrides that differ from built-in defaults are included.\n * The full defaults (enforce rules, doctest, etc.) are merged\n * automatically by `loadConfig()` → `mergeWithDefaults()`.\n * @internal\n */\nconst DEFAULT_CONFIG_CONTENT = `import { defineConfig } from \"@forge-ts/core\";\n\nexport default defineConfig({\n rootDir: \".\",\n outDir: \"docs/generated\",\n gen: {\n ssgTarget: \"mintlify\",\n },\n});\n`;\n\n/**\n * Builds tsdoc.json content, merging in customTags from the forge config.\n *\n * When `customTags` is non-empty, the written tsdoc.json includes both\n * `tagDefinitions` and `supportForTags` entries so that the TSDoc parser\n * (and any editor extensions) recognise the custom tags.\n *\n * @param customTags - Custom tag definitions from `ForgeConfig.tsdoc.customTags`.\n * @returns A JSON string for tsdoc.json.\n * @internal\n */\nexport function buildTsdocContent(\n\tcustomTags: Array<{ tagName: string; syntaxKind: \"block\" | \"inline\" | \"modifier\" }> = [],\n): string {\n\tconst tsdoc: Record<string, unknown> = {\n\t\t$schema: \"https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json\",\n\t\textends: [\"@forge-ts/core/tsdoc-preset/tsdoc.json\"],\n\t};\n\n\tif (customTags.length > 0) {\n\t\ttsdoc.tagDefinitions = customTags;\n\t\tconst supportForTags: Record<string, boolean> = {};\n\t\tfor (const tag of customTags) {\n\t\t\tsupportForTags[tag.tagName] = true;\n\t\t}\n\t\ttsdoc.supportForTags = supportForTags;\n\t}\n\n\treturn JSON.stringify(tsdoc, null, \"\\t\");\n}\n\n/**\n * Default npm scripts wired by `forge-ts init`.\n *\n * Each entry is only added when the key does **not** already exist in\n * the user's `package.json`, making the operation idempotent.\n * @internal\n */\nconst FORGE_SCRIPTS: Record<string, string> = {\n\t\"forge:check\": \"forge-ts check\",\n\t\"forge:test\": \"forge-ts test\",\n\t\"forge:build\": \"forge-ts build\",\n\t\"forge:doctor\": \"forge-ts doctor\",\n\tprepublishOnly: \"forge-ts prepublish\",\n};\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Runs the full project init flow.\n *\n * Steps:\n * 1. Detect project environment\n * 2. Write forge-ts.config.ts (if not exists)\n * 3. Write tsdoc.json (if not exists)\n * 4. Wire package.json scripts (idempotent)\n * 5. Validate tsconfig.json strictness\n * 6. Validate package.json\n * 7. Report summary\n *\n * @param args - CLI arguments for the init command.\n * @returns A typed `CommandOutput<InitProjectResult>`.\n * @example\n * ```typescript\n * import { runInitProject } from \"@forge-ts/cli/commands/init-project\";\n * const output = await runInitProject({ cwd: process.cwd() });\n * console.log(output.data.created); // [\"forge-ts.config.ts\", \"tsdoc.json\"]\n * ```\n * @public\n */\nexport async function runInitProject(\n\targs: InitProjectArgs,\n): Promise<CommandOutput<InitProjectResult>> {\n\tconst start = Date.now();\n\tconst rootDir = args.cwd ?? process.cwd();\n\n\tconst created: string[] = [];\n\tconst skipped: string[] = [];\n\tconst warnings: string[] = [];\n\tconst cliWarnings: ForgeCliWarning[] = [];\n\n\t// -----------------------------------------------------------------------\n\t// Step 1: Detect project environment\n\t// -----------------------------------------------------------------------\n\n\tconst environment = detectEnvironment(rootDir);\n\n\tif (!environment.packageJsonExists) {\n\t\tconst err: ForgeCliError = {\n\t\t\tcode: \"INIT_NO_PACKAGE_JSON\",\n\t\t\tmessage: \"package.json not found. Run `npm init` or `pnpm init` first.\",\n\t\t};\n\t\treturn {\n\t\t\toperation: \"init\",\n\t\t\tsuccess: false,\n\t\t\tdata: {\n\t\t\t\tsuccess: false,\n\t\t\t\tcreated: [],\n\t\t\t\tskipped: [],\n\t\t\t\twarnings: [],\n\t\t\t\tenvironment,\n\t\t\t\tnextSteps: [],\n\t\t\t\tscriptsAdded: [],\n\t\t\t},\n\t\t\terrors: [err],\n\t\t\tduration: Date.now() - start,\n\t\t};\n\t}\n\n\tif (!environment.tsconfigExists) {\n\t\twarnings.push(\"tsconfig.json not found. forge-ts requires TypeScript.\");\n\t\tcliWarnings.push({\n\t\t\tcode: \"INIT_NO_TSCONFIG\",\n\t\t\tmessage: \"tsconfig.json not found. forge-ts requires TypeScript.\",\n\t\t});\n\t}\n\n\tif (!environment.biomeDetected) {\n\t\t// Informational — not a warning\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Step 2: Write forge-ts.config.ts\n\t// -----------------------------------------------------------------------\n\n\tconst configPath = join(rootDir, \"forge-ts.config.ts\");\n\tif (existsSync(configPath)) {\n\t\tskipped.push(\"forge-ts.config.ts\");\n\t} else {\n\t\tawait mkdir(rootDir, { recursive: true });\n\t\tawait writeFile(configPath, DEFAULT_CONFIG_CONTENT, \"utf8\");\n\t\tcreated.push(\"forge-ts.config.ts\");\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Step 3: Write tsdoc.json (with customTags from config if available)\n\t// -----------------------------------------------------------------------\n\n\t// Attempt to load config to pick up customTags. If config loading fails\n\t// (e.g. the config was just created above), fall back to empty customTags.\n\tlet customTags: Array<{ tagName: string; syntaxKind: \"block\" | \"inline\" | \"modifier\" }> = [];\n\ttry {\n\t\tconst config = await loadConfig(rootDir);\n\t\tcustomTags = config.tsdoc.customTags;\n\t} catch {\n\t\t// Config not loadable yet — use empty customTags\n\t}\n\n\tconst tsdocPath = join(rootDir, \"tsdoc.json\");\n\tif (existsSync(tsdocPath)) {\n\t\tskipped.push(\"tsdoc.json\");\n\t} else {\n\t\tconst tsdocContent = buildTsdocContent(customTags);\n\t\tawait writeFile(tsdocPath, `${tsdocContent}\\n`, \"utf8\");\n\t\tcreated.push(\"tsdoc.json\");\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Step 4: Wire package.json scripts (idempotent)\n\t// -----------------------------------------------------------------------\n\n\tlet scriptsAdded: string[] = [];\n\tif (environment.packageJsonExists) {\n\t\tconst pkg = readPkgJson(rootDir);\n\t\tif (pkg) {\n\t\t\tscriptsAdded = addScripts(pkg, FORGE_SCRIPTS);\n\t\t\tif (scriptsAdded.length > 0) {\n\t\t\t\ttry {\n\t\t\t\t\tawait writePkgJson(pkg);\n\t\t\t\t} catch {\n\t\t\t\t\twarnings.push(\"package.json: failed to wire scripts — file may be malformed.\");\n\t\t\t\t\tcliWarnings.push({\n\t\t\t\t\t\tcode: \"INIT_SCRIPTS_FAILED\",\n\t\t\t\t\t\tmessage: \"package.json: failed to wire scripts — file may be malformed.\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Step 5: Validate tsconfig.json strictness\n\t// -----------------------------------------------------------------------\n\n\tif (environment.tsconfigExists) {\n\t\tconst tsconfigPath = join(rootDir, \"tsconfig.json\");\n\t\tconst tsconfig = readJsonSafe<{\n\t\t\tcompilerOptions?: { strict?: boolean };\n\t\t}>(tsconfigPath);\n\n\t\tif (tsconfig) {\n\t\t\tif (!tsconfig.compilerOptions || tsconfig.compilerOptions.strict !== true) {\n\t\t\t\twarnings.push(\"tsconfig.json: 'strict' is not enabled. forge-ts recommends strict mode.\");\n\t\t\t\tcliWarnings.push({\n\t\t\t\t\tcode: \"INIT_TSCONFIG_NOT_STRICT\",\n\t\t\t\t\tmessage: \"tsconfig.json: 'strict' is not enabled. forge-ts recommends strict mode.\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Step 6: Validate package.json\n\t// -----------------------------------------------------------------------\n\n\tconst pkgPath = join(rootDir, \"package.json\");\n\tconst pkg = readJsonSafe<PackageJsonShape>(pkgPath);\n\n\tif (pkg) {\n\t\tif (pkg.type !== \"module\") {\n\t\t\twarnings.push('package.json: missing \"type\": \"module\". forge-ts uses ESM.');\n\t\t\tcliWarnings.push({\n\t\t\t\tcode: \"INIT_NO_ESM\",\n\t\t\t\tmessage: 'package.json: missing \"type\": \"module\". forge-ts uses ESM.',\n\t\t\t});\n\t\t}\n\n\t\tif (!pkg.engines?.node) {\n\t\t\twarnings.push(\"package.json: missing engines.node field.\");\n\t\t\tcliWarnings.push({\n\t\t\t\tcode: \"INIT_NO_ENGINES\",\n\t\t\t\tmessage: \"package.json: missing engines.node field.\",\n\t\t\t});\n\t\t}\n\n\t\tconst allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n\t\tif (!(\"@forge-ts/cli\" in allDeps)) {\n\t\t\twarnings.push(\"package.json: @forge-ts/cli not in devDependencies (running via npx?).\");\n\t\t\tcliWarnings.push({\n\t\t\t\tcode: \"INIT_CLI_NOT_INSTALLED\",\n\t\t\t\tmessage: \"package.json: @forge-ts/cli not in devDependencies (running via npx?).\",\n\t\t\t});\n\t\t}\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Step 7: Build result\n\t// -----------------------------------------------------------------------\n\n\tconst nextSteps: string[] = [\n\t\t\"Run: forge-ts check (lint TSDoc coverage)\",\n\t\t\"Run: forge-ts init docs (scaffold documentation site)\",\n\t\t\"Run: forge-ts init hooks (scaffold pre-commit hooks)\",\n\t\t\"Run: forge-ts lock (lock config to prevent drift)\",\n\t];\n\n\tconst data: InitProjectResult = {\n\t\tsuccess: true,\n\t\tcreated,\n\t\tskipped,\n\t\twarnings,\n\t\tenvironment,\n\t\tnextSteps,\n\t\tscriptsAdded,\n\t};\n\n\treturn {\n\t\toperation: \"init\",\n\t\tsuccess: true,\n\t\tdata,\n\t\twarnings: cliWarnings.length > 0 ? cliWarnings : undefined,\n\t\tduration: Date.now() - start,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Human formatter\n// ---------------------------------------------------------------------------\n\n/**\n * Formats an InitProjectResult as human-readable text.\n * @internal\n */\nfunction formatInitProjectHuman(result: InitProjectResult): string {\n\tconst lines: string[] = [];\n\n\tlines.push(\"\\nforge-ts init: project setup complete\\n\");\n\n\t// Created files\n\tif (result.created.length > 0) {\n\t\tlines.push(\" Created:\");\n\t\tfor (const file of result.created) {\n\t\t\tlines.push(` ${file}`);\n\t\t}\n\t}\n\n\t// Skipped files\n\tif (result.skipped.length > 0) {\n\t\tlines.push(\"\");\n\t\tlines.push(\" Already exists (skipped):\");\n\t\tfor (const file of result.skipped) {\n\t\t\tlines.push(` ${file}`);\n\t\t}\n\t} else if (result.created.length > 0) {\n\t\tlines.push(\"\");\n\t\tlines.push(\" Already exists (skipped):\");\n\t\tlines.push(\" (none)\");\n\t}\n\n\t// Scripts added\n\tif (result.scriptsAdded.length > 0) {\n\t\tlines.push(\"\");\n\t\tlines.push(\" Scripts added to package.json:\");\n\t\tfor (const script of result.scriptsAdded) {\n\t\t\tlines.push(` ${script}`);\n\t\t}\n\t}\n\n\t// Warnings\n\tif (result.warnings.length > 0) {\n\t\tlines.push(\"\");\n\t\tlines.push(\" Warnings:\");\n\t\tfor (const warning of result.warnings) {\n\t\t\tlines.push(` ${warning}`);\n\t\t}\n\t}\n\n\t// Environment\n\tconst env = result.environment;\n\tlines.push(\"\");\n\tlines.push(\" Environment:\");\n\tlines.push(` TypeScript: ${env.typescriptVersion ?? \"not detected\"}`);\n\tlines.push(` Biome: ${env.biomeDetected ? \"detected\" : \"not detected\"}`);\n\n\tconst hookLabel = env.hookManager === \"none\" ? \"not detected\" : `${env.hookManager} detected`;\n\tlines.push(` Git hooks: ${hookLabel}`);\n\n\tif (env.monorepo) {\n\t\tlines.push(\n\t\t\t` Monorepo: ${env.monorepoType === \"pnpm\" ? \"pnpm workspaces\" : \"npm/yarn workspaces\"}`,\n\t\t);\n\t} else {\n\t\tlines.push(\" Monorepo: no\");\n\t}\n\n\t// Next steps\n\tif (result.nextSteps.length > 0) {\n\t\tlines.push(\"\");\n\t\tlines.push(\" Next steps:\");\n\t\tfor (const [idx, step] of result.nextSteps.entries()) {\n\t\t\tlines.push(` ${idx + 1}. ${step}`);\n\t\t}\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` (bare — full project setup).\n *\n * Detects the project environment, writes default configuration files,\n * validates tsconfig/package.json, and reports a summary.\n *\n * @example\n * ```typescript\n * import { initProjectCommand } from \"@forge-ts/cli/commands/init-project\";\n * // Registered as the default handler for `forge-ts init`\n * ```\n * @public\n */\nexport const initProjectCommand = defineCommand({\n\tmeta: {\n\t\tname: \"init\",\n\t\tdescription: \"Full project setup for forge-ts\",\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\",\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 runInitProject({\n\t\t\tcwd: args.cwd,\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 msg = cmd.errors?.[0]?.message ?? \"Init failed\";\n\t\t\t\tforgeLogger.error(msg);\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t\treturn formatInitProjectHuman(data);\n\t\t});\n\n\t\tprocess.exit(resolveExitCode(output));\n\t},\n});\n","/**\n * Shared utilities for idempotent package.json read-modify-write operations.\n *\n * Every command that touches package.json MUST use these helpers to ensure:\n * - Existing content is never lost\n * - JSON formatting (indent style, trailing newline) is preserved\n * - Scripts are only added when the key doesn't already exist\n *\n * @packageDocumentation\n * @internal\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Parsed package.json with formatting metadata for lossless round-tripping.\n * @internal\n */\nexport interface PkgJson {\n\t/** Absolute path to the file. */\n\tpath: string;\n\t/** Raw file content as read from disk. */\n\traw: string;\n\t/** Parsed JSON object. */\n\tobj: Record<string, unknown>;\n\t/** Detected indent string (tabs or spaces). */\n\tindent: string;\n\t/** Whether the original file ended with a newline. */\n\ttrailingNewline: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Read\n// ---------------------------------------------------------------------------\n\n/**\n * Read and parse package.json from a project root.\n *\n * Detects indent style and trailing newline for lossless round-tripping.\n * Returns `null` if the file doesn't exist or can't be parsed.\n *\n * @param rootDir - Absolute path to the project root.\n * @returns Parsed package.json with formatting metadata, or null.\n * @internal\n */\nexport function readPkgJson(rootDir: string): PkgJson | null {\n\tconst pkgPath = join(rootDir, \"package.json\");\n\tif (!existsSync(pkgPath)) return null;\n\ttry {\n\t\tconst raw = readFileSync(pkgPath, \"utf8\");\n\t\tconst obj = JSON.parse(raw) as Record<string, unknown>;\n\t\tconst match = raw.match(/\\n(\\s+)\"/);\n\t\tconst indent = match ? match[1] : \" \";\n\t\tconst trailingNewline = raw.endsWith(\"\\n\");\n\t\treturn { path: pkgPath, raw, obj, indent, trailingNewline };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Write\n// ---------------------------------------------------------------------------\n\n/**\n * Serialize a package.json object preserving original formatting.\n *\n * @param pkg - The parsed package.json with formatting metadata.\n * @returns Formatted JSON string ready to write to disk.\n * @internal\n */\nexport function serializePkgJson(pkg: PkgJson): string {\n\treturn JSON.stringify(pkg.obj, null, pkg.indent) + (pkg.trailingNewline ? \"\\n\" : \"\");\n}\n\n/**\n * Write a modified package.json back to disk, preserving formatting.\n *\n * @param pkg - The parsed and modified package.json.\n * @internal\n */\nexport async function writePkgJson(pkg: PkgJson): Promise<void> {\n\tawait writeFile(pkg.path, serializePkgJson(pkg), \"utf8\");\n}\n\n// ---------------------------------------------------------------------------\n// Script helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Add scripts to package.json idempotently.\n *\n * Only adds scripts where the key doesn't already exist.\n * Never overwrites existing script values. Returns the list of keys added.\n *\n * @param pkg - The parsed package.json to modify (mutated in place).\n * @param scripts - Map of script key to command value.\n * @returns Array of script keys that were added (empty if all already existed).\n * @internal\n */\nexport function addScripts(pkg: PkgJson, scripts: Record<string, string>): string[] {\n\tconst existing = (pkg.obj.scripts ?? {}) as Record<string, string>;\n\tconst added: string[] = [];\n\n\tfor (const [key, value] of Object.entries(scripts)) {\n\t\tif (!(key in existing)) {\n\t\t\texisting[key] = value;\n\t\t\tadded.push(key);\n\t\t}\n\t}\n\n\tif (added.length > 0) {\n\t\tpkg.obj.scripts = existing;\n\t}\n\n\treturn added;\n}\n"],"mappings":"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","names":["existsSync","readFileSync","writeFile","join","existsSync","readFileSync","join","writeFile","pkg"]}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
addScripts,
|
|
4
|
+
buildTsdocContent,
|
|
4
5
|
initProjectCommand,
|
|
5
6
|
readPkgJson,
|
|
6
7
|
runInitProject,
|
|
7
8
|
writePkgJson
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LIEBLWZO.js";
|
|
9
10
|
import {
|
|
10
11
|
configureLogger,
|
|
11
12
|
forgeLogger
|
|
@@ -945,6 +946,7 @@ import { execSync as execSync2 } from "child_process";
|
|
|
945
946
|
import { existsSync, readFileSync } from "fs";
|
|
946
947
|
import { mkdir, writeFile } from "fs/promises";
|
|
947
948
|
import { join } from "path";
|
|
949
|
+
import { loadConfig as loadConfig5 } from "@forge-ts/core";
|
|
948
950
|
import { defineCommand as defineCommand6 } from "citty";
|
|
949
951
|
function readJsonSafe(filePath) {
|
|
950
952
|
if (!existsSync(filePath)) {
|
|
@@ -967,14 +969,6 @@ export default defineConfig({
|
|
|
967
969
|
},
|
|
968
970
|
});
|
|
969
971
|
`;
|
|
970
|
-
var DEFAULT_TSDOC_CONTENT = JSON.stringify(
|
|
971
|
-
{
|
|
972
|
-
$schema: "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
|
|
973
|
-
extends: ["@forge-ts/core/tsdoc-preset/tsdoc.json"]
|
|
974
|
-
},
|
|
975
|
-
null,
|
|
976
|
-
" "
|
|
977
|
-
);
|
|
978
972
|
async function runDoctor(args) {
|
|
979
973
|
const start = Date.now();
|
|
980
974
|
const rootDir = args.cwd ?? process.cwd();
|
|
@@ -1028,7 +1022,13 @@ async function runDoctor(args) {
|
|
|
1028
1022
|
});
|
|
1029
1023
|
}
|
|
1030
1024
|
} else if (fix) {
|
|
1031
|
-
|
|
1025
|
+
let customTags = [];
|
|
1026
|
+
try {
|
|
1027
|
+
const config = await loadConfig5(rootDir);
|
|
1028
|
+
customTags = config.tsdoc.customTags;
|
|
1029
|
+
} catch {
|
|
1030
|
+
}
|
|
1031
|
+
await writeFile(tsdocPath, `${buildTsdocContent(customTags)}
|
|
1032
1032
|
`, "utf8");
|
|
1033
1033
|
fixed.push("tsdoc.json");
|
|
1034
1034
|
checks.push({
|
|
@@ -1485,7 +1485,7 @@ var doctorCommand = defineCommand6({
|
|
|
1485
1485
|
import { existsSync as existsSync2 } from "fs";
|
|
1486
1486
|
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
1487
1487
|
import { join as join2, resolve as resolve2 } from "path";
|
|
1488
|
-
import { loadConfig as
|
|
1488
|
+
import { loadConfig as loadConfig6 } from "@forge-ts/core";
|
|
1489
1489
|
import {
|
|
1490
1490
|
DEFAULT_TARGET as DEFAULT_TARGET2,
|
|
1491
1491
|
getAdapter as getAdapter2,
|
|
@@ -1517,7 +1517,7 @@ async function runInitDocs(args) {
|
|
|
1517
1517
|
}
|
|
1518
1518
|
const target = rawTarget;
|
|
1519
1519
|
const adapter = getAdapter2(target);
|
|
1520
|
-
const config = await
|
|
1520
|
+
const config = await loadConfig6(args.cwd);
|
|
1521
1521
|
const outDir = args.outDir ? resolve2(args.outDir) : config.outDir;
|
|
1522
1522
|
const alreadyExists = await adapter.detectExisting(outDir);
|
|
1523
1523
|
if (alreadyExists && !args.force) {
|
|
@@ -1576,14 +1576,7 @@ async function runInitDocs(args) {
|
|
|
1576
1576
|
message: "tsdoc.json already exists \u2014 skipping. Remove it and re-run to regenerate."
|
|
1577
1577
|
});
|
|
1578
1578
|
} else {
|
|
1579
|
-
const tsdocContent =
|
|
1580
|
-
{
|
|
1581
|
-
$schema: "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
|
|
1582
|
-
extends: ["@forge-ts/core/tsdoc-preset/tsdoc.json"]
|
|
1583
|
-
},
|
|
1584
|
-
null,
|
|
1585
|
-
" "
|
|
1586
|
-
);
|
|
1579
|
+
const tsdocContent = buildTsdocContent(config.tsdoc.customTags);
|
|
1587
1580
|
await mkdir2(config.rootDir, { recursive: true });
|
|
1588
1581
|
await writeFile2(tsdocPath, `${tsdocContent}
|
|
1589
1582
|
`, "utf8");
|
|
@@ -2013,13 +2006,13 @@ var initHooksCommand = defineCommand8({
|
|
|
2013
2006
|
import {
|
|
2014
2007
|
appendAuditEvent,
|
|
2015
2008
|
createLockManifest,
|
|
2016
|
-
loadConfig as
|
|
2009
|
+
loadConfig as loadConfig7,
|
|
2017
2010
|
readLockFile,
|
|
2018
2011
|
writeLockFile
|
|
2019
2012
|
} from "@forge-ts/core";
|
|
2020
2013
|
import { defineCommand as defineCommand9 } from "citty";
|
|
2021
2014
|
async function runLock(args) {
|
|
2022
|
-
const config = await
|
|
2015
|
+
const config = await loadConfig7(args.cwd);
|
|
2023
2016
|
const rootDir = config.rootDir;
|
|
2024
2017
|
const existingLock = readLockFile(rootDir);
|
|
2025
2018
|
const manifest = createLockManifest(config);
|
|
@@ -2277,11 +2270,11 @@ var prepublishCommand = defineCommand10({
|
|
|
2277
2270
|
});
|
|
2278
2271
|
|
|
2279
2272
|
// src/commands/test.ts
|
|
2280
|
-
import { loadConfig as
|
|
2273
|
+
import { loadConfig as loadConfig8 } from "@forge-ts/core";
|
|
2281
2274
|
import { doctest } from "@forge-ts/doctest";
|
|
2282
2275
|
import { defineCommand as defineCommand11 } from "citty";
|
|
2283
2276
|
async function runTest(args) {
|
|
2284
|
-
const config = await
|
|
2277
|
+
const config = await loadConfig8(args.cwd);
|
|
2285
2278
|
const result = await doctest(config);
|
|
2286
2279
|
const mviLevel = args.mvi ?? "standard";
|
|
2287
2280
|
const failCount = result.errors.length;
|
|
@@ -2379,13 +2372,13 @@ var testCommand = defineCommand11({
|
|
|
2379
2372
|
import {
|
|
2380
2373
|
appendAuditEvent as appendAuditEvent2,
|
|
2381
2374
|
getCurrentUser,
|
|
2382
|
-
loadConfig as
|
|
2375
|
+
loadConfig as loadConfig9,
|
|
2383
2376
|
readLockFile as readLockFile2,
|
|
2384
2377
|
removeLockFile
|
|
2385
2378
|
} from "@forge-ts/core";
|
|
2386
2379
|
import { defineCommand as defineCommand12 } from "citty";
|
|
2387
2380
|
async function runUnlock(args) {
|
|
2388
|
-
const config = await
|
|
2381
|
+
const config = await loadConfig9(args.cwd);
|
|
2389
2382
|
const rootDir = config.rootDir;
|
|
2390
2383
|
const existingLock = readLockFile2(rootDir);
|
|
2391
2384
|
if (!existingLock) {
|
|
@@ -2572,7 +2565,7 @@ var initCommand2 = defineCommand13({
|
|
|
2572
2565
|
if (hasSubCommand) {
|
|
2573
2566
|
return;
|
|
2574
2567
|
}
|
|
2575
|
-
const { runInitProject: runInitProject2 } = await import("./init-project-
|
|
2568
|
+
const { runInitProject: runInitProject2 } = await import("./init-project-GEZLDJOY.js");
|
|
2576
2569
|
const { emitResult: emitResult2, resolveExitCode: resolveExitCode2 } = await import("./output-OSCHMPOX.js");
|
|
2577
2570
|
const { forgeLogger: forgeLogger2 } = await import("./forge-logger-RTOBEKWH.js");
|
|
2578
2571
|
const output = await runInitProject2({
|