Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

blueprint injection or rerendering #115

Open
anithri opened this issue Sep 25, 2017 · 6 comments
Open

blueprint injection or rerendering #115

anithri opened this issue Sep 25, 2017 · 6 comments

Comments

@anithri
Copy link
Collaborator

anithri commented Sep 25, 2017

There are a number of cases where the ability to inject new text into an existing file would be very useful.
imports, Routes, reducers, sagas.

The trick is to figure out where this is supposed to happen, and what is to be inserted.

I think that any effort that involves parsing the file as code is too complicated and we should reach for a simpler solution. Parsing text and string matching is going to be faster and probably more reliable in the long run.

@anithri
Copy link
Collaborator Author

anithri commented Sep 25, 2017

Had a thought. Most of the time injection is useful for (generically) adding a member to a collection, a new route to the router, a new reducer for combineReducers. And most of the time, the target of the injection will be something that was generated by a related blueprint.

What if we rerender the target file by combining the config it used last time it was rendered and combine it with the current data. It'd have to be made clear that the file is autogenerated, and a mechanism for saving the original config would need to be established.

But it's much easier than scraping the file to find the right insertion point.

@anithri
Copy link
Collaborator Author

anithri commented Sep 25, 2017

There's been some discussion related to this at #6 I'll be closing that to continue here.

@SpencerCDixon
Copy link
Owner

In most of my personal blueprints I actually just look for 'magic comments' or imports that I know will never get removed and do my insertions related to those.

@jamesr73
Copy link
Contributor

@SpencerCDixon would be great if you could share an example of a blueprint you use to do that.

@SpencerCDixon
Copy link
Owner

SpencerCDixon commented Sep 27, 2017

Sure:

const path = require('path');
const fs   = require('fs');

const modulesPath = path.resolve('src', 'modules', 'index.js');

module.exports = {
  description() {
    return "Generates a new feature module";
  },

  fileMapTokens(options) {
    return {
      __module_name__: function(options) {
        return options.entity.name;
      }
    }
  },

  afterInstall(options) {
    this.writeImport(options.entity.name);
    this.writeReducer(options.entity.name);
  },

  writeImport(name) {
    this.ui.writeInfo('Adding import statement for module');
    const importString = `import ${name} from 'modules/${name}';`;
    const content = fs.readFileSync(modulesPath).toString().split('\n');
    content.splice(1, 0, importString);
    fs.writeFileSync(modulesPath, content.join('\n'), 'utf8');
    this.ui.writeCreate('Successfully added import of new module');
  },

  writeReducer(name) {
    this.ui.writeInfo('Adding reducer to modules');
    const reducerString = `  [${name}.constants.NAME]: ${name}.reducer,`;

    const content = fs.readFileSync(modulesPath).toString().split('\n');
    const reducerIndex = content.indexOf('export default combineReducers({') + 1;

    content.splice(reducerIndex, 0, reducerString);
    fs.writeFileSync(modulesPath, content.join('\n'), 'utf8');
    this.ui.writeCreate('Successfully added reducer of new module');
  },
};

It would be nice to come up with clean abstractions for how to add LOC in specific places. I think that the 'magic comment' idea would make the implementation much easier but open to discussing some potential solutions. The solution I show above is pretty flaky since if the source changes a bunch then it could break the BP. However, I depend on things that are pretty absolute. First one writing an import just does it in the beginning of the file and the one that adds the reducer looks for combineReducers which is an API of Redux that's not going to be changing

@anithri
Copy link
Collaborator Author

anithri commented Oct 1, 2017

  partial = string || function(data) || PartialBlueprint
  target = targeter.addImport(destFile);
  blueprint.insertPartial(partial, target, data);
  target = targeter.afterMatch(/pattern/,destFile);
  target = targeter.beforeMatch(/pattern/,destFile);
  target = targeter.afterComment(/interesting/, destination); # special case of Match
  target = targeter.beforeComment(/interesting/, destination); # special case of Match
  target = targeter.startOf(destFile);
  target = targeter.endOf(destFile);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants