猫史档案馆


NomenFileSystem@1.7.0 : 基于SQL的文件与目录管理系统

用户:NomenNomen查看:2 回复:6 评论:2 创建时间:2023-05-18T12:32:06


这里是没有开场白的Nomen,我注意到很多场景下NomenSQLite不能很方便地处理一些公用数据或储存,同时我觉得神岛地文件系统过于限制,所以我写了一个基于SQL的文件与目录管理系统

-----------

请注意!NomenFileSystem1.0.0依赖于NomenSQLite1.2.0

请先使用此链接升级到1.2.0,否则会出现错误:

shequ.codemao.cn/wiki/forum/540732

-----------

 

NomenFileSystem本体:

class NomenFS {
    constructor() {
        if (!this.operator) this.operator = (new NomenSQLite()).operate('NomenFileSystemMain');
        if (NomenFS.instance) return NomenFS.instance;
    }
    static async launch() {
        if (NomenSQLite) var ns = NomenSQLite;
        else throw new Error('NomenSQLite不存在')
        let NSqlite = await ns.launch({
            'NomenFileSystemMain': [
                { name: 'type', type: ns.DataType.TEXT, notnull: true },
                { name: 'path', type: ns.DataType.TEXT, notnull: true },
                { name: 'parent', type: ns.DataType.TEXT, notnull: true },
                { name: 'creationdate', type: ns.DataType.TEXT, notnull: true },
                { name: 'property', type: ns.DataType.TEXT, notnull: true },
                { name: 'owner', type: ns.DataType.TEXT },
                { name: 'file', type: ns.DataType.TEXT },
            ]
        }, ns.LaunchAction.CREATE_OR_LAUNCH, (v, r) => { if (r) throw NomenFS.ErrorGenerator('0', r) });
        if (!this.instance) this.instance = new this();
        if (!this.operator) this.operator = NSqlite.operate('NomenFileSystemMain');
        return this.instance;
    }

    /** 静态方法 */
    static getInstance() {
        if (!this.instance) {
            this.instance = new NomenFS();
        }
        return this.instance;
    }
    static ErrorGenerator(errorcode, errMessage) {
        return new Error(`[NomenFileSystem: ErrorCode:${errorcode}] ${NomenFS.ErrorCode[errorcode]}${errMessage ? ' : ' + errMessage : ''}`)
    }
    static pathSolver(path) {
        if (typeof path == "string") {
            if (path.startsWith('.')) path = path.substring(1);
            if (!path.startsWith('/')) path = `/${path}`;
        }
        return path;
    }
    static filePropertyGenerator(property) {
        let init = {
            readonly: false,
        }
        Object.assign(init, property);
        return init;
    }

    /** 静态属性 */
    static fileType = {
        'file': 'file',
        'folder': 'folder'
    }
    static ErrorCode = {
        "-3": 'Must specify a file name or folder name',
        "-2": 'The file name must not contain the following characters:[  "/" ":" "?" """ "<" ">" "\'" "|" "\\" "*" "~"  ]',
        "-1": 'Incoming parameters do not match expectations',
        "0": 'Unexpected errors',
        "1": 'File does not exist',
        "2": 'Folder does not exist',
        "3": 'A file or folder with the same name already exists in the current location'
    }

    /** 实例方法 */
    _pathParser(path) {
        let p = path.split('/').slice(0, -1).join('/');
        let c = path.split('/').slice(-1);
        if (/[/:?"<>|~'\\*]/g.test(c)) throw NomenFS.ErrorGenerator("-2");
        if (!c.length) throw NomenFS.ErrorGenerator("-3");
        return { parentFolder: p.length ? p : '/', currentFile: c[0] }
    }
    async readFile(path) {
        if (typeof path != "string") throw NomenFS.ErrorGenerator("-1");
        let result = await NomenFS.operator.select('path', NomenFS.pathSolver(path));
        if (result.length) return result[0].file;
        else throw NomenFS.ErrorGenerator("1");
    }
    async writeFile(path, content, readonly = false) {
        path = NomenFS.pathSolver(path);
        if (typeof path != "string" || typeof content !== "string") throw NomenFS.ErrorGenerator("-1");
        let cpath = this._pathParser(path);
        let ctn = {
            type: NomenFS.fileType['file'],
            path,
            parent: cpath.parentFolder,
            creationdate: Date.now(),
            property: JSON.stringify(NomenFS.filePropertyGenerator({ readonly })),
            file: content,
        };
        let prt = await NomenFS.operator.select('path', cpath.parentFolder);
        if (!prt.length || prt[0].type != NomenFS.fileType['folder']) throw NomenFS.ErrorGenerator("2");
        let crt = await NomenFS.operator.select('path', path);
        if (crt.length && crt[0].type == NomenFS.fileType['folder']) throw NomenFS.ErrorGenerator("3");
        if (crt.length) await NomenFS.operator.update(`path="${path}"`, ctn)
        else await NomenFS.operator.insert(ctn);
        return path;
    }
    async mkdir(path, readonly = false) {
        path = NomenFS.pathSolver(path);
        if (typeof path != "string") throw this.ErrorGenerator("-1");
        let fd = await NomenFS.operator.select('path', path);
        let cpath = this._pathParser(path);
        if (fd.length && fd[0].type == NomenFS.fileType['file']) throw NomenFS.ErrorGenerator("3");
        if (!fd.length) {
            await NomenFS.operator.insert({
                type: NomenFS.fileType['folder'],
                path,
                parent: cpath.parentFolder,
                creationdate: Date.now(),
                property: JSON.stringify(NomenFS.filePropertyGenerator({ readonly })),
            });
            if(cpath.parentFolder) await this.mkdir(cpath.parentFolder)
        }
        return path;
    }
    async unlink(path) {
        if (typeof path != "string") throw NomenFS.ErrorGenerator("-1");
        return await NomenFS.operator.remove('path', NomenFS.pathSolver(path));
    }
    async readdir(path) {
        path = NomenFS.pathSolver(path);
        if (typeof path != "string") throw NomenFS.ErrorGenerator("-1");
        if (path == '/') return (await NomenFS.operator.select('parent', '/')).map(v => v.path);
        let parentFolder = await NomenFS.operator.select('path', path);
        if (!parentFolder.length) throw NomenFS.ErrorGenerator("2");
        if (parentFolder.length && parentFolder[0].type == NomenFS.fileType["file"]) throw NomenFS.ErrorGenerator("3");
        return (await NomenFS.operator.select('parent', path)).map(v => v.path);
    }
    async rmdir(path) {
        path = NomenFS.pathSolver(path);
        if (typeof path != "string") throw NomenFS.ErrorGenerator("-1");
        let targetFolder = await NomenFS.operator.select('path', path);
        if (!targetFolder.length) throw NomenFS.ErrorGenerator("2");
        let childFolder = await NomenFS.operator.select('parent', path);
        if (childFolder.length) {
            for (let i = 0; i < childFolder.length; i++) {
                if ((await NomenFS.operator.select('parent', childFolder[i].path)).length) await this.rmdir(childFolder[i].path);
                await NomenFS.operator.remove('path', childFolder[i].path);
            }
        }
        await NomenFS.operator.remove('path', path);
        return path;
    }
    async appendFile(path, content) {
        path = NomenFS.pathSolver(path);
        if (typeof path != "string") throw NomenFS.ErrorGenerator("-1");
        let tf = await NomenFS.operator.select('path', path);
        if (!tf.length) throw NomenFS.ErrorGenerator("1");
        if (tf[0].type == NomenFS.fileType["folder"]) throw NomenFS.ErrorGenerator("3");
        await this.writeFile(path, tf[0].file.concat(content));
        return path;
    }
    async rename(path, newname) {
        path = NomenFS.pathSolver(path);
        if (typeof path != "string") throw NomenFS.ErrorGenerator("-1");
        let tt = await NomenFS.operator.select('path', path);
        if (!tt.length) throw NomenFS.ErrorGenerator("1");
        if (tt[0].type == NomenFS.fileType["file"]) {
            await NomenFS.operator.update(`path=${path}`, { path: path.replace(/\/[^\/]*$/, '/' + newname) });
        } else if (tt[0].type == NomenFS.fileType["folder"]) {
            function cname(rname, match) {
                for (let i = 0; i < rname.length; i++) { if (match[i] && (match[i] != rname[i])) { rname[i] = match[i]; break; } }
                return rname;
            }
            function inpath(rname, match) {
                for (let i = 0; i < rname.length; i++) { if (match[i] && (match[i] != rname[i])) return true; }
                return false;
            }
            let allFile = await NomenFS.operator.select('*');
            for (let i = 0; i < allFile.length; i++) {
                if (!inpath(allFile[i].path.split('/').slice(1), path.split('/').slice(1))) {
                    console.log(allFile[i].path + ' // ' + `/${cname(allFile[i].path.split('/').slice(1), path.replace(/\/[^\/]*$/, '/' + newname).split('/').slice(1)).join('/')}`)
                    await NomenFS.operator.update(`path=${allFile[i].path}`, {
                        path: `/${cname(allFile[i].path.split('/').slice(1), path.replace(/\/[^\/]*$/, '/' + newname).split('/').slice(1)).join('/')}`,
                        parent: `/${cname(allFile[i].path.split('/').slice(1), path.replace(/\/[^\/]*$/, '/' + newname).split('/').slice(1)).join('/')}`
                    });
                }
            }
        }
        return path;
    }
}

API示例:(注:所有的函数都绑定在实例上,并且所有的函数都是异步函数)

/**
 * 读取文件内容
 * @param {string} path 路径
 */
ns.readFile('/src/playerData/nomen.json');

/**
 * 写入文件内容
 * @param {string} path 路径
 * @param {string} content 文本内容
 */
ns.writeFile('/src/playerData/nomen.json','"{name:\\"Nomen\\",coin:10},bag:[\\"By NomenTeam - Nomen\\",\\"EasyCoding\\"]"');

/**
 * 创建文件喵件夹路径,自动创建子文件夹
 */
ns.mkdir('/src/playerData');

/**
 * 删除文件
 * @param {string} path 路径
 */
ns.unlink('/src/playerData/nomen.json');

/**
 * 读取文件夹下的第一层子目录
 * @param {string} path 路径
 */
ns.readdir('/src/playerData');

/**
 * 删除文件夹
 * @param {string} path 路径
 */
ns.rmdir('/src/playerData');

/**
 * 将文本内容写入到文件的最后
 * @param {string} path 路径
 * @param {string} content 文本内容
 */
ns.appendFile('/usr/.config/NomenSQLiteConfig.env','tables = "{}"');

/**
 * 重命名文件或文件喵径
 * @param {string} newname 新名字
 */
ns.rename('/src/playerData/nomen.json','nomenyyds.json');


回复

上一页1 页 / 共 1下一页
NomenNomen

照例沙发

点赞0


评论


NomenNomen

EasyCoding项目 - EasyController 是由萌新大佬开发的一款便于管理文件,代码的便捷工具

快速开始:

/**
 * EasyController 是由萌新大佬开发的一款便于管理文件,代码的便捷工具
 * 此工具完全开源,免费试用,共所有人学习与参考
 * 建议单独设立文件使用,并首个require
 * @author 萌新大佬 <https://box3.codemao.cn/u/mxdlorzorz>
 * @version 1.0.0
 */

//init

const assetTypes ={
    'js':'代码',
    'image':'图片',
    'lut':'滤镜',
    'snow':'雪花纹样',
    'mesh':'模型',
    'sound':'音乐/音效',
    'directory':'文件夹',
};
!function init(){
    console.clear();
    console.log('EasyController加载中...');
    console.log(`检测到EasyController存储位置:[${__dirname||'.'}/${__filename}]`);
    console.log('[EasyController]整理文件中...');
    console.log('[EasyController]文件:');
    /**
     * @param {Box3AssetListEntry[]} asts
     */
    function dir(asts,deep){
        for(const ast of asts){
            var log='';
            for(let i=1;i<=deep;i++)log+='····';
            console.log(`${log}[${assetTypes[ast.type]}]${ast.path.split('/').pop()}`);
            if(ast.type==Box3AssetType.DIRECTORY)dir(resources.ls(ast.path),deep+1);
        }
    }
    dir(resources.ls('.'),1);
}();

//tools
function getFileName(){
    try{
        throw Error();
    }catch(err){
        return err.stack.split('\n').
        find(x=>x.includes('eval')).slice(13).split(':')[0];
    }
}
function getLine(){
    try{
        throw Error();
    }catch(err){
        return err.stack.split('\n').
        find(x=>x.includes('eval')).slice(13).split(':')[1];
    }
}

//logger

class Logger{
    /**
     * 为每个文件建立独立对话框
     * @param {boolean?} showLine 是否显示输出的行数,默认为false
     * @param {boolean?} showTime 是否显示输出的时间,默认为false
     */
    constructor(showLine,showTime){
        this.filename=getFileName();
        this.showLine=showLine||false;
        this.showTime=showTime||false;
        this.log(`[logger] ${this.filename}logger加载完毕`);
    }
    get preLog(){
        var log='';
        var d=new Date();
        if(this.showTime)log+=`[${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}]`;
        log+='['+this.filename;
        if(this.showLine)log+=':'+getLine();
        return log+']';
    }
    log(...args){
        return console.log(this.preLog,...args);
    }
    warn(...args){
        return console.warn(this.preLog,...args);
    }
    error(...args){
        return console.error(this.preLog,...args);
    }
    clear(){
        console.clear();
        console.log(`clear at ${this.preLog}`);
    }
}

//exports

module.exports={    
    Logger,
}

点赞0


评论


神岛吉吉喵神岛吉吉喵

emotion_编程猫_厉害了有没有打算把之前的教程做个合集吗?

点赞1


评论


追梦ez追梦ez

nb!!!

点赞0


评论


伴只狗头伴只狗头

nb 

点赞1


评论


Function函数Function函数

ddd

点赞1


评论