-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validates tailwindcss
if Tailwind is used
#2465
base: main
Are you sure you want to change the base?
Conversation
@@ -149,10 +148,6 @@ resolveRef spec ref = | |||
$ find ((== refName ref) . fst) $ | |||
getDecls spec | |||
|
|||
doesConfigFileExist :: AppSpec -> Path' (Rel WaspProjectDir) File' -> Bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I needed the information if Tailwind is used (which is computed using doesConfigFileExist
) before we have the AppSpec so I pulled it out of here and rewritten it so it doesn't need the AppSpec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is it that you needed it before?
Are we getting into a situtation where we need a lot of info from AppSpec before AppSpec exists, pointing at some potential design issue, or do you think this is ok?
|
||
-- | Establishes the mapping of what config files to copy and where from/to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ormolu
doesConfigFileExist tailwindConfigFile | ||
&& doesConfigFileExist postcssConfigFile | ||
where | ||
doesConfigFileExist :: Path' (Rel WaspProjectDir) File' -> Bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only used for isTailwindUsed
so I inlined it even though it might be useful in the future - let's pull it out when it becomes necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you know it is a general utility, I would pull it out immediately, since then it is easier for somebody else to see it there and use it. If it was more tied down to this specific place then mabye not, but it seems quite ready to isolate right now, and I can easily imagine somebody else will want to check if certain congfi file exists, so yeah, let's go for it right now.
validatePackageJson :: P.PackageJson -> [ErrorMsg] | ||
validatePackageJson packageJson = | ||
validatePackageJson :: Bool -> P.PackageJson -> [ErrorMsg] | ||
validatePackageJson isTailwindUsed packageJson = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to thread through the isTailwindUsed
info unfortunately. Some sort of Reader would be useful here, but I didn't want to over-engineer it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get what you mean, and I agree it would be much going for Reader now.
That said, having just a Bool like this is not very nice, what if we add one or two more conditionals like this, would we have 2 more arguments? I would immediately go for grouping this into a record, even it if has just one field for now. Might be called something like ValidationConfig
or ValidationPreconditions
or ValidationContext
(I like that one!) or whatever you think is the best name. That will also make moving to Reader easier in the future if we want it, since you would just move that record into Reader. But it will also make this function immediately more readable and extendable.
@@ -61,25 +66,25 @@ analyzeWaspProject waspDir options = do | |||
analyzeWaspFile waspDir prismaSchemaAst waspFilePath >>= \case | |||
Left errors -> return (Left errors, []) | |||
Right declarations -> | |||
EC.analyzeExternalConfigs waspDir (getSrcTsConfigInWaspProjectDir waspFilePath) >>= \case | |||
EC.analyzeExternalConfigs isTailwindUsed waspDir (getSrcTsConfigInWaspProjectDir waspFilePath) >>= \case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure if I wanted to thread the configFiles
all the way down to validatePackageJson
and the call the G.CF.isTailwindUsed
check. Since validatePackageJson
doesn't need the list of configs, I decided not to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm maybe they don't need it all, but this function is called analyzeExternalConfigs
and now it takes a bool, waspDir, and then a specific config file (srcTsConfig). That is now quite messy, because you could look at those args as:
arg#1: info about config file
arg#2: context
arg#3: config file
Usually in Haskell we aim for "context" args at start, and then "core" args after that.
Since this function is about config files, any amount of them, then I would also find it more natural that it takes a list or record of config files, note one per argument.
So what I would consider is turning this function's signature into :: WaspDir -> ConfigFiles -> ReturnType
(I used a bit pseudo names here).
And it's not a problem if it takes a bit too much info -> it will analyze what it needs to analyze. We don't want to guess how it will analyze them, that is implementation detail.
where | ||
validate = validateDep packageJson | ||
|
||
tailwindValidations = | ||
[ validate ("tailwindcss", show tailwindCssVersion) IsListedWithExactVersion | isTailwindUsed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If Tailwind is used, validate that the tailwindcss
package is present in the package.json
with the correct version.
Signed-off-by: Mihovil Ilakovac <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All makes sense, but I believe we can improve data flow / function signatures a bit, left comments on that!
validatePackageJson :: P.PackageJson -> [ErrorMsg] | ||
validatePackageJson packageJson = | ||
validatePackageJson :: Bool -> P.PackageJson -> [ErrorMsg] | ||
validatePackageJson isTailwindUsed packageJson = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get what you mean, and I agree it would be much going for Reader now.
That said, having just a Bool like this is not very nice, what if we add one or two more conditionals like this, would we have 2 more arguments? I would immediately go for grouping this into a record, even it if has just one field for now. Might be called something like ValidationConfig
or ValidationPreconditions
or ValidationContext
(I like that one!) or whatever you think is the best name. That will also make moving to Reader easier in the future if we want it, since you would just move that record into Reader. But it will also make this function immediately more readable and extendable.
@@ -61,25 +66,25 @@ analyzeWaspProject waspDir options = do | |||
analyzeWaspFile waspDir prismaSchemaAst waspFilePath >>= \case | |||
Left errors -> return (Left errors, []) | |||
Right declarations -> | |||
EC.analyzeExternalConfigs waspDir (getSrcTsConfigInWaspProjectDir waspFilePath) >>= \case | |||
EC.analyzeExternalConfigs isTailwindUsed waspDir (getSrcTsConfigInWaspProjectDir waspFilePath) >>= \case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm maybe they don't need it all, but this function is called analyzeExternalConfigs
and now it takes a bool, waspDir, and then a specific config file (srcTsConfig). That is now quite messy, because you could look at those args as:
arg#1: info about config file
arg#2: context
arg#3: config file
Usually in Haskell we aim for "context" args at start, and then "core" args after that.
Since this function is about config files, any amount of them, then I would also find it more natural that it takes a list or record of config files, note one per argument.
So what I would consider is turning this function's signature into :: WaspDir -> ConfigFiles -> ReturnType
(I used a bit pseudo names here).
And it's not a problem if it takes a bit too much info -> it will analyze what it needs to analyze. We don't want to guess how it will analyze them, that is implementation detail.
Psl.Schema.Schema -> | ||
[AS.Decl] -> | ||
IO (Either [CompileError] AS.AppSpec, [CompileWarning]) | ||
constructAppSpec waspDir options externalConfigs parsedPrismaSchema decls = do | ||
constructAppSpec waspDir options externalConfigs configFiles parsedPrismaSchema decls = do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What confuses me a bit is that this function takes both external configs and congif file relocators. Actually those two kind of make sense -> I guess it takes them, and then rules how to relocate them, I am not up to date with this piece of code completely so I am not quite sure -> but then for relocators you use configFiles
name and that confuses me absolutely, because you said relocators but now it is files.
@@ -23,11 +23,12 @@ data ExternalConfigs = ExternalConfigs | |||
deriving (Show) | |||
|
|||
analyzeExternalConfigs :: | |||
Bool -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, seeing a Bool like this, where I can't tell from signature at all what it could be, is a bit suspicious. I commented more above why this one is probably not the right choice here.
@@ -18,11 +18,11 @@ import Wasp.Project.Common | |||
) | |||
import qualified Wasp.Util.IO as IOUtil | |||
|
|||
analyzePackageJsonFile :: Path' Abs (Dir WaspProjectDir) -> IO (Either [String] P.PackageJson) | |||
analyzePackageJsonFile waspProjectDir = runExceptT $ do | |||
analyzePackageJsonFile :: Bool -> Path' Abs (Dir WaspProjectDir) -> IO (Either [String] P.PackageJson) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably rework this signature also, with similar approach as to how I suggested in other comments.
doesConfigFileExist tailwindConfigFile | ||
&& doesConfigFileExist postcssConfigFile | ||
where | ||
doesConfigFileExist :: Path' (Rel WaspProjectDir) File' -> Bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you know it is a general utility, I would pull it out immediately, since then it is easier for somebody else to see it there and use it. If it was more tied down to this specific place then mabye not, but it seems quite ready to isolate right now, and I can easily imagine somebody else will want to check if certain congfi file exists, so yeah, let's go for it right now.
@@ -149,10 +148,6 @@ resolveRef spec ref = | |||
$ find ((== refName ref) . fst) $ | |||
getDecls spec | |||
|
|||
doesConfigFileExist :: AppSpec -> Path' (Rel WaspProjectDir) File' -> Bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is it that you needed it before?
Are we getting into a situtation where we need a lot of info from AppSpec before AppSpec exists, pointing at some potential design issue, or do you think this is ok?
For more details: #2464