Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

zip-local

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

zip-local - npm Package Compare versions

Comparing version 0.2.1 to 0.3.0

4

CHANGELOG.md

@@ -0,1 +1,5 @@

# v0.3.0
Released 4/2/2016
* Improved asynchronous error handeling by passing any error that occurs as the first argument of any callback function.
# v0.2.1

@@ -2,0 +6,0 @@ Released 10/1/2015

116

libs/ZipExport.js

@@ -24,7 +24,11 @@ var fs = require('fs');

if (err)
throw new Error(extraction_path + " doesn't exist");
if (err) {
callback(err);
return;
}
if (!stats.isDirectory())
throw new Error(extraction_path + " is not a directory");
if (!stats.isDirectory()) {
callback(new Error(extraction_path + " is not a directory"));
return;
}

@@ -35,5 +39,5 @@ // sort out the unzipped file to directories and files

for (var name in jszip.files) {
var entry = jszip.files[name];
if (entry.dir)

@@ -44,7 +48,7 @@ dirs.push(name);

}
// sort the directories ascendingy by level
dirs.sort(function (a, b) {
function dir_sep_count(dir) { return (dir.match(/\//g) || []).length; }
return dir_sep_count(a) - dir_sep_count(b);

@@ -59,4 +63,8 @@ });

fs.mkdir(dir, function () {
fs.mkdir(dir, function (err) {
// end of this iteration
if(err) {
end_iteration(err);
return;
}
end_iteration();

@@ -66,8 +74,9 @@ });

}, function (err) {
if (err)
throw err;
if (err) {
callback(err);
}
// write the files
async.each(files, function (file, end_iteration) {
async.each(files, function (file, end_iteration) {

@@ -77,6 +86,8 @@ var data = jszip.file(file).asNodeBuffer();

fs.writeFile(file, data, function (err) {
if (err)
throw err;
if (err) {
end_iteration(err);
return;
}
// end of this iteration

@@ -86,4 +97,9 @@ end_iteration();

});
}, function (err) {
}, function (err) {
if(err) {
callback(err);
return;
}
// change the process working directory back

@@ -93,3 +109,3 @@ process.chdir(current_working_dirctory);

// invoke the callback
callback();
callback(null);
});

@@ -106,6 +122,6 @@ });

function extract_to_sync(_path, jszip) {
var extraction_path = _path === null ? "./" : path.normalize(_path);
var current_working_dirctory = process.cwd();
// make sure that the extraction path points to a existing directory

@@ -117,3 +133,3 @@ var stats;

throw new Error(extraction_path + " is not a directory");
// sort out the unzipped file to directories and files

@@ -131,7 +147,7 @@ var dirs = [];

}
// sort the directories ascendingy by level
dirs.sort(function (a, b) {
function dir_sep_count(dir) { return (dir.match(/\//g) || []).length; }
return dir_sep_count(a) - dir_sep_count(b);

@@ -162,3 +178,3 @@ });

/*****************************************************************************************
********************************** MODULE PUBLIC APIS ************************************
********************************** MODULE PUBLIC APIS ************************************
***** THE MODULE CONTAINS THE APIS THAT DEAL WITH EXPORTING AFTER ZIPPING IS COMPLETE ****

@@ -174,12 +190,12 @@ *****************************************************************************************/

function ZipExport(jszip, unzipped, async) {
// hold the JSZip for exporting
this.content = jszip;
// determines if the exported will be compressed
this.compressed = false;
// determines if the source is an unzipped file
// determines if the source is an unzipped file
this.src_unzipped = unzipped ? true : false;
// determines if the exported file will be written asynchronously

@@ -196,3 +212,3 @@ this.save_async = async ? true : false;

return this.content;
}
}

@@ -206,3 +222,3 @@ /*

this.compressed = true;
return this;

@@ -216,3 +232,3 @@ }

ZipExport.prototype.memory = function() {
if (!this.src_unzipped) {

@@ -225,3 +241,3 @@

});
return new Buffer(buff);

@@ -242,5 +258,5 @@ }

ZipExport.prototype.save = function (_path, _callback) {
var callback = _callback || function () { };
if (!this.src_unzipped) {

@@ -252,12 +268,12 @@ // generate the zipped buffer

});
var normalized_path = path.normalize(_path);
var parsed_path = path.parse(normalized_path);
var current_working_directory = process.cwd();
// change process's directory to save directory if exists
if (parsed_path.dir !== '')
process.chdir(parsed_path.dir);
// write the new file

@@ -273,11 +289,13 @@ if (!this.save_async) {

fs.writeFile(parsed_path.base, buff, function (err) {
if (err)
throw err;
if (err) {
callback(err);
return;
}
// change process's directory back
process.chdir(current_working_directory);
//invoke the callback
callback();
callback(null);

@@ -287,3 +305,3 @@ });

else {
// extract the unzipped file to given directory

@@ -298,2 +316,2 @@ if (!this.save_async)

module.exports = ZipExport;
module.exports = ZipExport;

@@ -23,7 +23,9 @@ var fs = require('fs');

fs.readdir(dir, function (err, entries) {
if (err)
throw err;
var entries_paths = entries.map(function (entry) {
if (err) {
deferred.reject(err);
return;
}
var entries_paths = entries.map(function (entry) {
return path.normalize(dir + path.sep + entry);

@@ -33,3 +35,8 @@ });

async.map(entries_paths, fs.stat, function (err, stats) {
if(err) {
deffered.reject(err);
return;
}
var entries_count = entries_paths.length;

@@ -48,7 +55,7 @@

async.each(typed_entries, function (entry, callback) {
var parsed_entry_path = path.parse(entry.path);
if (entry.type === 'dir') {
var new_zipped_dir = zipped_dir.folder(parsed_entry_path.base);

@@ -60,2 +67,5 @@

callback();
})
.catch(function(error) {
callback(error);
}).done();

@@ -65,23 +75,25 @@ }

fs.readFile(entry.path, function (err, data) {
if (err)
throw err;
fs.readFile(entry.path, function (err, data) {
if (err) {
callback(err);
return;
}
//zip the file within the current subdir
zipped_dir.file(parsed_entry_path.base, data);
// the end of this iteration
callback();
});
}
}
}, function (err) {
// here all iterations are over
if (err)
throw err;
// resolve the deffered and fullfil the promise
deferred.resolve();
deffered.reject(err);
else
// resolve the deffered and fullfil the promise
deferred.resolve();
});

@@ -92,3 +104,3 @@ });

return deferred.promise;
}
}

@@ -101,15 +113,15 @@ /*

function zip_dir_sync(dir, zipped_dir) {
var entries = fs.readdirSync(dir);
var entries_count = entries.length;
for(var i = 0; i < entries_count; i++) {
var entry = entries[i];
var entry = entries[i];
var entry_normalized_path = path.normalize(dir + path.sep + entry);
var entry_stats = fs.statSync(entry_normalized_path);
if(entry_stats.isDirectory()) {
var new_zipped_dir = zipped_dir.folder(entry);
// recursively zip the newly found dir

@@ -119,5 +131,5 @@ zip_dir_sync(entry_normalized_path, new_zipped_dir);

else {
var file = fs.readFileSync(entry_normalized_path);
// zip the file within current subdir

@@ -146,40 +158,47 @@ zipped_dir.file(entry, file);

ZipLocal.zip = function (entity, _callback, _shiftedCallback) {
var zipped_obj = new JSZip();
if (typeof entity === "string") {
// the entity is a path pointing to a file or a directory
// the callback is not shifted
// the entity is a path pointing to a file or a directory
// the callback is not shifted
var callback = _callback || function () { };
var normalized_path = path.normalize(entity);
fs.stat(normalized_path, function (err, stats) {
if (err)
throw err;
if (err) {
callback(err);
return;
}
if (stats.isDirectory()) {
// start zipping the directory
Q.fcall(zip_dir, normalized_path, zipped_obj).then(function () {
// invoke the callback
callback(new ZipExport(zipped_obj, false, true));
callback(null, new ZipExport(zipped_obj, false, true));
})
.catch(function(error) {
callback(error);
}).done();
}
else {
var parsed_path = path.parse(normalized_path);
fs.readFile(normalized_path, function (err, file) {
if (err)
throw err;
if (err) {
callback(err);
return;
}
zipped_obj.file(parsed_path.base, file);
// invoke the callback
callback(new ZipExport(zipped_obj, false, true));
callback(null, new ZipExport(zipped_obj, false, true));

@@ -191,5 +210,5 @@ });

else if (entity instanceof Buffer) {
// the entity is a buffer containing a file
// the _callback argument is now the name of the file in buffer

@@ -201,5 +220,5 @@ // the callback is shifted to _shiftedCallback argument

zipped_obj.file(name, entity);
// invoke the callback
callback(new ZipExport(zipped_obj, false, true));
callback(null, new ZipExport(zipped_obj, false, true));
}

@@ -213,6 +232,6 @@

//invoke the callback
callback(new ZipExport(entity.unzipped_file, false, true));
callback(null, new ZipExport(entity.unzipped_file, false, true));
}
else {
throw new Error("Unsupported type: data is neither a path or a Buffer");
callback(new Error("Unsupported type: data is neither a path or a Buffer"));
}

@@ -227,18 +246,23 @@ }

ZipLocal.unzip = function (file, _callback) {
var callback = _callback || function () { };
var zipped_obj = new JSZip();
if (typeof file === "string") {
// file is a path that points to a zip file
var normalized_path = path.normalize(file);
fs.readFile(normalized_path, function (err, data) {
if(err) {
callback(err);
return;
}
zipped_obj.load(data);
//invoke the callback
callback(new ZipExport(zipped_obj, true, true))
callback(null, new ZipExport(zipped_obj, true, true))

@@ -248,15 +272,15 @@ });

else if (file instanceof Buffer) {
// file is a Buffer that contains the data
zipped_obj.load(file);
//invoke the callback
callback(new ZipExport(zipped_obj, true, true))
callback(null, new ZipExport(zipped_obj, true, true))
}
else {
throw new Error("Unsupported type: data is neither a path or a Buffer");
callback(new Error("Unsupported type: data is neither a path or a Buffer"));
}
}
}

@@ -270,30 +294,30 @@ /*

ZipLocal.sync.zip = function(entity, buffer_name) {
var zipped_obj = new JSZip();
if (typeof entity === "string") {
// the entity is a path pointing to a file or a directory
// the entity is a path pointing to a file or a directory
var normalized_path = path.normalize(entity);
var stats = fs.statSync(normalized_path);
if (stats.isDirectory()) {
// start zipping the directory
zip_dir_sync(normalized_path, zipped_obj);
return new ZipExport(zipped_obj);
}
else {
var parsed_path = path.parse(normalized_path);
var file = fs.readFileSync(normalized_path);
zipped_obj.file(parsed_path.base, file);
}
}
else if (entity instanceof Buffer) {
// the entity is a buffer containing a file

@@ -304,5 +328,5 @@

else if (entity instanceof ZippedFS) {
// the entity is a ZippedFS from an unzipped file
//change the zipped_obj

@@ -324,13 +348,13 @@ zipped_obj = entity.unzipped_file;

ZipLocal.sync.unzip = function (file) {
var zipped_obj = new JSZip();
if (typeof file === "string") {
// file is a path that points to a zip file
var normalized_path = path.normalize(file);
var data = fs.readFileSync(normalized_path);
zipped_obj.load(data);

@@ -349,5 +373,5 @@ }

return new ZipExport(zipped_obj, true, false);
};
};
module.exports = ZipLocal;
module.exports = ZipLocal;
{
"name": "zip-local",
"version": "0.2.1",
"version": "0.3.0",
"description": "very simple zipping/uzipping of local files and directories in node.js",

@@ -8,2 +8,3 @@ "main": "main.js",

"test": "./node_modules/.bin/mocha ./tests/*.test.js",
"pretest": "node ./tests/cleanup.js",
"posttest": "node ./tests/cleanup.js"

@@ -10,0 +11,0 @@ },

@@ -25,3 +25,3 @@ # zip-local

Zipping is done through <code>ZipLocal.zip</code> or its synchronous version <code> ZipLocal.sync.zip</code> by passing the path to the file or directory that needs to be zipped. In the asynchrnous version, the callback is passed an instance of <code> ZipExport</code> object that contains the APIs to export the
Zipping is done through <code>ZipLocal.zip</code> or its synchronous version <code> ZipLocal.sync.zip</code> by passing the path to the file or directory that needs to be zipped. In the asynchrnous version, the callback is passed an instance of <code> ZipExport</code> object that contains the APIs to export the
zipped file. In the synchronous version, the <code>ZipExport</code> object is returned.

@@ -35,12 +35,16 @@

// zipping a file
zipper.zip("./hello-world.cpp", function(zipped) {
zipped.compress(); // compress before exporting
var buff = zipped.memory(); // get the zipped file as a Buffer
// or save the zipped file to disk
zipped.save("../package.zip", function() {
console.log("saved successfully !");
});
zipper.zip("./hello-world.cpp", function(error, zipped) {
if(!error) {
zipped.compress(); // compress before exporting
var buff = zipped.memory(); // get the zipped file as a Buffer
// or save the zipped file to disk
zipped.save("../package.zip", function(error) {
if(!error) {
console.log("saved successfully !");
}
});
}
});

@@ -76,17 +80,19 @@ ```

zipper.unzip("../package.zip", function(unzipped) {
// extract to the current working directory
unzipped.save(null, function() { });
var unzippedfs = unzipped.memory();
// print an array of file paths in the unzipped file
console.log(unzippedfs.contents()); // prints [ 'hello-world.cpp' ]
// read the file as text
var txt = unzippedfs.read("hello-world.cpp", 'text');
// or read it as Buffer
var buff = unzippedfs.read("hello-world.cpp", 'buffer');
zipper.unzip("../package.zip", function(error, unzipped) {
if(!error) {
// extract to the current working directory
unzipped.save(null, function() { });
var unzippedfs = unzipped.memory();
// print an array of file paths in the unzipped file
console.log(unzippedfs.contents()); // prints [ 'hello-world.cpp' ]
// read the file as text
var txt = unzippedfs.read("hello-world.cpp", 'text');
// or read it as Buffer
var buff = unzippedfs.read("hello-world.cpp", 'buffer');
}
});

@@ -107,3 +113,3 @@ ```

// logs ['hello-world.txt', 'cpp/hello-world.cpp', 'java/hello-world.java']
console.log(unzippedfs.contents());
console.log(unzippedfs.contents());

@@ -127,10 +133,20 @@ // read file in buffer

var server = net.createServer(function (socket) {
socket.on('data', function(data) {
zipper.zip(data, "remote_file", function(zipped) {
zipper.zip(data, "remote_file", function(error, zipped) {
if(error) {
console.log("ERROR: %s", error.message);
return;
}
// cache a copy of the zipped file on the server
zipped.save("zipped_from" + socket.remoteAddress + ".zip");
zipped.save("zipped_from" + socket.remoteAddress + ".zip", function(error) {
if(error) {
console.log("ERROR: %s", error.message);
return;
}
});
// send the zipped file back to the client

@@ -147,3 +163,3 @@ socket.write(zipped.memory());

While the library was designed to provide a simple high-level APIs to zip/unzip local directories and files, it's sometimes needed to perform some low level operations on the before exporting it like adding new files to the zip or removing some files form an unzipped file before writing to disk. And since this library is based on JSZip which provides these low level operations, starting from v0.2.0 you can access the underlying <code>JSZip</code> object and all its low level features through the method <code>ZipExport#lowLevel()</code>. After you zip/unzip your data and acquire the <code>ZipExport</code> object, you can call this method from it and retrieve the underlying <code>JSZip</code> object and play around with it.
While the library was designed to provide a simple high-level APIs to zip/unzip local directories and files, it's sometimes needed to perform some low level operations on the data before exporting it like adding new files to the zip or removing some files form an unzipped file before writing to disk. And since this library is based on JSZip which provides these low level operations, starting from v0.2.0 you can access the underlying <code>JSZip</code> object and all its low level features through the method <code>ZipExport#lowLevel()</code>. After you zip/unzip your data and acquire the <code>ZipExport</code> object, you can call this method from it and retrieve the underlying <code>JSZip</code> object and play around with it.

@@ -155,8 +171,13 @@ Here's an example that utilizes the low level operations to remove files and also utilizes the ability to zip <code>ZippedFS</code> object. This code cleans zipped files from executables (namely .exe, .bat, and .sh):

zipper.unzip('package.zip', function(unzipped) {
zipper.unzip('package.zip', function(error, unzipped) {
if(error) {
console.log("ERROR: %s", error.message);
return;
}
var unzippedFS = unzipped.memory();
var files = unzippedFS.contents();
var notExecRegExp = new RegExp(/^[^.]+$|\.(?!(sh|exe|bat)$)([^.]+$)/);
files.forEach(function (file) {

@@ -166,10 +187,15 @@ if(!notExecRegExp.test(file))

});
var cleanUnzippedFS = unzipped.memory();
// re-zip the clean ZippedFS
zipper.zip(cleanUnzippedFS, function(zipped) {
zipped.save("package.zip", function() {
console.log("The file is scanned and cleaned of executables");
zipped.save("package.zip", function(error) {
if(error) {
console.log("ERROR: %s", error.message);
}
else {
console.log("The file is scanned and cleaned of executables");
}
});

@@ -176,0 +202,0 @@ });

@@ -19,12 +19,9 @@ var fs = require('fs');

async.each(file_list, function (file, callback) {
fs.unlink(file, function (err) {
if (err)
throw err;
callback();
});
}, function (err) {
}, function (err) {

@@ -39,5 +36,2 @@ if (err)

if (err)
throw err;
callback();

@@ -49,2 +43,2 @@ });

throw err;
});
});

@@ -13,4 +13,6 @@ var fs = require('fs');

zipper.unzip("./tests/assets/hello.zip", function (unzipped) {
zipper.unzip("./tests/assets/hello.zip", function (error, unzipped) {
expect(error).to.equal(null);
localMemory.T1ZippedFS = unzipped.memory();

@@ -23,3 +25,3 @@

it("checks if the ZippedFS object contains correct data", function () {
expect(localMemory.T1ZippedFS.contents()).to.include("hello/says-hello") &&

@@ -33,4 +35,6 @@ expect(localMemory.T1ZippedFS.read("hello/says-hello", 'text')).to.equal("Hello") &&

zipper.unzip("./tests/assets/hello.zip", function (unzipped) {
zipper.unzip("./tests/assets/hello.zip", function (error, unzipped) {
expect(error).to.equal(null);
fs.mkdir("./tests/assets/hello-async-unzip", function (err) {

@@ -40,3 +44,4 @@ if (err)

unzipped.save("./tests/assets/hello-async-unzip/", function () {
unzipped.save("./tests/assets/hello-async-unzip/", function (error) {
expect(error).to.equal(null);
done();

@@ -51,6 +56,6 @@ });

fs.readFile("./tests/assets/hello-async-unzip/hello/says-hello", 'utf8', function (err, data) {
if (err)
throw err;
expect(data).to.equal("Hello");

@@ -71,7 +76,9 @@

it("unzips a file directly from the buffer containing it", function (done) {
var buff = fs.readFileSync("./tests/assets/hello.zip");
zipper.unzip(buff, function (unzipped) {
zipper.unzip(buff, function (error, unzipped) {
expect(error).to.equal(null);
localMemory.T5ZippedFS = unzipped.memory();

@@ -82,5 +89,5 @@

});
it("checks if the ZippedFS object contains correct data", function () {
expect(localMemory.T5ZippedFS.contents()).to.include("hello/says-hello") &&

@@ -92,2 +99,2 @@ expect(localMemory.T5ZippedFS.read("hello/says-hello", 'text')).to.equal("Hello") &&

})
})

@@ -13,4 +13,6 @@ var fs = require('fs');

zipper.zip("./tests/assets/hello", function (zipped) {
zipper.zip("./tests/assets/hello", function (error, zipped) {
expect(error).to.equal(null);
localMemory.T1ZippedBuffer = zipped.memory();

@@ -24,3 +26,3 @@

it("checks if the zipped buffer contains correct data (using JSZip)", function () {
var zipped = new JSZip(localMemory.T1ZippedBuffer);

@@ -38,12 +40,16 @@

it("should zip a directory to disk without errors", function (done) {
zipper.zip("./tests/assets/hello", function (zipped) {
zipped.save("./tests/assets/dirs.async.T3Pack.zip", function () {
zipper.zip("./tests/assets/hello", function (error, zipped) {
expect(error).to.equal(null);
zipped.save("./tests/assets/dirs.async.T3Pack.zip", function (error) {
expect(error).to.equal(null);
// make sure that the file exists on disk
fs.readdir("./tests/assets/", function (err, entries) {
expect(entries).to.include('dirs.async.T3Pack.zip');
done();

@@ -57,7 +63,7 @@ });

it("checks if the zipped file contains correct data (using JSZip)", function (done) {
fs.readFile("./tests/assets/dirs.async.T3Pack.zip", function (err, data) {
var zipped = new JSZip(data);
expect(zipped.files).to.have.property("world/").with.property('dir', true) &&

@@ -68,3 +74,3 @@ expect(zipped.files).to.have.property("says-hello") &&

expect(zipped.file("world/says-world").asText()).to.equal('World');
done();

@@ -74,2 +80,2 @@ });

});
});

@@ -12,7 +12,9 @@ var fs = require('fs');

it("should zip a file in memory without any errors", function (done) {
zipper.zip("./tests/assets/hello-world", function (zipped) {
zipper.zip("./tests/assets/hello-world", function (error, zipped) {
expect(error).to.equal(null);
localMemory.T1ZippedBuffer = zipped.memory();
done();

@@ -35,9 +37,13 @@ });

zipper.zip("./tests/assets/hello-world", function (zipped) {
zipper.zip("./tests/assets/hello-world", function (error, zipped) {
zipped.save("./tests/assets/files.async.T3Pack.zip", function () {
expect(error).to.equal(null);
zipped.save("./tests/assets/files.async.T3Pack.zip", function (error) {
expect(error).to.equal(null);
// make sure that the file exists on disk
fs.readdir("./tests/assets/", function (err, entries) {
fs.readdir("./tests/assets/", function (err, entries) {
expect(entries).to.include('files.async.T3Pack.zip');

@@ -50,3 +56,3 @@

});
/* Test 4: making sure that the zipped file from Test 3 contains correct data */

@@ -56,5 +62,5 @@ it("checks if the zipped file contains correct data (using JSZip)", function (done) {

fs.readFile("./tests/assets/files.async.T3Pack.zip", function (err, data) {
var zipped = new JSZip(data);
expect(zipped.files).to.have.property("hello-world") &&

@@ -69,7 +75,9 @@ expect(zipped.file("hello-world").asText()).to.equal("Hello World.");

it("zips a file directly from the buffer containing it", function (done) {
var buff = fs.readFileSync("./tests/assets/hello-world");
zipper.zip(buff, "hello-world", function (zipped) {
zipper.zip(buff, "hello-world", function (error, zipped) {
expect(error).to.equal(null);
localMemory.T5ZippedBuffer = zipped.memory();

@@ -80,8 +88,8 @@

});
/* Test 6: making sure that the zipped buffer from Test 5 contains correct data */
it("checks if the zipped buffer contains correct data (using JSZip)", function () {
var zipped = new JSZip(localMemory.T5ZippedBuffer);
expect(zipped.files).to.have.property("hello-world") &&

@@ -94,7 +102,9 @@ expect(zipped.file("hello-world").asText()).to.equal("Hello World.");

it("zips a ZippedFS form a previously unzipped files", function (done) {
var unzippedfs = zipper.sync.unzip("./tests/assets/hello.zip").memory();
zipper.zip(unzippedfs, function (zipped) {
zipper.zip(unzippedfs, function (error, zipped) {
expect(error).to.equal(null);
localMemory.T7ZippedBuffer = zipped.memory();

@@ -105,8 +115,8 @@

});
/* Test 8: making sure that the zipped buffer from Test 7 contains correct data */
it("checks if the zipped buffer contains correct data", function () {
var T8ZippedFS = zipper.sync.unzip(localMemory.T7ZippedBuffer).memory();
expect(T8ZippedFS.contents()).to.include("hello/says-hello") &&

@@ -119,2 +129,2 @@ expect(T8ZippedFS.read("hello/says-hello", 'text')).to.equal("Hello") &&

});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc