npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

pac-maker

v4.0.0

Published

Proxy Auto-Configuration (PAC) file generator & loader, support proxy Node's `fetch` with PAC

Downloads

133

Readme

pac-maker

npm package node-current Test codecov

Proxy Auto Configuration (PAC) file generator & maintenance tool.

Features:

Usage

PAC files

Pre-generated PAC files at /dist can be used to bypass GFW:

  • blacklist.pac forward GFW blocked hostnames to the proxy server, other hostnames will connect directly.
  • whitelist.pac forward all but China hostnames to the proxy server.

By default, the proxy is SOCKS5 localhost:2080, you can change the value to your proxy server address.

Performance:

| file | Load time (ms) | Memory usage (MB) | FindProxyForURL (μs/op) | |--------------------------------------------------------|----------------|-------------------|-------------------------| | blacklist.pac | 3.53 | 0.65 | 0.74 | | whitelist.pac | 35.72 | 6.06 | 1.77 | | gfwlist2pac | 4.22 | 0.20 | 3355.43 |

Install

This package is pure ESM, it cannot be require()'d from CommonJS.

npm install pac-maker

Generate PAC files

pac-maker loads config file from working directory, default is pac.config.js, it can be specified by --config=<path> .

config file should export a configuration object:

import { builtinList, gfwlist, ofArray } from "pac-maker";

export default {
    /**
     * Location of the generated PAC file, default is "proxy.pac".
     */
    path: "proxy.pac",

    /**
     * Fallback route when no rule matching in `sources`, default is "DIRECT".
     */
    fallback: "DIRECT",

    /**
     * Proxy source map, the key is a proxy sorting, value is an array of HostnameSource.
     * pac-maker will get hostnames from all sources and route them to the corresponding key.
     */
    sources: {
        "SOCKS5 localhost:2080": [
            gfwlist(),
            builtinList("default"),
            builtinList("forbidden"),
            ofArray(["google.com"]),
        ],
    },
};

There are some built-in sources in pac-maker:

  • gfwlist Fetch hostnames from gfwlist.

  • hostnameFile Read hostnames from a file, for hostname file example, see the list directory.

  • builtinList Read hostnames from a file in the list directory.

  • ofArray Just use an array of hostnames.

CLI commands

generate

Generate a PAC file:

pac-maker generate [--config=<path>] [--watch]
  • --watch After the initial build, pac-maker will continue to watch for updates in any of the sources.

analyze

Find what hosts will be proxied by the PAC in browser history, support Chrome, Firefox, and Edge:

pac-maker analyze [--config=<path>] [--json=<path>]
  • --json Save matched rules to this file, default is matches.json.

bench

Benchmark PAC files, show load time, memory usage, and FindProxyForURL performance.

pac-maker bench <path/to/file.pac> [morefiles...] [--host=example.com] [--loadCount=<number>] [--workCount=<number>]
  • --host The host parameter passed to FindProxyForURL, default is "www.google.com".
  • --iterations Time or the number of load iterations to platform, default is "1s".

serve

Serve the PAC file with http, and update when source have changes:

pac-maker serve [--config=<file>] [--host=<host>] [--port=<port>]
  • --host By default, the server will accept connections from all addresses, It is possible to listen to just one selected interface using the host parameter.

  • --port The port number that http server to listened on, default is 7568.

JavaScript API

pac-maker exports some useful functions that allows you to play with PAC inside your own JavaScript program.

PACDispatcher

The undici dispatcher that dispatch requests based on rule described by the PAC.

It is designed to be used with the built-in fetch function. To proxy the requests with the http module, we recommend to use node-pac-proxy-agent.

import { readFileSync } from "fs";
import { PACDispatcher } from "pac-maker";

const pac = readFileSync("proxy.pac", "utf8");
const dispatcher = new PACDispatcher(pac);

const response = await fetch("https://example.com", { dispatcher });

buildPAC

Create a PAC script from rules, use the built-in template template/default.js.

The function takes two parameters, first is a rules object which key is a proxy string , and value is a hostname array. the second parameter will be returned from FindProxyForURL if no hostname matched, default is DIRECT.

import { writeFileSync } from "fs";
import { buildPAC } from "pac-maker";

const rules = {
    "HTTP 192.168.0.1:80": ["foo.com", "bar.com"],
    "SOCKS5 localhost:1080": ["example.com"],
};

writeFileSync("proxy.pac", buildPAC(rules));

loadPAC

Load and execute a PAC script, return an object includes all global variables defined in the PAC.

import { readFileSync } from "fs";
import { loadPAC } from "pac-maker";

const pac = loadPAC(readFileSync("proxy.pac", "utf8"));

console.log(pac.FindProxyForURL("", "example.com"));

parseProxies

Parse the return value of FindProxyForURL().

import { parseProxies } from "pac-maker";

console.log(parseProxies("HTTP localhost:80; DIRECT"));

output:

[
  { protocol: "HTTP", host: "localhost:80", port: 80, hostname: "localhost" },
  { protocol: "DIRECT", host: "", port: NaN, hostname: "" }
]

HostBlockVerifier

A tool to check which hostnames are blocked by your ISP.

This class is only support HTTP protocol, it cannot be used for hosts running non-HTTP services.

import { HostBlockVerifier } from "pac-maker";

const hosts = ["google.com", "github.com" /* ... */];
const verifier = new HostBlockVerifier("SOCKS5 localhost:1080");
(await verifier.verifyAll(hosts)).print();

Test a single hostname and return block type:

const reason = await verifier.verify("google.com");
if (reason === "DNS") {
    console.log("DNS cache pollution");
} else if (reason === "TCP") {
    console.log("TCP blocking");
} else if (reason === "Unavailable") {
    console.log("Site may be down");
} else {
    console.log("The host is not blocked");
}

commands

All commands supported by pac-maker can also be called in JavaScript code.

import { commands } from "pac-maker";
import config from "./pac.config.js";

commands.serve({ host: "localhost", port: 12345 }, config);

Run Tests

To run unit tests, you need to enable experimental vm modules.

NODE_OPTIONS=--experimental-vm-modules
pnpm test