2022-03-01 23:00:51 +03:00
|
|
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
2023-03-02 17:05:24 +03:00
|
|
|
{-# LANGUAGE InstanceSigs #-}
|
2022-03-01 23:00:51 +03:00
|
|
|
|
|
|
|
module ShellCommands
|
|
|
|
( ShellCommand,
|
|
|
|
ShellCommandContext (..),
|
|
|
|
ShellCommandBuilder (..),
|
|
|
|
runShellCommandBuilder,
|
|
|
|
combineShellCommands,
|
|
|
|
cdIntoCurrentProject,
|
|
|
|
appendToWaspFile,
|
2022-04-13 19:30:29 +03:00
|
|
|
createFile,
|
2022-03-01 23:00:51 +03:00
|
|
|
setDbToPSQL,
|
|
|
|
waspCliNew,
|
|
|
|
waspCliCompile,
|
|
|
|
waspCliMigrate,
|
|
|
|
waspCliBuild,
|
2022-12-13 13:34:59 +03:00
|
|
|
dockerBuild,
|
2023-03-02 17:05:24 +03:00
|
|
|
insertCodeIntoWaspFileAtLineNumber,
|
2022-03-01 23:00:51 +03:00
|
|
|
)
|
|
|
|
where
|
|
|
|
|
|
|
|
import Control.Monad.Reader (MonadReader (ask), Reader, runReader)
|
|
|
|
import Data.List (intercalate)
|
|
|
|
import System.FilePath (joinPath, (</>))
|
|
|
|
|
|
|
|
-- NOTE: Should we consider separating shell parts, Wasp CLI parts, and test helper parts in the future?
|
|
|
|
-- This would likely reqiure adoption of some library, and creating new layers of abstraction.
|
|
|
|
-- Deemed not worth it right now by all.
|
|
|
|
|
|
|
|
-- NOTE: Using `wasp-cli` herein so we can assume using latest `stack install` in CI and locally.
|
|
|
|
|
|
|
|
-- TODO: In future, find a good way to test `wasp-cli start`.
|
|
|
|
|
|
|
|
type ShellCommand = String
|
|
|
|
|
|
|
|
-- Each shell command gets access to the current project name, and maybe other things in future.
|
|
|
|
data ShellCommandContext = ShellCommandContext
|
|
|
|
{ _ctxtCurrentProjectName :: String
|
|
|
|
}
|
|
|
|
deriving (Show)
|
|
|
|
|
|
|
|
-- Used to construct shell commands, while still giving access to the context (if needed).
|
|
|
|
newtype ShellCommandBuilder a = ShellCommandBuilder {_runShellCommandBuilder :: Reader ShellCommandContext a}
|
|
|
|
deriving (Functor, Applicative, Monad, MonadReader ShellCommandContext)
|
|
|
|
|
|
|
|
runShellCommandBuilder :: ShellCommandBuilder a -> ShellCommandContext -> a
|
|
|
|
runShellCommandBuilder shellCommandBuilder context =
|
|
|
|
runReader (_runShellCommandBuilder shellCommandBuilder) context
|
|
|
|
|
|
|
|
combineShellCommands :: [ShellCommand] -> ShellCommand
|
|
|
|
combineShellCommands = intercalate " && "
|
|
|
|
|
|
|
|
cdIntoCurrentProject :: ShellCommandBuilder ShellCommand
|
|
|
|
cdIntoCurrentProject = do
|
|
|
|
context <- ask
|
|
|
|
return $ "cd " ++ _ctxtCurrentProjectName context
|
|
|
|
|
|
|
|
appendToWaspFile :: String -> ShellCommandBuilder ShellCommand
|
|
|
|
appendToWaspFile content =
|
|
|
|
-- NOTE: Using `show` to preserve newlines in string.
|
|
|
|
return $ "printf " ++ show (content ++ "\n") ++ " >> main.wasp"
|
|
|
|
|
2022-04-13 19:30:29 +03:00
|
|
|
-- NOTE: Pretty fragile. Can't handle spaces in args, *nix only, etc.
|
|
|
|
createFile :: String -> FilePath -> String -> ShellCommandBuilder ShellCommand
|
|
|
|
createFile content relDirFp filename = return $ combineShellCommands [createParentDir, writeContentsToFile]
|
|
|
|
where
|
|
|
|
createParentDir = "mkdir -p ./" ++ relDirFp
|
|
|
|
destinationFile = "./" ++ relDirFp ++ "/" ++ filename
|
|
|
|
contents = show (content ++ "\n")
|
|
|
|
writeContentsToFile = unwords ["printf", contents, ">", destinationFile]
|
|
|
|
|
2022-03-01 23:00:51 +03:00
|
|
|
-- NOTE: This is fragile and will likely break in future. Assumes `app` decl is first line and by default
|
|
|
|
-- we do not have a `db` field. Consider better alternatives.
|
|
|
|
setDbToPSQL :: ShellCommandBuilder ShellCommand
|
2023-03-02 17:05:24 +03:00
|
|
|
-- Change DB to postgres by adding string at specific line so it still parses.
|
|
|
|
setDbToPSQL = insertCodeIntoWaspFileAtLineNumber 2 " db: { system: PostgreSQL },"
|
|
|
|
|
|
|
|
insertCodeIntoWaspFileAtLineNumber :: Int -> String -> ShellCommandBuilder ShellCommand
|
|
|
|
insertCodeIntoWaspFileAtLineNumber atLineNumber line =
|
2022-03-01 23:00:51 +03:00
|
|
|
return $
|
|
|
|
combineShellCommands
|
2023-03-02 17:05:24 +03:00
|
|
|
[ "awk 'NR==" ++ show atLineNumber ++ "{print " ++ show line ++ "}1' main.wasp > main.wasp.tmp",
|
2022-03-01 23:00:51 +03:00
|
|
|
"mv main.wasp.tmp main.wasp"
|
|
|
|
]
|
|
|
|
|
|
|
|
waspCliNew :: ShellCommandBuilder ShellCommand
|
|
|
|
waspCliNew = do
|
|
|
|
context <- ask
|
|
|
|
return $ "wasp-cli new " ++ _ctxtCurrentProjectName context
|
|
|
|
|
|
|
|
waspCliCompile :: ShellCommandBuilder ShellCommand
|
|
|
|
waspCliCompile = return "wasp-cli compile"
|
|
|
|
|
|
|
|
-- TODO: We need to be careful what migration names we accept here, as Prisma will
|
|
|
|
-- normalize a migration name containing spaces/dashes to underscores (and maybe other rules).
|
|
|
|
-- This will impact our ability to move directories around if the names do not match exactly.
|
|
|
|
-- Put in some check eventually.
|
|
|
|
waspCliMigrate :: String -> ShellCommandBuilder ShellCommand
|
|
|
|
waspCliMigrate migrationName =
|
|
|
|
let generatedMigrationsDir = joinPath [".wasp", "out", "db", "migrations"]
|
|
|
|
waspMigrationsDir = "migrations"
|
|
|
|
in return $
|
|
|
|
combineShellCommands
|
|
|
|
[ -- Migrate using a migration name to avoid Prisma asking via CLI.
|
2022-12-13 21:55:01 +03:00
|
|
|
"wasp-cli db migrate-dev --name " ++ migrationName,
|
2022-03-01 23:00:51 +03:00
|
|
|
-- Rename both migrations to remove the date-specific portion of the directory to something static.
|
|
|
|
"mv " ++ (waspMigrationsDir </> ("*" ++ migrationName)) ++ " " ++ (waspMigrationsDir </> ("no-date-" ++ migrationName)),
|
|
|
|
"mv " ++ (generatedMigrationsDir </> ("*" ++ migrationName)) ++ " " ++ (generatedMigrationsDir </> ("no-date-" ++ migrationName))
|
|
|
|
]
|
|
|
|
|
|
|
|
waspCliBuild :: ShellCommandBuilder ShellCommand
|
|
|
|
waspCliBuild = return "wasp-cli build"
|
2022-12-13 13:34:59 +03:00
|
|
|
|
|
|
|
dockerBuild :: ShellCommandBuilder ShellCommand
|
|
|
|
dockerBuild =
|
|
|
|
return
|
|
|
|
"[ -z \"$WASP_E2E_TESTS_SKIP_DOCKER\" ] && cd .wasp/build && docker build . && cd ../.. || true"
|