From: David Schoonover Date: Thu, 12 Jul 2012 21:13:00 +0000 (-0700) Subject: Updates all controllers to recursively search for their data. X-Git-Url: http://git.less.ly:3516/?a=commitdiff_plain;h=a1580c8bd2e6aa60e939e953e6293a5dff5b8e56;p=limn.git Updates all controllers to recursively search for their data. --- diff --git a/src/server/controllers/datasource.co b/src/server/controllers/datasource.co index bce9946..df2cd88 100644 --- a/src/server/controllers/datasource.co +++ b/src/server/controllers/datasource.co @@ -22,13 +22,10 @@ YAML_OR_JSON_PAT = /\.(json|ya?ml)$/i */ class DataSourceController extends FileBackedController name : 'datasources' - dataDir : null - mapping : all : 'allData' -> super ... - toFile: @::toFileRecursive /** diff --git a/src/server/controllers/graph.co b/src/server/controllers/graph.co index a3ed631..fa09476 100644 --- a/src/server/controllers/graph.co +++ b/src/server/controllers/graph.co @@ -1,22 +1,26 @@ fs = require 'fs' path = require 'path' -{existsSync:exists} = path +exists = fs.existsSync or path.existsSync -_ = require 'underscore' Seq = require 'seq' +glob = require 'glob' yaml = require 'js-yaml' -{mkdirp, mkdirpAsync} = require '../mkdirp' -{ readJSONFilesAsync, +{ _, op, +} = require '../../util' +{ mkdirp, mkdirpAsync, +} = require '../mkdirp' +{ readFilesAsync, readJSONFilesAsync, } = require '../files' -Controller = require '../controller' +Controller = require '../controller' +FileBackedController = require '../file-controller' /** * @class Resource controller for graph requests. */ -class GraphController extends Controller +class GraphController extends FileBackedController PROTECTED_GRAPH_IDS : <[ unique_visitors pageviews @@ -33,42 +37,12 @@ class GraphController extends Controller ]> PROTECT_GRAPHS : true - name : 'graphs' - dataDir : null + name : 'graphs' + -> super ... - -> - super ... - limnOpts = @app.set 'limn options' - @dataDir = "#{limnOpts.dataDir}/graphs" - - - toFile: (id) -> "#{@dataDir}/#id.json" - - /** - * Auto-load :id for related requests. - */ - autoload: (id, cb) -> - file = @toFile id - parser = JSON.parse - - yamlFile = file.replace /\.json$/i, '.yaml' - if exists yamlFile - file = yamlFile - parser = yaml.load - - err, data <- fs.readFile file, 'utf8' - - if 'ENOENT' is err?.code - return cb null, {} - if err - console.error "GraphController.autoload(#id, #{typeof cb}) -->\nerr" - return cb err - try - cb null, parser data - catch err - console.error "GraphController.autoload(#id, #{typeof cb}) -->\nerr" - cb err + toFileSimple: (id) -> + "#{@dataDir}/#id.json" # GET /graphs.:format? index: (req, res) -> @@ -105,25 +79,33 @@ class GraphController extends Controller # POST /graphs create: (req, res) -> return unless data = @processBody req, res - file = @toFile data.id - if exists file - return res.send { result:"error", message:"Graph '#{data.id}' already exists!" }, 409 # 409: Resource Conflict - else - fs.writeFile file, JSON.stringify(data), "utf8", @errorHandler(res, "Error writing graph!") + Seq() + .seq @findFile, data.id, Seq + .seq (file) -> + res.send { result:"error", message:"Graph '#{data.id}' already exists!" }, 409 # 409: Resource Conflict + .catch (err) -> + fs.writeFile @toFileSimple(data.id), JSON.stringify(data), "utf8", @errorHandler(res, "Error writing graph!") # PUT /graphs/:graph update: (req, res) -> return unless data = @processBody req, res if @PROTECT_GRAPHS and _ @PROTECTED_GRAPH_IDS .contains data.id return res.send {result:"error", message:"Graph '#{data.id}' is read-only."}, 403 # 403: Forbidden - fs.writeFile @toFile(data.id), JSON.stringify(data), "utf8", @errorHandler(res, "Error writing graph!") + Seq() + .seq @findFile, data.id, (err, file) -> + @ok if err then @toFileSimple(data.id) else file + .seq (file) -> + fs.writeFile file, JSON.stringify(data), "utf8", @errorHandler(res, "Error writing graph!") # DELETE /graphs/:graph destroy: (req, res) -> id = req.param.graph if @PROTECT_GRAPHS and _ @PROTECTED_GRAPH_IDS .contains id return res.send {result:"error", message:"Graph '#{id}' is read-only."}, 403 # 403: Forbidden - fs.unlink @toFile(id), @errorHandler(res, "Graph '#{id}' does not exist!", 410) # 410: Resource Gone + Seq() + .seq @findFile, data.id, Seq + .seq (file) -> fs.unlink file, @errorHandler(res, "Error destroying Graph '#id'!", 500) + .catch (err) -> res.send {result:"error", message:"Graph '#id' does not exist!"}, 410 # 410: Resource Gone ### Helpers diff --git a/src/server/file-controller.co b/src/server/file-controller.co index e94f93d..c5d4e6a 100644 --- a/src/server/file-controller.co +++ b/src/server/file-controller.co @@ -4,6 +4,7 @@ exists = fs.existsSync or path.existsSync _ = require 'underscore' Seq = require 'seq' +glob = require 'glob' yaml = require 'js-yaml' { mkdirp, mkdirpAsync, @@ -30,34 +31,25 @@ class FileBackedController extends Controller @noun ?= @name.charAt(0).toUpperCase() + @name.slice(1) - /** - * Look up the resource in the dataDir. - * * @param {String} id ID of this resource. - * @returns {String} Path to file for this resource. - * @see toFileRecursive + * @returns {String} Glob path to file for this resource. */ - toFileFlat: (id) -> - return j if exists f = "#{@dataDir}/#id.json" - return y if exists y = "#{@dataDir}/#id.yaml" + toFile: (id) -> + "#{@dataDir}/**/#id.@(yaml|json)" /** - * Look up the resource by recursively searching the dataDir. + * Finds the reified filepath for the resource `id`. * * @param {String} id ID of this resource. - * @returns {String} Path to file for this resource. - * @see toFileFlat + * @param {Function} cb Callback `(err, filepath)`. */ - toFileRecursive: (id, cb) -> - files = glob "#{@dataDir}/**/#id.@(yaml|json)", {+nocase, +nosort, +sync} - files[0] + findFile: (id, cb) -> + glob @toFile(id), {+nocase, +nosort}, (err, files) -> + return cb err if err + return cb 'ENOENT' unless files.length + cb null, files[0] - /** - * Function for looking up the filepath to a resource. Defaults to a recursive lookup; - * use `toFileFlat()` to only check the top-level directory. - */ - toFile: @::toFileRecursive /** @@ -67,24 +59,10 @@ class FileBackedController extends Controller * @param {Function} cb Callback to invoke with the loaded object. */ autoload: (id, cb) -> - parser = JSON.parse - file = @toFile id - - if _.endsWith file, "#id.yaml" - parser = yaml.load - - err, data <- fs.readFile file, 'utf8' - - if 'ENOENT' is err?.code - return cb null, {} - if err - console.error "#{this}.autoload(#id, #{typeof cb}) --> Error reading data!\n", err - return cb err - try - cb null, parser data - catch err - console.error "#{this}.autoload(#id, #{typeof cb}) --> Error parsing data!\n", err - cb err + Seq() + .seq readJSONFilesAsync, @toFile(id), {+yaml, -appendExt}, Seq + .seq (data) -> cb null, _.values(data)[0] + .catch (err) -> cb err diff --git a/src/server/middleware.co b/src/server/middleware.co index 708cc0a..d193129 100755 --- a/src/server/middleware.co +++ b/src/server/middleware.co @@ -115,7 +115,7 @@ exports = module.exports = limn function limn(options) app = express.createServer() app = _.extend app, application - app.init() + app.init options app @@ -129,6 +129,7 @@ application = limn.application = * @constructor */ init : (opts={}) -> + app = this @REV = REV @BASE = BASE @@ -138,9 +139,14 @@ application = limn.application = opx.enabled = true if opx.enabled is false and (opx.whitelist or opx.blacklist) if opx.enabled opx.whitelist or= [ /.*/ ] + opx.whitelist = [opx.whitelist] unless _.isArray opx.whitelist opx.blacklist or= [] + opx.blacklist = [opx.blacklist] unless _.isArray opx.blacklist @set 'limn options', opts + # create data directory + mkdirp opts.dataDir + ### apply configuration @@ -235,7 +241,7 @@ application = limn.application = # serve static files @configure -> - {staticMaxAge} = @set 'limn options' + {varDir, staticMaxAge} = @set 'limn options' maxAge = staticMaxAge[NODE_ENV] ? staticMaxAge.default @use express.static varDir, {maxAge} @@ -250,7 +256,7 @@ application = limn.application = YAML_EXT_PAT = /\.ya?ml$/i @get '/datasources/all', (req, res, next) -> - opts = {varDir, dataDir} = @set 'limn options' + opts = {varDir, dataDir} = app.set 'limn options' data = {} Seq() diff --git a/src/server/server.co b/src/server/server.co index 47e943c..b866a13 100755 --- a/src/server/server.co +++ b/src/server/server.co @@ -13,14 +13,26 @@ LimnMiddleware = require './middleware' */ app = exports = module.exports = express.createServer() + +/** + * Load Limn middleware + */ +app.use limn = app.limn = LimnMiddleware do + varDir : './var' + dataDir : './var/data' + proxy : + enabled : true + whitelist : /.*/ + + /** * Handle webhook notification to pull from origin. */ app.all '/webhook/post-update', (req, res) -> - - # exec the pull async... cmd = 'git pull origin master' console.log "[/webhook/post-update] $ #cmd" + + # exec the pull async child = exec cmd, (err, stdout, stderr) -> res.contentType '.txt' console.log '[/webhook/post-update] ', stdout @@ -31,11 +43,6 @@ app.all '/webhook/post-update', (req, res) -> else res.send "$ #cmd\n\n#stdout\n\n#stderr", 200 -/** - * Load Limn middleware - */ -app.use limn = app.limn = LimnMiddleware() - mainfile = path.basename require.main?.filename @@ -51,7 +58,7 @@ if require.main is module or 'Cokefile' is mainfile throw err if err REV = stdout.trim! unless REV - console.log s = "Limn Server (port=#PORT, env=#NODE_ENV, rev=#REV, base_dir=#{limn.BASE})" + console.log s = "Limn Server (port=#PORT, env=#NODE_ENV, rev=#REV)" console.log '=' * s.length app.listen PORT diff --git a/www/data b/www/data deleted file mode 120000 index 4909e06..0000000 --- a/www/data +++ /dev/null @@ -1 +0,0 @@ -../data \ No newline at end of file diff --git a/www/docs b/www/docs deleted file mode 120000 index a9594bf..0000000 --- a/www/docs +++ /dev/null @@ -1 +0,0 @@ -../docs \ No newline at end of file diff --git a/www/js/kraken b/www/js/limn similarity index 100% rename from www/js/kraken rename to www/js/limn