Skip to content

Commit 9fe2ead

Browse files
authored
feat(dart_frig_cli): add new command to the cli (#641)
1 parent 44b39a1 commit 9fe2ead

File tree

14 files changed

+631
-15
lines changed

14 files changed

+631
-15
lines changed
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import 'package:dart_frog/dart_frog.dart';
2-
32
{{#is_route}}
43
{{> route.dart}}
54
{{/is_route}}{{#is_middleware}}
65
{{> middleware.dart}}
7-
{{/is_middleware}}
6+
{{/is_middleware}}

bricks/dart_frog_new/hooks/lib/src/route_to_path.dart

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'package:path/path.dart' as path;
2+
13
/// Convert a route to a file path.
24
///
35
/// If [preferIndex] is true, the path will be converted to a directory path
@@ -14,19 +16,23 @@ String routeToPath(
1416
String route, {
1517
bool preferIndex = false,
1618
String preamble = 'routes',
19+
path.Context? pathContext,
1720
}) {
21+
final context = pathContext ?? path.context;
22+
final separator = context.separator;
23+
1824
if (route == '/') {
19-
return '$preamble/index.dart';
25+
return '$preamble${separator}index.dart';
2026
}
2127

22-
final path =
23-
route.split('/').where((element) => element.isNotEmpty).join('/');
28+
final p =
29+
route.split('/').where((element) => element.isNotEmpty).join(separator);
2430

2531
if (preferIndex) {
26-
final pathWithIndex = '$path/index.dart';
27-
return '$preamble/$pathWithIndex';
32+
final pathWithIndex = context.join(p, 'index.dart');
33+
return context.join(preamble, pathWithIndex);
2834
}
2935

30-
final pathWithExtension = '$path.dart';
31-
return '$preamble/$pathWithExtension';
36+
final pathWithExtension = '$p.dart';
37+
return context.join(preamble, pathWithExtension);
3238
}

bricks/dart_frog_new/hooks/test/src/route_to_path_test.dart

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ import 'package:test/test.dart';
44

55
void main() {
66
group('routeToPath', () {
7+
test('defaults to current platform path context', () {
8+
expect(routeToPath('/'), equals(path.join('routes', 'index.dart')));
9+
});
10+
});
11+
12+
group('routeToPath posix', () {
713
group('preferIndex false', () {
814
final expectedRouteToPathMappings = <String, String>{
915
'/': '../routes/index.dart',
@@ -44,4 +50,55 @@ void main() {
4450
}
4551
});
4652
});
53+
54+
group('routeToPath windows', () {
55+
group('preferIndex false', () {
56+
final expectedRouteToPathMappings = <String, String>{
57+
'/': r'..\routes\index.dart',
58+
'/hello': r'..\routes\hello.dart',
59+
'/hello/world': r'..\routes\hello\world.dart',
60+
'/hello/[name]': r'..\routes\hello\[name].dart',
61+
'/[id]/item': r'..\routes\[id]\item.dart',
62+
'/[id]/part/item': r'..\routes\[id]\part\item.dart',
63+
};
64+
65+
for (final entry in expectedRouteToPathMappings.entries) {
66+
test('maps ${entry.key} -> ${entry.value}', () {
67+
expect(
68+
routeToPath(
69+
entry.key,
70+
preamble: r'..\routes',
71+
pathContext: path.windows,
72+
),
73+
equals(path.windows.normalize(entry.value)),
74+
);
75+
});
76+
}
77+
});
78+
79+
group('preferIndex true', () {
80+
final expectedRouteToPathMappings = <String, String>{
81+
'/': r'..\routes\index.dart',
82+
'/hello': r'..\routes\hello\index.dart',
83+
'/hello/world': r'..\routes\hello\world\index.dart',
84+
'/hello/[name]': r'..\routes\hello\[name]\index.dart',
85+
'/[id]/item': r'..\routes\[id]\item\index.dart',
86+
'/[id]/part/item': r'..\routes\[id]\part\item\index.dart',
87+
};
88+
89+
for (final entry in expectedRouteToPathMappings.entries) {
90+
test('maps ${entry.key} -> ${entry.value}', () {
91+
expect(
92+
routeToPath(
93+
entry.key,
94+
preferIndex: true,
95+
preamble: r'..\routes',
96+
pathContext: path.windows,
97+
),
98+
equals(path.windows.normalize(entry.value)),
99+
);
100+
});
101+
}
102+
});
103+
});
47104
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include: package:very_good_analysis/analysis_options.4.0.0.yaml

packages/dart_frog_cli/e2e/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: End to End tests for package:dart_frog_cli
33
publish_to: none
44

55
environment:
6-
sdk: ">=2.17.0 <3.0.0"
6+
sdk: ">=2.19.0 <3.0.0"
77

88
dev_dependencies:
99
dart_frog:
@@ -12,4 +12,4 @@ dev_dependencies:
1212
meta: ^1.7.0
1313
path: ^1.8.2
1414
test: ^1.19.2
15-
very_good_analysis: ^3.0.0
15+
very_good_analysis: ^4.0.0
File renamed without changes.
File renamed without changes.
File renamed without changes.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import 'dart:io';
2+
3+
import 'package:test/test.dart';
4+
5+
Future<void> dartFrogNewRoute(
6+
String routePath, {
7+
required Directory directory,
8+
}) =>
9+
_dartFrogNew(
10+
routePath: routePath,
11+
what: 'route',
12+
directory: directory,
13+
);
14+
15+
Future<void> dartFrogNewMiddleware(
16+
String routePath, {
17+
required Directory directory,
18+
}) =>
19+
_dartFrogNew(
20+
routePath: routePath,
21+
what: 'middleware',
22+
directory: directory,
23+
);
24+
25+
Future<void> _dartFrogNew({
26+
required String routePath,
27+
required String what,
28+
required Directory directory,
29+
}) async {
30+
final result = await Process.run(
31+
'dart_frog',
32+
['new', what, routePath],
33+
workingDirectory: directory.path,
34+
runInShell: true,
35+
);
36+
37+
if (result.exitCode != 0) {
38+
throw FormatException('${result.stderr}');
39+
}
40+
}
41+
42+
Matcher failsWithA({required String message}) {
43+
return throwsA(
44+
isA<FormatException>().having((e) => e.message.trim(), 'message', message),
45+
);
46+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import 'dart:io';
2+
import 'package:path/path.dart' as path;
3+
import 'package:test/test.dart';
4+
5+
File fileAt(String filePath, {required Directory on}) {
6+
return File(path.join(on.path, filePath));
7+
}
8+
9+
final exists = FileExistsMatcher(isTrue);
10+
final doesNotExist = FileExistsMatcher(isFalse);
11+
12+
class FileExistsMatcher extends CustomMatcher {
13+
FileExistsMatcher(Matcher matcher)
14+
: super(
15+
'File exists',
16+
'file exists',
17+
isA<File>().having((p) => p.existsSync(), 'exists', matcher),
18+
);
19+
}

0 commit comments

Comments
 (0)