feat: remove complete dependency on bun to be able to compile to .js

This commit is contained in:
2024-10-08 10:23:17 +05:30
parent 50d377d6bd
commit d5669b2988
8 changed files with 75 additions and 79 deletions

1
.gitignore vendored
View File

@@ -177,3 +177,4 @@ dist
# confidant
env.ts
test
executables

BIN
bun.lockb

Binary file not shown.

View File

@@ -1,7 +1,6 @@
#!/bin/env bun
#!/bin/env node
import { input, password } from "@inquirer/prompts";
import { $ } from "bun";
import chalk from "chalk-template";
import { Command } from "commander";
import { decrypt_vault, encrypt_vault, initialize, reset } from "./src/main";
@@ -18,7 +17,6 @@ import {
const program = new Command();
const { exit } = process;
$.nothrow();
program.name("confidant").description("Creates a very secure file vault.");

View File

@@ -1,15 +1,15 @@
{
"name": "confidant",
"version": "1.0.0",
"version": "1.1.0",
"module": "confidant.ts",
"type": "module",
"scripts": {
"init": "bun ./scripts/init.ts",
"sh": "bun ./scripts/sh.ts",
"build": "bun ./scripts/build.ts"
"build": "bun build --minify ./confidant.ts --target node --outfile ./dist/confidant.mjs",
"build-exec": "bun build --compile --minify ./confidant.ts --outfile ./dist/confidant"
},
"bin": {
"confidant": "./confidant.ts"
"confidant": "./dist/confidant.mjs"
},
"devDependencies": {
"@types/bun": "latest"
@@ -20,9 +20,11 @@
"dependencies": {
"@iarna/toml": "^2.2.5",
"@inquirer/prompts": "^6.0.1",
"@types/adm-zip": "^0.5.5",
"@types/commander": "^2.12.2",
"@types/crypto-js": "^4.2.2",
"@types/eccrypto": "^1.1.6",
"adm-zip": "^0.5.16",
"argon2": "^0.41.1",
"chalk": "^5.3.0",
"chalk-template": "^1.1.0",

View File

@@ -1,11 +0,0 @@
import { $ } from "bun";
import data from "../package.json";
const { version: ver } = data;
await $`
rm -rf ./dist
bun build --compile --minify --target=bun-linux-x64 ./confidant.ts --outfile ./dist/confidant_${ver}_linux_x64
bun build --compile --minify --target=bun-windows-x64 ./confidant.ts --outfile ./dist/confidant_${ver}_win_x64.exe
bun build --compile --minify --target=bun-darwin-arm64 ./confidant.ts --outfile ./dist/confidant_${ver}_darwin_arm64
`;

View File

@@ -1,7 +1,7 @@
import { $ } from "bun";
import { stringy } from "../src/utils";
import { randomBytes } from "crypto";
import chalkTemplate from "chalk-template";
import { writeFileSync } from "fs";
const envstring = `// env.ts
const env = {
@@ -15,5 +15,5 @@ const env = {
export default env;
`;
await $`echo ${envstring} > env.ts`;
writeFileSync("./env.ts", envstring);
console.log(chalkTemplate`{green env.ts initialized sucessfully!}`);

View File

@@ -1,8 +1,7 @@
import { parse, stringify } from "@iarna/toml";
import { $ } from "bun";
import { pbkdf2Sync as pbkdf2, randomBytes } from "crypto";
import { derive, getPublic } from "eccrypto";
import { readFileSync, writeFileSync } from "fs";
import { readFileSync, rmSync, writeFileSync } from "fs";
import {
buffer,
decrypt,
@@ -24,6 +23,7 @@ import env from "../env";
import { AES, enc, HmacSHA256 } from "crypto-js";
import chalk from "chalk-template";
import { input, password } from "@inquirer/prompts";
import AdmZip from "adm-zip";
console.info = function () {};
const { exit } = process;
@@ -36,8 +36,10 @@ export async function initialize(password: string, dirname: string) {
const salt = randomBytes(32);
const code = random(10000, 100000);
const D = pbkdf2(S_AB, salt, code, 64, "sha256");
await $`zip -r9 confidant.zip ${dirname} > /dev/null`;
await $`rm -rf ${dirname}`;
const zip = new AdmZip();
zip.addLocalFolder("./" + dirname);
zip.writeZip("./confidant.zip");
rmSync(dirname, { recursive: true });
const Z = readFileSync("confidant.zip");
const E_Z = encrypt_file(Z, D);
@@ -84,13 +86,12 @@ export async function initialize(password: string, dirname: string) {
console.log(`Recovery phrase:`);
console.log(chalk`{magenta ${recovery_phrase}}`);
await $`rm confidant.zip`;
rmSync("confidant.zip");
// create .gitignore
const gitignore = `# .gitignore
*.con
*.fid
*.key
*_recovery.txt
confidant.zip
*.confidant
@@ -132,7 +133,9 @@ export async function decrypt_vault(password: string, dirname: string) {
const Z = decrypt_file(E_Z, D);
writeFileSync(`confidant.zip`, Z);
writeFileSync(`.${dirname}.confidant`, encrypt(D, buffer(env.AUTH_KEY)));
await $`unzip confidant.zip > /dev/null && rm confidant.zip`;
const unzip = new AdmZip("./confidant.zip");
unzip.extractAllTo(`./${dirname}`, true);
rmSync("./confidant.zip");
} catch (e) {
panic`Error decrypting vault. The files could be corrupted.`;
}
@@ -145,8 +148,10 @@ export async function encrypt_vault(dirname: string) {
buffer(env.AUTH_KEY),
);
// create zip file and encrypt it
await $`zip -r9 confidant.zip ${dirname} > /dev/null`;
await $`rm -rf ${dirname}`;
const zip = new AdmZip();
zip.addLocalFolder("./" + dirname);
zip.writeZip("./confidant.zip");
rmSync(dirname, { recursive: true });
const Z = readFileSync("confidant.zip");
const E_Z = encrypt_file(Z, D);
@@ -159,7 +164,8 @@ export async function encrypt_vault(dirname: string) {
`${dirname}.vault`,
Buffer.concat([vaultfile.subarray(0, index), separator, E_Z]),
);
await $`rm confidant.zip .${dirname}.confidant`;
rmSync("./confidant.zip");
rmSync(`./.${dirname}.confidant`);
} catch (e) {
panic`Error encrypting vault. The files could be corrupted.`;
}
@@ -231,7 +237,7 @@ export async function reset(dirname: string, recoverystring: string) {
]),
);
writeFileSync(`${dirname}_recovery.txt`, newrecphrase);
writeFileSync(`${dirname}_recovery.txt`, newrecphrase + "\n");
console.log(`New recovery phrase:`);
console.log(chalk`{magenta ${newrecphrase}}`);
} catch (e) {

View File

@@ -3,7 +3,6 @@ import { createHmac } from "crypto";
import { generatePrivate, getPublic } from "eccrypto";
import { generate } from "random-words";
import chalk from "chalk-template";
import { $ } from "bun";
import { existsSync, readdirSync } from "fs";
import { select } from "@inquirer/prompts";
@@ -61,15 +60,6 @@ export function decrypt_file(input: Buffer, key: Buffer) {
return Buffer.from(result.toString(enc.Utf8), "base64");
}
export async function exists(dir: string) {
try {
await $`test -d ${dir}`;
return true;
} catch (e) {
return false;
}
}
export function log(
str: TemplateStringsArray,
...placeholders: unknown[]
@@ -109,13 +99,17 @@ export function print(key: string, value: string) {
export class Files {
data: string[] | null = null;
constructor(regex?: RegExp | string) {
constructor(regex?: RegExp | string | string[]) {
if (!regex) {
return this;
}
try {
const data = readdirSync(".").filter((x) => x.match(regex));
this.data = data ? data.map((x) => x.replace(regex, "$1")) : null;
if (Array.isArray(regex)) {
this.data = regex;
} else {
const data = readdirSync(".").filter((x) => x.match(regex));
this.data = data ? data.map((x) => x.replace(regex, "$1")) : null;
}
} catch (error) {
console.error("Error executing command:", error);
this.data = null;
@@ -130,51 +124,57 @@ export class Files {
return `[ ${this.data ? this.data.join(", ") : "empty"} ]`;
}
intersection(a: Files) {
intersection(a: Files): Files {
const obj = new Files();
obj.data = Array.from(new Set(this.data).intersection(new Set(a.data)));
if (this.data && a.data) {
obj.data = this.data.filter((x) => a.data!.includes(x));
}
return obj;
}
difference(a: Files) {
difference(a: Files): Files {
const obj = new Files();
obj.data = Array.from(new Set(this.data).difference(new Set(a.data)));
if (this.data && a.data) {
obj.data = this.data.filter((x) => !a.data!.includes(x));
}
return obj;
}
}
export async function getDirectoryNames() {
const dirlist = (await $`ls -d */`.text()).trim();
try {
const dirlist = readdirSync(".", { withFileTypes: true })
.filter((file) => file.isDirectory())
.map((file) => file.name);
if (!dirlist) {
panic`No directories found in current directory, please create one and run "init" again.`;
return;
if (dirlist.length === 0) {
panic`No directories found in current directory, please create one and run "init" again.`;
return;
}
const dirs = new Files(dirlist);
const vaults = new Files(/.*\.vault/g);
const usableDirs = dirs.difference(vaults);
if (usableDirs.data && usableDirs.data.length === 0) {
panic`No usable directories found in current directory, please create one and run "init" again.`;
return;
} else if (usableDirs.data && usableDirs.data.length === 1) {
return usableDirs.data[0];
}
const dirname = await select({
message: "Select a directory to use:",
choices: usableDirs.data!.map((x) => ({
name: x,
value: x,
})),
});
return dirname;
} catch (e) {
console.log(chalk`{red ${e.message}}`);
process.exit(1);
}
let dirs: string[];
const vaultList = (await $`ls *.vault`.text()).trim().match(/.*\.vault/g);
if (vaultList) {
const vaults = vaultList.map((x) => x.replace(".vault", ""));
dirs = Array.from(new Set(dirlist.split("\n")).difference(new Set(vaults)));
} else {
dirs = dirlist.split("\n");
}
if (dirs.length === 0) {
panic`No usable directories found in current directory, please create one and run "init" again.`;
return;
} else if (dirs.length === 1) {
return dirs[0];
}
const dirname = await select({
message: "Select a directory to use:",
choices: dirs.map((x) => ({
name: x,
value: x,
})),
});
return dirname;
}
export async function getVaultName() {
@@ -252,7 +252,7 @@ export async function getDecryptedName() {
export function getRandomPassword(length: number) {
const STRING =
"0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*()ABCDEFGHIJKLMNOPQRSTUVWXYZ";
"0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let pass = "";
while (pass.length < length) {