diff --git a/waspc/src/Wasp/Analyzer.hs b/waspc/src/Wasp/Analyzer.hs index 3f86d3407c..02530caf48 100644 --- a/waspc/src/Wasp/Analyzer.hs +++ b/waspc/src/Wasp/Analyzer.hs @@ -111,6 +111,7 @@ module Wasp.Analyzer -- * API analyze, + getEntityDecls, takeDecls, AnalyzeError (..), getErrorMessageAndCtx, @@ -127,8 +128,9 @@ import Wasp.Analyzer.AnalyzeError ) import Wasp.Analyzer.Evaluator (Decl, evaluate, takeDecls) import Wasp.Analyzer.Parser (parseStatements) +import qualified Wasp.Analyzer.Parser as Parser import Wasp.Analyzer.Parser.Valid (validateAst) -import Wasp.Analyzer.Prisma (injectEntitiesFromPrismaSchema) +import Wasp.Analyzer.Prisma (injectEntitiesFromPrismaSchema, parseEntityStatements) import Wasp.Analyzer.StdTypeDefinitions (stdTypes) import Wasp.Analyzer.TypeChecker (typeCheck) import qualified Wasp.Psl.Ast.Schema as Psl.Schema @@ -157,7 +159,18 @@ analyze prismaSchemaAst = ^ disallow entities here ^ inject entities here --} - >=> (left ((: []) . ValidationError) . validateAst) + >=> wrapAnalyzerError ValidationError . validateAst >=> injectEntitiesFromPrismaSchema prismaSchemaAst - >=> (left ((: []) . TypeError) . typeCheck stdTypes) - >=> (left ((: []) . EvaluationError) . evaluate stdTypes) + >=> (wrapAnalyzerError TypeError . typeCheck stdTypes) + >=> (wrapAnalyzerError EvaluationError . evaluate stdTypes) + +getEntityDecls :: Psl.Schema.Schema -> Either [AnalyzeError] [Decl] +getEntityDecls schema = + wrapAnalyzerError TypeError (typeCheck stdTypes ast) + >>= (wrapAnalyzerError EvaluationError . evaluate stdTypes) + where + entityStatements = parseEntityStatements schema + ast = Parser.AST entityStatements + +wrapAnalyzerError :: (e -> AnalyzeError) -> Either e a -> Either [AnalyzeError] a +wrapAnalyzerError makeError = left ((: []) . makeError) diff --git a/waspc/src/Wasp/Analyzer/Prisma.hs b/waspc/src/Wasp/Analyzer/Prisma.hs index ba070ebf49..161222fbec 100644 --- a/waspc/src/Wasp/Analyzer/Prisma.hs +++ b/waspc/src/Wasp/Analyzer/Prisma.hs @@ -1,5 +1,6 @@ module Wasp.Analyzer.Prisma ( injectEntitiesFromPrismaSchema, + parseEntityStatements, ) where @@ -11,9 +12,12 @@ import qualified Wasp.Psl.Generator.Model as Psl.Model.Generator injectEntitiesFromPrismaSchema :: Psl.Schema.Schema -> Parser.AST -> Either a Parser.AST injectEntitiesFromPrismaSchema schema ast = Right $ ast {Parser.astStmts = stmts ++ entityStmts} where - entityStmts = makeEntityStmt <$> generatePrismaModelSources schema + entityStmts = parseEntityStatements schema stmts = Parser.astStmts ast +parseEntityStatements :: Psl.Schema.Schema -> [WithCtx Parser.Stmt] +parseEntityStatements schema = makeEntityStmt <$> generatePrismaModelSources schema + type ModelName = String type ModelBody = String diff --git a/waspc/src/Wasp/AppSpec/ExtImport.hs b/waspc/src/Wasp/AppSpec/ExtImport.hs index 5de24f10da..907eb5dd42 100644 --- a/waspc/src/Wasp/AppSpec/ExtImport.hs +++ b/waspc/src/Wasp/AppSpec/ExtImport.hs @@ -12,8 +12,10 @@ where import Data.Aeson (FromJSON (parseJSON), withObject, (.:)) import Data.Aeson.Types (ToJSON) import Data.Data (Data) +import Data.List (stripPrefix) import GHC.Generics (Generic) import StrongPath (File', Path, Posix, Rel, parseRelFileP) +import qualified StrongPath as SP import Wasp.AppSpec.ExternalFiles (SourceExternalCodeDir) data ExtImport = ExtImport @@ -30,7 +32,9 @@ instance FromJSON ExtImport where nameStr <- o .: "name" pathStr <- o .: "path" extImportName <- parseExtImportName kindStr nameStr - extImportPath <- parseExtImportPath pathStr + extImportPath <- case parseExtImportPath pathStr of + Right path' -> pure path' + Left err -> fail err return $ ExtImport extImportName extImportPath where parseExtImportName kindStr nameStr = case kindStr of @@ -38,10 +42,6 @@ instance FromJSON ExtImport where "named" -> pure $ ExtImportField nameStr _ -> fail $ "Failed to parse import kind: " <> kindStr - parseExtImportPath pathStr = case parseRelFileP pathStr of - Just path' -> pure path' - Nothing -> fail $ "Failed to parse relative posix path to file: " <> pathStr - type ExtImportPath = Path Posix (Rel SourceExternalCodeDir) File' type Identifier = String @@ -57,3 +57,23 @@ importIdentifier :: ExtImport -> Identifier importIdentifier (ExtImport importName _) = case importName of ExtImportModule n -> n ExtImportField n -> n + +-- TODO: Remove duplication +parseExtImportPath :: String -> Either String ExtImportPath +parseExtImportPath extImportPath = case stripImportPrefix extImportPath of + Just relFileFP -> case SP.parseRelFileP relFileFP of + Left err -> Left $ "Failed to parse relative posix path to file: " ++ show err + Right path' -> Right path' + Nothing -> Left $ "Path in external import must start with \"" ++ extSrcPrefix ++ "\"!" + where + stripImportPrefix importPath = stripPrefix extSrcPrefix importPath + -- Filip: We no longer want separation between client and server code + -- todo (filip): Do we still want to know which is which. We might (because of the reloading). + -- For now, as we'd like (expect): + -- - Nodemon watches all files in the user's source folder (client files + -- included), but tsc only compiles the server files (I think because it + -- knows that the others aren't used). I am not yet sure how it knows this. + -- - Vite also only triggers on client files. I am not sure how it knows + -- about the difference either. + -- todo (filip): investigate + extSrcPrefix = "@src/" diff --git a/waspc/src/Wasp/Project/Analyze.hs b/waspc/src/Wasp/Project/Analyze.hs index b4fecc1e15..3a6f3f53ae 100644 --- a/waspc/src/Wasp/Project/Analyze.hs +++ b/waspc/src/Wasp/Project/Analyze.hs @@ -11,7 +11,7 @@ import Control.Applicative ((<|>)) import Control.Arrow (ArrowChoice (left)) import Control.Concurrent (newChan) import Control.Concurrent.Async (concurrently) -import Control.Monad.Except (ExceptT (..), runExceptT) +import Control.Monad.Except (ExceptT (..), liftEither, runExceptT) import qualified Data.Aeson as Aeson import Data.Conduit.Process.Typed (ExitCode (..)) import Data.List (find, isSuffixOf) @@ -105,7 +105,7 @@ analyzeWaspTsFile waspProjectDir prismaSchemaAst waspFilePath = runExceptT $ do -- because we also need that knowledge when generating a TS SDK project. compiledWaspJsFile <- ExceptT $ compileWaspTsFile waspProjectDir [relfile|tsconfig.node.json|] waspFilePath declsJsonFile <- ExceptT $ executeMainWaspJsFile waspProjectDir prismaSchemaAst compiledWaspJsFile - ExceptT $ readDeclsFromJsonFile declsJsonFile + ExceptT $ readDecls prismaSchemaAst declsJsonFile compileWaspTsFile :: Path' Abs (Dir WaspProjectDir) -> @@ -174,12 +174,22 @@ executeMainWaspJsFile waspProjectDir prismaSchemaAst absCompiledMainWaspJsFile = absDeclsOutputFile = waspProjectDir dotWaspDirInWaspProjectDir [relfile|decls.json|] allowedEntityNames = Psl.Schema.getModelNames prismaSchemaAst -readDeclsFromJsonFile :: Path' Abs (File DeclsJsonFile) -> IO (Either [CompileError] [AS.Decl]) -readDeclsFromJsonFile declsJsonFile = do - declsBytestring <- IOUtil.readFileBytes declsJsonFile - case Aeson.eitherDecode declsBytestring of - Right value -> return $ Right value - Left err -> return $ Left ["Error while parsing the declarations from JSON: " ++ err] +readDecls :: Psl.Schema.Schema -> Path' Abs (File DeclsJsonFile) -> IO (Either [CompileError] [AS.Decl]) +readDecls prismaSchemaAst declsJsonFile = runExceptT $ do + entityDecls <- liftEither entityDeclsOrErrors + remainingDecls <- ExceptT declsFromJsonOrError + return $ entityDecls ++ remainingDecls + where + entityDeclsOrErrors = + left (map fst) $ + left (map getErrorMessageAndCtx) $ + Analyzer.getEntityDecls prismaSchemaAst + + declsFromJsonOrError = do + declsBytestring <- IOUtil.readFileBytes declsJsonFile + return $ case Aeson.eitherDecode declsBytestring of + Left err -> Left ["Error while parsing the declarations from JSON: " ++ err] + Right value -> Right value analyzeWaspLangFile :: Psl.Schema.Schema -> Path' Abs (File WaspLangFile) -> IO (Either [CompileError] [AS.Decl]) analyzeWaspLangFile prismaSchemaAst waspFilePath = do diff --git a/waspc/src/Wasp/Project/Common.hs b/waspc/src/Wasp/Project/Common.hs index b182c76fbb..670a91ecc6 100644 --- a/waspc/src/Wasp/Project/Common.hs +++ b/waspc/src/Wasp/Project/Common.hs @@ -76,8 +76,9 @@ dotWaspInfoFileInGeneratedCodeDir = [relfile|.waspinfo|] packageJsonInWaspProjectDir :: Path' (Rel WaspProjectDir) (File PackageJsonFile) packageJsonInWaspProjectDir = [relfile|package.json|] +-- TODO: Do this properly tsConfigInWaspProjectDir :: Path' (Rel WaspProjectDir) (File TsConfigFile) -tsConfigInWaspProjectDir = [relfile|tsconfig.json|] +tsConfigInWaspProjectDir = [relfile|tsconfig.app.json|] packageLockJsonInWaspProjectDir :: Path' (Rel WaspProjectDir) File' packageLockJsonInWaspProjectDir = [relfile|package-lock.json|]