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 🙏

© 2026 – Pkg Stats / Ryan Hefner

viacomm

v1.1.8

Published

Thin layer over the fetch API, with built-in support for Vue 3.

Readme

ViaComm

Simple Fetch Wrapper with Vue 3 Plugin Support

ViaComm is a small wrapper around the browser's fetch API. It provides:

  • Shared defaults for all requests
  • Automatic URL and query-string handling
  • Separate request data handling for GET/HEAD and other methods
  • Convenient JSON requests
  • Dynamic request and header values
  • Consistent errors for unsuccessful HTTP responses
  • Optional Vue 3 plugin support through the $comm global property

Installation

Install ViaComm from npm:

npm install viacomm

ViaComm is intended for browser environments and requires the Fetch API, URL, URLSearchParams, Headers, and structuredClone.

Basic Usage

The package exports a configured comm singleton as its default export:

import comm from "viacomm";

const response = await comm.request({
    url: "/api/users",
});

const users = await response.json();

You can also import the named singleton:

import {comm} from "viacomm";

Every request returns a Promise<Response>, so the response can be handled using the standard Fetch API methods such as json(), text(), blob(), or arrayBuffer().

The Comm Class

The Comm class is the main request client. A new instance can be created when an application needs an independent set of defaults:

import {Comm} from "viacomm";

const api = new Comm();

const response = await api.request({
    url: "/api/status",
});

The package's default singleton is suitable for most applications.

Default Request Options

A new Comm instance starts with these defaults:

{
    cache: "default",
    credentials: "same-origin",
    keepalive: false,
    method: "GET",
    redirect: "follow",
    referrer: "client",
    referrerPolicy: "no-referrer-when-downgrade"
}

These values are passed to fetch unless overridden for an individual request.

Configuring Defaults

Use configure() to add or replace defaults for every request:

import comm from "viacomm";

comm.configure({
    headers: {
        "X-Client": "my-app"
    },
    credentials: "include"
});

Configuration is merged into the existing defaults. Calling configure() with a falsey value resets the defaults to their original values:

comm.configure(false);

Request-specific options take precedence over configured defaults.

Making Requests

request(options)

request() is an asynchronous method that returns a Promise<Response>. It accepts Fetch options plus the following ViaComm-specific options:

| Option | Type | Description | | --- | --- | --- | | url | string or URL | Required request URL. Relative URLs use window.location.origin. | | data | object or string | Query data for GET/HEAD, or request body data for other methods. | | headers | object or Function | Headers for this request. | | method | string | HTTP method, such as GET, POST, PUT, or DELETE. | | body | any | Standard Fetch request body. data takes precedence for non-GET/HEAD requests. |

Always await the returned promise or handle it with .then():

const response = await comm.request({
    url: "/api/products"
});

A relative URL:

const response = await comm.request({
    url: "/api/products"
});

To resolve a relative URL against an API host, provide baseURL:

const response = await comm.request({
    baseURL: "https://api.example.com/v1/",
    url: "/products"
});

The resulting request is sent to https://api.example.com/products. baseURL only affects relative URLs; an absolute url remains unchanged:

const response = await comm.request({
    baseURL: "https://api.example.com/v1/",
    url: "https://uploads.example.com/image.png"
});

To use the full baseURL with a relative URL, don't lead with a slash:

const response = await comm.request({
    baseURL: "https://api.example.com/v1/",
    url: "products"
});

The resulting request is sent to https://api.example.com/v1/products.

An absolute URL:

const response = await comm.request({
    url: "https://example.com/api/products"
});

Query Parameters

For GET and HEAD requests, data is added to the URL as query parameters. Existing query parameters are preserved, and matching values in data override them.

Values that are null or undefined are ignored:

const response = await comm.request({
    url: "/api/products?sort=name",
    data: {
        page: 2,
        limit: 25,
        discontinued: null
    }
});

This produces a request similar to:

/api/products?sort=name&page=2&limit=25

Request Bodies

For methods other than GET and HEAD, data is assigned to the Fetch request body:

    const response = await comm.request({
    url: "/api/products",
    method: "POST",
    data: "product data"
    });

For JSON payloads, use json() instead.

HTTP Verb Shortcuts

delete(), get(), head(), patch(), post(), put(), and options() are asynchronous convenience methods. Each returns a Promise<Response>, so calls should be awaited or handled as promises.

GET and HEAD shortcuts use query parameters and do not use JSON handling by default.

All other shortcuts send data as JSON by default.

const response = await comm.post("/api/products", {
    data: {
        name: "Example product"
    }
});

To send a non-JSON request, pass false as the second argument:

const response = await comm.post({
    url: "/api/products",
    data: "product data"
}, false);

JSON Requests

json(options)

json() is an asychronous convenience method that returns a Promise<Response> for requests that send JSON. It:

  • Sets the Accept header to application/json, text/plain, */*
  • Sets the Content-Type header to application/json
  • Serializes non-string data with JSON.stringify()
  • Delegates to request()
const response = await comm.json({
    url: "/api/products",
    method: "POST",
    data: {
        name: "Example product",
        price: 19.99
    }
});

const product = await response.json();

You can still provide additional headers:

await comm.json({
    url: "/api/products",
    method: "POST",
    headers: {
        Authorization: "Bearer token"
    },
    data: {
        name: "Example product"
    }
});

The JSON headers supplied by json() take precedence over matching headers supplied in the request options.

Dynamic Options and Headers

Option values may be functions. ViaComm evaluates them immediately before sending the request, passing the current request options:

comm.configure({
    headers: {
        Authorization: (url, data, options) =>
        `Bearer ${getAccessToken()}`
    }
});

Headers may also be functions that receive the resolved URL, request data, and request options:

await comm.request({
    url: "/api/account",
    headers: (url, data, options) => ({
        "X-Request-Method": options.method
    })
});

Individual header values can be functions as well:

await comm.request({
    url: "/api/account",
    headers: {
        "X-Request-ID": () => crypto.randomUUID()
    }
});

Request-specific headers are merged with configured headers rather than replacing them entirely.

Error Handling

When fetch() receives an unsuccessful HTTP response, ViaComm rejects the promise with a CommError. The original Response is available through the error's response property:

import {CommError} from "viacomm";

try {
    const response = await comm.request({
        url: "/api/products/does-not-exist"
    });
} catch (error) {
    if (error instanceof CommError) {
        console.error(error.message);
        console.error(error.response.status);
    } else {
        // Network and other non-HTTP errors are handled normally.
        console.error(error);
    }
}

A missing url causes the returned promise to reject:

try {
    await comm.request({});
} catch (error) {
    // Error: You must define a 'url' to make the request against.
}

The same behavior applies to json() and all HTTP verb shortcuts.

Request Hooks

Hooks allow code to run before a request is sent or after a response is received. Hooks may be registered on an individual Comm instance or on the shared comm singleton.

Before Hooks

Use before() to register a function that runs immediately before fetch():

const hookId = comm.before(async (url, data, options) => {
    options.headers.set("X-Request-Started", new Date().toISOString());
});

Before hooks receive:

  1. The resolved request URL as a URL instance
  2. The request data
  3. The resolved request options object

Hooks are awaited before the request is sent, so asynchronous work can be performed before fetch() runs.

After Hooks

Use after() to register a function that runs after fetch() resolves:

const hookId = comm.after(async (url, data, options, response) => {
    // Because we receive a clone of the response,
    // we can safely drain it and read its body without affecting the original.
    const requestLog = await response.json();
    console.log(`${options.method} ${url} returned ${response.status}`);
    console.log("Request log:", requestLog);

    return response;
});

After hooks may be synchronous or asynchronous. If an after hook returns a promise, ViaComm waits for that promise to resolve before continuing the request pipeline.

After hooks receive the same URL, data, and options arguments, followed by a clone of the response. The cloned response allows the hook to inspect or modify its copy without changing the response used by the request pipeline.

An after hook should return the response, or a promise that resolves to the response, that should continue through the request pipeline. If the response is unsuccessful, the returned promise rejects with a CommError after the hook has run.

Using hook() Directly

hook() can be used when the hook phase should be selected dynamically. Hooks run before requests by default; pass false as the second argument to register an after hook:

const beforeId = comm.hook((url, data, options) => {
    console.log("Sending request:", url.toString());
});

const afterId = comm.hook(async (url, data, options, response) => {
    await auditResponse(response);
    console.log("Received response:", response.status);
    return response;
}, false);

Each registration method returns a unique hook ID:

  • hook(func) and hook(func, pre) return the registered hook ID.
  • before(func) returns the registered before-hook ID.
  • after(func) returns the registered after-hook ID.

Removing Hooks

Pass a hook ID to unhook() to remove that hook:

const hookId = comm.before(() => {
    console.log("This runs before requests");
});

comm.unhook(hookId);

Pass false to remove all registered hooks from the client:

comm.unhook(false);

Hooks are registered independently for each Comm instance. Removing hooks from a newly created client does not affect hooks registered on the shared singleton, and vice versa.

Using ViaComm with Vue 3

ViaComm can be installed as a Vue 3 plugin. Installation exposes the shared singleton as $comm on every component.

Plugin Installation

Create a Vue plugin wrapper, for example plugins/comm.js:

import {comm, install} from "viacomm";

// Configure the shared singleton here if needed.
comm.configure({
    headers: {
        "X-Client": "my-vue-app"
    }
});

export default install;

Register the plugin in the application's entry point:

import {createApp} from "vue";
import App from "./App.vue";
import comm from "./plugins/comm";

const app = createApp(App);

app.use(comm);
app.mount("#app");

You can also install ViaComm directly:

import {createApp} from "vue";
import {install as comm} from "viacomm";
import App from "./App.vue";

const app = createApp(App);

app.use(comm);
app.mount("#app");

The plugin is safe to install more than once; repeated installation attempts are ignored.

Options API

After installation, use this.$comm inside Options API components:

<template>
<button @click="loadUsers">Load users</button>
</template>

<script>
export default {
    methods: {
        async loadUsers() {
            const response = await this.$comm.request({
                url: "/api/users"
            });

            this.users = await response.json();
        }
    },

    data() {
        return {
            users: []
        };
    }
};
</script>

Composition API

With the Composition API, import the singleton directly:

<script setup>
import {ref} from "vue";
import {comm} from "viacomm";

const users = ref([]);

async function loadUsers() {
    const response = await comm.request({
        url: "/api/users"
    });

    users.value = await response.json();
}
</script>

<template>
    <button @click="loadUsers">Load users</button>
    <pre>{{ users }}</pre>
</template>

Import Options

The standard package import is:

import comm, {Comm, CommError, install} from "viacomm";

The standard build expects lodash-es to be available as a peer dependency. A full build is also available, which includes the required lodash functionality:

import comm from "viacomm/dist/viacomm.full.js";

Minified builds are available at:

viacomm/dist/viacomm.min.js
viacomm/dist/viacomm.full.min.js

Vue is an optional peer dependency, so ViaComm can be used without Vue. The Vue plugin is only needed when installing ViaComm with app.use().

Browser Support

ViaComm uses browser APIs provided by the Fetch API, including:

  • fetch
  • URL
  • URLSearchParams
  • Headers
  • window.location.origin

Use an appropriate polyfill or compatible environment when targeting browsers that do not provide these APIs.

License

The LICENSE.txt file contains the license details. ViaComm is licensed under the Mozilla Public License, Version 2.0.