feat: add generator
This commit is contained in:
parent
a2ef01dcad
commit
4f86d6dbbd
6
tools/brick_generator/.gitignore
vendored
Normal file
6
tools/brick_generator/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# Files and directories created by pub.
|
||||
.dart_tool/
|
||||
.packages
|
||||
|
||||
# Conventional directory for build output.
|
||||
build/
|
3
tools/brick_generator/CHANGELOG.md
Normal file
3
tools/brick_generator/CHANGELOG.md
Normal file
@ -0,0 +1,3 @@
|
||||
## 1.0.0
|
||||
|
||||
- Initial version.
|
6
tools/brick_generator/README.md
Normal file
6
tools/brick_generator/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
A sample command-line application with an entrypoint in `bin/`, library code
|
||||
in `lib/`.
|
||||
|
||||
```sh
|
||||
dart /bin/brick_generator.dart wyatt_clean_code wyatt_clean_code wyatt-clean-code "Wyatt Demo" app.wyatt.io
|
||||
```
|
30
tools/brick_generator/analysis_options.yaml
Normal file
30
tools/brick_generator/analysis_options.yaml
Normal file
@ -0,0 +1,30 @@
|
||||
# This file configures the static analysis results for your project (errors,
|
||||
# warnings, and lints).
|
||||
#
|
||||
# This enables the 'recommended' set of lints from `package:lints`.
|
||||
# This set helps identify many issues that may lead to problems when running
|
||||
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
|
||||
# style and format.
|
||||
#
|
||||
# If you want a smaller set of lints you can change this to specify
|
||||
# 'package:lints/core.yaml'. These are just the most critical lints
|
||||
# (the recommended set includes the core lints).
|
||||
# The core lints are also what is used by pub.dev for scoring packages.
|
||||
|
||||
include: package:lints/recommended.yaml
|
||||
|
||||
# Uncomment the following section to specify additional rules.
|
||||
|
||||
# linter:
|
||||
# rules:
|
||||
# - camel_case_types
|
||||
|
||||
# analyzer:
|
||||
# exclude:
|
||||
# - path/to/excluded/files/**
|
||||
|
||||
# For more information about the core and recommended set of lints, see
|
||||
# https://dart.dev/go/core-lints
|
||||
|
||||
# For additional information about configuring this file, see
|
||||
# https://dart.dev/guides/language/analysis-options
|
6
tools/brick_generator/assets/MainActivity.kt
Normal file
6
tools/brick_generator/assets/MainActivity.kt
Normal file
@ -0,0 +1,6 @@
|
||||
package {{#dotCase}}{{org_name}}{{/dotCase}}.{{#snakeCase}}{{project_name}}{{/snakeCase}}
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
}
|
102
tools/brick_generator/bin/brick_generator.dart
Normal file
102
tools/brick_generator/bin/brick_generator.dart
Normal file
@ -0,0 +1,102 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:brick_generator/shell.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
// Constants
|
||||
final _apps = 'apps';
|
||||
final _bricks = 'bricks';
|
||||
final _staticDir = path.join('tools', 'brick_generator', 'assets');
|
||||
|
||||
Future<void> main(List<String> arguments) async {
|
||||
final _appName = arguments[0];
|
||||
|
||||
final _projectSnakeName = arguments[1];
|
||||
final _projectParamName = arguments[2];
|
||||
final _projectTitleName = arguments[3];
|
||||
final _orgName = arguments[4];
|
||||
|
||||
final _sourcePath = path.join(_apps, _appName);
|
||||
final _targetPath = path.join(_bricks, _appName, '__brick__');
|
||||
|
||||
final _androidPath = path.join(_targetPath, 'android');
|
||||
final _androidKotlinPath =
|
||||
path.join(_androidPath, 'app', 'src', 'main', 'kotlin');
|
||||
final _orgPath = path.join(_androidKotlinPath, 'com');
|
||||
|
||||
// Remove Previously Generated Files
|
||||
final targetDir = Directory(_targetPath);
|
||||
if (targetDir.existsSync()) {
|
||||
await targetDir.delete(recursive: true);
|
||||
}
|
||||
|
||||
// Copy Project Files
|
||||
await Shell.cp(_sourcePath, _targetPath);
|
||||
|
||||
// Delete Android's Organization Folder Hierarchy
|
||||
Directory(_orgPath).deleteSync(recursive: true);
|
||||
|
||||
// Convert Values to Variables
|
||||
await Future.wait(
|
||||
Directory(_targetPath)
|
||||
.listSync(recursive: true)
|
||||
.whereType<File>()
|
||||
.map((_) async {
|
||||
var file = _;
|
||||
|
||||
try {
|
||||
|
||||
if (path.extension(file.path) == '.dart') {
|
||||
final contents = await file.readAsString();
|
||||
file = await file.writeAsString(contents);
|
||||
}
|
||||
|
||||
final contents = await file.readAsString();
|
||||
file = await file.writeAsString(
|
||||
contents
|
||||
.replaceAll(
|
||||
_projectSnakeName,
|
||||
'{{#snakeCase}}{{project_name}}{{/snakeCase}}',
|
||||
)
|
||||
.replaceAll(
|
||||
_projectParamName,
|
||||
'{{#paramCase}}{{project_name}}{{/paramCase}}',
|
||||
)
|
||||
.replaceAll('A new Flutter project.', '{{{description}}}')
|
||||
.replaceAll(
|
||||
_projectTitleName,
|
||||
'{{#titleCase}}{{project_name}}{{/titleCase}}',
|
||||
)
|
||||
.replaceAll(
|
||||
_orgName,
|
||||
path.isWithin(_androidPath, file.path)
|
||||
? '{{#dotCase}}{{org_name}}{{/dotCase}}.{{#snakeCase}}{{project_name}}{{/snakeCase}}'
|
||||
: '{{#dotCase}}{{org_name}}{{/dotCase}}.{{#paramCase}}{{project_name}}{{/paramCase}}',
|
||||
),
|
||||
);
|
||||
final fileSegments = file.path.split('/').sublist(2);
|
||||
if (fileSegments.contains(_projectSnakeName)) {
|
||||
final newPathSegment = fileSegments.join('/').replaceAll(
|
||||
_projectSnakeName,
|
||||
'{{#snakeCase}}{{project_name}}{{/snakeCase}}',
|
||||
);
|
||||
final newPath = path.join(_targetPath, newPathSegment);
|
||||
File(newPath).createSync(recursive: true);
|
||||
file.renameSync(newPath);
|
||||
Directory(file.parent.path).deleteSync(recursive: true);
|
||||
}
|
||||
} catch (_) {}
|
||||
}),
|
||||
);
|
||||
|
||||
final mainActivityKt = File(
|
||||
path.join(
|
||||
_androidKotlinPath,
|
||||
'{{#pathCase}}{{org_name}}{{/pathCase}}',
|
||||
'MainActivity.kt',
|
||||
),
|
||||
);
|
||||
|
||||
await Shell.mkdir(mainActivityKt.parent.path);
|
||||
await Shell.cp(path.join(_staticDir, 'MainActivity.kt'), mainActivityKt.path);
|
||||
}
|
52
tools/brick_generator/lib/shell.dart
Normal file
52
tools/brick_generator/lib/shell.dart
Normal file
@ -0,0 +1,52 @@
|
||||
import 'dart:io';
|
||||
|
||||
class Shell {
|
||||
static Future<void> cp(String source, String destination) {
|
||||
return _Cmd.run('cp', ['-Rf', source, destination]);
|
||||
}
|
||||
|
||||
static Future<void> mkdir(String destination) {
|
||||
return _Cmd.run('mkdir', ['-p', destination]);
|
||||
}
|
||||
}
|
||||
|
||||
class _Cmd {
|
||||
static Future<ProcessResult> run(
|
||||
String cmd,
|
||||
List<String> args, {
|
||||
bool throwOnError = true,
|
||||
String? processWorkingDir,
|
||||
}) async {
|
||||
final result = await Process.run(cmd, args,
|
||||
workingDirectory: processWorkingDir, runInShell: true);
|
||||
|
||||
if (throwOnError) {
|
||||
_throwIfProcessFailed(result, cmd, args);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void _throwIfProcessFailed(
|
||||
ProcessResult pr,
|
||||
String process,
|
||||
List<String> args,
|
||||
) {
|
||||
if (pr.exitCode != 0) {
|
||||
final values = {
|
||||
'Standard out': pr.stdout.toString().trim(),
|
||||
'Standard error': pr.stderr.toString().trim()
|
||||
}..removeWhere((k, v) => v.isEmpty);
|
||||
|
||||
String message;
|
||||
if (values.isEmpty) {
|
||||
message = 'Unknown error';
|
||||
} else if (values.length == 1) {
|
||||
message = values.values.single;
|
||||
} else {
|
||||
message = values.entries.map((e) => '${e.key}\n${e.value}').join('\n');
|
||||
}
|
||||
|
||||
throw ProcessException(process, args, message, pr.exitCode);
|
||||
}
|
||||
}
|
||||
}
|
11
tools/brick_generator/pubspec.yaml
Normal file
11
tools/brick_generator/pubspec.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
name: brick_generator
|
||||
description: A template generator from real app.
|
||||
version: 1.0.0
|
||||
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: '>=2.17.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
path: ^1.8.2
|
Loading…
x
Reference in New Issue
Block a user