Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate user code into client and server directories #753

Merged
merged 41 commits into from
Nov 11, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
4e09b34
Separate ext code to client and server
sodic Oct 12, 2022
86e70fe
Use skeleton in createNewProject and refactor
sodic Oct 14, 2022
bb4107e
Refactor Lib.hs to use ExceptT
sodic Oct 14, 2022
cc7f353
Fix formatting
sodic Oct 14, 2022
492f247
Pop up returns
sodic Oct 14, 2022
d88e204
Extract liftIO and add a do block
sodic Oct 17, 2022
51b426a
Address some review comments
sodic Oct 24, 2022
789dc8f
Add skeleton comment
sodic Oct 24, 2022
6d29601
Extract common CommandError message
sodic Oct 24, 2022
11846e7
Separate skeleton comment into two rows
sodic Oct 24, 2022
4f834ec
Move server and client dirs into src
sodic Oct 24, 2022
385b35c
Simplify maybeToEither
sodic Oct 25, 2022
a7753d2
Further refactor Lib.hs
sodic Oct 25, 2022
53dc889
Further simplify skeleton comment
sodic Oct 25, 2022
8388b0f
Merge branch 'main' into filip-change-project-structure
sodic Oct 25, 2022
40f56d2
Add shared code directory to project structure
sodic Oct 31, 2022
936116b
Update e2e test inputs
sodic Oct 31, 2022
1d4e0d8
Update e2e test outputs
sodic Oct 31, 2022
dc753f4
Fix formatting
sodic Oct 31, 2022
281c3cf
Fix bug in compile function
sodic Oct 31, 2022
a64832c
Change map to fmap in compile function
sodic Oct 31, 2022
b30e3de
Fix formatting
sodic Oct 31, 2022
f40a8ce
Force git to include empty directories
sodic Oct 31, 2022
ddc8682
Remove extra empty line from .gitkeep files
sodic Oct 31, 2022
eb29d50
Watch shared directory for changes
sodic Oct 31, 2022
9fa7e9a
Fix regular and e2e tests
sodic Oct 31, 2022
8674887
Fix cli template packaging and update todoApp
sodic Nov 4, 2022
997fe72
Merge remote-tracking branch 'origin/main' into filip-change-project-…
sodic Nov 4, 2022
0cb6369
Add a shared function demo to todoApp
sodic Nov 4, 2022
8bb94cc
Update waspc and e2e tests
sodic Nov 4, 2022
5f47855
Fix compiler warnings and rename function
sodic Nov 4, 2022
54e0b02
Rename mkError to mkParserError
sodic Nov 4, 2022
0ae2631
Remove redundant empty line
sodic Nov 4, 2022
c5c326e
Merge remote-tracking branch 'origin/main' into filip-change-project-…
sodic Nov 4, 2022
fc76fb6
Fix test warnings
sodic Nov 4, 2022
dc29140
Fix formatting
sodic Nov 4, 2022
36e5766
Merge remote-tracking branch 'origin/main' into filip-change-project-…
sodic Nov 7, 2022
cd101ab
Merge branch 'main' into filip-change-project-structure
sodic Nov 7, 2022
bed02f1
Merge branch 'main' into filip-change-project-structure
sodic Nov 7, 2022
f384d14
Fix directory tree watching on wasp start
sodic Nov 9, 2022
d4a4c07
Implement review feedback
sodic Nov 9, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion waspc/cli/src/Wasp/Cli/Command/Build.hs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ buildIO waspProjectDir buildDir = compileIOWithOptions options waspProjectDir bu
where
options =
CompileOptions
{ externalCodeDirPath = waspProjectDir </> Common.extCodeDirInWaspProjectDir,
{ externalClientCodeDirPath = waspProjectDir </> Common.extClientCodeDirInWaspProjectDir,
externalServerCodeDirPath = waspProjectDir </> Common.extServerCodeDirInWaspProjectDir,
isBuild = True,
sendMessage = cliSendMessage,
-- Ignore "DB needs migration warnings" during build, as that is not a required step.
Expand Down
3 changes: 2 additions & 1 deletion waspc/cli/src/Wasp/Cli/Command/Compile.hs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ compileIOWithOptions options waspProjectDir outDir = do
defaultCompileOptions :: Path' Abs (Dir WaspProjectDir) -> CompileOptions
defaultCompileOptions waspProjectDir =
CompileOptions
{ externalCodeDirPath = waspProjectDir </> Common.extCodeDirInWaspProjectDir,
{ externalServerCodeDirPath = waspProjectDir </> Common.extServerCodeDirInWaspProjectDir,
externalClientCodeDirPath = waspProjectDir </> Common.extClientCodeDirInWaspProjectDir,
isBuild = False,
sendMessage = cliSendMessage,
generatorWarningsFilter = id
Expand Down
152 changes: 45 additions & 107 deletions waspc/cli/src/Wasp/Cli/Command/CreateNewProject.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ where
import Control.Monad.Except (throwError)
Copy link
Contributor Author

@sodic sodic Oct 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I introduced a lot of changes to this file. The best way to review it is probably to avoid looking at the diff altogether.

The main (non-refactor) changes are:

  • We now create two separate directories for user code: client and server
  • Since most of the project scaffolding doesn't depend on anything, we now create a new project mainly by copying a skeleton from our templates and dynamically generate files only when necessary (i.e., for main.wasp file which depends on ProjectInfo).

import Control.Monad.IO.Class (liftIO)
import Data.List (intercalate)
import StrongPath (Abs, Dir, File', Path', Rel, reldir, relfile, (</>))
import StrongPath (Abs, Dir, Path, Path', System, reldir, relfile, (</>))
import qualified StrongPath as SP
import System.Directory (createDirectory, getCurrentDirectory)
import qualified System.Directory
import System.Directory (getCurrentDirectory)
import qualified System.FilePath as FP
import Text.Printf (printf)
import Wasp.Analyzer.Parser (isValidWaspIdentifier)
import Wasp.AppSpec.ExternalCode (SourceExternalCodeDir)
import Wasp.Cli.Command (Command, CommandError (..))
import qualified Wasp.Cli.Command.Common as Command.Common
import Wasp.Cli.Common (WaspProjectDir)
import qualified Wasp.Cli.Common as Common
import qualified Wasp.Data
import qualified Wasp.Data as Data
import Wasp.Generator.FileDraft.WriteableMonad (WriteableMonad (copyDirectoryRecursive))
Martinsos marked this conversation as resolved.
Show resolved Hide resolved
import Wasp.Util (indent, kebabToCamelCase)
import qualified Wasp.Util.Terminal as Term

Expand All @@ -26,14 +26,21 @@ data ProjectInfo = ProjectInfo
_appName :: String
}

createNewProject :: String -> Command ()
createNewProject projectName = do
projectInfo <- parseProjectInfo projectName
createAndPopulateWaspProjectDir projectInfo
liftIO $ printInfoMessages projectInfo

-- Takes a project name String
-- Returns either the ProjectInfo type that contains both the Project name
-- and the App name (which might be the same), or an error describing why the name is invalid
parseProjectInfo :: String -> Either String ProjectInfo
parseProjectInfo :: String -> Command ProjectInfo
Martinsos marked this conversation as resolved.
Show resolved Hide resolved
parseProjectInfo name
| isValidWaspIdentifier appName = Right (ProjectInfo name appName)
| isValidWaspIdentifier appName = return $ ProjectInfo name appName
| otherwise =
Left $
throwError $
CommandError "Project creation failed" $
intercalate
"\n"
[ "The project's name is not in the valid format!",
Expand All @@ -44,81 +51,44 @@ parseProjectInfo name
where
appName = kebabToCamelCase name

createNewProject :: String -> Command ()
createNewProject name =
case parseProjectInfo name of
Right projectInfo -> createNewProject' projectInfo
Left parsedError ->
throwError $
CommandError "Project creation failed" parsedError

createNewProject' :: ProjectInfo -> Command ()
createNewProject' (ProjectInfo projectName appName) = do
createAndPopulateWaspProjectDir :: ProjectInfo -> Command ()
Martinsos marked this conversation as resolved.
Show resolved Hide resolved
createAndPopulateWaspProjectDir projectInfo = do
absWaspProjectDir <- getAbsoluteWaspProjectDir projectInfo
liftIO $ do
initializeProjectFromSkeleton absWaspProjectDir
writeMainWaspFile absWaspProjectDir projectInfo

printInfoMessages :: ProjectInfo -> IO ()
Martinsos marked this conversation as resolved.
Show resolved Hide resolved
printInfoMessages (ProjectInfo projectName _) = do
putStrLn $ Term.applyStyles [Term.Green] ("Created new Wasp app in ./" ++ projectName ++ " directory!")
putStrLn "To run it, do:"
putStrLn ""
putStrLn $ Term.applyStyles [Term.Bold] (" cd " ++ projectName)
putStrLn $ Term.applyStyles [Term.Bold] " wasp start"
putStrLn ""
putStrLn Command.Common.alphaWarningMessage

getAbsoluteWaspProjectDir :: ProjectInfo -> Command (Path System Abs (Dir WaspProjectDir))
shayneczyzewski marked this conversation as resolved.
Show resolved Hide resolved
getAbsoluteWaspProjectDir (ProjectInfo projectName _) = do
absCwd <- liftIO getCurrentDirectory
waspProjectDir <- case SP.parseAbsDir $ absCwd FP.</> projectName of
case SP.parseAbsDir $ absCwd FP.</> projectName of
Right sp -> return sp
Left err ->
throwError $
CommandError
"Project creation failed"
( "Failed to parse absolute path to wasp project dir: "
++ show err
)
Right sp -> return sp
liftIO $ do
createDirectorySP waspProjectDir
writeFileSP (waspProjectDir </> mainWaspFileInWaspProjectDir) mainWaspFileContent
writeFileSP (waspProjectDir </> gitignoreFileInWaspProjectDir) gitignoreFileContent
writeFileSP
(waspProjectDir </> Common.dotWaspRootFileInWaspProjectDir)
"File marking the root of Wasp project."

let extCodeDir = waspProjectDir </> Common.extCodeDirInWaspProjectDir
liftIO $ do
createDirectorySP extCodeDir
dataDir <- Wasp.Data.getAbsDataDirPath

let copyTemplateFile' = copyTemplateFile dataDir extCodeDir
("Failed to parse absolute path to wasp project dir: " ++ show err)

writeFileSP (extCodeDir </> waspignoreFileInExtCodeDir) waspignoreFileContent
initializeProjectFromSkeleton :: Path' Abs (Dir Common.WaspProjectDir) -> IO ()
Martinsos marked this conversation as resolved.
Show resolved Hide resolved
initializeProjectFromSkeleton absWaspProjectDir = do
dataDir <- Data.getAbsDataDirPath
let absSkeletonDir = dataDir </> [reldir|Cli/templates/new|]
copyDirectoryRecursive absSkeletonDir absWaspProjectDir

copyTemplateFile'
[relfile|new/ext/MainPage.js|]
mainPageJsFileInExtCodeDir

copyTemplateFile'
[relfile|new/ext/Main.css|]
mainCssFileInExtCodeDir

copyTemplateFile'
[relfile|new/ext/waspLogo.png|]
waspLogoFileInExtCodeDir

liftIO $ do
putStrLn $ Term.applyStyles [Term.Green] ("Created new Wasp app in ./" ++ projectName ++ " directory!")
putStrLn "To run it, do:"
putStrLn ""
putStrLn $ Term.applyStyles [Term.Bold] (" cd " ++ projectName)
putStrLn $ Term.applyStyles [Term.Bold] " wasp start"
putStrLn ""
putStrLn Command.Common.alphaWarningMessage
writeMainWaspFile :: Path System Abs (Dir WaspProjectDir) -> ProjectInfo -> IO ()
writeMainWaspFile waspProjectDir (ProjectInfo projectName appName) = writeFile mainWaspFileAbsPath mainWaspFileContent
where
copyTemplateFile ::
Path' Abs (Dir Wasp.Data.DataDir) ->
Path' Abs (Dir SourceExternalCodeDir) ->
Path' (Rel Common.CliTemplatesDir) File' ->
Path' (Rel SourceExternalCodeDir) File' ->
IO ()
copyTemplateFile dataDir extCodeDir srcTmplFile dstExtDirFile =
System.Directory.copyFile
(SP.fromAbsFile (dataDir </> cliTemplatesDirInDataDir </> srcTmplFile))
(SP.fromAbsFile (extCodeDir </> dstExtDirFile))

cliTemplatesDirInDataDir :: Path' (Rel Wasp.Data.DataDir) (Dir Common.CliTemplatesDir)
cliTemplatesDirInDataDir = [reldir|Cli/templates|]

mainWaspFileInWaspProjectDir :: Path' (Rel Common.WaspProjectDir) File'
mainWaspFileInWaspProjectDir = [relfile|main.wasp|]

mainWaspFileAbsPath = SP.fromAbsFile $ waspProjectDir </> [relfile|main.wasp|]
mainWaspFileContent =
unlines
[ "app %s {" `printf` appName,
Expand All @@ -130,35 +100,3 @@ createNewProject' (ProjectInfo projectName appName) = do
" component: import Main from \"@ext/MainPage.js\"",
"}"
]

gitignoreFileInWaspProjectDir :: Path' (Rel Common.WaspProjectDir) File'
gitignoreFileInWaspProjectDir = [relfile|.gitignore|]

gitignoreFileContent =
unlines
[ "/.wasp/",
"/.env.server",
"/.env.client"
]

waspignoreFileInExtCodeDir :: Path' (Rel SourceExternalCodeDir) File'
waspignoreFileInExtCodeDir = [relfile|.waspignore|]

waspignoreFileContent =
sodic marked this conversation as resolved.
Show resolved Hide resolved
unlines
[ "# Ignore editor tmp files",
"**/*~",
"**/#*#"
]

mainPageJsFileInExtCodeDir :: Path' (Rel SourceExternalCodeDir) File'
mainPageJsFileInExtCodeDir = [relfile|MainPage.js|]

mainCssFileInExtCodeDir :: Path' (Rel SourceExternalCodeDir) File'
mainCssFileInExtCodeDir = [relfile|Main.css|]

waspLogoFileInExtCodeDir :: Path' (Rel SourceExternalCodeDir) File'
waspLogoFileInExtCodeDir = [relfile|waspLogo.png|]

writeFileSP = writeFile . SP.fromAbsFile
createDirectorySP = createDirectory . SP.fromAbsDir
2 changes: 1 addition & 1 deletion waspc/cli/src/Wasp/Cli/Command/Deps.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import qualified Wasp.Util.Terminal as Term
deps :: Command ()
deps = do
waspProjectDir <- findWaspProjectRootDirFromCwd
(_, appSpecOrAnalyzerErrors) <- liftIO $ analyzeWaspProject waspProjectDir (defaultCompileOptions waspProjectDir)
appSpecOrAnalyzerErrors <- liftIO $ analyzeWaspProject waspProjectDir (defaultCompileOptions waspProjectDir)
appSpec <-
either
(throwError . CommandError "Determining dependencies failed due to a compilation error in your Wasp project" . unwords . toList)
Expand Down
3 changes: 2 additions & 1 deletion waspc/cli/src/Wasp/Cli/Command/Watch.hs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ watch waspProjectDir outDir = FSN.withManager $ \mgr -> do
currentTime <- getCurrentTime
chan <- newChan
_ <- FSN.watchDirChan mgr (SP.fromAbsDir waspProjectDir) eventFilter chan
_ <- FSN.watchTreeChan mgr (SP.fromAbsDir $ waspProjectDir </> Common.extCodeDirInWaspProjectDir) eventFilter chan
_ <- FSN.watchTreeChan mgr (SP.fromAbsDir $ waspProjectDir </> Common.extClientCodeDirInWaspProjectDir) eventFilter chan
_ <- FSN.watchTreeChan mgr (SP.fromAbsDir $ waspProjectDir </> Common.extServerCodeDirInWaspProjectDir) eventFilter chan
listenForEvents chan currentTime
where
listenForEvents :: Chan FSN.Event -> UTCTime -> IO ()
Expand Down
10 changes: 7 additions & 3 deletions waspc/cli/src/Wasp/Cli/Common.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ module Wasp.Cli.Common
dotWaspDirInWaspProjectDir,
dotWaspRootFileInWaspProjectDir,
dotWaspInfoFileInGeneratedCodeDir,
extCodeDirInWaspProjectDir,
extClientCodeDirInWaspProjectDir,
extServerCodeDirInWaspProjectDir,
generatedCodeDirInDotWaspDir,
buildDirInDotWaspDir,
waspSays,
Expand Down Expand Up @@ -41,8 +42,11 @@ dotWaspRootFileInWaspProjectDir = [relfile|.wasproot|]
dotWaspInfoFileInGeneratedCodeDir :: Path' (Rel Wasp.Generator.Common.ProjectRootDir) File'
dotWaspInfoFileInGeneratedCodeDir = [relfile|.waspinfo|]

extCodeDirInWaspProjectDir :: Path' (Rel WaspProjectDir) (Dir SourceExternalCodeDir)
extCodeDirInWaspProjectDir = [reldir|ext|]
extServerCodeDirInWaspProjectDir :: Path' (Rel WaspProjectDir) (Dir SourceExternalCodeDir)
extServerCodeDirInWaspProjectDir = [reldir|server|]

extClientCodeDirInWaspProjectDir :: Path' (Rel WaspProjectDir) (Dir SourceExternalCodeDir)
extClientCodeDirInWaspProjectDir = [reldir|client|]

waspSays :: String -> IO ()
waspSays what = putStrLn $ Term.applyStyles [Term.Yellow] what
Expand Down
3 changes: 3 additions & 0 deletions waspc/data/Cli/templates/new/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/.wasp/
/.env.server
/.env.client
1 change: 1 addition & 0 deletions waspc/data/Cli/templates/new/.wasproot
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
File marking the root of Wasp project.
3 changes: 3 additions & 0 deletions waspc/data/Cli/templates/new/client/.waspignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Ignore editor tmp files
**/*~
**/#*#
3 changes: 3 additions & 0 deletions waspc/data/Cli/templates/new/server/.waspignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Ignore editor tmp files
**/*~
**/#*#
6 changes: 3 additions & 3 deletions waspc/src/Wasp/AppSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ data AppSpec = AppSpec
{ -- | List of declarations like App, Page, Route, ... that describe the web app.
decls :: [Decl],
-- | List of external code files (they are referenced/used by the declarations).
externalCodeFiles :: [ExternalCode.File],
externalServerFiles :: [ExternalCode.File],
-- | List of external code files (they are referenced/used by the declarations).
externalClientFiles :: [ExternalCode.File],
-- | Absolute path to the directory in wasp project source that contains external code files.
externalCodeDirPath :: !(Path' Abs (Dir ExternalCode.SourceExternalCodeDir)),
-- | Absolute path to the directory in wasp project source that contains database migrations.
sodic marked this conversation as resolved.
Show resolved Hide resolved
migrationsDir :: Maybe (Path' Abs (Dir DbMigrationsDir)),
-- | Absolute path to the .env.server file in wasp project source. It contains env variables to be
-- provided to the server only during the development.
Expand Down
3 changes: 2 additions & 1 deletion waspc/src/Wasp/CompileOptions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import Wasp.Message (SendMessage)
-- It would be easier to pass around if it is part of Wasp data. But is it semantically correct?
-- Maybe it is, even more than this!
data CompileOptions = CompileOptions
{ externalCodeDirPath :: !(Path' Abs (Dir SourceExternalCodeDir)),
{ externalServerCodeDirPath :: !(Path' Abs (Dir SourceExternalCodeDir)),
externalClientCodeDirPath :: !(Path' Abs (Dir SourceExternalCodeDir)),
Martinsos marked this conversation as resolved.
Show resolved Hide resolved
isBuild :: !Bool,
-- We give the compiler the ability to send messages. The code that
-- invokes the compiler (such as the CLI) can then implement a way
Expand Down
2 changes: 1 addition & 1 deletion waspc/src/Wasp/Generator/ServerGenerator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ genServer spec =
genGitignore
]
<++> genSrcDir spec
<++> genExternalCodeDir ServerExternalCodeGenerator.generatorStrategy (AS.externalCodeFiles spec)
<++> genExternalCodeDir ServerExternalCodeGenerator.generatorStrategy (AS.externalServerFiles spec)
<++> genDotEnv spec
<++> genJobs spec
<++> genJobExecutors
Expand Down
2 changes: 1 addition & 1 deletion waspc/src/Wasp/Generator/WebAppGenerator.hs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ genWebApp spec = do
]
<++> genPublicDir spec
<++> genSrcDir spec
<++> genExternalCodeDir WebAppExternalCodeGenerator.generatorStrategy (AS.externalCodeFiles spec)
<++> genExternalCodeDir WebAppExternalCodeGenerator.generatorStrategy (AS.externalClientFiles spec)
<++> genDotEnv spec

genDotEnv :: AppSpec -> Generator [FileDraft]
Expand Down
Loading