clispark 1.9.0 → 1.10.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,172 +1,26 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
- import path6 from "path";
4
+ import path9 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
- // src/registry.ts
11
- var DEFAULT_REGISTRY_URL = "https://registry.npmjs.org";
12
- var FETCH_TIMEOUT_MS = 5e3;
13
- async function checkPackageNameAvailability(name, registryUrl = DEFAULT_REGISTRY_URL) {
14
- const url = `${registryUrl.replace(/\/$/, "")}/${encodeURIComponent(name)}`;
15
- try {
16
- const response = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });
17
- if (response.status === 404) return "available";
18
- if (response.status === 200) return "taken";
19
- return "unverified";
20
- } catch {
21
- return "unverified";
22
- }
23
- }
24
-
25
- // src/wizard.ts
26
- var defaultDeps = {
27
- checkAvailability: checkPackageNameAvailability
28
- };
29
- function exitIfCancelled(value) {
30
- if (isCancel(value)) {
31
- cancel("Operation cancelled.");
32
- process.exit(1);
33
- }
34
- }
35
- function validateProjectName(value) {
36
- if (!value || value.trim().length === 0) return "Project name is required.";
37
- if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {
38
- return "Use lowercase letters and numbers, with single hyphens between words (no leading, trailing, or repeated hyphens).";
39
- }
40
- return void 0;
41
- }
42
- async function runWizard(deps = defaultDeps) {
43
- intro("clispark \u2014 scaffold a new CLI project");
44
- const nameValue = await text({
45
- message: "Project name",
46
- validate: validateProjectName
47
- });
48
- exitIfCancelled(nameValue);
49
- let projectName = nameValue;
50
- const profileValue = await select({
51
- message: "Is this a work or private project?",
52
- options: [
53
- { value: "private", label: "Private" },
54
- { value: "work", label: "Work" }
55
- ]
56
- });
57
- exitIfCancelled(profileValue);
58
- const profile = profileValue;
59
- let registryUrl = DEFAULT_REGISTRY_URL;
60
- if (profile === "work") {
61
- const registryValue = await text({
62
- message: "Custom npm registry URL (leave empty for npmjs.org)",
63
- placeholder: DEFAULT_REGISTRY_URL,
64
- defaultValue: DEFAULT_REGISTRY_URL
65
- });
66
- exitIfCancelled(registryValue);
67
- registryUrl = registryValue || DEFAULT_REGISTRY_URL;
68
- }
69
- const publishIntentValue = await select({
70
- message: "Do you plan to publish this to npm?",
71
- options: [
72
- { value: false, label: "No" },
73
- { value: true, label: "Yes" }
74
- ],
75
- initialValue: false
76
- });
77
- exitIfCancelled(publishIntentValue);
78
- const publishIntent = publishIntentValue;
79
- let nameAvailability = "skipped";
80
- if (publishIntent) {
81
- nameAvailability = await deps.checkAvailability(projectName, registryUrl);
82
- while (nameAvailability === "taken") {
83
- log.warn(`"${projectName}" is already taken on ${registryUrl}. Please choose a different name.`);
84
- const retryValue = await text({
85
- message: "Project name",
86
- validate: validateProjectName
87
- });
88
- exitIfCancelled(retryValue);
89
- projectName = retryValue;
90
- nameAvailability = await deps.checkAvailability(projectName, registryUrl);
91
- }
92
- if (nameAvailability === "unverified") {
93
- log.warn(`Could not verify availability of "${projectName}" on ${registryUrl}. Continuing anyway.`);
94
- }
95
- }
96
- outro(`Ready to scaffold "${projectName}".`);
97
- return { projectName, profile, registryUrl, publishIntent, nameAvailability };
98
- }
99
-
100
- // src/scaffold.ts
101
- import spawn from "cross-spawn";
102
- import { fileURLToPath as fileURLToPath2 } from "url";
103
- import path3 from "path";
104
- import { cp, readdir, readFile as readFile3, rename, writeFile as writeFile3 } from "fs/promises";
10
+ // src/languages/packs/node-oclif.ts
11
+ import path4 from "path";
105
12
 
106
- // src/update/manifest.ts
107
- import { createHash } from "crypto";
13
+ // src/package-root.ts
108
14
  import { existsSync, readFileSync } from "fs";
109
- import { mkdir, readFile, writeFile } from "fs/promises";
110
15
  import path from "path";
111
16
  import { fileURLToPath } from "url";
112
-
113
- // src/errors.ts
114
- var UserError = class extends Error {
115
- constructor(message) {
116
- super(message);
117
- this.name = "UserError";
118
- }
119
- };
120
-
121
- // src/update/manifest.ts
122
- function hashContent(content) {
123
- return createHash("sha256").update(content).digest("hex");
124
- }
125
- async function hashCoreFiles(dir, adapter) {
126
- const entries = await Promise.all(
127
- adapter.coreFilePaths.map(async (relativePath) => {
128
- const content = await readFile(path.join(dir, relativePath), "utf8");
129
- return [relativePath, hashContent(content)];
130
- })
131
- );
132
- return Object.fromEntries(entries);
133
- }
134
- async function buildManifest(targetDir, generatorVersion, adapter) {
135
- const coreFiles = await hashCoreFiles(targetDir, adapter);
136
- const manifestFile = await adapter.readManifestFile(targetDir);
137
- const { coreDependencies, coreScripts, coreFields } = adapter.extractCoreFields(manifestFile);
138
- return { generatorVersion, coreFiles, coreDependencies, coreScripts, coreFields };
139
- }
140
- var MANIFEST_RELATIVE_PATH = path.join(".clispark", "manifest.json");
141
- async function writeManifest(targetDir, manifest) {
142
- const manifestPath = path.join(targetDir, MANIFEST_RELATIVE_PATH);
143
- await mkdir(path.dirname(manifestPath), { recursive: true });
144
- await writeFile(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
145
- }
146
- async function readManifest(targetDir) {
147
- try {
148
- const content = await readFile(path.join(targetDir, MANIFEST_RELATIVE_PATH), "utf8");
149
- return JSON.parse(content);
150
- } catch {
151
- return void 0;
152
- }
153
- }
154
- async function requireManifest(targetDir) {
155
- const manifest = await readManifest(targetDir);
156
- if (!manifest) {
157
- throw new UserError(
158
- "No .clispark/manifest.json found \u2014 this project predates update support, or is not a clispark project."
159
- );
160
- }
161
- return manifest;
162
- }
163
- function getGeneratorVersion() {
17
+ function findPackageRoot() {
164
18
  let dir = path.dirname(fileURLToPath(import.meta.url));
165
19
  while (true) {
166
20
  const pkgPath = path.join(dir, "package.json");
167
21
  if (existsSync(pkgPath)) {
168
22
  const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
169
- if (pkg.name === "clispark") return pkg.version;
23
+ if (pkg.name === "clispark") return dir;
170
24
  }
171
25
  const parentDir = path.dirname(dir);
172
26
  if (parentDir === dir) {
@@ -177,7 +31,7 @@ function getGeneratorVersion() {
177
31
  }
178
32
 
179
33
  // src/update/adapters/node-oclif.ts
180
- import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
34
+ import { readFile, writeFile } from "fs/promises";
181
35
  import path2 from "path";
182
36
 
183
37
  // src/update/reconcile.ts
@@ -316,11 +170,11 @@ var nodeOclifAdapter = {
316
170
  },
317
171
  manifestFileName: "package.json",
318
172
  async readManifestFile(dir) {
319
- const content = await readFile2(path2.join(dir, "package.json"), "utf8");
173
+ const content = await readFile(path2.join(dir, "package.json"), "utf8");
320
174
  return JSON.parse(content);
321
175
  },
322
176
  async writeManifestFile(dir, content) {
323
- await writeFile2(path2.join(dir, "package.json"), JSON.stringify(content, null, 2) + "\n");
177
+ await writeFile(path2.join(dir, "package.json"), JSON.stringify(content, null, 2) + "\n");
324
178
  },
325
179
  parseManifestFile(rawContent) {
326
180
  return JSON.parse(rawContent);
@@ -336,8 +190,218 @@ var nodeOclifAdapter = {
336
190
  }
337
191
  };
338
192
 
193
+ // src/languages/registry-checkers/npm.ts
194
+ import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
195
+ import path3 from "path";
196
+ var NPM_DEFAULT_REGISTRY_URL = "https://registry.npmjs.org";
197
+ var FETCH_TIMEOUT_MS = 5e3;
198
+ async function checkNameAvailability(name, registryUrl) {
199
+ const url = `${registryUrl.replace(/\/$/, "")}/${encodeURIComponent(name)}`;
200
+ try {
201
+ const response = await fetch(url, { signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });
202
+ if (response.status === 404) return "available";
203
+ if (response.status === 200) return "taken";
204
+ return "unverified";
205
+ } catch {
206
+ return "unverified";
207
+ }
208
+ }
209
+ async function applyPrivateIntent(targetDir) {
210
+ const packageJsonPath = path3.join(targetDir, "package.json");
211
+ const pkg = JSON.parse(await readFile2(packageJsonPath, "utf8"));
212
+ pkg.private = true;
213
+ await writeFile2(packageJsonPath, JSON.stringify(pkg, null, 2) + "\n");
214
+ }
215
+ var npmRegistryChecker = {
216
+ checkNameAvailability,
217
+ applyPrivateIntent
218
+ };
219
+
220
+ // src/languages/packs/node-oclif.ts
221
+ function validateProjectName(value) {
222
+ if (!value || value.trim().length === 0) return "Project name is required.";
223
+ if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) {
224
+ return "Use lowercase letters and numbers, with single hyphens between words (no leading, trailing, or repeated hyphens).";
225
+ }
226
+ return void 0;
227
+ }
228
+ var nodeOclifPack = {
229
+ id: "node",
230
+ displayName: "Node.js / TypeScript (oclif)",
231
+ templateDir: path4.join(findPackageRoot(), "templates", "node"),
232
+ scaffoldCommands: [
233
+ { command: "npm", args: ["install"] },
234
+ { command: "npm", args: ["run", "build"] }
235
+ ],
236
+ validateProjectName,
237
+ updateAdapter: nodeOclifAdapter,
238
+ registry: {
239
+ defaultUrl: NPM_DEFAULT_REGISTRY_URL,
240
+ promptLabel: "Custom npm registry URL (leave empty for npmjs.org)",
241
+ checkNameAvailability: npmRegistryChecker.checkNameAvailability,
242
+ applyPrivateIntent: npmRegistryChecker.applyPrivateIntent
243
+ }
244
+ };
245
+
246
+ // src/languages/index.ts
247
+ var LANGUAGE_PACKS = {
248
+ [nodeOclifPack.id]: nodeOclifPack
249
+ };
250
+
251
+ // src/wizard.ts
252
+ var defaultDeps = {
253
+ languagePacks: LANGUAGE_PACKS
254
+ };
255
+ function exitIfCancelled(value) {
256
+ if (isCancel(value)) {
257
+ cancel("Operation cancelled.");
258
+ process.exit(1);
259
+ }
260
+ }
261
+ async function runWizard(deps = defaultDeps) {
262
+ intro("clispark \u2014 scaffold a new CLI project");
263
+ const packs = Object.values(deps.languagePacks);
264
+ const languageValue = await select({
265
+ message: "Which language?",
266
+ options: packs.map((pack2) => ({ value: pack2.id, label: pack2.displayName }))
267
+ });
268
+ exitIfCancelled(languageValue);
269
+ const pack = deps.languagePacks[languageValue];
270
+ const nameValue = await text({
271
+ message: "Project name",
272
+ validate: pack.validateProjectName
273
+ });
274
+ exitIfCancelled(nameValue);
275
+ let projectName = nameValue;
276
+ const profileValue = await select({
277
+ message: "Is this a work or private project?",
278
+ options: [
279
+ { value: "private", label: "Private" },
280
+ { value: "work", label: "Work" }
281
+ ]
282
+ });
283
+ exitIfCancelled(profileValue);
284
+ const profile = profileValue;
285
+ let registryUrl = pack.registry.defaultUrl;
286
+ if (profile === "work") {
287
+ const registryValue = await text({
288
+ message: pack.registry.promptLabel,
289
+ placeholder: pack.registry.defaultUrl,
290
+ defaultValue: pack.registry.defaultUrl
291
+ });
292
+ exitIfCancelled(registryValue);
293
+ registryUrl = registryValue || pack.registry.defaultUrl;
294
+ }
295
+ const publishIntentValue = await select({
296
+ message: "Do you plan to publish this?",
297
+ options: [
298
+ { value: false, label: "No" },
299
+ { value: true, label: "Yes" }
300
+ ],
301
+ initialValue: false
302
+ });
303
+ exitIfCancelled(publishIntentValue);
304
+ const publishIntent = publishIntentValue;
305
+ let nameAvailability = "skipped";
306
+ if (publishIntent) {
307
+ nameAvailability = await pack.registry.checkNameAvailability(projectName, registryUrl);
308
+ while (nameAvailability === "taken") {
309
+ log.warn(`"${projectName}" is already taken on ${registryUrl}. Please choose a different name.`);
310
+ const retryValue = await text({
311
+ message: "Project name",
312
+ validate: pack.validateProjectName
313
+ });
314
+ exitIfCancelled(retryValue);
315
+ projectName = retryValue;
316
+ nameAvailability = await pack.registry.checkNameAvailability(projectName, registryUrl);
317
+ }
318
+ if (nameAvailability === "unverified") {
319
+ log.warn(`Could not verify availability of "${projectName}" on ${registryUrl}. Continuing anyway.`);
320
+ }
321
+ }
322
+ outro(`Ready to scaffold "${projectName}".`);
323
+ return { language: pack.id, projectName, profile, registryUrl, publishIntent, nameAvailability };
324
+ }
325
+
326
+ // src/scaffold.ts
327
+ import { cp, readdir, readFile as readFile4, rename, writeFile as writeFile4 } from "fs/promises";
328
+ import path6 from "path";
329
+ import spawn from "cross-spawn";
330
+
331
+ // src/update/manifest.ts
332
+ import { createHash } from "crypto";
333
+ 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";
336
+ import { fileURLToPath as fileURLToPath2 } from "url";
337
+
338
+ // src/errors.ts
339
+ var UserError = class extends Error {
340
+ constructor(message) {
341
+ super(message);
342
+ this.name = "UserError";
343
+ }
344
+ };
345
+
346
+ // src/update/manifest.ts
347
+ function hashContent(content) {
348
+ return createHash("sha256").update(content).digest("hex");
349
+ }
350
+ async function hashCoreFiles(dir, adapter) {
351
+ const entries = await Promise.all(
352
+ adapter.coreFilePaths.map(async (relativePath) => {
353
+ const content = await readFile3(path5.join(dir, relativePath), "utf8");
354
+ return [relativePath, hashContent(content)];
355
+ })
356
+ );
357
+ return Object.fromEntries(entries);
358
+ }
359
+ async function buildManifest(targetDir, generatorVersion, language, adapter) {
360
+ const coreFiles = await hashCoreFiles(targetDir, adapter);
361
+ const manifestFile = await adapter.readManifestFile(targetDir);
362
+ const { coreDependencies, coreScripts, coreFields } = adapter.extractCoreFields(manifestFile);
363
+ return { generatorVersion, language, coreFiles, coreDependencies, coreScripts, coreFields };
364
+ }
365
+ var MANIFEST_RELATIVE_PATH = path5.join(".clispark", "manifest.json");
366
+ 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");
370
+ }
371
+ async function readManifest(targetDir) {
372
+ try {
373
+ const content = await readFile3(path5.join(targetDir, MANIFEST_RELATIVE_PATH), "utf8");
374
+ return JSON.parse(content);
375
+ } catch {
376
+ return void 0;
377
+ }
378
+ }
379
+ async function requireManifest(targetDir) {
380
+ const manifest = await readManifest(targetDir);
381
+ if (!manifest) {
382
+ throw new UserError(
383
+ "No .clispark/manifest.json found \u2014 this project predates update support, or is not a clispark project."
384
+ );
385
+ }
386
+ return manifest;
387
+ }
388
+ function getGeneratorVersion() {
389
+ let dir = path5.dirname(fileURLToPath2(import.meta.url));
390
+ while (true) {
391
+ const pkgPath = path5.join(dir, "package.json");
392
+ if (existsSync2(pkgPath)) {
393
+ const pkg = JSON.parse(readFileSync2(pkgPath, "utf8"));
394
+ if (pkg.name === "clispark") return pkg.version;
395
+ }
396
+ const parentDir = path5.dirname(dir);
397
+ if (parentDir === dir) {
398
+ throw new Error("Could not locate clispark's own package.json.");
399
+ }
400
+ dir = parentDir;
401
+ }
402
+ }
403
+
339
404
  // src/scaffold.ts
340
- var TEMPLATE_DIR = path3.join(path3.dirname(fileURLToPath2(import.meta.url)), "..", "templates", "base");
341
405
  async function assertTargetDirIsUsable(targetDir) {
342
406
  let entries;
343
407
  try {
@@ -356,7 +420,7 @@ async function collectFiles(dir) {
356
420
  const entries = await readdir(dir, { withFileTypes: true });
357
421
  const files = await Promise.all(
358
422
  entries.map((entry) => {
359
- const fullPath = path3.join(dir, entry.name);
423
+ const fullPath = path6.join(dir, entry.name);
360
424
  return entry.isDirectory() ? collectFiles(fullPath) : Promise.resolve([fullPath]);
361
425
  })
362
426
  );
@@ -366,30 +430,24 @@ async function replacePlaceholdersInTree(targetDir, projectName) {
366
430
  const files = await collectFiles(targetDir);
367
431
  await Promise.all(
368
432
  files.map(async (filePath) => {
369
- const content = await readFile3(filePath, "utf8");
433
+ const content = await readFile4(filePath, "utf8");
370
434
  if (content.includes("{{projectName}}")) {
371
- await writeFile3(filePath, applyPlaceholders(content, projectName));
435
+ await writeFile4(filePath, applyPlaceholders(content, projectName));
372
436
  }
373
437
  })
374
438
  );
375
439
  }
376
- async function markPackageJsonPrivate(targetDir) {
377
- const packageJsonPath = path3.join(targetDir, "package.json");
378
- const pkg = JSON.parse(await readFile3(packageJsonPath, "utf8"));
379
- pkg.private = true;
380
- await writeFile3(packageJsonPath, JSON.stringify(pkg, null, 2) + "\n");
381
- }
382
- async function copyTemplate(options) {
440
+ async function copyTemplate(options, pack) {
383
441
  const { projectName, targetDir, registryUrl, publishIntent } = options;
384
442
  await assertTargetDirIsUsable(targetDir);
385
- await cp(TEMPLATE_DIR, targetDir, { recursive: true });
386
- await rename(path3.join(targetDir, "gitignore"), path3.join(targetDir, ".gitignore"));
443
+ await cp(pack.templateDir, targetDir, { recursive: true });
444
+ await rename(path6.join(targetDir, "gitignore"), path6.join(targetDir, ".gitignore"));
387
445
  await replacePlaceholdersInTree(targetDir, projectName);
388
446
  if (publishIntent === false) {
389
- await markPackageJsonPrivate(targetDir);
447
+ await pack.registry.applyPrivateIntent(targetDir);
390
448
  }
391
- if (registryUrl && registryUrl !== DEFAULT_REGISTRY_URL) {
392
- await writeFile3(path3.join(targetDir, ".npmrc"), `registry=${registryUrl}
449
+ if (registryUrl && registryUrl !== pack.registry.defaultUrl) {
450
+ await writeFile4(path6.join(targetDir, ".npmrc"), `registry=${registryUrl}
393
451
  `);
394
452
  }
395
453
  }
@@ -407,22 +465,23 @@ async function defaultRunCommand(command, args, cwd) {
407
465
  });
408
466
  }
409
467
  var defaultScaffoldDeps = { runCommand: defaultRunCommand };
410
- async function scaffoldProject(options, deps = defaultScaffoldDeps) {
411
- await copyTemplate(options);
468
+ async function scaffoldProject(options, pack, deps = defaultScaffoldDeps) {
469
+ await copyTemplate(options, pack);
412
470
  const { targetDir } = options;
413
- const manifest = await buildManifest(targetDir, getGeneratorVersion(), nodeOclifAdapter);
471
+ const manifest = await buildManifest(targetDir, getGeneratorVersion(), pack.id, pack.updateAdapter);
414
472
  await writeManifest(targetDir, manifest);
415
473
  await deps.runCommand("git", ["init"], targetDir);
416
474
  await deps.runCommand("git", ["add", "-A"], targetDir);
417
475
  await deps.runCommand("git", ["commit", "-m", "chore: initial scaffold from clispark"], targetDir);
418
- await deps.runCommand("npm", ["install"], targetDir);
419
- await deps.runCommand("npm", ["run", "build"], targetDir);
476
+ for (const scaffoldCommand of pack.scaffoldCommands) {
477
+ await deps.runCommand(scaffoldCommand.command, scaffoldCommand.args, targetDir);
478
+ }
420
479
  }
421
480
 
422
481
  // src/logger.ts
423
482
  import { randomBytes } from "crypto";
424
483
  import { mkdirSync, readdirSync, statSync, unlinkSync, writeFileSync } from "fs";
425
- import path4 from "path";
484
+ import path7 from "path";
426
485
  import envPaths from "env-paths";
427
486
  import pino from "pino";
428
487
  var paths = envPaths("clispark", { suffix: "" });
@@ -458,7 +517,7 @@ var SWEEP_MARKER_FILE = ".last-sweep";
458
517
  var SWEEP_THROTTLE_MS = 24 * 60 * 60 * 1e3;
459
518
  function sweepOldLogs(logDir) {
460
519
  safely(() => {
461
- const markerPath = path4.join(logDir, SWEEP_MARKER_FILE);
520
+ const markerPath = path7.join(logDir, SWEEP_MARKER_FILE);
462
521
  let shouldSweep = true;
463
522
  try {
464
523
  shouldSweep = Date.now() - statSync(markerPath).mtimeMs >= SWEEP_THROTTLE_MS;
@@ -468,7 +527,7 @@ function sweepOldLogs(logDir) {
468
527
  const cutoffMs = Date.now() - getRetentionDays() * 24 * 60 * 60 * 1e3;
469
528
  for (const file of readdirSync(logDir)) {
470
529
  if (file === SWEEP_MARKER_FILE) continue;
471
- const filePath = path4.join(logDir, file);
530
+ const filePath = path7.join(logDir, file);
472
531
  if (statSync(filePath).mtimeMs < cutoffMs) {
473
532
  unlinkSync(filePath);
474
533
  }
@@ -479,7 +538,7 @@ function sweepOldLogs(logDir) {
479
538
  function createLogger(commandName, logDir = paths.log) {
480
539
  mkdirSync(logDir, { recursive: true });
481
540
  sweepOldLogs(logDir);
482
- const logFilePath = path4.join(logDir, buildLogFileName(commandName));
541
+ const logFilePath = path7.join(logDir, buildLogFileName(commandName));
483
542
  const fileDestination = pino.destination({ dest: logFilePath, sync: true, mode: 384 });
484
543
  const destination = process.env.DEBUG ? pino.multistream([{ stream: fileDestination }, { stream: process.stdout }]) : fileDestination;
485
544
  const logger = pino({ redact: buildRedactPaths([...SENSITIVE_LOG_KEYS, "registryUrl"]) }, destination);
@@ -517,8 +576,8 @@ function withLogging(commandName, action, logDir = paths.log, loggerFactory = cr
517
576
  }
518
577
 
519
578
  // src/update/update.ts
520
- import { mkdir as mkdir2, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
521
- import path5 from "path";
579
+ import { mkdir as mkdir2, readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
580
+ import path8 from "path";
522
581
  import spawn2 from "cross-spawn";
523
582
 
524
583
  // src/update/releasenotes.ts
@@ -590,7 +649,7 @@ async function defaultCaptureCommand(command, args, cwd) {
590
649
  });
591
650
  }
592
651
  var defaultUpdateDeps = { runCommand: defaultRunCommand2, captureCommand: defaultCaptureCommand };
593
- async function updateProject(targetDir, adapter, deps = defaultUpdateDeps) {
652
+ async function updateProject(targetDir, adapter, templateDir, language, deps = defaultUpdateDeps) {
594
653
  const status = (await deps.captureCommand("git", ["status", "--porcelain"], targetDir)).trim();
595
654
  if (status.length > 0) {
596
655
  throw new UserError("Working tree is not clean. Commit or stash your changes before running update.");
@@ -604,7 +663,7 @@ async function updateProject(targetDir, adapter, deps = defaultUpdateDeps) {
604
663
  const currentManifestFile = await adapter.readManifestFile(targetDir);
605
664
  const projectName = adapter.readProjectName(currentManifestFile);
606
665
  const newTemplateRaw = applyPlaceholders(
607
- await readFile4(path5.join(TEMPLATE_DIR, adapter.manifestFileName), "utf8"),
666
+ await readFile5(path8.join(templateDir, adapter.manifestFileName), "utf8"),
608
667
  projectName
609
668
  );
610
669
  const newTemplateManifestFile = adapter.parseManifestFile(newTemplateRaw);
@@ -614,13 +673,13 @@ async function updateProject(targetDir, adapter, deps = defaultUpdateDeps) {
614
673
  const perFileResults = await Promise.all(
615
674
  adapter.coreFilePaths.map(async (relativePath) => {
616
675
  const newContent = applyPlaceholders(
617
- await readFile4(path5.join(TEMPLATE_DIR, adapter.templateSourcePath(relativePath)), "utf8"),
676
+ await readFile5(path8.join(templateDir, adapter.templateSourcePath(relativePath)), "utf8"),
618
677
  projectName
619
678
  );
620
679
  const newHash = hashContent(newContent);
621
680
  let currentHash;
622
681
  try {
623
- currentHash = hashContent(await readFile4(path5.join(targetDir, relativePath), "utf8"));
682
+ currentHash = hashContent(await readFile5(path8.join(targetDir, relativePath), "utf8"));
624
683
  } catch {
625
684
  currentHash = void 0;
626
685
  }
@@ -632,13 +691,13 @@ async function updateProject(targetDir, adapter, deps = defaultUpdateDeps) {
632
691
  files.push({ path: relativePath, outcome: result.outcome });
633
692
  newCoreFiles[relativePath] = result.value;
634
693
  if (result.outcome === "added" || result.outcome === "replaced") {
635
- fileWrites.push({ targetPath: path5.join(targetDir, relativePath), content: newContent });
694
+ fileWrites.push({ targetPath: path8.join(targetDir, relativePath), content: newContent });
636
695
  }
637
696
  }
638
697
  for (const relativePath of Object.keys(oldManifest.coreFiles)) {
639
698
  if (adapter.coreFilePaths.includes(relativePath)) continue;
640
699
  try {
641
- await readFile4(path5.join(targetDir, relativePath), "utf8");
700
+ await readFile5(path8.join(targetDir, relativePath), "utf8");
642
701
  files.push({ path: relativePath, outcome: "no-longer-core" });
643
702
  } catch {
644
703
  }
@@ -660,14 +719,15 @@ async function updateProject(targetDir, adapter, deps = defaultUpdateDeps) {
660
719
  };
661
720
  }
662
721
  for (const write of fileWrites) {
663
- await mkdir2(path5.dirname(write.targetPath), { recursive: true });
664
- await writeFile4(write.targetPath, write.content);
722
+ await mkdir2(path8.dirname(write.targetPath), { recursive: true });
723
+ await writeFile5(write.targetPath, write.content);
665
724
  }
666
725
  if (fileMerge.changed) {
667
726
  await adapter.writeManifestFile(targetDir, fileMerge.updatedFile);
668
727
  }
669
728
  const newManifest = {
670
729
  generatorVersion: toVersion,
730
+ language,
671
731
  coreFiles: newCoreFiles,
672
732
  coreDependencies: fileMerge.coreDependencies,
673
733
  coreScripts: fileMerge.coreScripts,
@@ -725,17 +785,28 @@ function formatUpdateSummary(result) {
725
785
  // src/cli.ts
726
786
  var program = new Command();
727
787
  program.name("clispark").description("Interactive scaffolding tool for new CLI projects").version(getGeneratorVersion());
788
+ function resolvePack(language) {
789
+ const pack = LANGUAGE_PACKS[language];
790
+ if (!pack) {
791
+ throw new UserError(`Unknown language "${language}" \u2014 is your clispark installation out of date?`);
792
+ }
793
+ return pack;
794
+ }
728
795
  program.action(
729
796
  withLogging("scaffold", async (logger) => {
730
797
  const answers = await runWizard();
731
- const targetDir = path6.join(process.cwd(), answers.projectName);
732
- logger.info({ projectName: answers.projectName, targetDir }, "scaffold started");
733
- await scaffoldProject({
734
- projectName: answers.projectName,
735
- targetDir,
736
- registryUrl: answers.registryUrl,
737
- publishIntent: answers.publishIntent
738
- });
798
+ const targetDir = path9.join(process.cwd(), answers.projectName);
799
+ const pack = resolvePack(answers.language);
800
+ logger.info({ projectName: answers.projectName, targetDir, language: pack.id }, "scaffold started");
801
+ await scaffoldProject(
802
+ {
803
+ projectName: answers.projectName,
804
+ targetDir,
805
+ registryUrl: answers.registryUrl,
806
+ publishIntent: answers.publishIntent
807
+ },
808
+ pack
809
+ );
739
810
  logger.info({ projectName: answers.projectName }, "scaffold completed");
740
811
  console.log(`
741
812
  Done! Your new CLI project is ready at ${targetDir}`);
@@ -744,8 +815,11 @@ Done! Your new CLI project is ready at ${targetDir}`);
744
815
  program.command("update").description("Update generator-managed core files and dependencies to the latest clispark version").action(
745
816
  withLogging("update", async (logger) => {
746
817
  const targetDir = process.cwd();
747
- logger.info({ targetDir }, "update started");
748
- const result = await updateProject(targetDir, nodeOclifAdapter);
818
+ const manifest = await requireManifest(targetDir);
819
+ const language = manifest.language ?? "node";
820
+ const pack = resolvePack(language);
821
+ logger.info({ targetDir, language }, "update started");
822
+ const result = await updateProject(targetDir, pack.updateAdapter, pack.templateDir, language);
749
823
  logger.info({ status: result.status }, "update completed");
750
824
  console.log(formatUpdateSummary(result));
751
825
  })
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/wizard.ts","../src/registry.ts","../src/scaffold.ts","../src/update/manifest.ts","../src/errors.ts","../src/update/adapters/node-oclif.ts","../src/update/reconcile.ts","../src/logger.ts","../src/update/update.ts","../src/update/releasenotes.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 { nodeOclifAdapter } from './update/adapters/node-oclif';\nimport { fetchReleaseNotes, formatReleaseNotes } from './update/releasenotes';\nimport { getGeneratorVersion } from './update/manifest';\n\nconst program = new Command();\n\nprogram\n .name('clispark')\n .description('Interactive scaffolding tool for new CLI projects')\n .version(getGeneratorVersion());\n\nprogram.action(\n withLogging('scaffold', async (logger) => {\n const answers = await runWizard();\n const targetDir = path.join(process.cwd(), answers.projectName);\n\n logger.info({ projectName: answers.projectName, targetDir }, 'scaffold started');\n await scaffoldProject({\n projectName: answers.projectName,\n targetDir,\n registryUrl: answers.registryUrl,\n publishIntent: answers.publishIntent,\n });\n logger.info({ projectName: answers.projectName }, 'scaffold completed');\n\n console.log(`\\nDone! Your new CLI project is ready at ${targetDir}`);\n }),\n);\n\nprogram\n .command('update')\n .description('Update generator-managed core files and dependencies to the latest clispark version')\n .action(\n withLogging('update', async (logger) => {\n const targetDir = process.cwd();\n logger.info({ targetDir }, 'update started');\n const result = await updateProject(targetDir, nodeOclifAdapter);\n logger.info({ status: result.status }, 'update completed');\n console.log(formatUpdateSummary(result));\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.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 { checkPackageNameAvailability, DEFAULT_REGISTRY_URL, type NameCheckResult } from './registry';\nimport type { Profile, WizardAnswers } from './types';\n\nexport interface WizardDeps {\n checkAvailability: typeof checkPackageNameAvailability;\n}\n\nconst defaultDeps: WizardDeps = {\n checkAvailability: checkPackageNameAvailability,\n};\n\nfunction exitIfCancelled(value: unknown): void {\n if (isCancel(value)) {\n cancel('Operation cancelled.');\n process.exit(1);\n }\n}\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 async function runWizard(deps: WizardDeps = defaultDeps): Promise<WizardAnswers> {\n intro('clispark — scaffold a new CLI project');\n\n const nameValue = await text({\n message: 'Project name',\n validate: 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 = DEFAULT_REGISTRY_URL;\n if (profile === 'work') {\n const registryValue = await text({\n message: 'Custom npm registry URL (leave empty for npmjs.org)',\n placeholder: DEFAULT_REGISTRY_URL,\n defaultValue: DEFAULT_REGISTRY_URL,\n });\n exitIfCancelled(registryValue);\n registryUrl = (registryValue as string) || DEFAULT_REGISTRY_URL;\n }\n\n const publishIntentValue = await select({\n message: 'Do you plan to publish this to npm?',\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 deps.checkAvailability(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: validateProjectName,\n });\n exitIfCancelled(retryValue);\n projectName = retryValue as string;\n\n nameAvailability = await deps.checkAvailability(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 { projectName, profile, registryUrl, publishIntent, nameAvailability };\n}\n","export const DEFAULT_REGISTRY_URL = 'https://registry.npmjs.org';\n\nexport type NameCheckResult = 'available' | 'taken' | 'unverified' | 'skipped';\n\nconst FETCH_TIMEOUT_MS = 5000;\n\nexport async function checkPackageNameAvailability(\n name: string,\n registryUrl: string = DEFAULT_REGISTRY_URL,\n): 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","import spawn from 'cross-spawn';\nimport { fileURLToPath } from 'node:url';\nimport path from 'node:path';\nimport { cp, readdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { DEFAULT_REGISTRY_URL } from './registry';\nimport { buildManifest, getGeneratorVersion, writeManifest } from './update/manifest';\nimport { nodeOclifAdapter } from './update/adapters/node-oclif';\nimport { UserError } from './errors';\n\nexport interface ScaffoldOptions {\n projectName: string;\n targetDir: string;\n registryUrl?: string;\n publishIntent?: boolean;\n}\n\nexport const TEMPLATE_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'templates', 'base');\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\nasync function markPackageJsonPrivate(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\nexport async function copyTemplate(options: ScaffoldOptions): Promise<void> {\n const { projectName, targetDir, registryUrl, publishIntent } = options;\n\n await assertTargetDirIsUsable(targetDir);\n await cp(TEMPLATE_DIR, 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 markPackageJsonPrivate(targetDir);\n }\n\n if (registryUrl && registryUrl !== DEFAULT_REGISTRY_URL) {\n await writeFile(path.join(targetDir, '.npmrc'), `registry=${registryUrl}\\n`);\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 deps: ScaffoldDeps = defaultScaffoldDeps,\n): Promise<void> {\n await copyTemplate(options);\n\n const { targetDir } = options;\n const manifest = await buildManifest(targetDir, getGeneratorVersion(), nodeOclifAdapter);\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 await deps.runCommand('npm', ['install'], targetDir);\n await deps.runCommand('npm', ['run', 'build'], targetDir);\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 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 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, 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","// 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","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, TEMPLATE_DIR } 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 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(TEMPLATE_DIR, 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(TEMPLATE_DIR, 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 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"],"mappings":"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","names":["path","fileURLToPath","path","readFile","writeFile","readFile","writeFile","path","readFile","path","writeFile","path","fileURLToPath","readFile","writeFile","path","mkdir","readFile","writeFile","path","spawn","FETCH_TIMEOUT_MS","defaultRunCommand","spawn","readFile","path","mkdir","writeFile","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/index.ts","../src/scaffold.ts","../src/update/manifest.ts","../src/errors.ts","../src/logger.ts","../src/update/update.ts","../src/update/releasenotes.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';\n\nconst program = new Command();\n\nprogram\n .name('clispark')\n .description('Interactive scaffolding tool for new CLI projects')\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(\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 }),\n);\n\nprogram\n .command('update')\n .description('Update generator-managed core files and dependencies to the latest clispark version')\n .action(\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 }),\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.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 },\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\nexport const npmRegistryChecker: RegistryChecker = {\n checkNameAvailability,\n applyPrivateIntent,\n};\n","// src/languages/index.ts\nimport type { LanguagePack } from './pack';\nimport { nodeOclifPack } from './packs/node-oclif';\n\nexport const LANGUAGE_PACKS: Record<string, LanguagePack> = {\n [nodeOclifPack.id]: nodeOclifPack,\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 writeFile(path.join(targetDir, '.npmrc'), `registry=${registryUrl}\\n`);\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"],"mappings":"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","names":["path","path","path","path","readFile","writeFile","path","path","pack","readFile","writeFile","path","existsSync","readFileSync","readFile","writeFile","path","fileURLToPath","readFile","path","writeFile","fileURLToPath","existsSync","readFileSync","path","readFile","writeFile","path","mkdir","readFile","writeFile","path","spawn","FETCH_TIMEOUT_MS","defaultRunCommand","spawn","readFile","path","mkdir","writeFile","path"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clispark",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "Interactive scaffolding tool for new CLI projects",
5
5
  "keywords": [
6
6
  "cli",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes