@postmate/cli 0.1.0 โ†’ 0.1.1

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
@@ -1 +1,148 @@
1
- # postmateli
1
+ # ๐Ÿš€ Postmate CLI
2
+
3
+ Run Postmate API collections directly from your terminal.
4
+
5
+ Postmate CLI enables environment-based execution, data-driven testing, JSON reporting, and CI/CD-ready exit codes โ€” all without a GUI.
6
+
7
+ ---
8
+
9
+ ## ๐Ÿ“ฆ Installation
10
+
11
+ Install globally using npm:
12
+
13
+ ```bash
14
+ npm install -g @postmate/cli
15
+ ```
16
+ Verify installation:
17
+ ```bash
18
+ pmc --version
19
+ ```
20
+ ๐Ÿ“ Project Structure
21
+
22
+ Postmate CLI works inside a project that contains a .postmate directory.
23
+
24
+ Example:
25
+ ```
26
+ my-project/
27
+ โ”‚
28
+ โ”œโ”€โ”€ .postmate/
29
+ โ”‚ โ”œโ”€โ”€ collections/
30
+ โ”‚ โ”œโ”€โ”€ environments/
31
+ โ”‚ โ”œโ”€โ”€ data/
32
+ โ”‚ โ””โ”€โ”€ reports/
33
+ โ”‚
34
+ โ””โ”€โ”€ package.json
35
+ ```
36
+ You can run the CLI from:
37
+ - Inside .postmate
38
+ - Or from the project root
39
+
40
+ The CLI automatically detects the correct project folder.
41
+
42
+ โ–ถ๏ธ Running a Collection
43
+
44
+ Basic usage:
45
+ ```
46
+ pmc run --collection <collectionName> --env <environmentName>
47
+ ```
48
+ Example:
49
+ ```
50
+ pmc run --collection school --env Dev
51
+ ```
52
+ Each row in the data file will execute the collection once.
53
+
54
+ Variables like:
55
+ ```
56
+ {{id}}
57
+ {{username}}
58
+ ```
59
+ will resolve per row.
60
+
61
+ ๐Ÿงช Execution Output
62
+
63
+ Example terminal output:
64
+ ```
65
+ ๐Ÿš€ Running school
66
+ Env: Dev
67
+ Iterations: 1
68
+ Total Requests: 10
69
+
70
+ โœ” [1] Get Users (200)
71
+ โœ– [1] Create User (500)
72
+
73
+ Finished in 3s 120ms
74
+ Total Requests: 10
75
+ Report saved: .postmate/reports/school-Dev-2026-02-14T15-32-10.json
76
+ ```
77
+ ๐Ÿ“„ Reports
78
+
79
+ After every run, a JSON report is automatically generated inside:
80
+ ```
81
+ .postmate/reports/
82
+ ```
83
+ Filename format:
84
+ ```
85
+ <collection>-<environment>-<timestamp>.json
86
+ ```
87
+ Example:
88
+ ```
89
+ school-Dev-2026-02-14T15-32-10.json
90
+ ```
91
+ Reports can be:
92
+ - Stored as CI artifacts
93
+ - Parsed for analytics
94
+ - Converted to JUnit
95
+ - Used for dashboards
96
+
97
+ โŒ Exit Codes (CI Ready)
98
+ Postmate CLI returns:
99
+ - 0 โ†’ All requests successful (HTTP 2xx)
100
+ - 1 โ†’ One or more failures
101
+
102
+ Example:
103
+ ```
104
+ pmc run --collection school --env Dev
105
+ echo $?
106
+ ```
107
+ This makes it ready for CI/CD pipelines.
108
+
109
+ โš™๏ธ Command Reference
110
+ Run Command
111
+ ```
112
+ pmc run --collection <name> --env <envName> [--data <dataFile>]
113
+ ```
114
+ Options
115
+ ```
116
+ | Option | Description |
117
+ | -------------- | -------------------------------- |
118
+ | `--collection` | Collection name |
119
+ | `--env` | Environment name |
120
+ | `--data` | Optional data file for iteration |
121
+ ```
122
+ ๐Ÿ— CI Example (GitHub Actions)
123
+ ```
124
+ - name: Run API Tests
125
+ run: pmc run --collection school --env QA
126
+ ```
127
+ If any request fails, the pipeline fails automatically.
128
+
129
+ ๐Ÿ’ก Best Practices
130
+ - Keep base URLs inside environment files
131
+ - Use data files for bulk execution
132
+ - Version control your .postmate directory
133
+ - Store reports as CI artifacts
134
+ - Use clear environment names (Dev, QA, Prod)
135
+
136
+ ๐Ÿ”ฅ Why Postmate CLI?
137
+ - Lightweight
138
+ - Deterministic
139
+ - Scriptable
140
+ - CI-friendly
141
+ - No GUI required
142
+ - Built for automation
143
+
144
+ ๐Ÿ“œ License
145
+
146
+ ISC
147
+
148
+ Made with โค๏ธ using Postmate
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import { Command } from 'commander';
3
3
  import { findPostmateRoot } from './utils/project.js';
4
4
  import { CoreContext } from '@postmate/core';
5
5
  import { cliLogger } from "./utils/cliLogger.js";
6
+ import { generateHtmlReport } from "./utils/reportHelper.js";
6
7
  import fs from "fs";
7
8
  import path from "path";
8
9
  const program = new Command();
@@ -83,11 +84,17 @@ const runCommand = program
83
84
  const timestamp = new Date()
84
85
  .toISOString()
85
86
  .replace(/:/g, "-");
86
- const fileName = `${collection}-${env}-${timestamp}.json`;
87
- const filePath = path.join(reportsDir, fileName);
87
+ const fileName = `${collection}-${env}-${timestamp}`;
88
+ const jsonFilePath = path.join(reportsDir, fileName + '.json');
89
+ const htmlFilePath = path.join(reportsDir, fileName + '.html');
88
90
  // 3๏ธโƒฃ Write JSON
89
- fs.writeFileSync(filePath, JSON.stringify(info.reportJson, null, 2), "utf-8");
90
- console.log(`Report saved: ${filePath}`);
91
+ fs.writeFileSync(jsonFilePath, JSON.stringify(info.reportJson, null, 2), "utf-8");
92
+ console.log(`Report saved: ${jsonFilePath}`);
93
+ //generate html report
94
+ const htmlReport = generateHtmlReport(info.reportJson, "Collection Name");
95
+ // 3๏ธโƒฃ Write JSON
96
+ fs.writeFileSync(htmlFilePath, htmlReport, "utf-8");
97
+ console.log(`HTML Report saved: ${htmlFilePath}`);
91
98
  },
92
99
  onError: (err) => {
93
100
  console.error('Run failed:', err);
@@ -0,0 +1,245 @@
1
+ export function generateHtmlReport(reportData, collectionName) {
2
+ const summary = reportData.summary;
3
+ const requests = reportData.requests || [];
4
+ const passRate = summary.totalTests
5
+ ? ((summary.passed / summary.totalTests) * 100).toFixed(1)
6
+ : "0";
7
+ return `
8
+ ${buildHtmlStart()}
9
+ ${buildHeader(collectionName)}
10
+ ${buildSummary(summary, passRate)}
11
+ ${buildRequests(requests)}
12
+ ${buildFooter()}
13
+ ${buildScript()}
14
+ </body>
15
+ </html>
16
+ `;
17
+ }
18
+ function buildHtmlStart() {
19
+ return `
20
+ <!DOCTYPE html>
21
+ <html>
22
+ <head>
23
+ <meta charset="UTF-8" />
24
+ <title>Postmate Execution Report</title>
25
+ <style>
26
+ body {
27
+ font-family: "Segoe UI", Arial, sans-serif;
28
+ background-color: #f4f6f9;
29
+ margin: 0;
30
+ padding: 20px;
31
+ color: #2c3e50;
32
+ }
33
+
34
+ .container { max-width: 1100px; margin: auto; }
35
+
36
+ .header {
37
+ background: #1f2937;
38
+ color: white;
39
+ padding: 20px;
40
+ border-radius: 8px;
41
+ }
42
+
43
+ .summary {
44
+ display: flex;
45
+ gap: 15px;
46
+ margin: 20px 0;
47
+ flex-wrap: wrap;
48
+ }
49
+
50
+ .card {
51
+ flex: 1;
52
+ min-width: 160px;
53
+ background: white;
54
+ padding: 15px;
55
+ border-radius: 8px;
56
+ box-shadow: 0 2px 6px rgba(0,0,0,0.05);
57
+ text-align: center;
58
+ }
59
+
60
+ .pass { color: #16a34a; }
61
+ .fail { color: #dc2626; }
62
+
63
+ .request {
64
+ background: white;
65
+ margin-bottom: 12px;
66
+ border-radius: 8px;
67
+ box-shadow: 0 2px 6px rgba(0,0,0,0.05);
68
+ }
69
+
70
+ .request-header {
71
+ padding: 12px 16px;
72
+ cursor: pointer;
73
+ display: flex;
74
+ justify-content: space-between;
75
+ }
76
+
77
+ .request-details {
78
+ display: none;
79
+ padding: 15px;
80
+ border-top: 1px solid #e5e7eb;
81
+ }
82
+
83
+ .badge-pass {
84
+ background: #dcfce7;
85
+ color: #166534;
86
+ padding: 4px 8px;
87
+ border-radius: 12px;
88
+ }
89
+
90
+ .badge-fail {
91
+ background: #fee2e2;
92
+ color: #991b1b;
93
+ padding: 4px 8px;
94
+ border-radius: 12px;
95
+ }
96
+ .test-status-pass {
97
+ color: #16a34a;
98
+ font-weight: 600;
99
+ }
100
+
101
+ .test-status-fail {
102
+ color: #dc2626;
103
+ font-weight: 600;
104
+ }
105
+
106
+ </style>
107
+ </head>
108
+ <body>
109
+ <div class="container">
110
+ `;
111
+ }
112
+ function buildHeader(collectionName) {
113
+ const logoBase64 = "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";
114
+ return `
115
+ <div class="header" style="
116
+ display:flex;
117
+ justify-content:space-between;
118
+ align-items:center;
119
+ ">
120
+ <div style="display:flex;align-items:center;gap:14px;">
121
+ <img src="data:image/png;base64,${logoBase64}" style="height:50px;" />
122
+ <div>
123
+ <h1 style="margin:0;">Execution Report</h1>
124
+ <div style="font-size:13px;opacity:0.8;">
125
+ ${collectionName}
126
+ </div>
127
+ </div>
128
+ </div>
129
+
130
+ <div style="font-size:12px;opacity:0.7;">
131
+ ${new Date().toLocaleString()}
132
+ </div>
133
+ </div>
134
+
135
+ `;
136
+ }
137
+ function buildSummary(summary, passRate) {
138
+ return `
139
+ <div class="summary">
140
+ <div class="card">
141
+ <div>Total Requests</div>
142
+ <h2>${summary.totalRequests}</h2>
143
+ </div>
144
+
145
+ <div class="card">
146
+ <div>Total Tests</div>
147
+ <h2>${summary.totalTests}</h2>
148
+ </div>
149
+
150
+ <div class="card">
151
+ <div>Passed</div>
152
+ <h2 class="pass">${summary.passed}</h2>
153
+ </div>
154
+
155
+ <div class="card">
156
+ <div>Failed</div>
157
+ <h2 class="fail">${summary.failed}</h2>
158
+ </div>
159
+
160
+ <div class="card">
161
+ <div>Pass Rate</div>
162
+ <h2>${passRate}%</h2>
163
+ </div>
164
+ </div>
165
+ `;
166
+ }
167
+ function buildRequests(requests) {
168
+ return requests.map((req, index) => buildRequestCard(req, index)).join("");
169
+ }
170
+ function buildRequestCard(req, index) {
171
+ const hasFailure = req.tests?.some((t) => t.status === "Failed");
172
+ const dataLine = req.data
173
+ ? `
174
+ <div style="
175
+ font-size:12px;
176
+ opacity:0.75;
177
+ margin-top:4px;
178
+ font-family: Consolas, monospace;
179
+ background:#f8fafc;
180
+ padding:6px;
181
+ border-radius:4px;
182
+ overflow-x:auto;
183
+ ">
184
+ ${escapeHtml(JSON.stringify(req.data, null, 2))}
185
+ </div>`
186
+ : "";
187
+ return `
188
+ <div class="request">
189
+ <div class="request-header" onclick="toggle(${index})">
190
+ <div>
191
+ <strong>${req.method}</strong> ${req.name}
192
+ <div style="font-size:12px;opacity:0.7;">${req.url}</div>
193
+ ${dataLine}
194
+ </div>
195
+ <div>
196
+ ${hasFailure
197
+ ? `<span class="badge-fail">FAILED</span>`
198
+ : `<span class="badge-pass">PASSED</span>`}
199
+ </div>
200
+ </div>
201
+
202
+ <div class="request-details" id="details-${index}">
203
+ <div style="font-size:13px;margin-bottom:8px;">
204
+ Status: <strong>${req.status}</strong> |
205
+ Duration: ${req.durationMs} ms
206
+ </div>
207
+
208
+ ${(req.tests || []).map(buildTestRow).join("")}
209
+ </div>
210
+ </div>
211
+ `;
212
+ }
213
+ function escapeHtml(str) {
214
+ return str
215
+ .replace(/&/g, "&amp;")
216
+ .replace(/</g, "&lt;")
217
+ .replace(/>/g, "&gt;");
218
+ }
219
+ function buildTestRow(test) {
220
+ return `
221
+ <div style="display:flex;justify-content:space-between;font-size:13px;padding:6px 0;">
222
+ <div>${test.description}</div>
223
+ <div class="${test.status === "Passed" ? "test-status-pass" : "test-status-fail"}">
224
+ ${test.status.toUpperCase()}
225
+ </div>
226
+ </div>
227
+ `;
228
+ }
229
+ function buildFooter() {
230
+ return `
231
+ <div style="text-align:center;font-size:12px;margin-top:30px;opacity:0.6;">
232
+ Generated by Postmate CLI
233
+ </div>
234
+ `;
235
+ }
236
+ function buildScript() {
237
+ return `
238
+ <script>
239
+ function toggle(index) {
240
+ const el = document.getElementById("details-" + index);
241
+ el.style.display = el.style.display === "block" ? "none" : "block";
242
+ }
243
+ </script>
244
+ `;
245
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postmate/cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Postmate CLI - Run API collections from terminal",
@@ -15,7 +15,7 @@
15
15
  "author": "Shyam Naryan Yadav",
16
16
  "license": "ISC",
17
17
  "dependencies": {
18
- "@postmate/core": "^0.1.15",
18
+ "@postmate/core": "^0.1.17",
19
19
  "chalk": "^5.6.2",
20
20
  "commander": "^14.0.3"
21
21
  },