Skip to main content

Editing Scaffolding Templates โœ๏ธ

In a future version, I plan to look for the templates a project folder and allow overriding the defaults that come with the bricks.

For now, however you will need to clone the desired bricks repo and edit the mustache templates.

The structure is well documented in mason creating brick documentation.

The key structure for template are in the files under the __brick__ folder

โ”œโ”€โ”€ brick.yaml
โ””โ”€โ”€ __brick__
โ””โ”€โ”€<templates files and directories>

Understanding scaffolding and scaffolding_test bricksโ€‹

For converting the properties string into fields and for bringing in optional bricks, the source code for the bricks leverages the hooks hooks/pre_gen.dart and hooks/post_gen.dart.

The result is for scaffolding and scaffolding_test the following variables are avaialble to the templates

VariableTypeExamples
packageStringstatic_scaffolding_sample
featureStringfeature1
propertiesList<Map>[{name: name, type: String, defaultValue: '', emptyValue: '', testValue: 'testString'}]
generate-testbooleantrue
generate-homebooleantrue

A sample of the template for {{feature}}_repoistory_impl.dart shows there variables in use. Also copied below:

import 'dart:async';
import 'package:{{package}}/features/{{feature}}/{{feature}}.dart';

class {{feature.pascalCase()}}RepositoryImpl extends {{feature.pascalCase()}}Repository {

final Map<String, {{feature.pascalCase()}}Model> _store = {};


Future<void> create({{feature.pascalCase()}} {{feature}}) async {
_store[{{feature}}.id] = {{feature.pascalCase()}}Model.from{{feature.pascalCase()}}({{feature}});
addToStream({{feature.pascalCase()}}ChangeInfo(type: {{feature.pascalCase()}}ChangeType.create, {{feature}}s: [{{feature}}]));
}


Future<void> readMore([bool refresh = true]) async {
await _get{{feature.pascalCase()}}sFromStore();
}


Future<void> update({{feature.pascalCase()}} {{feature}}) async {
_store[{{feature}}.id] = {{feature.pascalCase()}}Model.from{{feature.pascalCase()}}({{feature}});
addToStream({{feature.pascalCase()}}ChangeInfo(type: {{feature.pascalCase()}}ChangeType.update, {{feature}}s: [{{feature}}]));
}


Future<void> delete({{feature.pascalCase()}} {{feature}}) async {
_store.remove({{feature}}.id);
addToStream({{feature.pascalCase()}}ChangeInfo(type: {{feature.pascalCase()}}ChangeType.delete, {{feature}}s: [{{feature}}]));
}

Future<void> _get{{feature.pascalCase()}}sFromStore() async {
List<{{feature.pascalCase()}}> {{feature}}List = _store.entries
.map((e) => e.value.to{{feature.pascalCase()}}())
.toList();
addToStream({{feature.pascalCase()}}ChangeInfo(
type: {{feature.pascalCase()}}ChangeType.read,
{{feature}}s: {{feature}}List,
totalCount: {{feature}}List.length));
}
}

Understanding scaffolding_home and scaffolding_home_testโ€‹

The variables and tempalte for these bricks are much simpler. Table below shows and the sample code shows how this can be overridden.

VariableTypeExamples
packageStringstatic_scaffolding_sample
features[String][feature1,feature2]

A sample of the template for scaffold_app.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
{{#features}}import 'package:{{package}}/features/{{.}}/{{.}}.dart';
{{/features}}
class App extends StatelessWidget {
final NavigatorObserver? navigatorObserver;
const App({super.key, this.navigatorObserver});


Widget build(BuildContext context) {
return MaterialApp(
navigatorObservers: navigatorObserver != null ? [navigatorObserver!] : [],
debugShowCheckedModeBanner: false,
title: 'Scaffold App',
home: Builder(builder: (context) {
return Scaffold(
appBar: AppBar(title: const Text('Features')),
body: ListView(children: [
{{#features}}ListTile(
key: const Key('{{.}}-feature-tile'),
leading: const Icon(Icons.view_list, color: Colors.green),
horizontalTitleGap: 0,
title: const Text('{{#sentenceCase}}{{.}}{{/sentenceCase}}'),
onTap: () => Navigator.of(context).push({{#pascalCase}}{{.}}{{/pascalCase}}ReadView.route()),
),{{/features}}
]),
);
}),
);
}
}

Widget appWidget() {
{{#features}}final repo{{#pascalCase}}{{.}}{{/pascalCase}} = {{#pascalCase}}{{.}}{{/pascalCase}}RepositoryImpl();
{{/features}}return
MultiRepositoryProvider(
providers: [
{{#features}}RepositoryProvider<{{#pascalCase}}{{.}}{{/pascalCase}}Repository>.value(
value: repo{{#pascalCase}}{{.}}{{/pascalCase}},
),
{{/features}}],
child: const App(),
);
}

Clone locally and usingโ€‹

To clone the scaffolding bricks and use run the following:

mkdir ~/dev
cd ~/dev
git clone https://github.com/sjhorn/mason_bricks.git

Then to use the package in place of the orginal brick, change to the project directory and intialise as follows:

mason add scaffolding --path ~/dev/mason_broclscaffolding

Then run as explained in the previous pages. .