feat: add boolean file system support
This commit is contained in:
parent
18aeef9e35
commit
77e60213f9
@ -2,42 +2,365 @@
|
|||||||
|
|
||||||
A simple command-line application which allows to generate the template of a brick from a project which compiles.
|
A simple command-line application which allows to generate the template of a brick from a project which compiles.
|
||||||
|
|
||||||
With an entrypoint in `bin/`, library code in `lib/`.
|
With an entrypoint in `bin/` , library code in `lib/` .
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
|
||||||
|
* Add your app in `apps/`.
|
||||||
- Add your app in `apps/`.
|
* Add `brickgen.yaml` in you app folder and add this fields:
|
||||||
- Add `brick_config.yaml` in you app folder and add this fields:
|
|
||||||
|
|
||||||
> Here we have created `wyatt_feature_brick` app in `apps/`
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
name: wyatt_feature_brick
|
name: brick_name
|
||||||
description: New feature brick including state mananement
|
description: An awesome brick
|
||||||
path_to_brickify: lib/feature_name
|
|
||||||
|
|
||||||
version: 0.1.1
|
version: 0.1.0
|
||||||
|
|
||||||
vars:
|
vars:
|
||||||
feature_name:
|
bundle_id:
|
||||||
|
compilable: io.wyattapp.new
|
||||||
type: string
|
type: string
|
||||||
name: feature_name
|
description: The bundle id used in Android and iOS
|
||||||
description: Name of the feature
|
default: io.wyattapp.new
|
||||||
default: Dash
|
prompt: "What is the bundle id?"
|
||||||
prompt: What is the name of your new feature
|
|
||||||
|
flutter:
|
||||||
|
type: boolean
|
||||||
|
description: If this app is a Flutter or Dart project.
|
||||||
|
default: false
|
||||||
|
prompt: "Is it Flutter app ?"
|
||||||
|
|
||||||
|
brickgen:
|
||||||
|
path_to_brickify: brick_folder
|
||||||
|
ignore:
|
||||||
|
- .env
|
||||||
|
- node_modules/
|
||||||
|
hooks: true
|
||||||
|
boolean_file_system:
|
||||||
|
flutter:
|
||||||
|
folders:
|
||||||
|
on_true:
|
||||||
|
- android
|
||||||
|
- ios
|
||||||
|
on_false:
|
||||||
|
- bin
|
||||||
|
files:
|
||||||
|
on_true:
|
||||||
|
- l10n.yaml
|
||||||
|
- trapeze.yaml
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
then run command with project path
|
Project structure must be like:
|
||||||
|
|
||||||
|
```
|
||||||
|
apps
|
||||||
|
├── brick_name
|
||||||
|
│ ├── brickgen.yaml
|
||||||
|
│ ├── hooks
|
||||||
|
│ │ └── pre_gen.dart
|
||||||
|
│ ├── brick_folder
|
||||||
|
│ │ └── ... compilable project
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run command with project path
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
dart tools/brick_generator/bin/brick_generator.dart ./apps/wyatt_feature_brick
|
dart ./tools/brick_generator/bin/brickgen.dart ./apps/brick_name
|
||||||
```
|
```
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- [ ] bool variables
|
* [ ] hooks
|
||||||
- [ ] enum variables
|
- [x] post hooks
|
||||||
- [ ] array variables
|
- [x] pre hooks
|
||||||
- [ ] pre hooks
|
- [ ] add partial hooks
|
||||||
- [ ] post hooks
|
* [ ] bool variables
|
||||||
|
- [x] boolean file system
|
||||||
|
- [ ] boolean mapping
|
||||||
|
* [ ] enum variables
|
||||||
|
* [ ] array variables
|
||||||
|
|
||||||
|
## Current specification
|
||||||
|
|
||||||
|
### File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
apps
|
||||||
|
├── <brick_name>
|
||||||
|
│ ├── brickgen.yaml
|
||||||
|
│ ├── hooks
|
||||||
|
│ │ └── pre_gen.dart
|
||||||
|
│ ├── <brick_folder>
|
||||||
|
│ │ └── ... compilable project
|
||||||
|
```
|
||||||
|
|
||||||
|
### Brick (Mason)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: <brick_name>
|
||||||
|
description: <brick_description>
|
||||||
|
|
||||||
|
version: 0.1.0
|
||||||
|
|
||||||
|
vars:
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
- name: the brick name (will be in `brick.yaml`)
|
||||||
|
- description: the brick description (will be in `brick.yaml`)
|
||||||
|
- version: the brick version (will be in `brick.yaml`)
|
||||||
|
- vars: the brick variables (will be in `brick.yaml`)
|
||||||
|
|
||||||
|
#### String variable
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name:
|
||||||
|
compilable: <compilable>
|
||||||
|
type: string
|
||||||
|
description: <description>
|
||||||
|
default: <default>
|
||||||
|
prompt: <prompt>
|
||||||
|
```
|
||||||
|
|
||||||
|
- name: the variable name (will be in `brick.yaml`)
|
||||||
|
- compilable: the variable compilable name used in brickgen project
|
||||||
|
- type: variable type, here string, (will be in `brick.yaml`)
|
||||||
|
- default: default value (will be in `brick.yaml`)
|
||||||
|
- prompt: the displayed prompt at the brick generation (will be in `brick.yaml`)
|
||||||
|
|
||||||
|
#### Boolean variable
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name:
|
||||||
|
type: boolean
|
||||||
|
description: <description>
|
||||||
|
default: <default>
|
||||||
|
prompt: <prompt>
|
||||||
|
```
|
||||||
|
|
||||||
|
- name: the variable name (will be in `brick.yaml`)
|
||||||
|
- type: variable type, here string, (will be in `brick.yaml`)
|
||||||
|
- default: default value (will be in `brick.yaml`)
|
||||||
|
- prompt: the displayed prompt at the brick generation (will be in `brick.yaml`)
|
||||||
|
|
||||||
|
> Identical to Mason
|
||||||
|
|
||||||
|
### Brickgen
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
brickgen:
|
||||||
|
path_to_brickify: <brick_folder>
|
||||||
|
ignore:
|
||||||
|
- ...
|
||||||
|
hooks: true
|
||||||
|
boolean_file_system:
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
- path_to_brickify: the path of the compilable project that will be brickified
|
||||||
|
- ignore: list of the ignored files and folders.
|
||||||
|
- be sure to add an `/` at the end of the folders name.
|
||||||
|
- hooks: copy or not `hooks` folder
|
||||||
|
- boolean_file_system: list of the boolean file system variables
|
||||||
|
|
||||||
|
#### Boolean File System
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
boolean_file_system:
|
||||||
|
boolean:
|
||||||
|
folders:
|
||||||
|
on_true:
|
||||||
|
- ...
|
||||||
|
on_false:
|
||||||
|
- ...
|
||||||
|
files:
|
||||||
|
on_true:
|
||||||
|
- ...
|
||||||
|
on_false:
|
||||||
|
- ...
|
||||||
|
```
|
||||||
|
|
||||||
|
- boolean: name of the `boolean` variable used.
|
||||||
|
- folders
|
||||||
|
- on_true: list of the folders includes if the variable is `true`
|
||||||
|
- on_true: list of the folders includes if the variable is `false`
|
||||||
|
- files
|
||||||
|
- on_true: list of the files includes if the variable is `true`
|
||||||
|
- on_true: list of the files includes if the variable is `false`
|
||||||
|
|
||||||
|
> `on_true` and `on_false` are optionnal. (You are allowed to set one or two of them).
|
||||||
|
|
||||||
|
## Specifications (WIP)
|
||||||
|
|
||||||
|
File structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
apps
|
||||||
|
├── <brick_name>
|
||||||
|
│ ├── brickgen.yaml
|
||||||
|
│ ├── hooks
|
||||||
|
│ │ └── pre_gen.dart
|
||||||
|
│ ├── <brick_folder>
|
||||||
|
│ │ └── ... compilable project
|
||||||
|
```
|
||||||
|
|
||||||
|
Configuration: `brickgen.yaml`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: <brick_name>
|
||||||
|
description: <brick_description>
|
||||||
|
|
||||||
|
version: 0.1.0
|
||||||
|
|
||||||
|
vars:
|
||||||
|
display_name:
|
||||||
|
compilable: Display Name
|
||||||
|
type: string
|
||||||
|
description: The display name
|
||||||
|
default: Display Name
|
||||||
|
prompt: "What is the display name?"
|
||||||
|
|
||||||
|
project_name:
|
||||||
|
compilable: wyatt_app_template
|
||||||
|
type: string
|
||||||
|
description: The project name
|
||||||
|
default: wyatt_app
|
||||||
|
prompt: "What is the project name?"
|
||||||
|
|
||||||
|
bundle_id:
|
||||||
|
compilable: io.wyattapp.new
|
||||||
|
type: string
|
||||||
|
description: The bundle id used in Android and iOS
|
||||||
|
default: io.wyattapp.new
|
||||||
|
prompt: "What is the bundle id?"
|
||||||
|
|
||||||
|
flutter:
|
||||||
|
type: boolean
|
||||||
|
description: If this app is a Flutter or Dart project.
|
||||||
|
default: false
|
||||||
|
prompt: "Is it Flutter app ?"
|
||||||
|
|
||||||
|
brickgen:
|
||||||
|
path_to_brickify: <brick_folder>
|
||||||
|
ignore:
|
||||||
|
- .env
|
||||||
|
- node_modules/
|
||||||
|
hooks: true
|
||||||
|
boolean_mapping:
|
||||||
|
flutter:
|
||||||
|
folders:
|
||||||
|
- "test":
|
||||||
|
on_true: "test"
|
||||||
|
on_false: "test_dart"
|
||||||
|
files:
|
||||||
|
- "pubspec.yaml":
|
||||||
|
on_true: pubspec.yaml
|
||||||
|
on_false: pubspec.dart.yaml
|
||||||
|
boolean_file_system:
|
||||||
|
flutter:
|
||||||
|
folders:
|
||||||
|
on_true:
|
||||||
|
- android
|
||||||
|
- ios
|
||||||
|
on_false:
|
||||||
|
- bin
|
||||||
|
files:
|
||||||
|
on_true:
|
||||||
|
- l10n.yaml
|
||||||
|
- trapeze.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Will generate:
|
||||||
|
|
||||||
|
```
|
||||||
|
bricks
|
||||||
|
├── <brick_name>
|
||||||
|
│ ├── brick.yaml
|
||||||
|
│ ├── hooks
|
||||||
|
│ │ └── pre_gen.dart
|
||||||
|
│ ├── __brick__
|
||||||
|
│ │ └── <brick_folder>
|
||||||
|
```
|
||||||
|
|
||||||
|
> It creates a sub folder in __brick__
|
||||||
|
|
||||||
|
|
||||||
|
### How copy works
|
||||||
|
|
||||||
|
- Case 1
|
||||||
|
|
||||||
|
```
|
||||||
|
apps
|
||||||
|
├── brick_1
|
||||||
|
│ ├── brickgen.yaml
|
||||||
|
│ ├── hooks
|
||||||
|
│ │ └── pre_gen.dart
|
||||||
|
│ ├── brick_1
|
||||||
|
│ │ ├── lib/
|
||||||
|
│ │ └── pubspec.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
...
|
||||||
|
name: awesome_brick_1
|
||||||
|
brickgen:
|
||||||
|
path_to_brickify: brick_1
|
||||||
|
hooks: true
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dart ./tools/brick_generator/bin/brickgen.dart ./apps/brick_1
|
||||||
|
```
|
||||||
|
|
||||||
|
Will generate:
|
||||||
|
|
||||||
|
```
|
||||||
|
bricks
|
||||||
|
├── awesome_brick_1
|
||||||
|
│ ├── brick.yaml
|
||||||
|
│ ├── hooks
|
||||||
|
│ │ └── pre_gen.dart
|
||||||
|
│ ├── __brick__
|
||||||
|
│ │ ├── lib/
|
||||||
|
│ │ └── pubspec.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
- Case 2
|
||||||
|
|
||||||
|
```
|
||||||
|
apps
|
||||||
|
├── brick_2
|
||||||
|
│ ├── brickgen.yaml
|
||||||
|
│ ├── hooks
|
||||||
|
│ │ └── pre_gen.dart
|
||||||
|
│ ├── brick_2
|
||||||
|
│ │ ├── lib
|
||||||
|
│ │ │ └── widget.dart
|
||||||
|
│ │ └── pubspec.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
...
|
||||||
|
name: awesome_brick_2
|
||||||
|
brickgen:
|
||||||
|
path_to_brickify: brick_2/lib
|
||||||
|
hooks: false
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dart ./tools/brick_generator/bin/brickgen.dart ./apps/brick_2
|
||||||
|
```
|
||||||
|
|
||||||
|
Will generate:
|
||||||
|
|
||||||
|
```
|
||||||
|
bricks
|
||||||
|
├── awesome_brick_2
|
||||||
|
│ ├── brick.yaml
|
||||||
|
│ ├── __brick__
|
||||||
|
│ │ └── widget.dart
|
||||||
|
```
|
@ -1,30 +0,0 @@
|
|||||||
name: <brick_name>
|
|
||||||
description: <brick_description>
|
|
||||||
|
|
||||||
version: 0.1.0
|
|
||||||
|
|
||||||
vars:
|
|
||||||
display_name:
|
|
||||||
type: string
|
|
||||||
description: The display name
|
|
||||||
default: Display Name
|
|
||||||
prompt: What is the display name?
|
|
||||||
|
|
||||||
project_name:
|
|
||||||
type: string
|
|
||||||
description: The project name
|
|
||||||
default: wyatt_app
|
|
||||||
prompt: What is the project name?
|
|
||||||
|
|
||||||
bundle_id:
|
|
||||||
type: string
|
|
||||||
description: The bundle id used in Android and iOS
|
|
||||||
default: io.wyattapp.new
|
|
||||||
prompt: What is the bundle id?
|
|
||||||
|
|
||||||
flutter:
|
|
||||||
type: boolean
|
|
||||||
description: If this app is a Flutter or Dart project.
|
|
||||||
default: false
|
|
||||||
prompt: Is it Flutter app ?
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:brick_generator/core/logger.dart';
|
|
||||||
import 'package:brick_generator/core/shell.dart';
|
|
||||||
import 'package:brick_generator/file_system_utils.dart';
|
|
||||||
import 'package:brick_generator/models/brick_config.dart';
|
|
||||||
import 'package:brick_generator/yaml_reader.dart';
|
|
||||||
import 'package:path/path.dart' as path;
|
|
||||||
|
|
||||||
// Constants
|
|
||||||
const _bricks = 'bricks';
|
|
||||||
const _brickFolderLabel = '__brick__';
|
|
||||||
const _yamlFileName = 'brick_config.yaml';
|
|
||||||
const _cfgFileName = 'brick.yaml';
|
|
||||||
|
|
||||||
Future<void> main(List<String> arguments) async {
|
|
||||||
try {
|
|
||||||
if (arguments.length != 1) {
|
|
||||||
Logger.error('Please provide project path.');
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
final projectPath = arguments[0];
|
|
||||||
|
|
||||||
// Store options from yaml file
|
|
||||||
final configs =
|
|
||||||
YamlReader.readYamlFile(path.join(projectPath, _yamlFileName));
|
|
||||||
final brickConfig = BrickConfig.from(configs);
|
|
||||||
Logger.info('Config retrieved.');
|
|
||||||
|
|
||||||
brickConfig?.checkFormat();
|
|
||||||
|
|
||||||
// Define paths
|
|
||||||
final sourcePath = path.join(
|
|
||||||
projectPath,
|
|
||||||
brickConfig!.pathToBrickify,
|
|
||||||
);
|
|
||||||
final cfgTarget = path.join(
|
|
||||||
_bricks,
|
|
||||||
brickConfig.name,
|
|
||||||
_cfgFileName,
|
|
||||||
);
|
|
||||||
final targetPath = path.join(
|
|
||||||
_bricks,
|
|
||||||
brickConfig.name,
|
|
||||||
_brickFolderLabel,
|
|
||||||
);
|
|
||||||
Logger.info('Path defined.');
|
|
||||||
|
|
||||||
// Remove previously generated files
|
|
||||||
final targetDir = Directory(targetPath);
|
|
||||||
if (targetDir.existsSync()) {
|
|
||||||
await targetDir.delete(recursive: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
final cfgTargetFile = File(cfgTarget);
|
|
||||||
if (cfgTargetFile.existsSync()) {
|
|
||||||
await cfgTargetFile.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
// create target folder
|
|
||||||
await Shell.mkdir(targetPath);
|
|
||||||
|
|
||||||
// Copy project files
|
|
||||||
await Shell.cp(sourcePath, targetPath);
|
|
||||||
Logger.info('Files copied.');
|
|
||||||
|
|
||||||
// Remove ignored folders
|
|
||||||
final brickPath = path.join(targetPath, brickConfig.pathToBrickify);
|
|
||||||
await FileSystemUtils.deleteIgnoredFolders(brickConfig, brickPath);
|
|
||||||
|
|
||||||
// Convert values to variables
|
|
||||||
await FileSystemUtils.convertValuesToVariablesInFolder(
|
|
||||||
brickConfig,
|
|
||||||
targetPath,
|
|
||||||
);
|
|
||||||
Logger.info('Values converted into variables.');
|
|
||||||
|
|
||||||
// Rename files and folders
|
|
||||||
await FileSystemUtils.renamePathsInFolder(brickConfig, targetPath);
|
|
||||||
Logger.info('Folders and files renamed.');
|
|
||||||
|
|
||||||
// Create config file
|
|
||||||
cfgTargetFile.writeAsStringSync(brickConfig.toBrickYaml());
|
|
||||||
Logger.info('brick.yml added.');
|
|
||||||
|
|
||||||
await FileSystemUtils.deleteEmptyFolders(targetPath);
|
|
||||||
Logger.info('Empty folders removed');
|
|
||||||
Logger.success('Brick template available at $targetPath');
|
|
||||||
} catch (e) {
|
|
||||||
Logger.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,6 +26,7 @@ import 'package:path/path.dart';
|
|||||||
const _configurationFileName = 'brickgen.yaml';
|
const _configurationFileName = 'brickgen.yaml';
|
||||||
const _masonConfigurationFileName = 'brick.yaml';
|
const _masonConfigurationFileName = 'brick.yaml';
|
||||||
const _brickFolderName = '__brick__';
|
const _brickFolderName = '__brick__';
|
||||||
|
const _hooksFolderName = 'hooks';
|
||||||
|
|
||||||
const _helpOption = 'help';
|
const _helpOption = 'help';
|
||||||
const _verboseOption = 'verbose';
|
const _verboseOption = 'verbose';
|
||||||
@ -37,10 +38,12 @@ class Brickgen {
|
|||||||
final bool deleteEmptyFolders;
|
final bool deleteEmptyFolders;
|
||||||
|
|
||||||
late String configPath;
|
late String configPath;
|
||||||
|
late String hooksInputPath;
|
||||||
|
|
||||||
String? toBrickifyPath;
|
String? toBrickifyPath;
|
||||||
String? masonConfigPath;
|
String? masonConfigPath;
|
||||||
String? targetPath;
|
String? targetPath;
|
||||||
|
String? hooksOutputPath;
|
||||||
|
|
||||||
Brickgen({
|
Brickgen({
|
||||||
required this.brickPath,
|
required this.brickPath,
|
||||||
@ -48,6 +51,7 @@ class Brickgen {
|
|||||||
required this.deleteEmptyFolders,
|
required this.deleteEmptyFolders,
|
||||||
}) {
|
}) {
|
||||||
configPath = join(brickPath, _configurationFileName);
|
configPath = join(brickPath, _configurationFileName);
|
||||||
|
hooksInputPath = join(brickPath, _hooksFolderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> run() async {
|
Future<void> run() async {
|
||||||
@ -70,6 +74,13 @@ class Brickgen {
|
|||||||
);
|
);
|
||||||
Logger.debug('Define `masonConfigPath`: $masonConfigPath');
|
Logger.debug('Define `masonConfigPath`: $masonConfigPath');
|
||||||
|
|
||||||
|
hooksOutputPath = FileSystem.joinRecreate(
|
||||||
|
outputPath,
|
||||||
|
config.name,
|
||||||
|
_hooksFolderName,
|
||||||
|
);
|
||||||
|
Logger.debug('Define `hooksOutputPath`: $hooksOutputPath');
|
||||||
|
|
||||||
targetPath = FileSystem.joinRecreate(
|
targetPath = FileSystem.joinRecreate(
|
||||||
outputPath,
|
outputPath,
|
||||||
config.name,
|
config.name,
|
||||||
@ -78,7 +89,8 @@ class Brickgen {
|
|||||||
Logger.debug('Define `targetPath`: $targetPath');
|
Logger.debug('Define `targetPath`: $targetPath');
|
||||||
|
|
||||||
// Check paths
|
// Check paths
|
||||||
if (toBrickifyPath == null || targetPath == null) {
|
if (toBrickifyPath == null || targetPath == null
|
||||||
|
|| masonConfigPath == null || hooksOutputPath == null) {
|
||||||
throw Exception('An error occures during path definition.');
|
throw Exception('An error occures during path definition.');
|
||||||
}
|
}
|
||||||
Logger.info('Paths defined.');
|
Logger.info('Paths defined.');
|
||||||
@ -91,6 +103,11 @@ class Brickgen {
|
|||||||
);
|
);
|
||||||
Logger.info('Project copied.');
|
Logger.info('Project copied.');
|
||||||
|
|
||||||
|
// Take care of boolean mapping and boolean fs
|
||||||
|
FileSystem.applyBooleanFileSystem(config, targetPath!);
|
||||||
|
Logger.info('Boolean file system applied.');
|
||||||
|
// TODO(wyatt): generate hook to handle boolean mapping.
|
||||||
|
|
||||||
// Convert compilable values -> variables (in files)
|
// Convert compilable values -> variables (in files)
|
||||||
FileSystem.convertCompilableVariablesInFolder(config, targetPath!);
|
FileSystem.convertCompilableVariablesInFolder(config, targetPath!);
|
||||||
Logger.info('Files content converted with variables.');
|
Logger.info('Files content converted with variables.');
|
||||||
@ -109,17 +126,16 @@ class Brickgen {
|
|||||||
FileSystem.renameCompilableFilesInFolder(config, targetPath!);
|
FileSystem.renameCompilableFilesInFolder(config, targetPath!);
|
||||||
Logger.info('Files renamed with variables.');
|
Logger.info('Files renamed with variables.');
|
||||||
|
|
||||||
// Take care of boolean mapping and boolean fs
|
|
||||||
|
|
||||||
// Create Mason config
|
// Create Mason config
|
||||||
FileSystem.writeFile(masonConfigPath!, config.toMason());
|
FileSystem.writeFile(masonConfigPath!, config.toMason());
|
||||||
Logger.info('Mason `brick.yaml` generated.');
|
Logger.info('Mason `brick.yaml` generated.');
|
||||||
|
|
||||||
// Create gitkeep hook
|
// Copy hooks
|
||||||
|
await FileSystem.copyHooks(config, hooksInputPath, hooksOutputPath!);
|
||||||
// Copy custom hooks
|
|
||||||
|
|
||||||
// Success!
|
// Success!
|
||||||
|
Logger.success('Brick template available at $targetPath');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ abstract class FileSystem {
|
|||||||
if (toReplace != null && file.path.contains(toReplace)) {
|
if (toReplace != null && file.path.contains(toReplace)) {
|
||||||
final newPath = file.path.replaceAll(
|
final newPath = file.path.replaceAll(
|
||||||
toReplace,
|
toReplace,
|
||||||
'{{${variable.name}.${syntax.id}}}',
|
'{{${variable.name}.${syntax.id}()}}',
|
||||||
);
|
);
|
||||||
|
|
||||||
File(newPath).createSync(recursive: true);
|
File(newPath).createSync(recursive: true);
|
||||||
@ -354,4 +354,124 @@ abstract class FileSystem {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<void> copyHooks(
|
||||||
|
BrickConfig config,
|
||||||
|
String source,
|
||||||
|
String targetPath,
|
||||||
|
) async {
|
||||||
|
if (!config.brickgenConfig.hooks) {
|
||||||
|
Logger.debug('Ignore hooks');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FileSystemEntity.isDirectorySync(source)) {
|
||||||
|
throw ArgumentError('Source must be a directory', 'source');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FileSystemEntity.isDirectorySync(targetPath)) {
|
||||||
|
throw ArgumentError('Target must be a directory', 'targetPath');
|
||||||
|
}
|
||||||
|
|
||||||
|
await copyFolder(source, targetPath);
|
||||||
|
Logger.info('Hooks copied.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Apply boolean file system: create or not folders/files depending of
|
||||||
|
/// a boolean variable.
|
||||||
|
///
|
||||||
|
/// Example
|
||||||
|
/// ```yaml
|
||||||
|
/// boolean_file_system:
|
||||||
|
/// flutter:
|
||||||
|
/// folders:
|
||||||
|
/// on_true:
|
||||||
|
/// - android
|
||||||
|
/// - ios
|
||||||
|
/// - assets
|
||||||
|
/// on_false:
|
||||||
|
/// - bin
|
||||||
|
/// files:
|
||||||
|
/// on_true:
|
||||||
|
/// - l10n.yaml
|
||||||
|
/// - trapeze.yaml
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Creates some folders and files depending of `flutter` variable.
|
||||||
|
static void applyBooleanFileSystem(
|
||||||
|
BrickConfig config,
|
||||||
|
String targetPath,
|
||||||
|
) {
|
||||||
|
for (final variable in config.brickgenConfig.booleanFileSystem) {
|
||||||
|
final boolean = variable.booleanName;
|
||||||
|
|
||||||
|
String rename(
|
||||||
|
String boolean,
|
||||||
|
FileSystemEntity entity, {
|
||||||
|
bool? onValue,
|
||||||
|
}) {
|
||||||
|
final entityPath = entity.path;
|
||||||
|
final entityPathSplitted =
|
||||||
|
(entityPath.split('/')..removeWhere((element) => element.isEmpty));
|
||||||
|
final entityRenamed =
|
||||||
|
'{{${(onValue ?? true) ? "#" : "^"}$boolean}}${entityPathSplitted.last}{{/$boolean}}';
|
||||||
|
final entityNewPath =
|
||||||
|
((entityPathSplitted..removeLast())..add(entityRenamed)).join('/');
|
||||||
|
|
||||||
|
Logger.debug('Apply boolean file system on $entityPath');
|
||||||
|
|
||||||
|
return entityNewPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename folders
|
||||||
|
for (final folder in variable.folders.onTrueNames) {
|
||||||
|
final directory = Directory(join(targetPath, folder));
|
||||||
|
final newPath = rename(
|
||||||
|
boolean,
|
||||||
|
directory,
|
||||||
|
onValue: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
Directory(newPath).createSync(recursive: true);
|
||||||
|
directory.renameSync(newPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final folder in variable.folders.onFalseNames) {
|
||||||
|
final directory = Directory(join(targetPath, folder));
|
||||||
|
final newPath = rename(
|
||||||
|
boolean,
|
||||||
|
directory,
|
||||||
|
onValue: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
Directory(newPath).createSync(recursive: true);
|
||||||
|
directory.renameSync(newPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename files
|
||||||
|
for (final path in variable.files.onTrueNames) {
|
||||||
|
final file = File(join(targetPath, path));
|
||||||
|
final newPath = rename(
|
||||||
|
boolean,
|
||||||
|
file,
|
||||||
|
onValue: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
File(newPath).createSync(recursive: true);
|
||||||
|
file.renameSync(newPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final path in variable.files.onFalseNames) {
|
||||||
|
final file = File(join(targetPath, path));
|
||||||
|
final newPath = rename(
|
||||||
|
boolean,
|
||||||
|
file,
|
||||||
|
onValue: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
File(newPath).createSync(recursive: true);
|
||||||
|
file.renameSync(newPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,12 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:yaml/yaml.dart';
|
import 'package:yaml/yaml.dart';
|
||||||
|
|
||||||
class YamlReader {
|
abstract class Reader {}
|
||||||
static YamlMap readYamlFile(String path) =>
|
|
||||||
|
class YamlReader extends Reader {
|
||||||
|
static YamlMap read(String path) =>
|
||||||
loadYaml(File(path).readAsStringSync()) as YamlMap;
|
loadYaml(File(path).readAsStringSync()) as YamlMap;
|
||||||
}
|
}
|
@ -1,136 +0,0 @@
|
|||||||
// Copyright (C) 2023 WYATT GROUP
|
|
||||||
// Please see the AUTHORS file for details.
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:brick_generator/core/logger.dart';
|
|
||||||
import 'package:brick_generator/core/shell.dart';
|
|
||||||
import 'package:brick_generator/models/brick_config.dart';
|
|
||||||
import 'package:brick_generator/models/variable_string_syntax.dart';
|
|
||||||
import 'package:brick_generator/models/variable_type.dart';
|
|
||||||
import 'package:path/path.dart';
|
|
||||||
|
|
||||||
class FileSystemUtils {
|
|
||||||
static Future<void> convertValuesToVariablesInFolder(
|
|
||||||
BrickConfig brickConfig,
|
|
||||||
String path,
|
|
||||||
) async {
|
|
||||||
await Future.wait(
|
|
||||||
Directory(path)
|
|
||||||
.listSync(recursive: true)
|
|
||||||
.whereType<File>()
|
|
||||||
.map((f) async {
|
|
||||||
var file = f;
|
|
||||||
|
|
||||||
try {
|
|
||||||
var contents = await file.readAsString();
|
|
||||||
|
|
||||||
// Transform all values in variables
|
|
||||||
if (brickConfig.variables != null) {
|
|
||||||
for (final variable in brickConfig.variables!) {
|
|
||||||
// Replace all string variables
|
|
||||||
if (variable?.type == VariableType.string) {
|
|
||||||
for (final syntax in VariableStringSyntax.values) {
|
|
||||||
final toReplace = variable?.syntax?[syntax.mapKey];
|
|
||||||
if (toReplace != null) {
|
|
||||||
contents = contents.replaceAll(
|
|
||||||
toReplace,
|
|
||||||
'{{#${syntax.id}}}{{${variable?.name}}}{{/${syntax.id}}}',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Logger.debug(
|
|
||||||
'Variable `${variable?.name}` replaced in ${file.path}',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace content
|
|
||||||
file = await file.writeAsString(contents);
|
|
||||||
} catch (e) {
|
|
||||||
Logger.error(e);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<void> renamePathsInFolder(
|
|
||||||
BrickConfig brickConfig,
|
|
||||||
String path,
|
|
||||||
) async {
|
|
||||||
await Future.wait(
|
|
||||||
Directory(path)
|
|
||||||
.listSync(recursive: true)
|
|
||||||
.whereType<File>()
|
|
||||||
.map((_) async {
|
|
||||||
final file = _;
|
|
||||||
|
|
||||||
// Rename file if needed
|
|
||||||
if (brickConfig.variables != null) {
|
|
||||||
for (final variable in brickConfig.variables!) {
|
|
||||||
if (variable?.type == VariableType.string &&
|
|
||||||
variable?.syntax?[VariableStringSyntax.snakeCase.mapKey] !=
|
|
||||||
null) {
|
|
||||||
final snake =
|
|
||||||
variable!.syntax![VariableStringSyntax.snakeCase.mapKey];
|
|
||||||
if (snake == null) {
|
|
||||||
const err = 'Invalid snake_case syntax';
|
|
||||||
Logger.throwError(ArgumentError(err), err);
|
|
||||||
}
|
|
||||||
final newPath = file.path.replaceAll(
|
|
||||||
snake!,
|
|
||||||
'{{${variable.name}.snakeCase()}}',
|
|
||||||
);
|
|
||||||
|
|
||||||
await File(newPath).create(recursive: true);
|
|
||||||
await file.rename(newPath);
|
|
||||||
Logger.debug(
|
|
||||||
'${file.path} renamed with variable `${variable.name}`',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<void> deleteEmptyFolders(String path) async {
|
|
||||||
for (final dir in Directory(path).listSync(recursive: true).reversed) {
|
|
||||||
if (dir is Directory) {
|
|
||||||
if (dir.existsSync() && await dir.list().isEmpty) {
|
|
||||||
await dir.delete(recursive: true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For the moment ignored files are copied, then deleted...
|
|
||||||
static Future<void> deleteIgnoredFolders(
|
|
||||||
BrickConfig brickConfig,
|
|
||||||
String brickPath,
|
|
||||||
) async {
|
|
||||||
for (final String ignore in brickConfig.brickgenConfig.ignore.ignored) {
|
|
||||||
final String toDelete = join(brickPath, ignore);
|
|
||||||
if (FileSystemEntity.isDirectorySync(toDelete)) {
|
|
||||||
await Shell.rm(toDelete, recursive: true);
|
|
||||||
} else {
|
|
||||||
await Shell.rm(toDelete);
|
|
||||||
}
|
|
||||||
Logger.debug('$toDelete ignored.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,9 +14,9 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import 'package:brick_generator/core/reader.dart';
|
||||||
import 'package:brick_generator/models/brick_variable.dart';
|
import 'package:brick_generator/models/brick_variable.dart';
|
||||||
import 'package:brick_generator/models/brickgen_config.dart';
|
import 'package:brick_generator/models/brickgen_config.dart';
|
||||||
import 'package:brick_generator/yaml_reader.dart';
|
|
||||||
import 'package:yaml/yaml.dart';
|
import 'package:yaml/yaml.dart';
|
||||||
|
|
||||||
const _nameKey = 'name';
|
const _nameKey = 'name';
|
||||||
@ -62,7 +62,7 @@ class BrickConfig {
|
|||||||
throw ArgumentError.notNull('path');
|
throw ArgumentError.notNull('path');
|
||||||
}
|
}
|
||||||
|
|
||||||
final config = YamlReader.readYamlFile(path);
|
final config = YamlReader.read(path);
|
||||||
|
|
||||||
return BrickConfig.parse(config);
|
return BrickConfig.parse(config);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user