rekeens_flutter_cli 0.27.1
rekeens_flutter_cli: ^0.27.1 copied to clipboard
CLI tool for scaffolding Flutter applications with Feature-First Clean Architecture, Riverpod/BLoC, GoRouter, Dio, and modular code generators.
Changelog #
0.27.1 #
- New
CONTRIBUTING.md— public contributor guide covering the branch model (feature/<name>→dev→main), commit message conventions, local checks (dart format,dart analyze --fatal-infos,dart test), PR checklist, versioning/changelog rules, and issue reporting guidelines; linked fromREADME.md; no references to the private internal style guide remain in public docs
0.27.0 #
- Update existing models with
--add-field/--remove-field— after the initial generation, adding or removing a field previously required manual file editing;rekeens g modelcan now parse the existing model and regenerate itrekeens g model <feature> <model> --add-field name:type(repeatable) — appends new fields with fullfromJson/toJsonsupport; adding a name that already exists fails with an errorrekeens g model <feature> <model> --remove-field name(repeatable) — removes fields; unknown names fail with the list of existing fields; removing all fields is rejected--add-fieldand--remove-fieldcan be combined in one call; removals are applied before additions, so re-adding a removed name works as a type replacement- Windows fix — model parser now handles CRLF line endings, so field updates work on Windows-generated files
- New files:
lib/utils/model_file_parser.dart(parsesfinal <type> <name>;declarations back intoModelFields, reusing the generation-time type rules; enum fields are recognized via their.values.byName(...)fromJsonexpression),test/model_file_parser_test.dart(13 tests) ModelGenerator.updateFields— merge + regeneration via the existingmodel_with_fieldstemplate; the test stub is left untouched;--dry-runprints the planned field changesGenerateCommand— registers--add-field/--remove-fieldmulti-options; usage with a non-modelgenerator type or with positional fields throws aUsageException- Tests:
generators_test.dart(+11: add, remove, combined add+remove, enum preservation, untouched test stub, missing model, unknown field, duplicate add, remove-all, nothing-to-update, dry-run);generate_command_test.dart(+4: flag validation and multi-value parsing) - Docs:
README.md(quick-start example + command reference row),DOCUMENTATION.md(new "Updating an Existing Model" section)
0.26.3 #
- Add runnable example/ (main.dart, README.md, updated rekeens.yaml.example)
0.26.2 #
- Update Dart SDK constraint to >=3.12.0 <4.0.0
0.26.1 #
- Removed all references to internal style guidelines from
CHANGELOG.md— previous changelog entries referenced a private internal document with section numbers (e.g. "per §6"), creating a documentation ghost for public readers; all 6 references replaced with neutral descriptions of the changes themselves - Parameterized
datasource_impltemplate — the generated{{datasource_name}}_datasource_impl.dartno longer hardcodeshttps://api.example.com/{{datasource_name}}; the base URL is now a constructor parameter (String baseUrl = '...') defaulting to a configurable valueDatasourceGenerator.generate()accepts an optionalbaseUrlparameter, passed to the template as{{base_url}}GenerateCommandadds--base-urlCLI option; resolution priority: CLI flag →rekeens.yamldefaults.base-url→ built-in placeholderhttps://api.example.com
- CI: added test coverage upload to Codecov —
.github/workflows/dart.ymlnow runsdart test --coverage=coverage, formats it as lcov viadart run coverage:format_coverage, and uploadscoverage/lcov.infoto Codecov (ubuntu-latest only, to avoid duplicate matrix uploads);coverage: ^1.7.2added todev_dependencies
0.26.0 #
- New
datasourcegenerator —rekeens g featurecreatesdata/datasources/but there was no command to generate files inside it; the newdatasourcegenerator fills this gap, completing the data layer alongsidemodel,repository, andservicerekeens g datasource <feature> <name>— creates two files inlib/features/<feature>/data/datasources/:<name>_datasource.dart— abstract interface withfetchData()andpostData()methods<name>_datasource_impl.dart— concrete HTTP implementation usingdart:ioHttpClient, with JSON encoding/decoding, status code checking, and injectableHttpClientconstructor for testing
- New files:
lib/generators/datasource_generator.dart,templates/features/datasource/{{datasource_name}}_datasource.dart,templates/features/datasource/{{datasource_name}}_datasource_impl.dart,templates/tests/datasource/{{datasource_name}}_datasource_test.dart - Test stub:
fetchDatadecodes JSON on 200, throws on non-200,postDatacompletes on 201; uses_FakeHttpClient/_FakeHttpClientRequest/_FakeHttpClientResponseto avoid real network calls GenerateCommand— registersdatasourcecase with<feature> <name>validation; updated "Available:" list in unknown-type errorListCommand—generatorslist extended withdatasourceentry- Tests:
all_generators_test.dart(+7: interface+impl creation, force=false, force=true, invalid name, missing feature, test file by default, withTests=false);generate_command_test.dart(+1: missing datasource name);list_command_test.dart(extended assertions fordatasource) - Docs:
DOCUMENTATION.md— new "Datasource Generator" section + TOC entries for entity/usecase/datasource + test stubs table row;README.md— quick-start example and commands table updated
0.25.0 #
- Before/after generate hooks —
rekeens.yamlnow supports ahookssection that runs shell commands before and after everyrekeens generateinvocation, enabling auto-formatting, analysis, DI registration, and other post-generation tasks- New
hookssection inrekeens.yamlwithbefore_generateandafter_generatelists; each entry is either a plain string (runs for all generators) or a map withrun(required),when(optional list of generator types), anddescription(optional label) - New files:
lib/config/hooks.dart(HookConfig,HookSet,HookContext,HookRunner),test/hooks_test.dart(14 tests) ConfigLoader.loadHooks— parses thehookssection fromrekeens.yamlusing the same resolution chain (local → home); returns emptyHookSeton missing/malformed config with alogger.warnGenerateCommand— loads hooks before dispatch, runsbefore_generatehooks → generator →after_generatehooks; new--hooks(default) /--no-hooksflag;--dry-runskips hook execution and logs what would have run; constructor accepts injectableHookRunnerfor testing- Environment variables passed to every hook:
REKEENS_GENERATOR_TYPE,REKEENS_FEATURE_NAME,REKEENS_ENTITY_NAME - Behavior: hooks run in the project working directory via
sh -c(Linux/macOS) orcmd /c(Windows); non-zero exit code stops the pipeline and throws; hooks are filtered bywhenlist if present config_command.dart—defaultConfigContentnow includes a commented-outhooks:section with examplesDOCUMENTATION.md— new "Hooks" subsection under "Component Generators" with syntax, env vars table, and behavior notes; "Common Generator Flags" updated with--hooks/--no-hooks- Tests:
hooks_test.dart(+14:appliesTofiltering,HookSet.isEmpty, echo success, marker file, env var passing, skip onwhenmismatch, failure on non-zero exit, dry-run skip, multiple hooks in order);config_loader_test.dart(+6: empty on no config, empty on no hooks section, simple string hooks, map-style hooks, multiple hooks, skip entries withoutrun, malformed YAML);generate_command_test.dart(+2:--no-hooksflag, hook runner not called)
- New
0.24.0 #
- Model generator now supports nested custom models, enums, and
Map<String, dynamic>— previously only primitives,DateTime, andList<primitive>were accepted; real API models frequently need nested objects, enums, and arbitrary JSON maps- New field syntax (all nullable with
?):profile:UserProfile— custom model: emitsimport 'user_profile.dart';,UserProfile.fromJson(...)infromJson,.toJson()intoJsonitems:List<OrderItem>— list of custom models: emitsimport 'order_item.dart';,.map((e) => OrderItem.fromJson(e as Map<String, dynamic>)).toList()infromJson,.map((e) => e.toJson()).toList()intoJsonrole:enum Role— enum: emitsimport 'role.dart';,Role.values.byName(json[...] as String)infromJson,.nameintoJsonmetadata:Map<String, dynamic>— arbitrary JSON:Map<String, dynamic>.from(json[...] as Map)infromJson, passthrough intoJson- Case-insensitive aliases:
list<OrderItem>→List<OrderItem>
- Auto-imports: relative
importstatements are generated at the top of the model file for custom/enum/list-custom fields; imports are deduplicated (referencingUserProfiletwice produces one import line) ModelFieldclass extended withcategory(FieldCategoryenum:primitive,dateTime,listPrimitive,listCustom,custom,enumType,map),importPath(relative.dartpath ornull), andinnerType(element type forList<>fields)ModelGenerator—_fromJsonExpr/_toJsonExprrewritten asswitch (f.category); new_collectImportsmethod deduplicates and builds theimportslist for the template- Template
templates/features/model_with_fields/{{model_name}}_model.dart— added{{#each imports}}import '{{path}}';\n{{/each}}block beforeclass; empty imports list renders nothing - Tests:
model_fields_test.dart(+13 tests: custom, nullable custom,List<Custom>, nullableList<Custom>,list<>alias, enum, nullable enum, invalid enum name,Map<String, dynamic>,Mapwithout space, nullableMap,Map<String, int>rejection);generators_test.dart(+7 tests: custom model with import, nullable custom,List<CustomModel>with import, enum with import, nullable enum,Map<String, dynamic>, import deduplication) DOCUMENTATION.md— "Model Generator & Field Type System" section: field syntax table extended with 4 new rows (Map, custom model,List<Custom>, enum) including auto-import column; new explanatory paragraphs for nested models, enums, andMap; example command extendedREADME.md— quick-start model example and commands table updatedlib/commands/list_command.dart— model generator description updated to mention the new type support
- New field syntax (all nullable with
0.23.0 #
- Riverpod provider template upgraded from stateless
Provider<T>toStateNotifierProviderwith real state management, matching the cubit template's level of completenesstemplates/features/provider/{{provider_name}}_provider.dart— now declares aStateNotifierProvider<{{class_name}}Notifier, {{class_name}}State>backed by a{{class_name}}Notifier extends StateNotifier<{{class_name}}State>with adoSomethingmethod that togglesisLoadingand incrementscount(replaces the previous plainProvider<{{class_name}}Provider>with a no-op class)templates/features/provider/{{provider_name}}_state.dart(new) — immutable{{class_name}}Stateclass withcount/isLoadingfields andcopyWith, mirroring the cubit template's separate state filetemplates/tests/provider/{{provider_name}}_provider_test.dart— rewritten: initial state assertion (count=0,isLoading=false),doSomethingincrements count viacontainer.read(provider.notifier)test/all_generators_test.dart— ProviderGenerator group updated to assertAuthNotifier,StateNotifierProvider,StateNotifier, and the newauth_state.dartfile; test-generation group assertscount/isLoadingin the test stubDOCUMENTATION.md— "Provider / Cubit Generator" section and "Generated Test Stubs" table updated to describe theStateNotifierProvider+ state class outputREADME.md— quick-start note and commands table updatedlib/commands/list_command.dart— provider description updated to mentionStateNotifierProvider
0.22.4 #
- Removed commented-out
ShellRouteblock fromtemplates/bootstrap/router.dart: the go_router template shipped with a 15-line commented-outShellRouteexample (settings/profile routes inside aMainShell); removed entirely, leaving only the activeGoRoutefor the home page
0.22.3 #
main()is now thin —bin/rekeens_flutter_cli.dartcontained--versionhandling and theg→generatealias rewrite inline; both have been extracted intolib/utils/arg_preprocessor.dart- New
handleVersionFlag(List<String> args)— returnstruewhen--version/-vwas present (and printed the version),falseotherwise; caller exits ontrue - New
expandAliases(List<String> args)— rewrites a leadinggtogenerate, returns the args list unchanged otherwise; only the first positional argument is considered bin/rekeens_flutter_cli.dart—main()now callshandleVersionFlag, builds theCommandRunner, and callsrunner.run(expandAliases(args)); no inline business logic remains
- New
- Fixed
getAppVersioncrash when package root cannot be resolved —getPackageRoot()was called outside the try/catch inlib/utils/app_version.dart, so aStateError("Unable to locate rekeens_flutter_cli package root") propagated uncaught in environments where the CLI is not globally activated (e.g. unit tests); now wrapped in its own try/catch with alogger.warnand'unknown'fallback, consistent with the existing recovery pattern for YAML parsing errors - New test file
test/arg_preprocessor_test.dart(+10 tests: 4handleVersionFlagcovering absent/present/-v/mixed, 6expandAliasescoveringg/generate/non-g/empty/first-only/non-first)
0.22.2 #
- CI now matches the documented quality gates —
DOCUMENTATION.mdclaimeddart.ymlruns format verification and--fatal-infosanalysis, but the workflow only randart analyze(without--fatal-infos) anddart test.github/workflows/dart.yml— added "Verify formatting" step runningdart format --output=none --set-exit-if-changed lib test bin(onlylib/test/bin;templates/contain{{placeholders}}that are not valid Dart and cannot be formatted); changed "Analyze project source" fromdart analyzetodart analyze --fatal-infosto match the docsDOCUMENTATION.md— "Testing & Code Quality" code block updated to showlib test bin(not.) with a comment explaining thetemplates/exclusion;e2e_smoke.ymldescription corrected to state all three presets (minimal,mobile,full) are tested as a matrix, not just--preset=full
0.22.1 #
- Silent
catch (_) {}blocks now log a warning: 5 catch blocks across 4 files swallowed exceptions without any diagnostic output, making failures invisible to the userlib/services/project_scaffolder.dart— cleanup of partial project dir afterflutter createfailure now logsFailed to clean up partial project dir: <error>;taskkillfallback tosigkillon Windows now logstaskkill failed, falling back to sigkill: <error>lib/utils/template_resolver.dart—getPackageRoot()failure now logsCould not resolve package root: <error>before falling back to other template candidateslib/utils/package_metadata.dart—readPackageNamefailure now logsCould not read package name from <path>: <error>before returningnulllib/utils/app_version.dart—getAppVersionfailure now logsCould not read app version from <path>: <error>before returning'unknown'- All 5 blocks changed from
catch (_)tocatch (e)to include the underlying error in the warning message;loggerimport added totemplate_resolver.dart,package_metadata.dart, andapp_version.dart
0.22.0 #
- New
entityandusecasegenerators complete the domain layer of the Clean Architecture scaffolding:rekeens g featurealready createddomain/entities/,domain/repositories/, anddomain/usecases/directories, but onlyrepositoryhad a generator — entities and use cases had to be hand-writtenrekeens g entity <feature> <name>— createslib/features/<feature>/domain/entities/<name>_entity.dart(plain Dart class with value equality via==/hashCodeand aconstconstructor; no JSON codegen, no external deps)rekeens g usecase <feature> <name>— createslib/features/<feature>/domain/usecases/<name>_usecase.dartwith a<Name>UseCaseclass exposingFuture<String> call(<Name>Params params)and a matching<Name>Paramsclass, following the canonical Clean Architecture use case pattern- Both generators support
--force,--dry-run, and--tests/--no-testslike all other generators
- New templates:
templates/features/entity/,templates/features/usecase/,templates/tests/entity/,templates/tests/usecase/ - New generator classes:
EntityGenerator,UseCaseGenerator(inlib/generators/) GenerateCommand— registers both new generators withentityandusecasecases; updated "Available:" list in the unknown-type error messageListCommand—generatorslist extended withentityandusecaseentries (description + example)- Generated test stubs:
entity_test: value equality byid(same id → equal, different id → not equal)usecase_test:callreturns the injected params input; null input falls back to empty string
DOCUMENTATION.md— new "Entity Generator" and "Use Case Generator" sections; "Generated Test Stubs" table extended withentityandusecaserowsREADME.md— quick-start examples and commands table extended withentityandusecase- Tests:
all_generators_test.dart(+14 tests: 5 EntityGenerator + 5 UseCaseGenerator + 2 EntityGenerator tests + 2 UseCaseGenerator tests),generate_command_test.dart(+2 tests: missing entity name, missing usecase name),list_command_test.dart(extended assertions forentity/usecasein list, examples, and generators set)
0.21.3 #
- Repository test template now exercises the interface, not just the implementation: the generated
repository_test.dartinstantiatedRepositoryImpldirectly, leaving theabstract classinterface with no consumer in the testtemplates/tests/repository/{{repository_name}}_repository_test.dart— now imports the domain interface, declares both test subjects as{{class_name}}Repository(the interface type), and adds a_Fake{{class_name}}Repository implements {{class_name}}Repositorymock with injected items to demonstrate the interface is actually exercised- Two tests: impl returns empty list by default; fake returns the injected items through the interface
- No new dev dependency required (hand-written fake instead of mocktail/mockito, keeping the generated project dependency-light)
test/all_generators_test.dart— RepositoryGenerator test group now also asserts the test file imports thedomain/repositoriesinterface and containsimplements UserRepository
0.21.2 #
- Removed addressless
// TODO: implement ...comments from generator templates: templates must ship either a concrete example or a meaningful no-op stub, never a bare TODOtemplates/features/service/{{service_name}}_service.dart—performActionbody is now an emptyasync {}no-op (testperformAction completesstill passes)templates/features/provider/{{provider_name}}_provider.dart—doSomethingbody is now an emptyasync {}no-optemplates/features/cubit/{{provider_name}}_cubit.dart—doSomethingnow emits a concrete{{class_name}}Loadingstate instead of a TODO, demonstrating the canonicalemit(...)patterntemplates/features/cubit/{{provider_name}}_state.dart— added{{class_name}}Loadingstate class to back the emit example- Repository template TODO was already removed in 0.21.0 (
return [];stub)
0.21.1 #
dio_client.dartnow matcheshttp_client.dartHTTP verb coverage: addedputanddeletemethods so projects generated with--networking=diocan perform PUT/DELETE requests without manual editsput<T>(path, {body, headers})delegates to_dio.putvia the existing_requestwrapper (consistent error handling throughApiException)delete<T>(path, {headers})delegates to_dio.deletevia the same wrapper- Signatures mirror
http_client.dart(body+headersforput,headersonly fordelete)
0.21.0 #
- Repository generator split across Clean Architecture layers: the interface and implementation are no longer emitted into a single file inside
data/repositories/(which leftdomain/repositories/empty and violated layer separation)- Interface (
abstract class) is now created atlib/features/<feature>/domain/repositories/<name>_repository.dart - Implementation is now created at
lib/features/<feature>/data/repositories/<name>_repository_impl.dartand imports the interface via a relative path
- Interface (
templates/features/repository/restructured intodomain/anddata/subdirectories replacing the previous single{{repository_name}}_repository.darttemplateRepositoryGenerator.generate— checks both target paths for existing files (respecting--force), ensures both directories exist, and emits twocopyTemplatecalls; dry-run logs both planned filestemplates/tests/repository/{{repository_name}}_repository_test.dart— import updated to the_repository_impl.dartpathDOCUMENTATION.md— "Repository Generator" section updated to describe the two-file output and Clean Architecture split- Tests:
all_generators_test.dartRepositoryGenerator group updated to assert both thedomain/interface anddata/implementation files are created with correct content and relative import
0.20.1 #
- Fix info-level warning in generated app_typography.dart by using non-nullable fontFamily with empty string fallback
0.20.0 #
- Generated test stubs: all component generators (
feature,screen,model,repository,service,provider/cubit) now create a test file alongside the main source by default- Test files are placed under
test/features/<feature>/...mirroring thelib/structure model_test: constructor equality,fromJson,toJson, round-triprepository_test:getItemsreturns empty listservice_test:performActioncompletes without throwingscreen_test/feature_test: widget tests — AppBar title, body text, renders without throwingprovider_test(riverpod):ProviderContainerresolves the providercubit_test(bloc):blocTestverifies initial state- Test stubs use
package:{{project_name}}/...imports resolved frompubspec.yaml'sname:field
- Test files are placed under
- New
--tests/--no-testsflag onrekeens generate(default:--tests); use--no-teststo skip test generation BaseGenerator— newgenerateTest()helper andprojectDir/getProjectName()accessors;generate()methods in all 6 generators gained awithTestsparameter (defaulttrue); dry-run mode logs planned test file creation- New test templates under
templates/tests/category:feature/,screen/,model/,repository/,service/,cubit/,provider/— separate fromtemplates/features/for architectural clarity BaseGenerator.copyTemplate— newcategoryparameter (default'features');generateTest()passescategory: 'tests'GenerateCommand— new--testsflag, passeswithTeststo all generatorsDOCUMENTATION.md— "Common Generator Flags" section updated with--tests/--no-tests, new "Generated Test Stubs" table, templates table updated with test subdirectories- Tests: +14 new tests covering test file generation for all 6 generators (default creates test,
withTests=falseskips, dry-run doesn't write)
0.19.0 #
- New
--pin-versionsCLI flag (andpin_versionskey inrekeens.yaml): when enabled,flutter pub addis invoked with--exactso dependencies are pinned to the latest resolved version instead of using caret ranges — ensures reproducible installs across machines and over time ProjectScaffolder._addDependencies— newpinVersionsparameter; when true,--exactis inserted intoflutter pub addargs before--devand package names; applies to both regular and dev dependenciesProjectScaffolder.scaffold— readsoptions['pin_versions']and passes it to_addDependenciesfor both the main and dev dependency callsOptionsResolver—pin_versionsadded to_hasAnyCreateFlag,_collectOptionsFromFlags,_fillDefaults(defaultfalse), and interactive prompt (newaskYesNoafter codegen)CreateCommand— new--pin-versions/--no-pin-versionsflagConfigInitCommand— defaultrekeens.yamlnow includespin_versions: falseDOCUMENTATION.md— CLI flags table updated with--pin-versions, config schema updated withpin_versions- Tests:
options_resolver_test.dart(+3 tests:--pin-versionssets true,--no-pin-versionssets false, defaults false in preset/fillDefaults),project_scaffolder_test.dart(+2 tests:--exactpresent whenpin_versions=true, absent whenfalse),config_init_command_test.dart(+1 assertion:pin_versionsin loaded config)
0.18.0 #
templates/base/lib/app/theme/app_colors.dart— filled with real semantic color tokens: brand (primary/secondary/tertiary), semantic (error/success/warning/info), light & dark surfaces, outlines, dividers, scrim/shadow —seedColoris now a{{seed_color}}placeholder driven by the newseed_coloroptiontemplates/base/lib/app/theme/app_typography.dart— expanded from 4 styles to a complete Material 3TextTheme(all 15 styles: display/headline/title/body/label × large/medium/small) with proper font sizes, weights, letter-spacing, and line heights —fontFamilyis conditionally rendered via{{#if has_font}}from the newfont_familyoptiontemplates/base/lib/app/theme/app_theme.dart— now imports and usesAppColors.seedColor+AppTypography.textThemeto build light/darkThemeData(previously hardcodedColors.blueseed and ignored typography);useMaterial3is driven by{{use_material3}}placeholdertemplates/bootstrap/app.dart— replaced inlineThemeData(...)withtheme: AppTheme.light+darkTheme: AppTheme.dark(importstheme/app_theme.dart); theme logic is now centralized inAppThemeinstead of duplicated inlineProjectScaffolder._applyTemplate— now receivesoptionsmap and passesseed_color,font_family,use_material3as variables plushas_font/material3as conditions toTemplateService.copyTemplatefor the base template- New
--seed-colorCLI flag: accepts hex color in0xFFRRGGBB,#RRGGBB,RRGGBB, or0xAARRGGBBformat; normalized to0xFFRRGGBBuppercase byOptionsResolver._normalizeHexColor; validated for length and hex characters - New
--font-familyCLI flag: accepts a font family name string; empty value is not stored (system default) OptionsResolver:seed_colorandfont_familyadded to_hasAnyCreateFlag,_collectOptionsFromFlags,_fillDefaults(defaults0xFF2196F3and''), and interactive prompt (two newaskStringprompts after theme)Presetclass: addedseedColor(default0xFF2196F3) andfontFamily(default'') fields;toOptions()now includesseed_colorandfont_family- Presets updated:
minimaluses0xFF2196F3(blue),mobileuses0xFF6750A4(purple),fulluses0xFF6750A4+Robotofont ConfigInitCommanddefaultrekeens.yamlnow includesseed_color: 0xFF2196F3andfont_family: ''DOCUMENTATION.mdupdated: theme directory tree description, presets table (added Seed Color + Font columns), CLI flags table (added--seed-colorand--font-family), config schema (addedseed_colorandfont_family), new "Theme Customization" subsection documenting both keys- Tests:
presets_test.dart(+5 tests: seed_color/font_family for each preset + toOptions keys),options_resolver_test.dart(+7 tests: preset seed_color/font_family, invalid seed-color validation, hex normalization variants, empty font-family),config_init_command_test.dart(+2 assertions: seed_color and font_family in loaded config),project_file_writer_test.dart(theme tests rewritten: verify AppTheme.light/dark usage instead of inline ThemeData), newtheme_templates_test.dart(8 tests: app_colors seed_color substitution, app_typography full TextTheme + font_family conditional, app_theme useMaterial3 + AppColors/AppTypography references)
0.17.0 #
- New
analysis_optionstop-level section inrekeens.yaml: when present,rekeens createserializes its content toanalysis_options.yamlin the generated project, overriding the defaultflutter_lintsconfig fromflutter create— previously generated projects always used the default lints with no way to customize ConfigLoader.loadAnalysisOptions(): reads the top-levelanalysis_optionssection fromrekeens.yamland returns it as a deeply-convertedMap<String, dynamic>(nestedYamlMap/YamlListare recursively converted to plain Dart types via new_convertYamlNodehelper so the result can be serialized back to YAML)OptionsResolver.resolve()refactored: existing logic moved to_resolveOptions(),resolve()now wraps it and mergesanalysis_optionsfrom config into the options map — works regardless of whether preset, flags, config defaults, or interactive prompt produced the base optionsProjectFileWriter._renderAnalysisOptions(): writesanalysis_options.yamlusingYamlEditorwhenoptions['analysis_options']is present; skips silently when absent (default fromflutter createis preserved)ConfigInitCommanddefaultrekeens.yamlnow includes a commented-outanalysis_optionssection with exampleinclude,analyzer.language,analyzer.errors, andlinter.rulesentriesDOCUMENTATION.mdupdated: Schema Specification section now documents theanalysis_optionstop-level key with a full example and explanation- Tests:
config_loader_test.dart(+7 tests forloadAnalysisOptions: nested map, absent section, no config file, non-map value, list rules, invalid YAML warning, home config fallback),options_resolver_test.dart(+4 tests: analysis_options from config, absent section, with preset, no config file),project_file_writer_test.dart(+3 tests: writes YAML with nested map, skips when absent, handles list-style linter rules),config_init_command_test.dart(+2 tests: commented example present, commented section not parsed)
0.16.0 #
templates/bootstrap/router.dart(go_router variant) now includes a commentedShellRouteexample demonstrating nested routes with a shared wrapper widget (e.g. scaffold with nav bar) — the home route remains a top-levelGoRouteso the template compiles out of the box- New
lib/services/router_updater.dart(RouterUpdater): idempotently adds routes to an existinglib/app/router.dart— detects go_router vs simpleAppRoutervariant from file content, insertsGoRouteentries (with import) orstatic const Stringroute names, skips if the route path already exists, respects--dry-run, skips silently ifrouter.dartis absent FeatureGeneratornow callsRouterUpdaterafter creating a feature: adds/<feature_name>route pointing to<ClassName>Page(e.g./auth→AuthPage)ScreenGeneratornow callsRouterUpdaterafter creating a screen: adds/<feature_name>/<screen_name>route pointing to<ClassName>Screen(e.g./auth/login→LoginScreen)- Route naming convention: feature
auth→ path/auth; screenlogininauth→ path/auth/login; simple-router constant names use lowerCamelCase (e.g.authLogin) DOCUMENTATION.mdupdated: Feature Generator and Screen Generator sections now document automatic route addition;router.darttree description updated to mention ShellRoute example- New
test/router_updater_test.dart(10 tests): go_router route addition (feature + screen), idempotency, existing route preservation, dry-run, simple AppRouter route constants, camelCase naming for multi-word names, missing router.dart handling test/generators_test.dartupdated: 2 new tests verifying FeatureGenerator and ScreenGenerator add routes torouter.darttest/helpers/generator_test_helper.dartupdated: now createslib/app/router.dartwith a go_router template in the temp project so generator tests can verify route auto-addition
0.15.0 #
- New
--storageoption (shared_preferences,secure_storage,none, defaultshared_preferences) adds a local key-value storage abstraction to the generated project — previouslycore/storage/was an empty README despite being documented as a ready layer ProjectFileWriter.configureProjectFilesnow renderscore/storagetemplates:key_value_storage.dart(abstract interface withread/write/delete/clear) is always rendered when storage is enabled, plus the matching implementation (shared_preferences_storage.dartorsecure_storage.dart);--storage=none(or omitting the option) leaves the directory untouched- New
templates/core/key_value_storage.dart: abstractKeyValueStorageinterface —read,write,delete,clear— so features depend on the abstraction, not the concrete package - New
templates/core/shared_preferences_storage.dart:SharedPreferencesStorage implements KeyValueStoragewrappingpackage:shared_preferences - New
templates/core/secure_storage.dart:SecureStorage implements KeyValueStoragewrappingpackage:flutter_secure_storage DependencyResolvernow addsshared_preferencesorflutter_secure_storagebased on thestorageoptionPresetclass gains astoragefield:minimal→none,mobile→shared_preferences,full→secure_storage;toOptions()includesstorageOptionsResolvervalidates--storageagainst allowed values, includes it in_hasAnyCreateFlag,_fillDefaults,_validateConfigOptions, and the interactive prompt (after networking)ConfigInitCommanddefaultrekeens.yamlnow includesstorage: shared_preferencesListCommandpreset output now showsstorage: <value>CreateCommandexposes--storageflagDOCUMENTATION.mdupdated:core/storage/directory tree, presets table (new Storage column), CLI flags table (--storagerow),coreTemplate Categories row, config file schema example- Tests updated:
presets_test.dart(storage assertions for all 3 presets +toOptionskeys),options_resolver_test.dart(invalid/valid storage values, defaults, single-value flags, config file, interactive prompt),dependency_resolver_test.dart(shared_preferences + secure_storage deps),config_init_command_test.dart(storage in loaded config),list_command_test.dart(storage in output),project_scaffolder_test.dart(storage in options maps + dep assertions),project_file_writer_test.dart(4 new tests: shared_preferences, secure_storage, none, omitted)
0.14.0 #
ProjectFileWriter.configureProjectFilesnow renderscore/errorstemplates into the generated project, completing the error-handling stack:failure.dartandresult.dartare always rendered (foundational types),exception_to_failure_mapper.dartis rendered only when--networkingis notnone(it importsApiExceptionfromcore/network/)- New
templates/core/failure.dart: sealedFailureclass withServerFailure(5xx),ClientFailure(4xx),NetworkFailure,CacheFailure, andUnknownFailuresubclasses — replaces the draft that had aCacheFailureconstructor typo and noClientFailure(causing dead code in the mapper where both 4xx and 5xx returnedServerFailure) - New
templates/core/result.dart:Result<T>sealed class withSuccess<T>/FailureResult<T>and convenience getters (isSuccess,isFailure,valueOrNull,failureOrNull) — replacesEither<Failure, T>fromdartzwith a dependency-free idiomatic Dart 3 sealed class, avoiding unnecessary dependencies - Rewrote
templates/core/exception_to_failure_mapper.dart: fixed brokenpackage:rekeens_flutter_cli/...imports (templates render into a generated project with a different name — now uses relativeimport 'failure.dart'andimport '../network/api_exception.dart'); 4xx now maps toClientFailureinstead of falling through to the unreachableServerFailurebranch;nullstatusCode maps toNetworkFailure - Reuses the existing
ApiExceptionfromcore/network/api_exception.dart(added in 0.13.0) instead of duplicating it as a separateAppException— both carrymessage,statusCode, andresponseBody DOCUMENTATION.mdupdated:core/errors/directory tree now lists the generated files;corerow in Template Categories expanded to cover error templates- 5 new tests in
project_file_writer_test.dartcovering: failure+result always rendered (even without networking), mapper rendered for dio/http, mapper omitted for none/omitted networking, nopackage:rekeens_flutter_cliimports in rendered mapper
0.13.0 #
ProjectFileWriter.configureProjectFilesnow renderscore/networktemplates into the generated project based on the--networkingoption, so users get a ready-to-use HTTP layer instead of just a dependency- When
--networking=dioor--networking=http, the CLI writesnetwork_config.dart,api_exception.dart, and the matching client (dio_client.dart/http_client.dart) intolib/core/network/;--networking=none(or omitting the option) leaves the directory untouched - Rewrote
templates/core/dio_client.dartwith an auth-token interceptor (Authorization: Bearer), request logging viaLogInterceptor, and error handling that convertsDioExceptionintoApiException - Rewrote
templates/core/http_client.dartwith the same auth-token + logging + error-handling concerns, exposingget/post/put/deleteand throwingApiExceptionon non-2xx responses - New
templates/core/api_exception.dartprovides a typed exception carryingmessage,statusCode, andresponseBody templates/core/network_config.dartgains an optionalTokenProvidercallback so callers can supply the current bearer token without subclassing the client- Renamed the internal
_renderBootstrapFilehelper to_renderTemplateFile(now generic enough to render files from any template category, not justbootstrap) - New tests cover dio/http/none/omitted networking scenarios in
project_file_writer_test.dart DOCUMENTATION.mdupdated:core/network/directory tree now lists the generated files; newcorerow added to the Template Categories table;--networkingflag description notes the scaffolding output, not just the dependency
0.12.0 #
- Add validation for enum-like options (state-management, router, networking, theme, architecture, platforms) with clear error messages
- Log warning when
rekeens.yamlparsing fails instead of silently ignoring - Expand e2e smoke test to cover all presets (
minimal,mobile,full) using matrix strategy - Add unit tests for invalid option values
- Unify model generation with explicit fields through template system with
{{#each}}support - Add Windows CI matrix to run unit tests on Windows, covering Windows-specific process handling
0.11.10 #
Dart CIworkflow (.github/workflows/dart.yml) now runsdart analyze+dart teston bothubuntu-latestandwindows-latestvia an OS matrix, instead of only Ubuntu- Guarantees that Windows-specific code branches are actually executed in CI:
defaultScaffoldProcessRunner'scmd /cprocess spawn andtaskkill /F /T /PIDprocess-tree kill,ConfigLoader'sUSERPROFILEfallback,TemplateResolver'sUSERPROFILEhome detection, andDoctorCommand's Windows-only tool checks - The
defaultScaffoldProcessRunnertimeout test branches onPlatform.isWindows(ping -t localhostvssleep 30) — previously only thesleeppath ran in CI, leaving thetaskkillpath untested fail-fast: falseensures both OS jobs complete, surfacing failures on either platform in a single run- Cache key already used
${{ runner.os }}, so pub caches remain per-OS without key collisions
0.11.9 #
- Unified model generation on the template system:
ModelGeneratorno longer usesStringBufferto build model source for--fields— it now renders amodel_with_fieldstemplate viacopyTemplate, matching the approach used for all other generators and bootstrap files - Extended
TemplateServicewith{{#each list}}...{{/each}}loop support:renderContent,copyTemplate, andrenderFileaccept an optionallistsparameter (Map<String, List<Map<String, String>>>); each block's inner content is repeated per item with item-specific variable substitution - New template
templates/features/model_with_fields/{{model_name}}_model.dartcontains the class skeleton with four{{#each fields}}sections (field declarations, constructor params, fromJson lines, toJson lines) - Per-field expressions that involve type-specific logic (
fromJsoncasts,DateTimeparsing, nullable handling) are pre-computed in Dart (_buildFieldVariables) and passed as string variables to the template — the template handles structure and iteration, Dart handles type dispatch - Removed
_generateModelSource,_jsonKey, and unusedgenerateSourceForTestfromModelGenerator; removed unuseddart:ioimport BaseGenerator.copyTemplatenow accepts and forwards an optionallistsparameter- 6 new
template_service_test.darttests covering{{#each}}iteration, empty/missing lists, multiple blocks, combination with top-level variables, andcopyTemplateintegration
0.11.8 #
- E2E smoke workflow (
.github/workflows/e2e_smoke.yml) now scaffolds and validates all three presets (minimal,mobile,full) via astrategy.matrixinstead of only--preset=full - Each preset exercises a different combination of conditional template blocks (
{{#if}}/{{#unless}}onstate_management,router,networking,localization,codegen); theminimalpreset is the only one that hits thenonebranches for state/router/networking, so a regression there previously went undetected fail-fast: falseensures all preset jobs run to completion, surfacing every failing preset in a single push rather than aborting on the first failure- Job name reflects the preset:
create (<preset>) + analyze + test - E2E smoke workflow (
.github/workflows/e2e_smoke.yml) now scaffolds and validates all three presets (minimal,mobile,full) via astrategy.matrixinstead of only--preset=full - Each preset exercises a different combination of conditional template blocks (
{{#if}}/{{#unless}}onstate_management,router,networking,localization,codegen); theminimalpreset is the only one that hits thenonebranches for state/router/networking, so a regression there previously went undetected fail-fast: falseensures all preset jobs run to completion, surfacing every failing preset in a single push rather than aborting on the first failure- Job name reflects the preset:
create (<preset>) + analyze + test
0.11.7 #
ConfigLoader.loadnow logs awarningwhenrekeens.yamlfails to parse instead of silently swallowing the error viacatch (_) { return null; }- The warning includes the resolved config file path, the parse error message, and notes that the CLI is falling back to defaults
ConfigLoader.loadaccepts an optionalLogger? logparameter (defaults to the globallogger) for testability, mirroring theListCommand({Logger? log})injection pattern- New tests verify the warning is emitted for malformed YAML (unclosed flow sequences) and that no warning is logged when the config file is absent or valid but lacks a
defaultssection
0.11.6 #
- Validate enum-like options (
--state-management,--router,--networking,--theme,--architecture) against their allowed values inOptionsResolver._applyFlagsand when loading defaults fromrekeens.yaml - A typo such as
--state-management=Riverpodnow throws aUsageExceptionlisting the available values instead of silently producing a broken project (no dependency added, no template activated) architecturecurrently accepts onlyfeature-first; unsupported values are rejected with a clear message- New
_validateEnumValue/_validateConfigOptionshelpers mirror the existing preset validation
0.11.5 #
- Clarify documentation:
--architecturecurrently supports onlyfeature-first; other patterns are planned
0.11.4 #
- Removed hardcoded
packageVersionsmap fromDependencyResolver— dependency versions are no longer pinned in CLI source code flutter pub addnow receives bare package names (e.g.flutter_riverpodinstead offlutter_riverpod:^3.4.2) and resolves the latest compatible version automatically at project creation time- Eliminates version staleness: the CLI no longer ships outdated constraints that drift behind upstream releases between CLI updates
- Generated projects get the latest stable versions with caret constraints (
^x.y.z) written byflutter pub add, with exact versions pinned inpubspec.lockas usual - The E2E smoke test workflow (
e2e_smoke.yml) serves as the safety net: it scaffolds a--preset=fullproject and runsflutter analyze+flutter test, catching any breakage from upstream dependency changes - Updated
dependency_resolver_test.dartandproject_scaffolder_test.dartto expect bare package names instead ofpackage:versionstrings
0.11.3 #
- New E2E smoke test workflow (
.github/workflows/e2e_smoke.yml) that runs the fullrekeens createpipeline end-to-end in CI: installs Flutter SDK, activates the CLI globally, scaffolds a project with--preset=full, then runsflutter analyzeandflutter testinside the generated project - Protects templates from silent degradation when dependencies or templates are updated (regressions in generated
main.dart,app.dart,router.dart,l10n, or thefullpreset dependency set surface as CI failures) - Triggered on
push/pull_requesttomain/devand viaworkflow_dispatch; runs as a separate job alongsidedart.ymlto keep the heavy Flutter-SDK step isolated from the fast unit-test CI
0.11.2 #
- Add timeouts for all external process invocations (
flutter create,flutter pub add,flutter pub get,flutter gen-l10n,dart format,flutter analyze) to prevent the CLI from hanging indefinitely without feedback - New
ProcessTimeoutsclass with conservative per-command timeout constants:create(5 min),pub(3 min),genL10n(2 min),format(2 min),analyze(5 min) ScaffoldProcessRunnertypedef extended with optionaltimeoutparameterdefaultScaffoldProcessRunnerrewritten to uselisten/Completerinstead ofaddStream(avoids "StreamSink is already bound" errors when called sequentially), kills the process tree on timeout (taskkill /F /Ton Windows,SIGKILLon Unix), and throws a descriptiveTimeoutExceptionProjectScaffolderpasses the appropriateProcessTimeouts.*constant to every_runProcesscall- 3 new tests: timeout propagation through the scaffold pipeline (full and minimal), and
defaultScaffoldProcessRunnertimeout behavior (kills on timeout, completes within bounds, null timeout works)
0.11.1 #
- Fix:
AppCubitandAppStateare now generated inlib/core/state/instead oflib/app/, matching the project's layered architecture convention (state management belongs incore/, not the app shell) AppStateextracted into its ownapp_state.dartfile (was previously inlined inapp_cubit.dart) withisLoadingfield andcopyWithfor immutable state updatesAppCubitnow importsapp_state.dartand exposes asetLoading(bool)methodmain.dartimport path updated tocore/state/app_cubit.dart- New bootstrap template
templates/bootstrap/app_state.dart - Updated
project_file_writer_test.dartto verify the new file locations andAppStateseparation
0.11.0 #
ProjectFileWriter.enableFlutterGeneraterewritten to useyaml(parsing) +yaml_edit(targeted editing) instead of fragile line-by-lineStringBuffermanipulation- Fixes edge cases that could break the old implementation: CRLF line endings,
generate:inside comments, mixed indentation,flutter:section absent - Comments and original formatting are now preserved (YamlEditor performs string-level edits, not full regeneration)
- Added
yaml_edit: ^2.2.4dependency (official Dart team package for YAML manipulation with comment/whitespace preservation) - 5 new edge-case tests: CRLF line endings,
generate:in comments, comment preservation, already-true no-op, realflutter createpubspec format
0.10.0 #
- Bootstrap files (
main.dart,app.dart,router.dart,app_cubit.dart,l10n.yaml,app_en.arb) are now generated from templates intemplates/bootstrap/instead of imperativeStringBuffercode inProjectFileWriter TemplateServiceextended with conditional rendering ({{#if cond}}...{{/if}},{{#unless cond}}...{{/unless}}) and arenderFilemethod for single-file rendering with variables and conditionsProjectFileWriterrewritten to useTemplateService+TemplateResolver(same resolution chain as feature generators: home → local → built-in); accepts injectabletemplateService,templateResolver,workingDirectory, andtemplatesRootOverride- Static
main.dart,app.dart,router.dartremoved fromtemplates/base/(now generated fromtemplates/bootstrap/based on selected options) - Users can now override bootstrap templates by placing files in
~/.rekeens/templates/bootstrap/(home) or./.rekeens/templates/bootstrap/(local project) ProjectScaffoldernow propagatesworkingDirectoryto the defaultProjectFileWriter- No user-facing behavior changes; generated project files are identical to the previous
StringBufferoutput
0.9.0 #
- Refactor
CreateCommandinto a thin controller following SRP: orchestration and option resolution extracted into dedicated services - New
OptionsResolver(lib/services/options_resolver.dart) handles preset/flag/config/interactive resolution (_resolveOptions,_mergePresetWithFlags,_collectOptionsFromFlags,_fillDefaults,_collectOptions) — accepts injectablePrompterService,workingDirectory, andhomeDirectoryfor testing - New
ProjectScaffolder(lib/services/project_scaffolder.dart) runs the creation pipeline:flutter create→ template copy → file configuration → dependencies → dev dependencies → localization →dart format→flutter analyze; accepts injectableprocessRunner,TemplateService,TemplateResolver,ProjectFileWriter,Logger, andworkingDirectoryfor testing CreateCommand.run()reduced to argument validation, option resolution delegation, dry-run preview, and scaffolder invocation- Unit tests for
OptionsResolver(preset resolution, flag overrides, config file merge, defaults, interactive prompt, unknown preset error) andProjectScaffolder(full pipeline order, codegen/localization skipping, empty platforms,flutter createfailure cleanup) - No user-facing behavior changes; CLI flags and output are unchanged
0.8.0 #
rekeens doctornow checks additional tools beyond Dart/Flutter/Git:- Android SDK: resolves via
ANDROID_HOME/ANDROID_SDK_ROOTenv vars and verifies the directory exists; reports presence ofplatform-tools - Xcode: runs
xcodebuild -versionon macOS only; skipped on other platforms - Chrome: tries
google-chrome/chromium/chrome --version(Linux),/Applications/Google Chrome.app(macOS),chrome --version(Windows), and falls back to scanning standard install paths on disk
- Android SDK: resolves via
- Core tools (Dart/Flutter/Git) and optional tools (Android SDK/Xcode/Chrome) are reported in separate sections with distinct summary lines
exitCode=1is set only when a core tool is missing; missing optional tools produce a warning insteadDoctorCommandnow accepts injectableprocessRunnerandenvironmentfor testabilityextractVersionhandlesXcode(Xcode <version>) andChrome(<major>.<minor>.<build>.<patch>) outputs- Fixed duplicate tool name in doctor output (
Dart Dart 3.5.0→Dart 3.5.0) sinceextractVersionalready includes the tool name - Unit tests for new
extractVersioncases (Xcode, Chrome, Chromium) and process-runner-injectedrun()covering core-tool success/failure, Android SDK present/missing, and Chrome found/not-found
0.7.2 #
- New
rekeens listcommand shows all available presets and generators - Presets section lists
minimal,mobile,fullwith their configuration (platforms, state management, router, networking, theme, localization, codegen) - Generators section lists
feature,screen,model,repository,service,providerwith descriptions and usage examples - Output uses colored styling via
mason_logger(yellow section headers, cyan names) ListCommandaccepts an injectableLoggerfor testability- Unit tests for
ListCommandcovering preset/generator listing, example output, and generator-type consistency with thegeneratecommand
0.7.1 #
- New
rekeens config initcommand generates arekeens.yamlwith default settings in the current directory - Supports
--force/-fto overwrite an existing config and--dry-run/-nto preview the action without writing - Generated config is loadable by
ConfigLoaderand matches the CLI defaults (platforms, architecture, state management, router, networking, localization, theme, codegen) ConfigInitCommandaccepts an injectableworkingDirectoryfor testability- Unit tests for
ConfigInitCommandcovering creation, overwrite protection,--force,--dry-run(long and short forms),ConfigLoaderround-trip, and missing-subcommand handling
0.7.0 #
- Replace all
print()calls with colored terminal output viamason_logger(logger.info,logger.success,logger.warn,logger.err,logger.detail) - New shared
loggerinstance inlib/utils/logger.dart doctorcommand now reports tool checks with green success / red error styling instead of plain✓/✗bulletscreatecommand step messages uselogger.info, verbose output useslogger.detail, and the final result useslogger.success- Generator success messages (
feature,screen,model,repository,service,provider) and dry-run notices now go through the shared logger - Errors in
main()are reported vialogger.errinstead of writing tostderrdirectly
0.6.3 #
- Extract shared generator test setup (temp project creation,
setUpAll/setUp/tearDown,withAuthFeature) intotest/helpers/generator_test_helper.dart - Refactor
generators_test.dartandall_generators_test.dartto useGeneratorTestHelper, removing duplicated boilerplate
0.6.2 #
- Unit tests for
ConfigLoadercovering local/home config loading, precedence, invalid YAML, missing defaults section, list conversion, and boolean values - Unit tests for
presetscovering all three presets (minimal, mobile, full) andPreset.toOptions() - Extended
ProjectFileWritertests covering go_router vs none router, material3 vs material2 theme, localization file generation, andenableFlutterGenerate(insert, dedup, append, missing pubspec) - Extended
TemplateServicetests covering binary files, missing source, nested directories, .gitkeep, multiple variables, and unreplaced placeholders - Unit tests for
PrompterServicecoveringaskString,askYesNo,askChoice,askMultipleChoicewith mocked stdin/stdout ConfigLoader.loadnow accepts optionalworkingDirectoryandhomeDirectoryparameters for testabilityPrompterServicenow accepts injectableoutput(StringSink) andreadLinecallback for testability
0.6.1 #
- Unit tests for
DoctorCommandcovering version-string extraction for Dart, Flutter, Git, and edge cases (empty input, non-ASCII bullet stripping, multiline output) - Unit tests for
GenerateCommandcovering argument validation, unknown-type rejection, missing-name detection for all sub-generators, and--force/--dry-runflag parsing DoctorCommand.extractVersionexposed as@visibleForTestingto enable pure-logic testing without spawning real processesTemplateResolver.resolveno longer throws when the built-in package root cannot be located if a matching home or local template is found first
0.6.0 #
- Custom templates support: CLI now resolves templates by searching
~/.rekeens/templates/(user-global), then.rekeens/templates/in the current project (local), and finally the built-intemplates/shipped with the package - New
TemplateResolverutility drives bothcreate(base template) andgenerate(feature/screen/model/repository/service/provider templates), so any template can be overridden or new generator types added without modifying CLI source - Throws a clear
StateErrorlisting every searched path when a template cannot be found in any location - Unit tests for
TemplateResolvercovering home > local > built-in precedence and the not-found case
0.5.0 #
- Parameterized model generation:
rekeens g model auth user name:string age:intgenerates fields, constructor,fromJson, andtoJsonfromname:typearguments - Supported types:
String,int,double,bool,DateTime,List<String>,List<int>,List<double>,List<bool>(and nullable variants with?) - Type aliases: case-insensitive (
string→String,datetime/date→DateTime), and[]array syntax (string[]→List<String>) for Windows shells where<>are metacharacters - When no fields are provided, falls back to the default template (
id:int,name:String) - Rejects invalid field formats, unsupported types, and duplicate field names with clear
FormatExceptionmessages
0.4.2 #
- Make
getPackageRoot()reliable underdart pub global activateby resolving the package URI viaIsolate.resolvePackageUriinstead of walking up fromPlatform.script(which points at the Pub cache snapshot) - Fall back to walking up from
Platform.scriptandPlatform.resolvedExecutable, matching the package bynameinpubspec.yaml - Throw a clear
StateErrorwhen the package root cannot be located instead of silently returning an incorrect path
0.4.1 #
- Check
flutter createexit code and abort subsequent steps (template, dependencies, codegen) on failure with a clear error message - Clean up partially created project directory when
flutter createfails - Verify project directory exists after
flutter createsucceeds - Flush stderr before
exit(64)inmain()so error messages are not lost on Windows
0.4.0 #
- Pin dependency versions in
DependencyResolver(e.g.flutter_bloc:^9.1.1,dio:^5.11.0) so generated projects get reproducible, compatible package versions - Add
--codegenflag to installbuild_runner,freezed, andjson_serializableas dev_dependencies codegenoption is now part of interactive prompts, presets (fullpreset enables it), config file, and dry-run output- Fix version conflict between
freezedandbuild_runnerby using compatible pinned versions (build_runner:^2.15.1,freezed:^3.2.5,json_serializable:^6.14.0)
0.3.0 #
- Add BLoC support in templates:
main.dartwraps the app inBlocProviderwith anAppCubitwhenstate_management: blocis selected generate providernow auto-detects the project's state management frompubspec.yamland generates a Cubit + State (sealed class) for BLoC projects, or a Riverpod provider otherwise- New
cubittemplate ({{provider_name}}_cubit.dart+{{provider_name}}_state.dart)
0.2.0 #
- Add real localization support (l10n.yaml, ARB, flutter_localizations, flutter gen-l10n)
0.1.1 #
- Initial release
- Project creation with interactive and non-interactive modes
- Feature-first architecture template
- Code generators: feature, screen, model, repository, service, provider
- Presets: minimal, mobile, full
- Configuration file support (
rekeens.yaml) - Dynamic dependency management based on selected options
doctorcommand for environment diagnostics- Dry-run mode (
--dry-run) for create and generate commands - Unit tests for core logic
- Global installation support via
dart pub global activate