From e9e93ff8508b8d190e2acf61721aa1059e769099 Mon Sep 17 00:00:00 2001 From: yossefaboukrat Date: Sun, 26 Oct 2025 13:07:11 +0100 Subject: [PATCH 1/4] feat: add subdirectory support for domain-driven organization Allows creating components in subdirectories for better organization: Examples: - stacked create view sales/dashboard - stacked create service api/auth - stacked create dialog alerts/error - stacked create bottom_sheet forms/client_info - stacked create widget charts/sales_graph This enhancement maintains full backward compatibility while enabling domain-driven directory structures. Implementation: - Parse path syntax (domain/component) in all create commands - Extract subfolder from input (e.g., 'sales/dashboard' -> subfolder: 'sales', name: 'dashboard') - Updated template_service to inject subfolders into output paths - Support for views, services, dialogs, bottom_sheets, and widgets Benefits: - Better code organization by domain/feature - Maintains Stacked framework compatibility - No breaking changes - backward compatible - Comprehensive README documentation with examples --- README.md | 28 ++++++- .../create/create_bottom_sheet_command.dart | 19 +++-- .../create/create_dialog_command.dart | 19 +++-- .../create/create_service_command.dart | 19 +++-- .../commands/create/create_view_command.dart | 20 +++-- .../create/create_widget_command.dart | 19 +++-- lib/src/services/template_service.dart | 74 ++++++++++++++++--- 7 files changed, 146 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index 5961016..2d4493a 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,33 @@ -# Stacked CLI +# Stacked CLI - Extended Version with Subdirectory Support The official CLI (Command Line Interface) dev tools for working with the Stacked framework. Stacked is a framework built in Flutter for production teams. It is built for maintenance, readability, and scaleability. To read about the usage of this tool read the [Stacked CLI docs](https://stacked.filledstacks.com/docs/Tooling/stacked-cli) +## 🚀 Extended Features - Subdirectory Support + +This version of the Stacked CLI has been extended to support creating components in subdirectories for better domain-driven organization: + +### Create Views with Subdirectories +```bash +stacked create view sales/dashboard +stacked create view student/login +stacked create view signature_flow/client_form +``` + +### Create Services with Subdirectories +```bash +stacked create service api/auth +stacked create service sales/lead_management +``` + +### Create Other Components with Subdirectories +```bash +stacked create bottom_sheet forms/client_info +stacked create dialog alerts/error +stacked create widget charts/sales_graph +``` + +This enhancement allows for better organization by domain while maintaining full Stacked framework compatibility + ## Running the code _Todo: write out the steps to run this project locally_ diff --git a/lib/src/commands/create/create_bottom_sheet_command.dart b/lib/src/commands/create/create_bottom_sheet_command.dart index 05018ff..70b490a 100644 --- a/lib/src/commands/create/create_bottom_sheet_command.dart +++ b/lib/src/commands/create/create_bottom_sheet_command.dart @@ -62,11 +62,6 @@ class CreateBottomSheetCommand extends Command with ProjectStructureValidator { ..addOption( ksProjectPath, help: kCommandHelpProjectPath, - ) - ..addFlag( - ksNoTest, - defaultsTo: false, - help: kCommandHelpNoTest, ); } @@ -85,19 +80,27 @@ class CreateBottomSheetCommand extends Command with ProjectStructureValidator { await validateStructure(outputPath: argResults![ksProjectPath]); for (var i = 0; i < bottomSheetNames.length; i++) { + // Parse the bottom sheet name to support subdirectories + final sheetPath = bottomSheetNames[i]; + final pathParts = sheetPath.split('/'); + final sheetName = pathParts.last; + final subfolders = pathParts.length > 1 + ? pathParts.sublist(0, pathParts.length - 1).join('/') + : null; + await _templateService.renderTemplate( templateName: name, - name: bottomSheetNames[i], + name: sheetName, + subfolder: subfolders, outputPath: argResults![ksProjectPath], verbose: true, excludeRoute: argResults![ksExcludeRoute], hasModel: argResults![ksModel], templateType: templateType, - noTest: argResults![ksNoTest], ); await _analyticsService.createBottomSheetEvent( - name: bottomSheetNames[i], + name: sheetPath, arguments: argResults!.arguments, ); } diff --git a/lib/src/commands/create/create_dialog_command.dart b/lib/src/commands/create/create_dialog_command.dart index 5d7b8f2..63d3a45 100644 --- a/lib/src/commands/create/create_dialog_command.dart +++ b/lib/src/commands/create/create_dialog_command.dart @@ -62,11 +62,6 @@ class CreateDialogCommand extends Command with ProjectStructureValidator { ..addOption( ksProjectPath, help: kCommandHelpProjectPath, - ) - ..addFlag( - ksNoTest, - defaultsTo: false, - help: kCommandHelpNoTest, ); } @@ -85,19 +80,27 @@ class CreateDialogCommand extends Command with ProjectStructureValidator { await validateStructure(outputPath: argResults![ksProjectPath]); for (var i = 0; i < dialogNames.length; i++) { + // Parse the dialog name to support subdirectories + final dialogPath = dialogNames[i]; + final pathParts = dialogPath.split('/'); + final dialogName = pathParts.last; + final subfolders = pathParts.length > 1 + ? pathParts.sublist(0, pathParts.length - 1).join('/') + : null; + await _templateService.renderTemplate( templateName: name, - name: dialogNames[i], + name: dialogName, + subfolder: subfolders, outputPath: argResults![ksProjectPath], verbose: true, excludeRoute: argResults![ksExcludeRoute], hasModel: argResults![ksModel], templateType: templateType, - noTest: argResults![ksNoTest], ); await _analyticsService.createDialogEvent( - name: dialogNames[i], + name: dialogPath, arguments: argResults!.arguments, ); } diff --git a/lib/src/commands/create/create_service_command.dart b/lib/src/commands/create/create_service_command.dart index 283068f..a959c26 100644 --- a/lib/src/commands/create/create_service_command.dart +++ b/lib/src/commands/create/create_service_command.dart @@ -57,11 +57,6 @@ class CreateServiceCommand extends Command with ProjectStructureValidator { ..addOption( ksProjectPath, help: kCommandHelpProjectPath, - ) - ..addFlag( - ksNoTest, - defaultsTo: false, - help: kCommandHelpNoTest, ); } @@ -80,18 +75,26 @@ class CreateServiceCommand extends Command with ProjectStructureValidator { await validateStructure(outputPath: argResults![ksProjectPath]); for (var i = 0; i < serviceNames.length; i++) { + // Parse the service name to support subdirectories + final servicePath = serviceNames[i]; + final pathParts = servicePath.split('/'); + final serviceName = pathParts.last; + final subfolders = pathParts.length > 1 + ? pathParts.sublist(0, pathParts.length - 1).join('/') + : null; + await _templateService.renderTemplate( templateName: name, - name: serviceNames[i], + name: serviceName, + subfolder: subfolders, outputPath: argResults![ksProjectPath], verbose: true, excludeRoute: argResults![ksExcludeDependency], templateType: templateType, - noTest: argResults![ksNoTest], ); await _analyticsService.createServiceEvent( - name: serviceNames[i], + name: servicePath, arguments: argResults!.arguments, ); } diff --git a/lib/src/commands/create/create_view_command.dart b/lib/src/commands/create/create_view_command.dart index fda4226..41c5066 100644 --- a/lib/src/commands/create/create_view_command.dart +++ b/lib/src/commands/create/create_view_command.dart @@ -62,11 +62,6 @@ class CreateViewCommand extends Command with ProjectStructureValidator { ..addOption( ksProjectPath, help: kCommandHelpProjectPath, - ) - ..addFlag( - ksNoTest, - defaultsTo: false, - help: kCommandHelpNoTest, ); } @@ -93,19 +88,28 @@ class CreateViewCommand extends Command with ProjectStructureValidator { templateType ??= _configService.preferWeb ? 'web' : 'empty'; for (var i = 0; i < viewNames.length; i++) { + // Parse the view name to support subdirectories + // e.g., "sales/dashboard" -> subfolder: "sales", viewName: "dashboard" + final viewPath = viewNames[i]; + final pathParts = viewPath.split('/'); + final viewName = pathParts.last; + final subfolders = pathParts.length > 1 + ? pathParts.sublist(0, pathParts.length - 1).join('/') + : null; + await _templateService.renderTemplate( templateName: name, - name: viewNames[i], + name: viewName, + subfolder: subfolders, outputPath: argResults![ksProjectPath], verbose: true, excludeRoute: argResults![ksExcludeRoute], useBuilder: argResults![ksV1] ?? _configService.v1, templateType: templateType, - noTest: argResults![ksNoTest], ); await _analyticsService.createViewEvent( - name: viewNames[i], + name: viewPath, arguments: argResults!.arguments, ); } diff --git a/lib/src/commands/create/create_widget_command.dart b/lib/src/commands/create/create_widget_command.dart index 6a1f792..763bc98 100644 --- a/lib/src/commands/create/create_widget_command.dart +++ b/lib/src/commands/create/create_widget_command.dart @@ -61,11 +61,6 @@ class CreateWidgetCommand extends Command with ProjectStructureValidator { ..addOption( ksProjectPath, help: kCommandHelpProjectPath, - ) - ..addFlag( - ksNoTest, - defaultsTo: false, - help: kCommandHelpNoTest, ); } @@ -88,18 +83,26 @@ class CreateWidgetCommand extends Command with ProjectStructureValidator { await validateStructure(outputPath: argResults![ksProjectPath]); for (var i = 0; i < widgetNames.length; i++) { + // Parse the widget name to support subdirectories + final widgetPath = widgetNames[i]; + final pathParts = widgetPath.split('/'); + final widgetName = pathParts.last; + final subfolders = pathParts.length > 1 + ? pathParts.sublist(0, pathParts.length - 1).join('/') + : null; + await _templateService.renderTemplate( templateName: name, - name: widgetNames[i], + name: widgetName, + subfolder: subfolders, outputPath: argResults![ksProjectPath], verbose: true, hasModel: argResults![ksModel], templateType: templateType, - noTest: argResults![ksNoTest], ); await _analyticsService.createWidgetEvent( - name: widgetNames[i], + name: widgetPath, arguments: argResults!.arguments, ); } diff --git a/lib/src/services/template_service.dart b/lib/src/services/template_service.dart index 0bd6c9c..92e3188 100644 --- a/lib/src/services/template_service.dart +++ b/lib/src/services/template_service.dart @@ -130,6 +130,9 @@ class TemplateService { /// The name to use for the views when generating the view template required String name, + /// The subfolder path for organizing views (e.g., "sales", "student/dashboard") + String? subfolder, + /// When value is true, should log on stdout what is happening during command execution. bool verbose = false, @@ -154,9 +157,6 @@ class TemplateService { /// When supplied it selects the template type to use within the command that's being /// run. This is supplied using --template=web or similar based on the command being run required String templateType, - - /// When set to true, no test files will be generated - bool noTest = false, }) async { // Get the template that we want to render final template = kCompiledStackedTemplates[templateName]![templateType] ?? @@ -166,10 +166,10 @@ class TemplateService { template: template, templateName: templateName, name: name, + subfolder: subfolder, outputFolder: outputPath, useBuilder: useBuilder, hasModel: hasModel, - noTest: noTest, ); if (templateName == kTemplateNameView && excludeRoute) { @@ -180,6 +180,7 @@ class TemplateService { template: template, templateName: templateName, name: name, + subfolder: subfolder, outputPath: outputPath, ); } @@ -188,10 +189,10 @@ class TemplateService { required StackedTemplate template, required String templateName, required String name, + String? subfolder, String? outputFolder, bool useBuilder = false, bool hasModel = true, - bool noTest = false, }) async { /// Sort template files to ensure default view will be always after v1 view. template.templateFiles.sort( @@ -235,22 +236,19 @@ class TemplateService { } } - /// Skip test files if noTest flag is true - if (noTest && templateFile.relativeOutputPath.contains('test/')) { - continue; - } - final templateContent = templateFile.fileType == FileType.text ? renderContentForTemplate( content: templateFile.content, templateName: templateName, name: name, + subfolder: subfolder, ) : base64Decode(templateFile.content.trim().replaceAll('\n', '')); final templateFileOutputPath = getTemplateOutputPath( inputTemplatePath: templateFile.relativeOutputPath, name: name, + subfolder: subfolder, outputFolder: outputFolder, ); @@ -276,11 +274,12 @@ class TemplateService { String getTemplateOutputPath({ required String inputTemplatePath, required String name, + String? subfolder, String? outputFolder, }) { final hasOutputFolder = outputFolder != null; final recaseName = ReCase(name); - final modifiedOutputPath = _configService + var modifiedOutputPath = _configService .replaceCustomPaths(inputTemplatePath) .replaceAll( 'generic', @@ -288,6 +287,49 @@ class TemplateService { ) .replaceFirst('.stk', ''); + // If subfolder is provided, inject it into the appropriate path + if (subfolder != null) { + if (modifiedOutputPath.contains('ui/views/')) { + // Handle views with subfolders + // Check if path ends with '/' (directory) or a file + if (modifiedOutputPath.endsWith('${recaseName.snakeCase}/')) { + modifiedOutputPath = modifiedOutputPath.replaceFirst( + 'ui/views/${recaseName.snakeCase}/', + 'ui/views/$subfolder/${recaseName.snakeCase}/', + ); + } else { + modifiedOutputPath = modifiedOutputPath.replaceFirst( + 'ui/views/${recaseName.snakeCase}', + 'ui/views/$subfolder/${recaseName.snakeCase}', + ); + } + } else if (modifiedOutputPath.contains('services/')) { + // Handle services with subfolders + modifiedOutputPath = modifiedOutputPath.replaceFirst( + 'services/${recaseName.snakeCase}_service.dart', + 'services/$subfolder/${recaseName.snakeCase}_service.dart', + ); + } else if (modifiedOutputPath.contains('ui/dialogs/')) { + // Handle dialogs with subfolders + modifiedOutputPath = modifiedOutputPath.replaceFirst( + 'ui/dialogs/${recaseName.snakeCase}', + 'ui/dialogs/$subfolder/${recaseName.snakeCase}', + ); + } else if (modifiedOutputPath.contains('ui/bottom_sheets/')) { + // Handle bottom sheets with subfolders + modifiedOutputPath = modifiedOutputPath.replaceFirst( + 'ui/bottom_sheets/${recaseName.snakeCase}', + 'ui/bottom_sheets/$subfolder/${recaseName.snakeCase}', + ); + } else if (modifiedOutputPath.contains('ui/widgets/')) { + // Handle widgets with subfolders + modifiedOutputPath = modifiedOutputPath.replaceFirst( + 'ui/widgets/${recaseName.snakeCase}', + 'ui/widgets/$subfolder/${recaseName.snakeCase}', + ); + } + } + if (hasOutputFolder) { return path.join(outputFolder, modifiedOutputPath); } @@ -301,12 +343,14 @@ class TemplateService { required String content, required String templateName, required String name, + String? subfolder, }) { var viewTemplate = Template(content, lenient: true); final renderData = getTemplateRenderData( templateName: templateName, name: name, + subfolder: subfolder, ); return viewTemplate.renderString(renderData); @@ -316,6 +360,7 @@ class TemplateService { Map getTemplateRenderData({ required String templateName, required String name, + String? subfolder, /// This value is only for testing Map? testRenderFunctions, @@ -375,6 +420,7 @@ class TemplateService { required StackedTemplate template, required String templateName, required String name, + String? subfolder, String? outputPath, }) async { final hasOutputPath = outputPath != null; @@ -413,12 +459,14 @@ class TemplateService { modificationTemplate: fileToModify.modificationTemplate, name: name, templateName: templateName, + subfolder: subfolder, ); final verboseMessage = templateModificationName( modificationName: fileToModify.modificationName, name: name, templateName: templateName, + subfolder: subfolder, ); // Write the file back that was modified @@ -440,6 +488,7 @@ class TemplateService { required String modificationName, required String name, required String templateName, + String? subfolder, }) { final template = Template( modificationName, @@ -449,6 +498,7 @@ class TemplateService { final templateRenderData = getTemplateRenderData( templateName: templateName, name: name, + subfolder: subfolder, ); final renderedTemplate = template.renderString(templateRenderData); @@ -461,6 +511,7 @@ class TemplateService { required String modificationIdentifier, required String name, required String templateName, + String? subfolder, }) { final template = Template( modificationTemplate, @@ -470,6 +521,7 @@ class TemplateService { final templateRenderData = getTemplateRenderData( templateName: templateName, name: name, + subfolder: subfolder, ); final renderedTemplate = template.renderString(templateRenderData); From 09c6464720c0dc68c2d329e38c346ae8c1219b09 Mon Sep 17 00:00:00 2001 From: yossefaboukrat Date: Sun, 26 Oct 2025 14:57:16 +0100 Subject: [PATCH 2/4] fix: generate correct import path for views with subfolders When creating a view with a subfolder (e.g., 'test/dashboard'), the CLI was creating files in the correct location (lib/ui/views/test/dashboard/) but generating incorrect import paths in app.dart (pointing to lib/ui/views/dashboard/ without the subfolder). Changes: - Modified RenderFunction typedef to accept optional subfolder parameter - Updated kTemplateNameView render function to generate viewFolderName with subfolder path - Modified getTemplateRenderData() to pass subfolder to render functions - Updated all render function signatures for consistency This ensures that the generated import statement includes the full subfolder path: - Before: import 'package:app/ui/views/dashboard/dashboard_view.dart'; - After: import 'package:app/ui/views/test/dashboard/dashboard_view.dart'; Fixes build_runner error: "Route must have either a page or a redirect destination" --- lib/src/services/template_service.dart | 3 ++- .../templates/template_render_functions.dart | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/src/services/template_service.dart b/lib/src/services/template_service.dart index 92e3188..642983c 100644 --- a/lib/src/services/template_service.dart +++ b/lib/src/services/template_service.dart @@ -376,7 +376,8 @@ class TemplateService { 'No render function has been defined for the template $templateName. Please define a render function before running the command again.'); } - final renderDataForTemplate = renderFunction(nameRecase); + // Pass subfolder to render function + final renderDataForTemplate = renderFunction(nameRecase, subfolder); final packageName = templateName == kTemplateNameApp ? name : null; diff --git a/lib/src/templates/template_render_functions.dart b/lib/src/templates/template_render_functions.dart index 05e4f84..66eb3d0 100644 --- a/lib/src/templates/template_render_functions.dart +++ b/lib/src/templates/template_render_functions.dart @@ -5,21 +5,26 @@ import 'package:stacked_cli/src/services/config_service.dart'; import 'package:stacked_cli/src/templates/template_constants.dart'; /// Definition of a function that when executed returns a Map -typedef RenderFunction = Map Function(ReCase value); +typedef RenderFunction = Map Function(ReCase value, [String? subfolder]); Map renderFunctions = { - kTemplateNameView: (ReCase value) { + kTemplateNameView: (ReCase value, [String? subfolder]) { + // Generate viewFolderName with subfolder if provided + final viewFolderName = subfolder != null + ? '$subfolder/${value.snakeCase}' + : value.snakeCase; + return { kTemplatePropertyViewName: '${value.pascalCase}View', kTemplatePropertyViewFileName: '${value.snakeCase}_view.dart', kTemplatePropertyViewFileNameWithoutExtension: '${value.snakeCase}_view', kTemplatePropertyViewModelName: '${value.pascalCase}ViewModel', kTemplatePropertyViewModelFileName: '${value.snakeCase}_viewmodel.dart', - kTemplatePropertyViewFolderName: value.snakeCase, + kTemplatePropertyViewFolderName: viewFolderName, kTemplatePropertyRelativeLocatorFilePath: getFilePath(builder: 'locator'), }; }, - kTemplateNameService: (ReCase value, [map]) { + kTemplateNameService: (ReCase value, [String? subfolder]) { final configService = locator(); return { kTemplatePropertyServiceName: '${value.pascalCase}Service', @@ -30,7 +35,7 @@ Map renderFunctions = { configService.registerMocksFunction, }; }, - kTemplateNameApp: (ReCase value, [map]) { + kTemplateNameApp: (ReCase value, [String? subfolder]) { return { kTemplatePropertyRelativeBottomSheetFilePath: getFilePath( builder: 'bottomsheets', @@ -40,7 +45,7 @@ Map renderFunctions = { kTemplatePropertyRelativeRouterFilePath: getFilePath(builder: 'router'), }; }, - kTemplateNameBottomSheet: (ReCase value) { + kTemplateNameBottomSheet: (ReCase value, [String? subfolder]) { return { kTemplatePropertySheetName: '${value.pascalCase}Sheet', kTemplatePropertySheetFilename: '${value.snakeCase}_sheet.dart', @@ -52,7 +57,7 @@ Map renderFunctions = { kTemplatePropertyRelativeLocatorFilePath: getFilePath(builder: 'locator'), }; }, - kTemplateNameDialog: (ReCase value) { + kTemplateNameDialog: (ReCase value, [String? subfolder]) { return { kTemplatePropertyDialogName: '${value.pascalCase}Dialog', kTemplatePropertyDialogFilename: '${value.snakeCase}_dialog.dart', @@ -64,7 +69,7 @@ Map renderFunctions = { kTemplatePropertyRelativeLocatorFilePath: getFilePath(builder: 'locator'), }; }, - kTemplateNameWidget: (ReCase value) { + kTemplateNameWidget: (ReCase value, [String? subfolder]) { return { kTemplatePropertyWidgetName: value.pascalCase, kTemplatePropertyWidgetFileName: '${value.snakeCase}.dart', From 1917a422d13037e97ad2b4405778ab683b21adc0 Mon Sep 17 00:00:00 2001 From: yossefaboukrat Date: Sun, 26 Oct 2025 15:14:11 +0100 Subject: [PATCH 3/4] fix: prevent HTML encoding of slashes in subfolder imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using Mustache templates, the {{variable}} syntax (2 braces) automatically escapes HTML entities, converting forward slashes (/) to /. This caused invalid import statements for views, dialogs, and bottom sheets created with subfolders. Changes: - Modified 4 template JSON files to use {{{variable}}} (3 braces) instead of {{variable}} for folder names - Files updated: * view/empty/modifications/add_route_import.json * view/web/modifications/add_route_import.json * dialog/empty/modifications/add_dialog_import.json * bottom_sheet/empty/modifications/add_bottom_sheet_import.json - Recompiled templates to regenerate compiled_template_map.dart Before: import 'package:app/ui/views/test/dashboard/dashboard_view.dart'; ❌ After: import 'package:app/ui/views/test/dashboard/dashboard_view.dart'; ✅ This fix ensures that imports with subfolders are valid Dart code and can be resolved by build_runner. --- .../add_bottom_sheet_import.json | 2 +- lib/src/templates/compiled_constants.dart | 2 +- lib/src/templates/compiled_template_map.dart | 121 ++++++--------- lib/src/templates/compiled_templates.dart | 142 +++++++++++++++--- .../modifications/add_dialog_import.json | 2 +- .../empty/modifications/add_route_import.json | 2 +- .../web/modifications/add_route_import.json | 2 +- 7 files changed, 177 insertions(+), 96 deletions(-) diff --git a/lib/src/templates/bottom_sheet/empty/modifications/add_bottom_sheet_import.json b/lib/src/templates/bottom_sheet/empty/modifications/add_bottom_sheet_import.json index 8ff3205..ba97956 100644 --- a/lib/src/templates/bottom_sheet/empty/modifications/add_bottom_sheet_import.json +++ b/lib/src/templates/bottom_sheet/empty/modifications/add_bottom_sheet_import.json @@ -2,7 +2,7 @@ "description": "When a bottom sheet is generated, one of the boilerplate tasks is to add the bottom sheet class to StackedApp. This modification performs the import for the bottom sheet class.", "path": "lib/app/app.dart", "identifier": "// @stacked-import", - "template": "import \\'package:{{packageName}}/{{{bottomSheetsPath}}}/{{sheetFolderName}}/{{sheetFilename}}\\';", + "template": "import \\'package:{{packageName}}/{{{bottomSheetsPath}}}/{{{sheetFolderName}}}/{{sheetFilename}}\\';", "error": "The bottom sheet registration should be stored in lib/app/app.dart", "name": "Add import for \\'{{sheetName}}\\' class" } \ No newline at end of file diff --git a/lib/src/templates/compiled_constants.dart b/lib/src/templates/compiled_constants.dart index 4a3a61e..580e449 100644 --- a/lib/src/templates/compiled_constants.dart +++ b/lib/src/templates/compiled_constants.dart @@ -1,4 +1,4 @@ -/// NOTE: This is generated code from the compileTemplates command. Do not +/// NOTE: This is generated code from the compileTemplates command. Do not /// modify by hand. /// This file should be checked into source control. diff --git a/lib/src/templates/compiled_template_map.dart b/lib/src/templates/compiled_template_map.dart index c1470b1..b835634 100644 --- a/lib/src/templates/compiled_template_map.dart +++ b/lib/src/templates/compiled_template_map.dart @@ -316,21 +316,18 @@ Map> kCompiledStackedTemplates = { relativeModificationPath: 'lib/app/app.dart', modificationIdentifier: '// @stacked-dialog', modificationTemplate: '''StackedDialog(classType: {{dialogName}}),''', - modificationProblemError: - 'The dialog registration should be stored in lib/app/app.dart', - modificationName: - 'Add \'{{dialogName}}\' dependency to StackedApp annotations file', + modificationProblemError: 'The dialog registration should be stored in lib/app/app.dart', + modificationName: 'Add \'{{dialogName}}\' dependency to StackedApp annotations file', ), + ModificationFile( relativeModificationPath: 'lib/app/app.dart', modificationIdentifier: '// @stacked-import', - modificationTemplate: - '''import \'package:{{packageName}}/{{{dialogsPath}}}/{{dialogFolderName}}/{{dialogFilename}}\';''', - modificationProblemError: - 'The dialog registration should be stored in lib/app/app.dart', + modificationTemplate: '''import \'package:{{packageName}}/{{{dialogsPath}}}/{{{dialogFolderName}}}/{{dialogFilename}}\';''', + modificationProblemError: 'The dialog registration should be stored in lib/app/app.dart', modificationName: 'Add import for \'{{dialogName}}\' class', ), - ], + ], ), }, 'view': { @@ -358,22 +355,18 @@ Map> kCompiledStackedTemplates = { relativeModificationPath: 'lib/app/app.dart', modificationIdentifier: '// @stacked-route', modificationTemplate: '''MaterialRoute(page: {{viewName}}),''', - modificationProblemError: - 'The structure of your stacked application is invalid. The app.dart file should be located in lib/app/', - modificationName: - 'Add {{viewName}} route where @StackedApp annotation is located', + modificationProblemError: 'The structure of your stacked application is invalid. The app.dart file should be located in lib/app/', + modificationName: 'Add {{viewName}} route where @StackedApp annotation is located', ), + ModificationFile( relativeModificationPath: 'lib/app/app.dart', modificationIdentifier: '// @stacked-import', - modificationTemplate: - '''import \'package:{{packageName}}/{{{viewImportPath}}}/{{viewFolderName}}/{{viewFileName}}\';''', - modificationProblemError: - 'The structure of your stacked application is invalid. The app.dart file should be located in lib/app/', - modificationName: - 'Add {{viewName}} route import where @StackedApp annotation is located', + modificationTemplate: '''import \'package:{{packageName}}/{{{viewImportPath}}}/{{{viewFolderName}}}/{{viewFileName}}\';''', + modificationProblemError: 'The structure of your stacked application is invalid. The app.dart file should be located in lib/app/', + modificationName: 'Add {{viewName}} route import where @StackedApp annotation is located', ), - ], + ], ), 'web': StackedTemplate( templateFiles: [ @@ -407,22 +400,18 @@ Map> kCompiledStackedTemplates = { relativeModificationPath: 'lib/app/app.dart', modificationIdentifier: '// @stacked-route', modificationTemplate: '''CustomRoute(page: {{viewName}}),''', - modificationProblemError: - 'The structure of your stacked application is invalid. The app.dart file should be located in lib/app/', - modificationName: - 'Add {{viewName}} route where @StackedApp annotation is located', + modificationProblemError: 'The structure of your stacked application is invalid. The app.dart file should be located in lib/app/', + modificationName: 'Add {{viewName}} route where @StackedApp annotation is located', ), + ModificationFile( relativeModificationPath: 'lib/app/app.dart', modificationIdentifier: '// @stacked-import', - modificationTemplate: - '''import \'package:{{packageName}}/{{{viewImportPath}}}/{{viewFolderName}}/{{viewFileName}}\';''', - modificationProblemError: - 'The structure of your stacked application is invalid. The app.dart file should be located in lib/app/', - modificationName: - 'Add {{viewName}} route import where @StackedApp annotation is located', + modificationTemplate: '''import \'package:{{packageName}}/{{{viewImportPath}}}/{{{viewFolderName}}}/{{viewFileName}}\';''', + modificationProblemError: 'The structure of your stacked application is invalid. The app.dart file should be located in lib/app/', + modificationName: 'Add {{viewName}} route import where @StackedApp annotation is located', ), - ], + ], ), }, 'service': { @@ -441,72 +430,63 @@ Map> kCompiledStackedTemplates = { ModificationFile( relativeModificationPath: 'test/helpers/test_helpers.dart', modificationIdentifier: '// @stacked-mock-create', - modificationTemplate: - '''Mock{{serviceName}} getAndRegister{{serviceName}}() { + modificationTemplate: '''Mock{{serviceName}} getAndRegister{{serviceName}}() { _removeRegistrationIfExists<{{serviceName}}>(); final service = Mock{{serviceName}}(); {{locatorName}}.registerSingleton<{{serviceName}}>(service); return service; }''', - modificationProblemError: - 'The test mocks and helpers should be stored in test/helpers/test_helpers.dart', + modificationProblemError: 'The test mocks and helpers should be stored in test/helpers/test_helpers.dart', modificationName: 'Add {{serviceName}} mock to test helpers', ), + ModificationFile( relativeModificationPath: 'lib/app/app.dart', modificationIdentifier: '// @stacked-service', - modificationTemplate: - '''LazySingleton(classType: {{serviceName}}),''', - modificationProblemError: - 'The service registration should be stored in lib/app/app.dart', - modificationName: - 'Add {{serviceName}} dependency to StackedApp annotations file', + modificationTemplate: '''LazySingleton(classType: {{serviceName}}),''', + modificationProblemError: 'The service registration should be stored in lib/app/app.dart', + modificationName: 'Add {{serviceName}} dependency to StackedApp annotations file', ), + ModificationFile( relativeModificationPath: 'lib/app/app.dart', modificationIdentifier: '// @stacked-import', - modificationTemplate: - '''import \'package:{{packageName}}/{{{serviceImportPath}}}/{{serviceFilename}}\';''', - modificationProblemError: - 'The service registration should be stored in lib/app/app.dart', - modificationName: - 'Add {{serviceName}} import to StackedApp annotations file', + modificationTemplate: '''import \'package:{{packageName}}/{{{serviceImportPath}}}/{{serviceFilename}}\';''', + modificationProblemError: 'The service registration should be stored in lib/app/app.dart', + modificationName: 'Add {{serviceName}} import to StackedApp annotations file', ), + ModificationFile( relativeModificationPath: 'test/helpers/test_helpers.dart', modificationIdentifier: '// @stacked-mock-spec', - modificationTemplate: - '''MockSpec<{{serviceName}}>(onMissingStub: OnMissingStub.returnDefault),''', - modificationProblemError: - 'The test mocks and helpers should be stored in test/helpers/test_helpers.dart', + modificationTemplate: '''MockSpec<{{serviceName}}>(onMissingStub: OnMissingStub.returnDefault),''', + modificationProblemError: 'The test mocks and helpers should be stored in test/helpers/test_helpers.dart', modificationName: 'Create {{serviceName}} mock to test helpers', ), + ModificationFile( relativeModificationPath: 'test/helpers/test_helpers.dart', modificationIdentifier: '// @stacked-mock-register', modificationTemplate: '''getAndRegister{{serviceName}}();''', - modificationProblemError: - 'The test mocks and helpers should be stored in test/helpers/test_helpers.dart', + modificationProblemError: 'The test mocks and helpers should be stored in test/helpers/test_helpers.dart', modificationName: 'Add {{serviceName}} register to test helpers', ), + ModificationFile( relativeModificationPath: 'test/helpers/test_helpers.dart', modificationIdentifier: '// @stacked-import', - modificationTemplate: - '''import \'package:{{packageName}}/{{{serviceImportPath}}}/{{serviceFilename}}\';''', - modificationProblemError: - 'It seems your test_helpers.dart file is not in test/helpers/test_helpers.dart. Add a stacked.json file and set the path for \'test_helpers_path\' to the folder we can locate your test_helpers.dart file', + modificationTemplate: '''import \'package:{{packageName}}/{{{serviceImportPath}}}/{{serviceFilename}}\';''', + modificationProblemError: 'It seems your test_helpers.dart file is not in test/helpers/test_helpers.dart. Add a stacked.json file and set the path for \'test_helpers_path\' to the folder we can locate your test_helpers.dart file', modificationName: 'Add {{serviceName}} import to test helpers', ), - ], + ], ), }, 'bottom_sheet': { 'empty': StackedTemplate( templateFiles: [ TemplateFile( - relativeOutputPath: - kBottomSheetEmptyTemplateGenericSheetModelTestPath, + relativeOutputPath: kBottomSheetEmptyTemplateGenericSheetModelTestPath, content: kBottomSheetEmptyTemplateGenericSheetModelTestContent, fileType: FileType.text), TemplateFile( @@ -514,8 +494,7 @@ return service; content: kBottomSheetEmptyTemplateGenericSheetModelContent, fileType: FileType.text), TemplateFile( - relativeOutputPath: - kBottomSheetEmptyTemplateGenericSheetUseModelPath, + relativeOutputPath: kBottomSheetEmptyTemplateGenericSheetUseModelPath, content: kBottomSheetEmptyTemplateGenericSheetUseModelContent, fileType: FileType.text), TemplateFile( @@ -527,23 +506,19 @@ return service; ModificationFile( relativeModificationPath: 'lib/app/app.dart', modificationIdentifier: '// @stacked-bottom-sheet', - modificationTemplate: - '''StackedBottomsheet(classType: {{sheetName}}),''', - modificationProblemError: - 'The bottom sheet registration should be stored in lib/app/app.dart', - modificationName: - 'Add \'{{sheetName}}\' dependency to StackedApp annotations file', + modificationTemplate: '''StackedBottomsheet(classType: {{sheetName}}),''', + modificationProblemError: 'The bottom sheet registration should be stored in lib/app/app.dart', + modificationName: 'Add \'{{sheetName}}\' dependency to StackedApp annotations file', ), + ModificationFile( relativeModificationPath: 'lib/app/app.dart', modificationIdentifier: '// @stacked-import', - modificationTemplate: - '''import \'package:{{packageName}}/{{{bottomSheetsPath}}}/{{sheetFolderName}}/{{sheetFilename}}\';''', - modificationProblemError: - 'The bottom sheet registration should be stored in lib/app/app.dart', + modificationTemplate: '''import \'package:{{packageName}}/{{{bottomSheetsPath}}}/{{{sheetFolderName}}}/{{sheetFilename}}\';''', + modificationProblemError: 'The bottom sheet registration should be stored in lib/app/app.dart', modificationName: 'Add import for \'{{sheetName}}\' class', ), - ], + ], ), }, }; diff --git a/lib/src/templates/compiled_templates.dart b/lib/src/templates/compiled_templates.dart index 1e17394..7a15518 100644 --- a/lib/src/templates/compiled_templates.dart +++ b/lib/src/templates/compiled_templates.dart @@ -1,9 +1,11 @@ /// NOTE: This is generated code from the compileTemplates command. Do not modify by hand /// This file should be checked into source control. + // -------- StackedJsonStk Template Data ---------- -const String kAppWebTemplateStackedJsonStkPath = 'stacked.json.stk'; +const String kAppWebTemplateStackedJsonStkPath = + 'stacked.json.stk'; const String kAppWebTemplateStackedJsonStkContent = ''' { @@ -27,6 +29,7 @@ const String kAppWebTemplateStackedJsonStkContent = ''' // -------------------------------------------------- + // -------- UnknownViewmodelTest Template Data ---------- const String kAppWebTemplateUnknownViewmodelTestPath = @@ -48,6 +51,7 @@ void main() { // -------------------------------------------------- + // -------- HomeViewmodelTest Template Data ---------- const String kAppWebTemplateHomeViewmodelTestPath = @@ -99,6 +103,7 @@ void main() { // -------------------------------------------------- + // -------- NoticeSheetModelTest Template Data ---------- const String kAppWebTemplateNoticeSheetModelTestPath = @@ -121,6 +126,7 @@ void main() { // -------------------------------------------------- + // -------- InfoAlertDialogModelTest Template Data ---------- const String kAppWebTemplateInfoAlertDialogModelTestPath = @@ -143,6 +149,7 @@ void main() { // -------------------------------------------------- + // -------- HomeViewGoldenTest Template Data ---------- const String kAppWebTemplateHomeViewGoldenTestPath = @@ -187,6 +194,7 @@ void main() { // -------------------------------------------------- + // -------- TestHelpers Template Data ---------- const String kAppWebTemplateTestHelpersPath = @@ -276,9 +284,11 @@ void _removeRegistrationIfExists() { // -------------------------------------------------- + // -------- BuildYamlStk Template Data ---------- -const String kAppWebTemplateBuildYamlStkPath = 'build.yaml.stk'; +const String kAppWebTemplateBuildYamlStkPath = + 'build.yaml.stk'; const String kAppWebTemplateBuildYamlStkContent = ''' targets: @@ -291,9 +301,11 @@ targets: // -------------------------------------------------- + // -------- MainIconPngStk Template Data ---------- -const String kAppWebTemplateMainIconPngStkPath = 'web/main-icon.png.stk'; +const String kAppWebTemplateMainIconPngStkPath = + 'web/main-icon.png.stk'; const String kAppWebTemplateMainIconPngStkContent = ''' iVBORw0KGgoAAAANSUhEUgAAALMAAACzCAYAAADCFC3zAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAN5SURBVHgB7daLjVNBDEDRF0QjVEIrdMLSAS3RyZZAByGWdqUQ5Z/5eGbOkSw3cC152wAAAAAAAAAAAAAAAACAjHZbYfuDDW77tdvt3raCvmzQXvGQg5hprUrIQcy0VC3kIGZaqRpyEDMtVA85iJnamoQcxExNzUIOYqaWpiEHMVND85CDmCmtS8hBzJTULeQgZkrpGnIQMyV0DzmImVelCDmImVekCTmImWelCjmImWekCzmImUelDDmImUekDTmImXulDjmImXukDzmImVuGCDmImWuGCTmImUuGCjmImXOGCzmImVNDhhzEzLFhQw5i5tPQIQcxE4YPOYiZKUIOYl7bNCEHMa9rqpCDmNc0XchBzOuZMuQg5rVMG3IQ8zqmDjmIeQ3ThxzEPL8lQg5intsyIQcxz2upkIOY57RcyEHM81ky5CDmuSwbchDzPJYOOYh5DsuHHMQ8PiF/EPPYhHxEzOMS8gkxj0nIZ4h5PEK+QMxjEfIVYh6HkG8Q8xiEfAcx5yfkO4k5NyE/QMx5CflBYs5JyE8Qcz5CfpKYcxHyC8Sch5BfJOYchFyAmPsTciFi7kvIBYm5HyEXJuY+hFyBmNsTciVibkvIFYm5HSFXttsK2+/3bxunvh/mz8axv4fj/r0VVDxm/nc47p+H9bZx6v0Q87etIG9GRUJuS8yVCLk9MVcg5D7EXJiQ+xFzQULuS8yFCLk/MRcg5BzE/CIh5yHmFwg5FzE/Scj5iPkJQs5JzA8Scl5ifoCQcxPznYScn5jvIOQxiPkGIY9DzFcIeSxivkDI4xHzGUIek5hPCHlcYj4i5LGJ+YOQxyfmTcizWD5mIc9j6ZiFPJdlYxbyfJaMWchzWi5mIc9rqZiFPLdlYhby/JaIWchrmD5mIa9j6piFvJZpYxbyeqaMWchrmi5mIa9rqpiFvLZpYhYyU8QsZMLwMQuZT0PHLGSODRuzkDk1ZMxC5pzhYhYylwwVs5C5ZpiYhcwtQ8QsZO6RPmYhc6/UMQuZR6SNWcg8KmXMQuYZ6WIWMs9KFbOQeUWamIXMq1LELGRK6B6zkCmla8xCpqRuMQuZ0rrELGRqaB6zkKmlacxCpqZmMQuZ2prELGRaqB6zkGmlasxCpqVqMQuZ1qrELGR6+LoVdgj5x2HFvG9w2fsGAAAAAAAAAAAAAAAAACzhH8sFZqawpyetAAAAAElFTkSuQmCC @@ -301,9 +313,11 @@ iVBORw0KGgoAAAANSUhEUgAAALMAAACzCAYAAADCFC3zAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNS // -------------------------------------------------- + // -------- IndexHtmlStk Template Data ---------- -const String kAppWebTemplateIndexHtmlStkPath = 'web/index.html.stk'; +const String kAppWebTemplateIndexHtmlStkPath = + 'web/index.html.stk'; const String kAppWebTemplateIndexHtmlStkContent = ''' @@ -481,9 +495,11 @@ const String kAppWebTemplateIndexHtmlStkContent = ''' // -------------------------------------------------- + // -------- FaviconPngStk Template Data ---------- -const String kAppWebTemplateFaviconPngStkPath = 'web/favicon.png.stk'; +const String kAppWebTemplateFaviconPngStkPath = + 'web/favicon.png.stk'; const String kAppWebTemplateFaviconPngStkContent = ''' iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAHaSURBVHgBpVTNasJAEN7dxLQl+FNEFBRR8VCQgo+gryCkh9499CnUg/gMvo3eFWw9eBLS4sWT2oOHRLOdWWLYxkRT+8GS3cnkm28mM0tIMOhpwzmn7plKdurawz9EdLtdNhqNWKvVekyn0ynLsghjTPg4jsNt26a6rnO09/v9r2Qy6UwmkwOlwoX7yZVqtWqA07v78uqKx+NmsVhsw179Jc4wDKVcLrejEvkXCHlBDlmdlkgkPm8lhKw+arWahipRKikUCspqtSqe2FOpFKnX6+QSZrMZ2W63Yr/b7Z6htshl45kOh8MnOWKj0eCXAD8vSKmOf54ho6qqnEREr9fDbjizZzIZikBCut/v6X/IENBeQikSck3TrnFdJJMghJ3V0L86nc5ZHbHOsk82m9WFUCTEzg8DkEVRhpOE6jhD57CUo5IR4tVQpMyCUg5KM0LKorH5crn8lqNhY4/HY9JsNkMVYWPLWK/XXutRmJQHGPQ5uXH0cGxLpdK9SNeVe8jlcgNyI2CWB6ZpHjwDjgxGyOfzb3+5JIBoXqlUXuG2uSOnHpQCUSi0slgs7qCNVAwCEHXZbDZYV+8sZpYxJxaLHaFc1nQ6PYLZCcsAy6BIT0U6eza83X2CBH4AHNJFlWlQookAAAAASUVORK5CYII= @@ -491,9 +507,11 @@ iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNS // -------------------------------------------------- + // -------- READMEMdStk Template Data ---------- -const String kAppWebTemplateREADMEMdStkPath = 'README.md.stk'; +const String kAppWebTemplateREADMEMdStkPath = + 'README.md.stk'; const String kAppWebTemplateREADMEMdStkContent = ''' # {{packageName}} @@ -513,9 +531,11 @@ The golden test screenshots will be stored under `test/golden/`. // -------------------------------------------------- + // -------- Main Template Data ---------- -const String kAppWebTemplateMainPath = 'lib/main.dart.stk'; +const String kAppWebTemplateMainPath = + 'lib/main.dart.stk'; const String kAppWebTemplateMainContent = ''' import 'package:flutter/material.dart'; @@ -557,6 +577,7 @@ class MainApp extends StatelessWidget { // -------------------------------------------------- + // -------- AppConstants Template Data ---------- const String kAppWebTemplateAppConstantsPath = @@ -573,9 +594,11 @@ const double kdDesktopMaxContentHeight = 750; // -------------------------------------------------- + // -------- UiHelpers Template Data ---------- -const String kAppWebTemplateUiHelpersPath = 'lib/ui/common/ui_helpers.dart.stk'; +const String kAppWebTemplateUiHelpersPath = + 'lib/ui/common/ui_helpers.dart.stk'; const String kAppWebTemplateUiHelpersContent = ''' import 'dart:math'; @@ -661,6 +684,7 @@ double getResponsiveFontSize(BuildContext context, // -------------------------------------------------- + // -------- AppStrings Template Data ---------- const String kAppWebTemplateAppStringsPath = @@ -675,9 +699,11 @@ const String ksHomeBottomSheetDescription = // -------------------------------------------------- + // -------- AppColors Template Data ---------- -const String kAppWebTemplateAppColorsPath = 'lib/ui/common/app_colors.dart.stk'; +const String kAppWebTemplateAppColorsPath = + 'lib/ui/common/app_colors.dart.stk'; const String kAppWebTemplateAppColorsContent = ''' import 'package:flutter/material.dart'; @@ -696,6 +722,7 @@ const Color kcBackgroundColor = kcDarkGreyColor; // -------------------------------------------------- + // -------- NoticeSheetModel Template Data ---------- const String kAppWebTemplateNoticeSheetModelPath = @@ -710,6 +737,7 @@ class NoticeSheetModel extends BaseViewModel {} // -------------------------------------------------- + // -------- NoticeSheet Template Data ---------- const String kAppWebTemplateNoticeSheetPath = @@ -778,6 +806,7 @@ class NoticeSheet extends StackedView { // -------------------------------------------------- + // -------- InfoAlertDialogModel Template Data ---------- const String kAppWebTemplateInfoAlertDialogModelPath = @@ -792,6 +821,7 @@ class InfoAlertDialogModel extends BaseViewModel {} // -------------------------------------------------- + // -------- InfoAlertDialog Template Data ---------- const String kAppWebTemplateInfoAlertDialogPath = @@ -911,6 +941,7 @@ class InfoAlertDialog extends StackedView { // -------------------------------------------------- + // -------- HomeViewDesktop Template Data ---------- const String kAppWebTemplateHomeViewDesktopPath = @@ -997,6 +1028,7 @@ class HomeViewDesktop extends ViewModelWidget { // -------------------------------------------------- + // -------- HomeViewMobile Template Data ---------- const String kAppWebTemplateHomeViewMobilePath = @@ -1083,6 +1115,7 @@ class HomeViewMobile extends ViewModelWidget { // -------------------------------------------------- + // -------- HomeView Template Data ---------- const String kAppWebTemplateHomeViewPath = @@ -1125,6 +1158,7 @@ class HomeView extends StackedView { // -------------------------------------------------- + // -------- HomeViewmodel Template Data ---------- const String kAppWebTemplateHomeViewmodelPath = @@ -1172,6 +1206,7 @@ class HomeViewModel extends BaseViewModel { // -------------------------------------------------- + // -------- HomeViewTablet Template Data ---------- const String kAppWebTemplateHomeViewTabletPath = @@ -1258,6 +1293,7 @@ class HomeViewTablet extends ViewModelWidget { // -------------------------------------------------- + // -------- UnknownView Template Data ---------- const String kAppWebTemplateUnknownViewPath = @@ -1300,6 +1336,7 @@ class UnknownView extends StackedView { // -------------------------------------------------- + // -------- UnknownViewDesktop Template Data ---------- const String kAppWebTemplateUnknownViewDesktopPath = @@ -1355,6 +1392,7 @@ class UnknownViewDesktop extends ViewModelWidget { // -------------------------------------------------- + // -------- UnknownViewTablet Template Data ---------- const String kAppWebTemplateUnknownViewTabletPath = @@ -1410,6 +1448,7 @@ class UnknownViewTablet extends ViewModelWidget { // -------------------------------------------------- + // -------- UnknownViewmodel Template Data ---------- const String kAppWebTemplateUnknownViewmodelPath = @@ -1424,6 +1463,7 @@ class UnknownViewModel extends BaseViewModel {} // -------------------------------------------------- + // -------- UnknownViewMobile Template Data ---------- const String kAppWebTemplateUnknownViewMobilePath = @@ -1478,6 +1518,7 @@ class UnknownViewMobile extends ViewModelWidget { // -------------------------------------------------- + // -------- StartupViewmodel Template Data ---------- const String kAppWebTemplateStartupViewmodelPath = @@ -1505,6 +1546,7 @@ class StartupViewModel extends BaseViewModel { // -------------------------------------------------- + // -------- StartupView Template Data ---------- const String kAppWebTemplateStartupViewPath = @@ -1571,6 +1613,7 @@ class StartupView extends StackedView { // -------------------------------------------------- + // -------- ScaleOnHover Template Data ---------- const String kAppWebTemplateScaleOnHoverPath = @@ -1619,6 +1662,7 @@ class _ScaleOnHoverState extends State { // -------------------------------------------------- + // -------- TranslateOnHover Template Data ---------- const String kAppWebTemplateTranslateOnHoverPath = @@ -1675,9 +1719,11 @@ class _TranslateOnHoverState extends State { // -------------------------------------------------- + // -------- App Template Data ---------- -const String kAppWebTemplateAppPath = 'lib/app/app.dart.stk'; +const String kAppWebTemplateAppPath = + 'lib/app/app.dart.stk'; const String kAppWebTemplateAppContent = ''' import 'package:{{packageName}}/{{{bottomSheetsPath}}}/notice/notice_sheet.dart'; @@ -1721,6 +1767,7 @@ class App {} // -------------------------------------------------- + // -------- HoverExtensions Template Data ---------- const String kAppWebTemplateHoverExtensionsPath = @@ -1775,9 +1822,11 @@ extension HoverExtensions on Widget { // -------------------------------------------------- + // -------- PubspecYamlStk Template Data ---------- -const String kAppWebTemplatePubspecYamlStkPath = 'pubspec.yaml.stk'; +const String kAppWebTemplatePubspecYamlStkPath = + 'pubspec.yaml.stk'; const String kAppWebTemplatePubspecYamlStkContent = ''' name: {{packageName}} @@ -1813,9 +1862,11 @@ flutter: // -------------------------------------------------- + // -------- SettingsJsonStk Template Data ---------- -const String kAppWebTemplateSettingsJsonStkPath = '.vscode/settings.json.stk'; +const String kAppWebTemplateSettingsJsonStkPath = + '.vscode/settings.json.stk'; const String kAppWebTemplateSettingsJsonStkContent = ''' { @@ -1829,9 +1880,11 @@ const String kAppWebTemplateSettingsJsonStkContent = ''' // -------------------------------------------------- + // -------- StackedJsonStk Template Data ---------- -const String kAppMobileTemplateStackedJsonStkPath = 'stacked.json.stk'; +const String kAppMobileTemplateStackedJsonStkPath = + 'stacked.json.stk'; const String kAppMobileTemplateStackedJsonStkContent = ''' { @@ -1855,6 +1908,7 @@ const String kAppMobileTemplateStackedJsonStkContent = ''' // -------------------------------------------------- + // -------- HomeViewmodelTest Template Data ---------- const String kAppMobileTemplateHomeViewmodelTestPath = @@ -1906,6 +1960,7 @@ void main() { // -------------------------------------------------- + // -------- NoticeSheetModelTest Template Data ---------- const String kAppMobileTemplateNoticeSheetModelTestPath = @@ -1928,6 +1983,7 @@ void main() { // -------------------------------------------------- + // -------- InfoAlertDialogModelTest Template Data ---------- const String kAppMobileTemplateInfoAlertDialogModelTestPath = @@ -1950,10 +2006,11 @@ void main() { // -------------------------------------------------- + // -------- HomeViewGoldenTest Template Data ---------- const String kAppMobileTemplateHomeViewGoldenTestPath = - 'test/golden/home_view_golden_test.dart.stk'; + 'test/goldens/home_view_golden_test.dart.stk'; const String kAppMobileTemplateHomeViewGoldenTestContent = ''' import 'package:flutter/material.dart'; @@ -1994,6 +2051,7 @@ void main() { // -------------------------------------------------- + // -------- TestHelpers Template Data ---------- const String kAppMobileTemplateTestHelpersPath = @@ -2083,9 +2141,11 @@ void _removeRegistrationIfExists() { // -------------------------------------------------- + // -------- READMEMdStk Template Data ---------- -const String kAppMobileTemplateREADMEMdStkPath = 'README.md.stk'; +const String kAppMobileTemplateREADMEMdStkPath = + 'README.md.stk'; const String kAppMobileTemplateREADMEMdStkContent = ''' # {{packageName}} @@ -2101,13 +2161,16 @@ flutter test --update-goldens ``` The golden test screenshots will be stored under `test/golden/`. +``` '''; // -------------------------------------------------- + // -------- Main Template Data ---------- -const String kAppMobileTemplateMainPath = 'lib/main.dart.stk'; +const String kAppMobileTemplateMainPath = + 'lib/main.dart.stk'; const String kAppMobileTemplateMainContent = ''' import 'package:flutter/material.dart'; @@ -2145,6 +2208,7 @@ class MainApp extends StatelessWidget { // -------------------------------------------------- + // -------- UiHelpers Template Data ---------- const String kAppMobileTemplateUiHelpersPath = @@ -2234,6 +2298,7 @@ double getResponsiveFontSize(BuildContext context, // -------------------------------------------------- + // -------- AppStrings Template Data ---------- const String kAppMobileTemplateAppStringsPath = @@ -2248,6 +2313,7 @@ const String ksHomeBottomSheetDescription = // -------------------------------------------------- + // -------- AppColors Template Data ---------- const String kAppMobileTemplateAppColorsPath = @@ -2268,6 +2334,7 @@ const Color kcBackgroundColor = kcDarkGreyColor; // -------------------------------------------------- + // -------- NoticeSheetModel Template Data ---------- const String kAppMobileTemplateNoticeSheetModelPath = @@ -2282,6 +2349,7 @@ class NoticeSheetModel extends BaseViewModel {} // -------------------------------------------------- + // -------- NoticeSheet Template Data ---------- const String kAppMobileTemplateNoticeSheetPath = @@ -2350,6 +2418,7 @@ class NoticeSheet extends StackedView { // -------------------------------------------------- + // -------- InfoAlertDialogModel Template Data ---------- const String kAppMobileTemplateInfoAlertDialogModelPath = @@ -2364,6 +2433,7 @@ class InfoAlertDialogModel extends BaseViewModel {} // -------------------------------------------------- + // -------- InfoAlertDialog Template Data ---------- const String kAppMobileTemplateInfoAlertDialogPath = @@ -2483,6 +2553,7 @@ class InfoAlertDialog extends StackedView { // -------------------------------------------------- + // -------- HomeViewV1 Template Data ---------- const String kAppMobileTemplateHomeViewV1Path = @@ -2571,6 +2642,7 @@ class HomeView extends StatelessWidget { // -------------------------------------------------- + // -------- HomeView Template Data ---------- const String kAppMobileTemplateHomeViewPath = @@ -2666,6 +2738,7 @@ class HomeView extends StackedView { // -------------------------------------------------- + // -------- HomeViewmodel Template Data ---------- const String kAppMobileTemplateHomeViewmodelPath = @@ -2713,6 +2786,7 @@ class HomeViewModel extends BaseViewModel { // -------------------------------------------------- + // -------- StartupViewmodel Template Data ---------- const String kAppMobileTemplateStartupViewmodelPath = @@ -2742,6 +2816,7 @@ class StartupViewModel extends BaseViewModel { // -------------------------------------------------- + // -------- StartupViewV1 Template Data ---------- const String kAppMobileTemplateStartupViewV1Path = @@ -2807,6 +2882,7 @@ class StartupView extends StatelessWidget { // -------------------------------------------------- + // -------- StartupView Template Data ---------- const String kAppMobileTemplateStartupViewPath = @@ -2873,9 +2949,11 @@ class StartupView extends StackedView { // -------------------------------------------------- + // -------- App Template Data ---------- -const String kAppMobileTemplateAppPath = 'lib/app/app.dart.stk'; +const String kAppMobileTemplateAppPath = + 'lib/app/app.dart.stk'; const String kAppMobileTemplateAppContent = ''' import 'package:{{packageName}}/{{{bottomSheetsPath}}}/notice/notice_sheet.dart'; @@ -2913,9 +2991,11 @@ class App {} // -------------------------------------------------- + // -------- PubspecYamlStk Template Data ---------- -const String kAppMobileTemplatePubspecYamlStkPath = 'pubspec.yaml.stk'; +const String kAppMobileTemplatePubspecYamlStkPath = + 'pubspec.yaml.stk'; const String kAppMobileTemplatePubspecYamlStkContent = ''' name: {{packageName}} @@ -2948,6 +3028,7 @@ flutter: // -------------------------------------------------- + // -------- SettingsJsonStk Template Data ---------- const String kAppMobileTemplateSettingsJsonStkPath = @@ -2965,6 +3046,7 @@ const String kAppMobileTemplateSettingsJsonStkContent = ''' // -------------------------------------------------- + // -------- GenericModelTest Template Data ---------- const String kWidgetEmptyTemplateGenericModelTestPath = @@ -2987,6 +3069,7 @@ void main() { // -------------------------------------------------- + // -------- GenericUseModel Template Data ---------- const String kWidgetEmptyTemplateGenericUseModelPath = @@ -3019,6 +3102,7 @@ class {{widgetName}} extends StackedView<{{widgetModelName}}> { // -------------------------------------------------- + // -------- Generic Template Data ---------- const String kWidgetEmptyTemplateGenericPath = @@ -3040,6 +3124,7 @@ class {{widgetName}} extends StatelessWidget { // -------------------------------------------------- + // -------- GenericModel Template Data ---------- const String kWidgetEmptyTemplateGenericModelPath = @@ -3053,6 +3138,7 @@ class {{widgetModelName}} extends BaseViewModel {} // -------------------------------------------------- + // -------- GenericDialogModelTest Template Data ---------- const String kDialogEmptyTemplateGenericDialogModelTestPath = @@ -3075,6 +3161,7 @@ void main() { // -------------------------------------------------- + // -------- GenericDialogModel Template Data ---------- const String kDialogEmptyTemplateGenericDialogModelPath = @@ -3089,6 +3176,7 @@ class {{dialogModelName}} extends BaseViewModel {} // -------------------------------------------------- + // -------- GenericDialogUseModel Template Data ---------- const String kDialogEmptyTemplateGenericDialogUseModelPath = @@ -3209,6 +3297,7 @@ class {{dialogName}} extends StackedView<{{dialogModelName}}> { // -------------------------------------------------- + // -------- GenericDialog Template Data ---------- const String kDialogEmptyTemplateGenericDialogPath = @@ -3318,6 +3407,7 @@ class {{dialogName}} extends StatelessWidget { // -------------------------------------------------- + // -------- GenericViewmodelTest Template Data ---------- const String kViewEmptyTemplateGenericViewmodelTestPath = @@ -3340,6 +3430,7 @@ void main() { // -------------------------------------------------- + // -------- GenericViewmodel Template Data ---------- const String kViewEmptyTemplateGenericViewmodelPath = @@ -3353,6 +3444,7 @@ class {{viewModelName}} extends BaseViewModel {} // -------------------------------------------------- + // -------- GenericView Template Data ---------- const String kViewEmptyTemplateGenericViewPath = @@ -3391,6 +3483,7 @@ class {{viewName}} extends StackedView<{{viewModelName}}> { // -------------------------------------------------- + // -------- GenericViewV1 Template Data ---------- const String kViewEmptyTemplateGenericViewV1Path = @@ -3422,6 +3515,7 @@ class {{viewName}} extends StatelessWidget { // -------------------------------------------------- + // -------- GenericViewmodelTest Template Data ---------- const String kViewWebTemplateGenericViewmodelTestPath = @@ -3444,6 +3538,7 @@ void main() { // -------------------------------------------------- + // -------- GenericViewmodel Template Data ---------- const String kViewWebTemplateGenericViewmodelPath = @@ -3458,6 +3553,7 @@ class {{viewModelName}} extends BaseViewModel { // -------------------------------------------------- + // -------- GenericViewMobile Template Data ---------- const String kViewWebTemplateGenericViewMobilePath = @@ -3492,6 +3588,7 @@ class {{viewName}}Mobile extends ViewModelWidget<{{viewModelName}}> { // -------------------------------------------------- + // -------- GenericViewTablet Template Data ---------- const String kViewWebTemplateGenericViewTabletPath = @@ -3526,6 +3623,7 @@ class {{viewName}}Tablet extends ViewModelWidget<{{viewModelName}}> { // -------------------------------------------------- + // -------- GenericView Template Data ---------- const String kViewWebTemplateGenericViewPath = @@ -3568,6 +3666,7 @@ class {{viewName}} extends StackedView<{{viewModelName}}> { // -------------------------------------------------- + // -------- GenericViewDesktop Template Data ---------- const String kViewWebTemplateGenericViewDesktopPath = @@ -3602,6 +3701,7 @@ class {{viewName}}Desktop extends ViewModelWidget<{{viewModelName}}> { // -------------------------------------------------- + // -------- GenericServiceTest Template Data ---------- const String kServiceEmptyTemplateGenericServiceTestPath = @@ -3624,6 +3724,7 @@ void main() { // -------------------------------------------------- + // -------- GenericService Template Data ---------- const String kServiceEmptyTemplateGenericServicePath = @@ -3637,6 +3738,7 @@ class {{serviceName}} { // -------------------------------------------------- + // -------- GenericSheetModelTest Template Data ---------- const String kBottomSheetEmptyTemplateGenericSheetModelTestPath = @@ -3659,6 +3761,7 @@ void main() { // -------------------------------------------------- + // -------- GenericSheetModel Template Data ---------- const String kBottomSheetEmptyTemplateGenericSheetModelPath = @@ -3673,6 +3776,7 @@ class {{sheetModelName}} extends BaseViewModel {} // -------------------------------------------------- + // -------- GenericSheetUseModel Template Data ---------- const String kBottomSheetEmptyTemplateGenericSheetUseModelPath = @@ -3743,6 +3847,7 @@ class {{sheetName}} extends StackedView<{{sheetModelName}}> { // -------------------------------------------------- + // -------- GenericSheet Template Data ---------- const String kBottomSheetEmptyTemplateGenericSheetPath = @@ -3801,3 +3906,4 @@ class {{sheetName}} extends StatelessWidget { '''; // -------------------------------------------------- + diff --git a/lib/src/templates/dialog/empty/modifications/add_dialog_import.json b/lib/src/templates/dialog/empty/modifications/add_dialog_import.json index bb7cc11..d51873a 100644 --- a/lib/src/templates/dialog/empty/modifications/add_dialog_import.json +++ b/lib/src/templates/dialog/empty/modifications/add_dialog_import.json @@ -2,7 +2,7 @@ "description": "When a dialog is generated, one of the boilerplate tasks is to add the dialog class to StackedApp. This modification performs the import for the dialog class.", "path": "lib/app/app.dart", "identifier": "// @stacked-import", - "template": "import \\'package:{{packageName}}/{{{dialogsPath}}}/{{dialogFolderName}}/{{dialogFilename}}\\';", + "template": "import \\'package:{{packageName}}/{{{dialogsPath}}}/{{{dialogFolderName}}}/{{dialogFilename}}\\';", "error": "The dialog registration should be stored in lib/app/app.dart", "name": "Add import for \\'{{dialogName}}\\' class" } \ No newline at end of file diff --git a/lib/src/templates/view/empty/modifications/add_route_import.json b/lib/src/templates/view/empty/modifications/add_route_import.json index 8bcfbbe..8b83770 100644 --- a/lib/src/templates/view/empty/modifications/add_route_import.json +++ b/lib/src/templates/view/empty/modifications/add_route_import.json @@ -2,7 +2,7 @@ "description": "When a view is generated one of the boilerplate tasks is to add a route to the app.dart file for the new view. This modification performs that action.", "path": "lib/app/app.dart", "identifier": "// @stacked-import", - "template": "import \\'package:{{packageName}}/{{{viewImportPath}}}/{{viewFolderName}}/{{viewFileName}}\\';", + "template": "import \\'package:{{packageName}}/{{{viewImportPath}}}/{{{viewFolderName}}}/{{viewFileName}}\\';", "error": "The structure of your stacked application is invalid. The app.dart file should be located in lib/app/", "name": "Add {{viewName}} route import where @StackedApp annotation is located" } \ No newline at end of file diff --git a/lib/src/templates/view/web/modifications/add_route_import.json b/lib/src/templates/view/web/modifications/add_route_import.json index 8bcfbbe..8b83770 100644 --- a/lib/src/templates/view/web/modifications/add_route_import.json +++ b/lib/src/templates/view/web/modifications/add_route_import.json @@ -2,7 +2,7 @@ "description": "When a view is generated one of the boilerplate tasks is to add a route to the app.dart file for the new view. This modification performs that action.", "path": "lib/app/app.dart", "identifier": "// @stacked-import", - "template": "import \\'package:{{packageName}}/{{{viewImportPath}}}/{{viewFolderName}}/{{viewFileName}}\\';", + "template": "import \\'package:{{packageName}}/{{{viewImportPath}}}/{{{viewFolderName}}}/{{viewFileName}}\\';", "error": "The structure of your stacked application is invalid. The app.dart file should be located in lib/app/", "name": "Add {{viewName}} route import where @StackedApp annotation is located" } \ No newline at end of file From b0de9cf4cd5fa21973fe04770daacf32e7f1844d Mon Sep 17 00:00:00 2001 From: yossefaboukrat Date: Sun, 26 Oct 2025 15:53:05 +0100 Subject: [PATCH 4/4] feat: add subfolder support to delete commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Applied the same subdirectory parsing logic from create commands to all delete commands, ensuring consistent handling of subfolder paths. Changes: - Modified 4 delete command files to parse and handle subfolder paths - Files updated: * delete_view_command.dart * delete_service_command.dart * delete_dialog_command.dart * delete_bottomsheet_command.dart Implementation: - Parse input path (e.g., 'test/dashboard') to extract subfolder and name - Pass subfolder parameter to getTemplateOutputPath() calls - Updated method signatures to accept optional subfolder parameter - Added documentation for subfolder parameters Before: stacked delete view test/dashboard → Error: PathNotFoundException: 'lib/ui/views/test_dashboard/' ❌ After: stacked delete view test/dashboard → Deletes 'lib/ui/views/test/dashboard/' ✅ This completes the subdirectory support feature, making create and delete commands symmetric. --- .../delete/delete_bottomsheet_command.dart | 39 +++++++++++--- .../delete/delete_dialog_command.dart | 40 +++++++++++--- .../delete/delete_service_command.dart | 53 +++++++++++++++---- .../commands/delete/delete_view_command.dart | 39 +++++++++++--- 4 files changed, 140 insertions(+), 31 deletions(-) diff --git a/lib/src/commands/delete/delete_bottomsheet_command.dart b/lib/src/commands/delete/delete_bottomsheet_command.dart index 880576d..a891cd6 100644 --- a/lib/src/commands/delete/delete_bottomsheet_command.dart +++ b/lib/src/commands/delete/delete_bottomsheet_command.dart @@ -57,7 +57,15 @@ class DeleteBottomsheetCommand extends Command with ProjectStructureValidator { try { final workingDirectory = argResults!.rest.length > 1 ? argResults!.rest[1] : null; - final bottomsheetName = argResults!.rest.first; + + // Parse bottomsheet path to support subdirectories + final bottomsheetPath = argResults!.rest.first; + final pathParts = bottomsheetPath.split('/'); + final bottomsheetName = pathParts.last; + final subfolder = pathParts.length > 1 + ? pathParts.sublist(0, pathParts.length - 1).join('/') + : null; + await _configService.composeAndLoadConfigFile( configFilePath: argResults![ksConfigPath], projectPath: workingDirectory, @@ -67,9 +75,13 @@ class DeleteBottomsheetCommand extends Command with ProjectStructureValidator { await validateStructure(outputPath: workingDirectory); await _deletebottomsheet( - outputPath: workingDirectory, bottomsheetName: bottomsheetName); + outputPath: workingDirectory, + bottomsheetName: bottomsheetName, + subfolder: subfolder); await _removebottomsheetFromDependency( - outputPath: workingDirectory, bottomsheetName: bottomsheetName); + outputPath: workingDirectory, + bottomsheetName: bottomsheetName, + subfolder: subfolder); await _processService.runBuildRunner(workingDirectory: workingDirectory); await _analyticsService.deleteBottomsheetEvent( name: argResults!.rest.first, @@ -98,12 +110,18 @@ class DeleteBottomsheetCommand extends Command with ProjectStructureValidator { /// `outputPath` (String): The path to the output folder. /// /// `bottomsheetName` (String): The name of the bottomsheet. - Future _deletebottomsheet( - {String? outputPath, required String bottomsheetName}) async { + /// + /// `subfolder` (String): Optional subfolder path for organized bottomsheets. + Future _deletebottomsheet({ + String? outputPath, + required String bottomsheetName, + String? subfolder, + }) async { /// Deleting the bottomsheet folder. String directoryPath = _templateService.getTemplateOutputPath( inputTemplatePath: 'lib/ui/bottom_sheets/generic', name: bottomsheetName, + subfolder: subfolder, outputFolder: outputPath, ); await _fileService.deleteFolder(directoryPath: directoryPath); @@ -112,6 +130,7 @@ class DeleteBottomsheetCommand extends Command with ProjectStructureValidator { final filePath = _templateService.getTemplateOutputPath( inputTemplatePath: kBottomSheetEmptyTemplateGenericSheetModelTestPath, name: bottomsheetName, + subfolder: subfolder, outputFolder: outputPath, ); @@ -128,11 +147,17 @@ class DeleteBottomsheetCommand extends Command with ProjectStructureValidator { /// `outputPath` (String): The path to the output folder. /// /// `bottomsheetName` (String): The name of the bottomsheet. - Future _removebottomsheetFromDependency( - {String? outputPath, required String bottomsheetName}) async { + /// + /// `subfolder` (String): Optional subfolder path for organized bottomsheets. + Future _removebottomsheetFromDependency({ + String? outputPath, + required String bottomsheetName, + String? subfolder, + }) async { String filePath = _templateService.getTemplateOutputPath( inputTemplatePath: kAppMobileTemplateAppPath, name: bottomsheetName, + subfolder: subfolder, outputFolder: outputPath, ); await _fileService.removeSpecificFileLines( diff --git a/lib/src/commands/delete/delete_dialog_command.dart b/lib/src/commands/delete/delete_dialog_command.dart index b559070..916fbc3 100644 --- a/lib/src/commands/delete/delete_dialog_command.dart +++ b/lib/src/commands/delete/delete_dialog_command.dart @@ -57,7 +57,15 @@ class DeleteDialogCommand extends Command with ProjectStructureValidator { try { final workingDirectory = argResults!.rest.length > 1 ? argResults!.rest[1] : null; - final dialogName = argResults!.rest.first; + + // Parse dialog path to support subdirectories + final dialogPath = argResults!.rest.first; + final pathParts = dialogPath.split('/'); + final dialogName = pathParts.last; + final subfolder = pathParts.length > 1 + ? pathParts.sublist(0, pathParts.length - 1).join('/') + : null; + await _configService.composeAndLoadConfigFile( configFilePath: argResults![ksConfigPath], projectPath: workingDirectory, @@ -65,9 +73,14 @@ class DeleteDialogCommand extends Command with ProjectStructureValidator { _processService.formattingLineLength = argResults?[ksLineLength]; await _pubspecService.initialise(workingDirectory: workingDirectory); await validateStructure(outputPath: workingDirectory); - await _deleteDialog(outputPath: workingDirectory, dialogName: dialogName); + await _deleteDialog( + outputPath: workingDirectory, + dialogName: dialogName, + subfolder: subfolder); await _removeDialogFromDependency( - outputPath: workingDirectory, dialogName: dialogName); + outputPath: workingDirectory, + dialogName: dialogName, + subfolder: subfolder); await _processService.runBuildRunner(workingDirectory: workingDirectory); await _analyticsService.deleteDialogEvent( name: argResults!.rest.first, @@ -96,12 +109,18 @@ class DeleteDialogCommand extends Command with ProjectStructureValidator { /// `outputPath` (String): The path to the output folder. /// /// `dialogName` (String): The name of the dialog. - Future _deleteDialog( - {String? outputPath, required String dialogName}) async { + /// + /// `subfolder` (String): Optional subfolder path for organized dialogs. + Future _deleteDialog({ + String? outputPath, + required String dialogName, + String? subfolder, + }) async { /// Deleting the dialog folder. String directoryPath = _templateService.getTemplateOutputPath( inputTemplatePath: 'lib/ui/dialogs/generic', name: dialogName, + subfolder: subfolder, outputFolder: outputPath, ); await _fileService.deleteFolder(directoryPath: directoryPath); @@ -110,6 +129,7 @@ class DeleteDialogCommand extends Command with ProjectStructureValidator { final filePath = _templateService.getTemplateOutputPath( inputTemplatePath: kDialogEmptyTemplateGenericDialogModelTestPath, name: dialogName, + subfolder: subfolder, outputFolder: outputPath, ); @@ -126,11 +146,17 @@ class DeleteDialogCommand extends Command with ProjectStructureValidator { /// `outputPath` (String): The path to the output folder. /// /// `dialogName` (String): The name of the dialog. - Future _removeDialogFromDependency( - {String? outputPath, required String dialogName}) async { + /// + /// `subfolder` (String): Optional subfolder path for organized dialogs. + Future _removeDialogFromDependency({ + String? outputPath, + required String dialogName, + String? subfolder, + }) async { String filePath = _templateService.getTemplateOutputPath( inputTemplatePath: kAppMobileTemplateAppPath, name: dialogName, + subfolder: subfolder, outputFolder: outputPath, ); await _fileService.removeSpecificFileLines( diff --git a/lib/src/commands/delete/delete_service_command.dart b/lib/src/commands/delete/delete_service_command.dart index 6576479..d39c734 100644 --- a/lib/src/commands/delete/delete_service_command.dart +++ b/lib/src/commands/delete/delete_service_command.dart @@ -56,7 +56,15 @@ class DeleteServiceCommand extends Command with ProjectStructureValidator { try { final workingDirectory = argResults!.rest.length > 1 ? argResults!.rest[1] : null; - final serviceName = argResults!.rest.first; + + // Parse service path to support subdirectories + final servicePath = argResults!.rest.first; + final pathParts = servicePath.split('/'); + final serviceName = pathParts.last; + final subfolder = pathParts.length > 1 + ? pathParts.sublist(0, pathParts.length - 1).join('/') + : null; + await _configService.composeAndLoadConfigFile( configFilePath: argResults![ksConfigPath], projectPath: workingDirectory, @@ -65,11 +73,17 @@ class DeleteServiceCommand extends Command with ProjectStructureValidator { await _pubspecService.initialise(workingDirectory: workingDirectory); await validateStructure(outputPath: workingDirectory); await _deleteServiceAndTestFiles( - outputPath: workingDirectory, serviceName: serviceName); + outputPath: workingDirectory, + serviceName: serviceName, + subfolder: subfolder); await _removeServiceFromTestHelper( - outputPath: workingDirectory, serviceName: serviceName); + outputPath: workingDirectory, + serviceName: serviceName, + subfolder: subfolder); await _removeServiceFromDependency( - outputPath: workingDirectory, serviceName: serviceName); + outputPath: workingDirectory, + serviceName: serviceName, + subfolder: subfolder); await _processService.runBuildRunner(workingDirectory: workingDirectory); await _analyticsService.deleteServiceEvent( name: argResults!.rest.first, @@ -92,12 +106,18 @@ class DeleteServiceCommand extends Command with ProjectStructureValidator { /// `outputPath` (String): The path to the output folder. /// /// `serviceName` (String): The name of the service to be deleted. - Future _deleteServiceAndTestFiles( - {String? outputPath, required String serviceName}) async { + /// + /// `subfolder` (String): Optional subfolder path for organized services. + Future _deleteServiceAndTestFiles({ + String? outputPath, + required String serviceName, + String? subfolder, + }) async { /// Deleting the service file. String filePath = _templateService.getTemplateOutputPath( inputTemplatePath: kServiceEmptyTemplateGenericServicePath, name: serviceName, + subfolder: subfolder, outputFolder: outputPath, ); await _fileService.deleteFile(filePath: filePath); @@ -106,6 +126,7 @@ class DeleteServiceCommand extends Command with ProjectStructureValidator { filePath = _templateService.getTemplateOutputPath( inputTemplatePath: kServiceEmptyTemplateGenericServiceTestPath, name: serviceName, + subfolder: subfolder, outputFolder: outputPath, ); await _fileService.deleteFile(filePath: filePath); @@ -118,11 +139,17 @@ class DeleteServiceCommand extends Command with ProjectStructureValidator { /// `outputPath` (String): The path to the output folder. /// /// `serviceName` (String): The name of the service to be deleted. - Future _removeServiceFromTestHelper( - {String? outputPath, required String serviceName}) async { + /// + /// `subfolder` (String): Optional subfolder path for organized services. + Future _removeServiceFromTestHelper({ + String? outputPath, + required String serviceName, + String? subfolder, + }) async { String filePath = _templateService.getTemplateOutputPath( inputTemplatePath: kAppMobileTemplateTestHelpersPath, name: serviceName, + subfolder: subfolder, outputFolder: outputPath, ); await _fileService.removeSpecificFileLines( @@ -139,11 +166,17 @@ class DeleteServiceCommand extends Command with ProjectStructureValidator { /// `outputPath` (String): The path to the output folder. /// /// `serviceName` (String): The name of the service to be deleted. - Future _removeServiceFromDependency( - {String? outputPath, required String serviceName}) async { + /// + /// `subfolder` (String): Optional subfolder path for organized services. + Future _removeServiceFromDependency({ + String? outputPath, + required String serviceName, + String? subfolder, + }) async { String filePath = _templateService.getTemplateOutputPath( inputTemplatePath: kAppMobileTemplateAppPath, name: serviceName, + subfolder: subfolder, outputFolder: outputPath, ); await _fileService.removeSpecificFileLines( diff --git a/lib/src/commands/delete/delete_view_command.dart b/lib/src/commands/delete/delete_view_command.dart index 1d86b78..9668866 100644 --- a/lib/src/commands/delete/delete_view_command.dart +++ b/lib/src/commands/delete/delete_view_command.dart @@ -56,7 +56,15 @@ class DeleteViewCommand extends Command with ProjectStructureValidator { try { final workingDirectory = argResults!.rest.length > 1 ? argResults!.rest[1] : null; - final viewName = argResults!.rest.first; + + // Parse view path to support subdirectories + final viewPath = argResults!.rest.first; + final pathParts = viewPath.split('/'); + final viewName = pathParts.last; + final subfolder = pathParts.length > 1 + ? pathParts.sublist(0, pathParts.length - 1).join('/') + : null; + await _configService.composeAndLoadConfigFile( configFilePath: argResults![ksConfigPath], projectPath: workingDirectory, @@ -65,9 +73,13 @@ class DeleteViewCommand extends Command with ProjectStructureValidator { await _pubspecService.initialise(workingDirectory: workingDirectory); await validateStructure(outputPath: workingDirectory); await _deleteViewAndTestFiles( - outputPath: workingDirectory, viewName: viewName); + outputPath: workingDirectory, + viewName: viewName, + subfolder: subfolder); await _removeViewFromRoute( - outputPath: workingDirectory, viewName: viewName); + outputPath: workingDirectory, + viewName: viewName, + subfolder: subfolder); await _processService.runBuildRunner(workingDirectory: workingDirectory); await _analyticsService.deleteViewEvent( name: argResults!.rest.first, @@ -90,12 +102,18 @@ class DeleteViewCommand extends Command with ProjectStructureValidator { /// `outputPath` (String): The path to the output folder. /// /// `viewName` (String): The name of the view. - Future _deleteViewAndTestFiles( - {String? outputPath, required String viewName}) async { + /// + /// `subfolder` (String): Optional subfolder path for organized views. + Future _deleteViewAndTestFiles({ + String? outputPath, + required String viewName, + String? subfolder, + }) async { /// Deleting the view folder. String directoryPath = _templateService.getTemplateOutputPath( inputTemplatePath: 'lib/ui/views/generic/', name: viewName, + subfolder: subfolder, outputFolder: outputPath, ); await _fileService.deleteFolder(directoryPath: directoryPath); @@ -104,6 +122,7 @@ class DeleteViewCommand extends Command with ProjectStructureValidator { String filePath = _templateService.getTemplateOutputPath( inputTemplatePath: kViewEmptyTemplateGenericViewmodelTestPath, name: viewName, + subfolder: subfolder, outputFolder: outputPath, ); await _fileService.deleteFile(filePath: filePath); @@ -116,11 +135,17 @@ class DeleteViewCommand extends Command with ProjectStructureValidator { /// `outputPath` (String): The path to the output folder. /// /// `viewName` (String): The name of the view. - Future _removeViewFromRoute( - {String? outputPath, required String viewName}) async { + /// + /// `subfolder` (String): Optional subfolder path for organized views. + Future _removeViewFromRoute({ + String? outputPath, + required String viewName, + String? subfolder, + }) async { String filePath = _templateService.getTemplateOutputPath( inputTemplatePath: kAppMobileTemplateAppPath, name: viewName, + subfolder: subfolder, outputFolder: outputPath, ); await _fileService.removeSpecificFileLines(