github.com/gobuffalo/buffalo-cli/v2@v2.0.0-alpha.15.0.20200919213536-a7350c8e6799/cli/cmds/resource/generator.go (about)

     1  package resource
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"github.com/gobuffalo/buffalo-cli/v2/cli/cmds/generate"
    11  	"github.com/gobuffalo/flect/name"
    12  	"github.com/gobuffalo/genny/v2"
    13  	"github.com/gobuffalo/genny/v2/gogen"
    14  	"github.com/gobuffalo/plugins"
    15  	"github.com/gobuffalo/plugins/plugcmd"
    16  	"github.com/gobuffalo/plugins/plugio"
    17  	"github.com/gobuffalo/plugins/plugprint"
    18  	"github.com/spf13/pflag"
    19  )
    20  
    21  var _ plugcmd.Aliaser = Generator{}
    22  var _ generate.Generator = &Generator{}
    23  var _ plugins.Plugin = &Generator{}
    24  var _ plugins.Needer = &Generator{}
    25  var _ plugins.Scoper = &Generator{}
    26  
    27  type Generator struct {
    28  	skipActionTests    bool
    29  	skipActions        bool
    30  	skipMigrationTests bool
    31  	skipMigrations     bool
    32  	skipModelTests     bool
    33  	skipModels         bool
    34  	skipTemplateTests  bool
    35  	skipTemplates      bool
    36  
    37  	flags     *pflag.FlagSet
    38  	help      bool
    39  	pluginsFn plugins.Feeder
    40  }
    41  
    42  func (g *Generator) WithPlugins(f plugins.Feeder) {
    43  	g.pluginsFn = f
    44  }
    45  
    46  func (g Generator) PluginName() string {
    47  	return "resource"
    48  }
    49  
    50  func (g Generator) CmdAliases() []string {
    51  	return []string{"r"}
    52  }
    53  
    54  func (g *Generator) ScopedPlugins() []plugins.Plugin {
    55  	var plugs []plugins.Plugin
    56  	if g.pluginsFn != nil {
    57  		plugs = g.pluginsFn()
    58  	}
    59  
    60  	var builders []plugins.Plugin
    61  
    62  	for _, p := range plugs {
    63  		switch p.(type) {
    64  		case BeforeGenerator:
    65  			builders = append(builders, p)
    66  		case AfterGenerator:
    67  			builders = append(builders, p)
    68  		case Stdouter:
    69  			builders = append(builders, p)
    70  		case Actioner:
    71  			builders = append(builders, p)
    72  		case ActionTester:
    73  			builders = append(builders, p)
    74  		case Modeler:
    75  			builders = append(builders, p)
    76  		case ModelTester:
    77  			builders = append(builders, p)
    78  		case Templater:
    79  			builders = append(builders, p)
    80  		case TemplateTester:
    81  			builders = append(builders, p)
    82  		case Migrationer:
    83  			builders = append(builders, p)
    84  		case MigrationTester:
    85  			builders = append(builders, p)
    86  		case Flagger:
    87  			builders = append(builders, p)
    88  		case Pflagger:
    89  			builders = append(builders, p)
    90  		}
    91  	}
    92  
    93  	return builders
    94  }
    95  
    96  func (g *Generator) beforeGenerate(ctx context.Context, root string, args []string) error {
    97  	plugs := g.ScopedPlugins()
    98  
    99  	for _, p := range plugs {
   100  		if b, ok := p.(BeforeGenerator); ok {
   101  			if err := b.BeforeGenerateResource(ctx, root, args); err != nil {
   102  				return plugins.Wrap(p, err)
   103  			}
   104  		}
   105  	}
   106  
   107  	return nil
   108  }
   109  
   110  func (g *Generator) addResource(root string, n string) error {
   111  	fp := filepath.Join(root, "actions", "app.go")
   112  
   113  	b, err := ioutil.ReadFile(fp)
   114  	if err != nil {
   115  		return plugins.Wrap(g, err)
   116  	}
   117  
   118  	pres := name.New(n)
   119  	stmt := fmt.Sprintf("app.Resource(\"/%s\", %sResource{})", pres.URL(), pres.Resource())
   120  
   121  	gf, err := gogen.AddInsideBlock(genny.NewFileB(fp, b), "if app == nil {", stmt)
   122  	if err != nil {
   123  		return plugins.Wrap(g, err)
   124  	}
   125  
   126  	f, err := os.Create(fp)
   127  	if err != nil {
   128  		return plugins.Wrap(g, err)
   129  	}
   130  	defer f.Close()
   131  
   132  	_, err = f.WriteString(gf.String())
   133  	if err != nil {
   134  		return plugins.Wrap(g, err)
   135  	}
   136  
   137  	return nil
   138  }
   139  
   140  func (g *Generator) afterGenerate(ctx context.Context, root string, args []string, err error) error {
   141  	plugs := g.ScopedPlugins()
   142  
   143  	if err == nil && len(args) > 0 {
   144  		if err := g.addResource(root, args[0]); err != nil {
   145  			return plugins.Wrap(g, err)
   146  		}
   147  	}
   148  
   149  	for _, p := range plugs {
   150  		if b, ok := p.(AfterGenerator); ok {
   151  			if err := b.AfterGenerateResource(ctx, root, args, err); err != nil {
   152  				return plugins.Wrap(b, err)
   153  			}
   154  		}
   155  	}
   156  
   157  	return nil
   158  }
   159  
   160  // Generate implements generate.Generator and is the entry point for `buffalo generate resource`
   161  func (g *Generator) Generate(ctx context.Context, root string, args []string) error {
   162  	if len(args) == 0 {
   163  		err := fmt.Errorf("you must specify a name for the resource")
   164  		return plugins.Wrap(g, err)
   165  	}
   166  
   167  	flags := g.Flags()
   168  	if err := flags.Parse(args); err != nil {
   169  		return plugins.Wrap(g, err)
   170  	}
   171  
   172  	args = flags.Args()
   173  
   174  	plugs := g.ScopedPlugins()
   175  
   176  	if g.help {
   177  		return plugprint.Print(plugio.Stdout(plugs...), g)
   178  	}
   179  
   180  	err := g.run(ctx, root, args)
   181  	return g.afterGenerate(ctx, root, args, err)
   182  }
   183  
   184  func (g *Generator) run(ctx context.Context, root string, args []string) error {
   185  	if err := g.beforeGenerate(ctx, root, args); err != nil {
   186  		return plugins.Wrap(g, err)
   187  	}
   188  
   189  	type step func(context.Context, string, []string) error
   190  
   191  	steps := []step{
   192  		g.generateActionTests,
   193  		g.generateActions,
   194  		g.generateMigrationTests,
   195  		g.generateMigrations,
   196  		g.generateModelTests,
   197  		g.generateModels,
   198  		g.generateTemplateTests,
   199  		g.generateTemplates,
   200  	}
   201  
   202  	for i, step := range steps {
   203  		if err := step(ctx, root, args); err != nil {
   204  			return fmt.Errorf("(%d) %w", i, plugins.Wrap(g, err))
   205  		}
   206  	}
   207  
   208  	return nil
   209  }
   210  
   211  func (g *Generator) generateActions(ctx context.Context, root string, args []string) error {
   212  	if g.skipActions {
   213  		return nil
   214  	}
   215  
   216  	for _, p := range g.ScopedPlugins() {
   217  		if ag, ok := p.(Actioner); ok {
   218  			if err := ag.GenerateResourceActions(ctx, root, args); err != nil {
   219  				return plugins.Wrap(ag, err)
   220  			}
   221  		}
   222  	}
   223  
   224  	return nil
   225  }
   226  
   227  func (g *Generator) generateActionTests(ctx context.Context, root string, args []string) error {
   228  	if g.skipActionTests {
   229  		return nil
   230  	}
   231  
   232  	for _, p := range g.ScopedPlugins() {
   233  		if ag, ok := p.(ActionTester); ok {
   234  			if err := ag.GenerateResourceActionTests(ctx, root, args); err != nil {
   235  				return plugins.Wrap(ag, err)
   236  			}
   237  		}
   238  	}
   239  
   240  	return nil
   241  }
   242  
   243  func (g *Generator) generateTemplates(ctx context.Context, root string, args []string) error {
   244  	if g.skipTemplates {
   245  		return nil
   246  	}
   247  
   248  	for _, p := range g.ScopedPlugins() {
   249  		if ag, ok := p.(Templater); ok {
   250  			if err := ag.GenerateResourceTemplates(ctx, root, args); err != nil {
   251  				return plugins.Wrap(ag, err)
   252  			}
   253  		}
   254  	}
   255  
   256  	return nil
   257  }
   258  
   259  func (g *Generator) generateTemplateTests(ctx context.Context, root string, args []string) error {
   260  	if g.skipTemplateTests {
   261  		return nil
   262  	}
   263  
   264  	for _, p := range g.ScopedPlugins() {
   265  		if ag, ok := p.(TemplateTester); ok {
   266  			if err := ag.GenerateResourceTemplateTests(ctx, root, args); err != nil {
   267  				return plugins.Wrap(ag, err)
   268  			}
   269  		}
   270  	}
   271  
   272  	return nil
   273  }
   274  
   275  func (g *Generator) generateModels(ctx context.Context, root string, args []string) error {
   276  	if g.skipModels {
   277  		return nil
   278  	}
   279  	for _, p := range g.ScopedPlugins() {
   280  		if ag, ok := p.(Modeler); ok {
   281  			if err := ag.GenerateResourceModels(ctx, root, args); err != nil {
   282  				return plugins.Wrap(p, err)
   283  			}
   284  		}
   285  	}
   286  	return nil
   287  }
   288  
   289  func (g *Generator) generateModelTests(ctx context.Context, root string, args []string) error {
   290  	if g.skipModelTests {
   291  		return nil
   292  	}
   293  
   294  	for _, p := range g.ScopedPlugins() {
   295  		if ag, ok := p.(ModelTester); ok {
   296  			if err := ag.GenerateResourceModelTests(ctx, root, args); err != nil {
   297  				return plugins.Wrap(ag, err)
   298  			}
   299  		}
   300  	}
   301  
   302  	return nil
   303  }
   304  
   305  func (g *Generator) generateMigrations(ctx context.Context, root string, args []string) error {
   306  	if g.skipMigrations {
   307  		return nil
   308  	}
   309  
   310  	for _, p := range g.ScopedPlugins() {
   311  		if ag, ok := p.(Migrationer); ok {
   312  			if err := ag.GenerateResourceMigrations(ctx, root, args); err != nil {
   313  				return plugins.Wrap(ag, err)
   314  			}
   315  		}
   316  	}
   317  
   318  	return nil
   319  }
   320  
   321  func (g *Generator) generateMigrationTests(ctx context.Context, root string, args []string) error {
   322  	if g.skipMigrationTests {
   323  		return nil
   324  	}
   325  
   326  	for _, p := range g.ScopedPlugins() {
   327  		if ag, ok := p.(MigrationTester); ok {
   328  			if err := ag.GenerateResourceMigrationTests(ctx, root, args); err != nil {
   329  				return plugins.Wrap(ag, err)
   330  			}
   331  		}
   332  	}
   333  
   334  	return nil
   335  }