froggy-docs 1.1.1 → 1.1.4

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.
@@ -1,10 +1,24 @@
1
1
  import 'dart:io';
2
+ import 'dart:async';
2
3
  import 'package:watcher/watcher.dart';
3
4
  import 'package:path/path.dart' as p;
4
5
  import 'parser_engine.dart';
5
6
 
6
7
  class WatcherEngine {
7
- final ParserEngine _parser = ParserEngine();
8
+ final ParserEngine _parser;
9
+ Timer? _debounceTimer;
10
+ final Duration _debounceDuration;
11
+ final String? _ignorePattern;
12
+
13
+ WatcherEngine({
14
+ String outputPath = 'frontend/web/froggy_docs.json',
15
+ String ignorePattern = '',
16
+ Duration debounceDuration = const Duration(milliseconds: 300),
17
+ }) : _parser = ParserEngine(),
18
+ _debounceDuration = debounceDuration,
19
+ _ignorePattern = ignorePattern.isEmpty ? null : ignorePattern {
20
+ _parser.setOutputPath(outputPath);
21
+ }
8
22
 
9
23
  void startWatching(String directoryPath) {
10
24
  print('🚀 Initializing FroggyDocs scan...');
@@ -28,31 +42,49 @@ class WatcherEngine {
28
42
  }
29
43
  });
30
44
  } catch (e) {
31
- print('⚠️ Warning during initial scan: $e');
45
+ print('⚠️ Warning during initial scan: $e');
32
46
  }
33
47
  print('✅ Initial scan complete.\n');
34
48
  }
35
49
 
36
50
  bool _shouldIgnore(String path) {
37
51
  final normalizedPath = path.replaceAll('\\', '/');
38
- return normalizedPath.contains('/.dart_tool/') ||
52
+ if (normalizedPath.contains('/.dart_tool/') ||
39
53
  normalizedPath.contains('/frontend/') ||
40
54
  normalizedPath.contains('/node_modules/') ||
41
55
  normalizedPath.contains('/.git/') ||
42
56
  normalizedPath.endsWith('.json') ||
43
- normalizedPath.endsWith('.md');
57
+ normalizedPath.endsWith('.md')) {
58
+ return true;
59
+ }
60
+
61
+ if (_ignorePattern != null) {
62
+ final regexPattern = _ignorePattern
63
+ .replaceAll('.', r'\.')
64
+ .replaceAll('*', '.*')
65
+ .replaceAll('?', '.');
66
+ if (RegExp(regexPattern).hasMatch(normalizedPath)) {
67
+ return true;
68
+ }
69
+ }
70
+
71
+ return false;
44
72
  }
45
73
 
46
74
  void _handleFileChange(WatchEvent event) {
47
- switch (event.type) {
48
- case ChangeType.ADD:
49
- case ChangeType.MODIFY:
50
- _parser.parseFile(event.path);
51
- break;
52
- case ChangeType.REMOVE:
53
- print('🗑️ Removing documentation for: ${p.basename(event.path)}');
54
- _parser.removeFile(event.path);
55
- break;
56
- }
75
+ _debounceTimer?.cancel();
76
+
77
+ _debounceTimer = Timer(_debounceDuration, () {
78
+ switch (event.type) {
79
+ case ChangeType.ADD:
80
+ case ChangeType.MODIFY:
81
+ _parser.parseFile(event.path);
82
+ break;
83
+ case ChangeType.REMOVE:
84
+ print('🗑️ Removing documentation for: ${p.basename(event.path)}');
85
+ _parser.removeFile(event.path);
86
+ break;
87
+ }
88
+ });
57
89
  }
58
90
  }
@@ -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 (await file.existsSync()) {
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 (await file.existsSync()) {
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 (await indexFile.existsSync()) {
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,12 +164,21 @@ Router get _router {
154
164
  try {
155
165
  final targetUrl = '$_proxyUrl/api/$path';
156
166
  final method = request.method;
167
+ final contentType = request.headers['content-type'] ?? '';
157
168
 
158
169
  final client = http.Client();
159
170
  http.Request req;
160
171
 
161
172
  if (method == 'GET' || method == 'HEAD') {
162
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);
163
182
  } else {
164
183
  final body = await request.readAsString();
165
184
  req = http.Request(method, Uri.parse(targetUrl));
@@ -174,6 +193,10 @@ Router get _router {
174
193
  }
175
194
  });
176
195
 
196
+ if (contentType.contains('multipart/form-data')) {
197
+ req.headers['content-type'] = contentType;
198
+ }
199
+
177
200
  final streamedResponse = await client.send(req);
178
201
  final responseBody = await streamedResponse.stream.bytesToString();
179
202
 
@@ -195,14 +218,14 @@ Router get _router {
195
218
 
196
219
  router.get('/<path|[^/]+>', (Request request, String path) async {
197
220
  var file = File(p.join(deployDir, path));
198
- if (await file.existsSync()) {
221
+ if (file.existsSync()) {
199
222
  return Response.ok(
200
223
  file.openRead(),
201
224
  headers: {'Content-Type': _getContentType(path)},
202
225
  );
203
226
  }
204
227
  file = File(p.join(webDir, path));
205
- if (await file.existsSync()) {
228
+ if (file.existsSync()) {
206
229
  return Response.ok(
207
230
  file.openRead(),
208
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.1",
3
+ "version": "1.1.4",
4
4
  "description": "Auto-generate API documentation from code annotations. Works with any programming language.",
5
- "author": "Kaung Mrat Thu <kaungmyatthuu.dev@gmail.com>",
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": "./bin/froggy-docs"
22
+ "froggy-docs": "package.js"
23
23
  },
24
24
  "scripts": {},
25
25
  "engines": {
package/bin/froggy-docs DELETED
Binary file