season
Version:
CSON utilities
300 lines (282 loc) • 8.69 kB
JavaScript
(function() {
var CSON, crypto, csonCache, detectDuplicateKeys, fs, getCachePath, isAllCommentsAndWhitespace, parseCacheContents, parseContents, parseContentsSync, parseObject, path, stats, writeCacheFile, writeCacheFileSync;
crypto = require('crypto');
path = require('path');
fs = require('fs-plus');
CSON = null;
csonCache = null;
stats = {
hits: 0,
misses: 0
};
getCachePath = function(cson) {
var digest;
digest = crypto.createHash('sha1').update(cson, 'utf8').digest('hex');
return path.join(csonCache, "" + digest + ".json");
};
writeCacheFileSync = function(cachePath, object) {
try {
return fs.writeFileSync(cachePath, JSON.stringify(object));
} catch (_error) {}
};
writeCacheFile = function(cachePath, object) {
return fs.writeFile(cachePath, JSON.stringify(object), function() {});
};
parseObject = function(objectPath, contents, options) {
var error, parsed;
if (path.extname(objectPath) === '.cson') {
if (CSON == null) {
CSON = require('cson-parser');
}
try {
parsed = CSON.parse(contents, (options != null ? options.allowDuplicateKeys : void 0) === false ? detectDuplicateKeys : void 0);
stats.misses++;
return parsed;
} catch (_error) {
error = _error;
if (isAllCommentsAndWhitespace(contents)) {
return null;
} else {
throw error;
}
}
} else {
return JSON.parse(contents);
}
};
parseCacheContents = function(contents) {
var parsed;
parsed = JSON.parse(contents);
stats.hits++;
return parsed;
};
parseContentsSync = function(objectPath, cachePath, contents, options) {
var object, parseError;
try {
object = parseObject(objectPath, contents, options);
} catch (_error) {
parseError = _error;
if (parseError.path == null) {
parseError.path = objectPath;
}
if (parseError.filename == null) {
parseError.filename = objectPath;
}
throw parseError;
}
if (cachePath) {
writeCacheFileSync(cachePath, object);
}
return object;
};
isAllCommentsAndWhitespace = function(contents) {
var line, lines;
lines = contents.split('\n');
while (lines.length > 0) {
line = lines[0].trim();
if (line.length === 0 || line[0] === '#') {
lines.shift();
} else {
return false;
}
}
return true;
};
parseContents = function(objectPath, cachePath, contents, options, callback) {
var object, parseError;
try {
object = parseObject(objectPath, contents, options);
} catch (_error) {
parseError = _error;
parseError.path = objectPath;
if (parseError.filename == null) {
parseError.filename = objectPath;
}
parseError.message = "" + objectPath + ": " + parseError.message;
if (typeof callback === "function") {
callback(parseError);
}
return;
}
if (cachePath) {
writeCacheFile(cachePath, object);
}
if (typeof callback === "function") {
callback(null, object);
}
};
module.exports = {
setCacheDir: function(cacheDirectory) {
return csonCache = cacheDirectory;
},
isObjectPath: function(objectPath) {
var extension;
if (!objectPath) {
return false;
}
extension = path.extname(objectPath);
return extension === '.cson' || extension === '.json';
},
resolve: function(objectPath) {
var csonPath, jsonPath;
if (objectPath == null) {
objectPath = '';
}
if (!objectPath) {
return null;
}
if (this.isObjectPath(objectPath) && fs.isFileSync(objectPath)) {
return objectPath;
}
jsonPath = "" + objectPath + ".json";
if (fs.isFileSync(jsonPath)) {
return jsonPath;
}
csonPath = "" + objectPath + ".cson";
if (fs.isFileSync(csonPath)) {
return csonPath;
}
return null;
},
readFileSync: function(objectPath, options) {
var cachePath, contents, fsOptions, parseOptions;
if (options == null) {
options = {};
}
parseOptions = {
allowDuplicateKeys: options.allowDuplicateKeys
};
delete options.allowDuplicateKeys;
fsOptions = Object.assign({
encoding: 'utf8'
}, options);
contents = fs.readFileSync(objectPath, fsOptions);
if (contents.trim().length === 0) {
return null;
}
if (csonCache && path.extname(objectPath) === '.cson') {
cachePath = getCachePath(contents);
if (fs.isFileSync(cachePath)) {
try {
return parseCacheContents(fs.readFileSync(cachePath, 'utf8'));
} catch (_error) {}
}
}
return parseContentsSync(objectPath, cachePath, contents, parseOptions);
},
readFile: function(objectPath, options, callback) {
var fsOptions, parseOptions;
if (arguments.length < 3) {
callback = options;
options = {};
}
parseOptions = {
allowDuplicateKeys: options.allowDuplicateKeys
};
delete options.allowDuplicateKeys;
fsOptions = Object.assign({
encoding: 'utf8'
}, options);
return fs.readFile(objectPath, fsOptions, (function(_this) {
return function(error, contents) {
var cachePath;
if (error != null) {
return typeof callback === "function" ? callback(error) : void 0;
}
if (contents.trim().length === 0) {
return typeof callback === "function" ? callback(null, null) : void 0;
}
if (csonCache && path.extname(objectPath) === '.cson') {
cachePath = getCachePath(contents);
return fs.stat(cachePath, function(error, stat) {
if (stat != null ? stat.isFile() : void 0) {
return fs.readFile(cachePath, 'utf8', function(error, cached) {
var parsed;
try {
parsed = parseCacheContents(cached);
} catch (_error) {
error = _error;
try {
parseContents(objectPath, cachePath, contents, parseOptions, callback);
} catch (_error) {}
return;
}
return typeof callback === "function" ? callback(null, parsed) : void 0;
});
} else {
return parseContents(objectPath, cachePath, contents, parseOptions, callback);
}
});
} else {
return parseContents(objectPath, null, contents, parseOptions, callback);
}
};
})(this));
},
writeFile: function(objectPath, object, options, callback) {
var contents, error;
if (arguments.length < 4) {
callback = options;
options = {};
}
if (callback == null) {
callback = function() {};
}
try {
contents = this.stringifyPath(objectPath, object);
} catch (_error) {
error = _error;
callback(error);
return;
}
return fs.writeFile(objectPath, "" + contents + "\n", options, callback);
},
writeFileSync: function(objectPath, object, options) {
if (options == null) {
options = void 0;
}
return fs.writeFileSync(objectPath, "" + (this.stringifyPath(objectPath, object)) + "\n", options);
},
stringifyPath: function(objectPath, object, visitor, space) {
if (path.extname(objectPath) === '.cson') {
return this.stringify(object, visitor, space);
} else {
return JSON.stringify(object, void 0, 2);
}
},
stringify: function(object, visitor, space) {
if (space == null) {
space = 2;
}
if (CSON == null) {
CSON = require('cson-parser');
}
return CSON.stringify(object, visitor, space);
},
parse: function(str, reviver) {
if (CSON == null) {
CSON = require('cson-parser');
}
return CSON.parse(str, reviver);
},
getCacheHits: function() {
return stats.hits;
},
getCacheMisses: function() {
return stats.misses;
},
resetCacheStats: function() {
return stats = {
hits: 0,
misses: 0
};
}
};
detectDuplicateKeys = function(key, value) {
if (this.hasOwnProperty(key) && this[key] !== value) {
throw new Error("Duplicate key '" + key + "'");
} else {
return value;
}
};
}).call(this);