@n42/cli 0.3.16 → 0.3.46

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@n42/cli",
3
- "version": "0.3.16",
3
+ "version": "0.3.46",
4
4
  "description": "Node42 CLI – Command-line interface for Peppol eDelivery path discovery, diagnostics, and tooling",
5
5
  "keywords": [
6
6
  "node42",
@@ -4,7 +4,7 @@
4
4
  <meta charset="utf-8" />
5
5
  <title>Node42</title>
6
6
  <link rel="stylesheet" href="../../assets/wrapper-light.css">
7
- <link rel="stylesheet" href="../../assets/terminal-light.css">
7
+ <link id="terminal-style" rel="stylesheet" href="../../assets/terminal-light.css">
8
8
  </head>
9
9
  <body>
10
10
  <div id="app-header">
@@ -1,3 +1,6 @@
1
+ const apiUrl = "https://api.node42.dev";
2
+ const wwwUrl = "https://www.node42.dev";
3
+
1
4
  let terminal;
2
5
  let discoveryTrace;
3
6
 
@@ -66,8 +69,68 @@ function addSvgClickListener() {
66
69
  });
67
70
  }
68
71
  else {
69
- const naptr = link.getAttribute("data-naptr");
70
- console.log("naptr: " + naptr);
72
+ let itemUrl = null;
73
+
74
+ const item = url.replace("#", "");
75
+ switch (item) {
76
+ case "DISCOVERY": {
77
+ const discoveryId = link.getAttribute("data-discovery");
78
+ console.log("discoveryId: " + discoveryId);
79
+
80
+ terminal.show({
81
+ command: "trace",
82
+ run: true
83
+ });
84
+ break;
85
+ }
86
+
87
+ case "N42": {
88
+ itemUrl = link.getAttribute("data-n42-url");
89
+ break;
90
+ }
91
+
92
+ case "NAPTR": {
93
+ const naptrUrl = link.getAttribute("data-naptr-url");
94
+ console.log("naptr: " + naptrUrl);
95
+ break;
96
+ }
97
+
98
+ case "SMP": {
99
+ itemUrl = link.getAttribute("data-smp-url");
100
+ break;
101
+ }
102
+
103
+ case "SMP-SG": {
104
+ //itemUrl = link.getAttribute("data-smp-sg-url");
105
+ const trace = discoveryTrace.find(t => t.step === "smp.serviceGroup.url");
106
+ itemUrl = trace.data.url;
107
+ break;
108
+ }
109
+
110
+ case "SMP-SM": {
111
+ //itemUrl = link.getAttribute("data-smp-sm-url");
112
+ const trace = discoveryTrace.find(t => t.step === "smp.serviceMetadata.url");
113
+ itemUrl = trace.data.url;
114
+ break;
115
+ }
116
+
117
+ case "AP": {
118
+ itemUrl = link.getAttribute("data-ap-url");
119
+ break;
120
+ }
121
+
122
+ case "EP-TLS": {
123
+ itemUrl = link.getAttribute("data-ep-tls-url");
124
+ break;
125
+ }
126
+ }
127
+
128
+ if (itemUrl && itemUrl.length) {
129
+ terminal.open({
130
+ url: itemUrl,
131
+ method: "GET"
132
+ });
133
+ }
71
134
  }
72
135
  }
73
136
  }
@@ -106,8 +169,8 @@ document.addEventListener("DOMContentLoaded", () => {
106
169
  terminal = new Terminal({
107
170
  title: "Terminal",
108
171
  brand: "curl",
109
- textColor: "#d6dde6",
110
- terminalTextColor: "#33FF33",
172
+ theme: "light",
173
+ pkgVersion: "0.3.19"
111
174
  });
112
175
 
113
176
  addSvgClickListener();
@@ -93,7 +93,7 @@
93
93
  .cm-term {
94
94
  white-space: pre-wrap;
95
95
  word-break: break-word;
96
- color: #33FF33;
96
+ color: #d6dde6;;
97
97
  line-height: 1.35;
98
98
  font-size: 12px;
99
99
  }
@@ -131,9 +131,16 @@
131
131
  .cm-input {
132
132
  flex: 1;
133
133
  background: transparent;
134
- color: #33FF33;
134
+ color: #d6dde6;
135
135
  border: none;
136
136
  outline: none;
137
137
  font-family: inherit;
138
138
  font-size: 12px;
139
- }
139
+ }
140
+
141
+ .cm-json-key { color: #3f9cff; }
142
+ .cm-json-string { color: #a07c4f }
143
+ .cm-json-number { color: #f59e0b; }
144
+ .cm-json-boolean { color: #ec4899; }
145
+ .cm-json-null { color: #94a3b8; }
146
+ .cm-json-step { color: #4cb56f; }
@@ -143,4 +143,11 @@
143
143
  outline: none;
144
144
  font-family: inherit;
145
145
  font-size: 12px;
146
- }
146
+ }
147
+
148
+ .cm-json-key { color: #3f9cff; }
149
+ .cm-json-string { color: #a07c4f }
150
+ .cm-json-number { color: #f59e0b; }
151
+ .cm-json-boolean { color: #ec4899; }
152
+ .cm-json-null { color: #94a3b8; }
153
+ .cm-json-step { color: #4cb56f; }
@@ -12,6 +12,23 @@ class Terminal {
12
12
 
13
13
  this._history = [];
14
14
  this._historyIndex = -1;
15
+
16
+ // ---- reusable events ----
17
+ this.enterEvent = new KeyboardEvent("keydown", {
18
+ key: "Enter",
19
+ code: "Enter",
20
+ keyCode: 13,
21
+ which: 13,
22
+ bubbles: true
23
+ });
24
+
25
+ this.escEvent = new KeyboardEvent("keydown", {
26
+ key: "Escape",
27
+ code: "Escape",
28
+ keyCode: 27,
29
+ which: 27,
30
+ bubbles: true
31
+ });
15
32
  }
16
33
 
17
34
  async openAndRun(req) {
@@ -44,6 +61,34 @@ class Terminal {
44
61
  document.documentElement.style.overflow = "hidden";
45
62
  }
46
63
 
64
+ show(input) {
65
+ if (!this.overlay) {
66
+ this._ensureDom();
67
+ this._printHelp();
68
+ }
69
+
70
+ if (this._active) return;
71
+ this._active = true;
72
+
73
+ this._lastFocused = document.activeElement;
74
+
75
+ this.overlay.classList.remove("hidden");
76
+ this.dialog.classList.remove("hidden");
77
+
78
+ this.title.textContent = `Terminal [CMD]: ${input.command}`;
79
+
80
+ this.input.value = `${input.command}`;
81
+ this.input.focus();
82
+
83
+ if (input.run) {
84
+ this.input.dispatchEvent(this.enterEvent);
85
+ }
86
+
87
+ // prevent background scroll
88
+ this._prevOverflow = document.documentElement.style.overflow;
89
+ document.documentElement.style.overflow = "hidden";
90
+ }
91
+
47
92
  close() {
48
93
  if (!this._active) return;
49
94
  this._active = false;
@@ -102,7 +147,7 @@ class Terminal {
102
147
  method: normalized.method,
103
148
  headers: {
104
149
  ...normalized.headers,
105
- "X-N42-CLI-Source": "v1.0.0"
150
+ "X-N42-Client-Version": `v${this.opts.pkgVersion}`,
106
151
  },
107
152
  body: normalized.body,
108
153
  signal,
@@ -119,6 +164,8 @@ class Terminal {
119
164
  if (normalized.body) this._printLine(`> (body ${this._byteLen(normalized.body)} bytes)`);
120
165
  this._printLine("");
121
166
 
167
+ this.title.textContent = `Terminal [${normalized.method}]: curl`;
168
+
122
169
  const res = await fetch(normalized.url, fetchInit);
123
170
 
124
171
  const dt = (performance.now() - t0);
@@ -193,6 +240,40 @@ class Terminal {
193
240
  this._historyIndex = this._history.length;
194
241
  }
195
242
 
243
+ _jsonHighlight(json) {
244
+ if (typeof json !== "string") {
245
+ json = JSON.stringify(json, null, 2);
246
+ }
247
+
248
+ const esc = json
249
+ .replace(/&/g, "&amp;")
250
+ .replace(/</g, "&lt;")
251
+ .replace(/>/g, "&gt;");
252
+
253
+ return esc.replace(
254
+ /"(step)"(\s*:\s*)"([^"]+)"|("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d+)?)/g,
255
+ (match, stepKey, colon, stepValue) => {
256
+
257
+ // Special case: only color the VALUE of step
258
+ if (stepKey) {
259
+ return `<span class="cm-json-key">"${stepKey}"</span>${colon}<span class="cm-json-step">"${stepValue}"</span>`;
260
+ }
261
+
262
+ let cls = "number";
263
+
264
+ if (/^"/.test(match)) {
265
+ cls = /:$/.test(match) ? "key" : "string";
266
+ } else if (/true|false/.test(match)) {
267
+ cls = "boolean";
268
+ } else if (/null/.test(match)) {
269
+ cls = "null";
270
+ }
271
+
272
+ return `<span class="cm-json-${cls}">${match}</span>`;
273
+ }
274
+ );
275
+ }
276
+
196
277
  _handleCommand(cmd) {
197
278
  this._printLine(`$ ${cmd}`);
198
279
 
@@ -226,7 +307,7 @@ class Terminal {
226
307
 
227
308
  if (discoveryTrace) {
228
309
  this._resetTerminal();
229
- this._printLine(JSON.stringify(discoveryTrace, null, 2));
310
+ this._printHtml(this._jsonHighlight(discoveryTrace));
230
311
  } else {
231
312
  this._printLine("[error]: Discovery trace missing");
232
313
  }
@@ -245,140 +326,33 @@ class Terminal {
245
326
  return img;
246
327
  }
247
328
 
329
+ _toggleTheme() {
330
+ const themeLink = document.getElementById("terminal-style");
331
+
332
+ // Check current theme file
333
+ const isLight = themeLink.getAttribute("href").includes("terminal-light.css");
334
+
335
+ if (isLight) {
336
+ themeLink.setAttribute("href", "../../assets/terminal-dark.css");
337
+
338
+ // Invert all icons for dark background
339
+ //icons.forEach(icon => { icon.style.filter = "invert(100%) hue-rotate(180deg)"; });
340
+ }
341
+ else {
342
+ themeLink.setAttribute("href", "../../assets/terminal-light.css");
343
+
344
+ // Reset icon colors to normal
345
+ //icons.forEach(icon => { icon.style.filter = "none"; });
346
+ }
347
+ }
348
+
248
349
  _ensureDom() {
249
350
  if (this.overlay) return;
250
351
 
251
- const textColor = this.opts.textColor;
252
- const terminalTextColor = this.opts.terminalTextColor;
253
-
254
- // Styles (namespaced)
255
- const style = document.createElement("style");
256
- style.id = "terminal-style";
257
- style.textContent = `
258
- .cm-overlay {
259
- position: fixed; inset: 0;
260
- background: rgba(0,0,0,.55);
261
- display: flex;
262
- align-items: center;
263
- justify-content: center;
264
- padding: 24px;
265
- z-index: 2147483647;
266
- }
267
- .cm-overlay.hidden {
268
- display: none;
269
- }
270
- .cm-dialog {
271
- width: min(980px, 100%);
272
- height: min(720px, 100%);
273
- background: #0b0f14;
274
- color: ${textColor};
275
- border: 1px solid rgba(255,255,255,.12);
276
- border-radius: 12px;
277
- box-shadow: 0 18px 60px rgba(0,0,0,.55);
278
- display: flex;
279
- flex-direction: column;
280
- overflow: hidden;
281
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
282
- }
283
- .cm-display.hidden {
284
- display: none;
285
- }
286
- .cm-head {
287
- display: flex; align-items: center; gap: 12px;
288
- padding: 10px 11px 10px 14px;
289
- border-bottom: 1px solid rgba(255,255,255,.10);
290
- background: rgba(255,255,255,.03);
291
- }
292
- .cm-title {
293
- font-weight: 600;
294
- font-size: 14px;
295
- opacity: .95;
296
- }
297
- .cm-spacer { flex: 1; }
298
- .cm-btn {
299
- appearance: none;
300
- border: 1px solid rgba(255,255,255,.18);
301
- background: transparent;
302
- color: inherit;
303
- padding: 2px 6px 0 6px;
304
- border-radius: 6px;
305
- font-size: 12px;
306
- cursor: pointer;
307
- }
308
- .cm-btn img {
309
- width: 17px;
310
- }
311
- .cm-btn:hover {
312
- border: 1px solid rgba(255,255,255,.38);
313
- }
314
- .cm-btn:disabled { opacity: .55; cursor: not-allowed; }
315
- .cm-body {
316
- flex: 1;
317
- overflow: auto;
318
- padding: 12px;
319
-
320
- scrollbar-color: #323232 #0b0f14;
321
- scrollbar-width: thin;
322
- }
323
- .cm-body::-webkit-scrollbar {
324
- width: 10px;
325
- }
326
- .cm-body::-webkit-scrollbar-track {
327
- background: #0b0f14;
328
- }
329
- .cm-body::-webkit-scrollbar-thumb {
330
- background: #323232;
331
- border-radius: 6px;
332
- }
333
- .cm-body::-webkit-scrollbar-thumb:hover {
334
- background: #656565;
335
- }
336
- .cm-term {
337
- white-space: pre-wrap;
338
- word-break: break-word;
339
- color: ${terminalTextColor};
340
- line-height: 1.35;
341
- font-size: 12px;
342
- }
343
- .cm-foot {
344
- padding: 10px 12px;
345
- border-top: 1px solid rgba(255,255,255,.10);
346
- display: flex; align-items: center; gap: 10px;
347
- background: rgba(255,255,255,.02);
348
- }
349
- .cm-status { font-size: 12px; opacity: .85; }
350
- .cm-kbd {
351
- font-size: 11px; opacity: .7;
352
- border: 1px solid rgba(255,255,255,.16);
353
- padding: 3px 6px 2px 6px;
354
- border-radius: 6px;
355
- }
356
- .cm-input-row {
357
- display: flex;
358
- align-items: center;
359
- gap: 8px;
360
- padding: 8px 12px;
361
- border-top: 1px solid rgba(255,255,255,.10);
362
- background: rgba(255,255,255,.02);
363
- }
364
- .cm-prompt {
365
- opacity: .8;
366
- font-size: 12px;
367
- }
368
- .cm-input {
369
- flex: 1;
370
- background: transparent;
371
- color: ${terminalTextColor};
372
- border: none;
373
- outline: none;
374
- font-family: inherit;
375
- font-size: 12px;
376
- }
377
- `;
352
+ const theme = this.opts.theme;
353
+ const themeLink = document.getElementById("terminal-style");
378
354
 
379
- if (!document.getElementById("terminal-style")) {
380
- //document.head.appendChild(style);
381
- }
355
+ themeLink.setAttribute("href", `../../assets/terminal-${theme}.css`);
382
356
 
383
357
  // Overlay
384
358
  const overlay = document.createElement("div");
@@ -450,6 +424,7 @@ class Terminal {
450
424
  head.className = "cm-head";
451
425
 
452
426
  const title = document.createElement("div");
427
+ title.id = "terminal-title";
453
428
  title.className = "cm-title";
454
429
  title.textContent = this.opts.title;
455
430
 
@@ -461,7 +436,6 @@ class Terminal {
461
436
  btnCopy.className = "cm-btn copy";
462
437
  btnCopy.type = "button";
463
438
  btnCopy.title = "Copy";
464
- //btnCopy.textContent = "Copy";
465
439
  btnCopy.prepend(copyImg);
466
440
  btnCopy.addEventListener("click", () => this._copy());
467
441
 
@@ -470,7 +444,6 @@ class Terminal {
470
444
  btnDownload.className = "cm-btn";
471
445
  btnDownload.type = "button";
472
446
  btnDownload.title = "Download";
473
- //btnDownload.textContent = "Download";
474
447
  btnDownload.prepend(downloadImg);
475
448
  btnDownload.addEventListener("click", () => this._download());
476
449
 
@@ -479,19 +452,18 @@ class Terminal {
479
452
  btnOpenExt.className = "cm-btn";
480
453
  btnOpenExt.type = "button";
481
454
  btnOpenExt.title = "Open";
482
- //btnOpenExt.textContent = "Open";
483
455
  btnOpenExt.prepend(openExtImg);
484
456
  btnOpenExt.addEventListener("click", () => this._openExt());
485
457
 
486
- /*
487
- const btnClose = document.createElement("button");
488
- btnClose.className = "cm-btn";
489
- btnClose.type = "button";
490
- btnClose.textContent = "Close";
491
- btnClose.addEventListener("click", () => this.close());
492
- */
458
+ const themeImg = this._createImgEl("../../assets/theme-light.svg", 24, "Theme");
459
+ const btnTheme = document.createElement("button");
460
+ btnTheme.className = "cm-btn";
461
+ btnTheme.type = "button";
462
+ btnTheme.title = "Theme";
463
+ btnTheme.prepend(themeImg);
464
+ btnTheme.addEventListener("click", () => this._toggleTheme());
493
465
 
494
- head.append(title, spacer, btnCopy, btnDownload, btnOpenExt);
466
+ head.append(title, spacer, btnTheme, btnCopy, btnDownload, btnOpenExt);
495
467
 
496
468
  // Body
497
469
  const body = document.createElement("div");
@@ -534,6 +506,7 @@ class Terminal {
534
506
  // Store refs
535
507
  this.overlay = overlay;
536
508
  this.dialog = dialog;
509
+ this.title = title;
537
510
  this.input = input;
538
511
  this.term = term;
539
512
  this.statusEl = status;
@@ -541,7 +514,7 @@ class Terminal {
541
514
  this.btnCopy = btnCopy;
542
515
  this.btnDownload = btnDownload;
543
516
  this.btnOpenExt = btnOpenExt;
544
- //this.btnClose = btnClose;
517
+ this.btnTheme = btnTheme;
545
518
 
546
519
  // Close when clicking outside (optional)
547
520
  overlay.addEventListener("click", (e) => {
@@ -638,6 +611,11 @@ class Terminal {
638
611
  this._scrollToBottom();
639
612
  }
640
613
 
614
+ _printHtml(s) {
615
+ this.term.innerHTML = s;
616
+ this._scrollToBottom();
617
+ }
618
+
641
619
  _printRaw(s) {
642
620
  this.term.textContent += s;
643
621
  if (!s.endsWith("\n")) this.term.textContent += "\n";
@@ -0,0 +1,46 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <svg
3
+ width="800px"
4
+ height="800px"
5
+ viewBox="0 0 24 24"
6
+ version="1.1"
7
+ id="svg9"
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ xmlns:svg="http://www.w3.org/2000/svg"
10
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
11
+ xmlns:cc="http://creativecommons.org/ns#"
12
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
13
+ <defs
14
+ id="defs13" />
15
+ <!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
16
+ <title
17
+ id="title2">ic_fluent_dark_theme_24_regular</title>
18
+ <desc
19
+ id="desc4">Created with Sketch.</desc>
20
+ <g
21
+ id="🔍-Product-Icons"
22
+ stroke="none"
23
+ stroke-width="1"
24
+ fill="none"
25
+ fill-rule="evenodd">
26
+ <g
27
+ id="ic_fluent_dark_theme_24_regular"
28
+ fill="#212121"
29
+ fill-rule="nonzero"
30
+ style="fill:#6b7280;fill-opacity:1">
31
+ <path
32
+ d="M12,22 C17.5228475,22 22,17.5228475 22,12 C22,6.4771525 17.5228475,2 12,2 C6.4771525,2 2,6.4771525 2,12 C2,17.5228475 6.4771525,22 12,22 Z M12,20.5 L12,3.5 C16.6944204,3.5 20.5,7.30557963 20.5,12 C20.5,16.6944204 16.6944204,20.5 12,20.5 Z"
33
+ id="🎨-Color"
34
+ style="fill:#6b7280;fill-opacity:1" />
35
+ </g>
36
+ </g>
37
+ <metadata
38
+ id="metadata890">
39
+ <rdf:RDF>
40
+ <cc:Work
41
+ rdf:about="">
42
+ <dc:title>ic_fluent_dark_theme_24_regular</dc:title>
43
+ </cc:Work>
44
+ </rdf:RDF>
45
+ </metadata>
46
+ </svg>