froggy-docs 1.1.0 → 1.1.3
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/.claude/settings.local.json +21 -0
- package/.github/workflows/froggy-docs.yml +59 -0
- package/ABOUT.md +99 -0
- package/MILESTONE.md +29 -17
- package/bin/froggy_docs.dart +3 -45
- package/frontend/lib/app.dart +487 -280
- package/frontend/lib/components/file_field.dart +75 -0
- package/frontend/web/app.js +224 -67
- package/frontend/web/froggy_docs.json +288 -4
- package/lib/froggy_docs.dart +1 -0
- package/lib/src/cli_runner.dart +123 -0
- package/lib/src/parser_engine.dart +351 -22
- package/lib/src/watcher_engine.dart +46 -14
- package/lib/src/web_server.dart +57 -29
- package/package.js +0 -0
- package/package.json +4 -4
- package/bin/froggy-docs +0 -0
package/lib/src/web_server.dart
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import 'dart:io';
|
|
2
2
|
import 'dart:async';
|
|
3
3
|
import 'dart:convert';
|
|
4
|
+
import 'dart:typed_data';
|
|
4
5
|
import 'package:shelf/shelf.dart';
|
|
5
6
|
import 'package:shelf/shelf_io.dart' as shelf_io;
|
|
6
7
|
import 'package:shelf_router/shelf_router.dart';
|
|
@@ -47,14 +48,14 @@ Router get _router {
|
|
|
47
48
|
|
|
48
49
|
router.get('/froggy_docs.json', (Request request) async {
|
|
49
50
|
var file = File(p.join(userWebDir, 'froggy_docs.json'));
|
|
50
|
-
if (
|
|
51
|
+
if (file.existsSync()) {
|
|
51
52
|
return Response.ok(
|
|
52
53
|
file.openRead(),
|
|
53
54
|
headers: {'Content-Type': 'application/json'},
|
|
54
55
|
);
|
|
55
56
|
}
|
|
56
57
|
file = File(p.join(webDir, 'froggy_docs.json'));
|
|
57
|
-
if (
|
|
58
|
+
if (file.existsSync()) {
|
|
58
59
|
return Response.ok(
|
|
59
60
|
file.openRead(),
|
|
60
61
|
headers: {'Content-Type': 'application/json'},
|
|
@@ -65,7 +66,7 @@ Router get _router {
|
|
|
65
66
|
|
|
66
67
|
router.get('/', (Request request) async {
|
|
67
68
|
final indexFile = File(p.join(webDir, 'index.html'));
|
|
68
|
-
if (
|
|
69
|
+
if (indexFile.existsSync()) {
|
|
69
70
|
return Response.ok(
|
|
70
71
|
indexFile.openRead(),
|
|
71
72
|
headers: {'Content-Type': 'text/html'},
|
|
@@ -74,11 +75,6 @@ Router get _router {
|
|
|
74
75
|
return Response.notFound('index.html not found');
|
|
75
76
|
});
|
|
76
77
|
|
|
77
|
-
// ═════════════════════════════════════════════════════════════
|
|
78
|
-
// Demo/Mock API Endpoints
|
|
79
|
-
// These are included for testing "Try It Out" functionality
|
|
80
|
-
// Remove these routes in production - your real API will handle requests
|
|
81
|
-
// ═════════════════════════════════════════════════════════════
|
|
82
78
|
router.post('/api/simple', (Request request) async {
|
|
83
79
|
final body = await request.readAsString();
|
|
84
80
|
return Response.ok(
|
|
@@ -110,6 +106,27 @@ Router get _router {
|
|
|
110
106
|
);
|
|
111
107
|
});
|
|
112
108
|
|
|
109
|
+
router.post('/api/upload', (Request request) async {
|
|
110
|
+
final contentType = request.headers['content-type'] ?? '';
|
|
111
|
+
if (contentType.contains('multipart/form-data')) {
|
|
112
|
+
return Response.ok(
|
|
113
|
+
jsonEncode({
|
|
114
|
+
'status': 'success',
|
|
115
|
+
'message': 'File upload received (multipart/form-data)',
|
|
116
|
+
}),
|
|
117
|
+
headers: {'Content-Type': 'application/json'},
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
final body = await request.readAsString();
|
|
121
|
+
return Response.ok(
|
|
122
|
+
jsonEncode({
|
|
123
|
+
'status': 'success',
|
|
124
|
+
'received': body.isNotEmpty ? jsonDecode(body) : {},
|
|
125
|
+
}),
|
|
126
|
+
headers: {'Content-Type': 'application/json'},
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
|
|
113
130
|
router.get(
|
|
114
131
|
'/api/simple',
|
|
115
132
|
(Request request) => Response.ok(
|
|
@@ -139,13 +156,6 @@ Router get _router {
|
|
|
139
156
|
),
|
|
140
157
|
);
|
|
141
158
|
|
|
142
|
-
// ═════════════════════════════════════════════════════════════
|
|
143
|
-
// End of Demo/Mock API
|
|
144
|
-
// In production: Remove lines 66-124 or connect to your real API
|
|
145
|
-
// The "Try It Out" button will call your actual API endpoints
|
|
146
|
-
// ═══════════════════════════════════════════════════════════════
|
|
147
|
-
|
|
148
|
-
// Proxy API requests to backend server
|
|
149
159
|
router.all('/api/<path.*>', (Request request, String path) async {
|
|
150
160
|
if (_proxyUrl.isEmpty) {
|
|
151
161
|
return Response.notFound('{"error": "Proxy not configured. Use --proxy http://localhost:3000"');
|
|
@@ -154,29 +164,47 @@ Router get _router {
|
|
|
154
164
|
try {
|
|
155
165
|
final targetUrl = '$_proxyUrl/api/$path';
|
|
156
166
|
final method = request.method;
|
|
157
|
-
final
|
|
158
|
-
|
|
167
|
+
final contentType = request.headers['content-type'] ?? '';
|
|
168
|
+
|
|
169
|
+
final client = http.Client();
|
|
170
|
+
http.Request req;
|
|
171
|
+
|
|
172
|
+
if (method == 'GET' || method == 'HEAD') {
|
|
173
|
+
req = http.Request(method, Uri.parse(targetUrl));
|
|
174
|
+
} else if (contentType.contains('multipart/form-data')) {
|
|
175
|
+
// Read as bytes to preserve binary file data.
|
|
176
|
+
final chunks = <int>[];
|
|
177
|
+
await for (final chunk in request.read()) {
|
|
178
|
+
chunks.addAll(chunk);
|
|
179
|
+
}
|
|
180
|
+
req = http.Request(method, Uri.parse(targetUrl));
|
|
181
|
+
req.bodyBytes = Uint8List.fromList(chunks);
|
|
182
|
+
} else {
|
|
183
|
+
final body = await request.readAsString();
|
|
184
|
+
req = http.Request(method, Uri.parse(targetUrl));
|
|
185
|
+
if (body.isNotEmpty) {
|
|
186
|
+
req.body = body;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
159
190
|
request.headers.forEach((key, value) {
|
|
160
191
|
if (key.toLowerCase() != 'host') {
|
|
161
|
-
headers[key] = value;
|
|
192
|
+
req.headers[key] = value;
|
|
162
193
|
}
|
|
163
194
|
});
|
|
164
195
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
body = await request.readAsString();
|
|
196
|
+
if (contentType.contains('multipart/form-data')) {
|
|
197
|
+
req.headers['content-type'] = contentType;
|
|
168
198
|
}
|
|
169
199
|
|
|
170
|
-
final
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
final responseBody = await proxyResponse.stream.bytesToString();
|
|
200
|
+
final streamedResponse = await client.send(req);
|
|
201
|
+
final responseBody = await streamedResponse.stream.bytesToString();
|
|
174
202
|
|
|
175
203
|
return Response(
|
|
176
|
-
|
|
204
|
+
streamedResponse.statusCode,
|
|
177
205
|
body: responseBody,
|
|
178
206
|
headers: {
|
|
179
|
-
'Content-Type':
|
|
207
|
+
'Content-Type': streamedResponse.headers['content-type'] ?? 'application/json',
|
|
180
208
|
..._corsHeaders,
|
|
181
209
|
},
|
|
182
210
|
);
|
|
@@ -190,14 +218,14 @@ Router get _router {
|
|
|
190
218
|
|
|
191
219
|
router.get('/<path|[^/]+>', (Request request, String path) async {
|
|
192
220
|
var file = File(p.join(deployDir, path));
|
|
193
|
-
if (
|
|
221
|
+
if (file.existsSync()) {
|
|
194
222
|
return Response.ok(
|
|
195
223
|
file.openRead(),
|
|
196
224
|
headers: {'Content-Type': _getContentType(path)},
|
|
197
225
|
);
|
|
198
226
|
}
|
|
199
227
|
file = File(p.join(webDir, path));
|
|
200
|
-
if (
|
|
228
|
+
if (file.existsSync()) {
|
|
201
229
|
return Response.ok(
|
|
202
230
|
file.openRead(),
|
|
203
231
|
headers: {'Content-Type': _getContentType(path)},
|
package/package.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "froggy-docs",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Auto-generate API documentation from code annotations. Works with any programming language.",
|
|
5
|
-
"author": "Kaung Mrat Thu <
|
|
5
|
+
"author": "Kaung Mrat Thu <kaungmratthu.dev@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/Kaung-Myat/froggydocs",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "https://github.com/Kaung-Myat/froggydocs.git"
|
|
9
|
+
"url": "git+https://github.com/Kaung-Myat/froggydocs.git"
|
|
10
10
|
},
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"keywords": [
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"developer-tools"
|
|
20
20
|
],
|
|
21
21
|
"bin": {
|
|
22
|
-
"froggy-docs": "
|
|
22
|
+
"froggy-docs": "package.js"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {},
|
|
25
25
|
"engines": {
|
package/bin/froggy-docs
DELETED
|
Binary file
|