UNPKG

goldpankit

Version:

GoldPanKit是一款极速研发套件,可在套件中快速构建各类技术框架和项目。开源作者可发布自己的项目,并为其设定金额,实现开源项目的盈利。

284 lines (283 loc) 11 kB
const path = require('path') const Const = require('./constants/constants') const cache = require('./utils/cache') const object = require('./utils/object') const fs = require('./utils/fs') const pluginApi = require("./api/plugin"); const serviceTranslator = require('./service.translator') const serviceConf = require('./service.config') const serviceFile = require('./service.file') const userPluginApi = require('./api/user.plugin') const env = require('../env').getConfig() const ignore = require('ignore') module.exports = { /** * 删除插件 * dto = { * space: 空间名称, * service: 服务名称, * plugin: 插件名称 * } * @param dto */ deleteService (dto) { return new Promise((resolve, reject) => { userPluginApi.delete({ spaceName: dto.space, serviceName: dto.service, pluginName: dto.plugin }) .then(() => { cache.plugins.remove(dto.space, dto.service, dto.plugin) resolve() }) .catch(e => { reject(e) }) }) }, // 获取所有本地插件 getLocalPlugins () { return [...cache.plugins.getAll(), ...cache.services.getAll()] }, // 初始化 initialize(extConfig) { // 获取配置文件路径 const codespace = extConfig.codespace // 读取配置结构 const config = JSON.parse(JSON.stringify(Const.PLUGIN_CONFIG_CONTENT)) config.translator.output = Const.TRANSLATOR.DEFAULT_OUTPUT_PATH const configPath = this.__getConfigPath(codespace) // 合并配置 object.merge(extConfig, config) // 如果目标目录本身是一个服务,则直接用原来服务的配置信息,调整名称即可 if (fs.exists(configPath)) { const currentConfig = fs.readJSONFile(configPath) object.merge(currentConfig, config) } // 保留服务标识符和名称 config.name = extConfig.name config.label = extConfig.label || extConfig.name // 初始化服务文件 fs.createFile(configPath, fs.toJSONFileString(config), true) // 添加本地服务记录 cache.plugins.save({ space: extConfig.space, service: extConfig.service, name: extConfig.name, repository: extConfig.repository == null ? '' : extConfig.repository, codespace: extConfig.codespace }) }, // 获取插件简要信息 getProfile(spaceName, serviceName, pluginName) { // 读取本地服务配置 const pluginConfig = cache.plugins.get(spaceName, serviceName, pluginName) // 远程获取服务简介 return pluginApi.fetchProfile({ space: spaceName, service: serviceName, plugin: pluginName }) .then(data => { return { ...data, // 补充本地配置信息 local: pluginConfig == null ? null : { ...pluginConfig } } }) .catch(e => { return Promise.reject(e) }) }, // 获取服务配置信息 getPluginConfig(dto) { return serviceConf.getServiceConfig(dto) }, // 保存服务配置信息 savePluginConfig(dto) { const pluginConfig = this.getPluginConfig({ space: dto.space, service: dto.service, plugin: dto.plugin }) // 读取配置结构 const newConfig = JSON.parse(JSON.stringify(Const.PLUGIN_CONFIG_CONTENT)) // 合并配置 object .merge(pluginConfig, newConfig) .merge(dto, newConfig) // 写入配置文件 const configPath = this.__getConfigPath(pluginConfig.codespace) fs.rewrite(configPath, fs.toJSONFileString(newConfig)) // 保存服务repository if (dto.repository !== undefined) { cache.plugins.save({ space: dto.space, service: dto.service, name: dto.plugin, repository: dto.repository }) } }, // 获取服务文件树 getFileTree(space, service, plugin) { const pluginConfig = this.getPluginConfig({ space, service, plugin }) // 获取文件真实存放的路径 let fileStoragePath = pluginConfig.codespace if ((pluginConfig.translator.filepath != null && pluginConfig.translator.filepath !== '')|| (pluginConfig.translator.content != null && pluginConfig.translator.content !== '')) { fileStoragePath = path.join(fileStoragePath, pluginConfig.translator.output) if (!fs.exists(fileStoragePath)) { serviceTranslator.translate({ space, service, plugin }) return this.__getFileTree(fileStoragePath, fileStoragePath, pluginConfig.codespace) } } return this.__getFileTree(fileStoragePath, fileStoragePath, pluginConfig.codespace) }, // 保存服务文件 saveFileSetting (fileSettings) { const pluginConfig = cache.plugins.get(fileSettings.space, fileSettings.service, fileSettings.plugin) const configPath = this.__getConfigPath(pluginConfig.codespace) const config = fs.readJSONFile(configPath) // 读取配置结构 let settings = JSON.parse(JSON.stringify(Const.SERVICE_FILE_CONFIG_CONTENT)) object.merge(fileSettings, settings) // 修改path为relativePath settings.path = fileSettings.relativePath // 如果不存在配置信息,则将新文件配置添加到settings中 let targetFileSettings = config.settings.find(file => file.path === fileSettings.relativePath) if (targetFileSettings == null) { config.settings.push(settings) } // 如果存在文件配置,则使用Object.assign将最新配置写入原配置对象引用中,以实现增加配置项 else { Object.assign(targetFileSettings, settings) } fs.rewrite(configPath, fs.toJSONFileString(config)) }, // 保存变量 saveVariables (dto) { const plugin = cache.plugins.get(dto.space, dto.service, dto.plugin) const configPath = this.__getConfigPath(plugin.codespace) const config = fs.readJSONFile(configPath) config.variables = dto.variables fs.rewrite(configPath, fs.toJSONFileString(config)) }, // 发布服务版本 publish(dto) { // 获取服务文件 const pluginConfig = this.getPluginConfig({ space: dto.space, service: dto.service, plugin: dto.plugin }) let fileStoragePath = pluginConfig.codespace // 如果存在翻译器,自动翻译,且服务代码空间指定为翻译代码空间 if ((pluginConfig.translator.filepath != null && pluginConfig.translator.filepath !== '')|| (pluginConfig.translator.content != null && pluginConfig.translator.content !== '')) { fileStoragePath = path.join(fileStoragePath, Const.TRANSLATOR.DEFAULT_OUTPUT_PATH) serviceTranslator.translate({ space: dto.space, service: dto.service, plugin: dto.plugin }) } // 获取文件 let files = fs.getFilesWithChildren(fileStoragePath) // 验证文件数量 if (files.length > env.limitFiles) { return Promise.reject(`The number of files exceeds the limit of ${env.limitFiles}.`) } files = files.map(fullpath => { const filetype = fs.isDirectory(fullpath) ? 'DIRECTORY' : 'FILE' const relativePath = fs.getRelativePath(fullpath, fileStoragePath) const fileSetting = this.getFileSetting(pluginConfig.codespace, relativePath) const fileInfo = filetype === 'DIRECTORY' ? { encode: null, content: null } : fs.readFile(fullpath) return { filepath: relativePath, filetype, contentEncode: fileInfo.encode, content: fileInfo.content, compiler: fileSetting.compiler, variables: JSON.stringify(fileSetting.variables), enableExpress: fileSetting.enableExpress } }) // 执行发布 const publishParams = { space: dto.space, service: dto.service, plugin: dto.plugin, version: pluginConfig.version, withPrivate: pluginConfig.private, receivable: pluginConfig.receivable, prices: pluginConfig.prices, compiler: pluginConfig.compiler, supportedDatabases: pluginConfig.supportedDatabases.join(','), repository: pluginConfig.repository, builds: JSON.stringify(pluginConfig.builds), unbuilds: JSON.stringify(pluginConfig.unbuilds), variables: JSON.stringify(pluginConfig.variables), publishDescription: dto.publishDescription, introduce: pluginConfig.introduce, description: pluginConfig.readme, files } return pluginApi.publish(publishParams) }, // 获取文件设置 getFileSetting (codespace, fileRelativePath) { return serviceFile.getFileSetting(codespace, fileRelativePath) }, // 获取文件配置目录 __getConfigPath (codespace) { return serviceConf.__getConfigPath(codespace) }, /** * 获取文件树 * @param directoryPath 当前查询的目录路径 * @param fileStoragePath 真实服务代码空间路径(存在翻译器时真实代码空间不是codespace) * @param codespace 服务代码空间路径 * @param parentIgnoreInstance 上级文件忽略实例,用于在当前目录下没有配置.gitignore时使用 */ __getFileTree (directoryPath, fileStoragePath, codespace, parentIgnoreInstance = null) { let filePool = [] const files = fs.getFiles(directoryPath) /* 创建ignore实例 如果当前目录下没有.gitignore文件配置,则以父级的ignore实例作为当前目录的ignore实例 */ const ignoreFileConfig = fs.getIgnoreFileConfig(directoryPath) let ignoreInstance = parentIgnoreInstance if (ignoreInstance == null || ignoreFileConfig.ignoreFileConfig != null) { ignoreInstance = ignore().add(ignoreFileConfig.all) } files.forEach(file => { const fullpath = path.join(directoryPath, file) const fixedIgnoreInstance = ignore().add(Const.IGNORE_FILES) // 忽略目录,目录需要在路径后增加'/' if (fs.isDirectory(fullpath)) { if (fixedIgnoreInstance.ignores(file + '/')) { return } if (ignoreInstance != null && ignoreInstance.ignores(file + '/')) { return } } // 忽略文件 if (fixedIgnoreInstance.ignores(file)) { return } if (ignoreInstance != null && ignoreInstance.ignores(file)) { return } // 获取文件配置 const relativePath = fs.getRelativePath(fullpath, fileStoragePath, ignoreInstance) const fileSettings = this.getFileSetting(codespace, relativePath) // 构建文件对象 const isDirectory = fs.isDirectory(fullpath) const fileObject = { label: file, type: isDirectory ? 'DIRECTORY' : 'FILE', path: fullpath, relativePath, compiler: fileSettings.compiler, enableExpress: fileSettings.enableExpress, variables: fileSettings.variables, children: isDirectory ? [] : undefined } filePool.push(fileObject); if (fileObject.type === 'DIRECTORY') { fileObject.children = this.__getFileTree(fullpath, fileStoragePath, codespace); } }); return filePool } }