src/cli.ts   A
last analyzed

Complexity

Total Complexity 14
Complexity/F 14

Size

Lines of Code 90
Function Count 1

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 14
eloc 71
mnd 13
bc 13
fnc 1
dl 0
loc 90
rs 10
bpm 13
cpm 14
noi 0
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
A cli.ts ➔ printUsageAndExit 0 10 2
1
#!/usr/bin/env node
2
// TODO: Allow setting the default seed for future use. Use this: https://www.npmjs.com/package/preferences
3
import * as arrispwgen from '@borfast/arrispwgen';
4
5
function printUsageAndExit(exitCode?: number) {
6
    console.log(`\nUsage: ${process.argv0} start_date [end_date] [--seed=custom_seed]\n`);
7
    console.log('If you only want the password for one specific date, specify only "start_date".');
8
    console.log('If "end_date" is also passed, a password for each day between "start_date" and "end_date" will be generated.');
9
    console.log('The --seed parameter allows you to use a custom seed for the password generator. A seed must be 8 to 10 characters long.');
10
    console.log('The dates should be specified in ISO 8601 format, i.e. "YYYY-MM-DD". Example for Christmas day 2016: "2016-12-25".');
11
12
    if (exitCode) {
13
        process.exit(exitCode);
14
    }
15
}
16
17
const args = process.argv.slice(2);
18
19
if (args.indexOf('--help') > -1 || args.indexOf('-h') > -1) {
20
    printUsageAndExit(0);
21
}
22
if (args.length > 3) {
23
    console.log('Too many arguments.\n');
24
    printUsageAndExit(1);
25
}
26
27
const dates: Date[] = [];
28
let seed = arrispwgen.DEFAULT_SEED;
29
const dateRegex = /\d{4}-\d{2}-\d{2}/;
30
args.forEach((arg: string) => {
31
    if (arg.match(dateRegex)) {
32
        dates.push(new Date(arg));
33
    } else if (arg.indexOf('--seed=') == 0) {
34
        const s = arg.split('=')[1];
35
        if (s.length >= 8 && s.length <= 10) {
36
            seed = arg.split('=')[1];
37
        } else {
38
            const problem = s.length < 8 ? 'short' : s.length > 10 ? 'long' : ' unrecognized';
39
            console.log(`Seed is too ${problem}: ${s}.\nIt's ${s.length} characters but it must be between 8 and 10.`);
40
            printUsageAndExit(1);
41
        }
42
    } else {
43
        console.log(`Unrecognized argument: ${arg}.`);
44
        printUsageAndExit(1);
45
    }
46
});
47
48
49
const date_format_options = { weekday: 'short', year: 'numeric', month: 'long', day: '2-digit' };
50
const date_formatter = new Intl.DateTimeFormat('default', date_format_options);
51
52
let data = [];
53
54
// If no date is given, default to outputting the password for the current date.
55
if (dates.length === 0) {
56
    dates.push(new Date());
57
}
58
59
if (dates.length === 1) {
60
    const long_date = date_formatter.format(dates[0]);
61
    const potd = arrispwgen.generate(dates[0], seed);
62
    data.push({
63
        date: long_date,
64
        password: potd
65
    });
66
} else {
67
    const start_date = dates[0];
68
    const end_date = dates[1];
69
    try {
70
        const potd = arrispwgen.generate_multi(start_date, end_date, seed);
71
72
        for (const p of potd) {
73
            data.push({
74
                date: date_formatter.format(p['date']),
75
                password: p['password']
76
            });
77
        }
78
    } catch (e) {
79
        if (e instanceof arrispwgen.InvalidDateRangeError) {
80
            console.log('The given dates are out of order. Your start date is after the end date.');
81
            printUsageAndExit();
82
        } else {
83
            console.log(`Unknown error occurred: ${e.message}`);
84
        }
85
    }
86
}
87
88
console.log();
89
console.table(data, ['date', 'password']);
90