UNPKG

vivo-hap-toolkit

Version:

A command line toolkit for developing Quick Apps.

150 lines (138 loc) 5.85 kB
const fs = require('fs') const path = require('path') const { colorconsole, KnownError } = require('@vivo-hap-toolkit/shared-utils') const { compileOptionsMeta } = require('@vivo-hap-toolkit/shared-utils/compilation-config') // 主包保留名 const MAIN_PKG_NAME = compileOptionsMeta.MAIN_PKG_NAME // 能使用rpks能力的调试器最低版本 const RPKS_SUPPORT_VERSION_FROM = 1040 /** * 验证项目配置正确 */ exports.validateProject = function validateProject(manifestFile, sourceRoot) { if (!fs.existsSync(manifestFile)) { colorconsole.throw( `请确认项目%projectDir%/${sourceRoot}/下存在manifest.json文件:${manifestFile}` ) throw new KnownError(`找不到 ${sourceRoot}/manifest.json`) } } /** * 验证项目的应用全局配置 * @param {String} src - 项目src * @param {Object} manifest - manifest 对象 * @param {Object} options - compileOptionsObject */ exports.validateManifest = function validateManifest(src, manifest, options) { const { subpackages } = manifest // 验证分包规则 if (!options.disableSubpackages && subpackages && subpackages.length > 0) { validateManifestSubpackages(src, subpackages) } } /** * 检查subpackages字段配置。 * 除subpackages字段指定的文件是打进非主包外,剩余文件都打进主包 * 主包与是独立包的非主包,都需要manifest文件 * @param {object[]} subpackages 分包列表: [{ name, resource, standalone, icon }] * @param {string} subpackages[].name 分包名字,必填,不能重复,且不能是"base"(这是主包保留名),只能是 数字字母_ 组成 * @param {string} subpackages[].resource 分包资源路径,必须为src下文件目录,不能重复,分包间不能有包含关系,只能是 数字字母_ 开头,数字字母_-/ 组成 * @param {boolean} subpackages[].standalone 是否独立包标识,是独立包则需要manifest文件,缺省为false; * @param {boolean} subpackages[].icon 分包icon,是独立包则需要icon,缺省则为应用的icon; */ function validateManifestSubpackages(src, subpackages) { // 分包名的校验规则 const nameReg = /^\w+$/ // 资源名的校验规则 const resourceReg = /^\w[\w-/]*$/ // 用以检测分包名是否重复 const nameList = [] // 用以检测分包资源路径是否重复 const resList = [] // i18n文件目录地址,不能作为分包 const i18nPath = path.join(src, 'i18n') let name = '' let resource = '' // 资源路径的具体文件路径 let resPath = '' let index = 0 /** * 检查当前资源路径与已校验过的资源路径是否有包含关系。 * * @param {string} resource - 当前要校验的资源 * @param {number} index - 当前要校验资源的序号 * @return {boolean} true/false - 存在/不存在 */ function checkPathInclusion(resource, currentIndex) { for (let i = 0, l = resList.length; i < l; i++) { const _res = resList[i] if (resource.startsWith(_res) || _res.startsWith(resource)) { colorconsole.throw( `第${currentIndex}分包的资源'${resource}'与第${i + 1}分包的资源'${_res}'有包含关系,请修改` ) return true } } return false } subpackages.forEach((subpkg, i) => { name = subpkg.name resource = subpkg.resource resPath = resource && path.join(src, resource) index = i + 1 if (!name) { colorconsole.throw(`第${index}分包的名字不能为空,请添加`) } else if (!nameReg.test(name)) { colorconsole.throw(`第${index}分包的名字'${name}'不合法,只能是数字字母下划线组成,请修改`) } else if (name === MAIN_PKG_NAME) { colorconsole.throw(`第${index}分包的名字'${name}'是主包保留名,请修改`) } else if (nameList.indexOf(name) > -1) { colorconsole.throw(`第${index}分包的名字'${name}'已存在,请修改`) } else { nameList.push(name) } if (!resource) { colorconsole.throw(`第${index}分包的资源名不能为空,请添加`) } else if (!resourceReg.test(resource)) { colorconsole.throw( `第${index}分包的资源名'${resource}'不合法,只能是 数字字母_ 开头,数字字母_-/ 组成,请修改` ) } else if (resList.indexOf(resource) > -1) { colorconsole.throw(`第${index}分包的资源'${resource}'已被使用,请修改`) } else if (!fs.existsSync(resPath)) { colorconsole.throw(`第${index}分包的资源'${resource}',文件目录'${resPath}'不存在,请修改`) } else if (resPath === i18nPath) { colorconsole.throw( `第${index}分包的资源'${resource}',文件目录'${resPath}',i18n文件目录不能作为分包,请修改` ) } else if (!checkPathInclusion(resource, index)) { resList.push(resource) } if (subpkg.standalone && subpkg.icon && !fs.existsSync(path.join(src, subpkg.icon))) { colorconsole.throw(`第${index}分包配置的icon不存在,请修改`) } }) colorconsole.warn( `项目已配置分包,若想使用分包功能,请确保平台版本 >= ${RPKS_SUPPORT_VERSION_FROM}` ) } /** * sitemap校验。 * @param {String} src - 项目src路径 * @param {Object} manifest - manifest内容 */ exports.valiedateSitemap = function valiedateSitemap(src, manifest) { const sitemap = path.join(src, 'sitemap.json') if (fs.existsSync(sitemap)) { const rules = require(sitemap).rules const pages = Object.keys(manifest.router.pages || {}) rules.forEach((i, idx) => { const page = i.page if (page !== '*' && !pages.includes(page)) { colorconsole.throw(`sitemap rules第${idx + 1}项配置错误,该page不存在:${page}`) } return page }) } }