@@ -2,13 +2,18 @@ package main
22
33import (
44 "fmt"
5+ "os"
6+ "path/filepath"
7+ "strings"
58
9+ "github.com/Bananenpro/cli"
610 "github.com/code-game-project/go-utils/cgfile"
11+ "github.com/code-game-project/go-utils/exec"
712 "github.com/code-game-project/go-utils/modules"
13+ cp "github.com/otiai10/copy"
814)
915
1016func Build () error {
11- panic ("not implemented" )
1217 config , err := cgfile .LoadCodeGameFile ("" )
1318 if err != nil {
1419 return err
@@ -18,21 +23,115 @@ func Build() error {
1823 if err != nil {
1924 return err
2025 }
26+ if data .Output == "" {
27+ data .Output = "build"
28+ }
29+
30+ typescript := data .Lang == "ts"
31+
32+ runtime , _ := config .LangConfig ["runtime" ].(string )
33+ if runtime != "node" && runtime != "bundler" && (typescript || runtime != "browser" ) {
34+ return fmt .Errorf ("Invalid runtime: '%s'" , runtime )
35+ }
2136
2237 switch config .Type {
2338 case "client" :
24- return buildClient (config .Game , data .Output , config .URL )
39+ return buildClient (config .Game , data .Output , config .URL , typescript , runtime )
2540 case "server" :
26- return buildServer (data . Output )
41+ return buildServer ()
2742 default :
2843 return fmt .Errorf ("Unknown project type: %s" , config .Type )
2944 }
3045}
3146
32- func buildClient (gameName , output , url string ) error {
47+ func buildClient (gameName , output , url string , typescript bool , runtime string ) error {
48+ yes , err := cli .YesNo (fmt .Sprintf ("The '%s' directory will be completely overridden. Continue?" , output ), false )
49+ if err != nil || ! yes {
50+ return cli .ErrCanceled
51+ }
52+ os .RemoveAll (output )
53+ err = os .MkdirAll (output , 0o755 )
54+ if err != nil {
55+ return fmt .Errorf ("Failed to create output directory: %w" , err )
56+ }
57+
58+ cli .BeginLoading ("Building..." )
59+
60+ if runtime == "node" {
61+ if typescript {
62+ _ , err = exec .Execute (true , "npx" , "tsc" , "--outDir" , output )
63+ if err != nil {
64+ return err
65+ }
66+ } else {
67+ err = cp .Copy ("src" , output , cp.Options {
68+ OnSymlink : func (src string ) cp.SymlinkAction {
69+ return cp .Deep
70+ },
71+ })
72+ if err != nil {
73+ return fmt .Errorf ("Failed to copy source files to output directory: %s" , err )
74+ }
75+ }
76+ } else if runtime == "bundler" {
77+ gameJSPath := filepath .Join ("src" , gameName , "game.js" )
78+ if typescript {
79+ gameJSPath = filepath .Join ("src" , gameName , "game.ts" )
80+ }
81+ err = replaceInFile (gameJSPath , "throw 'Query parameter \" game_url\" must be set.'" , fmt .Sprintf ("return '%s'" , url ))
82+ if err != nil {
83+ return err
84+ }
85+
86+ _ , err = exec .Execute (true , "npx" , "parcel" , "build" , "--dist-dir" , output , "src/index.html" )
87+ if err != nil {
88+ return err
89+ }
90+
91+ err = replaceInFile (gameJSPath , fmt .Sprintf ("return '%s'" , url ), "throw 'Query parameter \" game_url\" must be set.'" )
92+ if err != nil {
93+ return err
94+ }
95+ } else if runtime == "browser" {
96+ err = cp .Copy ("." , output , cp.Options {
97+ Skip : func (src string ) (bool , error ) {
98+ return src == "build" || (src != "node_modules" && strings .HasPrefix (src , "node_modules" ) && ! strings .Contains (src , "@code-game-project" )) || src == ".codegame.json" || src == "package.json" || src == "package-lock.json" , nil
99+ },
100+ })
101+ if err != nil {
102+ return fmt .Errorf ("Failed to copy source files to output directory: %s" , err )
103+ }
104+ }
105+
106+ if runtime != "bundler" {
107+ gameJSPath := filepath .Join (output , gameName , "game.js" )
108+ if runtime == "node" {
109+ err = replaceInFile (gameJSPath , "throw 'Environment variable `CG_GAME_URL` must be set.'" , fmt .Sprintf ("return '%s'" , url ))
110+ } else {
111+ err = replaceInFile (gameJSPath , "throw 'Query parameter \" game_url\" must be set.'" , fmt .Sprintf ("return '%s'" , url ))
112+ }
113+ }
114+ if err != nil {
115+ return err
116+ }
117+ cli .FinishLoading ()
118+ return nil
119+ }
120+
121+ func replaceInFile (filename , old , new string ) error {
122+ content , err := os .ReadFile (filename )
123+ if err != nil {
124+ return fmt .Errorf ("Failed to replace '%s' with '%s' in '%s': %s" , old , new , filename , err )
125+ }
126+ content = []byte (strings .ReplaceAll (string (content ), old , new ))
127+ err = os .WriteFile (filename , content , 0o644 )
128+ if err != nil {
129+ return fmt .Errorf ("Failed to replace '%s' with '%s' in '%s': %s" , old , new , filename , err )
130+ }
33131 return nil
34132}
35133
36- func buildServer (output string ) error {
134+ func buildServer () error {
135+ panic ("not implemented" )
37136 return nil
38137}
0 commit comments