Added check of node version when running node commands.

This commit is contained in:
Martin Sosic 2020-09-14 23:18:04 +02:00 committed by Martin Šošić
parent 10823208f4
commit a4d56b41df
5 changed files with 73 additions and 18 deletions

View File

@ -1 +1,2 @@
v14.5.0
{{={= =}=}}
{= nodeVersion =}

View File

@ -59,6 +59,7 @@ library:
- conduit-extra
- async
- bytestring
- regex-tdfa
executables:
wasp:

View File

@ -1,5 +1,19 @@
module Generator.Common
( ProjectRootDir
, nodeVersion
, nodeVersionAsText
) where
import Text.Printf (printf)
data ProjectRootDir -- ^ Directory where the whole web app project (client, server, ...) is generated.
-- | Node version that node packages generated by this generator expect.
-- (major, minor, patch)
nodeVersion :: (Int, Int, Int)
nodeVersion = (14, 5, 0)
nodeVersionAsText :: String
nodeVersionAsText = printf "v%d.%d.%d" major minor patch
where (major, minor, patch) = nodeVersion

View File

@ -8,8 +8,12 @@ import qualified Data.ByteString.Char8 as BS
import Data.Conduit (runConduit, (.|))
import qualified Data.Conduit.List as CL
import qualified Data.Conduit.Process as CP
import System.Exit (ExitCode (..))
import qualified System.Process as P
import Text.Read (readMaybe)
import qualified Text.Regex.TDFA as R
import qualified Generator.Common as C
import qualified Generator.Job as J
import StrongPath (Abs, Dir, Path)
import qualified StrongPath as SP
@ -18,7 +22,7 @@ import qualified StrongPath as SP
-- | Runs a given process while streaming its stderr and stdout to provided channel.
-- Returns exit code of the process once it finishes, and also sends it to he channel.
runProcessAsJob :: P.CreateProcess -> J.JobType -> J.Job
runProcessAsJob process jobType = \chan -> do
runProcessAsJob process jobType chan = do
(CP.ClosedStream, stdoutStream, stderrStream, processHandle) <- CP.streamingProcess process
-- TODO: Do I need to use Concurrently to run concurrently these three below:
@ -42,8 +46,40 @@ runProcessAsJob process jobType = \chan -> do
return exitCode
runNodeCommandAsJob :: Path Abs (Dir a) -> String -> [String] -> J.JobType -> J.Job
runNodeCommandAsJob fromDir command args jobType = do
-- TODO: Check npm/node version.
let process = (P.proc command args) { P.cwd = Just $ SP.toFilePath fromDir }
runProcessAsJob process jobType
runNodeCommandAsJob fromDir command args jobType chan = do
errorOrNodeVersion <- getNodeVersion
case errorOrNodeVersion of
Left errorMsg -> exitWithError (ExitFailure 1) errorMsg
Right nodeVersion -> if nodeVersion < C.nodeVersion
then exitWithError (ExitFailure 1)
("Your node version is too low, it should be >= " ++ C.nodeVersionAsText)
else do
let process = (P.proc command args) { P.cwd = Just $ SP.toFilePath fromDir }
runProcessAsJob process jobType chan
where
exitWithError exitCode errorMsg = do
writeChan chan $ J.JobMessage
{ J._data = J.JobOutput errorMsg J.Stderr
, J._jobType = jobType }
writeChan chan $ J.JobMessage { J._data = J.JobExit exitCode
, J._jobType = jobType }
return exitCode
getNodeVersion :: IO (Either String (Int, Int, Int))
getNodeVersion = do
(exitCode, stdout, stderr) <- P.readProcessWithExitCode "node" ["--version"] ""
return $ case exitCode of
ExitFailure _ -> Left $ "Running 'node --version' failed: " ++ stderr
ExitSuccess -> case parseNodeVersion stdout of
Nothing -> Left "Wasp failed to parse node version."
Just version -> Right version
parseNodeVersion :: String -> Maybe (Int, Int, Int)
parseNodeVersion nodeVersionStr =
case nodeVersionStr R.=~ ("v([^\\.]+).([^\\.]+).(.+)" :: String) of
((_ , _, _, [majorStr, minorStr, patchStr]) :: (String, String, String, [String])) -> do
major <- readMaybe majorStr
minor <- readMaybe minorStr
patch <- readMaybe patchStr
return (major, minor, patch)
_ -> Nothing

View File

@ -3,19 +3,22 @@ module Generator.ServerGenerator
, operationsRouteInRootRouter
) where
import qualified Path as P
import Data.Aeson ((.=), object)
import Data.Aeson (object, (.=))
import qualified Path as P
import StrongPath (Path, Rel, File)
import qualified StrongPath as SP
import Wasp (Wasp)
import CompileOptions (CompileOptions)
import Generator.FileDraft (FileDraft)
import Generator.ExternalCodeGenerator (generateExternalCodeDir)
import Generator.ServerGenerator.OperationsGenerator (genOperations)
import Generator.ServerGenerator.Common (asTmplFile, asServerFile)
import qualified Generator.ServerGenerator.Common as C
import CompileOptions (CompileOptions)
import Generator.Common (nodeVersionAsText)
import Generator.ExternalCodeGenerator (generateExternalCodeDir)
import Generator.FileDraft (FileDraft)
import Generator.ServerGenerator.Common (asServerFile,
asTmplFile)
import qualified Generator.ServerGenerator.Common as C
import qualified Generator.ServerGenerator.ExternalCodeGenerator as ServerExternalCodeGenerator
import Generator.ServerGenerator.OperationsGenerator (genOperations)
import StrongPath (File, Path,
Rel)
import qualified StrongPath as SP
import Wasp (Wasp)
genServer :: Wasp -> CompileOptions -> [FileDraft]
@ -43,7 +46,7 @@ genNpmrc _ = C.makeTemplateFD (asTmplFile [P.relfile|npmrc|])
genNvmrc :: Wasp -> FileDraft
genNvmrc _ = C.makeTemplateFD (asTmplFile [P.relfile|nvmrc|])
(asServerFile [P.relfile|.nvmrc|])
Nothing
(Just (object ["nodeVersion" .= nodeVersionAsText]))
genGitignore :: Wasp -> FileDraft
genGitignore _ = C.makeTemplateFD (asTmplFile [P.relfile|gitignore|])