work on brick generator dart script

This commit is contained in:
Malo Léon 2022-08-07 23:31:22 +01:00
parent 4f86d6dbbd
commit fbe7abcc4f
5 changed files with 178 additions and 121 deletions

View File

@ -1,6 +1,38 @@
A sample command-line application with an entrypoint in `bin/`, library code
A sample command-line application to generate which allows to generate the template of a brick from a project which compiles. with an entrypoint in `bin/`, library code
in `lib/`.
# How to use
- Add your app in `apps`.
- Add `brick_config.yaml` in you app folder and add this fields :
```yaml
brick_name: wyatt_feature_brick
project_name: projet_name
path_to_brickify: lib/feature_brick_test_folder
syntax:
camel_case: featureBrick
constant_case: FEATURE_BRICK
dot_case: feature.brick
header_case: Feature-Brick
lower_case: feature brick
pascal_case: FeatureBrick
param_case: feature-brick
sentence_case: Feature brick
snake_case: feature_brick
title_case: Feature Brick
upper_case: FEATURE BRICK
```
then run command with project path
```sh
dart /bin/brick_generator.dart wyatt_clean_code wyatt_clean_code wyatt-clean-code "Wyatt Demo" app.wyatt.io
```
dart tools/brick_generator/bin/brick_generator.dart ./apps/wyatt_feature_brick
```
# TODO
- Work on bool variables
- Add several variables (here only one is possible)

View File

@ -1,30 +1 @@
# 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
include: package:wyatt_analysis/analysis_options.yaml

View File

@ -1,102 +1,141 @@
import 'dart:io';
import 'package:brick_generator/shell.dart';
import 'package:brick_generator/yaml_reader.dart';
import 'package:path/path.dart' as path;
import 'package:yaml/yaml.dart';
// Keys
enum Syntax {
camelCase('camel_case', 'camelCase'),
constantCase('constant_case', 'constantCase'),
dotCase('dot_case', 'dotCase'),
headerCase('header_case', 'headerCase'),
lowerCase('lower_case', 'lowerCase'),
pascalCase('pascal_case', 'pascalCase'),
paramCase('param_case', 'paramCase'),
sentenceCase('sentence_case', 'sentenceCase'),
snakeCase('snake_case', 'snakeCase'),
titleCase('title_case', 'titleCase'),
upperCase('upper_case', 'upperCase');
final String mapKey;
final String id;
const Syntax(this.mapKey, this.id);
}
// Other Keys
const _projectNameKey = 'project_name';
const _brickNameKey = 'brick_name';
const _pathToBrickifyKey = 'path_to_brickify';
const _syntaxKey = 'syntax';
// Constants
final _apps = 'apps';
final _bricks = 'bricks';
final _staticDir = path.join('tools', 'brick_generator', 'assets');
const _bricks = 'bricks';
const _brickFolderLabel = '__brick__';
const _yamlFileName = 'brick_config.yaml';
Future<void> main(List<String> arguments) async {
final _appName = arguments[0];
try {
if (arguments.length != 1) {
throw ArgumentError('Please entry exemple project path');
}
final _projectSnakeName = arguments[1];
final _projectParamName = arguments[2];
final _projectTitleName = arguments[3];
final _orgName = arguments[4];
final projectPath = arguments[0];
final _sourcePath = path.join(_apps, _appName);
final _targetPath = path.join(_bricks, _appName, '__brick__');
// Store options from yaml file
final option =
YamlReader.readYamlFile(path.join(projectPath, _yamlFileName));
final syntaxMap = option[_syntaxKey] as YamlMap;
stdout.writeln('🍺 get options $syntaxMap');
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}}',
),
for (final syntax in Syntax.values) {
if (syntaxMap[syntax.mapKey] == null) {
throw ArgumentError(
'Yaml file is not conform : ${syntax.toString()} is missing',
);
final fileSegments = file.path.split('/').sublist(2);
if (fileSegments.contains(_projectSnakeName)) {
final newPathSegment = fileSegments.join('/').replaceAll(
_projectSnakeName,
'{{#snakeCase}}{{project_name}}{{/snakeCase}}',
}
}
final projectName = option[_projectNameKey] as String;
final brickName = option[_brickNameKey] as String;
// Define paths
final sourcePath =
path.join(projectPath, option[_pathToBrickifyKey] as String);
final targetPath = path.join(_bricks, brickName, _brickFolderLabel);
stdout.writeln('🍺 path defined');
// Remove previously generated files
final targetDir = Directory(targetPath);
if (targetDir.existsSync()) {
await targetDir.delete(recursive: true);
}
// create target folder
await Shell.mkdir(targetPath);
// Copy project files
await Shell.cp(sourcePath, targetPath);
stdout.writeln('🍺 files copied');
// Convert values to variables
await Future.wait(
Directory(targetPath)
.listSync(recursive: true)
.whereType<File>()
.map((_) async {
var file = _;
try {
var contents = await file.readAsString();
// Transform all values in variables
for (final syntax in Syntax.values) {
contents = contents.replaceAll(
syntaxMap[syntax.mapKey] as String,
'{{#${syntax.id}}}{{$projectName}}{{/${syntax.id}}}',
);
}
file = await file.writeAsString(contents);
// Rename file if needed
final filePath = file.path;
if (filePath.contains(syntaxMap[Syntax.snakeCase.mapKey] as String)) {
try {
var pathList = filePath.split(Platform.pathSeparator).sublist(3);
pathList = pathList
.map(
(segment) => segment.replaceAll(
syntaxMap[Syntax.snakeCase.mapKey] as String,
'{{$projectName.snakeCase()}}',
),
)
.toList();
final newPath = path.join(
filePath
.split(Platform.pathSeparator)
.sublist(0, 3)
.join(Platform.pathSeparator),
pathList.join(Platform.pathSeparator),
);
final newPath = path.join(_targetPath, newPathSegment);
File(newPath).createSync(recursive: true);
file.renameSync(newPath);
Directory(file.parent.path).deleteSync(recursive: true);
File(newPath).createSync(recursive: true);
file.renameSync(newPath);
Directory(file.parent.path).deleteSync(recursive: true);
} catch (_) {
stdout.writeln('${_.toString()}');
}
}
} catch (_) {
stdout.writeln('${_.toString()}');
}
} 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);
}),
);
} catch (_) {
stdout.writeln('${_.toString()}');
}
}

View File

@ -0,0 +1,7 @@
import 'dart:io';
import 'package:yaml/yaml.dart';
class YamlReader {
static YamlMap readYamlFile(String path) =>
loadYaml(File(path).readAsStringSync()) as YamlMap;
}

View File

@ -5,7 +5,15 @@ version: 1.0.0
publish_to: none
environment:
sdk: '>=2.17.0 <3.0.0'
sdk: ">=2.17.0 <3.0.0"
dependencies:
path: ^1.8.2
yaml: ^3.1.1
dev_dependencies:
wyatt_analysis:
git:
url: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages
ref: wyatt_analysis-v2.1.0
path: packages/wyatt_analysis