jsdoczoom 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +90 -23
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -4,6 +4,7 @@ import { dirname, resolve } from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { drilldown, drilldownFiles } from "./drilldown.js";
6
6
  import { JsdocError } from "./errors.js";
7
+ import { discoverFiles } from "./file-discovery.js";
7
8
  import { lint, lintFiles } from "./lint.js";
8
9
  import { search, searchFiles } from "./search.js";
9
10
  import { parseSelector } from "./selector.js";
@@ -113,6 +114,7 @@ function parseArgs(args) {
113
114
  cacheDirectory: undefined,
114
115
  explainRule: undefined,
115
116
  selectorArg: undefined,
117
+ extraArgs: [],
116
118
  searchQuery: undefined,
117
119
  };
118
120
  for (let i = 0; i < args.length; i++) {
@@ -189,6 +191,8 @@ function parseArgs(args) {
189
191
  // Positional selector arg
190
192
  if (parsed.selectorArg === undefined) {
191
193
  parsed.selectorArg = arg;
194
+ } else {
195
+ parsed.extraArgs.push(arg);
192
196
  }
193
197
  }
194
198
  return parsed;
@@ -212,10 +216,10 @@ function extractDepthFromArg(selectorArg) {
212
216
  return parsed.depth;
213
217
  }
214
218
  /**
215
- * Process stdin mode: file paths piped in.
219
+ * Process an explicit list of resolved file paths.
216
220
  */
217
- async function processStdin(
218
- stdin,
221
+ async function processFileList(
222
+ filePaths,
219
223
  selectorArg,
220
224
  checkMode,
221
225
  lintMode,
@@ -226,12 +230,11 @@ async function processStdin(
226
230
  cacheConfig,
227
231
  searchQuery,
228
232
  ) {
229
- const stdinPaths = parseStdinPaths(stdin, cwd);
230
233
  const depth =
231
234
  selectorArg !== undefined ? extractDepthFromArg(selectorArg) : undefined;
232
235
  if (searchQuery !== undefined) {
233
236
  const result = await searchFiles(
234
- stdinPaths,
237
+ filePaths,
235
238
  searchQuery,
236
239
  cwd,
237
240
  limit,
@@ -241,14 +244,14 @@ async function processStdin(
241
244
  return;
242
245
  }
243
246
  if (lintMode) {
244
- const result = await lintFiles(stdinPaths, cwd, limit, cacheConfig);
247
+ const result = await lintFiles(filePaths, cwd, limit, cacheConfig);
245
248
  writeLintResult(result, pretty);
246
249
  } else if (checkMode) {
247
- const result = await validateFiles(stdinPaths, cwd, limit, cacheConfig);
250
+ const result = await validateFiles(filePaths, cwd, limit, cacheConfig);
248
251
  writeValidationResult(result, pretty);
249
252
  } else {
250
253
  const result = await drilldownFiles(
251
- stdinPaths,
254
+ filePaths,
252
255
  depth,
253
256
  cwd,
254
257
  limit,
@@ -257,6 +260,35 @@ async function processStdin(
257
260
  writeDrilldownResult(result, json, pretty);
258
261
  }
259
262
  }
263
+ /**
264
+ * Process stdin mode: file paths piped in.
265
+ */
266
+ async function processStdin(
267
+ stdin,
268
+ selectorArg,
269
+ checkMode,
270
+ lintMode,
271
+ json,
272
+ pretty,
273
+ limit,
274
+ cwd,
275
+ cacheConfig,
276
+ searchQuery,
277
+ ) {
278
+ const stdinPaths = parseStdinPaths(stdin, cwd);
279
+ await processFileList(
280
+ stdinPaths,
281
+ selectorArg,
282
+ checkMode,
283
+ lintMode,
284
+ json,
285
+ pretty,
286
+ limit,
287
+ cwd,
288
+ cacheConfig,
289
+ searchQuery,
290
+ );
291
+ }
260
292
  /**
261
293
  * Process selector mode: glob or path argument.
262
294
  */
@@ -305,19 +337,27 @@ async function processSelector(
305
337
  }
306
338
  }
307
339
  /**
308
- * Write an error to stderr as JSON and set exit code.
340
+ * Write an error to stderr as JSON or plain text depending on the json flag.
309
341
  */
310
- function writeError(error) {
342
+ function writeError(error, json) {
343
+ process.exitCode = 1;
344
+ if (json) {
345
+ if (error instanceof JsdocError) {
346
+ void process.stderr.write(`${JSON.stringify(error.toJSON())}\n`);
347
+ return;
348
+ }
349
+ const message = error instanceof Error ? error.message : String(error);
350
+ void process.stderr.write(
351
+ `${JSON.stringify({ error: { code: "INTERNAL_ERROR", message } })}\n`,
352
+ );
353
+ return;
354
+ }
311
355
  if (error instanceof JsdocError) {
312
- void process.stderr.write(`${JSON.stringify(error.toJSON())}\n`);
313
- process.exitCode = 1;
356
+ void process.stderr.write(`Error [${error.code}]: ${error.message}\n`);
314
357
  return;
315
358
  }
316
359
  const message = error instanceof Error ? error.message : String(error);
317
- void process.stderr.write(
318
- `${JSON.stringify({ error: { code: "INTERNAL_ERROR", message } })}\n`,
319
- );
320
- process.exitCode = 1;
360
+ void process.stderr.write(`Error: ${message}\n`);
321
361
  }
322
362
  /**
323
363
  * Handle --help flag by printing help text.
@@ -346,7 +386,7 @@ function handleSkill() {
346
386
  /**
347
387
  * Handle --explain-rule flag by printing rule explanation.
348
388
  */
349
- function handleExplainRule(ruleName) {
389
+ function handleExplainRule(ruleName, json) {
350
390
  const explanation = RULE_EXPLANATIONS[ruleName];
351
391
  if (explanation) {
352
392
  void process.stdout.write(explanation);
@@ -358,13 +398,14 @@ function handleExplainRule(ruleName) {
358
398
  "INVALID_SELECTOR",
359
399
  `Unknown rule: ${ruleName}. Available rules: ${available}`,
360
400
  ),
401
+ json,
361
402
  );
362
403
  }
363
404
  /**
364
405
  * Handle early-exit flags that print output and return without processing files.
365
406
  * Returns true if an early-exit flag was handled.
366
407
  */
367
- async function handleEarlyExitFlags(parsed) {
408
+ async function handleEarlyExitFlags(parsed, json) {
368
409
  if (parsed.help) {
369
410
  handleHelp();
370
411
  return true;
@@ -378,7 +419,7 @@ async function handleEarlyExitFlags(parsed) {
378
419
  return true;
379
420
  }
380
421
  if (parsed.explainRule !== undefined) {
381
- handleExplainRule(parsed.explainRule);
422
+ handleExplainRule(parsed.explainRule, json);
382
423
  return true;
383
424
  }
384
425
  return false;
@@ -387,10 +428,11 @@ async function handleEarlyExitFlags(parsed) {
387
428
  * Validate that mode flags are not used in incompatible combinations.
388
429
  * Returns true if validation passed (no conflicts), false if an error was written.
389
430
  */
390
- function validateModeCombinations(parsed) {
431
+ function validateModeCombinations(parsed, json) {
391
432
  if (parsed.checkMode && parsed.lintMode) {
392
433
  writeError(
393
434
  new JsdocError("INVALID_SELECTOR", "Cannot use -c and -l together"),
435
+ json,
394
436
  );
395
437
  return false;
396
438
  }
@@ -400,6 +442,7 @@ function validateModeCombinations(parsed) {
400
442
  ) {
401
443
  writeError(
402
444
  new JsdocError("INVALID_SELECTOR", "Cannot use --search with -c or -l"),
445
+ json,
403
446
  );
404
447
  return false;
405
448
  }
@@ -409,10 +452,11 @@ function validateModeCombinations(parsed) {
409
452
  * Main CLI entry point. Exported for testability.
410
453
  */
411
454
  export async function main(args, stdin) {
455
+ const json = args.includes("--json");
412
456
  try {
413
457
  const parsed = parseArgs(args);
414
- if (await handleEarlyExitFlags(parsed)) return;
415
- if (!validateModeCombinations(parsed)) return;
458
+ if (await handleEarlyExitFlags(parsed, json)) return;
459
+ if (!validateModeCombinations(parsed, json)) return;
416
460
  const cacheConfig = {
417
461
  enabled: !parsed.disableCache,
418
462
  directory: parsed.cacheDirectory ?? DEFAULT_CACHE_DIR,
@@ -431,6 +475,29 @@ export async function main(args, stdin) {
431
475
  cacheConfig,
432
476
  parsed.searchQuery,
433
477
  );
478
+ } else if (parsed.extraArgs.length > 0) {
479
+ // Multiple positional args (e.g. shell-expanded glob): expand each to
480
+ // .ts/.tsx files via discoverFiles (handles directories recursively)
481
+ const allArgPaths = [
482
+ ...(parsed.selectorArg ? [parsed.selectorArg] : []),
483
+ ...parsed.extraArgs,
484
+ ];
485
+ const fileLists = await Promise.all(
486
+ allArgPaths.map((p) => discoverFiles(p, cwd, parsed.gitignore)),
487
+ );
488
+ const filePaths = [...new Set(fileLists.flat())];
489
+ await processFileList(
490
+ filePaths,
491
+ parsed.selectorArg,
492
+ parsed.checkMode,
493
+ parsed.lintMode,
494
+ parsed.json,
495
+ parsed.pretty,
496
+ parsed.limit,
497
+ cwd,
498
+ cacheConfig,
499
+ parsed.searchQuery,
500
+ );
434
501
  } else {
435
502
  await processSelector(
436
503
  parsed.selectorArg,
@@ -446,7 +513,7 @@ export async function main(args, stdin) {
446
513
  );
447
514
  }
448
515
  } catch (error) {
449
- writeError(error);
516
+ writeError(error, json);
450
517
  }
451
518
  }
452
519
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsdoczoom",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "CLI tool for extracting JSDoc summaries at configurable depths",
5
5
  "type": "module",
6
6
  "sideEffects": false,