2020-05-29 22:22:00 +02:00
|
|
|
// Copyright 2017-2018 Xuan Sang LE <xsang.le AT gmail DOT com>
|
|
|
|
|
|
|
|
// AnTOS Web desktop is is licensed under the GNU General Public
|
|
|
|
// License v3.0, see the LICENCE file for more information
|
|
|
|
|
|
|
|
// This program is free software: you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
|
|
|
// published by the Free Software Foundation, either version 3 of
|
|
|
|
// the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// General Public License for more details.
|
|
|
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
//along with this program. If not, see https://www.gnu.org/licenses/.
|
2021-04-14 15:17:13 +02:00
|
|
|
type VFSFileHandleClass = { new(...args: any[]): OS.API.VFS.BaseFileHandle };
|
2020-05-29 22:22:00 +02:00
|
|
|
interface String {
|
2020-06-18 17:09:00 +02:00
|
|
|
/**
|
|
|
|
* Convert a string to VFS file handle.
|
|
|
|
*
|
|
|
|
* This function will create a file handle object from the string
|
|
|
|
* with the help of [[VFS.findHandles]]
|
|
|
|
*
|
|
|
|
* @returns {OS.API.VFS.BaseFileHandle}
|
|
|
|
* @memberof String
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
asFileHandle(): OS.API.VFS.BaseFileHandle;
|
|
|
|
}
|
|
|
|
namespace OS {
|
|
|
|
export namespace API {
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* User permission data type
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @interface UserPermissionType
|
|
|
|
*/
|
|
|
|
export interface UserPermissionType {
|
|
|
|
read: boolean;
|
|
|
|
write: boolean;
|
|
|
|
exec: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* VFS file meta-data data type
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @interface FileInfoType
|
|
|
|
*/
|
|
|
|
export interface FileInfoType {
|
2020-06-18 17:09:00 +02:00
|
|
|
/**
|
|
|
|
* File mime type
|
|
|
|
*
|
|
|
|
* @type {string}
|
|
|
|
* @memberof FileInfoType
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
mime: string;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* File size
|
|
|
|
*
|
|
|
|
* @type {number}
|
|
|
|
* @memberof FileInfoType
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
size: number;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* File name
|
|
|
|
*
|
|
|
|
* @type {string}
|
|
|
|
* @memberof FileInfoType
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
name: string;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* File path
|
|
|
|
*
|
|
|
|
* @type {string}
|
|
|
|
* @memberof FileInfoType
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
path: string;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* File type:
|
|
|
|
* - `file`
|
|
|
|
* - `dir`
|
|
|
|
* - `app`
|
|
|
|
*
|
|
|
|
* @type {string}
|
|
|
|
* @memberof FileInfoType
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
type: string;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* File permission
|
|
|
|
*
|
|
|
|
* @type {{
|
|
|
|
* group: UserPermissionType;
|
|
|
|
* owner: UserPermissionType;
|
|
|
|
* other: UserPermissionType;
|
|
|
|
* }}
|
|
|
|
* @memberof FileInfoType
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
perm?: {
|
2020-06-18 17:09:00 +02:00
|
|
|
/**
|
|
|
|
* Group permission
|
|
|
|
*
|
|
|
|
* @type {UserPermissionType}
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
group: UserPermissionType;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Owner permission
|
|
|
|
*
|
|
|
|
* @type {UserPermissionType}
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
owner: UserPermissionType;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Other permission
|
|
|
|
*
|
|
|
|
* @type {UserPermissionType}
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
other: UserPermissionType;
|
|
|
|
};
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Creation time
|
|
|
|
*
|
|
|
|
* @type {string}
|
|
|
|
* @memberof FileInfoType
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
ctime?: string;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Modification time
|
|
|
|
*
|
|
|
|
* @type {string}
|
|
|
|
* @memberof FileInfoType
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
mtime?: string;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Group id
|
|
|
|
*
|
|
|
|
* @type {number}
|
|
|
|
* @memberof FileInfoType
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
gid?: number;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* User id
|
|
|
|
*
|
|
|
|
* @type {number}
|
|
|
|
* @memberof FileInfoType
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
uid?: number;
|
|
|
|
[propName: string]: any;
|
|
|
|
}
|
|
|
|
|
2020-06-18 17:09:00 +02:00
|
|
|
/**
|
|
|
|
* This namespace is dedicated to all APIs related to
|
|
|
|
* AntOS Virtual File System (VFS)
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
export namespace VFS {
|
2021-04-14 15:17:13 +02:00
|
|
|
declare var JSZip: any;
|
|
|
|
|
2020-05-29 22:22:00 +02:00
|
|
|
String.prototype.asFileHandle = function (): BaseFileHandle {
|
|
|
|
const list = this.split("://");
|
|
|
|
const handles = API.VFS.findHandles(list[0]);
|
|
|
|
if (!handles || handles.length === 0) {
|
|
|
|
announcer.osfail(
|
|
|
|
__("VFS unknown handle: {0}", this),
|
|
|
|
API.throwe("OS.VFS")
|
|
|
|
);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return new handles[0](this);
|
|
|
|
};
|
|
|
|
|
2020-06-18 17:09:00 +02:00
|
|
|
/**
|
|
|
|
* Placeholder stores VFS file protocol patterns and its attached file handle class.
|
|
|
|
*
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
export const handles: GenericObject<VFSFileHandleClass> = {};
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Register a protocol to a handle class
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @export
|
2020-06-18 17:09:00 +02:00
|
|
|
* @param {string} protos VFS protocol pattern
|
|
|
|
* @param {VFSFileHandleClass} cls handle class
|
2020-05-29 22:22:00 +02:00
|
|
|
*/
|
|
|
|
export function register(
|
|
|
|
protos: string,
|
|
|
|
cls: VFSFileHandleClass
|
|
|
|
): void {
|
|
|
|
handles[protos] = cls;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Looking for a attached file handle class of a string protocol
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* When converting a string to file handle, the system will look
|
|
|
|
* for a protocol pattern in the string, if the protocol found,
|
|
|
|
* its attached handle class (found in [[VFS.handles]]) will be
|
|
|
|
* used to initialize a file handle object from the string
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* ```typescript
|
|
|
|
* "home://data/test.txt".asFileHandle() // -> an instance of RemoteFileHandle
|
|
|
|
* ```
|
2020-05-29 22:22:00 +02:00
|
|
|
* @export
|
2020-06-18 17:09:00 +02:00
|
|
|
* @param {string} proto protocol string
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {VFSFileHandleClass[]}
|
|
|
|
*/
|
|
|
|
export function findHandles(proto: string): VFSFileHandleClass[] {
|
|
|
|
const l = (() => {
|
|
|
|
const result = [];
|
|
|
|
for (let k in handles) {
|
|
|
|
const v = handles[k];
|
|
|
|
if (proto.trim().match(new RegExp(k, "g"))) {
|
|
|
|
result.push(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
})();
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Abstract prototype of all all VFS file handle definition.
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This prototype provides a standardized interface to access
|
|
|
|
* to different underlay file systems such as remote file,
|
|
|
|
* cloud file (Dropbox, Google drive, etc.), URL or memory-based file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @abstract
|
|
|
|
* @class BaseFileHandle
|
|
|
|
*/
|
|
|
|
export abstract class BaseFileHandle {
|
2020-06-18 17:09:00 +02:00
|
|
|
/**
|
|
|
|
* Flag indicates whether the file is dirty
|
|
|
|
*
|
|
|
|
* @type {boolean}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
dirty: boolean;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Once read, file content will be cached in this placeholder
|
|
|
|
*
|
|
|
|
* @type {*}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
cache: any;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Flag indicated whether the file meta-data is loaded
|
|
|
|
*
|
|
|
|
* @type {boolean}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
ready: boolean;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* File path
|
|
|
|
*
|
|
|
|
* @type {string}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
path: string;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* File protocol e.g:
|
|
|
|
* - `os://`
|
|
|
|
* - `home://`
|
|
|
|
*
|
|
|
|
* @type {string}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
protocol: string;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* List of path segments
|
|
|
|
*
|
|
|
|
* @type {string[]}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
genealogy: string[];
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* File base name
|
|
|
|
*
|
|
|
|
* @type {string}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
basename: string;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Once loaded, [[ready]] will be set to true and
|
|
|
|
* file meta-data will be stored in this place holder
|
|
|
|
*
|
|
|
|
* @type {FileInfoType}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
info: FileInfoType;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* File extension
|
|
|
|
*
|
|
|
|
* @type {string}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
ext: string;
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* File type
|
|
|
|
* @type {string}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-04 17:49:48 +02:00
|
|
|
type: string;
|
2020-05-29 22:22:00 +02:00
|
|
|
/**
|
|
|
|
*Creates an instance of BaseFileHandle.
|
2020-06-18 17:09:00 +02:00
|
|
|
* @param {string} path file path
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
constructor(path: string) {
|
|
|
|
this.dirty = false;
|
|
|
|
this.cache = undefined;
|
|
|
|
this.setPath(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Set a file path to the current file handle
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @param {string} p
|
|
|
|
* @returns {void}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
setPath(p: string): void {
|
|
|
|
this.ready = false;
|
|
|
|
if (!p) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.path = p.toString();
|
|
|
|
const list = this.path.split("://");
|
|
|
|
this.protocol = list[0];
|
|
|
|
if (!(list.length > 1)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const re = list[1].replace(/^\/+|\/+$/g, "");
|
|
|
|
if (re === "") {
|
|
|
|
return;
|
|
|
|
}
|
2021-04-17 20:11:00 +02:00
|
|
|
this.genealogy = re.split("/").filter(s=> s!="");
|
|
|
|
this.path = this.genealogy.join("/");
|
2020-05-29 22:22:00 +02:00
|
|
|
if (!this.isRoot()) {
|
|
|
|
this.basename = this.genealogy[
|
|
|
|
this.genealogy.length - 1
|
|
|
|
];
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
this.basename.lastIndexOf(".") !== 0 &&
|
|
|
|
this.basename.indexOf(".") !== -1
|
|
|
|
) {
|
|
|
|
this.ext = this.basename.split(".").pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Getter: Get the file basename
|
|
|
|
* Setter: set the file name
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {string}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-04 17:49:48 +02:00
|
|
|
get filename(): string {
|
2020-05-29 22:22:00 +02:00
|
|
|
if (!this.basename) {
|
|
|
|
return "Untitled";
|
|
|
|
}
|
|
|
|
return this.basename;
|
|
|
|
}
|
2020-06-18 17:09:00 +02:00
|
|
|
set filename(v: string) {
|
2020-06-04 17:49:48 +02:00
|
|
|
this.basename = v;
|
|
|
|
}
|
2020-05-29 22:22:00 +02:00
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Set data to the file cache
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @param {*} v data object
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {BaseFileHandle}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
setCache(v: any): BaseFileHandle {
|
|
|
|
this.cache = v;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Return the object itself
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {BaseFileHandle}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
asFileHandle(): BaseFileHandle {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Check whether the current file is the root of the file tree
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {boolean}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
isRoot(): boolean {
|
|
|
|
return !this.genealogy || this.genealogy.length === 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Check whether the current file is a hidden file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {boolean}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
isHidden(): boolean {
|
|
|
|
if (!this.basename) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return this.basename[0] === ".";
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Get hash number of the current file path
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {number}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
hash(): number {
|
|
|
|
if (!this.path) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return this.path.hash();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Convert the current file cache to Base64
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
|
|
|
* @param {string} t type of the file cache:
|
|
|
|
* - `object`
|
|
|
|
* - `mime type`
|
|
|
|
* @returns {(Promise<string | ArrayBuffer>)} promise on the converted data
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected b64(t: string): Promise<string | ArrayBuffer> {
|
2020-05-29 22:22:00 +02:00
|
|
|
// t is object or mime type
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const m = t === "object" ? "text/plain" : t;
|
|
|
|
if (!this.cache) {
|
|
|
|
return resolve("");
|
|
|
|
}
|
|
|
|
if (t === "object" || typeof this.cache === "string") {
|
|
|
|
let b64: string;
|
|
|
|
if (t === "object") {
|
|
|
|
b64 = JSON.stringify(
|
|
|
|
this.cache,
|
|
|
|
undefined,
|
|
|
|
4
|
|
|
|
).asBase64();
|
|
|
|
} else {
|
|
|
|
b64 = this.cache.asBase64();
|
|
|
|
}
|
|
|
|
b64 = `data:${m};base64,${b64}`;
|
|
|
|
return resolve(b64);
|
|
|
|
} else {
|
|
|
|
const reader = new FileReader();
|
|
|
|
reader.readAsDataURL(this.cache);
|
|
|
|
reader.onload = () => resolve(reader.result);
|
|
|
|
return (reader.onerror = (e) => reject(e));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Get the parent file handle of the current file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {BaseFileHandle}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
parent(): BaseFileHandle {
|
|
|
|
if (this.isRoot()) {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
this.protocol +
|
|
|
|
"://" +
|
|
|
|
this.genealogy
|
|
|
|
.slice(0, this.genealogy.length - 1)
|
|
|
|
.join("/")
|
|
|
|
).asFileHandle();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Load the file meta-data before performing
|
|
|
|
* any task
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @returns {Promise<FileInfoType>} a promise on file meta-data
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
onready(): Promise<FileInfoType> {
|
|
|
|
// read meta data
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
if (this.ready) {
|
|
|
|
return resolve(this.info);
|
|
|
|
}
|
|
|
|
return this.meta()
|
|
|
|
.then((d: RequestResult) => {
|
|
|
|
this.info = d.result as FileInfoType;
|
|
|
|
this.ready = true;
|
|
|
|
return resolve(d.result as FileInfoType);
|
|
|
|
})
|
|
|
|
.catch((e: Error) => reject(__e(e)));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Public read operation
|
|
|
|
*
|
|
|
|
* This function calls the [[_rd]] function to perform the operation.
|
|
|
|
*
|
|
|
|
* If the current file is a directory, then the operation
|
|
|
|
* will return the meta-data of all files inside of the directory.
|
|
|
|
* Otherwise, file content will be returned
|
|
|
|
*
|
|
|
|
* @param {string} t data type
|
|
|
|
* - jsonp: the response is an json object
|
|
|
|
* - script: the response is a javascript code
|
|
|
|
* - xml, html: the response is a XML/HTML object
|
|
|
|
* - text: plain text
|
|
|
|
* - binary
|
|
|
|
*
|
|
|
|
* @returns {Promise<any>} a promise on the file content
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
read(t?: string): Promise<any> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const r = await this.onready();
|
|
|
|
try {
|
|
|
|
const d = await this._rd(t);
|
|
|
|
return resolve(d);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
} catch (e_1) {
|
|
|
|
return reject(__e(e_1));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Write the file cache to the actual file
|
|
|
|
*
|
|
|
|
* This function calls the [[_wr]] function to perform the operation
|
|
|
|
*
|
|
|
|
* @param {string} t data type
|
|
|
|
* - `base64`
|
|
|
|
* - `object`
|
|
|
|
* - `mime type`
|
|
|
|
*
|
|
|
|
* @returns {Promise<RequestResult>} promise on the operation result
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
write(t: string): Promise<RequestResult> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const r: RequestResult = await this._wr(t);
|
|
|
|
announcer.ostrigger("VFS", {
|
|
|
|
m: "write",
|
|
|
|
file: this,
|
|
|
|
});
|
|
|
|
return resolve(r);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Sub-directory creation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function calls the [[_mk]] function to perform the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @param {string} d sub directory name
|
|
|
|
* @returns {Promise<RequestResult>} promise on the operation result
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
mk(d: string): Promise<RequestResult> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const r = await this.onready();
|
|
|
|
try {
|
|
|
|
const d_1 = await this._mk(d);
|
|
|
|
announcer.ostrigger("VFS", {
|
|
|
|
m: "mk",
|
|
|
|
file: this,
|
|
|
|
});
|
|
|
|
return resolve(d_1);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
} catch (e_1) {
|
|
|
|
return reject(__e(e_1));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Delete the file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function calls the [[_rm]] function to perform the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @returns {Promise<RequestResult>} promise on the operation result
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
remove(): Promise<RequestResult> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const r = await this.onready();
|
|
|
|
try {
|
|
|
|
const d = await this._rm();
|
|
|
|
announcer.ostrigger("VFS", {
|
|
|
|
m: "remove",
|
|
|
|
file: this,
|
|
|
|
});
|
|
|
|
return resolve(d);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
} catch (e_1) {
|
|
|
|
return reject(__e(e_1));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Upload a file to the current directory
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* Only work when the current file is a directory
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function calls the [[_up]] function to perform the operation
|
|
|
|
*
|
|
|
|
* @returns {Promise<RequestResult>} promise on the operation result
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
upload(): Promise<RequestResult> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const r = await this.onready();
|
|
|
|
try {
|
|
|
|
const d = await this._up();
|
|
|
|
announcer.ostrigger("VFS", {
|
|
|
|
m: "upload",
|
|
|
|
file: this,
|
|
|
|
});
|
|
|
|
return resolve(d);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
} catch (e_1) {
|
|
|
|
return reject(__e(e_1));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Share the file by publish it.
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* Only work with file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function calls the [[_pub]] function to perform the operation
|
|
|
|
*
|
|
|
|
* @returns {Promise<RequestResult>} promise on operation result
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
publish(): Promise<RequestResult> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const r = await this.onready();
|
|
|
|
try {
|
|
|
|
const d = await this._pub();
|
|
|
|
announcer.ostrigger("VFS", {
|
|
|
|
m: "publish",
|
|
|
|
file: this,
|
|
|
|
});
|
|
|
|
return resolve(d);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
} catch (e_1) {
|
|
|
|
return reject(__e(e_1));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Download the file.
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* Only work with file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function calls the [[_down]] function to perform the operation
|
|
|
|
*
|
|
|
|
* @returns {Promise<any>} Promise on the operation result
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
download(): Promise<any> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const r = await this.onready();
|
|
|
|
try {
|
|
|
|
const d = await this._down();
|
|
|
|
announcer.ostrigger("VFS", {
|
|
|
|
m: "download",
|
|
|
|
file: this,
|
|
|
|
});
|
|
|
|
return resolve(d);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
} catch (e_1) {
|
|
|
|
return reject(__e(e_1));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Move the current file to another location
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function calls the [[_mv]] function to perform the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @param {string} d destination location
|
|
|
|
* @returns {Promise<RequestResult>} promise on the operation result
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
move(d: string): Promise<RequestResult> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const r = await this.onready();
|
|
|
|
try {
|
|
|
|
const data = await this._mv(d);
|
|
|
|
announcer.ostrigger("VFS", {
|
|
|
|
m: "move",
|
|
|
|
file: d.asFileHandle(),
|
|
|
|
});
|
|
|
|
return resolve(data);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
} catch (e_1) {
|
|
|
|
return reject(__e(e_1));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Execute the current file.
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This action depends on each file protocol
|
|
|
|
*
|
|
|
|
* This function calls the [[_exec]] function to perform the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {Promise<any>}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
execute(): Promise<any> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const r = await this.onready();
|
|
|
|
try {
|
|
|
|
const d = await this._exec();
|
|
|
|
announcer.ostrigger("VFS", {
|
|
|
|
m: "execute",
|
|
|
|
file: this,
|
|
|
|
});
|
|
|
|
return resolve(d);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
} catch (e_1) {
|
|
|
|
return reject(__e(e_1));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Get an accessible link to the file
|
|
|
|
* that can be accessed from the browser
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {string}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
|
|
|
getlink(): string {
|
|
|
|
return this.path;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Helper function returns a promise on unsupported action
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @param {string} t action name
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected unsupported(t: string): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__(
|
|
|
|
"Action {0} is unsupported on: {1}",
|
|
|
|
t,
|
|
|
|
this.path
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Low level protocol-specific read operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function should be overridden on the file handle class
|
|
|
|
* that supports the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
|
|
|
* @param {string} t data type, see [[read]]
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _rd(t: string): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return this.unsupported("read");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Low level protocol-specific write operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function should be overridden by the file handle class
|
|
|
|
* that supports the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
|
|
|
* @param {string} t data type, see [[write]]
|
2020-05-29 22:22:00 +02:00
|
|
|
* @param {*} [d]
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _wr(t: string, d?: any): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return this.unsupported("write");
|
|
|
|
}
|
2020-06-18 17:09:00 +02:00
|
|
|
|
2020-05-29 22:22:00 +02:00
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Low level protocol-specific sub-directory creation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function should be overridden by the file handle class
|
|
|
|
* that supports the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
|
|
|
* @param {string} d sub directory name
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _mk(d: string): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return this.unsupported("mk");
|
|
|
|
}
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Low level protocol-specific delete operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function should be overridden by the file handle class
|
|
|
|
* that supports the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _rm(): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return this.unsupported("remove");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Low level protocol-specific move operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function should be overridden by the file handle class
|
|
|
|
* that supports the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
2020-05-29 22:22:00 +02:00
|
|
|
* @param {string} d
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _mv(d: string): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return this.unsupported("move");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Low level protocol-specific upload operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function should be overridden by the file handle class
|
|
|
|
* that supports the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _up(): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return this.unsupported("upload");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Low level protocol-specific download operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function should be overridden by the file handle class
|
|
|
|
* that supports the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {Promise<any>}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _down(): Promise<any> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return this.unsupported("download");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Low level protocol-specific execute operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function should be overridden by the file handle class
|
|
|
|
* that supports the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _exec(): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return this.unsupported("execute");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Low level protocol-specific share operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* This function should be overridden by the file handle class
|
|
|
|
* that supports the operation
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _pub(): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return this.unsupported("publish");
|
|
|
|
}
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Read the current file meta-data
|
|
|
|
*
|
|
|
|
* should be implemented by subclasses
|
|
|
|
*
|
|
|
|
* @abstract
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof BaseFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
abstract meta(): Promise<RequestResult>;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Remote file handle allows to perform file operation
|
|
|
|
* on AntOS remote server files. Its protocol is defined
|
|
|
|
* by the following pattern:
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* ```
|
|
|
|
* ^(home|desktop|os|Untitled)$
|
|
|
|
* ```
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @class RemoteFileHandle
|
|
|
|
* @extends {BaseFileHandle}
|
|
|
|
*/
|
2020-06-03 23:43:08 +02:00
|
|
|
export class RemoteFileHandle extends BaseFileHandle {
|
2020-06-18 17:09:00 +02:00
|
|
|
/**
|
|
|
|
*Creates an instance of RemoteFileHandle.
|
|
|
|
* @param {string} path file path
|
|
|
|
* @memberof RemoteFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
constructor(path: string) {
|
|
|
|
super(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Read remote file meta-data
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof RemoteFileHandle
|
|
|
|
*/
|
|
|
|
meta(): Promise<RequestResult> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
2020-06-18 17:09:00 +02:00
|
|
|
const d = await API.handle.fileinfo(this.path);
|
2020-05-29 22:22:00 +02:00
|
|
|
if (d.error) {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__("{0}: {1}", d.error, this.path)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return resolve(d);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Remote file access link
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {string}
|
|
|
|
* @memberof RemoteFileHandle
|
|
|
|
*/
|
|
|
|
getlink(): string {
|
|
|
|
return API.handle.get + "/" + this.path;
|
|
|
|
}
|
|
|
|
|
2020-06-18 17:09:00 +02:00
|
|
|
/**
|
|
|
|
* Read remote file content.
|
|
|
|
*
|
|
|
|
* If the current file is a directory, then the operation
|
|
|
|
* will return the meta-data of all files inside of the directory.
|
|
|
|
* Otherwise, file content will be returned
|
|
|
|
*
|
|
|
|
* @protected
|
|
|
|
* @param {string} t data type see [[read]]
|
|
|
|
* @returns {Promise<any>}
|
|
|
|
* @memberof RemoteFileHandle
|
|
|
|
*/
|
|
|
|
protected _rd(t: string): Promise<any> {
|
2020-05-29 22:22:00 +02:00
|
|
|
// t: binary, text, any type
|
|
|
|
if (!this.info) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__(
|
|
|
|
"file meta-data not found: {0}",
|
|
|
|
this.path
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if (this.info.type === "dir") {
|
|
|
|
return API.handle.scandir(this.path);
|
|
|
|
}
|
|
|
|
//read the file
|
|
|
|
if (t === "binary") {
|
|
|
|
return API.handle.fileblob(this.path);
|
|
|
|
}
|
2020-06-18 17:09:00 +02:00
|
|
|
return API.handle.readfile(this.path, t ? t : "text");
|
2020-05-29 22:22:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Write file cache to the remote file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
|
|
|
* @param {string} t data type see [[write]]
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof RemoteFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _wr(t: string): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
// t is base64 or undefined
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
if (t === "base64") {
|
|
|
|
try {
|
|
|
|
const d = await API.handle.write(
|
|
|
|
this.path,
|
|
|
|
this.cache
|
|
|
|
);
|
|
|
|
if (d.error) {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__("{0}: {1}", d.error, this.path)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return resolve(d);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
const r = await this.b64(t);
|
|
|
|
try {
|
|
|
|
const result = await API.handle.write(
|
|
|
|
this.path,
|
|
|
|
r as string
|
|
|
|
);
|
|
|
|
if (result.error) {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__(
|
|
|
|
"{0}: {1}",
|
|
|
|
result.error,
|
|
|
|
this.path
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return resolve(result);
|
|
|
|
} catch (e_1) {
|
|
|
|
return reject(__e(e_1));
|
|
|
|
}
|
|
|
|
} catch (e_2) {
|
|
|
|
return reject(__e(e_2));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Create sub directory
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* Only work on directory file handle
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
|
|
|
* @param {string} d sub directory name
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof RemoteFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _mk(d: string): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
if (!this.info) {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__(
|
|
|
|
"file meta-data not found: {0}",
|
|
|
|
this.path
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if (this.info.type === "file") {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__("{0} is not a directory", this.path)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return API.handle
|
|
|
|
.mkdir(`${this.path}/${d}`)
|
|
|
|
.then((d) => {
|
|
|
|
if (d.error) {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__("{0}: {1}", d.error, this.path)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return resolve(d);
|
|
|
|
})
|
|
|
|
.catch((e) => reject(__e(e)));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Delete file/folder
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof RemoteFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _rm(): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const d = await API.handle.remove(this.path);
|
|
|
|
if (d.error) {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__("{0}: {1}", d.error, this.path)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return resolve(d);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Move file/folder
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
2020-05-29 22:22:00 +02:00
|
|
|
* @param {string} d
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof RemoteFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _mv(d: string): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
2020-06-18 17:09:00 +02:00
|
|
|
const r = await API.handle.move(this.path, d);
|
2020-05-29 22:22:00 +02:00
|
|
|
if (r.error) {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__("{0}: {1}", r.error, this.path)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return resolve(r);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Upload a file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* Only work with directory file handle
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof RemoteFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _up(): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
if (this.info.type !== "dir") {
|
|
|
|
return reject(
|
2020-06-18 17:09:00 +02:00
|
|
|
API.throwe(__("{0} is not a file", this.path))
|
2020-05-29 22:22:00 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
return API.handle
|
|
|
|
.upload(this.path)
|
|
|
|
.then((d) => {
|
|
|
|
if (d.error) {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__("{0}: {1}", d.error, this.path)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return resolve(d);
|
|
|
|
})
|
|
|
|
.catch((e) => reject(__e(e)));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Download a file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* only work with file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
2020-12-20 16:45:51 +01:00
|
|
|
* @returns {Promise<void>}
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof RemoteFileHandle
|
|
|
|
*/
|
2020-12-20 16:45:51 +01:00
|
|
|
protected _down(): Promise<void> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
if (this.info.type === "dir") {
|
|
|
|
return API.throwe(
|
|
|
|
__("{0} is not a file", this.path)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return API.handle
|
|
|
|
.fileblob(this.path)
|
|
|
|
.then((d) => {
|
|
|
|
const blob = new Blob([d], {
|
|
|
|
type: "octet/stream",
|
|
|
|
});
|
|
|
|
API.saveblob(this.basename, blob);
|
|
|
|
return resolve();
|
|
|
|
})
|
|
|
|
.catch((e) => reject(__e(e)));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Publish a file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof RemoteFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _pub(): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const d = await API.handle.sharefile(
|
|
|
|
this.path,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
if (d.error) {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__("{0}: {1}", d.error, this.path)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return resolve(d);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
register("^(home|desktop|os|Untitled)$", RemoteFileHandle);
|
|
|
|
|
2021-04-14 15:17:13 +02:00
|
|
|
|
2020-08-04 19:51:32 +02:00
|
|
|
/**
|
|
|
|
* Package file is remote file ([[RemoteFileHandle]]) located either in
|
|
|
|
* the local user packages location or system packages
|
|
|
|
* location, it should be in the following format:
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
* pkg://PKG_NAME/path/to/file
|
|
|
|
*
|
|
|
|
* ```
|
|
|
|
*
|
|
|
|
* The system will locale the package name PKG_NAME either in the system domain
|
|
|
|
* or in user domain and return the correct path to the package
|
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @class PackageFileHandle
|
|
|
|
* @extends {RemoteFileHandle}
|
|
|
|
*/
|
2021-04-14 15:17:13 +02:00
|
|
|
export class PackageFileHandle extends RemoteFileHandle {
|
2020-08-04 19:51:32 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
*Creates an instance of PackageFileHandle.
|
|
|
|
* @param {string} pkg_path package path in string
|
|
|
|
* @memberof PackageFileHandle
|
|
|
|
*/
|
|
|
|
constructor(pkg_path: string) {
|
2021-04-14 15:17:13 +02:00
|
|
|
var error: FormattedString | string;
|
2020-08-04 19:51:32 +02:00
|
|
|
var pkg_name: string;
|
|
|
|
super(pkg_path);
|
|
|
|
// now find the correct path
|
2021-04-14 15:17:13 +02:00
|
|
|
if (!this.genealogy || this.genealogy.length == 0) {
|
2020-08-04 19:51:32 +02:00
|
|
|
error = __("Invalid package path");
|
|
|
|
announcer.oserror(error, API.throwe(error));
|
|
|
|
throw new Error(error.__());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// get the correct path of the package
|
2020-08-04 20:00:34 +02:00
|
|
|
pkg_name = this.genealogy.shift();
|
2021-04-14 15:17:13 +02:00
|
|
|
if (OS.setting.system.packages[pkg_name]) {
|
2020-08-04 20:00:34 +02:00
|
|
|
this.setPath(OS.setting.system.packages[pkg_name].path + "/" + this.genealogy.join("/"));
|
2020-08-04 19:51:32 +02:00
|
|
|
}
|
2021-04-14 15:17:13 +02:00
|
|
|
else {
|
2020-08-04 19:51:32 +02:00
|
|
|
error = __("Package not found {0}", pkg_name);
|
2021-04-14 15:17:13 +02:00
|
|
|
announcer.oserror(error, API.throwe(error));
|
2020-08-04 19:51:32 +02:00
|
|
|
throw new Error(error.__());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
register("^pkg$", PackageFileHandle);
|
|
|
|
|
2020-05-29 22:22:00 +02:00
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Application file is an AntOS special file allowing to
|
|
|
|
* refer to an application as a regular file. Its protocol
|
|
|
|
* pattern is defined as:
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* ```typescript
|
|
|
|
* "^app$" // e.g. app://Setting
|
|
|
|
* ```
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @class ApplicationHandle
|
|
|
|
* @extends {BaseFileHandle}
|
|
|
|
*/
|
2020-06-03 23:43:08 +02:00
|
|
|
export class ApplicationHandle extends BaseFileHandle {
|
2020-05-29 22:22:00 +02:00
|
|
|
/**
|
|
|
|
*Creates an instance of ApplicationHandle.
|
2020-06-18 17:09:00 +02:00
|
|
|
* @param {string} path file path
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof ApplicationHandle
|
|
|
|
*/
|
|
|
|
constructor(path: string) {
|
|
|
|
super(path);
|
|
|
|
if (this.basename) {
|
2020-06-18 17:09:00 +02:00
|
|
|
let v: any = OS.setting.system.packages[this.basename];
|
2020-05-29 22:22:00 +02:00
|
|
|
v.type = "app";
|
|
|
|
v.mime = "antos/app";
|
|
|
|
v.size = 0;
|
|
|
|
this.info = v as FileInfoType;
|
|
|
|
}
|
|
|
|
this.ready = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Read application meta-data
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof ApplicationHandle
|
|
|
|
*/
|
|
|
|
meta(): Promise<RequestResult> {
|
|
|
|
return new Promise((resolve, reject) =>
|
|
|
|
resolve({
|
|
|
|
result: this.info,
|
|
|
|
error: false,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* If the current file is root (e.g. `app://`), the operation
|
|
|
|
* will return all system packages meta-data.
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* Otherwise, an error will be thrown
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
2020-05-29 22:22:00 +02:00
|
|
|
* @param {string} t
|
|
|
|
* @returns {Promise<any>}
|
|
|
|
* @memberof ApplicationHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _rd(t: string): Promise<any> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
if (this.info) {
|
|
|
|
return resolve({
|
|
|
|
result: this.info,
|
|
|
|
error: false,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if (!this.isRoot()) {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__("Application meta data isnt found")
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
const result = [];
|
|
|
|
for (let k in OS.setting.system.packages) {
|
|
|
|
const v = OS.setting.system.packages[k];
|
2021-04-14 15:17:13 +02:00
|
|
|
if (v.app) {
|
2020-08-04 19:51:32 +02:00
|
|
|
result.push(v);
|
|
|
|
}
|
2020-05-29 22:22:00 +02:00
|
|
|
}
|
|
|
|
return resolve({
|
|
|
|
result: result,
|
|
|
|
error: false,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
register("^app$", ApplicationHandle);
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* A buffer file handle represents a virtual file that is stored
|
|
|
|
* on the system memory. Its protocol pattern is defined as:
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* ```typescript
|
|
|
|
* "^mem$" // e.g. mem://test.txt
|
|
|
|
* ```
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @class BufferFileHandle
|
|
|
|
* @extends {BaseFileHandle}
|
|
|
|
*/
|
2020-06-03 23:43:08 +02:00
|
|
|
export class BufferFileHandle extends BaseFileHandle {
|
2020-06-18 17:09:00 +02:00
|
|
|
/**
|
|
|
|
*Creates an instance of BufferFileHandle.
|
|
|
|
* @param {string} path file path
|
|
|
|
* @param {string} mime file mime-type
|
|
|
|
* @param {*} data file data
|
|
|
|
* @memberof BufferFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
constructor(path: string, mime: string, data: any) {
|
|
|
|
super(path);
|
|
|
|
if (data) {
|
|
|
|
this.cache = data;
|
|
|
|
}
|
|
|
|
this.info = {
|
|
|
|
mime: mime,
|
|
|
|
path: path,
|
|
|
|
size: data ? data.length : 0,
|
|
|
|
name: this.basename,
|
|
|
|
type: "file",
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Read the file meta-data
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof BufferFileHandle
|
|
|
|
*/
|
|
|
|
meta(): Promise<RequestResult> {
|
|
|
|
return new Promise((resolve, reject) =>
|
|
|
|
resolve({
|
|
|
|
result: this.info,
|
|
|
|
error: false,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Read file content stored in the file cached
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
|
|
|
* @param {string} t data type see [[read]]
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<any>}
|
|
|
|
* @memberof BufferFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _rd(t: string): Promise<any> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise((resolve, reject) => {
|
2020-06-06 18:41:43 +02:00
|
|
|
return resolve(this.cache);
|
2020-05-29 22:22:00 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Write data to the file cache
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
|
|
|
* @param {string} t data type, see [[write]]
|
|
|
|
* @param {*} d data
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof BufferFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _wr(t: string, d: any): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
this.cache = d;
|
|
|
|
return new Promise((resolve, reject) =>
|
|
|
|
resolve({
|
|
|
|
result: true,
|
|
|
|
error: false,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Download the buffer file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
2020-12-20 16:45:51 +01:00
|
|
|
* @returns {Promise<void>}
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof BufferFileHandle
|
|
|
|
*/
|
2020-12-20 16:45:51 +01:00
|
|
|
protected _down(): Promise<void> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const blob = new Blob([this.cache], {
|
|
|
|
type: "octet/stream",
|
|
|
|
});
|
|
|
|
API.saveblob(this.basename, blob);
|
|
|
|
return resolve();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
API.VFS.register("^mem$", BufferFileHandle);
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* URL file handle represents a HTTP/HTTPs link url
|
|
|
|
* as an AntOS VFS file handle. Its protocol is defined as
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* ```
|
|
|
|
* ^(http|https|ftp)$
|
|
|
|
* ```
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @class URLFileHandle
|
|
|
|
* @extends {BaseFileHandle}
|
|
|
|
*/
|
2020-06-03 23:43:08 +02:00
|
|
|
export class URLFileHandle extends BaseFileHandle {
|
2020-06-18 17:09:00 +02:00
|
|
|
/**
|
|
|
|
*Creates an instance of URLFileHandle.
|
|
|
|
* @param {string} path
|
|
|
|
* @memberof URLFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
constructor(path: string) {
|
|
|
|
super(path);
|
|
|
|
this.ready = true;
|
|
|
|
this.info = {
|
|
|
|
path: path,
|
|
|
|
name: path,
|
|
|
|
mime: "url",
|
|
|
|
type: "url",
|
|
|
|
size: 0,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Read file meta-data
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof URLFileHandle
|
|
|
|
*/
|
|
|
|
meta(): Promise<RequestResult> {
|
|
|
|
return new Promise((resolve, reject) =>
|
|
|
|
resolve({
|
|
|
|
result: this.info,
|
|
|
|
error: false,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
2020-06-18 17:09:00 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Read URL content
|
|
|
|
*
|
|
|
|
* @protected
|
|
|
|
* @param {string} t data type see [[read]]
|
|
|
|
* @returns {Promise<any>}
|
|
|
|
* @memberof URLFileHandle
|
|
|
|
*/
|
|
|
|
protected _rd(t: string): Promise<any> {
|
2020-12-21 15:55:02 +01:00
|
|
|
//read the file
|
|
|
|
if (t === "binary") {
|
|
|
|
//return API.handle.fileblob(this.path);
|
2021-04-14 15:17:13 +02:00
|
|
|
return API.blob(this.path + "?_=" + new Date().getTime());
|
2020-12-21 15:55:02 +01:00
|
|
|
}
|
2020-05-29 22:22:00 +02:00
|
|
|
return API.get(this.path, t ? t : "text");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
API.VFS.register("^(http|https|ftp)$", URLFileHandle);
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Shared file handle represents all AntOS shared file.
|
|
|
|
* Its protocol is defined as:
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* ```
|
|
|
|
* ^shared$
|
|
|
|
* ```
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @class SharedFileHandle
|
|
|
|
* @extends {API.VFS.BaseFileHandle}
|
|
|
|
*/
|
2020-06-03 23:43:08 +02:00
|
|
|
export class SharedFileHandle extends API.VFS.BaseFileHandle {
|
2020-06-18 17:09:00 +02:00
|
|
|
/**
|
|
|
|
*Creates an instance of SharedFileHandle.
|
|
|
|
* @param {string} path file path
|
|
|
|
* @memberof SharedFileHandle
|
|
|
|
*/
|
2020-05-29 22:22:00 +02:00
|
|
|
constructor(path: string) {
|
|
|
|
super(path);
|
|
|
|
if (this.isRoot()) {
|
|
|
|
this.ready = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Read file meta-data
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof SharedFileHandle
|
|
|
|
*/
|
|
|
|
meta(): Promise<RequestResult> {
|
|
|
|
return API.handle.fileinfo(this.path);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Read file content
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
|
|
|
* @param {string} t data type, see [[read]]
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<any>}
|
|
|
|
* @memberof SharedFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _rd(t: string): Promise<any> {
|
2020-05-29 22:22:00 +02:00
|
|
|
if (this.isRoot()) {
|
2020-06-18 17:09:00 +02:00
|
|
|
return API.get(`${API.handle.shared}/all`, t);
|
2020-05-29 22:22:00 +02:00
|
|
|
}
|
|
|
|
//read the file
|
|
|
|
if (t === "binary") {
|
|
|
|
return API.handle.fileblob(this.path);
|
|
|
|
}
|
2020-06-18 17:09:00 +02:00
|
|
|
return API.handle.readfile(this.path, t ? t : "text");
|
2020-05-29 22:22:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* write data to shared file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
|
|
|
* @param {string} t data type, see [[write]]
|
|
|
|
* @param {string} d file data
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof SharedFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _wr(t: string, d: string): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
2020-06-18 17:09:00 +02:00
|
|
|
const r = await API.handle.write(this.path, d);
|
2020-05-29 22:22:00 +02:00
|
|
|
if (r.error) {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__("{0}: {1}", r.error, this.path)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return resolve(r);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Un-publish the file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof SharedFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _rm(): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const d = await API.handle.sharefile(
|
|
|
|
this.basename,
|
|
|
|
false
|
|
|
|
);
|
|
|
|
if (d.error) {
|
|
|
|
return reject(
|
|
|
|
API.throwe(
|
|
|
|
__("{0}: {1}", d.error, this.path)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return resolve(d);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Download shared file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
2020-12-20 16:45:51 +01:00
|
|
|
* @returns {Promise<void>}
|
2020-05-29 22:22:00 +02:00
|
|
|
* @memberof SharedFileHandle
|
|
|
|
*/
|
2020-12-20 16:45:51 +01:00
|
|
|
protected _down(): Promise<void> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
if (this.info.type === "dir") {
|
|
|
|
return reject(
|
2020-06-18 17:09:00 +02:00
|
|
|
API.throwe(__("{0} is not a file", this.path))
|
2020-05-29 22:22:00 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
return API.handle
|
|
|
|
.fileblob(this.path)
|
|
|
|
.then((data) => {
|
|
|
|
const blob = new Blob([data], {
|
|
|
|
type: "octet/stream",
|
|
|
|
});
|
|
|
|
API.saveblob(this.basename, blob);
|
|
|
|
return resolve();
|
|
|
|
})
|
|
|
|
.catch((e) => reject(__e(e)));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-06-18 17:09:00 +02:00
|
|
|
* Un publish the file
|
2020-05-29 22:22:00 +02:00
|
|
|
*
|
2020-06-18 17:09:00 +02:00
|
|
|
* @protected
|
2020-05-29 22:22:00 +02:00
|
|
|
* @returns {Promise<RequestResult>}
|
|
|
|
* @memberof SharedFileHandle
|
|
|
|
*/
|
2020-06-18 17:09:00 +02:00
|
|
|
protected _pub(): Promise<RequestResult> {
|
2020-05-29 22:22:00 +02:00
|
|
|
return new Promise((resolve, reject) =>
|
|
|
|
resolve({
|
|
|
|
result: this.basename,
|
|
|
|
error: false,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
API.VFS.register("^shared$", SharedFileHandle);
|
2021-04-14 15:17:13 +02:00
|
|
|
|
|
|
|
/**Utilities global functions */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Read a file content from a zip archive
|
|
|
|
*
|
|
|
|
* The content type should be:
|
|
|
|
* - base64 : the result will be a string, the binary in a base64 form.
|
|
|
|
* - text (or string): the result will be an unicode string.
|
|
|
|
* - binarystring: the result will be a string in “binary” form, using 1 byte per char (2 bytes).
|
|
|
|
* - array: the result will be an Array of bytes (numbers between 0 and 255).
|
|
|
|
* - uint8array : the result will be a Uint8Array. This requires a compatible browser.
|
|
|
|
* - arraybuffer : the result will be a ArrayBuffer. This requires a compatible browser.
|
2021-04-17 17:33:04 +02:00
|
|
|
* - blob : the result will be a Blob. This requires a compatible browser. *
|
2021-04-14 15:17:13 +02:00
|
|
|
* If file_name is not specified, the first file_name in the zip archive will be read
|
|
|
|
* @export
|
|
|
|
* @param {string} file zip file
|
|
|
|
* @param {string} type content type to read
|
|
|
|
* @param {string} [file_name] the file should be read from the zip archive
|
|
|
|
* @return {*} {Promise<any>}
|
|
|
|
*/
|
|
|
|
export function readFileFromZip(file: string, type: string, file_name?: string): Promise<any> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
await API.requires("os://scripts/jszip.min.js");
|
2021-04-17 17:33:04 +02:00
|
|
|
const data = await file.asFileHandle().read("binary");
|
|
|
|
const zip = await JSZip.loadAsync(data);
|
|
|
|
if (!file_name) {
|
|
|
|
for (let name in zip.files) {
|
|
|
|
file_name = name;
|
|
|
|
break;
|
2021-04-14 15:17:13 +02:00
|
|
|
}
|
|
|
|
}
|
2021-04-17 17:33:04 +02:00
|
|
|
const udata = await zip.file(file_name).async(type);
|
|
|
|
resolve(udata);
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
2021-04-14 15:17:13 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2021-04-17 17:33:04 +02:00
|
|
|
* Cat all files to a single out-put
|
2021-04-14 15:17:13 +02:00
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @param {string[]} list list of VFS files
|
|
|
|
* @param {string} data input data string that will be cat to the files content
|
2021-04-17 17:33:04 +02:00
|
|
|
* @param {string} join_by join on files content by this string
|
2021-04-14 15:17:13 +02:00
|
|
|
* @return {*} {Promise<string>}
|
|
|
|
*/
|
2021-04-17 17:33:04 +02:00
|
|
|
export function cat(list: string[], data: string, join_by: string = "\n"): Promise<string> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
2021-04-14 15:17:13 +02:00
|
|
|
if (list.length === 0) {
|
|
|
|
return resolve(data);
|
|
|
|
}
|
2021-04-17 17:33:04 +02:00
|
|
|
const promises = [];
|
|
|
|
for (const file of list) {
|
|
|
|
promises.push(file.asFileHandle().read("text"));
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
const results = await Promise.all(promises);
|
|
|
|
resolve(`${data}${join_by}${results.join(join_by)}`);
|
|
|
|
} catch (error) {
|
|
|
|
reject(__e(error));
|
|
|
|
}
|
2021-04-14 15:17:13 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2021-04-17 17:33:04 +02:00
|
|
|
* Read all files content on the list
|
2021-04-14 15:17:13 +02:00
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @param {string[]} list list of VFS files
|
|
|
|
* @param {GenericObject<string>[]} contents content array
|
2021-04-17 17:33:04 +02:00
|
|
|
* @return {void}
|
2021-04-14 15:17:13 +02:00
|
|
|
*/
|
2021-04-17 17:33:04 +02:00
|
|
|
export function read_files(list: string[]): Promise<GenericObject<string>[]> {
|
|
|
|
const promises = [];
|
|
|
|
for (const file of list) {
|
|
|
|
promises.push(file.asFileHandle().read("text"));
|
|
|
|
}
|
|
|
|
return Promise.all(promises);
|
2021-04-14 15:17:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Copy files to a folder
|
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @param {string[]} files list of files
|
|
|
|
* @param {string} to destination folder
|
2021-04-17 17:33:04 +02:00
|
|
|
* @return {*} {Promise<any[]>}
|
2021-04-14 15:17:13 +02:00
|
|
|
*/
|
2021-04-17 17:33:04 +02:00
|
|
|
export function copy(files: string[], to: string): Promise<any[]> {
|
|
|
|
const promises = [];
|
|
|
|
for (const path of files) {
|
|
|
|
promises.push(new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const file = path.asFileHandle();
|
|
|
|
const tof = `${to}/${file.basename}`.asFileHandle();
|
|
|
|
const meta = await file.onready();
|
2021-04-14 15:17:13 +02:00
|
|
|
if (meta.type === "dir") {
|
|
|
|
const desdir = to.asFileHandle();
|
2021-04-17 17:33:04 +02:00
|
|
|
await desdir.mk(file.basename);
|
|
|
|
const ret = await file.read();
|
|
|
|
const files = ret.result.map((v: API.FileInfoType) => v.path);
|
|
|
|
if (files.length > 0) {
|
|
|
|
await copy(files, `${desdir.path}/${file.basename}`);
|
|
|
|
resolve(undefined);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
resolve(undefined);
|
|
|
|
}
|
2021-04-14 15:17:13 +02:00
|
|
|
}
|
2021-04-17 17:33:04 +02:00
|
|
|
else {
|
|
|
|
const content = await file.read("binary");
|
|
|
|
await tof
|
|
|
|
.setCache(
|
|
|
|
new Blob([content], {
|
|
|
|
type: file.info.mime,
|
|
|
|
}))
|
|
|
|
.write(file.info.mime);
|
|
|
|
resolve(undefined);
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
reject(__e(error));
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
return Promise.all(promises);
|
2021-04-14 15:17:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add a list of files to the zip archive
|
|
|
|
*
|
|
|
|
* @param {string[]} list list of VFS files
|
|
|
|
* @param {*} zip JSZip handle
|
|
|
|
* @param {string} base root path of all added files in the zip
|
|
|
|
* @return {*} {Promise<any>}
|
|
|
|
*/
|
|
|
|
function aradd(list: string[], zip: any, base: string): Promise<any> {
|
2021-04-17 17:33:04 +02:00
|
|
|
const promises = [];
|
|
|
|
for (const path of list) {
|
|
|
|
promises.push(new Promise(async (resolve, reject) => {
|
|
|
|
const file = path.asFileHandle();
|
|
|
|
try {
|
|
|
|
const meta = await file.asFileHandle().onready();
|
|
|
|
if (meta.type == "dir") {
|
|
|
|
const ret = await file.read();
|
|
|
|
const dirs: string[] = ret.result.map((v: API.FileInfoType) => v.path);
|
|
|
|
if (dirs.length > 0) {
|
|
|
|
await aradd(dirs, zip, `${base}${file.basename}/`);
|
|
|
|
resolve(undefined);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
resolve(undefined);
|
|
|
|
}
|
2021-04-14 15:17:13 +02:00
|
|
|
}
|
2021-04-17 17:33:04 +02:00
|
|
|
else {
|
|
|
|
const u_data = await file.read("binary");
|
|
|
|
const z_path = `${base}${file.basename}`.replace(
|
|
|
|
/^\/+|\/+$/g,
|
|
|
|
""
|
|
|
|
);
|
|
|
|
zip.file(z_path, u_data, { binary: true });
|
|
|
|
resolve(undefined);
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
reject(__e(error));
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
return Promise.all(promises);
|
2021-04-14 15:17:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a zip archive from a folder
|
|
|
|
*
|
|
|
|
* @export
|
2021-04-17 17:33:04 +02:00
|
|
|
* @param {string} src source file/folder
|
2021-04-14 15:17:13 +02:00
|
|
|
* @param {string} dest destination archive
|
|
|
|
* @return {*} {Promise<void>}
|
|
|
|
*/
|
|
|
|
export function mkar(src: string, dest: string): Promise<void> {
|
2021-04-17 17:33:04 +02:00
|
|
|
console.log(src, dest);
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
await API.requires("os://scripts/jszip.min.js");
|
|
|
|
const zip = new JSZip();
|
|
|
|
const fhd = src.asFileHandle();
|
|
|
|
const meta = await fhd.onready();
|
|
|
|
if(meta.type === "file")
|
|
|
|
{
|
|
|
|
await aradd([src], zip, "/");
|
2021-04-14 15:17:13 +02:00
|
|
|
}
|
2021-04-17 17:33:04 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
const ret = await fhd.read();
|
|
|
|
await aradd(
|
|
|
|
ret.result.map((v: API.FileInfoType) => v.path), zip, "/");
|
|
|
|
}
|
|
|
|
const z_data = await zip.generateAsync({ type: "base64" });
|
|
|
|
await dest.asFileHandle()
|
|
|
|
.setCache("data:application/zip;base64," + z_data)
|
|
|
|
.write("base64");
|
|
|
|
resolve();
|
|
|
|
} catch (error) {
|
|
|
|
reject(__e(error));
|
|
|
|
}
|
2021-04-14 15:17:13 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a list of directories
|
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @param {string[]} list of directories to be created
|
2021-04-17 17:33:04 +02:00
|
|
|
* @param {boolen} sync sync/async of directory creation
|
|
|
|
* @return {*} {Promise<any>}
|
2021-04-14 15:17:13 +02:00
|
|
|
*/
|
2021-04-17 17:33:04 +02:00
|
|
|
export function mkdirAll(list: string[], sync?: boolean): Promise<any> {
|
|
|
|
if (!sync) {
|
|
|
|
const promises = [];
|
|
|
|
for (const dir of list) {
|
|
|
|
const path = dir.asFileHandle()
|
|
|
|
promises.push(path.parent().mk(path.basename));
|
2021-04-14 15:17:13 +02:00
|
|
|
}
|
2021-04-17 17:33:04 +02:00
|
|
|
return Promise.all(promises);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
if (list.length === 0) {
|
|
|
|
return resolve(true);
|
|
|
|
}
|
|
|
|
const dir = list.splice(0, 1)[0].asFileHandle();
|
|
|
|
const path = dir.parent();
|
|
|
|
const dname = dir.basename;
|
|
|
|
const r = await path.asFileHandle().mk(dname);
|
|
|
|
if (r.error) {
|
|
|
|
return reject(
|
|
|
|
this._api.throwe(
|
|
|
|
__(
|
|
|
|
"Cannot create {0}",
|
|
|
|
`${path}/${dir}`
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
await mkdirAll(list, sync);
|
|
|
|
resolve(true);
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
reject(__e(e));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2021-04-14 15:17:13 +02:00
|
|
|
}
|
|
|
|
|
2021-04-17 17:33:04 +02:00
|
|
|
|
|
|
|
|
2021-04-14 15:17:13 +02:00
|
|
|
/**
|
|
|
|
*
|
2021-04-17 17:33:04 +02:00
|
|
|
*
|
|
|
|
* @export Extract a zip fle
|
|
|
|
* @param {string} zfile zip file to extract
|
|
|
|
* @param {(zip:any) => Promise<string>} [dest_callback] a callback to get extraction destination
|
2021-04-14 15:17:13 +02:00
|
|
|
* @return {*} {Promise<void>}
|
|
|
|
*/
|
2021-04-17 17:33:04 +02:00
|
|
|
export function extractZip(zfile: string | API.VFS.BaseFileHandle, dest_callback: (zip: any) => Promise<string>): Promise<void> {
|
|
|
|
return new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
await API.requires("os://scripts/jszip.min.js");
|
|
|
|
const data = await zfile.asFileHandle().read("binary");
|
|
|
|
const zip = await JSZip.loadAsync(data);
|
|
|
|
const to = await dest_callback(zip);
|
|
|
|
const dirs = [];
|
|
|
|
const files = [];
|
|
|
|
for (const name in zip.files) {
|
|
|
|
const file = zip.files[name];
|
|
|
|
if (file.dir) {
|
|
|
|
dirs.push(to + "/" + name);
|
|
|
|
} else {
|
|
|
|
files.push(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
await mkdirAll(dirs, true);
|
|
|
|
const promises = [];
|
|
|
|
for (const file of files) {
|
|
|
|
promises.push(new Promise(async (res, rej) => {
|
|
|
|
try {
|
|
|
|
const data = await zip.file(file).async("uint8array");
|
|
|
|
const path = `${to}/${file}`;
|
|
|
|
const fp = path.asFileHandle();
|
|
|
|
fp.cache = new Blob([data], { type: "octet/stream" });
|
|
|
|
const r = await fp.write("text/plain");
|
|
|
|
if (r.error) {
|
|
|
|
return rej(
|
|
|
|
API.throwe(
|
|
|
|
__("Cannot extract file to {0}", path)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return resolve(res(path));
|
|
|
|
} catch (error) {
|
|
|
|
rej(__e(error));
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
await Promise.all(promises);
|
|
|
|
resolve();
|
|
|
|
} catch (e) {
|
|
|
|
return reject(__e(e));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2021-04-14 15:17:13 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Make files from a set of template files
|
|
|
|
*
|
|
|
|
* @export
|
|
|
|
* @param {Array<string[]>} list mapping paths between templates files and created files
|
|
|
|
* @param {string} path files destination
|
|
|
|
* @param {(data: string) => string} callback: pre-processing files content before writing to destination files
|
2021-04-17 17:33:04 +02:00
|
|
|
* @return {*} {Promise<any[]>}
|
2021-04-14 15:17:13 +02:00
|
|
|
*/
|
|
|
|
export function mktpl(
|
|
|
|
list: Array<string[]>,
|
|
|
|
path: string,
|
|
|
|
callback: (data: string) => string
|
2021-04-17 17:33:04 +02:00
|
|
|
): Promise<any[]> {
|
|
|
|
const promises = [];
|
|
|
|
for (const tpl of list) {
|
|
|
|
promises.push(new Promise(async (resolve, reject) => {
|
|
|
|
try {
|
|
|
|
const data = await `${path}/${tpl[0]}`.asFileHandle().read();
|
|
|
|
const file = tpl[1].asFileHandle();
|
|
|
|
file.setCache(callback(data));
|
|
|
|
await file.write("text/plain");
|
|
|
|
resolve(undefined);
|
|
|
|
} catch (error) {
|
|
|
|
reject(__e(error));
|
|
|
|
}
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
return Promise.all(promises);
|
2021-04-14 15:17:13 +02:00
|
|
|
}
|
2020-05-29 22:22:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|