├── .gitignore
├── Distribution
├── .gitkeep
├── Block.js
├── Chain.js
└── Index.js
├── LICENSE
├── README.md
├── Source
├── Block.ts
├── Chain.ts
└── Index.ts
├── Tests
└── index.js
├── chainDB.svg
├── package-lock.json
├── package.json
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | *.code-workspace
--------------------------------------------------------------------------------
/Distribution/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChristoPy/chainDB/3a705f3126591afb36724bc268cc82cff27832b0/Distribution/.gitkeep
--------------------------------------------------------------------------------
/Distribution/Block.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 | var HashJS = require("hash.js");
4 | var BlowFish = require("egoroof-blowfish");
5 | var Hash = HashJS["sha"];
6 | var GENESIS_BLOCK_HASH = Hash.sha256().update("chainDB").digest("hex");
7 | var Block = /** @class */ (function () {
8 | function Block(Name, Content, PreviousBlockHash) {
9 | this.Name = Name;
10 | this.PreviousBlockHash = PreviousBlockHash || GENESIS_BLOCK_HASH;
11 | this.Content = Content;
12 | this.TimeStamp = new Date().toLocaleTimeString();
13 | }
14 | Block.prototype.Encrypt = function () {
15 | this.__EncryptBlockContent__();
16 | this.__CalculateHash__();
17 | };
18 | Block.prototype.Decrypt = function () {
19 | return this.__DecryptBlockContent__();
20 | };
21 | Block.prototype.__CalculateHash__ = function () {
22 | var ThingsToBeHashed = this.Name + " - " + this.Content + " - " + this.PreviousBlockHash + " - " + this.TimeStamp;
23 | this.BlockHash = Hash.sha256().update(ThingsToBeHashed).digest("hex");
24 | };
25 | Block.prototype.__EncryptBlockContent__ = function () {
26 | var BF = this.__ConfigureBlowFish__();
27 | this.Content = BF.encode(JSON.stringify(this.Content));
28 | };
29 | Block.prototype.__DecryptBlockContent__ = function () {
30 | var BF = this.__ConfigureBlowFish__();
31 | return BF.decode(Uint8Array.from(Object["values"](JSON.parse(this.Content))), BlowFish.TYPE.STRING);
32 | };
33 | Block.prototype.__ConfigureBlowFish__ = function () {
34 | var BF = new BlowFish(this.PreviousBlockHash, BlowFish.MODE.ECB, BlowFish.PADDING.NULL);
35 | BF.setIv(this.PreviousBlockHash.slice(0, 8));
36 | return BF;
37 | };
38 | return Block;
39 | }());
40 | exports["default"] = Block;
41 |
--------------------------------------------------------------------------------
/Distribution/Chain.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 | var FS = require("fs");
4 | var Path = require("path");
5 | var Block_1 = require("./Block");
6 | var OS = require("os");
7 | var Chain = /** @class */ (function () {
8 | function Chain(Name) {
9 | this.Chain = [];
10 | if (!Name) {
11 | throw new Error("The chain must have a name.");
12 | }
13 | this.Name = Name;
14 | this.__DBPath__ = Path.join(OS.homedir(), ".chainDB/" + this.Name);
15 | this.Chain = (FS.existsSync(Path.join(this.__DBPath__, "chainDB")) ? this.__GetFile__("chainDB", true) : []);
16 | this.__MakeChainPath__();
17 | }
18 | Chain.prototype.NewBlock = function (Name, Content) {
19 | this.CurrentBlock = new Block_1["default"](Name, Content, this.__PreviousBlockHash__());
20 | this.CurrentBlock.Encrypt();
21 | this.Chain.push({
22 | Name: this.CurrentBlock.Name,
23 | PreviousBlockHash: this.CurrentBlock.PreviousBlockHash,
24 | CurrentBlockHash: this.CurrentBlock.BlockHash
25 | });
26 | this.__MakeFile__(this.CurrentBlock.BlockHash, JSON.stringify(this.CurrentBlock.Content), null);
27 | this.__MakeFile__("chainDB", JSON.stringify(this.Chain));
28 | };
29 | Chain.prototype.GetBlock = function (BlockName, Return) {
30 | var _this = this;
31 | if (Return === void 0) { Return = "all"; }
32 | var ReturnEspecification = ["all", "last", "first"];
33 | var Found = this.Chain.filter(function (Block) { return Block.Name === BlockName; });
34 | if (Found.length === 0) {
35 | return null;
36 | }
37 | switch (Return) {
38 | case "first": return this.__DecryptBlock__(Found[0]);
39 | case "last": return this.__DecryptBlock__(Found[Found.length - 1]);
40 | default: return Found.map(function (BlockFound) { return JSON.parse(_this.__DecryptBlock__(BlockFound)); });
41 | }
42 | };
43 | Chain.prototype.__DecryptBlock__ = function (BlockData) {
44 | if (!BlockData) {
45 | throw new Error("A Block Must Be Given To Be Decrypted.");
46 | }
47 | var BlockDataContent = this.__GetFile__(BlockData.CurrentBlockHash);
48 | var DecryptedBlock = new Block_1["default"](BlockData.Name, BlockDataContent, BlockData.PreviousBlockHash);
49 | DecryptedBlock.BlockHash = BlockData.CurrentBlockHash;
50 | return DecryptedBlock.Decrypt();
51 | };
52 | Chain.prototype.__MakeChainPath__ = function () {
53 | try {
54 | FS.mkdirSync(this.__DBPath__);
55 | }
56 | catch (SomeError) {
57 | if (SomeError.code !== "EEXIST") {
58 | throw SomeError;
59 | }
60 | }
61 | };
62 | Chain.prototype.__GetFile__ = function (FileName, Parse, Encode) {
63 | if (Parse === void 0) { Parse = false; }
64 | if (Encode === void 0) { Encode = "utf-8"; }
65 | var File;
66 | try {
67 | File = FS.readFileSync(Path.join(this.__DBPath__, FileName), Encode);
68 | }
69 | catch (SomeError) {
70 | throw (SomeError);
71 | }
72 | if (File) {
73 | return (Parse ? JSON.parse(File) : File);
74 | }
75 | };
76 | Chain.prototype.__MakeFile__ = function (FileName, Content, Encode) {
77 | if (Encode === void 0) { Encode = "utf-8"; }
78 | try {
79 | FS.writeFileSync(Path.join(this.__DBPath__, FileName), Content, Encode);
80 | }
81 | catch (SomeError) {
82 | throw (SomeError);
83 | }
84 | };
85 | Chain.prototype.__PreviousBlockHash__ = function () {
86 | return this.Chain.length > 0 ? this.Chain[this.Chain.length - 1].CurrentBlockHash : null;
87 | };
88 | return Chain;
89 | }());
90 | exports["default"] = Chain;
91 |
--------------------------------------------------------------------------------
/Distribution/Index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var FS = require("fs");
3 | var Path = require("path");
4 | var OS = require("os");
5 | var Chain_1 = require("./Chain");
6 | try {
7 | FS.mkdirSync(Path.join(OS.homedir(), ".chainDB"));
8 | }
9 | catch (SomeError) {
10 | if (SomeError.code !== "EEXIST") {
11 | throw SomeError;
12 | }
13 | }
14 | var chainDB = /** @class */ (function () {
15 | function chainDB() {
16 | }
17 | chainDB.prototype.New = function (Name) {
18 | this.DB = new Chain_1["default"](Name);
19 | };
20 | chainDB.prototype.Add = function (Name, Content) {
21 | this.DB.NewBlock(Name, Content);
22 | };
23 | chainDB.prototype.First = function (Name) {
24 | return this.DB.GetBlock(Name, "first");
25 | };
26 | chainDB.prototype.Last = function (Name) {
27 | return this.DB.GetBlock(Name, "last");
28 | };
29 | chainDB.prototype.All = function (Name) {
30 | return this.DB.GetBlock(Name);
31 | };
32 | return chainDB;
33 | }());
34 | module.exports = new chainDB();
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Christopher Ribeiro
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | A noSQL database based on blockchain technology. It's purpose is to store data using a simple append only system (maybe a future way to edit Blocks?).
5 |
6 |