Skip to content

Commit cd65471

Browse files
committed
v3.0.0 updates
1 parent 2648eeb commit cd65471

14 files changed

+266
-47
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## [3.0.0] - 2022-04-29
2+
3+
* New command to create: Events, Providers and API Services
4+
* Remove command: project:init
5+
* Docs link updated in Model stub
6+
* Update README info
7+
* Remove nylo_support ref from stubs
8+
* Pubspec.yaml dependency updates
9+
110
## [2.2.0] - 2022-03-29
211

312
* Remove appended 'Widget' from Metro:make command for stateless and stateful widgets

README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
![Nylo Banner](https://nylo.dev/images/nylo_logo_header.png)
22

33
<p align="center">
4-
<a href="https://github.com/nylo-core/framework/releases/tag/v2.2.0"><img src="https://img.shields.io/github/v/release/nylo-core/framework?style=plastic" alt="Latest Release Version"></a>
5-
<a href="https://github.com/nylo-core/framework/releases/tag/v2.2.0"><img src="https://img.shields.io/github/license/nylo-core/framework?style=plastic" alt="Latest Stable Version"></a>
4+
<a href="https://github.com/nylo-core/framework/releases/latest"><img src="https://img.shields.io/github/v/release/nylo-core/framework?style=plastic" alt="Latest Release Version"></a>
5+
<a href="https://github.com/nylo-core/framework/releases/latest"><img src="https://img.shields.io/github/license/nylo-core/framework?style=plastic" alt="Latest Stable Version"></a>
66
<a href="https://github.com/nylo-core/framework"><img alt="GitHub stars" src="https://img.shields.io/github/stars/nylo-core/framework?style=plastic"></a>
77
</p>
88

9-
## Nylo Framework (v2.2.0)
9+
## Nylo Framework (v3.0.0)
1010

11-
Nylo is a micro-framework for Flutter which is designed to help simplify app development. Every project provides a simple boilerplate and MVC pattern to help you build apps easier.
11+
Nylo is a micro-framework for Flutter which is designed to help simplify app development. Every project provides a simple boilerplate and MVC pattern to help you build apps easier.
1212

1313
This project is open source and MIT-licenced, we welcome any contributions. You can join as a backer/sponsor to fund future development for this project [here](https://nylo.dev/contributions)
1414

@@ -18,10 +18,12 @@ This project is open source and MIT-licenced, we welcome any contributions. You
1818

1919
## Features
2020
Some core features available
21-
* Cli for generating new files
21+
* CLI for generating new files
2222
* Router file to manage routes
2323
* Light and dark themes preset for customization
2424
* Localization ready
25+
* Elegant API Services for Networking
26+
* Dispatch Events
2527
* Project structure for widgets, assets, controllers + more
2628

2729
## Documentation

example/pubspec.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,14 @@ packages:
202202
path: ".."
203203
relative: true
204204
source: path
205-
version: "2.2.0"
205+
version: "3.0.0"
206206
nylo_support:
207207
dependency: transitive
208208
description:
209209
name: nylo_support
210210
url: "https://pub.dartlang.org"
211211
source: hosted
212-
version: "2.4.0"
212+
version: "3.0.0"
213213
page_transition:
214214
dependency: transitive
215215
description:

lib/metro/menu.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ Options
88
-h
99
1010
All commands:
11-
project
12-
project:init
1311
1412
make
1513
make:controller
1614
make:model
1715
make:page
1816
make:stateful_widget
1917
make:stateless_widget
18+
make:provider
19+
make:event
20+
make:api_service
2021
make:theme
2122
""";

lib/metro/metro.dart

Lines changed: 138 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ library metro;
33
import 'package:collection/collection.dart' show IterableExtension;
44
import 'package:args/args.dart';
55
import 'package:nylo_framework/metro/menu.dart';
6+
import 'package:nylo_framework/metro/stubs/api_service_stub.dart';
7+
import 'package:nylo_framework/metro/stubs/event_stub.dart';
8+
import 'package:nylo_framework/metro/stubs/provider_stub.dart';
69
import 'package:nylo_framework/metro/stubs/theme_colors_stub.dart';
710
import 'package:nylo_framework/metro/stubs/theme_stub.dart';
811
import 'package:nylo_support/metro/constants/strings.dart';
@@ -21,12 +24,6 @@ import 'package:recase/recase.dart';
2124

2225
final ArgParser parser = ArgParser(allowTrailingOptions: true);
2326
List<NyCommand> _allCommands = [
24-
NyCommand(
25-
name: "init",
26-
options: 1,
27-
arguments: ["-h"],
28-
category: "project",
29-
action: _projectInit),
3027
NyCommand(
3128
name: "controller",
3229
options: 1,
@@ -57,6 +54,24 @@ List<NyCommand> _allCommands = [
5754
arguments: ["-h", "-f"],
5855
category: "make",
5956
action: _makeStatelessWidget),
57+
NyCommand(
58+
name: "provider",
59+
options: 1,
60+
arguments: ["-h", "-f"],
61+
category: "make",
62+
action: _makeProvider),
63+
NyCommand(
64+
name: "event",
65+
options: 1,
66+
arguments: ["-h", "-f"],
67+
category: "make",
68+
action: _makeEvent),
69+
NyCommand(
70+
name: "api_service",
71+
options: 1,
72+
arguments: ["-h", "-f", "-model", "-resource"],
73+
category: "make",
74+
action: _makeApiService),
6075
NyCommand(
6176
name: "theme",
6277
options: 1,
@@ -93,32 +108,14 @@ Future<void> commands(List<String> arguments) async {
93108
await nyCommand.action!(arguments);
94109
}
95110

96-
_projectInit(List<String> arguments) async {
97-
parser.addFlag(helpFlag,
98-
abbr: 'h', help: 'Initializes the Nylo project', negatable: false);
99-
100-
final ArgResults argResults = parser.parse(arguments);
101-
102-
_checkHelpFlag(argResults[helpFlag], parser.usage);
103-
104-
if (await MetroService.hasFile(".env") == false) {
105-
final File envExample = File('.env-example');
106-
final File env = File('.env');
107-
await env.writeAsString(await envExample.readAsString());
108-
MetroConsole.writeInGreen('.env file add from .env-example 🎉');
109-
}
110-
111-
MetroConsole.writeInGreen('Project initialized, create something great 🎉');
112-
}
113-
114111
_makeStatefulWidget(List<String> arguments) async {
115112
parser.addFlag(helpFlag,
116113
abbr: 'h',
117-
help: 'e.g. make:widget video_player_widget',
114+
help: 'e.g. make:stateful_widget video_player_widget',
118115
negatable: false);
119116
parser.addFlag(forceFlag,
120117
abbr: 'f',
121-
help: 'Creates a new widget even if it already exists.',
118+
help: 'Creates a new stateful widget even if it already exists.',
122119
negatable: false);
123120

124121
final ArgResults argResults = parser.parse(arguments);
@@ -127,6 +124,9 @@ _makeStatefulWidget(List<String> arguments) async {
127124

128125
_checkHelpFlag(argResults[helpFlag], parser.usage);
129126

127+
_checkArguments(arguments,
128+
'You are missing the \'name\' of the stateful widget that you want to create.\ne.g. make:stateful_widget my_new_widget');
129+
130130
String widgetName =
131131
argResults.arguments.first.replaceAll(RegExp(r'(_?widget)'), "");
132132

@@ -140,11 +140,11 @@ _makeStatefulWidget(List<String> arguments) async {
140140
_makeStatelessWidget(List<String> arguments) async {
141141
parser.addFlag(helpFlag,
142142
abbr: 'h',
143-
help: 'e.g. make:widget video_player_widget',
143+
help: 'e.g. make:stateless_widget video_player_widget',
144144
negatable: false);
145145
parser.addFlag(forceFlag,
146146
abbr: 'f',
147-
help: 'Creates a new widget even if it already exists.',
147+
help: 'Creates a new stateless widget even if it already exists.',
148148
negatable: false);
149149

150150
final ArgResults argResults = parser.parse(arguments);
@@ -166,6 +166,114 @@ _makeStatelessWidget(List<String> arguments) async {
166166
MetroConsole.writeInGreen(widgetName + ' created 🎉');
167167
}
168168

169+
_makeProvider(List<String> arguments) async {
170+
parser.addFlag(helpFlag,
171+
abbr: 'h', help: 'e.g. make:provider storage_provider', negatable: false);
172+
parser.addFlag(forceFlag,
173+
abbr: 'f',
174+
help: 'Creates a new provider even if it already exists.',
175+
negatable: false);
176+
177+
final ArgResults argResults = parser.parse(arguments);
178+
179+
bool? hasForceFlag = argResults[forceFlag];
180+
181+
_checkHelpFlag(argResults[helpFlag], parser.usage);
182+
183+
_checkArguments(arguments,
184+
'You are missing the \'name\' of the provider that you want to create.\ne.g. make:provider cache_provider');
185+
186+
String providerName =
187+
argResults.arguments.first.replaceAll(RegExp(r'(_?provider)'), "");
188+
189+
String stubProvider = providerStub(ReCase(providerName));
190+
await MetroService.makeProvider(providerName, stubProvider,
191+
forceCreate: hasForceFlag ?? false);
192+
193+
MetroConsole.writeInGreen(providerName + '_provider created 🎉');
194+
}
195+
196+
_makeEvent(List<String> arguments) async {
197+
parser.addFlag(helpFlag,
198+
abbr: 'h', help: 'e.g. make:event login_event', negatable: false);
199+
parser.addFlag(forceFlag,
200+
abbr: 'f',
201+
help: 'Creates a new event even if it already exists.',
202+
negatable: false);
203+
204+
final ArgResults argResults = parser.parse(arguments);
205+
206+
bool? hasForceFlag = argResults[forceFlag];
207+
208+
_checkHelpFlag(argResults[helpFlag], parser.usage);
209+
210+
_checkArguments(arguments,
211+
'You are missing the \'name\' of the event that you want to create.\ne.g. make:event login_event');
212+
213+
String eventName =
214+
argResults.arguments.first.replaceAll(RegExp(r'(_?event)'), "");
215+
216+
String stubEvent = eventStub(eventName: ReCase(eventName));
217+
await MetroService.makeEvent(eventName, stubEvent,
218+
forceCreate: hasForceFlag ?? false);
219+
220+
MetroConsole.writeInGreen(eventName + '_event created 🎉');
221+
}
222+
223+
_makeApiService(List<String> arguments) async {
224+
parser.addFlag(helpFlag,
225+
abbr: 'h',
226+
help: 'e.g. make:api_service user_api_service',
227+
negatable: false);
228+
parser.addFlag(forceFlag,
229+
abbr: 'f',
230+
help: 'Creates a new API service even if it already exists.',
231+
negatable: false);
232+
parser.addOption(
233+
modelFlag,
234+
abbr: 'm',
235+
help: 'Provide the Model that should be used in the API service.',
236+
);
237+
parser.addOption(
238+
urlFlag,
239+
abbr: 'u',
240+
help: 'Provide the Base Url that should be used in the API service.',
241+
);
242+
parser.addFlag(isResourceFlag,
243+
abbr: 'r',
244+
help: 'Creates a API service with crud methods',
245+
negatable: false);
246+
247+
final ArgResults argResults = parser.parse(arguments);
248+
249+
bool? hasForceFlag = argResults[forceFlag];
250+
bool hasResourceFlag = argResults[isResourceFlag] ?? false;
251+
String modelFlagValue = argResults[modelFlag] ?? "Model";
252+
String? baseUrlFlagValue = argResults[urlFlag];
253+
if (baseUrlFlagValue == null) {
254+
baseUrlFlagValue = "getEnv('API_BASE_URL')";
255+
} else {
256+
baseUrlFlagValue = "\"$baseUrlFlagValue\"";
257+
}
258+
259+
_checkHelpFlag(argResults[helpFlag], parser.usage);
260+
261+
_checkArguments(arguments,
262+
'You are missing the \'name\' of the API service that you want to create.\ne.g. make:api_service user_api_service');
263+
264+
String apiServiceName =
265+
argResults.arguments.first.replaceAll(RegExp(r'(_?api_service)'), "");
266+
267+
String stubApiService = apiServiceStub(ReCase(apiServiceName),
268+
model: ReCase(modelFlagValue),
269+
isResource: hasResourceFlag,
270+
baseUrl: baseUrlFlagValue);
271+
await MetroService.makeApiService(apiServiceName, stubApiService,
272+
forceCreate: hasForceFlag ?? false);
273+
274+
MetroConsole.writeInGreen(apiServiceName + '_api_service created 🎉');
275+
}
276+
169277
_makeTheme(List<String> arguments) async {
170278
parser.addFlag(helpFlag,
171279
abbr: 'h', help: 'e.g. make:theme bright_theme', negatable: false);
@@ -231,7 +339,8 @@ _makeController(List<String> arguments) async {
231339
_makeModel(List<String> arguments) async {
232340
parser.addFlag(helpFlag,
233341
abbr: 'h',
234-
help: 'Creates a new model in your project.',
342+
help:
343+
'To create a new model, use e.g. "flutter pub run nylo_framework:main make:model user"',
235344
negatable: false);
236345
parser.addFlag(forceFlag,
237346
abbr: 'f',
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import 'package:recase/recase.dart';
2+
3+
String apiServiceStub(ReCase rc,
4+
{required ReCase model,
5+
bool isResource = false,
6+
required String baseUrl}) =>
7+
'''
8+
import 'package:flutter/material.dart';
9+
import 'package:flutter_app/app/networking/dio/base_api_service.dart';
10+
${baseUrl == "getEnv('API_BASE_URL')" ? "import 'package:nylo_framework/nylo_framework.dart';" : ""}
11+
${model.originalText != 'Model' ? "import 'package:flutter_app/app/models/${model.snakeCase}.dart';" : ""}
12+
13+
class ${rc.pascalCase}ApiService extends BaseApiService {
14+
${rc.pascalCase}ApiService({BuildContext? buildContext}) : super(buildContext);
15+
16+
@override
17+
String get baseUrl => $baseUrl;
18+
19+
${isResource ? '''
20+
/// Return a list of users
21+
Future<List<${model.pascalCase}>?> fetchAll({dynamic query}) async {
22+
return await network<List<${model.pascalCase}>>(
23+
request: (request) => request.get("/endpoint-path", queryParameters: query),
24+
);
25+
}
26+
27+
/// Find a ${model.pascalCase}
28+
Future<${model.pascalCase}?> find({required int id}) async {
29+
return await network<${model.pascalCase}>(
30+
request: (request) => request.get("/endpoint-path/\$id"),
31+
);
32+
}
33+
34+
/// Create a ${model.pascalCase}
35+
Future<${model.pascalCase}?> create({required dynamic data}) async {
36+
return await network<${model.pascalCase}>(
37+
request: (request) => request.post("/endpoint-path", data: data),
38+
);
39+
}
40+
41+
/// Update a ${model.pascalCase}
42+
Future<${model.pascalCase}?> update({dynamic query}) async {
43+
return await network<${model.pascalCase}>(
44+
request: (request) => request.put("/endpoint-path", queryParameters: query),
45+
);
46+
}
47+
48+
/// Delete a ${model.pascalCase}
49+
Future<bool?> delete({required int id}) async {
50+
return await network<bool>(
51+
request: (request) => request.delete("/endpoint-path/\$id"),
52+
);
53+
}''' : '''
54+
/// Example API Request
55+
Future<dynamic> fetchData() async {
56+
return await network<dynamic>(
57+
request: (request) => request.get("/endpoint-path"),
58+
);
59+
}'''}
60+
}
61+
''';

lib/metro/stubs/event_stub.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import 'package:recase/recase.dart';
2+
3+
String eventStub({required ReCase eventName}) => '''
4+
import 'package:nylo_framework/nylo_framework.dart';
5+
6+
class ${eventName.pascalCase}Event implements NyEvent {
7+
8+
final listeners = {
9+
DefaultListener: DefaultListener(),
10+
};
11+
}
12+
13+
class DefaultListener extends NyListener {
14+
handle(dynamic event) async {
15+
// Handle the event
16+
17+
}
18+
}
19+
''';

0 commit comments

Comments
 (0)