kit.program/kit/src/remote/index.js
2025-03-13 15:31:16 +08:00

239 lines
6.9 KiB
JavaScript

/**
* remote 模块用来处理远程仓库相关事务
*/
const path = require("path")
const fs = require("fs")
const JSON5 = require('json5')
const { pipeline, Transform} = require("stream/promises");
module.exports = class Remote {
constructor() {
// this.__init()
this.func_publish = require("./publish")
this.func_install = require("./install")
}
async init() {
this.webdav = await import("webdav");
const uConfig = await $context.get("uConfig");
if ( uConfig.get("remoteServer") ){
let server = uConfig.get("remoteServer");
$logger.info("server " + server)
if ( server.startsWith("webdav") ) {
server = "http" + server.substring(6)
}
if ( uConfig.get("remoteAuth") ) {
let up = uConfig.get("remoteAuth");
$logger.info("remoteAuth " + up)
up = up.split(":", 2)
this.client = this.webdav.createClient(
server,
{
username: up[0],
password: up[1]
}
);
} else {
this.client = this.webdav.createClient(
server
);
}
}
}
async check() {
if ( ! this.webdav ) {
$logger.info("webdav unable")
return false
}
if ( ! this.client ) {
$logger.info("client unable")
return false
}
try {
// Get directory contents
const directoryItems = await this.client.getDirectoryContents("/");
$logger.info("directoryItems", directoryItems)
// 是否包含 index.json ?
// 不包含尝试创建
// 包含了尝试下载
const indexJsonFile = this.getIndexJson( directoryItems );
$logger.info("indexJsonFile", indexJsonFile)
if ( indexJsonFile ) {
// 包含了尝试下载
// 下载有缓存
this.download(indexJsonFile)
$logger.info("download index")
} else {
// 不包含尝试创建
await this.affireRemoteStore()
$logger.info("affireRemoteStore")
}
return true
}catch ( e ) {
$logger.error("remote check 过程中出错", e)
console.error(e)
return false
}
}
/**
* 先对比时间和长度,有不同才会真正下载,否则使用本地缓存。
* 本地缓存路径即本地仓库路径
* @param rFile
*/
download(rFile){
const lFilePath = path.resolve($sConfig.getLocalStorePath(), rFile.filename);
if ( fs.existsSync( lFilePath ) ) {
const lFileInfo = fs.statSync(lFilePath);
if ( lFileInfo.size === rFile.length
&& lFileInfo.mtime === rFile.lastmod
) {
// 使用缓存
$logger.debug("use cache")
return true
}
}
// 下载并覆盖
// 不知道是同步还是异步
this.wDownload( rFile.filename, lFilePath );
}
async affireRemoteStore(){
// Get directory contents
const directoryItems = await this.client.getDirectoryContents("/");
// 是否包含 index.json ?
// 不包含尝试创建
// 包含了尝试下载
const indexJsonFile = this.getIndexJson( directoryItems );
if ( ! indexJsonFile ) {
// 创建 index
await this.client.putFileContents("/index.json", JSON5.stringify({
modules : [],
tmpls : [],
lists : []
}, null, 4) , { overwrite: false });
}
const modulesFolder = this.getFileInfoByName(directoryItems, "modules")
if ( ! modulesFolder ) {
// 创建文件夹
await this.client.createDirectory("/modules");
}
const tmplsFolder = this.getFileInfoByName(directoryItems, "tmpls")
if ( ! tmplsFolder ) {
// 创建文件夹
await this.client.createDirectory("/tmpls");
}
const listsFolder = this.getFileInfoByName(directoryItems, "lists")
if ( ! listsFolder ) {
// 创建文件夹
await this.client.createDirectory("/lists");
}
}
getIndexJson(items){
return this.getFileInfoByName( items, "index.json" );
}
getFileInfoByName(items, name){
if ( ! items || items.length < 1 ) {
return false;
}
for ( let item of items ) {
if ( item.basename === name ) {
return item;
}
}
return false;
}
async publish(localFile, remotePath){
return await this.func_publish( this , localFile, remotePath )
}
async install(id){
return this.func_install( this, id )
}
async wUpload(from, to, debug){
const totalSize = fs.statSync(from).size;
debug ? console.log("totalSize", totalSize) : null
const rs = fs.createReadStream( from );
let wSize = 0;
let rSize = 0;
rs.on("data", (r)=>{
rSize += r.length;
debug ? console.log("r", rSize * 100 / totalSize + "%") : null
})
const ws = this.client.createWriteStream(to)
ws.on("data", (r)=>{
wSize += r.length;
debug ? console.log("w ", wSize * 100 / totalSize + "%") : null
})
await pipeline( rs, ws);
debug ? console.log("finish") : null
}
async wDownload(from, to){
$logger.info("download", from, to )
const stat = await this.client.stat(from);
const totalSize = stat.size;
let wSize = 0;
let rSize = 0;
const rs = this.client.createReadStream(from);
rs.on("data", (r)=>{
rSize += r.length;
// console.log("r", rSize * 100 / totalSize)
})
const ws = fs.createWriteStream(to);
ws.on("data", (r)=>{
wSize += r.length;
// console.log("w", wSize * 100 / totalSize)
})
return await pipeline(
rs, ws
)
}
async wMkdir(folder){
const folderfather = path.dirname( folder );
if ( ! await this.client.exists( folderfather ) ) {
// await remote.client.createDirectory( folderfather )
await this.wMkdir( folderfather )
}
if ( await this.client.exists( folder ) ) {
return
} else {
await this.client.createDirectory( folder )
}
}
async wGetModuleInfo(id){
let meta = await this.client.getFileContents("/modules/" + id + "/meta.json", { format: "text" });
let metaJson = JSON5.parse( meta );
return metaJson
}
}