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

Implement the project install step #1602

Merged
merged 20 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ replaceTemplatePlaceholdersInWaspFile ::
NewProjectAppName -> NewProjectName -> Path' Abs (Dir WaspProjectDir) -> IO ()
replaceTemplatePlaceholdersInWaspFile appName projectName projectDir = do
findWaspFile projectDir >>= \case
Left _ -> return ()
Right absMainWaspFile ->
Nothing -> return ()
Just absMainWaspFile ->
updateFileContentWith absMainWaspFile (replacePlaceholders waspFileReplacements)
where
updateFileContentWith :: Path' Abs (File f) -> (Text -> Text) -> IO ()
Expand Down
17 changes: 14 additions & 3 deletions waspc/data/Cli/templates/basic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,20 @@
"name": "prototype",
"dependencies": {
"wasp": "file:.wasp/out/sdk/wasp",
"react": "18.2.0"
"react": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.37"
}
"@types/react": "^18.0.37",
"prisma": "4.16.2"
Martinsos marked this conversation as resolved.
Show resolved Hide resolved
},
"//": [
"COMMENTS:",
{
"devDependencies.prisma": [
"We on purpose specify exact version for prisma.",
"Check this GH comment for the reasoning behind it:",
"https://github.com/wasp-lang/wasp/pull/634#issuecomment-1158802302 ."
]
}
],
}
5 changes: 4 additions & 1 deletion waspc/data/Generator/templates/react-app/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{={= =}=}}
/// <reference types="vitest" />
import { mergeConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import react from "@vitejs/plugin-react";

{=# customViteConfig.isDefined =}
{=& customViteConfig.importStatement =}
Expand Down Expand Up @@ -30,6 +30,9 @@ const defaultViteConfig = {
environment: "jsdom",
setupFiles: ["./src/test/vitest/setup.ts"],
},
// resolve: {
// dedupe: ["react", "react-dom"],
// },
};

// https://vitejs.dev/config/
Expand Down
5 changes: 5 additions & 0 deletions waspc/data/Generator/templates/sdk/dependencies.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,8 @@ depsRequiredByWebSockets spec,
("@types/cors", "^2.8.5")
]
}


LOG:
- react moved from web-app to project package.json
- react-dom moved from web-app to project package.json
1 change: 1 addition & 0 deletions waspc/examples/todo-typescript/cleanstart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rm -r .wasp node_modules package-lock.json migrations; cabal run wasp-cli db migrate-dev -- --name init && ./fix; cabal run wasp-cli start
1 change: 1 addition & 0 deletions waspc/examples/todo-typescript/fix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rm -r .wasp/out/web-app/node_modules/{react,.vite}
8 changes: 4 additions & 4 deletions waspc/examples/todo-typescript/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "prototype",
"dependencies": {
"@prisma/client": "^4.16.2",
"react": "18.2.0",
"wasp": "file:.wasp/out/sdk/wasp"
"wasp": "file:.wasp/out/sdk/wasp",
"@prisma/client": "4.16.2",
"react": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.37",
"prisma": "^4.16.2"
"prisma": "4.16.2"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ module Wasp.Analyzer.Evaluator.Evaluation.TypedExpr.Combinators
)
where

import Control.Applicative ((<|>))
import Control.Arrow (left)
import qualified Data.Aeson as Aeson
import qualified Data.ByteString.Lazy.UTF8 as ByteStringLazyUTF8
Expand Down
3 changes: 3 additions & 0 deletions waspc/src/Wasp/AppSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import qualified Wasp.AppSpec.ExternalCode as ExternalCode
import Wasp.AppSpec.Job (Job)
import Wasp.AppSpec.Operation (Operation)
import qualified Wasp.AppSpec.Operation as AS.Operation
import Wasp.AppSpec.PackageJson (PackageJson)
import Wasp.AppSpec.Page (Page)
import Wasp.AppSpec.Query (Query)
import Wasp.AppSpec.Route (Route)
Expand All @@ -59,6 +60,8 @@ import qualified Wasp.SemanticVersion as SV
data AppSpec = AppSpec
{ -- | List of declarations like App, Page, Route, ... that describe the web app.
decls :: [Decl],
-- | The contents of the package.json file found in the root directory of the wasp project.
packageJson :: PackageJson,
Martinsos marked this conversation as resolved.
Show resolved Hide resolved
-- | Absolute path to the directory containing the wasp project.
waspProjectDir :: Path' Abs (Dir WaspProjectDir),
-- | List of external server code files (they are referenced/used in the declarations).
Expand Down
2 changes: 0 additions & 2 deletions waspc/src/Wasp/AppSpec/App.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import Data.Data (Data)
import Wasp.AppSpec.App.Auth (Auth)
import Wasp.AppSpec.App.Client (Client)
import Wasp.AppSpec.App.Db (Db)
import Wasp.AppSpec.App.Dependency (Dependency)
import Wasp.AppSpec.App.EmailSender (EmailSender)
import Wasp.AppSpec.App.Server (Server)
import Wasp.AppSpec.App.Wasp (Wasp)
Expand All @@ -22,7 +21,6 @@ data App = App
client :: Maybe Client,
db :: Maybe Db,
emailSender :: Maybe EmailSender,
dependencies :: Maybe [Dependency],
webSocket :: Maybe WebSocket
}
deriving (Show, Eq, Data)
Expand Down
2 changes: 2 additions & 0 deletions waspc/src/Wasp/AppSpec/App/Dependency.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import GHC.Generics

data Dependency = Dependency
{ name :: String,
-- | NOTE: By npm docs, this can be semver version range,
-- but it can also be a URL (tarball, git or Github), or a local file path.
version :: String
}
deriving (Show, Eq, Data, Generic)
Expand Down
25 changes: 25 additions & 0 deletions waspc/src/Wasp/AppSpec/PackageJson.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{-# LANGUAGE DeriveGeneric #-}

module Wasp.AppSpec.PackageJson where

import Data.Aeson (FromJSON)
import Data.Map (Map)
import qualified Data.Map as M
import GHC.Generics (Generic)
import Wasp.AppSpec.App.Dependency (Dependency)
import qualified Wasp.AppSpec.App.Dependency as D

data PackageJson = PackageJson
{ name :: !String,
dependencies :: !(Map String String),
devDependencies :: !(Map String String)
}
deriving (Show, Generic)

instance FromJSON PackageJson

getDependencies :: PackageJson -> [Dependency]
getDependencies packageJson = D.fromList $ M.toList $ dependencies packageJson

getDevDependencies :: PackageJson -> [Dependency]
getDevDependencies packageJson = D.fromList $ M.toList $ devDependencies packageJson
2 changes: 1 addition & 1 deletion waspc/src/Wasp/AppSpec/Valid.hs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ validateWebAppBaseDir :: AppSpec -> [ValidationError]
validateWebAppBaseDir spec = case maybeBaseDir of
Just baseDir
| not (startsWithSlash baseDir) ->
[GenericValidationError "The app.client.baseDir should start with a slash e.g. \"/test\""]
[GenericValidationError "The app.client.baseDir should start with a slash e.g. \"/test\""]
_anyOtherCase -> []
where
maybeBaseDir = Client.baseDir =<< AS.App.client (snd $ getApp spec)
Expand Down
2 changes: 1 addition & 1 deletion waspc/src/Wasp/Generator/Job.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ data JobMessageData

data JobOutputType = Stdout | Stderr deriving (Show, Eq)

data JobType = WebApp | Server | Db deriving (Show, Eq, Ord, Bounded, Enum)
data JobType = WebApp | Server | Db | Wasp deriving (Show, Eq, Ord, Bounded, Enum)
46 changes: 32 additions & 14 deletions waspc/src/Wasp/Generator/Job/IO/PrefixedWriter.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TupleSections #-}

module Wasp.Generator.Job.IO.PrefixedWriter
( printJobMessagePrefixed,
Expand All @@ -10,10 +11,13 @@ where
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.State (get, put)
import Control.Monad.State.Strict (MonadState, StateT, runStateT)
import Data.List (maximumBy)
import Data.Ord (comparing)
import qualified Data.Set as S
import qualified Data.Text as T
import qualified Data.Text.IO as T.IO
import System.IO (hFlush, stderr)
import Wasp.Generator.Job (JobType)
import qualified Wasp.Generator.Job as J
import Wasp.Generator.Job.Common (getJobMessageContent, getJobMessageOutHandle)
import qualified Wasp.Util.Terminal as Term
Expand Down Expand Up @@ -169,30 +173,44 @@ getJobMessageOutput jm =

makeJobMessagePrefix :: J.JobMessage -> T.Text
makeJobMessagePrefix jobMsg =
(T.pack . buildPrefix . concat)
[ [("[", jobStyles)],
T.pack . concatMap (\(text, styles) -> Term.applyStyles styles text) . concat $
[ [(startDelimiter, jobStyles)],
[unstyled namePaddingFront],
[(jobName, jobStyles)],
[unstyled namePaddingBack],
styledFlags,
[("]", jobStyles)]
[(endDelimiter, jobStyles)],
[unstyled " "]
]
where
buildPrefix :: [StyledText] -> String
buildPrefix styledTexts =
concatMap styledTextToTermText styledTexts <> replicate paddingLength ' '
(namePaddingFront, namePaddingBack) =
( replicate namePaddingLengthFront ' ',
replicate namePaddingLengthBack ' '
)
where
numVisibleChars = length $ concatMap fst styledTexts
namePaddingLengthFront = paddingLength `div` 2
namePaddingLengthBack = paddingLength `div` 2 + paddingLength `mod` 2 - length (concatMap fst styledFlags)
paddingLength = max 0 (minPrefixLength - numVisibleChars)
styledTextToTermText (text, styles) = Term.applyStyles styles text
-- NOTE: Adjust this number if you expect longer prefixes!
minPrefixLength = 10
numVisibleChars = length . concat $ [startDelimiter, jobName, endDelimiter]
minPrefixLength = length $ startDelimiter <> " " <> longestJobName <> " " <> endDelimiter
longestJobName =
maximumBy (comparing length) $
fst . getJobNameAndStyles <$> [(minBound :: JobType) .. maxBound]

(jobName, jobStyles) = case J._jobType jobMsg of
(startDelimiter, endDelimiter) = ("[", "]")

styledFlags :: [StyledText]
styledFlags =
[("!", [Term.Red, Term.Bold]) | getJobMessageOutHandle jobMsg == stderr]

(jobName, jobStyles) = getJobNameAndStyles $ J._jobType jobMsg

getJobNameAndStyles = \case
J.Wasp -> ("Wasp", [Term.Yellow])
J.Server -> ("Server", [Term.Magenta])
J.WebApp -> ("Client", [Term.Cyan])
J.Db -> ("Db", [Term.Blue])

styledFlags :: [StyledText]
styledFlags =
[("!", [Term.Red]) | getJobMessageOutHandle jobMsg == stderr]
unstyled = (,[])

type StyledText = (String, [Term.Style])
25 changes: 10 additions & 15 deletions waspc/src/Wasp/Generator/NpmDependencies.hs
Martinsos marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ where
import Data.Aeson
import Data.List (intercalate, sort)
import qualified Data.Map as Map
import Data.Maybe (fromMaybe)
import qualified Data.Maybe as Maybe
import GHC.Generics
import Wasp.AppSpec (AppSpec)
import qualified Wasp.AppSpec.App as AS.App
import qualified Wasp.AppSpec as AS
import qualified Wasp.AppSpec.App.Dependency as D
import qualified Wasp.AppSpec.Valid as ASV
import qualified Wasp.AppSpec.PackageJson as AS.PackageJson
import Wasp.Generator.Monad (Generator, GeneratorError (..), logAndThrowGeneratorError)

data NpmDepsForFullStack = NpmDepsForFullStack
Expand Down Expand Up @@ -108,9 +107,9 @@ buildNpmDepsForFullStack spec forServer forWebApp =
getUserNpmDepsForPackage :: AppSpec -> NpmDepsForUser
getUserNpmDepsForPackage spec =
NpmDepsForUser
{ userDependencies = fromMaybe [] $ AS.App.dependencies $ snd $ ASV.getApp spec,
{ userDependencies = AS.PackageJson.getDependencies $ AS.packageJson spec,
-- Should we allow user devDependencies? https://github.com/wasp-lang/wasp/issues/456
userDevDependencies = []
userDevDependencies = AS.PackageJson.getDevDependencies $ AS.packageJson spec
}

conflictErrorToMessage :: DependencyConflictError -> String
Expand Down Expand Up @@ -141,9 +140,11 @@ combineNpmDepsForPackage npmDepsForWasp npmDepsForUser =
if null conflictErrors && null devConflictErrors
then
Right $
-- todo(filip): check whether dependency updates and npm install work properly
-- todo(filip): reconsider whether we want to change the {sever,web-app}/package.json dynamically
Martinsos marked this conversation as resolved.
Show resolved Hide resolved
NpmDepsForPackage
{ dependencies = waspDependencies npmDepsForWasp ++ remainingUserDeps,
devDependencies = waspDevDependencies npmDepsForWasp ++ remainingUserDevDeps
{ dependencies = Map.elems remainingWapsDeps,
devDependencies = Map.elems remainingWaspDevDeps
Martinsos marked this conversation as resolved.
Show resolved Hide resolved
}
else
Left $
Expand All @@ -159,8 +160,8 @@ combineNpmDepsForPackage npmDepsForWasp npmDepsForUser =
allWaspDepsByName = waspDepsByName `Map.union` waspDevDepsByName
conflictErrors = determineConflictErrors allWaspDepsByName userDepsByName
devConflictErrors = determineConflictErrors allWaspDepsByName userDevDepsByName
remainingUserDeps = getRemainingUserDeps allWaspDepsByName userDepsByName
remainingUserDevDeps = getRemainingUserDeps allWaspDepsByName userDevDepsByName
remainingWapsDeps = allWaspDepsByName `Map.difference` userDepsByName
remainingWaspDevDeps = allWaspDepsByName `Map.difference` userDevDepsByName

type DepsByName = Map.Map String D.Dependency

Expand All @@ -179,12 +180,6 @@ determineConflictErrors waspDepsByName userDepsByName =
then Just $ DependencyConflictError waspDep userDep
else Nothing

-- Given a map of wasp dependencies and a map of user dependencies, construct a
-- a list of user dependencies that remain once any overlapping wasp dependencies
-- have been removed. This assumes conflict detection was already passed.
getRemainingUserDeps :: DepsByName -> DepsByName -> [D.Dependency]
getRemainingUserDeps waspDepsByName userDepsByName = Map.elems $ userDepsByName `Map.difference` waspDepsByName

-- Construct a map of dependency keyed by dependency name.
makeDepsByName :: [D.Dependency] -> DepsByName
makeDepsByName = Map.fromList . fmap (\d -> (D.name d, d))
Expand Down
Loading
Loading