代码拉取完成,页面将自动刷新
const fs = require('fs');
const path = require('path')
const crypto = require('crypto');
const ini = require('ini');
const chalk = require('chalk');
const low = require('lowdb');
const FileSync = require('lowdb/adapters/FileSync');
const process = require('./process');
const { confirm, search } = require('@inquirer/prompts');
const { DEFAULT_SERVICE_PARAMS, DATATYPES, ENVRC, SUPOS_DIR_NAME, SUPOS_DIR, SUPOS_SERVICES, SUPOS_EXTENSIONS, SUPOS_WORK_DIR } = require('./constants');
const moment = require('moment');
const {find,filter,toLower,reduce,map,pick} = require("lodash")
const SUPOSDBRC = path.join(SUPOS_DIR, 'db.json');
const log = require('debug')("suphelps");
let logDebug = log;
const operate = {
PULL: "pull",
PUSH: "push",
DEBUG: "debug"
}
async function readFile(file) {
logDebug("readfile:%s", file)
return new Promise(resolve => {
if (!fs.existsSync(file)) {
resolve({});
} else {
try {
const content = ini.parse(fs.readFileSync(file, 'utf-8'));
resolve(content);
} catch (error) {
exit(error);
}
}
});
}
function isVersionLessThan4(versionString) {
// 提取版本号主要部分
const match = versionString.match(/V(\d+\.\d+\.\d+\.\d+)/);
if (!match) return false; // 如果无法匹配版本号格式,返回false
const version = match[1];
const parts = version.split('.').map(Number);
// 比较主版本号
return parts[0] <= 4;
}
function getPlatformDBRC(platform) {
const PLATFORMDBRC = path.join(SUPOS_DIR, platform, 'db.json')
return PLATFORMDBRC;
}
async function getPlatformDB(platform) {
const PLATFORMDBRC = path.join(SUPOS_DIR, platform, 'db.json')
return await dynamicLowdb(PLATFORMDBRC, 'template init')
}
async function getConfigDB() {
const PLATFORMDBRC = path.join(SUPOS_DIR, 'db.json')
const ConfigDB = await dynamicLowdb(PLATFORMDBRC, 'template init')
return ConfigDB;
}
async function writeFile(path, content) {
logDebug("writeFile:%s,%o", path, content)
return new Promise(resolve => {
try {
fs.writeFileSync(path, ini.stringify(content));
resolve();
} catch (error) {
exit(error);
}
});
}
async function readJSONFile(file) {
logDebug("readJSONFile:%s", file)
return new Promise(resolve => {
if (!fs.existsSync(file)) {
resolve({});
} else {
try {
const content = JSON.parse(fs.readFileSync(file, 'utf-8'));
resolve(content);
} catch (error) {
exit(error);
}
}
});
}
async function writeJSONFile(pathfile, content) {
logDebug("writeJSONFile:%s,%o", pathfile, content)
return new Promise(resolve => {
try {
let DIR = path.dirname(pathfile);
fs.mkdirSync(DIR, { recursive: true, });
fs.writeFileSync(pathfile, JSON.stringify(content));
resolve();
} catch (error) {
logDebug("error writeJSONFile: %o", error)
exit(error);
}
});
}
async function checkEnv(file, command) {
logDebug("checkEnv:%s,%s", file, command)
if (!SUPOS_WORK_DIR) {
throw chalk.red(`${chalk.yellow(process.cwd())} 及父目录下无法找到 ${SUPOS_DIR_NAME} 配置,请确认命令运行环境,或用 ${chalk.green('supos init')} 命令初始化插件工作环境。`)
}
if (!fs.existsSync(file)) {
throw chalk.red(`请使用 ${chalk.green(command)} 初始化配置! `)
}
fs.lstat(file,(err,fsStats)=>{
logDebug("checkEnv:%o", moment(fsStats.atimeMs).format('YYYY-MM-DD HH:mm:ss'))
})
}
function checkExistsFile(file) {
return fs.existsSync(file);
}
function padding(message = '', before = 1, after = 1) {
return new Array(before).fill(' ').join('') + message + new Array(after).fill(' ').join('');
}
function printSuccess(message) {
console.log(chalk.bgGreenBright(padding('SUCCESS')) + ' ' + message);
}
function printError(error) {
console.log(chalk.bgRed(padding('ERROR')) + ' ' + chalk.red(error));
}
function printMessages(messages) {
for (const message of messages) {
console.log(message);
}
}
function geneDashLine(message, length, separator = '-') {
const finalMessage = new Array(Math.max(2, length - message.length + 2)).join(separator);
return padding(chalk.dim(finalMessage));
}
async function dynamicLowdb(file, command, needCheck=true) {
let localFunLog = logDebug.extend("dynamicLowdb")
localFunLog("dynamicLowdb:%s", file)
if(needCheck){
await checkEnv(file, command);
}
//将建的db.json文件引入
const adapter = new FileSync(file);
//注册low数据库
const DB = low(adapter);
return DB;
}
function exit(error) {
error && printError(error);
process.exit(1);
}
async function getPlatFormCode() {
const DB = await getConfigDB()
const platform = DB.get("upstream").value();
logDebug("getPlatFormCode:%s", platform)
if (!platform) {
throw `未选择您的默认平台,请 ${chalk.green('supos remote login <code>')} 默认平台!`
}
return { platform, ConfigDB: DB };
}
async function confirmChoiceTemplate(DB) {
try {
const template = DB.get('config.currentTemplate').value();
if (!template) {
try {
const answer = await confirm({ message: '是否进行工作区的表单模版选择?' });
if (answer) {
return await getAllWorkTemplate(DB);
} else {
throw "未选择表单模板,无法进行操作!"
}
} catch (e) {
throw chalk.red("已退出!");
}
}
return template;
} catch (error) {
throw error
}
}
async function getAllWorkTemplate(DB,saveDB=true) {
try {
const templates = DB.get('templates').value();
if (templates.length) {
const choices = map(templates, template => ({
value: template.id,
name: [template.displayName, "(", template.enName, ")"].join(""),
description: template.displayName,
context: [toLower(template.enName), template.displayName].join("")
}));
const answer = await search({
message: '请选择工作区的表单模板!',
source: async (input, args) => {
if (input) {
return filter(choices, (choice) => choice.context.includes(input));
} else {
return choices;
}
},
}).catch((err) => { throw "已终止操作" });
const template = find(templates, template => template.id === answer);
if(saveDB){
DB.get('config').set('currentTemplate', template).write();
}
printSuccess('您选择了【' + chalk.green(template.displayName) + "】")
return template;
} else {
throw `请使用 ${chalk.green('template init')} 初始化表单模板`
}
} catch (e) {
console.debug(e)
throw "程序已退出!"
}
}
async function getAllLocalService(template, DB,check=true) {
const templateUUID = [template.namespace, template.enName].join("_");
const dbServices = DB.get(`services.${templateUUID}`).value();
if (!dbServices&&check) {
throw `本地工作区的表单模板下无任何服务,可以尝试 ${chalk.green('supos pull')} 拉取平台服务`;
}
return dbServices;
}
async function addEnv(newEnvObj) {
let localFunLog = logDebug.extend("addEnv")
try {
const envObj = await readFile(ENVRC);
localFunLog("原来的环境变量数据:%o", envObj)
Object.assign(envObj, newEnvObj);
localFunLog("新的环境变量数据:%o", envObj)
await writeFile(ENVRC, envObj);
require("dotenv").config({ override: true,path:ENVRC })
} catch (err) {
localFunLog("error 写入环境配置文件失败,新环境变量数据为: %o", newEnvObj)
throw "添加环境配置失败"
}
}
/**
* 检查是否登录且登录未过期
*
* @param {*} name
* @param {*} DB
* @returns
*/
async function checkLogin(name, DB) {
const ticketInfo = DB.get(`${name}.ticketInfo`).value();
if (ticketInfo) {
const isExpire = await checkLoginExpire(name, DB);
logDebug("isExpire:%s", isExpire)
if (isExpire) {
return ticketInfo;
} else {
throw `运行 ${chalk.green("supos remote login [code]")} 以重新登录!`
}
} else {
logDebug("%s没有登录", name)
throw `运行 ${chalk.green("supos remote login [code]")} 以重新登录!`
}
}
async function checkLoginExpire(name, DB) {
const ticketInfo = DB.get(`${name}.ticketInfo`).value()
if (ticketInfo) {
logDebug("checkLoginExpire:%s", ticketInfo)
return moment().isBefore(moment(ticketInfo.expireDate))
} else {
return false;
}
}
// 加密函数
function encrypt(text) {
require("dotenv").config({ override: true, path: ENVRC });
const secretKey = process.env.SECRETKEY;
// 生成一个随机的IV
const iv = crypto.randomBytes(16);
// 创建cipher实例
const cipher = crypto.createCipheriv('aes-128-cbc', Buffer.from(secretKey), iv);
// 加密数据
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
// 将IV和加密后的数据拼接起来返回
// 注意:这里使用简单的拼接,实际应用中可能需要更复杂的格式
// return Buffer.concat(iv.toString('hex'),encrypted).toString('hex');
return `${iv.toString('hex')}:${encrypted}`;
}
// 解密函数
function decrypt(text) {
require("dotenv").config({ override: true, path: ENVRC });
const secretKey = process.env.SECRETKEY;
// Buffer.from(text).toString('')
// 分割IV和加密后的数据
const [ivHex, encryptedText] = text.split(':');
const iv = Buffer.from(ivHex, 'hex');
// 创建decipher实例
const decipher = crypto.createDecipheriv('aes-128-cbc', Buffer.from(secretKey), iv);
// 解密数据
let decrypted = decipher.update(encryptedText, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
async function md5(content) {
// console.debug(content)
const hash = crypto.createHash('md5').update(content, 'utf8').digest('hex');
// console.log(hash,content.length);
return hash;
}
async function sha256(content) {
require("dotenv").config({ override: true });
const secretKey = process.env.SECRETKEY;
const hash = crypto.createHmac('sha256', secretKey).update(content).digest('hex');
//console.log(hash,content.length)
return hash;
}
async function envContextBuild() {
const secretKey = crypto.randomBytes(16).toString('hex');
let envObj = { IV: `${crypto.randomBytes(16).toString('hex')}`, SECRETKEY: `${secretKey.substring(0, secretKey.length / 2)}` };
return envObj;
}
async function printRemoteResp(resp, defaultMsg = "出现未知错误,请检查控制台输出!") {
if (resp.code === "600001010") {
console.log(chalk.red(`因:${resp.error},请使用 ${chalk.green('supos remote login')} 重新登录!`))
console.error(defaultMsg)
} else if (resp.code === 200) {
printSuccess("操作成功")
} else {
console.log(resp);
console.error(defaultMsg)
}
}
async function syncCloudServiceToLocal(templateEnName, serviceEnName, script) {
try {
const SERVICEADDR = path.join(SUPOS_SERVICES, `${process.env.platform}`, templateEnName, serviceEnName + ".js")
let dirname = path.dirname(SERVICEADDR);
fs.mkdirSync(dirname, { recursive: true });
fs.chmodSync(dirname, '700');
fs.writeFileSync(SERVICEADDR, script);
fs.chmodSync(SERVICEADDR, '600');
logDebug("syncCloudServiceToLocal path: %s", SERVICEADDR)
return 'success';
} catch (e) {
logDebug("syncCloudServiceToLocal error %s", e)
throw e;
}
}
function sortObjectKeys(obj) {
// 提取键,对键进行排序,并创建一个新对象,其中包含按排序顺序的键值对
return Object.keys(obj).sort().reduce((result, key) => {
result[key] = obj[key];
return result;
}, {});
}
async function readServiceFromLocal(templateEnName, serviceEnName) {
if (!templateEnName) {
throw "表单模板别名参数缺失"
}
if (!serviceEnName) {
throw "服务别名参数缺失"
}
const SERVICEADDR = path.join(SUPOS_SERVICES, `${process.env.platform}`, templateEnName, serviceEnName + ".js");
logDebug("readServiceFromLocal path: %s", SERVICEADDR)
if (checkExistsFile(SERVICEADDR)) {
return await fs.readFileSync(SERVICEADDR, { encoding: 'UTF-8' }, (err, data) => {
if (err) throw err;
return data;
});
} else {
return "";
}
}
async function getSeviceByEnName(enName, DB) {
const template = await confirmChoiceTemplate(DB);
const dbServices = await getAllLocalService(template, DB);
return find(dbServices, dbService => dbService.enName === enName);
}
module.exports = {
exit,
getAllLocalService,
printError,
printSuccess,
printMessages,
geneDashLine,
readFile,
readJSONFile,
writeFile,
writeJSONFile,
padding,
checkExistsFile,
dynamicLowdb,
checkEnv,
checkLogin,
checkLoginExpire,
confirmChoiceTemplate,
addEnv,
getPlatFormCode,
getAllWorkTemplate,
DEFAULT_SERVICE_PARAMS,
DATATYPES,
SUPOSDBRC,
SUPOS_DIR,
SUPOS_DIR_NAME,
SUPOS_SERVICES,
SUPOS_EXTENSIONS,
ENVRC,
getPlatformDB,
getPlatformDBRC,
syncCloudServiceToLocal,
readServiceFromLocal,
sortObjectKeys,
envContextBuild,
encrypt,
decrypt,
md5,
sha256,
printRemoteResp,
getConfigDB,
isVersionLessThan4,
operate
};
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。