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