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 🙏

© 2025 – Pkg Stats / Ryan Hefner

adrenaline

v1.0.2

Published

Relay-like framework with simplier API

Downloads

106

Readme

Adrenaline

build status npm version npm downloads

This library provides a subset of Relay's behaviour with a cleaner API.

Why?

Relay is a great framework with exciting ideas behind it. The downside is that in order to get all the cool features, you need to deal with a complex API. Relay provides you a lot of tricky optimizations which probably are more suitable for huge projects. In small, medium and even large ones you would prefer to have better developer experience while working with a simple, minimalistic set of APIs.

Adrenaline intends to provide you Relay-like ability to describe your components with declarative data requirements, while keeping the API as simple as possible. You are free to use it with different libraries like Redux, React Router, etc.

When not to use it?

  • You have a huge project and highly need tricky optimisations to reduce client-server traffic.
  • When you don't understand why you should prefer Adrenaline to Relay.

Installation

npm install --save adrenaline

Adrenaline requires React 15.0 or later.

Adrenaline uses fetch under the hood so you need to install the polyfill by yourself.

npm install --save whatwg-fetch

and then import it at the very top of your entry JavaScript file:

import 'whatwg-fetch';
import React from 'react';
import ReactDOM from 'react-dom';
import { Adrenaline } from 'adrenaline';

import App from './components/App';

ReactDOM.render(
  <Adrenaline>
    <App />
  </Adrenaline>,
  document.getElementById('root')
)

API

Adrenaline follows the idea of Presentational and Container Components

<Adrenaline endpoint />

Root of your application should be wrapped with Adrenaline component. This component is a provider component which injects some helpful stuff into your React application.

prop name | type | default/required | purpose ----------|--------|------------------|-------- endpoint | string | "/graphql" | URI of your GraphQL endpoint

container({ variables, query })(Component)

In Adrenaline, you create container components mostly for your route handlers. The purpose of containers is to collect data requirements from presentation components in a single GraphQL query. They also behave like view controllers and are able to speak to the outside world using mutations.

key | type | default/required | purpose ----------|--------------------------|------------------|-------- variables | (props: Props) => Object | () => ({}) | describe query variables as a pure function of props query | string | required | your GraphQL query for this container

import React, { Component, PropTypes } from 'react';
import { container } from 'adrenaline';
import TodoList from './TodoList';

class UserItem extends Component {
  static propTypes = {
    viewer: PropTypes.object.isRequired,
  }
  /* ... */
}

export default container({
  variables: (props) => ({
    id: props.userId,
  }),
  query: `
    query ($id: ID!) {
      viewer(id: $id) {
        id,
        name,
        ${TodoList.getFragment('todos')}
      }
    }
  `,
})(UserItem);

Containers may also pass 2 additional properties to your component: mutate and isFetching.

  • mutate({ mutation: String, variables: Object = {}, invalidate: boolean = true }): Promise: You need to use this function in order to perform mutations. invalidate argument means you need to resolve data declarations after mutation.
  • isFetching: boolean: This property helps you understand if your component is in the middle of resolving data.

presenter({ fragments })(Component)

As in the presentational components idea, all your dumb components may be declared as simple React components. But if you want to declare your data requirements in a way similar to Relay, you can use the presenter() higher-order component.

import React, { Component } from 'react';
import { presenter } from 'adrenaline';

class TodoList extends Component {
  /* ... */
}

export default presenter({
  fragments: {
    todos: `
      fragment on User {
        todos {
          id,
          text
        }
      }
    `,
  },
})(TodoList);

Using ES7 decorators

Adrenaline works as higher-order components, so you can decorate your container components using ES7 decorators

import { container } from 'adrenaline'

@container({
  variables: (props) => ({
    id: props.userId,
  }),
  query: `
    query ($id: ID!) {
      viewer(id: $id) {
        id,
        name,
        ${TodoList.getFragment('todos')}
      }
    }
  `
})
export default class extends Component {
  static propTypes = {
    viewer: PropTypes.object.isRequired,
  }
  /* ... */
}

Mutations

You can declare your mutations as simple as:

const createTodo = `
  mutation ($text: String, $owner: ID) {
    createTodo(text: $text, owner: $owner) {
      id,
      text,
      owner {
        id
      }
    }
  }
`;

Then you can use this mutation with your component:

import React, { Component, PropTypes } from 'react';
import { createSmartComponent } from 'adrenaline';

class UserItem extends Component {
  static propTypes = {
    viewer: PropTypes.object.isRequired,
  }

  onSomeButtonClick() {
    this.props.mutate({
      mutation: createTodo,
      variables: {
        text: hello,
        owner: this.props.viewer.id
      },
    });
  }

  render() {
    /* render some stuff */
  }
}

Testing

There is a common problem I've discovered so far while developing applications. When you change the GraphQL schema, you'd like to know which particular subtrees in your applications need to be fixed. And you probably do not want to check this by running your application and going through it by hand.

For this case, Adrenaline provides you helper utilities for integration testing (currently for expect only). You can use toBeValidAgainst for checking your components' data requirements against your schema with GraphQL validation mechanism.

import expect from 'expect';
import TestUtils from 'adrenaline/lib/test';

import schema from 'path/to/schema';
// TodoApp is a container component
import TodoApp from 'path/to/TodoApp';

expect.extend(TestUtils.expect);

describe('Queries regression', () => {
  it('for TodoApp', () => {
    expect(TodoApp).toBeValidAgainst(schema);
  });
});

Image