forgemap 0.4.1-dev.79-818a2fa → 0.4.1-dev.80-662a8e8

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.
@@ -5,7 +5,7 @@ import { access, mkdir, readFile, readdir, rename, rm, rmdir, stat, writeFile }
5
5
  import { colors, formatTree } from "consola/utils";
6
6
  import { dirname, isAbsolute, join, resolve } from "pathe";
7
7
  import { homedir } from "node:os";
8
- import { existsSync } from "node:fs";
8
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
9
9
  import { loadConfig } from "c12";
10
10
  import { createHash } from "node:crypto";
11
11
  import { spawn } from "node:child_process";
@@ -93,7 +93,30 @@ var DEFAULT_CONFIG$1 = {
93
93
  async function loadForgeMapConfig(options = {}) {
94
94
  const envConfig = process.env.FORGEMAP_CONFIG;
95
95
  const startDir = options.cwd ?? process.cwd();
96
- const explicit = options.configFile ?? envConfig ?? findConfigUp(startDir) ?? findGlobalConfig();
96
+ let explicit;
97
+ let source;
98
+ if (options.configFile) {
99
+ explicit = options.configFile;
100
+ source = "flag";
101
+ } else if (envConfig) {
102
+ explicit = envConfig;
103
+ source = "env";
104
+ } else {
105
+ const walkedUp = findConfigUp(startDir);
106
+ if (walkedUp) {
107
+ explicit = walkedUp;
108
+ source = "walk-up";
109
+ } else {
110
+ const global = findGlobalConfig();
111
+ if (global) {
112
+ explicit = global;
113
+ source = "global";
114
+ } else {
115
+ explicit = void 0;
116
+ source = "default";
117
+ }
118
+ }
119
+ }
97
120
  const cwd = explicit ? dirname(explicit) : startDir;
98
121
  const { config, configFile } = await loadConfig({
99
122
  name: "forgemap",
@@ -103,14 +126,17 @@ async function loadForgeMapConfig(options = {}) {
103
126
  globalRc: false,
104
127
  dotenv: false
105
128
  });
129
+ const merged = {
130
+ root: config.root ?? DEFAULT_CONFIG$1.root,
131
+ defaultForge: config.defaultForge ?? DEFAULT_CONFIG$1.defaultForge,
132
+ forges: config.forges && Object.keys(config.forges).length > 0 ? config.forges : DEFAULT_CONFIG$1.forges
133
+ };
134
+ const resolvedFile = source === "default" ? void 0 : configFile || void 0;
106
135
  return {
107
- config: {
108
- root: config.root ?? DEFAULT_CONFIG$1.root,
109
- defaultForge: config.defaultForge ?? DEFAULT_CONFIG$1.defaultForge,
110
- forges: config.forges && Object.keys(config.forges).length > 0 ? config.forges : DEFAULT_CONFIG$1.forges
111
- },
112
- configFile: configFile || void 0,
113
- cwd
136
+ config: merged,
137
+ configFile: resolvedFile,
138
+ cwd,
139
+ source: resolvedFile ? source : "default"
114
140
  };
115
141
  }
116
142
  //#endregion
@@ -2243,6 +2269,170 @@ var importCommand = defineCommand({
2243
2269
  }
2244
2270
  });
2245
2271
  //#endregion
2272
+ //#region src/commands/info.ts
2273
+ /** Resolve the real executed file behind any shim or symlink. */
2274
+ function resolveBinary(entry) {
2275
+ if (!entry) return {
2276
+ invoked: null,
2277
+ resolved: null
2278
+ };
2279
+ try {
2280
+ return {
2281
+ invoked: entry,
2282
+ resolved: realpathSync(entry)
2283
+ };
2284
+ } catch {
2285
+ return {
2286
+ invoked: entry,
2287
+ resolved: entry
2288
+ };
2289
+ }
2290
+ }
2291
+ /** Walk up from `start` to the nearest package.json, returning its dir + name. */
2292
+ function findPackageRoot(start) {
2293
+ let dir = resolve(start);
2294
+ for (;;) {
2295
+ const pkgPath = join(dir, "package.json");
2296
+ if (existsSync(pkgPath)) try {
2297
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
2298
+ return {
2299
+ dir,
2300
+ name: pkg.name
2301
+ };
2302
+ } catch {
2303
+ return {
2304
+ dir,
2305
+ name: void 0
2306
+ };
2307
+ }
2308
+ const parent = dirname(dir);
2309
+ if (parent === dir) return null;
2310
+ dir = parent;
2311
+ }
2312
+ }
2313
+ /**
2314
+ * Distinguish a linked/dev build from an installed release: the resolved binary
2315
+ * lives inside a git work tree whose package.json is named `forgemap`. An
2316
+ * installed package has the same package.json but no `.git` beside it. When the
2317
+ * binary or a `forgemap` package.json cannot be located, report `unknown`
2318
+ * rather than guessing.
2319
+ */
2320
+ function detectBuild(resolved) {
2321
+ if (!resolved) return {
2322
+ kind: "unknown",
2323
+ packageRoot: null,
2324
+ reason: "binary path could not be resolved"
2325
+ };
2326
+ const pkg = findPackageRoot(dirname(resolved));
2327
+ if (!pkg) return {
2328
+ kind: "unknown",
2329
+ packageRoot: null,
2330
+ reason: "no package.json found above the binary"
2331
+ };
2332
+ if (pkg.name !== "forgemap") return {
2333
+ kind: "unknown",
2334
+ packageRoot: pkg.dir,
2335
+ reason: `nearest package.json is "${pkg.name ?? "unnamed"}", not forgemap`
2336
+ };
2337
+ const inGitTree = existsSync(join(pkg.dir, ".git"));
2338
+ return {
2339
+ kind: inGitTree ? "linked" : "release",
2340
+ packageRoot: pkg.dir,
2341
+ reason: inGitTree ? "runs from a git work tree named forgemap" : "installed forgemap package (no git work tree beside it)"
2342
+ };
2343
+ }
2344
+ async function gatherConfig(configFile) {
2345
+ try {
2346
+ const loaded = await loadForgeMapConfig({ configFile });
2347
+ const configDir = loaded.configFile ? dirname(loaded.configFile) : loaded.cwd;
2348
+ return {
2349
+ source: loaded.source,
2350
+ file: loaded.configFile ?? null,
2351
+ root: resolveRoot(loaded.config.root, configDir),
2352
+ forges: Object.entries(loaded.config.forges).map(([name, forge]) => ({
2353
+ name,
2354
+ type: forge.type,
2355
+ dir: forge.dir
2356
+ })),
2357
+ error: null
2358
+ };
2359
+ } catch (error) {
2360
+ return {
2361
+ source: "error",
2362
+ file: null,
2363
+ root: null,
2364
+ forges: [],
2365
+ error: error.message
2366
+ };
2367
+ }
2368
+ }
2369
+ var SOURCE_LABELS = {
2370
+ flag: "--config flag",
2371
+ env: "FORGEMAP_CONFIG env",
2372
+ "walk-up": "walk-up from cwd",
2373
+ global: "global ($XDG_CONFIG_HOME/forgemap)",
2374
+ default: "built-in defaults (no config file found)",
2375
+ error: "failed to load"
2376
+ };
2377
+ var BUILD_LABELS = {
2378
+ linked: "linked / dev build",
2379
+ release: "installed release",
2380
+ unknown: "unknown"
2381
+ };
2382
+ function row(label, value) {
2383
+ return ` ${colors.dim(label.padEnd(9))} ${value}\n`;
2384
+ }
2385
+ function renderPretty(info) {
2386
+ let out = `${colors.bold("forgemap")} ${colors.cyan(`v${info.version}`)} ${colors.dim(`(${BUILD_LABELS[info.build.kind]})`)}\n`;
2387
+ out += row("build", colors.dim(info.build.reason));
2388
+ out += row("binary", info.binary.resolved ?? colors.dim("unknown"));
2389
+ if (info.binary.invoked && info.binary.invoked !== info.binary.resolved) out += row("", colors.dim(`via ${info.binary.invoked}`));
2390
+ out += row("node", info.node);
2391
+ out += `\n${colors.bold("config")}\n`;
2392
+ out += row("source", SOURCE_LABELS[info.config.source]);
2393
+ if (info.config.error) out += row("error", colors.red(info.config.error));
2394
+ else {
2395
+ out += row("file", info.config.file ?? colors.dim("none"));
2396
+ out += row("root", info.config.root ?? colors.dim("unknown"));
2397
+ }
2398
+ out += `\n${colors.bold("forges")}\n`;
2399
+ if (info.config.forges.length === 0) out += ` ${colors.dim("none")}\n`;
2400
+ else for (const forge of info.config.forges) out += ` ${colors.cyan(forge.name.padEnd(12))} ${forge.type} ${colors.dim("→")} ${forge.dir}\n`;
2401
+ return out;
2402
+ }
2403
+ var infoCommand = defineCommand({
2404
+ meta: {
2405
+ name: "info",
2406
+ description: "Describe this installation: version, binary path, node, and resolved config"
2407
+ },
2408
+ args: {
2409
+ json: {
2410
+ type: "boolean",
2411
+ description: "Emit a machine-readable JSON report",
2412
+ default: false
2413
+ },
2414
+ config: {
2415
+ type: "string",
2416
+ description: "Path to forgemap.config.ts (overrides walk-up discovery)"
2417
+ }
2418
+ },
2419
+ async run({ args }) {
2420
+ const binary = resolveBinary(process.argv[1]);
2421
+ const info = {
2422
+ version: "0.4.1-dev.80-662a8e8",
2423
+ build: detectBuild(binary.resolved),
2424
+ binary,
2425
+ node: process.version,
2426
+ config: await gatherConfig(args.config)
2427
+ };
2428
+ if (args.json) {
2429
+ process.stdout.write(`${JSON.stringify(info, null, 2)}\n`);
2430
+ return;
2431
+ }
2432
+ process.stdout.write(renderPretty(info));
2433
+ }
2434
+ });
2435
+ //#endregion
2246
2436
  //#region src/repos/match.ts
2247
2437
  /**
2248
2438
  * The one Fuse configuration every fuzzy lookup shares — `search`, `pick`
@@ -3141,6 +3331,7 @@ function severitySymbol(severity) {
3141
3331
  runMain(defineCommand({
3142
3332
  meta: {
3143
3333
  name: "forgemap",
3334
+ version: "0.4.1-dev.80-662a8e8",
3144
3335
  description: "Manage a local repo layout of the form <root>/<forge.dir>/<owner>/<repo>"
3145
3336
  },
3146
3337
  subCommands: {
@@ -3191,6 +3382,7 @@ runMain(defineCommand({
3191
3382
  if (!loaded.configFile) consola.warn("No forgemap.config.ts found — using built-in defaults. Run `forgemap config init` to materialize one.");
3192
3383
  }
3193
3384
  }),
3385
+ info: infoCommand,
3194
3386
  completion: completionCommand,
3195
3387
  "shell-init": shellInitCommand,
3196
3388
  config: configCommand