-
-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🎨 Collect & simplify package utils (#8080)
closes #8056 🎨 Collect together the package-related utils - read directory actually reads a directory of packages - parse package json is very tighly related to this 🎨 Move filterPaths -> packages.filterPackages - this function is related to packages, not settings - move the function to the new utils/packages - add 100% test coverage 🎨 Simplify filterPackages code 🎨 Simplify reading of packages & themes - This massively reduces all the complex code in the read packages & themes utils - Added full test coverage 🎨 Improve & clarify active prop in filterPackages - active is returned from API endpoints to combine data from multiple sources - see #8064 (comment) 🎨 Better error handling 🔥 Temporarily remove custom error templates - we will reimplement this later when we have got a better concept of loading the active theme in place - refs #8079
- Loading branch information
Showing
13 changed files
with
747 additions
and
477 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
var _ = require('lodash'), | ||
notAPackageRegex = /^\.|_messages|README.md/i, | ||
filterPackages; | ||
|
||
/** | ||
* ### Filter Packages | ||
* Normalizes packages read by read-packages so that the apps and themes modules can use them. | ||
* Iterates over each package and return an array of objects which are simplified representations of the package | ||
* with 3 properties: | ||
* - `name` - the package name | ||
* - `package` - contents of the package.json or false if there isn't one | ||
* - `active` - set to true if this package is active | ||
* This data structure is used for listings of packages provided over the API and as such | ||
* deliberately combines multiple sources of information in order to be efficient. | ||
* | ||
* TODO: simplify the package.json representation to contain only fields we use | ||
* | ||
* @param {object} packages as returned by read-packages | ||
* @param {array/string} active as read from the settings object | ||
* @returns {Array} of objects with useful info about apps / themes | ||
*/ | ||
filterPackages = function filterPackages(packages, active) { | ||
// turn active into an array (so themes and apps can be checked the same) | ||
if (!Array.isArray(active)) { | ||
active = [active]; | ||
} | ||
|
||
return _.reduce(packages, function (result, pkg, key) { | ||
var item = {}; | ||
if (!key.match(notAPackageRegex)) { | ||
item = { | ||
name: key, | ||
package: pkg['package.json'] || false, | ||
active: _.indexOf(active, key) !== -1 | ||
}; | ||
|
||
result.push(item); | ||
} | ||
|
||
return result; | ||
}, []); | ||
}; | ||
|
||
module.exports = filterPackages; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/** | ||
* # Package Utils | ||
* | ||
* Ghost has / is in the process of gaining support for several different types of sub-packages: | ||
* - Themes: have always been packages, but we're going to lean more heavily on npm & package.json in future | ||
* - Adapters: an early version of apps, replace fundamental pieces like storage, will become npm modules | ||
* - Apps: plugins that can be installed whilst Ghost is running & modify behaviour | ||
* - More? | ||
* | ||
* These utils facilitate loading, reading, managing etc, packages from the file system. | ||
*/ | ||
|
||
module.exports = { | ||
read: require('./read-packages'), | ||
parsePackageJSON: require('./parse-package-json'), | ||
filterPackages: require('./filter-packages') | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/** | ||
* Dependencies | ||
*/ | ||
|
||
var parsePackageJson = require('./parse-package-json'), | ||
Promise = require('bluebird'), | ||
_ = require('lodash'), | ||
join = require('path').join, | ||
fs = require('fs'), | ||
|
||
notAPackageRegex = /^\.|_messages|README.md|node_modules|bower_components/i, | ||
packageJSONPath = 'package.json', | ||
|
||
statFile = Promise.promisify(fs.stat), | ||
readDir = Promise.promisify(fs.readdir), | ||
|
||
readPackage, | ||
readPackages, | ||
processPackage; | ||
|
||
/** | ||
* Recursively read directory and find the packages in it | ||
*/ | ||
processPackage = function processPackage(absolutePath, packageName) { | ||
var pkg = { | ||
name: packageName, | ||
path: absolutePath | ||
}; | ||
return parsePackageJson(join(absolutePath, packageJSONPath)) | ||
.then(function gotPackageJSON(packageJSON) { | ||
pkg['package.json'] = packageJSON; | ||
return pkg; | ||
}) | ||
.catch(function noPackageJSON() { | ||
// ignore invalid package.json for now, | ||
// because Ghost does not rely/use them at the moment | ||
// in the future, this .catch() will need to be removed, | ||
// so that error is thrown on invalid json syntax | ||
pkg['package.json'] = null; | ||
return pkg; | ||
}); | ||
}; | ||
|
||
readPackage = function readPackage(packagePath, packageName) { | ||
var absolutePath = join(packagePath, packageName); | ||
return statFile(absolutePath) | ||
.then(function (stat) { | ||
if (!stat.isDirectory()) { | ||
return {}; | ||
} | ||
|
||
return processPackage(absolutePath, packageName) | ||
.then(function gotPackage(pkg) { | ||
var res = {}; | ||
res[packageName] = pkg; | ||
return res; | ||
}); | ||
}) | ||
.catch(function () { | ||
return Promise.reject(new Error('Package not found')); | ||
}); | ||
}; | ||
|
||
readPackages = function readPackages(packagePath) { | ||
return readDir(packagePath) | ||
.filter(function (packageName) { | ||
// Filter out things which are not packages by regex | ||
if (packageName.match(notAPackageRegex)) { | ||
return; | ||
} | ||
// Check the remaining items to ensure they are a directory | ||
return statFile(join(packagePath, packageName)).then(function (stat) { | ||
return stat.isDirectory(); | ||
}); | ||
}) | ||
.map(function readPackageJson(packageName) { | ||
var absolutePath = join(packagePath, packageName); | ||
return processPackage(absolutePath, packageName); | ||
}) | ||
.then(function (packages) { | ||
return _.keyBy(packages, 'name'); | ||
}); | ||
}; | ||
|
||
/** | ||
* Expose Public API | ||
*/ | ||
module.exports.all = readPackages; | ||
module.exports.one = readPackage; |
Oops, something went wrong.