@vnphu/nestjs-api-explorer 0.2.4 → 0.2.6
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 +47 -5
- package/dist/api-explorer.html.d.ts.map +1 -1
- package/dist/api-explorer.html.js +118 -53
- package/dist/api-explorer.html.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ An in-app API explorer for NestJS — like Postman, but embedded directly into y
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Route auto-discovery** — scans the live Express router, no decorators needed
|
|
8
|
-
- **Markdown docs** — document body fields, query params, headers, and responses in a simple `.md` file
|
|
8
|
+
- **Markdown docs** — document body fields, query params, headers, and responses in a simple `.md` file or a folder of `.md` files
|
|
9
9
|
- **Full request builder** — path params, query params, headers, auth, and body
|
|
10
10
|
- **Global auth** — set Bearer Token / Basic Auth / API Key once, applies to all requests
|
|
11
11
|
- **Body types** — JSON (with formatter), Form-encoded, Plain text
|
|
@@ -42,9 +42,44 @@ Open your browser at `http://localhost:3000/api-explorer`.
|
|
|
42
42
|
|
|
43
43
|
---
|
|
44
44
|
|
|
45
|
-
## Documenting your API (Markdown
|
|
45
|
+
## Documenting your API (Markdown)
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
### Option A — Single file
|
|
48
|
+
|
|
49
|
+
Point `docsFile` to a `.md` file anywhere in your project:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
ApiExplorerModule.register({
|
|
53
|
+
docsFile: './api-explorer.md',
|
|
54
|
+
})
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Option B — Folder of files
|
|
58
|
+
|
|
59
|
+
Point `docsFolder` to a directory. All `.md` files inside (including subfolders) are scanned and merged automatically:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
ApiExplorerModule.register({
|
|
63
|
+
docsFolder: './docs',
|
|
64
|
+
})
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Example folder structure:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
docs/
|
|
71
|
+
├── auth.md
|
|
72
|
+
├── users.md
|
|
73
|
+
└── shop/
|
|
74
|
+
├── products.md
|
|
75
|
+
└── orders.md
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Each file follows the same markdown syntax. Routes from all files are merged into one map. If two files define the same `METHOD /path`, the last file read wins.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### Full example
|
|
48
83
|
|
|
49
84
|
### Full example
|
|
50
85
|
|
|
@@ -366,11 +401,17 @@ ApiExplorerModule.register({
|
|
|
366
401
|
// Default: 'API Explorer'
|
|
367
402
|
title: 'My API — Explorer',
|
|
368
403
|
|
|
369
|
-
// Path to
|
|
404
|
+
// Path to a single markdown docs file
|
|
370
405
|
// Relative paths are resolved from process.cwd()
|
|
371
|
-
// Default: null
|
|
406
|
+
// Default: null
|
|
372
407
|
docsFile: './api-explorer.md',
|
|
373
408
|
|
|
409
|
+
// Path to a folder of markdown docs files (scanned recursively)
|
|
410
|
+
// All .md files found are merged together
|
|
411
|
+
// If both docsFile and docsFolder are set, docsFolder takes priority
|
|
412
|
+
// Default: null
|
|
413
|
+
docsFolder: './docs',
|
|
414
|
+
|
|
374
415
|
// Explicitly enable or disable
|
|
375
416
|
// The explorer is ALWAYS disabled when NODE_ENV === 'production'
|
|
376
417
|
// Default: true
|
|
@@ -436,6 +477,7 @@ import {
|
|
|
436
477
|
RouteInfo,
|
|
437
478
|
DocField,
|
|
438
479
|
parseDocsFile,
|
|
480
|
+
parseDocsFolder,
|
|
439
481
|
} from '@vnphu/nestjs-api-explorer';
|
|
440
482
|
|
|
441
483
|
// DocField — one field in body/query/params/headers/response
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-explorer.html.d.ts","sourceRoot":"","sources":["../src/api-explorer.html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAEnE,wBAAgB,eAAe,CAAC,OAAO,EAAE,0BAA0B,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"api-explorer.html.d.ts","sourceRoot":"","sources":["../src/api-explorer.html.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAEnE,wBAAgB,eAAe,CAAC,OAAO,EAAE,0BAA0B,GAAG,MAAM,CAsrD3E"}
|
|
@@ -871,6 +871,46 @@ const S = {
|
|
|
871
871
|
};
|
|
872
872
|
function uid() { return ++S._uid; }
|
|
873
873
|
|
|
874
|
+
// ── Default value helper ────────────────────────────────────────────
|
|
875
|
+
function getDefaultVal(f) {
|
|
876
|
+
const dr = (f.rules || []).find(r => r.toLowerCase().startsWith('default('));
|
|
877
|
+
if (dr) {
|
|
878
|
+
const raw = dr.slice(8, -1);
|
|
879
|
+
if (f.type === 'number') { const n = Number(raw); return isNaN(n) ? 0 : n; }
|
|
880
|
+
if (f.type === 'boolean') return raw === 'true';
|
|
881
|
+
return raw;
|
|
882
|
+
}
|
|
883
|
+
if (f.type === 'number') return 0;
|
|
884
|
+
if (f.type === 'boolean') return false;
|
|
885
|
+
if (f.type === 'array') return [];
|
|
886
|
+
if (f.type === 'object') return {};
|
|
887
|
+
return '';
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// ── localStorage helpers ────────────────────────────────────────────
|
|
891
|
+
const LS_NS = 'api-explorer';
|
|
892
|
+
function lsSave(k, v) { try { localStorage.setItem(LS_NS+':'+k, JSON.stringify(v)); } catch {} }
|
|
893
|
+
function lsLoad(k, d) { try { const v = localStorage.getItem(LS_NS+':'+k); return v !== null ? JSON.parse(v) : d; } catch { return d; } }
|
|
894
|
+
function routeKey(r) { return 'route:'+r.method+':'+r.path; }
|
|
895
|
+
function saveGlobal() { lsSave('global', { baseUrl: el.baseUrl.value, globalAuth: S.globalAuth }); }
|
|
896
|
+
function saveRoute() { if (!S.selected) return; lsSave(routeKey(S.selected), { pathParams: S.pathParams, queryParams: S.queryParams, reqHeaders: S.reqHeaders, auth: S.auth, body: S.body }); }
|
|
897
|
+
|
|
898
|
+
function restoreGlobalAuthUi() {
|
|
899
|
+
const ga = S.globalAuth;
|
|
900
|
+
document.querySelectorAll('.gauth-type-btn').forEach(b => b.classList.toggle('active', b.dataset.gauth === ga.type));
|
|
901
|
+
['none','bearer','apikey'].forEach(x => $('gauth-'+x+'-panel').classList.toggle('hidden', x !== ga.type));
|
|
902
|
+
$('gauth-bearer-token').value = ga.bearerToken || '';
|
|
903
|
+
$('gauth-apikey-name').value = ga.apiKeyName || 'X-API-Key';
|
|
904
|
+
$('gauth-apikey-value').value = ga.apiKeyValue || '';
|
|
905
|
+
$('gauth-apikey-in').value = ga.apiKeyIn || 'header';
|
|
906
|
+
const isActive = ga.type !== 'none' && !!(ga.bearerToken || ga.apiKeyValue);
|
|
907
|
+
$('gauth-active-badge').classList.toggle('hidden', !isActive);
|
|
908
|
+
$('global-auth-btn').classList.toggle('active', isActive);
|
|
909
|
+
if (isActive && !$('global-auth-btn').querySelector('.dot')) {
|
|
910
|
+
const d = document.createElement('span'); d.className = 'dot'; $('global-auth-btn').appendChild(d);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
|
|
874
914
|
// ── Elements ───────────────────────────────────────────────────────
|
|
875
915
|
const $ = id => document.getElementById(id);
|
|
876
916
|
const el = {
|
|
@@ -903,6 +943,11 @@ function init() {
|
|
|
903
943
|
el.envTag.textContent = isLocal ? 'dev' : 'staging';
|
|
904
944
|
if (isLocal) el.envTag.classList.add('dev');
|
|
905
945
|
bindEvents();
|
|
946
|
+
const savedGlobal = lsLoad('global', null);
|
|
947
|
+
if (savedGlobal) {
|
|
948
|
+
if (savedGlobal.baseUrl) el.baseUrl.value = savedGlobal.baseUrl;
|
|
949
|
+
if (savedGlobal.globalAuth) { S.globalAuth = savedGlobal.globalAuth; restoreGlobalAuthUi(); }
|
|
950
|
+
}
|
|
906
951
|
loadRoutes();
|
|
907
952
|
renderSummary();
|
|
908
953
|
}
|
|
@@ -1010,46 +1055,63 @@ function renderRouteList() {
|
|
|
1010
1055
|
|
|
1011
1056
|
function selectRoute(route) {
|
|
1012
1057
|
S.selected = route;
|
|
1013
|
-
S.pathParams = {};
|
|
1014
|
-
(route.params || []).forEach(p => { S.pathParams[p] = ''; });
|
|
1015
1058
|
S.response = null;
|
|
1016
|
-
|
|
1059
|
+
|
|
1060
|
+
const saved = lsLoad(routeKey(route), null);
|
|
1061
|
+
if (saved) {
|
|
1062
|
+
S.pathParams = saved.pathParams || {};
|
|
1063
|
+
(route.params || []).forEach(p => { if (!(p in S.pathParams)) S.pathParams[p] = ''; });
|
|
1064
|
+
S.queryParams = (saved.queryParams || []).map(p => ({...p, id: uid()}));
|
|
1065
|
+
S.reqHeaders = (saved.reqHeaders || []).map(h => ({...h, id: uid()}));
|
|
1066
|
+
S.auth = saved.auth || { type: 'none', bearerToken: '', basicUsername: '', basicPassword: '', apiKeyName: 'X-API-Key', apiKeyValue: '', apiKeyIn: 'header' };
|
|
1067
|
+
S.body = saved.body || { type: 'none', content: '' };
|
|
1068
|
+
} else {
|
|
1069
|
+
S.pathParams = {};
|
|
1070
|
+
(route.params || []).forEach(p => { S.pathParams[p] = ''; });
|
|
1071
|
+
S.queryParams = (route.query || []).map(f => ({ id: uid(), key: f.name, value: String(getDefaultVal(f) ?? ''), enabled: true }));
|
|
1072
|
+
S.reqHeaders = (route.headers || []).map(f => ({ id: uid(), key: f.name, value: '', enabled: true }));
|
|
1073
|
+
S.auth = { type: 'none', bearerToken: '', basicUsername: '', basicPassword: '', apiKeyName: 'X-API-Key', apiKeyValue: '', apiKeyIn: 'header' };
|
|
1074
|
+
const bodyMethods = ['POST', 'PUT', 'PATCH'];
|
|
1075
|
+
if (bodyMethods.includes(route.method) && route.body?.length) {
|
|
1076
|
+
const template = {};
|
|
1077
|
+
route.body.forEach(f => { template[f.name] = getDefaultVal(f); });
|
|
1078
|
+
S.body = { type: 'json', content: JSON.stringify(template, null, 2) };
|
|
1079
|
+
} else {
|
|
1080
|
+
S.body = { type: 'none', content: '' };
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
// Restore auth UI
|
|
1085
|
+
document.querySelectorAll('.auth-type-btn').forEach(b => b.classList.toggle('active', b.dataset.auth === S.auth.type));
|
|
1086
|
+
['none','bearer','basic','apikey'].forEach(t => $('auth-'+t+'-panel').classList.toggle('hidden', t !== S.auth.type));
|
|
1087
|
+
el.bearerToken.value = S.auth.bearerToken;
|
|
1088
|
+
el.basicUsername.value = S.auth.basicUsername;
|
|
1089
|
+
el.basicPassword.value = S.auth.basicPassword;
|
|
1090
|
+
el.apikeyName.value = S.auth.apiKeyName;
|
|
1091
|
+
el.apikeyValue.value = S.auth.apiKeyValue;
|
|
1092
|
+
el.apikeyIn.value = S.auth.apiKeyIn;
|
|
1093
|
+
|
|
1094
|
+
// Restore body UI
|
|
1095
|
+
document.querySelectorAll('.body-type-btn').forEach(b => b.classList.toggle('active', b.dataset.body === S.body.type));
|
|
1096
|
+
const showBody = S.body.type !== 'none';
|
|
1097
|
+
el.bodyEditorWrap.classList.toggle('hidden', !showBody);
|
|
1098
|
+
el.bodyNoneMsg.classList.toggle('hidden', showBody);
|
|
1099
|
+
el.bodyEditor.value = S.body.content;
|
|
1100
|
+
el.formatBtn.style.display = S.body.type === 'json' ? '' : 'none';
|
|
1101
|
+
|
|
1102
|
+
renderResponse(); renderUrlBar(); renderPathParams(); renderQueryParams(); renderReqHeaders(); renderRouteList(); renderSummary();
|
|
1017
1103
|
el.sendBtn.disabled = false;
|
|
1018
1104
|
el.methodPill.style.visibility = 'visible';
|
|
1019
1105
|
|
|
1020
|
-
// Auto-switch to Params tab (always — it shows both path & query params)
|
|
1021
1106
|
el.reqTabBar.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
|
1022
|
-
el.reqTabBar.querySelector('[data-tab="params"]').classList.add('active');
|
|
1023
1107
|
document.querySelectorAll('#req-panel-inner .tab-panel').forEach(p => p.classList.remove('active'));
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
// Auto-fill body editor from body schema if available
|
|
1027
|
-
const bodyMethods = ['POST', 'PUT', 'PATCH'];
|
|
1028
|
-
if (bodyMethods.includes(route.method) && route.body?.length) {
|
|
1029
|
-
const template = {};
|
|
1030
|
-
route.body.forEach(f => {
|
|
1031
|
-
if (f.type === 'number') template[f.name] = 0;
|
|
1032
|
-
else if (f.type === 'boolean') template[f.name] = false;
|
|
1033
|
-
else if (f.type === 'array') template[f.name] = [];
|
|
1034
|
-
else if (f.type === 'object') template[f.name] = {};
|
|
1035
|
-
else template[f.name] = '';
|
|
1036
|
-
});
|
|
1037
|
-
S.body.content = JSON.stringify(template, null, 2);
|
|
1038
|
-
S.body.type = 'json';
|
|
1039
|
-
el.bodyEditor.value = S.body.content;
|
|
1040
|
-
// Sync body type radio
|
|
1041
|
-
document.querySelectorAll('[name="body-type"]').forEach(r => {
|
|
1042
|
-
r.checked = r.value === 'json';
|
|
1043
|
-
});
|
|
1044
|
-
el.formatBtn.style.display = '';
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
// Auto-switch to Body tab for methods that send a body
|
|
1048
|
-
if (bodyMethods.includes(route.method) && !route.params.length) {
|
|
1049
|
-
el.reqTabBar.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
|
1108
|
+
const bodyMethods2 = ['POST', 'PUT', 'PATCH'];
|
|
1109
|
+
if (bodyMethods2.includes(route.method) && !route.params.length) {
|
|
1050
1110
|
el.reqTabBar.querySelector('[data-tab="body"]').classList.add('active');
|
|
1051
|
-
document.querySelectorAll('#req-panel-inner .tab-panel').forEach(p => p.classList.remove('active'));
|
|
1052
1111
|
document.getElementById('tab-body').classList.add('active');
|
|
1112
|
+
} else {
|
|
1113
|
+
el.reqTabBar.querySelector('[data-tab="params"]').classList.add('active');
|
|
1114
|
+
document.getElementById('tab-params').classList.add('active');
|
|
1053
1115
|
}
|
|
1054
1116
|
}
|
|
1055
1117
|
|
|
@@ -1091,7 +1153,7 @@ function renderPathParams() {
|
|
|
1091
1153
|
<input class="kv-input" data-path-param="\${esc(p)}" placeholder="value" value="\${esc(S.pathParams[p] || '')}" spellcheck="false" />
|
|
1092
1154
|
</div>\`).join('');
|
|
1093
1155
|
el.pathParamsRows.querySelectorAll('[data-path-param]').forEach(input => {
|
|
1094
|
-
input.addEventListener('input', () => { S.pathParams[input.dataset.pathParam] = input.value; renderUrlBar(); renderSummary(); });
|
|
1156
|
+
input.addEventListener('input', () => { S.pathParams[input.dataset.pathParam] = input.value; renderUrlBar(); renderSummary(); saveRoute(); });
|
|
1095
1157
|
});
|
|
1096
1158
|
}
|
|
1097
1159
|
|
|
@@ -1120,14 +1182,14 @@ function renderReqHeaders() {
|
|
|
1120
1182
|
function bindKvAction(node) {
|
|
1121
1183
|
const { action, id } = node.dataset; const pid = +id;
|
|
1122
1184
|
const handlers = {
|
|
1123
|
-
'toggle-query': () => { const p = S.queryParams.find(x=>x.id===pid); if(p){p.enabled=node.checked;renderUrlBar();} },
|
|
1124
|
-
'key-query': () => { const p = S.queryParams.find(x=>x.id===pid); if(p){p.key=node.value;renderUrlBar();} },
|
|
1125
|
-
'val-query': () => { const p = S.queryParams.find(x=>x.id===pid); if(p){p.value=node.value;renderUrlBar();} },
|
|
1126
|
-
'remove-query': () => { S.queryParams=S.queryParams.filter(x=>x.id!==pid); renderQueryParams(); renderUrlBar(); },
|
|
1127
|
-
'toggle-header': () => { const h = S.reqHeaders.find(x=>x.id===pid); if(h) h.enabled=node.checked; },
|
|
1128
|
-
'key-header': () => { const h = S.reqHeaders.find(x=>x.id===pid); if(h) h.key=node.value; },
|
|
1129
|
-
'val-header': () => { const h = S.reqHeaders.find(x=>x.id===pid); if(h) h.value=node.value; },
|
|
1130
|
-
'remove-header': () => { S.reqHeaders=S.reqHeaders.filter(x=>x.id!==pid); renderReqHeaders(); },
|
|
1185
|
+
'toggle-query': () => { const p = S.queryParams.find(x=>x.id===pid); if(p){p.enabled=node.checked;renderUrlBar();saveRoute();} },
|
|
1186
|
+
'key-query': () => { const p = S.queryParams.find(x=>x.id===pid); if(p){p.key=node.value;renderUrlBar();saveRoute();} },
|
|
1187
|
+
'val-query': () => { const p = S.queryParams.find(x=>x.id===pid); if(p){p.value=node.value;renderUrlBar();saveRoute();} },
|
|
1188
|
+
'remove-query': () => { S.queryParams=S.queryParams.filter(x=>x.id!==pid); renderQueryParams(); renderUrlBar(); saveRoute(); },
|
|
1189
|
+
'toggle-header': () => { const h = S.reqHeaders.find(x=>x.id===pid); if(h) { h.enabled=node.checked; saveRoute(); } },
|
|
1190
|
+
'key-header': () => { const h = S.reqHeaders.find(x=>x.id===pid); if(h) { h.key=node.value; saveRoute(); } },
|
|
1191
|
+
'val-header': () => { const h = S.reqHeaders.find(x=>x.id===pid); if(h) { h.value=node.value; saveRoute(); } },
|
|
1192
|
+
'remove-header': () => { S.reqHeaders=S.reqHeaders.filter(x=>x.id!==pid); renderReqHeaders(); saveRoute(); },
|
|
1131
1193
|
};
|
|
1132
1194
|
const evt = action.startsWith('toggle') || action.startsWith('remove') ? 'change' : 'input';
|
|
1133
1195
|
if (action.startsWith('remove')) node.addEventListener('click', handlers[action]);
|
|
@@ -1566,7 +1628,7 @@ function bindEvents() {
|
|
|
1566
1628
|
gauthBtn.appendChild(d);
|
|
1567
1629
|
} else if (!isActive && dot) dot.remove();
|
|
1568
1630
|
gauthDrop.classList.add('hidden');
|
|
1569
|
-
renderUrlBar(); renderSummary();
|
|
1631
|
+
renderUrlBar(); renderSummary(); saveGlobal();
|
|
1570
1632
|
});
|
|
1571
1633
|
|
|
1572
1634
|
$('gauth-clear-btn').addEventListener('click', () => {
|
|
@@ -1578,20 +1640,20 @@ function bindEvents() {
|
|
|
1578
1640
|
gauthBadge.classList.add('hidden');
|
|
1579
1641
|
gauthBtn.classList.remove('active');
|
|
1580
1642
|
gauthBtn.querySelector('.dot')?.remove();
|
|
1581
|
-
renderUrlBar();
|
|
1643
|
+
renderUrlBar(); saveGlobal();
|
|
1582
1644
|
});
|
|
1583
|
-
el.baseUrl.addEventListener('input', () => { renderUrlBar(); renderSummary(); });
|
|
1645
|
+
el.baseUrl.addEventListener('input', () => { renderUrlBar(); renderSummary(); saveGlobal(); });
|
|
1584
1646
|
el.sendBtn.addEventListener('click', sendRequest);
|
|
1585
1647
|
|
|
1586
1648
|
$('summary-copy-btn').addEventListener('click', copySummary);
|
|
1587
1649
|
|
|
1588
1650
|
el.addQueryBtn.addEventListener('click', () => {
|
|
1589
1651
|
S.queryParams.push({ id: uid(), key: '', value: '', enabled: true });
|
|
1590
|
-
renderQueryParams();
|
|
1652
|
+
renderQueryParams(); saveRoute();
|
|
1591
1653
|
});
|
|
1592
1654
|
el.addHeaderBtn.addEventListener('click', () => {
|
|
1593
1655
|
S.reqHeaders.push({ id: uid(), key: '', value: '', enabled: true });
|
|
1594
|
-
renderReqHeaders();
|
|
1656
|
+
renderReqHeaders(); saveRoute();
|
|
1595
1657
|
});
|
|
1596
1658
|
|
|
1597
1659
|
document.querySelectorAll('.auth-type-btn').forEach(btn => {
|
|
@@ -1601,14 +1663,15 @@ function bindEvents() {
|
|
|
1601
1663
|
['none','bearer','basic','apikey'].forEach(t => {
|
|
1602
1664
|
$('auth-'+t+'-panel').classList.toggle('hidden', t !== S.auth.type);
|
|
1603
1665
|
});
|
|
1666
|
+
saveRoute();
|
|
1604
1667
|
});
|
|
1605
1668
|
});
|
|
1606
|
-
el.bearerToken.addEventListener('input', () => { S.auth.bearerToken = el.bearerToken.value; });
|
|
1607
|
-
el.basicUsername.addEventListener('input', () => { S.auth.basicUsername = el.basicUsername.value; });
|
|
1608
|
-
el.basicPassword.addEventListener('input', () => { S.auth.basicPassword = el.basicPassword.value; });
|
|
1609
|
-
el.apikeyName.addEventListener('input', () => { S.auth.apiKeyName = el.apikeyName.value; });
|
|
1610
|
-
el.apikeyValue.addEventListener('input', () => { S.auth.apiKeyValue = el.apikeyValue.value; });
|
|
1611
|
-
el.apikeyIn.addEventListener('change', () => { S.auth.apiKeyIn = el.apikeyIn.value; renderUrlBar(); });
|
|
1669
|
+
el.bearerToken.addEventListener('input', () => { S.auth.bearerToken = el.bearerToken.value; saveRoute(); });
|
|
1670
|
+
el.basicUsername.addEventListener('input', () => { S.auth.basicUsername = el.basicUsername.value; saveRoute(); });
|
|
1671
|
+
el.basicPassword.addEventListener('input', () => { S.auth.basicPassword = el.basicPassword.value; saveRoute(); });
|
|
1672
|
+
el.apikeyName.addEventListener('input', () => { S.auth.apiKeyName = el.apikeyName.value; saveRoute(); });
|
|
1673
|
+
el.apikeyValue.addEventListener('input', () => { S.auth.apiKeyValue = el.apikeyValue.value; saveRoute(); });
|
|
1674
|
+
el.apikeyIn.addEventListener('change', () => { S.auth.apiKeyIn = el.apikeyIn.value; renderUrlBar(); saveRoute(); });
|
|
1612
1675
|
|
|
1613
1676
|
document.querySelectorAll('.body-type-btn').forEach(btn => {
|
|
1614
1677
|
btn.addEventListener('click', () => {
|
|
@@ -1618,13 +1681,15 @@ function bindEvents() {
|
|
|
1618
1681
|
el.bodyEditorWrap.classList.toggle('hidden', !show);
|
|
1619
1682
|
el.bodyNoneMsg.classList.toggle('hidden', show);
|
|
1620
1683
|
el.formatBtn.style.display = S.body.type === 'json' ? '' : 'none';
|
|
1684
|
+
saveRoute();
|
|
1621
1685
|
});
|
|
1622
1686
|
});
|
|
1623
|
-
el.bodyEditor.addEventListener('input', () => { S.body.content = el.bodyEditor.value; renderSummary(); });
|
|
1687
|
+
el.bodyEditor.addEventListener('input', () => { S.body.content = el.bodyEditor.value; renderSummary(); saveRoute(); });
|
|
1624
1688
|
el.formatBtn.addEventListener('click', () => {
|
|
1625
1689
|
try {
|
|
1626
1690
|
el.bodyEditor.value = JSON.stringify(JSON.parse(el.bodyEditor.value), null, 2);
|
|
1627
1691
|
S.body.content = el.bodyEditor.value;
|
|
1692
|
+
saveRoute();
|
|
1628
1693
|
} catch {
|
|
1629
1694
|
el.bodyEditor.style.borderColor = '#ef4444';
|
|
1630
1695
|
setTimeout(() => { el.bodyEditor.style.borderColor = ''; }, 800);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-explorer.html.js","sourceRoot":"","sources":["../src/api-explorer.html.ts"],"names":[],"mappings":";;AAEA,
|
|
1
|
+
{"version":3,"file":"api-explorer.html.js","sourceRoot":"","sources":["../src/api-explorer.html.ts"],"names":[],"mappings":";;AAEA,0CAsrDC;AAtrDD,SAAgB,eAAe,CAAC,OAAmC;IACjE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAChC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAE/C,OAAO,UAAU,CAAC;;;;;WAKT,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAi1BC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA21Bf,CAAC;AACT,CAAC"}
|
package/package.json
CHANGED