UNPKG

asset-rack

Version:

Asset management framework for nodejs

114 lines (102 loc) 3.98 kB
async = require 'async' crypto = require 'crypto' pathutil = require 'path' mime = require 'mime' {extend} = require './util' {EventEmitter} = require 'events' class exports.Asset extends EventEmitter defaultMaxAge: 60*60*24*365 # one year constructor: (options) -> super() options ?= {} @url = options.url if options.url? @contents = options.contents if options.contents? @headers = if options.headers then options.headers else {} headers = {} for key, value of @headers headers[key.toLowerCase()] = value @headers = headers @ext = pathutil.extname @url @mimetype = options.mimetype if options.mimetype? @mimetype ?= mime.types[@ext.slice(1, @ext.length)] @mimetype ?= 'text/plain' @hash = options.hash if options.hash? @maxAge = options.maxAge if options.maxAge? @allowNoHashCache = options.allowNoHashCache if options.allowNoHashCache? @on 'newListener', (event, listener) => if event is 'complete' and @completed is true listener() @on 'created', (data) => if data?.contents? @contents = data.contents if data?.assets? @assets = data.assets if @contents? @createSpecificUrl() @createHeaders() @completed = true @emit 'complete' @on 'error', (error) => throw error if @listeners 'error' is 1 @on 'start', => @maxAge ?= @rack?.maxAge @maxAge ?= @defaultMaxAge unless @hash is false @allowNoHashCache ?= @rack?.allowNoHashCache @create options process.nextTick => @maxAge ?= @defaultMaxAge return @create options unless @rack? respond: (request, response) -> headers = {} if request.url is @url and @allowNoHashCache isnt true for key, value of @headers headers[key] = value delete headers['cache-control'] else headers = @headers for key, value of headers response.header key, value return response.send @contents checkUrl: (url) -> url is @specificUrl or (not @hash? and url is @url) handle: (request, response, next) -> handle = => if @assets? for asset in @assets if asset.checkUrl request.url return asset.respond request, response if @checkUrl(request.url) @respond request, response else next() if @completed is true handle() else @on 'complete', -> handle() create: (options) -> @emit 'created' createHeaders: -> @headers['content-type'] ?= @mimetype @headers['content-length'] = @contents.length if @maxAge? @headers['cache-control'] ?= "public, max-age=#{@maxAge}" tag: -> switch @mimetype when 'text/javascript' tag = "\n<script type=\"#{@mimetype}\" " return tag += "src=\"#{@specificUrl}\"></script>" when 'text/css' return "\n<link rel=\"stylesheet\" href=\"#{@specificUrl}\">" createSpecificUrl: -> @md5 = crypto.createHash('md5').update(@contents).digest 'hex' if @hash is false @useDefaultMaxAge = false return @specificUrl = @url @specificUrl = "#{@url.slice(0, @url.length - @ext.length)}-#{@md5}#{@ext}" if @hostname? @specificUrl = "//#{@hostname}#{@specificUrl}" isRelevantUrl: (specificUrl) -> baseUrl = @url.slice(0, @url.length - @ext.length) if specificUrl.indexOf baseUrl isnt -1 and @ext is pathutil.extname specificUrl return true return false @extend: extend