├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github └── workflows │ ├── main.yml │ └── publish.yml ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── examples ├── conversion_chaining.js ├── convert_base64_content.js ├── convert_stream.js ├── convert_url_to_pdf.js ├── convert_word_to_pdf_and_png.js ├── create_pdf_thumbnail.js ├── files │ ├── test.docx │ └── test.pdf ├── get_result_file_stream.js ├── index.js ├── retrieve_user_information.js └── split_and_merge_pdf.js ├── index.d.ts ├── package-lock.json ├── package.json ├── src ├── client.js ├── error.js ├── index.js ├── result.js ├── result_file.js ├── task.js ├── upload_result.js └── utils.js └── test └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "development": { 4 | "presets": [ 5 | ["env", { "targets": { "node": 6 } }] 6 | ] 7 | }, 8 | "production": { 9 | "presets": [ 10 | ["env", { "targets": { "node": 6 } }] 11 | ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain 2 | # consistent coding styles between different editors and IDEs. 3 | 4 | root = true 5 | 6 | [*] 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "extends": "airbnb", 4 | "env": { 5 | "mocha": true 6 | }, 7 | "rules": { 8 | "comma-dangle": ["error", "only-multiline"] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - master 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | node-version: 13 | - 21 14 | - 20 15 | - 18 16 | - 16 17 | name: Node ${{ matrix.node-version }} sample 18 | steps: 19 | - uses: actions/checkout@v3 20 | - uses: actions/setup-node@v3 21 | with: 22 | node-version: ${{ matrix.node-version }} 23 | - run: npm install --ignore-scripts 24 | - env: 25 | CONVERT_API_SECRET: ${{ secrets.CONVERTAPI_SECRET }} 26 | run: npm test 27 | - run: npm run build 28 | - env: 29 | CONVERT_API_SECRET: ${{ secrets.CONVERTAPI_SECRET }} 30 | run: npm run test:examples 31 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish package to npmjs 2 | on: 3 | release: 4 | types: [published] 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | # Setup .npmrc file to publish to npm 11 | - uses: actions/setup-node@v3 12 | with: 13 | node-version: '20.x' 14 | registry-url: 'https://registry.npmjs.org' 15 | - run: npm ci 16 | env: 17 | CONVERT_API_SECRET: ${{ secrets.CONVERTAPI_SECRET }} 18 | - run: npm publish 19 | env: 20 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 21 | CONVERT_API_SECRET: ${{ secrets.CONVERTAPI_SECRET }} 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Compiled binary addons (http://nodejs.org/api/addons.html) 21 | build/Release 22 | 23 | # Dependency directories 24 | node_modules 25 | jspm_packages 26 | 27 | # Optional npm cache directory 28 | .npm 29 | .npmrc 30 | 31 | # Optional REPL history 32 | .node_repl_history 33 | 34 | # Editors 35 | .idea 36 | 37 | # Lib 38 | lib 39 | 40 | # npm package lock 41 | #package-lock.json 42 | yarn.lock 43 | 44 | others 45 | .DS_Store -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.log 2 | npm-debug.log* 3 | 4 | # Coverage directory used by tools like istanbul 5 | coverage 6 | .nyc_output 7 | 8 | # Dependency directories 9 | node_modules 10 | 11 | # npm package lock 12 | package-lock.json 13 | yarn.lock 14 | 15 | # project files 16 | src 17 | test 18 | examples 19 | CHANGELOG.md 20 | .travis.yml 21 | .editorconfig 22 | .eslintignore 23 | .eslintrc 24 | .babelrc 25 | .gitignore 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ConvertAPI 2 | https://www.convertapi.com 3 | (c) 2011-2018 Baltsoft 4 | 5 | ConvertAPI.Node 6 | https://github.com/ConvertAPI/convertapi-node 7 | Copyright (c) 2018 Tomas Rutkauskas 8 | 9 | The MIT License 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 12 | modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 13 | is furnished to do so, subject to the following conditions: 14 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 16 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 17 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 18 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ConvertAPI Node.js Client 2 | 3 | [![npm version](https://badge.fury.io/js/convertapi.svg)](https://badge.fury.io/js/convertapi) 4 | [![Build Status](https://github.com/ConvertAPI/convertapi-node/actions/workflows/main.yml/badge.svg)](https://github.com/ConvertAPI/convertapi-node/actions) 5 | [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) 6 | 7 | ## Convert your files with our online file conversion API 8 | 9 | [The ConvertAPI](https://convertapi.com) helps in converting various file formats. Creating PDF and Images from various sources like Word, Excel, Powerpoint, images, web pages or raw HTML codes. Merge, Encrypt, Split, Repair and Decrypt PDF files and many other file manipulations. You can integrate it into your application in just a few minutes and use it easily. 10 | 11 | ## Installation 12 | 13 | ```sh 14 | npm install convertapi --save 15 | ``` 16 | 17 | ## Usage 18 | 19 | The package needs to be configured with your account's token which is available at https://www.convertapi.com/a/authentication 20 | 21 | Require it with the key's value: 22 | 23 | ```javascript 24 | var convertapi = require('convertapi')('api-token'); 25 | ``` 26 | 27 | Or using ES modules: 28 | 29 | ```javascript 30 | import ConvertAPI from 'convertapi'; 31 | 32 | const convertapi = new ConvertAPI('api-token'); 33 | ``` 34 | 35 | You can specify additional options, like proxy configuration and timeouts, when initializing the client: 36 | 37 | ```javascript 38 | var convertapi = require('convertapi')('api-token', { 39 | conversionTimeout: 60, 40 | uploadTimeout: 60, 41 | downloadTimeout: 60, 42 | proxy: { 43 | host: '127.0.0.1', 44 | port: 9000, 45 | auth: { 46 | username: 'testuser', 47 | password: 'secret' 48 | } 49 | }, 50 | keepAlive: true 51 | }); 52 | ``` 53 | 54 | If using ES module: 55 | 56 | ```javascript 57 | const convertapi = new ConvertAPI('api-token', { conversionTimeout: 60 }); 58 | ``` 59 | 60 | ### File conversion 61 | 62 | Convert file to PDF example. All supported file formats and options can be found 63 | [here](https://www.convertapi.com/conversions). 64 | 65 | ```javascript 66 | convertapi.convert('pdf', { File: '/path/to/my_file.docx' }) 67 | .then(function(result) { 68 | // get converted file url 69 | console.log("Converted file url: " + result.file.url); 70 | 71 | // save to file 72 | return result.file.save('/path/to/save/file.pdf'); 73 | }) 74 | .then(function(file) { 75 | console.log("File saved: " + file); 76 | }) 77 | .catch(function(e) { 78 | console.error(e.toString()); 79 | }); 80 | ``` 81 | 82 | Other result operations: 83 | 84 | ```javascript 85 | // save all result files to folder 86 | result.saveFiles('/path/to/save/files').then(function(files) { 87 | console.log("Files saved: " + files); 88 | }); 89 | 90 | // get conversion cost 91 | console.log("Conversion cost: " + result.conversionCost); 92 | ``` 93 | 94 | #### Convert file url 95 | 96 | ```javascript 97 | var resultPromise = convertapi.convert('pdf', { File: 'https://website/my_file.docx' }); 98 | ``` 99 | 100 | #### Specifying from format 101 | 102 | ```javascript 103 | var resultPromise = convertapi.convert('pdf', { File: 'https://website/my_file' }, 'docx'); 104 | ``` 105 | 106 | #### Additional conversion parameters 107 | 108 | ConvertAPI accepts additional conversion parameters depending on selected formats. All conversion 109 | parameters and explanations can be found [here](https://www.convertapi.com/conversions). 110 | 111 | ```javascript 112 | var resultPromise = convertapi.convert( 113 | 'pdf', 114 | { 115 | File: '/path/to/my_file.docx', 116 | PageRange: '1-10', 117 | PdfResolution: '150', 118 | } 119 | ); 120 | ``` 121 | 122 | ### User information 123 | 124 | You can always check your conversion counts by fetching [user information](https://www.convertapi.com/doc/user). 125 | 126 | ```javascript 127 | convertapi.getUser().then(function(info) { 128 | console.log("ConversionsTotal: " + info.ConversionsTotal); 129 | console.log("ConversionsConsumed: " + info.ConversionsConsumed); 130 | }); 131 | ``` 132 | 133 | ### Error handling 134 | 135 | ```javascript 136 | convertapi 137 | .convert('pdf', { File: 'https://website/my_file.docx' }) 138 | .catch(function(e) { 139 | console.error(e.toString()); 140 | console.debug(e.request); 141 | console.debug(e.response); 142 | }); 143 | ``` 144 | 145 | ### Alternative domain 146 | 147 | Set `base_uri` parameter to use other service domains. Dedicated to the region [domain list](https://www.convertapi.com/doc/servers-location). 148 | 149 | ```js 150 | var convertapi = require('../lib')(process.env.API_TOKEN, { baseUri: 'https://eu-v2.convertapi.com/' }); 151 | ``` 152 | 153 | ### More examples 154 | 155 | Find more advanced examples in the [examples/](https://github.com/ConvertAPI/convertapi-node/tree/master/examples) folder. 156 | 157 | ## Development Commands 158 | 159 | - `npm run clean` - Remove the `lib/` directory 160 | - `npm test` - Run tests with linting and coverage results. 161 | - `npm run test:only` - Run tests without linting or coverage. 162 | - `npm run test:watch` - You can even re-run tests on file changes! 163 | - `npm run test:prod` - Run tests with minified code. 164 | - `npm run test:examples` - Test written examples on pure JS for better understanding module usage. 165 | - `npm run lint` - Run ESlint with airbnb-config 166 | - `npm run cover` - Get coverage report for your code. 167 | - `npm run build` - Babel will transpile ES6 => ES5 and minify the code. 168 | - `npm run prepublish` - Hook for npm. Do all the checks before publishing your module. 169 | 170 | ## Contributing 171 | 172 | Bug reports and pull requests are welcome on GitHub at https://github.com/ConvertAPI/convertapi-node. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. 173 | 174 | ## License 175 | 176 | ConvertAPI Node.js Client is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). 177 | -------------------------------------------------------------------------------- /examples/conversion_chaining.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | // set your api token 4 | var convertapi = require('../lib')(process.env.API_TOKEN); 5 | 6 | // Short example of conversions chaining, the PDF pages extracted and saved as separated JPGs and then ZIP'ed 7 | // https://www.convertapi.com/doc/chaining 8 | 9 | var dir = require('os').tmpdir(); 10 | 11 | console.log("Converting PDF to JPG and compressing result files with ZIP\n"); 12 | 13 | convertapi.convert('jpg', { File: './examples/files/test.pdf' }) 14 | .then(function(jpgResult) { 15 | return convertapi.convert('zip', { Files: jpgResult }); 16 | }) 17 | .then(function(zipResult) { 18 | return zipResult.saveFiles(dir); 19 | }) 20 | .then(function(files) { 21 | console.log("Files saved to\n" + files); 22 | }) 23 | .catch(function(e) { 24 | console.error(e.toString()); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/convert_base64_content.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | // set your api token 4 | var convertapi = require('../lib')(process.env.API_TOKEN); 5 | 6 | // Example of using buffer and stream to convert base64 encoded content to pdf 7 | // https://www.convertapi.com/png-to-pdf 8 | 9 | var dir = require('os').tmpdir(); 10 | var Readable = require('stream').Readable; 11 | 12 | var base64Content = "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"; 13 | 14 | // get buffer from base64 string 15 | var buffer = Buffer.from(base64Content, 'base64'); 16 | 17 | // get readble stream from buffer 18 | var stream = new Readable() 19 | stream.push(buffer); 20 | stream.push(null); 21 | 22 | // Upload stream to the API. When uploading stream, file name must be provided. 23 | var uploadResult = convertapi.upload(stream, 'test.png'); 24 | 25 | convertapi.convert('pdf', { File: uploadResult }) 26 | .then(function(result) { 27 | return result.saveFiles(dir); 28 | }) 29 | .then(function(files) { 30 | console.log("The PDF saved to\n" + files); 31 | }) 32 | .catch(function(e) { 33 | console.error(e.toString()); 34 | }); 35 | -------------------------------------------------------------------------------- /examples/convert_stream.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | var fs = require('fs'); 4 | 5 | // set your api token 6 | var convertapi = require('../lib')(process.env.API_TOKEN); 7 | 8 | // Example of using readable stream to convert to pdf 9 | // https://www.convertapi.com/docx-to-pdf 10 | 11 | var dir = require('os').tmpdir(); 12 | 13 | // get readble stream (could be any readable stream) 14 | var stream = fs.createReadStream('./examples/files/test.docx'); 15 | 16 | // Upload stream to the API. When uploading stream, file name must be provided. 17 | var uploadResult = convertapi.upload(stream, 'test.docx'); 18 | 19 | convertapi.convert('pdf', { File: uploadResult }) 20 | .then(function(result) { 21 | return result.saveFiles(dir); 22 | }) 23 | .then(function(files) { 24 | console.log("The PDF saved to\n" + files); 25 | }) 26 | .catch(function(e) { 27 | console.error(e.toString()); 28 | }); 29 | -------------------------------------------------------------------------------- /examples/convert_url_to_pdf.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | // set your api token 4 | var convertapi = require('../lib')(process.env.API_TOKEN); 5 | 6 | // Example of converting Web Page URL to PDF file 7 | // https://www.convertapi.com/web-to-pdf 8 | 9 | var dir = require('os').tmpdir(); 10 | var fromFormat = 'web'; 11 | var conversionTimeout = 180; 12 | 13 | var params = { 14 | Url: 'https://en.wikipedia.org/wiki/Data_conversion', 15 | FileName: 'web-example' 16 | }; 17 | 18 | convertapi.convert('pdf', params, fromFormat, conversionTimeout) 19 | .then(function(result) { 20 | return result.saveFiles(dir); 21 | }) 22 | .then(function(files) { 23 | console.log("The web page PDF saved to\n" + files); 24 | }) 25 | .catch(function(e) { 26 | console.error(e.toString()); 27 | }); 28 | -------------------------------------------------------------------------------- /examples/convert_word_to_pdf_and_png.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | // set your api token 4 | var convertapi = require('../lib')(process.env.API_TOKEN); 5 | 6 | // Example of saving Word docx to PDF and to PNG 7 | // https://www.convertapi.com/docx-to-pdf 8 | // https://www.convertapi.com/docx-to-png 9 | 10 | var dir = require('os').tmpdir(); 11 | 12 | // Upload to the API only once 13 | var upload = convertapi.upload('./examples/files/test.docx'); 14 | 15 | convertapi.convert('pdf', { File: upload }) 16 | .then(function(result) { 17 | return result.saveFiles(dir); 18 | }) 19 | .then(function(files) { 20 | console.log("The PDF saved to\n" + files); 21 | }) 22 | .catch(function(e) { 23 | console.error(e.toString()); 24 | }); 25 | 26 | // Reuse the same uploaded file 27 | convertapi.convert('png', { File: upload }) 28 | .then(function(result) { 29 | return result.saveFiles(dir); 30 | }) 31 | .then(function(files) { 32 | console.log("The PNG saved to\n" + files); 33 | }) 34 | .catch(function(e) { 35 | console.error(e.toString()); 36 | }); 37 | -------------------------------------------------------------------------------- /examples/create_pdf_thumbnail.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | // set your api token 4 | var convertapi = require('../lib')(process.env.API_TOKEN); 5 | 6 | // Example of extracting first page from PDF and then chaining conversion PDF page to JPG. 7 | // https://www.convertapi.com/pdf-to-extract 8 | // https://www.convertapi.com/pdf-to-jpg 9 | 10 | var dir = require('os').tmpdir(); 11 | 12 | var pdfResultPromise = convertapi.convert('extract', { 13 | File: './examples/files/test.pdf', 14 | PageRange: 1 15 | }); 16 | 17 | convertapi.convert('jpg', { 18 | File: pdfResultPromise, 19 | ScaleImage: true, 20 | ScaleProportions: true, 21 | ImageHeight: 300, 22 | ImageWidth: 300 23 | }) 24 | .then(function(jpgResult) { 25 | return jpgResult.saveFiles(dir); 26 | }) 27 | .then(function(files) { 28 | console.log("The thumbnail saved to\n" + files); 29 | }) 30 | .catch(function(e) { 31 | console.error(e.toString()); 32 | }); 33 | -------------------------------------------------------------------------------- /examples/files/test.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConvertAPI/convertapi-library-node/8b09eea893db29c13513c2bd404f1a9ee5461338/examples/files/test.docx -------------------------------------------------------------------------------- /examples/files/test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ConvertAPI/convertapi-library-node/8b09eea893db29c13513c2bd404f1a9ee5461338/examples/files/test.pdf -------------------------------------------------------------------------------- /examples/get_result_file_stream.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | // set your api token 4 | var convertapi = require('../lib')(process.env.API_TOKEN); 5 | 6 | // Example of converting Web Page URL to PDF and reading file data as string 7 | // https://www.convertapi.com/web-to-pdf 8 | 9 | var fromFormat = 'web'; 10 | var conversionTimeout = 180; 11 | var https = require('https'); 12 | var Stream = require('stream').Transform; 13 | var params = { 14 | Url: 'https://en.wikipedia.org/wiki/Data_conversion', 15 | FileName: 'web-example' 16 | }; 17 | 18 | convertapi.convert('pdf', params, fromFormat, conversionTimeout) 19 | .then(function(result) { 20 | result.files.forEach(function(resultFile) { 21 | console.log("Result url: " + resultFile.url); 22 | 23 | https.get(resultFile.url, function(response) { 24 | var stream = new Stream(); 25 | 26 | response.on('data', function(chunk) { 27 | stream.push(chunk); 28 | }); 29 | 30 | response.on('end', function() { 31 | var data = stream.read() 32 | 33 | console.log("Downloaded data size: " + data.length); 34 | }); 35 | }); 36 | }); 37 | }) 38 | .catch(function(e) { 39 | console.error(e.toString()); 40 | }); 41 | -------------------------------------------------------------------------------- /examples/index.js: -------------------------------------------------------------------------------- 1 | const conversion_chaining = require('./conversion_chaining'); 2 | const convert_url_to_pdf = require('./convert_url_to_pdf'); 3 | const convert_word_to_pdf_and_png = require('./convert_word_to_pdf_and_png'); 4 | const create_pdf_thumbnail = require('./create_pdf_thumbnail'); 5 | const convert_stream = require('./convert_stream'); 6 | const convert_base64_content = require('./convert_base64_content'); 7 | const get_result_file_stream = require('./get_result_file_stream'); 8 | const retrieve_user_information = require('./retrieve_user_information'); 9 | 10 | module.exports = { 11 | conversion_chaining, 12 | convert_url_to_pdf, 13 | convert_word_to_pdf_and_png, 14 | create_pdf_thumbnail, 15 | convert_stream, 16 | convert_base64_content, 17 | get_result_file_stream, 18 | retrieve_user_information 19 | }; 20 | -------------------------------------------------------------------------------- /examples/retrieve_user_information.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | // set your api token 4 | var convertapi = require('../lib')(process.env.API_TOKEN); 5 | 6 | // Retrieve user information 7 | // https://www.convertapi.com/doc/user 8 | 9 | convertapi.getUser() 10 | .then(function(info) { 11 | console.log("Name: " + info.FullName); 12 | }) 13 | .catch(function(e) { 14 | console.error(e.toString()); 15 | }); 16 | -------------------------------------------------------------------------------- /examples/split_and_merge_pdf.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | // set your api token 4 | var convertapi = require('../lib')(process.env.API_TOKEN); 5 | 6 | // Example of extracting first and last pages from PDF and then merging them back to new PDF. 7 | // https://www.convertapi.com/pdf-to-split 8 | // https://www.convertapi.com/pdf-to-merge 9 | 10 | var dir = require('os').tmpdir(); 11 | 12 | convertapi 13 | .convert('split', { 14 | File: './examples/files/test.pdf', 15 | }) 16 | .then(function (result) { 17 | var firstPage = result.files[0]; 18 | var lastPage = result.files[result.files.length - 1]; 19 | var files = [firstPage, lastPage]; 20 | 21 | return convertapi.convert('merge', { Files: files }); 22 | }) 23 | .then(function(result) { 24 | return result.saveFiles(dir); 25 | }) 26 | .then(function(files) { 27 | console.log("The PDF saved to " + files); 28 | }) 29 | .catch(function(e) { 30 | console.error(e.toString()); 31 | }); 32 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | export interface Options { 2 | conversionTimeout?: number; 3 | conversionTimeoutDelta?: number; 4 | uploadTimeout?: number; 5 | downloadTimeout?: number; 6 | proxy?: object; 7 | baseUri?: string; 8 | keepAlive?: boolean; 9 | } 10 | 11 | export interface ResultFile { 12 | readonly url: string; 13 | readonly fileName: string; 14 | readonly fileSize: number; 15 | save(filePath: string): Promise; 16 | } 17 | 18 | export interface Result { 19 | readonly response: object; 20 | readonly conversionCost: number; 21 | readonly jobId?: string; 22 | readonly file: ResultFile; 23 | readonly files: [ResultFile]; 24 | saveFiles(path: string): Promise<[string]>; 25 | } 26 | 27 | export interface UploadResult { 28 | readonly fileId: string; 29 | readonly fileName: string; 30 | readonly fileExt: string; 31 | toString(): string; 32 | } 33 | 34 | export interface Client { 35 | get(path: string, params?: any, timeout?: number): Promise; 36 | post(path: string, params: any, timeout?: number): Promise; 37 | download(url: string, path: string): Promise; 38 | upload(stream: string | NodeJS.ReadableStream, fileName: string): Promise; 39 | } 40 | 41 | export class ConvertAPI { 42 | client: Client; 43 | constructor (credentials: string, options?: Options); 44 | convert(toFormat: string, params: object, fromFormat?: string, conversionTimeout?: number): Promise; 45 | getUser(): Promise; 46 | upload(source: string | NodeJS.ReadableStream, fileName?: string): Promise; 47 | } 48 | 49 | export default ConvertAPI; 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "convertapi", 3 | "version": "1.15.0", 4 | "description": "Official convertapi.com API client", 5 | "main": "./lib/index.js", 6 | "types": "./index.d.ts", 7 | "scripts": { 8 | "clean": "rimraf lib", 9 | "test": "npm run lint && npm run cover", 10 | "test:prod": "cross-env BABEL_ENV=production npm run test", 11 | "test:only": "mocha --require babel-core/register --require babel-polyfill --recursive --timeout 15000", 12 | "test:watch": "npm test -- --watch", 13 | "test:examples": "node examples/", 14 | "cover": "istanbul cover _mocha -- --require babel-core/register --require babel-polyfill --recursive --timeout 15000", 15 | "lint": "eslint src test", 16 | "build": "cross-env BABEL_ENV=production babel src --out-dir lib", 17 | "prepublish": "npm run clean && npm run lint && npm run test && npm run build" 18 | }, 19 | "files": [ 20 | "lib", 21 | "src", 22 | "index.d.ts" 23 | ], 24 | "repository": { 25 | "type": "git", 26 | "url": "git+https://github.com/ConvertAPI/convertapi-node.git" 27 | }, 28 | "keywords": [ 29 | "convert", 30 | "api", 31 | "client", 32 | "sdk", 33 | "conversion", 34 | "convertapi", 35 | "files" 36 | ], 37 | "author": "Tomas Rutkauskas ", 38 | "license": "MIT", 39 | "bugs": { 40 | "url": "https://github.com/ConvertAPI/convertapi-node/issues" 41 | }, 42 | "homepage": "https://github.com/ConvertAPI/convertapi-node#readme", 43 | "dependencies": { 44 | "axios": "^1.6.2" 45 | }, 46 | "devDependencies": { 47 | "babel-cli": "^6.26.0", 48 | "babel-eslint": "^10.1.0", 49 | "babel-plugin-add-module-exports": "^0.2.1", 50 | "babel-polyfill": "^6.26.0", 51 | "babel-preset-env": "^1.6.1", 52 | "babel-preset-minify": "^0.4.3", 53 | "chai": "^4.1.2", 54 | "chai-as-promised": "^ 7.1.1", 55 | "chai-fs": "^2.0.0", 56 | "cross-env": "^5.1.3", 57 | "eslint": "^4.19.1", 58 | "eslint-config-airbnb": "~17.0.0", 59 | "eslint-plugin-import": "^2.7.0", 60 | "eslint-plugin-jsx-a11y": "^6.0.2", 61 | "eslint-plugin-react": "^7.4.0", 62 | "istanbul": "^1.0.0-alpha", 63 | "mocha": "^10.2.0", 64 | "rimraf": "^2.6.2" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/client.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import fs from 'fs'; 3 | import https from 'https'; 4 | import { buildQueryString, encodeFileName } from './utils'; 5 | import UploadResult from './upload_result'; 6 | import Error from './error'; 7 | 8 | export default class Client { 9 | constructor(api) { 10 | this.api = api; 11 | this.defaultHeader = { 12 | 'User-Agent': api.userAgent, 13 | 'Content-Type': 'application/x-www-form-urlencoded', 14 | Authorization: `Bearer ${api.credentials}`, 15 | Accept: 'application/json', 16 | }; 17 | this.httpsAgent = new https.Agent({ keepAlive: api.keepAlive }); 18 | } 19 | 20 | get(path, params = {}, timeout = null) { 21 | const options = this.buildOptions({ 22 | method: 'get', 23 | url: this.url(path), 24 | params, 25 | timeout: timeout * 1000, 26 | }); 27 | 28 | return axios(options) 29 | .then(response => response.data) 30 | .catch(error => Client.handleError(error)); 31 | } 32 | 33 | post(path, params, timeout = null) { 34 | const options = this.buildOptions({ 35 | method: 'post', 36 | url: this.url(path), 37 | data: buildQueryString(params), 38 | timeout: timeout * 1000, 39 | }); 40 | 41 | return axios(options) 42 | .then(response => response.data) 43 | .catch(error => Client.handleError(error)); 44 | } 45 | 46 | async download(url, path) { 47 | const options = this.buildOptions({ 48 | url, 49 | timeout: this.api.downloadTimeout * 1000, 50 | responseType: 'stream', 51 | }); 52 | 53 | const response = await axios(options) 54 | .catch(error => Client.handleError(error)); 55 | 56 | const writer = fs.createWriteStream(path); 57 | 58 | response.data.pipe(writer); 59 | 60 | return new Promise((resolve, reject) => { 61 | writer.on('finish', () => { 62 | resolve(path); 63 | }); 64 | 65 | writer.on('error', (error) => { 66 | reject(new Error(error)); 67 | }); 68 | 69 | response.data.on('error', (error) => { 70 | reject(new Error(error)); 71 | }); 72 | }); 73 | } 74 | 75 | upload(stream, fileName) { 76 | const encodedFileName = encodeFileName(fileName); 77 | 78 | const headers = Object.assign({ 79 | 'Content-Type': 'application/octet-stream', 80 | 'Content-Disposition': `attachment; filename*=UTF-8''${encodedFileName}` 81 | }, this.defaultHeader); 82 | 83 | const options = this.buildOptions({ 84 | method: 'post', 85 | url: this.url('upload'), 86 | headers, 87 | data: stream, 88 | timeout: this.api.uploadTimeout * 1000, 89 | }); 90 | 91 | return axios(options) 92 | .then(response => new UploadResult(response.data)) 93 | .catch(error => Client.handleError(error)); 94 | } 95 | 96 | url(path) { 97 | return `${this.api.baseUri}${path}`; 98 | } 99 | 100 | buildOptions(options) { 101 | return Object.assign({ 102 | headers: this.defaultHeader, 103 | maxContentLength: Infinity, 104 | maxBodyLength: Infinity, 105 | proxy: this.api.proxy, 106 | httpsAgent: this.httpsAgent, 107 | }, options); 108 | } 109 | 110 | static handleError(error) { 111 | let data; 112 | 113 | if (error.response && error.response.data) { 114 | ({ data } = error.response); 115 | } 116 | 117 | throw new Error(error, data); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/error.js: -------------------------------------------------------------------------------- 1 | export default class ClientError extends Error { 2 | constructor(error, data = null) { 3 | let message; 4 | 5 | if (data && data.Message) { 6 | message = `${data.Message} Code: ${data.Code}`; 7 | 8 | if (data.InvalidParameters) { 9 | message += ` ${JSON.stringify(data.InvalidParameters)}`; 10 | } 11 | } 12 | 13 | super(message || error.message); 14 | 15 | this.request = error.request; 16 | this.response = error.response; 17 | this.data = data; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import pkg from '../package.json'; 3 | import Task from './task'; 4 | import Client from './client'; 5 | import { getReadableStream, normalizeBaseUri } from './utils'; 6 | 7 | function ConvertAPI(credentials, options = {}) { 8 | if (!(this instanceof ConvertAPI)) { 9 | return new ConvertAPI(credentials, options); 10 | } 11 | 12 | this.credentials = credentials; 13 | this.baseUri = normalizeBaseUri(options.baseUri || 'https://v2.convertapi.com/'); 14 | this.conversionTimeout = options.conversionTimeout; 15 | this.conversionTimeoutDelta = options.conversionTimeoutDelta || 10; 16 | this.uploadTimeout = options.uploadTimeout || 1800; 17 | this.downloadTimeout = options.downloadTimeout || 1800; 18 | this.userAgent = `ConvertAPI-Node/${pkg.version}`; 19 | this.proxy = options.proxy; 20 | this.keepAlive = options.keepAlive !== undefined ? options.keepAlive : true; 21 | 22 | this.client = new Client(this); 23 | } 24 | 25 | async function convert(toFormat, params, fromFormat = null, conversionTimeout = null) { 26 | const task = new Task(this, fromFormat, toFormat, params, conversionTimeout); 27 | return task.run(); 28 | } 29 | 30 | async function getUser() { 31 | return this.client.get('user'); 32 | } 33 | 34 | async function upload(source, fileName = null) { 35 | const resolvedFileName = fileName || path.basename(source); 36 | const stream = getReadableStream(source); 37 | 38 | return this.client.upload(stream, resolvedFileName); 39 | } 40 | 41 | ConvertAPI.prototype = { convert, getUser, upload }; 42 | 43 | module.exports = ConvertAPI; 44 | 45 | // expose constructor as a named property to enable mocking with Sinon.JS 46 | module.exports.ConvertAPI = ConvertAPI; 47 | 48 | // Allow use with the TypeScript compiler without `esModuleInterop`. 49 | module.exports.default = ConvertAPI; 50 | -------------------------------------------------------------------------------- /src/result.js: -------------------------------------------------------------------------------- 1 | import ResultFile from './result_file'; 2 | 3 | export default class Result { 4 | constructor(api, response) { 5 | this.api = api; 6 | this.response = response; 7 | } 8 | 9 | get conversionCost() { 10 | return this.response.ConversionCost; 11 | } 12 | 13 | get jobId() { 14 | return this.response.JobId; 15 | } 16 | 17 | get file() { 18 | return this.files[0]; 19 | } 20 | 21 | get files() { 22 | const list = this.response.Files || []; 23 | return list.map(file => new ResultFile(this.api, file)); 24 | } 25 | 26 | async saveFiles(path) { 27 | const promises = this.files.map(file => file.save(path)); 28 | 29 | return Promise.all(promises); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/result_file.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | 4 | export default class ResultFile { 5 | constructor(api, fileInfo) { 6 | this.api = api; 7 | this.fileInfo = fileInfo; 8 | } 9 | 10 | get url() { 11 | return this.fileInfo.Url; 12 | } 13 | 14 | get fileName() { 15 | return this.fileInfo.FileName; 16 | } 17 | 18 | get fileSize() { 19 | return this.fileInfo.FileSize; 20 | } 21 | 22 | async save(filePath) { 23 | let downloadPath; 24 | 25 | if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) { 26 | downloadPath = filePath + path.sep + this.fileName; 27 | } else { 28 | downloadPath = filePath; 29 | } 30 | 31 | return this.api.client.download(this.url, downloadPath); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/task.js: -------------------------------------------------------------------------------- 1 | import { 2 | normalizeFilesParam, 3 | buildFileParam, 4 | detectFormat, 5 | } from './utils'; 6 | import Result from './result'; 7 | 8 | const Task = class { 9 | constructor(api, fromFormat, toFormat, params, conversionTimeout) { 10 | this.api = api; 11 | this.fromFormat = fromFormat; 12 | this.toFormat = toFormat; 13 | this.conversionTimeout = conversionTimeout || api.conversionTimeout; 14 | this.params = params; 15 | this.defaultParams = { StoreFile: true }; 16 | } 17 | 18 | async run() { 19 | let timeout; 20 | 21 | const params = await this.normalizeParams(this.params); 22 | 23 | if (this.conversionTimeout) { 24 | params.Timeout = this.conversionTimeout; 25 | timeout = this.conversionTimeout + this.api.conversionTimeoutDelta; 26 | } 27 | 28 | const fromFormat = this.fromFormat || detectFormat(params, this.toFormat); 29 | const path = `convert/${fromFormat}/to/${this.toFormat}`; 30 | const response = await this.api.client.post(path, params, timeout); 31 | 32 | return new Result(this.api, response); 33 | } 34 | 35 | async normalizeParams(params) { 36 | const result = Object.assign({}, params, this.defaultParams); 37 | const fileParams = Object.keys(params).filter(key => key.endsWith('File') && key !== 'StoreFile'); 38 | 39 | await Promise.all(fileParams.map(async (key) => { 40 | const file = await params[key]; 41 | result[key] = await buildFileParam(this.api, file); 42 | })); 43 | 44 | if (params.Files) { 45 | const files = await normalizeFilesParam(params.Files); 46 | const promises = files.map(file => buildFileParam(this.api, file)); 47 | result.Files = await Promise.all(promises); 48 | } 49 | 50 | return result; 51 | } 52 | }; 53 | 54 | export default Task; 55 | -------------------------------------------------------------------------------- /src/upload_result.js: -------------------------------------------------------------------------------- 1 | export default class UploadResult { 2 | constructor(result) { 3 | this.fileId = result.FileId; 4 | this.fileName = result.FileName; 5 | this.fileExt = result.FileExt; 6 | } 7 | 8 | toString() { 9 | return this.fileId; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import url from 'url'; 3 | import querystring from 'querystring'; 4 | import fs from 'fs'; 5 | import stream from 'stream'; 6 | import Result from './result'; 7 | import ResultFile from './result_file'; 8 | import UploadResult from './upload_result'; 9 | 10 | const URI_REGEXP = /^https?:/i; 11 | const DEFAULT_URL_FORMAT = 'url'; 12 | const ANY_FORMAT = 'any'; 13 | 14 | export const normalizeFilesParam = async (promise) => { 15 | const value = await promise; 16 | 17 | if (value instanceof Result) { 18 | return value.files; 19 | } 20 | 21 | return Promise.all(value); 22 | }; 23 | 24 | export const normalizeBaseUri = (baseUri) => { 25 | if (baseUri[baseUri.length - 1] !== '/') { 26 | return `${baseUri}/`; 27 | } 28 | 29 | return baseUri; 30 | }; 31 | 32 | export const buildFileParam = async (api, value) => { 33 | if (URI_REGEXP.test(value)) { 34 | return value; 35 | } 36 | 37 | if (value instanceof Result) { 38 | return value.file.url; 39 | } 40 | 41 | if (value instanceof ResultFile) { 42 | return value.url; 43 | } 44 | 45 | if (value instanceof UploadResult) { 46 | return value; 47 | } 48 | 49 | return api.upload(value); 50 | }; 51 | 52 | export const detectFormat = (params, toFormat) => { 53 | let resource; 54 | 55 | if (toFormat.toString().toLowerCase() === 'zip') { 56 | return ANY_FORMAT; 57 | } 58 | 59 | if (params.Url) { 60 | return DEFAULT_URL_FORMAT; 61 | } 62 | 63 | if (params.File) { 64 | resource = params.File; 65 | } else if (params.Files) { 66 | [resource] = params.Files; 67 | } 68 | 69 | if (resource instanceof ResultFile) { 70 | resource = resource.url; 71 | } 72 | 73 | if (resource instanceof UploadResult) { 74 | return resource.fileExt; 75 | } 76 | 77 | const { pathname } = url.parse(resource); 78 | 79 | return path.extname(pathname).substring(1); 80 | }; 81 | 82 | export const buildQueryString = (params) => { 83 | const result = {}; 84 | 85 | Object.keys(params).forEach((key) => { 86 | const val = params[key]; 87 | 88 | if (val instanceof Array) { 89 | val.forEach((v, i) => { 90 | result[`${key}[${i}]`] = v.toString(); 91 | }); 92 | } else { 93 | result[key] = val.toString(); 94 | } 95 | }); 96 | 97 | return querystring.stringify(result); 98 | }; 99 | 100 | export const getReadableStream = (source) => { 101 | if (source instanceof stream.Readable) { 102 | return source; 103 | } 104 | 105 | return fs.createReadStream(source); 106 | }; 107 | 108 | export const encodeFileName = (fileName) => { 109 | const str = encodeURIComponent(fileName); 110 | return str.replace(/[!'()*]/g, c => `%${c.charCodeAt(0).toString(16)}`); 111 | }; 112 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import chai from 'chai'; 3 | import ConvertAPI from '../src'; 4 | 5 | chai.use(require('chai-as-promised')); 6 | chai.use(require('chai-fs')); 7 | 8 | const expect = chai.expect; 9 | const api = new ConvertAPI(process.env.CONVERT_API_SECRET); 10 | 11 | describe('ConvertAPI', () => { 12 | it('should be accessible as function', () => { 13 | expect(ConvertAPI('test').credentials).to.equal('test'); 14 | }); 15 | 16 | it('should assign credentials', () => { 17 | const expectedVal = process.env.CONVERT_API_SECRET; 18 | expect(api.credentials).to.equal(expectedVal); 19 | }); 20 | 21 | it ('should upload file', () => { 22 | const file = './examples/files/test.pdf'; 23 | const result = api.upload(file); 24 | 25 | return expect(result).to.eventually.have.property('fileId'); 26 | }); 27 | 28 | it ('should upload stream', () => { 29 | const stream = fs.createReadStream('./examples/files/test.pdf'); 30 | const result = api.upload(stream, 'test.pdf'); 31 | 32 | return expect(result).to.eventually.have.property('fileId'); 33 | }); 34 | 35 | it ('should upload file with special characters in the name', () => { 36 | const file = './examples/files/test.pdf'; 37 | const result = api.upload(file, 'test(ok).pdf'); 38 | 39 | return expect(result).to.eventually.have.property('fileId'); 40 | }); 41 | 42 | it ('should convert file to pdf', async () => { 43 | const params = { File: './examples/files/test.docx' }; 44 | const result = await api.convert('pdf', params); 45 | 46 | expect(result.file.url).to.be.a('string'); 47 | 48 | const files = await result.saveFiles('/tmp'); 49 | 50 | expect(files[0]).to.be.a.file().and.not.empty; 51 | 52 | files.map(file => fs.unlinkSync(file)); 53 | 54 | // test saving multiple times 55 | const file1 = await result.files[0].save('/tmp'); 56 | expect(file1).to.be.a.file().and.not.empty; 57 | fs.unlinkSync(file1); 58 | 59 | const file2 = await result.files[0].save('/tmp/convertapi-node-test-' + process.hrtime().join('')); 60 | expect(file2).to.be.a.file().and.not.empty; 61 | fs.unlinkSync(file2); 62 | }); 63 | 64 | it ('should convert file to pdf with uploaded file', async () => { 65 | const upload = api.upload('./examples/files/test.docx'); 66 | const params = { File: upload }; 67 | const result = await api.convert('pdf', params); 68 | 69 | expect(result.file.url).to.be.a('string'); 70 | }); 71 | 72 | it ('should convert file url to pdf', async () => { 73 | const params = { File: 'https://cdn.convertapi.com/cara/testfiles/document.docx?test=1' }; 74 | const result = await api.convert('pdf', params); 75 | 76 | expect(result.file.url).to.be.a('string'); 77 | }); 78 | 79 | it('should convert url to pdf', async () => { 80 | const params = { Url: 'http://convertapi.com' }; 81 | const result = await api.convert('pdf', params, 'web'); 82 | 83 | expect(result.file.url).to.be.a('string'); 84 | }); 85 | 86 | it('should zip multiple files', async () => { 87 | const files = ['./examples/files/test.docx', './examples/files/test.pdf']; 88 | const params = { Files: files }; 89 | 90 | const result = await api.convert('zip', params); 91 | 92 | expect(result.file.url).to.be.a('string'); 93 | }); 94 | 95 | it('should perform chained conversion', async () => { 96 | const params1 = { File: './examples/files/test.docx' }; 97 | 98 | const result1Promise = api.convert('pdf', params1); 99 | 100 | const params2 = { Files: result1Promise }; 101 | 102 | const result2 = await api.convert('zip', params2); 103 | 104 | expect(result2.file.url).to.be.a('string'); 105 | }); 106 | 107 | it('should perform chained conversion with result files', async () => { 108 | const result = await api 109 | .convert('pdf', { File: './examples/files/test.docx' }) 110 | .then(pdfResult => api.convert('zip', { Files: pdfResult.files })); 111 | 112 | expect(result.file.url).to.be.a('string'); 113 | }); 114 | 115 | it('should compare files', async () => { 116 | const params = { 117 | File: './examples/files/test.docx', 118 | CompareFile: './examples/files/test.docx', 119 | }; 120 | 121 | const result = await api.convert('compare', params); 122 | 123 | expect(result.file.url).to.be.a('string'); 124 | }); 125 | 126 | it('should handle api errors', () => { 127 | const params = { Url: 'https://www.w3.org/TR/PNG/iso_8859-1.txt' }; 128 | 129 | const promise = api.convert('pdf', params, 'web', -10); 130 | 131 | expect(promise).to.be.rejectedWith(/Parameter validation error/); 132 | }); 133 | 134 | it('should handle client errors', () => { 135 | const fastApi = new ConvertAPI(process.env.CONVERT_API_SECRET, { uploadTimeout: 0.0001 }); 136 | 137 | const params = { File: './examples/files/test.docx' }; 138 | 139 | const promise = fastApi.convert('pdf', params); 140 | 141 | expect(promise).to.be.rejectedWith(/timeout/); 142 | }); 143 | 144 | it('fetches user info', () => { 145 | const result = api.getUser(); 146 | 147 | return expect(result).to.eventually.have.property('ConversionsConsumed'); 148 | }); 149 | }); 150 | --------------------------------------------------------------------------------