From 6d03463a5d66d16afe61312957495512601a418d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Sodi=C4=87?= Date: Tue, 10 Dec 2024 09:46:16 +0100 Subject: [PATCH 1/7] Move Wasp file logic into a separate module --- .../StarterTemplates/Templating.hs | 3 +- .../Wasp/AI/GenerateNewProject/WaspFile.hs | 2 +- .../Evaluation/TypedExpr/Combinators.hs | 1 - waspc/src/Wasp/Project/Analyze.hs | 161 +-------------- waspc/src/Wasp/Project/Common.hs | 1 - waspc/src/Wasp/Project/WaspFile.hs | 190 ++++++++++++++++++ waspc/src/Wasp/Util.hs | 4 + waspc/waspc.cabal | 3 +- 8 files changed, 200 insertions(+), 165 deletions(-) create mode 100644 waspc/src/Wasp/Project/WaspFile.hs diff --git a/waspc/cli/src/Wasp/Cli/Command/CreateNewProject/StarterTemplates/Templating.hs b/waspc/cli/src/Wasp/Cli/Command/CreateNewProject/StarterTemplates/Templating.hs index 57ea86b0f0..968aacd1f9 100644 --- a/waspc/cli/src/Wasp/Cli/Command/CreateNewProject/StarterTemplates/Templating.hs +++ b/waspc/cli/src/Wasp/Cli/Command/CreateNewProject/StarterTemplates/Templating.hs @@ -10,9 +10,10 @@ import StrongPath (Abs, Dir, File, Path') import Wasp.Cli.Command.CreateNewProject.Common (defaultWaspVersionBounds) import Wasp.Cli.Command.CreateNewProject.ProjectDescription (NewProjectAppName, NewProjectName) import Wasp.NodePackageFFI (InstallablePackage (WaspConfigPackage), getPackageInstallationPath) -import Wasp.Project.Analyze (WaspFilePath (..), findWaspFile) +import Wasp.Project.Analyze (WaspFilePath (..)) import Wasp.Project.Common (WaspProjectDir) import Wasp.Project.ExternalConfig.PackageJson (findPackageJsonFile) +import Wasp.Project.WaspFile (findWaspFile) import qualified Wasp.Util.IO as IOUtil replaceTemplatePlaceholdersInTemplateFiles :: NewProjectAppName -> NewProjectName -> Path' Abs (Dir WaspProjectDir) -> IO () diff --git a/waspc/src/Wasp/AI/GenerateNewProject/WaspFile.hs b/waspc/src/Wasp/AI/GenerateNewProject/WaspFile.hs index 3d0ef8f76d..799a8a2b5d 100644 --- a/waspc/src/Wasp/AI/GenerateNewProject/WaspFile.hs +++ b/waspc/src/Wasp/AI/GenerateNewProject/WaspFile.hs @@ -24,7 +24,7 @@ import qualified Wasp.AI.GenerateNewProject.Common.Prompts as Prompts import Wasp.AI.GenerateNewProject.Plan (Plan) import Wasp.AI.OpenAI.ChatGPT (ChatMessage (..), ChatRole (..)) import Wasp.Analyzer.Parser.Ctx (Ctx (..)) -import Wasp.Project.Analyze (analyzeWaspFileContent) +import Wasp.Project.WaspFile (analyzeWaspFileContent) import qualified Wasp.Psl.Ast.Schema as Psl.Schema import qualified Wasp.Util.Aeson as Utils.Aeson diff --git a/waspc/src/Wasp/Analyzer/Evaluator/Evaluation/TypedExpr/Combinators.hs b/waspc/src/Wasp/Analyzer/Evaluator/Evaluation/TypedExpr/Combinators.hs index 410b8f19b3..0b2bef955b 100644 --- a/waspc/src/Wasp/Analyzer/Evaluator/Evaluation/TypedExpr/Combinators.hs +++ b/waspc/src/Wasp/Analyzer/Evaluator/Evaluation/TypedExpr/Combinators.hs @@ -154,7 +154,6 @@ tuple4 eval1 eval2 eval3 eval4 = evaluation $ \(typeDefs, bindings) -> withCtx $ extImport :: TypedExprEvaluation AppSpec.ExtImport.ExtImport extImport = evaluation' . withCtx $ \ctx -> \case TypedAST.ExtImport name extImportPath -> - -- NOTE(martin): This parsing here could instead be done in Parser. -- NOTE(martin): This parsing here could instead be done in Parser. -- I don't have a very good reason for doing it here instead of Parser, except -- for being somewhat simpler to implement. diff --git a/waspc/src/Wasp/Project/Analyze.hs b/waspc/src/Wasp/Project/Analyze.hs index e34d00f7ca..235c29df26 100644 --- a/waspc/src/Wasp/Project/Analyze.hs +++ b/waspc/src/Wasp/Project/Analyze.hs @@ -1,57 +1,30 @@ module Wasp.Project.Analyze ( analyzeWaspProject, - analyzeWaspFileContent, - findWaspFile, analyzePrismaSchema, WaspFilePath (..), ) where import Control.Arrow (ArrowChoice (left)) -import Control.Concurrent (newChan) -import Control.Concurrent.Async (concurrently) -import Control.Monad.Except (ExceptT (..), liftEither, runExceptT) -import qualified Data.Aeson as Aeson -import Data.List (find, isSuffixOf) -import Data.Maybe (fromMaybe) import StrongPath ( Abs, Dir, - File, File', Path', - Rel, - basename, - castFile, fromAbsDir, - fromAbsFile, - fromRelFile, - relfile, - (), ) -import System.Exit (ExitCode (..)) -import qualified Wasp.Analyzer as Analyzer -import Wasp.Analyzer.AnalyzeError (getErrorMessageAndCtx) -import Wasp.Analyzer.Parser.Ctx (Ctx) import qualified Wasp.AppSpec as AS import Wasp.AppSpec.Core.Decl.JSON () import qualified Wasp.AppSpec.Valid as ASV import Wasp.CompileOptions (CompileOptions) import qualified Wasp.CompileOptions as CompileOptions import qualified Wasp.ConfigFile as CF -import Wasp.Error (showCompilerErrorForTerminal) import qualified Wasp.Generator.ConfigFile as G.CF -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.IO (readJobMessagesAndPrintThemPrefixed) -import Wasp.Generator.Job.Process (runNodeCommandAsJob) import Wasp.Project.Common ( CompileError, CompileWarning, WaspFilePath (..), - WaspLangFile, WaspProjectDir, - WaspTsFile, - dotWaspDirInWaspProjectDir, findFileInWaspProjectDir, getSrcTsConfigInWaspProjectDir, prismaSchemaFileInWaspProjectDir, @@ -63,13 +36,12 @@ import Wasp.Project.Env (readDotEnvClient, readDotEnvServer) import qualified Wasp.Project.ExternalConfig as EC import qualified Wasp.Project.ExternalFiles as ExternalFiles import Wasp.Project.Vite (findCustomViteConfigPath) +import Wasp.Project.WaspFile (analyzeWaspFile, findWaspFile) import qualified Wasp.Psl.Ast.Schema as Psl.Schema import qualified Wasp.Psl.Parser.Schema as Psl.Parser import Wasp.Psl.Valid (getValidDbSystemFromPrismaSchema) import qualified Wasp.Psl.Valid as PslV -import Wasp.Util.Aeson (encodeToString) import qualified Wasp.Util.IO as IOUtil -import Wasp.Util.StrongPath (replaceRelExtension) import Wasp.Valid (ValidationError) import qualified Wasp.Valid as Valid @@ -79,7 +51,6 @@ analyzeWaspProject :: IO (Either [CompileError] AS.AppSpec, [CompileWarning]) analyzeWaspProject waspDir options = do waspFilePathOrError <- left (: []) <$> findWaspFile waspDir - case waspFilePathOrError of Left err -> return (Left err, []) Right waspFilePath -> @@ -94,118 +65,6 @@ analyzeWaspProject waspDir options = do Left errors -> return (Left errors, []) Right externalConfigs -> constructAppSpec waspDir options externalConfigs prismaSchemaAst declarations -data CompiledWaspJsFile - -data AppSpecDeclsJsonFile - -analyzeWaspFile :: Path' Abs (Dir WaspProjectDir) -> Psl.Schema.Schema -> WaspFilePath -> IO (Either [CompileError] [AS.Decl]) -analyzeWaspFile waspDir prismaSchemaAst = \case - WaspLang waspFilePath -> analyzeWaspLangFile prismaSchemaAst waspFilePath - WaspTs waspFilePath -> analyzeWaspTsFile waspDir prismaSchemaAst waspFilePath - -analyzeWaspTsFile :: Path' Abs (Dir WaspProjectDir) -> Psl.Schema.Schema -> Path' Abs (File WaspTsFile) -> IO (Either [CompileError] [AS.Decl]) -analyzeWaspTsFile waspProjectDir prismaSchemaAst waspFilePath = runExceptT $ do - -- TODO: I'm not yet sure where tsconfig.node.json location should come from - -- because we also need that knowledge when generating a TS SDK project. - compiledWaspJsFile <- ExceptT $ compileWaspTsFile waspProjectDir [relfile|tsconfig.wasp.json|] waspFilePath - declsJsonFile <- ExceptT $ executeMainWaspJsFileAndGetDeclsFile waspProjectDir prismaSchemaAst compiledWaspJsFile - ExceptT $ readDecls prismaSchemaAst declsJsonFile - -compileWaspTsFile :: - Path' Abs (Dir WaspProjectDir) -> - Path' (Rel WaspProjectDir) File' -> - Path' Abs (File WaspTsFile) -> - IO (Either [CompileError] (Path' Abs (File CompiledWaspJsFile))) -compileWaspTsFile waspProjectDir tsconfigNodeFileInWaspProjectDir waspFilePath = do - chan <- newChan - (_, tscExitCode) <- - concurrently - (readJobMessagesAndPrintThemPrefixed chan) - ( runNodeCommandAsJob - waspProjectDir - "npx" - [ "tsc", - "-p", - fromAbsFile (waspProjectDir tsconfigNodeFileInWaspProjectDir), - "--noEmit", - "false", - "--outDir", - fromAbsDir outDir - ] - J.Wasp - chan - ) - return $ case tscExitCode of - ExitFailure _status -> Left ["Got TypeScript compiler errors for " ++ fromAbsFile waspFilePath ++ "."] - ExitSuccess -> Right absCompiledWaspJsFile - where - outDir = waspProjectDir dotWaspDirInWaspProjectDir - absCompiledWaspJsFile = outDir compiledWaspJsFileInDotWaspDir - compiledWaspJsFileInDotWaspDir = - castFile $ - fromMaybe - (error $ "Couldn't calculate the compiled JS file path for " ++ fromAbsFile waspFilePath ++ ".") - (replaceRelExtension (basename waspFilePath) ".js") - -executeMainWaspJsFileAndGetDeclsFile :: - Path' Abs (Dir WaspProjectDir) -> - Psl.Schema.Schema -> - Path' Abs (File CompiledWaspJsFile) -> - IO (Either [CompileError] (Path' Abs (File AppSpecDeclsJsonFile))) -executeMainWaspJsFileAndGetDeclsFile waspProjectDir prismaSchemaAst absCompiledMainWaspJsFile = do - chan <- newChan - (_, runExitCode) <- do - concurrently - (readJobMessagesAndPrintThemPrefixed chan) - ( runNodeCommandAsJob - waspProjectDir - "npx" - -- TODO: Figure out how to keep running instructions in a single - -- place (e.g., this is string the same as the package name, but it's - -- repeated in two places). - -- Before this, I had the entrypoint file hardcoded, which was bad - -- too: waspProjectDir [relfile|node_modules/wasp-config/dist/run.js|] - [ "wasp-config", - fromAbsFile absCompiledMainWaspJsFile, - fromAbsFile absDeclsOutputFile, - encodeToString allowedEntityNames - ] - J.Wasp - chan - ) - case runExitCode of - ExitFailure _status -> return $ Left ["Error while running the compiled *.wasp.ts file."] - ExitSuccess -> return $ Right absDeclsOutputFile - where - absDeclsOutputFile = waspProjectDir dotWaspDirInWaspProjectDir [relfile|decls.json|] - allowedEntityNames = Psl.Schema.getModelNames prismaSchemaAst - -readDecls :: Psl.Schema.Schema -> Path' Abs (File AppSpecDeclsJsonFile) -> IO (Either [CompileError] [AS.Decl]) -readDecls prismaSchemaAst declsJsonFile = runExceptT $ do - entityDecls <- liftEither entityDeclsOrErrors - remainingDecls <- ExceptT $ left (: []) <$> declsFromJsonOrError - return $ entityDecls ++ remainingDecls - where - entityDeclsOrErrors = - left (map fst) $ - left (map getErrorMessageAndCtx) $ - Analyzer.getEntityDecls prismaSchemaAst - - declsFromJsonOrError = do - declsBytestring <- IOUtil.readFileBytes declsJsonFile - return $ - left ("Error while reading the declarations from JSON: " ++) $ - Aeson.eitherDecode declsBytestring - -analyzeWaspLangFile :: Psl.Schema.Schema -> Path' Abs (File WaspLangFile) -> IO (Either [CompileError] [AS.Decl]) -analyzeWaspLangFile prismaSchemaAst waspFilePath = do - waspFileContent <- IOUtil.readFile waspFilePath - left (map $ showCompilerErrorForTerminal (waspFilePath, waspFileContent)) - <$> analyzeWaspFileContent prismaSchemaAst waspFileContent - -analyzeWaspFileContent :: Psl.Schema.Schema -> String -> IO (Either [(String, Ctx)] [AS.Decl]) -analyzeWaspFileContent prismaSchemaAst = return . left (map getErrorMessageAndCtx) . Analyzer.analyze prismaSchemaAst - constructAppSpec :: Path' Abs (Dir WaspProjectDir) -> CompileOptions -> @@ -248,24 +107,6 @@ constructAppSpec waspDir options externalConfigs parsedPrismaSchema decls = do return $ runValidation ASV.validateAppSpec appSpec -findWaspFile :: Path' Abs (Dir WaspProjectDir) -> IO (Either String WaspFilePath) -findWaspFile waspDir = do - files <- fst <$> IOUtil.listDirectory waspDir - return $ case (findWaspTsFile files, findWaspLangFile files) of - (Just _, Just _) -> Left bothFilesFoundMessage - (Nothing, Nothing) -> Left fileNotFoundMessage - (Just waspTsFile, Nothing) -> Right waspTsFile - (Nothing, Just waspLangFile) -> Right waspLangFile - where - findWaspTsFile files = WaspTs <$> findFileThatEndsWith ".wasp.ts" files - findWaspLangFile files = WaspLang <$> findFileThatEndsWith ".wasp" files - findFileThatEndsWith suffix files = castFile . (waspDir ) <$> find ((suffix `isSuffixOf`) . fromRelFile) files - - fileNotFoundMessage = "Couldn't find the *.wasp or a *.wasp.ts file in the " ++ fromAbsDir waspDir ++ " directory" - bothFilesFoundMessage = - "Found both *.wasp and *.wasp.ts files in the project directory. " - ++ "You must choose how you want to define your app (using Wasp or TypeScript) and only keep one of them." - analyzePrismaSchema :: Path' Abs (Dir WaspProjectDir) -> IO (Either [CompileError] Psl.Schema.Schema, [CompileWarning]) analyzePrismaSchema waspProjectDir = do findPrismaSchemaFile waspProjectDir >>= \case diff --git a/waspc/src/Wasp/Project/Common.hs b/waspc/src/Wasp/Project/Common.hs index 9fb166e924..662d261636 100644 --- a/waspc/src/Wasp/Project/Common.hs +++ b/waspc/src/Wasp/Project/Common.hs @@ -88,7 +88,6 @@ dotWaspInfoFileInGeneratedCodeDir = [relfile|.waspinfo|] packageJsonInWaspProjectDir :: Path' (Rel WaspProjectDir) (File PackageJsonFile) packageJsonInWaspProjectDir = [relfile|package.json|] --- TODO: The entire tsconfig story is very fragile getSrcTsConfigInWaspProjectDir :: WaspFilePath -> Path' (Rel WaspProjectDir) (File SrcTsConfigFile) getSrcTsConfigInWaspProjectDir = \case WaspTs _ -> srcTsConfigInWaspTsProject diff --git a/waspc/src/Wasp/Project/WaspFile.hs b/waspc/src/Wasp/Project/WaspFile.hs new file mode 100644 index 0000000000..b721031e57 --- /dev/null +++ b/waspc/src/Wasp/Project/WaspFile.hs @@ -0,0 +1,190 @@ +module Wasp.Project.WaspFile + ( findWaspFile, + analyzeWaspFile, + analyzeWaspFileContent, + ) +where + +import Control.Arrow (left) +import Control.Concurrent (newChan) +import Control.Concurrent.Async (concurrently) +import Control.Monad.Except (ExceptT (ExceptT), liftEither, runExceptT) +import qualified Data.Aeson as Aeson +import Data.List (find, isSuffixOf) +import StrongPath + ( Abs, + Dir, + File, + File', + Path', + Rel, + basename, + castFile, + fromAbsDir, + fromAbsFile, + fromRelFile, + relfile, + (), + ) +import System.Exit (ExitCode (..)) +import qualified Wasp.Analyzer as Analyzer +import Wasp.Analyzer.Parser.Ctx (Ctx) +import qualified Wasp.AppSpec as AS +import Wasp.AppSpec.Core.Decl.JSON () +import Wasp.Error (showCompilerErrorForTerminal) +import qualified Wasp.Generator.Job as J +import Wasp.Generator.Job.IO (readJobMessagesAndPrintThemPrefixed) +import Wasp.Generator.Job.Process (runNodeCommandAsJob) +import Wasp.Project.Common + ( CompileError, + WaspFilePath (..), + WaspLangFile, + WaspProjectDir, + WaspTsFile, + dotWaspDirInWaspProjectDir, + ) +import qualified Wasp.Psl.Ast.Schema as Psl.Schema +import Wasp.Util (orElse) +import Wasp.Util.Aeson (encodeToString) +import qualified Wasp.Util.IO as IOUtil +import Wasp.Util.StrongPath (replaceRelExtension) + +data CompiledWaspJsFile + +data AppSpecDeclsJsonFile + +findWaspFile :: Path' Abs (Dir WaspProjectDir) -> IO (Either String WaspFilePath) +findWaspFile waspDir = do + files <- fst <$> IOUtil.listDirectory waspDir + return $ case (findWaspTsFile files, findWaspLangFile files) of + (Just _, Just _) -> Left bothFilesFoundMessage + (Nothing, Nothing) -> Left fileNotFoundMessage + (Just waspTsFile, Nothing) -> Right waspTsFile + (Nothing, Just waspLangFile) -> Right waspLangFile + where + findWaspTsFile files = WaspTs <$> findFileThatEndsWith ".wasp.ts" files + findWaspLangFile files = WaspLang <$> findFileThatEndsWith ".wasp" files + findFileThatEndsWith suffix files = castFile . (waspDir ) <$> find ((suffix `isSuffixOf`) . fromRelFile) files + + fileNotFoundMessage = "Couldn't find the *.wasp or a *.wasp.ts file in the " ++ fromAbsDir waspDir ++ " directory" + bothFilesFoundMessage = + "Found both *.wasp and *.wasp.ts files in the project directory. " + ++ "You must choose how you want to define your app (using Wasp or TypeScript) and only keep one of them." + +analyzeWaspFile :: + Path' Abs (Dir WaspProjectDir) -> + Psl.Schema.Schema -> + WaspFilePath -> + IO (Either [CompileError] [AS.Decl]) +analyzeWaspFile waspDir prismaSchemaAst = \case + WaspLang waspFilePath -> analyzeWaspLangFile prismaSchemaAst waspFilePath + WaspTs waspFilePath -> analyzeWaspTsFile waspDir prismaSchemaAst waspFilePath + +analyzeWaspTsFile :: + Path' Abs (Dir WaspProjectDir) -> + Psl.Schema.Schema -> + Path' Abs (File WaspTsFile) -> + IO (Either [CompileError] [AS.Decl]) +analyzeWaspTsFile waspProjectDir prismaSchemaAst waspFilePath = runExceptT $ do + -- TODO: I'm not yet sure where tsconfig.node.json location should come from + -- because we also need that knowledge when generating a TS SDK project. + compiledWaspJsFile <- ExceptT $ compileWaspTsFile waspProjectDir [relfile|tsconfig.wasp.json|] waspFilePath + declsJsonFile <- ExceptT $ executeMainWaspJsFileAndGetDeclsFile waspProjectDir prismaSchemaAst compiledWaspJsFile + ExceptT $ readDecls prismaSchemaAst declsJsonFile + +analyzeWaspLangFile :: Psl.Schema.Schema -> Path' Abs (File WaspLangFile) -> IO (Either [CompileError] [AS.Decl]) +analyzeWaspLangFile prismaSchemaAst waspFilePath = do + waspFileContent <- IOUtil.readFile waspFilePath + left (map $ showCompilerErrorForTerminal (waspFilePath, waspFileContent)) + <$> analyzeWaspFileContent prismaSchemaAst waspFileContent + +analyzeWaspFileContent :: Psl.Schema.Schema -> String -> IO (Either [(String, Ctx)] [AS.Decl]) +analyzeWaspFileContent prismaSchemaAst = + return + . left (map Analyzer.getErrorMessageAndCtx) + . Analyzer.analyze prismaSchemaAst + +compileWaspTsFile :: + Path' Abs (Dir WaspProjectDir) -> + Path' (Rel WaspProjectDir) File' -> + Path' Abs (File WaspTsFile) -> + IO (Either [CompileError] (Path' Abs (File CompiledWaspJsFile))) +compileWaspTsFile waspProjectDir tsconfigNodeFileInWaspProjectDir waspFilePath = do + chan <- newChan + (_, tscExitCode) <- + concurrently + (readJobMessagesAndPrintThemPrefixed chan) + ( runNodeCommandAsJob + waspProjectDir + "npx" + [ "tsc", + "-p", + fromAbsFile (waspProjectDir tsconfigNodeFileInWaspProjectDir), + "--noEmit", + "false", + "--outDir", + fromAbsDir outDir + ] + J.Wasp + chan + ) + return $ case tscExitCode of + ExitFailure _status -> Left ["Got TypeScript compiler errors for " ++ fromAbsFile waspFilePath ++ "."] + ExitSuccess -> Right absCompiledWaspJsFile + where + outDir = waspProjectDir dotWaspDirInWaspProjectDir + absCompiledWaspJsFile = outDir compiledWaspJsFileInDotWaspDir + compiledWaspJsFileInDotWaspDir = + castFile $ + replaceRelExtension (basename waspFilePath) ".js" + `orElse` error ("Couldn't calculate the compiled JS file path for " ++ fromAbsFile waspFilePath ++ ".") + +executeMainWaspJsFileAndGetDeclsFile :: + Path' Abs (Dir WaspProjectDir) -> + Psl.Schema.Schema -> + Path' Abs (File CompiledWaspJsFile) -> + IO (Either [CompileError] (Path' Abs (File AppSpecDeclsJsonFile))) +executeMainWaspJsFileAndGetDeclsFile waspProjectDir prismaSchemaAst absCompiledMainWaspJsFile = do + chan <- newChan + (_, runExitCode) <- do + concurrently + (readJobMessagesAndPrintThemPrefixed chan) + ( runNodeCommandAsJob + waspProjectDir + "npx" + -- TODO: Figure out how to keep running instructions in a single + -- place (e.g., this is string the same as the package name, but it's + -- repeated in two places). + -- Before this, I had the entrypoint file hardcoded, which was bad + -- too: waspProjectDir [relfile|node_modules/wasp-config/dist/run.js|] + [ "wasp-config", + fromAbsFile absCompiledMainWaspJsFile, + fromAbsFile absDeclsOutputFile, + encodeToString allowedEntityNames + ] + J.Wasp + chan + ) + case runExitCode of + ExitFailure _status -> return $ Left ["Error while running the compiled *.wasp.ts file."] + ExitSuccess -> return $ Right absDeclsOutputFile + where + absDeclsOutputFile = waspProjectDir dotWaspDirInWaspProjectDir [relfile|decls.json|] + allowedEntityNames = Psl.Schema.getModelNames prismaSchemaAst + +readDecls :: Psl.Schema.Schema -> Path' Abs (File AppSpecDeclsJsonFile) -> IO (Either [CompileError] [AS.Decl]) +readDecls prismaSchemaAst declsJsonFile = runExceptT $ do + entityDecls <- liftEither entityDeclsOrErrors + remainingDecls <- ExceptT $ left (: []) <$> declsFromJsonOrError + return $ entityDecls ++ remainingDecls + where + entityDeclsOrErrors = + left (map fst) $ + left (map Analyzer.getErrorMessageAndCtx) $ + Analyzer.getEntityDecls prismaSchemaAst + + declsFromJsonOrError = do + declsBytestring <- IOUtil.readFileBytes declsJsonFile + return $ + left ("Error while reading the declarations from JSON: " ++) $ + Aeson.eitherDecode declsBytestring diff --git a/waspc/src/Wasp/Util.hs b/waspc/src/Wasp/Util.hs index 9cedb4e0d7..8be4da55f1 100644 --- a/waspc/src/Wasp/Util.hs +++ b/waspc/src/Wasp/Util.hs @@ -34,6 +34,7 @@ module Wasp.Util kebabToCamelCase, maybeToEither, eitherToMaybe, + orElse, whenM, naiveTrimJSON, textToLazyBS, @@ -250,6 +251,9 @@ eitherToMaybe :: Either e a -> Maybe a eitherToMaybe (Right x) = Just x eitherToMaybe (Left _) = Nothing +orElse :: Maybe a -> a -> a +orElse = flip fromMaybe + getEnvVarDefinition :: (String, String) -> String getEnvVarDefinition (name, value) = concat [name, "=", value] diff --git a/waspc/waspc.cabal b/waspc/waspc.cabal index e7fdd2317e..c8acd7b505 100644 --- a/waspc/waspc.cabal +++ b/waspc/waspc.cabal @@ -365,10 +365,10 @@ library Wasp.Project.Analyze Wasp.Project.Common Wasp.Project.Db - Wasp.Project.Db.Migrations Wasp.Project.Db.Dev Wasp.Project.Db.Dev.Postgres Wasp.Project.Db.Dev.Sqlite + Wasp.Project.Db.Migrations Wasp.Project.Deployment Wasp.Project.Env Wasp.Project.ExternalConfig @@ -377,6 +377,7 @@ library Wasp.Project.ExternalFiles Wasp.Project.Studio Wasp.Project.Vite + Wasp.Project.WaspFile Wasp.Psl.Ast.Argument Wasp.Psl.Ast.Attribute Wasp.Psl.Ast.Common From 9638e32f677f6e0b93ebed9f7195e3ff66484fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Sodi=C4=87?= Date: Tue, 10 Dec 2024 11:49:47 +0100 Subject: [PATCH 2/7] Add elaborating comments and improve type for wasp file --- waspc/src/Wasp/Analyzer.hs | 10 ++++++++++ waspc/src/Wasp/Error.hs | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/waspc/src/Wasp/Analyzer.hs b/waspc/src/Wasp/Analyzer.hs index 8c4c98a68a..1c78f1d7d4 100644 --- a/waspc/src/Wasp/Analyzer.hs +++ b/waspc/src/Wasp/Analyzer.hs @@ -164,6 +164,16 @@ analyze prismaSchemaAst = >=> (wrapAnalyzerError TypeError . typeCheck stdTypes) >=> (wrapAnalyzerError EvaluationError . evaluate stdTypes) +-- | When writing main.wasp.ts, TypeScript should know about all the available +-- entities. +-- Since Wasp's AST includes entity declarations, the easiest way to get a list +-- of all entities defined in the Prisma Schema is by: +-- 1. Creating an AST with (and only with) the declarations for the Prisma +-- schema Entities. +-- 2. Type-checking that AST and returning the result. +-- This gives us a list of entity declarations we can then forward to +-- TypeScript (which then validates the user config only uses existing +-- entities). getEntityDecls :: Psl.Schema.Schema -> Either [AnalyzeError] [Decl] getEntityDecls schema = wrapAnalyzerError TypeError (typeCheck stdTypes astWithEntitiesOnly) diff --git a/waspc/src/Wasp/Error.hs b/waspc/src/Wasp/Error.hs index aa4ef8474a..a02cb070f6 100644 --- a/waspc/src/Wasp/Error.hs +++ b/waspc/src/Wasp/Error.hs @@ -7,13 +7,14 @@ import StrongPath.Types (File) import Wasp.Analyzer.Parser.Ctx (Ctx, getCtxRgn) import Wasp.Analyzer.Parser.SourcePosition (SourcePosition (..)) import Wasp.Analyzer.Parser.SourceRegion (SourceRegion (..)) +import Wasp.Project.Common (WaspLangFile) import Wasp.Util (indent, insertAt, leftPad) import qualified Wasp.Util.Terminal as T -- | Transforms compiler error (error with parse context) into an informative, pretty String that -- can be printed directly into the terminal. It uses terminal features like escape codes -- (colors, styling, ...). -showCompilerErrorForTerminal :: (Path' Abs (File f), String) -> (String, Ctx) -> String +showCompilerErrorForTerminal :: (Path' Abs (File WaspLangFile), String) -> (String, Ctx) -> String showCompilerErrorForTerminal (waspFilePath, waspFileContent) (errMsg, errCtx) = let srcRegion = getCtxRgn errCtx in intercalate From a1bd9ab0d0de2899a51e8315f5590d00cc5d46e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Sodi=C4=87?= Date: Tue, 10 Dec 2024 12:08:33 +0100 Subject: [PATCH 3/7] Change case to either --- waspc/src/Wasp/AppSpec/ExtImport.hs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/waspc/src/Wasp/AppSpec/ExtImport.hs b/waspc/src/Wasp/AppSpec/ExtImport.hs index fee7606a78..165030fd99 100644 --- a/waspc/src/Wasp/AppSpec/ExtImport.hs +++ b/waspc/src/Wasp/AppSpec/ExtImport.hs @@ -34,9 +34,7 @@ instance FromJSON ExtImport where nameStr <- o .: "name" pathStr <- o .: "path" extImportName <- parseExtImportName kindStr nameStr - extImportPath <- case parseExtImportPath pathStr of - Right path' -> pure path' - Left err -> fail err + extImportPath <- either fail pure $ parseExtImportPath pathStr return $ ExtImport extImportName extImportPath where parseExtImportName kindStr nameStr = case kindStr of From a79e19bd249abf3590a2c094c54916b5d03f401f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Sodi=C4=87?= Date: Tue, 10 Dec 2024 12:22:33 +0100 Subject: [PATCH 4/7] Move Job helpers out of the generator --- waspc/cli/src/Wasp/Cli/Command/Db/Studio.hs | 2 +- waspc/cli/src/Wasp/Cli/Command/TsConfigSetup.hs | 6 +++--- waspc/src/Wasp/Generator/DbGenerator/Jobs.hs | 4 ++-- waspc/src/Wasp/Generator/DbGenerator/Operations.hs | 2 +- waspc/src/Wasp/Generator/NpmInstall.hs | 6 +++--- waspc/src/Wasp/Generator/SdkGenerator.hs | 6 +++--- waspc/src/Wasp/Generator/ServerGenerator/Setup.hs | 4 ++-- waspc/src/Wasp/Generator/ServerGenerator/Start.hs | 4 ++-- waspc/src/Wasp/Generator/Start.hs | 4 ++-- waspc/src/Wasp/Generator/Test.hs | 2 +- waspc/src/Wasp/Generator/WebAppGenerator/Setup.hs | 4 ++-- waspc/src/Wasp/Generator/WebAppGenerator/Start.hs | 4 ++-- waspc/src/Wasp/Generator/WebAppGenerator/Test.hs | 4 ++-- waspc/src/Wasp/{Generator => }/Job.hs | 2 +- waspc/src/Wasp/{Generator => }/Job/Common.hs | 4 ++-- waspc/src/Wasp/{Generator => }/Job/IO.hs | 8 ++++---- .../src/Wasp/{Generator => }/Job/IO/PrefixedWriter.hs | 8 ++++---- waspc/src/Wasp/{Generator => }/Job/Process.hs | 4 ++-- waspc/src/Wasp/Project/WaspFile.hs | 6 +++--- waspc/waspc.cabal | 10 +++++----- 20 files changed, 47 insertions(+), 47 deletions(-) rename waspc/src/Wasp/{Generator => }/Job.hs (96%) rename waspc/src/Wasp/{Generator => }/Job/Common.hs (90%) rename waspc/src/Wasp/{Generator => }/Job/IO.hs (85%) rename waspc/src/Wasp/{Generator => }/Job/IO/PrefixedWriter.hs (97%) rename waspc/src/Wasp/{Generator => }/Job/Process.hs (98%) diff --git a/waspc/cli/src/Wasp/Cli/Command/Db/Studio.hs b/waspc/cli/src/Wasp/Cli/Command/Db/Studio.hs index 09db8ca458..91abc66c03 100644 --- a/waspc/cli/src/Wasp/Cli/Command/Db/Studio.hs +++ b/waspc/cli/src/Wasp/Cli/Command/Db/Studio.hs @@ -11,7 +11,7 @@ import Wasp.Cli.Command (Command) import Wasp.Cli.Command.Message (cliSendMessageC) import Wasp.Cli.Command.Require (InWaspProject (InWaspProject), require) import Wasp.Generator.DbGenerator.Jobs (runStudio) -import Wasp.Generator.Job.IO (readJobMessagesAndPrintThemPrefixed) +import Wasp.Job.IO (readJobMessagesAndPrintThemPrefixed) import qualified Wasp.Message as Msg import Wasp.Project.Common (dotWaspDirInWaspProjectDir, generatedCodeDirInDotWaspDir) diff --git a/waspc/cli/src/Wasp/Cli/Command/TsConfigSetup.hs b/waspc/cli/src/Wasp/Cli/Command/TsConfigSetup.hs index beaf6328b8..62751a780b 100644 --- a/waspc/cli/src/Wasp/Cli/Command/TsConfigSetup.hs +++ b/waspc/cli/src/Wasp/Cli/Command/TsConfigSetup.hs @@ -8,9 +8,9 @@ import StrongPath (Abs, Dir, Path') import System.Exit (ExitCode (..)) import Wasp.Cli.Command (Command, CommandError (..), require) import Wasp.Cli.Command.Require (InWaspProject (InWaspProject)) -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.IO (readJobMessagesAndPrintThemPrefixed) -import Wasp.Generator.Job.Process (runNodeCommandAsJob) +import qualified Wasp.Job as J +import Wasp.Job.IO (readJobMessagesAndPrintThemPrefixed) +import Wasp.Job.Process (runNodeCommandAsJob) import Wasp.NodePackageFFI (InstallablePackage (WaspConfigPackage), getPackageInstallationPath) -- | Prepares the project for using Wasp's TypeScript SDK. diff --git a/waspc/src/Wasp/Generator/DbGenerator/Jobs.hs b/waspc/src/Wasp/Generator/DbGenerator/Jobs.hs index 0687b23a28..3a1c0b28ea 100644 --- a/waspc/src/Wasp/Generator/DbGenerator/Jobs.hs +++ b/waspc/src/Wasp/Generator/DbGenerator/Jobs.hs @@ -19,8 +19,8 @@ import StrongPath.TH (relfile) import qualified System.Info import Wasp.Generator.Common (ProjectRootDir) import Wasp.Generator.DbGenerator.Common (MigrateArgs (..), dbSchemaFileInProjectRootDir) -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.Process (runNodeCommandAsJob, runNodeCommandAsJobWithExtraEnv) +import qualified Wasp.Job as J +import Wasp.Job.Process (runNodeCommandAsJob, runNodeCommandAsJobWithExtraEnv) import Wasp.Generator.ServerGenerator.Common (serverRootDirInProjectRootDir) import Wasp.Generator.ServerGenerator.Db.Seed (dbSeedNameEnvVarName) import Wasp.Project.Common (WaspProjectDir, waspProjectDirFromProjectRootDir) diff --git a/waspc/src/Wasp/Generator/DbGenerator/Operations.hs b/waspc/src/Wasp/Generator/DbGenerator/Operations.hs index 503e912938..8a85e70f29 100644 --- a/waspc/src/Wasp/Generator/DbGenerator/Operations.hs +++ b/waspc/src/Wasp/Generator/DbGenerator/Operations.hs @@ -36,7 +36,7 @@ import Wasp.Generator.DbGenerator.Common ) import qualified Wasp.Generator.DbGenerator.Jobs as DbJobs import Wasp.Generator.FileDraft.WriteableMonad (WriteableMonad (copyDirectoryRecursive, doesDirectoryExist)) -import Wasp.Generator.Job.IO +import Wasp.Job.IO ( collectJobTextOutputUntilExitReceived, printJobMsgsUntilExitReceived, readJobMessagesAndPrintThemPrefixed, diff --git a/waspc/src/Wasp/Generator/NpmInstall.hs b/waspc/src/Wasp/Generator/NpmInstall.hs index 316b9fb6e7..f9bda66efe 100644 --- a/waspc/src/Wasp/Generator/NpmInstall.hs +++ b/waspc/src/Wasp/Generator/NpmInstall.hs @@ -16,9 +16,9 @@ import System.Exit (ExitCode (..)) import UnliftIO (race) import Wasp.AppSpec (AppSpec (waspProjectDir)) import Wasp.Generator.Common (ProjectRootDir) -import Wasp.Generator.Job (Job, JobMessage, JobType) -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.IO.PrefixedWriter (PrefixedWriter, printJobMessagePrefixed, runPrefixedWriter) +import Wasp.Job (Job, JobMessage, JobType) +import qualified Wasp.Job as J +import Wasp.Job.IO.PrefixedWriter (PrefixedWriter, printJobMessagePrefixed, runPrefixedWriter) import Wasp.Generator.Monad (GeneratorError (..)) import Wasp.Generator.NpmInstall.Common (AllNpmDeps (..), getAllNpmDeps) import Wasp.Generator.NpmInstall.InstalledNpmDepsLog (forgetInstalledNpmDepsLog, loadInstalledNpmDepsLog, saveInstalledNpmDepsLog) diff --git a/waspc/src/Wasp/Generator/SdkGenerator.hs b/waspc/src/Wasp/Generator/SdkGenerator.hs index ad0e8a1b12..453e2da974 100644 --- a/waspc/src/Wasp/Generator/SdkGenerator.hs +++ b/waspc/src/Wasp/Generator/SdkGenerator.hs @@ -37,9 +37,9 @@ import Wasp.Generator.DbGenerator (getEntitiesForPrismaSchema) import qualified Wasp.Generator.DbGenerator.Auth as DbAuth import Wasp.Generator.FileDraft (FileDraft) import qualified Wasp.Generator.FileDraft as FD -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.IO (readJobMessagesAndPrintThemPrefixed) -import Wasp.Generator.Job.Process (runNodeCommandAsJob) +import qualified Wasp.Job as J +import Wasp.Job.IO (readJobMessagesAndPrintThemPrefixed) +import Wasp.Job.Process (runNodeCommandAsJob) import Wasp.Generator.Monad (Generator) import qualified Wasp.Generator.NpmDependencies as N import Wasp.Generator.SdkGenerator.AuthG (genAuth) diff --git a/waspc/src/Wasp/Generator/ServerGenerator/Setup.hs b/waspc/src/Wasp/Generator/ServerGenerator/Setup.hs index 03194b729f..9d5d97bc21 100644 --- a/waspc/src/Wasp/Generator/ServerGenerator/Setup.hs +++ b/waspc/src/Wasp/Generator/ServerGenerator/Setup.hs @@ -5,8 +5,8 @@ where import StrongPath (Abs, Dir, Path', ()) import Wasp.Generator.Common (ProjectRootDir) -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.Process (runNodeCommandAsJob) +import qualified Wasp.Job as J +import Wasp.Job.Process (runNodeCommandAsJob) import qualified Wasp.Generator.ServerGenerator.Common as Common installNpmDependencies :: Path' Abs (Dir ProjectRootDir) -> J.Job diff --git a/waspc/src/Wasp/Generator/ServerGenerator/Start.hs b/waspc/src/Wasp/Generator/ServerGenerator/Start.hs index 1f5dfd95bf..84560a9974 100644 --- a/waspc/src/Wasp/Generator/ServerGenerator/Start.hs +++ b/waspc/src/Wasp/Generator/ServerGenerator/Start.hs @@ -5,8 +5,8 @@ where import StrongPath (Abs, Dir, Path', ()) import Wasp.Generator.Common (ProjectRootDir) -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.Process (runNodeCommandAsJob) +import qualified Wasp.Job as J +import Wasp.Job.Process (runNodeCommandAsJob) import qualified Wasp.Generator.ServerGenerator.Common as Common startServer :: Path' Abs (Dir ProjectRootDir) -> J.Job diff --git a/waspc/src/Wasp/Generator/Start.hs b/waspc/src/Wasp/Generator/Start.hs index 43cb9b8c4a..ba7928469d 100644 --- a/waspc/src/Wasp/Generator/Start.hs +++ b/waspc/src/Wasp/Generator/Start.hs @@ -9,8 +9,8 @@ import Control.Concurrent.Extra (threadDelay) import Control.Monad (void) import StrongPath (Abs, Dir, Path') import Wasp.Generator.Common (ProjectRootDir) -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.IO (readJobMessagesAndPrintThemPrefixed) +import qualified Wasp.Job as J +import Wasp.Job.IO (readJobMessagesAndPrintThemPrefixed) import Wasp.Generator.ServerGenerator.Start (startServer) import Wasp.Generator.WebAppGenerator.Start (startWebApp) diff --git a/waspc/src/Wasp/Generator/Test.hs b/waspc/src/Wasp/Generator/Test.hs index c266f0ec3b..4f07e9fbf2 100644 --- a/waspc/src/Wasp/Generator/Test.hs +++ b/waspc/src/Wasp/Generator/Test.hs @@ -7,7 +7,7 @@ import Control.Concurrent (newChan) import Control.Concurrent.Async (concurrently) import StrongPath (Abs, Dir, Path') import System.Exit (ExitCode (..)) -import Wasp.Generator.Job.IO (readJobMessagesAndPrintThemPrefixed) +import Wasp.Job.IO (readJobMessagesAndPrintThemPrefixed) import qualified Wasp.Generator.WebAppGenerator.Test as WebAppTest import Wasp.Project.Common (WaspProjectDir) diff --git a/waspc/src/Wasp/Generator/WebAppGenerator/Setup.hs b/waspc/src/Wasp/Generator/WebAppGenerator/Setup.hs index 4e82d4d399..c77d5db972 100644 --- a/waspc/src/Wasp/Generator/WebAppGenerator/Setup.hs +++ b/waspc/src/Wasp/Generator/WebAppGenerator/Setup.hs @@ -5,8 +5,8 @@ where import StrongPath (Abs, Dir, Path', ()) import Wasp.Generator.Common (ProjectRootDir) -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.Process (runNodeCommandAsJob) +import qualified Wasp.Job as J +import Wasp.Job.Process (runNodeCommandAsJob) import qualified Wasp.Generator.WebAppGenerator.Common as Common installNpmDependencies :: Path' Abs (Dir ProjectRootDir) -> J.Job diff --git a/waspc/src/Wasp/Generator/WebAppGenerator/Start.hs b/waspc/src/Wasp/Generator/WebAppGenerator/Start.hs index 188560ee81..5391f78bc1 100644 --- a/waspc/src/Wasp/Generator/WebAppGenerator/Start.hs +++ b/waspc/src/Wasp/Generator/WebAppGenerator/Start.hs @@ -5,8 +5,8 @@ where import StrongPath (Abs, Dir, Path', ()) import Wasp.Generator.Common (ProjectRootDir) -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.Process (runNodeCommandAsJob) +import qualified Wasp.Job as J +import Wasp.Job.Process (runNodeCommandAsJob) import qualified Wasp.Generator.WebAppGenerator.Common as Common startWebApp :: Path' Abs (Dir ProjectRootDir) -> J.Job diff --git a/waspc/src/Wasp/Generator/WebAppGenerator/Test.hs b/waspc/src/Wasp/Generator/WebAppGenerator/Test.hs index 6755395503..490ba92410 100644 --- a/waspc/src/Wasp/Generator/WebAppGenerator/Test.hs +++ b/waspc/src/Wasp/Generator/WebAppGenerator/Test.hs @@ -5,8 +5,8 @@ where import StrongPath (Abs, Dir, Path', relfile, ()) import qualified StrongPath as SP -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.Process (runNodeCommandAsJob) +import qualified Wasp.Job as J +import Wasp.Job.Process (runNodeCommandAsJob) import Wasp.Generator.WebAppGenerator.Common (webAppRootDirInProjectRootDir) import Wasp.Project.Common (WaspProjectDir, dotWaspDirInWaspProjectDir, generatedCodeDirInDotWaspDir) diff --git a/waspc/src/Wasp/Generator/Job.hs b/waspc/src/Wasp/Job.hs similarity index 96% rename from waspc/src/Wasp/Generator/Job.hs rename to waspc/src/Wasp/Job.hs index 45730c29a2..ac34fcaceb 100644 --- a/waspc/src/Wasp/Generator/Job.hs +++ b/waspc/src/Wasp/Job.hs @@ -1,4 +1,4 @@ -module Wasp.Generator.Job +module Wasp.Job ( Job, JobMessage (..), JobMessageData (..), diff --git a/waspc/src/Wasp/Generator/Job/Common.hs b/waspc/src/Wasp/Job/Common.hs similarity index 90% rename from waspc/src/Wasp/Generator/Job/Common.hs rename to waspc/src/Wasp/Job/Common.hs index a979e475ff..8d6b046e9e 100644 --- a/waspc/src/Wasp/Generator/Job/Common.hs +++ b/waspc/src/Wasp/Job/Common.hs @@ -1,4 +1,4 @@ -module Wasp.Generator.Job.Common +module Wasp.Job.Common ( getJobMessageOutHandle, getJobMessageContent, ) @@ -7,7 +7,7 @@ where import qualified Data.Text as T import System.Exit (ExitCode (..)) import System.IO (Handle, stderr, stdout) -import qualified Wasp.Generator.Job as J +import qualified Wasp.Job as J getJobMessageOutHandle :: J.JobMessage -> Handle getJobMessageOutHandle jobMsg = case J._data jobMsg of diff --git a/waspc/src/Wasp/Generator/Job/IO.hs b/waspc/src/Wasp/Job/IO.hs similarity index 85% rename from waspc/src/Wasp/Generator/Job/IO.hs rename to waspc/src/Wasp/Job/IO.hs index ef563eb8c7..54fe3b8ca3 100644 --- a/waspc/src/Wasp/Generator/Job/IO.hs +++ b/waspc/src/Wasp/Job/IO.hs @@ -1,4 +1,4 @@ -module Wasp.Generator.Job.IO +module Wasp.Job.IO ( readJobMessagesAndPrintThemPrefixed, printJobMessage, printJobMsgsUntilExitReceived, @@ -11,9 +11,9 @@ import Control.Monad.IO.Class (liftIO) import Data.Text (Text) import qualified Data.Text.IO as T.IO import System.IO (hFlush) -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.Common (getJobMessageContent, getJobMessageOutHandle) -import Wasp.Generator.Job.IO.PrefixedWriter (printJobMessagePrefixed, runPrefixedWriter) +import qualified Wasp.Job as J +import Wasp.Job.Common (getJobMessageContent, getJobMessageOutHandle) +import Wasp.Job.IO.PrefixedWriter (printJobMessagePrefixed, runPrefixedWriter) printJobMsgsUntilExitReceived :: Chan J.JobMessage -> IO () printJobMsgsUntilExitReceived chan = do diff --git a/waspc/src/Wasp/Generator/Job/IO/PrefixedWriter.hs b/waspc/src/Wasp/Job/IO/PrefixedWriter.hs similarity index 97% rename from waspc/src/Wasp/Generator/Job/IO/PrefixedWriter.hs rename to waspc/src/Wasp/Job/IO/PrefixedWriter.hs index d3f3bd0d97..8e0325553b 100644 --- a/waspc/src/Wasp/Generator/Job/IO/PrefixedWriter.hs +++ b/waspc/src/Wasp/Job/IO/PrefixedWriter.hs @@ -1,7 +1,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE TupleSections #-} -module Wasp.Generator.Job.IO.PrefixedWriter +module Wasp.Job.IO.PrefixedWriter ( printJobMessagePrefixed, runPrefixedWriter, PrefixedWriter, @@ -17,9 +17,9 @@ 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 Wasp.Job (JobType) +import qualified Wasp.Job as J +import Wasp.Job.Common (getJobMessageContent, getJobMessageOutHandle) import qualified Wasp.Util.Terminal as Term -- | diff --git a/waspc/src/Wasp/Generator/Job/Process.hs b/waspc/src/Wasp/Job/Process.hs similarity index 98% rename from waspc/src/Wasp/Generator/Job/Process.hs rename to waspc/src/Wasp/Job/Process.hs index 3c02ec68ed..5af60d14e3 100644 --- a/waspc/src/Wasp/Generator/Job/Process.hs +++ b/waspc/src/Wasp/Job/Process.hs @@ -1,6 +1,6 @@ {-# LANGUAGE ScopedTypeVariables #-} -module Wasp.Generator.Job.Process +module Wasp.Job.Process ( runProcessAsJob, runNodeCommandAsJob, runNodeCommandAsJobWithExtraEnv, @@ -21,7 +21,7 @@ import System.Exit (ExitCode (..)) import qualified System.Info import qualified System.Process as P import UnliftIO.Exception (bracket) -import qualified Wasp.Generator.Job as J +import qualified Wasp.Job as J import qualified Wasp.Node.Version as NodeVersion -- TODO: diff --git a/waspc/src/Wasp/Project/WaspFile.hs b/waspc/src/Wasp/Project/WaspFile.hs index b721031e57..fc94cbb547 100644 --- a/waspc/src/Wasp/Project/WaspFile.hs +++ b/waspc/src/Wasp/Project/WaspFile.hs @@ -32,9 +32,9 @@ import Wasp.Analyzer.Parser.Ctx (Ctx) import qualified Wasp.AppSpec as AS import Wasp.AppSpec.Core.Decl.JSON () import Wasp.Error (showCompilerErrorForTerminal) -import qualified Wasp.Generator.Job as J -import Wasp.Generator.Job.IO (readJobMessagesAndPrintThemPrefixed) -import Wasp.Generator.Job.Process (runNodeCommandAsJob) +import qualified Wasp.Job as J +import Wasp.Job.IO (readJobMessagesAndPrintThemPrefixed) +import Wasp.Job.Process (runNodeCommandAsJob) import Wasp.Project.Common ( CompileError, WaspFilePath (..), diff --git a/waspc/waspc.cabal b/waspc/waspc.cabal index c8acd7b505..1b3c423eca 100644 --- a/waspc/waspc.cabal +++ b/waspc/waspc.cabal @@ -293,11 +293,6 @@ library Wasp.Generator.FileDraft.CopyAndModifyTextFileDraft Wasp.Generator.FileDraft.Writeable Wasp.Generator.FileDraft.WriteableMonad - Wasp.Generator.Job - Wasp.Generator.Job.Common - Wasp.Generator.Job.IO - Wasp.Generator.Job.IO.PrefixedWriter - Wasp.Generator.Job.Process Wasp.Generator.JsImport Wasp.Generator.Monad Wasp.Generator.NpmDependencies @@ -357,6 +352,11 @@ library Wasp.Generator.WebSocket Wasp.Generator.WriteFileDrafts Wasp.JsImport + Wasp.Job + Wasp.Job.Common + Wasp.Job.IO + Wasp.Job.IO.PrefixedWriter + Wasp.Job.Process Wasp.Message Wasp.Node.Version Wasp.NpmDependency From 026b48c50bfc74950e6f4a87087e9fe7b9f91da2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Sodi=C4=87?= Date: Fri, 20 Dec 2024 12:00:32 +0100 Subject: [PATCH 5/7] Address PR comments --- waspc/src/Wasp/Analyzer.hs | 18 ++++++++---------- waspc/src/Wasp/Project/WaspFile.hs | 5 ++++- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/waspc/src/Wasp/Analyzer.hs b/waspc/src/Wasp/Analyzer.hs index 1c78f1d7d4..77441dedf9 100644 --- a/waspc/src/Wasp/Analyzer.hs +++ b/waspc/src/Wasp/Analyzer.hs @@ -164,18 +164,16 @@ analyze prismaSchemaAst = >=> (wrapAnalyzerError TypeError . typeCheck stdTypes) >=> (wrapAnalyzerError EvaluationError . evaluate stdTypes) --- | When writing main.wasp.ts, TypeScript should know about all the available --- entities. --- Since Wasp's AST includes entity declarations, the easiest way to get a list --- of all entities defined in the Prisma Schema is by: --- 1. Creating an AST with (and only with) the declarations for the Prisma --- schema Entities. --- 2. Type-checking that AST and returning the result. --- This gives us a list of entity declarations we can then forward to --- TypeScript (which then validates the user config only uses existing --- entities). getEntityDecls :: Psl.Schema.Schema -> Either [AnalyzeError] [Decl] getEntityDecls schema = + -- Since Wasp's AST includes entity declarations, the easiest way to get a list + -- of all entities defined in the Prisma Schema is by: + -- 1. Creating an AST with (and only with) the declarations for the Prisma + -- schema Entities. + -- 2. Type-checking that AST and returning the result. + -- This gives us a list of entity declarations we can then forward to + -- TypeScript (which then validates the user config only uses existing + -- entities). wrapAnalyzerError TypeError (typeCheck stdTypes astWithEntitiesOnly) >>= (wrapAnalyzerError EvaluationError . evaluate stdTypes) where diff --git a/waspc/src/Wasp/Project/WaspFile.hs b/waspc/src/Wasp/Project/WaspFile.hs index fc94cbb547..b87b71f545 100644 --- a/waspc/src/Wasp/Project/WaspFile.hs +++ b/waspc/src/Wasp/Project/WaspFile.hs @@ -86,7 +86,7 @@ analyzeWaspTsFile :: Path' Abs (File WaspTsFile) -> IO (Either [CompileError] [AS.Decl]) analyzeWaspTsFile waspProjectDir prismaSchemaAst waspFilePath = runExceptT $ do - -- TODO: I'm not yet sure where tsconfig.node.json location should come from + -- TODO: I'm not yet sure where tsconfig.wasp.json location should come from -- because we also need that knowledge when generating a TS SDK project. compiledWaspJsFile <- ExceptT $ compileWaspTsFile waspProjectDir [relfile|tsconfig.wasp.json|] waspFilePath declsJsonFile <- ExceptT $ executeMainWaspJsFileAndGetDeclsFile waspProjectDir prismaSchemaAst compiledWaspJsFile @@ -160,6 +160,9 @@ executeMainWaspJsFileAndGetDeclsFile waspProjectDir prismaSchemaAst absCompiledM [ "wasp-config", fromAbsFile absCompiledMainWaspJsFile, fromAbsFile absDeclsOutputFile, + -- When the user is coding main.wasp.ts, TypeScript must know about + -- all the available entities to warn the user if they use an + -- entity that doesn't exist. encodeToString allowedEntityNames ] J.Wasp From 4ab6e946e753e958fc14bdf731dec37f693636ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Sodi=C4=87?= Date: Fri, 20 Dec 2024 18:27:15 +0100 Subject: [PATCH 6/7] Separate WaspFile into modules --- .../Wasp/AI/GenerateNewProject/WaspFile.hs | 2 +- waspc/src/Wasp/Project/WaspFile.hs | 148 +----------------- waspc/src/Wasp/Project/WaspFile/TypeScript.hs | 146 +++++++++++++++++ waspc/src/Wasp/Project/WaspFile/WaspLang.hs | 35 +++++ waspc/waspc.cabal | 2 + 5 files changed, 190 insertions(+), 143 deletions(-) create mode 100644 waspc/src/Wasp/Project/WaspFile/TypeScript.hs create mode 100644 waspc/src/Wasp/Project/WaspFile/WaspLang.hs diff --git a/waspc/src/Wasp/AI/GenerateNewProject/WaspFile.hs b/waspc/src/Wasp/AI/GenerateNewProject/WaspFile.hs index 799a8a2b5d..c164015a1e 100644 --- a/waspc/src/Wasp/AI/GenerateNewProject/WaspFile.hs +++ b/waspc/src/Wasp/AI/GenerateNewProject/WaspFile.hs @@ -24,7 +24,7 @@ import qualified Wasp.AI.GenerateNewProject.Common.Prompts as Prompts import Wasp.AI.GenerateNewProject.Plan (Plan) import Wasp.AI.OpenAI.ChatGPT (ChatMessage (..), ChatRole (..)) import Wasp.Analyzer.Parser.Ctx (Ctx (..)) -import Wasp.Project.WaspFile (analyzeWaspFileContent) +import Wasp.Project.WaspFile.WaspLang (analyzeWaspFileContent) import qualified Wasp.Psl.Ast.Schema as Psl.Schema import qualified Wasp.Util.Aeson as Utils.Aeson diff --git a/waspc/src/Wasp/Project/WaspFile.hs b/waspc/src/Wasp/Project/WaspFile.hs index b87b71f545..82502ca07a 100644 --- a/waspc/src/Wasp/Project/WaspFile.hs +++ b/waspc/src/Wasp/Project/WaspFile.hs @@ -1,57 +1,30 @@ module Wasp.Project.WaspFile ( findWaspFile, analyzeWaspFile, - analyzeWaspFileContent, ) where -import Control.Arrow (left) -import Control.Concurrent (newChan) -import Control.Concurrent.Async (concurrently) -import Control.Monad.Except (ExceptT (ExceptT), liftEither, runExceptT) -import qualified Data.Aeson as Aeson import Data.List (find, isSuffixOf) import StrongPath ( Abs, Dir, - File, - File', Path', - Rel, - basename, castFile, fromAbsDir, - fromAbsFile, fromRelFile, - relfile, (), ) -import System.Exit (ExitCode (..)) -import qualified Wasp.Analyzer as Analyzer -import Wasp.Analyzer.Parser.Ctx (Ctx) import qualified Wasp.AppSpec as AS import Wasp.AppSpec.Core.Decl.JSON () -import Wasp.Error (showCompilerErrorForTerminal) -import qualified Wasp.Job as J -import Wasp.Job.IO (readJobMessagesAndPrintThemPrefixed) -import Wasp.Job.Process (runNodeCommandAsJob) import Wasp.Project.Common ( CompileError, WaspFilePath (..), - WaspLangFile, WaspProjectDir, - WaspTsFile, - dotWaspDirInWaspProjectDir, ) +import Wasp.Project.WaspFile.TypeScript (analyzeWaspTsFile) +import Wasp.Project.WaspFile.WaspLang (analyzeWaspLangFile) import qualified Wasp.Psl.Ast.Schema as Psl.Schema -import Wasp.Util (orElse) -import Wasp.Util.Aeson (encodeToString) import qualified Wasp.Util.IO as IOUtil -import Wasp.Util.StrongPath (replaceRelExtension) - -data CompiledWaspJsFile - -data AppSpecDeclsJsonFile findWaspFile :: Path' Abs (Dir WaspProjectDir) -> IO (Either String WaspFilePath) findWaspFile waspDir = do @@ -64,7 +37,10 @@ findWaspFile waspDir = do where findWaspTsFile files = WaspTs <$> findFileThatEndsWith ".wasp.ts" files findWaspLangFile files = WaspLang <$> findFileThatEndsWith ".wasp" files - findFileThatEndsWith suffix files = castFile . (waspDir ) <$> find ((suffix `isSuffixOf`) . fromRelFile) files + findFileThatEndsWith suffix files = + castFile + . (waspDir ) + <$> find ((suffix `isSuffixOf`) . fromRelFile) files fileNotFoundMessage = "Couldn't find the *.wasp or a *.wasp.ts file in the " ++ fromAbsDir waspDir ++ " directory" bothFilesFoundMessage = @@ -79,115 +55,3 @@ analyzeWaspFile :: analyzeWaspFile waspDir prismaSchemaAst = \case WaspLang waspFilePath -> analyzeWaspLangFile prismaSchemaAst waspFilePath WaspTs waspFilePath -> analyzeWaspTsFile waspDir prismaSchemaAst waspFilePath - -analyzeWaspTsFile :: - Path' Abs (Dir WaspProjectDir) -> - Psl.Schema.Schema -> - Path' Abs (File WaspTsFile) -> - IO (Either [CompileError] [AS.Decl]) -analyzeWaspTsFile waspProjectDir prismaSchemaAst waspFilePath = runExceptT $ do - -- TODO: I'm not yet sure where tsconfig.wasp.json location should come from - -- because we also need that knowledge when generating a TS SDK project. - compiledWaspJsFile <- ExceptT $ compileWaspTsFile waspProjectDir [relfile|tsconfig.wasp.json|] waspFilePath - declsJsonFile <- ExceptT $ executeMainWaspJsFileAndGetDeclsFile waspProjectDir prismaSchemaAst compiledWaspJsFile - ExceptT $ readDecls prismaSchemaAst declsJsonFile - -analyzeWaspLangFile :: Psl.Schema.Schema -> Path' Abs (File WaspLangFile) -> IO (Either [CompileError] [AS.Decl]) -analyzeWaspLangFile prismaSchemaAst waspFilePath = do - waspFileContent <- IOUtil.readFile waspFilePath - left (map $ showCompilerErrorForTerminal (waspFilePath, waspFileContent)) - <$> analyzeWaspFileContent prismaSchemaAst waspFileContent - -analyzeWaspFileContent :: Psl.Schema.Schema -> String -> IO (Either [(String, Ctx)] [AS.Decl]) -analyzeWaspFileContent prismaSchemaAst = - return - . left (map Analyzer.getErrorMessageAndCtx) - . Analyzer.analyze prismaSchemaAst - -compileWaspTsFile :: - Path' Abs (Dir WaspProjectDir) -> - Path' (Rel WaspProjectDir) File' -> - Path' Abs (File WaspTsFile) -> - IO (Either [CompileError] (Path' Abs (File CompiledWaspJsFile))) -compileWaspTsFile waspProjectDir tsconfigNodeFileInWaspProjectDir waspFilePath = do - chan <- newChan - (_, tscExitCode) <- - concurrently - (readJobMessagesAndPrintThemPrefixed chan) - ( runNodeCommandAsJob - waspProjectDir - "npx" - [ "tsc", - "-p", - fromAbsFile (waspProjectDir tsconfigNodeFileInWaspProjectDir), - "--noEmit", - "false", - "--outDir", - fromAbsDir outDir - ] - J.Wasp - chan - ) - return $ case tscExitCode of - ExitFailure _status -> Left ["Got TypeScript compiler errors for " ++ fromAbsFile waspFilePath ++ "."] - ExitSuccess -> Right absCompiledWaspJsFile - where - outDir = waspProjectDir dotWaspDirInWaspProjectDir - absCompiledWaspJsFile = outDir compiledWaspJsFileInDotWaspDir - compiledWaspJsFileInDotWaspDir = - castFile $ - replaceRelExtension (basename waspFilePath) ".js" - `orElse` error ("Couldn't calculate the compiled JS file path for " ++ fromAbsFile waspFilePath ++ ".") - -executeMainWaspJsFileAndGetDeclsFile :: - Path' Abs (Dir WaspProjectDir) -> - Psl.Schema.Schema -> - Path' Abs (File CompiledWaspJsFile) -> - IO (Either [CompileError] (Path' Abs (File AppSpecDeclsJsonFile))) -executeMainWaspJsFileAndGetDeclsFile waspProjectDir prismaSchemaAst absCompiledMainWaspJsFile = do - chan <- newChan - (_, runExitCode) <- do - concurrently - (readJobMessagesAndPrintThemPrefixed chan) - ( runNodeCommandAsJob - waspProjectDir - "npx" - -- TODO: Figure out how to keep running instructions in a single - -- place (e.g., this is string the same as the package name, but it's - -- repeated in two places). - -- Before this, I had the entrypoint file hardcoded, which was bad - -- too: waspProjectDir [relfile|node_modules/wasp-config/dist/run.js|] - [ "wasp-config", - fromAbsFile absCompiledMainWaspJsFile, - fromAbsFile absDeclsOutputFile, - -- When the user is coding main.wasp.ts, TypeScript must know about - -- all the available entities to warn the user if they use an - -- entity that doesn't exist. - encodeToString allowedEntityNames - ] - J.Wasp - chan - ) - case runExitCode of - ExitFailure _status -> return $ Left ["Error while running the compiled *.wasp.ts file."] - ExitSuccess -> return $ Right absDeclsOutputFile - where - absDeclsOutputFile = waspProjectDir dotWaspDirInWaspProjectDir [relfile|decls.json|] - allowedEntityNames = Psl.Schema.getModelNames prismaSchemaAst - -readDecls :: Psl.Schema.Schema -> Path' Abs (File AppSpecDeclsJsonFile) -> IO (Either [CompileError] [AS.Decl]) -readDecls prismaSchemaAst declsJsonFile = runExceptT $ do - entityDecls <- liftEither entityDeclsOrErrors - remainingDecls <- ExceptT $ left (: []) <$> declsFromJsonOrError - return $ entityDecls ++ remainingDecls - where - entityDeclsOrErrors = - left (map fst) $ - left (map Analyzer.getErrorMessageAndCtx) $ - Analyzer.getEntityDecls prismaSchemaAst - - declsFromJsonOrError = do - declsBytestring <- IOUtil.readFileBytes declsJsonFile - return $ - left ("Error while reading the declarations from JSON: " ++) $ - Aeson.eitherDecode declsBytestring diff --git a/waspc/src/Wasp/Project/WaspFile/TypeScript.hs b/waspc/src/Wasp/Project/WaspFile/TypeScript.hs new file mode 100644 index 0000000000..36e76720bb --- /dev/null +++ b/waspc/src/Wasp/Project/WaspFile/TypeScript.hs @@ -0,0 +1,146 @@ +module Wasp.Project.WaspFile.TypeScript + ( analyzeWaspTsFile, + ) +where + +import Control.Arrow (left) +import Control.Concurrent (newChan) +import Control.Concurrent.Async (concurrently) +import Control.Monad.Except (ExceptT (ExceptT), liftEither, runExceptT) +import qualified Data.Aeson as Aeson +import StrongPath + ( Abs, + Dir, + File, + File', + Path', + Rel, + basename, + castFile, + fromAbsDir, + fromAbsFile, + relfile, + (), + ) +import System.Exit (ExitCode (..)) +import qualified Wasp.Analyzer as Analyzer +import qualified Wasp.AppSpec as AS +import Wasp.AppSpec.Core.Decl.JSON () +import qualified Wasp.Job as J +import Wasp.Job.IO (readJobMessagesAndPrintThemPrefixed) +import Wasp.Job.Process (runNodeCommandAsJob) +import Wasp.Project.Common + ( CompileError, + WaspProjectDir, + WaspTsFile, + dotWaspDirInWaspProjectDir, + ) +import qualified Wasp.Psl.Ast.Schema as Psl.Schema +import Wasp.Util (orElse) +import Wasp.Util.Aeson (encodeToString) +import qualified Wasp.Util.IO as IOUtil +import Wasp.Util.StrongPath (replaceRelExtension) + +data CompiledWaspJsFile + +data AppSpecDeclsJsonFile + +analyzeWaspTsFile :: + Path' Abs (Dir WaspProjectDir) -> + Psl.Schema.Schema -> + Path' Abs (File WaspTsFile) -> + IO (Either [CompileError] [AS.Decl]) +analyzeWaspTsFile waspProjectDir prismaSchemaAst waspFilePath = runExceptT $ do + -- TODO: I'm not yet sure where tsconfig.wasp.json location should come from + -- because we also need that knowledge when generating a TS SDK project. + compiledWaspJsFile <- ExceptT $ compileWaspTsFile waspProjectDir [relfile|tsconfig.wasp.json|] waspFilePath + declsJsonFile <- ExceptT $ executeMainWaspJsFileAndGetDeclsFile waspProjectDir prismaSchemaAst compiledWaspJsFile + ExceptT $ readDecls prismaSchemaAst declsJsonFile + +compileWaspTsFile :: + Path' Abs (Dir WaspProjectDir) -> + Path' (Rel WaspProjectDir) File' -> + Path' Abs (File WaspTsFile) -> + IO (Either [CompileError] (Path' Abs (File CompiledWaspJsFile))) +compileWaspTsFile waspProjectDir tsconfigNodeFileInWaspProjectDir waspFilePath = do + chan <- newChan + (_, tscExitCode) <- + concurrently + (readJobMessagesAndPrintThemPrefixed chan) + ( runNodeCommandAsJob + waspProjectDir + "npx" + [ "tsc", + "-p", + fromAbsFile (waspProjectDir tsconfigNodeFileInWaspProjectDir), + "--noEmit", + "false", + "--outDir", + fromAbsDir outDir + ] + J.Wasp + chan + ) + return $ case tscExitCode of + ExitFailure _status -> Left ["Got TypeScript compiler errors for " ++ fromAbsFile waspFilePath ++ "."] + ExitSuccess -> Right absCompiledWaspJsFile + where + outDir = waspProjectDir dotWaspDirInWaspProjectDir + absCompiledWaspJsFile = outDir compiledWaspJsFileInDotWaspDir + compiledWaspJsFileInDotWaspDir = + castFile $ + replaceRelExtension (basename waspFilePath) ".js" + `orElse` error ("Couldn't calculate the compiled JS file path for " ++ fromAbsFile waspFilePath ++ ".") + +executeMainWaspJsFileAndGetDeclsFile :: + Path' Abs (Dir WaspProjectDir) -> + Psl.Schema.Schema -> + Path' Abs (File CompiledWaspJsFile) -> + IO (Either [CompileError] (Path' Abs (File AppSpecDeclsJsonFile))) +executeMainWaspJsFileAndGetDeclsFile waspProjectDir prismaSchemaAst absCompiledMainWaspJsFile = do + chan <- newChan + (_, runExitCode) <- do + concurrently + (readJobMessagesAndPrintThemPrefixed chan) + ( runNodeCommandAsJob + waspProjectDir + "npx" + -- TODO: Figure out how to keep running instructions in a single + -- place (e.g., this is string the same as the package name, but it's + -- repeated in two places). + -- Before this, I had the entrypoint file hardcoded, which was bad + -- too: waspProjectDir [relfile|node_modules/wasp-config/dist/run.js|] + [ "wasp-config", + fromAbsFile absCompiledMainWaspJsFile, + fromAbsFile absDeclsOutputFile, + -- When the user is coding main.wasp.ts, TypeScript must know about + -- all the available entities to warn the user if they use an + -- entity that doesn't exist. + encodeToString allowedEntityNames + ] + J.Wasp + chan + ) + case runExitCode of + ExitFailure _status -> return $ Left ["Error while running the compiled *.wasp.ts file."] + ExitSuccess -> return $ Right absDeclsOutputFile + where + absDeclsOutputFile = waspProjectDir dotWaspDirInWaspProjectDir [relfile|decls.json|] + allowedEntityNames = Psl.Schema.getModelNames prismaSchemaAst + +readDecls :: Psl.Schema.Schema -> Path' Abs (File AppSpecDeclsJsonFile) -> IO (Either [CompileError] [AS.Decl]) +readDecls prismaSchemaAst declsJsonFile = runExceptT $ do + entityDecls <- liftEither entityDeclsOrErrors + remainingDecls <- ExceptT $ left (: []) <$> declsFromJsonOrError + return $ entityDecls ++ remainingDecls + where + entityDeclsOrErrors = + left (map fst) $ + left (map Analyzer.getErrorMessageAndCtx) $ + Analyzer.getEntityDecls prismaSchemaAst + + declsFromJsonOrError = do + declsBytestring <- IOUtil.readFileBytes declsJsonFile + return $ + left ("Error while reading the declarations from JSON: " ++) $ + Aeson.eitherDecode declsBytestring diff --git a/waspc/src/Wasp/Project/WaspFile/WaspLang.hs b/waspc/src/Wasp/Project/WaspFile/WaspLang.hs new file mode 100644 index 0000000000..065596d37a --- /dev/null +++ b/waspc/src/Wasp/Project/WaspFile/WaspLang.hs @@ -0,0 +1,35 @@ +module Wasp.Project.WaspFile.WaspLang + ( analyzeWaspLangFile, + analyzeWaspFileContent, + ) +where + +import Control.Arrow (left) +import StrongPath + ( Abs, + File, + Path', + ) +import qualified Wasp.Analyzer as Analyzer +import Wasp.Analyzer.Parser.Ctx (Ctx) +import qualified Wasp.AppSpec as AS +import Wasp.AppSpec.Core.Decl.JSON () +import Wasp.Error (showCompilerErrorForTerminal) +import Wasp.Project.Common + ( CompileError, + WaspLangFile, + ) +import qualified Wasp.Psl.Ast.Schema as Psl.Schema +import qualified Wasp.Util.IO as IOUtil + +analyzeWaspLangFile :: Psl.Schema.Schema -> Path' Abs (File WaspLangFile) -> IO (Either [CompileError] [AS.Decl]) +analyzeWaspLangFile prismaSchemaAst waspFilePath = do + waspFileContent <- IOUtil.readFile waspFilePath + left (map $ showCompilerErrorForTerminal (waspFilePath, waspFileContent)) + <$> analyzeWaspFileContent prismaSchemaAst waspFileContent + +analyzeWaspFileContent :: Psl.Schema.Schema -> String -> IO (Either [(String, Ctx)] [AS.Decl]) +analyzeWaspFileContent prismaSchemaAst = + return + . left (map Analyzer.getErrorMessageAndCtx) + . Analyzer.analyze prismaSchemaAst diff --git a/waspc/waspc.cabal b/waspc/waspc.cabal index 1b3c423eca..f428c957a8 100644 --- a/waspc/waspc.cabal +++ b/waspc/waspc.cabal @@ -378,6 +378,8 @@ library Wasp.Project.Studio Wasp.Project.Vite Wasp.Project.WaspFile + Wasp.Project.WaspFile.TypeScript + Wasp.Project.WaspFile.WaspLang Wasp.Psl.Ast.Argument Wasp.Psl.Ast.Attribute Wasp.Psl.Ast.Common From 9a9e3d8dd6f336b26d0ad22fd75f832af2628900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Sodi=C4=87?= Date: Thu, 2 Jan 2025 14:24:08 +0100 Subject: [PATCH 7/7] Remove redundant part of the implementation comment --- waspc/src/Wasp/Analyzer.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/waspc/src/Wasp/Analyzer.hs b/waspc/src/Wasp/Analyzer.hs index 77441dedf9..2d32232ede 100644 --- a/waspc/src/Wasp/Analyzer.hs +++ b/waspc/src/Wasp/Analyzer.hs @@ -171,9 +171,6 @@ getEntityDecls schema = -- 1. Creating an AST with (and only with) the declarations for the Prisma -- schema Entities. -- 2. Type-checking that AST and returning the result. - -- This gives us a list of entity declarations we can then forward to - -- TypeScript (which then validates the user config only uses existing - -- entities). wrapAnalyzerError TypeError (typeCheck stdTypes astWithEntitiesOnly) >>= (wrapAnalyzerError EvaluationError . evaluate stdTypes) where