diff --git a/waspc/data/Generator/templates/react-app/src/router.js b/waspc/data/Generator/templates/react-app/src/router.js index 53dd29738..896e3031a 100644 --- a/waspc/data/Generator/templates/react-app/src/router.js +++ b/waspc/data/Generator/templates/react-app/src/router.js @@ -7,7 +7,7 @@ import createAuthRequiredPage from "./auth/pages/createAuthRequiredPage.js" {=/ isAuthEnabled =} {=# pagesToImport =} -import {= importWhat =} from "{= importFrom =}" +{=& importStatement =} {=/ pagesToImport =} {=# isExternalAuthEnabled =} diff --git a/waspc/data/Generator/templates/server/src/routes/operations/_action.js b/waspc/data/Generator/templates/server/src/routes/operations/_action.js index e1fad13a3..299b07230 100644 --- a/waspc/data/Generator/templates/server/src/routes/operations/_action.js +++ b/waspc/data/Generator/templates/server/src/routes/operations/_action.js @@ -1,8 +1,7 @@ {{={= =}=}} import { handleRejection } from '../../utils.js' -import {= operationName =} from "{= operationImportPath =}" - +{=& operationImportStmt =} export default handleRejection(async (req, res) => { const args = req.body || {} diff --git a/waspc/data/Generator/templates/server/src/routes/operations/_query.js b/waspc/data/Generator/templates/server/src/routes/operations/_query.js index 85352b683..26b56c2d3 100644 --- a/waspc/data/Generator/templates/server/src/routes/operations/_query.js +++ b/waspc/data/Generator/templates/server/src/routes/operations/_query.js @@ -1,7 +1,7 @@ {{={= =}=}} import { handleRejection } from '../../utils.js' -import {= operationName =} from "{= operationImportPath =}" +{=& operationImportStmt =} export default handleRejection(async (req, res) => { {=! TODO: When generating express route for query, generated code would be most human-like if we diff --git a/waspc/data/Generator/templates/server/src/routes/operations/index.js b/waspc/data/Generator/templates/server/src/routes/operations/index.js index e32048b57..747e43af8 100644 --- a/waspc/data/Generator/templates/server/src/routes/operations/index.js +++ b/waspc/data/Generator/templates/server/src/routes/operations/index.js @@ -6,7 +6,7 @@ import auth from '../../core/auth.js' {=/ isAuthEnabled =} {=# operationRoutes =} -import {= importIdentifier =} from '{= importPath =}' +{=& importStatement =} {=/ operationRoutes =} const router = express.Router() diff --git a/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/.waspchecksums b/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/.waspchecksums index f86bf50e3..f0d865717 100644 --- a/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/.waspchecksums +++ b/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/.waspchecksums @@ -403,7 +403,7 @@ "file", "web-app/src/router.js" ], - "65a91308a13f2c8444e3ad7372c1fca85a194b85e8f8f7d11613f78fcfe7af6f" + "62928b69543a870338ab09c2f7493ec7594993bc4f2922052da3c3a9d804e0cd" ], [ [ diff --git a/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/web-app/src/router.js b/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/web-app/src/router.js index 7d3f45f13..695fa47e8 100644 --- a/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/web-app/src/router.js +++ b/waspc/e2e-test/test-outputs/waspBuild-golden/waspBuild/.wasp/build/web-app/src/router.js @@ -2,7 +2,7 @@ import React from 'react' import { Route, BrowserRouter as Router } from 'react-router-dom' -import MainPage from "./ext-src/MainPage" +import MainPage from './ext-src/MainPage' const router = ( diff --git a/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/.waspchecksums b/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/.waspchecksums index 121897152..096607d15 100644 --- a/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/.waspchecksums +++ b/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/.waspchecksums @@ -403,7 +403,7 @@ "file", "web-app/src/router.js" ], - "65a91308a13f2c8444e3ad7372c1fca85a194b85e8f8f7d11613f78fcfe7af6f" + "62928b69543a870338ab09c2f7493ec7594993bc4f2922052da3c3a9d804e0cd" ], [ [ diff --git a/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/web-app/src/router.js b/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/web-app/src/router.js index 7d3f45f13..695fa47e8 100644 --- a/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/web-app/src/router.js +++ b/waspc/e2e-test/test-outputs/waspCompile-golden/waspCompile/.wasp/out/web-app/src/router.js @@ -2,7 +2,7 @@ import React from 'react' import { Route, BrowserRouter as Router } from 'react-router-dom' -import MainPage from "./ext-src/MainPage" +import MainPage from './ext-src/MainPage' const router = ( diff --git a/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/.waspchecksums b/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/.waspchecksums index a1e39814f..723a48ba1 100644 --- a/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/.waspchecksums +++ b/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/.waspchecksums @@ -130,7 +130,7 @@ "file", "server/src/jobs/MySpecialJob.js" ], - "69926a4b7eafc2e80e50732fee80865625c06f74004cbcd7be1701b4ce9249eb" + "9bf6a5f7005d3ab4ca933fb239ef21f13ba68aef30d8767230d6cc03911ca0e1" ], [ [ @@ -417,7 +417,7 @@ "file", "web-app/src/router.js" ], - "65a91308a13f2c8444e3ad7372c1fca85a194b85e8f8f7d11613f78fcfe7af6f" + "62928b69543a870338ab09c2f7493ec7594993bc4f2922052da3c3a9d804e0cd" ], [ [ diff --git a/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/server/src/jobs/MySpecialJob.js b/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/server/src/jobs/MySpecialJob.js index d9fddc6a3..a0f0eab4c 100644 --- a/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/server/src/jobs/MySpecialJob.js +++ b/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/server/src/jobs/MySpecialJob.js @@ -1,6 +1,6 @@ import prisma from '../dbClient.js' import { createJob } from './core/pgBoss/pgBossJob.js' -import { foo } from './../ext-src/jobs/bar.js' +import { foo } from '../ext-src/jobs/bar.js' export const MySpecialJob = createJob({ jobName: "MySpecialJob", diff --git a/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/web-app/src/router.js b/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/web-app/src/router.js index 7d3f45f13..695fa47e8 100644 --- a/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/web-app/src/router.js +++ b/waspc/e2e-test/test-outputs/waspJob-golden/waspJob/.wasp/out/web-app/src/router.js @@ -2,7 +2,7 @@ import React from 'react' import { Route, BrowserRouter as Router } from 'react-router-dom' -import MainPage from "./ext-src/MainPage" +import MainPage from './ext-src/MainPage' const router = ( diff --git a/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/.waspchecksums b/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/.waspchecksums index 1b7dedc73..10577589d 100644 --- a/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/.waspchecksums +++ b/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/.waspchecksums @@ -403,7 +403,7 @@ "file", "web-app/src/router.js" ], - "65a91308a13f2c8444e3ad7372c1fca85a194b85e8f8f7d11613f78fcfe7af6f" + "62928b69543a870338ab09c2f7493ec7594993bc4f2922052da3c3a9d804e0cd" ], [ [ diff --git a/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/web-app/src/router.js b/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/web-app/src/router.js index 7d3f45f13..695fa47e8 100644 --- a/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/web-app/src/router.js +++ b/waspc/e2e-test/test-outputs/waspMigrate-golden/waspMigrate/.wasp/out/web-app/src/router.js @@ -2,7 +2,7 @@ import React from 'react' import { Route, BrowserRouter as Router } from 'react-router-dom' -import MainPage from "./ext-src/MainPage" +import MainPage from './ext-src/MainPage' const router = ( diff --git a/waspc/src/Wasp/Generator/Common.hs b/waspc/src/Wasp/Generator/Common.hs index 3a9d61be7..6ebac3139 100644 --- a/waspc/src/Wasp/Generator/Common.hs +++ b/waspc/src/Wasp/Generator/Common.hs @@ -9,6 +9,7 @@ module Wasp.Generator.Common npmVersionRange, prismaVersion, makeJsonWithEntityData, + GeneratedSrcDir, ) where @@ -20,6 +21,10 @@ import Wasp.Util (toLowerFirst) -- | Directory where the whole web app project (client, server, ...) is generated. data ProjectRootDir +-- | Type representing top-level src/ dir in an app component (e.g. in web app or in server). +-- Examples: web-app/src/, server/src/, ... . +class GeneratedSrcDir d + class AppComponentRootDir d data ServerRootDir diff --git a/waspc/src/Wasp/Generator/JsImport.hs b/waspc/src/Wasp/Generator/JsImport.hs index a4e1dfdaf..6547149c7 100644 --- a/waspc/src/Wasp/Generator/JsImport.hs +++ b/waspc/src/Wasp/Generator/JsImport.hs @@ -1,26 +1,34 @@ module Wasp.Generator.JsImport - ( getJsImportDetailsForExtFnImport, + ( extImportToJsImport, + PathFromImportLocationToSrcDir, ) where -import StrongPath (Dir, Path, Posix, Rel, ()) +import StrongPath (Dir, File', Path, Posix, Rel, ()) import qualified StrongPath as SP -import qualified Wasp.AppSpec.ExtImport as AS.ExtImport +import qualified Wasp.AppSpec.ExtImport as EI +import Wasp.Generator.Common (GeneratedSrcDir) import Wasp.Generator.ExternalCodeGenerator.Common (GeneratedExternalCodeDir) +import Wasp.JsImport + ( JsImport, + JsImportName (JsImportField, JsImportModule), + makeJsImport, + ) -getJsImportDetailsForExtFnImport :: - -- | Path to generated external code directory, relative to the directory in which file doing the importing is. - Path Posix (Rel a) (Dir GeneratedExternalCodeDir) -> - AS.ExtImport.ExtImport -> - -- | (importIdentifier, importStmt) - -- - importIdentifier -> Identifier via which you can access ext js function after you import it with importStmt. - -- - importStmt -> Javascript import statement via which you should do the import. - (String, String) -getJsImportDetailsForExtFnImport relPosixPathToExtCodeDir extImport = (importIdentifier, importStmt) +type PathFromImportLocationToSrcDir d = Path Posix (Rel ()) (Dir d) + +extImportToJsImport :: + GeneratedSrcDir d => + Path Posix (Rel d) (Dir GeneratedExternalCodeDir) -> + PathFromImportLocationToSrcDir d -> + EI.ExtImport -> + JsImport +extImportToJsImport pathFromSrcDirToExtCodeDir pathFromImportLocationToSrcDir extImport = makeJsImport importPath importName where - importStmt = "import " ++ importWhat ++ " from '" ++ importFrom ++ "'" - importFrom = "./" ++ SP.fromRelFileP (relPosixPathToExtCodeDir SP.castRel (AS.ExtImport.path extImport)) - (importIdentifier, importWhat) = - case AS.ExtImport.name extImport of - AS.ExtImport.ExtImportModule defaultImport -> (defaultImport, defaultImport) - AS.ExtImport.ExtImportField namedImport -> (namedImport, "{ " ++ namedImport ++ " }") + userDefinedPathInExtSrcDir = SP.castRel $ EI.path extImport :: Path Posix (Rel GeneratedExternalCodeDir) File' + importName = extImportNameToJsImportName $ EI.name extImport + importPath = SP.castRel $ pathFromImportLocationToSrcDir pathFromSrcDirToExtCodeDir userDefinedPathInExtSrcDir + + extImportNameToJsImportName :: EI.ExtImportName -> JsImportName + extImportNameToJsImportName (EI.ExtImportModule name) = JsImportModule name + extImportNameToJsImportName (EI.ExtImportField name) = JsImportField name diff --git a/waspc/src/Wasp/Generator/ServerGenerator.hs b/waspc/src/Wasp/Generator/ServerGenerator.hs index da0c076c7..06de93dec 100644 --- a/waspc/src/Wasp/Generator/ServerGenerator.hs +++ b/waspc/src/Wasp/Generator/ServerGenerator.hs @@ -22,8 +22,8 @@ import StrongPath Path', Posix, Rel, - relDirToPosix, reldir, + reldirP, relfile, (), ) @@ -45,17 +45,16 @@ import Wasp.Generator.Common prismaVersion, ) import Wasp.Generator.ExternalCodeGenerator (genExternalCodeDir) -import Wasp.Generator.ExternalCodeGenerator.Common (GeneratedExternalCodeDir) import Wasp.Generator.FileDraft (FileDraft, createCopyFileDraft) -import Wasp.Generator.JsImport (getJsImportDetailsForExtFnImport) import Wasp.Generator.Monad (Generator) import qualified Wasp.Generator.NpmDependencies as N import Wasp.Generator.ServerGenerator.AuthG (genAuth) import qualified Wasp.Generator.ServerGenerator.Common as C import Wasp.Generator.ServerGenerator.ConfigG (genConfigFile) import Wasp.Generator.ServerGenerator.ExternalAuthG (depsRequiredByPassport) -import Wasp.Generator.ServerGenerator.ExternalCodeGenerator (extServerCodeDirInServerSrcDir, extServerCodeGeneratorStrategy, extSharedCodeGeneratorStrategy) +import Wasp.Generator.ServerGenerator.ExternalCodeGenerator (extServerCodeGeneratorStrategy, extSharedCodeGeneratorStrategy) import Wasp.Generator.ServerGenerator.JobGenerator (depsRequiredByJobs, genJobExecutors, genJobs) +import Wasp.Generator.ServerGenerator.JsImport (getJsImportStmtAndIdentifier) import Wasp.Generator.ServerGenerator.OperationsG (genOperations) import Wasp.Generator.ServerGenerator.OperationsRoutesG (genOperationsRoutes) import Wasp.SemanticVersion (major) @@ -221,12 +220,12 @@ genServerJs spec = ) where maybeSetupJsFunction = AS.App.Server.setupFn =<< AS.App.server (snd $ getApp spec) - maybeSetupJsFnImportDetails = getJsImportDetailsForExtFnImport extServerCodeDirInServerSrcDirP <$> maybeSetupJsFunction - (maybeSetupJsFnImportIdentifier, maybeSetupJsFnImportStmt) = + maybeSetupJsFnImportDetails = getJsImportStmtAndIdentifier relPathToServerSrcDir <$> maybeSetupJsFunction + (maybeSetupJsFnImportStmt, maybeSetupJsFnImportIdentifier) = (fst <$> maybeSetupJsFnImportDetails, snd <$> maybeSetupJsFnImportDetails) -extServerCodeDirInServerSrcDirP :: Path Posix (Rel C.ServerSrcDir) (Dir GeneratedExternalCodeDir) -extServerCodeDirInServerSrcDirP = fromJust $ relDirToPosix extServerCodeDirInServerSrcDir + relPathToServerSrcDir :: Path Posix (Rel ()) (Dir C.ServerSrcDir) + relPathToServerSrcDir = [reldirP|./|] genRoutesDir :: AppSpec -> Generator [FileDraft] genRoutesDir spec = diff --git a/waspc/src/Wasp/Generator/ServerGenerator/Common.hs b/waspc/src/Wasp/Generator/ServerGenerator/Common.hs index c26fc116b..325b1bc03 100644 --- a/waspc/src/Wasp/Generator/ServerGenerator/Common.hs +++ b/waspc/src/Wasp/Generator/ServerGenerator/Common.hs @@ -23,7 +23,7 @@ import StrongPath (Dir, File', Path', Rel, reldir, relfile, ()) import qualified StrongPath as SP import System.FilePath (splitExtension) import Wasp.Common (WaspProjectDir) -import Wasp.Generator.Common (ProjectRootDir, ServerRootDir) +import Wasp.Generator.Common (GeneratedSrcDir, ProjectRootDir, ServerRootDir) import Wasp.Generator.FileDraft (FileDraft, createTemplateFileDraft) import Wasp.Generator.Templates (TemplatesDir) @@ -33,6 +33,8 @@ data ServerTemplatesDir data ServerTemplatesSrcDir +instance GeneratedSrcDir ServerSrcDir + asTmplFile :: Path' (Rel d) File' -> Path' (Rel ServerTemplatesDir) File' asTmplFile = SP.castRel diff --git a/waspc/src/Wasp/Generator/ServerGenerator/ExternalAuthG.hs b/waspc/src/Wasp/Generator/ServerGenerator/ExternalAuthG.hs index a07b0ae78..f2ea709fc 100644 --- a/waspc/src/Wasp/Generator/ServerGenerator/ExternalAuthG.hs +++ b/waspc/src/Wasp/Generator/ServerGenerator/ExternalAuthG.hs @@ -6,7 +6,7 @@ where import Data.Aeson (object, (.=)) import qualified Data.Aeson as Aeson -import Data.Maybe (fromJust, fromMaybe, isJust) +import Data.Maybe (fromMaybe, isJust) import StrongPath ( Dir, File', @@ -26,12 +26,10 @@ import qualified Wasp.AppSpec.App.Auth as AS.App.Auth import qualified Wasp.AppSpec.App.Auth as AS.Auth import qualified Wasp.AppSpec.App.Dependency as App.Dependency import Wasp.AppSpec.Valid (getApp) -import Wasp.Generator.ExternalCodeGenerator.Common (GeneratedExternalCodeDir) import Wasp.Generator.FileDraft (FileDraft) -import Wasp.Generator.JsImport (getJsImportDetailsForExtFnImport) import Wasp.Generator.Monad (Generator) import qualified Wasp.Generator.ServerGenerator.Common as C -import Wasp.Generator.ServerGenerator.ExternalCodeGenerator (extServerCodeDirInServerSrcDir) +import Wasp.Generator.ServerGenerator.JsImport (getJsImportStmtAndIdentifier) import Wasp.Generator.WebAppGenerator.ExternalAuthG (ExternalAuthInfo (..), gitHubAuthInfo, googleAuthInfo, templateFilePathInPassportDir) import Wasp.Util ((<++>)) @@ -135,16 +133,17 @@ getTmplDataForAuthMethodConfig auth authMethod = "getUserFieldsFnIdentifier" .= fromMaybe "" maybeOnSignInFnImportIdentifier ] where + getJsImportStmtAndIdentifier' = getJsImportStmtAndIdentifier relPathFromAuthConfigToServerSrcDir maybeConfigFn = AS.Auth.configFn =<< authMethod (AS.Auth.methods auth) - maybeConfigFnImportDetails = getJsImportDetailsForExtFnImport relPosixPathFromAuthMethodDirToExtSrcDir <$> maybeConfigFn - (maybeConfigFnImportIdentifier, maybeConfigFnImportStmt) = (fst <$> maybeConfigFnImportDetails, snd <$> maybeConfigFnImportDetails) + maybeConfigFnImportDetails = getJsImportStmtAndIdentifier' <$> maybeConfigFn + (maybeConfigFnImportStmt, maybeConfigFnImportIdentifier) = (fst <$> maybeConfigFnImportDetails, snd <$> maybeConfigFnImportDetails) maybeGetUserFieldsFn = AS.Auth.getUserFieldsFn =<< authMethod (AS.Auth.methods auth) - maybeOnSignInFnImportDetails = getJsImportDetailsForExtFnImport relPosixPathFromAuthMethodDirToExtSrcDir <$> maybeGetUserFieldsFn - (maybeOnSignInFnImportIdentifier, maybeOnSignInFnImportStmt) = (fst <$> maybeOnSignInFnImportDetails, snd <$> maybeOnSignInFnImportDetails) + maybeOnSignInFnImportDetails = getJsImportStmtAndIdentifier' <$> maybeGetUserFieldsFn + (maybeOnSignInFnImportStmt, maybeOnSignInFnImportIdentifier) = (fst <$> maybeOnSignInFnImportDetails, snd <$> maybeOnSignInFnImportDetails) - relPosixPathFromAuthMethodDirToExtSrcDir :: Path Posix (Rel (Dir C.ServerSrcDir)) (Dir GeneratedExternalCodeDir) - relPosixPathFromAuthMethodDirToExtSrcDir = [reldirP|../../../../|] fromJust (SP.relDirToPosix extServerCodeDirInServerSrcDir) + relPathFromAuthConfigToServerSrcDir :: Path Posix (Rel ()) (Dir C.ServerSrcDir) + relPathFromAuthConfigToServerSrcDir = [reldirP|../../../../|] depsRequiredByPassport :: AppSpec -> [App.Dependency.Dependency] depsRequiredByPassport spec = diff --git a/waspc/src/Wasp/Generator/ServerGenerator/JobGenerator.hs b/waspc/src/Wasp/Generator/ServerGenerator/JobGenerator.hs index e2362513e..9e8b3689a 100644 --- a/waspc/src/Wasp/Generator/ServerGenerator/JobGenerator.hs +++ b/waspc/src/Wasp/Generator/ServerGenerator/JobGenerator.hs @@ -33,17 +33,14 @@ import Wasp.AppSpec.Job (Job, JobExecutor (PgBoss, Simple), jobExecutors) import qualified Wasp.AppSpec.Job as J import Wasp.AppSpec.Util (isPgBossJobExecutorUsed) import Wasp.Generator.Common (ServerRootDir, makeJsonWithEntityData) -import Wasp.Generator.ExternalCodeGenerator.Common (GeneratedExternalCodeDir) import Wasp.Generator.FileDraft (FileDraft) -import Wasp.Generator.JsImport (getJsImportDetailsForExtFnImport) import Wasp.Generator.Monad (Generator) import Wasp.Generator.ServerGenerator.Common - ( ServerSrcDir, - ServerTemplatesDir, + ( ServerTemplatesDir, srcDirInServerTemplatesDir, ) import qualified Wasp.Generator.ServerGenerator.Common as C -import Wasp.Generator.ServerGenerator.ExternalCodeGenerator (extServerCodeDirInServerSrcDir) +import Wasp.Generator.ServerGenerator.JsImport (getJsImportStmtAndIdentifier) import qualified Wasp.SemanticVersion as SV genJobs :: AppSpec -> Generator [FileDraft] @@ -71,7 +68,7 @@ genJob (jobName, job) = where tmplFile = C.asTmplFile $ jobsDirInServerTemplatesDir SP. [relfile|_job.js|] dstFile = jobsDirInServerRootDir SP. fromJust (parseRelFile $ jobName ++ ".js") - (jobPerformFnName, jobPerformFnImportStatement) = getJsImportDetailsForExtFnImport relPosixPathFromJobFileToExtSrcDir $ (J.fn . J.perform) job + (jobPerformFnImportStatement, jobPerformFnName) = getJsImportStmtAndIdentifier relPathFromJobsDirToServerSrcDir $ (J.fn . J.perform) job maybeJobPerformOptions = J.performExecutorOptionsJson job jobScheduleTmplData s = object @@ -81,6 +78,9 @@ genJob (jobName, job) = ] maybeJobSchedule = jobScheduleTmplData <$> J.schedule job + relPathFromJobsDirToServerSrcDir :: Path Posix (Rel ()) (Dir C.ServerSrcDir) + relPathFromJobsDirToServerSrcDir = [reldirP|../|] + -- Creates a file that is imported on the server to ensure all job JS modules are loaded -- even if they are not referenced by user code. This ensures schedules are started, etc. genAllJobImports :: AppSpec -> FileDraft @@ -101,9 +101,6 @@ genAllJobImports spec = [ "name" .= jobName ] -relPosixPathFromJobFileToExtSrcDir :: Path Posix (Rel ServerSrcDir) (Dir GeneratedExternalCodeDir) -relPosixPathFromJobFileToExtSrcDir = [reldirP|../|] SP. fromJust (SP.relDirToPosix extServerCodeDirInServerSrcDir) - genJobExecutors :: Generator [FileDraft] genJobExecutors = return $ jobExecutorFds ++ jobExecutorHelperFds where diff --git a/waspc/src/Wasp/Generator/ServerGenerator/JsImport.hs b/waspc/src/Wasp/Generator/ServerGenerator/JsImport.hs new file mode 100644 index 000000000..c4ac165e5 --- /dev/null +++ b/waspc/src/Wasp/Generator/ServerGenerator/JsImport.hs @@ -0,0 +1,29 @@ +module Wasp.Generator.ServerGenerator.JsImport where + +import Data.Maybe (fromJust) +import qualified StrongPath as SP +import qualified Wasp.AppSpec.ExtImport as EI +import Wasp.Generator.JsImport (PathFromImportLocationToSrcDir) +import qualified Wasp.Generator.JsImport as GJI +import Wasp.Generator.ServerGenerator.Common (ServerSrcDir) +import Wasp.Generator.ServerGenerator.ExternalCodeGenerator (extServerCodeDirInServerSrcDir) +import Wasp.JsImport + ( JsImport, + JsImportIdentifier, + JsImportStatement, + ) +import qualified Wasp.JsImport as JI + +getJsImportStmtAndIdentifier :: + PathFromImportLocationToSrcDir ServerSrcDir -> + EI.ExtImport -> + (JsImportStatement, JsImportIdentifier) +getJsImportStmtAndIdentifier pathFromImportLocationToExtCodeDir = JI.getJsImportStmtAndIdentifier . extImportToJsImport pathFromImportLocationToExtCodeDir + +extImportToJsImport :: + PathFromImportLocationToSrcDir ServerSrcDir -> + EI.ExtImport -> + JsImport +extImportToJsImport = GJI.extImportToJsImport serverExtDir + where + serverExtDir = fromJust (SP.relDirToPosix extServerCodeDirInServerSrcDir) diff --git a/waspc/src/Wasp/Generator/ServerGenerator/OperationsG.hs b/waspc/src/Wasp/Generator/ServerGenerator/OperationsG.hs index 8aec44133..cc9a236ac 100644 --- a/waspc/src/Wasp/Generator/ServerGenerator/OperationsG.hs +++ b/waspc/src/Wasp/Generator/ServerGenerator/OperationsG.hs @@ -12,7 +12,7 @@ import Data.Aeson (object, (.=)) import qualified Data.Aeson as Aeson import Data.List (nub) import Data.Maybe (fromJust, fromMaybe) -import StrongPath (Dir, Dir', File', Path, Path', Posix, Rel, relDirToPosix, reldir, reldirP, relfile, ()) +import StrongPath (Dir, File', Path, Path', Posix, Rel, reldir, reldirP, relfile, ()) import qualified StrongPath as SP import Wasp.AppSpec (AppSpec) import qualified Wasp.AppSpec as AS @@ -22,12 +22,10 @@ import qualified Wasp.AppSpec.Operation as AS.Operation import qualified Wasp.AppSpec.Query as AS.Query import Wasp.AppSpec.Valid (isAuthEnabled) import Wasp.Generator.Common (ServerRootDir, makeJsonWithEntityData) -import Wasp.Generator.ExternalCodeGenerator.Common (GeneratedExternalCodeDir) import Wasp.Generator.FileDraft (FileDraft) -import Wasp.Generator.JsImport (getJsImportDetailsForExtFnImport) import Wasp.Generator.Monad (Generator) import qualified Wasp.Generator.ServerGenerator.Common as C -import Wasp.Generator.ServerGenerator.ExternalCodeGenerator (extServerCodeDirInServerSrcDir) +import Wasp.Generator.ServerGenerator.JsImport (getJsImportStmtAndIdentifier) import Wasp.Util (toUpperFirst, (<++>)) genOperations :: AppSpec -> Generator [FileDraft] @@ -122,10 +120,6 @@ operationFileInSrcDir :: AS.Operation.Operation -> Path' (Rel C.ServerSrcDir) Fi operationFileInSrcDir (AS.Operation.QueryOp name _) = queryFileInSrcDir name operationFileInSrcDir (AS.Operation.ActionOp name _) = actionFileInSrcDir name -relPosixPathFromOperationFileToExtSrcDir :: Path Posix (Rel Dir') (Dir GeneratedExternalCodeDir) -relPosixPathFromOperationFileToExtSrcDir = - [reldirP|../|] fromJust (relDirToPosix extServerCodeDirInServerSrcDir) - operationTmplData :: AS.Operation.Operation -> Aeson.Value operationTmplData operation = object @@ -138,6 +132,7 @@ operationTmplData operation = (AS.Operation.getEntities operation) ] where - (importIdentifier, importStmt) = - getJsImportDetailsForExtFnImport relPosixPathFromOperationFileToExtSrcDir $ - AS.Operation.getFn operation + (importStmt, importIdentifier) = getJsImportStmtAndIdentifier relPathFromOperationsDirToServerSrcDir (AS.Operation.getFn operation) + + relPathFromOperationsDirToServerSrcDir :: Path Posix (Rel ()) (Dir C.ServerSrcDir) + relPathFromOperationsDirToServerSrcDir = [reldirP|../|] diff --git a/waspc/src/Wasp/Generator/ServerGenerator/OperationsRoutesG.hs b/waspc/src/Wasp/Generator/ServerGenerator/OperationsRoutesG.hs index 41cf43efe..9c333c282 100644 --- a/waspc/src/Wasp/Generator/ServerGenerator/OperationsRoutesG.hs +++ b/waspc/src/Wasp/Generator/ServerGenerator/OperationsRoutesG.hs @@ -24,6 +24,7 @@ import Wasp.Generator.FileDraft (FileDraft) import Wasp.Generator.Monad (Generator, GeneratorError (GenericGeneratorError), logAndThrowGeneratorError) import qualified Wasp.Generator.ServerGenerator.Common as C import Wasp.Generator.ServerGenerator.OperationsG (operationFileInSrcDir) +import Wasp.JsImport (JsImportName (..), getJsImportStmtAndIdentifier, makeJsImport) import qualified Wasp.Util as U genOperationsRoutes :: AppSpec -> Generator [FileDraft] @@ -53,8 +54,8 @@ genOperationRoute spec operation tmplFile = return $ C.mkTmplFdWithDstAndData tm baseTmplData = object - [ "operationImportPath" .= (operationImportPath :: FilePath), - "operationName" .= (AS.Operation.getName operation :: String) + [ "operationName" .= (operationImportIdentifier :: String), + "operationImportStmt" .= (operationImportStmt :: String) ] tmplData = case AS.App.auth (snd $ getApp spec) of @@ -65,11 +66,19 @@ genOperationRoute spec operation tmplFile = return $ C.mkTmplFdWithDstAndData tm (Aeson.toJSON (U.toLowerFirst $ AS.refName $ AS.Auth.userEntity auth)) baseTmplData + pathToOperationFile = + relPosixPathFromOperationsRoutesDirToSrcDir + fromJust (SP.relFileToPosix $ operationFileInSrcDir operation) + operationImportPath = - C.toESModulesImportPath $ - SP.fromRelFileP $ - relPosixPathFromOperationsRoutesDirToSrcDir - fromJust (SP.relFileToPosix $ operationFileInSrcDir operation) + fromJust $ + SP.parseRelFileP $ + C.toESModulesImportPath $ + SP.fromRelFileP pathToOperationFile + + operationName = AS.Operation.getName operation + + (operationImportStmt, operationImportIdentifier) = getJsImportStmtAndIdentifier $ makeJsImport operationImportPath (JsImportModule operationName) data OperationsRoutesDir @@ -103,14 +112,11 @@ genOperationsRouter spec ] makeOperationRoute operation = let operationName = AS.Operation.getName operation + importPath = fromJust $ SP.relFileToPosix $ SP.castRel $ operationRouteFileInOperationsRoutesDir operation + (importStmt, importIdentifier) = getJsImportStmtAndIdentifier $ makeJsImport importPath (JsImportModule operationName) in object - [ "importIdentifier" .= operationName, - "importPath" - .= ( "./" - ++ SP.fromRelFileP - ( fromJust $ SP.relFileToPosix $ operationRouteFileInOperationsRoutesDir operation - ) - ), + [ "importIdentifier" .= importIdentifier, + "importStatement" .= importStmt, "routePath" .= ("/" ++ operationRouteInOperationsRouter operation), "isUsingAuth" .= isAuthEnabledForOperation operation ] diff --git a/waspc/src/Wasp/Generator/WebAppGenerator.hs b/waspc/src/Wasp/Generator/WebAppGenerator.hs index 57c1bfded..94f9bb646 100644 --- a/waspc/src/Wasp/Generator/WebAppGenerator.hs +++ b/waspc/src/Wasp/Generator/WebAppGenerator.hs @@ -8,7 +8,7 @@ where import Data.Aeson (object, (.=)) import Data.List (intercalate) -import Data.Maybe (fromJust, fromMaybe, isJust) +import Data.Maybe (fromMaybe, isJust) import StrongPath ( Dir, File', @@ -16,8 +16,8 @@ import StrongPath Path', Posix, Rel, - relDirToPosix, reldir, + reldirP, relfile, (), ) @@ -37,19 +37,17 @@ import Wasp.Generator.Common ) import qualified Wasp.Generator.ConfigFile as G.CF import Wasp.Generator.ExternalCodeGenerator (genExternalCodeDir) -import Wasp.Generator.ExternalCodeGenerator.Common (GeneratedExternalCodeDir) import Wasp.Generator.FileDraft -import Wasp.Generator.JsImport (getJsImportDetailsForExtFnImport) import Wasp.Generator.Monad (Generator) import qualified Wasp.Generator.NpmDependencies as N import Wasp.Generator.WebAppGenerator.AuthG (genAuth) import qualified Wasp.Generator.WebAppGenerator.Common as C import Wasp.Generator.WebAppGenerator.ExternalAuthG (ExternalAuthInfo (..), gitHubAuthInfo, googleAuthInfo) import Wasp.Generator.WebAppGenerator.ExternalCodeGenerator - ( extClientCodeDirInWebAppSrcDir, - extClientCodeGeneratorStrategy, + ( extClientCodeGeneratorStrategy, extSharedCodeGeneratorStrategy, ) +import Wasp.Generator.WebAppGenerator.JsImport (getJsImportStmtAndIdentifier) import Wasp.Generator.WebAppGenerator.OperationsGenerator (genOperations) import Wasp.Generator.WebAppGenerator.RouterGenerator (genRouter) import Wasp.Util ((<++>)) @@ -257,9 +255,9 @@ genIndexJs spec = ) where maybeSetupJsFunction = AS.App.Client.setupFn =<< AS.App.client (snd $ getApp spec) - maybeSetupJsFnImportDetails = getJsImportDetailsForExtFnImport extClientCodeDirInWebAppSrcDirP <$> maybeSetupJsFunction - (maybeSetupJsFnImportIdentifier, maybeSetupJsFnImportStmt) = + maybeSetupJsFnImportDetails = getJsImportStmtAndIdentifier relPathToWebAppSrcDir <$> maybeSetupJsFunction + (maybeSetupJsFnImportStmt, maybeSetupJsFnImportIdentifier) = (fst <$> maybeSetupJsFnImportDetails, snd <$> maybeSetupJsFnImportDetails) -extClientCodeDirInWebAppSrcDirP :: Path Posix (Rel C.WebAppSrcDir) (Dir GeneratedExternalCodeDir) -extClientCodeDirInWebAppSrcDirP = fromJust $ relDirToPosix extClientCodeDirInWebAppSrcDir + relPathToWebAppSrcDir :: Path Posix (Rel ()) (Dir C.WebAppSrcDir) + relPathToWebAppSrcDir = [reldirP|./|] diff --git a/waspc/src/Wasp/Generator/WebAppGenerator/Common.hs b/waspc/src/Wasp/Generator/WebAppGenerator/Common.hs index 0c059bda4..1aaaf90b6 100644 --- a/waspc/src/Wasp/Generator/WebAppGenerator/Common.hs +++ b/waspc/src/Wasp/Generator/WebAppGenerator/Common.hs @@ -23,7 +23,7 @@ import qualified Data.Aeson as Aeson import StrongPath (Dir, File', Path', Rel, reldir, relfile, ()) import qualified StrongPath as SP import Wasp.Common (WaspProjectDir) -import Wasp.Generator.Common (ProjectRootDir, WebAppRootDir) +import Wasp.Generator.Common (GeneratedSrcDir, ProjectRootDir, WebAppRootDir) import Wasp.Generator.FileDraft (FileDraft, createTemplateFileDraft) import Wasp.Generator.Templates (TemplatesDir) @@ -33,6 +33,8 @@ data WebAppTemplatesDir data WebAppTemplatesSrcDir +instance GeneratedSrcDir WebAppSrcDir + asTmplFile :: Path' (Rel d) File' -> Path' (Rel WebAppTemplatesDir) File' asTmplFile = SP.castRel diff --git a/waspc/src/Wasp/Generator/WebAppGenerator/JsImport.hs b/waspc/src/Wasp/Generator/WebAppGenerator/JsImport.hs new file mode 100644 index 000000000..ca23ead7b --- /dev/null +++ b/waspc/src/Wasp/Generator/WebAppGenerator/JsImport.hs @@ -0,0 +1,29 @@ +module Wasp.Generator.WebAppGenerator.JsImport where + +import Data.Maybe (fromJust) +import qualified StrongPath as SP +import qualified Wasp.AppSpec.ExtImport as EI +import Wasp.Generator.JsImport (PathFromImportLocationToSrcDir) +import qualified Wasp.Generator.JsImport as GJI +import Wasp.Generator.WebAppGenerator.Common (WebAppSrcDir) +import Wasp.Generator.WebAppGenerator.ExternalCodeGenerator (extClientCodeDirInWebAppSrcDir) +import Wasp.JsImport + ( JsImport, + JsImportIdentifier, + JsImportStatement, + ) +import qualified Wasp.JsImport as JI + +getJsImportStmtAndIdentifier :: + PathFromImportLocationToSrcDir WebAppSrcDir -> + EI.ExtImport -> + (JsImportStatement, JsImportIdentifier) +getJsImportStmtAndIdentifier pathFromImportLocationToSrcDir = JI.getJsImportStmtAndIdentifier . extImportToJsImport pathFromImportLocationToSrcDir + +extImportToJsImport :: + PathFromImportLocationToSrcDir WebAppSrcDir -> + EI.ExtImport -> + JsImport +extImportToJsImport = GJI.extImportToJsImport webAppExtDir + where + webAppExtDir = fromJust (SP.relDirToPosix extClientCodeDirInWebAppSrcDir) diff --git a/waspc/src/Wasp/Generator/WebAppGenerator/RouterGenerator.hs b/waspc/src/Wasp/Generator/WebAppGenerator/RouterGenerator.hs index 2eb776d5b..8bbc6c729 100644 --- a/waspc/src/Wasp/Generator/WebAppGenerator/RouterGenerator.hs +++ b/waspc/src/Wasp/Generator/WebAppGenerator/RouterGenerator.hs @@ -8,9 +8,8 @@ where import Data.Aeson (ToJSON (..), object, (.=)) import Data.List (find) import Data.Maybe (fromMaybe) -import StrongPath (reldir, relfile, ()) -import qualified StrongPath as SP -import qualified System.FilePath as FP +import StrongPath (Dir, Path, Rel, reldir, reldirP, relfile, ()) +import StrongPath.Types (Posix) import Wasp.AppSpec (AppSpec) import qualified Wasp.AppSpec as AS import qualified Wasp.AppSpec.App as AS.App @@ -24,7 +23,8 @@ import Wasp.Generator.Monad (Generator) import Wasp.Generator.WebAppGenerator.Common (asTmplFile, asWebAppSrcFile) import qualified Wasp.Generator.WebAppGenerator.Common as C import Wasp.Generator.WebAppGenerator.ExternalAuthG (ExternalAuthInfo (..), frontendLoginUrl, gitHubAuthInfo, googleAuthInfo, serverOauthRedirectHandlerUrl) -import Wasp.Generator.WebAppGenerator.ExternalCodeGenerator (extClientCodeDirInWebAppSrcDir) +import Wasp.Generator.WebAppGenerator.JsImport (extImportToJsImport) +import Wasp.JsImport (applyJsImportAlias, getJsImportStmtAndIdentifier) data RouterTemplateData = RouterTemplateData { _routes :: ![RouteTemplateData], @@ -57,16 +57,14 @@ instance ToJSON RouteTemplateData where ] data PageTemplateData = PageTemplateData - { _importWhat :: !String, - _importFrom :: !String + { _importStmt :: !String } deriving (Show, Eq) instance ToJSON PageTemplateData where toJSON pageTD = object - [ "importWhat" .= _importWhat pageTD, - "importFrom" .= _importFrom pageTD + [ "importStatement" .= _importStmt pageTD ] data ExternalAuthProviderTemplateData = ExternalAuthProviderTemplateData @@ -163,21 +161,17 @@ determineRouteTargetComponent spec (_, route) = createPageTemplateData :: (String, AS.Page.Page) -> PageTemplateData createPageTemplateData page = PageTemplateData - { _importFrom = relPathToExtSrcDir FP. SP.fromRelFileP (AS.ExtImport.path pageComponent), - _importWhat = case AS.ExtImport.name pageComponent of - AS.ExtImport.ExtImportModule _ -> pageName - AS.ExtImport.ExtImportField identifier -> "{ " ++ mkNamedImportExpr identifier pageName ++ " }" + { _importStmt = importStmt } where - relPathToExtSrcDir = "./" FP. SP.toFilePath extClientCodeDirInWebAppSrcDir + importStmt :: String + (importStmt, _) = getJsImportStmtAndIdentifier $ applyJsImportAlias (Just importAlias) $ extImportToJsImport relPathToWebAppSrcDir pageComponent - pageName :: String - pageName = fst page + relPathToWebAppSrcDir :: Path Posix (Rel ()) (Dir C.WebAppSrcDir) + relPathToWebAppSrcDir = [reldirP|./|] pageComponent :: AS.ExtImport.ExtImport pageComponent = AS.Page.component $ snd page -mkNamedImportExpr :: String -> String -> String -mkNamedImportExpr identifier alias - | identifier == alias = identifier - | otherwise = identifier ++ " as " ++ alias + importAlias :: String + importAlias = fst page diff --git a/waspc/src/Wasp/JsImport.hs b/waspc/src/Wasp/JsImport.hs new file mode 100644 index 000000000..39a0db10f --- /dev/null +++ b/waspc/src/Wasp/JsImport.hs @@ -0,0 +1,90 @@ +{-# LANGUAGE DeriveDataTypeable #-} + +module Wasp.JsImport + ( JsImport (..), + JsImportName (..), + JsImportAlias, + JsImportPath, + JsImportIdentifier, + JsImportStatement, + makeJsImport, + applyJsImportAlias, + getJsImportStmtAndIdentifier, + ) +where + +import Data.Data (Data) +import Data.List (isPrefixOf) +import StrongPath (Dir', File', Path, Posix, Rel) +import qualified StrongPath as SP + +-- | Represents a JS import data type that can be used to generate import statements +-- in generated code. It doesn't fully support all types of JS imports (multiple imports) +-- but this is enough for our current use case. +data JsImport = JsImport + { -- | Path from which we are importing. + _path :: JsImportPath, + -- | What is being imported. NOTE: We don't currenly support multiple names in one statement, + -- that's why it's "name" and not "names". + _name :: JsImportName, + -- | Alias for the imported name. + _importAlias :: Maybe JsImportAlias + } + deriving (Show, Eq, Data) + +type JsImportPath = Path Posix (Rel Dir') File' + +type JsImportAlias = String + +data JsImportName + = -- | Represents external imports like @import Identifier from "file.js"@ + JsImportModule JsImportIdentifier + | -- | Represents external imports like @import { Identifier } from "file.js"@ + JsImportField JsImportIdentifier + deriving (Show, Eq, Data) + +type JsImportIdentifier = String + +-- | Represents the left side of the import statement, between @import@ and @from@, +-- e.g. @{ Name }@ or @{ Name as Alias }@ or @NameForDefault@ . +type JsImportClause = String + +-- | Represents the full import statement e.g. @import { Name } from "file.js"@ +type JsImportStatement = String + +makeJsImport :: JsImportPath -> JsImportName -> JsImport +makeJsImport importPath importName = JsImport importPath importName Nothing + +applyJsImportAlias :: Maybe JsImportAlias -> JsImport -> JsImport +applyJsImportAlias importAlias jsImport = jsImport {_importAlias = importAlias} + +getJsImportStmtAndIdentifier :: JsImport -> (JsImportStatement, JsImportIdentifier) +getJsImportStmtAndIdentifier (JsImport importPath importName maybeImportAlias) = + (importStatement, importIdentifier) + where + (importIdentifier, importClause) = jsImportIdentifierAndClause + + importStatement :: JsImportStatement + importStatement = "import " ++ importClause ++ " from '" ++ normalizedPath ++ "'" + where + filePath = SP.fromRelFileP importPath + normalizedPath = if ".." `isPrefixOf` filePath then filePath else "./" ++ filePath + + -- First part of import statement based on type of import and alias + -- e.g. for import { Name as Alias } from "file.js" it returns ("Alias", "{ Name as Alias }") + -- e.g. for import Name from "file.js" it returns ("Name", "Name") + jsImportIdentifierAndClause :: (JsImportIdentifier, JsImportClause) + jsImportIdentifierAndClause = case importName of + JsImportModule defaultImport -> getForDefault defaultImport maybeImportAlias + JsImportField namedImport -> getForNamed namedImport maybeImportAlias + where + getForDefault :: JsImportIdentifier -> Maybe JsImportAlias -> (JsImportIdentifier, JsImportClause) + getForDefault identifier Nothing = (identifier, identifier) + getForDefault _ (Just importAlias) = (importAlias, importAlias) + + getForNamed :: JsImportIdentifier -> Maybe JsImportAlias -> (JsImportIdentifier, JsImportClause) + getForNamed identifier Nothing = (identifier, "{ " ++ identifier ++ " }") + getForNamed identifier (Just importAlias) = (importAlias, "{ " ++ resolvedIdentifier ++ " }") + where + resolvedIdentifier = + if identifier == importAlias then identifier else identifier ++ " as " ++ importAlias diff --git a/waspc/test/Generator/JsImportTest.hs b/waspc/test/Generator/JsImportTest.hs new file mode 100644 index 000000000..a402024f7 --- /dev/null +++ b/waspc/test/Generator/JsImportTest.hs @@ -0,0 +1,28 @@ +module Generator.JsImportTest where + +import StrongPath (Dir, Path, Posix, Rel) +import qualified StrongPath as SP +import Test.Tasty.Hspec +import Wasp.AppSpec.ExtImport +import Wasp.Generator.ExternalCodeGenerator.Common (GeneratedExternalCodeDir) +import Wasp.Generator.JsImport +import Wasp.Generator.ServerGenerator.Common (ServerSrcDir) +import Wasp.JsImport as JI + +spec_GeneratorJsImportTest :: Spec +spec_GeneratorJsImportTest = do + describe "extImportToJsImport" $ do + let pathToExtCodeDir = [SP.reldirP|ext-src|] :: (Path Posix (Rel ServerSrcDir) (Dir GeneratedExternalCodeDir)) + pathFromImportLocationToExtCodeDir = [SP.reldirP|../|] + extImport = + ExtImport + { name = ExtImportModule "test", + path = [SP.relfileP|folder/test.js|] + } + it "makes a JsImport from ExtImport" $ do + extImportToJsImport pathToExtCodeDir pathFromImportLocationToExtCodeDir extImport + `shouldBe` JI.JsImport + { JI._path = [SP.relfileP|../ext-src/folder/test.js|], + JI._name = JsImportModule "test", + JI._importAlias = Nothing + } diff --git a/waspc/test/JsImportTest.hs b/waspc/test/JsImportTest.hs new file mode 100644 index 000000000..e61086105 --- /dev/null +++ b/waspc/test/JsImportTest.hs @@ -0,0 +1,51 @@ +module JsImportTest where + +import StrongPath (Dir', File', Path, Posix, Rel, ()) +import qualified StrongPath as SP +import Test.Tasty.Hspec (Spec, describe, it, shouldBe) +import Wasp.JsImport + +spec_JsImportTest :: Spec +spec_JsImportTest = do + describe "makeJsImport" $ do + it "makes JsImport with default import from a path" $ do + makeJsImport testJsFileImportPath (JsImportModule "test") + `shouldBe` JsImport + { _path = testJsFileImportPath, + _name = JsImportModule "test", + _importAlias = Nothing + } + describe "applyJsImportAlias" $ do + it "applies alias to JsImport" $ do + let jsImport = makeJsImport testJsFileImportPath (JsImportModule "test") + applyJsImportAlias (Just "alias") jsImport + `shouldBe` jsImport {_importAlias = Just "alias"} + describe "getJsImportStmtAndIdentifier" $ do + describe "generates import statement and identifier from" $ do + it "default import" $ do + getJsImportStmtAndIdentifier + (makeJsImport testJsFileImportPath (JsImportModule "test")) + `shouldBe` ("import test from '" ++ generatedImportPathForTestJsFile ++ "'", "test") + it "default import with alias" $ do + getJsImportStmtAndIdentifier + ( applyJsImportAlias + (Just "alias") + (makeJsImport testJsFileImportPath (JsImportModule "test")) + ) + `shouldBe` ("import alias from '" ++ generatedImportPathForTestJsFile ++ "'", "alias") + it "named import" $ do + getJsImportStmtAndIdentifier + (makeJsImport testJsFileImportPath (JsImportField "test")) + `shouldBe` ("import { test } from '" ++ generatedImportPathForTestJsFile ++ "'", "test") + it "named import with alias" $ do + getJsImportStmtAndIdentifier + ( applyJsImportAlias + (Just "alias") + (makeJsImport testJsFileImportPath (JsImportField "test")) + ) + `shouldBe` ("import { test as alias } from '" ++ generatedImportPathForTestJsFile ++ "'", "alias") + where + testJsFileImportPath :: Path Posix (Rel Dir') File' + testJsFileImportPath = [SP.reldirP|ext-src|] [SP.relfileP|folder/test.js|] + + generatedImportPathForTestJsFile = "./ext-src/folder/test.js" diff --git a/waspc/waspc.cabal b/waspc/waspc.cabal index e9cf958c9..a3d34bd76 100644 --- a/waspc/waspc.cabal +++ b/waspc/waspc.cabal @@ -207,6 +207,7 @@ library Wasp.Data Wasp.Error Wasp.ExternalCode + Wasp.JsImport Wasp.Generator Wasp.Generator.Common Wasp.Generator.ConfigFile @@ -234,6 +235,7 @@ library Wasp.Generator.JsImport Wasp.Generator.Monad Wasp.Generator.ServerGenerator + Wasp.Generator.ServerGenerator.JsImport Wasp.Generator.ServerGenerator.AuthG Wasp.Generator.ServerGenerator.Common Wasp.Generator.ServerGenerator.ConfigG @@ -248,6 +250,7 @@ library Wasp.Generator.Start Wasp.Generator.Templates Wasp.Generator.WebAppGenerator + Wasp.Generator.WebAppGenerator.JsImport Wasp.Generator.WebAppGenerator.AuthG Wasp.Generator.WebAppGenerator.Common Wasp.Generator.WebAppGenerator.ExternalAuthG @@ -424,6 +427,7 @@ test-suite waspc-test Generator.MockWriteableMonad Generator.WebAppGeneratorTest Generator.WriteFileDraftsTest + Generator.JsImportTest Psl.Common.ModelTest Psl.Generator.ModelTest Psl.Parser.ModelTest @@ -436,6 +440,7 @@ test-suite waspc-test WaspignoreFileTest Paths_waspc Generator.NpmDependenciesTest + JsImportTest test-suite cli-test import: common-all, common-exe