@fullgreengn/converter 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,6 +4,7 @@ A CLI to convert:
4
4
 
5
5
  - `.heic` -> `.jpg` or `.png` (via `sharp`)
6
6
  - `.docx` -> `.pdf` (via `mammoth` + `puppeteer`)
7
+ - audio files -> `.mp3` or `.wav` (via bundled `ffmpeg-static`)
7
8
 
8
9
  ## Requirements
9
10
 
@@ -16,7 +17,7 @@ A CLI to convert:
16
17
  pnpm install
17
18
  ```
18
19
 
19
- If `pnpm` blocks install scripts (common in pnpm v10+), allow Puppeteer and install Chromium:
20
+ If `pnpm` blocks install scripts (common in pnpm v10+), allow Puppeteer and `ffmpeg-static` to finish their setup steps:
20
21
 
21
22
  ```bash
22
23
  pnpm approve-builds
@@ -52,11 +53,18 @@ fullgreen-convert ./report.docx
52
53
 
53
54
  # Explicit output path
54
55
  fullgreen-convert ./report.docx ./exports/report.pdf
56
+
57
+ # Convert music to MP3 by default
58
+ fullgreen-convert ./track.flac
59
+
60
+ # Convert music to WAV explicitly
61
+ fullgreen-convert ./track.m4a ./track.wav --format wav
55
62
  ```
56
63
 
57
64
  ### Interactive mode
58
65
 
59
- If no arguments are provided, the CLI prompts for input and output details:
66
+ If no arguments are provided, the CLI prompts for input and output details.
67
+ File paths use autocomplete-style suggestions, and `.docx` inputs show `.pdf` as the selectable output format:
60
68
 
61
69
  ```bash
62
70
  fullgreen-convert
@@ -111,8 +119,12 @@ pnpm test
111
119
 
112
120
  - HEIC conversion supports only JPG and PNG outputs.
113
121
  - DOCX conversion is Node-only and uses an embedded Chromium runtime from `puppeteer`.
122
+ - Audio conversion supports common music formats and outputs MP3 or WAV.
114
123
  - The first install can take longer because `puppeteer` downloads a browser binary.
115
124
  - Unsupported file extensions are rejected with clear error messages.
125
+ - In interactive mode, file paths use autocomplete suggestions and `.pdf` is available as a selectable output format for `.docx` inputs.
126
+ - Audio inputs can be converted interactively to either MP3 or WAV.
127
+ - The codebase is split into `src/cli/*` and `src/converters/*` so the entrypoint stays thin.
116
128
 
117
129
  ## Troubleshooting HEIC Errors
118
130
 
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import u from"path";import{access as B}from"fs/promises";import p from"chalk";import{Command as N}from"commander";import l from"inquirer";import h from"ora";import{access as x}from"fs/promises";import F from"path";import b from"mammoth";import C from"puppeteer";async function g(e){let{inputPath:t,outputPath:n}=e;await S(t);let r=F.extname(t).toLowerCase();if(r!==".docx")throw new Error(`Unsupported document input format: ${r||"unknown"}. Only .docx is supported.`);let o=await O(t);return await T(o,n),n}async function O(e){try{let t=await b.convertToHtml({path:e});if(!t.value?.trim())throw new Error("DOCX to HTML conversion returned empty content.");return $(t.value)}catch(t){let n=t instanceof Error?t.message:String(t);throw new Error(`DOCX parsing failed: ${n}`)}}async function T(e,t){let n;try{n=await C.launch({headless:!0});let r=await n.newPage();await r.setContent(e,{waitUntil:"networkidle0"}),await r.pdf({path:t,format:"A4",printBackground:!0,margin:{top:"18mm",right:"14mm",bottom:"18mm",left:"14mm"}})}catch(r){let o=r instanceof Error?r.message:String(r),i=o.toLowerCase();throw i.includes("could not find chrome")||i.includes("failed to launch the browser process")?new Error(`PDF rendering failed: Puppeteer browser is not available.
2
+ import y from"path";import u from"chalk";import{Command as mt}from"commander";import F from"ora";import d from"path";import{access as S}from"fs/promises";import f from"path";import{spawn as k}from"child_process";import T from"ffmpeg-static";var l=[".aac",".alac",".flac",".m4a",".mp3",".ogg",".opus",".wav",".wma",".webm"];async function A(t){let{inputPath:r,outputPath:o,format:e}=t;await j(r);let n=f.extname(r).toLowerCase();if(!l.includes(n))throw new Error(`Unsupported audio input format: ${n||"unknown"}. Supported formats are ${l.join(", ")}.`);let i=T;if(!i)throw new Error("Audio conversion failed: ffmpeg-static binary is not available for this platform.");let a=["-y","-i",r,"-vn"];return e==="mp3"?a.push("-codec:a","libmp3lame","-q:a","2",o):a.push("-codec:a","pcm_s16le",o),await L(i,a),o}var P={key:"audio",label:"Audio",inputExtensions:l,outputFormats:["mp3","wav"],defaultOutputFormat:"mp3",convert:({inputPath:t,outputPath:r,format:o})=>A({inputPath:t,outputPath:r,format:o}),buildDefaultOutputPath:(t,r)=>H(t,r)};function H(t,r){let o=f.parse(t);return f.join(o.dir,`${o.name}.${r}`)}async function j(t){try{await S(t)}catch{throw new Error(`Input file not found: ${t}`)}}function L(t,r){return new Promise((o,e)=>{let n=k(t,r,{stdio:"inherit"});n.on("error",i=>{e(new Error(`Audio conversion failed to start: ${i.message}`))}),n.on("exit",i=>{if(i===0){o();return}e(new Error(`Audio conversion failed: ffmpeg exited with code ${i??"unknown"}.`))})})}import{access as U}from"fs/promises";import R from"path";import M from"mammoth";import z from"puppeteer";async function x(t){let{inputPath:r,outputPath:o}=t;await q(r);let e=R.extname(r).toLowerCase();if(e!==".docx")throw new Error(`Unsupported document input format: ${e||"unknown"}. Only .docx is supported.`);let n=await W(r);return await X(n,o),o}async function W(t){try{let r=await M.convertToHtml({path:t});if(!r.value?.trim())throw new Error("DOCX to HTML conversion returned empty content.");return _(r.value)}catch(r){let o=r instanceof Error?r.message:String(r);throw new Error(`DOCX parsing failed: ${o}`)}}async function X(t,r){let o;try{o=await z.launch({headless:!0});let e=await o.newPage();await e.setContent(t,{waitUntil:"networkidle0"}),await e.pdf({path:r,format:"A4",printBackground:!0,margin:{top:"18mm",right:"14mm",bottom:"18mm",left:"14mm"}})}catch(e){let n=e instanceof Error?e.message:String(e),i=n.toLowerCase();throw i.includes("could not find chrome")||i.includes("failed to launch the browser process")?new Error(`PDF rendering failed: Puppeteer browser is not available.
3
3
  If you are using pnpm v10+, allow install scripts and install Chromium:
4
4
  1) pnpm approve-builds
5
5
  2) pnpm rebuild puppeteer
6
- 3) pnpm exec puppeteer browsers install chrome`):new Error(`PDF rendering failed: ${o}`)}finally{n&&await n.close()}}function $(e){return`<!doctype html>
6
+ 3) pnpm exec puppeteer browsers install chrome`):new Error(`PDF rendering failed: ${n}`)}finally{o&&await o.close()}}function _(t){return`<!doctype html>
7
7
  <html>
8
8
  <head>
9
9
  <meta charset="utf-8" />
@@ -28,19 +28,19 @@ If you are using pnpm v10+, allow install scripts and install Chromium:
28
28
  </style>
29
29
  </head>
30
30
  <body>
31
- ${e}
31
+ ${t}
32
32
  </body>
33
- </html>`}async function S(e){try{await x(e)}catch{throw new Error(`Input file not found: ${e}`)}}import{access as H}from"fs/promises";import j from"path";import{execFile as k}from"child_process";import{promisify as R}from"util";import D from"sharp";var A=R(k);async function d(e){let{inputPath:t,outputPath:n,format:r}=e;await M(t);let o=j.extname(t).toLowerCase();if(o!==".heic")throw new Error(`Unsupported image input format: ${o||"unknown"}. Only .heic is supported.`);if(!["jpg","png"].includes(r))throw new Error(`Unsupported output image format: ${r}. Supported formats are jpg and png.`);try{let i=D(t,{failOn:"error"});r==="jpg"?await i.jpeg({quality:90}).toFile(n):await i.png().toFile(n)}catch(i){if(L(i))try{return await U({inputPath:t,outputPath:n,format:r}),n}catch(s){throw f(i,t,s)}throw f(i,t)}return n}function f(e,t,n){let r=e instanceof Error?e.message:String(e),o=r.toLowerCase(),i=n?`
34
- Fallback (macOS sips) error: ${n instanceof Error?n.message:String(n)}`:"";return o.includes("support for this compression format has not been built in")||o.includes("heif: error while loading plugin")?new Error(`HEIC decoding is not available in the current sharp/libvips runtime.
35
- Input: ${t}
33
+ </html>`}async function q(t){try{await U(t)}catch{throw new Error(`Input file not found: ${t}`)}}import{access as B}from"fs/promises";import N from"path";import{execFile as G}from"child_process";import{promisify as J}from"util";import K from"sharp";var Q=J(G);async function E(t){let{inputPath:r,outputPath:o,format:e}=t;await V(r);let n=N.extname(r).toLowerCase();if(n!==".heic")throw new Error(`Unsupported image input format: ${n||"unknown"}. Only .heic is supported.`);if(!["jpg","png"].includes(e))throw new Error(`Unsupported output image format: ${e}. Supported formats are jpg and png.`);try{let i=K(r,{failOn:"error"});e==="jpg"?await i.jpeg({quality:90}).toFile(o):await i.png().toFile(o)}catch(i){if(Y(i))try{return await Z({inputPath:r,outputPath:o,format:e}),o}catch(a){throw b(i,r,a)}throw b(i,r)}return o}function b(t,r,o){let e=t instanceof Error?t.message:String(t),n=e.toLowerCase(),i=o?`
34
+ Fallback (macOS sips) error: ${o instanceof Error?o.message:String(o)}`:"";return n.includes("support for this compression format has not been built in")||n.includes("heif: error while loading plugin")?new Error(`HEIC decoding is not available in the current sharp/libvips runtime.
35
+ Input: ${r}
36
36
  Try one of the following:
37
37
  1) Use Node.js 20 or 22 LTS (Node 25 may not have compatible native binaries yet)
38
38
  2) Reinstall sharp for your platform: pnpm rebuild sharp
39
39
  3) Update sharp to the latest version
40
40
  4) Convert this HEIC using another tool and retry
41
- Original error: ${r}`+i):o.includes("no decoding plugin installed for this compression format")?new Error(`HEIC decoding plugin is unavailable for this runtime.
42
- Input: ${t}
41
+ Original error: ${e}`+i):n.includes("no decoding plugin installed for this compression format")?new Error(`HEIC decoding plugin is unavailable for this runtime.
42
+ Input: ${r}
43
43
  1) Reinstall sharp for your platform: pnpm rebuild sharp
44
- Original error: ${r}`+i):o.includes("bad seek")||o.includes("invalid input")?new Error(`The HEIC file appears corrupted or partially unreadable: ${t}
45
- Original error: ${r}`+i):new Error(`Image conversion failed for ${t}: ${r}${i}`)}function L(e){if(process.platform!=="darwin")return!1;let t=(e instanceof Error?e.message:String(e)).toLowerCase();return t.includes("support for this compression format has not been built in")||t.includes("heif: error while loading plugin")||t.includes("no decoding plugin installed for this compression format")}async function U(e){let{inputPath:t,outputPath:n,format:r}=e;await A("sips",["-s","format",r==="jpg"?"jpeg":"png",t,"--out",n])}async function M(e){try{await H(e)}catch{throw new Error(`Input file not found: ${e}`)}}var w=new N;w.name("fullgreen-convert").description("Convert .heic images to .jpg/.png and .docx documents to .pdf").argument("[input]","input file path").argument("[output]","output file path").option("-f, --format <format>","output format for HEIC conversion (jpg|png)").action(async(e,t,n)=>{try{if(!e){await z();return}await q(e,t,n??{})}catch(r){E(r)}});w.parseAsync(process.argv).catch(e=>E(e));async function q(e,t,n){let r=m(e);await I(r);let o=v(r),i=G(n?.format),s=X({inputPath:r,outputPathRaw:t,inputType:o,imageFormat:i}),c=h(`Converting ${p.cyan(u.basename(r))}...`).start();try{await y({inputPath:r,outputPath:s,inputType:o,imageFormat:i}),c.succeed(p.green(`Conversion completed: ${s}`))}catch(a){throw c.fail(p.red("Conversion failed")),a}}async function z(){let e=await l.prompt([{type:"input",name:"inputPathRaw",message:"Input file path:",validate:a=>a.trim().length>0?!0:"Please provide an input file path."}]),t=m(e.inputPathRaw);await I(t);let n=v(t),r="jpg";n==="heic"&&(r=(await l.prompt([{type:"list",name:"format",message:"Select output image format:",choices:[{name:"JPG",value:"jpg"},{name:"PNG",value:"png"}]}])).format);let o=P({inputPath:t,inputType:n,imageFormat:r}),i=await l.prompt([{type:"input",name:"outputPathRaw",message:"Output file path:",default:o,filter:a=>a.trim(),validate:a=>a.trim().length>0?!0:"Please provide an output file path."}]),s=m(i.outputPathRaw),c=h(`Converting ${p.cyan(u.basename(t))}...`).start();try{await y({inputPath:t,outputPath:s,inputType:n,imageFormat:r}),c.succeed(p.green(`Conversion completed: ${s}`))}catch(a){throw c.fail(p.red("Conversion failed")),a}}async function y(e){let{inputPath:t,outputPath:n,inputType:r,imageFormat:o}=e;if(r==="heic"){await d({inputPath:t,outputPath:n,format:o});return}await g({inputPath:t,outputPath:n})}function v(e){let t=u.extname(e).toLowerCase();if(t===".heic")return"heic";if(t===".docx")return"docx";throw new Error(`Unsupported input format: ${t||"unknown"}. Supported formats are .heic and .docx.`)}function G(e){if(!e)return"jpg";let t=e.toLowerCase();if(t!=="jpg"&&t!=="png")throw new Error(`Invalid format option: ${e}. Allowed values are jpg or png.`);return t}function X(e){let{inputPath:t,outputPathRaw:n,inputType:r,imageFormat:o}=e;return n?m(n):P({inputPath:t,inputType:r,imageFormat:o})}function P(e){let{inputPath:t,inputType:n,imageFormat:r}=e,o=n==="heic"?r:"pdf",i=u.parse(t);return u.join(i.dir,`${i.name}.${o}`)}function m(e){return u.resolve(process.cwd(),e)}async function I(e){try{await B(e)}catch{throw new Error(`Input file not found: ${e}`)}}function E(e){let t=e instanceof Error?e.message:String(e);console.error(p.red(`Error: ${t}`)),process.exit(1)}
44
+ Original error: ${e}`+i):n.includes("bad seek")||n.includes("invalid input")?new Error(`The HEIC file appears corrupted or partially unreadable: ${r}
45
+ Original error: ${e}`+i):new Error(`Image conversion failed for ${r}: ${e}${i}`)}function Y(t){if(process.platform!=="darwin")return!1;let r=(t instanceof Error?t.message:String(t)).toLowerCase();return r.includes("support for this compression format has not been built in")||r.includes("heif: error while loading plugin")||r.includes("no decoding plugin installed for this compression format")}async function Z(t){let{inputPath:r,outputPath:o,format:e}=t;await Q("sips",["-s","format",e==="jpg"?"jpeg":"png",r,"--out",o])}async function V(t){try{await B(t)}catch{throw new Error(`Input file not found: ${t}`)}}var tt={key:"image",label:"Image",inputExtensions:[".heic"],outputFormats:["jpg","png"],defaultOutputFormat:"jpg",convert:({inputPath:t,outputPath:r,format:o})=>E({inputPath:t,outputPath:r,format:o}),buildDefaultOutputPath:(t,r)=>O(t,r)},rt={key:"document",label:"Document",inputExtensions:[".docx"],outputFormats:["pdf"],defaultOutputFormat:"pdf",convert:({inputPath:t,outputPath:r,format:o})=>x({inputPath:t,outputPath:r}),buildDefaultOutputPath:t=>O(t,"pdf")},ot=[tt,rt,P];function g(t){let r=d.extname(t).toLowerCase(),o=ot.find(e=>e.inputExtensions.includes(r));if(!o)throw new Error(`Unsupported input format: ${r||"unknown"}. Supported formats are .heic, .docx, and audio formats like .mp3 or .wav.`);return{type:o.key,definition:o}}function O(t,r){let o=d.parse(t);return d.join(o.dir,`${o.name}.${r}`)}import h from"path";import{readdirSync as et}from"fs";import{access as nt}from"fs/promises";import{createInterface as it}from"readline";import{stdin as at,stdout as st}from"process";import pt from"inquirer";async function w(t,r=""){let o=ut(),e=it({input:at,output:st,completer:n=>{let i=n.trim().toLowerCase(),a=o.filter(s=>s.toLowerCase().includes(i)).slice(0,10);return[a.length>0?a:o.slice(0,10),n]}});try{let n=r?`${t} (${r}): `:`${t}: `,a=(await new Promise(s=>{e.question(n,s)})).trim()||r.trim();if(!a)throw new Error(`Please provide a ${t.toLowerCase()}.`);return a}finally{e.close()}}async function $(t){return(await pt.prompt([{type:"list",name:"format",message:"Select output format:",choices:t.outputFormats.map(o=>({name:o.toUpperCase(),value:o}))}])).format}async function v(t){try{await nt(t)}catch{throw new Error(`Input file not found: ${t}`)}}function ut(){let t=process.cwd(),r=200,o=4,e=new Set;return n(t,0),[...e].slice(0,r);function n(i,a){if(e.size>=r||a>o)return;let s;try{s=et(i,{withFileTypes:!0})}catch{return}s.sort((p,c)=>p.name.localeCompare(c.name));for(let p of s){if(e.size>=r)break;if(ct(p.name))continue;let c=h.join(i,p.name),C=h.relative(t,c)||p.name,D=p.isDirectory()?`${C}${h.sep}`:C;e.add(D),p.isDirectory()&&n(c,a+1)}}}function ct(t){return t==="node_modules"||t===".git"||t==="dist"||t.startsWith(".pnpm")}async function I(){let t=new mt;t.name("fullgreen-convert").description("Convert HEIC images, DOCX documents, and audio files.").argument("[input]","input file path").argument("[output]","output file path").option("-f, --format <format>","output format for the detected converter").action(async(r,o,e)=>{try{if(!r){await lt();return}await ft(r,o,e??{})}catch(n){gt(n)}}),await t.parseAsync(process.argv)}async function ft(t,r,o){let e=m(t);await v(e);let{definition:n}=g(e),i=dt(n.outputFormats,o?.format,n.defaultOutputFormat),a=r?m(r):n.buildDefaultOutputPath(e,i),s=F(`Converting ${u.cyan(y.basename(e))}...`).start();try{await n.convert({inputPath:e,outputPath:a,format:i}),s.succeed(u.green(`Conversion completed: ${a}`))}catch(p){throw s.fail(u.red("Conversion failed")),p}}async function lt(){let t=await w("Input file path"),r=m(t);await v(r);let{definition:o}=g(r),e=await $(o),n=o.buildDefaultOutputPath(r,e),i=await w("Output file path",n),a=m(i),s=F(`Converting ${u.cyan(y.basename(r))}...`).start();try{await o.convert({inputPath:r,outputPath:a,format:e}),s.succeed(u.green(`Conversion completed: ${a}`))}catch(p){throw s.fail(u.red("Conversion failed")),p}}function dt(t,r,o){if(!r)return o;let e=r.toLowerCase();if(!t.includes(e))throw new Error(`Invalid format option: ${r}. Allowed values are ${t.join(", ")}.`);return e}function m(t){return y.resolve(process.cwd(),t)}function gt(t){let r=t instanceof Error?t.message:String(t);console.error(u.red(`Error: ${r}`)),process.exit(1)}await I();
46
46
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/converters/document.ts","../src/converters/image.ts"],"sourcesContent":["\nimport path from 'node:path';\nimport { access } from 'node:fs/promises';\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport inquirer from 'inquirer';\nimport ora from 'ora';\nimport { convertDocxToPdf } from './converters/document.js';\nimport { convertHeicToImage, type ImageOutputFormat } from './converters/image.js';\n\ntype SupportedInputType = 'heic' | 'docx';\n\ninterface CliOptions {\n format?: ImageOutputFormat;\n}\n\nconst program = new Command();\n\nprogram\n .name('fullgreen-convert')\n .description('Convert .heic images to .jpg/.png and .docx documents to .pdf')\n .argument('[input]', 'input file path')\n .argument('[output]', 'output file path')\n .option('-f, --format <format>', 'output format for HEIC conversion (jpg|png)')\n .action(async (input?: string, output?: string, options?: CliOptions) => {\n\ttry {\n\t if (!input) {\n\t\tawait runInteractiveMode();\n\t\treturn;\n\t }\n\n\t await runDirectMode(input, output, options ?? {});\n\t} catch (error) {\n\t handleFatalError(error);\n\t}\n });\n\nprogram.parseAsync(process.argv).catch((error) => handleFatalError(error));\n\nasync function runDirectMode(inputPathRaw: string, outputPathRaw?: string, options?: CliOptions): Promise<void> {\n const inputPath = resolvePath(inputPathRaw);\n await ensureFileExists(inputPath);\n\n const inputType = detectInputType(inputPath);\n const imageFormat = resolveImageFormat(options?.format);\n const outputPath = resolveOutputPath({ inputPath, outputPathRaw, inputType, imageFormat });\n\n const spinner = ora(`Converting ${chalk.cyan(path.basename(inputPath))}...`).start();\n try {\n\tawait convertByType({ inputPath, outputPath, inputType, imageFormat });\n\tspinner.succeed(chalk.green(`Conversion completed: ${outputPath}`));\n } catch (error) {\n\tspinner.fail(chalk.red('Conversion failed'));\n\tthrow error;\n }\n}\n\nasync function runInteractiveMode(): Promise<void> {\n const answers = await inquirer.prompt<{\n\tinputPathRaw: string;\n }>([\n\t{\n\t type: 'input',\n\t name: 'inputPathRaw',\n\t message: 'Input file path:',\n\t validate: (value: string) => (value.trim().length > 0 ? true : 'Please provide an input file path.'),\n\t},\n ]);\n\n const inputPath = resolvePath(answers.inputPathRaw);\n await ensureFileExists(inputPath);\n const inputType = detectInputType(inputPath);\n\n let imageFormat: ImageOutputFormat = 'jpg';\n if (inputType === 'heic') {\n\tconst imageAnswers = await inquirer.prompt<{\n\t format: ImageOutputFormat;\n\t}>([\n\t {\n\t\ttype: 'list',\n\t\tname: 'format',\n\t\tmessage: 'Select output image format:',\n\t\tchoices: [\n\t\t { name: 'JPG', value: 'jpg' },\n\t\t { name: 'PNG', value: 'png' },\n\t\t],\n\t },\n\t]);\n\timageFormat = imageAnswers.format;\n }\n\n const defaultOutputPath = buildDefaultOutputPath({ inputPath, inputType, imageFormat });\n const outputAnswers = await inquirer.prompt<{\n\toutputPathRaw: string;\n }>([\n\t{\n\t type: 'input',\n\t name: 'outputPathRaw',\n\t message: 'Output file path:',\n\t default: defaultOutputPath,\n\t filter: (value: string) => value.trim(),\n\t validate: (value: string) => (value.trim().length > 0 ? true : 'Please provide an output file path.'),\n\t},\n ]);\n\n const outputPath = resolvePath(outputAnswers.outputPathRaw);\n const spinner = ora(`Converting ${chalk.cyan(path.basename(inputPath))}...`).start();\n try {\n\tawait convertByType({ inputPath, outputPath, inputType, imageFormat });\n\tspinner.succeed(chalk.green(`Conversion completed: ${outputPath}`));\n } catch (error) {\n\tspinner.fail(chalk.red('Conversion failed'));\n\tthrow error;\n }\n}\n\nasync function convertByType(params: {\n inputPath: string;\n outputPath: string;\n inputType: SupportedInputType;\n imageFormat: ImageOutputFormat;\n}): Promise<void> {\n const { inputPath, outputPath, inputType, imageFormat } = params;\n\n if (inputType === 'heic') {\n\tawait convertHeicToImage({\n\t inputPath,\n\t outputPath,\n\t format: imageFormat,\n\t});\n\treturn;\n }\n\n await convertDocxToPdf({\n\tinputPath,\n\toutputPath,\n });\n}\n\nfunction detectInputType(inputPath: string): SupportedInputType {\n const extension = path.extname(inputPath).toLowerCase();\n if (extension === '.heic') {\n\treturn 'heic';\n }\n\n if (extension === '.docx') {\n\treturn 'docx';\n }\n\n throw new Error(`Unsupported input format: ${extension || 'unknown'}. Supported formats are .heic and .docx.`);\n}\n\nfunction resolveImageFormat(format?: string): ImageOutputFormat {\n if (!format) {\n\treturn 'jpg';\n }\n\n const normalized = format.toLowerCase();\n if (normalized !== 'jpg' && normalized !== 'png') {\n\tthrow new Error(`Invalid format option: ${format}. Allowed values are jpg or png.`);\n }\n\n return normalized;\n}\n\nfunction resolveOutputPath(params: {\n inputPath: string;\n outputPathRaw?: string;\n inputType: SupportedInputType;\n imageFormat: ImageOutputFormat;\n}): string {\n const { inputPath, outputPathRaw, inputType, imageFormat } = params;\n if (outputPathRaw) {\n\treturn resolvePath(outputPathRaw);\n }\n\n return buildDefaultOutputPath({ inputPath, inputType, imageFormat });\n}\n\nfunction buildDefaultOutputPath(params: {\n inputPath: string;\n inputType: SupportedInputType;\n imageFormat: ImageOutputFormat;\n}): string {\n const { inputPath, inputType, imageFormat } = params;\n const outputExt = inputType === 'heic' ? imageFormat : 'pdf';\n const parsed = path.parse(inputPath);\n return path.join(parsed.dir, `${parsed.name}.${outputExt}`);\n}\n\nfunction resolvePath(filePath: string): string {\n return path.resolve(process.cwd(), filePath);\n}\n\nasync function ensureFileExists(filePath: string): Promise<void> {\n try {\n\tawait access(filePath);\n } catch {\n\tthrow new Error(`Input file not found: ${filePath}`);\n }\n}\n\nfunction handleFatalError(error: unknown): never {\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n}\n","import { access } from 'node:fs/promises';\nimport path from 'node:path';\nimport mammoth from 'mammoth';\nimport puppeteer from 'puppeteer';\n\nexport interface ConvertDocxToPdfOptions {\n inputPath: string;\n outputPath: string;\n}\n\nexport async function convertDocxToPdf(options: ConvertDocxToPdfOptions): Promise<string> {\n const { inputPath, outputPath } = options;\n\n await ensureFileExists(inputPath);\n\n const inputExtension = path.extname(inputPath).toLowerCase();\n if (inputExtension !== '.docx') {\n throw new Error(`Unsupported document input format: ${inputExtension || 'unknown'}. Only .docx is supported.`);\n }\n\n const html = await convertDocxToHtml(inputPath);\n await renderHtmlToPdf(html, outputPath);\n return outputPath;\n}\n\nasync function convertDocxToHtml(inputPath: string): Promise<string> {\n try {\n const result = await mammoth.convertToHtml({ path: inputPath });\n if (!result.value?.trim()) {\n throw new Error('DOCX to HTML conversion returned empty content.');\n }\n\n return wrapHtmlDocument(result.value);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`DOCX parsing failed: ${message}`);\n }\n}\n\nasync function renderHtmlToPdf(html: string, outputPath: string): Promise<void> {\n let browser: Awaited<ReturnType<typeof puppeteer.launch>> | undefined;\n\n try {\n browser = await puppeteer.launch({ headless: true });\n const page = await browser.newPage();\n await page.setContent(html, { waitUntil: 'networkidle0' });\n await page.pdf({\n path: outputPath,\n format: 'A4',\n printBackground: true,\n margin: {\n top: '18mm',\n right: '14mm',\n bottom: '18mm',\n left: '14mm',\n },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const lowered = message.toLowerCase();\n\n if (lowered.includes('could not find chrome') || lowered.includes('failed to launch the browser process')) {\n throw new Error(\n 'PDF rendering failed: Puppeteer browser is not available.\\n' +\n 'If you are using pnpm v10+, allow install scripts and install Chromium:\\n' +\n '1) pnpm approve-builds\\n' +\n '2) pnpm rebuild puppeteer\\n' +\n '3) pnpm exec puppeteer browsers install chrome',\n );\n }\n\n throw new Error(`PDF rendering failed: ${message}`);\n } finally {\n if (browser) {\n await browser.close();\n }\n }\n}\n\nfunction wrapHtmlDocument(content: string): string {\n return `<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Arial, sans-serif;\n line-height: 1.5;\n font-size: 12pt;\n }\n img {\n max-width: 100%;\n height: auto;\n }\n table {\n border-collapse: collapse;\n width: 100%;\n }\n td, th {\n border: 1px solid #ddd;\n padding: 6px;\n }\n </style>\n </head>\n <body>\n ${content}\n </body>\n</html>`;\n}\n\nasync function ensureFileExists(filePath: string): Promise<void> {\n try {\n await access(filePath);\n } catch {\n throw new Error(`Input file not found: ${filePath}`);\n }\n}\n\n","import { access } from 'node:fs/promises';\nimport path from 'node:path';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport sharp from 'sharp';\n\nexport type ImageOutputFormat = 'jpg' | 'png';\n\nexport interface ConvertHeicToImageOptions {\n inputPath: string;\n outputPath: string;\n format: ImageOutputFormat;\n}\n\nconst execFileAsync = promisify(execFile);\n\nexport async function convertHeicToImage(options: ConvertHeicToImageOptions): Promise<string> {\n const { inputPath, outputPath, format } = options;\n\n await ensureFileExists(inputPath);\n\n const inputExtension = path.extname(inputPath).toLowerCase();\n if (inputExtension !== '.heic') {\n throw new Error(`Unsupported image input format: ${inputExtension || 'unknown'}. Only .heic is supported.`);\n }\n\n if (!['jpg', 'png'].includes(format)) {\n throw new Error(`Unsupported output image format: ${format}. Supported formats are jpg and png.`);\n }\n\n try {\n const image = sharp(inputPath, { failOn: 'error' });\n\n if (format === 'jpg') {\n await image.jpeg({ quality: 90 }).toFile(outputPath);\n } else {\n await image.png().toFile(outputPath);\n }\n } catch (error) {\n if (canUseMacOSSipsFallback(error)) {\n try {\n await convertHeicWithSips({ inputPath, outputPath, format });\n return outputPath;\n } catch (fallbackError) {\n throw mapHeicRuntimeError(error, inputPath, fallbackError);\n }\n }\n\n throw mapHeicRuntimeError(error, inputPath);\n }\n\n return outputPath;\n}\n\nfunction mapHeicRuntimeError(error: unknown, inputPath: string, fallbackError?: unknown): Error {\n const rawMessage = error instanceof Error ? error.message : String(error);\n const lowered = rawMessage.toLowerCase();\n const fallbackMessage = fallbackError\n ? `\\nFallback (macOS sips) error: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`\n : '';\n\n if (lowered.includes('support for this compression format has not been built in') || lowered.includes('heif: error while loading plugin')) {\n return new Error(\n `HEIC decoding is not available in the current sharp/libvips runtime.\\n` +\n `Input: ${inputPath}\\n` +\n 'Try one of the following:\\n' +\n '1) Use Node.js 20 or 22 LTS (Node 25 may not have compatible native binaries yet)\\n' +\n '2) Reinstall sharp for your platform: pnpm rebuild sharp\\n' +\n '3) Update sharp to the latest version\\n' +\n '4) Convert this HEIC using another tool and retry\\n' +\n `Original error: ${rawMessage}` +\n fallbackMessage,\n );\n }\n\n if (lowered.includes('no decoding plugin installed for this compression format')) {\n return new Error(\n `HEIC decoding plugin is unavailable for this runtime.\\n` +\n `Input: ${inputPath}\\n` +\n '1) Reinstall sharp for your platform: pnpm rebuild sharp\\n' +\n `Original error: ${rawMessage}` +\n fallbackMessage,\n );\n }\n\n if (lowered.includes('bad seek') || lowered.includes('invalid input')) {\n return new Error(\n `The HEIC file appears corrupted or partially unreadable: ${inputPath}\\n` +\n `Original error: ${rawMessage}` +\n fallbackMessage,\n );\n }\n\n return new Error(`Image conversion failed for ${inputPath}: ${rawMessage}${fallbackMessage}`);\n}\n\nfunction canUseMacOSSipsFallback(error: unknown): boolean {\n if (process.platform !== 'darwin') {\n return false;\n }\n\n const message = (error instanceof Error ? error.message : String(error)).toLowerCase();\n return (\n message.includes('support for this compression format has not been built in') ||\n message.includes('heif: error while loading plugin') ||\n message.includes('no decoding plugin installed for this compression format')\n );\n}\n\nasync function convertHeicWithSips(options: ConvertHeicToImageOptions): Promise<void> {\n const { inputPath, outputPath, format } = options;\n const sipsFormat = format === 'jpg' ? 'jpeg' : 'png';\n\n await execFileAsync('sips', ['-s', 'format', sipsFormat, inputPath, '--out', outputPath]);\n}\n\nasync function ensureFileExists(filePath: string): Promise<void> {\n try {\n await access(filePath);\n } catch {\n throw new Error(`Input file not found: ${filePath}`);\n }\n}\n\n"],"mappings":"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","names":["path","access","chalk","Command","inquirer","ora","access","path","mammoth","puppeteer","convertDocxToPdf","options","inputPath","outputPath","ensureFileExists","inputExtension","html","convertDocxToHtml","renderHtmlToPdf","result","wrapHtmlDocument","error","message","browser","page","lowered","content","filePath","access","path","execFile","promisify","sharp","execFileAsync","convertHeicToImage","options","inputPath","outputPath","format","ensureFileExists","inputExtension","image","error","canUseMacOSSipsFallback","convertHeicWithSips","fallbackError","mapHeicRuntimeError","rawMessage","lowered","fallbackMessage","message","filePath","program","Command","input","output","options","runInteractiveMode","runDirectMode","error","handleFatalError","inputPathRaw","outputPathRaw","inputPath","resolvePath","ensureFileExists","inputType","detectInputType","imageFormat","resolveImageFormat","outputPath","resolveOutputPath","spinner","ora","chalk","path","convertByType","answers","inquirer","value","defaultOutputPath","buildDefaultOutputPath","outputAnswers","params","convertHeicToImage","convertDocxToPdf","extension","format","normalized","outputExt","parsed","filePath","access","message"]}
1
+ {"version":3,"sources":["../src/cli/app.ts","../src/converters/index.ts","../src/converters/audio.ts","../src/converters/document.ts","../src/converters/image.ts","../src/cli/prompts.ts","../src/index.ts"],"sourcesContent":["import path from 'node:path';\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport ora from 'ora';\nimport { resolveConverter } from '../converters/index.js';\nimport { ensureFileExists, promptOutputFormat, promptPathWithAutocomplete } from './prompts.js';\n\ninterface CliOptions {\n format?: string;\n}\n\nexport async function runCli(): Promise<void> {\n const program = new Command();\n\n program\n .name('fullgreen-convert')\n .description('Convert HEIC images, DOCX documents, and audio files.')\n .argument('[input]', 'input file path')\n .argument('[output]', 'output file path')\n .option('-f, --format <format>', 'output format for the detected converter')\n .action(async (input?: string, output?: string, options?: CliOptions) => {\n try {\n if (!input) {\n await runInteractiveMode();\n return;\n }\n\n await runDirectMode(input, output, options ?? {});\n } catch (error) {\n handleFatalError(error);\n }\n });\n\n await program.parseAsync(process.argv);\n}\n\nasync function runDirectMode(inputPathRaw: string, outputPathRaw?: string, options?: CliOptions): Promise<void> {\n const inputPath = resolvePath(inputPathRaw);\n await ensureFileExists(inputPath);\n\n const { definition } = resolveConverter(inputPath);\n const format = resolveDirectFormat(definition.outputFormats, options?.format, definition.defaultOutputFormat);\n const outputPath = outputPathRaw ? resolvePath(outputPathRaw) : definition.buildDefaultOutputPath(inputPath, format);\n\n const spinner = ora(`Converting ${chalk.cyan(path.basename(inputPath))}...`).start();\n try {\n await definition.convert({ inputPath, outputPath, format: format as never });\n spinner.succeed(chalk.green(`Conversion completed: ${outputPath}`));\n } catch (error) {\n spinner.fail(chalk.red('Conversion failed'));\n throw error;\n }\n}\n\nasync function runInteractiveMode(): Promise<void> {\n const inputPathRaw = await promptPathWithAutocomplete('Input file path');\n const inputPath = resolvePath(inputPathRaw);\n await ensureFileExists(inputPath);\n\n const { definition } = resolveConverter(inputPath);\n const outputFormat = await promptOutputFormat(definition);\n const defaultOutputPath = definition.buildDefaultOutputPath(inputPath, outputFormat);\n const outputPathRaw = await promptPathWithAutocomplete('Output file path', defaultOutputPath);\n const outputPath = resolvePath(outputPathRaw);\n\n const spinner = ora(`Converting ${chalk.cyan(path.basename(inputPath))}...`).start();\n try {\n await definition.convert({ inputPath, outputPath, format: outputFormat });\n spinner.succeed(chalk.green(`Conversion completed: ${outputPath}`));\n } catch (error) {\n spinner.fail(chalk.red('Conversion failed'));\n throw error;\n }\n}\n\nfunction resolveDirectFormat(allowedFormats: readonly string[], requestedFormat: string | undefined, defaultFormat: string): string {\n if (!requestedFormat) {\n return defaultFormat;\n }\n\n const normalized = requestedFormat.toLowerCase();\n if (!allowedFormats.includes(normalized)) {\n throw new Error(`Invalid format option: ${requestedFormat}. Allowed values are ${allowedFormats.join(', ')}.`);\n }\n\n return normalized;\n}\n\nfunction resolvePath(filePath: string): string {\n return path.resolve(process.cwd(), filePath);\n}\n\nfunction handleFatalError(error: unknown): never {\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n}\n\n","import path from 'node:path';\nimport { audioConverter } from './audio.js';\nimport { convertDocxToPdf } from './document.js';\nimport { convertHeicToImage } from './image.js';\nimport { type ConverterDefinition } from './types.js';\nimport { type ImageOutputFormat } from './image.js';\n\nexport type SupportedInputType = 'image' | 'document' | 'audio';\n\nexport interface ResolvedConverter {\n type: SupportedInputType;\n definition: ConverterDefinition<any>;\n}\n\nconst imageConverter: ConverterDefinition<ImageOutputFormat> = {\n key: 'image',\n label: 'Image',\n inputExtensions: ['.heic'],\n outputFormats: ['jpg', 'png'],\n defaultOutputFormat: 'jpg',\n convert: ({ inputPath, outputPath, format }) => convertHeicToImage({ inputPath, outputPath, format }),\n buildDefaultOutputPath: (inputPath, format) => buildDefaultOutputPath(inputPath, format),\n};\n\nconst documentConverter: ConverterDefinition<'pdf'> = {\n key: 'document',\n label: 'Document',\n inputExtensions: ['.docx'],\n outputFormats: ['pdf'],\n defaultOutputFormat: 'pdf',\n convert: ({ inputPath, outputPath, format: _format }) => convertDocxToPdf({ inputPath, outputPath }),\n buildDefaultOutputPath: (inputPath) => buildDefaultOutputPath(inputPath, 'pdf'),\n};\n\nexport const converters: Array<ConverterDefinition<any>> = [imageConverter, documentConverter, audioConverter];\n\nexport function resolveConverter(inputPath: string): ResolvedConverter {\n const extension = path.extname(inputPath).toLowerCase();\n const definition = converters.find((candidate) => candidate.inputExtensions.includes(extension));\n\n if (!definition) {\n throw new Error(`Unsupported input format: ${extension || 'unknown'}. Supported formats are .heic, .docx, and audio formats like .mp3 or .wav.`);\n }\n\n return {\n type: definition.key as SupportedInputType,\n definition,\n };\n}\n\nfunction buildDefaultOutputPath(inputPath: string, format: string): string {\n const parsed = path.parse(inputPath);\n return path.join(parsed.dir, `${parsed.name}.${format}`);\n}\n\n","import { access } from 'node:fs/promises';\nimport path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport ffmpegStatic from 'ffmpeg-static';\nimport { type ConverterDefinition } from './types.js';\n\nexport type AudioOutputFormat = 'mp3' | 'wav';\n\nconst audioInputExtensions = ['.aac', '.alac', '.flac', '.m4a', '.mp3', '.ogg', '.opus', '.wav', '.wma', '.webm'];\n\nexport async function convertAudioToFile(options: {\n inputPath: string;\n outputPath: string;\n format: AudioOutputFormat;\n}): Promise<string> {\n const { inputPath, outputPath, format } = options;\n\n await ensureFileExists(inputPath);\n\n const inputExtension = path.extname(inputPath).toLowerCase();\n if (!audioInputExtensions.includes(inputExtension)) {\n throw new Error(`Unsupported audio input format: ${inputExtension || 'unknown'}. Supported formats are ${audioInputExtensions.join(', ')}.`);\n }\n\n const ffmpegPath = ffmpegStatic;\n if (!ffmpegPath) {\n throw new Error('Audio conversion failed: ffmpeg-static binary is not available for this platform.');\n }\n\n const args = ['-y', '-i', inputPath, '-vn'];\n if (format === 'mp3') {\n args.push('-codec:a', 'libmp3lame', '-q:a', '2', outputPath);\n } else {\n args.push('-codec:a', 'pcm_s16le', outputPath);\n }\n\n await runFfmpeg(ffmpegPath, args);\n return outputPath;\n}\n\nexport const audioConverter: ConverterDefinition<AudioOutputFormat> = {\n key: 'audio',\n label: 'Audio',\n inputExtensions: audioInputExtensions,\n outputFormats: ['mp3', 'wav'],\n defaultOutputFormat: 'mp3',\n convert: ({ inputPath, outputPath, format }) => convertAudioToFile({ inputPath, outputPath, format }),\n buildDefaultOutputPath: (inputPath, format) => buildDefaultOutputPath(inputPath, format),\n};\n\nfunction buildDefaultOutputPath(inputPath: string, format: AudioOutputFormat): string {\n const parsed = path.parse(inputPath);\n return path.join(parsed.dir, `${parsed.name}.${format}`);\n}\n\nasync function ensureFileExists(filePath: string): Promise<void> {\n try {\n await access(filePath);\n } catch {\n throw new Error(`Input file not found: ${filePath}`);\n }\n}\n\nfunction runFfmpeg(ffmpegPath: string, args: string[]): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(ffmpegPath, args, { stdio: 'inherit' });\n\n child.on('error', (error) => {\n reject(new Error(`Audio conversion failed to start: ${error.message}`));\n });\n\n child.on('exit', (code) => {\n if (code === 0) {\n resolve();\n return;\n }\n\n reject(new Error(`Audio conversion failed: ffmpeg exited with code ${code ?? 'unknown'}.`));\n });\n });\n}\n\n\n","import { access } from 'node:fs/promises';\nimport path from 'node:path';\nimport mammoth from 'mammoth';\nimport puppeteer from 'puppeteer';\n\nexport interface ConvertDocxToPdfOptions {\n inputPath: string;\n outputPath: string;\n}\n\nexport async function convertDocxToPdf(options: ConvertDocxToPdfOptions): Promise<string> {\n const { inputPath, outputPath } = options;\n\n await ensureFileExists(inputPath);\n\n const inputExtension = path.extname(inputPath).toLowerCase();\n if (inputExtension !== '.docx') {\n throw new Error(`Unsupported document input format: ${inputExtension || 'unknown'}. Only .docx is supported.`);\n }\n\n const html = await convertDocxToHtml(inputPath);\n await renderHtmlToPdf(html, outputPath);\n return outputPath;\n}\n\nasync function convertDocxToHtml(inputPath: string): Promise<string> {\n try {\n const result = await mammoth.convertToHtml({ path: inputPath });\n if (!result.value?.trim()) {\n throw new Error('DOCX to HTML conversion returned empty content.');\n }\n\n return wrapHtmlDocument(result.value);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`DOCX parsing failed: ${message}`);\n }\n}\n\nasync function renderHtmlToPdf(html: string, outputPath: string): Promise<void> {\n let browser: Awaited<ReturnType<typeof puppeteer.launch>> | undefined;\n\n try {\n browser = await puppeteer.launch({ headless: true });\n const page = await browser.newPage();\n await page.setContent(html, { waitUntil: 'networkidle0' });\n await page.pdf({\n path: outputPath,\n format: 'A4',\n printBackground: true,\n margin: {\n top: '18mm',\n right: '14mm',\n bottom: '18mm',\n left: '14mm',\n },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const lowered = message.toLowerCase();\n\n if (lowered.includes('could not find chrome') || lowered.includes('failed to launch the browser process')) {\n throw new Error(\n 'PDF rendering failed: Puppeteer browser is not available.\\n' +\n 'If you are using pnpm v10+, allow install scripts and install Chromium:\\n' +\n '1) pnpm approve-builds\\n' +\n '2) pnpm rebuild puppeteer\\n' +\n '3) pnpm exec puppeteer browsers install chrome',\n );\n }\n\n throw new Error(`PDF rendering failed: ${message}`);\n } finally {\n if (browser) {\n await browser.close();\n }\n }\n}\n\nfunction wrapHtmlDocument(content: string): string {\n return `<!doctype html>\n<html>\n <head>\n <meta charset=\"utf-8\" />\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Arial, sans-serif;\n line-height: 1.5;\n font-size: 12pt;\n }\n img {\n max-width: 100%;\n height: auto;\n }\n table {\n border-collapse: collapse;\n width: 100%;\n }\n td, th {\n border: 1px solid #ddd;\n padding: 6px;\n }\n </style>\n </head>\n <body>\n ${content}\n </body>\n</html>`;\n}\n\nasync function ensureFileExists(filePath: string): Promise<void> {\n try {\n await access(filePath);\n } catch {\n throw new Error(`Input file not found: ${filePath}`);\n }\n}\n\n","import { access } from 'node:fs/promises';\nimport path from 'node:path';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport sharp from 'sharp';\n\nexport type ImageOutputFormat = 'jpg' | 'png';\n\nexport interface ConvertHeicToImageOptions {\n inputPath: string;\n outputPath: string;\n format: ImageOutputFormat;\n}\n\nconst execFileAsync = promisify(execFile);\n\nexport async function convertHeicToImage(options: ConvertHeicToImageOptions): Promise<string> {\n const { inputPath, outputPath, format } = options;\n\n await ensureFileExists(inputPath);\n\n const inputExtension = path.extname(inputPath).toLowerCase();\n if (inputExtension !== '.heic') {\n throw new Error(`Unsupported image input format: ${inputExtension || 'unknown'}. Only .heic is supported.`);\n }\n\n if (!['jpg', 'png'].includes(format)) {\n throw new Error(`Unsupported output image format: ${format}. Supported formats are jpg and png.`);\n }\n\n try {\n const image = sharp(inputPath, { failOn: 'error' });\n\n if (format === 'jpg') {\n await image.jpeg({ quality: 90 }).toFile(outputPath);\n } else {\n await image.png().toFile(outputPath);\n }\n } catch (error) {\n if (canUseMacOSSipsFallback(error)) {\n try {\n await convertHeicWithSips({ inputPath, outputPath, format });\n return outputPath;\n } catch (fallbackError) {\n throw mapHeicRuntimeError(error, inputPath, fallbackError);\n }\n }\n\n throw mapHeicRuntimeError(error, inputPath);\n }\n\n return outputPath;\n}\n\nfunction mapHeicRuntimeError(error: unknown, inputPath: string, fallbackError?: unknown): Error {\n const rawMessage = error instanceof Error ? error.message : String(error);\n const lowered = rawMessage.toLowerCase();\n const fallbackMessage = fallbackError\n ? `\\nFallback (macOS sips) error: ${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`\n : '';\n\n if (lowered.includes('support for this compression format has not been built in') || lowered.includes('heif: error while loading plugin')) {\n return new Error(\n `HEIC decoding is not available in the current sharp/libvips runtime.\\n` +\n `Input: ${inputPath}\\n` +\n 'Try one of the following:\\n' +\n '1) Use Node.js 20 or 22 LTS (Node 25 may not have compatible native binaries yet)\\n' +\n '2) Reinstall sharp for your platform: pnpm rebuild sharp\\n' +\n '3) Update sharp to the latest version\\n' +\n '4) Convert this HEIC using another tool and retry\\n' +\n `Original error: ${rawMessage}` +\n fallbackMessage,\n );\n }\n\n if (lowered.includes('no decoding plugin installed for this compression format')) {\n return new Error(\n `HEIC decoding plugin is unavailable for this runtime.\\n` +\n `Input: ${inputPath}\\n` +\n '1) Reinstall sharp for your platform: pnpm rebuild sharp\\n' +\n `Original error: ${rawMessage}` +\n fallbackMessage,\n );\n }\n\n if (lowered.includes('bad seek') || lowered.includes('invalid input')) {\n return new Error(\n `The HEIC file appears corrupted or partially unreadable: ${inputPath}\\n` +\n `Original error: ${rawMessage}` +\n fallbackMessage,\n );\n }\n\n return new Error(`Image conversion failed for ${inputPath}: ${rawMessage}${fallbackMessage}`);\n}\n\nfunction canUseMacOSSipsFallback(error: unknown): boolean {\n if (process.platform !== 'darwin') {\n return false;\n }\n\n const message = (error instanceof Error ? error.message : String(error)).toLowerCase();\n return (\n message.includes('support for this compression format has not been built in') ||\n message.includes('heif: error while loading plugin') ||\n message.includes('no decoding plugin installed for this compression format')\n );\n}\n\nasync function convertHeicWithSips(options: ConvertHeicToImageOptions): Promise<void> {\n const { inputPath, outputPath, format } = options;\n const sipsFormat = format === 'jpg' ? 'jpeg' : 'png';\n\n await execFileAsync('sips', ['-s', 'format', sipsFormat, inputPath, '--out', outputPath]);\n}\n\nasync function ensureFileExists(filePath: string): Promise<void> {\n try {\n await access(filePath);\n } catch {\n throw new Error(`Input file not found: ${filePath}`);\n }\n}\n\n","import path from 'node:path';\nimport { readdirSync } from 'node:fs';\nimport { access } from 'node:fs/promises';\nimport { createInterface } from 'node:readline';\nimport { stdin as inputStream, stdout as outputStream } from 'node:process';\nimport inquirer from 'inquirer';\nimport { type ConverterDefinition } from '../converters/types.js';\n\nexport async function promptPathWithAutocomplete(message: string, defaultValue = ''): Promise<string> {\n const suggestions = collectPathSuggestions();\n const rl = createInterface({\n input: inputStream,\n output: outputStream,\n completer: (line: string) => {\n const normalized = line.trim().toLowerCase();\n const matches = suggestions.filter((candidate) => candidate.toLowerCase().includes(normalized)).slice(0, 10);\n return [matches.length > 0 ? matches : suggestions.slice(0, 10), line];\n },\n });\n\n try {\n const promptLabel = defaultValue ? `${message} (${defaultValue}): ` : `${message}: `;\n const answer = await new Promise<string>((resolve) => {\n rl.question(promptLabel, resolve);\n });\n const resolved = answer.trim() || defaultValue.trim();\n\n if (!resolved) {\n throw new Error(`Please provide a ${message.toLowerCase()}.`);\n }\n\n return resolved;\n } finally {\n rl.close();\n }\n}\n\nexport async function promptOutputFormat(definition: ConverterDefinition): Promise<string> {\n const answers = (await inquirer.prompt([\n {\n type: 'list',\n name: 'format',\n message: 'Select output format:',\n choices: definition.outputFormats.map((format) => ({ name: format.toUpperCase(), value: format })),\n },\n ])) as { format: string };\n\n return answers.format;\n}\n\nexport async function ensureFileExists(filePath: string): Promise<void> {\n try {\n await access(filePath);\n } catch {\n throw new Error(`Input file not found: ${filePath}`);\n }\n}\n\nfunction collectPathSuggestions(): string[] {\n const root = process.cwd();\n const maxResults = 200;\n const maxDepth = 4;\n const results = new Set<string>();\n\n walk(root, 0);\n return [...results].slice(0, maxResults);\n\n function walk(currentDir: string, depth: number): void {\n if (results.size >= maxResults || depth > maxDepth) {\n return;\n }\n\n let entries;\n try {\n entries = readdirSync(currentDir, { withFileTypes: true });\n } catch {\n return;\n }\n\n entries.sort((a, b) => a.name.localeCompare(b.name));\n for (const entry of entries) {\n if (results.size >= maxResults) {\n break;\n }\n\n if (shouldIgnorePath(entry.name)) {\n continue;\n }\n\n const fullPath = path.join(currentDir, entry.name);\n const relativePath = path.relative(root, fullPath) || entry.name;\n const candidate = entry.isDirectory() ? `${relativePath}${path.sep}` : relativePath;\n results.add(candidate);\n\n if (entry.isDirectory()) {\n walk(fullPath, depth + 1);\n }\n }\n }\n}\n\nfunction shouldIgnorePath(name: string): boolean {\n return name === 'node_modules' || name === '.git' || name === 'dist' || name.startsWith('.pnpm');\n}\n\n","import { runCli } from './cli/app.js';\n\nawait runCli();\n"],"mappings":"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","names":["path","chalk","Command","ora","path","access","path","spawn","ffmpegStatic","audioInputExtensions","convertAudioToFile","options","inputPath","outputPath","format","ensureFileExists","inputExtension","ffmpegPath","args","runFfmpeg","audioConverter","buildDefaultOutputPath","parsed","filePath","resolve","reject","child","error","code","access","path","mammoth","puppeteer","convertDocxToPdf","options","inputPath","outputPath","ensureFileExists","inputExtension","html","convertDocxToHtml","renderHtmlToPdf","result","wrapHtmlDocument","error","message","browser","page","lowered","content","filePath","access","path","execFile","promisify","sharp","execFileAsync","convertHeicToImage","options","inputPath","outputPath","format","ensureFileExists","inputExtension","image","error","canUseMacOSSipsFallback","convertHeicWithSips","fallbackError","mapHeicRuntimeError","rawMessage","lowered","fallbackMessage","message","filePath","imageConverter","inputPath","outputPath","format","convertHeicToImage","buildDefaultOutputPath","documentConverter","_format","convertDocxToPdf","converters","audioConverter","resolveConverter","extension","path","definition","candidate","parsed","path","readdirSync","access","createInterface","inputStream","outputStream","inquirer","promptPathWithAutocomplete","message","defaultValue","suggestions","collectPathSuggestions","rl","line","normalized","matches","candidate","promptLabel","resolved","resolve","promptOutputFormat","definition","format","ensureFileExists","filePath","root","maxResults","maxDepth","results","walk","currentDir","depth","entries","a","b","entry","shouldIgnorePath","fullPath","relativePath","name","runCli","program","Command","input","output","options","runInteractiveMode","runDirectMode","error","handleFatalError","inputPathRaw","outputPathRaw","inputPath","resolvePath","ensureFileExists","definition","resolveConverter","format","resolveDirectFormat","outputPath","spinner","ora","chalk","path","promptPathWithAutocomplete","outputFormat","promptOutputFormat","defaultOutputPath","allowedFormats","requestedFormat","defaultFormat","normalized","filePath","message","runCli"]}
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@fullgreengn/converter",
3
- "version": "1.0.0",
4
- "description": "Professional CLI to convert HEIC and DOCX files.",
3
+ "version": "1.0.1",
4
+ "description": "Professional CLI to convert documents, images, and videos with ease.",
5
5
  "bin": {
6
6
  "fullgreen-convert": "dist/index.js"
7
7
  },
8
8
  "type": "module",
9
9
  "main": "dist/index.js",
10
10
  "engines": {
11
- "node": ">=20 <25"
11
+ "node": ">=20"
12
12
  },
13
13
  "files": [
14
14
  "dist"
@@ -18,6 +18,7 @@
18
18
  "commander": "^14.0.3",
19
19
  "inquirer": "^13.4.1",
20
20
  "mammoth": "^1.9.1",
21
+ "ffmpeg-static": "^5.2.0",
21
22
  "ora": "^9.3.0",
22
23
  "puppeteer": "^24.7.2",
23
24
  "sharp": "^0.34.5"