Skip to content
This repository has been archived by the owner on Mar 22, 2024. It is now read-only.

Commit

Permalink
move to typescript (#285)
Browse files Browse the repository at this point in the history
* move to typescript

* remove package-lock.json from .gitignore

* increase code coverage
  • Loading branch information
artiebits authored Oct 15, 2021
1 parent ccd3054 commit 8d86cd0
Show file tree
Hide file tree
Showing 23 changed files with 2,948 additions and 4,624 deletions.
5 changes: 3 additions & 2 deletions .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"node": "current"
}
}
]
],
"@babel/preset-typescript"
]
}
}
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ dist
.DS_Store
yarn.lock
.idea
package-lock.json
13 changes: 5 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,19 @@
A utility to print PDF files from Node.js and Electron.

- Supports label printers such as [Rollo](https://www.rolloprinter.com/) and [Zebra](https://www.zebra.com/us/en/products/printers.html).
- Works on Windows only.
- Works on Windows only.

If you are looking for a utility that will work on **Unix-like operating systems**, then take a look at https://github.com/artiebits/unix-print.

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

**Table of Contents**

- [Installation](#installation)
- [Basic Usage](#basic-usage)
- [API](#api)
- [`.print(pdf[, options]) => Promise<void>`](#printpdf-options--promisevoid)
- [`.getPrinters() => Promise<Printer[]>`](#getprinters--promiseprinter)
- [`.getDefaultPrinter() => Promise<Printer | null>`](#getdefaultprinter--promiseprinter--null)
- [Contact](#contact)
- [`.print(pdf[, options]) => Promise<void>`](#printpdf-options--promisevoid)
- [`.getPrinters() => Promise<Printer[]>`](#getprinters--promiseprinter)
- [`.getDefaultPrinter() => Promise<Printer | null>`](#getdefaultprinter--promiseprinter--null)
- [Sponsor this project](#sponsor-this-project)
- [License](#license)

Expand Down
7,291 changes: 2,789 additions & 4,502 deletions package-lock.json

Large diffs are not rendered by default.

16 changes: 11 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"url": "https://github.com/artiebits/pdf-to-printer.git"
},
"main": "dist/bundle.js",
"types": "dist/types.d.ts",
"types": "dist/**/*.d.ts",
"files": [
"dist"
],
Expand All @@ -33,15 +33,21 @@
"@babel/cli": "7.12.1",
"@babel/core": "7.12.3",
"@babel/preset-env": "7.10.4",
"babel-jest": "26.5.2",
"@babel/preset-typescript": "^7.15.0",
"@types/jest": "^27.0.2",
"@types/node": "^16.11.0",
"babel-jest": "^27.2.5",
"clean-webpack-plugin": "3.0.0",
"copy-webpack-plugin": "^5.1.2",
"husky": "^4.3.0",
"jest": "26.5.3",
"jest": "^27.2.5",
"lint-staged": "^10.4.2",
"prettier": "2.1.2",
"webpack": "4.43.0",
"webpack-cli": "3.3.12"
"ts-jest": "^27.0.6",
"ts-loader": "^9.2.6",
"typescript": "^4.4.4",
"webpack": "^5.58.2",
"webpack-cli": "^4.9.0"
},
"keywords": [
"pdf",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import execAsync from "../utils/exec-file-async";
import { mocked } from "ts-jest/utils";
import getDefaultPrinter from "./get-default-printer";
import execAsync from "../utils/exec-file-async";

jest.mock("../utils/exec-file-async");
const mockedExecAsync = mocked(execAsync);

const mockDefaultPrinterStdout = `
Expand All @@ -18,9 +20,10 @@ CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemPrope
`;

it("gets the default printer", async () => {
execAsync.mockImplementation(() =>
Promise.resolve({ stdout: mockDefaultPrinterStdout })
);
mockedExecAsync.mockResolvedValue({
stdout: mockDefaultPrinterStdout,
stderr: "",
});

const result = await getDefaultPrinter();

Expand All @@ -30,8 +33,8 @@ it("gets the default printer", async () => {
});
});

test("no default printer defined", async () => {
execAsync.mockImplementation(() => Promise.resolve({ stdout: "" }));
it("returns null when default printer is not defined", async () => {
mockedExecAsync.mockResolvedValue({ stdout: "", stderr: "" });

const result = await getDefaultPrinter();

Expand All @@ -47,14 +50,14 @@ it("when did not find any printer info", async () => {
Availability :
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties
`;
execAsync.mockImplementation(() => Promise.resolve({ stdout }));
mockedExecAsync.mockResolvedValue({ stdout, stderr: "" });

const result = await getDefaultPrinter();

return expect(result).toBe(null);
});

it("fails with an error", () => {
execAsync.mockImplementation(() => Promise.reject("error"));
it("throws when execAsync fails", () => {
mockedExecAsync.mockRejectedValue("error");
return expect(getDefaultPrinter()).rejects.toBe("error");
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
"use strict";
import execFileAsync from "../utils/exec-file-async";
import isValidPrinter from "../utils/windows-printer-valid";

const execFileAsync = require("../utils/exec-file-async");
const isValidPrinter = require("../utils/windows-printer-valid");
export interface Printer {
deviceId: string;
name: string;
}

async function getDefaultPrinter() {
async function getDefaultPrinter(): Promise<Printer | null> {
try {
const { stdout } = await execFileAsync("Powershell.exe", [
"-Command",
Expand All @@ -26,4 +29,4 @@ async function getDefaultPrinter() {
}
}

module.exports = getDefaultPrinter;
export default getDefaultPrinter;
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { mocked } from "ts-jest/utils";
import execAsync from "../utils/exec-file-async";
import getPrinters from "./get-printers";

jest.mock("../utils/exec-file-async");
const mockedExecAsync = mocked(execAsync);

afterEach(() => {
// restore the original implementation
execAsync.mockRestore();
mockedExecAsync.mockRestore();
});

const mockPrinterListStdout = `
Expand Down Expand Up @@ -58,9 +60,10 @@ CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemPrope
`;

it("returns list of available printers", async () => {
execAsync.mockImplementation(() =>
Promise.resolve({ stdout: mockPrinterListStdout })
);
mockedExecAsync.mockResolvedValue({
stdout: mockPrinterListStdout,
stderr: "",
});

const result = await getPrinters();

Expand Down Expand Up @@ -90,14 +93,14 @@ it("when did not find any printer info", async () => {
Availability :
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties
`;
execAsync.mockImplementation(() => Promise.resolve({ stdout }));
mockedExecAsync.mockResolvedValue({ stdout, stderr: "" });

const result = await getPrinters();

return expect(result).toEqual([]);
});

it("fails with an error", () => {
execAsync.mockImplementation(() => Promise.reject("error"));
mockedExecAsync.mockRejectedValue("error");
return expect(getPrinters()).rejects.toBe("error");
});
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
"use strict";
import execFileAsync from "../utils/exec-file-async";
import isValidPrinter from "../utils/windows-printer-valid";
import { Printer } from "../get-default-printer/get-default-printer";

const execFileAsync = require("../utils/exec-file-async");
const isValidPrinter = require("../utils/windows-printer-valid");

async function getPrinters() {
function stdoutHandler(stdout) {
const printers = [];
async function getPrinters(): Promise<Printer[]> {
function stdoutHandler(stdout: string) {
const printers: Printer[] = [];

stdout
.split(/(\r?\n){2,}/)
Expand Down Expand Up @@ -33,4 +32,4 @@ async function getPrinters() {
}
}

module.exports = getPrinters;
export default getPrinters;
13 changes: 0 additions & 13 deletions src/index.js

This file was deleted.

File renamed without changes.
8 changes: 8 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export { default as print } from "./print/print";
export { default as getPrinters } from "./get-printers/get-printers";
export { default as getDefaultPrinter } from "./get-default-printer/get-default-printer";
import os from "os";

if (os.platform() !== "win32") {
throw new Error("Platform not supported");
}
34 changes: 23 additions & 11 deletions src/print/print.test.js → src/print/print.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use strict";

import { existsSync } from "fs";
import { join } from "path";
import { mocked } from "ts-jest/utils";
import execAsync from "../utils/exec-file-async";
import fixPathForAsarUnpack from "../utils/electron-util";
import print from "./print";
Expand All @@ -11,32 +10,39 @@ jest.mock("path");
jest.mock("../utils/exec-file-async");
jest.mock("../utils/electron-util");

const mockedFixPathForAsarUnpack = mocked(fixPathForAsarUnpack);
const mockedExistsSync = mocked(existsSync);
const mockedExecAsync = mocked(execAsync);
const mockedJoin = mocked(join);

beforeEach(() => {
// override the implementations
fixPathForAsarUnpack.mockImplementation((path) => path);
existsSync.mockImplementation(() => true);
execAsync.mockImplementation(() => Promise.resolve());
join.mockImplementation((_, filename) => "mocked_path_" + filename);
mockedFixPathForAsarUnpack.mockImplementation((path) => path);
mockedExistsSync.mockImplementation(() => true);
mockedExecAsync.mockResolvedValue({ stdout: "", stderr: "" });
mockedJoin.mockImplementation((_, filename) => "mocked_path_" + filename);
});

afterEach(() => {
// restore the original implementations
fixPathForAsarUnpack.mockRestore();
existsSync.mockRestore();
execAsync.mockRestore();
join.mockRestore();
mockedFixPathForAsarUnpack.mockRestore();
mockedExistsSync.mockRestore();
mockedExecAsync.mockRestore();
mockedJoin.mockRestore();
});

it("throws when no file is specified.", async () => {
// @ts-ignore
await expect(print()).rejects.toMatch("No PDF specified");
});

test("throws when path to the file is invalid", async () => {
// @ts-ignore
await expect(print(123)).rejects.toMatch("Invalid PDF name");
});

it("throws when file not found", async () => {
existsSync.mockImplementation(() => false);
mockedExistsSync.mockImplementation(() => false);

await expect(print("file.txt")).rejects.toMatch("No such file");
});
Expand Down Expand Up @@ -149,6 +155,7 @@ it("ignores the passed printer when -print-dialog is set", async () => {
it("throws when options passed not as an array.", async () => {
const filename = "assets/pdf-sample.pdf";
const options = { win32: '-print-settings "fit"' };
// @ts-ignore
await expect(print(filename, options)).rejects.toMatch(
"options.win32 should be an array"
);
Expand All @@ -166,3 +173,8 @@ it("works when custom SumatraPDF path specified", async () => {
filename,
]);
});

it("fails with an error", () => {
mockedExecAsync.mockRejectedValue("error");
return expect(print("pdf-sample.pdf")).rejects.toBe("error");
});
25 changes: 15 additions & 10 deletions src/print/print.js → src/print/print.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
"use strict";
import path from "path";
import fs from "fs";
import splitArgs from "../utils/split-args";
import execAsync from "../utils/exec-file-async";
import fixPathForAsarUnpack from "../utils/electron-util";

const path = require("path");
const fs = require("fs");
const splitArgs = require("../utils/split-args");
const execAsync = require("../utils/exec-file-async");
const fixPathForAsarUnpack = require("../utils/electron-util");
export interface PrintOptions {
printer?: string;
win32?: string[];
sumatraPdfPath?: string;
}

const validDestinationArgs = [
"-print-to",
"-print-to-default",
"-print-dialog",
];

async function print(pdf, options = {}) {
export default async function print(
pdf: string,
options: PrintOptions = {}
): Promise<void> {
if (!pdf) throw "No PDF specified";
if (typeof pdf !== "string") throw "Invalid PDF name";
if (!fs.existsSync(pdf)) throw "No such file";
Expand All @@ -21,7 +28,7 @@ async function print(pdf, options = {}) {
options.sumatraPdfPath || path.join(__dirname, "SumatraPDF.exe");
if (!options.sumatraPdfPath) sumatraPdf = fixPathForAsarUnpack(sumatraPdf);

const args = [];
const args: string[] = [];

const { printer, win32 } = options;

Expand Down Expand Up @@ -61,5 +68,3 @@ async function print(pdf, options = {}) {
throw error;
}
}

module.exports = print;
16 changes: 0 additions & 16 deletions src/types.d.ts

This file was deleted.

Loading

0 comments on commit 8d86cd0

Please sign in to comment.