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

adapter

v1.0.0-beta.10

Published

A TypeScript utility for writing I/O agnostic programs

Downloads

1,268

Readme

🔌 adapter

npm version github actions min size conventional commits

write I/O agnostic utilities

What is it?

adapter is a tiny TypeScript helper for writing I/O agnostic utilities in a standardized way. Your code could run in a headless process, an interactive commandline tool, or in a graphical program, but either way your code remains the same.

The idea is difficult to appreciate without an example. If you're comfortable with writing your own Promises and async/await patterns, the following example should be fairly intuitive.

Example

Let's say that you have some code that creates a remote repository via the GitHub API. It might look roughly like this:

import axios from 'axios';    // http library

const url = 'https://api.github.com/user/repos';
const headers = { Authorization: 'token <access-token>' };
const data = { name: '<repo-name>', private: true };

await axios.post(url, data, {headers});

adapter can be used to improve this code by injecting (or "plugging in") the means of handling I/O (input/output), just as Promises inject the means of handling success/failure (resolve/reject). Let's rewrite the above code leveraging these injections:

// github-service.ts

import axios, {AxiosResponse} from 'axios';
import {makeAdapter} from 'adapter';

type Resolve = AxiosResponse;
type Input = {
    types: { 'text': string, 'yes-no': boolean },
    options: {
        [type: string]: { message: string }
    },
    keys: {
        'access-token': 'text',
        'repo-name': 'text',
        'private': 'yes-no',
        'retry': 'yes-no',
    }
};
type Output = string;

export const createRepo = () => makeAdapter<Resolve, Input, Output>(
    async (input, output) => {
        const url = 'https://api.github.com/user/repos';
        const headers = {
            Authorization: 'token ' + await input(
                'access-token', 'text', {message: 'Personal Access Token: '}
            )
        };
        const data = {
            name: await input(
                'repo-name', 'text', {message: 'Repository Name: '}
            ),
            private: await input(
                'private', 'yes-no', {message: 'Private?: '}
            )        	
        };
        
        output('Making API call to GitHub...');
        let response;
        try {
            response = await axios.post(url, data, {headers});
        } catch (e) {
            output('Something went wrong... Status code: ' + e.response.status);
            if (await input('retry', 'yes-no', {message: 'Would you like to try again? '})) {
                return await createRepo().attach({input, output});
            } else {
                throw e;
            }
        }
        
        output('Repository created!');
        return response;
    }
);

Now that our input and output functions are injected, we can use this service anywhere. Say we want to use it as part of a CLI application:

// cli-app.ts

import {prompt} from 'inquirer';    // inquirer is tool for getting cli input
import {createRepo} from './github-service';

const then = console.info;
const output = console.log;
const input = async (type, key, options) => {
    if (type === 'text') type = 'input';
    if (type === 'yes-no') type = 'confirm';
    
    return await prompt([{
        name: key,
        type: type,
        message: options.message
    }]);
};

createRepo()                        // calling our service gives us an `Adapter`
    .attach({then, output, input})  // here we "plug in" our attachments
    .exec();                        // and this executes our code

We could also utilize the same service in a web application:

// browser-app.ts

import service from './service';

service()                      // you can also attach handlers independently,
    .then(console.info)        // like so:
    .catch(console.error)
    .output(console.log)
    .input(async (type, key, options) => {
    	if (type === 'yes-no') {
            const yn = window.prompt(options.message + '(Y/n)');
            return yn === 'y';
    	} else {
            return window.prompt(options.message);
    	}
    })
    .exec();

Hopefully seeing these two applications side by side illustrates the advantages of using adapter.

Installation

npm install adapter

or

yarn add adapter

Documentation

More complete documentation is coming soon!

Author

Tanner Nielsen [email protected]

Website | GitHub