@n42/cli 0.1.88 → 0.1.91

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/README.md CHANGED
@@ -11,13 +11,14 @@ routing, SMP resolution, and Access Point behavior.
11
11
 
12
12
  ## Features
13
13
 
14
- - Peppol eDelivery path discovery
15
- - SMP and Access Point resolution diagnostics
16
- - Supported document type detection
17
- - PlantUML and SVG visualizations
18
- - Authenticated API access
19
- - Deterministic, script-friendly output
20
- - No browser automation or UI side effects
14
+ - Peppol eDelivery path discovery
15
+ - SMP and Access Point resolution diagnostics
16
+ - Supported document type detection
17
+ - PlantUML and SVG visualizations
18
+ - Authenticated API access
19
+ - Deterministic, script-friendly output
20
+ - No browser automation or UI side effects
21
+ - Local artefact history inspection
21
22
 
22
23
  ## Installation
23
24
 
@@ -43,7 +44,7 @@ n42 --version
43
44
  ## Authentication
44
45
 
45
46
  Authenticate once using your Node42 account credentials.\
46
- Tokens are stored locally under `~/.node42/`.
47
+ Tokens are stored locally under `~/.node42/tokens.json`.
47
48
 
48
49
  ``` bash
49
50
  n42 login
@@ -65,6 +66,35 @@ n42 me
65
66
  n42 discover peppol <participantId>
66
67
  ```
67
68
 
69
+ #### Available options:
70
+ - **-e**, **--env** `<environment>` Environment (TEST | PROD)
71
+ - **-o**, **--output** `<type>` Result type (json | plantuml)
72
+ - **-f**, **--format** `<format>` When output=plantuml (svg | text)
73
+ - **--force-https** Force HTTPS endpoints
74
+ - **--insecure** Disable TLS certificate validation
75
+ - **--fetch-business-card** Fetch Peppol business card
76
+ - **--reverse-lookup** Enable reverse lookup
77
+ - **--probe-endpoints** Probe resolved endpoints
78
+
79
+ ### History
80
+
81
+ ``` bash
82
+ n42 history <participantId>
83
+ ```
84
+
85
+ Example output:
86
+
87
+ ```bash
88
+ DATE PID FILE
89
+ 2026-01-30 15:42:18 9915:helger ~/.node42/artefacts/discovery/b91f83e2.svg
90
+ 2026-01-30 15:42:10 9915:helger ~/.node42/artefacts/discovery/ba1cbc8d.svg
91
+ ```
92
+
93
+ #### Available options:
94
+ - **--today** Show only today's artefacts
95
+ - **--day** `<yyyy-mm-dd>` Show artefacts for a specific day
96
+ - **--last** `<n>` Show only last N results
97
+
68
98
  ------------------------------------------------------------------------
69
99
 
70
100
  ## Artefacts
package/docs/DB_USAGE.md CHANGED
@@ -33,7 +33,6 @@ Example `db.json`:
33
33
  {
34
34
  "user": {},
35
35
  "artefacts": [],
36
- "usage": {},
37
36
  }
38
37
  ```
39
38
 
package/jest.config.js ADDED
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ testEnvironment: "node",
3
+ verbose: true,
4
+ coverageDirectory: "coverage",
5
+ testMatch: ["**/test/**/*.test.js"]
6
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@n42/cli",
3
- "version": "0.1.88",
3
+ "version": "0.1.91",
4
4
  "description": "Node42 CLI – Command-line interface for Peppol eDelivery path discovery, diagnostics, and tooling",
5
5
  "keywords": [
6
6
  "node42"
package/src/auth.js CHANGED
@@ -3,7 +3,9 @@ const { NODE42_DIR, TOKENS_FILE, API_URL, EP_SIGNIN, EP_REFRESH, EP_ME } = requi
3
3
  const { handleError } = require("./errors");
4
4
  const { getUserWithIndex } = require("./user");
5
5
  const { clearScreen, ask, startSpinner } = require("./utils");
6
+
6
7
  const db = require("./db");
8
+ const C = require("./colors");
7
9
 
8
10
 
9
11
  async function login() {
@@ -25,7 +27,7 @@ async function login() {
25
27
  if (!res.ok) {
26
28
  stopSpinner();
27
29
 
28
- console.error(`Login failed (${res.status}) Invalid credentials`);
30
+ console.error(`[${res.status}] ${C.RED}Login failed${C.RESET} - Invalid credentials`);
29
31
  process.exit(1);
30
32
  }
31
33
 
@@ -34,7 +36,7 @@ async function login() {
34
36
 
35
37
  const { accessToken, refreshToken, idToken } = tokens;
36
38
  if (!accessToken || !refreshToken || !idToken) {
37
- console.error("Invalid auth response");
39
+ console.error(`${C.RED}Invalid auth response`);
38
40
  process.exit(1);
39
41
  }
40
42
 
@@ -50,14 +52,12 @@ async function login() {
50
52
  stopSpinner();
51
53
 
52
54
  if (!authenticated) {
53
- console.error("Not authenticated");
55
+ console.error(`${C.RED}Not authenticated${C.RESET}`);
54
56
  process.exit(1);
55
57
  }
56
58
 
57
59
  user = getUserWithIndex(0);
58
- console.log(
59
- `Authenticated as ${user.userName} <${user.userMail}> (${user.role})`
60
- );
60
+ console.log(`Authenticated as ${user.userName} <${C.BLUE}${user.userMail}${C.RESET}> ${C.DIM}(${user.role})${C.RESET}\n`);
61
61
  }
62
62
 
63
63
  function logout() {
@@ -69,7 +69,8 @@ function logout() {
69
69
 
70
70
  function loadTokens() {
71
71
  if (!fs.existsSync(TOKENS_FILE)) {
72
- console.error("Tokens missing...\nRun: n42 login");
72
+ console.error(`Tokens missing...`);
73
+ console.log(`Run: ${C.BLUE}n42 login${C.RESET}\n`);
73
74
  process.exit(1);
74
75
  }
75
76
  return JSON.parse(fs.readFileSync(TOKENS_FILE, "utf8"));
package/src/cli.js CHANGED
@@ -12,6 +12,7 @@ createAppDirs();
12
12
  const program = new Command();
13
13
  const pkg = require("../package.json");
14
14
  const db = require("./db");
15
+ const C = require("./colors");
15
16
 
16
17
  const fs = require("fs");
17
18
  const path = require("path");
@@ -27,7 +28,7 @@ program
27
28
  .action((shell) => {
28
29
 
29
30
  if (shell !== "bash") {
30
- console.error("Only bash supported");
31
+ console.error(`${C.RED}Only bash supported${C.RESET}`);
31
32
  return;
32
33
  }
33
34
 
@@ -35,9 +36,9 @@ program
35
36
  const dest = path.join(NODE42_DIR, "completion.bash");
36
37
  fs.copyFileSync(src, dest);
37
38
 
38
- console.log(`Completion script saved to ${dest}`);
39
+ console.log(`${C.DIM}Completion script saved to ${dest}${C.RESET}\n`);
39
40
  console.log(`Run this once:`);
40
- console.log(`source ${dest}`);
41
+ console.log(`${C.BLUE}source ${dest}${C.RESET}\n`);
41
42
  });
42
43
 
43
44
  program
@@ -80,21 +81,21 @@ program
80
81
  const user = getUserWithIndex(0);
81
82
  const currentMonth = new Date().toISOString().slice(0, 7);
82
83
  console.log(`Node42 CLI v${pkg.version}
83
- User
84
- ID : ${user.id}
84
+ ${C.BOLD}User${C.RESET}
85
+ ID : ${C.CYAN}${user.id}${C.RESET}
85
86
  Name : ${user.userName}
86
87
  Email : ${user.userMail}
87
88
  Role : ${user.role}
88
89
 
89
- Rate Limits
90
- Discovery : ${user.rateLimits.discovery}
91
- Transactions : ${user.rateLimits.transactions}
92
- Validation : ${user.rateLimits.validation}
90
+ ${C.BOLD}Rate Limits${C.RESET}
91
+ Discovery : ${C.RED}${user.rateLimits.discovery}${C.RESET}
92
+ Transactions : ${C.RED}${user.rateLimits.transactions}${C.RESET}
93
+ Validation : ${C.RED}${user.rateLimits.validation}${C.RESET}
93
94
 
94
- Usage (Current Month)
95
- Discovery : ${user.serviceUsage.discovery[currentMonth] ?? 0}
96
- Transactions : ${user.serviceUsage.transactions[currentMonth] ?? 0}
97
- Validation : ${user.serviceUsage.validation[currentMonth] ?? 0}
95
+ ${C.BOLD}Usage${C.RESET} ${C.DIM}(Current Month)${C.RESET}
96
+ Discovery : ${C.RED}${user.serviceUsage.discovery[currentMonth] ?? 0}${C.RESET}
97
+ Transactions : ${C.RED}${user.serviceUsage.transactions[currentMonth] ?? 0}${C.RESET}
98
+ Validation : ${C.RED}${user.serviceUsage.validation[currentMonth] ?? 0}${C.RESET}
98
99
  `);
99
100
  });
100
101
 
@@ -110,8 +111,9 @@ program
110
111
  usage = 0;
111
112
  }
112
113
 
113
- clearScreen(`Node42 CLI v${pkg.version}`);
114
- console.log(`Usage for ${service} (${currentMonth}): ${usage}`);
114
+ clearScreen(`Node42 CLI v${pkg.version}\n`);
115
+ console.log(`Usage ${C.BOLD}${service}${C.RESET}`);
116
+ console.log(`${C.DIM}${currentMonth}:${C.RESET} ${C.RED}${usage}${C.RESET}\n`);
115
117
  });
116
118
 
117
119
  program
@@ -156,30 +158,34 @@ program
156
158
 
157
159
  if (!artefacts.length) {
158
160
  clearScreen(`Node42 CLI v${pkg.version}`);
159
- console.log(`No artefacts found. (${dayFilter})`);
161
+ const filter = dayFilter !== null ? ` (${dayFilter})` : ``;
162
+ console.log(`No artefacts found.${filter}`);
160
163
  return;
161
164
  }
162
165
 
163
166
  // ---- OUTPUT ----
164
167
  clearScreen(`Node42 CLI v${pkg.version}`);
165
- console.log(`Found ${artefacts.length} artefact(s)${filterInfo}\n`);
168
+ console.log(`Found ${C.RED}${artefacts.length}${C.RESET} artefact(s)${filterInfo}\n`);
166
169
 
167
170
  const DATE = "DATE".padEnd(19);
168
171
  const PID = "PID".padEnd(15);
169
172
  const FILE = "FILE";
170
- console.log(`${DATE} ${PID} ${FILE}`);
173
+ console.log(`${DATE} ${C.CYAN}${PID}${C.RESET} ${FILE}`);
171
174
 
172
175
  for (const item of artefacts) {
173
176
  const d = new Date(item.createdAt);
174
- const dt = d.toISOString().slice(0, 19).replace("T", " ");
177
+ const iso = d.toISOString(); // 2026-01-30T16:53:28.123Z
178
+ const date = iso.slice(0, 10); // 2026-01-30
179
+ const time = iso.slice(11, 19); // 16:53:28
175
180
  const file = path.join(ARTEFACTS_DIR, `${item.file}`);
181
+ const link = `\u001B]8;;file://${file}\u0007Open\u001B]8;;\u0007`
176
182
 
177
183
  let pid = item.participantId;
178
184
  if (!participantId) {
179
185
  pid = pid.length > 15 ? pid.substring(0, 12) + "..." : pid
180
- console.log(`${dt} ${pid.padEnd(15)} ${file}`);
186
+ console.log(`${date} ${C.DIM}${time}${C.RESET} ${C.CYAN}${pid.padEnd(15)}${C.RESET} ${item.file} ${C.BLUE}[${link}]${C.RESET}`);
181
187
  } else {
182
- console.log(`${dt} ${file}`);
188
+ console.log(`${date} ${C.DIM}${time}${C.RESET} ${item.file} ${C.BLUE}[${link}]${C.RESET}`);
183
189
  }
184
190
  }
185
191
 
package/src/colors.js ADDED
@@ -0,0 +1,42 @@
1
+ const RESET = "\x1b[0m";
2
+
3
+ const BLACK = "\x1b[30m";
4
+ const RED = "\x1b[31m";
5
+ const GREEN = "\x1b[32m";
6
+ const YELLOW = "\x1b[33m";
7
+ const BLUE = "\x1b[34m";
8
+ const MAGENTA = "\x1b[35m";
9
+ const CYAN = "\x1b[36m";
10
+ const WHITE = "\x1b[37m";
11
+
12
+ const BOLD = "\x1b[1m";
13
+ const DIM = "\x1b[2m";
14
+ const UNDERLINE = "\x1b[4m";
15
+
16
+ const RED_BOLD = "\x1b[1;31m";
17
+ const GREEN_BOLD = "\x1b[1;32m";
18
+ const YELLOW_BOLD = "\x1b[1;33m";
19
+ const BLUE_BOLD = "\x1b[1;34m";
20
+ const MAGENTA_BOLD = "\x1b[1;35m";
21
+ const CYAN_BOLD = "\x1b[1;36m";
22
+
23
+ module.exports = {
24
+ RESET,
25
+ BLACK,
26
+ RED,
27
+ GREEN,
28
+ YELLOW,
29
+ BLUE,
30
+ MAGENTA,
31
+ CYAN,
32
+ WHITE,
33
+ BOLD,
34
+ DIM,
35
+ UNDERLINE,
36
+ RED_BOLD,
37
+ GREEN_BOLD,
38
+ YELLOW_BOLD,
39
+ BLUE_BOLD,
40
+ MAGENTA_BOLD,
41
+ CYAN_BOLD
42
+ };
package/src/utils.js CHANGED
@@ -3,6 +3,7 @@ const inquirer = require("inquirer");
3
3
  const readline = require("readline");
4
4
  const config = require("./config");
5
5
  const db = require("./db");
6
+ const C = require("./colors");
6
7
 
7
8
 
8
9
  function clearScreen(text) {
@@ -20,7 +21,7 @@ function ask(question, def, hidden=false) {
20
21
  terminal: true
21
22
  });
22
23
 
23
- const q = def ? `${question} (${def}): ` : `${question}: `;
24
+ const q = def ? `${question} ${C.DIM}(${def})${C.RESET}: ` : `${question}: `;
24
25
 
25
26
  process.stdin.on("data", char => {
26
27
  char = char + "";