github.com/TNTworks/flogo-cli@v0.9.1-0.20220522183836-60b8a963ae00/api/create.go (about)

     1  package api
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	"github.com/TNTworks/flogo-cli/common"
    12  	"github.com/TNTworks/flogo-cli/util"
    13  )
    14  
    15  var fileSampleEngineMain = filepath.Join("examples", "engine", "main.go")
    16  
    17  func CreateProject(basePath, appName, appCfgPath, coreVersion string) (common.AppProject, error) {
    18  
    19  	var err error
    20  	var appJson string
    21  
    22  	if appCfgPath != "" {
    23  
    24  		if util.IsRemote(appCfgPath) {
    25  
    26  			appJson, err = util.LoadRemoteFile(appCfgPath)
    27  			if err != nil {
    28  				return nil, fmt.Errorf("unable to load remote app file '%s' - %s", appCfgPath, err.Error())
    29  			}
    30  		} else {
    31  			appJson, err = util.LoadLocalFile(appCfgPath)
    32  			if err != nil {
    33  				return nil, fmt.Errorf("unable to load app file '%s' - %s", appCfgPath, err.Error())
    34  			}
    35  		}
    36  	} else {
    37  		if len(appName) == 0 {
    38  			return nil, fmt.Errorf("app name not specified")
    39  		}
    40  	}
    41  
    42  	appName, err = getAppName(appName, appJson)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  
    47  	fmt.Printf("Creating Flogo App: %s\n", appName)
    48  
    49  	appDir, err := createAppDirectory(basePath, appName)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  
    54  	srcDir := filepath.Join(appDir, "src")
    55  	dm := util.NewDepManager(srcDir)
    56  
    57  	if Verbose() {
    58  		fmt.Printf("Setting up app directory: %s\n", appDir)
    59  	}
    60  
    61  	err = setupAppDirectory(dm, appDir, coreVersion)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	if Verbose() {
    67  		if appJson == "" {
    68  			fmt.Println("Adding sample flogo.json")
    69  		}
    70  	}
    71  	err = createAppJson(dm, appDir, appName, appJson)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	err = createMain(dm, appDir)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  
    81  	project := NewAppProject(appDir)
    82  
    83  	if Verbose() {
    84  		fmt.Println("Importing Dependencies...")
    85  	}
    86  
    87  	err = importDependencies(project)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	if Verbose() {
    93  		fmt.Printf("Created App: %s\n", appName)
    94  	}
    95  
    96  	return project, nil
    97  }
    98  
    99  // createAppDirectory creates the flogo app directory
   100  func createAppDirectory(basePath, appName string) (string, error) {
   101  
   102  	var err error
   103  
   104  	if basePath == "." {
   105  		basePath, err = os.Getwd()
   106  		if err != nil {
   107  			return "", err
   108  		}
   109  	}
   110  
   111  	appPath := filepath.Join(basePath, appName)
   112  	err = os.Mkdir(appPath, os.ModePerm)
   113  	if err != nil {
   114  		return "", err
   115  	}
   116  
   117  	return appPath, nil
   118  }
   119  
   120  //setupAppDirectory sets up the flogo app directory
   121  func setupAppDirectory(dm util.DepManager, appPath, coreVersion string) error {
   122  
   123  	err := os.Mkdir(filepath.Join(appPath, dirBin), os.ModePerm)
   124  	if err != nil {
   125  		return err
   126  	}
   127  
   128  	srcDir := filepath.Join(appPath, dirSrc)
   129  	err = os.Mkdir(srcDir, os.ModePerm)
   130  	if err != nil {
   131  		return err
   132  	}
   133  
   134  	_, err = os.Create(filepath.Join(srcDir, fileImportsGo))
   135  	if err != nil {
   136  		return err
   137  	}
   138  	err = ioutil.WriteFile(filepath.Join(srcDir, fileImportsGo), []byte("package main\n"), 0644)
   139  	if err != nil {
   140  		return err
   141  	}
   142  
   143  	err = dm.Init()
   144  	if err != nil {
   145  		return err
   146  	}
   147  
   148  	flogoCoreImport := util.NewFlogoImport(flogoCoreRepo, "", coreVersion, "")
   149  
   150  	//todo get the actual version installed from the go.mod file
   151  	if coreVersion == "" {
   152  		fmt.Printf("Installing: %s@latest\n", flogoCoreImport.CanonicalImport())
   153  	} else {
   154  		fmt.Printf("Installing: %s\n", flogoCoreImport.CanonicalImport())
   155  	}
   156  
   157  	// add & fetch the core library
   158  	err = dm.AddDependency(flogoCoreImport)
   159  	if err != nil {
   160  		return err
   161  	}
   162  
   163  	return nil
   164  }
   165  
   166  // createAppJson create the flogo app json
   167  func createAppJson(dm util.DepManager, appDir, appName, appJson string) error {
   168  
   169  	updatedJson, err := getAndUpdateAppJson(dm, appName, appJson)
   170  	if err != nil {
   171  		return err
   172  	}
   173  
   174  	err = ioutil.WriteFile(filepath.Join(appDir, fileFlogoJson), []byte(updatedJson), 0644)
   175  	if err != nil {
   176  		return err
   177  	}
   178  
   179  	return nil
   180  }
   181  
   182  // importDependencies import all dependencies
   183  func importDependencies(project common.AppProject) error {
   184  
   185  	ai, err := util.GetAppImports(filepath.Join(project.Dir(), fileFlogoJson), project.DepManager(), true)
   186  	if err != nil {
   187  		return err
   188  	}
   189  
   190  	imports := ai.GetAllImports()
   191  
   192  	if len(imports) == 0 {
   193  		return nil
   194  	}
   195  
   196  	err = project.AddImports(true, false, imports...)
   197  	if err != nil {
   198  		return err
   199  	}
   200  
   201  	legacySupportRequired := false
   202  
   203  	for _, details := range ai.GetAllImportDetails() {
   204  
   205  		path, err := project.GetPath(details.Imp)
   206  		if err != nil {
   207  			return err
   208  		}
   209  
   210  		desc, err := util.GetContribDescriptor(path)
   211  
   212  		if err != nil {
   213  			return err
   214  		}
   215  
   216  		if desc != nil {
   217  
   218  			cType := desc.GetContribType()
   219  			if desc.IsLegacy {
   220  				legacySupportRequired = true
   221  				cType = "legacy " + desc.GetContribType()
   222  				err := CreateLegacyMetadata(path, desc.GetContribType(), details.Imp.GoImportPath())
   223  				if err != nil {
   224  					return err
   225  				}
   226  			}
   227  
   228  			fmt.Printf("Installed %s: %s\n", cType, details.Imp)
   229  			//instStr := fmt.Sprintf("Installed %s:", cType)
   230  			//fmt.Printf("%-20s %s\n", instStr, imp)
   231  		}
   232  	}
   233  
   234  	if legacySupportRequired {
   235  		err := InstallLegacySupport(project)
   236  		return err
   237  	}
   238  
   239  	return nil
   240  }
   241  
   242  func createMain(dm util.DepManager, appDir string) error {
   243  
   244  	flogoCoreImport, err := util.NewFlogoImportFromPath(flogoCoreRepo)
   245  	if err != nil {
   246  		return err
   247  	}
   248  
   249  	corePath, err := dm.GetPath(flogoCoreImport)
   250  	if err != nil {
   251  		return err
   252  	}
   253  
   254  	bytes, err := ioutil.ReadFile(filepath.Join(corePath, fileSampleEngineMain))
   255  	if err != nil {
   256  		return err
   257  	}
   258  
   259  	err = ioutil.WriteFile(filepath.Join(appDir, dirSrc, fileMainGo), bytes, 0644)
   260  	if err != nil {
   261  		return err
   262  	}
   263  
   264  	return nil
   265  }
   266  
   267  func getAndUpdateAppJson(dm util.DepManager, appName, appJson string) (string, error) {
   268  
   269  	if len(appJson) == 0 {
   270  		appJson = emptyFlogoJson
   271  	}
   272  
   273  	descriptor, err := util.ParseAppDescriptor(appJson)
   274  	if err != nil {
   275  		return "", err
   276  	}
   277  
   278  	if appName != "" {
   279  		// override the application name
   280  
   281  		altJson := strings.Replace(appJson, `"`+descriptor.Name+`"`, `"`+appName+`"`, 1)
   282  		altDescriptor, err := util.ParseAppDescriptor(altJson)
   283  
   284  		//see if we can get away with simple replace so we don't reorder the existing json
   285  		if err == nil && altDescriptor.Name == appName {
   286  			appJson = altJson
   287  		} else {
   288  			//simple replace didn't work so we have to unmarshal & re-marshal the supplied json
   289  			var appObj map[string]interface{}
   290  			err := json.Unmarshal([]byte(appJson), &appObj)
   291  			if err != nil {
   292  				return "", err
   293  			}
   294  
   295  			appObj["name"] = appName
   296  
   297  			updApp, err := json.MarshalIndent(appObj, "", "  ")
   298  			if err != nil {
   299  				return "", err
   300  			}
   301  			appJson = string(updApp)
   302  		}
   303  
   304  		descriptor.Name = appName
   305  	} else {
   306  		appName = descriptor.Name
   307  	}
   308  
   309  	return appJson, nil
   310  }
   311  
   312  func getAppName(appName, appJson string) (string, error) {
   313  
   314  	if appJson != "" && appName == "" {
   315  		descriptor, err := util.ParseAppDescriptor(appJson)
   316  		if err != nil {
   317  			return "", err
   318  		}
   319  
   320  		return descriptor.Name, nil
   321  	}
   322  
   323  	return appName, nil
   324  }
   325  func GetTempDir() (string, error) {
   326  
   327  	tempDir, err := ioutil.TempDir("", "flogo")
   328  	if err != nil {
   329  		return "", err
   330  	}
   331  	return tempDir, nil
   332  }
   333  
   334  var emptyFlogoJson = `
   335  {
   336  	"name": "{{.AppName}}",
   337  	"type": "flogo:app",
   338  	"version": "0.0.1",
   339  	"description": "My Flogo Application Description",
   340  	"appModel": "1.1.0",
   341  	"imports": [],
   342  	"triggers": [],
   343  	"resources":[]
   344    }
   345    `