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

trolley

v1.0.6

Published

Persistent logging and request handling for Express apps.

Downloads

140

Readme

🚋 Trolley

Trolley is an opinionated, easy to use and extensible logging tool and response abstraction for Express-based APIs.


Usage / public API

In action:

// server.js

const Trolley = require('./my-trolley-instance.js');
const { somethingIsWrongWith, allIsGoodWith } = require('./somefile.js');

app.use('/health', (req, res) => Trolley.deliver('API is up and running!', res))

app.use('/myRoute', (req, res) => {
    try {
        if (somethingIsWrongWith(req.data)) {
            Trolley.crash('SomeValue is invalid!', res);
        } else if (allIsGoodWith(req.data)) {
            Trolley.deliver({ updated: true }, res);
        } else {
            Trolley.send({ code: 420, message: 'Hello world!' }, res);
        }
    } catch (e) {
        Trolley.explode({ message: 'Sorry! We\'re experiencing issues.' }, res);
    }
})

Trolley.create({ config })

Trolley.create is the main method used to create a trolley instance. The resulting instance has methods for flusing responses (.deliver, .crash, .explode, .send) as well as methods for adding additional handlers (.onDeliver, etc.)

// my-trolley-instance.js

const trolley = require('trolley');
const { reportBadRequestSomehow, reportExceptionSomehow } = require('./somefile.js')

module.exports = trolley.create({
    onCrash: reportBadRequestSomehow,
    onExplode: reportExceptionSomehow
});

Responses from .crash and .explode both include some metadata about the failed request, to assist with debugging. Given the above .crash usage, the client will receive JSON like this:

{
    "timestamp": 1000000000,
    "status": 400,
    "statusText": "Bad Request",
    "error": "SomeValue is invalid!"
}

Use .crash to return an error-type response, 400 by default. you can provide whatever response code you wish by giving { code: number } or { status: number } or { statusCode: number } within the payload.

Trolley also offers means to set default response handlers in your Express API. For instance, if you always perform some action when a request fails for client-side reasons (4XX errors), or for server-side reasons (5XX errors), you can set those up in just one place.

const trolley = require('trolley').create({
    // onRespond is called for all responses through Trolley
    onRespond: (payload) => console.log('server responded with this payload:', payload),
    // onDeliver is called when .deliver is used (successes)
    onDeliver: (payload) => console.log('huzzah, successful response:', payload)
    // onCrash is called when .crash is used (errors)
    onCrash: (payload) => console.log('server got a bad request', payload),
    // onExplode is called when .explode is used (exceptions)
    onExplode: (payload) => console.log('server ran into an exception!', payload)
});

Trolley.createLogger({ loggerConfig })

Returns a logger, which is a function that takes a single line to log to the output file specified in the loggerConfig.

// logger.js

const trolley = require('trolley');
const logger = trolley.createLogger({
    logPath: 'auth_server.log',
    useLineBreaks: true
})

Trolley.withLogger({ combinedLoggerAndTrolleyConfig })

Returns a trolley instance with a pre-built logger added as an onRespond handler.


Internals / utilities

Trolley.statuses

Map of status codes -> status names, like:

{
  100: 'Continue',
  101: 'Switching Protocols',
  102: 'Processing',
  200: 'OK',
  201: 'Created',
  202: 'Accepted',
  [etc]

Trolley.statusCodes

Map of status names -> status codes, like:

{
  Continue: 100,
  SwitchingProtocols: 101,
  Processing: 102,
  OK: 200,
  Created: 201,
  Accepted: 202,
  [etc]

Trolley.utils

toFunctionArray(whatever)

If given an array of functions, returns that function array. If given a function, returns an array of just that function. If given anything else, returns empty array.

toFunctionArray(null)
=> []

toFunctionArray(myCoolFunction)
=> [myCoolFunction]

toFunctionArray([someFunc, anotherFunc, thirdFunc])
=> [someFunc, anotherFunc, thirdFunc]

stringify(whatever)

Does JSON.stringify, but unwraps the added quotes if the value is already a string.

stringify({ ok: 1234, what: true })
=> '{ "ok": 1234, "what": true }'

stringify(43)
=> '43'

stringify('hey')
=> 'hey'

capitalize(string)

Capitalizes the first letter of the string given. Leaves the rest of the casings untouched.

capitalize('hello there')
=> 'Hello there'

lowercase(string)

Lowercases the whole darn string.

lowercase('OMG!')
=> 'omg!'

camelCase(string)

Splits the string into words (breaking by non-alphanumeric chars), doesn't touch the first word, and runs capitalize on the subsequent words, joining them without spaces.

Warning! This and other code-casing functions remove all whitespace and non-alphanumeric characters.

camelCase('what the heck!? I am only 29.')
=> 'whatTheHeckIAmOnly29'

camelCase('OMG')
=> 'OMG'

camelCase('What is it anyway') // note the capital initial
=> 'WhatIsItAnyway'

camelCase('$)!$(#')
=> ''

pascalCase(string)

Splits the string into words (breaking by non-alphanumeric chars) and runs capitalize on each word, joining them without spaces.

Warning! This and other code-casing functions remove all whitespace and non-alphanumeric characters.

pascalCase('possible unreality')
=> 'PossibleUnreality'

snakeCase(string)

Splits the string into words (breaking by non-alphanumeric chars) and runs lowercase on all of them, joining them by underscores (_).

Warning! This and other code-casing functions remove all whitespace and non-alphanumeric characters.

snakeCase('Possible Unreality')
=> 'possible_unreality'

kebabCase(string)

Splits the string into words (breaking by non-alphanumeric chars) and runs lowercase on all of them, joining them by dashes (-).

Warning! This and other code-casing functions remove all whitespace and non-alphanumeric characters.

kebabCase('Possible Unreality Detected!')
=> 'possible-unreality-detected'

keys(object)

Returns all the keys of an object, same as Object.keys (but with an object-type-check included).

keys('lol')
=> TypeError: 'lol' is not an object.

keys({ ok: 'yes', what: true })
=> ['ok', 'what']

withoutKeys(object, keysToRemove: String[])

Returns the given object without any properties whose names match strings in keysToRemove.

getPayloadStatusCode(payload, defaultCode)

Checks payload for code, status, or statusCode properties containing a number. Returns the first it finds. If none, return defaultCode, or if none given, return 200 if the payload is truthy or 0, otherwise 204 (No Content).

unwrapQuotes(string)

If given a string that has double quotes (") at the beginning and the end, returns the same string without them.

Type checkers

Fairly self-explanatory:

  • isNumber
  • isFunction
  • isString
  • isDefined
  • isNonEmptyString
  • isArray
  • isBoolean
  • isNull
  • isObject
  • isRegex
  • isPrimitive
  • isFunctionArray