mason icon indicating copy to clipboard operation
mason copied to clipboard

feat: Read a default configuration file by convention instead of configuration

Open jsroest opened this issue 2 years ago ā€¢ 2 comments

Description

I have a brick that generates two files:

  1. page
  2. controller

To be able to share the brick across projects, I've added some variables:

  1. project_name
  2. page_id
  3. page_name

This works great, but when you are working on a project, the project_name is for that project always the same. Asking the project_name is redundant and error-prone.

So I've added a configuration file mason-variables.json.

The Flutter project source is also generated using Mason, which means that this file is in my case always available and the content is specific for the generated Flutter project.

{
    "project_name": "flutter_demo_app"
}

So now I can run:

mason make rubigo_page -c mason-variables.json

and now the brick only asks for

  1. page_id
  2. page_name

Is there a way that I can eliminate the need for adding -c mason-variables.json to the mason command?

Of course, I could write a shell script, but that's not platform-independent. I also tried mason_hooks, but the pre_gen hook is executed after the variables are asked to the user.

A better idea might be to solve this by convention, for example, that a file with the name mason-variables.json in the working directory is read by default by Mason.

jsroest avatar Sep 05 '22 13:09 jsroest

Hi @jsroest šŸ‘‹ Thanks for opening an issue!

Can you please provide a bit more context?

Using the -c flag is what Iā€™d recommend in this case. Do you just not like specifying the path to the configuration file?

You should be able to use a pre_gen.dart hook to dynamically set the project name. You can remove the project name from vars in the brick.yaml and just use the hook to populate the variable.

Lastly, you can always create an alias for this if you want to type slightly slightly fewer characters.

Let me know what you think, thanks!

felangel avatar Sep 05 '22 13:09 felangel

Hi,

Thanks for your quick reply.

Do you just not like specifying the path to the configuration file?

That's exactly the case.

Lastly, you can always create an alias for this if you want to type slightly fewer characters.

We have a mixed environment here, macOS and Windows. That would not be cross-platform.

You should be able to use a pre_gen.dart hook to dynamically set the project name. You can remove the project name from vars in the brick.yaml and just use the hook to populate the variable.

I've tried that.

This is the content of pre_gen.dart:

import 'package:mason/mason.dart';

void run(HookContext context) {
  // Read/Write vars
  context.vars = {...context.vars, 'project_name': 'flutter_demo_app'};

  // Use the logger
  context.logger.info('hook says hi!');
}

The problem with that is the variable project_name is still asked by Mason, and after that, overwritten by the pre_gen hook. This is confusing.

johannesroest@ws-z14 app % mason make rubigo_page
? What is the project name? this_will_be_overwritten
? What is the page id? s010
? What is the page name? ask_for_credentials
hook says hi!
āœ“ Made brick rubigo_page (64ms)
āœ“ Generated 2 file(s):
  /Users/johannesroest/repos/1122334-flutter_demo_app/packages/app/lib/pages/s010_ask_for_credentials/s010_ask_for_credentials_controller.dart (identical)
  /Users/johannesroest/repos/1122334-flutter_demo_app/packages/app/lib/pages/s010_ask_for_credentials/s010_ask_for_credentials_page.dart (identical)

This is the brick where you can find the {{project_name}}.

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:{{project_name}}/pages/pages.dart';
import 'package:{{project_name}}/pages/{{#snakeCase}}{{page_id}}_{{page_name}}{{/snakeCase}}/{{#snakeCase}}{{page_id}}_{{page_name}}{{/snakeCase}}_controller.dart';
import 'package:rubigo_navigator/rubigo_navigator.dart';

class {{#pascalCase}}{{page_id}}{{/pascalCase}}{{#pascalCase}}{{page_name}}{{/pascalCase}}Page extends RubigoPage<Pages, {{#pascalCase}}{{page_id}}{{/pascalCase}}{{#pascalCase}}{{page_name}}{{/pascalCase}}Controller> {
  const {{#pascalCase}}{{page_id}}{{/pascalCase}}{{#pascalCase}}{{page_name}}{{/pascalCase}}Page(ChangeNotifierProvider<{{#pascalCase}}{{page_id}}{{/pascalCase}}{{#pascalCase}}{{page_name}}{{/pascalCase}}Controller> controllerProvider,
      {Key? key})
      : super(controllerProvider, key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('{{#snakeCase}}{{page_id}}_{{page_name}}{{/snakeCase}}'),
      ),
      body: Container(),
    );
  }
}

That's why it's great for my case if Mason loads a configuration file with a specific name, for example mason-variables.json in the current folder by default. If the file is there, it will be read automatically, if the file is not there, Mason will ask for the variable.

It's not something that I can not live without, but it does streamline our use case.

jsroest avatar Sep 05 '22 14:09 jsroest