@@ -28,6 +28,7 @@ RouteConfiguration buildRouteConfiguration(Directory directory) {
28
28
if (globalMiddleware != null ) globalMiddleware
29
29
];
30
30
final routes = < RouteFile > [];
31
+ final rogueRoutes = < RouteFile > [];
31
32
final directories = _getRouteDirectories (
32
33
directory: routesDirectory,
33
34
routesDirectory: routesDirectory,
@@ -40,13 +41,15 @@ RouteConfiguration buildRouteConfiguration(Directory directory) {
40
41
endpoints[endpoint]! .add (file);
41
42
}
42
43
},
44
+ onRogueRoute: rogueRoutes.add,
43
45
);
44
46
final publicDirectory = Directory (path.join (directory.path, 'public' ));
45
47
return RouteConfiguration (
46
48
globalMiddleware: globalMiddleware,
47
49
middleware: middleware,
48
50
directories: directories,
49
51
routes: routes,
52
+ rogueRoutes: rogueRoutes,
50
53
endpoints: endpoints,
51
54
serveStaticFiles: publicDirectory.existsSync (),
52
55
);
@@ -58,6 +61,7 @@ List<RouteDirectory> _getRouteDirectories({
58
61
required void Function (RouteFile route) onRoute,
59
62
required void Function (MiddlewareFile route) onMiddleware,
60
63
required void Function (String endpoint, RouteFile file) onEndpoint,
64
+ required void Function (RouteFile route) onRogueRoute,
61
65
}) {
62
66
final directories = < RouteDirectory > [];
63
67
final entities = directory.listSync ().sorted ();
@@ -87,11 +91,13 @@ List<RouteDirectory> _getRouteDirectories({
87
91
directory: directory,
88
92
routesDirectory: routesDirectory,
89
93
onRoute: onRoute,
94
+ onRogueRoute: onRogueRoute,
90
95
),
91
96
..._getRouteFilesForDynamicDirectories (
92
97
directory: directory,
93
98
routesDirectory: routesDirectory,
94
99
onRoute: onRoute,
100
+ onRogueRoute: onRogueRoute,
95
101
),
96
102
];
97
103
@@ -123,6 +129,7 @@ List<RouteDirectory> _getRouteDirectories({
123
129
onRoute: onRoute,
124
130
onMiddleware: onMiddleware,
125
131
onEndpoint: onEndpoint,
132
+ onRogueRoute: onRogueRoute,
126
133
),
127
134
);
128
135
}
@@ -135,6 +142,7 @@ List<RouteFile> _getRouteFilesForDynamicDirectories({
135
142
required Directory directory,
136
143
required Directory routesDirectory,
137
144
required void Function (RouteFile route) onRoute,
145
+ required void Function (RouteFile route) onRogueRoute,
138
146
String prefix = '' ,
139
147
}) {
140
148
final files = < RouteFile > [];
@@ -149,12 +157,14 @@ List<RouteFile> _getRouteFilesForDynamicDirectories({
149
157
directory: dynamicDirectory,
150
158
routesDirectory: routesDirectory,
151
159
onRoute: onRoute,
160
+ onRogueRoute: onRogueRoute,
152
161
prefix: newPrefix,
153
162
);
154
163
final dynamicSubset = _getRouteFilesForDynamicDirectories (
155
164
directory: dynamicDirectory,
156
165
routesDirectory: routesDirectory,
157
166
onRoute: onRoute,
167
+ onRogueRoute: onRogueRoute,
158
168
prefix: newPrefix,
159
169
);
160
170
files.addAll ([...subset, ...dynamicSubset]);
@@ -166,6 +176,7 @@ List<RouteFile> _getRouteFiles({
166
176
required Directory directory,
167
177
required Directory routesDirectory,
168
178
required void Function (RouteFile route) onRoute,
179
+ required void Function (RouteFile route) onRogueRoute,
169
180
String prefix = '' ,
170
181
}) {
171
182
final files = < RouteFile > [];
@@ -175,6 +186,10 @@ List<RouteFile> _getRouteFiles({
175
186
? directorySegment
176
187
: '/$directorySegment ' ;
177
188
final entities = directory.listSync ().sorted ();
189
+ final subDirectories = entities
190
+ .whereType <Directory >()
191
+ .map ((directory) => path.basename (directory.path))
192
+ .toSet ();
178
193
entities.where ((e) => e.isRoute).cast <File >().forEach ((entity) {
179
194
final filePath = path
180
195
.relative (entity.path, from: routesDirectory.path)
@@ -209,6 +224,10 @@ List<RouteFile> _getRouteFiles({
209
224
);
210
225
onRoute (route);
211
226
files.add (route);
227
+
228
+ if (subDirectories.contains (path.basenameWithoutExtension (filePath))) {
229
+ onRogueRoute (route);
230
+ }
212
231
});
213
232
return files;
214
233
}
@@ -261,6 +280,7 @@ class RouteConfiguration {
261
280
required this .directories,
262
281
required this .routes,
263
282
required this .endpoints,
283
+ required this .rogueRoutes,
264
284
this .serveStaticFiles = false ,
265
285
});
266
286
@@ -283,6 +303,34 @@ class RouteConfiguration {
283
303
284
304
/// A map of all endpoint paths to resolved route files.
285
305
final Map <String , List <RouteFile >> endpoints;
306
+
307
+ /// List of all rogue routes.
308
+ ///
309
+ /// A route is considered rogue when it is defined outside
310
+ /// of an existing subdirectory with the same name.
311
+ ///
312
+ /// For example:
313
+ ///
314
+ /// ```
315
+ /// ├── routes
316
+ /// │ ├── foo
317
+ /// │ │ └── example.dart
318
+ /// │ ├── foo.dart
319
+ /// ```
320
+ ///
321
+ /// In the above scenario, `foo.dart` is rogue because it is defined
322
+ /// outside of the existing `foo` directory.
323
+ ///
324
+ /// Instead, `foo.dart` should be renamed to `index.dart` and placed within
325
+ /// the `foo` directory like:
326
+ ///
327
+ /// ```
328
+ /// ├── routes
329
+ /// │ ├── foo
330
+ /// │ │ ├── example.dart
331
+ /// │ │ └── index.dart
332
+ /// ```
333
+ final List <RouteFile > rogueRoutes;
286
334
}
287
335
288
336
/// {@template route_directory}
@@ -336,7 +384,7 @@ class RouteDirectory {
336
384
}
337
385
338
386
/// {@template route_file}
339
- /// A class containing metadata regarding a route directory .
387
+ /// A class containing metadata regarding a route file .
340
388
/// {@endtemplate}
341
389
class RouteFile {
342
390
/// {@macro route_file}
@@ -346,7 +394,7 @@ class RouteFile {
346
394
required this .route,
347
395
});
348
396
349
- /// The alias for the current directory .
397
+ /// The alias for the current file .
350
398
final String name;
351
399
352
400
/// The import path for the current instance.
0 commit comments