@umeshindu222/apisnap 1.1.3 → 1.1.5

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
@@ -7,60 +7,315 @@
7
7
 
8
8
  ---
9
9
 
10
- ## Why APISnap?
10
+ ## What is APISnap?
11
11
 
12
- **The Problem:** Every time you make a change to your Express.js backend, you have to manually open Postman, find every route, and click "Send" one by one. For a project with 20+ endpoints, this is slow, error-prone, and boring.
12
+ Every time you change your Express backend, manually testing all your routes in Postman is slow and boring. **APISnap auto-discovers every route in your app and health-checks all of them in seconds** with zero configuration.
13
13
 
14
- **The Solution:** APISnap plugs directly into your Express app, **automatically discovers every route you've registered**, and then health-checks all of them in seconds with zero configuration.
14
+ One command. Every route. Instant results.
15
15
 
16
16
  ---
17
17
 
18
- ## Features
18
+ ## Features
19
19
 
20
- - **Auto Route Discovery** — Scans your Express router stack, no manual config needed
21
- - **Auth Header Support** — Pass JWT tokens or API keys via `--header`
22
- - **Slow Route Detection** — Flags endpoints that exceed your response time threshold
23
- - **JSON Report Export** — Save results to a file for CI/CD pipelines or sharing
24
- - **Beautiful CLI Output** — Color-coded results with spinners and summary table
25
- - **Express v4 & v5** — Compatible with both versions
20
+ - 🔍 **Auto Route Discovery** — finds every route including nested sub-routers
21
+ - 🔐 **Full Auth Support** — JWT, API Keys, Cookies, multiple headers at once
22
+ - 💡 **Auth Hints** tells you exactly how to fix 401/403 errors
23
+ -**Slow Route Detection** — flags endpoints that are too slow
24
+ - 🔁 **Retry Logic** auto-retries failed requests
25
+ - 📊 **HTML Reports** — beautiful visual reports you can share
26
+ - 💾 **JSON Export** — structured output for CI/CD pipelines
27
+ - ⚙️ **Config File** — save your settings so you don't retype every time
28
+ - 🎯 **Method Filter** — test only GET, POST, DELETE etc.
29
+ - 🧠 **Smart Path Params** — auto-replaces `:id`, `:slug`, `:uuid` with safe defaults
30
+ - 🚀 **Express v4 & v5** — works with both versions
26
31
 
27
32
  ---
28
33
 
29
- ## 🚀 Quick Start
34
+ ## Quick Start
30
35
 
31
- ### Step 1: Install and add the middleware to your Express app
36
+ ### Step 1 Install
32
37
 
33
38
  ```bash
34
39
  npm install @umeshindu222/apisnap
35
40
  ```
36
41
 
42
+ ### Step 2 — Add to your server file
43
+
44
+ Open your main server file (`server.js`, `app.js`, `app.ts`) and add **2 lines**:
45
+
46
+ ```javascript
47
+ const apisnap = require('@umeshindu222/apisnap'); // ADD THIS at the top
48
+
49
+ // ... all your existing routes stay exactly the same ...
50
+
51
+ apisnap.init(app); // ADD THIS — after your routes
52
+ ```
53
+
54
+ ### Step 3 — Start your server
55
+
56
+ ```bash
57
+ node server.js
58
+ # or
59
+ npm run dev
60
+ ```
61
+
62
+ You will see this line confirming it works:
63
+ ```
64
+ ✅ [APISnap] Discovery active → http://localhost:3000/__apisnap_discovery
65
+ ```
66
+
67
+ ### Step 4 — Run the health check
68
+
69
+ Open a **second terminal** in your project folder and run:
70
+
71
+ ```bash
72
+ npx @umeshindu222/apisnap --port 3000
73
+ ```
74
+
75
+ That's it. You will see every route tested automatically.
76
+
77
+ ---
78
+
79
+ ## Full Setup Examples
80
+
81
+ ### JavaScript (CommonJS)
82
+
37
83
  ```javascript
38
84
  const express = require('express');
39
85
  const apisnap = require('@umeshindu222/apisnap');
40
86
 
41
87
  const app = express();
88
+ app.use(express.json());
42
89
 
43
- // Your routes here
90
+ // Your routes
91
+ app.get('/health', (req, res) => res.json({ status: 'ok' }));
44
92
  app.get('/users', (req, res) => res.json({ users: [] }));
45
- app.post('/users', (req, res) => res.json({ message: 'Created' }));
93
+ app.post('/users', (req, res) => res.json({ message: 'created' }));
94
+ app.delete('/users/:id', (req, res) => res.json({ deleted: true }));
46
95
 
47
- // Add APISnap — place AFTER your routes
96
+ // APISnap — place AFTER your routes
97
+ apisnap.init(app);
98
+
99
+ app.listen(3000, () => console.log('Server running on port 3000'));
100
+ ```
101
+
102
+ ---
103
+
104
+ ### TypeScript
105
+
106
+ > ⚠️ **TypeScript users — import must be written exactly like this:**
107
+
108
+ ```typescript
109
+ // ✅ CORRECT — use import * as
110
+ import * as apisnap from '@umeshindu222/apisnap';
111
+
112
+ // ❌ WRONG — will give "has no default export" red error
113
+ import apisnap from '@umeshindu222/apisnap';
114
+
115
+ // ❌ WRONG — never mix import and require in TypeScript
116
+ import apisnap from '@umeshindu222/apisnap';
117
+ const apisnap = require('@umeshindu222/apisnap');
118
+ ```
119
+
120
+ Full example:
121
+
122
+ ```typescript
123
+ import express, { Application, Request, Response, NextFunction } from 'express';
124
+ import * as apisnap from '@umeshindu222/apisnap'; // ✅ correct
125
+
126
+ const app: Application = express();
127
+ app.use(express.json());
128
+
129
+ // Your routes
130
+ app.get('/health', (req: Request, res: Response) => res.json({ status: 'ok' }));
131
+ app.get('/users', (req: Request, res: Response) => res.json({ users: [] }));
132
+ app.post('/users', (req: Request, res: Response) => res.json({ message: 'created' }));
133
+
134
+ // APISnap — place AFTER your routes
135
+ apisnap.init(app);
136
+
137
+ app.listen(3000, () => console.log('Server running on port 3000'));
138
+
139
+ export default app;
140
+ ```
141
+
142
+ If TypeScript still shows a red error under the import, create a file called `apisnap.d.ts` in your project root:
143
+
144
+ ```typescript
145
+ declare module '@umeshindu222/apisnap' {
146
+ interface APISnapOptions {
147
+ skip?: string[];
148
+ name?: string;
149
+ }
150
+ export function init(app: any, options?: APISnapOptions): void;
151
+ }
152
+ ```
153
+
154
+ ---
155
+
156
+ ### With Sub-Routers (Real World Project)
157
+
158
+ ```javascript
159
+ const express = require('express');
160
+ const apisnap = require('@umeshindu222/apisnap');
161
+ const userRoutes = require('./routes/users');
162
+ const postRoutes = require('./routes/posts');
163
+ const authRoutes = require('./routes/auth');
164
+
165
+ const app = express();
166
+ app.use(express.json());
167
+
168
+ // Register all your routers
169
+ app.use('/api/users', userRoutes);
170
+ app.use('/api/posts', postRoutes);
171
+ app.use('/api/auth', authRoutes);
172
+
173
+ // APISnap discovers ALL routes including sub-routers
48
174
  apisnap.init(app);
49
175
 
50
176
  app.listen(3000);
51
177
  ```
52
178
 
53
- ### Step 2: Run the health check
179
+ ---
180
+
181
+ ### With Global Auth Middleware
182
+
183
+ > ⚠️ **Important:** If you use global auth middleware (`app.use(authMiddleware)`), you must place `apisnap.init(app)` **before** it. Otherwise auth will block the discovery endpoint.
184
+
185
+ ```javascript
186
+ const express = require('express');
187
+ const apisnap = require('@umeshindu222/apisnap');
188
+ const authMiddleware = require('./middleware/auth');
189
+
190
+ const app = express();
191
+ app.use(express.json());
192
+
193
+ // Register routes first
194
+ app.get('/health', (req, res) => res.json({ status: 'ok' }));
195
+ app.use('/api/users', userRoutes);
196
+ app.use('/api/posts', postRoutes);
197
+
198
+ // ✅ APISnap BEFORE global auth middleware
199
+ apisnap.init(app);
200
+
201
+ // ✅ Global auth AFTER apisnap
202
+ app.use(authMiddleware);
203
+
204
+ app.listen(3000);
205
+ ```
206
+
207
+ ---
208
+
209
+ ### Skip Specific Routes
210
+
211
+ ```javascript
212
+ // Don't test certain routes (e.g. auth callbacks, webhooks, admin)
213
+ apisnap.init(app, {
214
+ skip: ['/api/auth', '/webhooks', '/admin']
215
+ });
216
+ ```
217
+
218
+ ---
219
+
220
+ ## 🔐 Fixing 401 / 403 Errors
221
+
222
+ 401 and 403 errors are **completely normal** — it just means your routes are protected and APISnap needs credentials, exactly like any real client would.
223
+
224
+ ### JWT / Bearer Token
54
225
 
55
226
  ```bash
56
- npx @umeshindu222/apisnap --port 3000
227
+ npx @umeshindu222/apisnap --port 3000 -H "Authorization: Bearer eyJhbGci..."
228
+ ```
229
+
230
+ ### API Key
231
+
232
+ ```bash
233
+ npx @umeshindu222/apisnap --port 3000 -H "x-api-key: your-secret-key"
234
+ ```
235
+
236
+ ### Cookie / Session Auth (Passport.js, express-session)
237
+
238
+ ```bash
239
+ npx @umeshindu222/apisnap --port 3000 --cookie "connect.sid=s%3Aabc123"
240
+ ```
241
+
242
+ ### Multiple Headers at Once
243
+
244
+ The `-H` flag can be repeated as many times as you need:
245
+
246
+ ```bash
247
+ npx @umeshindu222/apisnap --port 3000 \
248
+ -H "Authorization: Bearer TOKEN" \
249
+ -H "x-api-key: SECRET" \
250
+ -H "x-tenant-id: my-company"
57
251
  ```
58
252
 
59
- That's it. APISnap finds and tests every route automatically.
253
+ ### How to Get Your JWT Token
254
+
255
+ 1. Open Postman
256
+ 2. Call your login endpoint:
257
+ ```
258
+ POST http://localhost:3000/api/auth/login
259
+ Content-Type: application/json
260
+
261
+ {
262
+ "email": "your@email.com",
263
+ "password": "yourpassword"
264
+ }
265
+ ```
266
+ 3. Copy the token from the response
267
+ 4. Use it in the `-H` flag above
268
+
269
+ ---
270
+
271
+ ## ⚙️ Config File (Recommended)
272
+
273
+ Instead of typing your token every single time, save your settings in a config file. Create `.apisnaprc.json` in your project root:
274
+
275
+ ```json
276
+ {
277
+ "port": "3000",
278
+ "slow": "300",
279
+ "headers": [
280
+ "Authorization: Bearer YOUR_JWT_TOKEN_HERE"
281
+ ]
282
+ }
283
+ ```
284
+
285
+ Now just run with no flags:
286
+ ```bash
287
+ npx @umeshindu222/apisnap
288
+ ```
289
+
290
+ APISnap reads the config file automatically.
291
+
292
+ > ⚠️ **Add `.apisnaprc.json` to your `.gitignore`** so your token is never committed to GitHub.
293
+
294
+ ### Full Config File Options
295
+
296
+ ```json
297
+ {
298
+ "port": "3000",
299
+ "slow": "300",
300
+ "timeout": "5000",
301
+ "retry": "1",
302
+ "headers": [
303
+ "Authorization: Bearer YOUR_TOKEN",
304
+ "x-api-key: YOUR_API_KEY"
305
+ ],
306
+ "cookie": "sessionId=your-session-id",
307
+ "params": {
308
+ "id": "1",
309
+ "userId": "1",
310
+ "slug": "hello-world",
311
+ "uuid": "550e8400-e29b-41d4-a716-446655440000"
312
+ }
313
+ }
314
+ ```
60
315
 
61
316
  ---
62
317
 
63
- ## 📋 CLI Usage
318
+ ## CLI Reference
64
319
 
65
320
  ```bash
66
321
  npx @umeshindu222/apisnap [options]
@@ -68,114 +323,264 @@ npx @umeshindu222/apisnap [options]
68
323
 
69
324
  | Option | Description | Default |
70
325
  |--------|-------------|---------|
71
- | `-p, --port <number>` | Port your server is running on | `3000` |
72
- | `-H, --header <string>` | Custom header for auth (e.g., `"Authorization: Bearer token"`) | — |
73
- | `-s, --slow <number>` | Response time threshold in ms for slow warnings | `200` |
74
- | `-e, --export <filename>` | Export results to a JSON file | |
75
- | `-V, --version` | Show version number | |
76
- | `-h, --help` | Show help | |
326
+ | `-p, --port <n>` | Port your server runs on | `3000` |
327
+ | `-H, --header <str>` | Auth header can repeat multiple times | — |
328
+ | `-c, --cookie <str>` | Cookie string for session auth | |
329
+ | `-s, --slow <n>` | Flag routes slower than this (ms) | `200` |
330
+ | `-t, --timeout <n>` | Request timeout in ms | `5000` |
331
+ | `-r, --retry <n>` | Retry failed requests N times | `0` |
332
+ | `-e, --export <file>` | Save JSON report to file | — |
333
+ | `--html <file>` | Save HTML report to file | — |
334
+ | `--only <methods>` | Only test these methods e.g. `GET,POST` | — |
335
+ | `--base-url <url>` | Test a different server e.g. staging | `localhost` |
336
+ | `--params <json>` | Override path params as JSON | — |
337
+ | `--fail-on-slow` | Exit code 1 if slow routes found | `false` |
77
338
 
78
339
  ---
79
340
 
80
- ## Examples
341
+ ## Examples
81
342
 
82
- ### Basic health check
343
+ ### Basic check
83
344
  ```bash
84
345
  npx @umeshindu222/apisnap --port 3000
85
346
  ```
86
347
 
87
- ### With authentication (JWT / Bearer tokens)
348
+ ### With JWT auth
88
349
  ```bash
89
- npx @umeshindu222/apisnap --port 3000 --header "Authorization: Bearer eyJhbGci..."
350
+ npx @umeshindu222/apisnap -p 3000 -H "Authorization: Bearer eyJhbGci..."
90
351
  ```
91
352
 
92
- ### Custom slow threshold (flag routes > 500ms)
353
+ ### Custom path params
354
+
355
+ If your route is `/users/:id/posts/:postId` and the default `1` doesn't work in your database:
93
356
  ```bash
94
- npx @umeshindu222/apisnap --port 3000 --slow 500
357
+ npx @umeshindu222/apisnap --params '{"id":"42","postId":"7"}'
95
358
  ```
96
359
 
97
- ### Export report to JSON
360
+ ### Only test GET routes
98
361
  ```bash
99
- npx @umeshindu222/apisnap --port 3000 --export my-report
100
- # Creates: my-report.json
362
+ npx @umeshindu222/apisnap --only GET
101
363
  ```
102
364
 
103
- ### All options together
365
+ ### Test your staging server
104
366
  ```bash
105
- npx @umeshindu222/apisnap --port 5000 --header "Authorization: Bearer TOKEN" --slow 300 --export ci-report
367
+ npx @umeshindu222/apisnap --base-url https://staging.myapp.com -H "Authorization: Bearer TOKEN"
106
368
  ```
107
369
 
108
- ---
370
+ ### Generate an HTML report
371
+ ```bash
372
+ npx @umeshindu222/apisnap --html report
373
+ ```
109
374
 
110
- ## Sample Output
375
+ Then open it:
376
+ ```bash
377
+ # Windows
378
+ start report.html
379
+
380
+ # Mac
381
+ open report.html
111
382
 
383
+ # Linux
384
+ xdg-open report.html
112
385
  ```
113
- 📸 APISnap v1.0.0
114
- Slow threshold: 200ms
115
386
 
116
- Connected! Found 6 endpoints.
387
+ ### Generate a JSON report
388
+ ```bash
389
+ npx @umeshindu222/apisnap --export report
390
+ # Creates: report.json
391
+ ```
392
+
393
+ ### Retry flaky endpoints
394
+ ```bash
395
+ npx @umeshindu222/apisnap --retry 3
396
+ ```
397
+
398
+ ### CI/CD — fail the pipeline if any endpoint is broken
399
+ ```bash
400
+ npx @umeshindu222/apisnap --export ci-report
401
+ # Exits with code 1 automatically if any endpoint fails
402
+ ```
403
+
404
+ ### All options together
405
+ ```bash
406
+ npx @umeshindu222/apisnap \
407
+ -p 5000 \
408
+ -H "Authorization: Bearer TOKEN" \
409
+ -H "x-api-key: SECRET" \
410
+ --cookie "sessionId=abc" \
411
+ --slow 300 \
412
+ --retry 2 \
413
+ --html report \
414
+ --export report
415
+ ```
117
416
 
118
- ✔ GET /health [200 OK] 3ms
119
- ✔ GET /users [200 OK] 12ms
120
- ✔ POST /users [200 OK] 8ms
121
- ✔ GET /users/1 [200 OK] 15ms
122
- ⚠️ GET /reports [200 OK] 543ms ← slow!
123
- ✖ DELETE /users/1 [401]
417
+ ---
418
+
419
+ ## Sample Output
420
+
421
+ ```
422
+ 📸 APISnap v1.1.4
423
+ Target: http://localhost:3000
424
+ Slow: >200ms
425
+ Timeout: 5000ms
426
+ Headers: {"Authorization":"Bearer ey••••••"}
427
+
428
+ ✔ Connected! Found 6 endpoints to test.
429
+
430
+ ✔ GET /health [200] 3ms
431
+ ✔ GET /users [200] 12ms
432
+ ✔ POST /users [200] 8ms
433
+ ✔ GET /users/1 [200] 5ms
434
+ ⚠️ GET /reports [200] 543ms ← slow!
435
+ ✖ DELETE /users/1 [401] 2ms
436
+ 💡 Hint: 401 Unauthorized — try adding -H "Authorization: Bearer YOUR_TOKEN"
124
437
 
125
438
  📊 Summary:
126
439
  ✅ Passed: 5
127
440
  ❌ Failed: 1
128
441
  ⚠️ Slow: 1 (>200ms)
442
+ ⏱ Avg: 95ms
443
+ 🕐 Total: 573ms
129
444
 
130
445
  ⚠️ Some endpoints are unhealthy!
131
446
  ```
132
447
 
133
448
  ---
134
449
 
135
- ## 💾 JSON Report Format
136
-
137
- When using `--export`, a structured JSON file is created:
450
+ ## JSON Report Format
138
451
 
139
452
  ```json
140
453
  {
141
454
  "tool": "APISnap",
142
- "generatedAt": "2026-03-06T15:56:20.375Z",
143
- "config": { "port": "3000", "slowThreshold": 200 },
144
- "summary": { "total": 6, "passed": 5, "failed": 1, "slow": 1 },
455
+ "version": "1.1.4",
456
+ "generatedAt": "2026-03-08T10:00:00.000Z",
457
+ "config": {
458
+ "port": "3000",
459
+ "slowThreshold": 200,
460
+ "timeout": 5000
461
+ },
462
+ "summary": {
463
+ "total": 6,
464
+ "passed": 5,
465
+ "failed": 1,
466
+ "slow": 1,
467
+ "avgDuration": 95,
468
+ "totalDuration": 573
469
+ },
145
470
  "results": [
146
- { "method": "GET", "path": "/health", "status": 200, "duration": 3, "success": true, "slow": false },
147
- { "method": "GET", "path": "/users", "status": 200, "duration": 12, "success": true, "slow": false },
148
- { "method": "GET", "path": "/reports", "status": 200, "duration": 543,"success": true, "slow": true }
471
+ {
472
+ "method": "GET",
473
+ "path": "/users",
474
+ "status": 200,
475
+ "duration": 12,
476
+ "success": true,
477
+ "slow": false,
478
+ "retries": 0
479
+ }
149
480
  ]
150
481
  }
151
482
  ```
152
483
 
153
- > **CI/CD tip:** Parse `summary.failed` and fail your pipeline build if it's greater than `0`!
484
+ > **CI/CD tip:** Check `summary.failed > 0` to fail your build automatically.
485
+
486
+ ---
487
+
488
+ ## Common Problems & Fixes
489
+
490
+ ### "Cannot reach discovery endpoint"
491
+
492
+ ```
493
+ ✖ Cannot reach discovery endpoint: http://localhost:3000/__apisnap_discovery
494
+ ```
495
+
496
+ **Causes:**
497
+ - Your server is not running — start it first in another terminal
498
+ - Wrong port — use `-p YOUR_PORT` to specify the correct one
499
+ - You forgot to add `apisnap.init(app)` to your server
500
+
501
+ ---
502
+
503
+ ### All routes show 401
504
+
505
+ **Cause:** Your routes are protected and no credentials were provided.
506
+
507
+ **Fix:**
508
+ ```bash
509
+ npx @umeshindu222/apisnap -H "Authorization: Bearer YOUR_REAL_TOKEN"
510
+ ```
511
+
512
+ Also check your middleware order — `apisnap.init(app)` must come **before** any global `app.use(authMiddleware)`.
513
+
514
+ ---
515
+
516
+ ### Routes are missing from the output
517
+
518
+ **Cause:** `apisnap.init(app)` was called before the routes were registered.
519
+
520
+ **Fix:** Make sure `apisnap.init(app)` is the **last thing** before `app.listen()`:
521
+
522
+ ```javascript
523
+ // All routes first
524
+ app.use('/api/users', userRoutes);
525
+ app.use('/api/posts', postRoutes);
526
+
527
+ // APISnap last (before app.listen)
528
+ apisnap.init(app);
529
+
530
+ app.listen(3000);
531
+ ```
532
+
533
+ ---
534
+
535
+ ### Config file not loading
536
+
537
+ **Cause:** On Windows, creating JSON files with PowerShell `echo` saves them with wrong encoding (UTF-16).
538
+
539
+ **Fix:** Create `.apisnaprc.json` manually in VS Code or Notepad — File → Save As → select **UTF-8** encoding.
540
+
541
+ ---
542
+
543
+ ### 404 on routes with path params
544
+
545
+ Routes like `/users/:id` get `:id` replaced with `1` by default. If `1` is not a valid ID in your database, override it:
546
+
547
+ ```bash
548
+ npx @umeshindu222/apisnap --params '{"id":"YOUR_REAL_ID"}'
549
+ ```
550
+
551
+ Or in your config file:
552
+ ```json
553
+ {
554
+ "params": {
555
+ "id": "64f1a2b3c4d5e6f7a8b9c0d1"
556
+ }
557
+ }
558
+ ```
154
559
 
155
560
  ---
156
561
 
157
- ## 🔧 How It Works
562
+ ## How It Works
158
563
 
159
- APISnap uses a two-part architecture:
564
+ APISnap has two parts:
160
565
 
161
- 1. **Middleware (The Seeker)** — `apisnap.init(app)` injects a hidden endpoint `/__apisnap_discovery` into your Express app. When called, it recursively walks the Express router stack and returns a map of every registered route — including nested sub-routers.
566
+ **1. Middleware** — `apisnap.init(app)` registers a hidden endpoint `/__apisnap_discovery` in your Express app. When called, it recursively walks the entire Express router stack and returns a map of every registered route — including all nested sub-routers.
162
567
 
163
- 2. **CLI Runner (The Checker)** — `npx @umeshindu222/apisnap` calls the discovery endpoint, gets the route map, then "pings" each route using axios injecting your headers, replacing path params with safe defaults (`:id` → `1`), and timing each response.
568
+ **2. CLI** — `npx @umeshindu222/apisnap` calls the discovery endpoint, gets the full route list, then sends a real HTTP request to each route using your headers and cookies. It replaces path params with smart defaults (`:id` → `1`, `:uuid` → valid UUID, `:slug` → `"example"`), measures response time, and reports everything.
164
569
 
165
570
  ---
166
571
 
167
- ## 🤝 Contributing
572
+ ## Contributing
168
573
 
169
574
  Contributions, issues and feature requests are welcome!
170
575
 
171
576
  1. Fork the repo
172
- 2. Create your feature branch: `git checkout -b feat/amazing-feature`
173
- 3. Commit your changes: `git commit -m 'feat: add amazing feature'`
174
- 4. Push to the branch: `git push origin feat/amazing-feature`
577
+ 2. Create your branch: `git checkout -b feat/amazing-feature`
578
+ 3. Commit: `git commit -m 'feat: add amazing feature'`
579
+ 4. Push: `git push origin feat/amazing-feature`
175
580
  5. Open a Pull Request
176
581
 
177
582
  ---
178
583
 
179
- ## 📄 License
584
+ ## License
180
585
 
181
586
  MIT © [Umesh Induranga](https://github.com/Umeshinduranga)