mirror of
https://github.com/wasp-lang/wasp.git
synced 2024-11-23 19:29:17 +03:00
Wasper can now specify npm dependencies.
This commit is contained in:
parent
d936eeba28
commit
ca039304f9
@ -1,22 +1,9 @@
|
||||
{{={= =}=}}
|
||||
{
|
||||
"name": "{= app.name =}",
|
||||
"name": "{= wasp.app.name =}",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.9.1",
|
||||
"@reduxjs/toolkit": "^1.2.3",
|
||||
"axios": "^0.20.0",
|
||||
"lodash": "^4.17.15",
|
||||
"react": "^16.12.0",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-query": "^2.14.1",
|
||||
"react-redux": "^7.1.3",
|
||||
"react-router-dom": "^5.1.2",
|
||||
"react-scripts": "3.4.0",
|
||||
"redux": "^4.0.5",
|
||||
"uuid": "^3.4.0"
|
||||
},
|
||||
{=& depsChunk =},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
|
@ -12,14 +12,7 @@
|
||||
"engines": {
|
||||
"node": ">={= nodeVersion =}"
|
||||
},
|
||||
"dependencies": {
|
||||
"cookie-parser": "~1.4.4",
|
||||
"cors": "^2.8.5",
|
||||
"debug": "~2.6.9",
|
||||
"express": "~4.16.1",
|
||||
"morgan": "~1.9.1",
|
||||
"@prisma/client": "2.x"
|
||||
},
|
||||
{=& depsChunk =},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.4",
|
||||
"standard": "^14.3.4",
|
||||
|
@ -59,6 +59,7 @@ library:
|
||||
- async
|
||||
- bytestring
|
||||
- regex-tdfa
|
||||
- utf8-string
|
||||
|
||||
executables:
|
||||
wasp:
|
||||
@ -114,3 +115,4 @@ tests:
|
||||
- parsec
|
||||
- deepseq
|
||||
- path
|
||||
- unordered-containers
|
||||
|
58
waspc/src/Generator/PackageJsonGenerator.hs
Normal file
58
waspc/src/Generator/PackageJsonGenerator.hs
Normal file
@ -0,0 +1,58 @@
|
||||
module Generator.PackageJsonGenerator
|
||||
( resolveNpmDeps
|
||||
, toPackageJsonDependenciesString
|
||||
) where
|
||||
|
||||
import Data.List (find, intercalate)
|
||||
import Data.Maybe (fromJust, isJust)
|
||||
|
||||
import qualified NpmDependency as ND
|
||||
|
||||
|
||||
type NpmDependenciesConflictError = String
|
||||
|
||||
-- | Takes wasp npm dependencies and user npm dependencies and figures out how to
|
||||
-- combine them together, returning (Right) a list of npm dependencies to be used on
|
||||
-- behalf of wasp and then also a list of npm dependencies to be used on behalf
|
||||
-- of user. These lists might be the same as the initial ones, but might also
|
||||
-- be different.
|
||||
-- On error (Left), returns list of conflicting user deps together with the error message
|
||||
-- explaining what the error is.
|
||||
resolveNpmDeps
|
||||
:: [ND.NpmDependency]
|
||||
-> [ND.NpmDependency]
|
||||
-> Either [(ND.NpmDependency, NpmDependenciesConflictError)]
|
||||
([ND.NpmDependency], [ND.NpmDependency])
|
||||
resolveNpmDeps waspDeps userDeps = if null conflictingUserDeps
|
||||
then Right (waspDeps, userDepsNotInWaspDeps)
|
||||
else Left conflictingUserDeps
|
||||
where
|
||||
conflictingUserDeps :: [(ND.NpmDependency, NpmDependenciesConflictError)]
|
||||
conflictingUserDeps = map (\(dep, err) -> (dep, fromJust err))
|
||||
$ filter (isJust . snd)
|
||||
$ map (\dep -> (dep, checkIfConflictingUserDep dep)) userDeps
|
||||
|
||||
checkIfConflictingUserDep :: ND.NpmDependency -> Maybe NpmDependenciesConflictError
|
||||
checkIfConflictingUserDep userDep =
|
||||
let attachErrorMessage dep = "Error: Dependency conflict for user npm dependency ("
|
||||
++ ND._name dep ++ ", " ++ ND._version dep ++ "): "
|
||||
++ "Version must be set to the exactly the same version as"
|
||||
++ " the one wasp is using: "
|
||||
++ ND._version dep
|
||||
in attachErrorMessage <$> find (areTwoDepsInConflict userDep) waspDeps
|
||||
|
||||
areTwoDepsInConflict :: ND.NpmDependency -> ND.NpmDependency -> Bool
|
||||
areTwoDepsInConflict d1 d2 = ND._name d1 == ND._name d2
|
||||
&& ND._version d1 /= ND._version d2
|
||||
|
||||
userDepsNotInWaspDeps :: [ND.NpmDependency]
|
||||
userDepsNotInWaspDeps = filter (not . isDepWithNameInWaspDeps . ND._name) userDeps
|
||||
|
||||
isDepWithNameInWaspDeps :: String -> Bool
|
||||
isDepWithNameInWaspDeps name = any ((name ==). ND._name) waspDeps
|
||||
|
||||
toPackageJsonDependenciesString :: [ND.NpmDependency] -> String
|
||||
toPackageJsonDependenciesString deps =
|
||||
"\"dependencies\": {"
|
||||
++ intercalate ",\n " (map (\dep -> "\"" ++ ND._name dep ++ "\": \"" ++ ND._version dep ++ "\"") deps)
|
||||
++ "\n}"
|
@ -4,27 +4,32 @@ module Generator.ServerGenerator
|
||||
) where
|
||||
|
||||
import Data.Aeson (object, (.=))
|
||||
import Data.List (intercalate)
|
||||
import qualified Path as P
|
||||
|
||||
import CompileOptions (CompileOptions)
|
||||
import Generator.Common (nodeVersionAsText)
|
||||
import Generator.ExternalCodeGenerator (generateExternalCodeDir)
|
||||
import Generator.FileDraft (FileDraft)
|
||||
import Generator.PackageJsonGenerator (resolveNpmDeps, toPackageJsonDependenciesString)
|
||||
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 qualified NpmDependency as ND
|
||||
import StrongPath (File, Path,
|
||||
Rel)
|
||||
import qualified StrongPath as SP
|
||||
import Wasp (Wasp)
|
||||
import qualified Wasp
|
||||
import qualified Wasp.NpmDependencies as WND
|
||||
|
||||
|
||||
genServer :: Wasp -> CompileOptions -> [FileDraft]
|
||||
genServer wasp _ = concat
|
||||
[ [genReadme wasp]
|
||||
, [genPackageJson wasp]
|
||||
, [genPackageJson wasp waspNpmDeps]
|
||||
, [genNpmrc wasp]
|
||||
, [genNvmrc wasp]
|
||||
, [genGitignore wasp]
|
||||
@ -35,10 +40,35 @@ genServer wasp _ = concat
|
||||
genReadme :: Wasp -> FileDraft
|
||||
genReadme _ = C.copyTmplAsIs (asTmplFile [P.relfile|README.md|])
|
||||
|
||||
genPackageJson :: Wasp -> FileDraft
|
||||
genPackageJson _ = C.makeTemplateFD (asTmplFile [P.relfile|package.json|])
|
||||
(asServerFile [P.relfile|package.json|])
|
||||
(Just (object ["nodeVersion" .= nodeVersionAsText]))
|
||||
genPackageJson :: Wasp -> [ND.NpmDependency] -> FileDraft
|
||||
genPackageJson wasp waspDeps = C.makeTemplateFD
|
||||
(asTmplFile [P.relfile|package.json|])
|
||||
(asServerFile [P.relfile|package.json|])
|
||||
(Just $ object
|
||||
[ "wasp" .= wasp
|
||||
, "depsChunk" .= toPackageJsonDependenciesString (resolvedWaspDeps ++ resolvedUserDeps)
|
||||
, "nodeVersion" .= nodeVersionAsText
|
||||
])
|
||||
where
|
||||
(resolvedWaspDeps, resolvedUserDeps) =
|
||||
case resolveNpmDeps waspDeps userDeps of
|
||||
Right deps -> deps
|
||||
Left depsAndErrors -> error $ intercalate " ; " $ map snd depsAndErrors
|
||||
|
||||
userDeps :: [ND.NpmDependency]
|
||||
userDeps = WND._dependencies $ Wasp.getNpmDependencies wasp
|
||||
|
||||
waspNpmDeps :: [ND.NpmDependency]
|
||||
waspNpmDeps = ND.fromList
|
||||
[ ("cookie-parser", "~1.4.4")
|
||||
, ("cors", "^2.8.5")
|
||||
, ("debug", "~2.6.9")
|
||||
, ("express", "~4.16.1")
|
||||
, ("morgan", "~1.9.1")
|
||||
, ("@prisma/client", "2.x")
|
||||
]
|
||||
|
||||
-- TODO: Also extract devDependencies like we did dependencies (waspNpmDeps).
|
||||
|
||||
genNpmrc :: Wasp -> FileDraft
|
||||
genNpmrc _ = C.makeTemplateFD (asTmplFile [P.relfile|npmrc|])
|
||||
|
@ -2,40 +2,79 @@ module Generator.WebAppGenerator
|
||||
( generateWebApp
|
||||
) where
|
||||
|
||||
import Data.Aeson (ToJSON(..), (.=), object)
|
||||
import qualified Path as P
|
||||
import Data.Aeson (ToJSON (..),
|
||||
object, (.=))
|
||||
import Data.List (intercalate)
|
||||
import qualified Path as P
|
||||
|
||||
import StrongPath (Path, Rel, Dir, (</>))
|
||||
import qualified StrongPath as SP
|
||||
import qualified Util
|
||||
import CompileOptions (CompileOptions)
|
||||
import Wasp
|
||||
import Generator.FileDraft
|
||||
import Generator.ExternalCodeGenerator (generateExternalCodeDir)
|
||||
import qualified Generator.WebAppGenerator.EntityGenerator as EntityGenerator
|
||||
import qualified Generator.WebAppGenerator.RouterGenerator as RouterGenerator
|
||||
import Generator.WebAppGenerator.Common (asTmplFile, asWebAppFile, asWebAppSrcFile)
|
||||
import qualified Generator.WebAppGenerator.Common as C
|
||||
import CompileOptions (CompileOptions)
|
||||
import Generator.ExternalCodeGenerator (generateExternalCodeDir)
|
||||
import Generator.FileDraft
|
||||
import Generator.PackageJsonGenerator (resolveNpmDeps, toPackageJsonDependenciesString)
|
||||
import Generator.WebAppGenerator.Common (asTmplFile,
|
||||
asWebAppFile,
|
||||
asWebAppSrcFile)
|
||||
import qualified Generator.WebAppGenerator.Common as C
|
||||
import qualified Generator.WebAppGenerator.EntityGenerator as EntityGenerator
|
||||
import qualified Generator.WebAppGenerator.ExternalCodeGenerator as WebAppExternalCodeGenerator
|
||||
import Generator.WebAppGenerator.OperationsGenerator (genOperations)
|
||||
import Generator.WebAppGenerator.OperationsGenerator (genOperations)
|
||||
import qualified Generator.WebAppGenerator.RouterGenerator as RouterGenerator
|
||||
import qualified NpmDependency as ND
|
||||
import StrongPath (Dir, Path,
|
||||
Rel, (</>))
|
||||
import qualified StrongPath as SP
|
||||
import qualified Util
|
||||
import Wasp
|
||||
import qualified Wasp.NpmDependencies as WND
|
||||
|
||||
|
||||
generateWebApp :: Wasp -> CompileOptions -> [FileDraft]
|
||||
generateWebApp wasp _ = concatMap ($ wasp)
|
||||
[ (:[]) . generateReadme
|
||||
, (:[]) . generatePackageJson
|
||||
, (:[]) . generateGitignore
|
||||
, generatePublicDir
|
||||
, generateSrcDir
|
||||
, generateExternalCodeDir WebAppExternalCodeGenerator.generatorStrategy
|
||||
generateWebApp wasp _ = concat
|
||||
[ [generateReadme wasp]
|
||||
, [genPackageJson wasp waspNpmDeps]
|
||||
, [generateGitignore wasp]
|
||||
, generatePublicDir wasp
|
||||
, generateSrcDir wasp
|
||||
, generateExternalCodeDir WebAppExternalCodeGenerator.generatorStrategy wasp
|
||||
]
|
||||
|
||||
|
||||
generateReadme :: Wasp -> FileDraft
|
||||
generateReadme wasp = C.makeSimpleTemplateFD (asTmplFile [P.relfile|README.md|]) wasp
|
||||
|
||||
generatePackageJson :: Wasp -> FileDraft
|
||||
generatePackageJson wasp = C.makeSimpleTemplateFD (asTmplFile [P.relfile|package.json|]) wasp
|
||||
genPackageJson :: Wasp -> [ND.NpmDependency] -> FileDraft
|
||||
genPackageJson wasp waspDeps = C.makeTemplateFD
|
||||
(C.asTmplFile [P.relfile|package.json|])
|
||||
(C.asWebAppFile [P.relfile|package.json|])
|
||||
(Just $ object
|
||||
[ "wasp" .= wasp
|
||||
, "depsChunk" .= toPackageJsonDependenciesString (resolvedWaspDeps ++ resolvedUserDeps)
|
||||
])
|
||||
where
|
||||
(resolvedWaspDeps, resolvedUserDeps) =
|
||||
case resolveNpmDeps waspDeps userDeps of
|
||||
Right deps -> deps
|
||||
Left depsAndErrors -> error $ intercalate " ; " $ map snd depsAndErrors
|
||||
|
||||
userDeps :: [ND.NpmDependency]
|
||||
userDeps = WND._dependencies $ Wasp.getNpmDependencies wasp
|
||||
|
||||
waspNpmDeps :: [ND.NpmDependency]
|
||||
waspNpmDeps = ND.fromList
|
||||
[ ("@material-ui/core", "^4.9.1")
|
||||
, ("@reduxjs/toolkit", "^1.2.3")
|
||||
, ("axios", "^0.20.0")
|
||||
, ("lodash", "^4.17.15")
|
||||
, ("react", "^16.12.0")
|
||||
, ("react-dom", "^16.12.0")
|
||||
, ("react-query", "^2.14.1")
|
||||
, ("react-redux", "^7.1.3")
|
||||
, ("react-router-dom", "^5.1.2")
|
||||
, ("react-scripts", "3.4.0")
|
||||
, ("redux", "^4.0.5")
|
||||
, ("uuid", "^3.4.0")
|
||||
]
|
||||
|
||||
-- TODO: Also extract devDependencies like we did dependencies (waspNpmDeps).
|
||||
|
||||
generateGitignore :: Wasp -> FileDraft
|
||||
generateGitignore wasp = C.makeTemplateFD (asTmplFile [P.relfile|gitignore|])
|
||||
|
@ -43,6 +43,9 @@ reservedNameQuery = "query"
|
||||
reservedNameAction :: String
|
||||
reservedNameAction = "action"
|
||||
|
||||
reservedNameDependencies :: String
|
||||
reservedNameDependencies = "dependencies"
|
||||
|
||||
-- * Data types.
|
||||
|
||||
reservedNameString :: String
|
||||
@ -63,6 +66,7 @@ reservedNames =
|
||||
, reservedNameFrom
|
||||
-- * Wasp element types
|
||||
, reservedNameApp
|
||||
, reservedNameDependencies
|
||||
, reservedNamePage
|
||||
, reservedNameRoute
|
||||
, reservedNameEntityPSL
|
||||
|
21
waspc/src/NpmDependency.hs
Normal file
21
waspc/src/NpmDependency.hs
Normal file
@ -0,0 +1,21 @@
|
||||
module NpmDependency
|
||||
( NpmDependency (..)
|
||||
, fromList
|
||||
) where
|
||||
|
||||
import Data.Aeson (ToJSON (..), object, (.=))
|
||||
|
||||
|
||||
data NpmDependency = NpmDependency
|
||||
{ _name :: !String
|
||||
, _version :: !String }
|
||||
deriving (Show, Eq)
|
||||
|
||||
fromList :: [(String, String)] -> [NpmDependency]
|
||||
fromList = map (\(name, version) -> NpmDependency { _name = name, _version = version })
|
||||
|
||||
instance ToJSON NpmDependency where
|
||||
toJSON npmDep = object
|
||||
[ "name" .= _name npmDep
|
||||
, "version" .= _version npmDep
|
||||
]
|
@ -23,6 +23,7 @@ import Parser.JsImport (jsImport)
|
||||
import Parser.Common (runWaspParser)
|
||||
import qualified Parser.Query
|
||||
import qualified Parser.Action
|
||||
import qualified Parser.NpmDependencies
|
||||
|
||||
waspElement :: Parser Wasp.WaspElement
|
||||
waspElement
|
||||
@ -37,6 +38,7 @@ waspElement
|
||||
<|> waspElementEntity
|
||||
<|> waspElementEntityForm
|
||||
<|> waspElementEntityList
|
||||
<|> waspElementNpmDependencies
|
||||
|
||||
waspElementApp :: Parser Wasp.WaspElement
|
||||
waspElementApp = Wasp.WaspElementApp <$> app
|
||||
@ -68,6 +70,10 @@ waspElementQuery = Wasp.WaspElementQuery <$> Parser.Query.query
|
||||
waspElementAction :: Parser Wasp.WaspElement
|
||||
waspElementAction = Wasp.WaspElementAction <$> Parser.Action.action
|
||||
|
||||
waspElementNpmDependencies :: Parser Wasp.WaspElement
|
||||
waspElementNpmDependencies = Wasp.WaspElementNpmDependencies <$> Parser.NpmDependencies.npmDependencies
|
||||
|
||||
|
||||
-- | Top level parser, produces Wasp.
|
||||
waspParser :: Parser Wasp.Wasp
|
||||
waspParser = do
|
||||
|
@ -36,7 +36,7 @@ waspElementNameAndClosure
|
||||
:: String -- ^ Element type
|
||||
-> Parser a -- ^ Closure parser (needs to parse braces as well, not just the content)
|
||||
-> Parser (String, a) -- ^ Name of the element and parsed closure content.
|
||||
waspElementNameAndClosure elementType closure =
|
||||
waspElementNameAndClosure elementType closure =
|
||||
-- NOTE(matija): It is important to have `try` here because we don't want to consume the
|
||||
-- content intended for other parsers.
|
||||
-- E.g. if we tried to parse "entity-form" this parser would have been tried first for
|
||||
@ -54,7 +54,7 @@ waspElementNameAndClosure elementType closure =
|
||||
elementName <- L.identifier
|
||||
closureContent <- closure
|
||||
|
||||
return (elementName, closureContent)
|
||||
return (elementName, closureContent)
|
||||
|
||||
-- | Parses declaration of a wasp element linked to an entity.
|
||||
-- E.g. "entity-form<Task> ..." or "action<Task> ..."
|
||||
|
31
waspc/src/Parser/NpmDependencies.hs
Normal file
31
waspc/src/Parser/NpmDependencies.hs
Normal file
@ -0,0 +1,31 @@
|
||||
module Parser.NpmDependencies
|
||||
( npmDependencies
|
||||
) where
|
||||
|
||||
import qualified Data.Aeson as Aeson
|
||||
import qualified Data.ByteString.Lazy.UTF8 as BLU
|
||||
import qualified Data.HashMap.Strict as M
|
||||
import Text.Parsec (try)
|
||||
import Text.Parsec.String (Parser)
|
||||
|
||||
import qualified Lexer as L
|
||||
import qualified NpmDependency as ND
|
||||
import qualified Parser.Common as P
|
||||
import Wasp.NpmDependencies (NpmDependencies)
|
||||
import qualified Wasp.NpmDependencies as NpmDependencies
|
||||
|
||||
|
||||
npmDependencies :: Parser NpmDependencies
|
||||
npmDependencies = try $ do
|
||||
L.reserved L.reservedNameDependencies
|
||||
closureContent <- P.waspNamedClosure "json"
|
||||
let jsonBytestring = BLU.fromString $ "{ " ++ closureContent ++ " }"
|
||||
npmDeps <- case Aeson.eitherDecode' jsonBytestring :: Either String (M.HashMap String String) of
|
||||
Left errorMessage -> fail $ "Failed to parse dependencies JSON: " ++ errorMessage
|
||||
Right rawDeps -> return $ map rawDepToNpmDep (M.toList rawDeps)
|
||||
return NpmDependencies.NpmDependencies
|
||||
{ NpmDependencies._dependencies = npmDeps
|
||||
}
|
||||
where
|
||||
rawDepToNpmDep :: (String, String) -> ND.NpmDependency
|
||||
rawDepToNpmDep (name, version) = ND.NpmDependency { ND._name = name, ND._version = version }
|
@ -38,38 +38,43 @@ module Wasp
|
||||
|
||||
, setExternalCodeFiles
|
||||
, getExternalCodeFiles
|
||||
|
||||
, setNpmDependencies
|
||||
, getNpmDependencies
|
||||
) where
|
||||
|
||||
import Data.Aeson ((.=), object, ToJSON(..))
|
||||
import Data.Aeson (ToJSON (..), object, (.=))
|
||||
|
||||
import qualified ExternalCode
|
||||
import Wasp.App
|
||||
import qualified Util as U
|
||||
import qualified Wasp.Action
|
||||
import Wasp.App
|
||||
import Wasp.EntityPSL
|
||||
import Wasp.JsImport
|
||||
import Wasp.NpmDependencies (NpmDependencies)
|
||||
import qualified Wasp.NpmDependencies
|
||||
import Wasp.Page
|
||||
import qualified Wasp.Query
|
||||
import Wasp.Route
|
||||
|
||||
-- TODO(matija): old Entity stuff, to be removed
|
||||
import Wasp.Entity
|
||||
import qualified Wasp.EntityForm as EF
|
||||
import qualified Wasp.EntityList as EL
|
||||
import Wasp.Entity
|
||||
import qualified Wasp.EntityForm as EF
|
||||
import qualified Wasp.EntityList as EL
|
||||
|
||||
import Wasp.EntityPSL
|
||||
import Wasp.JsImport
|
||||
import Wasp.Page
|
||||
import Wasp.Route
|
||||
import qualified Wasp.Query
|
||||
import qualified Wasp.Action
|
||||
|
||||
import qualified Util as U
|
||||
|
||||
-- * Wasp
|
||||
|
||||
data Wasp = Wasp
|
||||
{ waspElements :: [WaspElement]
|
||||
, waspJsImports :: [JsImport]
|
||||
{ waspElements :: [WaspElement]
|
||||
, waspJsImports :: [JsImport]
|
||||
, externalCodeFiles :: [ExternalCode.File]
|
||||
} deriving (Show, Eq)
|
||||
|
||||
data WaspElement
|
||||
= WaspElementApp !App
|
||||
| WaspElementPage !Page
|
||||
| WaspElementNpmDependencies !NpmDependencies
|
||||
| WaspElementRoute !Route
|
||||
| WaspElementEntityPSL !Wasp.EntityPSL.EntityPSL
|
||||
| WaspElementQuery !Wasp.Query.Query
|
||||
@ -115,7 +120,7 @@ getApp wasp = let apps = getApps wasp in
|
||||
|
||||
isAppElem :: WaspElement -> Bool
|
||||
isAppElem WaspElementApp{} = True
|
||||
isAppElem _ = False
|
||||
isAppElem _ = False
|
||||
|
||||
getApps :: Wasp -> [App]
|
||||
getApps wasp = [app | (WaspElementApp app) <- waspElements wasp]
|
||||
@ -126,6 +131,25 @@ setApp wasp app = wasp { waspElements = (WaspElementApp app) : (filter (not . is
|
||||
fromApp :: App -> Wasp
|
||||
fromApp app = fromWaspElems [WaspElementApp app]
|
||||
|
||||
-- * NpmDependencies
|
||||
|
||||
getNpmDependencies :: Wasp -> NpmDependencies
|
||||
getNpmDependencies wasp
|
||||
= let depses = [d | (WaspElementNpmDependencies d) <- waspElements wasp]
|
||||
in case depses of
|
||||
[] -> Wasp.NpmDependencies.empty
|
||||
[deps] -> deps
|
||||
_ -> error "Wasp can't contain more than one NpmDependencies element!"
|
||||
|
||||
isNpmDependenciesElem :: WaspElement -> Bool
|
||||
isNpmDependenciesElem WaspElementNpmDependencies{} = True
|
||||
isNpmDependenciesElem _ = False
|
||||
|
||||
setNpmDependencies :: Wasp -> NpmDependencies -> Wasp
|
||||
setNpmDependencies wasp deps = wasp
|
||||
{ waspElements = WaspElementNpmDependencies deps : filter (not . isNpmDependenciesElem) (waspElements wasp)
|
||||
}
|
||||
|
||||
-- * Routes
|
||||
|
||||
getRoutes :: Wasp -> [Route]
|
||||
|
20
waspc/src/Wasp/NpmDependencies.hs
Normal file
20
waspc/src/Wasp/NpmDependencies.hs
Normal file
@ -0,0 +1,20 @@
|
||||
module Wasp.NpmDependencies
|
||||
( NpmDependencies(..)
|
||||
, empty
|
||||
) where
|
||||
|
||||
import Data.Aeson (ToJSON (..), object, (.=))
|
||||
import NpmDependency
|
||||
|
||||
|
||||
data NpmDependencies = NpmDependencies
|
||||
{ _dependencies :: ![NpmDependency]
|
||||
} deriving (Show, Eq)
|
||||
|
||||
empty :: NpmDependencies
|
||||
empty = NpmDependencies { _dependencies = [] }
|
||||
|
||||
instance ToJSON NpmDependencies where
|
||||
toJSON deps = object
|
||||
[ "dependencies" .= _dependencies deps
|
||||
]
|
34
waspc/test/Generator/PackageJsonGeneratorTest.hs
Normal file
34
waspc/test/Generator/PackageJsonGeneratorTest.hs
Normal file
@ -0,0 +1,34 @@
|
||||
module Generator.PackageJsonGeneratorTest where
|
||||
|
||||
import Test.Tasty.Hspec
|
||||
|
||||
import Generator.PackageJsonGenerator (resolveNpmDeps)
|
||||
import qualified NpmDependency as ND
|
||||
|
||||
|
||||
spec_resolveNpmDeps :: Spec
|
||||
spec_resolveNpmDeps = do
|
||||
let waspDeps = [ ("axios", "^0.20.0")
|
||||
, ("lodash", "^4.17.15")
|
||||
]
|
||||
|
||||
it "Concatenates two distincts lists of deps." $ do
|
||||
let userDeps = [ ("foo", "bar")
|
||||
, ("foo2", "bar2")
|
||||
]
|
||||
resolveNpmDeps (ND.fromList waspDeps) (ND.fromList userDeps)
|
||||
`shouldBe` Right (ND.fromList waspDeps, ND.fromList userDeps)
|
||||
|
||||
it "Does not repeat dep if it is both user and wasp dep." $ do
|
||||
let userDeps = [ ("axios", "^0.20.0")
|
||||
, ("foo", "bar")
|
||||
]
|
||||
resolveNpmDeps (ND.fromList waspDeps) (ND.fromList userDeps)
|
||||
`shouldBe` Right (ND.fromList waspDeps, ND.fromList [("foo", "bar")])
|
||||
|
||||
it "Reports error if user dep version does not match wasp dep version." $ do
|
||||
let userDeps = [ ("axios", "^1.20.0")
|
||||
, ("foo", "bar")
|
||||
]
|
||||
let Left conflicts = resolveNpmDeps (ND.fromList waspDeps) (ND.fromList userDeps)
|
||||
(map fst conflicts) `shouldBe` ND.fromList [("axios", "^1.20.0")]
|
28
waspc/test/Parser/NpmDependenciesTest.hs
Normal file
28
waspc/test/Parser/NpmDependenciesTest.hs
Normal file
@ -0,0 +1,28 @@
|
||||
module Parser.NpmDependenciesTest where
|
||||
|
||||
import Test.Tasty.Hspec
|
||||
|
||||
import Data.Aeson ((.=))
|
||||
import Data.Either (isLeft)
|
||||
import Data.HashMap.Strict (fromList)
|
||||
|
||||
import qualified NpmDependency as ND
|
||||
import Parser.Common (runWaspParser)
|
||||
import Parser.NpmDependencies (npmDependencies)
|
||||
import Wasp.NpmDependencies
|
||||
|
||||
|
||||
spec_parseNpmDependencies :: Spec
|
||||
spec_parseNpmDependencies = do
|
||||
describe "Parsing npm dependencies" $ do
|
||||
it "When given a valid declaration with valid json, parses it correctly" $ do
|
||||
runWaspParser npmDependencies "dependencies {=json \"foo\": \"test1\", \"bar\": \"test2\" json=}"
|
||||
`shouldBe` Right NpmDependencies
|
||||
{ _dependencies =
|
||||
[ ND.NpmDependency { ND._name = "foo", ND._version = "test1" }
|
||||
, ND.NpmDependency { ND._name = "bar", ND._version = "test2" }
|
||||
]
|
||||
}
|
||||
it "When given invalid json, reports error" $ do
|
||||
isLeft (runWaspParser npmDependencies "dependencies {=json foo: 42 json=}")
|
||||
`shouldBe` True
|
@ -1,22 +1,24 @@
|
||||
module Parser.ParserTest where
|
||||
|
||||
import Data.Either
|
||||
import qualified Path.Posix as PPosix
|
||||
import qualified Path.Posix as PPosix
|
||||
import Test.Tasty.Hspec
|
||||
|
||||
import NpmDependency as ND
|
||||
import Parser
|
||||
import qualified StrongPath as SP
|
||||
import qualified StrongPath as SP
|
||||
import Wasp
|
||||
import qualified Wasp.EntityPSL
|
||||
import qualified Wasp.JsCode
|
||||
import qualified Wasp.JsImport
|
||||
import qualified Wasp.NpmDependencies
|
||||
import qualified Wasp.Page
|
||||
import qualified Wasp.Query
|
||||
import qualified Wasp.Route as R
|
||||
import qualified Wasp.Route as R
|
||||
|
||||
-- TODO(matija): old Entity stuff, to be removed.
|
||||
import qualified Wasp.EntityForm as EF
|
||||
import qualified Wasp.EntityList as EL
|
||||
import qualified Wasp.EntityForm as EF
|
||||
import qualified Wasp.EntityList as EL
|
||||
|
||||
|
||||
spec_parseWasp :: Spec
|
||||
@ -127,6 +129,14 @@ spec_parseWasp =
|
||||
, Wasp.JsImport._from = SP.fromPathRelFileP [PPosix.relfile|some/path|]
|
||||
}
|
||||
}
|
||||
, WaspElementNpmDependencies $ Wasp.NpmDependencies.NpmDependencies
|
||||
{ Wasp.NpmDependencies._dependencies =
|
||||
[ ND.NpmDependency
|
||||
{ ND._name = "lodash"
|
||||
, ND._version = "^4.17.15"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
`setJsImports` [ JsImport (Just "something") [] (SP.fromPathRelFileP [PPosix.relfile|some/file|]) ]
|
||||
)
|
||||
|
@ -69,8 +69,10 @@ entity-list<Task> TaskList {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
query myQuery {
|
||||
fn: import { myJsQuery } from "@ext/some/path"
|
||||
}
|
||||
|
||||
dependencies {=json
|
||||
"lodash": "^4.17.15"
|
||||
json=}
|
||||
|
Loading…
Reference in New Issue
Block a user