diff --git a/packages/envied/README.md b/packages/envied/README.md index bce5bd2..3de47db 100644 --- a/packages/envied/README.md +++ b/packages/envied/README.md @@ -221,6 +221,22 @@ static const String apiKey; // Searches for a variable named 'DEBUG_API_KEY' ins These example illustrates how the field name `apiKey` is automatically transformed to `API_KEY`, adhering to the `CONSTANT_CASE` convention commonly used as the variable name inside the `.env` file. This feature contributes to improved code consistency and readability, while also aligning with [Effective Dart](https://dart.dev/effective-dart) naming conventions. +### **Build configuration overrides** + +You can override the default `.env` file path by creating a `build.yaml` file in the root of your project. + +```yaml +targets: + $default: + builders: + envied_generator|envied: + options: + path: .env.custom + override: true +``` + +Note that **both** `path` and `override` must be set for the override to work. + ### Known issues When modifying the `.env` file, the generator might not pick up the change due to [dart-lang/build#967](https://github.com/dart-lang/build/issues/967). diff --git a/packages/envied_generator/lib/builder.dart b/packages/envied_generator/lib/builder.dart index a1b1378..fdf75f1 100644 --- a/packages/envied_generator/lib/builder.dart +++ b/packages/envied_generator/lib/builder.dart @@ -2,8 +2,15 @@ library envied.builder; import 'package:build/build.dart'; import 'package:envied_generator/envied_generator.dart'; +import 'package:envied_generator/src/build_options.dart'; import 'package:source_gen/source_gen.dart'; /// Primary builder to build the generated code from the `EnviedGenerator` -Builder enviedBuilder(BuilderOptions options) => - SharedPartBuilder([const EnviedGenerator()], 'envied'); +Builder enviedBuilder(BuilderOptions options) => SharedPartBuilder( + [ + EnviedGenerator( + BuildOptions.fromMap(options.config), + ) + ], + 'envied', + ); diff --git a/packages/envied_generator/lib/src/build_options.dart b/packages/envied_generator/lib/src/build_options.dart new file mode 100644 index 0000000..ac7411c --- /dev/null +++ b/packages/envied_generator/lib/src/build_options.dart @@ -0,0 +1,27 @@ +/// Represents the options passed to the build runner via build.yaml. +/// +/// For example +/// +/// ```yaml +/// targets: +/// $default: +/// builders: +/// envied_generator|envied: +/// options: +/// path: .env.test +/// override: true +/// ``` +class BuildOptions { + const BuildOptions({ + this.override, + this.path, + }); + + final String? path; + final bool? override; + + factory BuildOptions.fromMap(Map map) => BuildOptions( + override: map['override'] as bool?, + path: map['path'] as String?, + ); +} diff --git a/packages/envied_generator/lib/src/generator.dart b/packages/envied_generator/lib/src/generator.dart index 77d7b3b..dc3a4fb 100644 --- a/packages/envied_generator/lib/src/generator.dart +++ b/packages/envied_generator/lib/src/generator.dart @@ -8,6 +8,7 @@ import 'package:build/build.dart'; import 'package:code_builder/code_builder.dart'; import 'package:dart_style/dart_style.dart'; import 'package:envied/envied.dart'; +import 'package:envied_generator/src/build_options.dart'; import 'package:envied_generator/src/generate_field.dart'; import 'package:envied_generator/src/generate_field_encrypted.dart'; import 'package:envied_generator/src/load_envs.dart'; @@ -19,7 +20,9 @@ import 'package:source_gen/source_gen.dart'; /// Will throw an [InvalidGenerationSourceError] if the annotated /// element is not a [classElement]. final class EnviedGenerator extends GeneratorForAnnotation { - const EnviedGenerator(); + const EnviedGenerator(this._buildOptions); + + final BuildOptions _buildOptions; @override Future generateForAnnotatedElement( @@ -36,7 +39,10 @@ final class EnviedGenerator extends GeneratorForAnnotation { } final Envied config = Envied( - path: annotation.read('path').literalValue as String?, + path: _buildOptions.override == true && + _buildOptions.path?.isNotEmpty == true + ? _buildOptions.path + : annotation.read('path').literalValue as String?, requireEnvFile: annotation.read('requireEnvFile').literalValue as bool? ?? false, name: annotation.read('name').literalValue as String?, diff --git a/packages/envied_generator/test/.env.example_with_path_override b/packages/envied_generator/test/.env.example_with_path_override new file mode 100644 index 0000000..fc4e5fd --- /dev/null +++ b/packages/envied_generator/test/.env.example_with_path_override @@ -0,0 +1,2 @@ +foo=bar +baz=qux diff --git a/packages/envied_generator/test/envy_generator_test.dart b/packages/envied_generator/test/envy_generator_test.dart index 831ea05..9ab4863 100644 --- a/packages/envied_generator/test/envy_generator_test.dart +++ b/packages/envied_generator/test/envy_generator_test.dart @@ -1,18 +1,33 @@ import 'package:envied_generator/envied_generator.dart'; +import 'package:envied_generator/src/build_options.dart'; import 'package:source_gen_test/source_gen_test.dart'; Future main() async { // for annotated elements initializeBuildLogTracking(); - final reader = await initializeLibraryReaderForDirectory( - 'test/src', - 'generator_tests.dart', - ); // print(Platform.environment['SYSTEM_VAR']); testAnnotatedElements( - reader, - EnviedGenerator(), + await initializeLibraryReaderForDirectory( + 'test/src', + 'generator_tests.dart', + ), + EnviedGenerator( + const BuildOptions(), + ), + ); + + testAnnotatedElements( + await initializeLibraryReaderForDirectory( + 'test/src', + 'generator_tests_with_path_override.dart', + ), + EnviedGenerator( + const BuildOptions( + path: 'test/.env.example_with_path_override', + override: true, + ), + ), ); } diff --git a/packages/envied_generator/test/src/generator_tests_with_path_override.dart b/packages/envied_generator/test/src/generator_tests_with_path_override.dart new file mode 100644 index 0000000..d25bd2d --- /dev/null +++ b/packages/envied_generator/test/src/generator_tests_with_path_override.dart @@ -0,0 +1,37 @@ +// ignore_for_file: unnecessary_nullable_for_final_variable_declarations + +import 'package:envied/envied.dart'; +import 'package:source_gen_test/annotations.dart'; + +@ShouldGenerate(''' +// coverage:ignore-file +// ignore_for_file: type=lint +final class _EnvWithPathOverride0 {} +''') +@Envied() +abstract class EnvWithPathOverride0 {} + +@ShouldGenerate(''' +// coverage:ignore-file +// ignore_for_file: type=lint +final class _EnvWithPathOverride1 {} +''') +@Envied(requireEnvFile: true) +abstract class EnvWithPathOverride1 {} + +@ShouldGenerate(''' +// coverage:ignore-file +// ignore_for_file: type=lint +final class _EnvWithPathOverride2 { + static const String foo = 'bar'; + + static const String baz = 'qux'; +} +''') +@Envied() +abstract class EnvWithPathOverride2 { + @EnviedField() + static const String? foo = null; + @EnviedField() + static const String? baz = null; +}