Skip to content

Commit 1e62987

Browse files
authored
Fix building with TS config (#2372)
1 parent c350cbe commit 1e62987

File tree

4 files changed

+112
-33
lines changed

4 files changed

+112
-33
lines changed

waspc/cli/src/Wasp/Cli/Command/Build.hs

Lines changed: 87 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,40 @@ module Wasp.Cli.Command.Build
33
)
44
where
55

6+
import Control.Lens
67
import Control.Monad (unless, when)
7-
import Control.Monad.Except (throwError)
8+
import Control.Monad.Except (ExceptT (ExceptT), runExceptT, throwError)
89
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)
915
import StrongPath (Abs, Dir, Path', castRel, (</>))
16+
import qualified System.FilePath as FP
1017
import Wasp.Cli.Command (Command, CommandError (..))
1118
import Wasp.Cli.Command.Compile (compileIOWithOptions, printCompilationResult)
1219
import Wasp.Cli.Command.Message (cliSendMessageC)
1320
import Wasp.Cli.Command.Require (InWaspProject (InWaspProject), require)
1421
import Wasp.Cli.Message (cliSendMessage)
1522
import Wasp.CompileOptions (CompileOptions (..))
16-
import qualified Wasp.Generator
23+
import Wasp.Generator.Common (ProjectRootDir)
1724
import Wasp.Generator.Monad (GeneratorWarning (GeneratorNeedsMigrationWarning))
1825
import Wasp.Generator.SdkGenerator.Common (sdkRootDirInGeneratedCodeDir, sdkRootDirInProjectRootDir)
1926
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+
)
2238
import Wasp.Util.IO (copyDirectory, copyFile, doesDirectoryExist, removeDirectory)
39+
import Wasp.Util.Json (updateJsonFile)
2340

2441
-- | Builds Wasp project that the current working directory is part of.
2542
-- Does all the steps, from analysis to generation, and at the end writes generated code
@@ -58,40 +75,79 @@ build = do
5875
throwError $
5976
CommandError "Building of wasp project failed" $ show (length errors) ++ " errors found."
6077

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 ()
6281

6382
cliSendMessageC $
6483
Msg.Success "Your wasp project has been successfully built! Check it out in the .wasp/build directory."
6584
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
91147

92148
buildIO ::
93149
Path' Abs (Dir WaspProjectDir) ->
94-
Path' Abs (Dir Wasp.Generator.ProjectRootDir) ->
150+
Path' Abs (Dir ProjectRootDir) ->
95151
IO ([CompileWarning], [CompileError])
96152
buildIO waspProjectDir buildDir = compileIOWithOptions options waspProjectDir buildDir
97153
where

waspc/src/Wasp/Util/IO.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module Wasp.Util.IO
1818
isDirectoryEmpty,
1919
writeFileFromText,
2020
readFileBytes,
21+
writeFileBytes,
2122
)
2223
where
2324

@@ -115,6 +116,9 @@ readFileStrict = T.IO.readFile . SP.toFilePath
115116
writeFile :: Path' Abs (File f) -> String -> IO ()
116117
writeFile = P.writeFile . SP.fromAbsFile
117118

119+
writeFileBytes :: Path' Abs (File f) -> B.ByteString -> IO ()
120+
writeFileBytes = B.writeFile . SP.fromAbsFile
121+
118122
writeFileFromText :: Path' Abs (File f) -> Text -> IO ()
119123
writeFileFromText = T.IO.writeFile . SP.fromAbsFile
120124

waspc/src/Wasp/Util/Json.hs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
1-
module Wasp.Util.Json (parseJsonWithComments) where
1+
module Wasp.Util.Json
2+
( parseJsonWithComments,
3+
updateJsonFile,
4+
)
5+
where
26

3-
import Data.Aeson (FromJSON)
7+
import Control.Monad.Except (ExceptT (..), runExceptT)
8+
import Control.Monad.IO.Class (liftIO)
9+
import Data.Aeson (FromJSON, Value (..), eitherDecode, encode)
10+
import StrongPath (Abs, File, Path')
411
import System.Exit (ExitCode (..))
512
import qualified System.Process as P
613
import Wasp.Util.Aeson (decodeFromString)
14+
import qualified Wasp.Util.IO as IOUtil
715

816
-- | Uses Node.js to parse JSON with comments by treating it as a JavaScript object.
917
-- We use this technique because Aeson can't read JSON with comments and we didn't want to write
@@ -16,3 +24,11 @@ parseJsonWithComments jsonStr = do
1624
case exitCode of
1725
ExitSuccess -> return $ decodeFromString response
1826
_exitFailure -> return $ Left stderr
27+
28+
updateJsonFile :: (Value -> Value) -> Path' Abs (File a) -> IO (Either String ())
29+
updateJsonFile updateFn jsonFilePath = runExceptT $ do
30+
jsonContent <- ExceptT $ eitherDecode <$> IOUtil.readFileBytes jsonFilePath
31+
liftIO $ writeJsonValue jsonFilePath $ updateFn jsonContent
32+
33+
writeJsonValue :: Path' Abs (File f) -> Value -> IO ()
34+
writeJsonValue file = IOUtil.writeFileBytes file . encode

waspc/waspc.cabal

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,8 @@ library cli-lib
505505
, mtl
506506
, async
507507
, exceptions
508+
, lens ^>=5.1
509+
, lens-aeson ^>=1.1.3
508510
, cryptonite
509511
, fsnotify
510512
, http-conduit
@@ -521,6 +523,7 @@ library cli-lib
521523
, waspls
522524
, neat-interpolation
523525
, unliftio ^>= 0.2.20
526+
, unordered-containers ^>= 0.2.16
524527
, bytestring ^>= 0.10.12
525528
, tar ^>=0.5.1.1
526529
, zlib ^>=0.6.3.0

0 commit comments

Comments
 (0)