@amirdaraee/namewise 0.7.2 → 0.9.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.
Files changed (123) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +118 -21
  3. package/dist/cli/apply.d.ts.map +1 -1
  4. package/dist/cli/apply.js +9 -3
  5. package/dist/cli/apply.js.map +1 -1
  6. package/dist/cli/clean-empty.d.ts.map +1 -1
  7. package/dist/cli/clean-empty.js +9 -3
  8. package/dist/cli/clean-empty.js.map +1 -1
  9. package/dist/cli/commands.d.ts.map +1 -1
  10. package/dist/cli/commands.js +52 -30
  11. package/dist/cli/commands.js.map +1 -1
  12. package/dist/cli/config-cmd.d.ts.map +1 -1
  13. package/dist/cli/config-cmd.js +6 -5
  14. package/dist/cli/config-cmd.js.map +1 -1
  15. package/dist/cli/dedup.d.ts.map +1 -1
  16. package/dist/cli/dedup.js +8 -7
  17. package/dist/cli/dedup.js.map +1 -1
  18. package/dist/cli/diff.d.ts.map +1 -1
  19. package/dist/cli/diff.js +9 -8
  20. package/dist/cli/diff.js.map +1 -1
  21. package/dist/cli/find.d.ts.map +1 -1
  22. package/dist/cli/find.js +3 -2
  23. package/dist/cli/find.js.map +1 -1
  24. package/dist/cli/flatten.d.ts.map +1 -1
  25. package/dist/cli/flatten.js +9 -3
  26. package/dist/cli/flatten.js.map +1 -1
  27. package/dist/cli/info.d.ts.map +1 -1
  28. package/dist/cli/info.js +3 -2
  29. package/dist/cli/info.js.map +1 -1
  30. package/dist/cli/init.d.ts.map +1 -1
  31. package/dist/cli/init.js +8 -7
  32. package/dist/cli/init.js.map +1 -1
  33. package/dist/cli/organize.d.ts.map +1 -1
  34. package/dist/cli/organize.js +9 -3
  35. package/dist/cli/organize.js.map +1 -1
  36. package/dist/cli/rename.d.ts.map +1 -1
  37. package/dist/cli/rename.js +101 -62
  38. package/dist/cli/rename.js.map +1 -1
  39. package/dist/cli/sanitize.d.ts.map +1 -1
  40. package/dist/cli/sanitize.js +9 -3
  41. package/dist/cli/sanitize.js.map +1 -1
  42. package/dist/cli/stats.d.ts.map +1 -1
  43. package/dist/cli/stats.js +6 -5
  44. package/dist/cli/stats.js.map +1 -1
  45. package/dist/cli/tree.d.ts.map +1 -1
  46. package/dist/cli/tree.js +2 -1
  47. package/dist/cli/tree.js.map +1 -1
  48. package/dist/cli/undo.d.ts.map +1 -1
  49. package/dist/cli/undo.js +13 -12
  50. package/dist/cli/undo.js.map +1 -1
  51. package/dist/cli/watch.d.ts.map +1 -1
  52. package/dist/cli/watch.js +8 -7
  53. package/dist/cli/watch.js.map +1 -1
  54. package/dist/errors.d.ts +35 -0
  55. package/dist/errors.d.ts.map +1 -0
  56. package/dist/errors.js +75 -0
  57. package/dist/errors.js.map +1 -0
  58. package/dist/index.js +4 -2
  59. package/dist/index.js.map +1 -1
  60. package/dist/parsers/excel-parser.d.ts.map +1 -1
  61. package/dist/parsers/excel-parser.js +5 -1
  62. package/dist/parsers/excel-parser.js.map +1 -1
  63. package/dist/parsers/factory.d.ts.map +1 -1
  64. package/dist/parsers/factory.js +7 -2
  65. package/dist/parsers/factory.js.map +1 -1
  66. package/dist/parsers/image-parser.d.ts +6 -0
  67. package/dist/parsers/image-parser.d.ts.map +1 -0
  68. package/dist/parsers/image-parser.js +29 -0
  69. package/dist/parsers/image-parser.js.map +1 -0
  70. package/dist/parsers/pdf-parser.d.ts.map +1 -1
  71. package/dist/parsers/pdf-parser.js +35 -30
  72. package/dist/parsers/pdf-parser.js.map +1 -1
  73. package/dist/parsers/text-parser.d.ts.map +1 -1
  74. package/dist/parsers/text-parser.js +5 -1
  75. package/dist/parsers/text-parser.js.map +1 -1
  76. package/dist/parsers/word-parser.d.ts.map +1 -1
  77. package/dist/parsers/word-parser.js +5 -1
  78. package/dist/parsers/word-parser.js.map +1 -1
  79. package/dist/services/ai-factory.d.ts.map +1 -1
  80. package/dist/services/ai-factory.js +4 -3
  81. package/dist/services/ai-factory.js.map +1 -1
  82. package/dist/services/claude-service.d.ts +1 -1
  83. package/dist/services/claude-service.d.ts.map +1 -1
  84. package/dist/services/claude-service.js +23 -33
  85. package/dist/services/claude-service.js.map +1 -1
  86. package/dist/services/file-renamer.d.ts +1 -1
  87. package/dist/services/file-renamer.d.ts.map +1 -1
  88. package/dist/services/file-renamer.js +57 -50
  89. package/dist/services/file-renamer.js.map +1 -1
  90. package/dist/services/lmstudio-service.d.ts +1 -2
  91. package/dist/services/lmstudio-service.d.ts.map +1 -1
  92. package/dist/services/lmstudio-service.js +39 -35
  93. package/dist/services/lmstudio-service.js.map +1 -1
  94. package/dist/services/ollama-service.d.ts +1 -3
  95. package/dist/services/ollama-service.d.ts.map +1 -1
  96. package/dist/services/ollama-service.js +47 -90
  97. package/dist/services/ollama-service.js.map +1 -1
  98. package/dist/services/openai-service.d.ts +1 -1
  99. package/dist/services/openai-service.d.ts.map +1 -1
  100. package/dist/services/openai-service.js +22 -37
  101. package/dist/services/openai-service.js.map +1 -1
  102. package/dist/types/index.d.ts +2 -1
  103. package/dist/types/index.d.ts.map +1 -1
  104. package/dist/utils/config-loader.d.ts +1 -0
  105. package/dist/utils/config-loader.d.ts.map +1 -1
  106. package/dist/utils/config-loader.js.map +1 -1
  107. package/dist/utils/image-compressor.d.ts +13 -0
  108. package/dist/utils/image-compressor.d.ts.map +1 -0
  109. package/dist/utils/image-compressor.js +52 -0
  110. package/dist/utils/image-compressor.js.map +1 -0
  111. package/dist/utils/logger.d.ts +30 -0
  112. package/dist/utils/logger.d.ts.map +1 -0
  113. package/dist/utils/logger.js +99 -0
  114. package/dist/utils/logger.js.map +1 -0
  115. package/dist/utils/pdf-to-image.d.ts +0 -1
  116. package/dist/utils/pdf-to-image.d.ts.map +1 -1
  117. package/dist/utils/pdf-to-image.js +6 -51
  118. package/dist/utils/pdf-to-image.js.map +1 -1
  119. package/dist/utils/ui.d.ts +35 -0
  120. package/dist/utils/ui.d.ts.map +1 -0
  121. package/dist/utils/ui.js +125 -0
  122. package/dist/utils/ui.js.map +1 -0
  123. package/package.json +8 -1
@@ -0,0 +1,99 @@
1
+ import { promises as fs } from 'fs';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ const LOG_DIR = path.join(os.homedir(), '.namewise', 'logs');
5
+ const MAX_LOG_FILES = 20;
6
+ export class Logger {
7
+ currentLogPath;
8
+ enabled;
9
+ initialized = false;
10
+ writeQueue = Promise.resolve();
11
+ constructor(command, enabled) {
12
+ this.enabled = enabled;
13
+ // ISO string with colons replaced for safe filenames: 2026-04-12T10-30-00
14
+ const ts = new Date().toISOString().replace(/:/g, '-').slice(0, 19);
15
+ this.currentLogPath = path.join(LOG_DIR, `${ts}-${command}.log`);
16
+ }
17
+ write(entry) {
18
+ if (!this.enabled)
19
+ return;
20
+ const line = JSON.stringify(entry) + '\n';
21
+ this.writeQueue = this.writeQueue.then(async () => {
22
+ try {
23
+ if (!this.initialized) {
24
+ await fs.mkdir(LOG_DIR, { recursive: true });
25
+ await pruneOldLogs();
26
+ this.initialized = true;
27
+ }
28
+ await fs.appendFile(this.currentLogPath, line, 'utf-8');
29
+ }
30
+ catch {
31
+ // logger must never crash the host process
32
+ }
33
+ });
34
+ }
35
+ session(ctx) {
36
+ this.write({ ts: new Date().toISOString(), level: 'info', msg: 'session_start', ...ctx });
37
+ }
38
+ info(msg, ctx) {
39
+ this.write({ ts: new Date().toISOString(), level: 'info', msg, ...ctx });
40
+ }
41
+ warn(msg, ctx) {
42
+ this.write({ ts: new Date().toISOString(), level: 'warn', msg, ...ctx });
43
+ }
44
+ error(err, ctx) {
45
+ const entry = { ts: new Date().toISOString(), level: 'error', msg: 'unknown_error' };
46
+ if (err && typeof err === 'object' && 'name' in err && 'message' in err) {
47
+ const e = err;
48
+ entry.msg = e.name ?? 'Error';
49
+ entry.message = e.message;
50
+ entry.stack = e.stack;
51
+ if (e.hint !== undefined)
52
+ entry.hint = e.hint;
53
+ if (e.details !== undefined)
54
+ entry.details = e.details;
55
+ }
56
+ else {
57
+ entry.value = String(err);
58
+ }
59
+ if (ctx)
60
+ Object.assign(entry, ctx);
61
+ this.write(entry);
62
+ }
63
+ summary(ctx) {
64
+ this.write({
65
+ ts: new Date().toISOString(),
66
+ level: 'info',
67
+ msg: 'session_end',
68
+ total: ctx.total,
69
+ succeeded: ctx.succeeded,
70
+ failed: ctx.failed,
71
+ inputTokens: ctx.tokenUsage.inputTokens,
72
+ outputTokens: ctx.tokenUsage.outputTokens,
73
+ elapsedMs: ctx.elapsedMs
74
+ });
75
+ }
76
+ }
77
+ async function pruneOldLogs() {
78
+ try {
79
+ const files = await fs.readdir(LOG_DIR);
80
+ const logFiles = files
81
+ .filter(f => f.endsWith('.log'))
82
+ .sort(); // ISO-prefixed names sort lexicographically by date
83
+ if (logFiles.length >= MAX_LOG_FILES) {
84
+ const deleteCount = logFiles.length - MAX_LOG_FILES + 1;
85
+ const toDelete = logFiles.slice(0, deleteCount);
86
+ await Promise.all(toDelete.map(f => fs.unlink(path.join(LOG_DIR, f)).catch(() => { })));
87
+ }
88
+ }
89
+ catch {
90
+ // LOG_DIR doesn't exist yet on first run — fs.mkdir above will create it
91
+ }
92
+ }
93
+ // Module-level singleton. createLogger() replaces it at the start of each CLI command.
94
+ export let logger = new Logger('namewise', false);
95
+ export function createLogger(command, enabled = false) {
96
+ logger = new Logger(command, enabled);
97
+ return logger;
98
+ }
99
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,6 @@ export interface PDFToImageOptions {
4
4
  firstPageOnly?: boolean;
5
5
  }
6
6
  export declare class PDFToImageConverter {
7
- private static readonly MAX_IMAGE_SIZE_BYTES;
8
7
  static convertFirstPageToBase64(pdfBuffer: Buffer, options?: PDFToImageOptions): Promise<string>;
9
8
  static isScannedPDF(extractedText: string): boolean;
10
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pdf-to-image.d.ts","sourceRoot":"","sources":["../../src/utils/pdf-to-image.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,qBAAa,mBAAmB;IAE9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAmB;WAElD,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,MAAM,CAAC;IAyFlB,MAAM,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;CAapD"}
1
+ {"version":3,"file":"pdf-to-image.d.ts","sourceRoot":"","sources":["../../src/utils/pdf-to-image.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,qBAAa,mBAAmB;WACjB,wBAAwB,CACnC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,MAAM,CAAC;IA8BlB,MAAM,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;CAapD"}
@@ -1,6 +1,7 @@
1
1
  import { pdfToPng } from 'pdf-to-png-converter';
2
- import { createCanvas, loadImage, DOMMatrix } from 'canvas';
2
+ import { DOMMatrix } from 'canvas';
3
3
  import { createRequire } from 'module';
4
+ import { ImageCompressor } from './image-compressor.js';
4
5
  // Polyfill DOMMatrix for Node.js environments (required by pdf-to-png-converter)
5
6
  if (typeof global !== 'undefined' && !global.DOMMatrix) {
6
7
  global.DOMMatrix = DOMMatrix;
@@ -18,74 +19,28 @@ if (typeof process !== 'undefined' && !process.getBuiltinModule) {
18
19
  };
19
20
  }
20
21
  export class PDFToImageConverter {
21
- // Claude's maximum image size is 5MB
22
- static MAX_IMAGE_SIZE_BYTES = 5 * 1024 * 1024;
23
22
  static async convertFirstPageToBase64(pdfBuffer, options = {}) {
24
- const { scale = 2.0, // Higher scale for better quality (1-3 recommended)
25
- format = 'png' } = options;
23
+ const { scale = 2.0 } = options;
26
24
  try {
27
- // Convert PDF to PNG using pdf-to-png-converter
28
- // This package handles all the canvas/image compatibility issues
29
25
  const pngPages = await pdfToPng(pdfBuffer, {
30
26
  disableFontFace: false,
31
27
  useSystemFonts: false,
32
- pagesToProcess: [1], // Only convert first page
28
+ pagesToProcess: [1],
33
29
  verbosityLevel: 0,
34
30
  viewportScale: scale
35
31
  });
36
32
  if (!pngPages || pngPages.length === 0) {
37
33
  throw new Error('No pages could be converted from PDF');
38
34
  }
39
- // Get the first page
40
35
  const firstPage = pngPages[0];
41
36
  if (!firstPage || !firstPage.content) {
42
37
  throw new Error('First page conversion failed');
43
38
  }
44
- // Load the PNG image for optimization
45
- const img = await loadImage(firstPage.content);
46
- // Always use JPEG for better compression and size control
47
- // Try different quality levels to fit under the size limit
48
- const qualities = [0.85, 0.7, 0.6, 0.5, 0.4, 0.3];
49
- for (const quality of qualities) {
50
- const canvas = createCanvas(img.width, img.height);
51
- const ctx = canvas.getContext('2d');
52
- ctx.drawImage(img, 0, 0);
53
- const dataUrl = canvas.toDataURL('image/jpeg', quality);
54
- const sizeInBytes = Math.ceil((dataUrl.length - 'data:image/jpeg;base64,'.length) * 0.75);
55
- if (sizeInBytes <= this.MAX_IMAGE_SIZE_BYTES) {
56
- return dataUrl;
57
- }
58
- }
59
- // If still too large, reduce dimensions
60
- const scaleFactor = 0.7;
61
- const newWidth = Math.floor(img.width * scaleFactor);
62
- const newHeight = Math.floor(img.height * scaleFactor);
63
- const canvas = createCanvas(newWidth, newHeight);
64
- const ctx = canvas.getContext('2d');
65
- ctx.drawImage(img, 0, 0, newWidth, newHeight);
66
- // Try with reduced dimensions
67
- for (const quality of qualities) {
68
- const dataUrl = canvas.toDataURL('image/jpeg', quality);
69
- const sizeInBytes = Math.ceil((dataUrl.length - 'data:image/jpeg;base64,'.length) * 0.75);
70
- if (sizeInBytes <= this.MAX_IMAGE_SIZE_BYTES) {
71
- return dataUrl;
72
- }
73
- }
74
- // Last resort: heavily compressed small image
75
- const smallCanvas = createCanvas(Math.floor(newWidth * 0.5), Math.floor(newHeight * 0.5));
76
- const smallCtx = smallCanvas.getContext('2d');
77
- smallCtx.drawImage(img, 0, 0, smallCanvas.width, smallCanvas.height);
78
- return smallCanvas.toDataURL('image/jpeg', 0.3);
39
+ // Delegate all compression/resize logic to ImageCompressor
40
+ return await ImageCompressor.compress(firstPage.content, 'image/png');
79
41
  }
80
42
  catch (error) {
81
- // Enhanced error logging for debugging
82
43
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
83
- const errorStack = error instanceof Error ? error.stack : '';
84
- console.error('PDF to image conversion detailed error:', {
85
- message: errorMessage,
86
- stack: errorStack,
87
- errorType: error?.constructor?.name
88
- });
89
44
  throw new Error(`PDF to image conversion failed: ${errorMessage}`);
90
45
  }
91
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pdf-to-image.js","sourceRoot":"","sources":["../../src/utils/pdf-to-image.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pdf-to-image.js","sourceRoot":"","sources":["../../src/utils/pdf-to-image.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { type Ora } from 'ora';
2
+ import type { FileInfo, RenameResult } from '../types/index.js';
3
+ export declare function suppressStderr(): void;
4
+ export declare function restoreStderr(): void;
5
+ /** Plain message — no decoration. Keeps toHaveBeenCalledWith(msg) tests green. */
6
+ export declare function info(msg: string): void;
7
+ /** Dim/muted text — for secondary information. */
8
+ export declare function dim(msg: string): void;
9
+ /** ✓ green success line */
10
+ export declare function success(msg: string): void;
11
+ /** ! yellow warning line */
12
+ export declare function warn(msg: string): void;
13
+ /** ✗ red error line */
14
+ export declare function error(msg: string): void;
15
+ /** → dim indented suggestion — shown below an error or warning line */
16
+ export declare function hint(msg: string): void;
17
+ /** Print a labelled section header with a horizontal rule below it. */
18
+ export declare function section(title: string): void;
19
+ /** Print a short horizontal rule with no label. */
20
+ export declare function rule(): void;
21
+ export declare function spinner(text: string): Ora;
22
+ /** Print one file's rename result as a single-line entry. */
23
+ export declare function fileRow(result: RenameResult): void;
24
+ export declare function renameStats(opts: {
25
+ elapsed: number;
26
+ files: FileInfo[];
27
+ successCount: number;
28
+ failCount: number;
29
+ tokenUsage: {
30
+ inputTokens?: number;
31
+ outputTokens?: number;
32
+ };
33
+ dryRun: boolean;
34
+ }): void;
35
+ //# sourceMappingURL=ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/utils/ui.ts"],"names":[],"mappings":"AACA,OAAY,EAAE,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAEpC,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOhE,wBAAgB,cAAc,IAAI,IAAI,CAIrC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAIpC;AAID,kFAAkF;AAClF,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtC;AAED,kDAAkD;AAClD,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAErC;AAED,2BAA2B;AAC3B,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEzC;AAED,4BAA4B;AAC5B,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtC;AAED,uBAAuB;AACvB,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEvC;AAED,uEAAuE;AACvE,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEtC;AAID,uEAAuE;AACvE,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAI3C;AAED,mDAAmD;AACnD,wBAAgB,IAAI,IAAI,IAAI,CAE3B;AAID,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAEzC;AAaD,6DAA6D;AAC7D,wBAAgB,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAoBlD;AAUD,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5D,MAAM,EAAE,OAAO,CAAC;CACjB,GAAG,IAAI,CAkCP"}
@@ -0,0 +1,125 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import path from 'path';
4
+ // ── Stderr suppression ───────────────────────────────────────────────────────
5
+ // Used to silence library noise (pdfjs "TT: undefined function" warnings).
6
+ let _originalStderr = null;
7
+ export function suppressStderr() {
8
+ if (_originalStderr)
9
+ return;
10
+ _originalStderr = process.stderr.write.bind(process.stderr);
11
+ process.stderr.write = () => true;
12
+ }
13
+ export function restoreStderr() {
14
+ if (!_originalStderr)
15
+ return;
16
+ process.stderr.write = _originalStderr;
17
+ _originalStderr = null;
18
+ }
19
+ // ── Core output ──────────────────────────────────────────────────────────────
20
+ /** Plain message — no decoration. Keeps toHaveBeenCalledWith(msg) tests green. */
21
+ export function info(msg) {
22
+ console.log(msg);
23
+ }
24
+ /** Dim/muted text — for secondary information. */
25
+ export function dim(msg) {
26
+ console.log(chalk.dim(msg));
27
+ }
28
+ /** ✓ green success line */
29
+ export function success(msg) {
30
+ console.log(chalk.green('✓') + ' ' + msg);
31
+ }
32
+ /** ! yellow warning line */
33
+ export function warn(msg) {
34
+ console.warn(chalk.yellow('!') + ' ' + msg);
35
+ }
36
+ /** ✗ red error line */
37
+ export function error(msg) {
38
+ console.error(chalk.red('✗') + ' ' + msg);
39
+ }
40
+ /** → dim indented suggestion — shown below an error or warning line */
41
+ export function hint(msg) {
42
+ console.log(chalk.dim(' → ') + chalk.dim(msg));
43
+ }
44
+ // ── Structural ───────────────────────────────────────────────────────────────
45
+ /** Print a labelled section header with a horizontal rule below it. */
46
+ export function section(title) {
47
+ const rule = chalk.dim('─'.repeat(56));
48
+ console.log('\n' + chalk.bold(title));
49
+ console.log(rule);
50
+ }
51
+ /** Print a short horizontal rule with no label. */
52
+ export function rule() {
53
+ console.log(chalk.dim('─'.repeat(56)));
54
+ }
55
+ // ── Spinner factory ──────────────────────────────────────────────────────────
56
+ export function spinner(text) {
57
+ return ora({ text, color: 'cyan' });
58
+ }
59
+ // ── Rename result rows ───────────────────────────────────────────────────────
60
+ // ✓ <original> → <new-name> — all on one line, 80-col budget:
61
+ // prefix(3) + orig(30) + sep(5) + new(40) = 78
62
+ const MAX_ORIG = 30;
63
+ const MAX_NEW = 40;
64
+ function truncate(s, max) {
65
+ return s.length > max ? s.slice(0, max - 1) + '…' : s;
66
+ }
67
+ /** Print one file's rename result as a single-line entry. */
68
+ export function fileRow(result) {
69
+ const original = path.basename(result.originalPath);
70
+ const newName = path.basename(result.newPath);
71
+ if (!result.success) {
72
+ console.log(chalk.red('✗') + ' ' + chalk.dim(truncate(original, MAX_ORIG)));
73
+ if (result.error) {
74
+ console.log(' ' + chalk.dim('! ') + chalk.yellow(result.error));
75
+ }
76
+ return;
77
+ }
78
+ const origFmt = chalk.dim(truncate(original, MAX_ORIG));
79
+ if (newName === original) {
80
+ console.log(chalk.green('✓') + ' ' + origFmt);
81
+ return;
82
+ }
83
+ // Renamed — show original → new on one line
84
+ console.log(chalk.green('✓') + ' ' + origFmt + ' ' + chalk.dim('→') + ' ' + truncate(newName, MAX_NEW));
85
+ }
86
+ // ── Stats block ──────────────────────────────────────────────────────────────
87
+ function formatBytes(bytes) {
88
+ if (bytes >= 1024 * 1024)
89
+ return (bytes / 1024 / 1024).toFixed(1) + ' MB';
90
+ if (bytes >= 1024)
91
+ return (bytes / 1024).toFixed(1) + ' KB';
92
+ return bytes + ' B';
93
+ }
94
+ export function renameStats(opts) {
95
+ const { elapsed, files, successCount, failCount, tokenUsage, dryRun } = opts;
96
+ const elapsedStr = elapsed < 1000
97
+ ? elapsed + 'ms'
98
+ : (elapsed / 1000).toFixed(1) + 's';
99
+ const totalBytes = files.reduce((s, f) => s + f.size, 0);
100
+ const extCounts = {};
101
+ for (const f of files) {
102
+ const ext = f.extension.slice(1).toUpperCase();
103
+ extCounts[ext] = (extCounts[ext] ?? 0) + 1;
104
+ }
105
+ const extSummary = Object.entries(extCounts)
106
+ .sort(([a], [b]) => a.localeCompare(b))
107
+ .map(([ext, n]) => chalk.dim(n + ' ' + ext))
108
+ .join(' ');
109
+ rule();
110
+ // Pad to 12 chars so "Renamed" and "Would rename" align columns identically
111
+ const verb = (dryRun ? 'Would rename' : 'Renamed').padEnd(12);
112
+ const renamedStr = chalk.green(String(successCount));
113
+ const failedStr = failCount > 0 ? chalk.red(String(failCount)) : chalk.dim('0');
114
+ console.log(`${verb} ${renamedStr} ${chalk.dim('Failed')} ${failedStr}`);
115
+ console.log(`${chalk.dim('Data')} ${formatBytes(totalBytes)} · ${extSummary}`);
116
+ if (tokenUsage.inputTokens !== undefined && tokenUsage.outputTokens !== undefined) {
117
+ const inStr = tokenUsage.inputTokens.toLocaleString();
118
+ const outStr = tokenUsage.outputTokens.toLocaleString();
119
+ console.log(`${chalk.dim('Tokens')} ${inStr} in · ${outStr} out ${chalk.dim(elapsedStr)}`);
120
+ }
121
+ else {
122
+ console.log(`${chalk.dim('Time')} ${elapsedStr} ${chalk.dim('Tokens N/A (local provider)')}`);
123
+ }
124
+ }
125
+ //# sourceMappingURL=ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../../src/utils/ui.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amirdaraee/namewise",
3
- "version": "0.7.2",
3
+ "version": "0.9.0",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "bin": {
@@ -54,10 +54,13 @@
54
54
  "description": "AI-powered CLI tool that intelligently renames files based on their content using Claude or OpenAI",
55
55
  "devDependencies": {
56
56
  "@types/fs-extra": "^11.0.4",
57
+ "@types/heic-convert": "2.1.0",
57
58
  "@types/inquirer": "^9.0.9",
58
59
  "@types/node": "^24.3.1",
60
+ "@types/pdfkit": "0.17.5",
59
61
  "@vitest/coverage-v8": "^3.2.4",
60
62
  "@vitest/ui": "^3.2.4",
63
+ "pdfkit": "0.8.3",
61
64
  "tsx": "4.21.0",
62
65
  "typescript": "^5.9.2",
63
66
  "vitest": "^3.2.4"
@@ -65,13 +68,17 @@
65
68
  "dependencies": {
66
69
  "@anthropic-ai/sdk": "^0.61.0",
67
70
  "canvas": "3.2.3",
71
+ "chalk": "5.6.2",
68
72
  "chokidar": "5.0.0",
69
73
  "commander": "14.0.3",
70
74
  "exceljs": "^4.4.0",
75
+ "exifr": "7.1.3",
71
76
  "fs-extra": "11.3.4",
77
+ "heic-convert": "2.1.0",
72
78
  "inquirer": "^12.9.4",
73
79
  "mammoth": "1.12.0",
74
80
  "openai": "^5.19.1",
81
+ "ora": "9.3.0",
75
82
  "pdf-extraction": "^1.0.2",
76
83
  "pdf-to-png-converter": "3.14.0",
77
84
  "pdfjs-dist": "5.4.149"