mirror of
				https://github.com/lxsang/antos-frontend.git
				synced 2025-10-31 02:15:47 +01:00 
			
		
		
		
	Improvement on core API:
- improvement performance of some VFS utility API - Allow compress/extract zip file in Files - CodePad/Files/MarketPlace use some common system APIs instead of defining in-package functions
This commit is contained in:
		
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										457
									
								
								src/core/vfs.ts
									
									
									
									
									
								
							
							
						
						
									
										457
									
								
								src/core/vfs.ts
									
									
									
									
									
								
							| @@ -1770,9 +1770,7 @@ namespace OS { | |||||||
|              * - array: the result will be an Array of bytes (numbers between 0 and 255). |              * - 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. |              * - uint8array : the result will be a Uint8Array. This requires a compatible browser. | ||||||
|              * - arraybuffer : the result will be a ArrayBuffer. This requires a compatible browser. |              * - arraybuffer : the result will be a ArrayBuffer. This requires a compatible browser. | ||||||
|              * - blob : the result will be a Blob. This requires a compatible browser. |              * - blob : the result will be a Blob. This requires a compatible browser.             *  | ||||||
|              * - nodebuffer : the result will be a nodejs Buffer. This requires nodejs. |  | ||||||
|              *  |  | ||||||
|              * If file_name is not specified, the first file_name in the zip archive will be read |              * If file_name is not specified, the first file_name in the zip archive will be read | ||||||
|              * @export |              * @export | ||||||
|              * @param {string} file zip file |              * @param {string} file zip file | ||||||
| @@ -1784,9 +1782,7 @@ namespace OS { | |||||||
|                 return new Promise(async (resolve, reject) => { |                 return new Promise(async (resolve, reject) => { | ||||||
|                     try { |                     try { | ||||||
|                         await API.requires("os://scripts/jszip.min.js"); |                         await API.requires("os://scripts/jszip.min.js"); | ||||||
|                         try { |  | ||||||
|                         const data = await file.asFileHandle().read("binary"); |                         const data = await file.asFileHandle().read("binary"); | ||||||
|                             try { |  | ||||||
|                         const zip = await JSZip.loadAsync(data); |                         const zip = await JSZip.loadAsync(data); | ||||||
|                         if (!file_name) { |                         if (!file_name) { | ||||||
|                             for (let name in zip.files) { |                             for (let name in zip.files) { | ||||||
| @@ -1794,81 +1790,57 @@ namespace OS { | |||||||
|                                 break; |                                 break; | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                                 try { |  | ||||||
|                         const udata = await zip.file(file_name).async(type); |                         const udata = await zip.file(file_name).async(type); | ||||||
|                         resolve(udata); |                         resolve(udata); | ||||||
|                                 } catch (e_2) { |  | ||||||
|                                     return reject(__e(e_2)); |  | ||||||
|                                 } |  | ||||||
|                             } catch (e_1) { |  | ||||||
|                                 return reject(__e(e_1)); |  | ||||||
|                             } |  | ||||||
|                     } catch (e) { |                     } catch (e) { | ||||||
|                         return reject(__e(e)); |                         return reject(__e(e)); | ||||||
|                     } |                     } | ||||||
|                     } catch (e_3) { |  | ||||||
|                         return reject(__e(e_3)); |  | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |  | ||||||
|             /** |             /** | ||||||
|              * Cat al file to a single out-put |              * Cat all files to a single out-put | ||||||
|              * |              * | ||||||
|              * @export |              * @export | ||||||
|              * @param {string[]} list list of VFS files |              * @param {string[]} list list of VFS files | ||||||
|              * @param {string} data input data string that will be cat to the files content |              * @param {string} data input data string that will be cat to the files content | ||||||
|  |              * @param {string} join_by join on files content by this string | ||||||
|              * @return {*}  {Promise<string>} |              * @return {*}  {Promise<string>} | ||||||
|              */ |              */ | ||||||
|             export function cat(list: string[], data: string): Promise<string> { |             export function cat(list: string[], data: string, join_by: string = "\n"): Promise<string> { | ||||||
|                 return new Promise((resolve, reject) => { |                 return new Promise(async (resolve, reject) => { | ||||||
|                     if (list.length === 0) { |                     if (list.length === 0) { | ||||||
|                         return resolve(data); |                         return resolve(data); | ||||||
|                     } |                     } | ||||||
|                     const file = list.splice(0, 1)[0].asFileHandle(); |                     const promises = []; | ||||||
|                     return file |                     for (const file of list) { | ||||||
|                         .read() |                         promises.push(file.asFileHandle().read("text")); | ||||||
|                         .then((text: string) => { |                     } | ||||||
|                             data = data + "\n" + text; |                     try { | ||||||
|                             return cat(list, data) |                         const results = await Promise.all(promises); | ||||||
|                                 .then((d) => resolve(d)) |                         resolve(`${data}${join_by}${results.join(join_by)}`); | ||||||
|                                 .catch((e) => reject(__e(e))); |                     } catch (error) { | ||||||
|                         }) |                         reject(__e(error)); | ||||||
|                         .catch((e: Error) => reject(__e(e))); |                     } | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |  | ||||||
|             /** |             /** | ||||||
|              * Read all files content to on the list |              * Read all files content on the list | ||||||
|              * |              * | ||||||
|              * @export |              * @export | ||||||
|              * @param {string[]} list list of VFS files |              * @param {string[]} list list of VFS files | ||||||
|              * @param {GenericObject<string>[]} contents content array |              * @param {GenericObject<string>[]} contents content array | ||||||
|              * @return {*}  {Promise<GenericObject<string>[]>} |              * @return {void} | ||||||
|              */ |              */ | ||||||
|             export function read_files(list: string[], contents: GenericObject<string>[]): Promise<GenericObject<string>[]> { |             export function read_files(list: string[]): Promise<GenericObject<string>[]> { | ||||||
|                 return new Promise((resolve, reject) => { |                 const promises = []; | ||||||
|                     if (list.length === 0) { |                 for (const file of list) { | ||||||
|                         return resolve(contents); |                     promises.push(file.asFileHandle().read("text")); | ||||||
|                 } |                 } | ||||||
|                     const file = list.splice(0, 1)[0].asFileHandle(); |                 return Promise.all(promises); | ||||||
|                     return file |  | ||||||
|                         .read() |  | ||||||
|                         .then((text: string) => { |  | ||||||
|                             contents.push({ |  | ||||||
|                                 path: file.path, |  | ||||||
|                                 content: text |  | ||||||
|                             }); |  | ||||||
|                             return read_files(list, contents) |  | ||||||
|                                 .then((d) => resolve(d)) |  | ||||||
|                                 .catch((e) => reject(__e(e))); |  | ||||||
|                         }) |  | ||||||
|                         .catch((e: Error) => reject(__e(e))); |  | ||||||
|                 }); |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1878,71 +1850,45 @@ namespace OS { | |||||||
|              * @export |              * @export | ||||||
|              * @param {string[]} files list of files |              * @param {string[]} files list of files | ||||||
|              * @param {string} to destination folder |              * @param {string} to destination folder | ||||||
|              * @return {*}  {Promise<void>} |              * @return {*}  {Promise<any[]>} | ||||||
|              */ |              */ | ||||||
|             export function copy(files: string[], to: string): Promise<void> { |             export function copy(files: string[], to: string): Promise<any[]> { | ||||||
|                 return new Promise((resolve, reject) => { |                 const promises = []; | ||||||
|                     if (files.length === 0) { |                 for (const path of files) { | ||||||
|                         return resolve(); |                     promises.push(new Promise(async (resolve, reject) => { | ||||||
|                     } |  | ||||||
|                     const file = files.splice(0, 1)[0].asFileHandle(); |  | ||||||
|                     const tof = `${to}/${file.basename}`.asFileHandle(); |  | ||||||
|                     return file |  | ||||||
|                         .onready() |  | ||||||
|                         .then((meta: { type: string }) => { |  | ||||||
|                             if (meta.type === "dir") { |  | ||||||
|                                 // copy directory |  | ||||||
|                                 const desdir = to.asFileHandle(); |  | ||||||
|                                 return desdir |  | ||||||
|                                     .mk(file.basename) |  | ||||||
|                                     .then(() => { |  | ||||||
|                                         // read the dir content |  | ||||||
|                                         return file |  | ||||||
|                                             .read() |  | ||||||
|                                             .then((data: API.RequestResult) => { |  | ||||||
|                                                 const list = (data.result as API.FileInfoType[]).map( |  | ||||||
|                                                     (v) => v.path |  | ||||||
|                                                 ); |  | ||||||
|                                                 return copy( |  | ||||||
|                                                     list, |  | ||||||
|                                                     `${desdir.path}/${file.basename}` |  | ||||||
|                                                 ) |  | ||||||
|                                                     .then(() => { |  | ||||||
|                                                         return copy(files, to) |  | ||||||
|                                                             .then(() => resolve()) |  | ||||||
|                                                             .catch((e) => |  | ||||||
|                                                                 reject(__e(e)) |  | ||||||
|                                                             ); |  | ||||||
|                                                     }) |  | ||||||
|                                                     .catch((e) => reject(__e(e))); |  | ||||||
|                                             }) |  | ||||||
|                                             .catch((e: Error) => reject(__e(e))); |  | ||||||
|                                     }) |  | ||||||
|                                     .catch((e: Error) => reject(__e(e))); |  | ||||||
|                             } else { |  | ||||||
|                                 // copy file |  | ||||||
|                                 return file |  | ||||||
|                                     .read("binary") |  | ||||||
|                                     .then(async (data: ArrayBuffer) => { |  | ||||||
|                                         const d = await tof |  | ||||||
|                                             .setCache( |  | ||||||
|                                                 new Blob([data], { |  | ||||||
|                                                     type: file.info.mime, |  | ||||||
|                                                 }) |  | ||||||
|                                             ) |  | ||||||
|                                             .write(file.info.mime); |  | ||||||
|                         try { |                         try { | ||||||
|                                             await copy(files, to); |                             const file = path.asFileHandle(); | ||||||
|                                             return resolve(); |                             const tof = `${to}/${file.basename}`.asFileHandle(); | ||||||
|                                         } catch (e) { |                             const meta = await file.onready(); | ||||||
|                                             return reject(__e(e)); |                             if (meta.type === "dir") { | ||||||
|  |                                 const desdir = to.asFileHandle(); | ||||||
|  |                                 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 { | ||||||
|                                     .catch((e: Error) => reject(__e(e))); |                                     resolve(undefined); | ||||||
|                                 } |                                 } | ||||||
|                         }) |                             } | ||||||
|                         .catch((e: Error) => reject(__e(e))); |                             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); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             /** |             /** | ||||||
| @@ -1954,69 +1900,38 @@ namespace OS { | |||||||
|              * @return {*}  {Promise<any>} |              * @return {*}  {Promise<any>} | ||||||
|              */ |              */ | ||||||
|             function aradd(list: string[], zip: any, base: string): Promise<any> { |             function aradd(list: string[], zip: any, base: string): Promise<any> { | ||||||
|                 return new Promise((resolve, reject) => { |                 const promises = []; | ||||||
|                     if (list.length === 0) { |                 for (const path of list) { | ||||||
|                         return resolve(zip); |                     promises.push(new Promise(async (resolve, reject) => { | ||||||
|                     } |  | ||||||
|                     const path = list.splice(0, 1)[0]; |  | ||||||
|                         const file = path.asFileHandle(); |                         const file = path.asFileHandle(); | ||||||
|                     return file |                         try { | ||||||
|                         .onready() |                             const meta = await file.asFileHandle().onready(); | ||||||
|                         .then((meta: { type: string }) => { |                             if (meta.type == "dir") { | ||||||
|                             if (meta.type === "dir") { |                                 const ret = await file.read(); | ||||||
|                                 return file |                                 const dirs: string[] = ret.result.map((v: API.FileInfoType) => v.path); | ||||||
|                                     .read() |                                 if (dirs.length > 0) { | ||||||
|                                     .then( |                                     await aradd(dirs, zip, `${base}${file.basename}/`); | ||||||
|                                         (d: { |                                     resolve(undefined); | ||||||
|                                             result: |  | ||||||
|                                             | Iterable<unknown> |  | ||||||
|                                             | ArrayLike<unknown>; |  | ||||||
|                                         }) => { |  | ||||||
|                                             const l = (d.result as API.FileInfoType[]).map( |  | ||||||
|                                                 (v) => v.path |  | ||||||
|                                             ); |  | ||||||
|                                             return aradd( |  | ||||||
|                                                 l, |  | ||||||
|                                                 zip, |  | ||||||
|                                                 `${base}${file.basename}/` |  | ||||||
|                                             ) |  | ||||||
|                                                 .then(() => { |  | ||||||
|                                                     return aradd( |  | ||||||
|                                                         list, |  | ||||||
|                                                         zip, |  | ||||||
|                                                         base |  | ||||||
|                                                     ) |  | ||||||
|                                                         .then(() => resolve(zip)) |  | ||||||
|                                                         .catch((e) => |  | ||||||
|                                                             reject(__e(e)) |  | ||||||
|                                                         ); |  | ||||||
|                                                 }) |  | ||||||
|                                                 .catch((e) => reject(__e(e))); |  | ||||||
|                                 } |                                 } | ||||||
|                                     ) |                                 else { | ||||||
|                                     .catch((e: Error) => reject(__e(e))); |                                     resolve(undefined); | ||||||
|                             } else { |                                 } | ||||||
|                                 return file |                             } | ||||||
|                                     .read("binary") |                             else { | ||||||
|                                     .then(async (d: any) => { |                                 const u_data = await file.read("binary"); | ||||||
|                                         const zpath = `${base}${file.basename}`.replace( |                                 const z_path = `${base}${file.basename}`.replace( | ||||||
|                                     /^\/+|\/+$/g, |                                     /^\/+|\/+$/g, | ||||||
|                                     "" |                                     "" | ||||||
|                                 ); |                                 ); | ||||||
|                                         zip.file(zpath, d, { binary: true }); |                                 zip.file(z_path, u_data, { binary: true }); | ||||||
|                                         try { |                                 resolve(undefined); | ||||||
|                                             await aradd(list, zip, base); |  | ||||||
|                                             return resolve(zip); |  | ||||||
|                             } |                             } | ||||||
|                                         catch (e) { |                         } catch (error) { | ||||||
|                                             return reject(__e(e)); |                             reject(__e(error)); | ||||||
|                         } |                         } | ||||||
|                                     }) |                     })); | ||||||
|                                     .catch((e: Error) => reject(__e(e))); |  | ||||||
|                 } |                 } | ||||||
|                         }) |                 return Promise.all(promises); | ||||||
|                         .catch((e: Error) => reject(__e(e))); |  | ||||||
|                 }); |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -2024,57 +1939,36 @@ namespace OS { | |||||||
|              * Create a zip archive from a folder |              * Create a zip archive from a folder | ||||||
|              * |              * | ||||||
|              * @export |              * @export | ||||||
|              * @param {string} src source folder |              * @param {string} src source file/folder | ||||||
|              * @param {string} dest destination archive |              * @param {string} dest destination archive | ||||||
|              * @return {*}  {Promise<void>} |              * @return {*}  {Promise<void>} | ||||||
|              */ |              */ | ||||||
|             export function mkar(src: string, dest: string): Promise<void> { |             export function mkar(src: string, dest: string): Promise<void> { | ||||||
|                 return new Promise((resolve, reject) => { |                 console.log(src, dest); | ||||||
|                     return new Promise(async (r, e) => { |                 return new Promise(async (resolve, reject) => { | ||||||
|                     try { |                     try { | ||||||
|                         await API.requires("os://scripts/jszip.min.js"); |                         await API.requires("os://scripts/jszip.min.js"); | ||||||
|                             try { |  | ||||||
|                                 const d = await src.asFileHandle().read(); |  | ||||||
|                                 return r(d.result); |  | ||||||
|                             } catch (ex) { |  | ||||||
|                                 return e(__e(ex)); |  | ||||||
|                             } |  | ||||||
|                         } catch (ex_1) { |  | ||||||
|                             return e(__e(ex_1)); |  | ||||||
|                         } |  | ||||||
|                     }) |  | ||||||
|                         .then((files: API.FileInfoType[]) => { |  | ||||||
|                             return new Promise(async (r, e) => { |  | ||||||
|                         const zip = new JSZip(); |                         const zip = new JSZip(); | ||||||
|                                 try { |                         const fhd =  src.asFileHandle(); | ||||||
|                                     const z = await aradd( |                         const meta = await fhd.onready(); | ||||||
|                                         files.map((v: { path: any }) => v.path), |                         if(meta.type === "file") | ||||||
|                                         zip, |                         { | ||||||
|                                         "/" |                             await aradd([src], zip, "/"); | ||||||
|                                     ); |  | ||||||
|                                     return r(z); |  | ||||||
|                                 } catch (ex) { |  | ||||||
|                                     return e(__e(ex)); |  | ||||||
|                         } |                         } | ||||||
|                             }); |                         else | ||||||
|                         }) |                         { | ||||||
|                         .then((zip: any) => { |                             const ret = await fhd.read(); | ||||||
|                             return zip |                             await aradd( | ||||||
|                                 .generateAsync({ type: "base64" }) |                                 ret.result.map((v: API.FileInfoType) => v.path), zip, "/"); | ||||||
|                                 .then((data: string) => { |                         } | ||||||
|                                     return dest |                         const z_data = await zip.generateAsync({ type: "base64" }); | ||||||
|                                         .asFileHandle() |                         await dest.asFileHandle() | ||||||
|                                         .setCache( |                             .setCache("data:application/zip;base64," + z_data) | ||||||
|                                             "data:application/zip;base64," + data |                             .write("base64"); | ||||||
|                                         ) |  | ||||||
|                                         .write("base64") |  | ||||||
|                                         .then((r: any) => { |  | ||||||
|                         resolve(); |                         resolve(); | ||||||
|                                         }) |                     } catch (error) { | ||||||
|                                         .catch((e: Error) => reject(__e(e))); |                         reject(__e(error)); | ||||||
|                                 }); |                     } | ||||||
|                         }) |  | ||||||
|                         .catch((e) => reject(__e(e))); |  | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -2083,35 +1977,105 @@ namespace OS { | |||||||
|              * |              * | ||||||
|              * @export |              * @export | ||||||
|              * @param {string[]} list of directories to be created |              * @param {string[]} list of directories to be created | ||||||
|              * @return {*}  {Promise<void>} |              * @param {boolen} sync sync/async of directory creation | ||||||
|  |              * @return {*}  {Promise<any>} | ||||||
|              */ |              */ | ||||||
|             export function mkdirAll(list: string[]): Promise<void> { |             export function mkdirAll(list: string[], sync?: boolean): Promise<any> { | ||||||
|                 return new Promise((resolve, reject) => { |                 if (!sync) { | ||||||
|                     if (list.length === 0) { |                     const promises = []; | ||||||
|                         return resolve(); |                     for (const dir of list) { | ||||||
|  |                         const path = dir.asFileHandle() | ||||||
|  |                         promises.push(path.parent().mk(path.basename)); | ||||||
|  |                     } | ||||||
|  |                     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)); | ||||||
|                         } |                         } | ||||||
|                     const path = list.splice(0, 1)[0].asFileHandle(); |  | ||||||
|                     return path |  | ||||||
|                         .parent() |  | ||||||
|                         .mk(path.basename) |  | ||||||
|                         .then((d: any) => { |  | ||||||
|                             return mkdirAll(list) |  | ||||||
|                                 .then(() => resolve()) |  | ||||||
|                                 .catch((e) => reject(__e(e))); |  | ||||||
|                         }) |  | ||||||
|                         .catch((e: Error) => reject(__e(e))); |  | ||||||
|                     }); |                     }); | ||||||
|                 } |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|             /** |             /** | ||||||
|              * |              * | ||||||
|              * |              * | ||||||
|              * @export |              * @export Extract a zip fle | ||||||
|              * @param {Array<string[]>} list of templates mapping files |              * @param {string} zfile zip file to extract | ||||||
|              * @param {string} path path stored create files |              * @param {(zip:any) => Promise<string>} [dest_callback] a callback to get extraction destination | ||||||
|              * @param {string} name |  | ||||||
|              * @return {*}  {Promise<void>} |              * @return {*}  {Promise<void>} | ||||||
|              */ |              */ | ||||||
|  |             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)); | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |  | ||||||
|             /** |             /** | ||||||
|              * Make files from a set of template files |              * Make files from a set of template files | ||||||
| @@ -2120,35 +2084,28 @@ namespace OS { | |||||||
|              * @param {Array<string[]>} list mapping paths between templates files and created files |              * @param {Array<string[]>} list mapping paths between templates files and created files | ||||||
|              * @param {string} path files destination |              * @param {string} path files destination | ||||||
|              * @param {(data: string) => string} callback: pre-processing files content before writing to destination files |              * @param {(data: string) => string} callback: pre-processing files content before writing to destination files | ||||||
|              * @return {*}  {Promise<void>} |              * @return {*}  {Promise<any[]>} | ||||||
|              */ |              */ | ||||||
|             export function mktpl( |             export function mktpl( | ||||||
|                 list: Array<string[]>, |                 list: Array<string[]>, | ||||||
|                 path: string, |                 path: string, | ||||||
|                 callback: (data: string) => string |                 callback: (data: string) => string | ||||||
|             ): Promise<void> { |             ): Promise<any[]> { | ||||||
|                 return new Promise((resolve, reject) => { |                 const promises = []; | ||||||
|                     if (list.length === 0) { |                 for (const tpl of list) { | ||||||
|                         return resolve(); |                     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)); | ||||||
|                         } |                         } | ||||||
|                     const item = list.splice(0, 1)[0]; |                     })); | ||||||
|                     return `${path}/${item[0]}` |                 } | ||||||
|                         .asFileHandle() |                 return Promise.all(promises); | ||||||
|                         .read() |  | ||||||
|                         .then((data) => { |  | ||||||
|                             const file = item[1].asFileHandle(); |  | ||||||
|                             return file |  | ||||||
|                                 .setCache(callback(data)) |  | ||||||
|                                 .write("text/plain") |  | ||||||
|                                 .then(() => { |  | ||||||
|                                     return mktpl(list, path, callback) |  | ||||||
|                                         .then(() => resolve()) |  | ||||||
|                                         .catch((e) => reject(__e(e))); |  | ||||||
|                                 }) |  | ||||||
|                                 .catch((e: Error) => reject(__e(e))); |  | ||||||
|                         }) |  | ||||||
|                         .catch((e) => reject(__e(e))); |  | ||||||
|                 }); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -89,13 +89,9 @@ namespace OS { | |||||||
|                 .then(async (meta) => { |                 .then(async (meta) => { | ||||||
|                     try { |                     try { | ||||||
|                         await this.build(meta, true); |                         await this.build(meta, true); | ||||||
|                         try { |                         await this.run(meta); | ||||||
|                             return this.run(meta); |  | ||||||
|                         } catch (e) { |  | ||||||
|                             return this.logger().error(__("Unable to run project: {0}", e.stack)); |  | ||||||
|                         } |  | ||||||
|                     } catch (e_1) { |                     } catch (e_1) { | ||||||
|                         return this.logger().error(__("Unable to build project: {0}", e_1.stack)); |                         return this.logger().error(__("Unable to build and run project: {0}", e_1.stack)); | ||||||
|                     } |                     } | ||||||
|                 }) |                 }) | ||||||
|                 .catch((e) => this.logger().error(__("Unable to read meta-data: {0}", e.stack))); |                 .catch((e) => this.logger().error(__("Unable to read meta-data: {0}", e.stack))); | ||||||
| @@ -112,19 +108,13 @@ namespace OS { | |||||||
|                 .then(async (meta) => { |                 .then(async (meta) => { | ||||||
|                     try { |                     try { | ||||||
|                         await this.build(meta, false); |                         await this.build(meta, false); | ||||||
|                         try { |                         await API.VFS.mkar( | ||||||
|                             return API.VFS.mkar( |  | ||||||
|                             `${meta.root}/build/debug`, |                             `${meta.root}/build/debug`, | ||||||
|                             `${meta.root}/build/release/${meta.name}.zip` |                             `${meta.root}/build/release/${meta.name}.zip` | ||||||
|                         ); |                         ); | ||||||
|                         } catch (e) { |                         this.logger().info(__("Archive generate at: {0}", `${meta.root}/build/release/${meta.name}.zip`)); | ||||||
|                             return this.logger().error( |  | ||||||
|                                 __("Unable to create package archive: {0}", |  | ||||||
|                                     e.stack) |  | ||||||
|                             ); |  | ||||||
|                         } |  | ||||||
|                     } catch (e_1) { |                     } catch (e_1) { | ||||||
|                         return this.logger().error(__("Unable to build project: {0}", e_1.stack)); |                         return this.logger().error(__("Unable to release project: {0}", e_1.stack)); | ||||||
|                     } |                     } | ||||||
|                 }) |                 }) | ||||||
|                 .catch((e) => this.logger().error(__("Unable to read meta-data: {0}", e.stack))); |                 .catch((e) => this.logger().error(__("Unable to read meta-data: {0}", e.stack))); | ||||||
| @@ -253,14 +243,13 @@ namespace OS { | |||||||
|                 const core_lib = "os://packages/CodePad/libs/corelib.d.ts"; |                 const core_lib = "os://packages/CodePad/libs/corelib.d.ts"; | ||||||
|                 try { |                 try { | ||||||
|                     await this.load_corelib(core_lib); |                     await this.load_corelib(core_lib); | ||||||
|                     const arr = []; |                     const arr = await API.VFS.read_files(files); | ||||||
|                     API.VFS.read_files(files, arr).then((_result) => { |                     const libs: string[] = files.map((e) => e) | ||||||
|                         const libs: string[] = arr.map((e) => e.path) |  | ||||||
|                     libs.unshift(core_lib); |                     libs.unshift(core_lib); | ||||||
|                     const src_files: GenericObject<any> = {}; |                     const src_files: GenericObject<any> = {}; | ||||||
|                     src_files[core_lib] = AntOSDK.corelib["ts"]; |                     src_files[core_lib] = AntOSDK.corelib["ts"]; | ||||||
|                         for (const el of arr) { |                     for (const i in arr) { | ||||||
|                             src_files[el.path] = ts.createSourceFile(el.path, el.content, ts.ScriptTarget.Latest); |                         src_files[files[i]] = ts.createSourceFile(files[i], arr[i], ts.ScriptTarget.Latest); | ||||||
|                     } |                     } | ||||||
|                     let js_code = ""; |                     let js_code = ""; | ||||||
|                     const host = { |                     const host = { | ||||||
| @@ -298,9 +287,10 @@ namespace OS { | |||||||
|                         }); |                         }); | ||||||
|                         return reject(API.throwe(__("Typescript compile error"))); |                         return reject(API.throwe(__("Typescript compile error"))); | ||||||
|                     } |                     } | ||||||
|  |                     for (const file of files) { | ||||||
|  |                         this.logger().info(__("Compiled: {0}", file)); | ||||||
|  |                     } | ||||||
|                     resolve(js_code); |                     resolve(js_code); | ||||||
|                     }) |  | ||||||
|                         .catch((e) => { reject(__e(e)) }); |  | ||||||
|                 } catch (e) { |                 } catch (e) { | ||||||
|                     return reject(__e(e)); |                     return reject(__e(e)); | ||||||
|                 } |                 } | ||||||
| @@ -331,12 +321,12 @@ namespace OS { | |||||||
|                     const ts_list = meta.ts.map( |                     const ts_list = meta.ts.map( | ||||||
|                         (v: string) => `${meta.root.trimBy("/")}/${v}` |                         (v: string) => `${meta.root.trimBy("/")}/${v}` | ||||||
|                     ); |                     ); | ||||||
|                     Promise.all([ |                     const results = await Promise.all([ | ||||||
|                         this.compile_ts(ts_list), |                         this.compile_ts(ts_list), | ||||||
|                         this.compile_coffee(coffee_list) |                         this.compile_coffee(coffee_list) | ||||||
|                     ]).then((js_codes: string[]) => { |                     ]); | ||||||
|                         resolve(js_codes.join("\n")); |  | ||||||
|                     }).catch((e_1) => reject(__e(e_1))); |                     resolve(results.join("\n")); | ||||||
|                 } catch (e_2) { |                 } catch (e_2) { | ||||||
|                     return reject(__e(e_2)); |                     return reject(__e(e_2)); | ||||||
|                 } |                 } | ||||||
| @@ -358,14 +348,12 @@ namespace OS { | |||||||
|                 } |                 } | ||||||
|                 try { |                 try { | ||||||
|                     await this.verify_coffee(list.map((x: string) => x)); |                     await this.verify_coffee(list.map((x: string) => x)); | ||||||
|                     try { |  | ||||||
|                     const code = await API.VFS.cat(list, ""); |                     const code = await API.VFS.cat(list, ""); | ||||||
|                     const jsrc = CoffeeScript.compile(code); |                     const jsrc = CoffeeScript.compile(code); | ||||||
|                         this.logger().info(__("Compiled successful")); |                     for (const file of list) { | ||||||
|                         return resolve(jsrc); |                         this.logger().info(__("Compiled: {0}", file)); | ||||||
|                     } catch (e) { |  | ||||||
|                         return reject(__e(e)); |  | ||||||
|                     } |                     } | ||||||
|  |                     return resolve(jsrc); | ||||||
|                 } catch (e_1) { |                 } catch (e_1) { | ||||||
|                     return reject(__e(e_1)); |                     return reject(__e(e_1)); | ||||||
|                 } |                 } | ||||||
| @@ -382,30 +370,13 @@ namespace OS { | |||||||
|          * @memberof AntOSDK |          * @memberof AntOSDK | ||||||
|          */ |          */ | ||||||
|         private build(meta: GenericObject<any>, debug: boolean): Promise<void> { |         private build(meta: GenericObject<any>, debug: boolean): Promise<void> { | ||||||
|             const dirs = [ |  | ||||||
|                 `${meta.root}/build`, |  | ||||||
|                 `${meta.root}/build/debug`, |  | ||||||
|                 `${meta.root}/build/release`, |  | ||||||
|             ]; |  | ||||||
|             return new Promise(async (resolve, reject) => { |             return new Promise(async (resolve, reject) => { | ||||||
|                 try { |                 try { | ||||||
|                     await API.VFS.mkdirAll(dirs); |                     this.logger().info(__("Building the package", meta.name)); | ||||||
|                     try { |                     await API.VFS.mkdirAll([`${meta.root}/build`,]); | ||||||
|  |                     await API.VFS.mkdirAll([`${meta.root}/build/debug`, `${meta.root}/build/release`]); | ||||||
|                     const src = await this.compile(meta); |                     const src = await this.compile(meta); | ||||||
|                         let v: string; |                     let code = await API.VFS.cat(meta.javascripts.map(v => `${meta.root}/${v}`), src); | ||||||
|                         try { |  | ||||||
|                             let jsrc = await API.VFS.cat( |  | ||||||
|                                 (() => { |  | ||||||
|                                     const result = []; |  | ||||||
|                                     for (v of meta.javascripts) { |  | ||||||
|                                         result.push(`${meta.root}/${v}`); |  | ||||||
|                                     } |  | ||||||
|                                     return result; |  | ||||||
|                                 })(), |  | ||||||
|                                 src |  | ||||||
|                             ); |  | ||||||
|                             await new Promise<void>(async function (r, e) { |  | ||||||
|                                 let code = jsrc; |  | ||||||
|                     if (!debug) { |                     if (!debug) { | ||||||
|                         const options = { |                         const options = { | ||||||
|                             toplevel: true, |                             toplevel: true, | ||||||
| @@ -417,75 +388,37 @@ namespace OS { | |||||||
|                                 //beautify: true, |                                 //beautify: true, | ||||||
|                             }, |                             }, | ||||||
|                         }; |                         }; | ||||||
|                                     const result_1 = Terser.minify( |                         const result = Terser.minify(code, options); | ||||||
|                                         jsrc, |                         if (result.error) { | ||||||
|                                         options |  | ||||||
|                                     ); |  | ||||||
|                                     if (result_1.error) { |  | ||||||
|                             this.logger().error( |                             this.logger().error( | ||||||
|                                 __( |                                 __( | ||||||
|                                     "Unable to minify code: {0}", |                                     "Unable to minify code: {0}", | ||||||
|                                                 result_1.error |                                     result.error | ||||||
|                                 ) |                                 ) | ||||||
|                             ); |                             ); | ||||||
|                         } else { |                         } else { | ||||||
|                                         ({ code } = result_1); |                             code = result.code; | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                                 try { |                     if (code != "") | ||||||
|                                     const d = await `${meta.root}/build/debug/main.js` |                         await `${meta.root}/build/debug/main.js` | ||||||
|                             .asFileHandle() |                             .asFileHandle() | ||||||
|                             .setCache(code) |                             .setCache(code) | ||||||
|                             .write("text/plain"); |                             .write("text/plain"); | ||||||
|                                     return r(); |                     const txt = await API.VFS.cat(meta.css.map(v => `${meta.root}/${v}`), ""); | ||||||
|                                 } catch (ex) { |                     if (txt != "") | ||||||
|                                     return e(__e(ex)); |                         await `${meta.root}/build/debug/main.css` | ||||||
|                                 } |  | ||||||
|                             }); |  | ||||||
|                             await new Promise<void>(async (r, e) => { |  | ||||||
|                                 const txt = await API.VFS.cat( |  | ||||||
|                                     (() => { |  | ||||||
|                                         const result1 = []; |  | ||||||
|                                         for (v of meta.css) { |  | ||||||
|                                             result1.push(`${meta.root}/${v}`); |  | ||||||
|                                         } |  | ||||||
|                                         return result1; |  | ||||||
|                                     })(), |  | ||||||
|                                     "" |  | ||||||
|                                 ); |  | ||||||
|                                 if (txt === "") { |  | ||||||
|                                     return r(); |  | ||||||
|                                 } |  | ||||||
|                                 try { |  | ||||||
|                                     const d_1 = await `${meta.root}/build/debug/main.css` |  | ||||||
|                             .asFileHandle() |                             .asFileHandle() | ||||||
|                             .setCache(txt) |                             .setCache(txt) | ||||||
|                             .write("text/plain"); |                             .write("text/plain"); | ||||||
|                                     return r(); |  | ||||||
|                                 } catch (ex_1) { |  | ||||||
|                                     return e(__e(ex_1)); |  | ||||||
|                                 } |  | ||||||
|                             }); |  | ||||||
|                     await API.VFS.copy( |                     await API.VFS.copy( | ||||||
|                                 (() => { |                         meta.copies.map(v => `${meta.root}/${v}`), | ||||||
|                                     const result1_1 = []; |  | ||||||
|                                     for (v of meta.copies) { |  | ||||||
|                                         result1_1.push(`${meta.root}/${v}`); |  | ||||||
|                                     } |  | ||||||
|                                     return result1_1; |  | ||||||
|                                 })(), |  | ||||||
|                         `${meta.root}/build/debug` |                         `${meta.root}/build/debug` | ||||||
|                     ); |                     ); | ||||||
|                             return resolve(); |                     resolve(); | ||||||
|                 } catch (e) { |                 } catch (e) { | ||||||
|                     return reject(__e(e)); |                     return reject(__e(e)); | ||||||
|                 } |                 } | ||||||
|                     } catch (e_1) { |  | ||||||
|                         return reject(__e(e_1)); |  | ||||||
|                     } |  | ||||||
|                 } catch (e_2) { |  | ||||||
|                     return reject(__e(e_2)); |  | ||||||
|                 } |  | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
										
											Binary file not shown.
										
									
								
							| @@ -87,8 +87,7 @@ namespace OS { | |||||||
|                             iconclass: v.iconclass, |                             iconclass: v.iconclass, | ||||||
|                         }); |                         }); | ||||||
|                     } |                     } | ||||||
|  |                     let ctx_menu = [ | ||||||
|                     m.items = [ |  | ||||||
|                         { |                         { | ||||||
|                             text: "__(Open with)", |                             text: "__(Open with)", | ||||||
|                             nodes: apps, |                             nodes: apps, | ||||||
| @@ -103,6 +102,75 @@ namespace OS { | |||||||
|                         this.mnFile(), |                         this.mnFile(), | ||||||
|                         this.mnEdit(), |                         this.mnEdit(), | ||||||
|                     ]; |                     ]; | ||||||
|  |                     if(file.mime === "application/zip") | ||||||
|  |                     { | ||||||
|  |                         ctx_menu = ctx_menu.concat([ | ||||||
|  |                             { | ||||||
|  |                                 text: "__(Extract Here)", | ||||||
|  |                                 onmenuselect: (e: GUI.TagEventType<GUI.tag.MenuEventData>) => { | ||||||
|  |                                     if (!e) { | ||||||
|  |                                         return; | ||||||
|  |                                     } | ||||||
|  |                                     API.VFS.extractZip(file.path, | ||||||
|  |                                         (z) => new Promise((r,e) => r(file.path.asFileHandle().parent().path))) | ||||||
|  |                                     .catch((err) => this.error(__("Unable to extract file"), err)); | ||||||
|  |                                 }, | ||||||
|  |                             }, | ||||||
|  |                             { | ||||||
|  |                                 text: "__(Extract to)", | ||||||
|  |                                 onmenuselect: async (e: GUI.TagEventType<GUI.tag.MenuEventData>) => { | ||||||
|  |                                     if (!e) { | ||||||
|  |                                         return; | ||||||
|  |                                     } | ||||||
|  |                                     try { | ||||||
|  |                                         OS.GUI.dialogs.FileDialog.last_opened = this.currdir.path; | ||||||
|  |                                         const d = await this.openDialog("FileDialog", { | ||||||
|  |                                             title: __("Select extract destination"), | ||||||
|  |                                             type: "dir", | ||||||
|  |                                             file: file.path.replace(".zip","").asFileHandle() | ||||||
|  |                                         }); | ||||||
|  |                                         const path = `${d.file.path}/${d.name}`; | ||||||
|  |                                         await API.VFS.mkdirAll([path]); | ||||||
|  |                                         await API.VFS.extractZip(file.path, | ||||||
|  |                                             (z) => new Promise((r,e) => r(path))); | ||||||
|  |                                     } catch (error) { | ||||||
|  |                                         this.error(__("Unable to extract file"), error); | ||||||
|  |                                     } | ||||||
|  |                                 }, | ||||||
|  |                             }, | ||||||
|  |                         ]); | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         ctx_menu.push( | ||||||
|  |                             { | ||||||
|  |                                 text: "__(Compress)", | ||||||
|  |                                 onmenuselect: async (e: GUI.TagEventType<GUI.tag.MenuEventData>) => { | ||||||
|  |                                     if (!e) { | ||||||
|  |                                         return; | ||||||
|  |                                     } | ||||||
|  |                                     try { | ||||||
|  |                                         OS.GUI.dialogs.FileDialog.last_opened = this.currdir.path; | ||||||
|  |                                         const d = await this.openDialog("FileDialog", { | ||||||
|  |                                             title: __("Save compressed file to"), | ||||||
|  |                                             type: "dir", | ||||||
|  |                                             file: `${this.currdir.path}/${file.name}.zip`.asFileHandle() | ||||||
|  |                                         }); | ||||||
|  |                                         if(d.name.trim() === "") | ||||||
|  |                                         { | ||||||
|  |                                             return this.error(__("Invalid file name")); | ||||||
|  |                                         } | ||||||
|  |                                         const path = `${d.file.path}/${d.name}`; | ||||||
|  |                                         await API.VFS.mkar(file.path, path); | ||||||
|  |                                         this.notify(__("Archive file created: {0}",path )); | ||||||
|  |                                     } catch (error) { | ||||||
|  |                                         this.error(__("Unable to compress file, folder"), error); | ||||||
|  |                                     } | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|  |                         ); | ||||||
|  |                     } | ||||||
|  |                     m.items = ctx_menu; | ||||||
|                     m.show(e); |                     m.show(e); | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
| @@ -546,7 +614,7 @@ namespace OS { | |||||||
|                         return this.notify(__("File {0} cut", file.filename)); |                         return this.notify(__("File {0} cut", file.filename)); | ||||||
|  |  | ||||||
|                     case `${this.name}-copy`: |                     case `${this.name}-copy`: | ||||||
|                         if (!file && file.type !== "dir") { |                         if (!file) { | ||||||
|                             return; |                             return; | ||||||
|                         } |                         } | ||||||
|                         this.clipboard = { |                         this.clipboard = { | ||||||
| @@ -579,30 +647,12 @@ namespace OS { | |||||||
|                                     ); |                                     ); | ||||||
|                                 }); |                                 }); | ||||||
|                         } else { |                         } else { | ||||||
|                             this.clipboard.file |                             API.VFS.copy([this.clipboard.file.path],this.currdir.path) | ||||||
|                                 .read("binary") |                                 .then(() => { | ||||||
|                                 .then(async (d) => { |  | ||||||
|                                     const blob = new Blob([d], { |  | ||||||
|                                         type: this.clipboard.file.info.mime, |  | ||||||
|                                     }); |  | ||||||
|                                     const fp = `${this.currdir.path}/${this.clipboard.file.basename}`.asFileHandle(); |  | ||||||
|                                     fp.cache = blob; |  | ||||||
|                                     try { |  | ||||||
|                                         const r = await fp.write(this.clipboard.file.info.mime); |  | ||||||
|                                     return (this.clipboard = undefined); |                                     return (this.clipboard = undefined); | ||||||
|                                     } |  | ||||||
|                                     catch (e) { |  | ||||||
|                                         return this.error(__("Fail to paste: {0}", this.clipboard.file.path), e); |  | ||||||
|                                     } |  | ||||||
|                                 }) |                                 }) | ||||||
|                                 .catch((e) => { |                                 .catch((e) => { | ||||||
|                                     return this.error( |                                     return this.error(__("Fail to paste: {0}", this.clipboard.file.path), e); | ||||||
|                                         __( |  | ||||||
|                                             "Fail to read: {0}", |  | ||||||
|                                             this.clipboard.file.path |  | ||||||
|                                         ), |  | ||||||
|                                         e |  | ||||||
|                                     ); |  | ||||||
|                                 }); |                                 }); | ||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
|         "author": "Xuan Sang LE", |         "author": "Xuan Sang LE", | ||||||
|         "email": "xsang.le@gmail.com" |         "email": "xsang.le@gmail.com" | ||||||
|     }, |     }, | ||||||
|     "version":"0.1.2-a", |     "version":"0.1.3-a", | ||||||
|     "category":"System", |     "category":"System", | ||||||
|     "iconclass":"fa fa-hdd-o", |     "iconclass":"fa fa-hdd-o", | ||||||
|     "mimes":["dir"], |     "mimes":["dir"], | ||||||
|   | |||||||
| @@ -68,19 +68,15 @@ namespace OS { | |||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
|                 this.btinstall.onbtclick = async () => { |                 this.btinstall.onbtclick = async () => { | ||||||
|                     if (this.btinstall.data.dirty) { |  | ||||||
|                     try { |                     try { | ||||||
|  |                         if (this.btinstall.data.dirty) { | ||||||
|                             await this.updatePackage(); |                             await this.updatePackage(); | ||||||
|                             return this.notify(__("Package updated")); |                             return this.notify(__("Package updated")); | ||||||
|                         } catch (e) { |  | ||||||
|                             return this.error(e.toString(), e); |  | ||||||
|                         } |                         } | ||||||
|                     } |  | ||||||
|                     try { |  | ||||||
|                         const n = await this.remoteInstall(); |                         const n = await this.remoteInstall(); | ||||||
|                         return this.notify(__("Package installed: {0}", n)); |                         return this.notify(__("Package installed: {0}", n)); | ||||||
|                     } catch (e_1) { |                     } catch (error) { | ||||||
|                         return this.error(e_1.toString(), e_1); |                         return this.error(error.toString(), error); | ||||||
|                     } |                     } | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
| @@ -466,40 +462,19 @@ namespace OS { | |||||||
|                         return reject(this._api.throwe(__("Unable to find package: {0}", pkgname))); |                         return reject(this._api.throwe(__("Unable to find package: {0}", pkgname))); | ||||||
|                     } |                     } | ||||||
|                     try { |                     try { | ||||||
|                         const data = await this._api.blob( |                         const n = await this.install(meta.download + "?_=" + new Date().getTime(), meta); | ||||||
|                             meta.download + "?_=" + new Date().getTime() |  | ||||||
|                         ); |  | ||||||
|                         try { |  | ||||||
|                             const n = await this.install(data, meta); |  | ||||||
|                         return resolve(meta); |                         return resolve(meta); | ||||||
|                         } catch (e) { |  | ||||||
|                             return reject(__e(e)); |  | ||||||
|                         } |  | ||||||
|                     } catch (e_1) { |                     } catch (e_1) { | ||||||
|                         return reject(__e(e_1)); |                         return reject(__e(e_1)); | ||||||
|                     } |                     } | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|             private bulkInstall(list: string[]): Promise<any> { |             private bulkInstall(list: string[]): Promise<any> { | ||||||
|                 return new Promise((resolve, reject) => { |                 const promises = []; | ||||||
|                     if (list.length == 0) { |                 for (let pkgname of list) { | ||||||
|                         return resolve(true); |                     promises.push(this.installPkg(pkgname)); | ||||||
|                 } |                 } | ||||||
|                     const pkgname = list.splice(0, 1)[0]; |                 return Promise.all(promises); | ||||||
|                     this.installPkg(pkgname) |  | ||||||
|                         .then((_meta) => { |  | ||||||
|                             this.bulkInstall(list) |  | ||||||
|                                 .then((b) => { |  | ||||||
|                                     resolve(b); |  | ||||||
|                                 }) |  | ||||||
|                                 .catch((e) => { |  | ||||||
|                                     reject(e); |  | ||||||
|                                 }) |  | ||||||
|                         }) |  | ||||||
|                         .catch((err) => { |  | ||||||
|                             reject(err); |  | ||||||
|                         }) |  | ||||||
|                 }); |  | ||||||
|             } |             } | ||||||
|             private remoteInstall(): Promise<string> { |             private remoteInstall(): Promise<string> { | ||||||
|                 const el = this.applist.selectedItem; |                 const el = this.applist.selectedItem; | ||||||
| @@ -512,10 +487,11 @@ namespace OS { | |||||||
|                 } |                 } | ||||||
|                 // get blob file |                 // get blob file | ||||||
|                 return new Promise(async (resolve, reject) => { |                 return new Promise(async (resolve, reject) => { | ||||||
|  |                     try { | ||||||
|                         let pkgname = `${el.data.pkgname}@${el.data.version}`; |                         let pkgname = `${el.data.pkgname}@${el.data.version}`; | ||||||
|                         const dep = this.checkDependencies(pkgname); |                         const dep = this.checkDependencies(pkgname); | ||||||
|                         if (dep.notfound.size != 0) { |                         if (dep.notfound.size != 0) { | ||||||
|                         return this.openDialog("TextDialog", { |                             this.openDialog("TextDialog", { | ||||||
|                                 disable: true, |                                 disable: true, | ||||||
|                                 title: __("Unresolved dependencies"), |                                 title: __("Unresolved dependencies"), | ||||||
|                                 value: __( |                                 value: __( | ||||||
| @@ -523,12 +499,10 @@ namespace OS { | |||||||
|                                     pkgname, |                                     pkgname, | ||||||
|                                     [...dep.notfound].join("\n") |                                     [...dep.notfound].join("\n") | ||||||
|                                 ) |                                 ) | ||||||
|                         }) |  | ||||||
|                             .then((_v) => { |  | ||||||
|                                 reject(__("Unresolved dependencies on: {0}", pkgname)) |  | ||||||
|                             }); |                             }); | ||||||
|  |                             return reject(__("Unresolved dependencies on: {0}", pkgname)); | ||||||
|                         } |                         } | ||||||
|                     this.openDialog("TextDialog", { |                         const t = await this.openDialog("TextDialog", { | ||||||
|                             title: __("Confirm install"), |                             title: __("Confirm install"), | ||||||
|                             disable: true, |                             disable: true, | ||||||
|                             value: __( |                             value: __( | ||||||
| @@ -538,36 +512,26 @@ namespace OS { | |||||||
|                                 dep.install.size.toString(), |                                 dep.install.size.toString(), | ||||||
|                                 [...dep.install].join("\n") |                                 [...dep.install].join("\n") | ||||||
|                             ) |                             ) | ||||||
|                     }).then((_v) => { |                         }); | ||||||
|                         this.bulkUninstall([...dep.uninstall]) |                         if (!t) return; | ||||||
|                             .then((_b) => { |                         await this.bulkUninstall([...dep.uninstall]); | ||||||
|                                 this.bulkInstall([...dep.install]) |                         const metas = await this.bulkInstall([...dep.install]); | ||||||
|                                     .then((_b1) => { |                         this.appDetail(metas.pop()); | ||||||
|                         resolve(pkgname); |                         resolve(pkgname); | ||||||
|                                     }) |                     } catch (error) { | ||||||
|                                     .catch((e1) => { |                         reject(__e(error)); | ||||||
|                                         reject(e1); |                     } | ||||||
|                                     }) |  | ||||||
|                             }) |  | ||||||
|                             .catch((e2) => { |  | ||||||
|                                 reject(e2); |  | ||||||
|                             }) |  | ||||||
|                     }) |  | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             private localInstall(): Promise<string> { |             private localInstall(): Promise<string> { | ||||||
|                 return new Promise((resolve, reject) => { |                 return new Promise(async (resolve, reject) => { | ||||||
|                     return this.openDialog("FileDialog", { |                     try { | ||||||
|  |                         const d = await this.openDialog("FileDialog", { | ||||||
|                             title: "__(Select package archive)", |                             title: "__(Select package archive)", | ||||||
|                             mimes: [".*/zip"], |                             mimes: [".*/zip"], | ||||||
|                     }).then((d) => { |                         }); | ||||||
|                         return d.file.path |                         const n = await this.install(d.file.path); | ||||||
|                             .asFileHandle() |  | ||||||
|                             .read("binary") |  | ||||||
|                             .then((data: Uint8Array) => { |  | ||||||
|                                 return this.install(data) |  | ||||||
|                                     .then((n) => { |  | ||||||
|                         const apps = this.applist.data.map( |                         const apps = this.applist.data.map( | ||||||
|                             (v) => v.pkgname |                             (v) => v.pkgname | ||||||
|                         ); |                         ); | ||||||
| @@ -575,49 +539,35 @@ namespace OS { | |||||||
|                         if (idx >= 0) { |                         if (idx >= 0) { | ||||||
|                             this.applist.selected = idx; |                             this.applist.selected = idx; | ||||||
|                         } |                         } | ||||||
|                                         return resolve(n); |                         return resolve(n.name); | ||||||
|                                     }) |                     } catch (error) { | ||||||
|                                     .catch((e: Error) => reject(__e(e))) |                         reject(__e(error)); | ||||||
|                                     .catch((e: Error) => reject(__e(e))); |                     } | ||||||
|                             }) |  | ||||||
|                             .catch((e: Error) => reject(__e(e))); |  | ||||||
|                     }); |  | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             private install( |             private install( | ||||||
|                 data: ArrayBuffer, |                 zfile: string, | ||||||
|                 meta?: GenericObject<any> |                 meta?: GenericObject<any> | ||||||
|             ): Promise<string> { |             ): Promise<GenericObject<any>> { | ||||||
|                 return new Promise((resolve, reject) => { |                 return new Promise(async (resolve, reject) => { | ||||||
|                     return JSZip.loadAsync(data) |                     try { | ||||||
|                         .then((zip: any) => { |                         let v: API.PackageMetaType; | ||||||
|                             return zip |                         let pth: string = ""; | ||||||
|                                 .file("package.json") |                         await API.VFS.extractZip(zfile, (zip) => { | ||||||
|                                 .async("string") |                             return new Promise(async (res, rej) => { | ||||||
|                                 .then((d: string) => { |                                 try { | ||||||
|                                     let name: string; |                                     const d = await zip.file("package.json").async("string"); | ||||||
|                                     const v = JSON.parse(d); |                                     v = JSON.parse(d); | ||||||
|                                     const pth = `${this.installdir}/${v.pkgname ? v.pkgname : v.app}`; |                                     pth = `${this.installdir}/${v.pkgname ? v.pkgname : v.app}`; | ||||||
|                                     const dir = [pth]; |                                     await API.VFS.mkdirAll([pth]); | ||||||
|                                     const files = []; |                                     res(pth); | ||||||
|                                     for (name in zip.files) { |                                 } catch (error) { | ||||||
|                                         const file = zip.files[name]; |                                     rej(__e(error)) | ||||||
|                                         if (file.dir) { |  | ||||||
|                                             dir.push(pth + "/" + name); |  | ||||||
|                                         } else { |  | ||||||
|                                             files.push(name); |  | ||||||
|                                 } |                                 } | ||||||
|                                     } |                             }); | ||||||
|                                     // create all directory |  | ||||||
|                                     return this.mkdirs(dir) |                         }); | ||||||
|                                         .then(() => { |  | ||||||
|                                             return this.installFile( |  | ||||||
|                                                 v.pkgname ? v.pkgname : v.app, |  | ||||||
|                                                 zip, |  | ||||||
|                                                 files |  | ||||||
|                                             ) |  | ||||||
|                                                 .then(() => { |  | ||||||
|                         const app_meta = { |                         const app_meta = { | ||||||
|                             pkgname: v.pkgname ? v.pkgname : v.app, |                             pkgname: v.pkgname ? v.pkgname : v.app, | ||||||
|                             name: v.name, |                             name: v.name, | ||||||
| @@ -649,38 +599,18 @@ namespace OS { | |||||||
|                         this.systemsetting.system.packages[ |                         this.systemsetting.system.packages[ | ||||||
|                             v.pkgname ? v.pkgname : v.app |                             v.pkgname ? v.pkgname : v.app | ||||||
|                         ] = v; |                         ] = v; | ||||||
|                                                     this.appDetail(app_meta); |                         return resolve(app_meta); | ||||||
|                                                     return resolve(v.name); |                     } catch (error) { | ||||||
|                                                 }) |                         reject(__e(error)); | ||||||
|                                                 .catch((e) => reject(__e(e))); |                     } | ||||||
|                                         }) |  | ||||||
|                                         .catch((e) => reject(__e(e))); |  | ||||||
|                                 }) |  | ||||||
|                                 .catch((err: Error) => reject(__e(err))); |  | ||||||
|                         }) |  | ||||||
|                         .catch((e: Error) => reject(__e(e))); |  | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|             private bulkUninstall(list: string[]): Promise<any> { |             private bulkUninstall(list: string[]): Promise<any> { | ||||||
|                 return new Promise(async (resolve, reject) => { |                 const promises = []; | ||||||
|                     if (list.length == 0) { |                 for (let pkgname of list) { | ||||||
|                         return resolve(true); |                     promises.push(this.uninstallPkg(pkgname)); | ||||||
|                 } |                 } | ||||||
|                     const pkgname = list.splice(0, 1)[0]; |                 return Promise.all(promises); | ||||||
|                     this.uninstallPkg(pkgname) |  | ||||||
|                         .then((_meta) => { |  | ||||||
|                             this.bulkUninstall(list) |  | ||||||
|                                 .then((b) => { |  | ||||||
|                                     resolve(b); |  | ||||||
|                                 }) |  | ||||||
|                                 .catch((e) => { |  | ||||||
|                                     reject(e); |  | ||||||
|                                 }) |  | ||||||
|                         }) |  | ||||||
|                         .catch((err) => { |  | ||||||
|                             reject(err); |  | ||||||
|                         }) |  | ||||||
|                 }); |  | ||||||
|             } |             } | ||||||
|             private uninstallPkg(pkgname: string): Promise<any> { |             private uninstallPkg(pkgname: string): Promise<any> { | ||||||
|                 return new Promise(async (resolve, reject) => { |                 return new Promise(async (resolve, reject) => { | ||||||
| @@ -782,90 +712,20 @@ namespace OS { | |||||||
|                         } |                         } | ||||||
|                         const meta = this.apps_meta[`${sel.pkgname}@${app.version}`]; |                         const meta = this.apps_meta[`${sel.pkgname}@${app.version}`]; | ||||||
|                         await this.remoteInstall(); |                         await this.remoteInstall(); | ||||||
|                         try { |  | ||||||
|                         if (meta) { |                         if (meta) { | ||||||
|                             if (meta.domel) |                             if (meta.domel) | ||||||
|                                 this.applist.delete(meta.domel); |                                 this.applist.delete(meta.domel); | ||||||
|                         } |                         } | ||||||
|                         return resolve(true); |                         return resolve(true); | ||||||
|                     } |                     } | ||||||
|                         catch (e) { |  | ||||||
|                             return reject(__e(e)); |  | ||||||
|                         } |  | ||||||
|  |  | ||||||
|                     } |  | ||||||
|                     catch (e_1) { |                     catch (e_1) { | ||||||
|                         return reject(__e(e_1)); |                         return reject(__e(e_1)); | ||||||
|                     } |                     } | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             private mkdirs(list: string[]): Promise<any> { |  | ||||||
|                 return new Promise((resolve, reject) => { |  | ||||||
|                     if (list.length === 0) { |  | ||||||
|                         return resolve(true); |  | ||||||
|                     } |  | ||||||
|                     const dir = list.splice(0, 1)[0].asFileHandle(); |  | ||||||
|                     const path = dir.parent(); |  | ||||||
|                     const dname = dir.basename; |  | ||||||
|                     return path |  | ||||||
|                         .asFileHandle() |  | ||||||
|                         .mk(dname) |  | ||||||
|                         .then((r) => { |  | ||||||
|                             if (r.error) { |  | ||||||
|                                 return reject( |  | ||||||
|                                     this._api.throwe( |  | ||||||
|                                         __( |  | ||||||
|                                             "Cannot create {0}", |  | ||||||
|                                             `${path}/${dir}` |  | ||||||
|                                         ) |  | ||||||
|                                     ) |  | ||||||
|                                 ); |  | ||||||
|                             } |  | ||||||
|                             return this.mkdirs(list) |  | ||||||
|                                 .then(() => resolve(true)) |  | ||||||
|                                 .catch((e) => reject(__e(e))); |  | ||||||
|                         }) |  | ||||||
|                         .catch((e) => reject(__e(e))); |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             private installFile(n: string, zip: any, files: string[]): Promise<any> { |  | ||||||
|                 return new Promise((resolve, reject) => { |  | ||||||
|                     if (files.length === 0) { |  | ||||||
|                         return resolve(true); |  | ||||||
|                     } |  | ||||||
|                     const file = files.splice(0, 1)[0]; |  | ||||||
|                     const path = `${this.installdir}/${n}/${file}`; |  | ||||||
|                     return zip |  | ||||||
|                         .file(file) |  | ||||||
|                         .async("uint8array") |  | ||||||
|                         .then((d: Uint8Array) => { |  | ||||||
|                             const fp = path.asFileHandle(); |  | ||||||
|                             fp.cache = new Blob([d], { type: "octet/stream" }); |  | ||||||
|                             return fp |  | ||||||
|                                 .write("text/plain") |  | ||||||
|                                 .then((r) => { |  | ||||||
|                                     if (r.error) { |  | ||||||
|                                         return reject( |  | ||||||
|                                             this._api.throwe( |  | ||||||
|                                                 __("Cannot install {0}", path) |  | ||||||
|                                             ) |  | ||||||
|                                         ); |  | ||||||
|                                     } |  | ||||||
|                                     return this.installFile(n, zip, files) |  | ||||||
|                                         .then(() => resolve(true)) |  | ||||||
|                                         .catch((e) => reject(__e(e))); |  | ||||||
|                                 }) |  | ||||||
|                                 .catch((e) => reject(__e(e))); |  | ||||||
|                         }) |  | ||||||
|                         .catch((e: Error) => reject(__e(e))); |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         MarketPlace.dependencies = [ |         MarketPlace.dependencies = [ | ||||||
|             "os://scripts/jszip.min.js", |  | ||||||
|             "os://scripts/showdown.min.js", |             "os://scripts/showdown.min.js", | ||||||
|         ]; |         ]; | ||||||
|         MarketPlace.singleton = true; |         MarketPlace.singleton = true; | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| { | { | ||||||
|     "app":"MarketPlace", |     "app":"MarketPlace", | ||||||
|     "name":"Application store", |     "name":"AntOS Application store", | ||||||
|     "description":"Application store", |     "description":"Application store", | ||||||
|     "info":{ |     "info":{ | ||||||
|         "author": "Xuan Sang LE", |         "author": "Xuan Sang LE", | ||||||
|         "email": "xsang.le@gmail.com" |         "email": "xsang.le@gmail.com" | ||||||
|     }, |     }, | ||||||
|     "version":"0.2.2-a", |     "version":"0.2.3-a", | ||||||
|     "category":"System", |     "category":"System", | ||||||
|     "iconclass":"fa  fa-shopping-bag", |     "iconclass":"fa  fa-shopping-bag", | ||||||
|     "mimes":["none"], |     "mimes":["none"], | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user