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

spike-records

v2.2.1

Published

compile remote data into your templates

Downloads

69

Readme

Spike Records

npm tests dependencies coverage

remote data -> static templates

Why should you care?

Static is the best, but sometimes you need to fetch data from a remote source which makes things not so static. Spike Records is a little webpack plugin intended for use with spike which allows you to make data pulled from a file or url available in your view templates.

It can pull data from the following places:

  • A javascript object
  • A file containing a javascript object or JSON
  • A URL that returns JSON
  • A GraphQL endpoint

Installation

Install into your project with npm i spike-records -S.

Then load it up as a plugin in app.js like this:

const Records = require('spike-records')
const standard = require('reshape-standard')
const locals = {}

module.exports = {
  reshape: standard({ locals: () => locals }),
  plugins: [new Records({
    addDataTo: locals,
    test: { file: 'data.json' }
  })]
}

Usage

The primary use case for spike-records is to inject local variables into your html templates, although technically it can be used for anything. In the example above, we use the reshape-standard plugin pack to add variables (among other functionality) to your html. Spike's default template also uses reshape-standard.

In order to use the results from spike-records, you must pass it an object, which it will put the resolved data on, using the addDataTo key. This plugin runs early in spike's compile process, so by the time templates are being compiled, the object will have all the data necessary on it. If you are using the data with other plugins, ensure that spike-records is the first plugin in the array.

I know this is an unusual pattern for a javascript library, but the way it works is quite effective in this particular system, and affords a lot of flexibility and power.

The records plugin accepts an object, and each key in the object (other than addDataTo) should contain another object as it's value, with either a file, url, data, graphql or callback property. For example:

const Records = require('spike-records')
const locals = {}
function myFunc () {
  // call any arbitrary API or computation to produce data
  return new Promise((resolve, reject) => {...})
}

module.exports = {
  plugins: [new Records({
    addDataTo: locals,
    one: { file: 'data.json' },
    two: { url: 'http://api.carrotcreative.com/staff' },
    three: { data: { foo: 'bar' } },
    four: {
      graphql: {
        url: 'http://localhost:1234',
        query: 'query { allPosts { title } }',
        variables: 'xxx', // optional
        headers: { authorization: 'Bearer xxx' } // optional
      }
    },
    five: { callback: myFunc }
  })]
}

Whatever data source you provide, it will be resolved and added to your view templates as [key]. So for example, if you were trying to access three in your templates, you could access it with three.foo, and it would return 'bar', as such:

p {{ three.foo }}

Now let's get into some more details for each of the data types.

File

file accepts a file path, either absolute or relative to your spike project's root. So for the example above, it would resolve to /path/to/project/data.json.

Url

url accepts either a string or an object. If provided with a string, it will make a request to the provided url and parse the result as JSON, then return it as a local. If you need to modify this behavior, you can pass in an object instead. The object is passed through directly to rest.js, their docs for acceptable values for this object can be found here. These options allow modification of the method, headers, params, request entity, etc. and should cover any additional needs.

Data

The most straightforward of the options, this will just pass the data right through to the locals. Also if you provide a A+ compliant promise for a value, it will be resolved and passed in to the template.

Additional Options

Alongside any of the data sources above, there are a few additional options you can provide in order to further manipulate the output.

Transform

If you want to transform the data from your source in any way before injecting it as a local, you can use this option. For example:

const Records = require('spike-records')
const locals = {}

module.exports = {
  plugins: [new Records({
    addDataTo: locals,
    blog: {
      url: 'http://blog.com/api/posts',
      transform: (data) => { return data.response.posts }
    }
  })]
}

Transform Raw

If you want to transform the data from your source before it is processed by rest, for instance to remove cross site scripting protections, you can use this option. For example:

const Records = require('spike-records')
const locals = {}

module.exports = {
  plugins: [new Records({
    addDataTo: locals,
    blog: {
      transformRaw: (data) => { return data.replace('])}while(1);</x>', '') },
      url: 'https://medium.com/glassboard-blog/?format=json'
    }
  })]
}

Template

Using the template option allows you to write objects returned from records to single page templates. For example, if you are trying to render a blog as static, you might want each post returned from the API to be rendered as a single page by itself.

The template option is an object with path and output keys. path is an absolute or relative path to a template to be used to render each item, and output is a function with the currently iterated item as a parameter, which should return a string representing a path relative to the project root where the single view should be rendered. For example:

const Records = require('spike-records')
const locals = {}

module.exports = {
  plugins: [new Records({
    addDataTo: locals,
    blog: {
      url: 'http://blog.com/api/posts',
      template: {
        path: 'templates/single.sgr',
        output: (post) => { return `posts/${post.slug}.html` }
      }
    }
  })]
}

Note that for this feature to work correctly, the data returned from your data source must be an array. If it's not, the plugin will throw an error. If you need to transform the data before it is rendered into templates, you can do so using a transform function, as such:

const Records = require('spike-records')
const locals = {}

module.exports = {
  plugins: [new Records({
    addDataTo: locals,
    blog: {
      url: 'http://blog.com/api/posts',
      template: {
        transform: (data) => { return data.response.posts },
        path: 'templates/single.sml',
        output: (post) => { return `posts/${post.slug}.html` }
      }
    }
  })]
}

If you use a transform function outside of the template block, this will still work. The difference is that a transform inside the template block will only use the transformed data for rendering single templates, whereas the normal transform option will alter that data that is injected into your view templates as locals, as well as the single templates.

Inside your template, a local called item will be injected, which contains the contents of the item for which the template has been rendered. It will also contain all the other locals injected by spike-records and otherwise, fully transformed by any transform functions provided.

License & Contributing