Skip to content

Commit 82dde97

Browse files
AndreiAndrei
authored andcommitted
new: parser
1 parent 4587d93 commit 82dde97

File tree

7 files changed

+329
-102
lines changed

7 files changed

+329
-102
lines changed

bun.lockb

702 Bytes
Binary file not shown.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
},
88
"devDependencies": {
99
"@types/bun": "latest",
10-
"@types/fs-extra": "^11.0.4"
10+
"@types/fs-extra": "^11.0.4",
11+
"@types/minimist": "^1.2.5"
1112
},
1213
"peerDependencies": {
1314
"typescript": "^5.0.0"
@@ -18,6 +19,7 @@
1819
"commander": "^12.1.0",
1920
"fs-extra": "^11.2.0",
2021
"inquirer": "^12.0.0",
22+
"minimist": "^1.2.8",
2123
"open": "^10.1.0"
2224
}
2325
}

src/index.ts

Lines changed: 88 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,25 @@
1-
import os from "os";
2-
import fs from "fs-extra";
31
import path from "path";
4-
import inquirer from "inquirer";
52
import { Command } from "commander";
6-
import logger from "./utils/logger"; // Assuming you have a logger utility
7-
import open from "open"
3+
import logger from "./utils/logger";
84
import Invoice from "./utils/invoice";
5+
import minimist from "minimist"
6+
import { initConfig, openConfigDirectory, openConfigurationFile, timeout } from "./utils";
7+
import * as os from "os"
8+
import inquirer from "inquirer";
9+
10+
const args = minimist(process.argv.slice(2))
11+
const isDebug = args.debug || false
12+
13+
logger.setDebugMode(isDebug)
914

1015
const program = new Command();
1116

1217
export const DEFAULT_DIR = path.join(os.homedir(), ".config", "icli/");
18+
export const DEFAULT_INVOICES_DIR = path.join(os.homedir(), "Documents", "Invoices/")
1319
export const DEFAULT_PATH = path.join(os.homedir(), ".config", "icli/icli.json");
1420
export const INVOICE_PATH = path.join(path.dirname(DEFAULT_PATH), "invoices.json");
1521

16-
export function configSetup(configPath: string) {
17-
return fs.existsSync(configPath);
18-
}
19-
20-
async function initConfig() {
21-
if (!configSetup(DEFAULT_PATH)) {
22-
const config = {
23-
appName: "Invoice CLI Tool",
24-
version: "1.0.0",
25-
createdAt: new Date().toISOString(),
26-
};
27-
28-
try {
29-
fs.ensureFileSync(DEFAULT_PATH);
30-
fs.writeJsonSync(DEFAULT_PATH, config, { spaces: 2 });
31-
logger.info(`Your configuration file has been set up.`);
32-
} catch (error) {
33-
console.log(error)
34-
logger.error('Error setting up configuration file');
35-
}
36-
}
37-
}
38-
39-
40-
async function openConfigDirectory() {
41-
const configDir = path.dirname(DEFAULT_PATH);
42-
try {
43-
await open(configDir); // Open the directory
44-
logger.info(`Opened configuration directory: ${configDir}`);
45-
} catch (error) {
46-
console.log(error)
47-
logger.error("Error opening configuration directory")
48-
}
49-
}
50-
51-
52-
53-
program
54-
.version("1.0.0")
55-
.description("Invoice CLI Tool");
56-
57-
program
58-
.command("setup")
59-
.description("Setup configuration file")
60-
.action(async () => {
61-
await initConfig();
62-
mainMenu();
63-
});
64-
65-
program
66-
.command("history")
67-
.description("View invoice history")
68-
.action(() => {
69-
new Invoice().viewHistory();
70-
mainMenu();
71-
});
72-
73-
program
74-
.command("create")
75-
.description("Create a new invoice")
76-
.action(async () => {
77-
await new Invoice().createInvoice();
78-
mainMenu();
79-
});
80-
81-
program
82-
.command('config')
83-
.description('Open the configuration file.')
84-
.action(openConfigDirectory)
85-
86-
program
87-
.command("exit")
88-
.description("Exit the CLI")
89-
.action(() => {
90-
logger.info("Exiting CLI...");
91-
process.exit(0);
92-
});
93-
94-
// Main menu to loop back to choices
95-
async function mainMenu() {
22+
export async function mainMenu() {
9623
const choices = await inquirer.prompt([
9724
{
9825
type: "list",
@@ -117,4 +44,80 @@ async function mainMenu() {
11744
mainMenu();
11845
}
11946

47+
48+
const commands = [
49+
{
50+
name: "setup",
51+
description: "Setup configuration file",
52+
action: async () => {
53+
await initConfig();
54+
await mainMenu();
55+
}
56+
},
57+
{
58+
name: "history",
59+
description: "View invoice history",
60+
action: async () => {
61+
new Invoice().viewHistory()
62+
await mainMenu()
63+
}
64+
},
65+
{
66+
name: "create",
67+
description: "Create a new invoice",
68+
action: async () => {
69+
await new Invoice().createInvoice(args.explicit ? false : true)
70+
await mainMenu()
71+
},
72+
option: [{
73+
value: 'explicit',
74+
description: "Explicitly select the values for your personal details"
75+
}]
76+
},
77+
{
78+
name: "config",
79+
description: "Open the configuration file",
80+
action: openConfigurationFile
81+
},
82+
{
83+
name: "cd",
84+
description: "Open the configuration directory",
85+
action: openConfigDirectory
86+
},
87+
{
88+
name: "defaults",
89+
description: "Setup your default details for creating invoices.",
90+
// options: [Object.keys(Invoice.prototype.defaultOptionPrompts).map(k => ({value: k, description: `Change default value for: ${k}`}))],
91+
options:
92+
Object.keys(new Invoice().defaultOptionPrompts)
93+
.map(o => ({ value: o.toLowerCase(), description: `Change default for: ${o}` })),
94+
action: async () => {
95+
await new Invoice().setupDefaultValues(Array.from(new Set(Object.keys(args).filter(o => o !== "_" && o !== "debug"))))
96+
},
97+
},
98+
{
99+
name: "exit",
100+
description: "Exit the CLI tool",
101+
action: () => {
102+
logger.info('Exiting CLI...')
103+
process.exit(0)
104+
}
105+
},
106+
]
107+
program
108+
.version("1.0.0")
109+
.description("Invoice CLI Tool")
110+
.option('--debug', "Display external logs")
111+
112+
commands.forEach((c) => {
113+
const cmd = program
114+
.command(c.name)
115+
.description(c.description)
116+
.action(c.action)
117+
118+
c.options?.forEach(c => {
119+
cmd.option(`--${c.value}`, c.description)
120+
})
121+
})
122+
120123
program.parse(process.argv);

src/utils/html.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import logger from "./logger"
22
import path from "path"
33
import fs from "fs-extra"
4-
import { load } from "cheerio"
4+
import { load, type CheerioAPI } from "cheerio"
55

66
class HTML {
7-
private requiredIds: string[] = ["sefu"]
7+
private requiredIds: string[] = ["wow"]
88

99
create(path: string) {
1010
return this.parser(path)
@@ -28,19 +28,23 @@ class HTML {
2828
const missingIds = this.requiredIds.filter(id => !idsFound.includes(id));
2929

3030
if (missingIds.length > 0 || !idsFound.length) {
31-
logger.error(`Missing IDs: ${missingIds.join(', ')}`);
31+
logger.debug().error(`Missing IDs: ${missingIds.join(', ')}`);
32+
throw new Error("Missing IDs")
3233
} else {
33-
logger.success('All required IDs are present in the HTML.');
34+
logger.debug().success('All required IDs are present in the HTML.');
3435
}
3536

3637
return true
3738
} catch (error) {
38-
logger.error(`An error occured`)
39-
39+
logger.debug().error(`An error occured: ${error}`)
4040
return false
4141
}
4242
}
4343

44+
async editor($: CheerioAPI) {
45+
46+
}
47+
4448
}
4549

4650
export default HTML

src/utils/index.ts

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import open from "open"
2+
import { exec } from "child_process"
3+
import * as os from "os"
4+
import path from "path"
5+
import logger from "./logger"
6+
import { DEFAULT_INVOICES_DIR, DEFAULT_PATH, mainMenu } from ".."
7+
import inquirer from "inquirer"
8+
import fs from "fs-extra"
9+
10+
export const timeout = async (t: number) => new Promise(r => setTimeout(r, t))
11+
12+
export async function openConfigurationFile() {
13+
const platform = os.platform()
14+
15+
if (platform !== 'darwin') {
16+
return logger.error('Unsupported operating system.')
17+
}
18+
19+
exec(`open ${DEFAULT_PATH}`, e => {
20+
if (e) {
21+
logger.error(`Can't open configuration file`)
22+
logger.debug().info(`${e}`)
23+
}
24+
})
25+
}
26+
27+
export async function openConfigDirectory() {
28+
const configDir = path.dirname(DEFAULT_PATH);
29+
try {
30+
await open(configDir);
31+
logger.info(`Opened configuration directory: ${configDir}`);
32+
} catch (error) {
33+
logger.error("Error opening configuration directory")
34+
}
35+
36+
process.exit(0)
37+
}
38+
39+
export async function getInvoiceDirectory() {
40+
const config = fs.readJsonSync(DEFAULT_PATH)
41+
if (config.invoices_path) return;
42+
43+
const { path } = await inquirer.prompt([
44+
{
45+
type: "input",
46+
name: "path",
47+
message: "Where should we save all your invoices?",
48+
default: DEFAULT_INVOICES_DIR,
49+
}
50+
])
51+
52+
try {
53+
config['invoices_path'] = path;
54+
ensureExists(path, 0o744, async function (e) {
55+
if (e) return logger.error(`Was unable to add the invoice directory. Please do this manually: ${path}`)
56+
57+
fs.writeJsonSync(DEFAULT_PATH, config, { spaces: 2 })
58+
logger.success("Created invoice path.")
59+
60+
})
61+
62+
return await timeout(2000)
63+
64+
} catch (e) {
65+
logger.error("Coundn't add the invoice path")
66+
logger.debug().error(`${e}`)
67+
}
68+
69+
}
70+
71+
function ensureExists(path: string, mask: any, cb: (v: any) => void) {
72+
if (typeof mask === 'function') {
73+
cb = mask;
74+
mask = 0o744
75+
}
76+
fs.mkdir(path, mask, function (e) {
77+
if (e) {
78+
if (e.code === "EEXIST") cb(null)
79+
else cb(e)
80+
} else cb(null)
81+
})
82+
}
83+
84+
export async function initConfig() {
85+
if (!configSetup(DEFAULT_PATH)) {
86+
const config = {
87+
appName: "Invoice CLI Tool",
88+
version: "1.0.0",
89+
createdAt: new Date().toISOString(),
90+
};
91+
92+
try {
93+
fs.ensureFileSync(DEFAULT_PATH);
94+
fs.writeJsonSync(DEFAULT_PATH, config, { spaces: 2 });
95+
logger.info(`Your configuration file has been set up.`);
96+
} catch (error) {
97+
logger.error('Error setting up configuration file');
98+
}
99+
}
100+
101+
await getInvoiceDirectory()
102+
}
103+
104+
export function configSetup(configPath: string) {
105+
return fs.existsSync(configPath);
106+
}
107+
108+

0 commit comments

Comments
 (0)