clispark 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import path9 from "path";
4
+ import path12 from "path";
5
5
  import { Command } from "commander";
6
6
 
7
7
  // src/wizard.ts
@@ -212,9 +212,14 @@ async function applyPrivateIntent(targetDir) {
212
212
  pkg.private = true;
213
213
  await writeFile2(packageJsonPath, JSON.stringify(pkg, null, 2) + "\n");
214
214
  }
215
+ async function applyRegistryUrl(targetDir, registryUrl) {
216
+ await writeFile2(path3.join(targetDir, ".npmrc"), `registry=${registryUrl}
217
+ `);
218
+ }
215
219
  var npmRegistryChecker = {
216
220
  checkNameAvailability,
217
- applyPrivateIntent
221
+ applyPrivateIntent,
222
+ applyRegistryUrl
218
223
  };
219
224
 
220
225
  // src/languages/packs/node-oclif.ts
@@ -239,13 +244,223 @@ var nodeOclifPack = {
239
244
  defaultUrl: NPM_DEFAULT_REGISTRY_URL,
240
245
  promptLabel: "Custom npm registry URL (leave empty for npmjs.org)",
241
246
  checkNameAvailability: npmRegistryChecker.checkNameAvailability,
242
- applyPrivateIntent: npmRegistryChecker.applyPrivateIntent
247
+ applyPrivateIntent: npmRegistryChecker.applyPrivateIntent,
248
+ applyRegistryUrl: npmRegistryChecker.applyRegistryUrl
249
+ }
250
+ };
251
+
252
+ // src/languages/packs/dotnet.ts
253
+ import path7 from "path";
254
+
255
+ // src/update/adapters/dotnet.ts
256
+ import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
257
+ import path5 from "path";
258
+ var CORE_FILE_PATHS2 = [
259
+ "Cli.slnx",
260
+ "src/Program.cs",
261
+ "src/ICliCommand.cs",
262
+ "src/CommandPathAttribute.cs",
263
+ "src/CommandDiscovery.cs",
264
+ "src/CliUserException.cs",
265
+ "src/Logging/CliLoggerFactory.cs",
266
+ "src/Logging/SensitivePropertyEnricher.cs",
267
+ "tests/Cli.Tests.csproj",
268
+ "ARCHITECTURE.md",
269
+ ".gitignore"
270
+ ];
271
+ function escapeRegExp(value) {
272
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
273
+ }
274
+ function extractTag(content, tag) {
275
+ const match = content.match(new RegExp(`<${tag}>([^<]*)</${tag}>`));
276
+ if (!match) throw new Error(`.csproj is missing a <${tag}> tag`);
277
+ return match[1];
278
+ }
279
+ function extractPackageReferences(content) {
280
+ const refs = {};
281
+ const re = /<PackageReference\s+Include="([^"]+)"\s+Version="([^"]+)"\s*\/>/g;
282
+ let m;
283
+ while (m = re.exec(content)) {
284
+ refs[m[1]] = m[2];
285
+ }
286
+ return refs;
287
+ }
288
+ function setTag(content, tag, value) {
289
+ const escapedTag = escapeRegExp(tag);
290
+ return content.replace(new RegExp(`(<${escapedTag}>)[^<]*(</${escapedTag}>)`), `$1${value}$2`);
291
+ }
292
+ function setPackageReferenceVersion(content, name, version) {
293
+ const re = new RegExp(`(<PackageReference\\s+Include="${escapeRegExp(name)}"\\s+Version=")[^"]+(")`);
294
+ return content.replace(re, `$1${version}$2`);
295
+ }
296
+ function addPackageReference(content, name, version) {
297
+ const re = /^([ \t]*)<PackageReference[^\n]*\/>\n(?=[ \t]*<\/ItemGroup>)/m;
298
+ return content.replace(re, (match, indent) => `${match}${indent}<PackageReference Include="${name}" Version="${version}" />
299
+ `);
300
+ }
301
+ function parseManifestFile(rawContent) {
302
+ return {
303
+ raw: rawContent,
304
+ version: extractTag(rawContent, "Version"),
305
+ targetFramework: extractTag(rawContent, "TargetFramework"),
306
+ packageId: extractTag(rawContent, "PackageId"),
307
+ toolCommandName: extractTag(rawContent, "ToolCommandName"),
308
+ packageReferences: extractPackageReferences(rawContent)
309
+ };
310
+ }
311
+ function extractCoreFields2(manifestFile) {
312
+ return {
313
+ coreDependencies: manifestFile.packageReferences,
314
+ coreScripts: {},
315
+ coreFields: { TargetFramework: manifestFile.targetFramework }
316
+ };
317
+ }
318
+ function mergeManifestFile(current, oldManifest, newTemplate) {
319
+ let raw = current.raw;
320
+ let changed = false;
321
+ const dependencies = [];
322
+ const coreDependencies = {};
323
+ for (const name of Object.keys(newTemplate.packageReferences)) {
324
+ const newValue = newTemplate.packageReferences[name];
325
+ const currentValue = current.packageReferences[name];
326
+ const oldValue = oldManifest.coreDependencies[name];
327
+ const result = reconcileEntry(currentValue, oldValue, newValue, stringEquals);
328
+ dependencies.push({ key: name, outcome: result.outcome });
329
+ coreDependencies[name] = result.value;
330
+ if (result.outcome === "added") {
331
+ changed = true;
332
+ raw = addPackageReference(raw, name, result.value);
333
+ } else if (result.outcome !== "skipped" && result.value !== currentValue) {
334
+ changed = true;
335
+ raw = setPackageReferenceVersion(raw, name, result.value);
336
+ }
337
+ }
338
+ const oldCoreFields = oldManifest.coreFields;
339
+ const fields = [];
340
+ const targetFrameworkResult = reconcileEntry(
341
+ current.targetFramework,
342
+ oldCoreFields.TargetFramework,
343
+ newTemplate.targetFramework,
344
+ stringEquals
345
+ );
346
+ fields.push({ key: "TargetFramework", outcome: targetFrameworkResult.outcome });
347
+ if (targetFrameworkResult.outcome !== "skipped" && targetFrameworkResult.value !== current.targetFramework) {
348
+ changed = true;
349
+ raw = setTag(raw, "TargetFramework", targetFrameworkResult.value);
350
+ }
351
+ return {
352
+ updatedFile: { ...current, raw },
353
+ changed,
354
+ dependencies,
355
+ scripts: [],
356
+ fields,
357
+ coreDependencies,
358
+ coreScripts: {},
359
+ coreFields: { TargetFramework: targetFrameworkResult.value }
360
+ };
361
+ }
362
+ var dotnetAdapter = {
363
+ coreFilePaths: CORE_FILE_PATHS2,
364
+ templateSourcePath(relativePath) {
365
+ return relativePath === ".gitignore" ? "gitignore" : relativePath;
366
+ },
367
+ manifestFileName: "src/Cli.csproj",
368
+ async readManifestFile(dir) {
369
+ const content = await readFile3(path5.join(dir, "src", "Cli.csproj"), "utf8");
370
+ return parseManifestFile(content);
371
+ },
372
+ async writeManifestFile(dir, content) {
373
+ await writeFile3(path5.join(dir, "src", "Cli.csproj"), content.raw);
374
+ },
375
+ parseManifestFile,
376
+ readProjectName(manifestFile) {
377
+ return manifestFile.packageId;
378
+ },
379
+ extractCoreFields(manifestFile) {
380
+ return extractCoreFields2(manifestFile);
381
+ },
382
+ mergeManifestFile(current, oldManifest, newTemplate) {
383
+ return mergeManifestFile(current, oldManifest, newTemplate);
384
+ }
385
+ };
386
+
387
+ // src/languages/registry-checkers/nuget.ts
388
+ import { mkdir, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
389
+ import path6 from "path";
390
+ var NUGET_DEFAULT_REGISTRY_URL = "https://api.nuget.org/v3/index.json";
391
+ var NUGET_FLATCONTAINER_BASE = "https://api.nuget.org/v3-flatcontainer";
392
+ var FETCH_TIMEOUT_MS2 = 5e3;
393
+ async function checkNameAvailability2(name) {
394
+ const url = `${NUGET_FLATCONTAINER_BASE}/${encodeURIComponent(name.toLowerCase())}/index.json`;
395
+ try {
396
+ const response = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS2) });
397
+ if (response.status === 404) return "available";
398
+ if (response.status === 200) return "taken";
399
+ return "unverified";
400
+ } catch {
401
+ return "unverified";
402
+ }
403
+ }
404
+ async function applyPrivateIntent2(targetDir) {
405
+ const csprojPath = path6.join(targetDir, "src", "Cli.csproj");
406
+ const content = await readFile4(csprojPath, "utf8");
407
+ const updated = content.replace(
408
+ /(<PropertyGroup>\s*\n)/,
409
+ "$1 <IsPackable>false</IsPackable>\n"
410
+ );
411
+ await writeFile4(csprojPath, updated);
412
+ }
413
+ async function applyRegistryUrl2(targetDir, registryUrl) {
414
+ const config = [
415
+ '<?xml version="1.0" encoding="utf-8"?>',
416
+ "<configuration>",
417
+ " <packageSources>",
418
+ " <clear />",
419
+ ` <add key="custom" value="${registryUrl}" />`,
420
+ " </packageSources>",
421
+ "</configuration>",
422
+ ""
423
+ ].join("\n");
424
+ await mkdir(targetDir, { recursive: true });
425
+ await writeFile4(path6.join(targetDir, "NuGet.config"), config);
426
+ }
427
+ var nugetRegistryChecker = {
428
+ checkNameAvailability: checkNameAvailability2,
429
+ applyPrivateIntent: applyPrivateIntent2,
430
+ applyRegistryUrl: applyRegistryUrl2
431
+ };
432
+
433
+ // src/languages/packs/dotnet.ts
434
+ function validateProjectName2(value) {
435
+ if (!value || value.trim().length === 0) return "Project name is required.";
436
+ if (!/^[A-Z][A-Za-z0-9]*$/.test(value)) {
437
+ return "Use PascalCase, starting with an uppercase letter (e.g. MyTool).";
438
+ }
439
+ return void 0;
440
+ }
441
+ var dotnetPack = {
442
+ id: "dotnet",
443
+ displayName: ".NET / C# (System.CommandLine)",
444
+ templateDir: path7.join(findPackageRoot(), "templates", "dotnet"),
445
+ scaffoldCommands: [
446
+ { command: "dotnet", args: ["restore"] },
447
+ { command: "dotnet", args: ["build"] }
448
+ ],
449
+ validateProjectName: validateProjectName2,
450
+ updateAdapter: dotnetAdapter,
451
+ registry: {
452
+ defaultUrl: NUGET_DEFAULT_REGISTRY_URL,
453
+ promptLabel: "Custom NuGet feed URL (leave empty for nuget.org)",
454
+ checkNameAvailability: nugetRegistryChecker.checkNameAvailability,
455
+ applyPrivateIntent: nugetRegistryChecker.applyPrivateIntent,
456
+ applyRegistryUrl: nugetRegistryChecker.applyRegistryUrl
243
457
  }
244
458
  };
245
459
 
246
460
  // src/languages/index.ts
247
461
  var LANGUAGE_PACKS = {
248
- [nodeOclifPack.id]: nodeOclifPack
462
+ [nodeOclifPack.id]: nodeOclifPack,
463
+ [dotnetPack.id]: dotnetPack
249
464
  };
250
465
 
251
466
  // src/wizard.ts
@@ -324,15 +539,15 @@ async function runWizard(deps = defaultDeps) {
324
539
  }
325
540
 
326
541
  // src/scaffold.ts
327
- import { cp, readdir, readFile as readFile4, rename, writeFile as writeFile4 } from "fs/promises";
328
- import path6 from "path";
542
+ import { cp, readdir, readFile as readFile6, rename, writeFile as writeFile6 } from "fs/promises";
543
+ import path9 from "path";
329
544
  import spawn from "cross-spawn";
330
545
 
331
546
  // src/update/manifest.ts
332
547
  import { createHash } from "crypto";
333
548
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
334
- import { mkdir, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
335
- import path5 from "path";
549
+ import { mkdir as mkdir2, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
550
+ import path8 from "path";
336
551
  import { fileURLToPath as fileURLToPath2 } from "url";
337
552
 
338
553
  // src/errors.ts
@@ -350,7 +565,7 @@ function hashContent(content) {
350
565
  async function hashCoreFiles(dir, adapter) {
351
566
  const entries = await Promise.all(
352
567
  adapter.coreFilePaths.map(async (relativePath) => {
353
- const content = await readFile3(path5.join(dir, relativePath), "utf8");
568
+ const content = await readFile5(path8.join(dir, relativePath), "utf8");
354
569
  return [relativePath, hashContent(content)];
355
570
  })
356
571
  );
@@ -362,15 +577,15 @@ async function buildManifest(targetDir, generatorVersion, language, adapter) {
362
577
  const { coreDependencies, coreScripts, coreFields } = adapter.extractCoreFields(manifestFile);
363
578
  return { generatorVersion, language, coreFiles, coreDependencies, coreScripts, coreFields };
364
579
  }
365
- var MANIFEST_RELATIVE_PATH = path5.join(".clispark", "manifest.json");
580
+ var MANIFEST_RELATIVE_PATH = path8.join(".clispark", "manifest.json");
366
581
  async function writeManifest(targetDir, manifest) {
367
- const manifestPath = path5.join(targetDir, MANIFEST_RELATIVE_PATH);
368
- await mkdir(path5.dirname(manifestPath), { recursive: true });
369
- await writeFile3(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
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");
370
585
  }
371
586
  async function readManifest(targetDir) {
372
587
  try {
373
- const content = await readFile3(path5.join(targetDir, MANIFEST_RELATIVE_PATH), "utf8");
588
+ const content = await readFile5(path8.join(targetDir, MANIFEST_RELATIVE_PATH), "utf8");
374
589
  return JSON.parse(content);
375
590
  } catch {
376
591
  return void 0;
@@ -386,14 +601,14 @@ async function requireManifest(targetDir) {
386
601
  return manifest;
387
602
  }
388
603
  function getGeneratorVersion() {
389
- let dir = path5.dirname(fileURLToPath2(import.meta.url));
604
+ let dir = path8.dirname(fileURLToPath2(import.meta.url));
390
605
  while (true) {
391
- const pkgPath = path5.join(dir, "package.json");
606
+ const pkgPath = path8.join(dir, "package.json");
392
607
  if (existsSync2(pkgPath)) {
393
608
  const pkg = JSON.parse(readFileSync2(pkgPath, "utf8"));
394
609
  if (pkg.name === "clispark") return pkg.version;
395
610
  }
396
- const parentDir = path5.dirname(dir);
611
+ const parentDir = path8.dirname(dir);
397
612
  if (parentDir === dir) {
398
613
  throw new Error("Could not locate clispark's own package.json.");
399
614
  }
@@ -420,7 +635,7 @@ async function collectFiles(dir) {
420
635
  const entries = await readdir(dir, { withFileTypes: true });
421
636
  const files = await Promise.all(
422
637
  entries.map((entry) => {
423
- const fullPath = path6.join(dir, entry.name);
638
+ const fullPath = path9.join(dir, entry.name);
424
639
  return entry.isDirectory() ? collectFiles(fullPath) : Promise.resolve([fullPath]);
425
640
  })
426
641
  );
@@ -430,9 +645,9 @@ async function replacePlaceholdersInTree(targetDir, projectName) {
430
645
  const files = await collectFiles(targetDir);
431
646
  await Promise.all(
432
647
  files.map(async (filePath) => {
433
- const content = await readFile4(filePath, "utf8");
648
+ const content = await readFile6(filePath, "utf8");
434
649
  if (content.includes("{{projectName}}")) {
435
- await writeFile4(filePath, applyPlaceholders(content, projectName));
650
+ await writeFile6(filePath, applyPlaceholders(content, projectName));
436
651
  }
437
652
  })
438
653
  );
@@ -441,14 +656,13 @@ async function copyTemplate(options, pack) {
441
656
  const { projectName, targetDir, registryUrl, publishIntent } = options;
442
657
  await assertTargetDirIsUsable(targetDir);
443
658
  await cp(pack.templateDir, targetDir, { recursive: true });
444
- await rename(path6.join(targetDir, "gitignore"), path6.join(targetDir, ".gitignore"));
659
+ await rename(path9.join(targetDir, "gitignore"), path9.join(targetDir, ".gitignore"));
445
660
  await replacePlaceholdersInTree(targetDir, projectName);
446
661
  if (publishIntent === false) {
447
662
  await pack.registry.applyPrivateIntent(targetDir);
448
663
  }
449
664
  if (registryUrl && registryUrl !== pack.registry.defaultUrl) {
450
- await writeFile4(path6.join(targetDir, ".npmrc"), `registry=${registryUrl}
451
- `);
665
+ await pack.registry.applyRegistryUrl(targetDir, registryUrl);
452
666
  }
453
667
  }
454
668
  async function defaultRunCommand(command, args, cwd) {
@@ -481,7 +695,7 @@ async function scaffoldProject(options, pack, deps = defaultScaffoldDeps) {
481
695
  // src/logger.ts
482
696
  import { randomBytes } from "crypto";
483
697
  import { mkdirSync, readdirSync, statSync, unlinkSync, writeFileSync } from "fs";
484
- import path7 from "path";
698
+ import path10 from "path";
485
699
  import envPaths from "env-paths";
486
700
  import pino from "pino";
487
701
  var paths = envPaths("clispark", { suffix: "" });
@@ -517,7 +731,7 @@ var SWEEP_MARKER_FILE = ".last-sweep";
517
731
  var SWEEP_THROTTLE_MS = 24 * 60 * 60 * 1e3;
518
732
  function sweepOldLogs(logDir) {
519
733
  safely(() => {
520
- const markerPath = path7.join(logDir, SWEEP_MARKER_FILE);
734
+ const markerPath = path10.join(logDir, SWEEP_MARKER_FILE);
521
735
  let shouldSweep = true;
522
736
  try {
523
737
  shouldSweep = Date.now() - statSync(markerPath).mtimeMs >= SWEEP_THROTTLE_MS;
@@ -527,7 +741,7 @@ function sweepOldLogs(logDir) {
527
741
  const cutoffMs = Date.now() - getRetentionDays() * 24 * 60 * 60 * 1e3;
528
742
  for (const file of readdirSync(logDir)) {
529
743
  if (file === SWEEP_MARKER_FILE) continue;
530
- const filePath = path7.join(logDir, file);
744
+ const filePath = path10.join(logDir, file);
531
745
  if (statSync(filePath).mtimeMs < cutoffMs) {
532
746
  unlinkSync(filePath);
533
747
  }
@@ -538,7 +752,7 @@ function sweepOldLogs(logDir) {
538
752
  function createLogger(commandName, logDir = paths.log) {
539
753
  mkdirSync(logDir, { recursive: true });
540
754
  sweepOldLogs(logDir);
541
- const logFilePath = path7.join(logDir, buildLogFileName(commandName));
755
+ const logFilePath = path10.join(logDir, buildLogFileName(commandName));
542
756
  const fileDestination = pino.destination({ dest: logFilePath, sync: true, mode: 384 });
543
757
  const destination = process.env.DEBUG ? pino.multistream([{ stream: fileDestination }, { stream: process.stdout }]) : fileDestination;
544
758
  const logger = pino({ redact: buildRedactPaths([...SENSITIVE_LOG_KEYS, "registryUrl"]) }, destination);
@@ -576,8 +790,8 @@ function withLogging(commandName, action, logDir = paths.log, loggerFactory = cr
576
790
  }
577
791
 
578
792
  // src/update/update.ts
579
- import { mkdir as mkdir2, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
580
- import path8 from "path";
793
+ import { mkdir as mkdir3, readFile as readFile7, writeFile as writeFile7 } from "fs/promises";
794
+ import path11 from "path";
581
795
  import spawn2 from "cross-spawn";
582
796
 
583
797
  // src/update/releasenotes.ts
@@ -595,7 +809,7 @@ function compareVersions(a, b) {
595
809
  return 0;
596
810
  }
597
811
  var RELEASES_URL = "https://api.github.com/repos/martinwichner/clispark/releases";
598
- var FETCH_TIMEOUT_MS2 = 5e3;
812
+ var FETCH_TIMEOUT_MS3 = 5e3;
599
813
  async function fetchReleaseNotes(targetDir, fetchFn = fetch) {
600
814
  const manifest = await requireManifest(targetDir);
601
815
  const fromVersion = manifest.generatorVersion;
@@ -603,7 +817,7 @@ async function fetchReleaseNotes(targetDir, fetchFn = fetch) {
603
817
  if (compareVersions(fromVersion, toVersion) >= 0) {
604
818
  return { status: "up-to-date", fromVersion, toVersion, releases: [] };
605
819
  }
606
- const response = await fetchFn(RELEASES_URL, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS2) });
820
+ const response = await fetchFn(RELEASES_URL, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS3) });
607
821
  if (!response.ok) {
608
822
  throw new Error(`Failed to fetch release notes: GitHub API responded with ${response.status}`);
609
823
  }
@@ -663,7 +877,7 @@ async function updateProject(targetDir, adapter, templateDir, language, deps = d
663
877
  const currentManifestFile = await adapter.readManifestFile(targetDir);
664
878
  const projectName = adapter.readProjectName(currentManifestFile);
665
879
  const newTemplateRaw = applyPlaceholders(
666
- await readFile5(path8.join(templateDir, adapter.manifestFileName), "utf8"),
880
+ await readFile7(path11.join(templateDir, adapter.manifestFileName), "utf8"),
667
881
  projectName
668
882
  );
669
883
  const newTemplateManifestFile = adapter.parseManifestFile(newTemplateRaw);
@@ -673,13 +887,13 @@ async function updateProject(targetDir, adapter, templateDir, language, deps = d
673
887
  const perFileResults = await Promise.all(
674
888
  adapter.coreFilePaths.map(async (relativePath) => {
675
889
  const newContent = applyPlaceholders(
676
- await readFile5(path8.join(templateDir, adapter.templateSourcePath(relativePath)), "utf8"),
890
+ await readFile7(path11.join(templateDir, adapter.templateSourcePath(relativePath)), "utf8"),
677
891
  projectName
678
892
  );
679
893
  const newHash = hashContent(newContent);
680
894
  let currentHash;
681
895
  try {
682
- currentHash = hashContent(await readFile5(path8.join(targetDir, relativePath), "utf8"));
896
+ currentHash = hashContent(await readFile7(path11.join(targetDir, relativePath), "utf8"));
683
897
  } catch {
684
898
  currentHash = void 0;
685
899
  }
@@ -691,13 +905,13 @@ async function updateProject(targetDir, adapter, templateDir, language, deps = d
691
905
  files.push({ path: relativePath, outcome: result.outcome });
692
906
  newCoreFiles[relativePath] = result.value;
693
907
  if (result.outcome === "added" || result.outcome === "replaced") {
694
- fileWrites.push({ targetPath: path8.join(targetDir, relativePath), content: newContent });
908
+ fileWrites.push({ targetPath: path11.join(targetDir, relativePath), content: newContent });
695
909
  }
696
910
  }
697
911
  for (const relativePath of Object.keys(oldManifest.coreFiles)) {
698
912
  if (adapter.coreFilePaths.includes(relativePath)) continue;
699
913
  try {
700
- await readFile5(path8.join(targetDir, relativePath), "utf8");
914
+ await readFile7(path11.join(targetDir, relativePath), "utf8");
701
915
  files.push({ path: relativePath, outcome: "no-longer-core" });
702
916
  } catch {
703
917
  }
@@ -719,8 +933,8 @@ async function updateProject(targetDir, adapter, templateDir, language, deps = d
719
933
  };
720
934
  }
721
935
  for (const write of fileWrites) {
722
- await mkdir2(path8.dirname(write.targetPath), { recursive: true });
723
- await writeFile5(write.targetPath, write.content);
936
+ await mkdir3(path11.dirname(write.targetPath), { recursive: true });
937
+ await writeFile7(write.targetPath, write.content);
724
938
  }
725
939
  if (fileMerge.changed) {
726
940
  await adapter.writeManifestFile(targetDir, fileMerge.updatedFile);
@@ -785,7 +999,7 @@ function formatUpdateSummary(result) {
785
999
  // src/whoami.ts
786
1000
  import os from "os";
787
1001
  var JOKE_API_URL = "https://v2.jokeapi.dev/joke/Programming,Miscellaneous";
788
- var FETCH_TIMEOUT_MS3 = 3e3;
1002
+ var FETCH_TIMEOUT_MS4 = 3e3;
789
1003
  var SUPPORTED_JOKE_LANGUAGES = ["cs", "de", "en", "es", "fr", "pt"];
790
1004
  var LOGO = String.raw`
791
1005
  ⚡ clispark
@@ -843,7 +1057,7 @@ function getRandomFunFact(osFacts = defaultOsFacts, randomFn = Math.random) {
843
1057
  async function fetchJoke(language, fetchFn) {
844
1058
  try {
845
1059
  const url = `${JOKE_API_URL}?lang=${language}&safe-mode`;
846
- const response = await fetchFn(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS3) });
1060
+ const response = await fetchFn(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS4) });
847
1061
  if (!response.ok) return void 0;
848
1062
  const data = await response.json();
849
1063
  if (data.error) return void 0;
@@ -896,7 +1110,7 @@ function resolvePack(language) {
896
1110
  program.action(
897
1111
  (options) => withLogging("scaffold", async (logger) => {
898
1112
  const answers = await runWizard();
899
- const targetDir = path9.join(process.cwd(), answers.projectName);
1113
+ const targetDir = path12.join(process.cwd(), answers.projectName);
900
1114
  const pack = resolvePack(answers.language);
901
1115
  logger.info({ projectName: answers.projectName, targetDir, language: pack.id }, "scaffold started");
902
1116
  await scaffoldProject(