A TypeScript utility for writing I/O agnostic programs

Usage no npm install needed!

<script type="module">
  import adapter from '';


🔌 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.


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 = '';
const headers = { Authorization: 'token <access-token>' };
const data = { name: '<repo-name>', private: true };

await, 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 = '';
        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, 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 =;
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(        // like so:
    .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);

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


npm install adapter


yarn add adapter


More complete documentation is coming soon!


Tanner Nielsen

Website | GitHub