📑 Simple yet powerful JavaScript library that generates PDF invoice, estimates & payment receipts from a JSON data. It can be used in any Node JS/Bun JS environment.
Installation
via npm:
npm install @h1dd3nsn1p3r/pdf-invoice
via yarn:
yarn add @h1dd3nsn1p3r/pdf-invoice
via pnpm:
pnpm add @h1dd3nsn1p3r/pdf-invoice
Use
Once installed, you can import either using require
or import
:
const { PDFInvoice } = require('@h1dd3nsn1p3r/pdf-invoice');
or ES6 import:
import { PDFInvoice } from '@h1dd3nsn1p3r/pdf-invoice';
PDFInvoice
is a class that takes the payload as an argument. The payload is the data that you want to show on the invoice. For more information check the Payload data example.
Payload Data
The payload is the data that you want to show on the invoice. It is an object with the following structure:
const payload = {
company: {
logo: "<svg>...</svg>",
name: "Festrol Corp.",
address: "1711 W. El Segundo Blvd, Hawthorne, Canada - 90250",
phone: "Tel: (+11) 245 543 903",
email: "Mail: hello@festrol.io",
website: "Web: https://www.festrolcorp.io",
taxId: "Tax ID: 1234567890",
},
customer: {
name: "John Doe",
company: "Xero Inc.",
address: "1234 Main Street, New York, NY 10001",
phone: "Tel: (555) 555-5555",
email: "Mail: joe@example.com",
taxId: "Tax ID: 1234567890",
},
invoice: {
number: 1721,
date: "25/12/2023",
dueDate: "25/12/2023",
status: "Paid!",
currency: "€",
path: "./invoice.pdf",
},
items: [
{
name: "Cloud VPS Server - Starter Plan",
quantity: 1,
price: 400,
tax: 0,
},
{
name: "Domain Registration - example.com",
quantity: 1,
price: 20,
tax: 0,
},
{
name: "Maintenance Charge - Yearly",
quantity: 1,
price: 300,
tax: 0,
},
],
qr: {
data: "https://www.festrolcorp.io",
width: 100,
},
note: {
text: "Thank you for your business.",
italic: false,
}
};
Note: If the string is long, then you can use \n
to break the line. For example:
const payload = {
company: {
name: "Festrol Corp.",
address: "1711 W. El Segundo Blvd, Hawthorne, \n Canada - 90250",
phone: "Tel: (+11) 245 543 903",
email: "Mail: email@yourcompany.com"
},
};
Let's understand each of the fields in the payload.
Company
This is the information about your company. It is an object with the following structure:
const company = {
logo: "<svg>...</svg>",
name: "Festrol Corp.",
address: "1711 W. El Segundo Blvd, Hawthorne, \n Canada - 90250",
phone: "Tel: (+11) 245 543 903",
email: "hello@company.com",
website: "Web: https://www.festrolcorp.io"
taxId: "Tax ID: 1234567890",
}
For now, only svg logo can be used. If you wish to use logo & do not want the company name, then do not pass the name
field. Rest of the fields are optional.
### Invoice
This is the information about the invoice. It is an object with the following structure:
```js
const invoice = {
number: 1721, // Required.
date: "25/12/2023", // Optional. Default is current date.
dueDate: "25/12/2023", // Optional. Default is current date.
status: "Paid!", // Optional. Default is "Due pending!".
currency: "€", // Optional. Default is "$".
}
The invoice number is required. It might be a integer
that you use to track your invoices. In most cases, it is a unique number that reference the order ID
or invoice sequence number in your database. Rest of the fields are optional.
If path is supplied in the payload, then the PDF will be generated at that location. For example:
const file = "invoice" + "-#" + 1729 + "-" + new Date().getTime();
const location = path.join(__dirname, "/invoices/" + file + ".pdf");
const invoice = {
path: location,
}
If path is not supplied in the payload, then the PDF will be generated in current working directory with the name invoice.pdf
.
Customer
This is the information about your customer. It is an object with the following structure:
const customer = {
name: "John Doe",
company: "Xero Inc.",
address: "1234 Main Street, New York, \n NY 10001",
phone: "Tel: (555) 555-5555",
email: "joedeo@example.com",
taxId: "Tax ID: 1234567890",
}
The name of the customer is required. Rest of the fields are optional.
Items
Items are the products or services that you are selling. It is an array
of objects with the following structure:
const items = [
{
name: "Cloud VPS Server - Starter Plan",
quantity: 1,
price: 400,
tax: 0,
},
{
name: "Domain Registration - example.com",
quantity: 1,
price: 20,
tax: 0,
},
{
name: "Maintenance Charge - Yearly",
quantity: 1,
price: 300,
tax: 0,
},
];
The name
, quantity
and price
of the item is required. Rest of the fields are optional. Although if you have single item in the invoice, you need to pass it as an object. For example:
const items = [
{
name: "Cloud VPS Server - Starter Plan",
quantity: 1,
price: 400,
tax: 0,
},
];
QR Code
If you want to add a QR code to the invoice, then you can use this field. It is an object with the following structure:
const qr = {
data: "https://www.festrolcorp.io/",
width: "100",
}
The data
field is required. It is the data that you want to encode in the QR code. The width
field is optional. It is the width of the QR code in pixels. Default is 50
. The recommended width of QR is 30 - 100.
Note
Use this field if you want to add a note to the invoice. It is an string with the following structure:
const note = "Thank you for your business.";
Generate PDF
Once you have the payload ready, you can generate the PDF using the following code:
const { PDFInvoice } = require('@h1dd3nsn1p3r/pdf-invoice');
const handleInvoice = async(): Promise<void> => {
const payload = {
};
const invoice = new PDFInvoice(payload);
const pdf = await invoice.create();
console.log(pdf);
}
handleInvoice();
Once you call the create
method, it will return a promise. You can either use async/await
or .then()
to handle the promise. The create
method will return the path to the PDF file if the PDF is generated successfully. Otherwise, it will throw an error.
Configuration
If required you can change the configuration of the invoice. It is an object with the following structure:
const { PDFInvoice } = require('@h1dd3nsn1p3r/pdf-invoice');
const create = async(): Promise<void> => {
const payload = {
};
const config = {
string: {
invoice: "F A C T U A",
refNumber: "Referencia",
date: "Fecha",
dueDate: "Fecha de vencimiento",
status: "Estado",
billTo: "Facturar a",
item: "Artículo",
quantity: "Cantidad",
price: "Precio",
tax: "Impuesto",
total: "Total",
subTotal: "Subtotal",
totalTax: "Total Impuesto",
},
};
const invoice = new PDFInvoice(payload, config);
const pdf = await invoice.create();
console.log(pdf);
}
Config limitations:
For now only latin
characters are supported. It seems like a limitation of Helvetica
font. I'll be adding support for other languages soon.
Types
This library is written in TypeScript. If you need to import the types, then you can import them from global.d.ts
file. Refer to Global types file for more information.
Import example:
import type { CompanyInfo, CustomerInfo, InvoiceInfo, ItemInfo, QRInfo, InvoicePayLoad } from '@h1dd3nsn1p3r/pdf-invoice/global.d.ts';
Changelog:
Refer to releases section for more information.
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Todo