clispark 1.15.0 → 1.16.1

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/cli.js CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import path12 from "path";
4
+ import path14 from "path";
5
5
  import { Command } from "commander";
6
6
 
7
7
  // src/wizard.ts
8
8
  import { intro, outro, text, select, log, isCancel, cancel } from "@clack/prompts";
9
9
 
10
10
  // src/languages/packs/node-oclif.ts
11
- import path4 from "path";
11
+ import path5 from "path";
12
12
 
13
13
  // src/package-root.ts
14
14
  import { existsSync, readFileSync } from "fs";
@@ -222,6 +222,127 @@ var npmRegistryChecker = {
222
222
  applyRegistryUrl
223
223
  };
224
224
 
225
+ // src/languages/command-generators/node-oclif.ts
226
+ import { mkdir, readdir, writeFile as writeFile3 } from "fs/promises";
227
+ import path4 from "path";
228
+
229
+ // src/languages/command-generator.ts
230
+ function buildCommandTree(paths2) {
231
+ const nodesByPath = /* @__PURE__ */ new Map();
232
+ const roots = [];
233
+ function getOrCreateNode(nodePath) {
234
+ let node = nodesByPath.get(nodePath);
235
+ if (!node) {
236
+ const segments = nodePath.split(" ");
237
+ node = { path: nodePath, displayLabel: segments.join(" > "), children: [] };
238
+ nodesByPath.set(nodePath, node);
239
+ if (segments.length === 1) {
240
+ roots.push(node);
241
+ } else {
242
+ const parent = getOrCreateNode(segments.slice(0, -1).join(" "));
243
+ parent.children.push(node);
244
+ }
245
+ }
246
+ return node;
247
+ }
248
+ for (const p of paths2) {
249
+ getOrCreateNode(p);
250
+ }
251
+ return roots;
252
+ }
253
+
254
+ // src/languages/command-generators/node-oclif.ts
255
+ async function collectCommandFiles(dir, baseDir = dir) {
256
+ const entries = await readdir(dir, { withFileTypes: true });
257
+ const files = [];
258
+ for (const entry of entries) {
259
+ const fullPath = path4.join(dir, entry.name);
260
+ if (entry.isDirectory()) {
261
+ files.push(...await collectCommandFiles(fullPath, baseDir));
262
+ } else if (entry.name.endsWith(".ts") && !entry.name.endsWith(".test.ts")) {
263
+ files.push(path4.relative(baseDir, fullPath));
264
+ }
265
+ }
266
+ return files;
267
+ }
268
+ function toCommandPath(relativeFilePath) {
269
+ return relativeFilePath.replace(/\.ts$/, "").split(path4.sep).join(" ");
270
+ }
271
+ async function listExistingCommands(targetDir) {
272
+ const commandsDir = path4.join(targetDir, "src", "commands");
273
+ const files = await collectCommandFiles(commandsDir);
274
+ return buildCommandTree(files.map(toCommandPath));
275
+ }
276
+ function toClassName(pathSegments) {
277
+ return pathSegments.map((seg) => seg[0].toUpperCase() + seg.slice(1)).join("");
278
+ }
279
+ function argFor(param) {
280
+ const opts = [`required: ${param.required}`, `description: '${param.name}'`];
281
+ if (param.type === "enum") {
282
+ opts.push(`options: [${(param.allowedValues ?? []).map((v) => `'${v}'`).join(", ")}]`);
283
+ }
284
+ const argsMethod = param.type === "enum" ? "string" : param.type;
285
+ return `Args.${argsMethod}({ ${opts.join(", ")} })`;
286
+ }
287
+ function generateCommandFileContent(spec) {
288
+ const className = toClassName(spec.pathSegments);
289
+ const argsLines = spec.parameters.map((p) => ` ${p.name}: ${argFor(p)},`).join("\n");
290
+ const logExpr = spec.parameters.map((p) => `${p.name}=\${args.${p.name}}`).join(" ");
291
+ const depth = spec.pathSegments.length;
292
+ const baseCommandImportPath = "../".repeat(depth) + "base-command";
293
+ return `import { Args } from '@oclif/core';
294
+ import { BaseCommand } from '${baseCommandImportPath}';
295
+
296
+ export default class ${className} extends BaseCommand {
297
+ static description = '${spec.pathSegments[spec.pathSegments.length - 1]} command';
298
+ static args = {
299
+ ${argsLines}
300
+ };
301
+ static flags = {};
302
+
303
+ async run(): Promise<void> {
304
+ const { args } = await this.parse(${className});
305
+ this.log(\`${logExpr}\`);
306
+ }
307
+ }
308
+ `;
309
+ }
310
+ function sampleArgValue(param) {
311
+ if (param.type === "enum") return param.allowedValues?.[0] ?? "";
312
+ if (param.type === "integer") return "1";
313
+ if (param.type === "boolean") return "true";
314
+ return "value";
315
+ }
316
+ function generateTestFileContent(spec) {
317
+ const commandInvocation = spec.pathSegments.join(" ");
318
+ const sampleArgs = spec.parameters.map(sampleArgValue).join(" ");
319
+ const fullInvocation = sampleArgs ? `${commandInvocation} ${sampleArgs}` : commandInvocation;
320
+ return `import { describe, it, expect } from 'vitest';
321
+ import { runCommand } from '@oclif/test';
322
+
323
+ describe('${commandInvocation}', () => {
324
+ it('runs successfully', async () => {
325
+ const { error } = await runCommand('${fullInvocation}');
326
+ expect(error).toBeUndefined();
327
+ });
328
+ });
329
+ `;
330
+ }
331
+ async function generateCommand(targetDir, spec) {
332
+ const relDir = path4.join("src", "commands", ...spec.pathSegments.slice(0, -1));
333
+ const fileName = spec.pathSegments[spec.pathSegments.length - 1];
334
+ const commandRelPath = path4.join(relDir, `${fileName}.ts`);
335
+ const testRelPath = path4.join(relDir, `${fileName}.test.ts`);
336
+ await mkdir(path4.join(targetDir, relDir), { recursive: true });
337
+ await writeFile3(path4.join(targetDir, commandRelPath), generateCommandFileContent(spec));
338
+ await writeFile3(path4.join(targetDir, testRelPath), generateTestFileContent(spec));
339
+ return { commandFile: commandRelPath, testFile: testRelPath };
340
+ }
341
+ var nodeOclifCommandGenerator = {
342
+ listExistingCommands,
343
+ generateCommand
344
+ };
345
+
225
346
  // src/languages/packs/node-oclif.ts
226
347
  function validateProjectName(value) {
227
348
  if (!value || value.trim().length === 0) return "Project name is required.";
@@ -233,7 +354,7 @@ function validateProjectName(value) {
233
354
  var nodeOclifPack = {
234
355
  id: "node",
235
356
  displayName: "Node.js / TypeScript (oclif)",
236
- templateDir: path4.join(findPackageRoot(), "templates", "node"),
357
+ templateDir: path5.join(findPackageRoot(), "templates", "node"),
237
358
  scaffoldCommands: [
238
359
  { command: "npm", args: ["install"] },
239
360
  { command: "npm", args: ["run", "build"] }
@@ -246,15 +367,16 @@ var nodeOclifPack = {
246
367
  checkNameAvailability: npmRegistryChecker.checkNameAvailability,
247
368
  applyPrivateIntent: npmRegistryChecker.applyPrivateIntent,
248
369
  applyRegistryUrl: npmRegistryChecker.applyRegistryUrl
249
- }
370
+ },
371
+ commandGenerator: nodeOclifCommandGenerator
250
372
  };
251
373
 
252
374
  // src/languages/packs/dotnet.ts
253
- import path7 from "path";
375
+ import path9 from "path";
254
376
 
255
377
  // src/update/adapters/dotnet.ts
256
- import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
257
- import path5 from "path";
378
+ import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
379
+ import path6 from "path";
258
380
  var CORE_FILE_PATHS2 = [
259
381
  "Cli.slnx",
260
382
  "src/Program.cs",
@@ -366,11 +488,11 @@ var dotnetAdapter = {
366
488
  },
367
489
  manifestFileName: "src/Cli.csproj",
368
490
  async readManifestFile(dir) {
369
- const content = await readFile3(path5.join(dir, "src", "Cli.csproj"), "utf8");
491
+ const content = await readFile3(path6.join(dir, "src", "Cli.csproj"), "utf8");
370
492
  return parseManifestFile(content);
371
493
  },
372
494
  async writeManifestFile(dir, content) {
373
- await writeFile3(path5.join(dir, "src", "Cli.csproj"), content.raw);
495
+ await writeFile4(path6.join(dir, "src", "Cli.csproj"), content.raw);
374
496
  },
375
497
  parseManifestFile,
376
498
  readProjectName(manifestFile) {
@@ -385,8 +507,8 @@ var dotnetAdapter = {
385
507
  };
386
508
 
387
509
  // src/languages/registry-checkers/nuget.ts
388
- import { mkdir, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
389
- import path6 from "path";
510
+ import { mkdir as mkdir2, readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
511
+ import path7 from "path";
390
512
  var NUGET_DEFAULT_REGISTRY_URL = "https://api.nuget.org/v3/index.json";
391
513
  var NUGET_FLATCONTAINER_BASE = "https://api.nuget.org/v3-flatcontainer";
392
514
  var FETCH_TIMEOUT_MS2 = 5e3;
@@ -402,13 +524,13 @@ async function checkNameAvailability2(name) {
402
524
  }
403
525
  }
404
526
  async function applyPrivateIntent2(targetDir) {
405
- const csprojPath = path6.join(targetDir, "src", "Cli.csproj");
527
+ const csprojPath = path7.join(targetDir, "src", "Cli.csproj");
406
528
  const content = await readFile4(csprojPath, "utf8");
407
529
  const updated = content.replace(
408
530
  /(<PropertyGroup>\s*\n)/,
409
531
  "$1 <IsPackable>false</IsPackable>\n"
410
532
  );
411
- await writeFile4(csprojPath, updated);
533
+ await writeFile5(csprojPath, updated);
412
534
  }
413
535
  async function applyRegistryUrl2(targetDir, registryUrl) {
414
536
  const config = [
@@ -421,8 +543,8 @@ async function applyRegistryUrl2(targetDir, registryUrl) {
421
543
  "</configuration>",
422
544
  ""
423
545
  ].join("\n");
424
- await mkdir(targetDir, { recursive: true });
425
- await writeFile4(path6.join(targetDir, "NuGet.config"), config);
546
+ await mkdir2(targetDir, { recursive: true });
547
+ await writeFile5(path7.join(targetDir, "NuGet.config"), config);
426
548
  }
427
549
  var nugetRegistryChecker = {
428
550
  checkNameAvailability: checkNameAvailability2,
@@ -430,6 +552,120 @@ var nugetRegistryChecker = {
430
552
  applyRegistryUrl: applyRegistryUrl2
431
553
  };
432
554
 
555
+ // src/languages/command-generators/dotnet.ts
556
+ import { mkdir as mkdir3, readFile as readFile5, readdir as readdir2, writeFile as writeFile6 } from "fs/promises";
557
+ import path8 from "path";
558
+ async function listExistingCommands2(targetDir) {
559
+ const commandsDir = path8.join(targetDir, "src", "Commands");
560
+ const files = await readdir2(commandsDir);
561
+ const paths2 = [];
562
+ for (const file of files) {
563
+ if (!file.endsWith(".cs")) continue;
564
+ const content = await readFile5(path8.join(commandsDir, file), "utf8");
565
+ const match = content.match(/\[CommandPath\("([^"]+)"\)\]/);
566
+ if (match) paths2.push(match[1]);
567
+ }
568
+ return buildCommandTree(paths2);
569
+ }
570
+ function toClassName2(pathSegments) {
571
+ return pathSegments.map((seg) => seg[0].toUpperCase() + seg.slice(1)).join("") + "Command";
572
+ }
573
+ function csharpDeclType(param) {
574
+ const baseType = param.type === "integer" ? "int" : param.type === "boolean" ? "bool" : "string";
575
+ if (param.required) return baseType;
576
+ return `${baseType}?`;
577
+ }
578
+ function argumentDeclaration(param) {
579
+ const varName = `${param.name}Argument`;
580
+ const declType = csharpDeclType(param);
581
+ const arityLine = param.required ? "" : "\n Arity = ArgumentArity.ZeroOrOne,";
582
+ const lines = [
583
+ ` var ${varName} = new Argument<${declType}>("${param.name}")`,
584
+ ` {`,
585
+ ` Description = "${param.name}",${arityLine}`,
586
+ ` };`
587
+ ];
588
+ if (param.type === "enum") {
589
+ lines.push(` ${varName}.AcceptOnlyFromAmong(${(param.allowedValues ?? []).map((v) => `"${v}"`).join(", ")});`);
590
+ }
591
+ return lines.join("\n");
592
+ }
593
+ function generateCommandFileContent2(spec) {
594
+ const className = toClassName2(spec.pathSegments);
595
+ const commandPath = spec.pathSegments.join(" ");
596
+ const lastSegment = spec.pathSegments[spec.pathSegments.length - 1];
597
+ const argDecls = spec.parameters.map(argumentDeclaration).join("\n\n");
598
+ const addLines = spec.parameters.map((p) => ` command.Arguments.Add(${p.name}Argument);`).join("\n");
599
+ const getValueLines = spec.parameters.map((p) => ` var ${p.name} = parseResult.GetValue(${p.name}Argument);`).join("\n");
600
+ const interpolated = spec.parameters.map((p) => `${p.name}={${p.name}}`).join(" ");
601
+ return `using System.CommandLine;
602
+
603
+ namespace Cli.Commands;
604
+
605
+ [CommandPath("${commandPath}")]
606
+ public sealed class ${className} : ICliCommand
607
+ {
608
+ public Command Build()
609
+ {
610
+ ${argDecls}
611
+
612
+ var command = new Command("${lastSegment}", "${lastSegment} command");
613
+ ${addLines}
614
+ command.SetAction(parseResult =>
615
+ {
616
+ ${getValueLines}
617
+ Console.WriteLine($"${interpolated}");
618
+ });
619
+
620
+ return command;
621
+ }
622
+ }
623
+ `;
624
+ }
625
+ function sampleArgValue2(param) {
626
+ if (param.type === "enum") return param.allowedValues?.[0] ?? "";
627
+ if (param.type === "integer") return "1";
628
+ if (param.type === "boolean") return "true";
629
+ return "value";
630
+ }
631
+ function generateTestFileContent2(spec) {
632
+ const className = toClassName2(spec.pathSegments);
633
+ const sampleArgs = spec.parameters.map(sampleArgValue2);
634
+ return `using System.CommandLine;
635
+ using Cli.Commands;
636
+
637
+ namespace Cli.Tests;
638
+
639
+ public class ${className}Tests
640
+ {
641
+ [Fact]
642
+ public void RunsSuccessfully()
643
+ {
644
+ var command = new ${className}().Build();
645
+ var parseResult = command.Parse([${sampleArgs.map((a) => `"${a}"`).join(", ")}]);
646
+
647
+ var exitCode = parseResult.Invoke();
648
+
649
+ Assert.Equal(0, exitCode);
650
+ }
651
+ }
652
+ `;
653
+ }
654
+ async function generateCommand2(targetDir, spec) {
655
+ const className = toClassName2(spec.pathSegments);
656
+ const commandRelPath = path8.join("src", "Commands", `${className}.cs`);
657
+ const testRelPath = path8.join("tests", `${className}Tests.cs`);
658
+ await mkdir3(path8.join(targetDir, "src", "Commands"), { recursive: true });
659
+ await mkdir3(path8.join(targetDir, "tests"), { recursive: true });
660
+ await writeFile6(path8.join(targetDir, commandRelPath), generateCommandFileContent2(spec));
661
+ await writeFile6(path8.join(targetDir, testRelPath), generateTestFileContent2(spec));
662
+ return { commandFile: commandRelPath, testFile: testRelPath };
663
+ }
664
+ var dotnetCommandGenerator = {
665
+ listExistingCommands: listExistingCommands2,
666
+ generateCommand: generateCommand2
667
+ };
668
+
433
669
  // src/languages/packs/dotnet.ts
434
670
  function validateProjectName2(value) {
435
671
  if (!value || value.trim().length === 0) return "Project name is required.";
@@ -441,7 +677,7 @@ function validateProjectName2(value) {
441
677
  var dotnetPack = {
442
678
  id: "dotnet",
443
679
  displayName: ".NET / C# (System.CommandLine)",
444
- templateDir: path7.join(findPackageRoot(), "templates", "dotnet"),
680
+ templateDir: path9.join(findPackageRoot(), "templates", "dotnet"),
445
681
  scaffoldCommands: [
446
682
  { command: "dotnet", args: ["restore"] },
447
683
  { command: "dotnet", args: ["build"] }
@@ -454,7 +690,8 @@ var dotnetPack = {
454
690
  checkNameAvailability: nugetRegistryChecker.checkNameAvailability,
455
691
  applyPrivateIntent: nugetRegistryChecker.applyPrivateIntent,
456
692
  applyRegistryUrl: nugetRegistryChecker.applyRegistryUrl
457
- }
693
+ },
694
+ commandGenerator: dotnetCommandGenerator
458
695
  };
459
696
 
460
697
  // src/languages/index.ts
@@ -539,15 +776,15 @@ async function runWizard(deps = defaultDeps) {
539
776
  }
540
777
 
541
778
  // src/scaffold.ts
542
- import { cp, readdir, readFile as readFile6, rename, writeFile as writeFile6 } from "fs/promises";
543
- import path9 from "path";
779
+ import { cp, readdir as readdir3, readFile as readFile7, rename, writeFile as writeFile8 } from "fs/promises";
780
+ import path11 from "path";
544
781
  import spawn from "cross-spawn";
545
782
 
546
783
  // src/update/manifest.ts
547
784
  import { createHash } from "crypto";
548
785
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
549
- import { mkdir as mkdir2, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
550
- import path8 from "path";
786
+ import { mkdir as mkdir4, readFile as readFile6, writeFile as writeFile7 } from "fs/promises";
787
+ import path10 from "path";
551
788
  import { fileURLToPath as fileURLToPath2 } from "url";
552
789
 
553
790
  // src/errors.ts
@@ -565,7 +802,7 @@ function hashContent(content) {
565
802
  async function hashCoreFiles(dir, adapter) {
566
803
  const entries = await Promise.all(
567
804
  adapter.coreFilePaths.map(async (relativePath) => {
568
- const content = await readFile5(path8.join(dir, relativePath), "utf8");
805
+ const content = await readFile6(path10.join(dir, relativePath), "utf8");
569
806
  return [relativePath, hashContent(content)];
570
807
  })
571
808
  );
@@ -577,15 +814,15 @@ async function buildManifest(targetDir, generatorVersion, language, adapter) {
577
814
  const { coreDependencies, coreScripts, coreFields } = adapter.extractCoreFields(manifestFile);
578
815
  return { generatorVersion, language, coreFiles, coreDependencies, coreScripts, coreFields };
579
816
  }
580
- var MANIFEST_RELATIVE_PATH = path8.join(".clispark", "manifest.json");
817
+ var MANIFEST_RELATIVE_PATH = path10.join(".clispark", "manifest.json");
581
818
  async function writeManifest(targetDir, manifest) {
582
- const manifestPath = path8.join(targetDir, MANIFEST_RELATIVE_PATH);
583
- await mkdir2(path8.dirname(manifestPath), { recursive: true });
584
- await writeFile5(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
819
+ const manifestPath = path10.join(targetDir, MANIFEST_RELATIVE_PATH);
820
+ await mkdir4(path10.dirname(manifestPath), { recursive: true });
821
+ await writeFile7(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
585
822
  }
586
823
  async function readManifest(targetDir) {
587
824
  try {
588
- const content = await readFile5(path8.join(targetDir, MANIFEST_RELATIVE_PATH), "utf8");
825
+ const content = await readFile6(path10.join(targetDir, MANIFEST_RELATIVE_PATH), "utf8");
589
826
  return JSON.parse(content);
590
827
  } catch {
591
828
  return void 0;
@@ -601,14 +838,14 @@ async function requireManifest(targetDir) {
601
838
  return manifest;
602
839
  }
603
840
  function getGeneratorVersion() {
604
- let dir = path8.dirname(fileURLToPath2(import.meta.url));
841
+ let dir = path10.dirname(fileURLToPath2(import.meta.url));
605
842
  while (true) {
606
- const pkgPath = path8.join(dir, "package.json");
843
+ const pkgPath = path10.join(dir, "package.json");
607
844
  if (existsSync2(pkgPath)) {
608
845
  const pkg = JSON.parse(readFileSync2(pkgPath, "utf8"));
609
846
  if (pkg.name === "clispark") return pkg.version;
610
847
  }
611
- const parentDir = path8.dirname(dir);
848
+ const parentDir = path10.dirname(dir);
612
849
  if (parentDir === dir) {
613
850
  throw new Error("Could not locate clispark's own package.json.");
614
851
  }
@@ -620,7 +857,7 @@ function getGeneratorVersion() {
620
857
  async function assertTargetDirIsUsable(targetDir) {
621
858
  let entries;
622
859
  try {
623
- entries = await readdir(targetDir);
860
+ entries = await readdir3(targetDir);
624
861
  } catch {
625
862
  return;
626
863
  }
@@ -632,10 +869,10 @@ function applyPlaceholders(content, projectName) {
632
869
  return content.replaceAll("{{projectName}}", projectName);
633
870
  }
634
871
  async function collectFiles(dir) {
635
- const entries = await readdir(dir, { withFileTypes: true });
872
+ const entries = await readdir3(dir, { withFileTypes: true });
636
873
  const files = await Promise.all(
637
874
  entries.map((entry) => {
638
- const fullPath = path9.join(dir, entry.name);
875
+ const fullPath = path11.join(dir, entry.name);
639
876
  return entry.isDirectory() ? collectFiles(fullPath) : Promise.resolve([fullPath]);
640
877
  })
641
878
  );
@@ -645,9 +882,9 @@ async function replacePlaceholdersInTree(targetDir, projectName) {
645
882
  const files = await collectFiles(targetDir);
646
883
  await Promise.all(
647
884
  files.map(async (filePath) => {
648
- const content = await readFile6(filePath, "utf8");
885
+ const content = await readFile7(filePath, "utf8");
649
886
  if (content.includes("{{projectName}}")) {
650
- await writeFile6(filePath, applyPlaceholders(content, projectName));
887
+ await writeFile8(filePath, applyPlaceholders(content, projectName));
651
888
  }
652
889
  })
653
890
  );
@@ -656,7 +893,7 @@ async function copyTemplate(options, pack) {
656
893
  const { projectName, targetDir, registryUrl, publishIntent } = options;
657
894
  await assertTargetDirIsUsable(targetDir);
658
895
  await cp(pack.templateDir, targetDir, { recursive: true });
659
- await rename(path9.join(targetDir, "gitignore"), path9.join(targetDir, ".gitignore"));
896
+ await rename(path11.join(targetDir, "gitignore"), path11.join(targetDir, ".gitignore"));
660
897
  await replacePlaceholdersInTree(targetDir, projectName);
661
898
  if (publishIntent === false) {
662
899
  await pack.registry.applyPrivateIntent(targetDir);
@@ -695,7 +932,7 @@ async function scaffoldProject(options, pack, deps = defaultScaffoldDeps) {
695
932
  // src/logger.ts
696
933
  import { randomBytes } from "crypto";
697
934
  import { mkdirSync, readdirSync, statSync, unlinkSync, writeFileSync } from "fs";
698
- import path10 from "path";
935
+ import path12 from "path";
699
936
  import envPaths from "env-paths";
700
937
  import pino from "pino";
701
938
  var paths = envPaths("clispark", { suffix: "" });
@@ -731,7 +968,7 @@ var SWEEP_MARKER_FILE = ".last-sweep";
731
968
  var SWEEP_THROTTLE_MS = 24 * 60 * 60 * 1e3;
732
969
  function sweepOldLogs(logDir) {
733
970
  safely(() => {
734
- const markerPath = path10.join(logDir, SWEEP_MARKER_FILE);
971
+ const markerPath = path12.join(logDir, SWEEP_MARKER_FILE);
735
972
  let shouldSweep = true;
736
973
  try {
737
974
  shouldSweep = Date.now() - statSync(markerPath).mtimeMs >= SWEEP_THROTTLE_MS;
@@ -741,7 +978,7 @@ function sweepOldLogs(logDir) {
741
978
  const cutoffMs = Date.now() - getRetentionDays() * 24 * 60 * 60 * 1e3;
742
979
  for (const file of readdirSync(logDir)) {
743
980
  if (file === SWEEP_MARKER_FILE) continue;
744
- const filePath = path10.join(logDir, file);
981
+ const filePath = path12.join(logDir, file);
745
982
  if (statSync(filePath).mtimeMs < cutoffMs) {
746
983
  unlinkSync(filePath);
747
984
  }
@@ -752,7 +989,7 @@ function sweepOldLogs(logDir) {
752
989
  function createLogger(commandName, logDir = paths.log) {
753
990
  mkdirSync(logDir, { recursive: true });
754
991
  sweepOldLogs(logDir);
755
- const logFilePath = path10.join(logDir, buildLogFileName(commandName));
992
+ const logFilePath = path12.join(logDir, buildLogFileName(commandName));
756
993
  const fileDestination = pino.destination({ dest: logFilePath, sync: true, mode: 384 });
757
994
  const destination = process.env.DEBUG ? pino.multistream([{ stream: fileDestination }, { stream: process.stdout }]) : fileDestination;
758
995
  const logger = pino({ redact: buildRedactPaths([...SENSITIVE_LOG_KEYS, "registryUrl"]) }, destination);
@@ -790,8 +1027,8 @@ function withLogging(commandName, action, logDir = paths.log, loggerFactory = cr
790
1027
  }
791
1028
 
792
1029
  // src/update/update.ts
793
- import { mkdir as mkdir3, readFile as readFile7, writeFile as writeFile7 } from "fs/promises";
794
- import path11 from "path";
1030
+ import { mkdir as mkdir5, readFile as readFile8, writeFile as writeFile9 } from "fs/promises";
1031
+ import path13 from "path";
795
1032
  import spawn2 from "cross-spawn";
796
1033
 
797
1034
  // src/update/releasenotes.ts
@@ -877,7 +1114,7 @@ async function updateProject(targetDir, adapter, templateDir, language, deps = d
877
1114
  const currentManifestFile = await adapter.readManifestFile(targetDir);
878
1115
  const projectName = adapter.readProjectName(currentManifestFile);
879
1116
  const newTemplateRaw = applyPlaceholders(
880
- await readFile7(path11.join(templateDir, adapter.manifestFileName), "utf8"),
1117
+ await readFile8(path13.join(templateDir, adapter.manifestFileName), "utf8"),
881
1118
  projectName
882
1119
  );
883
1120
  const newTemplateManifestFile = adapter.parseManifestFile(newTemplateRaw);
@@ -887,13 +1124,13 @@ async function updateProject(targetDir, adapter, templateDir, language, deps = d
887
1124
  const perFileResults = await Promise.all(
888
1125
  adapter.coreFilePaths.map(async (relativePath) => {
889
1126
  const newContent = applyPlaceholders(
890
- await readFile7(path11.join(templateDir, adapter.templateSourcePath(relativePath)), "utf8"),
1127
+ await readFile8(path13.join(templateDir, adapter.templateSourcePath(relativePath)), "utf8"),
891
1128
  projectName
892
1129
  );
893
1130
  const newHash = hashContent(newContent);
894
1131
  let currentHash;
895
1132
  try {
896
- currentHash = hashContent(await readFile7(path11.join(targetDir, relativePath), "utf8"));
1133
+ currentHash = hashContent(await readFile8(path13.join(targetDir, relativePath), "utf8"));
897
1134
  } catch {
898
1135
  currentHash = void 0;
899
1136
  }
@@ -905,13 +1142,13 @@ async function updateProject(targetDir, adapter, templateDir, language, deps = d
905
1142
  files.push({ path: relativePath, outcome: result.outcome });
906
1143
  newCoreFiles[relativePath] = result.value;
907
1144
  if (result.outcome === "added" || result.outcome === "replaced") {
908
- fileWrites.push({ targetPath: path11.join(targetDir, relativePath), content: newContent });
1145
+ fileWrites.push({ targetPath: path13.join(targetDir, relativePath), content: newContent });
909
1146
  }
910
1147
  }
911
1148
  for (const relativePath of Object.keys(oldManifest.coreFiles)) {
912
1149
  if (adapter.coreFilePaths.includes(relativePath)) continue;
913
1150
  try {
914
- await readFile7(path11.join(targetDir, relativePath), "utf8");
1151
+ await readFile8(path13.join(targetDir, relativePath), "utf8");
915
1152
  files.push({ path: relativePath, outcome: "no-longer-core" });
916
1153
  } catch {
917
1154
  }
@@ -933,8 +1170,8 @@ async function updateProject(targetDir, adapter, templateDir, language, deps = d
933
1170
  };
934
1171
  }
935
1172
  for (const write of fileWrites) {
936
- await mkdir3(path11.dirname(write.targetPath), { recursive: true });
937
- await writeFile7(write.targetPath, write.content);
1173
+ await mkdir5(path13.dirname(write.targetPath), { recursive: true });
1174
+ await writeFile9(write.targetPath, write.content);
938
1175
  }
939
1176
  if (fileMerge.changed) {
940
1177
  await adapter.writeManifestFile(targetDir, fileMerge.updatedFile);
@@ -996,6 +1233,153 @@ function formatUpdateSummary(result) {
996
1233
  return lines.join("\n");
997
1234
  }
998
1235
 
1236
+ // src/add-wizard.ts
1237
+ import { intro as intro2, outro as outro2, select as select2, text as text2, confirm, isCancel as isCancel2, cancel as cancel2, log as log2 } from "@clack/prompts";
1238
+ function exitIfCancelled2(value) {
1239
+ if (isCancel2(value)) {
1240
+ cancel2("Operation cancelled.");
1241
+ process.exit(1);
1242
+ }
1243
+ }
1244
+ var NEW_TOP_LEVEL = "__new_top_level__";
1245
+ var HERE = "__here__";
1246
+ function flattenForMenu(nodes) {
1247
+ const result = [];
1248
+ for (const node of nodes) {
1249
+ result.push({ value: node.path, label: node.displayLabel });
1250
+ result.push(...flattenForMenu(node.children));
1251
+ }
1252
+ return result;
1253
+ }
1254
+ function findNode(nodes, targetPath) {
1255
+ for (const node of nodes) {
1256
+ if (node.path === targetPath) return node;
1257
+ const found = findNode(node.children, targetPath);
1258
+ if (found) return found;
1259
+ }
1260
+ return void 0;
1261
+ }
1262
+ async function selectWithinNode(node) {
1263
+ if (node.children.length === 0) {
1264
+ return node.path.split(" ");
1265
+ }
1266
+ const options = [
1267
+ { value: HERE, label: `Direct subcommand of "${node.path}"` },
1268
+ ...node.children.map((child) => ({ value: child.path, label: `Under "${child.path}"` }))
1269
+ ];
1270
+ const choice = await select2({ message: `Where under "${node.path}"?`, options });
1271
+ exitIfCancelled2(choice);
1272
+ if (choice === HERE) {
1273
+ return node.path.split(" ");
1274
+ }
1275
+ const childNode = node.children.find((c) => c.path === choice);
1276
+ return selectWithinNode(childNode);
1277
+ }
1278
+ async function selectPath(existing) {
1279
+ const options = [{ value: NEW_TOP_LEVEL, label: "New top-level command" }, ...flattenForMenu(existing)];
1280
+ const choice = await select2({ message: "Where should the new command go?", options });
1281
+ exitIfCancelled2(choice);
1282
+ if (choice === NEW_TOP_LEVEL) {
1283
+ return [];
1284
+ }
1285
+ const node = findNode(existing, choice);
1286
+ return selectWithinNode(node);
1287
+ }
1288
+ function flattenPaths(nodes) {
1289
+ return nodes.flatMap((node) => [node.path, ...flattenPaths(node.children)]);
1290
+ }
1291
+ async function collectParameters() {
1292
+ const parameters = [];
1293
+ let hasOptional = false;
1294
+ for (; ; ) {
1295
+ const addMore = await confirm({
1296
+ message: parameters.length === 0 ? "Add a parameter?" : "Add another parameter?"
1297
+ });
1298
+ exitIfCancelled2(addMore);
1299
+ if (!addMore) break;
1300
+ const nameValue = await text2({
1301
+ message: "Parameter name",
1302
+ validate: (value) => {
1303
+ if (!/^[a-z][a-zA-Z0-9]*$/.test(value)) return "Use a single word starting with a lowercase letter.";
1304
+ if (parameters.some((p) => p.name === value)) return "A parameter with this name already exists.";
1305
+ return void 0;
1306
+ }
1307
+ });
1308
+ exitIfCancelled2(nameValue);
1309
+ const name = nameValue;
1310
+ const typeValue = await select2({
1311
+ message: "Parameter type",
1312
+ options: [
1313
+ { value: "string", label: "String" },
1314
+ { value: "integer", label: "Integer" },
1315
+ { value: "boolean", label: "Boolean" },
1316
+ { value: "enum", label: "String with allowed values" }
1317
+ ]
1318
+ });
1319
+ exitIfCancelled2(typeValue);
1320
+ const type = typeValue;
1321
+ let required = false;
1322
+ if (type !== "boolean") {
1323
+ const options = hasOptional ? [{ value: false, label: "Optional" }] : [
1324
+ { value: true, label: "Required" },
1325
+ { value: false, label: "Optional" }
1326
+ ];
1327
+ const requiredValue = await select2({ message: "Required or optional?", options });
1328
+ exitIfCancelled2(requiredValue);
1329
+ required = requiredValue;
1330
+ }
1331
+ if (!required) hasOptional = true;
1332
+ let allowedValues;
1333
+ if (type === "enum") {
1334
+ const valuesInput = await text2({
1335
+ message: "Allowed values (comma-separated)",
1336
+ validate: (value) => {
1337
+ const values = value.split(",").map((v) => v.trim()).filter(Boolean);
1338
+ if (values.length < 2) return "Enter at least two comma-separated values.";
1339
+ for (const v of values) {
1340
+ if (!/^[A-Za-z0-9_-]+$/.test(v)) {
1341
+ return `Invalid value "${v}": use only letters, numbers, hyphens, and underscores.`;
1342
+ }
1343
+ }
1344
+ return void 0;
1345
+ }
1346
+ });
1347
+ exitIfCancelled2(valuesInput);
1348
+ allowedValues = valuesInput.split(",").map((v) => v.trim()).filter(Boolean);
1349
+ }
1350
+ parameters.push({ name, type, required, allowedValues });
1351
+ }
1352
+ return parameters;
1353
+ }
1354
+ async function runAddWizard(targetDir, deps) {
1355
+ intro2("clispark add \u2014 add a new command");
1356
+ const existing = await deps.commandGenerator.listExistingCommands(targetDir);
1357
+ const pathSegments = await selectPath(existing);
1358
+ const existingPaths = new Set(flattenPaths(existing));
1359
+ const nameValue = await text2({
1360
+ message: "Command name",
1361
+ validate: (value) => {
1362
+ if (!/^[a-z][a-zA-Z0-9]*$/.test(value)) return "Use a single word starting with a lowercase letter.";
1363
+ const fullPath = [...pathSegments, value].join(" ");
1364
+ if (existingPaths.has(fullPath)) return `"${fullPath}" already exists.`;
1365
+ return void 0;
1366
+ }
1367
+ });
1368
+ exitIfCancelled2(nameValue);
1369
+ const fullPathSegments = [...pathSegments, nameValue];
1370
+ const parameters = await collectParameters();
1371
+ log2.info(`About to create "${fullPathSegments.join(" ")}" with ${parameters.length} parameter(s).`);
1372
+ const proceed = await confirm({ message: "Proceed?" });
1373
+ exitIfCancelled2(proceed);
1374
+ if (!proceed) {
1375
+ cancel2("Cancelled.");
1376
+ process.exit(1);
1377
+ }
1378
+ const spec = { pathSegments: fullPathSegments, parameters };
1379
+ const result = await deps.commandGenerator.generateCommand(targetDir, spec);
1380
+ outro2(`Created ${result.commandFile} and ${result.testFile}.`);
1381
+ }
1382
+
999
1383
  // src/whoami.ts
1000
1384
  import os from "os";
1001
1385
  var JOKE_API_URL = "https://v2.jokeapi.dev/joke/Programming,Miscellaneous";
@@ -1110,7 +1494,7 @@ function resolvePack(language) {
1110
1494
  program.action(
1111
1495
  (options) => withLogging("scaffold", async (logger) => {
1112
1496
  const answers = await runWizard();
1113
- const targetDir = path12.join(process.cwd(), answers.projectName);
1497
+ const targetDir = path14.join(process.cwd(), answers.projectName);
1114
1498
  const pack = resolvePack(answers.language);
1115
1499
  logger.info({ projectName: answers.projectName, targetDir, language: pack.id }, "scaffold started");
1116
1500
  await scaffoldProject(
@@ -1151,6 +1535,17 @@ program.command("releasenotes").description("Show what changed between this proj
1151
1535
  console.log(formatReleaseNotes(result));
1152
1536
  })
1153
1537
  );
1538
+ program.command("add").description("Add a new command to an already-scaffolded project").action(
1539
+ withLogging("add", async (logger) => {
1540
+ const targetDir = process.cwd();
1541
+ const manifest = await requireManifest(targetDir);
1542
+ const language = manifest.language ?? "node";
1543
+ const pack = resolvePack(language);
1544
+ logger.info({ targetDir, language }, "add started");
1545
+ await runAddWizard(targetDir, { commandGenerator: pack.commandGenerator });
1546
+ logger.info({}, "add completed");
1547
+ })
1548
+ );
1154
1549
  function resolveWhoamiMode(options) {
1155
1550
  if (options.joke && options.fact) {
1156
1551
  throw new UserError("Use either --joke or --fact, not both.");
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/wizard.ts","../src/languages/packs/node-oclif.ts","../src/package-root.ts","../src/update/adapters/node-oclif.ts","../src/update/reconcile.ts","../src/languages/registry-checkers/npm.ts","../src/languages/packs/dotnet.ts","../src/update/adapters/dotnet.ts","../src/languages/registry-checkers/nuget.ts","../src/languages/index.ts","../src/scaffold.ts","../src/update/manifest.ts","../src/errors.ts","../src/logger.ts","../src/update/update.ts","../src/update/releasenotes.ts","../src/whoami.ts","../src/confetti.ts"],"sourcesContent":["// src/cli.ts\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { runWizard } from './wizard';\nimport { scaffoldProject } from './scaffold';\nimport { withLogging } from './logger';\nimport { formatUpdateSummary, updateProject } from './update/update';\nimport { fetchReleaseNotes, formatReleaseNotes } from './update/releasenotes';\nimport { getGeneratorVersion, requireManifest } from './update/manifest';\nimport { LANGUAGE_PACKS } from './languages';\nimport type { LanguagePack } from './languages/pack';\nimport { UserError } from './errors';\nimport { getWhoamiOutput, type WhoamiMode } from './whoami';\nimport { printConfetti } from './confetti';\n\nconst program = new Command();\n\nprogram\n .name('clispark')\n .description('Interactive scaffolding tool for new CLI projects')\n .option('--no-confetti', 'Skip the confetti after a successful run')\n .configureHelp({ showGlobalOptions: true })\n .version(getGeneratorVersion());\n\nfunction resolvePack(language: string): LanguagePack {\n const pack = LANGUAGE_PACKS[language];\n if (!pack) {\n throw new UserError(`Unknown language \"${language}\" — is your clispark installation out of date?`);\n }\n return pack;\n}\n\nprogram.action((options: { confetti?: boolean }) =>\n withLogging('scaffold', async (logger) => {\n const answers = await runWizard();\n const targetDir = path.join(process.cwd(), answers.projectName);\n const pack = resolvePack(answers.language);\n\n logger.info({ projectName: answers.projectName, targetDir, language: pack.id }, 'scaffold started');\n await scaffoldProject(\n {\n projectName: answers.projectName,\n targetDir,\n registryUrl: answers.registryUrl,\n publishIntent: answers.publishIntent,\n },\n pack,\n );\n logger.info({ projectName: answers.projectName }, 'scaffold completed');\n\n console.log(`\\nDone! Your new CLI project is ready at ${targetDir}`);\n if (options.confetti !== false) printConfetti();\n })(),\n);\n\nprogram\n .command('update')\n .description('Update generator-managed core files and dependencies to the latest clispark version')\n .action((_options: unknown, command: Command) =>\n withLogging('update', async (logger) => {\n const targetDir = process.cwd();\n const manifest = await requireManifest(targetDir);\n const language = manifest.language ?? 'node';\n const pack = resolvePack(language);\n logger.info({ targetDir, language }, 'update started');\n const result = await updateProject(targetDir, pack.updateAdapter, pack.templateDir, language);\n logger.info({ status: result.status }, 'update completed');\n console.log(formatUpdateSummary(result));\n const { confetti } = command.optsWithGlobals<{ confetti?: boolean }>();\n if (confetti !== false && result.status === 'updated') printConfetti();\n })(),\n );\n\nprogram\n .command('releasenotes')\n .description(\"Show what changed between this project's generator version and the latest clispark version\")\n .action(\n withLogging('releasenotes', async (logger) => {\n const targetDir = process.cwd();\n logger.info({ targetDir }, 'releasenotes started');\n const result = await fetchReleaseNotes(targetDir);\n logger.info({ status: result.status }, 'releasenotes completed');\n console.log(formatReleaseNotes(result));\n }),\n );\n\nfunction resolveWhoamiMode(options: { joke?: boolean; fact?: boolean }): WhoamiMode {\n if (options.joke && options.fact) {\n throw new UserError('Use either --joke or --fact, not both.');\n }\n if (options.joke) return 'joke';\n if (options.fact) return 'fact';\n return 'random';\n}\n\nprogram\n .command('whoami')\n .description('A little something extra')\n .option('--joke', 'Always show a joke')\n .option('--fact', 'Always show a fun fact about this machine')\n .action((options: { joke?: boolean; fact?: boolean }) =>\n withLogging('whoami', async (logger) => {\n const mode = resolveWhoamiMode(options);\n logger.info({ mode }, 'whoami started');\n console.log(await getWhoamiOutput(fetch, undefined, undefined, mode));\n logger.info({}, 'whoami completed');\n })(),\n );\n\nprogram.parseAsync(process.argv).catch((error: unknown) => {\n console.error(error);\n process.exit(1);\n});\n","// src/wizard.ts\nimport { intro, outro, text, select, log, isCancel, cancel } from '@clack/prompts';\nimport { LANGUAGE_PACKS } from './languages';\nimport type { LanguagePack } from './languages/pack';\nimport type { NameCheckResult } from './languages/registry-checker';\nimport type { Profile, WizardAnswers } from './types';\n\nexport interface WizardDeps {\n languagePacks: Record<string, LanguagePack>;\n}\n\nconst defaultDeps: WizardDeps = {\n languagePacks: LANGUAGE_PACKS,\n};\n\nfunction exitIfCancelled(value: unknown): void {\n if (isCancel(value)) {\n cancel('Operation cancelled.');\n process.exit(1);\n }\n}\n\nexport async function runWizard(deps: WizardDeps = defaultDeps): Promise<WizardAnswers> {\n intro('clispark — scaffold a new CLI project');\n\n const packs = Object.values(deps.languagePacks);\n const languageValue = await select({\n message: 'Which language?',\n options: packs.map((pack) => ({ value: pack.id, label: pack.displayName })),\n });\n exitIfCancelled(languageValue);\n const pack = deps.languagePacks[languageValue as string];\n\n const nameValue = await text({\n message: 'Project name',\n validate: pack.validateProjectName,\n });\n exitIfCancelled(nameValue);\n let projectName = nameValue as string;\n\n const profileValue = await select({\n message: 'Is this a work or private project?',\n options: [\n { value: 'private', label: 'Private' },\n { value: 'work', label: 'Work' },\n ],\n });\n exitIfCancelled(profileValue);\n const profile = profileValue as Profile;\n\n let registryUrl = pack.registry.defaultUrl;\n if (profile === 'work') {\n const registryValue = await text({\n message: pack.registry.promptLabel,\n placeholder: pack.registry.defaultUrl,\n defaultValue: pack.registry.defaultUrl,\n });\n exitIfCancelled(registryValue);\n registryUrl = (registryValue as string) || pack.registry.defaultUrl;\n }\n\n const publishIntentValue = await select({\n message: 'Do you plan to publish this?',\n options: [\n { value: false, label: 'No' },\n { value: true, label: 'Yes' },\n ],\n initialValue: false,\n });\n exitIfCancelled(publishIntentValue);\n const publishIntent = publishIntentValue as boolean;\n\n let nameAvailability: NameCheckResult = 'skipped';\n\n if (publishIntent) {\n nameAvailability = await pack.registry.checkNameAvailability(projectName, registryUrl);\n\n while (nameAvailability === 'taken') {\n log.warn(`\"${projectName}\" is already taken on ${registryUrl}. Please choose a different name.`);\n\n const retryValue = await text({\n message: 'Project name',\n validate: pack.validateProjectName,\n });\n exitIfCancelled(retryValue);\n projectName = retryValue as string;\n\n nameAvailability = await pack.registry.checkNameAvailability(projectName, registryUrl);\n }\n\n if (nameAvailability === 'unverified') {\n log.warn(`Could not verify availability of \"${projectName}\" on ${registryUrl}. Continuing anyway.`);\n }\n }\n\n outro(`Ready to scaffold \"${projectName}\".`);\n\n return { language: pack.id, projectName, profile, registryUrl, publishIntent, nameAvailability };\n}\n","// src/languages/packs/node-oclif.ts\nimport path from 'node:path';\nimport { findPackageRoot } from '../../package-root';\nimport type { LanguagePack } from '../pack';\nimport { nodeOclifAdapter } from '../../update/adapters/node-oclif';\nimport { npmRegistryChecker, NPM_DEFAULT_REGISTRY_URL } from '../registry-checkers/npm';\n\nfunction validateProjectName(value: string): string | undefined {\n if (!value || value.trim().length === 0) return 'Project name is required.';\n if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {\n return 'Use lowercase letters and numbers, with single hyphens between words (no leading, trailing, or repeated hyphens).';\n }\n return undefined;\n}\n\nexport const nodeOclifPack: LanguagePack = {\n id: 'node',\n displayName: 'Node.js / TypeScript (oclif)',\n templateDir: path.join(findPackageRoot(), 'templates', 'node'),\n scaffoldCommands: [\n { command: 'npm', args: ['install'] },\n { command: 'npm', args: ['run', 'build'] },\n ],\n validateProjectName,\n updateAdapter: nodeOclifAdapter,\n registry: {\n defaultUrl: NPM_DEFAULT_REGISTRY_URL,\n promptLabel: 'Custom npm registry URL (leave empty for npmjs.org)',\n checkNameAvailability: npmRegistryChecker.checkNameAvailability,\n applyPrivateIntent: npmRegistryChecker.applyPrivateIntent,\n applyRegistryUrl: npmRegistryChecker.applyRegistryUrl,\n },\n};\n","import { existsSync, readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Finds clispark's own package root by walking up from this module's\n * location. A fixed relative path can't work here: this module's depth\n * below the package root differs between running from source (tests) and\n * running as part of the bundled `dist/cli.js` (tsup flattens everything\n * into one file, so `import.meta.url` no longer reflects the original\n * per-module nesting) — but the walk-up strategy is depth-independent\n * either way, since it doesn't matter where exactly the walk starts.\n */\nexport function findPackageRoot(): string {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n while (true) {\n const pkgPath = path.join(dir, 'package.json');\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as { name?: string };\n if (pkg.name === 'clispark') return dir;\n }\n const parentDir = path.dirname(dir);\n if (parentDir === dir) {\n throw new Error(\"Could not locate clispark's own package.json.\");\n }\n dir = parentDir;\n }\n}\n","// src/update/adapters/node-oclif.ts\nimport { readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Manifest } from '../manifest';\nimport type { CoreFieldsExtraction, ManifestFileMergeResult, UpdateAdapter } from '../adapter';\nimport { deepEquals, reconcileEntry, stringEquals, type FieldOutcome } from '../reconcile';\n\nexport const CORE_FILE_PATHS = [\n 'bin/run.ts',\n 'src/index.ts',\n 'src/base-command.ts',\n 'src/logger.ts',\n 'tsup.config.ts',\n 'vitest.config.ts',\n 'tsconfig.json',\n 'ARCHITECTURE.md',\n '.gitignore',\n] as const;\n\nexport const CORE_SCRIPT_NAMES = ['build', 'postbuild', 'pretest', 'test', 'typecheck'] as const;\n\nexport interface PackageJsonShape {\n name: string;\n version: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n engines?: Record<string, string>;\n oclif?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nfunction currentDependencyValue(\n pkg: PackageJsonShape,\n name: string,\n): { section: 'dependencies' | 'devDependencies'; value: string } | undefined {\n if (pkg.dependencies?.[name] !== undefined) return { section: 'dependencies', value: pkg.dependencies[name] };\n if (pkg.devDependencies?.[name] !== undefined) {\n return { section: 'devDependencies', value: pkg.devDependencies[name] };\n }\n return undefined;\n}\n\nfunction extractCoreFields(pkg: PackageJsonShape): CoreFieldsExtraction {\n const coreDependencies = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n\n const coreScripts: Record<string, string> = {};\n for (const name of CORE_SCRIPT_NAMES) {\n const value = pkg.scripts?.[name];\n if (value !== undefined) coreScripts[name] = value;\n }\n\n return {\n coreDependencies,\n coreScripts,\n coreFields: {\n engines: pkg.engines ?? {},\n oclif: pkg.oclif ?? {},\n },\n };\n}\n\nfunction mergePackageJson(\n currentPkg: PackageJsonShape,\n oldManifest: Manifest,\n newTemplatePkg: PackageJsonShape,\n): ManifestFileMergeResult {\n const updatedFile: PackageJsonShape = { ...currentPkg };\n let changed = false;\n\n const dependencies: FieldOutcome[] = [];\n const coreDependencies: Record<string, string> = {};\n const dependencyNames = new Set([\n ...Object.keys(newTemplatePkg.dependencies ?? {}),\n ...Object.keys(newTemplatePkg.devDependencies ?? {}),\n ]);\n\n for (const name of dependencyNames) {\n const inNewDependencies = newTemplatePkg.dependencies?.[name] !== undefined;\n const newValue = (inNewDependencies ? newTemplatePkg.dependencies : newTemplatePkg.devDependencies)![name];\n const current = currentDependencyValue(currentPkg, name);\n const oldValue = oldManifest.coreDependencies[name];\n\n const result = reconcileEntry(current?.value, oldValue, newValue, stringEquals);\n dependencies.push({ key: name, outcome: result.outcome });\n coreDependencies[name] = result.value;\n\n if (result.outcome !== 'skipped' && result.value !== current?.value) {\n changed = true;\n const section = current?.section ?? (inNewDependencies ? 'dependencies' : 'devDependencies');\n updatedFile[section] = { ...updatedFile[section], [name]: result.value };\n }\n }\n\n const scripts: FieldOutcome[] = [];\n const coreScripts: Record<string, string> = {};\n\n for (const name of CORE_SCRIPT_NAMES) {\n const newValue = newTemplatePkg.scripts?.[name];\n if (newValue === undefined) continue;\n const currentValue = currentPkg.scripts?.[name];\n const oldValue = oldManifest.coreScripts[name];\n\n const result = reconcileEntry(currentValue, oldValue, newValue, stringEquals);\n scripts.push({ key: name, outcome: result.outcome });\n coreScripts[name] = result.value;\n\n if (result.outcome !== 'skipped' && result.value !== currentValue) {\n changed = true;\n updatedFile.scripts = { ...updatedFile.scripts, [name]: result.value };\n }\n }\n\n const oldCoreFields = oldManifest.coreFields as {\n engines?: Record<string, string>;\n oclif?: Record<string, unknown>;\n };\n const fields: FieldOutcome[] = [];\n let enginesValue: Record<string, string> = oldCoreFields.engines ?? {};\n let oclifValue: Record<string, unknown> = oldCoreFields.oclif ?? {};\n\n if (newTemplatePkg.engines !== undefined) {\n const enginesResult = reconcileEntry(\n currentPkg.engines,\n oldCoreFields.engines,\n newTemplatePkg.engines,\n deepEquals,\n );\n fields.push({ key: 'engines', outcome: enginesResult.outcome });\n enginesValue = enginesResult.value;\n if (enginesResult.outcome !== 'skipped' && !deepEquals(enginesResult.value, currentPkg.engines)) {\n changed = true;\n updatedFile.engines = enginesResult.value;\n }\n }\n\n if (newTemplatePkg.oclif !== undefined) {\n const oclifResult = reconcileEntry(currentPkg.oclif, oldCoreFields.oclif, newTemplatePkg.oclif, deepEquals);\n fields.push({ key: 'oclif', outcome: oclifResult.outcome });\n oclifValue = oclifResult.value;\n if (oclifResult.outcome !== 'skipped' && !deepEquals(oclifResult.value, currentPkg.oclif)) {\n changed = true;\n updatedFile.oclif = oclifResult.value;\n }\n }\n\n return {\n updatedFile,\n changed,\n dependencies,\n scripts,\n fields,\n coreDependencies,\n coreScripts,\n coreFields: { engines: enginesValue, oclif: oclifValue },\n };\n}\n\nexport const nodeOclifAdapter: UpdateAdapter = {\n coreFilePaths: CORE_FILE_PATHS,\n\n templateSourcePath(relativePath) {\n return relativePath === '.gitignore' ? 'gitignore' : relativePath;\n },\n\n manifestFileName: 'package.json',\n\n async readManifestFile(dir) {\n const content = await readFile(path.join(dir, 'package.json'), 'utf8');\n return JSON.parse(content) as PackageJsonShape;\n },\n\n async writeManifestFile(dir, content) {\n await writeFile(path.join(dir, 'package.json'), JSON.stringify(content, null, 2) + '\\n');\n },\n\n parseManifestFile(rawContent) {\n return JSON.parse(rawContent) as PackageJsonShape;\n },\n\n readProjectName(manifestFile) {\n return (manifestFile as PackageJsonShape).name;\n },\n\n extractCoreFields(manifestFile) {\n return extractCoreFields(manifestFile as PackageJsonShape);\n },\n\n mergeManifestFile(current, oldManifest, newTemplate) {\n return mergePackageJson(current as PackageJsonShape, oldManifest, newTemplate as PackageJsonShape);\n },\n};\n","export type ReconcileOutcome = 'added' | 'replaced' | 'skipped';\n\n/** A named field/dependency/script whose reconciliation outcome should be reported to the user (e.g. \"pino: replaced\"). */\nexport interface FieldOutcome {\n key: string;\n outcome: ReconcileOutcome;\n}\n\nexport interface ReconcileResult<T> {\n outcome: ReconcileOutcome;\n value: T;\n}\n\nexport function reconcileEntry<T>(\n currentLiveValue: T | undefined,\n oldManifestValue: T | undefined,\n newTemplateValue: T,\n isEqual: (a: T, b: T) => boolean,\n): ReconcileResult<T> {\n if (currentLiveValue === undefined) {\n return { outcome: 'added', value: newTemplateValue };\n }\n if (oldManifestValue !== undefined && isEqual(currentLiveValue, oldManifestValue)) {\n return { outcome: 'replaced', value: newTemplateValue };\n }\n return { outcome: 'skipped', value: oldManifestValue ?? currentLiveValue };\n}\n\nexport function stringEquals(a: string, b: string): boolean {\n return a === b;\n}\n\nexport function deepEquals(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n","// src/languages/registry-checkers/npm.ts\nimport { readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { NameCheckResult, RegistryChecker } from '../registry-checker';\n\nexport const NPM_DEFAULT_REGISTRY_URL = 'https://registry.npmjs.org';\n\nconst FETCH_TIMEOUT_MS = 5000;\n\nasync function checkNameAvailability(name: string, registryUrl: string): Promise<NameCheckResult> {\n const url = `${registryUrl.replace(/\\/$/, '')}/${encodeURIComponent(name)}`;\n\n try {\n const response = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n if (response.status === 404) return 'available';\n if (response.status === 200) return 'taken';\n return 'unverified';\n } catch {\n return 'unverified';\n }\n}\n\nasync function applyPrivateIntent(targetDir: string): Promise<void> {\n const packageJsonPath = path.join(targetDir, 'package.json');\n const pkg = JSON.parse(await readFile(packageJsonPath, 'utf8')) as Record<string, unknown>;\n pkg.private = true;\n await writeFile(packageJsonPath, JSON.stringify(pkg, null, 2) + '\\n');\n}\n\nasync function applyRegistryUrl(targetDir: string, registryUrl: string): Promise<void> {\n await writeFile(path.join(targetDir, '.npmrc'), `registry=${registryUrl}\\n`);\n}\n\nexport const npmRegistryChecker: RegistryChecker = {\n checkNameAvailability,\n applyPrivateIntent,\n applyRegistryUrl,\n};\n","// src/languages/packs/dotnet.ts\nimport path from 'node:path';\nimport { findPackageRoot } from '../../package-root';\nimport type { LanguagePack } from '../pack';\nimport { dotnetAdapter } from '../../update/adapters/dotnet';\nimport { nugetRegistryChecker, NUGET_DEFAULT_REGISTRY_URL } from '../registry-checkers/nuget';\n\nfunction validateProjectName(value: string): string | undefined {\n if (!value || value.trim().length === 0) return 'Project name is required.';\n if (!/^[A-Z][A-Za-z0-9]*$/.test(value)) {\n return 'Use PascalCase, starting with an uppercase letter (e.g. MyTool).';\n }\n return undefined;\n}\n\nexport const dotnetPack: LanguagePack = {\n id: 'dotnet',\n displayName: '.NET / C# (System.CommandLine)',\n templateDir: path.join(findPackageRoot(), 'templates', 'dotnet'),\n scaffoldCommands: [\n { command: 'dotnet', args: ['restore'] },\n { command: 'dotnet', args: ['build'] },\n ],\n validateProjectName,\n updateAdapter: dotnetAdapter,\n registry: {\n defaultUrl: NUGET_DEFAULT_REGISTRY_URL,\n promptLabel: 'Custom NuGet feed URL (leave empty for nuget.org)',\n checkNameAvailability: nugetRegistryChecker.checkNameAvailability,\n applyPrivateIntent: nugetRegistryChecker.applyPrivateIntent,\n applyRegistryUrl: nugetRegistryChecker.applyRegistryUrl,\n },\n};\n","// src/update/adapters/dotnet.ts\nimport { readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Manifest } from '../manifest';\nimport type { CoreFieldsExtraction, ManifestFileMergeResult, UpdateAdapter } from '../adapter';\nimport { reconcileEntry, stringEquals, type FieldOutcome } from '../reconcile';\n\nexport const CORE_FILE_PATHS = [\n 'Cli.slnx',\n 'src/Program.cs',\n 'src/ICliCommand.cs',\n 'src/CommandPathAttribute.cs',\n 'src/CommandDiscovery.cs',\n 'src/CliUserException.cs',\n 'src/Logging/CliLoggerFactory.cs',\n 'src/Logging/SensitivePropertyEnricher.cs',\n 'tests/Cli.Tests.csproj',\n 'ARCHITECTURE.md',\n '.gitignore',\n] as const;\n\nexport interface DotnetManifestFile {\n raw: string;\n version: string;\n targetFramework: string;\n packageId: string;\n toolCommandName: string;\n packageReferences: Record<string, string>;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction extractTag(content: string, tag: string): string {\n const match = content.match(new RegExp(`<${tag}>([^<]*)</${tag}>`));\n if (!match) throw new Error(`.csproj is missing a <${tag}> tag`);\n return match[1];\n}\n\nfunction extractPackageReferences(content: string): Record<string, string> {\n const refs: Record<string, string> = {};\n const re = /<PackageReference\\s+Include=\"([^\"]+)\"\\s+Version=\"([^\"]+)\"\\s*\\/>/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(content))) {\n refs[m[1]] = m[2];\n }\n return refs;\n}\n\nfunction setTag(content: string, tag: string, value: string): string {\n const escapedTag = escapeRegExp(tag);\n return content.replace(new RegExp(`(<${escapedTag}>)[^<]*(</${escapedTag}>)`), `$1${value}$2`);\n}\n\nfunction setPackageReferenceVersion(content: string, name: string, version: string): string {\n const re = new RegExp(`(<PackageReference\\\\s+Include=\"${escapeRegExp(name)}\"\\\\s+Version=\")[^\"]+(\")`);\n return content.replace(re, `$1${version}$2`);\n}\n\nfunction addPackageReference(content: string, name: string, version: string): string {\n // Reuses the indentation of the last existing <PackageReference> line\n // immediately preceding </ItemGroup>, so the new line matches siblings exactly.\n const re = /^([ \\t]*)<PackageReference[^\\n]*\\/>\\n(?=[ \\t]*<\\/ItemGroup>)/m;\n return content.replace(re, (match, indent: string) => `${match}${indent}<PackageReference Include=\"${name}\" Version=\"${version}\" />\\n`);\n}\n\nfunction parseManifestFile(rawContent: string): DotnetManifestFile {\n return {\n raw: rawContent,\n version: extractTag(rawContent, 'Version'),\n targetFramework: extractTag(rawContent, 'TargetFramework'),\n packageId: extractTag(rawContent, 'PackageId'),\n toolCommandName: extractTag(rawContent, 'ToolCommandName'),\n packageReferences: extractPackageReferences(rawContent),\n };\n}\n\nfunction extractCoreFields(manifestFile: DotnetManifestFile): CoreFieldsExtraction {\n return {\n coreDependencies: manifestFile.packageReferences,\n coreScripts: {},\n coreFields: { TargetFramework: manifestFile.targetFramework },\n };\n}\n\nfunction mergeManifestFile(\n current: DotnetManifestFile,\n oldManifest: Manifest,\n newTemplate: DotnetManifestFile,\n): ManifestFileMergeResult {\n let raw = current.raw;\n let changed = false;\n\n const dependencies: FieldOutcome[] = [];\n const coreDependencies: Record<string, string> = {};\n\n for (const name of Object.keys(newTemplate.packageReferences)) {\n const newValue = newTemplate.packageReferences[name];\n const currentValue = current.packageReferences[name];\n const oldValue = oldManifest.coreDependencies[name];\n\n const result = reconcileEntry(currentValue, oldValue, newValue, stringEquals);\n dependencies.push({ key: name, outcome: result.outcome });\n coreDependencies[name] = result.value;\n\n if (result.outcome === 'added') {\n changed = true;\n raw = addPackageReference(raw, name, result.value);\n } else if (result.outcome !== 'skipped' && result.value !== currentValue) {\n changed = true;\n raw = setPackageReferenceVersion(raw, name, result.value);\n }\n }\n\n const oldCoreFields = oldManifest.coreFields as { TargetFramework?: string };\n const fields: FieldOutcome[] = [];\n\n const targetFrameworkResult = reconcileEntry(\n current.targetFramework,\n oldCoreFields.TargetFramework,\n newTemplate.targetFramework,\n stringEquals,\n );\n fields.push({ key: 'TargetFramework', outcome: targetFrameworkResult.outcome });\n if (targetFrameworkResult.outcome !== 'skipped' && targetFrameworkResult.value !== current.targetFramework) {\n changed = true;\n raw = setTag(raw, 'TargetFramework', targetFrameworkResult.value);\n }\n\n return {\n updatedFile: { ...current, raw },\n changed,\n dependencies,\n scripts: [],\n fields,\n coreDependencies,\n coreScripts: {},\n coreFields: { TargetFramework: targetFrameworkResult.value },\n };\n}\n\nexport const dotnetAdapter: UpdateAdapter = {\n coreFilePaths: CORE_FILE_PATHS,\n\n templateSourcePath(relativePath) {\n return relativePath === '.gitignore' ? 'gitignore' : relativePath;\n },\n\n manifestFileName: 'src/Cli.csproj',\n\n async readManifestFile(dir) {\n const content = await readFile(path.join(dir, 'src', 'Cli.csproj'), 'utf8');\n return parseManifestFile(content);\n },\n\n async writeManifestFile(dir, content) {\n await writeFile(path.join(dir, 'src', 'Cli.csproj'), (content as DotnetManifestFile).raw);\n },\n\n parseManifestFile,\n\n readProjectName(manifestFile) {\n return (manifestFile as DotnetManifestFile).packageId;\n },\n\n extractCoreFields(manifestFile) {\n return extractCoreFields(manifestFile as DotnetManifestFile);\n },\n\n mergeManifestFile(current, oldManifest, newTemplate) {\n return mergeManifestFile(current as DotnetManifestFile, oldManifest, newTemplate as DotnetManifestFile);\n },\n};\n","// src/languages/registry-checkers/nuget.ts\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { NameCheckResult, RegistryChecker } from '../registry-checker';\n\nexport const NUGET_DEFAULT_REGISTRY_URL = 'https://api.nuget.org/v3/index.json';\n\nconst NUGET_FLATCONTAINER_BASE = 'https://api.nuget.org/v3-flatcontainer';\nconst FETCH_TIMEOUT_MS = 5000;\n\nasync function checkNameAvailability(name: string): Promise<NameCheckResult> {\n const url = `${NUGET_FLATCONTAINER_BASE}/${encodeURIComponent(name.toLowerCase())}/index.json`;\n\n try {\n const response = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n if (response.status === 404) return 'available';\n if (response.status === 200) return 'taken';\n return 'unverified';\n } catch {\n return 'unverified';\n }\n}\n\nasync function applyPrivateIntent(targetDir: string): Promise<void> {\n const csprojPath = path.join(targetDir, 'src', 'Cli.csproj');\n const content = await readFile(csprojPath, 'utf8');\n const updated = content.replace(\n /(<PropertyGroup>\\s*\\n)/,\n '$1 <IsPackable>false</IsPackable>\\n',\n );\n await writeFile(csprojPath, updated);\n}\n\nasync function applyRegistryUrl(targetDir: string, registryUrl: string): Promise<void> {\n const config = [\n '<?xml version=\"1.0\" encoding=\"utf-8\"?>',\n '<configuration>',\n ' <packageSources>',\n ' <clear />',\n ` <add key=\"custom\" value=\"${registryUrl}\" />`,\n ' </packageSources>',\n '</configuration>',\n '',\n ].join('\\n');\n await mkdir(targetDir, { recursive: true });\n await writeFile(path.join(targetDir, 'NuGet.config'), config);\n}\n\nexport const nugetRegistryChecker: RegistryChecker = {\n checkNameAvailability,\n applyPrivateIntent,\n applyRegistryUrl,\n};\n","// src/languages/index.ts\nimport type { LanguagePack } from './pack';\nimport { nodeOclifPack } from './packs/node-oclif';\nimport { dotnetPack } from './packs/dotnet';\n\nexport const LANGUAGE_PACKS: Record<string, LanguagePack> = {\n [nodeOclifPack.id]: nodeOclifPack,\n [dotnetPack.id]: dotnetPack,\n};\n\nexport function getPackById(id: string): LanguagePack | undefined {\n return LANGUAGE_PACKS[id];\n}\n","// src/scaffold.ts\nimport { cp, readdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport spawn from 'cross-spawn';\nimport type { LanguagePack } from './languages/pack';\nimport { buildManifest, getGeneratorVersion, writeManifest } from './update/manifest';\nimport { UserError } from './errors';\n\nexport interface ScaffoldOptions {\n projectName: string;\n targetDir: string;\n registryUrl?: string;\n publishIntent?: boolean;\n}\n\nasync function assertTargetDirIsUsable(targetDir: string): Promise<void> {\n let entries: string[];\n try {\n entries = await readdir(targetDir);\n } catch {\n return;\n }\n if (entries.length > 0) {\n throw new UserError(`Directory \"${targetDir}\" already exists and is not empty.`);\n }\n}\n\nexport function applyPlaceholders(content: string, projectName: string): string {\n return content.replaceAll('{{projectName}}', projectName);\n}\n\nasync function collectFiles(dir: string): Promise<string[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const files = await Promise.all(\n entries.map((entry) => {\n const fullPath = path.join(dir, entry.name);\n return entry.isDirectory() ? collectFiles(fullPath) : Promise.resolve([fullPath]);\n }),\n );\n return files.flat();\n}\n\n// Scans every copied file rather than a hardcoded list, so a new template file\n// that needs {{projectName}} substituted can't silently be forgotten here.\nasync function replacePlaceholdersInTree(targetDir: string, projectName: string): Promise<void> {\n const files = await collectFiles(targetDir);\n await Promise.all(\n files.map(async (filePath) => {\n const content = await readFile(filePath, 'utf8');\n if (content.includes('{{projectName}}')) {\n await writeFile(filePath, applyPlaceholders(content, projectName));\n }\n }),\n );\n}\n\nexport async function copyTemplate(options: ScaffoldOptions, pack: LanguagePack): Promise<void> {\n const { projectName, targetDir, registryUrl, publishIntent } = options;\n\n await assertTargetDirIsUsable(targetDir);\n await cp(pack.templateDir, targetDir, { recursive: true });\n\n await rename(path.join(targetDir, 'gitignore'), path.join(targetDir, '.gitignore'));\n\n await replacePlaceholdersInTree(targetDir, projectName);\n\n if (publishIntent === false) {\n await pack.registry.applyPrivateIntent(targetDir);\n }\n\n if (registryUrl && registryUrl !== pack.registry.defaultUrl) {\n await pack.registry.applyRegistryUrl(targetDir, registryUrl);\n }\n}\n\nexport interface ScaffoldDeps {\n runCommand: (command: string, args: string[], cwd: string) => Promise<void>;\n}\n\nasync function defaultRunCommand(command: string, args: string[], cwd: string): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(command, args, { cwd, stdio: 'inherit' });\n child.on('error', reject);\n child.on('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`Command \"${command} ${args.join(' ')}\" exited with code ${code}`));\n }\n });\n });\n}\n\nconst defaultScaffoldDeps: ScaffoldDeps = { runCommand: defaultRunCommand };\n\nexport async function scaffoldProject(\n options: ScaffoldOptions,\n pack: LanguagePack,\n deps: ScaffoldDeps = defaultScaffoldDeps,\n): Promise<void> {\n await copyTemplate(options, pack);\n\n const { targetDir } = options;\n const manifest = await buildManifest(targetDir, getGeneratorVersion(), pack.id, pack.updateAdapter);\n await writeManifest(targetDir, manifest);\n\n await deps.runCommand('git', ['init'], targetDir);\n await deps.runCommand('git', ['add', '-A'], targetDir);\n await deps.runCommand('git', ['commit', '-m', 'chore: initial scaffold from clispark'], targetDir);\n\n for (const scaffoldCommand of pack.scaffoldCommands) {\n await deps.runCommand(scaffoldCommand.command, scaffoldCommand.args, targetDir);\n }\n}\n","// src/update/manifest.ts\nimport { createHash } from 'node:crypto';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { UserError } from '../errors';\nimport type { UpdateAdapter } from './adapter';\n\nexport interface Manifest {\n generatorVersion: string;\n language: string;\n coreFiles: Record<string, string>;\n coreDependencies: Record<string, string>;\n coreScripts: Record<string, string>;\n coreFields: Record<string, unknown>;\n}\n\nexport function hashContent(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nexport async function hashCoreFiles(dir: string, adapter: UpdateAdapter): Promise<Record<string, string>> {\n const entries = await Promise.all(\n adapter.coreFilePaths.map(async (relativePath) => {\n const content = await readFile(path.join(dir, relativePath), 'utf8');\n return [relativePath, hashContent(content)] as const;\n }),\n );\n return Object.fromEntries(entries);\n}\n\nexport async function buildManifest(\n targetDir: string,\n generatorVersion: string,\n language: string,\n adapter: UpdateAdapter,\n): Promise<Manifest> {\n const coreFiles = await hashCoreFiles(targetDir, adapter);\n const manifestFile = await adapter.readManifestFile(targetDir);\n const { coreDependencies, coreScripts, coreFields } = adapter.extractCoreFields(manifestFile);\n return { generatorVersion, language, coreFiles, coreDependencies, coreScripts, coreFields };\n}\n\nexport const MANIFEST_RELATIVE_PATH = path.join('.clispark', 'manifest.json');\n\nexport async function writeManifest(targetDir: string, manifest: Manifest): Promise<void> {\n const manifestPath = path.join(targetDir, MANIFEST_RELATIVE_PATH);\n await mkdir(path.dirname(manifestPath), { recursive: true });\n await writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\\n');\n}\n\nexport async function readManifest(targetDir: string): Promise<Manifest | undefined> {\n try {\n const content = await readFile(path.join(targetDir, MANIFEST_RELATIVE_PATH), 'utf8');\n return JSON.parse(content) as Manifest;\n } catch {\n return undefined;\n }\n}\n\nexport async function requireManifest(targetDir: string): Promise<Manifest> {\n const manifest = await readManifest(targetDir);\n if (!manifest) {\n throw new UserError(\n 'No .clispark/manifest.json found — this project predates update support, or is not a clispark project.',\n );\n }\n return manifest;\n}\n\n/**\n * Finds clispark's own package.json by walking up from this file's location.\n * A fixed relative path (`../package.json`) can't work here: this module's\n * depth below the package root differs between running from source (tests)\n * and running as part of the bundled `dist/cli.js` (tsup flattens everything\n * into one file, so `import.meta.url` no longer reflects the original\n * per-module nesting).\n */\nexport function getGeneratorVersion(): string {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n while (true) {\n const pkgPath = path.join(dir, 'package.json');\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as { name?: string; version: string };\n if (pkg.name === 'clispark') return pkg.version;\n }\n const parentDir = path.dirname(dir);\n if (parentDir === dir) {\n throw new Error(\"Could not locate clispark's own package.json.\");\n }\n dir = parentDir;\n }\n}\n","// src/errors.ts\n\n/** An expected, user-fixable failure (bad input, unmet precondition) — distinct from an unexpected crash. */\nexport class UserError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UserError';\n }\n}\n","import { randomBytes } from 'node:crypto';\nimport { mkdirSync, readdirSync, statSync, unlinkSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\nimport envPaths from 'env-paths';\nimport pino, { type Logger } from 'pino';\n\nconst paths = envPaths('clispark', { suffix: '' });\n\n/** Runs fn, silently swallowing any error — for best-effort work that must never abort the caller. */\nexport function safely(fn: () => void): void {\n try {\n fn();\n } catch {\n // best-effort; a failure here must never affect the surrounding operation\n }\n}\n\nexport interface LoggerHandle {\n logger: Logger;\n logFilePath: string;\n}\n\nfunction buildLogFileName(commandName: string): string {\n const timestamp = new Date().toISOString().replaceAll(/[:.]/g, '-');\n const suffix = randomBytes(3).toString('hex');\n return `${commandName}-${timestamp}-${suffix}.log`;\n}\n\nfunction getRetentionDays(): number {\n const parsed = Number(process.env.LOG_RETENTION_DAYS);\n return Number.isFinite(parsed) ? parsed : 14;\n}\n\n// Common secret-shaped field names, redacted at the top level and one level of\n// nesting (`*.<key>`). Edit this list directly if your own logging needs more.\nexport const SENSITIVE_LOG_KEYS = [\n 'password',\n 'secret',\n 'token',\n 'apiKey',\n 'accessToken',\n 'refreshToken',\n 'clientSecret',\n 'authorization',\n];\n\nfunction buildRedactPaths(keys: string[]): string[] {\n return keys.flatMap((key) => [key, `*.${key}`]);\n}\n\nconst SWEEP_MARKER_FILE = '.last-sweep';\nconst SWEEP_THROTTLE_MS = 24 * 60 * 60 * 1000; // once a day is enough given day-granularity retention\n\nfunction sweepOldLogs(logDir: string): void {\n safely(() => {\n const markerPath = path.join(logDir, SWEEP_MARKER_FILE);\n let shouldSweep = true;\n try {\n shouldSweep = Date.now() - statSync(markerPath).mtimeMs >= SWEEP_THROTTLE_MS;\n } catch {\n // no marker yet (first run in this directory) - sweep now\n }\n if (!shouldSweep) return;\n\n const cutoffMs = Date.now() - getRetentionDays() * 24 * 60 * 60 * 1000;\n for (const file of readdirSync(logDir)) {\n if (file === SWEEP_MARKER_FILE) continue;\n const filePath = path.join(logDir, file);\n if (statSync(filePath).mtimeMs < cutoffMs) {\n unlinkSync(filePath);\n }\n }\n writeFileSync(markerPath, '');\n });\n}\n\nexport function createLogger(commandName: string, logDir: string = paths.log): LoggerHandle {\n mkdirSync(logDir, { recursive: true });\n sweepOldLogs(logDir);\n\n const logFilePath = path.join(logDir, buildLogFileName(commandName));\n const fileDestination = pino.destination({ dest: logFilePath, sync: true, mode: 0o600 });\n const destination = process.env.DEBUG\n ? pino.multistream([{ stream: fileDestination }, { stream: process.stdout }])\n : fileDestination;\n const logger = pino({ redact: buildRedactPaths([...SENSITIVE_LOG_KEYS, 'registryUrl']) }, destination);\n\n return { logger, logFilePath };\n}\n\nexport function withLogging(\n commandName: string,\n action: (logger: Logger) => Promise<void>,\n logDir: string = paths.log,\n loggerFactory: typeof createLogger = createLogger,\n): () => Promise<void> {\n return async () => {\n let handle: LoggerHandle;\n try {\n handle = loggerFactory(commandName, logDir);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(`\\n✖ ${message}`);\n process.exit(1);\n return;\n }\n\n const { logger, logFilePath } = handle;\n safely(() => logger.info({ command: commandName }, 'started'));\n\n try {\n await action(logger);\n safely(() => logger.info({ command: commandName }, 'completed'));\n if (process.env.DEBUG) {\n console.log(`Details: ${logFilePath}`);\n }\n } catch (error) {\n safely(() => logger.error({ command: commandName, err: error }, 'failed'));\n const message = error instanceof Error ? error.message : String(error);\n console.error(`\\n✖ ${message}`);\n console.error(`Details: ${logFilePath}`);\n process.exit(1);\n }\n };\n}\n","// src/update/update.ts\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport spawn from 'cross-spawn';\nimport { applyPlaceholders } from '../scaffold';\nimport { getGeneratorVersion, hashContent, requireManifest, writeManifest, type Manifest } from './manifest';\nimport { reconcileEntry, stringEquals, type FieldOutcome } from './reconcile';\nimport { UserError } from '../errors';\nimport { compareVersions } from './releasenotes';\nimport type { UpdateAdapter } from './adapter';\n\nexport interface UpdateDeps {\n runCommand: (command: string, args: string[], cwd: string) => Promise<void>;\n captureCommand: (command: string, args: string[], cwd: string) => Promise<string>;\n}\n\nasync function defaultRunCommand(command: string, args: string[], cwd: string): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(command, args, { cwd, stdio: 'inherit' });\n child.on('error', reject);\n child.on('close', (code) => {\n if (code === 0) resolve();\n else reject(new Error(`Command \"${command} ${args.join(' ')}\" exited with code ${code}`));\n });\n });\n}\n\nasync function defaultCaptureCommand(command: string, args: string[], cwd: string): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n const child = spawn(command, args, { cwd });\n let stdout = '';\n child.stdout?.on('data', (chunk: Buffer) => {\n stdout += chunk.toString();\n });\n child.on('error', reject);\n child.on('close', (code) => {\n if (code === 0) resolve(stdout);\n else reject(new Error(`Command \"${command} ${args.join(' ')}\" exited with code ${code}`));\n });\n });\n}\n\nconst defaultUpdateDeps: UpdateDeps = { runCommand: defaultRunCommand, captureCommand: defaultCaptureCommand };\n\nexport interface FileOutcomeEntry {\n path: string;\n outcome: 'added' | 'replaced' | 'skipped' | 'no-longer-core';\n}\n\nexport interface UpdateResult {\n status: 'up-to-date' | 'no-changes' | 'updated';\n fromVersion: string;\n toVersion: string;\n files: FileOutcomeEntry[];\n dependencies: FieldOutcome[];\n scripts: FieldOutcome[];\n fields: FieldOutcome[];\n}\n\nexport async function updateProject(\n targetDir: string,\n adapter: UpdateAdapter,\n templateDir: string,\n language: string,\n deps: UpdateDeps = defaultUpdateDeps,\n): Promise<UpdateResult> {\n const status = (await deps.captureCommand('git', ['status', '--porcelain'], targetDir)).trim();\n if (status.length > 0) {\n throw new UserError('Working tree is not clean. Commit or stash your changes before running update.');\n }\n\n const oldManifest = await requireManifest(targetDir);\n const toVersion = getGeneratorVersion();\n const fromVersion = oldManifest.generatorVersion;\n\n if (compareVersions(fromVersion, toVersion) >= 0) {\n return { status: 'up-to-date', fromVersion, toVersion, files: [], dependencies: [], scripts: [], fields: [] };\n }\n\n const currentManifestFile = await adapter.readManifestFile(targetDir);\n const projectName = adapter.readProjectName(currentManifestFile);\n\n const newTemplateRaw = applyPlaceholders(\n await readFile(path.join(templateDir, adapter.manifestFileName), 'utf8'),\n projectName,\n );\n const newTemplateManifestFile = adapter.parseManifestFile(newTemplateRaw);\n\n const files: FileOutcomeEntry[] = [];\n const newCoreFiles: Record<string, string> = {};\n const fileWrites: { targetPath: string; content: string }[] = [];\n\n // Reads + hashes run in parallel; results are then applied in adapter.coreFilePaths\n // order below so files/fileWrites stay deterministic regardless of I/O timing.\n const perFileResults = await Promise.all(\n adapter.coreFilePaths.map(async (relativePath) => {\n const newContent = applyPlaceholders(\n await readFile(path.join(templateDir, adapter.templateSourcePath(relativePath)), 'utf8'),\n projectName,\n );\n const newHash = hashContent(newContent);\n\n let currentHash: string | undefined;\n try {\n currentHash = hashContent(await readFile(path.join(targetDir, relativePath), 'utf8'));\n } catch {\n currentHash = undefined;\n }\n\n const result = reconcileEntry(currentHash, oldManifest.coreFiles[relativePath], newHash, stringEquals);\n return { relativePath, newContent, result };\n }),\n );\n\n for (const { relativePath, newContent, result } of perFileResults) {\n files.push({ path: relativePath, outcome: result.outcome });\n newCoreFiles[relativePath] = result.value;\n\n if (result.outcome === 'added' || result.outcome === 'replaced') {\n fileWrites.push({ targetPath: path.join(targetDir, relativePath), content: newContent });\n }\n }\n\n for (const relativePath of Object.keys(oldManifest.coreFiles)) {\n if (adapter.coreFilePaths.includes(relativePath)) continue;\n try {\n await readFile(path.join(targetDir, relativePath), 'utf8');\n files.push({ path: relativePath, outcome: 'no-longer-core' });\n } catch {\n // already gone locally, nothing to report\n }\n }\n\n const fileMerge = adapter.mergeManifestFile(currentManifestFile, oldManifest, newTemplateManifestFile);\n\n const hasFileChanges = files.some(\n (f) => f.outcome === 'added' || f.outcome === 'replaced' || f.outcome === 'no-longer-core',\n );\n const hasChanges = hasFileChanges || fileMerge.changed;\n\n if (!hasChanges) {\n return {\n status: 'no-changes',\n fromVersion,\n toVersion,\n files,\n dependencies: fileMerge.dependencies,\n scripts: fileMerge.scripts,\n fields: fileMerge.fields,\n };\n }\n\n for (const write of fileWrites) {\n await mkdir(path.dirname(write.targetPath), { recursive: true });\n await writeFile(write.targetPath, write.content);\n }\n\n if (fileMerge.changed) {\n await adapter.writeManifestFile(targetDir, fileMerge.updatedFile);\n }\n\n const newManifest: Manifest = {\n generatorVersion: toVersion,\n language,\n coreFiles: newCoreFiles,\n coreDependencies: fileMerge.coreDependencies,\n coreScripts: fileMerge.coreScripts,\n coreFields: fileMerge.coreFields,\n };\n await writeManifest(targetDir, newManifest);\n\n await deps.runCommand('git', ['add', '-A'], targetDir);\n await deps.runCommand('git', ['commit', '-m', `chore: update clispark core to v${toVersion}`], targetDir);\n\n return {\n status: 'updated',\n fromVersion,\n toVersion,\n files,\n dependencies: fileMerge.dependencies,\n scripts: fileMerge.scripts,\n fields: fileMerge.fields,\n };\n}\n\nexport function formatUpdateSummary(result: UpdateResult): string {\n if (result.status === 'up-to-date') {\n return `Already up to date (v${result.toVersion}).`;\n }\n\n const added = result.files.filter((f) => f.outcome === 'added');\n const replaced = result.files.filter((f) => f.outcome === 'replaced');\n const skipped = result.files.filter((f) => f.outcome === 'skipped');\n const noLongerCore = result.files.filter((f) => f.outcome === 'no-longer-core');\n\n const lines: string[] = [];\n if (result.status === 'no-changes') {\n lines.push(\n noLongerCore.length\n ? `No changes applied: nothing to update since v${result.fromVersion}.`\n : `No changes applied: every core file/field has been modified locally since v${result.fromVersion}.`,\n );\n } else {\n lines.push(`Updated core from v${result.fromVersion} to v${result.toVersion}.`);\n }\n\n if (added.length) lines.push(` New: ${added.map((f) => f.path).join(', ')}`);\n if (replaced.length) lines.push(` Updated: ${replaced.map((f) => f.path).join(', ')}`);\n if (skipped.length) lines.push(` Skipped (locally modified): ${skipped.map((f) => f.path).join(', ')}`);\n if (noLongerCore.length) {\n lines.push(\n ` No longer part of the core, safe to remove manually: ${noLongerCore.map((f) => f.path).join(', ')}`,\n );\n }\n\n const fieldOutcomes = [...result.dependencies, ...result.scripts, ...result.fields].filter(\n (o) => o.outcome !== 'skipped',\n );\n if (fieldOutcomes.length) {\n lines.push(` Manifest: ${fieldOutcomes.map((o) => `${o.key} (${o.outcome})`).join(', ')}`);\n }\n\n if (result.status === 'updated') {\n lines.push('Run \"clispark releasenotes\" to see what changed.');\n }\n\n return lines.join('\\n');\n}\n","// src/update/releasenotes.ts\nimport { getGeneratorVersion, requireManifest } from './manifest';\n\nexport interface GitHubRelease {\n tag_name: string;\n name: string;\n body: string;\n}\n\nfunction stripV(version: string): string {\n return version.startsWith('v') ? version.slice(1) : version;\n}\n\nexport function compareVersions(a: string, b: string): number {\n const partsA = stripV(a).split('.').map(Number);\n const partsB = stripV(b).split('.').map(Number);\n const length = Math.max(partsA.length, partsB.length);\n for (let i = 0; i < length; i++) {\n const diff = (partsA[i] ?? 0) - (partsB[i] ?? 0);\n if (diff !== 0) return diff;\n }\n return 0;\n}\n\nexport interface ReleaseNotesResult {\n status: 'up-to-date' | 'releases-found';\n fromVersion: string;\n toVersion: string;\n releases: GitHubRelease[];\n}\n\nconst RELEASES_URL = 'https://api.github.com/repos/martinwichner/clispark/releases';\nconst FETCH_TIMEOUT_MS = 5000;\n\nexport async function fetchReleaseNotes(\n targetDir: string,\n fetchFn: typeof fetch = fetch,\n): Promise<ReleaseNotesResult> {\n const manifest = await requireManifest(targetDir);\n const fromVersion = manifest.generatorVersion;\n const toVersion = getGeneratorVersion();\n\n if (compareVersions(fromVersion, toVersion) >= 0) {\n return { status: 'up-to-date', fromVersion, toVersion, releases: [] };\n }\n\n const response = await fetchFn(RELEASES_URL, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n if (!response.ok) {\n throw new Error(`Failed to fetch release notes: GitHub API responded with ${response.status}`);\n }\n const allReleases = (await response.json()) as GitHubRelease[];\n\n const releases = allReleases\n .filter((r) => compareVersions(r.tag_name, fromVersion) > 0 && compareVersions(r.tag_name, toVersion) <= 0)\n .sort((a, b) => compareVersions(b.tag_name, a.tag_name));\n\n return { status: 'releases-found', fromVersion, toVersion, releases };\n}\n\nexport function formatReleaseNotes(result: ReleaseNotesResult): string {\n if (result.status === 'up-to-date') {\n return `You're on the latest clispark version (v${result.toVersion}), nothing to show.`;\n }\n if (result.releases.length === 0) {\n return `No published releases found between v${result.fromVersion} and v${result.toVersion}.`;\n }\n return result.releases.map((r) => `## ${r.tag_name}\\n\\n${r.body}`).join('\\n\\n');\n}\n","// src/whoami.ts\nimport os from 'node:os';\n\nconst JOKE_API_URL = 'https://v2.jokeapi.dev/joke/Programming,Miscellaneous';\nconst FETCH_TIMEOUT_MS = 3000;\n\n/** Languages JokeAPI (https://jokeapi.dev/) currently supports, per its /languages endpoint. */\nconst SUPPORTED_JOKE_LANGUAGES = ['cs', 'de', 'en', 'es', 'fr', 'pt'];\n\nexport const LOGO = String.raw`\n ⚡ clispark\n`;\n\nexport const FALLBACK_QUOTES = [\n \"Green unit tests don't mean it works. Real end-to-end verification does.\",\n 'A default value can silently reintroduce coupling you just removed.',\n \"The bug you can't find locally is waiting for you in CI.\",\n \"YAGNI until you actually need it — then it's just an adapter away.\",\n 'Every folder move has a bundling-depth bug waiting to happen.',\n 'The cheapest fix is the one you verify before you ship it.',\n 'TDD: write the failing test first, or explain later why it passed by accident.',\n \"If it's not tested against a real filesystem, it's a theory, not a fact.\",\n];\n\ninterface JokeApiSingle {\n error: false;\n type: 'single';\n joke: string;\n}\n\ninterface JokeApiTwoPart {\n error: false;\n type: 'twopart';\n setup: string;\n delivery: string;\n}\n\ninterface JokeApiError {\n error: true;\n}\n\ntype JokeApiResponse = JokeApiSingle | JokeApiTwoPart | JokeApiError;\n\n/** Maps a BCP-47 locale (e.g. \"de-DE\") to a JokeAPI language code, defaulting to \"en\" when unsupported. */\nexport function detectJokeLanguage(\n locale: string = Intl.DateTimeFormat().resolvedOptions().locale,\n): string {\n const primary = locale.split('-')[0].toLowerCase();\n return SUPPORTED_JOKE_LANGUAGES.includes(primary) ? primary : 'en';\n}\n\nfunction pickFallbackQuote(): string {\n return FALLBACK_QUOTES[Math.floor(Math.random() * FALLBACK_QUOTES.length)];\n}\n\nexport interface OsFacts {\n uptime: () => number;\n hostname: () => string;\n cpus: () => os.CpuInfo[];\n totalmem: () => number;\n platform: () => NodeJS.Platform;\n release: () => string;\n arch: () => string;\n}\n\nconst defaultOsFacts: OsFacts = {\n uptime: () => os.uptime(),\n hostname: () => os.hostname(),\n cpus: () => os.cpus(),\n totalmem: () => os.totalmem(),\n platform: () => os.platform(),\n release: () => os.release(),\n arch: () => os.arch(),\n};\n\nfunction formatUptime(seconds: number): string {\n const days = Math.floor(seconds / 86400);\n const hours = Math.floor((seconds % 86400) / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n const parts: string[] = [];\n if (days > 0) parts.push(`${days}d`);\n if (days > 0 || hours > 0) parts.push(`${hours}h`);\n parts.push(`${minutes}m`);\n return parts.join(' ');\n}\n\nconst FACT_GENERATORS: Array<(facts: OsFacts) => string> = [\n (facts) => `This machine has been up for ${formatUptime(facts.uptime())}.`,\n (facts) => `Hostname: ${facts.hostname()}`,\n (facts) => {\n const cpus = facts.cpus();\n return `CPU: ${cpus[0]?.model.trim() ?? 'unknown'} (${cpus.length} logical cores)`;\n },\n (facts) => `RAM: ${(facts.totalmem() / 1024 ** 3).toFixed(1)} GB total`,\n (facts) => `OS: ${facts.platform()} ${facts.release()} (${facts.arch()})`,\n];\n\nexport function getRandomFunFact(osFacts: OsFacts = defaultOsFacts, randomFn: () => number = Math.random): string {\n const index = Math.floor(randomFn() * FACT_GENERATORS.length);\n return FACT_GENERATORS[index](osFacts);\n}\n\nasync function fetchJoke(language: string, fetchFn: typeof fetch): Promise<string | undefined> {\n try {\n const url = `${JOKE_API_URL}?lang=${language}&safe-mode`;\n const response = await fetchFn(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n if (!response.ok) return undefined;\n\n const data = (await response.json()) as JokeApiResponse;\n if (data.error) return undefined;\n return data.type === 'single' ? data.joke : `${data.setup}\\n${data.delivery}`;\n } catch {\n return undefined;\n }\n}\n\nexport type WhoamiMode = 'joke' | 'fact' | 'random';\n\nexport async function getWhoamiOutput(\n fetchFn: typeof fetch = fetch,\n osFacts: OsFacts = defaultOsFacts,\n randomFn: () => number = Math.random,\n mode: WhoamiMode = 'random',\n): Promise<string> {\n const showFact = mode === 'fact' || (mode === 'random' && randomFn() < 0.5);\n if (showFact) {\n return `${LOGO}\\n${getRandomFunFact(osFacts, randomFn)}\\n`;\n }\n\n const language = detectJokeLanguage();\n const quote = (await fetchJoke(language, fetchFn)) ?? pickFallbackQuote();\n return `${LOGO}\\n${quote}\\n`;\n}\n","// src/confetti.ts\n\nconst CONFETTI_VARIANTS = [\n '✨ 🎉 ✨ 🎊 ✨ 🎉 ✨\\n 🎈 🎊 🎈\\n✨ 🎉 ✨ 🎉',\n '🎊 ✨ 🎈 ✨ 🎊\\n 🎉 🎉 🎉\\n✨ 🎈 ✨ 🎈 ✨',\n '🎉✨🎊✨🎉✨🎊✨🎉\\n 🎈 🎈\\n✨🎊✨🎉✨🎊✨🎉✨',\n];\n\nexport function getConfetti(randomFn: () => number = Math.random): string {\n const index = Math.floor(randomFn() * CONFETTI_VARIANTS.length);\n return CONFETTI_VARIANTS[index];\n}\n\nexport function printConfetti(randomFn: () => number = Math.random): void {\n console.log(`\\n${getConfetti(randomFn)}\\n`);\n}\n"],"mappings":"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","names":["path","path","path","path","readFile","writeFile","path","path","path","readFile","writeFile","path","CORE_FILE_PATHS","extractCoreFields","readFile","path","writeFile","readFile","writeFile","path","FETCH_TIMEOUT_MS","checkNameAvailability","applyPrivateIntent","applyRegistryUrl","validateProjectName","path","pack","readFile","writeFile","path","existsSync","readFileSync","mkdir","readFile","writeFile","path","fileURLToPath","readFile","path","mkdir","writeFile","fileURLToPath","existsSync","readFileSync","path","readFile","writeFile","path","mkdir","readFile","writeFile","path","spawn","FETCH_TIMEOUT_MS","defaultRunCommand","spawn","readFile","path","mkdir","writeFile","FETCH_TIMEOUT_MS","path"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/wizard.ts","../src/languages/packs/node-oclif.ts","../src/package-root.ts","../src/update/adapters/node-oclif.ts","../src/update/reconcile.ts","../src/languages/registry-checkers/npm.ts","../src/languages/command-generators/node-oclif.ts","../src/languages/command-generator.ts","../src/languages/packs/dotnet.ts","../src/update/adapters/dotnet.ts","../src/languages/registry-checkers/nuget.ts","../src/languages/command-generators/dotnet.ts","../src/languages/index.ts","../src/scaffold.ts","../src/update/manifest.ts","../src/errors.ts","../src/logger.ts","../src/update/update.ts","../src/update/releasenotes.ts","../src/add-wizard.ts","../src/whoami.ts","../src/confetti.ts"],"sourcesContent":["// src/cli.ts\nimport path from 'node:path';\nimport { Command } from 'commander';\nimport { runWizard } from './wizard';\nimport { scaffoldProject } from './scaffold';\nimport { withLogging } from './logger';\nimport { formatUpdateSummary, updateProject } from './update/update';\nimport { fetchReleaseNotes, formatReleaseNotes } from './update/releasenotes';\nimport { getGeneratorVersion, requireManifest } from './update/manifest';\nimport { LANGUAGE_PACKS } from './languages';\nimport type { LanguagePack } from './languages/pack';\nimport { UserError } from './errors';\nimport { runAddWizard } from './add-wizard';\nimport { getWhoamiOutput, type WhoamiMode } from './whoami';\nimport { printConfetti } from './confetti';\n\nconst program = new Command();\n\nprogram\n .name('clispark')\n .description('Interactive scaffolding tool for new CLI projects')\n .option('--no-confetti', 'Skip the confetti after a successful run')\n .configureHelp({ showGlobalOptions: true })\n .version(getGeneratorVersion());\n\nfunction resolvePack(language: string): LanguagePack {\n const pack = LANGUAGE_PACKS[language];\n if (!pack) {\n throw new UserError(`Unknown language \"${language}\" — is your clispark installation out of date?`);\n }\n return pack;\n}\n\nprogram.action((options: { confetti?: boolean }) =>\n withLogging('scaffold', async (logger) => {\n const answers = await runWizard();\n const targetDir = path.join(process.cwd(), answers.projectName);\n const pack = resolvePack(answers.language);\n\n logger.info({ projectName: answers.projectName, targetDir, language: pack.id }, 'scaffold started');\n await scaffoldProject(\n {\n projectName: answers.projectName,\n targetDir,\n registryUrl: answers.registryUrl,\n publishIntent: answers.publishIntent,\n },\n pack,\n );\n logger.info({ projectName: answers.projectName }, 'scaffold completed');\n\n console.log(`\\nDone! Your new CLI project is ready at ${targetDir}`);\n if (options.confetti !== false) printConfetti();\n })(),\n);\n\nprogram\n .command('update')\n .description('Update generator-managed core files and dependencies to the latest clispark version')\n .action((_options: unknown, command: Command) =>\n withLogging('update', async (logger) => {\n const targetDir = process.cwd();\n const manifest = await requireManifest(targetDir);\n const language = manifest.language ?? 'node';\n const pack = resolvePack(language);\n logger.info({ targetDir, language }, 'update started');\n const result = await updateProject(targetDir, pack.updateAdapter, pack.templateDir, language);\n logger.info({ status: result.status }, 'update completed');\n console.log(formatUpdateSummary(result));\n const { confetti } = command.optsWithGlobals<{ confetti?: boolean }>();\n if (confetti !== false && result.status === 'updated') printConfetti();\n })(),\n );\n\nprogram\n .command('releasenotes')\n .description(\"Show what changed between this project's generator version and the latest clispark version\")\n .action(\n withLogging('releasenotes', async (logger) => {\n const targetDir = process.cwd();\n logger.info({ targetDir }, 'releasenotes started');\n const result = await fetchReleaseNotes(targetDir);\n logger.info({ status: result.status }, 'releasenotes completed');\n console.log(formatReleaseNotes(result));\n }),\n );\n\nprogram\n .command('add')\n .description('Add a new command to an already-scaffolded project')\n .action(\n withLogging('add', async (logger) => {\n const targetDir = process.cwd();\n const manifest = await requireManifest(targetDir);\n const language = manifest.language ?? 'node';\n const pack = resolvePack(language);\n logger.info({ targetDir, language }, 'add started');\n await runAddWizard(targetDir, { commandGenerator: pack.commandGenerator });\n logger.info({}, 'add completed');\n }),\n );\n\nfunction resolveWhoamiMode(options: { joke?: boolean; fact?: boolean }): WhoamiMode {\n if (options.joke && options.fact) {\n throw new UserError('Use either --joke or --fact, not both.');\n }\n if (options.joke) return 'joke';\n if (options.fact) return 'fact';\n return 'random';\n}\n\nprogram\n .command('whoami')\n .description('A little something extra')\n .option('--joke', 'Always show a joke')\n .option('--fact', 'Always show a fun fact about this machine')\n .action((options: { joke?: boolean; fact?: boolean }) =>\n withLogging('whoami', async (logger) => {\n const mode = resolveWhoamiMode(options);\n logger.info({ mode }, 'whoami started');\n console.log(await getWhoamiOutput(fetch, undefined, undefined, mode));\n logger.info({}, 'whoami completed');\n })(),\n );\n\nprogram.parseAsync(process.argv).catch((error: unknown) => {\n console.error(error);\n process.exit(1);\n});\n","// src/wizard.ts\nimport { intro, outro, text, select, log, isCancel, cancel } from '@clack/prompts';\nimport { LANGUAGE_PACKS } from './languages';\nimport type { LanguagePack } from './languages/pack';\nimport type { NameCheckResult } from './languages/registry-checker';\nimport type { Profile, WizardAnswers } from './types';\n\nexport interface WizardDeps {\n languagePacks: Record<string, LanguagePack>;\n}\n\nconst defaultDeps: WizardDeps = {\n languagePacks: LANGUAGE_PACKS,\n};\n\nfunction exitIfCancelled(value: unknown): void {\n if (isCancel(value)) {\n cancel('Operation cancelled.');\n process.exit(1);\n }\n}\n\nexport async function runWizard(deps: WizardDeps = defaultDeps): Promise<WizardAnswers> {\n intro('clispark — scaffold a new CLI project');\n\n const packs = Object.values(deps.languagePacks);\n const languageValue = await select({\n message: 'Which language?',\n options: packs.map((pack) => ({ value: pack.id, label: pack.displayName })),\n });\n exitIfCancelled(languageValue);\n const pack = deps.languagePacks[languageValue as string];\n\n const nameValue = await text({\n message: 'Project name',\n validate: pack.validateProjectName,\n });\n exitIfCancelled(nameValue);\n let projectName = nameValue as string;\n\n const profileValue = await select({\n message: 'Is this a work or private project?',\n options: [\n { value: 'private', label: 'Private' },\n { value: 'work', label: 'Work' },\n ],\n });\n exitIfCancelled(profileValue);\n const profile = profileValue as Profile;\n\n let registryUrl = pack.registry.defaultUrl;\n if (profile === 'work') {\n const registryValue = await text({\n message: pack.registry.promptLabel,\n placeholder: pack.registry.defaultUrl,\n defaultValue: pack.registry.defaultUrl,\n });\n exitIfCancelled(registryValue);\n registryUrl = (registryValue as string) || pack.registry.defaultUrl;\n }\n\n const publishIntentValue = await select({\n message: 'Do you plan to publish this?',\n options: [\n { value: false, label: 'No' },\n { value: true, label: 'Yes' },\n ],\n initialValue: false,\n });\n exitIfCancelled(publishIntentValue);\n const publishIntent = publishIntentValue as boolean;\n\n let nameAvailability: NameCheckResult = 'skipped';\n\n if (publishIntent) {\n nameAvailability = await pack.registry.checkNameAvailability(projectName, registryUrl);\n\n while (nameAvailability === 'taken') {\n log.warn(`\"${projectName}\" is already taken on ${registryUrl}. Please choose a different name.`);\n\n const retryValue = await text({\n message: 'Project name',\n validate: pack.validateProjectName,\n });\n exitIfCancelled(retryValue);\n projectName = retryValue as string;\n\n nameAvailability = await pack.registry.checkNameAvailability(projectName, registryUrl);\n }\n\n if (nameAvailability === 'unverified') {\n log.warn(`Could not verify availability of \"${projectName}\" on ${registryUrl}. Continuing anyway.`);\n }\n }\n\n outro(`Ready to scaffold \"${projectName}\".`);\n\n return { language: pack.id, projectName, profile, registryUrl, publishIntent, nameAvailability };\n}\n","// src/languages/packs/node-oclif.ts\nimport path from 'node:path';\nimport { findPackageRoot } from '../../package-root';\nimport type { LanguagePack } from '../pack';\nimport { nodeOclifAdapter } from '../../update/adapters/node-oclif';\nimport { npmRegistryChecker, NPM_DEFAULT_REGISTRY_URL } from '../registry-checkers/npm';\nimport { nodeOclifCommandGenerator } from '../command-generators/node-oclif';\n\nfunction validateProjectName(value: string): string | undefined {\n if (!value || value.trim().length === 0) return 'Project name is required.';\n if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {\n return 'Use lowercase letters and numbers, with single hyphens between words (no leading, trailing, or repeated hyphens).';\n }\n return undefined;\n}\n\nexport const nodeOclifPack: LanguagePack = {\n id: 'node',\n displayName: 'Node.js / TypeScript (oclif)',\n templateDir: path.join(findPackageRoot(), 'templates', 'node'),\n scaffoldCommands: [\n { command: 'npm', args: ['install'] },\n { command: 'npm', args: ['run', 'build'] },\n ],\n validateProjectName,\n updateAdapter: nodeOclifAdapter,\n registry: {\n defaultUrl: NPM_DEFAULT_REGISTRY_URL,\n promptLabel: 'Custom npm registry URL (leave empty for npmjs.org)',\n checkNameAvailability: npmRegistryChecker.checkNameAvailability,\n applyPrivateIntent: npmRegistryChecker.applyPrivateIntent,\n applyRegistryUrl: npmRegistryChecker.applyRegistryUrl,\n },\n commandGenerator: nodeOclifCommandGenerator,\n};\n","import { existsSync, readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Finds clispark's own package root by walking up from this module's\n * location. A fixed relative path can't work here: this module's depth\n * below the package root differs between running from source (tests) and\n * running as part of the bundled `dist/cli.js` (tsup flattens everything\n * into one file, so `import.meta.url` no longer reflects the original\n * per-module nesting) — but the walk-up strategy is depth-independent\n * either way, since it doesn't matter where exactly the walk starts.\n */\nexport function findPackageRoot(): string {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n while (true) {\n const pkgPath = path.join(dir, 'package.json');\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as { name?: string };\n if (pkg.name === 'clispark') return dir;\n }\n const parentDir = path.dirname(dir);\n if (parentDir === dir) {\n throw new Error(\"Could not locate clispark's own package.json.\");\n }\n dir = parentDir;\n }\n}\n","// src/update/adapters/node-oclif.ts\nimport { readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Manifest } from '../manifest';\nimport type { CoreFieldsExtraction, ManifestFileMergeResult, UpdateAdapter } from '../adapter';\nimport { deepEquals, reconcileEntry, stringEquals, type FieldOutcome } from '../reconcile';\n\nexport const CORE_FILE_PATHS = [\n 'bin/run.ts',\n 'src/index.ts',\n 'src/base-command.ts',\n 'src/logger.ts',\n 'tsup.config.ts',\n 'vitest.config.ts',\n 'tsconfig.json',\n 'ARCHITECTURE.md',\n '.gitignore',\n] as const;\n\nexport const CORE_SCRIPT_NAMES = ['build', 'postbuild', 'pretest', 'test', 'typecheck'] as const;\n\nexport interface PackageJsonShape {\n name: string;\n version: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n engines?: Record<string, string>;\n oclif?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\nfunction currentDependencyValue(\n pkg: PackageJsonShape,\n name: string,\n): { section: 'dependencies' | 'devDependencies'; value: string } | undefined {\n if (pkg.dependencies?.[name] !== undefined) return { section: 'dependencies', value: pkg.dependencies[name] };\n if (pkg.devDependencies?.[name] !== undefined) {\n return { section: 'devDependencies', value: pkg.devDependencies[name] };\n }\n return undefined;\n}\n\nfunction extractCoreFields(pkg: PackageJsonShape): CoreFieldsExtraction {\n const coreDependencies = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n\n const coreScripts: Record<string, string> = {};\n for (const name of CORE_SCRIPT_NAMES) {\n const value = pkg.scripts?.[name];\n if (value !== undefined) coreScripts[name] = value;\n }\n\n return {\n coreDependencies,\n coreScripts,\n coreFields: {\n engines: pkg.engines ?? {},\n oclif: pkg.oclif ?? {},\n },\n };\n}\n\nfunction mergePackageJson(\n currentPkg: PackageJsonShape,\n oldManifest: Manifest,\n newTemplatePkg: PackageJsonShape,\n): ManifestFileMergeResult {\n const updatedFile: PackageJsonShape = { ...currentPkg };\n let changed = false;\n\n const dependencies: FieldOutcome[] = [];\n const coreDependencies: Record<string, string> = {};\n const dependencyNames = new Set([\n ...Object.keys(newTemplatePkg.dependencies ?? {}),\n ...Object.keys(newTemplatePkg.devDependencies ?? {}),\n ]);\n\n for (const name of dependencyNames) {\n const inNewDependencies = newTemplatePkg.dependencies?.[name] !== undefined;\n const newValue = (inNewDependencies ? newTemplatePkg.dependencies : newTemplatePkg.devDependencies)![name];\n const current = currentDependencyValue(currentPkg, name);\n const oldValue = oldManifest.coreDependencies[name];\n\n const result = reconcileEntry(current?.value, oldValue, newValue, stringEquals);\n dependencies.push({ key: name, outcome: result.outcome });\n coreDependencies[name] = result.value;\n\n if (result.outcome !== 'skipped' && result.value !== current?.value) {\n changed = true;\n const section = current?.section ?? (inNewDependencies ? 'dependencies' : 'devDependencies');\n updatedFile[section] = { ...updatedFile[section], [name]: result.value };\n }\n }\n\n const scripts: FieldOutcome[] = [];\n const coreScripts: Record<string, string> = {};\n\n for (const name of CORE_SCRIPT_NAMES) {\n const newValue = newTemplatePkg.scripts?.[name];\n if (newValue === undefined) continue;\n const currentValue = currentPkg.scripts?.[name];\n const oldValue = oldManifest.coreScripts[name];\n\n const result = reconcileEntry(currentValue, oldValue, newValue, stringEquals);\n scripts.push({ key: name, outcome: result.outcome });\n coreScripts[name] = result.value;\n\n if (result.outcome !== 'skipped' && result.value !== currentValue) {\n changed = true;\n updatedFile.scripts = { ...updatedFile.scripts, [name]: result.value };\n }\n }\n\n const oldCoreFields = oldManifest.coreFields as {\n engines?: Record<string, string>;\n oclif?: Record<string, unknown>;\n };\n const fields: FieldOutcome[] = [];\n let enginesValue: Record<string, string> = oldCoreFields.engines ?? {};\n let oclifValue: Record<string, unknown> = oldCoreFields.oclif ?? {};\n\n if (newTemplatePkg.engines !== undefined) {\n const enginesResult = reconcileEntry(\n currentPkg.engines,\n oldCoreFields.engines,\n newTemplatePkg.engines,\n deepEquals,\n );\n fields.push({ key: 'engines', outcome: enginesResult.outcome });\n enginesValue = enginesResult.value;\n if (enginesResult.outcome !== 'skipped' && !deepEquals(enginesResult.value, currentPkg.engines)) {\n changed = true;\n updatedFile.engines = enginesResult.value;\n }\n }\n\n if (newTemplatePkg.oclif !== undefined) {\n const oclifResult = reconcileEntry(currentPkg.oclif, oldCoreFields.oclif, newTemplatePkg.oclif, deepEquals);\n fields.push({ key: 'oclif', outcome: oclifResult.outcome });\n oclifValue = oclifResult.value;\n if (oclifResult.outcome !== 'skipped' && !deepEquals(oclifResult.value, currentPkg.oclif)) {\n changed = true;\n updatedFile.oclif = oclifResult.value;\n }\n }\n\n return {\n updatedFile,\n changed,\n dependencies,\n scripts,\n fields,\n coreDependencies,\n coreScripts,\n coreFields: { engines: enginesValue, oclif: oclifValue },\n };\n}\n\nexport const nodeOclifAdapter: UpdateAdapter = {\n coreFilePaths: CORE_FILE_PATHS,\n\n templateSourcePath(relativePath) {\n return relativePath === '.gitignore' ? 'gitignore' : relativePath;\n },\n\n manifestFileName: 'package.json',\n\n async readManifestFile(dir) {\n const content = await readFile(path.join(dir, 'package.json'), 'utf8');\n return JSON.parse(content) as PackageJsonShape;\n },\n\n async writeManifestFile(dir, content) {\n await writeFile(path.join(dir, 'package.json'), JSON.stringify(content, null, 2) + '\\n');\n },\n\n parseManifestFile(rawContent) {\n return JSON.parse(rawContent) as PackageJsonShape;\n },\n\n readProjectName(manifestFile) {\n return (manifestFile as PackageJsonShape).name;\n },\n\n extractCoreFields(manifestFile) {\n return extractCoreFields(manifestFile as PackageJsonShape);\n },\n\n mergeManifestFile(current, oldManifest, newTemplate) {\n return mergePackageJson(current as PackageJsonShape, oldManifest, newTemplate as PackageJsonShape);\n },\n};\n","export type ReconcileOutcome = 'added' | 'replaced' | 'skipped';\n\n/** A named field/dependency/script whose reconciliation outcome should be reported to the user (e.g. \"pino: replaced\"). */\nexport interface FieldOutcome {\n key: string;\n outcome: ReconcileOutcome;\n}\n\nexport interface ReconcileResult<T> {\n outcome: ReconcileOutcome;\n value: T;\n}\n\nexport function reconcileEntry<T>(\n currentLiveValue: T | undefined,\n oldManifestValue: T | undefined,\n newTemplateValue: T,\n isEqual: (a: T, b: T) => boolean,\n): ReconcileResult<T> {\n if (currentLiveValue === undefined) {\n return { outcome: 'added', value: newTemplateValue };\n }\n if (oldManifestValue !== undefined && isEqual(currentLiveValue, oldManifestValue)) {\n return { outcome: 'replaced', value: newTemplateValue };\n }\n return { outcome: 'skipped', value: oldManifestValue ?? currentLiveValue };\n}\n\nexport function stringEquals(a: string, b: string): boolean {\n return a === b;\n}\n\nexport function deepEquals(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n","// src/languages/registry-checkers/npm.ts\nimport { readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { NameCheckResult, RegistryChecker } from '../registry-checker';\n\nexport const NPM_DEFAULT_REGISTRY_URL = 'https://registry.npmjs.org';\n\nconst FETCH_TIMEOUT_MS = 5000;\n\nasync function checkNameAvailability(name: string, registryUrl: string): Promise<NameCheckResult> {\n const url = `${registryUrl.replace(/\\/$/, '')}/${encodeURIComponent(name)}`;\n\n try {\n const response = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n if (response.status === 404) return 'available';\n if (response.status === 200) return 'taken';\n return 'unverified';\n } catch {\n return 'unverified';\n }\n}\n\nasync function applyPrivateIntent(targetDir: string): Promise<void> {\n const packageJsonPath = path.join(targetDir, 'package.json');\n const pkg = JSON.parse(await readFile(packageJsonPath, 'utf8')) as Record<string, unknown>;\n pkg.private = true;\n await writeFile(packageJsonPath, JSON.stringify(pkg, null, 2) + '\\n');\n}\n\nasync function applyRegistryUrl(targetDir: string, registryUrl: string): Promise<void> {\n await writeFile(path.join(targetDir, '.npmrc'), `registry=${registryUrl}\\n`);\n}\n\nexport const npmRegistryChecker: RegistryChecker = {\n checkNameAvailability,\n applyPrivateIntent,\n applyRegistryUrl,\n};\n","// src/languages/command-generators/node-oclif.ts\nimport { mkdir, readdir, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type {\n CommandGenerator,\n CommandSpec,\n ExistingCommandNode,\n GeneratedFiles,\n ParameterSpec,\n} from '../command-generator';\nimport { buildCommandTree } from '../command-generator';\n\nasync function collectCommandFiles(dir: string, baseDir: string = dir): Promise<string[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const files: string[] = [];\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await collectCommandFiles(fullPath, baseDir)));\n } else if (entry.name.endsWith('.ts') && !entry.name.endsWith('.test.ts')) {\n files.push(path.relative(baseDir, fullPath));\n }\n }\n return files;\n}\n\nfunction toCommandPath(relativeFilePath: string): string {\n return relativeFilePath.replace(/\\.ts$/, '').split(path.sep).join(' ');\n}\n\nasync function listExistingCommands(targetDir: string): Promise<ExistingCommandNode[]> {\n const commandsDir = path.join(targetDir, 'src', 'commands');\n const files = await collectCommandFiles(commandsDir);\n return buildCommandTree(files.map(toCommandPath));\n}\n\nfunction toClassName(pathSegments: string[]): string {\n return pathSegments.map((seg) => seg[0].toUpperCase() + seg.slice(1)).join('');\n}\n\nfunction argFor(param: ParameterSpec): string {\n const opts = [`required: ${param.required}`, `description: '${param.name}'`];\n if (param.type === 'enum') {\n opts.push(`options: [${(param.allowedValues ?? []).map((v) => `'${v}'`).join(', ')}]`);\n }\n const argsMethod = param.type === 'enum' ? 'string' : param.type;\n return `Args.${argsMethod}({ ${opts.join(', ')} })`;\n}\n\nfunction generateCommandFileContent(spec: CommandSpec): string {\n const className = toClassName(spec.pathSegments);\n const argsLines = spec.parameters.map((p) => ` ${p.name}: ${argFor(p)},`).join('\\n');\n const logExpr = spec.parameters.map((p) => `${p.name}=\\${args.${p.name}}`).join(' ');\n const depth = spec.pathSegments.length;\n const baseCommandImportPath = '../'.repeat(depth) + 'base-command';\n\n return `import { Args } from '@oclif/core';\nimport { BaseCommand } from '${baseCommandImportPath}';\n\nexport default class ${className} extends BaseCommand {\n static description = '${spec.pathSegments[spec.pathSegments.length - 1]} command';\n static args = {\n${argsLines}\n };\n static flags = {};\n\n async run(): Promise<void> {\n const { args } = await this.parse(${className});\n this.log(\\`${logExpr}\\`);\n }\n}\n`;\n}\n\nfunction sampleArgValue(param: ParameterSpec): string {\n if (param.type === 'enum') return param.allowedValues?.[0] ?? '';\n if (param.type === 'integer') return '1';\n if (param.type === 'boolean') return 'true';\n return 'value';\n}\n\nfunction generateTestFileContent(spec: CommandSpec): string {\n const commandInvocation = spec.pathSegments.join(' ');\n const sampleArgs = spec.parameters.map(sampleArgValue).join(' ');\n const fullInvocation = sampleArgs ? `${commandInvocation} ${sampleArgs}` : commandInvocation;\n\n return `import { describe, it, expect } from 'vitest';\nimport { runCommand } from '@oclif/test';\n\ndescribe('${commandInvocation}', () => {\n it('runs successfully', async () => {\n const { error } = await runCommand('${fullInvocation}');\n expect(error).toBeUndefined();\n });\n});\n`;\n}\n\nasync function generateCommand(targetDir: string, spec: CommandSpec): Promise<GeneratedFiles> {\n const relDir = path.join('src', 'commands', ...spec.pathSegments.slice(0, -1));\n const fileName = spec.pathSegments[spec.pathSegments.length - 1];\n const commandRelPath = path.join(relDir, `${fileName}.ts`);\n const testRelPath = path.join(relDir, `${fileName}.test.ts`);\n\n await mkdir(path.join(targetDir, relDir), { recursive: true });\n await writeFile(path.join(targetDir, commandRelPath), generateCommandFileContent(spec));\n await writeFile(path.join(targetDir, testRelPath), generateTestFileContent(spec));\n\n return { commandFile: commandRelPath, testFile: testRelPath };\n}\n\nexport const nodeOclifCommandGenerator: CommandGenerator = {\n listExistingCommands,\n generateCommand,\n};\n","// src/languages/command-generator.ts\n\nexport interface ExistingCommandNode {\n path: string;\n displayLabel: string;\n children: ExistingCommandNode[];\n}\n\nexport type ParameterType = 'string' | 'integer' | 'boolean' | 'enum';\n\nexport interface ParameterSpec {\n name: string;\n type: ParameterType;\n required: boolean;\n allowedValues?: string[];\n}\n\nexport interface CommandSpec {\n pathSegments: string[];\n parameters: ParameterSpec[];\n}\n\nexport interface GeneratedFiles {\n commandFile: string;\n testFile: string;\n}\n\nexport interface CommandGenerator {\n listExistingCommands(targetDir: string): Promise<ExistingCommandNode[]>;\n generateCommand(targetDir: string, spec: CommandSpec): Promise<GeneratedFiles>;\n}\n\n/** Builds a tree of ExistingCommandNode from a flat list of space-separated command paths. */\nexport function buildCommandTree(paths: string[]): ExistingCommandNode[] {\n const nodesByPath = new Map<string, ExistingCommandNode>();\n const roots: ExistingCommandNode[] = [];\n\n function getOrCreateNode(nodePath: string): ExistingCommandNode {\n let node = nodesByPath.get(nodePath);\n if (!node) {\n const segments = nodePath.split(' ');\n node = { path: nodePath, displayLabel: segments.join(' > '), children: [] };\n nodesByPath.set(nodePath, node);\n if (segments.length === 1) {\n roots.push(node);\n } else {\n const parent = getOrCreateNode(segments.slice(0, -1).join(' '));\n parent.children.push(node);\n }\n }\n return node;\n }\n\n for (const p of paths) {\n getOrCreateNode(p);\n }\n\n return roots;\n}\n","// src/languages/packs/dotnet.ts\nimport path from 'node:path';\nimport { findPackageRoot } from '../../package-root';\nimport type { LanguagePack } from '../pack';\nimport { dotnetAdapter } from '../../update/adapters/dotnet';\nimport { nugetRegistryChecker, NUGET_DEFAULT_REGISTRY_URL } from '../registry-checkers/nuget';\nimport { dotnetCommandGenerator } from '../command-generators/dotnet';\n\nfunction validateProjectName(value: string): string | undefined {\n if (!value || value.trim().length === 0) return 'Project name is required.';\n if (!/^[A-Z][A-Za-z0-9]*$/.test(value)) {\n return 'Use PascalCase, starting with an uppercase letter (e.g. MyTool).';\n }\n return undefined;\n}\n\nexport const dotnetPack: LanguagePack = {\n id: 'dotnet',\n displayName: '.NET / C# (System.CommandLine)',\n templateDir: path.join(findPackageRoot(), 'templates', 'dotnet'),\n scaffoldCommands: [\n { command: 'dotnet', args: ['restore'] },\n { command: 'dotnet', args: ['build'] },\n ],\n validateProjectName,\n updateAdapter: dotnetAdapter,\n registry: {\n defaultUrl: NUGET_DEFAULT_REGISTRY_URL,\n promptLabel: 'Custom NuGet feed URL (leave empty for nuget.org)',\n checkNameAvailability: nugetRegistryChecker.checkNameAvailability,\n applyPrivateIntent: nugetRegistryChecker.applyPrivateIntent,\n applyRegistryUrl: nugetRegistryChecker.applyRegistryUrl,\n },\n commandGenerator: dotnetCommandGenerator,\n};\n","// src/update/adapters/dotnet.ts\nimport { readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Manifest } from '../manifest';\nimport type { CoreFieldsExtraction, ManifestFileMergeResult, UpdateAdapter } from '../adapter';\nimport { reconcileEntry, stringEquals, type FieldOutcome } from '../reconcile';\n\nexport const CORE_FILE_PATHS = [\n 'Cli.slnx',\n 'src/Program.cs',\n 'src/ICliCommand.cs',\n 'src/CommandPathAttribute.cs',\n 'src/CommandDiscovery.cs',\n 'src/CliUserException.cs',\n 'src/Logging/CliLoggerFactory.cs',\n 'src/Logging/SensitivePropertyEnricher.cs',\n 'tests/Cli.Tests.csproj',\n 'ARCHITECTURE.md',\n '.gitignore',\n] as const;\n\nexport interface DotnetManifestFile {\n raw: string;\n version: string;\n targetFramework: string;\n packageId: string;\n toolCommandName: string;\n packageReferences: Record<string, string>;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction extractTag(content: string, tag: string): string {\n const match = content.match(new RegExp(`<${tag}>([^<]*)</${tag}>`));\n if (!match) throw new Error(`.csproj is missing a <${tag}> tag`);\n return match[1];\n}\n\nfunction extractPackageReferences(content: string): Record<string, string> {\n const refs: Record<string, string> = {};\n const re = /<PackageReference\\s+Include=\"([^\"]+)\"\\s+Version=\"([^\"]+)\"\\s*\\/>/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(content))) {\n refs[m[1]] = m[2];\n }\n return refs;\n}\n\nfunction setTag(content: string, tag: string, value: string): string {\n const escapedTag = escapeRegExp(tag);\n return content.replace(new RegExp(`(<${escapedTag}>)[^<]*(</${escapedTag}>)`), `$1${value}$2`);\n}\n\nfunction setPackageReferenceVersion(content: string, name: string, version: string): string {\n const re = new RegExp(`(<PackageReference\\\\s+Include=\"${escapeRegExp(name)}\"\\\\s+Version=\")[^\"]+(\")`);\n return content.replace(re, `$1${version}$2`);\n}\n\nfunction addPackageReference(content: string, name: string, version: string): string {\n // Reuses the indentation of the last existing <PackageReference> line\n // immediately preceding </ItemGroup>, so the new line matches siblings exactly.\n const re = /^([ \\t]*)<PackageReference[^\\n]*\\/>\\n(?=[ \\t]*<\\/ItemGroup>)/m;\n return content.replace(re, (match, indent: string) => `${match}${indent}<PackageReference Include=\"${name}\" Version=\"${version}\" />\\n`);\n}\n\nfunction parseManifestFile(rawContent: string): DotnetManifestFile {\n return {\n raw: rawContent,\n version: extractTag(rawContent, 'Version'),\n targetFramework: extractTag(rawContent, 'TargetFramework'),\n packageId: extractTag(rawContent, 'PackageId'),\n toolCommandName: extractTag(rawContent, 'ToolCommandName'),\n packageReferences: extractPackageReferences(rawContent),\n };\n}\n\nfunction extractCoreFields(manifestFile: DotnetManifestFile): CoreFieldsExtraction {\n return {\n coreDependencies: manifestFile.packageReferences,\n coreScripts: {},\n coreFields: { TargetFramework: manifestFile.targetFramework },\n };\n}\n\nfunction mergeManifestFile(\n current: DotnetManifestFile,\n oldManifest: Manifest,\n newTemplate: DotnetManifestFile,\n): ManifestFileMergeResult {\n let raw = current.raw;\n let changed = false;\n\n const dependencies: FieldOutcome[] = [];\n const coreDependencies: Record<string, string> = {};\n\n for (const name of Object.keys(newTemplate.packageReferences)) {\n const newValue = newTemplate.packageReferences[name];\n const currentValue = current.packageReferences[name];\n const oldValue = oldManifest.coreDependencies[name];\n\n const result = reconcileEntry(currentValue, oldValue, newValue, stringEquals);\n dependencies.push({ key: name, outcome: result.outcome });\n coreDependencies[name] = result.value;\n\n if (result.outcome === 'added') {\n changed = true;\n raw = addPackageReference(raw, name, result.value);\n } else if (result.outcome !== 'skipped' && result.value !== currentValue) {\n changed = true;\n raw = setPackageReferenceVersion(raw, name, result.value);\n }\n }\n\n const oldCoreFields = oldManifest.coreFields as { TargetFramework?: string };\n const fields: FieldOutcome[] = [];\n\n const targetFrameworkResult = reconcileEntry(\n current.targetFramework,\n oldCoreFields.TargetFramework,\n newTemplate.targetFramework,\n stringEquals,\n );\n fields.push({ key: 'TargetFramework', outcome: targetFrameworkResult.outcome });\n if (targetFrameworkResult.outcome !== 'skipped' && targetFrameworkResult.value !== current.targetFramework) {\n changed = true;\n raw = setTag(raw, 'TargetFramework', targetFrameworkResult.value);\n }\n\n return {\n updatedFile: { ...current, raw },\n changed,\n dependencies,\n scripts: [],\n fields,\n coreDependencies,\n coreScripts: {},\n coreFields: { TargetFramework: targetFrameworkResult.value },\n };\n}\n\nexport const dotnetAdapter: UpdateAdapter = {\n coreFilePaths: CORE_FILE_PATHS,\n\n templateSourcePath(relativePath) {\n return relativePath === '.gitignore' ? 'gitignore' : relativePath;\n },\n\n manifestFileName: 'src/Cli.csproj',\n\n async readManifestFile(dir) {\n const content = await readFile(path.join(dir, 'src', 'Cli.csproj'), 'utf8');\n return parseManifestFile(content);\n },\n\n async writeManifestFile(dir, content) {\n await writeFile(path.join(dir, 'src', 'Cli.csproj'), (content as DotnetManifestFile).raw);\n },\n\n parseManifestFile,\n\n readProjectName(manifestFile) {\n return (manifestFile as DotnetManifestFile).packageId;\n },\n\n extractCoreFields(manifestFile) {\n return extractCoreFields(manifestFile as DotnetManifestFile);\n },\n\n mergeManifestFile(current, oldManifest, newTemplate) {\n return mergeManifestFile(current as DotnetManifestFile, oldManifest, newTemplate as DotnetManifestFile);\n },\n};\n","// src/languages/registry-checkers/nuget.ts\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { NameCheckResult, RegistryChecker } from '../registry-checker';\n\nexport const NUGET_DEFAULT_REGISTRY_URL = 'https://api.nuget.org/v3/index.json';\n\nconst NUGET_FLATCONTAINER_BASE = 'https://api.nuget.org/v3-flatcontainer';\nconst FETCH_TIMEOUT_MS = 5000;\n\nasync function checkNameAvailability(name: string): Promise<NameCheckResult> {\n const url = `${NUGET_FLATCONTAINER_BASE}/${encodeURIComponent(name.toLowerCase())}/index.json`;\n\n try {\n const response = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n if (response.status === 404) return 'available';\n if (response.status === 200) return 'taken';\n return 'unverified';\n } catch {\n return 'unverified';\n }\n}\n\nasync function applyPrivateIntent(targetDir: string): Promise<void> {\n const csprojPath = path.join(targetDir, 'src', 'Cli.csproj');\n const content = await readFile(csprojPath, 'utf8');\n const updated = content.replace(\n /(<PropertyGroup>\\s*\\n)/,\n '$1 <IsPackable>false</IsPackable>\\n',\n );\n await writeFile(csprojPath, updated);\n}\n\nasync function applyRegistryUrl(targetDir: string, registryUrl: string): Promise<void> {\n const config = [\n '<?xml version=\"1.0\" encoding=\"utf-8\"?>',\n '<configuration>',\n ' <packageSources>',\n ' <clear />',\n ` <add key=\"custom\" value=\"${registryUrl}\" />`,\n ' </packageSources>',\n '</configuration>',\n '',\n ].join('\\n');\n await mkdir(targetDir, { recursive: true });\n await writeFile(path.join(targetDir, 'NuGet.config'), config);\n}\n\nexport const nugetRegistryChecker: RegistryChecker = {\n checkNameAvailability,\n applyPrivateIntent,\n applyRegistryUrl,\n};\n","// src/languages/command-generators/dotnet.ts\nimport { mkdir, readFile, readdir, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type {\n CommandGenerator,\n CommandSpec,\n ExistingCommandNode,\n GeneratedFiles,\n ParameterSpec,\n} from '../command-generator';\nimport { buildCommandTree } from '../command-generator';\n\nasync function listExistingCommands(targetDir: string): Promise<ExistingCommandNode[]> {\n const commandsDir = path.join(targetDir, 'src', 'Commands');\n const files = await readdir(commandsDir);\n const paths: string[] = [];\n for (const file of files) {\n if (!file.endsWith('.cs')) continue;\n const content = await readFile(path.join(commandsDir, file), 'utf8');\n const match = content.match(/\\[CommandPath\\(\"([^\"]+)\"\\)\\]/);\n if (match) paths.push(match[1]);\n }\n return buildCommandTree(paths);\n}\n\nfunction toClassName(pathSegments: string[]): string {\n return pathSegments.map((seg) => seg[0].toUpperCase() + seg.slice(1)).join('') + 'Command';\n}\n\nfunction csharpDeclType(param: ParameterSpec): string {\n const baseType = param.type === 'integer' ? 'int' : param.type === 'boolean' ? 'bool' : 'string';\n if (param.required) return baseType;\n return `${baseType}?`;\n}\n\nfunction argumentDeclaration(param: ParameterSpec): string {\n const varName = `${param.name}Argument`;\n const declType = csharpDeclType(param);\n const arityLine = param.required ? '' : '\\n Arity = ArgumentArity.ZeroOrOne,';\n const lines = [\n ` var ${varName} = new Argument<${declType}>(\"${param.name}\")`,\n ` {`,\n ` Description = \"${param.name}\",${arityLine}`,\n ` };`,\n ];\n if (param.type === 'enum') {\n lines.push(` ${varName}.AcceptOnlyFromAmong(${(param.allowedValues ?? []).map((v) => `\"${v}\"`).join(', ')});`);\n }\n return lines.join('\\n');\n}\n\nfunction generateCommandFileContent(spec: CommandSpec): string {\n const className = toClassName(spec.pathSegments);\n const commandPath = spec.pathSegments.join(' ');\n const lastSegment = spec.pathSegments[spec.pathSegments.length - 1];\n\n const argDecls = spec.parameters.map(argumentDeclaration).join('\\n\\n');\n const addLines = spec.parameters.map((p) => ` command.Arguments.Add(${p.name}Argument);`).join('\\n');\n const getValueLines = spec.parameters\n .map((p) => ` var ${p.name} = parseResult.GetValue(${p.name}Argument);`)\n .join('\\n');\n const interpolated = spec.parameters.map((p) => `${p.name}={${p.name}}`).join(' ');\n\n return `using System.CommandLine;\n\nnamespace Cli.Commands;\n\n[CommandPath(\"${commandPath}\")]\npublic sealed class ${className} : ICliCommand\n{\n public Command Build()\n {\n${argDecls}\n\n var command = new Command(\"${lastSegment}\", \"${lastSegment} command\");\n${addLines}\n command.SetAction(parseResult =>\n {\n${getValueLines}\n Console.WriteLine($\"${interpolated}\");\n });\n\n return command;\n }\n}\n`;\n}\n\nfunction sampleArgValue(param: ParameterSpec): string {\n if (param.type === 'enum') return param.allowedValues?.[0] ?? '';\n if (param.type === 'integer') return '1';\n if (param.type === 'boolean') return 'true';\n return 'value';\n}\n\nfunction generateTestFileContent(spec: CommandSpec): string {\n const className = toClassName(spec.pathSegments);\n const sampleArgs = spec.parameters.map(sampleArgValue);\n\n return `using System.CommandLine;\nusing Cli.Commands;\n\nnamespace Cli.Tests;\n\npublic class ${className}Tests\n{\n [Fact]\n public void RunsSuccessfully()\n {\n var command = new ${className}().Build();\n var parseResult = command.Parse([${sampleArgs.map((a) => `\"${a}\"`).join(', ')}]);\n\n var exitCode = parseResult.Invoke();\n\n Assert.Equal(0, exitCode);\n }\n}\n`;\n}\n\nasync function generateCommand(targetDir: string, spec: CommandSpec): Promise<GeneratedFiles> {\n const className = toClassName(spec.pathSegments);\n const commandRelPath = path.join('src', 'Commands', `${className}.cs`);\n const testRelPath = path.join('tests', `${className}Tests.cs`);\n\n await mkdir(path.join(targetDir, 'src', 'Commands'), { recursive: true });\n await mkdir(path.join(targetDir, 'tests'), { recursive: true });\n await writeFile(path.join(targetDir, commandRelPath), generateCommandFileContent(spec));\n await writeFile(path.join(targetDir, testRelPath), generateTestFileContent(spec));\n\n return { commandFile: commandRelPath, testFile: testRelPath };\n}\n\nexport const dotnetCommandGenerator: CommandGenerator = {\n listExistingCommands,\n generateCommand,\n};\n","// src/languages/index.ts\nimport type { LanguagePack } from './pack';\nimport { nodeOclifPack } from './packs/node-oclif';\nimport { dotnetPack } from './packs/dotnet';\n\nexport const LANGUAGE_PACKS: Record<string, LanguagePack> = {\n [nodeOclifPack.id]: nodeOclifPack,\n [dotnetPack.id]: dotnetPack,\n};\n\nexport function getPackById(id: string): LanguagePack | undefined {\n return LANGUAGE_PACKS[id];\n}\n","// src/scaffold.ts\nimport { cp, readdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport spawn from 'cross-spawn';\nimport type { LanguagePack } from './languages/pack';\nimport { buildManifest, getGeneratorVersion, writeManifest } from './update/manifest';\nimport { UserError } from './errors';\n\nexport interface ScaffoldOptions {\n projectName: string;\n targetDir: string;\n registryUrl?: string;\n publishIntent?: boolean;\n}\n\nasync function assertTargetDirIsUsable(targetDir: string): Promise<void> {\n let entries: string[];\n try {\n entries = await readdir(targetDir);\n } catch {\n return;\n }\n if (entries.length > 0) {\n throw new UserError(`Directory \"${targetDir}\" already exists and is not empty.`);\n }\n}\n\nexport function applyPlaceholders(content: string, projectName: string): string {\n return content.replaceAll('{{projectName}}', projectName);\n}\n\nasync function collectFiles(dir: string): Promise<string[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const files = await Promise.all(\n entries.map((entry) => {\n const fullPath = path.join(dir, entry.name);\n return entry.isDirectory() ? collectFiles(fullPath) : Promise.resolve([fullPath]);\n }),\n );\n return files.flat();\n}\n\n// Scans every copied file rather than a hardcoded list, so a new template file\n// that needs {{projectName}} substituted can't silently be forgotten here.\nasync function replacePlaceholdersInTree(targetDir: string, projectName: string): Promise<void> {\n const files = await collectFiles(targetDir);\n await Promise.all(\n files.map(async (filePath) => {\n const content = await readFile(filePath, 'utf8');\n if (content.includes('{{projectName}}')) {\n await writeFile(filePath, applyPlaceholders(content, projectName));\n }\n }),\n );\n}\n\nexport async function copyTemplate(options: ScaffoldOptions, pack: LanguagePack): Promise<void> {\n const { projectName, targetDir, registryUrl, publishIntent } = options;\n\n await assertTargetDirIsUsable(targetDir);\n await cp(pack.templateDir, targetDir, { recursive: true });\n\n await rename(path.join(targetDir, 'gitignore'), path.join(targetDir, '.gitignore'));\n\n await replacePlaceholdersInTree(targetDir, projectName);\n\n if (publishIntent === false) {\n await pack.registry.applyPrivateIntent(targetDir);\n }\n\n if (registryUrl && registryUrl !== pack.registry.defaultUrl) {\n await pack.registry.applyRegistryUrl(targetDir, registryUrl);\n }\n}\n\nexport interface ScaffoldDeps {\n runCommand: (command: string, args: string[], cwd: string) => Promise<void>;\n}\n\nasync function defaultRunCommand(command: string, args: string[], cwd: string): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(command, args, { cwd, stdio: 'inherit' });\n child.on('error', reject);\n child.on('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`Command \"${command} ${args.join(' ')}\" exited with code ${code}`));\n }\n });\n });\n}\n\nconst defaultScaffoldDeps: ScaffoldDeps = { runCommand: defaultRunCommand };\n\nexport async function scaffoldProject(\n options: ScaffoldOptions,\n pack: LanguagePack,\n deps: ScaffoldDeps = defaultScaffoldDeps,\n): Promise<void> {\n await copyTemplate(options, pack);\n\n const { targetDir } = options;\n const manifest = await buildManifest(targetDir, getGeneratorVersion(), pack.id, pack.updateAdapter);\n await writeManifest(targetDir, manifest);\n\n await deps.runCommand('git', ['init'], targetDir);\n await deps.runCommand('git', ['add', '-A'], targetDir);\n await deps.runCommand('git', ['commit', '-m', 'chore: initial scaffold from clispark'], targetDir);\n\n for (const scaffoldCommand of pack.scaffoldCommands) {\n await deps.runCommand(scaffoldCommand.command, scaffoldCommand.args, targetDir);\n }\n}\n","// src/update/manifest.ts\nimport { createHash } from 'node:crypto';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { UserError } from '../errors';\nimport type { UpdateAdapter } from './adapter';\n\nexport interface Manifest {\n generatorVersion: string;\n language: string;\n coreFiles: Record<string, string>;\n coreDependencies: Record<string, string>;\n coreScripts: Record<string, string>;\n coreFields: Record<string, unknown>;\n}\n\nexport function hashContent(content: string): string {\n return createHash('sha256').update(content).digest('hex');\n}\n\nexport async function hashCoreFiles(dir: string, adapter: UpdateAdapter): Promise<Record<string, string>> {\n const entries = await Promise.all(\n adapter.coreFilePaths.map(async (relativePath) => {\n const content = await readFile(path.join(dir, relativePath), 'utf8');\n return [relativePath, hashContent(content)] as const;\n }),\n );\n return Object.fromEntries(entries);\n}\n\nexport async function buildManifest(\n targetDir: string,\n generatorVersion: string,\n language: string,\n adapter: UpdateAdapter,\n): Promise<Manifest> {\n const coreFiles = await hashCoreFiles(targetDir, adapter);\n const manifestFile = await adapter.readManifestFile(targetDir);\n const { coreDependencies, coreScripts, coreFields } = adapter.extractCoreFields(manifestFile);\n return { generatorVersion, language, coreFiles, coreDependencies, coreScripts, coreFields };\n}\n\nexport const MANIFEST_RELATIVE_PATH = path.join('.clispark', 'manifest.json');\n\nexport async function writeManifest(targetDir: string, manifest: Manifest): Promise<void> {\n const manifestPath = path.join(targetDir, MANIFEST_RELATIVE_PATH);\n await mkdir(path.dirname(manifestPath), { recursive: true });\n await writeFile(manifestPath, JSON.stringify(manifest, null, 2) + '\\n');\n}\n\nexport async function readManifest(targetDir: string): Promise<Manifest | undefined> {\n try {\n const content = await readFile(path.join(targetDir, MANIFEST_RELATIVE_PATH), 'utf8');\n return JSON.parse(content) as Manifest;\n } catch {\n return undefined;\n }\n}\n\nexport async function requireManifest(targetDir: string): Promise<Manifest> {\n const manifest = await readManifest(targetDir);\n if (!manifest) {\n throw new UserError(\n 'No .clispark/manifest.json found — this project predates update support, or is not a clispark project.',\n );\n }\n return manifest;\n}\n\n/**\n * Finds clispark's own package.json by walking up from this file's location.\n * A fixed relative path (`../package.json`) can't work here: this module's\n * depth below the package root differs between running from source (tests)\n * and running as part of the bundled `dist/cli.js` (tsup flattens everything\n * into one file, so `import.meta.url` no longer reflects the original\n * per-module nesting).\n */\nexport function getGeneratorVersion(): string {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n while (true) {\n const pkgPath = path.join(dir, 'package.json');\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as { name?: string; version: string };\n if (pkg.name === 'clispark') return pkg.version;\n }\n const parentDir = path.dirname(dir);\n if (parentDir === dir) {\n throw new Error(\"Could not locate clispark's own package.json.\");\n }\n dir = parentDir;\n }\n}\n","// src/errors.ts\n\n/** An expected, user-fixable failure (bad input, unmet precondition) — distinct from an unexpected crash. */\nexport class UserError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UserError';\n }\n}\n","import { randomBytes } from 'node:crypto';\nimport { mkdirSync, readdirSync, statSync, unlinkSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\nimport envPaths from 'env-paths';\nimport pino, { type Logger } from 'pino';\n\nconst paths = envPaths('clispark', { suffix: '' });\n\n/** Runs fn, silently swallowing any error — for best-effort work that must never abort the caller. */\nexport function safely(fn: () => void): void {\n try {\n fn();\n } catch {\n // best-effort; a failure here must never affect the surrounding operation\n }\n}\n\nexport interface LoggerHandle {\n logger: Logger;\n logFilePath: string;\n}\n\nfunction buildLogFileName(commandName: string): string {\n const timestamp = new Date().toISOString().replaceAll(/[:.]/g, '-');\n const suffix = randomBytes(3).toString('hex');\n return `${commandName}-${timestamp}-${suffix}.log`;\n}\n\nfunction getRetentionDays(): number {\n const parsed = Number(process.env.LOG_RETENTION_DAYS);\n return Number.isFinite(parsed) ? parsed : 14;\n}\n\n// Common secret-shaped field names, redacted at the top level and one level of\n// nesting (`*.<key>`). Edit this list directly if your own logging needs more.\nexport const SENSITIVE_LOG_KEYS = [\n 'password',\n 'secret',\n 'token',\n 'apiKey',\n 'accessToken',\n 'refreshToken',\n 'clientSecret',\n 'authorization',\n];\n\nfunction buildRedactPaths(keys: string[]): string[] {\n return keys.flatMap((key) => [key, `*.${key}`]);\n}\n\nconst SWEEP_MARKER_FILE = '.last-sweep';\nconst SWEEP_THROTTLE_MS = 24 * 60 * 60 * 1000; // once a day is enough given day-granularity retention\n\nfunction sweepOldLogs(logDir: string): void {\n safely(() => {\n const markerPath = path.join(logDir, SWEEP_MARKER_FILE);\n let shouldSweep = true;\n try {\n shouldSweep = Date.now() - statSync(markerPath).mtimeMs >= SWEEP_THROTTLE_MS;\n } catch {\n // no marker yet (first run in this directory) - sweep now\n }\n if (!shouldSweep) return;\n\n const cutoffMs = Date.now() - getRetentionDays() * 24 * 60 * 60 * 1000;\n for (const file of readdirSync(logDir)) {\n if (file === SWEEP_MARKER_FILE) continue;\n const filePath = path.join(logDir, file);\n if (statSync(filePath).mtimeMs < cutoffMs) {\n unlinkSync(filePath);\n }\n }\n writeFileSync(markerPath, '');\n });\n}\n\nexport function createLogger(commandName: string, logDir: string = paths.log): LoggerHandle {\n mkdirSync(logDir, { recursive: true });\n sweepOldLogs(logDir);\n\n const logFilePath = path.join(logDir, buildLogFileName(commandName));\n const fileDestination = pino.destination({ dest: logFilePath, sync: true, mode: 0o600 });\n const destination = process.env.DEBUG\n ? pino.multistream([{ stream: fileDestination }, { stream: process.stdout }])\n : fileDestination;\n const logger = pino({ redact: buildRedactPaths([...SENSITIVE_LOG_KEYS, 'registryUrl']) }, destination);\n\n return { logger, logFilePath };\n}\n\nexport function withLogging(\n commandName: string,\n action: (logger: Logger) => Promise<void>,\n logDir: string = paths.log,\n loggerFactory: typeof createLogger = createLogger,\n): () => Promise<void> {\n return async () => {\n let handle: LoggerHandle;\n try {\n handle = loggerFactory(commandName, logDir);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(`\\n✖ ${message}`);\n process.exit(1);\n return;\n }\n\n const { logger, logFilePath } = handle;\n safely(() => logger.info({ command: commandName }, 'started'));\n\n try {\n await action(logger);\n safely(() => logger.info({ command: commandName }, 'completed'));\n if (process.env.DEBUG) {\n console.log(`Details: ${logFilePath}`);\n }\n } catch (error) {\n safely(() => logger.error({ command: commandName, err: error }, 'failed'));\n const message = error instanceof Error ? error.message : String(error);\n console.error(`\\n✖ ${message}`);\n console.error(`Details: ${logFilePath}`);\n process.exit(1);\n }\n };\n}\n","// src/update/update.ts\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport spawn from 'cross-spawn';\nimport { applyPlaceholders } from '../scaffold';\nimport { getGeneratorVersion, hashContent, requireManifest, writeManifest, type Manifest } from './manifest';\nimport { reconcileEntry, stringEquals, type FieldOutcome } from './reconcile';\nimport { UserError } from '../errors';\nimport { compareVersions } from './releasenotes';\nimport type { UpdateAdapter } from './adapter';\n\nexport interface UpdateDeps {\n runCommand: (command: string, args: string[], cwd: string) => Promise<void>;\n captureCommand: (command: string, args: string[], cwd: string) => Promise<string>;\n}\n\nasync function defaultRunCommand(command: string, args: string[], cwd: string): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(command, args, { cwd, stdio: 'inherit' });\n child.on('error', reject);\n child.on('close', (code) => {\n if (code === 0) resolve();\n else reject(new Error(`Command \"${command} ${args.join(' ')}\" exited with code ${code}`));\n });\n });\n}\n\nasync function defaultCaptureCommand(command: string, args: string[], cwd: string): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n const child = spawn(command, args, { cwd });\n let stdout = '';\n child.stdout?.on('data', (chunk: Buffer) => {\n stdout += chunk.toString();\n });\n child.on('error', reject);\n child.on('close', (code) => {\n if (code === 0) resolve(stdout);\n else reject(new Error(`Command \"${command} ${args.join(' ')}\" exited with code ${code}`));\n });\n });\n}\n\nconst defaultUpdateDeps: UpdateDeps = { runCommand: defaultRunCommand, captureCommand: defaultCaptureCommand };\n\nexport interface FileOutcomeEntry {\n path: string;\n outcome: 'added' | 'replaced' | 'skipped' | 'no-longer-core';\n}\n\nexport interface UpdateResult {\n status: 'up-to-date' | 'no-changes' | 'updated';\n fromVersion: string;\n toVersion: string;\n files: FileOutcomeEntry[];\n dependencies: FieldOutcome[];\n scripts: FieldOutcome[];\n fields: FieldOutcome[];\n}\n\nexport async function updateProject(\n targetDir: string,\n adapter: UpdateAdapter,\n templateDir: string,\n language: string,\n deps: UpdateDeps = defaultUpdateDeps,\n): Promise<UpdateResult> {\n const status = (await deps.captureCommand('git', ['status', '--porcelain'], targetDir)).trim();\n if (status.length > 0) {\n throw new UserError('Working tree is not clean. Commit or stash your changes before running update.');\n }\n\n const oldManifest = await requireManifest(targetDir);\n const toVersion = getGeneratorVersion();\n const fromVersion = oldManifest.generatorVersion;\n\n if (compareVersions(fromVersion, toVersion) >= 0) {\n return { status: 'up-to-date', fromVersion, toVersion, files: [], dependencies: [], scripts: [], fields: [] };\n }\n\n const currentManifestFile = await adapter.readManifestFile(targetDir);\n const projectName = adapter.readProjectName(currentManifestFile);\n\n const newTemplateRaw = applyPlaceholders(\n await readFile(path.join(templateDir, adapter.manifestFileName), 'utf8'),\n projectName,\n );\n const newTemplateManifestFile = adapter.parseManifestFile(newTemplateRaw);\n\n const files: FileOutcomeEntry[] = [];\n const newCoreFiles: Record<string, string> = {};\n const fileWrites: { targetPath: string; content: string }[] = [];\n\n // Reads + hashes run in parallel; results are then applied in adapter.coreFilePaths\n // order below so files/fileWrites stay deterministic regardless of I/O timing.\n const perFileResults = await Promise.all(\n adapter.coreFilePaths.map(async (relativePath) => {\n const newContent = applyPlaceholders(\n await readFile(path.join(templateDir, adapter.templateSourcePath(relativePath)), 'utf8'),\n projectName,\n );\n const newHash = hashContent(newContent);\n\n let currentHash: string | undefined;\n try {\n currentHash = hashContent(await readFile(path.join(targetDir, relativePath), 'utf8'));\n } catch {\n currentHash = undefined;\n }\n\n const result = reconcileEntry(currentHash, oldManifest.coreFiles[relativePath], newHash, stringEquals);\n return { relativePath, newContent, result };\n }),\n );\n\n for (const { relativePath, newContent, result } of perFileResults) {\n files.push({ path: relativePath, outcome: result.outcome });\n newCoreFiles[relativePath] = result.value;\n\n if (result.outcome === 'added' || result.outcome === 'replaced') {\n fileWrites.push({ targetPath: path.join(targetDir, relativePath), content: newContent });\n }\n }\n\n for (const relativePath of Object.keys(oldManifest.coreFiles)) {\n if (adapter.coreFilePaths.includes(relativePath)) continue;\n try {\n await readFile(path.join(targetDir, relativePath), 'utf8');\n files.push({ path: relativePath, outcome: 'no-longer-core' });\n } catch {\n // already gone locally, nothing to report\n }\n }\n\n const fileMerge = adapter.mergeManifestFile(currentManifestFile, oldManifest, newTemplateManifestFile);\n\n const hasFileChanges = files.some(\n (f) => f.outcome === 'added' || f.outcome === 'replaced' || f.outcome === 'no-longer-core',\n );\n const hasChanges = hasFileChanges || fileMerge.changed;\n\n if (!hasChanges) {\n return {\n status: 'no-changes',\n fromVersion,\n toVersion,\n files,\n dependencies: fileMerge.dependencies,\n scripts: fileMerge.scripts,\n fields: fileMerge.fields,\n };\n }\n\n for (const write of fileWrites) {\n await mkdir(path.dirname(write.targetPath), { recursive: true });\n await writeFile(write.targetPath, write.content);\n }\n\n if (fileMerge.changed) {\n await adapter.writeManifestFile(targetDir, fileMerge.updatedFile);\n }\n\n const newManifest: Manifest = {\n generatorVersion: toVersion,\n language,\n coreFiles: newCoreFiles,\n coreDependencies: fileMerge.coreDependencies,\n coreScripts: fileMerge.coreScripts,\n coreFields: fileMerge.coreFields,\n };\n await writeManifest(targetDir, newManifest);\n\n await deps.runCommand('git', ['add', '-A'], targetDir);\n await deps.runCommand('git', ['commit', '-m', `chore: update clispark core to v${toVersion}`], targetDir);\n\n return {\n status: 'updated',\n fromVersion,\n toVersion,\n files,\n dependencies: fileMerge.dependencies,\n scripts: fileMerge.scripts,\n fields: fileMerge.fields,\n };\n}\n\nexport function formatUpdateSummary(result: UpdateResult): string {\n if (result.status === 'up-to-date') {\n return `Already up to date (v${result.toVersion}).`;\n }\n\n const added = result.files.filter((f) => f.outcome === 'added');\n const replaced = result.files.filter((f) => f.outcome === 'replaced');\n const skipped = result.files.filter((f) => f.outcome === 'skipped');\n const noLongerCore = result.files.filter((f) => f.outcome === 'no-longer-core');\n\n const lines: string[] = [];\n if (result.status === 'no-changes') {\n lines.push(\n noLongerCore.length\n ? `No changes applied: nothing to update since v${result.fromVersion}.`\n : `No changes applied: every core file/field has been modified locally since v${result.fromVersion}.`,\n );\n } else {\n lines.push(`Updated core from v${result.fromVersion} to v${result.toVersion}.`);\n }\n\n if (added.length) lines.push(` New: ${added.map((f) => f.path).join(', ')}`);\n if (replaced.length) lines.push(` Updated: ${replaced.map((f) => f.path).join(', ')}`);\n if (skipped.length) lines.push(` Skipped (locally modified): ${skipped.map((f) => f.path).join(', ')}`);\n if (noLongerCore.length) {\n lines.push(\n ` No longer part of the core, safe to remove manually: ${noLongerCore.map((f) => f.path).join(', ')}`,\n );\n }\n\n const fieldOutcomes = [...result.dependencies, ...result.scripts, ...result.fields].filter(\n (o) => o.outcome !== 'skipped',\n );\n if (fieldOutcomes.length) {\n lines.push(` Manifest: ${fieldOutcomes.map((o) => `${o.key} (${o.outcome})`).join(', ')}`);\n }\n\n if (result.status === 'updated') {\n lines.push('Run \"clispark releasenotes\" to see what changed.');\n }\n\n return lines.join('\\n');\n}\n","// src/update/releasenotes.ts\nimport { getGeneratorVersion, requireManifest } from './manifest';\n\nexport interface GitHubRelease {\n tag_name: string;\n name: string;\n body: string;\n}\n\nfunction stripV(version: string): string {\n return version.startsWith('v') ? version.slice(1) : version;\n}\n\nexport function compareVersions(a: string, b: string): number {\n const partsA = stripV(a).split('.').map(Number);\n const partsB = stripV(b).split('.').map(Number);\n const length = Math.max(partsA.length, partsB.length);\n for (let i = 0; i < length; i++) {\n const diff = (partsA[i] ?? 0) - (partsB[i] ?? 0);\n if (diff !== 0) return diff;\n }\n return 0;\n}\n\nexport interface ReleaseNotesResult {\n status: 'up-to-date' | 'releases-found';\n fromVersion: string;\n toVersion: string;\n releases: GitHubRelease[];\n}\n\nconst RELEASES_URL = 'https://api.github.com/repos/martinwichner/clispark/releases';\nconst FETCH_TIMEOUT_MS = 5000;\n\nexport async function fetchReleaseNotes(\n targetDir: string,\n fetchFn: typeof fetch = fetch,\n): Promise<ReleaseNotesResult> {\n const manifest = await requireManifest(targetDir);\n const fromVersion = manifest.generatorVersion;\n const toVersion = getGeneratorVersion();\n\n if (compareVersions(fromVersion, toVersion) >= 0) {\n return { status: 'up-to-date', fromVersion, toVersion, releases: [] };\n }\n\n const response = await fetchFn(RELEASES_URL, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n if (!response.ok) {\n throw new Error(`Failed to fetch release notes: GitHub API responded with ${response.status}`);\n }\n const allReleases = (await response.json()) as GitHubRelease[];\n\n const releases = allReleases\n .filter((r) => compareVersions(r.tag_name, fromVersion) > 0 && compareVersions(r.tag_name, toVersion) <= 0)\n .sort((a, b) => compareVersions(b.tag_name, a.tag_name));\n\n return { status: 'releases-found', fromVersion, toVersion, releases };\n}\n\nexport function formatReleaseNotes(result: ReleaseNotesResult): string {\n if (result.status === 'up-to-date') {\n return `You're on the latest clispark version (v${result.toVersion}), nothing to show.`;\n }\n if (result.releases.length === 0) {\n return `No published releases found between v${result.fromVersion} and v${result.toVersion}.`;\n }\n return result.releases.map((r) => `## ${r.tag_name}\\n\\n${r.body}`).join('\\n\\n');\n}\n","// src/add-wizard.ts\nimport { intro, outro, select, text, confirm, isCancel, cancel, log } from '@clack/prompts';\nimport type {\n CommandGenerator,\n CommandSpec,\n ExistingCommandNode,\n ParameterSpec,\n ParameterType,\n} from './languages/command-generator';\n\nexport interface AddWizardDeps {\n commandGenerator: CommandGenerator;\n}\n\nfunction exitIfCancelled(value: unknown): void {\n if (isCancel(value)) {\n cancel('Operation cancelled.');\n process.exit(1);\n }\n}\n\nconst NEW_TOP_LEVEL = '__new_top_level__';\nconst HERE = '__here__';\n\nfunction flattenForMenu(nodes: ExistingCommandNode[]): { value: string; label: string }[] {\n const result: { value: string; label: string }[] = [];\n for (const node of nodes) {\n result.push({ value: node.path, label: node.displayLabel });\n result.push(...flattenForMenu(node.children));\n }\n return result;\n}\n\nfunction findNode(nodes: ExistingCommandNode[], targetPath: string): ExistingCommandNode | undefined {\n for (const node of nodes) {\n if (node.path === targetPath) return node;\n const found = findNode(node.children, targetPath);\n if (found) return found;\n }\n return undefined;\n}\n\nasync function selectWithinNode(node: ExistingCommandNode): Promise<string[]> {\n if (node.children.length === 0) {\n return node.path.split(' ');\n }\n\n const options = [\n { value: HERE, label: `Direct subcommand of \"${node.path}\"` },\n ...node.children.map((child) => ({ value: child.path, label: `Under \"${child.path}\"` })),\n ];\n const choice = await select({ message: `Where under \"${node.path}\"?`, options });\n exitIfCancelled(choice);\n\n if (choice === HERE) {\n return node.path.split(' ');\n }\n const childNode = node.children.find((c) => c.path === choice)!;\n return selectWithinNode(childNode);\n}\n\nasync function selectPath(existing: ExistingCommandNode[]): Promise<string[]> {\n const options = [{ value: NEW_TOP_LEVEL, label: 'New top-level command' }, ...flattenForMenu(existing)];\n const choice = await select({ message: 'Where should the new command go?', options });\n exitIfCancelled(choice);\n\n if (choice === NEW_TOP_LEVEL) {\n return [];\n }\n\n const node = findNode(existing, choice as string)!;\n return selectWithinNode(node);\n}\n\nfunction flattenPaths(nodes: ExistingCommandNode[]): string[] {\n return nodes.flatMap((node) => [node.path, ...flattenPaths(node.children)]);\n}\n\nasync function collectParameters(): Promise<ParameterSpec[]> {\n const parameters: ParameterSpec[] = [];\n let hasOptional = false;\n\n for (;;) {\n const addMore = await confirm({\n message: parameters.length === 0 ? 'Add a parameter?' : 'Add another parameter?',\n });\n exitIfCancelled(addMore);\n if (!addMore) break;\n\n const nameValue = await text({\n message: 'Parameter name',\n validate: (value) => {\n if (!/^[a-z][a-zA-Z0-9]*$/.test(value)) return 'Use a single word starting with a lowercase letter.';\n if (parameters.some((p) => p.name === value)) return 'A parameter with this name already exists.';\n return undefined;\n },\n });\n exitIfCancelled(nameValue);\n const name = nameValue as string;\n\n const typeValue = await select({\n message: 'Parameter type',\n options: [\n { value: 'string', label: 'String' },\n { value: 'integer', label: 'Integer' },\n { value: 'boolean', label: 'Boolean' },\n { value: 'enum', label: 'String with allowed values' },\n ],\n });\n exitIfCancelled(typeValue);\n const type = typeValue as ParameterType;\n\n let required = false;\n if (type !== 'boolean') {\n const options = hasOptional\n ? [{ value: false, label: 'Optional' }]\n : [\n { value: true, label: 'Required' },\n { value: false, label: 'Optional' },\n ];\n const requiredValue = await select({ message: 'Required or optional?', options });\n exitIfCancelled(requiredValue);\n required = requiredValue as boolean;\n }\n if (!required) hasOptional = true;\n\n let allowedValues: string[] | undefined;\n if (type === 'enum') {\n const valuesInput = await text({\n message: 'Allowed values (comma-separated)',\n validate: (value) => {\n const values = value\n .split(',')\n .map((v) => v.trim())\n .filter(Boolean);\n if (values.length < 2) return 'Enter at least two comma-separated values.';\n for (const v of values) {\n if (!/^[A-Za-z0-9_-]+$/.test(v)) {\n return `Invalid value \"${v}\": use only letters, numbers, hyphens, and underscores.`;\n }\n }\n return undefined;\n },\n });\n exitIfCancelled(valuesInput);\n allowedValues = (valuesInput as string)\n .split(',')\n .map((v) => v.trim())\n .filter(Boolean);\n }\n\n parameters.push({ name, type, required, allowedValues });\n }\n\n return parameters;\n}\n\nexport async function runAddWizard(targetDir: string, deps: AddWizardDeps): Promise<void> {\n intro('clispark add — add a new command');\n\n const existing = await deps.commandGenerator.listExistingCommands(targetDir);\n const pathSegments = await selectPath(existing);\n const existingPaths = new Set(flattenPaths(existing));\n\n const nameValue = await text({\n message: 'Command name',\n validate: (value) => {\n if (!/^[a-z][a-zA-Z0-9]*$/.test(value)) return 'Use a single word starting with a lowercase letter.';\n const fullPath = [...pathSegments, value].join(' ');\n if (existingPaths.has(fullPath)) return `\"${fullPath}\" already exists.`;\n return undefined;\n },\n });\n exitIfCancelled(nameValue);\n const fullPathSegments = [...pathSegments, nameValue as string];\n\n const parameters = await collectParameters();\n\n log.info(`About to create \"${fullPathSegments.join(' ')}\" with ${parameters.length} parameter(s).`);\n const proceed = await confirm({ message: 'Proceed?' });\n exitIfCancelled(proceed);\n if (!proceed) {\n cancel('Cancelled.');\n process.exit(1);\n }\n\n const spec: CommandSpec = { pathSegments: fullPathSegments, parameters };\n const result = await deps.commandGenerator.generateCommand(targetDir, spec);\n\n outro(`Created ${result.commandFile} and ${result.testFile}.`);\n}\n","// src/whoami.ts\nimport os from 'node:os';\n\nconst JOKE_API_URL = 'https://v2.jokeapi.dev/joke/Programming,Miscellaneous';\nconst FETCH_TIMEOUT_MS = 3000;\n\n/** Languages JokeAPI (https://jokeapi.dev/) currently supports, per its /languages endpoint. */\nconst SUPPORTED_JOKE_LANGUAGES = ['cs', 'de', 'en', 'es', 'fr', 'pt'];\n\nexport const LOGO = String.raw`\n ⚡ clispark\n`;\n\nexport const FALLBACK_QUOTES = [\n \"Green unit tests don't mean it works. Real end-to-end verification does.\",\n 'A default value can silently reintroduce coupling you just removed.',\n \"The bug you can't find locally is waiting for you in CI.\",\n \"YAGNI until you actually need it — then it's just an adapter away.\",\n 'Every folder move has a bundling-depth bug waiting to happen.',\n 'The cheapest fix is the one you verify before you ship it.',\n 'TDD: write the failing test first, or explain later why it passed by accident.',\n \"If it's not tested against a real filesystem, it's a theory, not a fact.\",\n];\n\ninterface JokeApiSingle {\n error: false;\n type: 'single';\n joke: string;\n}\n\ninterface JokeApiTwoPart {\n error: false;\n type: 'twopart';\n setup: string;\n delivery: string;\n}\n\ninterface JokeApiError {\n error: true;\n}\n\ntype JokeApiResponse = JokeApiSingle | JokeApiTwoPart | JokeApiError;\n\n/** Maps a BCP-47 locale (e.g. \"de-DE\") to a JokeAPI language code, defaulting to \"en\" when unsupported. */\nexport function detectJokeLanguage(\n locale: string = Intl.DateTimeFormat().resolvedOptions().locale,\n): string {\n const primary = locale.split('-')[0].toLowerCase();\n return SUPPORTED_JOKE_LANGUAGES.includes(primary) ? primary : 'en';\n}\n\nfunction pickFallbackQuote(): string {\n return FALLBACK_QUOTES[Math.floor(Math.random() * FALLBACK_QUOTES.length)];\n}\n\nexport interface OsFacts {\n uptime: () => number;\n hostname: () => string;\n cpus: () => os.CpuInfo[];\n totalmem: () => number;\n platform: () => NodeJS.Platform;\n release: () => string;\n arch: () => string;\n}\n\nconst defaultOsFacts: OsFacts = {\n uptime: () => os.uptime(),\n hostname: () => os.hostname(),\n cpus: () => os.cpus(),\n totalmem: () => os.totalmem(),\n platform: () => os.platform(),\n release: () => os.release(),\n arch: () => os.arch(),\n};\n\nfunction formatUptime(seconds: number): string {\n const days = Math.floor(seconds / 86400);\n const hours = Math.floor((seconds % 86400) / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n const parts: string[] = [];\n if (days > 0) parts.push(`${days}d`);\n if (days > 0 || hours > 0) parts.push(`${hours}h`);\n parts.push(`${minutes}m`);\n return parts.join(' ');\n}\n\nconst FACT_GENERATORS: Array<(facts: OsFacts) => string> = [\n (facts) => `This machine has been up for ${formatUptime(facts.uptime())}.`,\n (facts) => `Hostname: ${facts.hostname()}`,\n (facts) => {\n const cpus = facts.cpus();\n return `CPU: ${cpus[0]?.model.trim() ?? 'unknown'} (${cpus.length} logical cores)`;\n },\n (facts) => `RAM: ${(facts.totalmem() / 1024 ** 3).toFixed(1)} GB total`,\n (facts) => `OS: ${facts.platform()} ${facts.release()} (${facts.arch()})`,\n];\n\nexport function getRandomFunFact(osFacts: OsFacts = defaultOsFacts, randomFn: () => number = Math.random): string {\n const index = Math.floor(randomFn() * FACT_GENERATORS.length);\n return FACT_GENERATORS[index](osFacts);\n}\n\nasync function fetchJoke(language: string, fetchFn: typeof fetch): Promise<string | undefined> {\n try {\n const url = `${JOKE_API_URL}?lang=${language}&safe-mode`;\n const response = await fetchFn(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });\n if (!response.ok) return undefined;\n\n const data = (await response.json()) as JokeApiResponse;\n if (data.error) return undefined;\n return data.type === 'single' ? data.joke : `${data.setup}\\n${data.delivery}`;\n } catch {\n return undefined;\n }\n}\n\nexport type WhoamiMode = 'joke' | 'fact' | 'random';\n\nexport async function getWhoamiOutput(\n fetchFn: typeof fetch = fetch,\n osFacts: OsFacts = defaultOsFacts,\n randomFn: () => number = Math.random,\n mode: WhoamiMode = 'random',\n): Promise<string> {\n const showFact = mode === 'fact' || (mode === 'random' && randomFn() < 0.5);\n if (showFact) {\n return `${LOGO}\\n${getRandomFunFact(osFacts, randomFn)}\\n`;\n }\n\n const language = detectJokeLanguage();\n const quote = (await fetchJoke(language, fetchFn)) ?? pickFallbackQuote();\n return `${LOGO}\\n${quote}\\n`;\n}\n","// src/confetti.ts\n\nconst CONFETTI_VARIANTS = [\n '✨ 🎉 ✨ 🎊 ✨ 🎉 ✨\\n 🎈 🎊 🎈\\n✨ 🎉 ✨ 🎉',\n '🎊 ✨ 🎈 ✨ 🎊\\n 🎉 🎉 🎉\\n✨ 🎈 ✨ 🎈 ✨',\n '🎉✨🎊✨🎉✨🎊✨🎉\\n 🎈 🎈\\n✨🎊✨🎉✨🎊✨🎉✨',\n];\n\nexport function getConfetti(randomFn: () => number = Math.random): string {\n const index = Math.floor(randomFn() * CONFETTI_VARIANTS.length);\n return CONFETTI_VARIANTS[index];\n}\n\nexport function printConfetti(randomFn: () => number = Math.random): void {\n console.log(`\\n${getConfetti(randomFn)}\\n`);\n}\n"],"mappings":"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","names":["path","path","path","path","readFile","writeFile","path","writeFile","path","paths","path","writeFile","path","path","readFile","writeFile","path","CORE_FILE_PATHS","extractCoreFields","readFile","path","writeFile","mkdir","readFile","writeFile","path","FETCH_TIMEOUT_MS","checkNameAvailability","applyPrivateIntent","applyRegistryUrl","mkdir","readFile","readdir","writeFile","path","listExistingCommands","path","readdir","paths","readFile","toClassName","generateCommandFileContent","sampleArgValue","generateTestFileContent","generateCommand","mkdir","writeFile","validateProjectName","path","pack","readdir","readFile","writeFile","path","existsSync","readFileSync","mkdir","readFile","writeFile","path","fileURLToPath","readFile","path","mkdir","writeFile","fileURLToPath","existsSync","readFileSync","readdir","path","readFile","writeFile","path","mkdir","readFile","writeFile","path","spawn","FETCH_TIMEOUT_MS","defaultRunCommand","spawn","readFile","path","mkdir","writeFile","intro","outro","select","text","isCancel","cancel","log","exitIfCancelled","FETCH_TIMEOUT_MS","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clispark",
3
- "version": "1.15.0",
3
+ "version": "1.16.1",
4
4
  "description": "Interactive scaffolding tool for new CLI projects",
5
5
  "keywords": [
6
6
  "cli",