Skip to content

Instantly share code, notes, and snippets.

@ForbesLindesay
Last active August 29, 2015 14:08
Show Gist options
  • Save ForbesLindesay/e636f25aef9afd14ef57 to your computer and use it in GitHub Desktop.
Save ForbesLindesay/e636f25aef9afd14ef57 to your computer and use it in GitHub Desktop.

Asset Key Spec

Asset key is a specification for defining a common API for all compilable languages.

compiler.compile(src, options) => Promise({body: string, type: string, dependencies: []})

Compiles a string with some options and returns a promise for an asset. This should never attempt to implement any caching internally, regardless of options passed in.

If the transform requires a filename, this method should not be implemented.

e.g.

var compiler = require('asset-key-less');

compiler.compile('.foo { .bar { color: red; } }');
// => Promise.resolve({body: '.foo .bar { color: red; }', type: 'css', dependencies: []})

default implementation (consumers should provide this, to keep implementations minimal):

exports.compile = function () {
  throw new Error('This transform does not support compiling a string, you must pass a filename.');
};

compiler.compileFile(filename, options) => Promise({body: string | Buffer, type: string, dependencies: [filename]})

Compiles a file with some options and returns a promise for an asset. This should never attempt to implement any caching internally, regardless of options passed in.

e.g.

var compiler = require('asset-key-raw');

compiler.compileFile('my-image.png');
// => Promise.resolve({body: Buffer, type: 'png', dependencies: [process.cwd() + '/my-image.png']})

default implementation (consumers should provide this, to keep implementations minimal):

exports.compileFile = function () {
  assert(typeof filename === 'string', 'filename must be a string');
  return readFile(filename, 'utf8').then(function (res) {
    return exports.compile(res, options);
  }).then(function (res) {
    res.dependencies = [filename];
  });
};

compiler.compileFileDynamic(filename, options) => () => Promise({body: string, type: string, dependencies: [filename]})

e.g.

var compiler = require('asset-key-raw-string');

var fn = compiler.compileFileDynamic('my-script.js');
fn();
// => Promise.resolve({body: 'alert("hello world");', type: 'js', dependencies: [process.cwd() + '/my-script.png']})

setTimeout(function () {
  fs.writFileSync('my-script.js', 'alert("goodbye");');
  fn();
  // => Promise.resolve({body: 'alert("goodbye");', type: 'js', dependencies: [process.cwd() + '/my-script.png']})
}, 100);

default implementation (consumers should provide this, to keep implementations minimal):

exports.compileFileDynamic = function (filename, options) {
  assert(typeof filename === 'string', 'filename must be a string');
  var compiled, times;
  function getTimes(start) {
    return compiled.then(function (result) {
      return Promise.all(result.dependencies.map(function (filename) {
        return stat(filename).then(function (st) {
          return start ? Math.min(start, st.mtime.getTime()) : st.mtime.getTime();
        });
      });
    });
  }
  function compile() {
    var start = Date.now();
    compiled = exports.compileFile(filename, options);
    times = getTimes(start);
    return compiled;
  }
  compile();

  return function () {
    return Promise.all([times, getTimes()]).then(function (res) {
      if (res[0].length === 0 || res[0].length !== res[1].length) {
        return compile();
      } else {
        for (var i = 0; i < res[0].length; i++) {
          if (res[0][i] !== res[1][i]) return compile();
        }
        return compiled;
      }
    });
  };
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment