Comparing version 0.6.3 to 0.6.4
'use strict'; | ||
function TimeoutError(message) { | ||
this.message = message; | ||
this.stack = (new Error()).stack; | ||
this.message = message; | ||
this.stack = (new Error()).stack; | ||
} | ||
@@ -7,0 +7,0 @@ |
'use strict'; | ||
function ValidationError(message) { | ||
this.message = message; | ||
this.stack = (new Error()).stack; | ||
this.message = message; | ||
this.stack = (new Error()).stack; | ||
} | ||
@@ -7,0 +7,0 @@ |
@@ -19,14 +19,14 @@ 'use strict'; | ||
var Grille = function(sheets, storage, timeout, parallel, retry) { | ||
var self = this; | ||
sheets = typeof sheets === 'string' ? [sheets] : sheets; | ||
var self = this; | ||
sheets = typeof sheets === 'string' ? [sheets] : sheets; | ||
this.storage = storage || new RedisGrilleStorage(); | ||
this.content = Grille.deepFreeze({}); | ||
this.storage = storage || new RedisGrilleStorage(); | ||
this.content = Grille.deepFreeze({}); | ||
this.version = null; | ||
this.version = null; | ||
this.spreadsheets = []; | ||
sheets.forEach(function(sheet_id) { | ||
self.spreadsheets.push(new Spreadsheet(sheet_id, timeout, parallel, retry)); | ||
}); | ||
this.spreadsheets = []; | ||
sheets.forEach(function(sheet_id) { | ||
self.spreadsheets.push(new Spreadsheet(sheet_id, timeout, parallel, retry)); | ||
}); | ||
}; | ||
@@ -38,45 +38,45 @@ | ||
Grille.prototype.load = function(callback) { | ||
var self = this; | ||
var self = this; | ||
this.storage.loadDefaultVersion(function(err, data, version) { | ||
if (err || !data || !version) { | ||
return async.eachSeries(self.spreadsheets, function(spreadsheet, cb) { | ||
spreadsheet.load(cb); | ||
}, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
this.storage.loadDefaultVersion(function(err, data, version) { | ||
if (err || !data || !version) { | ||
return async.eachSeries(self.spreadsheets, function(spreadsheet, cb) { | ||
spreadsheet.load(cb); | ||
}, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
var new_data = {}; | ||
var new_data = {}; | ||
self.spreadsheets.forEach(function(spreadsheet) { | ||
extend(new_data, spreadsheet.content); | ||
}); | ||
self.spreadsheets.forEach(function(spreadsheet) { | ||
extend(new_data, spreadsheet.content); | ||
}); | ||
self.version = Grille.versionFromDate(); | ||
new_data.version = self.version; | ||
self.content = Grille.deepFreeze(new_data); | ||
self.version = Grille.versionFromDate(); | ||
new_data.version = self.version; | ||
self.content = Grille.deepFreeze(new_data); | ||
self.storage.save(self.version, new_data, function(err) { | ||
if (err) { | ||
return callback(new Error("Error persisting loaded data")); | ||
} | ||
self.storage.save(self.version, new_data, function(err) { | ||
if (err) { | ||
return callback(new Error("Error persisting loaded data")); | ||
} | ||
self.storage.setDefaultVersion(self.version, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
self.storage.setDefaultVersion(self.version, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
callback(null, new_data, version); | ||
}); | ||
}); | ||
}); | ||
} | ||
callback(null, new_data, version); | ||
}); | ||
}); | ||
}); | ||
} | ||
data.version = version; | ||
self.version = version; | ||
self.content = Grille.deepFreeze(data); | ||
data.version = version; | ||
self.version = version; | ||
self.content = Grille.deepFreeze(data); | ||
callback(null, data, version); | ||
}); | ||
callback(null, data, version); | ||
}); | ||
@@ -89,15 +89,15 @@ }; | ||
Grille.prototype.loadVersion = function(version, callback) { | ||
var self = this; | ||
var self = this; | ||
this.storage.load(version, function(err, data) { | ||
if (err || !data) { | ||
return callback(new Error("Version " + version + " of CMS data is not available")); | ||
} | ||
self.version = version; | ||
data.version = version; | ||
self.content = Grille.deepFreeze(data); | ||
this.storage.load(version, function(err, data) { | ||
if (err || !data) { | ||
return callback(new Error("Version " + version + " of CMS data is not available")); | ||
} | ||
callback(null, data); | ||
}); | ||
self.version = version; | ||
data.version = version; | ||
self.content = Grille.deepFreeze(data); | ||
callback(null, data); | ||
}); | ||
}; | ||
@@ -111,35 +111,35 @@ | ||
Grille.prototype.update = function(callback) { | ||
var self = this; | ||
var self = this; | ||
async.eachSeries(self.spreadsheets, function(spreadsheet, cb) { | ||
spreadsheet.load(cb); | ||
}, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
async.eachSeries(self.spreadsheets, function(spreadsheet, cb) { | ||
spreadsheet.load(cb); | ||
}, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
var new_data = {}; | ||
var new_data = {}; | ||
self.spreadsheets.forEach(function(spreadsheet) { | ||
extend(new_data, spreadsheet.content); | ||
}); | ||
self.spreadsheets.forEach(function(spreadsheet) { | ||
extend(new_data, spreadsheet.content); | ||
}); | ||
self.version = Grille.versionFromDate(); | ||
new_data.version = self.version; | ||
self.content = Grille.deepFreeze(new_data); | ||
self.version = Grille.versionFromDate(); | ||
new_data.version = self.version; | ||
self.content = Grille.deepFreeze(new_data); | ||
self.storage.save(self.version, self.content, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
self.storage.save(self.version, self.content, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
self.storage.setDefaultVersion(self.version, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
self.storage.setDefaultVersion(self.version, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
callback(null, self.content, self.version); | ||
}); | ||
}); | ||
}); | ||
callback(null, self.content, self.version); | ||
}); | ||
}); | ||
}); | ||
}; | ||
@@ -154,11 +154,11 @@ | ||
Grille.prototype.get = function(collection, identifier) { | ||
if (!this.content[collection]) { | ||
return null; | ||
} | ||
if (!this.content[collection]) { | ||
return null; | ||
} | ||
if (typeof identifier === 'undefined') { | ||
return this.content[collection]; | ||
} | ||
if (typeof identifier === 'undefined') { | ||
return this.content[collection]; | ||
} | ||
return this.content[collection][identifier]; | ||
return this.content[collection][identifier]; | ||
}; | ||
@@ -170,10 +170,10 @@ | ||
Grille.prototype.toJSON = function() { | ||
return this.content; | ||
return this.content; | ||
}; | ||
/** | ||
* Returns the date as YYYYMMDDHHMMSS as to be an ever increasing numeric string | ||
* Returns the current date as YYYYMMDDHHMMSS as to be an ever increasing numeric string | ||
*/ | ||
Grille.versionFromDate = function(date) { | ||
return (new Date()).toISOString().replace(/\D/g, '').slice(0, -3); | ||
Grille.versionFromDate = function() { | ||
return (new Date()).toISOString().replace(/\D/g, '').slice(0, -3); | ||
}; | ||
@@ -188,18 +188,18 @@ | ||
Grille.deepFreeze = function(o) { | ||
var prop, propKey; | ||
Object.freeze(o); // First freeze the object. | ||
var prop, propKey; | ||
Object.freeze(o); // First freeze the object. | ||
for (propKey in o) { | ||
prop = o[propKey]; | ||
if (!o.hasOwnProperty(propKey) || prop === null || typeof prop !== 'object' || Object.isFrozen(prop)) { | ||
// If the object is on the prototype, not an object, or is already frozen, | ||
// skip it. Note that this might leave an unfrozen reference somewhere in the | ||
// object if there is an already frozen object containing an unfrozen object. | ||
continue; | ||
} | ||
for (propKey in o) { | ||
prop = o[propKey]; | ||
if (!o.hasOwnProperty(propKey) || prop === null || typeof prop !== 'object' || Object.isFrozen(prop)) { | ||
// If the object is on the prototype, not an object, or is already frozen, | ||
// skip it. Note that this might leave an unfrozen reference somewhere in the | ||
// object if there is an already frozen object containing an unfrozen object. | ||
continue; | ||
} | ||
Grille.deepFreeze(prop); // Recursively call deepFreeze. | ||
} | ||
Grille.deepFreeze(prop); // Recursively call deepFreeze. | ||
} | ||
return o; | ||
return o; | ||
}; | ||
@@ -206,0 +206,0 @@ |
@@ -24,13 +24,13 @@ 'use strict'; | ||
var Spreadsheet = function(sheet_id, timeout, parallel, retry) { | ||
this.id = sheet_id; | ||
this.timeout = timeout || DEFAULT_TIMEOUT; | ||
this.parallel = parallel || DEFAULT_PARALLEL_LIMIT; | ||
this.retry = retry || DEFAULT_RETRY; | ||
this.id = sheet_id; | ||
this.timeout = timeout || DEFAULT_TIMEOUT; | ||
this.parallel = parallel || DEFAULT_PARALLEL_LIMIT; | ||
this.retry = retry || DEFAULT_RETRY; | ||
this.meta_worksheet = new Worksheet(sheet_id, Spreadsheet.META); | ||
this.meta_worksheet = new Worksheet(sheet_id, Spreadsheet.META); | ||
this.meta = null; | ||
this.content = {}; | ||
this.ready = false; | ||
this.last_updated = null; | ||
this.meta = null; | ||
this.content = {}; | ||
this.ready = false; | ||
this.last_updated = null; | ||
}; | ||
@@ -41,39 +41,29 @@ | ||
Spreadsheet.prototype.setTimeout = function(timeout) { | ||
this.timeout = timeout; | ||
this.timeout = timeout; | ||
}; | ||
Spreadsheet.prototype.load = function(load_callback) { | ||
var self = this; | ||
var self = this; | ||
async.series({ | ||
meta: function(meta_callback) { | ||
self.meta_worksheet.load(function(err, data) { | ||
if (err) { | ||
return meta_callback(err); | ||
} | ||
async.series({ | ||
meta: function(meta_callback) { | ||
self.meta_worksheet.load(function(err, data) { | ||
if (err) { | ||
return meta_callback(err); | ||
} | ||
self.meta = data; | ||
self.last_updated = self.meta_worksheet.last_updated; | ||
self.meta = data; | ||
self.last_updated = self.meta_worksheet.last_updated; | ||
meta_callback(); | ||
}); | ||
}, | ||
sheets: function(sheets_callback) { | ||
var tabs = Object.keys(self.meta); | ||
meta_callback(); | ||
}); | ||
}, | ||
sheets: function(sheets_callback) { | ||
var tabs = Object.keys(self.meta); | ||
async.eachLimit(tabs, self.parallel, function(tab, cb) { | ||
self.loadWorksheet(tab, self.meta[tab].format, cb); | ||
}, function(err, results) { | ||
if (err) { | ||
return sheets_callback(err); | ||
} | ||
self.ready = true; | ||
sheets_callback(); | ||
}); | ||
} | ||
}, function(err, results) { | ||
async.eachLimit(tabs, self.parallel, function(tab, cb) { | ||
self.loadWorksheet(tab, self.meta[tab].format, cb); | ||
}, function(err, results) { | ||
if (err) { | ||
return load_callback(err); | ||
return sheets_callback(err); | ||
} | ||
@@ -83,81 +73,91 @@ | ||
load_callback(null, self.content); | ||
}); | ||
sheets_callback(); | ||
}); | ||
} | ||
}, function(err, results) { | ||
if (err) { | ||
return load_callback(err); | ||
} | ||
self.ready = true; | ||
load_callback(null, self.content); | ||
}); | ||
}; | ||
Spreadsheet.prototype.toJSON = function() { | ||
return this.content; | ||
return this.content; | ||
}; | ||
Spreadsheet.prototype.get = function(collection, identifier) { | ||
if (!this.ready) { | ||
return null; | ||
} | ||
if (!this.ready) { | ||
return null; | ||
} | ||
if (!this.content[collection]) { | ||
return null; | ||
} | ||
if (!this.content[collection]) { | ||
return null; | ||
} | ||
if (typeof identifier === 'undefined') { | ||
return this.content[collection]; | ||
} | ||
if (typeof identifier === 'undefined') { | ||
return this.content[collection]; | ||
} | ||
return this.content[collection][identifier]; | ||
return this.content[collection][identifier]; | ||
}; | ||
Spreadsheet.prototype.loadWorksheet = function(collection, type, callback, attempt) { | ||
var self = this; | ||
var callbackFired = false; | ||
var self = this; | ||
var callbackFired = false; | ||
if (!attempt) { | ||
attempt = 1; | ||
} | ||
if (!attempt) { | ||
attempt = 1; | ||
} | ||
var timeout = setTimeout(function() { | ||
callbackFired = true; | ||
var timeout = setTimeout(function() { | ||
callbackFired = true; | ||
if (attempt > self.retry) { | ||
return callback(new TimeoutError(collection)); | ||
} | ||
if (attempt > self.retry) { | ||
return callback(new TimeoutError(collection)); | ||
} | ||
console.log("Re-Attempting to download worksheet:", collection, "attempt #:", attempt); | ||
console.log("Re-Attempting to download worksheet:", collection, "attempt #:", attempt); | ||
self.loadWorksheet(collection, type, callback, attempt + 1); | ||
}, this.timeout); | ||
self.loadWorksheet(collection, type, callback, attempt + 1); | ||
}, this.timeout); | ||
var worksheet = new Worksheet(this.id, collection); | ||
var worksheet = new Worksheet(this.id, collection); | ||
worksheet.load(function(err, data) { | ||
if (callbackFired) { | ||
// We got the data back from Google but it was too late. | ||
return; | ||
} | ||
worksheet.load(function(err, data) { | ||
if (callbackFired) { | ||
// We got the data back from Google but it was too late. | ||
return; | ||
} | ||
callbackFired = true; | ||
callbackFired = true; | ||
clearTimeout(timeout); | ||
clearTimeout(timeout); | ||
if (err) { | ||
return callback(err); | ||
} | ||
if (err) { | ||
return callback(err); | ||
} | ||
var path = self.meta[collection].collection; | ||
var path = self.meta[collection].collection; | ||
if (type === 'hash') { | ||
Spreadsheet.dotSet(self.content, data, path); | ||
} else if (type === 'keyvalue') { | ||
var new_data = Spreadsheet.extractKeyValue(data); | ||
if (type === 'hash') { | ||
Spreadsheet.dotSet(self.content, data, path); | ||
} else if (type === 'keyvalue') { | ||
var new_data = Spreadsheet.extractKeyValue(data); | ||
if (!self.content[path]) { | ||
self.content[path] = {}; | ||
} | ||
if (!self.content[path]) { | ||
self.content[path] = {}; | ||
} | ||
Spreadsheet.dotMerge(self.content, new_data, path); | ||
} else if (type === 'array') { | ||
Spreadsheet.dotSet(self.content, Spreadsheet.extractArray(data), path); | ||
} | ||
Spreadsheet.dotMerge(self.content, new_data, path); | ||
} else if (type === 'array') { | ||
Spreadsheet.dotSet(self.content, Spreadsheet.extractArray(data), path); | ||
} | ||
callback(null); | ||
}); | ||
callback(null); | ||
}); | ||
}; | ||
@@ -171,7 +171,7 @@ | ||
Spreadsheet.extractKeyValue = function(keyvalues) { | ||
Object.keys(keyvalues).map(function(key) { | ||
keyvalues[key] = keyvalues[key].value; | ||
}); | ||
Object.keys(keyvalues).map(function(key) { | ||
keyvalues[key] = keyvalues[key].value; | ||
}); | ||
return keyvalues; | ||
return keyvalues; | ||
}; | ||
@@ -185,14 +185,14 @@ | ||
Spreadsheet.extractArray = function(values) { | ||
var array = []; | ||
var rows = Object.keys(values).length; | ||
var columns = Object.keys(values['1']).length - 1; // id column is 1 | ||
var array = []; | ||
var rows = Object.keys(values).length; | ||
var columns = Object.keys(values['1']).length - 1; // id column is 1 | ||
for (var y = 0; y < rows; y++) { | ||
array[y] = []; | ||
for (var x = 0; x < columns; x++) { | ||
array[y][x] = values[y+1]['col-'+(x+1)]; | ||
} | ||
for (var y = 0; y < rows; y++) { | ||
array[y] = []; | ||
for (var x = 0; x < columns; x++) { | ||
array[y][x] = values[y+1]['col-'+(x+1)]; | ||
} | ||
} | ||
return array; | ||
return array; | ||
}; | ||
@@ -208,17 +208,17 @@ | ||
Spreadsheet.dotSet = function(destination, source, path) { | ||
var nodes = path.split("."); // e.g. x, y, z | ||
var nodes = path.split("."); // e.g. x, y, z | ||
var pointer = destination; | ||
var pointer = destination; | ||
for (var i = 0; i < nodes.length - 1; i++) { | ||
if (!pointer[nodes[i]]) { | ||
pointer[nodes[i]] = {}; | ||
} | ||
pointer = pointer[nodes[i]]; | ||
for (var i = 0; i < nodes.length - 1; i++) { | ||
if (!pointer[nodes[i]]) { | ||
pointer[nodes[i]] = {}; | ||
} | ||
pointer[nodes[nodes.length-1]] = source; | ||
pointer = pointer[nodes[i]]; | ||
} | ||
return destination; | ||
pointer[nodes[nodes.length-1]] = source; | ||
return destination; | ||
}; | ||
@@ -234,19 +234,19 @@ | ||
Spreadsheet.dotMerge = function(destination, source, path) { | ||
var nodes = path.split("."); // e.g. x, y, z | ||
var nodes = path.split("."); // e.g. x, y, z | ||
var pointer = destination; | ||
var pointer = destination; | ||
for (var i = 0; i < nodes.length; i++) { | ||
if (!pointer[nodes[i]]) { | ||
pointer[nodes[i]] = {}; | ||
} | ||
pointer = pointer[nodes[i]]; | ||
for (var i = 0; i < nodes.length; i++) { | ||
if (!pointer[nodes[i]]) { | ||
pointer[nodes[i]] = {}; | ||
} | ||
_.extend(pointer, source); | ||
pointer = pointer[nodes[i]]; | ||
} | ||
return destination; | ||
_.extend(pointer, source); | ||
return destination; | ||
}; | ||
module.exports = Spreadsheet; |
@@ -9,14 +9,14 @@ 'use strict'; | ||
var RedisGrilleStorage = function(config) { | ||
if (!config) { | ||
config = {}; | ||
} | ||
if (!config) { | ||
config = {}; | ||
} | ||
this.host = config.host || '127.0.0.1'; | ||
this.port = config.port || 6379; | ||
this.host = config.host || '127.0.0.1'; | ||
this.port = config.port || 6379; | ||
this.keys = {}; | ||
this.keys.current = config.current || 'grille-current'; | ||
this.keys.collection = config.collection || 'grille-content'; | ||
this.keys = {}; | ||
this.keys.current = config.current || 'grille-current'; | ||
this.keys.collection = config.collection || 'grille-content'; | ||
this.redis = redis.createClient(this.port, this.host, {}); | ||
this.redis = redis.createClient(this.port, this.host, {}); | ||
}; | ||
@@ -28,15 +28,15 @@ | ||
RedisGrilleStorage.prototype.save = function(version, data, callback) { | ||
if (!version) { | ||
throw new Error("Invalid Version for RedisGrilleStorage.save()!"); | ||
} | ||
if (!version) { | ||
throw new Error("Invalid Version for RedisGrilleStorage.save()!"); | ||
} | ||
data = JSON.stringify(data); | ||
data = JSON.stringify(data); | ||
this.redis.hset(this.keys.collection, version, data, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
this.redis.hset(this.keys.collection, version, data, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
callback(null); | ||
}); | ||
callback(null); | ||
}); | ||
}; | ||
@@ -48,13 +48,13 @@ | ||
RedisGrilleStorage.prototype.setDefaultVersion = function(version, callback) { | ||
if (!version) { | ||
throw new Error("Invalid Version for RedisGrilleStorage.setDefaultVersion()!"); | ||
if (!version) { | ||
throw new Error("Invalid Version for RedisGrilleStorage.setDefaultVersion()!"); | ||
} | ||
this.redis.set(this.keys.current, version, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
this.redis.set(this.keys.current, version, function(err) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
callback(null); | ||
}); | ||
callback(null); | ||
}); | ||
}; | ||
@@ -66,13 +66,13 @@ | ||
RedisGrilleStorage.prototype.getDefaultVersion = function(callback) { | ||
this.redis.get(this.keys.current, function(err, version) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
this.redis.get(this.keys.current, function(err, version) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
if (!version) { | ||
return callback(new Error("Cannot get default version")); | ||
} | ||
if (!version) { | ||
return callback(new Error("Cannot get default version")); | ||
} | ||
callback(null, version); | ||
}); | ||
callback(null, version); | ||
}); | ||
}; | ||
@@ -84,19 +84,19 @@ | ||
RedisGrilleStorage.prototype.load = function(version, callback) { | ||
if (!version) { | ||
throw new Error("Invalid Version for RedisGrilleStorage.load()!"); | ||
if (!version) { | ||
throw new Error("Invalid Version for RedisGrilleStorage.load()!"); | ||
} | ||
this.redis.hget(this.keys.collection, version, function(err, data) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
this.redis.hget(this.keys.collection, version, function(err, data) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
if (!data) { | ||
return callback(new Error("Cannot find data matching this version number")); | ||
} | ||
if (!data) { | ||
return callback(new Error("Cannot find data matching this version number")); | ||
} | ||
data = JSON.parse(data); | ||
data = JSON.parse(data); | ||
callback(null, data); | ||
}); | ||
callback(null, data); | ||
}); | ||
}; | ||
@@ -109,17 +109,17 @@ | ||
RedisGrilleStorage.prototype.loadDefaultVersion = function(callback) { | ||
var self = this; | ||
var self = this; | ||
this.getDefaultVersion(function(err, version) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
this.getDefaultVersion(function(err, version) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
self.load(version, function(err, data) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
self.load(version, function(err, data) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
callback(null, data, version); | ||
}); | ||
callback(null, data, version); | ||
}); | ||
}); | ||
}; | ||
@@ -131,9 +131,9 @@ | ||
RedisGrilleStorage.prototype.list = function(callback) { | ||
this.redis.hkeys(this.keys.collection, function(err, versions) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
this.redis.hkeys(this.keys.collection, function(err, versions) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
callback(null, versions); | ||
}); | ||
callback(null, versions); | ||
}); | ||
}; | ||
@@ -145,10 +145,10 @@ | ||
RedisGrilleStorage.prototype.clear = function(callback) { | ||
var self = this; | ||
var self = this; | ||
this.redis.multi() | ||
.del(this.keys.collection) | ||
.del(this.keys.current) | ||
.exec(callback); | ||
this.redis.multi() | ||
.del(this.keys.collection) | ||
.del(this.keys.current) | ||
.exec(callback); | ||
}; | ||
module.exports = RedisGrilleStorage; |
@@ -14,229 +14,229 @@ 'use strict'; | ||
var Worksheet = function(id, name) { | ||
this.spreadsheet = new GoogleSpreadsheet(id); | ||
this.name = name; | ||
this.spreadsheet = new GoogleSpreadsheet(id); | ||
this.name = name; | ||
this.last_updated = null; | ||
this.last_updated = null; | ||
}; | ||
Worksheet.parseWorksheetData = function(row) { | ||
var parsed = {}; | ||
var descriptors = Worksheet.removeExcessKeys(row.shift()); | ||
var parsed = {}; | ||
var descriptors = Worksheet.removeExcessKeys(row.shift()); | ||
row.forEach(function(row) { | ||
row = Worksheet.removeExcessKeys(row); | ||
row = Worksheet.convertKeys(descriptors, row); | ||
row.forEach(function(row) { | ||
row = Worksheet.removeExcessKeys(row); | ||
row = Worksheet.convertKeys(descriptors, row); | ||
parsed[row.id] = row; | ||
}); | ||
parsed[row.id] = row; | ||
}); | ||
return parsed; | ||
return parsed; | ||
}; | ||
Worksheet.removeExcessKeys = function(row) { | ||
delete row._xml; | ||
delete row._links; | ||
delete row.content; | ||
delete row.save; | ||
delete row.del; | ||
delete row.title; | ||
delete row._xml; | ||
delete row._links; | ||
delete row.content; | ||
delete row.save; | ||
delete row.del; | ||
delete row.title; | ||
return row; | ||
return row; | ||
}; | ||
Worksheet.convertKeys = function(descriptors, row) { | ||
Object.keys(descriptors).forEach(function(column) { | ||
var type = descriptors[column]; | ||
Object.keys(descriptors).forEach(function(column) { | ||
var type = descriptors[column]; | ||
switch(type) { | ||
case 'ignore': | ||
delete row[column]; | ||
switch(type) { | ||
case 'ignore': | ||
delete row[column]; | ||
break; | ||
break; | ||
case 'integer': | ||
row[column] = Math.floor(row[column]); | ||
case 'integer': | ||
row[column] = Math.floor(row[column]); | ||
break; | ||
break; | ||
case 'float': | ||
row[column] = parseFloat(row[column]); | ||
case 'float': | ||
row[column] = parseFloat(row[column]); | ||
break; | ||
break; | ||
case 'string': | ||
row[column] = row[column]; | ||
case 'string': | ||
row[column] = row[column]; | ||
break; | ||
break; | ||
case 'boolean': | ||
row[column] = row[column].toUpperCase(); | ||
case 'boolean': | ||
row[column] = row[column].toUpperCase(); | ||
if (row[column] !== 'TRUE' && row[column] !== 'FALSE') { | ||
throw new ValidationError("Not a boolean"); | ||
} | ||
if (row[column] !== 'TRUE' && row[column] !== 'FALSE') { | ||
throw new ValidationError("Not a boolean"); | ||
} | ||
row[column] = row[column] === 'TRUE'; | ||
row[column] = row[column] === 'TRUE'; | ||
break; | ||
break; | ||
case 'array': | ||
if (row[column]) { | ||
try { | ||
row[column] = JSON.parse(row[column]); | ||
} catch(e) { | ||
throw new ValidationError("Unable to parse JSON: " + row[column]); | ||
} | ||
case 'array': | ||
if (row[column]) { | ||
try { | ||
row[column] = JSON.parse(row[column]); | ||
} catch(e) { | ||
throw new ValidationError("Unable to parse JSON: " + row[column]); | ||
} | ||
if (!Array.isArray(row[column])) { | ||
throw new ValidationError("Data is not of type array: " + column); | ||
} | ||
} else { | ||
row[column] = []; | ||
} | ||
if (!Array.isArray(row[column])) { | ||
throw new ValidationError("Data is not of type array: " + column); | ||
} | ||
} else { | ||
row[column] = []; | ||
} | ||
break; | ||
break; | ||
case 'array.integer': | ||
if (row[column]) { | ||
try { | ||
row[column] = JSON.parse(row[column]); | ||
} catch(e) { | ||
throw new ValidationError("Unable to parse JSON: " + row[column]); | ||
} | ||
case 'array.integer': | ||
if (row[column]) { | ||
try { | ||
row[column] = JSON.parse(row[column]); | ||
} catch(e) { | ||
throw new ValidationError("Unable to parse JSON: " + row[column]); | ||
} | ||
if (!Array.isArray(row[column])) { | ||
throw new ValidationError("Data is not of type array: " + column); | ||
} | ||
if (!Array.isArray(row[column])) { | ||
throw new ValidationError("Data is not of type array: " + column); | ||
} | ||
row[column].forEach(function(value) { | ||
if (typeof value !== 'number' || value % 1 !== 0) { | ||
throw new ValidationError("Not an array of integers"); | ||
} | ||
}); | ||
} else { | ||
row[column] = []; | ||
} | ||
row[column].forEach(function(value) { | ||
if (typeof value !== 'number' || value % 1 !== 0) { | ||
throw new ValidationError("Not an array of integers"); | ||
} | ||
}); | ||
} else { | ||
row[column] = []; | ||
} | ||
break; | ||
break; | ||
case 'array.string': | ||
if (row[column]) { | ||
try { | ||
row[column] = JSON.parse(row[column]); | ||
} catch(e) { | ||
throw new ValidationError("Unable to parse JSON: " + row[column]); | ||
} | ||
case 'array.string': | ||
if (row[column]) { | ||
try { | ||
row[column] = JSON.parse(row[column]); | ||
} catch(e) { | ||
throw new ValidationError("Unable to parse JSON: " + row[column]); | ||
} | ||
if (!Array.isArray(row[column])) { | ||
throw new ValidationError("Data is not of type array: " + column); | ||
} | ||
if (!Array.isArray(row[column])) { | ||
throw new ValidationError("Data is not of type array: " + column); | ||
} | ||
row[column].forEach(function(value) { | ||
if (typeof value !== 'string') { | ||
throw new ValidationError("Not an array of strings"); | ||
} | ||
}); | ||
} else { | ||
row[column] = []; | ||
} | ||
row[column].forEach(function(value) { | ||
if (typeof value !== 'string') { | ||
throw new ValidationError("Not an array of strings"); | ||
} | ||
}); | ||
} else { | ||
row[column] = []; | ||
} | ||
break; | ||
break; | ||
case 'array.boolean': | ||
if (row[column]) { | ||
try { | ||
row[column] = JSON.parse(row[column]); | ||
} catch(e) { | ||
throw new ValidationError("Unable to parse JSON: " + row[column]); | ||
} | ||
case 'array.boolean': | ||
if (row[column]) { | ||
try { | ||
row[column] = JSON.parse(row[column]); | ||
} catch(e) { | ||
throw new ValidationError("Unable to parse JSON: " + row[column]); | ||
} | ||
if (!Array.isArray(row[column])) { | ||
throw new ValidationError("Data is not of type array: " + column); | ||
} | ||
if (!Array.isArray(row[column])) { | ||
throw new ValidationError("Data is not of type array: " + column); | ||
} | ||
row[column].forEach(function(value) { | ||
if (typeof value !== 'boolean') { | ||
throw new ValidationError("Not an array of booleans"); | ||
} | ||
}); | ||
} else { | ||
row[column] = []; | ||
} | ||
row[column].forEach(function(value) { | ||
if (typeof value !== 'boolean') { | ||
throw new ValidationError("Not an array of booleans"); | ||
} | ||
}); | ||
} else { | ||
row[column] = []; | ||
} | ||
break; | ||
break; | ||
case 'array.float': | ||
if (row[column]) { | ||
try { | ||
row[column] = JSON.parse(row[column]); | ||
} catch(e) { | ||
throw new ValidationError("Unable to parse JSON: " + row[column]); | ||
} | ||
case 'array.float': | ||
if (row[column]) { | ||
try { | ||
row[column] = JSON.parse(row[column]); | ||
} catch(e) { | ||
throw new ValidationError("Unable to parse JSON: " + row[column]); | ||
} | ||
if (!Array.isArray(row[column])) { | ||
throw new ValidationError("Data is not of type array: " + column); | ||
} | ||
if (!Array.isArray(row[column])) { | ||
throw new ValidationError("Data is not of type array: " + column); | ||
} | ||
row[column].forEach(function(value) { | ||
if (typeof value !== 'number') { | ||
throw new ValidationError("Not an array of floats"); | ||
} | ||
}); | ||
} else { | ||
row[column] = []; | ||
} | ||
row[column].forEach(function(value) { | ||
if (typeof value !== 'number') { | ||
throw new ValidationError("Not an array of floats"); | ||
} | ||
}); | ||
} else { | ||
row[column] = []; | ||
} | ||
break; | ||
break; | ||
case 'json': | ||
if (row[column]) { | ||
try { | ||
row[column] = JSON.parse(row[column]); | ||
} catch(e) { | ||
throw new ValidationError("Unable to parse JSON: " + row[column]); | ||
} | ||
} else { | ||
row[column] = null; | ||
} | ||
case 'json': | ||
if (row[column]) { | ||
try { | ||
row[column] = JSON.parse(row[column]); | ||
} catch(e) { | ||
throw new ValidationError("Unable to parse JSON: " + row[column]); | ||
} | ||
} else { | ||
row[column] = null; | ||
} | ||
break; | ||
break; | ||
default: | ||
console.log("NOTICE: Unable to parse data type, assuming string", JSON.stringify(type)); | ||
default: | ||
console.log("NOTICE: Unable to parse data type, assuming string", JSON.stringify(type)); | ||
row[column] = row[column]; | ||
row[column] = row[column]; | ||
break; | ||
} | ||
}); | ||
break; | ||
} | ||
}); | ||
return row; | ||
return row; | ||
}; | ||
Worksheet.getIndex = function(name, data) { | ||
for (var i = 0; i < data.worksheets.length; i++) { | ||
if (data.worksheets[i].title === name) { | ||
return i + 1; // Google Spreadsheet uses 1-based indexes | ||
} | ||
for (var i = 0; i < data.worksheets.length; i++) { | ||
if (data.worksheets[i].title === name) { | ||
return i + 1; // Google Spreadsheet uses 1-based indexes | ||
} | ||
} | ||
return null; | ||
return null; | ||
}; | ||
Worksheet.prototype.load = function(callback) { | ||
var self = this; | ||
var self = this; | ||
this.getWorksheetIndex(function(err, sheet) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
this.getWorksheetIndex(function(err, sheet) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
self.spreadsheet.getRows(sheet, function(err, data) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
self.spreadsheet.getRows(sheet, function(err, data) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
callback(null, Worksheet.parseWorksheetData(data)); | ||
}); | ||
callback(null, Worksheet.parseWorksheetData(data)); | ||
}); | ||
}); | ||
}; | ||
@@ -246,21 +246,21 @@ | ||
Worksheet.prototype.getWorksheetIndex = function(callback) { | ||
var self = this; | ||
var self = this; | ||
self.spreadsheet.getInfo(function(err, data) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
self.spreadsheet.getInfo(function(err, data) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
self.last_updated = new Date(data.updated); | ||
self.last_updated = new Date(data.updated); | ||
var worksheet_index = Worksheet.getIndex(self.name, data); | ||
var worksheet_index = Worksheet.getIndex(self.name, data); | ||
if (!worksheet_index) { | ||
return callback("Couldn't find a worksheet tab named '" + self.name + "'!"); | ||
} | ||
if (!worksheet_index) { | ||
return callback("Couldn't find a worksheet tab named '" + self.name + "'!"); | ||
} | ||
callback(null, worksheet_index); | ||
}); | ||
callback(null, worksheet_index); | ||
}); | ||
}; | ||
module.exports = Worksheet; |
{ | ||
"name": "grille", | ||
"version": "0.6.3", | ||
"version": "0.6.4", | ||
"description": "Simple CMS using Google Spreadsheets", | ||
@@ -13,3 +13,3 @@ "main": "lib/grille.js", | ||
"author": "Thomas Hunter II <me@thomashunter.name>", | ||
"license": "BSD", | ||
"license": "BSD-2-Clause", | ||
"dependencies": { | ||
@@ -16,0 +16,0 @@ "async": "^0.9.0", |
Misc. License Issues
License(Experimental) A package's licensing information has fine-grained problems.
Found 1 instance in 1 package
16
0
58625