fix bug on zip archive

This commit is contained in:
mrsang 2021-04-18 23:29:50 +02:00
parent bbad08d310
commit 9f501fed07
20 changed files with 25 additions and 71631 deletions

Binary file not shown.

View File

@ -43,9 +43,9 @@
"name": "vfs-cp",
"data": {
"src": [
"core",
"package.json",
"README.md",
"core"
"README.md"
],
"dest":"build/debug"
}
@ -53,7 +53,7 @@
]
},
"release": {
"depend": ["build","uglify", "copy"],
"depend": ["clean","build","uglify", "copy"],
"require": ["zip"],
"jobs": [
{

View File

@ -1,15 +0,0 @@
# libantosdk
This is an example project, generated by AntOS Development Kit
## Howto
Use the CodePad command palette to access to the SDK functionalities:
1. Create new project
2. Init the project from the current folder located in side bar
3. Build and run the project
4. Release the project in zip package
## Set up build target
Open the `project.json` file from the current project tree and add/remove
build target entries. Save the file

View File

@ -1,52 +0,0 @@
importScripts('coffeescript.js');
class CompileCoffeeJob extends AntOSDKBaseJob {
constructor(data)
{
super(data);
}
execute()
{
if(!CoffeeScript)
{
const e_msg = "CoffeeScript module is not loaded";
this.log_error(e_msg);
return this.error(e_msg);
}
// very files all data
this.read_files(this.job.data.src)
.then((contents) => {
const errors = [];
for(let i in contents)
{
const data = contents[i];
const file = this.job.data.src[i];
try {
CoffeeScript.nodes(data);
this.log_info(`File ${file} verified`);
} catch (ex) {
errors.push(ex);
this.log_error(`${file}: ${ex.toString()}`);
}
}
if(errors.length > 0)
{
return this.error(errors);
}
const code = contents.join("\n");
const jsrc = CoffeeScript.compile(code);
// write to file
this.save_file(this.job.data.dest,jsrc)
.then(r => {
this.log_info(`File ${this.job.data.dest} generated`);
this.result(this.job.data.dest);
})
.catch(e1 => {
this.error(e1);
});
})
.catch(e => this.error(e));
}
}
API.jobhandle["coffee-compile"] = CompileCoffeeJob;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,50 +0,0 @@
importScripts('terser.min.js');
class UglifyCodeJob extends AntOSDKBaseJob {
constructor(data)
{
super(data);
}
execute() {
if(!Terser)
{
const e_msg = "Terser module is not loaded";
this.log_error(e_msg);
return this.error(e_m);
}
this.read_files(this.job.data)
.then((contents) => {
const promises = [];
const options = {
toplevel: false,
compress: {
passes: 3,
},
mangle: true,
output: {
//beautify: true,
},
};
for(let i in contents)
{
const result = Terser.minify(contents[i], options);
if (result.error) {
this.log_error(`${this.job.data[i]}:${result.error}`);
promises.push(new Promise((r,e) => e(result.error)));
} else {
this.log_info(`File ${this.job.data[i]} uglified`);
promises.push(this.save_file(this.job.data[i],result.code));
}
}
Promise.all(promises)
.then((r) => this.result(r))
.catch((e) => this.error(e));
})
.catch((e1) => this.error(e1));
}
}
API.jobhandle["terser-uglify"] = UglifyCodeJob;

View File

@ -1,131 +0,0 @@
importScripts('typescript.min.js');
const tslib = {};
class TSJob extends AntOSDKBaseJob {
constructor(data)
{
super(data);
}
execute(){
if(!ts)
{
const e_msg = "typescript module is not loaded";
this.log_error(e_msg);
return this.error(e_msg);
}
switch (this.job.cmd) {
case 'ts-import':
this.importlib();
break;
case 'ts-compile':
this.compile();
break;
default:
const err_msg = `Unkown job ${this.job.cmd}`;
this.log_error(err_msg);
return this.error(err_msg);
}
}
importlib()
{
if(!ts)
{
const e_msg = "typescript module is not loaded";
this.log_error(e_msg);
return this.error(e_msg);
}
this.read_files(this.job.data)
.then((results) => {
for(let i in this.job.data)
{
const lib = this.job.data[i];
if(!tslib[lib])
{
tslib[lib] = ts.createSourceFile(lib, results[i], ts.ScriptTarget.Latest);
this.log_info(`Typescript library ${lib} loaded`);
}
}
this.result("Typescript libraries loaded");
})
.catch((e) => {
this.log_error("Fail to load Typescript module");
this.error(e);
});
}
compile()
{
let files = [];
const src_files = {};
for(let i in tslib)
{
files.push(i);
src_files[i] = tslib[i];
}
files = files.concat(this.job.data.src);
this.read_files(this.job.data.src)
.then((contents) => {
for(let i in contents)
{
const m = this.job.data.src[i];
src_files[m] = ts.createSourceFile(m, contents[i], ts.ScriptTarget.Latest);
}
let js_code = "";
const host = {
fileExists: (path) => {
return src_files[path] !== undefined;
},
directoryExists: (path) => {
return true;
},
getCurrentDirectory: () => "/",
getDirectories: () => [],
getCanonicalFileName: (path) => path,
getNewLine: () => "\n",
getDefaultLibFileName: () => "",
getSourceFile: (path) => src_files[path],
readFile: (path) => undefined,
useCaseSensitiveFileNames: () => true,
writeFile: (path, data) => js_code = `${js_code}\n${data}`
};
const program = ts.createProgram(files, {
"target": "es6",
"skipLibCheck": true,
}, host);
const result = program.emit();
const diagnostics = result.diagnostics.concat((ts.getPreEmitDiagnostics(program)));
const errors = [];
if (diagnostics.length > 0) {
diagnostics.forEach(diagnostic => {
let err_msg = "";
if (diagnostic.file) {
let { line, character } = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
err_msg = `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`;
} else {
err_msg = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
}
errors.push(err_msg);
this.log_error(err_msg);
});
return this.error(errors);
}
// write to file
this.save_file(this.job.data.dest,js_code)
.then(r => {
if(r.error)
{
this.log_error(error);
return this.error(r.error);
}
this.result(this.job.data.dest);
})
.catch(e1 => this.error(e1));
})
.catch(e => this.error(e));
}
}
API.jobhandle["ts-import"] = TSJob;
API.jobhandle["ts-compile"] = TSJob;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,464 +0,0 @@
String.prototype.getlink = function(root)
{
return API.REST + "/VFS/get/" + this.abspath(root);
}
String.prototype.abspath = function(root)
{
const list = this.split("://");
if(list.length == 1)
{
return root + "/" + this;
}
const proto = list[0];
const arr = list[1].split("/");
if(proto === "pkg")
{
const pkg = arr.shift();
if(API.pkgs[pkg]) {
return API.pkgs[pkg].path + "/" + arr.join("/");
}
}
if(proto === "sdk")
{
return `pkg://libantosdk/${arr.join("/")}`.abspath(root);
}
return this;
}
const API = {
REST: "",
jobhandle: {},
modules: {},
pkgs:{}
};
class AntOSDKBaseJob {
constructor(data)
{
this.job = data;
}
result(data) {
const result = {
id: this.job.id,
type: "result",
error: false,
result: data
};
postMessage(result);
}
error(msg) {
const result = {
id: this.job.id,
type: "result",
error: msg,
result: false
};
postMessage(result);
}
log_info(data) {
postMessage({
id: this.job.id,
type: "log",
error: false,
result: data
});
}
log_error(data) {
postMessage({
id: this.job.id,
type: "log",
error: true,
result: data
});
}
get(url, type) {
return new Promise((resolve, reject) => {
const req = new XMLHttpRequest();
req.open("GET", url, true);
if(type)
{
req.responseType = type;
}
req.onload = function() {
if (req.readyState === 4 && req.status === 200) {
resolve(req.response);
}
else
{
this.log_error(req.statusText);
reject(req.statusText);
}
};
req.send(null);
});
}
post(url, data, type) {
return new Promise((resolve, reject) => {
const req = new XMLHttpRequest();
req.open("POST", url, true);
req.setRequestHeader("Content-Type", "application/json");
if(type)
{
req.responseType = type;
}
req.onload = function() {
if (req.readyState === 4 && req.status === 200) {
try {
const json = JSON.parse(req.response);
resolve(json);
} catch (e) {
resolve(req.response);
}
}
else
{
this.log_error(req.statusText);
reject(req.statusText);
}
};
req.send(JSON.stringify(data));
});
}
read_files(files)
{
return new Promise( async (resolve, reject) => {
try{
let promises = [];
for(let file of files)
{
promises.push(this.meta(file.abspath(this.job.root)));
}
await Promise.all(promises);
promises = [];
for(let file of files)
{
promises.push(this.get(file.getlink(this.job.root)));
}
const contents = await Promise.all(promises);
resolve(contents);
} catch (e)
{
this.log_error(e.toString());
reject(e);
}
});
}
cat(files, data)
{
return new Promise((resolve, reject) => {
this.read_files(files)
.then((results) => {
resolve(`${data}\n${results.join("\n")}`);
})
.catch((e) => {
reject(e);
this.log_error(e.toString());
});
});
}
save_file(file, data, t)
{
return new Promise((res,rej) => {
this.b64(t,data)
.then((enc) => {
this.post(API.REST+"/VFS/write", {
path: file.abspath(this.job.root),
data: enc
})
.then(d => {
if(d.error){
this.log_error(`Unable to saved to ${file}: ${d.error}`);
return rej(d.error);
}
this.log_info(`${file} saved`);
res(d);
})
.catch(e1 => {
this.log_error(`Unable to saved to ${file}: ${e1.toString()}`);
rej(e1);
});
})
.catch((e) => {
this.log_error(`Unable to saved to ${file}: ${e.toString()}`);
rej(e);
});
});
}
b64(t, data) {
return new Promise((resolve, reject) => {
if(t === "base64")
return resolve(data);
let m = t === "object" ? "text/plain" : t;
if(!t)
m = "text/plain";
if (t === "object" || typeof data === "string") {
let b64;
if (t === "object") {
b64 = btoa(JSON.stringify(data, undefined, 4));
}
else {
b64 = btoa(data);
}
b64 = `data:${m};base64,${b64}`;
return resolve(b64);
}
else {
//blob
const reader = new FileReader();
reader.readAsDataURL(data);
reader.onload = () => resolve(reader.result);
return (reader.onerror = (e) => reject(e));
}
});
}
delete(files)
{
const promises = [];
for(const file of files)
{
promises.push(new Promise((resolve, reject) =>{
this.post(API.REST+"/VFS/delete", {path: file.abspath(this.job.root)})
.then(r => {
if(r.error)
{
this.log_error(`${file}:${r.error}`);
return reject(r.error);
}
this.log_info(`${file} deleted`);
return resolve(r.result);
})
.catch(e =>{
this.log_error(e.toString());
reject(e);
});
}));
}
return Promise.all(promises);
}
mkdir(list) {
return new Promise( async (resolve, reject) => {
try {
if (list.length === 0) {
return resolve(true);
}
const dir = list.splice(0, 1)[0];
const ret = await this.post(API.REST+"/VFS/mkdir", {path: dir.abspath(this.job.root)});
if(ret.error)
{
this.log_error(`${dir}: ${ret.error}`);
return reject(ret.error);
}
this.log_info(`${dir} created`);
await this.mkdir(list);
resolve(true);
}
catch (e) {
this.log_error(e.toString());
reject(e);
}
});
}
copy(files, to) {
const promises = [];
for (const path of files.map(f =>f.abspath(this.job.root))) {
promises.push(new Promise(async (resolve, reject) => {
try {
const file = path.split("/").filter(s=>s!="").pop();
const tof = `${to}/${file}`;
const meta = await this.meta(path);
if (meta.type === "dir") {
await this.mkdir([tof]);
const dirs = await this.scandir(path);
const files = dirs.map((v) => v.path);
if (files.length > 0) {
await this.copy(files, tof);
}
resolve(undefined);
}
else {
const ret = await this.read_files([path], "arraybuffer");
const blob = new Blob([ret[0]], {
type: meta.mime});
await this.save_file(tof, blob,"binary");
this.log_info(`COPIED: ${path} -> ${tof}`);
resolve(undefined);
}
} catch (error) {
this.log_error(error.toString());
reject(error);
}
}));
}
return Promise.all(promises);
}
meta(path)
{
const file = path.abspath(this.job.root);
return new Promise((resolve,reject) =>{
this.post(API.REST+"/VFS/fileinfo", {path:file})
.then(json =>{
if(json.error)
{
this.log_error(`${file}: ${json.error}`);
return reject(json.error);
}
return resolve(json.result);
})
.catch(e => {
this.log_error(e.toString());
resolve(e);
});
});
}
scandir(path)
{
return new Promise((resolve,reject) =>{
this.post(API.REST+"/VFS/scandir", {path:path.abspath(this.job.root)})
.then(json =>{
if(json.error)
return reject(json.error);
return resolve(json.result);
})
.catch(e =>{
this.log_error(e.toString());
resolve(e);
});
});
}
execute() {}
}
class UnknownJob extends AntOSDKBaseJob {
constructor(data)
{
super(data);
}
execute() {
this.log_error("Unknown job " + this.job.cmd);
this.error("Unknown job " + this.job.cmd);
}
}
class SDKSetup extends AntOSDKBaseJob {
constructor(data)
{
super(data);
}
execute() {
for(let k in this.job.data)
{
API[k] = this.job.data[k];
}
this.result("ANTOS Sdk set up");
}
}
class LoadScritpJob extends AntOSDKBaseJob {
constructor(data)
{
super(data);
}
execute() {
try
{
for(let lib of this.job.data)
{
if(!API.modules[lib])
{
this.log_info("Importing module:" + lib);
importScripts(lib);
API.modules[lib] = true;
}
else
{
console.log("Module " + lib + " is already loaded");
}
}
this.log_info("All Modules loaded" );
this.result(this.job.data);
}
catch(e)
{
this.error(e);
}
}
}
class VFSJob extends AntOSDKBaseJob {
constructor(data)
{
super(data);
}
execute() {
const arr = this.job.cmd.split("-");
if(arr.length > 1)
{
switch (arr[1]) {
case 'cat':
this.cat(this.job.data.src,"")
.then(data => {
this.save_file(this.job.data.dest, data)
.then(r => this.result(r))
.catch(e1 => this.error(e1));
})
.catch(e => this.error(e));
break;
case 'rm':
this.delete(this.job.data)
.then(d => this.result(d))
.catch(e => this.error(e));
break;
case 'mkdir':
this.mkdir(this.job.data)
.then(d => this.result(d))
.catch(e => this.error(e));
break;
case 'cp':
this.copy(this.job.data.src, this.job.data.dest)
.then(d => this.result(d))
.catch(e => this.error(e));
break;
default:
this.error("Unknown command: " + this.job.cmd);
}
}
else
{
this.error("Unknown command: " + this.job.cmd);
}
}
}
API.jobhandle["sdk-import"] = LoadScritpJob;
API.jobhandle["sdk-setup"] = SDKSetup;
API.jobhandle["vfs-cat"] = VFSJob;
API.jobhandle["vfs-rm"] = VFSJob;
API.jobhandle["vfs-mkdir"] = VFSJob;
API.jobhandle["vfs-cp"] = VFSJob;
onmessage = (e) => {
if(API.jobhandle[e.data.cmd])
{
return (new API.jobhandle[e.data.cmd](e.data)).execute();
}
(new UnknownJob(e.data)).execute();
}

View File

@ -1,98 +0,0 @@
importScripts("os://scripts/jszip.min.js".getlink());
class ZipJob extends AntOSDKBaseJob {
constructor(data)
{
super(data);
}
execute()
{
if(!JSZip)
{
const e_msg = "JSZip module is not loaded";
this.log_error(e_msg);
return this.error(e_msg);
}
switch (this.job.cmd) {
case 'zip-mk':
this.mkar()
.then(d => this.result(d))
.catch(e => this.error(e));
break;
default:
const err_msg = `Unkown job ${this.job.cmd}`;
this.log_error(err_msg);
return this.error(err_msg);
}
}
aradd(list, zip, base)
{
const promises = [];
for (const file of list) {
promises.push(new Promise(async (resolve, reject) => {
try {
const basename = file.split("/").pop();
const meta = await this.meta(file);
if (meta.type == "dir") {
const ret = await this.scandir(file);
const dirs = ret.map(v => v.path);
if (dirs.length > 0) {
await this.aradd(dirs, zip, `${base}${basename}/`);
resolve(undefined);
}
else {
resolve(undefined);
}
}
else {
const ret = await this.read_files([file], "arraybuffer");
const u_data = ret[0];
const z_path = `${base}${basename}`.replace(
/^\/+|\/+$/g,
"");
zip.file(z_path, u_data, { binary: true });
this.log_info(`${file} added to zip`);
resolve(undefined);
}
} catch (error) {
this.log_error(`${file}: ${error.toString()}`);
reject(error);
}
}));
}
return Promise.all(promises);
}
mkar()
{
const src = this.job.data.src;
const dest = this.job.data.dest;
return new Promise(async (resolve, reject) => {
try {
const zip = new JSZip();
const meta = await this.meta(this.job.data.src);
if(meta.type === "file")
{
await this.aradd([src], zip, "/");
}
else
{
const ret = await this.scandir(src);
await this.aradd(ret.map(v => v.path), zip, "/");
}
const z_data = await zip.generateAsync({ type: "base64" });
await this.save_file(dest, "data:application/zip;base64," + z_data, "base64");
this.log_info(`Zip archive saved in ${dest}`);
resolve(dest);
} catch (error) {
this.log_error(`Unable to commpress ${src} -> ${dest}: ${error.toString()}`);
reject(error);
}
});
}
}
API.jobhandle["zip-mk"] = ZipJob;

View File

@ -1 +0,0 @@
var OS;!function(t){let e;!function(e){class r{constructor(e){this.worker=new Worker(e.asFileHandle().getlink()),this.jobs={},this.worker.onmessage=t=>{let e=t.data,r=this.jobs[e.id];r?"log"===e.type?r.logger&&(e.error?r.logger.error(e.result):r.logger.info(e.result)):(r.callback(e),delete this.jobs[e.id]):console.log("Unable to identify result of job",e.id,e)};const r={};for(const e in t.setting.system.packages){const o=t.setting.system.packages[e];r[e]={path:o.path,name:o.pkgname}}this.submit("sdk-setup",{REST:t.API.REST,pkgs:r})}newJobID(){return"job_"+Math.random().toString(36).replace(".","")}exectue_job(t,e,r,o,s){const i=this.newJobID(),n={id:i,cmd:t,data:e,root:r};this.jobs[i]={callback:o,logger:s},this.worker.postMessage(n)}submit(t,e,r,o){return new Promise((s,i)=>{this.exectue_job(t,e,r,t=>{if(t.error)return i(t.error);s(t.result)},o)})}terminate(){this.worker.terminate()}}class o{constructor(t,e){this.root=e,this.logger=t,o.worker||(o.worker=new r("pkg://libantosdk/core/worker.js"))}require(t){return this.run("sdk-import",t.map(t=>t+".worker.js"))}compile(t,e){return new Promise(async(r,o)=>{try{await this.require([t]),r(await this.run(t+"-compile",e))}catch(t){o(__e(t))}})}run(t,e){return o.worker.submit(t,e,this.root,this.logger)}batch(t,e){return e.root&&(this.root=e.root),new Promise(async(r,o)=>{try{e.targets||o("No target found");for(const r of t){const t=e.targets[r];if(!t)return o(__("No target: "+r));if(t.depend&&await this.batch(t.depend,e),t.require&&await this.require(t.require),this.logger&&this.logger.info(__(`### RUNNING STAGE: ${r}###`).__()),t.jobs)for(const e of t.jobs)await this.run(e.name,e.data)}r(void 0)}catch(t){o(t)}})}}let s;e.AntOSDKBuilder=o,function(t){class e extends t.RemoteFileHandle{constructor(t){super(t);const e="pkg://libantosdk/"+this.genealogy.join("/");this.setPath(e.asFileHandle().path)}}t.SDKFileHandle=e,t.register("^sdk$",e)}(s=e.VFS||(e.VFS={}))}(e=t.API||(t.API={}))}(OS||(OS={})),function(){}.call(this);

View File

@ -1,15 +0,0 @@
{
"pkgname": "libantosdk",
"name":"AntOSDK",
"description":"AntOS Software Development Kit",
"info":{
"author": "Xuan Sang LE",
"email": "mrsang@iohub.dev"
},
"version":"0.0.2-a",
"category":"Other",
"iconclass":"fa fa-cog",
"mimes":["none"],
"dependencies":[],
"locale": {}
}

View File

@ -2,6 +2,15 @@ String.prototype.getlink = function(root)
{
return API.REST + "/VFS/get/" + this.abspath(root);
}
String.prototype.asBase64 = function () {
const tmp = encodeURIComponent(this);
return btoa(
tmp.replace(/%([0-9A-F]{2})/g, (match, p1) =>
String.fromCharCode(parseInt(p1, 16))
)
);
};
String.prototype.abspath = function(root)
{
const list = this.split("://");
@ -206,10 +215,10 @@ class AntOSDKBaseJob {
if (t === "object" || typeof data === "string") {
let b64;
if (t === "object") {
b64 = btoa(JSON.stringify(data, undefined, 4));
b64 = JSON.stringify(data, undefined, 4).asBase64();
}
else {
b64 = btoa(data);
b64 = data.asBase64();
}
b64 = `data:${m};base64,${b64}`;
return resolve(b64);

View File

@ -49,11 +49,14 @@ class ZipJob extends AntOSDKBaseJob {
}
else {
const ret = await this.read_files([file], "arraybuffer");
const u_data = ret[0];
const blob = new Blob( [ret[0]], {
type: "octet/stream",
});
const b64 = await this.b64("binary", blob);
const z_path = `${base}${basename}`.replace(
/^\/+|\/+$/g,
"");
zip.file(z_path, u_data, { binary: true });
zip.file(z_path, b64.replace("data:octet/stream;base64,",""), { base64: true, compression : "DEFLATE" });
this.log_info(`${file} added to zip`);
resolve(undefined);
}
@ -83,8 +86,10 @@ class ZipJob extends AntOSDKBaseJob {
const ret = await this.scandir(src);
await this.aradd(ret.map(v => v.path), zip, "/");
}
const z_data = await zip.generateAsync({ type: "base64" });
await this.save_file(dest, "data:application/zip;base64," + z_data, "base64");
const z_data = await zip.generateAsync({ type: "arraybuffer" });
const blob = new Blob([z_data], {
type: "application/octet-stream"});
await this.save_file(dest, blob,"binary");
this.log_info(`Zip archive saved in ${dest}`);
resolve(dest);
} catch (error) {

View File

@ -3,6 +3,6 @@
"css": [],
"javascripts": [],
"coffees": [],
"ts": ["ts/main.ts"],
"copies": ["core","package.json", "README.md"]
"ts": ["ts/main.ts", "ts/test.ts"],
"copies": ["core","package.json","scheme.html", "README.md"]
}