From 1daa6eda610192292a1fb71cd577bb2a082177c6 Mon Sep 17 00:00:00 2001 From: Hannah Wolfe Date: Wed, 9 Jun 2021 15:10:36 +0100 Subject: [PATCH] Improved typing in package-json - fixed type warnings - introduced explicit use of bluebird to help with type warnings and also make it clear when we're actually using Bluebird features --- ghost/package-json/lib/package-json.js | 41 +++++++++++++++++--------- ghost/package-json/lib/parse.js | 4 +-- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/ghost/package-json/lib/package-json.js b/ghost/package-json/lib/package-json.js index f3d7cabe69..cfcb3ce498 100644 --- a/ghost/package-json/lib/package-json.js +++ b/ghost/package-json/lib/package-json.js @@ -9,21 +9,28 @@ * */ const _ = require('lodash'); -const Promise = require('bluebird'); const fs = require('fs-extra'); const join = require('path').join; const errors = require('@tryghost/errors'); const parse = require('./parse'); +// Require bluebird with its own namespace and use it explicitly where we need additional features +const Bluebird = require('bluebird'); + const notAPackageRegex = /^\.|_messages|README.md|node_modules|bower_components/i; const packageJSONPath = 'package.json'; +/** + * @typedef {object} PackageList + * @typedef {object} Package + */ + /** * Recursively read directory and find the packages in it * * @param {string} absolutePath * @param {string} packageName - * @returns {object} + * @returns {Promise} */ async function processPackage(absolutePath, packageName) { const pkg = { @@ -47,20 +54,23 @@ async function processPackage(absolutePath, packageName) { /** * ### Filter Packages - * Normalizes packages read by read-packages so that the themes module can use them. + * Normalizes packages read by readPackages so that the themes module 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 + * + * @typedef {object} SimplePackage + * @prop {string} name - the package name + * @prop {object|boolean} package - contents of the package.json or false if there isn't one + * @prop {boolean} 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 themes + * @param {PackageList} packages object made up of packages keyed by name as returned by readPackages + * @param {array|string} [active] optional set of names of packages that are active + * @returns {Array} array of objects with useful info about themes */ function filter(packages, active) { // turn active into an array if it isn't one, so this function can deal with lists and one-offs @@ -87,6 +97,7 @@ function filter(packages, active) { /** * @param {string} packagePath * @param {string} packageName + * @returns {Promise} */ async function readPackage(packagePath, packageName) { const absolutePath = join(packagePath, packageName); @@ -113,18 +124,20 @@ async function readPackage(packagePath, packageName) { /** * @param {string} packagePath + * @returns {Promise} */ -function readPackages(packagePath) { - return Promise.resolve(fs.readdir(packagePath)) +async function readPackages(packagePath) { + return Bluebird.resolve(fs.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 fs.stat(join(packagePath, packageName)).then(function (stat) { - return stat.isDirectory(); - }); + return fs.stat(join(packagePath, packageName)) + .then(function (stat) { + return stat.isDirectory(); + }); }) .map(function readPackageJson(packageName) { const absolutePath = join(packagePath, packageName); diff --git a/ghost/package-json/lib/parse.js b/ghost/package-json/lib/parse.js index 1739fb96e8..0a81a081fe 100644 --- a/ghost/package-json/lib/parse.js +++ b/ghost/package-json/lib/parse.js @@ -1,4 +1,3 @@ -const Promise = require('bluebird'); const fs = require('fs-extra'); const errors = require('@tryghost/errors'); const tpl = require('@tryghost/tpl'); @@ -15,13 +14,14 @@ const messages = { * all the required fields * * @param {string} path + * @returns {Promise} */ async function parse(path) { let source; let json; try { - source = await fs.readFile(path); + source = await fs.readFile(path, {encoding: 'utf8'}); } catch (readError) { const err = new errors.IncorrectUsageError(); err.message = tpl(messages.couldNotReadPackage);