github.com/secoba/wails/v2@v2.6.4/internal/project/project.go (about) 1 package project 2 3 import ( 4 "encoding/json" 5 "os" 6 "path/filepath" 7 "runtime" 8 "strings" 9 10 "github.com/samber/lo" 11 ) 12 13 // Project holds the data related to a Wails project 14 type Project struct { 15 /*** Application Data ***/ 16 Name string `json:"name"` 17 AssetDirectory string `json:"assetdir,omitempty"` 18 19 ReloadDirectories string `json:"reloaddirs,omitempty"` 20 21 BuildCommand string `json:"frontend:build"` 22 InstallCommand string `json:"frontend:install"` 23 24 // Commands used in `wails dev` 25 DevCommand string `json:"frontend:dev"` 26 DevBuildCommand string `json:"frontend:dev:build"` 27 DevInstallCommand string `json:"frontend:dev:install"` 28 DevWatcherCommand string `json:"frontend:dev:watcher"` 29 // The url of the external wails dev server. If this is set, this server is used for the frontend. Default "" 30 FrontendDevServerURL string `json:"frontend:dev:serverUrl"` 31 32 // Directory to generate the API Module 33 WailsJSDir string `json:"wailsjsdir"` 34 35 Version string `json:"version"` 36 37 /*** Internal Data ***/ 38 39 // The path to the project directory 40 Path string `json:"projectdir"` 41 42 // Build directory 43 BuildDir string `json:"build:dir"` 44 45 // The output filename 46 OutputFilename string `json:"outputfilename"` 47 48 // The type of application. EG: Desktop, Server, etc 49 OutputType string 50 51 // The platform to target 52 Platform string 53 54 // RunNonNativeBuildHooks will run build hooks though they are defined for a GOOS which is not equal to the host os 55 RunNonNativeBuildHooks bool `json:"runNonNativeBuildHooks"` 56 57 // Build hooks for different targets, the hooks are executed in the following order 58 // Key: GOOS/GOARCH - Executed at build level before/after a build of the specific platform and arch 59 // Key: GOOS/* - Executed at build level before/after a build of the specific platform 60 // Key: */* - Executed at build level before/after a build 61 // The following keys are not yet supported. 62 // Key: GOOS - Executed at platform level before/after all builds of the specific platform 63 // Key: * - Executed at platform level before/after all builds of a platform 64 // Key: [empty] - Executed at global level before/after all builds of all platforms 65 PostBuildHooks map[string]string `json:"postBuildHooks"` 66 PreBuildHooks map[string]string `json:"preBuildHooks"` 67 68 // The application author 69 Author Author 70 71 // The application information 72 Info Info 73 74 // Fully qualified filename 75 filename string 76 77 // The debounce time for hot-reload of the built-in dev server. Default 100 78 DebounceMS int `json:"debounceMS"` 79 80 // The address to bind the wails dev server to. Default "localhost:34115" 81 DevServer string `json:"devServer"` 82 83 // Arguments that are forwared to the application in dev mode 84 AppArgs string `json:"appargs"` 85 86 // NSISType to be build 87 NSISType string `json:"nsisType"` 88 89 // Garble 90 Obfuscated bool `json:"obfuscated"` 91 GarbleArgs string `json:"garbleargs"` 92 93 // Frontend directory 94 FrontendDir string `json:"frontend:dir"` 95 96 Bindings Bindings `json:"bindings"` 97 } 98 99 func (p *Project) GetFrontendDir() string { 100 if filepath.IsAbs(p.FrontendDir) { 101 return p.FrontendDir 102 } 103 return filepath.Join(p.Path, p.FrontendDir) 104 } 105 106 func (p *Project) GetWailsJSDir() string { 107 if filepath.IsAbs(p.WailsJSDir) { 108 return p.WailsJSDir 109 } 110 return filepath.Join(p.Path, p.WailsJSDir) 111 } 112 113 func (p *Project) GetBuildDir() string { 114 if filepath.IsAbs(p.BuildDir) { 115 return p.BuildDir 116 } 117 return filepath.Join(p.Path, p.BuildDir) 118 } 119 120 func (p *Project) GetDevBuildCommand() string { 121 if p.DevBuildCommand != "" { 122 return p.DevBuildCommand 123 } 124 if p.DevCommand != "" { 125 return p.DevCommand 126 } 127 return p.BuildCommand 128 } 129 130 func (p *Project) GetDevInstallerCommand() string { 131 if p.DevInstallCommand != "" { 132 return p.DevInstallCommand 133 } 134 return p.InstallCommand 135 } 136 137 func (p *Project) IsFrontendDevServerURLAutoDiscovery() bool { 138 return p.FrontendDevServerURL == "auto" 139 } 140 141 func (p *Project) Save() error { 142 data, err := json.MarshalIndent(p, "", " ") 143 if err != nil { 144 return err 145 } 146 return os.WriteFile(p.filename, data, 0o755) 147 } 148 149 func (p *Project) setDefaults() { 150 if p.Path == "" { 151 p.Path = lo.Must(os.Getwd()) 152 } 153 if p.Version == "" { 154 p.Version = "2" 155 } 156 // Create default name if not given 157 if p.Name == "" { 158 p.Name = "wailsapp" 159 } 160 if p.OutputFilename == "" { 161 p.OutputFilename = p.Name 162 } 163 if p.FrontendDir == "" { 164 p.FrontendDir = "frontend" 165 } 166 if p.WailsJSDir == "" { 167 p.WailsJSDir = p.FrontendDir 168 } 169 if p.BuildDir == "" { 170 p.BuildDir = "build" 171 } 172 if p.DebounceMS == 0 { 173 p.DebounceMS = 100 174 } 175 if p.DevServer == "" { 176 p.DevServer = "localhost:34115" 177 } 178 if p.NSISType == "" { 179 p.NSISType = "multiple" 180 } 181 if p.Info.CompanyName == "" { 182 p.Info.CompanyName = p.Name 183 } 184 if p.Info.ProductName == "" { 185 p.Info.ProductName = p.Name 186 } 187 if p.Info.ProductVersion == "" { 188 p.Info.ProductVersion = "1.0.0" 189 } 190 if p.Info.Copyright == nil { 191 v := "Copyright........." 192 p.Info.Copyright = &v 193 } 194 if p.Info.Comments == nil { 195 v := "Built using Wails (https://wails.io)" 196 p.Info.Comments = &v 197 } 198 199 // Fix up OutputFilename 200 switch runtime.GOOS { 201 case "windows": 202 if !strings.HasSuffix(p.OutputFilename, ".exe") { 203 p.OutputFilename += ".exe" 204 } 205 case "darwin", "linux": 206 p.OutputFilename = strings.TrimSuffix(p.OutputFilename, ".exe") 207 } 208 } 209 210 // Author stores details about the application author 211 type Author struct { 212 Name string `json:"name"` 213 Email string `json:"email"` 214 } 215 216 type Info struct { 217 CompanyName string `json:"companyName"` 218 ProductName string `json:"productName"` 219 ProductVersion string `json:"productVersion"` 220 Copyright *string `json:"copyright"` 221 Comments *string `json:"comments"` 222 FileAssociations []FileAssociation `json:"fileAssociations"` 223 Protocols []Protocol `json:"protocols"` 224 } 225 226 type FileAssociation struct { 227 Ext string `json:"ext"` 228 Name string `json:"name"` 229 Description string `json:"description"` 230 IconName string `json:"iconName"` 231 Role string `json:"role"` 232 } 233 234 type Protocol struct { 235 Scheme string `json:"scheme"` 236 Description string `json:"description"` 237 Role string `json:"role"` 238 } 239 240 type Bindings struct { 241 TsGeneration TsGeneration `json:"ts_generation"` 242 } 243 244 type TsGeneration struct { 245 Prefix string `json:"prefix"` 246 Suffix string `json:"suffix"` 247 } 248 249 // Parse the given JSON data into a Project struct 250 func Parse(projectData []byte) (*Project, error) { 251 project := &Project{} 252 err := json.Unmarshal(projectData, project) 253 if err != nil { 254 return nil, err 255 } 256 project.setDefaults() 257 return project, nil 258 } 259 260 // Load the project from the current working directory 261 func Load(projectPath string) (*Project, error) { 262 projectFile := filepath.Join(projectPath, "wails.json") 263 rawBytes, err := os.ReadFile(projectFile) 264 if err != nil { 265 return nil, err 266 } 267 result, err := Parse(rawBytes) 268 if err != nil { 269 return nil, err 270 } 271 result.filename = projectFile 272 return result, nil 273 }