amber icon indicating copy to clipboard operation
amber copied to clipboard

[CLI] generate code snippets from plugin recipes

Open damianham opened this issue 7 years ago • 7 comments

Description

The recipe generator could be used to generate all kinds of code snippets. For example it has been suggested that the auth generator be moved out to a plugin. This is a suggestion to create a plugins folder at the root level of amberframework/recipes and to add a plugin generator to amber as part of the recipes generator. When given a plugin name that corresponds to the name of a zip file in the amberframeworks/recipes/plugins folder the generator should download that zip file and use it as the template for the plugin. When given a local directory path the plugin generator should use it as the location of the plugin template.

The named plugin could also be provided by the recipe that was used to create the amber application. The plugin generator should first check a plugins folder in the recipe used to create the application for a plugin corresponding to the given plugin name.

Steps to Reproduce

N/A

Expected behavior:

amber g plugin <plugin_name_or_path>

Actual behavior: [What actually happens] N/A Reproduces how often: [What percentage of the time does it reproduce?] N/A

Versions

Additional Information

damianham avatar Apr 10 '18 14:04 damianham

Hello !

Any news about it?

Maybe if someone have time to make a schema, I could code the plugin manager :smile:

alex-lairan avatar Nov 22 '18 18:11 alex-lairan

#1009 restructures the generators to establish an API for creating your own.

drujensen avatar Dec 30 '18 04:12 drujensen

My current thoughts on the implementation of a plugins feature;

Plugins should be pieces of code that you drop into an Amber app that adds features to your app, much like a gem such as Devise adds features for handling user authentication to a Rails app. Plugins should add namespaced routes, controllers, views, models and migrations where appropriate. Other commands could be added to the Amber plugin CLI to manage plugins. The set of plugin commands could be e.g.

  • amber plugin add PLUGIN_URI
  • amber plugin remove PLUGIN_URI
  • amber plugin migrate [PLUGIN_URI] (migrate all or named plugins)
  • amber plugin rollback [PLUGIN_URI] (rollback the most recent or named plugin migration)

A PLUGIN_URI corresponds to a github repo, e.g. ambercommunity/calendar or a URL to an archive containing the plugin, e.g. https://example-plugin.com/calendar.tgz

Plugins may have shard dependencies which need to be added to the app's shard.yml. This should not necessarily be automatic by the plugin CLI module and could instead form part of the plugin readme so the developer is informed about which shards to add to shard.yml in order to use the plugin. In order to render views from within the plugin folder the damianham/amber_render_module shard will be required. I am in favour of moving this shard to ambercommunity.

Plugins should live in $ROOT/plugins - so ambercommunity/calendar would live in $ROOT/plugins/ambercommunity/calendar. A plugins.cr file should exist in the $ROOT/config/initializers folder that requires every plugin. The CLI plugin module should then add and remove require() calls to this file. The file that is required to load the plugin should be named plugin.cr and live in the plugin folder ($ROOT/plugins/ambercommunity/calendar/plugin.cr) - thus $ROOT/config/initializers/plugins.cr would contain the line require "../../plugins/ambercommunity/calendar/plugin"

Plugin artifacts should be namespaced to avoid conflict with any other plugin or application artifact and the routes MUST be namespaced. The namespace need not be the full repo identity. For example the namespace for ambercommunity/calendar could be ACCalendar. It is not likely there will be many thousands of plugins and if plugin authors follow the rule of tagging the github repo with a set of tags that identify the repo as an Amber plugin (e.g. amber-framework, amber-plugin plugin-namespace-ACCalendar), namespace conflicts can be avoided.

A plugin may include some assets which need to be accessible from $ROOT/public. I am not in favour of copying assets from a plugin assets folder into the public folder during plugin installation but would prefer instead to use symbolic links to make a plugin's assets available to web clients.

A plugin may provide user centric features and Amber CLI allows the auth generator to generate authentication for a named class. In practice this is invariably 'User' although for admin purposes it could be 'Admin' or something else. The plugin readme should clearly state what assumptions it makes about the application, for example that a current_user value of the controller context holds the value of the current logged in user.

damianham avatar Feb 19 '20 06:02 damianham

We could also have a plugin sub-command to generate plugins from a plugin recipe, e.g.

amber plugin generate PLUGIN_URI

which would work along the same lines as the recipe feature in downloading the plugin recipe from the PLUGIN_URI and generating the plugin from the downloaded recipe template.

damianham avatar Feb 20 '20 11:02 damianham

I have a few issues with the current implementation idea.

  1. Why not install the plug-in as a shard? Let shards handle the fetching. This solves the dependency problem. So instead of uri for the plug-in command, you just call the module name. This feels more natural. It would also make the remove command easy as you can scan shards plug-in folder from the shard to see what it adds.

  2. Why a zip? Teeplate works fine? I make shard, at root I make a 'plugin' folder. In there is just some .ecr files like how Amber uses the templates folder in the cli. Installation is easy. Removal scans the shards plug-in folder, keeps a list of the file names and removes those from the project.

However, this idea seems like it would break your syslink idea for public. I mean it doesn't have to but if we are just using teeplate, it would be easiest to install the public files.

What are you thoughts?

The flow would be: Add shard to .yml file, install shard, command to install plugin(teeplates actually installs the files), done. We can even provide some way for plugin authors to use helper methods like "add_routes" for easy insertion.

AndiLavera avatar Feb 21 '20 21:02 AndiLavera

@andrewc910 I agree with you on using a shard and allowing it to handle all the dependencies. Something @damianham and I have been discussing for a while.

The instructions to use your plugin/recipe will be to include your shard and rebuild amber by running shard build amber which will build a local instance in bin/amber. Then run your generator via bin/amber g mycoolplugin args

The issue I ran into when attempting this was adding the generator command to amber. You can recompile amber easily but you cannot include the source from the shards lib directory easily.

If you can figure that out, plugins/recipes can be created by simply cloning a generic template github project and implementing you're templates or generators.

Maybe there is a way to dynamically include the generator and templates without rebuilding amber. Haven't attempted that yet.

drujensen avatar Feb 21 '20 22:02 drujensen

I don't disagree that there is an advantage of adding a plugin as a shard to bring in the dependencies but as you point out Dru you cannot include the source from the shards lib directory easily.

What do you think about if the plugin add command can also added dependencies required by the plugin to shard.yml if they are not already present ? Then post-install and after adding dependencies to shards.yml the plugin add command could run shards install to install them.

What I am proposing is something very similar to NPM node modules (but without a central registry) apart from having the plugin dependencies in the $ROOT/lib folder rather than in $ROOT/plugins/ambercommunity/calender/lib in that they are installed and removed with simple commands as in yarn add npm_name and yarn remove npm_name and once installed you can use the features the plugin provides in your application.

Adding the routes during plugin install would be a good option to make the whole process a lot easier for developers. What would be ultra cool is also adding the plugin routes to menus etc.

damianham avatar Feb 22 '20 08:02 damianham