mirror of
https://github.com/wasp-lang/wasp.git
synced 2024-09-11 07:16:09 +03:00
Make sure entity
declaration is not used in the Wasp file (#2152)
This commit is contained in:
parent
0eef00d5d9
commit
8f136fb5cd
@ -127,6 +127,7 @@ import Wasp.Analyzer.AnalyzeError
|
||||
)
|
||||
import Wasp.Analyzer.Evaluator (Decl, evaluate, takeDecls)
|
||||
import Wasp.Analyzer.Parser (parseStatements)
|
||||
import Wasp.Analyzer.Parser.Valid (validateAst)
|
||||
import Wasp.Analyzer.Prisma (injectEntitiesFromPrismaSchema)
|
||||
import Wasp.Analyzer.StdTypeDefinitions (stdTypes)
|
||||
import Wasp.Analyzer.TypeChecker (typeCheck)
|
||||
@ -138,6 +139,25 @@ import qualified Wasp.Psl.Ast.Schema as Psl.Schema
|
||||
analyze :: Psl.Schema.Schema -> String -> Either [AnalyzeError] [Decl]
|
||||
analyze prismaSchemaAst =
|
||||
(left (map ParseError) . parseStatements)
|
||||
{--
|
||||
Why introduce AST validation and not just throw a ParseError from the parser?
|
||||
|
||||
We want to support the `entity` declaration in the AST but not in the Wasp source
|
||||
file.
|
||||
|
||||
This was the fastest and cleanest (e.g. not having to hack the type checker) way
|
||||
to allow users to define entities in the Prisma schema file. We are parsing
|
||||
the `schema.prisma` file and injecting the models into the Wasp AST as entity
|
||||
statements.
|
||||
|
||||
We validate the AST to prevent users from defining entities in the Wasp source
|
||||
file since we don't want to allow defining entities in two places.
|
||||
|
||||
Wasp file -(parse)-> AST -(validate)-> AST -(injectEntities)-> AST (...)
|
||||
^ disallow entities here
|
||||
^ inject entities here
|
||||
--}
|
||||
>=> (left ((: []) . ValidationError) . validateAst)
|
||||
>=> injectEntitiesFromPrismaSchema prismaSchemaAst
|
||||
>=> (left ((: []) . TypeError) . typeCheck stdTypes)
|
||||
>=> (left ((: []) . EvaluationError) . evaluate stdTypes)
|
||||
|
@ -16,10 +16,12 @@ data AnalyzeError
|
||||
= ParseError PE.ParseError
|
||||
| TypeError TE.TypeError
|
||||
| EvaluationError EE.EvaluationError
|
||||
| ValidationError (String, Ctx)
|
||||
deriving (Show, Eq)
|
||||
|
||||
getErrorMessageAndCtx :: AnalyzeError -> (String, Ctx)
|
||||
getErrorMessageAndCtx = \case
|
||||
ParseError e -> first (("Parse error:\n" ++) . indent 2) $ PE.getErrorMessageAndCtx e
|
||||
ValidationError (msg, ctx) -> ("Validation error:\n" ++ indent 2 msg, ctx)
|
||||
TypeError e -> first (("Type error:\n" ++) . indent 2) $ TE.getErrorMessageAndCtx e
|
||||
EvaluationError e -> first (("Evaluation error:\n" ++) . indent 2) $ EE.getErrorMessageAndCtx e
|
||||
|
26
waspc/src/Wasp/Analyzer/Parser/Valid.hs
Normal file
26
waspc/src/Wasp/Analyzer/Parser/Valid.hs
Normal file
@ -0,0 +1,26 @@
|
||||
module Wasp.Analyzer.Parser.Valid
|
||||
( validateAst,
|
||||
)
|
||||
where
|
||||
|
||||
import Data.List (find)
|
||||
import qualified Wasp.Analyzer.Parser as P
|
||||
import Wasp.Analyzer.StdTypeDefinitions.Entity (entityDeclTypeName)
|
||||
|
||||
validateAst :: P.AST -> Either (String, P.Ctx) P.AST
|
||||
validateAst = validateNoEntityDeclInWaspFile
|
||||
|
||||
validateNoEntityDeclInWaspFile :: P.AST -> Either (String, P.Ctx) P.AST
|
||||
validateNoEntityDeclInWaspFile ast@(P.AST stmts) = case findEntityStmt stmts of
|
||||
Just (P.WithCtx ctx _) -> Left (entitiesNoLongerSupportedError, ctx)
|
||||
Nothing -> Right ast
|
||||
where
|
||||
findEntityStmt :: [P.WithCtx P.Stmt] -> Maybe (P.WithCtx P.Stmt)
|
||||
findEntityStmt =
|
||||
find
|
||||
( \(P.WithCtx _ (P.Decl declTypeName _ _)) -> declTypeName == entityDeclTypeName
|
||||
)
|
||||
|
||||
entitiesNoLongerSupportedError :: String
|
||||
entitiesNoLongerSupportedError =
|
||||
"Entities can no longer be defined in the .wasp file. You should migrate your entities to the schema.prisma file. Read more: https://wasp-lang.dev/docs/migrate-from-0-13-to-0-14#migrate-to-the-new-schemaprisma-file"
|
@ -1,7 +1,10 @@
|
||||
{-# LANGUAGE TypeApplications #-}
|
||||
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||
|
||||
module Wasp.Analyzer.StdTypeDefinitions.Entity () where
|
||||
module Wasp.Analyzer.StdTypeDefinitions.Entity
|
||||
( entityDeclTypeName,
|
||||
)
|
||||
where
|
||||
|
||||
import Control.Arrow (left)
|
||||
import Wasp.Analyzer.Evaluator.EvaluationError (mkEvaluationError)
|
||||
@ -16,7 +19,7 @@ import qualified Wasp.Psl.Parser.Model
|
||||
instance IsDeclType Entity where
|
||||
declType =
|
||||
DeclType
|
||||
{ dtName = "entity",
|
||||
{ dtName = entityDeclTypeName,
|
||||
dtBodyType = Type.QuoterType "psl",
|
||||
dtEvaluate = \typeDefinitions bindings declName expr ->
|
||||
Decl.makeDecl @Entity declName <$> declEvaluate typeDefinitions bindings expr
|
||||
@ -27,3 +30,6 @@ instance IsDeclType Entity where
|
||||
left (ER.mkEvaluationError ctx . ER.ParseError . ER.EvaluationParseErrorParsec) $
|
||||
makeEntity <$> Wasp.Psl.Parser.Model.parseBody pslString
|
||||
_ -> Left $ mkEvaluationError ctx $ ER.ExpectedType (Type.QuoterType "psl") (TC.AST.exprType expr)
|
||||
|
||||
entityDeclTypeName :: String
|
||||
entityDeclTypeName = "entity"
|
||||
|
@ -27,15 +27,15 @@ data TypeError'
|
||||
-- We use "unify" in the TypeChecker when trying to infer the common type for
|
||||
-- typed expressions that we know should be of the same type (e.g. for
|
||||
-- elements in the list).
|
||||
= UnificationError TypeCoercionError
|
||||
= UnificationError TypeCoercionError
|
||||
-- | Type coercion error that occurs when trying to use the typed expression
|
||||
-- of type T1 where T2 is expected. If T2 is a super type of T1 and T1 can be
|
||||
-- safely coerced to T2, no problem, but if not, we get this error.
|
||||
| CoercionError TypeCoercionError
|
||||
| NoDeclarationType TypeName
|
||||
| UndefinedIdentifier Identifier
|
||||
| QuoterUnknownTag QuoterTag
|
||||
| DictDuplicateField DictFieldName
|
||||
| CoercionError TypeCoercionError
|
||||
| NoDeclarationType TypeName
|
||||
| UndefinedIdentifier Identifier
|
||||
| QuoterUnknownTag QuoterTag
|
||||
| DictDuplicateField DictFieldName
|
||||
deriving (Eq, Show)
|
||||
{- ORMOLU_ENABLE -}
|
||||
|
||||
|
71
waspc/test/Analyzer/ValidTest.hs
Normal file
71
waspc/test/Analyzer/ValidTest.hs
Normal file
@ -0,0 +1,71 @@
|
||||
module Analyzer.ValidTest where
|
||||
|
||||
import Data.Either (fromRight, isRight)
|
||||
import Test.Tasty.Hspec
|
||||
import Wasp.Analyzer.Parser hiding (withCtx)
|
||||
import qualified Wasp.Analyzer.Parser as P
|
||||
import Wasp.Analyzer.Parser.Valid (validateAst)
|
||||
import qualified Wasp.Version as WV
|
||||
|
||||
spec_ValidateAst :: Spec
|
||||
spec_ValidateAst = do
|
||||
it "Returns an error when entities are used" $ do
|
||||
validateAndParseSource (waspSourceLines ++ entityDeclarationLines)
|
||||
`shouldBe` Left
|
||||
( "Entities can no longer be defined in the .wasp file. You should migrate your entities to the schema.prisma file. Read more: https://wasp-lang.dev/docs/migrate-from-0-13-to-0-14#migrate-to-the-new-schemaprisma-file",
|
||||
P.Ctx
|
||||
( P.SourceRegion
|
||||
(P.SourcePosition 34 1)
|
||||
(P.SourcePosition 37 5)
|
||||
)
|
||||
)
|
||||
|
||||
it "Returns AST when everything is correct" $ do
|
||||
isRight (validateAndParseSource waspSourceLines) `shouldBe` True
|
||||
where
|
||||
validateAndParseSource = validateAst . parseSource
|
||||
|
||||
parseSource = fromRight (error "Parsing went wrong") . parseStatements . unlines
|
||||
|
||||
waspSourceLines =
|
||||
[ "app Todo {",
|
||||
" wasp: {",
|
||||
" version: \"^" ++ show WV.waspVersion ++ "\",",
|
||||
" },",
|
||||
" title: \"Todo App\",",
|
||||
" head: [\"foo\", \"bar\"],",
|
||||
" auth: {",
|
||||
" userEntity: User,",
|
||||
" methods: {",
|
||||
" usernameAndPassword: {",
|
||||
" userSignupFields: import { getUserFields } from \"@src/auth/signup.js\",",
|
||||
" }",
|
||||
" },",
|
||||
" onAuthFailedRedirectTo: \"/\",",
|
||||
" },",
|
||||
"}",
|
||||
"",
|
||||
"page HomePage {",
|
||||
" component: import Home from \"@src/pages/Main\"",
|
||||
"}",
|
||||
"",
|
||||
"route HomeRoute { path: \"/\", to: HomePage }",
|
||||
"",
|
||||
"query getUsers {",
|
||||
" fn: import { getAllUsers } from \"@src/foo.js\",",
|
||||
" entities: [User]",
|
||||
"}",
|
||||
"",
|
||||
"action updateUser {",
|
||||
" fn: import { updateUser } from \"@src/foo.js\",",
|
||||
" entities: [User],",
|
||||
" auth: true",
|
||||
"}"
|
||||
]
|
||||
|
||||
entityDeclarationLines =
|
||||
[ "entity User {=psl",
|
||||
" id Int @id @default(autoincrement())",
|
||||
" email String @unique",
|
||||
"psl=}"
|
||||
]
|
@ -201,6 +201,7 @@ library
|
||||
Wasp.Analyzer.Parser.SourceSpan
|
||||
Wasp.Analyzer.Parser.Token
|
||||
Wasp.Analyzer.Parser.TokenSet
|
||||
Wasp.Analyzer.Parser.Valid
|
||||
Wasp.Analyzer.StdTypeDefinitions
|
||||
Wasp.Analyzer.StdTypeDefinitions.App.Dependency
|
||||
Wasp.Analyzer.StdTypeDefinitions.Entity
|
||||
@ -612,6 +613,7 @@ test-suite waspc-test
|
||||
Analyzer.TestUtil
|
||||
Analyzer.TypeChecker.InternalTest
|
||||
Analyzer.TypeCheckerTest
|
||||
Analyzer.ValidTest
|
||||
AnalyzerTest
|
||||
AppSpec.ValidTest
|
||||
AppSpec.EntityTest
|
||||
|
@ -108,6 +108,7 @@ waspErrorAsPrettyEditorMessage = Text.pack . fst . W.getErrorMessageAndCtx
|
||||
|
||||
waspErrorSource :: W.AnalyzeError -> Text
|
||||
waspErrorSource (W.ParseError _) = "parse"
|
||||
waspErrorSource (W.ValidationError _) = "validate"
|
||||
waspErrorSource (W.TypeError _) = "typecheck"
|
||||
waspErrorSource (W.EvaluationError _) = "evaluate"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user