@@ -123,6 +123,10 @@ List<RouteDirectory> _getRouteDirectories({
123
123
onEndpoint (endpoint, file);
124
124
}
125
125
126
+ if (directoryPath.isWildcard ()) {
127
+ throw ArgumentError ('Only files can be named with a wildcard alias.' );
128
+ }
129
+
126
130
directories.add (
127
131
RouteDirectory (
128
132
name: directoryPath.toAlias (),
@@ -191,11 +195,15 @@ List<RouteFile> _getRouteFiles({
191
195
192
196
final fileRoute = getFileRoute ();
193
197
final relativeFilePath = path.join ('..' , 'routes' , filePath);
198
+
199
+ final isWildcard = filePath.isWildcard ();
200
+
194
201
final route = RouteFile (
195
202
name: filePath.toAlias (),
196
203
path: relativeFilePath.replaceAll (r'\' , '/' ),
197
204
route: fileRoute.toRoute (),
198
205
params: fileRoute.toParams (),
206
+ wildcard: isWildcard,
199
207
);
200
208
onRoute (route);
201
209
files.add (route);
@@ -212,25 +220,44 @@ List<RouteFile> _getRouteFiles({
212
220
return files;
213
221
}
214
222
215
- extension on String {
223
+ /// Extension on [String] with helper methods regarding
224
+ /// Dart Frog routes.
225
+ extension RouteStringX on String {
226
+ /// Parses the stirng into a route alias.
216
227
String toAlias () {
217
228
final alias = path
218
229
.withoutExtension (this )
219
230
.replaceAll ('[' , r'$' )
220
231
.replaceAll (']' , '' )
221
- .replaceAll ('/' , '_' );
232
+ .replaceAll ('/' , '_' )
233
+ .replaceAll ('...' , 'wildcard_' );
222
234
if (alias == '' ) return 'index' ;
223
235
return alias;
224
236
}
225
237
238
+ /// Returns if this value matches a wildcard route.
239
+ bool isWildcard () {
240
+ final value = endsWith ('.dart' )
241
+ ? path.basenameWithoutExtension (this )
242
+ : path.basename (this );
243
+
244
+ return RegExp (r'\[\.\.\.(.*?)\]' ).hasMatch (value);
245
+ }
246
+
247
+ /// Parses the string into a route path.
226
248
String toRoute () {
249
+ if (isWildcard ()) return '/' ;
227
250
return replaceAll ('[' , '<' ).replaceAll (']' , '>' ).replaceAll (r'\' , '/' );
228
251
}
229
252
253
+ /// Parses the string into a list of route parameters.
230
254
List <String > toParams () {
231
255
final regexp = RegExp (r'\[(.*?)\]' );
232
256
final matches = regexp.allMatches (this );
233
- return matches.map ((m) => m[0 ]! .replaceAll (RegExp (r'\[|\]' ), '' )).toList ();
257
+ return matches.map ((m) {
258
+ final match = m[0 ]! ;
259
+ return match.replaceAll (RegExp (r'\[|\]' ), '' ).replaceFirst ('...' , '' );
260
+ }).toList ();
234
261
}
235
262
}
236
263
@@ -388,6 +415,7 @@ class RouteFile {
388
415
required this .path,
389
416
required this .route,
390
417
required this .params,
418
+ required this .wildcard,
391
419
});
392
420
393
421
/// The alias for the current file.
@@ -402,18 +430,23 @@ class RouteFile {
402
430
/// The dynamic route params associated with the file.
403
431
final List <String > params;
404
432
433
+ /// Whether the route is a wildcard route.
434
+ final bool wildcard;
435
+
405
436
/// Create a copy of the current instance and override zero or more values.
406
437
RouteFile copyWith ({
407
438
String ? name,
408
439
String ? path,
409
440
String ? route,
410
441
List <String >? params,
442
+ bool ? wildcard,
411
443
}) {
412
444
return RouteFile (
413
445
name: name ?? this .name,
414
446
path: path ?? this .path,
415
447
route: route ?? this .route,
416
448
params: params ?? this .params,
449
+ wildcard: wildcard ?? this .wildcard,
417
450
);
418
451
}
419
452
@@ -424,6 +457,7 @@ class RouteFile {
424
457
'path' : path,
425
458
'route' : route,
426
459
'file_params' : params,
460
+ 'wildcard' : wildcard,
427
461
};
428
462
}
429
463
}
0 commit comments