@@ -3,23 +3,40 @@ module Wasp.Cli.Command.Build
3
3
)
4
4
where
5
5
6
+ import Control.Lens
6
7
import Control.Monad (unless , when )
7
- import Control.Monad.Except (throwError )
8
+ import Control.Monad.Except (ExceptT ( ExceptT ), runExceptT , throwError )
8
9
import Control.Monad.IO.Class (liftIO )
10
+ import Data.Aeson (Value (.. ))
11
+ import Data.Aeson.Lens
12
+ import qualified Data.HashMap.Strict as HM
13
+ import Data.List (isSuffixOf )
14
+ import Data.Text (Text , unpack )
9
15
import StrongPath (Abs , Dir , Path' , castRel , (</>) )
16
+ import qualified System.FilePath as FP
10
17
import Wasp.Cli.Command (Command , CommandError (.. ))
11
18
import Wasp.Cli.Command.Compile (compileIOWithOptions , printCompilationResult )
12
19
import Wasp.Cli.Command.Message (cliSendMessageC )
13
20
import Wasp.Cli.Command.Require (InWaspProject (InWaspProject ), require )
14
21
import Wasp.Cli.Message (cliSendMessage )
15
22
import Wasp.CompileOptions (CompileOptions (.. ))
16
- import qualified Wasp.Generator
23
+ import Wasp.Generator.Common ( ProjectRootDir )
17
24
import Wasp.Generator.Monad (GeneratorWarning (GeneratorNeedsMigrationWarning ))
18
25
import Wasp.Generator.SdkGenerator.Common (sdkRootDirInGeneratedCodeDir , sdkRootDirInProjectRootDir )
19
26
import qualified Wasp.Message as Msg
20
- import Wasp.Project (CompileError , CompileWarning , WaspProjectDir )
21
- import Wasp.Project.Common (buildDirInDotWaspDir , dotWaspDirInWaspProjectDir , generatedCodeDirInDotWaspDir , packageJsonInWaspProjectDir , packageLockJsonInWaspProjectDir , srcDirInWaspProjectDir )
27
+ import Wasp.Project.Common
28
+ ( CompileError ,
29
+ CompileWarning ,
30
+ WaspProjectDir ,
31
+ buildDirInDotWaspDir ,
32
+ dotWaspDirInWaspProjectDir ,
33
+ generatedCodeDirInDotWaspDir ,
34
+ packageJsonInWaspProjectDir ,
35
+ packageLockJsonInWaspProjectDir ,
36
+ srcDirInWaspProjectDir ,
37
+ )
22
38
import Wasp.Util.IO (copyDirectory , copyFile , doesDirectoryExist , removeDirectory )
39
+ import Wasp.Util.Json (updateJsonFile )
23
40
24
41
-- | Builds Wasp project that the current working directory is part of.
25
42
-- Does all the steps, from analysis to generation, and at the end writes generated code
@@ -58,40 +75,79 @@ build = do
58
75
throwError $
59
76
CommandError " Building of wasp project failed" $ show (length errors) ++ " errors found."
60
77
61
- liftIO $ copyUserFilesNecessaryForBuild waspProjectDir buildDir
78
+ liftIO (prepareFilesNecessaryForDockerBuild waspProjectDir buildDir) >>= \ case
79
+ Left err -> throwError $ CommandError " Failed to prepare files necessary for docker build" err
80
+ Right () -> return ()
62
81
63
82
cliSendMessageC $
64
83
Msg. Success " Your wasp project has been successfully built! Check it out in the .wasp/build directory."
65
84
where
66
- -- Until we implement the solution described in https://github.com/wasp-lang/wasp/issues/1769,
67
- -- we're copying all files and folders necessary for the build into the .wasp/build directory.
68
- -- We chose this approach for 0.12.0 (instead of building from the project root) because:
69
- -- - The build context remains small (~1.5 MB vs ~900 MB).
70
- -- - We don't risk copying possible secrets from the project root into the build context.
71
- -- - The commands for building the project stay the same as before
72
- -- 0.12.0, which is good for both us (e.g., for fly deployment) and our
73
- -- users (no changes in CI/CD scripts).
74
- -- For more details, read the issue linked above.
75
- copyUserFilesNecessaryForBuild waspProjectDir buildDir = do
76
- copyDirectory
77
- (waspProjectDir </> srcDirInWaspProjectDir)
78
- (buildDir </> castRel srcDirInWaspProjectDir)
79
-
80
- copyDirectory
81
- (waspProjectDir </> dotWaspDirInWaspProjectDir </> generatedCodeDirInDotWaspDir </> sdkRootDirInGeneratedCodeDir)
82
- (buildDir </> sdkRootDirInGeneratedCodeDir)
83
-
84
- copyFile
85
- (waspProjectDir </> packageJsonInWaspProjectDir)
86
- (buildDir </> castRel packageJsonInWaspProjectDir)
87
-
88
- copyFile
89
- (waspProjectDir </> packageLockJsonInWaspProjectDir)
90
- (buildDir </> castRel packageLockJsonInWaspProjectDir)
85
+ prepareFilesNecessaryForDockerBuild waspProjectDir buildDir = runExceptT $ do
86
+ -- Until we implement the solution described in https://github.com/wasp-lang/wasp/issues/1769,
87
+ -- we're copying all files and folders necessary for Docker build into the .wasp/build directory.
88
+ -- We chose this approach for 0.12.0 (instead of building from the project root) because:
89
+ -- - The Docker build context remains small (~1.5 MB vs ~900 MB).
90
+ -- - We don't risk copying possible secrets from the project root into Docker's build context.
91
+ -- - The commands for building the project stay the same as before
92
+ -- 0.12.0, which is good for both us (e.g., for fly deployment) and our
93
+ -- users (no changes in CI/CD scripts).
94
+ -- For more details, read the issue linked above.
95
+ liftIO $
96
+ copyDirectory
97
+ (waspProjectDir </> srcDirInWaspProjectDir)
98
+ (buildDir </> castRel srcDirInWaspProjectDir)
99
+
100
+ liftIO $
101
+ copyDirectory
102
+ (waspProjectDir </> dotWaspDirInWaspProjectDir </> generatedCodeDirInDotWaspDir </> sdkRootDirInGeneratedCodeDir)
103
+ (buildDir </> sdkRootDirInGeneratedCodeDir)
104
+
105
+ let packageJsonInBuildDir = buildDir </> castRel packageJsonInWaspProjectDir
106
+ let packageLockJsonInBuildDir = buildDir </> castRel packageLockJsonInWaspProjectDir
107
+
108
+ liftIO $
109
+ copyFile
110
+ (waspProjectDir </> packageJsonInWaspProjectDir)
111
+ packageJsonInBuildDir
112
+
113
+ liftIO $
114
+ copyFile
115
+ (waspProjectDir </> packageLockJsonInWaspProjectDir)
116
+ packageLockJsonInBuildDir
117
+
118
+ -- A hacky quick fix for https://github.com/wasp-lang/wasp/issues/2368
119
+ -- We should remove this code once we implement a proper solution.
120
+ ExceptT $ updateJsonFile removeWaspConfigFromDevDependenciesArray packageJsonInBuildDir
121
+ ExceptT $ updateJsonFile removeAllMentionsOfWaspConfigInPackageLockJson packageLockJsonInBuildDir
122
+
123
+ removeAllMentionsOfWaspConfigInPackageLockJson :: Value -> Value
124
+ removeAllMentionsOfWaspConfigInPackageLockJson packageLockJsonObject =
125
+ -- We want to:
126
+ -- 1. Remove the `wasp-config` dev dependency from the root package in package-lock.json.
127
+ -- This is at `packageLock["packages"][""]["wasp-config"]`.
128
+ -- 2. Remove all package location entries for the `wasp-config` package
129
+ -- (i.e., entries whose location keys end in `/wasp-config`).
130
+ -- Example locations include:
131
+ -- packageLock["packages"]["../../data/packages/wasp-config"]
132
+ -- packageLock["packages"]["node_modules/wasp-config"]
133
+ -- packageLock["packages"]["/home/filip/../wasp-config"]
134
+ packageLockJsonObject
135
+ & key " packages" . key " " %~ removeWaspConfigFromDevDependenciesArray
136
+ & key " packages" . _Object
137
+ %~ HM. filterWithKey
138
+ (\ packageLocation _ -> not $ isWaspConfigPackageLocation packageLocation)
139
+
140
+ isWaspConfigPackageLocation :: Text -> Bool
141
+ isWaspConfigPackageLocation packageLocation =
142
+ (FP. pathSeparator : " wasp-config" ) `isSuffixOf` unpack packageLocation
143
+
144
+ removeWaspConfigFromDevDependenciesArray :: Value -> Value
145
+ removeWaspConfigFromDevDependenciesArray original =
146
+ original & key " devDependencies" . _Object . at " wasp-config" .~ Nothing
91
147
92
148
buildIO ::
93
149
Path' Abs (Dir WaspProjectDir ) ->
94
- Path' Abs (Dir Wasp.Generator. ProjectRootDir ) ->
150
+ Path' Abs (Dir ProjectRootDir ) ->
95
151
IO ([CompileWarning ], [CompileError ])
96
152
buildIO waspProjectDir buildDir = compileIOWithOptions options waspProjectDir buildDir
97
153
where
0 commit comments