@n42/cli 0.1.71 → 0.1.88
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/auth.js +34 -36
- package/src/cli.js +53 -19
- package/src/completion/bash.sh +8 -1
- package/src/config.js +3 -2
- package/src/db.js +7 -2
- package/src/discover.js +18 -10
- package/src/errors.js +3 -3
- package/src/user.js +38 -13
- package/src/utils.js +68 -2
- package/test/auth.test.js +12 -7
- package/test/db.test.js +0 -1
package/package.json
CHANGED
package/src/auth.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
|
-
const { NODE42_DIR, TOKENS_FILE, API_URL, EP_SIGNIN, EP_REFRESH } = require("./config");
|
|
2
|
+
const { NODE42_DIR, TOKENS_FILE, API_URL, EP_SIGNIN, EP_REFRESH, EP_ME } = require("./config");
|
|
3
3
|
const { handleError } = require("./errors");
|
|
4
|
-
const {
|
|
4
|
+
const { getUserWithIndex } = require("./user");
|
|
5
5
|
const { clearScreen, ask, startSpinner } = require("./utils");
|
|
6
6
|
const db = require("./db");
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
async function login() {
|
|
10
10
|
clearScreen("Sign in to Node42");
|
|
11
|
-
let user =
|
|
11
|
+
let user = getUserWithIndex(0);
|
|
12
12
|
|
|
13
13
|
const username = await ask("Username", user.userMail ?? "");
|
|
14
14
|
const password = await ask("Password", null, true);
|
|
@@ -24,17 +24,16 @@ async function login() {
|
|
|
24
24
|
|
|
25
25
|
if (!res.ok) {
|
|
26
26
|
stopSpinner();
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
console.error(`Login failed (${res.status}) – Invalid credentials`);
|
|
29
29
|
process.exit(1);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const tokens = await res.json();
|
|
33
|
-
|
|
33
|
+
stopSpinner();
|
|
34
|
+
|
|
34
35
|
const { accessToken, refreshToken, idToken } = tokens;
|
|
35
36
|
if (!accessToken || !refreshToken || !idToken) {
|
|
36
|
-
stopSpinner();
|
|
37
|
-
|
|
38
37
|
console.error("Invalid auth response");
|
|
39
38
|
process.exit(1);
|
|
40
39
|
}
|
|
@@ -45,13 +44,17 @@ async function login() {
|
|
|
45
44
|
JSON.stringify({ accessToken, refreshToken, idToken }, null, 2)
|
|
46
45
|
);
|
|
47
46
|
|
|
48
|
-
stopSpinner();
|
|
49
47
|
stopSpinner = startSpinner();
|
|
50
48
|
|
|
51
|
-
await checkAuth();
|
|
52
|
-
user = getUser();
|
|
49
|
+
const authenticated = await checkAuth();
|
|
53
50
|
stopSpinner();
|
|
54
|
-
|
|
51
|
+
|
|
52
|
+
if (!authenticated) {
|
|
53
|
+
console.error("Not authenticated");
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
user = getUserWithIndex(0);
|
|
55
58
|
console.log(
|
|
56
59
|
`Authenticated as ${user.userName} <${user.userMail}> (${user.role})`
|
|
57
60
|
);
|
|
@@ -61,14 +64,12 @@ function logout() {
|
|
|
61
64
|
if (fs.existsSync(TOKENS_FILE)) {
|
|
62
65
|
fs.unlinkSync(TOKENS_FILE);
|
|
63
66
|
}
|
|
64
|
-
|
|
65
|
-
let user = getUser();
|
|
66
|
-
db.delete("user", user.id);
|
|
67
|
+
db.clear("user");
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
function
|
|
70
|
+
function loadTokens() {
|
|
70
71
|
if (!fs.existsSync(TOKENS_FILE)) {
|
|
71
|
-
console.error("
|
|
72
|
+
console.error("Tokens missing...\nRun: n42 login");
|
|
72
73
|
process.exit(1);
|
|
73
74
|
}
|
|
74
75
|
return JSON.parse(fs.readFileSync(TOKENS_FILE, "utf8"));
|
|
@@ -77,10 +78,10 @@ function loadAuth() {
|
|
|
77
78
|
async function checkAuth() {
|
|
78
79
|
if (!fs.existsSync(TOKENS_FILE)) {
|
|
79
80
|
handleError({ code: "N42E-9033", message: "Token missing..."})
|
|
80
|
-
|
|
81
|
+
return false;
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
const res = await fetchWithAuth(`${API_URL}
|
|
84
|
+
const res = await fetchWithAuth(`${API_URL}/${EP_ME}`, {
|
|
84
85
|
method: "GET",
|
|
85
86
|
headers: {
|
|
86
87
|
"Content-Type": "application/json"
|
|
@@ -93,25 +94,22 @@ async function checkAuth() {
|
|
|
93
94
|
|
|
94
95
|
if (!res.ok) {
|
|
95
96
|
const err = await res.json();
|
|
96
|
-
|
|
97
|
+
handleError(err);
|
|
97
98
|
return false;
|
|
98
99
|
}
|
|
99
100
|
|
|
100
|
-
const
|
|
101
|
-
//console.log(
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
const userInfo = await res.json();
|
|
102
|
+
//console.log(userInfo);
|
|
103
|
+
|
|
104
|
+
if (userInfo) {
|
|
104
105
|
db.upsert("user", {
|
|
105
|
-
id:
|
|
106
|
-
userName:
|
|
107
|
-
userMail:
|
|
108
|
-
role:
|
|
109
|
-
rateLimits:
|
|
110
|
-
serviceUsage:
|
|
106
|
+
id: userInfo.sub,
|
|
107
|
+
userName: userInfo.userName,
|
|
108
|
+
userMail: userInfo.userMail,
|
|
109
|
+
role: userInfo.role,
|
|
110
|
+
rateLimits: userInfo.rateLimits,
|
|
111
|
+
serviceUsage: userInfo.serviceUsage,
|
|
111
112
|
})
|
|
112
|
-
|
|
113
|
-
db.replace("serviceUsage", auth.serviceUsage);
|
|
114
|
-
db.replace("rateLimits", auth.rateLimits);
|
|
115
113
|
return true;
|
|
116
114
|
}
|
|
117
115
|
|
|
@@ -119,7 +117,7 @@ async function checkAuth() {
|
|
|
119
117
|
}
|
|
120
118
|
|
|
121
119
|
async function refreshSession() {
|
|
122
|
-
const { refreshToken } =
|
|
120
|
+
const { refreshToken } = loadTokens();
|
|
123
121
|
if (!refreshToken) {
|
|
124
122
|
return false;
|
|
125
123
|
}
|
|
@@ -160,7 +158,7 @@ async function refreshSession() {
|
|
|
160
158
|
}
|
|
161
159
|
|
|
162
160
|
async function fetchWithAuth(url, options = {}) {
|
|
163
|
-
let { accessToken } =
|
|
161
|
+
let { accessToken } = loadTokens();
|
|
164
162
|
if (!accessToken) {
|
|
165
163
|
handleError({ code: "N42E-9032" });
|
|
166
164
|
return;
|
|
@@ -183,7 +181,7 @@ async function fetchWithAuth(url, options = {}) {
|
|
|
183
181
|
return res;
|
|
184
182
|
}
|
|
185
183
|
|
|
186
|
-
accessToken =
|
|
184
|
+
accessToken = loadTokens().accessToken;
|
|
187
185
|
return fetch(url, {
|
|
188
186
|
...options,
|
|
189
187
|
headers: {
|
|
@@ -193,4 +191,4 @@ async function fetchWithAuth(url, options = {}) {
|
|
|
193
191
|
});
|
|
194
192
|
}
|
|
195
193
|
|
|
196
|
-
module.exports = { login, logout,
|
|
194
|
+
module.exports = { login, logout, loadTokens, checkAuth, fetchWithAuth };
|
package/src/cli.js
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const { Command } = require("commander");
|
|
4
4
|
const { login, logout, checkAuth } = require("./auth");
|
|
5
|
-
const {
|
|
5
|
+
const { getUserWithIndex, getUserUsage } = require("./user");
|
|
6
6
|
const { runDiscovery } = require("./discover");
|
|
7
|
-
const { clearScreen, startSpinner, validateEnv, validateId, createAppDirs, getArtefactExt } = require("./utils");
|
|
7
|
+
const { clearScreen, startSpinner, validateEnv, validateId, createAppDirs, getArtefactExt, cleanAppDirs } = require("./utils");
|
|
8
8
|
const { NODE42_DIR, ARTEFACTS_DIR, DEFAULT_OUTPUT, DEFAULT_FORMAT } = require("./config");
|
|
9
9
|
|
|
10
10
|
createAppDirs();
|
|
@@ -18,7 +18,7 @@ const path = require("path");
|
|
|
18
18
|
|
|
19
19
|
program
|
|
20
20
|
.name("n42")
|
|
21
|
-
.description("Command-line interface for eDelivery path discovery and diagnostics")
|
|
21
|
+
.description("Node42 Command-line interface for eDelivery path discovery and diagnostics")
|
|
22
22
|
.version(pkg.version);
|
|
23
23
|
|
|
24
24
|
program
|
|
@@ -50,16 +50,34 @@ program
|
|
|
50
50
|
.description("Terminate user session and delete all local tokens")
|
|
51
51
|
.action(logout);
|
|
52
52
|
|
|
53
|
+
program
|
|
54
|
+
.command("clean")
|
|
55
|
+
.description("Remove locally stored artefacts and cache")
|
|
56
|
+
.option("--tokens", "Remove stored authentication tokens")
|
|
57
|
+
.option("--artefacts", "Remove artefacts")
|
|
58
|
+
.option("--transactions", "Remove transactions")
|
|
59
|
+
.option("--validations", "Remove validations")
|
|
60
|
+
.option("--db", "Remove local database")
|
|
61
|
+
.option("--all", "Wipe all local data")
|
|
62
|
+
.action((options)=> {
|
|
63
|
+
cleanAppDirs(options);
|
|
64
|
+
});
|
|
65
|
+
|
|
53
66
|
program
|
|
54
67
|
.command("me")
|
|
55
68
|
.description("Returns identity and billing status for the authenticated user.")
|
|
56
69
|
.action(async () => {
|
|
57
70
|
const stopSpinner = startSpinner();
|
|
58
71
|
|
|
59
|
-
await checkAuth();
|
|
60
|
-
const user = getUser();
|
|
72
|
+
const authenticated = await checkAuth();
|
|
61
73
|
stopSpinner();
|
|
74
|
+
|
|
75
|
+
if (!authenticated) {
|
|
76
|
+
console.error("Not authenticated");
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
62
79
|
|
|
80
|
+
const user = getUserWithIndex(0);
|
|
63
81
|
const currentMonth = new Date().toISOString().slice(0, 7);
|
|
64
82
|
console.log(`Node42 CLI v${pkg.version}
|
|
65
83
|
User
|
|
@@ -71,7 +89,7 @@ program
|
|
|
71
89
|
Rate Limits
|
|
72
90
|
Discovery : ${user.rateLimits.discovery}
|
|
73
91
|
Transactions : ${user.rateLimits.transactions}
|
|
74
|
-
Validation
|
|
92
|
+
Validation : ${user.rateLimits.validation}
|
|
75
93
|
|
|
76
94
|
Usage (Current Month)
|
|
77
95
|
Discovery : ${user.serviceUsage.discovery[currentMonth] ?? 0}
|
|
@@ -83,25 +101,31 @@ program
|
|
|
83
101
|
program
|
|
84
102
|
.command("usage <service>")
|
|
85
103
|
.description("Returns usage for the authenticated user.")
|
|
86
|
-
.
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
104
|
+
.option("-m, --month <yyyy-mm>", "Show usage for a specific month")
|
|
105
|
+
.action((service, options) => {
|
|
106
|
+
const user = getUserWithIndex(0);
|
|
107
|
+
const currentMonth = options.month ? options.month : new Date().toISOString().slice(0, 7);
|
|
108
|
+
let usage = getUserUsage(user.id, service, currentMonth);
|
|
109
|
+
if (!usage) {
|
|
110
|
+
usage = 0;
|
|
111
|
+
}
|
|
92
112
|
|
|
93
113
|
clearScreen(`Node42 CLI v${pkg.version}`);
|
|
94
114
|
console.log(`Usage for ${service} (${currentMonth}): ${usage}`);
|
|
95
115
|
});
|
|
96
116
|
|
|
97
117
|
program
|
|
98
|
-
.command("history
|
|
118
|
+
.command("history [participantId]")
|
|
99
119
|
.description("Show local discovery history for a participant")
|
|
100
120
|
.option("--today", "Show only today's artefacts")
|
|
101
121
|
.option("--day <yyyy-mm-dd>", "Show artefacts for a specific day")
|
|
102
122
|
.option("--last <n>", "Show only last N results", parseInt)
|
|
103
123
|
.action((participantId, options) => {
|
|
104
|
-
let artefacts =
|
|
124
|
+
let artefacts = participantId
|
|
125
|
+
? db.artefactsByParticipant(participantId)
|
|
126
|
+
: db.get("artefacts");
|
|
127
|
+
|
|
128
|
+
artefacts ??= [];
|
|
105
129
|
|
|
106
130
|
// newest first
|
|
107
131
|
artefacts.sort((a, b) => b.createdAt - a.createdAt);
|
|
@@ -140,13 +164,23 @@ program
|
|
|
140
164
|
clearScreen(`Node42 CLI v${pkg.version}`);
|
|
141
165
|
console.log(`Found ${artefacts.length} artefact(s)${filterInfo}\n`);
|
|
142
166
|
|
|
167
|
+
const DATE = "DATE".padEnd(19);
|
|
168
|
+
const PID = "PID".padEnd(15);
|
|
169
|
+
const FILE = "FILE";
|
|
170
|
+
console.log(`${DATE} ${PID} ${FILE}`);
|
|
171
|
+
|
|
143
172
|
for (const item of artefacts) {
|
|
144
173
|
const d = new Date(item.createdAt);
|
|
145
174
|
const dt = d.toISOString().slice(0, 19).replace("T", " ");
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
175
|
+
const file = path.join(ARTEFACTS_DIR, `${item.file}`);
|
|
176
|
+
|
|
177
|
+
let pid = item.participantId;
|
|
178
|
+
if (!participantId) {
|
|
179
|
+
pid = pid.length > 15 ? pid.substring(0, 12) + "..." : pid
|
|
180
|
+
console.log(`${dt} ${pid.padEnd(15)} ${file}`);
|
|
181
|
+
} else {
|
|
182
|
+
console.log(`${dt} ${file}`);
|
|
183
|
+
}
|
|
150
184
|
}
|
|
151
185
|
|
|
152
186
|
console.log("");
|
|
@@ -159,7 +193,7 @@ const discover = program
|
|
|
159
193
|
|
|
160
194
|
discover
|
|
161
195
|
.command("peppol <participantId>")
|
|
162
|
-
.description("Resolve the Peppol eDelivery
|
|
196
|
+
.description("Resolve and validate the full (Peppol) eDelivery path:\nSML/SMK (BDXR DNS) lookup, SMP resolution, endpoint discovery, and TLS diagnostics.")
|
|
163
197
|
.option("-e, --env <environment>", "Environment", "TEST")
|
|
164
198
|
.option("-o, --output <type>", "Result type (json | plantuml)", DEFAULT_OUTPUT)
|
|
165
199
|
.option("-f, --format <format>", "When output=plantuml (svg | text)", DEFAULT_FORMAT)
|
package/src/completion/bash.sh
CHANGED
|
@@ -3,17 +3,24 @@ _n42_completions()
|
|
|
3
3
|
local cur prev words cword
|
|
4
4
|
_init_completion || return
|
|
5
5
|
|
|
6
|
-
local commands="login logout me usage history discover"
|
|
6
|
+
local commands="login logout me usage history discover clean"
|
|
7
7
|
|
|
8
8
|
if [[ $cword -eq 1 ]]; then
|
|
9
9
|
COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
|
|
10
10
|
return
|
|
11
11
|
fi
|
|
12
12
|
|
|
13
|
+
# discover peppol
|
|
13
14
|
if [[ ${words[1]} == "discover" && $cword -eq 2 ]]; then
|
|
14
15
|
COMPREPLY=( $(compgen -W "peppol" -- "$cur") )
|
|
15
16
|
return
|
|
16
17
|
fi
|
|
18
|
+
|
|
19
|
+
# usage discovery|validation|transactions
|
|
20
|
+
if [[ ${words[1]} == "usage" && $cword -eq 2 ]]; then
|
|
21
|
+
COMPREPLY=( $(compgen -W "discovery validation transactions" -- "$cur") )
|
|
22
|
+
return
|
|
23
|
+
fi
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
complete -F _n42_completions n42
|
package/src/config.js
CHANGED
|
@@ -12,7 +12,7 @@ const config = {
|
|
|
12
12
|
|
|
13
13
|
ARTEFACTS_DIR: null,
|
|
14
14
|
TRANSACTIONS_DIR: null,
|
|
15
|
-
|
|
15
|
+
VALIDATIONS_DIR: null,
|
|
16
16
|
|
|
17
17
|
DATABASE_FILE: null,
|
|
18
18
|
TOKENS_FILE: null,
|
|
@@ -23,12 +23,13 @@ const config = {
|
|
|
23
23
|
|
|
24
24
|
EP_SIGNIN: "auth/signin",
|
|
25
25
|
EP_REFRESH: "auth/refresh",
|
|
26
|
+
EP_ME: "users/me",
|
|
26
27
|
EP_DISCOVER: "discover/peppol"
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
config.ARTEFACTS_DIR = path.join(config.NODE42_DIR, "artefacts", "discovery");
|
|
30
31
|
config.TRANSACTIONS_DIR = path.join(config.NODE42_DIR, "artefacts", "transactions");
|
|
31
|
-
config.
|
|
32
|
+
config.VALIDATIONS_DIR = path.join(config.NODE42_DIR, "artefacts", "validations");
|
|
32
33
|
|
|
33
34
|
config.DATABASE_FILE = path.join(config.NODE42_DIR, "db.json");
|
|
34
35
|
config.TOKENS_FILE = path.join(config.NODE42_DIR, "tokens.json");
|
package/src/db.js
CHANGED
|
@@ -13,7 +13,6 @@ function load() {
|
|
|
13
13
|
if (!fs.existsSync(DATABASE_FILE)) return {
|
|
14
14
|
user: [],
|
|
15
15
|
artefacts: [],
|
|
16
|
-
usage: [],
|
|
17
16
|
};
|
|
18
17
|
return JSON.parse(fs.readFileSync(DATABASE_FILE, "utf8"));
|
|
19
18
|
}
|
|
@@ -91,6 +90,12 @@ function remove(collection, keyValue, key = "id") {
|
|
|
91
90
|
save(db);
|
|
92
91
|
}
|
|
93
92
|
|
|
93
|
+
function clear(collection) {
|
|
94
|
+
const db = load();
|
|
95
|
+
db[collection] = [];
|
|
96
|
+
save(db);
|
|
97
|
+
}
|
|
98
|
+
|
|
94
99
|
function get(collection) {
|
|
95
100
|
const db = load();
|
|
96
101
|
return db[collection] ?? [];
|
|
@@ -154,4 +159,4 @@ function artefactsByParticipant(pid) {
|
|
|
154
159
|
return idx[pid] ?? [];
|
|
155
160
|
}
|
|
156
161
|
|
|
157
|
-
module.exports = { setSource, load, save, insert, update, upsert, replace, set, remove, get, find, indexBy, indexByFn, indexByMap, artefactsByParticipant };
|
|
162
|
+
module.exports = { setSource, load, save, insert, update, upsert, replace, set, remove, clear, get, find, indexBy, indexByFn, indexByMap, artefactsByParticipant };
|
package/src/discover.js
CHANGED
|
@@ -5,8 +5,8 @@ const db = require("./db");
|
|
|
5
5
|
|
|
6
6
|
const { fetchWithAuth } = require("./auth");
|
|
7
7
|
const { API_URL, EP_DISCOVER, DEFAULT_OUTPUT, DEFAULT_FORMAT, ARTEFACTS_DIR } = require("./config");
|
|
8
|
-
const {
|
|
9
|
-
const { clearScreen, startSpinner, buildDocLabel, promptForDocument } = require("./utils");
|
|
8
|
+
const { getUserWithIndex, setUserUsage } = require("./user");
|
|
9
|
+
const { clearScreen, startSpinner, buildDocLabel, promptForDocument, getShortId, getArtefactExt } = require("./utils");
|
|
10
10
|
const { handleError } = require("./errors");
|
|
11
11
|
|
|
12
12
|
const DEFAULT_DISCOVERY_INPUT = {
|
|
@@ -115,17 +115,25 @@ async function runDiscovery(participantId, options) {
|
|
|
115
115
|
const serviceUsage = res.headers.get("X-Node42-ServiceUsage");
|
|
116
116
|
const rateLimit = res.headers.get("X-Node42-RateLimit");
|
|
117
117
|
const encodedDocs = res.headers.get("X-Node42-Documents");
|
|
118
|
-
|
|
119
|
-
const userUsage = getUserUsage();
|
|
120
118
|
const currentMonth = new Date().toISOString().slice(0, 7);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
|
|
120
|
+
const user = getUserWithIndex(0);
|
|
121
|
+
setUserUsage(
|
|
122
|
+
user.id,
|
|
123
|
+
"discovery",
|
|
124
|
+
currentMonth,
|
|
125
|
+
serviceUsage
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const fileId = getShortId(refId);
|
|
129
|
+
const fileExt = getArtefactExt(output, format);
|
|
130
|
+
const fileName = `${fileId}.${fileExt}`;
|
|
124
131
|
|
|
125
132
|
db.insert("artefacts", {
|
|
126
133
|
id: refId,
|
|
127
134
|
participantId,
|
|
128
135
|
options,
|
|
136
|
+
file: fileName,
|
|
129
137
|
createdAt: Date.now()
|
|
130
138
|
});
|
|
131
139
|
|
|
@@ -142,7 +150,7 @@ async function runDiscovery(participantId, options) {
|
|
|
142
150
|
await runDiscovery(participantId, options);
|
|
143
151
|
});
|
|
144
152
|
|
|
145
|
-
const file = path.join(ARTEFACTS_DIR, `${
|
|
153
|
+
const file = path.join(ARTEFACTS_DIR, `${fileName}`);
|
|
146
154
|
fs.writeFileSync(file, svg);
|
|
147
155
|
|
|
148
156
|
console.log(`Discovery completed`);
|
|
@@ -159,7 +167,7 @@ async function runDiscovery(participantId, options) {
|
|
|
159
167
|
await runDiscovery(participantId, options);
|
|
160
168
|
});
|
|
161
169
|
|
|
162
|
-
const file = path.join(ARTEFACTS_DIR, `${
|
|
170
|
+
const file = path.join(ARTEFACTS_DIR, `${fileName}`);
|
|
163
171
|
fs.writeFileSync(file, text);
|
|
164
172
|
|
|
165
173
|
console.log(`Discovery completed`);
|
|
@@ -176,7 +184,7 @@ async function runDiscovery(participantId, options) {
|
|
|
176
184
|
await runDiscovery(participantId, options);
|
|
177
185
|
});
|
|
178
186
|
|
|
179
|
-
const file = path.join(ARTEFACTS_DIR, `${
|
|
187
|
+
const file = path.join(ARTEFACTS_DIR, `${fileName}`);
|
|
180
188
|
fs.writeFileSync(file, JSON.stringify(json, null, 2));
|
|
181
189
|
|
|
182
190
|
console.log(`Discovery completed`);
|
package/src/errors.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { WWW_URL } = require("./config");
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
function handleError(err) {
|
|
5
5
|
//console.log(err);
|
|
6
6
|
|
|
7
7
|
const code = err.code?.startsWith("N42E-")
|
|
@@ -16,9 +16,9 @@ async function handleError(err) {
|
|
|
16
16
|
//console.log(url);
|
|
17
17
|
|
|
18
18
|
if (message) {
|
|
19
|
-
console.error(
|
|
19
|
+
console.error(`\r${err.message}\nSee details: ${url}\n`);
|
|
20
20
|
} else {
|
|
21
|
-
console.error(
|
|
21
|
+
console.error(`\rSee details: ${url}\n`);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
package/src/user.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const db = require("./db");
|
|
2
2
|
|
|
3
|
-
function
|
|
3
|
+
function getUserWithIndex(index) {
|
|
4
4
|
const users = db.get("user");
|
|
5
|
-
return users.length ? users[
|
|
5
|
+
return users.length ? users[index] : {
|
|
6
6
|
"id": "n/a",
|
|
7
7
|
"userName": "n/a",
|
|
8
8
|
"userMail": "n/a",
|
|
@@ -10,18 +10,43 @@ function getUser() {
|
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
function
|
|
14
|
-
const
|
|
13
|
+
function getUserWithId(userId) {
|
|
14
|
+
const database = db.load();
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
const u = database.user.find(x => x.id === userId);
|
|
17
|
+
if (!u) {
|
|
18
|
+
return {
|
|
19
|
+
"id": "n/a",
|
|
20
|
+
"userName": "n/a",
|
|
21
|
+
"userMail": "n/a",
|
|
22
|
+
"role": "n/a"
|
|
23
23
|
}
|
|
24
|
-
}
|
|
24
|
+
}
|
|
25
|
+
return u;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getUserUsage(userId, service, month) {
|
|
29
|
+
const database = db.load();
|
|
30
|
+
|
|
31
|
+
const u = database.user.find(x => x.id === userId);
|
|
32
|
+
if (!u) return;
|
|
33
|
+
|
|
34
|
+
u.serviceUsage[service] ??= {};
|
|
35
|
+
const usage = u.serviceUsage[service][month];
|
|
36
|
+
return usage;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
function setUserUsage(userId, service, month, value) {
|
|
41
|
+
const database = db.load();
|
|
42
|
+
|
|
43
|
+
const u = database.user.find(x => x.id === userId);
|
|
44
|
+
if (!u) return;
|
|
45
|
+
|
|
46
|
+
u.serviceUsage[service] ??= {};
|
|
47
|
+
u.serviceUsage[service][month] = value;
|
|
48
|
+
|
|
49
|
+
db.save(database);
|
|
25
50
|
}
|
|
26
51
|
|
|
27
|
-
module.exports = {
|
|
52
|
+
module.exports = { getUserWithIndex, getUserWithId, getUserUsage, setUserUsage };
|
package/src/utils.js
CHANGED
|
@@ -2,6 +2,7 @@ const fs = require("fs");
|
|
|
2
2
|
const inquirer = require("inquirer");
|
|
3
3
|
const readline = require("readline");
|
|
4
4
|
const config = require("./config");
|
|
5
|
+
const db = require("./db");
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
function clearScreen(text) {
|
|
@@ -97,11 +98,15 @@ function validateId(type, id) {
|
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
|
|
101
|
+
function getShortId(id) {
|
|
102
|
+
return id.slice(0, 8);
|
|
103
|
+
}
|
|
104
|
+
|
|
100
105
|
function createAppDirs(force=false) {
|
|
101
106
|
fs.mkdirSync(config.NODE42_DIR, { recursive: true });
|
|
102
107
|
fs.mkdirSync(config.ARTEFACTS_DIR, { recursive: true });
|
|
103
108
|
fs.mkdirSync(config.TRANSACTIONS_DIR, { recursive: true });
|
|
104
|
-
fs.mkdirSync(config.
|
|
109
|
+
fs.mkdirSync(config.VALIDATIONS_DIR, { recursive: true });
|
|
105
110
|
|
|
106
111
|
if (!fs.existsSync(config.CONFIG_FILE) || force) {
|
|
107
112
|
fs.writeFileSync(
|
|
@@ -114,6 +119,67 @@ function createAppDirs(force=false) {
|
|
|
114
119
|
}
|
|
115
120
|
}
|
|
116
121
|
|
|
122
|
+
function cleanAppDirs(options) {
|
|
123
|
+
const {
|
|
124
|
+
tokens,
|
|
125
|
+
artefacts,
|
|
126
|
+
transactions,
|
|
127
|
+
validations,
|
|
128
|
+
db: dbFlag,
|
|
129
|
+
all
|
|
130
|
+
} = options;
|
|
131
|
+
|
|
132
|
+
if ((all || tokens) && fs.existsSync(config.TOKENS_FILE)) {
|
|
133
|
+
fs.unlinkSync(config.TOKENS_FILE);
|
|
134
|
+
console.log("Tokens removed");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if ((all || dbFlag) && fs.existsSync(config.DATABASE_FILE)) {
|
|
138
|
+
fs.unlinkSync(config.DATABASE_FILE);
|
|
139
|
+
console.log("Database removed");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (all || artefacts) {
|
|
143
|
+
try {
|
|
144
|
+
db.clear("artefacts");
|
|
145
|
+
} catch {}
|
|
146
|
+
|
|
147
|
+
if (fs.existsSync(config.ARTEFACTS_DIR)) {
|
|
148
|
+
fs.rmSync(config.ARTEFACTS_DIR, { recursive: true, force: true });
|
|
149
|
+
fs.mkdirSync(config.ARTEFACTS_DIR, { recursive: true });
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
console.log("Artefacts removed");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (all || transactions) {
|
|
156
|
+
try {
|
|
157
|
+
db.clear("transactions");
|
|
158
|
+
} catch {}
|
|
159
|
+
|
|
160
|
+
if (fs.existsSync(config.TRANSACTIONS_DIR)) {
|
|
161
|
+
fs.rmSync(config.TRANSACTIONS_DIR, { recursive: true, force: true });
|
|
162
|
+
fs.mkdirSync(config.TRANSACTIONS_DIR, { recursive: true });
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
console.log("Transactions removed");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (all || validations) {
|
|
169
|
+
try {
|
|
170
|
+
db.clear("validations");
|
|
171
|
+
} catch {}
|
|
172
|
+
|
|
173
|
+
if (fs.existsSync(config.VALIDATIONS_DIR)) {
|
|
174
|
+
fs.rmSync(config.VALIDATIONS_DIR, { recursive: true, force: true });
|
|
175
|
+
fs.mkdirSync(config.VALIDATIONS_DIR, { recursive: true });
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
console.log("Transactions removed");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
}
|
|
182
|
+
|
|
117
183
|
function buildDocLabel({ scheme, value }) {
|
|
118
184
|
// 1. Document name (after :: before ##)
|
|
119
185
|
const docMatch = value.match(/::([^#]+)##/);
|
|
@@ -163,4 +229,4 @@ function getArtefactExt(output, format) {
|
|
|
163
229
|
}
|
|
164
230
|
}
|
|
165
231
|
|
|
166
|
-
module.exports = { clearScreen, startSpinner, ask, buildDocLabel, promptForDocument, validateEnv, validateId, createAppDirs, getArtefactExt };
|
|
232
|
+
module.exports = { clearScreen, startSpinner, ask, buildDocLabel, promptForDocument, validateEnv, validateId, getShortId, createAppDirs, cleanAppDirs, getArtefactExt };
|
package/test/auth.test.js
CHANGED
|
@@ -17,6 +17,8 @@ describe("auth", () => {
|
|
|
17
17
|
beforeEach(() => {
|
|
18
18
|
sinon.restore();
|
|
19
19
|
|
|
20
|
+
global.fetch = sinon.stub();
|
|
21
|
+
|
|
20
22
|
db.setSource(TEST_DB);
|
|
21
23
|
if (fs.existsSync(TEST_DB)) fs.unlinkSync(TEST_DB);
|
|
22
24
|
|
|
@@ -34,14 +36,17 @@ describe("auth", () => {
|
|
|
34
36
|
.onSecondCall().resolves("secret");
|
|
35
37
|
|
|
36
38
|
sinon.stub(utils, "startSpinner").callsFake(() => () => {});
|
|
37
|
-
sinon.stub(user, "
|
|
39
|
+
sinon.stub(user, "getUserWithIndex")
|
|
40
|
+
.withArgs(0)
|
|
41
|
+
.returns({
|
|
42
|
+
id: "1",
|
|
38
43
|
userName: "User",
|
|
39
44
|
userMail: "user@test.com",
|
|
40
|
-
role: "user"
|
|
45
|
+
role: "user",
|
|
41
46
|
});
|
|
42
47
|
|
|
43
|
-
sinon.
|
|
44
|
-
sinon.
|
|
48
|
+
sinon.spy(fs, "mkdirSync");
|
|
49
|
+
sinon.spy(fs, "writeFileSync");
|
|
45
50
|
|
|
46
51
|
sinon.stub(console, "log");
|
|
47
52
|
sinon.stub(console, "error");
|
|
@@ -52,7 +57,7 @@ describe("auth", () => {
|
|
|
52
57
|
auth = require("../src/auth");
|
|
53
58
|
login = auth.login;
|
|
54
59
|
|
|
55
|
-
sinon.stub(auth, "checkAuth").
|
|
60
|
+
sinon.stub(auth, "checkAuth").resolves(true);
|
|
56
61
|
});
|
|
57
62
|
|
|
58
63
|
afterEach(() => {
|
|
@@ -62,7 +67,7 @@ describe("auth", () => {
|
|
|
62
67
|
|
|
63
68
|
it("logs in successfully and writes tokens", async () => {
|
|
64
69
|
// mock fetch
|
|
65
|
-
global.fetch
|
|
70
|
+
global.fetch.resolves({
|
|
66
71
|
ok: true,
|
|
67
72
|
json: async () => ({
|
|
68
73
|
accessToken: "a",
|
|
@@ -78,7 +83,7 @@ describe("auth", () => {
|
|
|
78
83
|
});
|
|
79
84
|
|
|
80
85
|
it("exits on http error", async () => {
|
|
81
|
-
global.fetch
|
|
86
|
+
global.fetch.resolves({
|
|
82
87
|
ok: false,
|
|
83
88
|
status: 401,
|
|
84
89
|
json: async () => ({})
|