zibri-cli 1.6.0 → 1.6.2

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.
@@ -42,9 +42,9 @@ class NewCommand extends base_command_model_1.BaseCommand {
42
42
  '',
43
43
  'async function start(): Promise<void> {',
44
44
  '',
45
- 'if (!isVersion(version)) {',
46
- ' throw new Error(\'The version of the package.json is not valid.\');',
47
- '}',
45
+ ' if (!isVersion(version)) {',
46
+ ' throw new Error(\'The version of the package.json is not valid.\');',
47
+ ' }',
48
48
  '',
49
49
  ' const app = new ZibriApplication({',
50
50
  ` name: '${configuration.name}',`,
@@ -56,17 +56,17 @@ class NewCommand extends base_command_model_1.BaseCommand {
56
56
  ' { token: UserRepository, useClass: UserRepository},',
57
57
  ' {',
58
58
  ' token: ZIBRI_DI_TOKENS.JWT_ACCESS_TOKEN_SECRET,',
59
- ' useFactory: () => \'test\'',
59
+ ' useFactory: () => \'JWT_ACCESS_TOKEN_SECRET\'',
60
60
  ' },',
61
61
  ' {',
62
62
  ' token: ZIBRI_DI_TOKENS.JWT_REFRESH_TOKEN_SECRET,',
63
- ' useFactory: () => \'test\'',
63
+ ' useFactory: () => \'JWT_REFRESH_TOKEN_SECRET\'',
64
64
  ' },',
65
65
  ' {',
66
66
  ' token: ZIBRI_DI_TOKENS.EMAIL_CONFIG,',
67
67
  ' useFactory: (): EmailConfigInput => {',
68
68
  ' return {',
69
- ' maxEmailsPerHour: 0,',
69
+ ' maxEmailsPerHour: 3600,',
70
70
  ' defaultSender: \'\',',
71
71
  ' host: \'\',',
72
72
  ' port: 0,',
@@ -1 +1 @@
1
- {"version":3,"file":"new.command.js","sourceRoot":"","sources":["../../../src/commands/new/new.command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"new.command.js","sourceRoot":"","sources":["../../../src/commands/new/new.command.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,16 +1,22 @@
1
1
  {
2
2
  "name": "zibri-cli",
3
- "version": "1.6.0",
3
+ "version": "1.6.2",
4
4
  "license": "MIT",
5
5
  "main": "index.js",
6
- "files": ["./dist", "./README.md", "./LICENSE", "./assets"],
6
+ "files": [
7
+ "./dist",
8
+ "./README.md",
9
+ "./LICENSE",
10
+ "./assets",
11
+ "./templates"
12
+ ],
7
13
  "engines": {
8
14
  "node": ">=20"
9
15
  },
10
16
  "keywords": [
11
17
  "zibri",
12
18
  "cli"
13
- ],
19
+ ],
14
20
  "author": "Tim Fabian",
15
21
  "description": "",
16
22
  "bin": {
@@ -33,6 +39,7 @@
33
39
  "typescript": "^5.8.3"
34
40
  },
35
41
  "dependencies": {
42
+ "chalk": "^5.4.1",
36
43
  "death": "^1.1.0",
37
44
  "figlet": "^1.8.1",
38
45
  "inquirer": "^10.2.2"
@@ -0,0 +1,93 @@
1
+ <!DOCTYPE html>
2
+
3
+ <html xmlns="http://www.w3.org/1999/xhtml" lang="en" style="height: 100%;">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
7
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
9
+ <title>{{base.title}}</title>
10
+ <style>
11
+ .button:hover {
12
+ color: white !important;
13
+ background-color: #0e456f !important;
14
+ }
15
+ @media only screen and (max-width:600px) {
16
+ .root-container { max-width: 95% !important; }
17
+ }
18
+ </style>
19
+ <!--[if mso]>
20
+ <xml>
21
+ <o:OfficeDocumentSettings>
22
+ <o:AllowPNG/>
23
+ <o:PixelsPerInch>96</o:PixelsPerInch>
24
+ </o:OfficeDocumentSettings>
25
+ </xml>
26
+ <style>
27
+ .fallback-font { font-family: Arial, sans-serif !important; }
28
+ </style>
29
+ <![endif]-->
30
+ </head>
31
+
32
+ <body style="
33
+ margin: 0;
34
+ padding: 0;
35
+ background: #2a2a35;
36
+ color:#f4f4f4;
37
+ height: 100%;
38
+ line-height: 1.4;
39
+ font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
40
+ ">
41
+
42
+ <table width="100%" height="100%" border="0" cellpadding="0" cellspacing="0">
43
+ <tr>
44
+ <td align="center" valign="middle">
45
+ <table
46
+ class="root-container"
47
+ role="presentation"
48
+ cellspacing="0"
49
+ cellpadding="0"
50
+ border="0"
51
+ width="600"
52
+ align="center"
53
+ style="
54
+ max-width: fit-content;
55
+ margin: 2.5% auto;
56
+ background: #1a1a26;
57
+ padding: 30px;
58
+ padding-top: 0px;
59
+ padding-bottom: 15px;
60
+ border-radius: 5px;
61
+ box-shadow: 0 0 8px 4px rgba(0, 0, 0, 0.15);
62
+ "
63
+ >
64
+ <tr>
65
+ <td class="fallback-font">
66
+ <img src="/assets/logo.jpg" width="200px" height="200px" style="display: block; margin-left: auto; margin-right: auto;">
67
+ {{{content}}}
68
+ <p style="margin-top: 24px;">Kind regards,</p>
69
+ <p>Your team from api</p>
70
+ <p style="color: gray; margin-bottom: 0px; margin-top: 32px; font-size: 12px; text-align: center;">
71
+ CompanyName, Example Street 1, 12345 Example City
72
+ </p>
73
+ {{#if base.mailingListData}}
74
+ <a style="
75
+ color: gray;
76
+ display: block;
77
+ text-align: center;
78
+ font-size: 12px;
79
+ margin-top: 8px;
80
+ "
81
+ href="{{base.baseUrl}}/{{base.mailingListData.mailingListBaseRoute}}/{{base.mailingListData.mailingList.id}}/unsubscribe?subscriberId={{base.mailingListData.subscriber.id}}"
82
+ >
83
+ unsubscribe
84
+ </a>
85
+ {{/if}}
86
+ </td>
87
+ </tr>
88
+ </table>
89
+ </td>
90
+ </tr>
91
+ </table>
92
+ </body>
93
+ </html>
@@ -0,0 +1,32 @@
1
+ <h1>{{levelName}} from {{appName}}:</h1>
2
+
3
+ <div style="padding: 15px; border-radius: 5px; background-color: {{boxBgColor}}; color: black;">
4
+ <div><b>id:</b> {{log.id}}</div>
5
+ <div><b>createdAt</b>: {{createdAtString}}</div>
6
+ <div><b>origin:</b> {{log.context.origin}}</div>
7
+ <br>
8
+
9
+ {{#if log.context.request}}
10
+ <div><b>request:</b></div>
11
+ <pre style="margin: 0px; font-size: 14px; white-space: normal;">id: {{log.context.request.id}}</pre>
12
+ <pre style="margin: 0px; font-size: 14px; white-space: normal;">endpoint: {{log.context.request.method}} {{log.context.request.url}}</pre>
13
+ <pre style="margin: 0px; font-size: 14px; white-space: normal;">clientIp: {{log.context.request.clientIp}}</pre>
14
+ <pre style="margin: 0px; font-size: 14px; white-space: normal;">userAgent: {{log.context.request.userAgent}}</pre>
15
+
16
+ {{#if (and log.context.request.status log.context.request.durationInMs)}}
17
+ <pre style="margin: 0px; font-size: 14px; white-space: normal;">response: {{log.context.request.status}} after {{log.context.request.durationInMs}} ms</pre>
18
+ {{/if}}
19
+ <br>
20
+ {{/if}}
21
+
22
+ <div><b>message:</b></div>
23
+ <div>{{log.message}}</div>
24
+ <br>
25
+
26
+ {{#if log.error}}
27
+ <div><b>error:</b></div>
28
+ {{#each log.error.paragraphs}}
29
+ <pre style="margin: 0px; font-size: 14px; white-space: normal;">{{this}}</pre>
30
+ {{/each}}
31
+ {{/if}}
32
+ </div>
@@ -0,0 +1,26 @@
1
+ <p style="margin-bottom: 24px;">Hello {{user.name}},</p>
2
+ <p>
3
+ A password reset was requested for your account.
4
+ <br>
5
+ Click the link down below to proceed.
6
+ </p>
7
+ <a
8
+ class="button"
9
+ style="
10
+ display: inline-block;
11
+ padding: 10px;
12
+ padding-top: 7px;
13
+ border-radius: 5px;
14
+ box-sizing: border-box;
15
+ color: whitesmoke;
16
+ background-color: #2a2a35;
17
+ text-decoration: none;
18
+ transition: 0.3s ease;
19
+ "
20
+ href="{{confirmPasswordResetUrl}}/{{resetToken}}"
21
+ >
22
+ Reset Password
23
+ </a>
24
+ <p>
25
+ If you did not request to reset your password, you can ignore this mail.
26
+ </p>
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <title>Assets | {{name}}</title>
7
+ <link rel="icon" href="/assets/favicon.png">
8
+ <link rel="stylesheet" href="/assets/style.css">
9
+ </head>
10
+
11
+ <body>
12
+ <div class="container">
13
+ <div style="display: flex; flex-direction: column; gap: 30px; width: 500px;">
14
+ <div class="box" style="display: flex; align-items: center; margin: 0px; max-width: 100%;">
15
+ <a href="/"><img src="/assets/logo.jpg" width="100" height="100"></a>
16
+ <a href="/" style="margin-left: auto; margin-right: auto;"><h1>{{name}}</h1></a>
17
+ </div>
18
+ <div class="box" style="margin: 0px; max-width: 100%; height: 500px; overflow: scroll;">
19
+ {{{renderTree tree}}}
20
+ </div>
21
+ </div>
22
+ </div>
23
+ </body>
24
+
25
+ </html>
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>{{base.title}}</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <link rel="icon" type="image/png" href="/assets/favicon.png">
8
+ <link rel="stylesheet" href="/assets/style.css">
9
+ </head>
10
+ <body>
11
+ <div class="container">
12
+ {{{content}}}
13
+ </div>
14
+ </body>
15
+ </html>
@@ -0,0 +1,41 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>{{error.title}} | {{name}}</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <link rel="icon" type="image/png" href="/assets/favicon.png">
8
+ <link rel="stylesheet" href="/assets/style.css">
9
+ </head>
10
+ <body>
11
+ <div class="container">
12
+ <div style="display: flex; flex-direction: column; gap: 15px;">
13
+
14
+ <div style="display: flex; gap: 30px;">
15
+ <div class="box" style="padding-top: 0px; max-width: 250px;">
16
+ <a href="/"><img src="/assets/logo.jpg" width="250px" height="250px"></a>
17
+ <a href="/"><h2>{{name}}</h2></a>
18
+ </div>
19
+ <div style="width: 500px; display: flex; flex-direction: column; gap: 15px">
20
+ <div class="box" style="margin: 0px; max-width: 100%;">
21
+ <h1 style="text-align: left;">{{error.status}}: {{error.title}}</h1>
22
+ </div>
23
+ <div class="box" style="margin: 0px; max-width: 100%; flex: 1;">
24
+ <div style="display: flex; flex-direction: column; gap: 8px;">
25
+ {{#each error.paragraphs}}
26
+ <p style="font-size: 110%;">
27
+ {{this}}
28
+ </p>
29
+ {{/each}}
30
+ </div>
31
+ </div>
32
+ <div class="box" style="margin: 0px; max-width: 100%; display: flex; align-items: center; gap: 5px;">
33
+ <img src="/assets/open-api/swagger.png" width="30px" height="30px">
34
+ <a href="/explorer"><h2>OpenAPI Explorer</h2></a>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </body>
41
+ </html>
@@ -0,0 +1,20 @@
1
+ <div style="display: flex; flex-direction: column; gap: 30px;">
2
+ <div class="box" style="padding-top: 0px; width: 300px;">
3
+ <img src="/assets/logo.jpg" width="300px" height="300px">
4
+ <h1>{{name}}</h1>
5
+ </div>
6
+ <div style="display: flex; gap: 20px; justify-content: space-evenly; width: 600px;">
7
+ <div class="box" style="flex: 1; margin: 0px; max-width: 100%;">
8
+ <div style="display: flex; align-items: center; justify-content: center; gap: 5px;">
9
+ <img style="filter: brightness(0) saturate(100%) invert(60%) sepia(100%) saturate(700%) hue-rotate(15deg) contrast(1.1);" src="/assets/assets.svg" width="30px" height="30px">
10
+ <a href="/assets"><h2>Assets</h2></a>
11
+ </div>
12
+ </div>
13
+ <div class="box" style="flex: 1; margin: 0px; max-width: 100%;">
14
+ <div style="display: flex; align-items: center; justify-content: center; gap: 5px;">
15
+ <img src="/assets/open-api/swagger.png" width="30px" height="30px">
16
+ <a href="/explorer"><h2>OpenAPI Explorer</h2></a>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ </div>
@@ -0,0 +1,152 @@
1
+ <div class="box" style="display: flex; flex-direction: column; gap: 24px;">
2
+ <img src="/assets/logo.jpg" width="200px" height="200px" style="display: block; margin-left: auto; margin-right: auto;">
3
+ <p style="text-align: center;">{{maskEmail subscriber.email}}</p>
4
+ <h1 style="margin-bottom: 8px; margin-top: 8px;">
5
+ Mailing list preferences
6
+ </h1>
7
+ <ul>
8
+ {{#each mailingLists}}
9
+ <li style="margin-bottom: 8px;">
10
+ <div style="display: flex; align-items: center; font-size: 16px; column-gap: 8px;">
11
+ <input
12
+ type="checkbox"
13
+ id="{{this.data.id}}"
14
+ onchange="updateCheckedMailingListIds(event)"
15
+ {{#if this.isSubscribedTo}}checked{{/if}}
16
+ >
17
+ <label style="cursor: pointer;" for="{{this.data.id}}">{{this.data.name}}</label>
18
+ </div>
19
+ </li>
20
+ {{/each}}
21
+ </ul>
22
+ <button style="margin-left: auto; margin-right: auto;" onclick="update()">Update</button>
23
+ <div class="status-bar">
24
+ </div>
25
+ </div>
26
+
27
+ <script>
28
+ let checkedMailingListIdsPriorChanges = getCheckedMailingListIds();
29
+ let currentCheckedMailingListIds = getCheckedMailingListIds();
30
+ document.querySelector('button').disabled = true;
31
+
32
+ function updateCheckedMailingListIds(event) {
33
+ const targetId = event.target.id;
34
+ const isChecked = event.target.checked;
35
+
36
+ if (isChecked) {
37
+ currentCheckedMailingListIds.push(targetId);
38
+ }
39
+ else {
40
+ currentCheckedMailingListIds = currentCheckedMailingListIds.filter(id => id !== targetId);
41
+ }
42
+
43
+ checkIsDirty();
44
+ }
45
+
46
+ function checkIsDirty() {
47
+ if (checkedMailingListIdsPriorChanges.find(id => !currentCheckedMailingListIds.includes(id))) {
48
+ document.querySelector('button').disabled = false;
49
+ return;
50
+ }
51
+ if (currentCheckedMailingListIds.find(id => !checkedMailingListIdsPriorChanges.includes(id))) {
52
+ document.querySelector('button').disabled = false;
53
+ return;
54
+ }
55
+
56
+ document.querySelector('button').disabled = true;
57
+ }
58
+
59
+ function getCheckedMailingListIds() {
60
+ const checkboxes = document.querySelectorAll('input');
61
+ const mailingListIds = [];
62
+ for (const checkbox of checkboxes) {
63
+ if (checkbox.checked) {
64
+ mailingListIds.push(checkbox.id);
65
+ }
66
+ }
67
+ return mailingListIds;
68
+ }
69
+
70
+ async function update() {
71
+ setIsLoading();
72
+
73
+ const success = (await fetch(
74
+ `{{base.baseUrl}}{{mailingListBaseRoute}}/preferences?subscriberId={{subscriber.id}}`,
75
+ { method: 'PATCH', body: JSON.stringify({ mailingListIds: currentCheckedMailingListIds }), headers: { 'content-type': 'application/json' } }
76
+ )).ok;
77
+
78
+ if (success) {
79
+ setIsSuccess();
80
+ return;
81
+ }
82
+
83
+ for (const id of mailingListIds) {
84
+ if (!checkedMailingListIdsPriorChanges.includes(id)) {
85
+ document.getElementById(id).checked = false;
86
+ }
87
+ }
88
+ for (const id of checkedMailingListIdsPriorChanges) {
89
+ if (!mailingListIds.includes(id)) {
90
+ document.getElementById(id).checked = true;
91
+ }
92
+ }
93
+ setIsFailed();
94
+ }
95
+
96
+ function reset() {
97
+ checkedMailingListIdsPriorChanges = getCheckedMailingListIds();
98
+ checkIsDirty();
99
+ }
100
+ function removeStatus() {
101
+ document.querySelector('.status-bar').classList.remove('status-loading');
102
+ document.querySelector('.status-bar').classList.remove('status-success');
103
+ document.querySelector('.status-bar').classList.remove('status-failed');
104
+ document.querySelector('.status-bar').textContent = null;
105
+ }
106
+ function setIsLoading() {
107
+ document.querySelector('button').disabled = true;
108
+ document.querySelector('.status-bar').classList.add('status-loading');
109
+ document.querySelector('.status-bar').textContent = 'loading...';
110
+ }
111
+ function setIsSuccess() {
112
+ removeStatus();
113
+ document.querySelector('.status-bar').classList.add('status-success');
114
+ document.querySelector('.status-bar').textContent = 'preferences updated';
115
+ reset();
116
+ setTimeout(removeStatus, 3000);
117
+ }
118
+ function setIsFailed() {
119
+ removeStatus();
120
+ document.querySelector('.status-bar').classList.add('status-failed');
121
+ document.querySelector('.status-bar').textContent = 'failed updating preferences';
122
+ reset();
123
+ setTimeout(removeStatus, 3000);
124
+ }
125
+ </script>
126
+
127
+ <style>
128
+ .status-bar {
129
+ display: flex;
130
+ justify-content: center;
131
+ align-items: center;
132
+ height: 24px;
133
+ margin-top: -9px;
134
+ margin-bottom: -15px;
135
+ margin-left: -15px;
136
+ margin-right: -15px;
137
+ border-bottom-right-radius: 5px;
138
+ border-bottom-left-radius: 5px;
139
+ }
140
+ .status-loading {
141
+ background-color: gray;
142
+ transition: 0.3s ease;
143
+ }
144
+ .status-success {
145
+ background-color: green;
146
+ transition: 0.3s ease;
147
+ }
148
+ .status-failed {
149
+ background-color: red;
150
+ transition: 0.3s ease;
151
+ }
152
+ </style>
@@ -0,0 +1,25 @@
1
+ <div class="box" style="text-align: center; display: flex; flex-direction: column; gap: 24px;">
2
+ <img src="/assets/logo.jpg" width="200px" height="200px" style="display: block; margin-left: auto; margin-right: auto;">
3
+ <p>{{maskEmail subscriber.email}}</p>
4
+ <h1 style="margin-bottom: 8px; margin-top: 8px;">
5
+ You've unsubscribed from
6
+ <br>
7
+ {{mailingList.name}}
8
+ </h1>
9
+ <p style="margin-bottom: 16px">
10
+ We are sad to see you go 😕
11
+ </p>
12
+ <!-- <p>
13
+ If you have any feedback for us, we would be happy to hear it:
14
+ </p>
15
+ <textarea style="margin-left: 16px; margin-right: 16px;"></textarea>
16
+ <button style="margin-left: auto; margin-right: auto;" onclick="console.debug('Hello World')">Send</button> -->
17
+ <div>
18
+ <hr>
19
+ </div>
20
+ <p>
21
+ Unsubscribed by accident?
22
+ <br>
23
+ <a href="">Subscribe again</a> or <a href="/mailing-lists/preferences">manage other email preferences</a>
24
+ </p>
25
+ </div>
@@ -0,0 +1,443 @@
1
+ <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
2
+ <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns"></script>
3
+
4
+ <div style="height: 100%; width: 100%; color: whitesmoke; padding-left: 40px; padding-right: 40px;">
5
+ <h1 style="margin-top: 20px; margin-bottom: 20px;">{{name}} Metrics</h1>
6
+ <div style="display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 20px; margin-bottom: 20px; grid-auto-rows: 1fr;">
7
+ <div style="grid-column: span 2; display: flex; flex-direction: column; gap: 20px;">
8
+ <div style="display: flex; gap: 20px;">
9
+ <div class="metrics-container" style="flex: 1; display: flex; justify-content: center; align-items: center;">
10
+ <a href="/"><img src="/assets/logo.jpg" width="100" height="100"></a>
11
+ <a href="/" style="margin-left: auto; margin-right: auto;"><h2>{{name}}</h2></a>
12
+ </div>
13
+ <div class="metrics-container" style="flex: 1;">
14
+ <h2>Status</h2>
15
+
16
+ <div style="display: flex; justify-content: center; align-items: center; gap: 5px;">
17
+ <input id="automaticReload"
18
+ type="checkbox"
19
+ checked="true"
20
+ onchange="updateAutomaticReload(event)"
21
+ >
22
+ <label style="cursor: pointer;" for="automaticReload">Automatic reload</label>
23
+ </div>
24
+
25
+ <div style="width: fit-content; margin-left: auto; margin-right: auto; margin-bottom: 20px; margin-top: 20px;">
26
+ <div style="display: flex; justify-content: space-between; gap: 40px;">
27
+ <div>Version:</div>
28
+ <div>{{version}}</div>
29
+ </div>
30
+ <div style="display: flex; justify-content: space-between; gap: 40px;">
31
+ <div>Uptime:</div>
32
+ <div id="uptimeInfo">...</div>
33
+ </div>
34
+ <div style="display: flex; justify-content: space-between; gap: 40px;">
35
+ <div>Since:</div>
36
+ <div id="uptimeInfoSince">...</div>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </div>
41
+
42
+ <div class="metrics-container" style="flex: 1;">
43
+ <h2 style="margin-bottom: 10px;">Request duration</h2>
44
+ <canvas id="requestDurationChart"></canvas>
45
+ </div>
46
+ </div>
47
+
48
+ <div class="metrics-container" style="grid-column: span 3;">
49
+ <h2>Requests per second</h2>
50
+ <canvas id="rpsChart"></canvas>
51
+ </div>
52
+ </div>
53
+ <div style="display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px;">
54
+ <div class="metrics-container" style="margin-bottom: 40px;">
55
+ <h2>Resource Usage</h2>
56
+ <canvas id="resourceChart"></canvas>
57
+ </div>
58
+ <div class="metrics-container" style="margin-bottom: 40px;">
59
+ <h2>Network</h2>
60
+ <canvas id="networkChart"></canvas>
61
+ </div>
62
+ </div>
63
+ </div>
64
+
65
+ <script>
66
+ const primary = '#0e456f';
67
+ const secondary = '#00b4d8';
68
+ Chart.defaults.color = 'whitesmoke';
69
+ Chart.defaults.borderColor = 'whitesmoke';
70
+ Chart.defaults.backgroundColor = secondary;
71
+ Chart.defaults.scale.grid.color = 'rgba(200, 200, 200, 0.3)';
72
+
73
+ let automaticReload = true;
74
+ let snaps = [];
75
+ let rpsChart;
76
+ let requestDurationChart;
77
+ let resourceChart;
78
+ let networkChart;
79
+
80
+ window.addEventListener('load', () => {
81
+ loadSnapshots();
82
+ setInterval(loadSnapshots, 1000);
83
+ });
84
+
85
+ async function loadSnapshots() {
86
+ if (!automaticReload) {
87
+ return;
88
+ }
89
+ try {
90
+ const resp = await fetch('/metrics');
91
+ snaps = await resp.json();
92
+ updateData();
93
+ }
94
+ catch (err) {
95
+ console.error('failed to load metrics', err);
96
+ }
97
+ }
98
+
99
+ function updateData() {
100
+ renderRequestDurationChart();
101
+ renderRequestsPerSecondChart();
102
+ renderMemoryChart();
103
+ renderNetworkChart();
104
+ renderUptime();
105
+ }
106
+
107
+ function updateAutomaticReload(event) {
108
+ automaticReload = !automaticReload;
109
+ }
110
+
111
+ function renderUptime() {
112
+ const latest = snaps[snaps.length - 1];
113
+ if (!latest) return;
114
+
115
+ const startTimeMetric = latest.metrics.find(m => m.name === 'process_start_time_seconds');
116
+ if (!startTimeMetric) return;
117
+
118
+ const start = startTimeMetric.value * 1000;
119
+ const diffMs = Date.now() - start;
120
+ const diff = {
121
+ days: Math.floor(diffMs / 86400000),
122
+ hours: Math.floor((diffMs % 86400000) / 3600000),
123
+ minutes: Math.floor((diffMs % 3600000) / 60000),
124
+ seconds: Math.floor((diffMs % 60000) / 1000)
125
+ };
126
+
127
+ const text = `${diff.days}d ${diff.hours}h ${diff.minutes}m ${diff.seconds}s`;
128
+ const sinceText = `${new Date(start).toLocaleDateString('de', { year: 'numeric', day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })}`;
129
+ document.getElementById('uptimeInfo').textContent = text;
130
+ document.getElementById('uptimeInfoSince').textContent = sinceText;
131
+ }
132
+
133
+ function renderRequestsPerSecondChart() {
134
+ // 1) Build per‐snapshot RPS deltas by status class
135
+ const intervalSec = 5;
136
+ const seriesSuccess = [];
137
+ const seriesClientError = [];
138
+ const seriesServerError = [];
139
+
140
+ snaps.forEach((snap, i, all) => {
141
+ const t = new Date(snap.timestamp);
142
+ if (i === 0) {
143
+ seriesSuccess.push({ x: t, y: 0 });
144
+ seriesClientError.push({ x: t, y: 0 });
145
+ seriesServerError.push({ x: t, y: 0 });
146
+ return;
147
+ }
148
+ const prev = all[i - 1].metrics;
149
+ const curr = snap.metrics;
150
+ // sum counts by class
151
+ const sumFor = (codeRx) => {
152
+ const sum = (metrics) =>
153
+ metrics
154
+ .filter(m => {
155
+ if (m.name !== 'http_requests_total') {
156
+ return false;
157
+ }
158
+ switch (codeRx) {
159
+ case 'success': {
160
+ return !m.labels.status_code.startsWith('5') && !m.labels.status_code.startsWith('4')
161
+ }
162
+ case 'client': {
163
+ return m.labels.status_code.startsWith('4');
164
+ }
165
+ case 'server': {
166
+ return m.labels.status_code.startsWith('5');
167
+ }
168
+ }
169
+ })
170
+ .reduce((acc, m) => acc + m.value, 0);
171
+ return (sum(curr) - sum(prev)) / intervalSec;
172
+ };
173
+ seriesSuccess.push({ x: t, y: sumFor('success') });
174
+ seriesClientError.push({ x: t, y: sumFor('client') });
175
+ seriesServerError.push({ x: t, y: sumFor('server') });
176
+ });
177
+
178
+ // build event‑loop lag series (in ms)
179
+ const lagSeries = snaps.map(snap => {
180
+ const m = snap.metrics.find(m => m.name === 'nodejs_eventloop_lag_seconds');
181
+ return {
182
+ x: new Date(snap.timestamp),
183
+ y: m ? m.value * 1000 : 0
184
+ };
185
+ });
186
+
187
+ const datasets = [
188
+ {
189
+ label: 'Event Loop Lag',
190
+ data: lagSeries,
191
+ fill: false,
192
+ yAxisID: 'y1',
193
+ backgroundColor: 'purple',
194
+ borderColor: 'purple'
195
+ },
196
+ {
197
+ label: 'Server Error',
198
+ data: seriesServerError,
199
+ fill: true,
200
+ backgroundColor: 'red',
201
+ borderColor: 'red'
202
+ },
203
+ {
204
+ label: 'Client Error',
205
+ data: seriesClientError,
206
+ fill: true,
207
+ borderColor: secondary
208
+ },
209
+ {
210
+ label: 'Success',
211
+ data: seriesSuccess,
212
+ fill: true,
213
+ backgroundColor: 'green',
214
+ borderColor: 'green'
215
+ }
216
+ ];
217
+
218
+ if (rpsChart) {
219
+ rpsChart.data.datasets[0].data = datasets[0].data;
220
+ rpsChart.data.datasets[1].data = datasets[1].data;
221
+ rpsChart.data.datasets[2].data = datasets[2].data;
222
+ rpsChart.data.datasets[3].data = datasets[3].data;
223
+ rpsChart.update();
224
+ return;
225
+ }
226
+
227
+ // render RPS chart
228
+ rpsChart = new Chart(document.getElementById('rpsChart'), {
229
+ type: 'line',
230
+ data: { datasets },
231
+ options: {
232
+ scales: {
233
+ x: {
234
+ type: 'time',
235
+ time: {
236
+ unit: 'second',
237
+ displayFormats: {
238
+ second: 'HH:mm:ss'
239
+ }
240
+ },
241
+ grid: { display: false }
242
+ },
243
+ y: {
244
+ stacked: true,
245
+ beginAtZero: true,
246
+ title: { display: true, text: 'Requests/sec' },
247
+ grid: { display: true }
248
+ },
249
+ y1: {
250
+ position: 'right',
251
+ title: { display: true, text: 'Lag (ms)' },
252
+ ticks: { callback: v => `${v} ms` }
253
+ }
254
+ },
255
+ ticks: {
256
+ stepSize: 5,
257
+ source: 'auto'
258
+ }
259
+ }
260
+ });
261
+ }
262
+
263
+ function renderRequestDurationChart() {
264
+ // Build histogram from the *latest* snapshot only
265
+ const latest = snaps[snaps.length - 1]?.metrics ?? [];
266
+ const sumsByLe = latest
267
+ .filter(m => m.name === 'http_request_duration_ms' && m.labels.le !== undefined)
268
+ .reduce((map,m) => {
269
+ const le = m.labels.le;
270
+ map[le] = (map[le] || 0) + m.value;
271
+ return map;
272
+ }, {});
273
+ const sorted = Object.entries(sumsByLe)
274
+ .map(([le,v]) => ({ le, v }))
275
+ .sort((a,b) => {
276
+ const na = a.le==='+Inf'? Infinity: +a.le;
277
+ const nb = b.le==='+Inf'? Infinity: +b.le;
278
+ return na-nb;
279
+ });
280
+ const perBucket = sorted.map((cur, i) => {
281
+ const prev = i > 0 ? sorted[i - 1].v : 0;
282
+ return { le: cur.le, v: cur.v - prev };
283
+ });
284
+ const hist = perBucket.reduce(
285
+ (acc,m) => {
286
+ acc.labels.push(`${m.le} ms`);
287
+ acc.values.push(m.v);
288
+ return acc;
289
+ },
290
+ { labels:[], values:[] }
291
+ );
292
+
293
+ if (requestDurationChart) {
294
+ requestDurationChart.data.labels = hist.labels;
295
+ requestDurationChart.data.datasets[0].data = hist.values;
296
+ requestDurationChart.update();
297
+ return;
298
+ }
299
+
300
+ // render latency histogram
301
+ requestDurationChart = new Chart(document.getElementById('requestDurationChart'), {
302
+ type: 'bar',
303
+ data: { labels: hist.labels, datasets: [{ label: 'Count', data: hist.values }] }
304
+ });
305
+ }
306
+
307
+ function renderMemoryChart() {
308
+ const data = snaps.map(snap => {
309
+ const mem = snap.metrics.find(m => m.name === 'process_resident_memory_bytes');
310
+ return {
311
+ x: new Date(snap.timestamp),
312
+ y: mem ? mem.value / 1024 / 1024 : 0 // MB
313
+ };
314
+ });
315
+
316
+ const userSeries = snaps.map(s => s.metrics.find(m => m.name==='process_cpu_user_seconds_total')?.value || 0);
317
+ const systemSeries = snaps.map(s => s.metrics.find(m => m.name==='process_cpu_system_seconds_total')?.value|| 0);
318
+ const times = snaps.map(s => new Date(s.timestamp).getTime()/1000); // seconds
319
+ const cpuSeries = times.map((t,i) => {
320
+ if (i === 0) {
321
+ return { t, pct: 0 };
322
+ }
323
+ const dt = t - times[i-1]; // interval in seconds (should be ~5)
324
+ const du = userSeries[i] - userSeries[i-1];
325
+ const ds = systemSeries[i] - systemSeries[i-1];
326
+ const usedSec = du + ds; // total CPU seconds used in that interval
327
+ const cores = navigator.hardwareConcurrency || 1;
328
+ const pct = (usedSec / dt / cores) * 100; // CPU% across all cores
329
+ return { x: new Date(t*1000), y: pct };
330
+ });
331
+
332
+ if (resourceChart) {
333
+ resourceChart.data.datasets[0].data = data;
334
+ resourceChart.data.datasets[1].data = cpuSeries;
335
+ resourceChart.update();
336
+ return;
337
+ }
338
+
339
+ resourceChart = new Chart(document.getElementById('resourceChart'), {
340
+ type: 'line',
341
+ data: {
342
+ datasets: [
343
+ {
344
+ label: 'RAM (MB)',
345
+ data,
346
+ yAxisID: 'y',
347
+ borderColor: secondary,
348
+ },
349
+ {
350
+ label: 'CPU (%)',
351
+ data: cpuSeries,
352
+ yAxisID: 'yCPU',
353
+ borderColor: primary,
354
+ backgroundColor: primary
355
+ }
356
+ ]
357
+ },
358
+ options: {
359
+ scales: {
360
+ x: {
361
+ type: 'time',
362
+ time: {
363
+ unit: 'second',
364
+ displayFormats: {
365
+ second: 'HH:mm:ss'
366
+ }
367
+ },
368
+ grid: {display: false }
369
+ },
370
+ y: {
371
+ ticks: {
372
+ callback: v => `${v} MB`
373
+ },
374
+ beginAtZero: true,
375
+ },
376
+ yCPU: {
377
+ position: 'right',
378
+ grid: { drawOnChartArea: false }, // don't duplicate grid lines
379
+ ticks: {
380
+ callback: v => `${v}%`
381
+ }
382
+ }
383
+ }
384
+ }
385
+ });
386
+ }
387
+
388
+ function renderNetworkChart() {
389
+ if (snaps.length < 2) {
390
+ return;
391
+ }
392
+ const intervalSec = 5;
393
+
394
+ // extract series of cumulative values
395
+ const rxSeries = snaps.map(s => s.metrics.find(m => m.name==='network_bytes_received_total')?.value||0);
396
+ const txSeries = snaps.map(s => s.metrics.find(m => m.name==='network_bytes_transmitted_total')?.value||0);
397
+ const times = snaps.map(s => new Date(s.timestamp));
398
+
399
+ // build bytes/sec points
400
+ const dataRx = times.map((t,i) => {
401
+ if (i===0) return { x:t, y:0 };
402
+ return { x:t, y:(rxSeries[i]-rxSeries[i-1])/intervalSec };
403
+ });
404
+ const dataTx = times.map((t,i) => {
405
+ if (i===0) return { x:t, y:0 };
406
+ return { x:t, y:(txSeries[i]-txSeries[i-1])/intervalSec };
407
+ });
408
+
409
+ const datasets = [
410
+ { label:'bytes received', data: dataRx, borderColor: secondary },
411
+ { label:'bytes sent', data: dataTx, backgroundColor: primary, borderColor: primary },
412
+ ];
413
+
414
+ if (networkChart) {
415
+ networkChart.data.datasets[0].data = datasets[0].data;
416
+ networkChart.data.datasets[1].data = datasets[1].data;
417
+ networkChart.update();
418
+ return;
419
+ }
420
+
421
+ networkChart = new Chart(document.getElementById('networkChart'), {
422
+ type: 'line',
423
+ data: { datasets },
424
+ options: {
425
+ scales: {
426
+ x: {
427
+ type: 'time',
428
+ time: { unit:'second', displayFormats: { second:'HH:mm:ss' } },
429
+ grid: { display: false }
430
+ },
431
+ y: {
432
+ beginAtZero: true,
433
+ ticks: {
434
+ callback: v => `${v/1000} KB`
435
+ },
436
+ }
437
+ },
438
+ plugins:{ legend: { position:'top' } }
439
+ }
440
+ });
441
+ }
442
+
443
+ </script>