From 089a63b8d4cfb8bf354c5d521a04d74804a0570b Mon Sep 17 00:00:00 2001 From: Felix Angelov Date: Sun, 11 Sep 2022 16:26:50 -0500 Subject: [PATCH 1/6] fix: support mounting dynamic routes --- packages/dart_frog/lib/src/_internal.dart | 1 + packages/dart_frog/lib/src/router.dart | 130 ++++++++++-- packages/dart_frog/test/src/router_test.dart | 188 +++++++++++++++++- .../lib/src/build_route_configuration.dart | 82 ++------ 4 files changed, 306 insertions(+), 95 deletions(-) diff --git a/packages/dart_frog/lib/src/_internal.dart b/packages/dart_frog/lib/src/_internal.dart index 48978e27b..3e70aac3c 100644 --- a/packages/dart_frog/lib/src/_internal.dart +++ b/packages/dart_frog/lib/src/_internal.dart @@ -1,3 +1,4 @@ +import 'dart:collection'; import 'dart:convert'; import 'dart:io'; diff --git a/packages/dart_frog/lib/src/router.dart b/packages/dart_frog/lib/src/router.dart index 3234347ef..d120ef91a 100644 --- a/packages/dart_frog/lib/src/router.dart +++ b/packages/dart_frog/lib/src/router.dart @@ -39,6 +39,13 @@ class Router { Router({Handler notFoundHandler = _defaultNotFound}) : _notFoundHandler = notFoundHandler; + /// Name of the parameter used for matching + /// the rest of the path in a mounted route. + /// + /// Two underscore prefix to avoid conflicts + /// with user-defined path parameters. + static const _kMountedPathParamRest = '__path'; + final List _routes = []; final Handler _notFoundHandler; @@ -65,37 +72,83 @@ class Router { /// Handle all request to [route] using [handler]. void all(String route, Function handler) { - _routes.add(RouterEntry('ALL', route, handler)); + _all(route, handler, mounted: false); + } + + void _all(String route, Function handler, {required bool mounted}) { + _routes.add(RouterEntry('ALL', route, handler, mounted: mounted)); } /// Mount a handler below a prefix. - /// - /// In this case prefix may not contain any parameters, nor - void mount(String prefix, Handler handler) { + void mount(String prefix, Function handler) { if (!prefix.startsWith('/')) { throw ArgumentError.value(prefix, 'prefix', 'must start with a slash'); } - // The first slash is always in request.handlerPath - final path = prefix.substring(1); if (prefix.endsWith('/')) { - all('$prefix', (RequestContext context) { - return handler( - RequestContext._(context.request._request.change(path: path)), - ); - }); + _all( + '$prefix<$_kMountedPathParamRest|[^]*>', + (RequestContext context, List params) { + return _invokeMountedHandler( + context, + handler, + // Remove path param from extracted route params + [...params]..removeLast(), + ); + }, + mounted: true, + ); + } else { + _all( + prefix, + (RequestContext context, List params) { + return _invokeMountedHandler(context, handler, params); + }, + mounted: true, + ); + _all( + '$prefix/<$_kMountedPathParamRest|[^]*>', + (RequestContext context, List params) { + return _invokeMountedHandler( + context, + handler, + // Remove path param from extracted route params + [...params]..removeLast(), + ); + }, + mounted: true, + ); + } + } + + Future _invokeMountedHandler( + RequestContext context, + Function handler, + List pathParams, + ) async { + final request = context.request; + final params = request._request.params; + final pathParamSegment = params[_kMountedPathParamRest]; + final urlPath = request.url.path; + late final String effectivePath; + if (pathParamSegment != null && pathParamSegment.isNotEmpty) { + /// If we encounter the `_kMountedPathParamRest` parameter we remove it + /// from the request path that shelf will handle. + effectivePath = urlPath.substring( + 0, + urlPath.length - pathParamSegment.length, + ); } else { - all(prefix, (RequestContext context) { - return handler( - RequestContext._(context.request._request.change(path: path)), - ); - }); - all('$prefix/', (RequestContext context) { - return handler( - RequestContext._(context.request._request.change(path: '$path/')), - ); - }); + effectivePath = urlPath; } + final modifiedRequestContext = RequestContext._( + request._request.change(path: effectivePath), + ); + + return await Function.apply(handler, [ + modifiedRequestContext, + ...pathParams.map((param) => params[param]), + ]) as Response; } /// Route incoming requests to registered handlers. @@ -196,6 +249,7 @@ class RouterEntry { String route, Function handler, { Middleware? middleware, + bool mounted = false, }) { middleware = middleware ?? ((Handler fn) => fn); @@ -233,6 +287,7 @@ class RouterEntry { middleware, routePattern, params, + mounted, ); } @@ -243,6 +298,7 @@ class RouterEntry { this._middleware, this._routePattern, this._params, + this._mounted, ); /// Pattern for parsing the route pattern @@ -253,14 +309,19 @@ class RouterEntry { final Function _handler; final Middleware _middleware; + /// Indicates this entry is used as a mounting point. + final bool _mounted; + /// Expression that the request path must match. /// /// This also captures any parameters in the route pattern. final RegExp _routePattern; - /// Names for the parameters in the route pattern. final List _params; + /// Names for the parameters in the route pattern. + List get params => _params.toList(); + /// Returns a map from parameter name to value, if the path matches the /// route pattern. Otherwise returns null. Map? match(String path) { @@ -287,6 +348,13 @@ class RouterEntry { final _context = RequestContext._(request); return await _middleware((request) async { + if (_mounted) { + // if this route is mounted, we include + // the route entry params so that the mount can extract the parameters/ + // ignore: avoid_dynamic_calls + return await _handler(_context, this.params) as Response; + } + if (_handler is Handler || _params.isEmpty) { // ignore: avoid_dynamic_calls return await _handler(_context) as Response; @@ -300,3 +368,21 @@ class RouterEntry { })(_context); } } + +final _emptyParams = UnmodifiableMapView({}); + +/// Extension on [shelf.Request] which provides access to +/// URL parameters captured by the [Router]. +extension RouterParams on shelf.Request { + /// Get URL parameters captured by the [Router]. + /// If no parameters are captured this returns an empty map. + /// + /// The returned map is unmodifiable. + Map get params { + final p = context['shelf_router/params']; + if (p is Map) { + return UnmodifiableMapView(p); + } + return _emptyParams; + } +} diff --git a/packages/dart_frog/test/src/router_test.dart b/packages/dart_frog/test/src/router_test.dart index cfeb1e5cc..a556e46ea 100644 --- a/packages/dart_frog/test/src/router_test.dart +++ b/packages/dart_frog/test/src/router_test.dart @@ -27,6 +27,8 @@ import 'package:test/test.dart'; class _MockRequestContext extends Mock implements RequestContext {} +class _MockShelfRequest extends Mock implements shelf.Request {} + void main() { // Create a server that listens on localhost for testing late io.IOServer server; @@ -441,6 +443,166 @@ void main() { expect(response.body(), completion(equals('Route not found'))); }); + test('can mount route without params', () async { + final context = _MockRequestContext(); + final app = Router()..mount('/', (RequestContext context) => Response()); + + server.mount((request) async { + when(() => context.request).thenReturn( + Request(request.method, request.requestedUri), + ); + final response = await app.call(context); + final body = await response.body(); + return shelf.Response(response.statusCode, body: body); + }); + + final response = await http.get(Uri.parse('${server.url}/')); + expect(response.body, isEmpty); + expect(response.statusCode, equals(HttpStatus.ok)); + }); + + test('can mount dynamic routes', () async { + final context = _MockRequestContext(); + + // Routes for to . + // This gets nested parameters from previous mounts. + Handler createUserToOtherHandler(String user, String other) { + final router = Router() + ..get('/', (RequestContext context, String action) { + return Response(body: '$user to $other: $action'); + }); + + return router; + } + + // Routes for a specific . + // The user value is extracted from the mount. + Handler createUserHandler(String user) { + final router = Router() + ..mount('/to//', (RequestContext context, String other) { + final handler = createUserToOtherHandler(user, other); + return handler(context); + }) + ..get('/self', (RequestContext context) { + return Response(body: "I'm $user"); + }) + ..get('/', (RequestContext context) { + return Response(body: '$user root'); + }); + return router; + } + + final app = Router() + ..get('/hello', (RequestContext context) { + return Response(body: 'hello-world'); + }) + ..mount('/users/', (RequestContext context, String user) { + final handler = createUserHandler(user); + return handler(context); + }) + ..all('/<_|[^]*>', (RequestContext context) { + return Response(body: 'catch-all-handler'); + }); + + server.mount((request) async { + when(() => context.request).thenReturn( + Request(request.method, request.requestedUri), + ); + final response = await app.call(context); + final body = await response.body(); + return shelf.Response(response.statusCode, body: body); + }); + + final helloResponse = await http.get(Uri.parse('${server.url}/hello')); + expect(helloResponse.body, equals('hello-world')); + + final greetingResponse = await http.get( + Uri.parse('${server.url}/users/dartfrog/to/dash/hi'), + ); + expect(greetingResponse.body, equals('dartfrog to dash: hi')); + + final farewellResponse = await http.get( + Uri.parse('${server.url}/users/dash/to/dartfrog/bye'), + ); + expect(farewellResponse.body, equals('dash to dartfrog: bye')); + + final introResponse = await http.get( + Uri.parse('${server.url}/users/dash/self'), + ); + expect(introResponse.body, equals("I'm dash")); + + final rootResponse = await http.get( + Uri.parse('${server.url}/users/dartfrog'), + ); + expect(rootResponse.body, equals('dartfrog root')); + + final catchAllResponse = await http.get( + Uri.parse('${server.url}/users/dartfrog/no-route'), + ); + expect(catchAllResponse.body, equals('catch-all-handler')); + }); + + test('can mount dynamic routes with multiple parameters', () async { + final context = _MockRequestContext(); + final app = Router() + ..mount(r'/first//third//last', ( + RequestContext context, + String second, + String fourthNum, + ) { + final router = Router() + ..get('/', (r) => Response(body: '$second ${int.parse(fourthNum)}')); + return router(context); + }); + + server.mount((request) async { + when(() => context.request).thenReturn( + Request(request.method, request.requestedUri), + ); + final response = await app.call(context); + final body = await response.body(); + return shelf.Response(response.statusCode, body: body); + }); + + final response = await http.get( + Uri.parse('${server.url}/first/hello/third/42/last'), + ); + expect(response.body, equals('hello 42')); + }); + + test('can mount dynamic routes with regexp', () async { + final context = _MockRequestContext(); + final app = Router() + ..mount(r'/before//after', + (RequestContext context, String bookId) { + final router = Router() + ..get('/', (r) => Response(body: 'book ${int.parse(bookId)}')); + return router(context); + }) + ..all('/<_|[^]*>', (RequestContext context) { + return Response(body: 'catch-all-handler'); + }); + + server.mount((request) async { + when(() => context.request).thenReturn( + Request(request.method, request.requestedUri), + ); + final response = await app.call(context); + final body = await response.body(); + return shelf.Response(response.statusCode, body: body); + }); + + final bookResponse = await http.get( + Uri.parse('${server.url}/before/42/after'), + ); + expect(bookResponse.body, equals('book 42')); + + final catchAllResponse = await http.get( + Uri.parse('${server.url}/before/abc/after'), + ); + expect(catchAllResponse.body, equals('catch-all-handler')); + }); + group('RouterEntry', () { void testPattern( String pattern, { @@ -464,13 +626,8 @@ void main() { testPattern( '/hello', - match: { - '/hello': {}, - }, - notMatch: [ - '/not-hello', - '/', - ], + match: {'/hello': {}}, + notMatch: ['/not-hello', '/'], ); testPattern( @@ -507,4 +664,21 @@ void main() { ); }); }); + + group('RouterParams', () { + test('returns empty params when none are found', () async { + final request = _MockShelfRequest(); + when(() => request.context).thenReturn({}); + + expect(request.params, isEmpty); + }); + + test('returns params when they are found', () async { + const params = {'foo': 'bar'}; + final request = _MockShelfRequest(); + when(() => request.context).thenReturn({'shelf_router/params': params}); + + expect(request.params, equals(params)); + }); + }); } diff --git a/packages/dart_frog_gen/lib/src/build_route_configuration.dart b/packages/dart_frog_gen/lib/src/build_route_configuration.dart index 1c07d08c6..48639076e 100644 --- a/packages/dart_frog_gen/lib/src/build_route_configuration.dart +++ b/packages/dart_frog_gen/lib/src/build_route_configuration.dart @@ -88,20 +88,12 @@ List _getRouteDirectories({ } } - final files = [ - ..._getRouteFiles( - directory: directory, - routesDirectory: routesDirectory, - onRoute: onRoute, - onRogueRoute: onRogueRoute, - ), - ..._getRouteFilesForDynamicDirectories( - directory: directory, - routesDirectory: routesDirectory, - onRoute: onRoute, - onRogueRoute: onRogueRoute, - ), - ]; + final files = _getRouteFiles( + directory: directory, + routesDirectory: routesDirectory, + onRoute: onRoute, + onRogueRoute: onRogueRoute, + ); final baseRoute = directoryPath.toRoute(); for (final file in files) { @@ -123,57 +115,21 @@ List _getRouteDirectories({ ); entities.whereType().forEach((directory) { - if (!directory.isDynamicRoute) { - directories.addAll( - _getRouteDirectories( - directory: directory, - routesDirectory: routesDirectory, - onRoute: onRoute, - onMiddleware: onMiddleware, - onEndpoint: onEndpoint, - onRogueRoute: onRogueRoute, - ), - ); - } + directories.addAll( + _getRouteDirectories( + directory: directory, + routesDirectory: routesDirectory, + onRoute: onRoute, + onMiddleware: onMiddleware, + onEndpoint: onEndpoint, + onRogueRoute: onRogueRoute, + ), + ); }); return directories; } -List _getRouteFilesForDynamicDirectories({ - required Directory directory, - required Directory routesDirectory, - required void Function(RouteFile route) onRoute, - required void Function(RouteFile route) onRogueRoute, - String prefix = '', -}) { - final files = []; - directory - .listSync() - .sorted() - .whereType() - .where((d) => prefix.isNotEmpty || d.isDynamicRoute) - .forEach((dynamicDirectory) { - final newPrefix = '$prefix/${path.basename(dynamicDirectory.path)}'; - final subset = _getRouteFiles( - directory: dynamicDirectory, - routesDirectory: routesDirectory, - onRoute: onRoute, - onRogueRoute: onRogueRoute, - prefix: newPrefix, - ); - final dynamicSubset = _getRouteFilesForDynamicDirectories( - directory: dynamicDirectory, - routesDirectory: routesDirectory, - onRoute: onRoute, - onRogueRoute: onRogueRoute, - prefix: newPrefix, - ); - files.addAll([...subset, ...dynamicSubset]); - }); - return files; -} - List _getRouteFiles({ required Directory directory, required Directory routesDirectory, @@ -261,12 +217,6 @@ extension on List { } } -extension on Directory { - bool get isDynamicRoute { - return RegExp(r'\[(.*)\]').hasMatch(path.basename(this.path)); - } -} - extension on FileSystemEntity { bool get isRoute { return this is File && From 38fc724fd5153fe83f668890f8187605af6bc1c9 Mon Sep 17 00:00:00 2001 From: Felix Angelov Date: Mon, 3 Oct 2022 16:53:11 -0500 Subject: [PATCH 2/6] test(dart_frog_gen): update buildRouteConfiguration tests --- .../src/build_route_configuration_test.dart | 92 +++++++++++++++++-- 1 file changed, 85 insertions(+), 7 deletions(-) diff --git a/packages/dart_frog_gen/test/src/build_route_configuration_test.dart b/packages/dart_frog_gen/test/src/build_route_configuration_test.dart index 01badc277..72f52cf19 100644 --- a/packages/dart_frog_gen/test/src/build_route_configuration_test.dart +++ b/packages/dart_frog_gen/test/src/build_route_configuration_test.dart @@ -365,15 +365,29 @@ void main() { 'middleware': false, 'files': [ {'name': 'index', 'path': '../routes/index.dart', 'route': '/'}, + ] + }, + { + 'name': r'_$user', + 'route': '/', + 'middleware': false, + 'files': [ { 'name': r'$user_$name', 'path': '../routes/[user]/[name].dart', - 'route': '//' - }, + 'route': '/' + } + ] + }, + { + 'name': r'_$user_$id', + 'route': '//', + 'middleware': false, + 'files': [ { 'name': r'$user_$id_index', 'path': '../routes/[user]/[id]/index.dart', - 'route': '//' + 'route': '/' } ] } @@ -436,10 +450,23 @@ void main() { 'middleware': false, 'files': [ {'name': 'index', 'path': '../routes/index.dart', 'route': '/'}, + ] + }, + { + 'name': r'_$id', + 'route': '/', + 'middleware': false, + 'files': >[] + }, + { + 'name': r'_$id_api', + 'route': '//api', + 'middleware': false, + 'files': [ { 'name': r'$id_api_index', 'path': '../routes/[id]/api/index.dart', - 'route': '//api' + 'route': '/' } ] } @@ -494,10 +521,23 @@ void main() { 'middleware': false, 'files': [ {'name': 'index', 'path': '../routes/index.dart', 'route': '/'}, + ] + }, + { + 'name': r'_$id', + 'route': '/', + 'middleware': false, + 'files': >[] + }, + { + 'name': r'_$id_api', + 'route': '//api', + 'middleware': false, + 'files': [ { 'name': r'$id_api_test', 'path': '../routes/[id]/api/test.dart', - 'route': '//api/test' + 'route': '/test' } ] } @@ -552,10 +592,29 @@ void main() { 'middleware': false, 'files': [ {'name': 'index', 'path': '../routes/index.dart', 'route': '/'}, + ] + }, + { + 'name': r'_$id', + 'route': '/', + 'middleware': false, + 'files': >[] + }, + { + 'name': r'_$id_api', + 'route': '//api', + 'middleware': false, + 'files': >[] + }, + { + 'name': r'_$id_api_$name', + 'route': '//api/', + 'middleware': false, + 'files': [ { 'name': r'$id_api_$name_index', 'path': '../routes/[id]/api/[name]/index.dart', - 'route': '//api/' + 'route': '/' } ] } @@ -612,10 +671,29 @@ void main() { 'middleware': false, 'files': [ {'name': 'index', 'path': '../routes/index.dart', 'route': '/'}, + ] + }, + { + 'name': r'_$id', + 'route': '/', + 'middleware': false, + 'files': >[] + }, + { + 'name': r'_$id_api', + 'route': '//api', + 'middleware': false, + 'files': >[] + }, + { + 'name': r'_$id_api_$name', + 'route': '//api/', + 'middleware': false, + 'files': [ { 'name': r'$id_api_$name_test', 'path': '../routes/[id]/api/[name]/test.dart', - 'route': '//api//test' + 'route': '/test' } ] } From 553ee7d784c889067956f6ea0f602f8ad1ed84d0 Mon Sep 17 00:00:00 2001 From: Felix Angelov Date: Mon, 3 Oct 2022 16:58:46 -0500 Subject: [PATCH 3/6] chore: remove dead code --- .../dart_frog_gen/lib/src/build_route_configuration.dart | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/dart_frog_gen/lib/src/build_route_configuration.dart b/packages/dart_frog_gen/lib/src/build_route_configuration.dart index 48639076e..292835916 100644 --- a/packages/dart_frog_gen/lib/src/build_route_configuration.dart +++ b/packages/dart_frog_gen/lib/src/build_route_configuration.dart @@ -163,12 +163,7 @@ List _getRouteFiles({ var fileRoute = fileRoutePath.isEmpty ? '/' : fileRoutePath; fileRoute = prefix + fileRoute; - if (!fileRoute.startsWith('/')) { - fileRoute = '/$fileRoute'; - } - if (fileRoute != '/' && fileRoute.endsWith('/')) { - fileRoute = fileRoute.substring(0, fileRoute.length - 1); - } + if (!fileRoute.startsWith('/')) fileRoute = '/$fileRoute'; return fileRoute; } From b5b18d7dcd5029eb1dee3729614449921cb06a04 Mon Sep 17 00:00:00 2001 From: Felix Angelov Date: Mon, 10 Oct 2022 16:02:59 -0500 Subject: [PATCH 4/6] feat(dart_frog_gen): RouteDirectory and RouteFile include params --- .../lib/src/build_route_configuration.dart | 28 +- .../src/build_route_configuration_test.dart | 239 +++++++++++++----- .../test/src/route_directory_test.dart | 25 +- .../test/src/route_file_test.dart | 31 ++- 4 files changed, 254 insertions(+), 69 deletions(-) diff --git a/packages/dart_frog_gen/lib/src/build_route_configuration.dart b/packages/dart_frog_gen/lib/src/build_route_configuration.dart index 292835916..271f788a2 100644 --- a/packages/dart_frog_gen/lib/src/build_route_configuration.dart +++ b/packages/dart_frog_gen/lib/src/build_route_configuration.dart @@ -111,6 +111,7 @@ List _getRouteDirectories({ route: baseRoute, middleware: middleware, files: files, + params: directoryPath.toParams(), ), ); @@ -174,6 +175,7 @@ List _getRouteFiles({ name: filePath.toAlias(), path: relativeFilePath.replaceAll(r'\', '/'), route: fileRoute.toRoute(), + params: fileRoute.toParams(), ); onRoute(route); files.add(route); @@ -204,6 +206,12 @@ extension on String { String toRoute() { return replaceAll('[', '<').replaceAll(']', '>').replaceAll(r'\', '/'); } + + List toParams() { + final regexp = RegExp(r'\[(.*?)\]'); + final matches = regexp.allMatches(this); + return matches.map((m) => m[0]!.replaceAll(RegExp(r'\[|\]'), '')).toList(); + } } extension on List { @@ -299,6 +307,7 @@ class RouteDirectory { required this.route, required this.middleware, required this.files, + required this.params, }); /// The alias for the current directory. @@ -307,6 +316,9 @@ class RouteDirectory { /// The route which will be used to mount routers. final String route; + /// The dynamic route params associated with the directory. + final List params; + /// Optional middleware for the provided router. final MiddlewareFile? middleware; @@ -319,12 +331,14 @@ class RouteDirectory { String? route, MiddlewareFile? middleware, List? files, + List? params, }) { return RouteDirectory( name: name ?? this.name, route: route ?? this.route, middleware: middleware ?? this.middleware, files: files ?? this.files, + params: params ?? this.params, ); } @@ -335,6 +349,7 @@ class RouteDirectory { 'route': route, 'middleware': middleware?.toJson() ?? false, 'files': files.map((f) => f.toJson()).toList(), + 'params': params, }; } } @@ -348,6 +363,7 @@ class RouteFile { required this.name, required this.path, required this.route, + required this.params, }); /// The alias for the current file. @@ -359,12 +375,21 @@ class RouteFile { /// The route used by router instances. final String route; + /// The dynamic route params associated with the file. + final List params; + /// Create a copy of the current instance and override zero or more values. - RouteFile copyWith({String? name, String? path, String? route}) { + RouteFile copyWith({ + String? name, + String? path, + String? route, + List? params, + }) { return RouteFile( name: name ?? this.name, path: path ?? this.path, route: route ?? this.route, + params: params ?? this.params, ); } @@ -374,6 +399,7 @@ class RouteFile { 'name': name, 'path': path, 'route': route, + 'params': params, }; } } diff --git a/packages/dart_frog_gen/test/src/build_route_configuration_test.dart b/packages/dart_frog_gen/test/src/build_route_configuration_test.dart index 72f52cf19..fdbaf45a4 100644 --- a/packages/dart_frog_gen/test/src/build_route_configuration_test.dart +++ b/packages/dart_frog_gen/test/src/build_route_configuration_test.dart @@ -106,8 +106,14 @@ void main() { 'route': '/', 'middleware': false, 'files': [ - {'name': 'index', 'path': '../routes/index.dart', 'route': '/'} - ] + { + 'name': 'index', + 'path': '../routes/index.dart', + 'route': '/', + 'params': [], + } + ], + 'params': [], } ]; final directory = Directory( @@ -142,9 +148,20 @@ void main() { 'route': '/', 'middleware': false, 'files': [ - {'name': 'index', 'path': '../routes/index.dart', 'route': '/'}, - {'name': 'hello', 'path': '../routes/hello.dart', 'route': '/hello'} - ] + { + 'name': 'index', + 'path': '../routes/index.dart', + 'route': '/', + 'params': [], + }, + { + 'name': 'hello', + 'path': '../routes/hello.dart', + 'route': '/hello', + 'params': [], + } + ], + 'params': [], } ]; final directory = Directory( @@ -192,8 +209,14 @@ void main() { 'route': '/', 'middleware': false, 'files': [ - {'name': 'index', 'path': '../routes/index.dart', 'route': '/'} - ] + { + 'name': 'index', + 'path': '../routes/index.dart', + 'route': '/', + 'params': [], + } + ], + 'params': [], }, { 'name': '_echo', @@ -203,9 +226,11 @@ void main() { { 'name': 'echo_message', 'path': '../routes/echo/message.dart', - 'route': '/message' + 'route': '/message', + 'params': [], } - ] + ], + 'params': [], } ]; final directory = Directory( @@ -245,12 +270,19 @@ void main() { test('includes nested directories', () { const expected = [ - {'name': '_', 'route': '/', 'middleware': false, 'files': []}, + { + 'name': '_', + 'route': '/', + 'middleware': false, + 'files': [], + 'params': [], + }, { 'name': '_echo', 'route': '/echo', 'middleware': false, - 'files': [] + 'files': [], + 'params': [], }, { 'name': '_echo_message', @@ -260,9 +292,11 @@ void main() { { 'name': 'echo_message_index', 'path': '../routes/echo/message/index.dart', - 'route': '/' + 'route': '/', + 'params': [], } - ] + ], + 'params': [], } ]; final directory = Directory( @@ -306,8 +340,14 @@ void main() { 'route': '/', 'middleware': false, 'files': [ - {'name': 'index', 'path': '../routes/index.dart', 'route': '/'} - ] + { + 'name': 'index', + 'path': '../routes/index.dart', + 'route': '/', + 'params': [], + } + ], + 'params': [], }, { 'name': '_echo', @@ -317,9 +357,11 @@ void main() { { 'name': r'echo_$message', 'path': '../routes/echo/[message].dart', - 'route': '/' + 'route': '/', + 'params': ['message'], } - ] + ], + 'params': [], } ]; final directory = Directory( @@ -364,8 +406,14 @@ void main() { 'route': '/', 'middleware': false, 'files': [ - {'name': 'index', 'path': '../routes/index.dart', 'route': '/'}, - ] + { + 'name': 'index', + 'path': '../routes/index.dart', + 'route': '/', + 'params': [], + }, + ], + 'params': [], }, { 'name': r'_$user', @@ -375,9 +423,11 @@ void main() { { 'name': r'$user_$name', 'path': '../routes/[user]/[name].dart', - 'route': '/' + 'route': '/', + 'params': ['name'], } - ] + ], + 'params': ['user'], }, { 'name': r'_$user_$id', @@ -387,9 +437,11 @@ void main() { { 'name': r'$user_$id_index', 'path': '../routes/[user]/[id]/index.dart', - 'route': '/' + 'route': '/', + 'params': [], } - ] + ], + 'params': ['user', 'id'], } ]; final directory = Directory( @@ -449,14 +501,21 @@ void main() { 'route': '/', 'middleware': false, 'files': [ - {'name': 'index', 'path': '../routes/index.dart', 'route': '/'}, - ] + { + 'name': 'index', + 'path': '../routes/index.dart', + 'route': '/', + 'params': [], + }, + ], + 'params': [], }, { 'name': r'_$id', 'route': '/', 'middleware': false, - 'files': >[] + 'files': >[], + 'params': ['id'], }, { 'name': r'_$id_api', @@ -466,9 +525,11 @@ void main() { { 'name': r'$id_api_index', 'path': '../routes/[id]/api/index.dart', - 'route': '/' + 'route': '/', + 'params': [], } - ] + ], + 'params': ['id'], } ]; final directory = Directory( @@ -520,14 +581,21 @@ void main() { 'route': '/', 'middleware': false, 'files': [ - {'name': 'index', 'path': '../routes/index.dart', 'route': '/'}, - ] + { + 'name': 'index', + 'path': '../routes/index.dart', + 'route': '/', + 'params': [], + }, + ], + 'params': [], }, { 'name': r'_$id', 'route': '/', 'middleware': false, - 'files': >[] + 'files': >[], + 'params': ['id'], }, { 'name': r'_$id_api', @@ -537,9 +605,11 @@ void main() { { 'name': r'$id_api_test', 'path': '../routes/[id]/api/test.dart', - 'route': '/test' + 'route': '/test', + 'params': [], } - ] + ], + 'params': ['id'], } ]; final directory = Directory( @@ -591,20 +661,28 @@ void main() { 'route': '/', 'middleware': false, 'files': [ - {'name': 'index', 'path': '../routes/index.dart', 'route': '/'}, - ] + { + 'name': 'index', + 'path': '../routes/index.dart', + 'route': '/', + 'params': [], + }, + ], + 'params': [], }, { 'name': r'_$id', 'route': '/', 'middleware': false, - 'files': >[] + 'files': >[], + 'params': ['id'], }, { 'name': r'_$id_api', 'route': '//api', 'middleware': false, - 'files': >[] + 'files': >[], + 'params': ['id'], }, { 'name': r'_$id_api_$name', @@ -614,9 +692,11 @@ void main() { { 'name': r'$id_api_$name_index', 'path': '../routes/[id]/api/[name]/index.dart', - 'route': '/' + 'route': '/', + 'params': [], } - ] + ], + 'params': ['id', 'name'], } ]; final directory = Directory( @@ -670,20 +750,28 @@ void main() { 'route': '/', 'middleware': false, 'files': [ - {'name': 'index', 'path': '../routes/index.dart', 'route': '/'}, - ] + { + 'name': 'index', + 'path': '../routes/index.dart', + 'route': '/', + 'params': [], + }, + ], + 'params': [], }, { 'name': r'_$id', 'route': '/', 'middleware': false, - 'files': >[] + 'files': >[], + 'params': ['id'], }, { 'name': r'_$id_api', 'route': '//api', 'middleware': false, - 'files': >[] + 'files': >[], + 'params': ['id'], }, { 'name': r'_$id_api_$name', @@ -693,9 +781,11 @@ void main() { { 'name': r'$id_api_$name_test', 'path': '../routes/[id]/api/[name]/test.dart', - 'route': '/test' + 'route': '/test', + 'params': [], } - ] + ], + 'params': ['id', 'name'], } ]; final directory = Directory( @@ -744,7 +834,13 @@ void main() { test('supports /api/api.dart', () { const expected = [ - {'name': '_', 'route': '/', 'middleware': false, 'files': []}, + { + 'name': '_', + 'route': '/', + 'middleware': false, + 'files': [], + 'params': [], + }, { 'name': '_api', 'route': '/api', @@ -753,9 +849,11 @@ void main() { { 'name': 'api_api', 'path': '../routes/api/api.dart', - 'route': '/api' + 'route': '/api', + 'params': [], } - ] + ], + 'params': [], } ]; final directory = Directory( @@ -797,21 +895,34 @@ void main() { 'route': '/', 'middleware': false, 'files': [ - {'name': 'api', 'path': '../routes/api.dart', 'route': '/api'} - ] + { + 'name': 'api', + 'path': '../routes/api.dart', + 'route': '/api', + 'params': [], + } + ], + 'params': [], }, { 'name': '_api', 'route': '/api', 'middleware': false, 'files': [ - {'name': 'api_v1', 'path': '../routes/api/v1.dart', 'route': '/v1'}, + { + 'name': 'api_v1', + 'path': '../routes/api/v1.dart', + 'route': '/v1', + 'params': [], + }, { 'name': r'api_$id', 'path': '../routes/api/[id].dart', - 'route': '/' + 'route': '/', + 'params': ['id'], } - ] + ], + 'params': [], }, { 'name': '_api_v1', @@ -821,9 +932,11 @@ void main() { { 'name': 'api_v1_hello', 'path': '../routes/api/v1/hello.dart', - 'route': '/hello' + 'route': '/hello', + 'params': [], } - ] + ], + 'params': [], } ]; final directory = Directory( @@ -906,8 +1019,14 @@ void main() { 'route': '/', 'middleware': false, 'files': [ - {'name': 'api', 'path': '../routes/api.dart', 'route': '/api'} - ] + { + 'name': 'api', + 'path': '../routes/api.dart', + 'route': '/api', + 'params': [], + } + ], + 'params': [], }, { 'name': '_api', @@ -917,9 +1036,11 @@ void main() { { 'name': 'api_index', 'path': '../routes/api/index.dart', - 'route': '/' + 'route': '/', + 'params': [], } - ] + ], + 'params': [], } ]; final directory = Directory( diff --git a/packages/dart_frog_gen/test/src/route_directory_test.dart b/packages/dart_frog_gen/test/src/route_directory_test.dart index c28f72095..c0270ffc0 100644 --- a/packages/dart_frog_gen/test/src/route_directory_test.dart +++ b/packages/dart_frog_gen/test/src/route_directory_test.dart @@ -11,12 +11,14 @@ void main() { route: '/', middleware: null, files: [], + params: [], ); final copy = original.copyWith(); expect(copy.name, equals(original.name)); expect(copy.route, equals(original.route)); expect(copy.middleware, original.middleware); expect(copy.files, original.files); + expect(copy.params, original.params); }); test('copyWith creates a copy (updates)', () { @@ -25,39 +27,52 @@ void main() { route: '/', middleware: null, files: [], + params: [], ); final copy = original.copyWith( name: 'copy', route: '/copy', middleware: MiddlewareFile(name: '/', path: '/'), files: [], + params: ['copy'], ); expect(copy.name, equals('copy')); expect(copy.route, equals('/copy')); expect(copy.middleware, isNotNull); expect(copy.files, isEmpty); + expect(copy.params, equals(['copy'])); }); test('toJson returns correct map', () { final routeDirectory = RouteDirectory( name: 'index', - route: '/', + route: '/api/v1/users/', middleware: null, - files: [RouteFile(name: 'name', path: '/path', route: '/route')], + files: [ + RouteFile( + name: 'name', + path: '/path', + route: '/route/', + params: ['name'], + ) + ], + params: ['id'], ); expect( routeDirectory.toJson(), equals({ 'name': 'index', - 'route': '/', + 'route': '/api/v1/users/', 'middleware': false, 'files': [ { 'name': 'name', 'path': '/path', - 'route': '/route' + 'route': '/route/', + 'params': ['name'], } - ] + ], + 'params': ['id'], }), ); }); diff --git a/packages/dart_frog_gen/test/src/route_file_test.dart b/packages/dart_frog_gen/test/src/route_file_test.dart index 1caba56ae..cd7bfbff5 100644 --- a/packages/dart_frog_gen/test/src/route_file_test.dart +++ b/packages/dart_frog_gen/test/src/route_file_test.dart @@ -6,31 +6,54 @@ import 'package:test/test.dart'; void main() { group('RouteFile', () { test('copyWith creates a copy (no updates)', () { - final original = RouteFile(name: 'index', route: '/', path: '/path'); + final original = RouteFile( + name: 'index', + route: '/', + path: '/path', + params: [], + ); final copy = original.copyWith(); expect(copy.name, equals(original.name)); expect(copy.route, equals(original.route)); expect(copy.path, equals(original.path)); + expect(copy.params, equals(original.params)); }); test('copyWith creates a copy (updates)', () { - final original = RouteFile(name: 'index', route: '/', path: '/path'); + final original = RouteFile( + name: 'index', + route: '/', + path: '/path', + params: [], + ); final copy = original.copyWith( name: 'copy', route: '/copy', path: '/copy', + params: ['copy'], ); expect(copy.name, equals('copy')); expect(copy.route, equals('/copy')); expect(copy.path, equals('/copy')); + expect(copy.params, equals(['copy'])); }); test('toJson returns correct map', () { - final routeFile = RouteFile(name: 'index', route: '/', path: '/path'); + final routeFile = RouteFile( + name: 'index', + route: '/', + path: '/path', + params: ['id'], + ); expect( routeFile.toJson(), equals( - {'name': 'index', 'path': '/path', 'route': '/'}, + { + 'name': 'index', + 'path': '/path', + 'route': '/', + 'params': ['id'] + }, ), ); }); From 92545549c5678fe525558a6ade75c86633af217c Mon Sep 17 00:00:00 2001 From: Felix Angelov Date: Mon, 10 Oct 2022 17:21:47 -0500 Subject: [PATCH 5/6] e2e working --- .../__brick__/server.dart | 6 +- packages/dart_frog/test/src/router_test.dart | 19 +++ .../lib/src/build_route_configuration.dart | 4 +- .../src/build_route_configuration_test.dart | 124 +++++++++--------- .../test/src/route_directory_test.dart | 4 +- .../test/src/route_file_test.dart | 2 +- 6 files changed, 91 insertions(+), 68 deletions(-) diff --git a/bricks/dart_frog_dev_server/__brick__/server.dart b/bricks/dart_frog_dev_server/__brick__/server.dart index abadacba7..fa93a0c80 100644 --- a/bricks/dart_frog_dev_server/__brick__/server.dart +++ b/bricks/dart_frog_dev_server/__brick__/server.dart @@ -22,14 +22,14 @@ Future createServer() { Handler buildRootHandler() { final pipeline = const Pipeline(){{#globalMiddleware}}.addMiddleware({{#snakeCase}}{{{name}}}{{/snakeCase}}.middleware){{/globalMiddleware}}; final router = Router(){{#directories}} - ..mount('{{{route}}}', (r) => build{{#pascalCase}}{{{name}}}{{/pascalCase}}Handler()(r)){{/directories}}; + ..mount('{{{route}}}', (ctx, {{#directory_params}}{{.}},{{/directory_params}}) => build{{#pascalCase}}{{{name}}}{{/pascalCase}}Handler({{#directory_params}}{{.}},{{/directory_params}})(ctx)){{/directories}}; return pipeline.addHandler(router); } {{#directories}} -Handler build{{#pascalCase}}{{{name}}}{{/pascalCase}}Handler() { +Handler build{{#pascalCase}}{{{name}}}{{/pascalCase}}Handler({{#directory_params}}String {{.}},{{/directory_params}}) { {{#middleware}}final pipeline = const Pipeline(){{#middleware}}.addMiddleware({{#snakeCase}}{{{name}}}{{/snakeCase}}.middleware);{{/middleware}}{{/middleware}}{{^middleware}}const pipeline = Pipeline();{{/middleware}} final router = Router() - {{#files}}..all('{{{route}}}', {{#snakeCase}}{{{name}}}{{/snakeCase}}.onRequest){{/files}}; + {{#files}}..all('{{{route}}}', (ctx,{{#file_params}}{{.}},{{/file_params}}) => {{#snakeCase}}{{{name}}}{{/snakeCase}}.onRequest(ctx, {{#directory_params}}{{.}},{{/directory_params}}{{#file_params}}{{.}},{{/file_params}})){{/files}}; return pipeline.addHandler(router); } {{/directories}} \ No newline at end of file diff --git a/packages/dart_frog/test/src/router_test.dart b/packages/dart_frog/test/src/router_test.dart index a556e46ea..37e3198ce 100644 --- a/packages/dart_frog/test/src/router_test.dart +++ b/packages/dart_frog/test/src/router_test.dart @@ -461,6 +461,25 @@ void main() { expect(response.statusCode, equals(HttpStatus.ok)); }); + test('can mount dynamic route', () async { + final context = _MockRequestContext(); + final app = Router() + ..mount('/api/v1/posts/', (RequestContext context, String id) { + return Response(body: '/api/v1/posts/$id'); + }); + server.mount((request) async { + when(() => context.request).thenReturn( + Request(request.method, request.requestedUri), + ); + final response = await app.call(context); + final body = await response.body(); + return shelf.Response(response.statusCode, body: body); + }); + + final response = await http.get(Uri.parse('${server.url}/api/v1/posts/42')); + expect(response.body, equals('/api/v1/posts/42')); + }); + test('can mount dynamic routes', () async { final context = _MockRequestContext(); diff --git a/packages/dart_frog_gen/lib/src/build_route_configuration.dart b/packages/dart_frog_gen/lib/src/build_route_configuration.dart index 271f788a2..84b882a8c 100644 --- a/packages/dart_frog_gen/lib/src/build_route_configuration.dart +++ b/packages/dart_frog_gen/lib/src/build_route_configuration.dart @@ -349,7 +349,7 @@ class RouteDirectory { 'route': route, 'middleware': middleware?.toJson() ?? false, 'files': files.map((f) => f.toJson()).toList(), - 'params': params, + 'directory_params': params, }; } } @@ -399,7 +399,7 @@ class RouteFile { 'name': name, 'path': path, 'route': route, - 'params': params, + 'file_params': params, }; } } diff --git a/packages/dart_frog_gen/test/src/build_route_configuration_test.dart b/packages/dart_frog_gen/test/src/build_route_configuration_test.dart index fdbaf45a4..ed4fb823d 100644 --- a/packages/dart_frog_gen/test/src/build_route_configuration_test.dart +++ b/packages/dart_frog_gen/test/src/build_route_configuration_test.dart @@ -110,10 +110,10 @@ void main() { 'name': 'index', 'path': '../routes/index.dart', 'route': '/', - 'params': [], + 'file_params': [], } ], - 'params': [], + 'directory_params': [], } ]; final directory = Directory( @@ -152,16 +152,16 @@ void main() { 'name': 'index', 'path': '../routes/index.dart', 'route': '/', - 'params': [], + 'file_params': [], }, { 'name': 'hello', 'path': '../routes/hello.dart', 'route': '/hello', - 'params': [], + 'file_params': [], } ], - 'params': [], + 'directory_params': [], } ]; final directory = Directory( @@ -213,10 +213,10 @@ void main() { 'name': 'index', 'path': '../routes/index.dart', 'route': '/', - 'params': [], + 'file_params': [], } ], - 'params': [], + 'directory_params': [], }, { 'name': '_echo', @@ -227,10 +227,10 @@ void main() { 'name': 'echo_message', 'path': '../routes/echo/message.dart', 'route': '/message', - 'params': [], + 'file_params': [], } ], - 'params': [], + 'directory_params': [], } ]; final directory = Directory( @@ -275,14 +275,14 @@ void main() { 'route': '/', 'middleware': false, 'files': [], - 'params': [], + 'directory_params': [], }, { 'name': '_echo', 'route': '/echo', 'middleware': false, 'files': [], - 'params': [], + 'directory_params': [], }, { 'name': '_echo_message', @@ -293,10 +293,10 @@ void main() { 'name': 'echo_message_index', 'path': '../routes/echo/message/index.dart', 'route': '/', - 'params': [], + 'file_params': [], } ], - 'params': [], + 'directory_params': [], } ]; final directory = Directory( @@ -344,10 +344,10 @@ void main() { 'name': 'index', 'path': '../routes/index.dart', 'route': '/', - 'params': [], + 'file_params': [], } ], - 'params': [], + 'directory_params': [], }, { 'name': '_echo', @@ -358,10 +358,10 @@ void main() { 'name': r'echo_$message', 'path': '../routes/echo/[message].dart', 'route': '/', - 'params': ['message'], + 'file_params': ['message'], } ], - 'params': [], + 'directory_params': [], } ]; final directory = Directory( @@ -410,10 +410,10 @@ void main() { 'name': 'index', 'path': '../routes/index.dart', 'route': '/', - 'params': [], + 'file_params': [], }, ], - 'params': [], + 'directory_params': [], }, { 'name': r'_$user', @@ -424,24 +424,27 @@ void main() { 'name': r'$user_$name', 'path': '../routes/[user]/[name].dart', 'route': '/', - 'params': ['name'], + 'file_params': ['name'], } ], - 'params': ['user'], + 'directory_params': ['user'], }, { 'name': r'_$user_$id', 'route': '//', - 'middleware': false, + 'middleware': { + 'name': r'$user_$id__middleware', + 'path': '../routes/[user]/[id]/_middleware.dart' + }, 'files': [ { 'name': r'$user_$id_index', 'path': '../routes/[user]/[id]/index.dart', 'route': '/', - 'params': [], + 'file_params': [], } ], - 'params': ['user', 'id'], + 'directory_params': ['user', 'id'], } ]; final directory = Directory( @@ -461,6 +464,7 @@ void main() { final idDirectory = Directory(path.join(userDirectory.path, '[id]')) ..createSync(); File(path.join(idDirectory.path, 'index.dart')).createSync(); + File(path.join(idDirectory.path, '_middleware.dart')).createSync(); final configuration = buildRouteConfiguration(directory); expect( configuration.directories.map((d) => d.toJson()).toList(), @@ -505,17 +509,17 @@ void main() { 'name': 'index', 'path': '../routes/index.dart', 'route': '/', - 'params': [], + 'file_params': [], }, ], - 'params': [], + 'directory_params': [], }, { 'name': r'_$id', 'route': '/', 'middleware': false, 'files': >[], - 'params': ['id'], + 'directory_params': ['id'], }, { 'name': r'_$id_api', @@ -526,10 +530,10 @@ void main() { 'name': r'$id_api_index', 'path': '../routes/[id]/api/index.dart', 'route': '/', - 'params': [], + 'file_params': [], } ], - 'params': ['id'], + 'directory_params': ['id'], } ]; final directory = Directory( @@ -585,17 +589,17 @@ void main() { 'name': 'index', 'path': '../routes/index.dart', 'route': '/', - 'params': [], + 'file_params': [], }, ], - 'params': [], + 'directory_params': [], }, { 'name': r'_$id', 'route': '/', 'middleware': false, 'files': >[], - 'params': ['id'], + 'directory_params': ['id'], }, { 'name': r'_$id_api', @@ -606,10 +610,10 @@ void main() { 'name': r'$id_api_test', 'path': '../routes/[id]/api/test.dart', 'route': '/test', - 'params': [], + 'file_params': [], } ], - 'params': ['id'], + 'directory_params': ['id'], } ]; final directory = Directory( @@ -665,24 +669,24 @@ void main() { 'name': 'index', 'path': '../routes/index.dart', 'route': '/', - 'params': [], + 'file_params': [], }, ], - 'params': [], + 'directory_params': [], }, { 'name': r'_$id', 'route': '/', 'middleware': false, 'files': >[], - 'params': ['id'], + 'directory_params': ['id'], }, { 'name': r'_$id_api', 'route': '//api', 'middleware': false, 'files': >[], - 'params': ['id'], + 'directory_params': ['id'], }, { 'name': r'_$id_api_$name', @@ -693,10 +697,10 @@ void main() { 'name': r'$id_api_$name_index', 'path': '../routes/[id]/api/[name]/index.dart', 'route': '/', - 'params': [], + 'file_params': [], } ], - 'params': ['id', 'name'], + 'directory_params': ['id', 'name'], } ]; final directory = Directory( @@ -754,24 +758,24 @@ void main() { 'name': 'index', 'path': '../routes/index.dart', 'route': '/', - 'params': [], + 'file_params': [], }, ], - 'params': [], + 'directory_params': [], }, { 'name': r'_$id', 'route': '/', 'middleware': false, 'files': >[], - 'params': ['id'], + 'directory_params': ['id'], }, { 'name': r'_$id_api', 'route': '//api', 'middleware': false, 'files': >[], - 'params': ['id'], + 'directory_params': ['id'], }, { 'name': r'_$id_api_$name', @@ -782,10 +786,10 @@ void main() { 'name': r'$id_api_$name_test', 'path': '../routes/[id]/api/[name]/test.dart', 'route': '/test', - 'params': [], + 'file_params': [], } ], - 'params': ['id', 'name'], + 'directory_params': ['id', 'name'], } ]; final directory = Directory( @@ -839,7 +843,7 @@ void main() { 'route': '/', 'middleware': false, 'files': [], - 'params': [], + 'directory_params': [], }, { 'name': '_api', @@ -850,10 +854,10 @@ void main() { 'name': 'api_api', 'path': '../routes/api/api.dart', 'route': '/api', - 'params': [], + 'file_params': [], } ], - 'params': [], + 'directory_params': [], } ]; final directory = Directory( @@ -899,10 +903,10 @@ void main() { 'name': 'api', 'path': '../routes/api.dart', 'route': '/api', - 'params': [], + 'file_params': [], } ], - 'params': [], + 'directory_params': [], }, { 'name': '_api', @@ -913,16 +917,16 @@ void main() { 'name': 'api_v1', 'path': '../routes/api/v1.dart', 'route': '/v1', - 'params': [], + 'file_params': [], }, { 'name': r'api_$id', 'path': '../routes/api/[id].dart', 'route': '/', - 'params': ['id'], + 'file_params': ['id'], } ], - 'params': [], + 'directory_params': [], }, { 'name': '_api_v1', @@ -933,10 +937,10 @@ void main() { 'name': 'api_v1_hello', 'path': '../routes/api/v1/hello.dart', 'route': '/hello', - 'params': [], + 'file_params': [], } ], - 'params': [], + 'directory_params': [], } ]; final directory = Directory( @@ -1023,10 +1027,10 @@ void main() { 'name': 'api', 'path': '../routes/api.dart', 'route': '/api', - 'params': [], + 'file_params': [], } ], - 'params': [], + 'directory_params': [], }, { 'name': '_api', @@ -1037,10 +1041,10 @@ void main() { 'name': 'api_index', 'path': '../routes/api/index.dart', 'route': '/', - 'params': [], + 'file_params': [], } ], - 'params': [], + 'directory_params': [], } ]; final directory = Directory( diff --git a/packages/dart_frog_gen/test/src/route_directory_test.dart b/packages/dart_frog_gen/test/src/route_directory_test.dart index c0270ffc0..2b939891f 100644 --- a/packages/dart_frog_gen/test/src/route_directory_test.dart +++ b/packages/dart_frog_gen/test/src/route_directory_test.dart @@ -69,10 +69,10 @@ void main() { 'name': 'name', 'path': '/path', 'route': '/route/', - 'params': ['name'], + 'file_params': ['name'], } ], - 'params': ['id'], + 'directory_params': ['id'], }), ); }); diff --git a/packages/dart_frog_gen/test/src/route_file_test.dart b/packages/dart_frog_gen/test/src/route_file_test.dart index cd7bfbff5..10bff8241 100644 --- a/packages/dart_frog_gen/test/src/route_file_test.dart +++ b/packages/dart_frog_gen/test/src/route_file_test.dart @@ -52,7 +52,7 @@ void main() { 'name': 'index', 'path': '/path', 'route': '/', - 'params': ['id'] + 'file_params': ['id'] }, ), ); From 68ad1186217a97d88529adacf00d616baf659f28 Mon Sep 17 00:00:00 2001 From: Felix Angelov Date: Thu, 13 Oct 2022 15:40:30 -0500 Subject: [PATCH 6/6] prod brick updates --- .../dart_frog_prod_server/__brick__/build/bin/server.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bricks/dart_frog_prod_server/__brick__/build/bin/server.dart b/bricks/dart_frog_prod_server/__brick__/build/bin/server.dart index 3d1a0e54c..96835ae7b 100644 --- a/bricks/dart_frog_prod_server/__brick__/build/bin/server.dart +++ b/bricks/dart_frog_prod_server/__brick__/build/bin/server.dart @@ -22,14 +22,14 @@ Future createServer() async { Handler buildRootHandler() { final pipeline = const Pipeline(){{#globalMiddleware}}.addMiddleware({{#snakeCase}}{{{name}}}{{/snakeCase}}.middleware){{/globalMiddleware}}; final router = Router(){{#directories}} - ..mount('{{{route}}}', (r) => build{{#pascalCase}}{{{name}}}{{/pascalCase}}Handler()(r)){{/directories}}; + ..mount('{{{route}}}', (ctx, {{#directory_params}}{{.}},{{/directory_params}}) => build{{#pascalCase}}{{{name}}}{{/pascalCase}}Handler({{#directory_params}}{{.}},{{/directory_params}})(ctx)){{/directories}}; return pipeline.addHandler(router); } {{#directories}} -Handler build{{#pascalCase}}{{{name}}}{{/pascalCase}}Handler() { +Handler build{{#pascalCase}}{{{name}}}{{/pascalCase}}Handler({{#directory_params}}String {{.}},{{/directory_params}}) { final pipeline = const Pipeline(){{#middleware}}.addMiddleware({{#snakeCase}}{{{name}}}{{/snakeCase}}.middleware){{/middleware}}; final router = Router() - {{#files}}..all('{{{route}}}', {{#snakeCase}}{{{name}}}{{/snakeCase}}.onRequest){{/files}}; + {{#files}}..all('{{{route}}}', (ctx,{{#file_params}}{{.}},{{/file_params}}) => {{#snakeCase}}{{{name}}}{{/snakeCase}}.onRequest(ctx, {{#directory_params}}{{.}},{{/directory_params}}{{#file_params}}{{.}},{{/file_params}})){{/files}}; return pipeline.addHandler(router); } {{/directories}} \ No newline at end of file