@vnphu/nestjs-api-explorer 0.1.0 → 0.2.0

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.
@@ -0,0 +1,234 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseDocsFile = parseDocsFile;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const KNOWN_TYPES = new Set(['string', 'number', 'boolean', 'array', 'object']);
40
+ /**
41
+ * Rule tokens are either:
42
+ * - bare keywords: required, isEmail, isUrl, isInt, isFloat, isDate,
43
+ * isBoolean, isString, isNumber, isArray, isObject, isUUID,
44
+ * isAlpha, isAlphanumeric, isNotEmpty
45
+ * - parameterized: minLength(n), maxLength(n), min(n), max(n),
46
+ * default(val), isIn(a,b,c), matches(regex)
47
+ */
48
+ const RULE_RE = /^(required|isEmail|isUrl|isInt|isFloat|isDate|isBoolean|isString|isNumber|isArray|isObject|isUUID|isAlpha|isAlphanumeric|isNotEmpty|minLength\([^)]+\)|maxLength\([^)]+\)|min\([^)]+\)|max\([^)]+\)|default\([^)]+\)|isIn\([^)]+\)|matches\([^)]+\))$/i;
49
+ /**
50
+ * Split a comma-separated string while respecting parentheses.
51
+ * e.g. "string, required, isIn(a,b,c), some description"
52
+ * → ["string", "required", "isIn(a,b,c)", "some description"]
53
+ */
54
+ function splitTokens(raw) {
55
+ const tokens = [];
56
+ let current = '';
57
+ let depth = 0;
58
+ for (const ch of raw) {
59
+ if (ch === '(') {
60
+ depth++;
61
+ current += ch;
62
+ }
63
+ else if (ch === ')') {
64
+ depth--;
65
+ current += ch;
66
+ }
67
+ else if (ch === ',' && depth === 0) {
68
+ tokens.push(current.trim());
69
+ current = '';
70
+ }
71
+ else {
72
+ current += ch;
73
+ }
74
+ }
75
+ if (current.trim())
76
+ tokens.push(current.trim());
77
+ return tokens.filter(Boolean);
78
+ }
79
+ /**
80
+ * Parse one field line into a DocField.
81
+ *
82
+ * Format: <name>: [type,] [rules...,] [description...]
83
+ *
84
+ * Examples:
85
+ * email: string, required, isEmail
86
+ * password: string, required, minLength(6), mật khẩu tối thiểu 6 ký tự
87
+ * role: string, isIn(admin,user,guest)
88
+ * page: number, default(1)
89
+ * tags: array
90
+ * meta: object
91
+ * Authorization: required, Bearer token
92
+ */
93
+ function parseField(line) {
94
+ const trimmed = line.trim();
95
+ if (!trimmed || !trimmed.includes(':'))
96
+ return null;
97
+ const colonIdx = trimmed.indexOf(':');
98
+ const name = trimmed.slice(0, colonIdx).trim();
99
+ const rest = trimmed.slice(colonIdx + 1).trim();
100
+ if (!name)
101
+ return null;
102
+ const tokens = splitTokens(rest);
103
+ let type = '';
104
+ let required = false;
105
+ const rules = [];
106
+ const descParts = [];
107
+ let isFirst = true;
108
+ for (const token of tokens) {
109
+ const t = token.trim();
110
+ if (!t)
111
+ continue;
112
+ // First token may be a type declaration
113
+ if (isFirst) {
114
+ isFirst = false;
115
+ if (KNOWN_TYPES.has(t.toLowerCase())) {
116
+ type = t.toLowerCase();
117
+ continue;
118
+ }
119
+ }
120
+ if (t.toLowerCase() === 'required') {
121
+ required = true;
122
+ }
123
+ else if (RULE_RE.test(t)) {
124
+ rules.push(t);
125
+ }
126
+ else {
127
+ descParts.push(t);
128
+ }
129
+ }
130
+ return {
131
+ name,
132
+ type,
133
+ required,
134
+ rules,
135
+ description: descParts.join(', '),
136
+ };
137
+ }
138
+ /**
139
+ * Parse a full docs file (absolute path) into a map of
140
+ * `"METHOD:path"` → RouteDoc.
141
+ */
142
+ function parseDocsFile(filePath) {
143
+ const map = new Map();
144
+ let raw;
145
+ try {
146
+ const resolved = path.isAbsolute(filePath)
147
+ ? filePath
148
+ : path.resolve(process.cwd(), filePath);
149
+ raw = fs.readFileSync(resolved, 'utf-8');
150
+ }
151
+ catch {
152
+ return map;
153
+ }
154
+ const lines = raw.split(/\r?\n/);
155
+ let currentGroup = '';
156
+ let currentRoute = null;
157
+ let currentSection = null;
158
+ const flush = () => {
159
+ if (!currentRoute)
160
+ return;
161
+ map.set(`${currentRoute.method}:${currentRoute.path}`, currentRoute);
162
+ currentRoute = null;
163
+ currentSection = null;
164
+ };
165
+ for (const rawLine of lines) {
166
+ // ── Group heading # Group Name ──────────────────────────────
167
+ if (/^#\s+/.test(rawLine) && !/^##\s+/.test(rawLine)) {
168
+ flush();
169
+ currentGroup = rawLine.replace(/^#\s+/, '').trim();
170
+ continue;
171
+ }
172
+ // ── Route heading ## METHOD /path ───────────────────────────
173
+ const routeMatch = rawLine.match(/^##\s+(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD)\s+(\/\S*)/i);
174
+ if (routeMatch) {
175
+ flush();
176
+ currentRoute = {
177
+ method: routeMatch[1].toUpperCase(),
178
+ path: routeMatch[2],
179
+ group: currentGroup,
180
+ description: '',
181
+ body: [],
182
+ query: [],
183
+ params: [],
184
+ headers: [],
185
+ response: [],
186
+ };
187
+ currentSection = null;
188
+ continue;
189
+ }
190
+ if (!currentRoute)
191
+ continue;
192
+ // ── Description lines > text ─────────────────────────────────
193
+ if (/^>\s*/.test(rawLine)) {
194
+ const desc = rawLine.replace(/^>\s*/, '').trim();
195
+ currentRoute.description = currentRoute.description
196
+ ? currentRoute.description + '\n' + desc
197
+ : desc;
198
+ continue;
199
+ }
200
+ // ── Section headers body: / query: / params: / headers: / response: ──
201
+ if (/^body:\s*$/.test(rawLine.trim())) {
202
+ currentSection = 'body';
203
+ continue;
204
+ }
205
+ if (/^query:\s*$/.test(rawLine.trim())) {
206
+ currentSection = 'query';
207
+ continue;
208
+ }
209
+ if (/^params:\s*$/.test(rawLine.trim())) {
210
+ currentSection = 'params';
211
+ continue;
212
+ }
213
+ if (/^headers:\s*$/.test(rawLine.trim())) {
214
+ currentSection = 'headers';
215
+ continue;
216
+ }
217
+ if (/^response:\s*$/.test(rawLine.trim())) {
218
+ currentSection = 'response';
219
+ continue;
220
+ }
221
+ // ── Separator / blank / comments — skip ──────────────────────
222
+ if (/^---/.test(rawLine.trim()) || rawLine.trim() === '')
223
+ continue;
224
+ // ── Field lines (indented or starts with content) ────────────
225
+ if (currentSection && rawLine.match(/^\s+\S/)) {
226
+ const field = parseField(rawLine);
227
+ if (field)
228
+ currentRoute[currentSection].push(field);
229
+ }
230
+ }
231
+ flush();
232
+ return map;
233
+ }
234
+ //# sourceMappingURL=api-docs-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-docs-parser.js","sourceRoot":"","sources":["../src/api-docs-parser.ts"],"names":[],"mappings":"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"}
@@ -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,CAsiC3E"}
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,CAmhD3E"}