-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Moving logic from templates to libs #2989
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
base: main
Are you sure you want to change the base?
Conversation
0770d1f
to
679a882
Compare
Signed-off-by: Mihovil Ilakovac <[email protected]>
679a882
to
b4e1769
Compare
Deploying wasp-docs-on-main with
|
Latest commit: |
4e6ddbb
|
Status: | ✅ Deploy successful! |
Preview URL: | https://00fbde5c.wasp-docs-on-main.pages.dev |
Branch Preview URL: | https://templates-to-libs.wasp-docs-on-main.pages.dev |
08f9765
to
72e2676
Compare
72e2676
to
49d979c
Compare
@@ -1,13 +1,13 @@ | |||
import { parseCookies } from "@wasp.sh/libs-auth"; |
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 made this refactor by mistake not realizing that I'm touching the server
and not the SDK. It works because the @wasp.sh/libs-auth
is installed in the root node_modules
... but it breaks our philosophy that we introduced with 0.12.0: user imports from the SDK -> framework imports user code.
If the server
imports the auth lib directly, I consider that importing the SDK since the auth lib is just an implementation detail of the SDK.
So, how do we tackle this? The server
doesn't have oslo
listed as one of its deps (meaning this worked just because SDK had oslo
as a dep).
Do we add oslo
as the dep of the server
to be precise?
Can we avoid the server
using oslo
directly? That would mean that the server uses the SDK?
Do we consider server
using the auth lib directly a violation of our 0.12.0 philosophy?
cc: @sodic
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 think a straightforward solution would be to have libs-auth-server
and libs-auth-sdk
etc
Or the same library with multiple exports should be fine, no?
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've encoded this worry in this issue as we'll need to figure out the naming: #3069
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.
Latest status: I've implemented the proposal from the linked issue in this PR #3069
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 like the idea of not "dragging" the server's import chain through the SDK if it isn't necessary. Since SDK will become heavily templated, we want to decouple it from the rest of our codebase as best we can, which means minimizing SDK exports into the framework code.
the SDK since the auth lib is just an implementation detail of the SDK.
This makes sense too because framework code importing stuff from multiple locations seems messy, and I'm 90% sure it will have to import templated stuff at some point.
I'll have to think about this some more, we can discuss it on a call.
@Martinsos @sodic ready! |
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.
Did another round!
I thoroughly reviewed all but TS code, that I didn't go into at all, because I feel others will cover that better (@FranjoMindek already did, and @sodic also should).
waspc/libs/README.md
Outdated
Run `tools/install_libs_to_data_dir.sh` to compile the libs and copy | ||
them into `data/`. Then you can use `./run wasp-cli` as normal. You can run | ||
`./run install` which will run the script before installing the | ||
Wasp CLI. |
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 woudl shortly explain that while developing libs, we work on them here. But when we run (dev version) of wasp binary and want it to use the latest version of libs, it will be searching for them in the data
dir, not here. So we need to compile and ...
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.
Btw I wondered here is there a way to avoid this copying. Can't we somehow work on developing them direclty in the data
dir, but then we smartly replace them with their targz versions when installing it or something? Hm. Any idea how we could skip this copying?
Btw also possibly related issue, would love to get your opinion on it while at this: #2629 .
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.
then we smartly replace them with their targz versions when installing it or something?
We have to run something, we can't use the package as-is - either npm pack
and then delete stuff or npm pack
and then copy stuff. I'm not sure which solution is less complex, but I think copying is a bit cleaner.
I'll chime in on the issues you linked 👍
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.
So - I'd say, let's keep the old way of doing things in this PR and let's refactor to non-copying for both libs and packages in a separate PR.
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.
Sounds good! Let's mention libs in that issue also then.
raw
waspDataDirTarball :: NpmTarball LibsSourceDir, | ||
waspDataDirTarballAbsPath :: Path' Abs File', |
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 am confused about the difference between these two, what is the difference?
Aha ok, I do remember tarball is nothing but a name right?
So you need abs path also. But that abs path also contains that name? So redundancy? Yeah this is a bit confusing for me.
And also why do you have generatedCodeDirTarball
also, if it is only name in there, aren't those the same regarding data they contain?
Maybe the very concept of NpmTarball
is a bit confusing, because you know, what is that, how can you have Tarball here in a variable hah?
My feeling is that stuff should be more simpler / obvious, but I am not yet sure how, so I am asking these questions.
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.
So you need abs path also. But that abs path also contains that name? So redundancy? Yeah this is a bit confusing for me.
You are right, we didn't need to have the tarball filename and the abs path for the data dir file.
And also why do you have generatedCodeDirTarball also, if it is only name in there, aren't those the same regarding data they contain?
Nope, the generated code tarball has the checksum in the name - so it's serving a different purpose. It's the destination tarball name.
I've tried to simplify it a bit, let me know what you think!
makeWaspLib :: String -> IO WaspLib | ||
makeWaspLib waspLibPackageName = do | ||
libsSourceDirPath <- getAbsLibsSourceDirPath | ||
|
||
-- Libs have a fixed version "0.0.0" which means we use the same version for the tarballs | ||
-- in the data directory (e.g. lib-0.0.0.tgz). When the tarballs are copied to the generated project directory, | ||
-- the tarball filename version is replaced with the checksum of the tarball (e.g. lib-<checksum>.tgz). | ||
let waspDataDirTarball' = Npm.Tarball.makeNpmTarball sanitizedTarballName "0.0.0" | ||
let waspDataDirTarballAbsPath' = libsSourceDirPath </> Npm.Tarball.filename waspDataDirTarball' | ||
|
||
waspDataDirTarballChecksum <- computeTarballChecksum waspDataDirTarballAbsPath' | ||
let generatedCodeDirTarball' = Npm.Tarball.makeNpmTarball sanitizedTarballName waspDataDirTarballChecksum | ||
|
||
return $ | ||
WaspLib | ||
{ packageName = waspLibPackageName, | ||
waspDataDirTarball = waspDataDirTarball', | ||
waspDataDirTarballAbsPath = waspDataDirTarballAbsPath', | ||
generatedCodeDirTarball = generatedCodeDirTarball' | ||
} | ||
where | ||
sanitizedTarballName = Npm.Tarball.sanitizePackageNameForTarballName waspLibPackageName |
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 code is for some reason very hard for me to read and understand.
I wonder if problem is in the concept of Npm.Tarball. Maybe ti should be named Npm.TarballName.
Or maybe problem is in definition of WaspLib. Maybe it should have different contents.
Or makeWaspLib should be written in a simpler manner, more clean codish.
But something is throwing me off here, all together it is very hard to wrap a head around. Well, harder than it should be, I think.
So what is really happening here? When we say makeWaspLib
? We, given a name of the package in /libs
, want to create an object that has information on that wasp lib, right? But we are also doing something on the disk, any effects? No, just calculating the checksum, right?
How would you describe, in a sentence or two or three, what does makeWaspLib
do? But simple enough that I can understand it? While also kind of explaining what WaspLib and Npm.Tarball are, I guess?
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've tried to simplify this code, let me know what you think.
This is what's going on:
- We have an npm library we want to use in the generated code.
- This library has some sort of name e.g.
@wasp.sh/miho
and a dummy version of0.0.0
- This library is packaged with
npm pack
which gives us a tarball on diskwasp.sh-miho-0.0.0.tgz
- In order to avoid caching issues with
npm install
we replace the dummy version0.0.0
with the archive checksum e.g.wasp.sh-miho-xxxxxx.tgz
. Anytime the lib changes, the checksum changes and we bust npms cache.
We want to encode all of this in the WaspLib
type in Haskell:
- Package name
- Abs path to the tarball in the
data
dir - Tarball file name which will be used in the generated code
So it comes down to this:
WaspLib (packageName, waspDataDirTarballDirAbsPath, generatedCodeDirTarballFilename)
|
||
let allEntities = [userEntity, someOtherEntity] | ||
let (_generatorWarnings, generatorResult) = runGenerator $ injectAuth allEntities userEntity | ||
let config = makeGeneratorConfig [] |
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.
Just an idea, can help with readability / intention.
let config = makeGeneratorConfig [] | |
let config = let waspLibs = [] in makeGeneratorConfig waspLibs |
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 do you think about creating a specialized function like:
runGeneratorWithoutWaspLibs :: Generator a -> ([GeneratorWarning], Either (NonEmpty GeneratorError) a)
runGeneratorWithoutWaspLibs = runGenerator (makeGeneratorConfig [])
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.
Change for now:
I've updated it to be:
-- We make a generator config with no WaspLibs because they are not needed
-- for Dockerfile generation.
let config = GeneratorConfig {gcWaspLibs = []}
because I didn't like the nested let ... in
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.
That's all right! Yeah this is the safest really, why not.
@Martinsos ready for another look! |
The filename of a npm tarball copied to the generated Wasp app contains the checksum of the | ||
tarball, to avoid npm caching the tarball. |
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.
EDIT: Yep, adding the auth lib to the optimizeDeps.exclude array sorted it out 🎉
@infomiho @cprecioso Is this a hack though? By this I mean, assuming there's a standrad:
- Are we just lucky that NPM does not respect the standard, and Vite is actually doing things correctly?
- Or is Vite the one not respecting the standard and optimizes the dependencies too eagerly?
Btw, I advise doing discussions such as this one in a regular comment thread that allows replies (not a final review note) because quote discussions are difficult to follow, especially on PRs.
We can continue discussing in this comment's thread.
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.
There's no standard here, just implementations loosely mimicking each other. We're just tuning ourselves to the behaviours of disparate tools trying not to step on one another.
Changing the name of the tarball file only affects said tarball file, not its installed form, so that's why Vite is not discovering the changes. It specifically checks the contents of package-lock.json
.
I think doing something like a random version number every time would probably kick Vite into reoptimizing the dependency (this was floated at some point when Miho and I talked in the beginning), but in this case I prefer this workaround of opting out of optimization than the random version number which feels way more hack-ish.
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.
Btw, if we hook this up into npm workspaces #3159, Vite says it has some special cases for it, that should be the most semantically accurate way of setting our dependencies.
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.
Went through all the comments and discussion to get context.
I'll now go deep into the review.
-- Libs have a fixed version "0.0.0" which means we use the same version for the tarballs | ||
-- in the data directory (e.g. lib-0.0.0.tgz). When the tarballs are copied to the generated project directory, | ||
-- the tarball filename version is replaced with the checksum of the tarball (e.g. lib-<checksum>.tgz). |
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 comment says a lot about what we do and not a lot about why we do it.
I think the whole tarball/cache situation could use more explanation, even examples (@infomiho similar to how you explained it in the PR comments).
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.
Pleas apply them to the old script too :)
Generator/templates/**/*.jsx | ||
Generator/templates/**/*.tsx | ||
Generator/templates/**/*.png | ||
Generator/libs/*.tgz |
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 opens up a question, why didn't we ship our the SDK like this? Oh well, we maybe didn't know we could or it wasn't practical at the time.
Hm, I did know about tarballs but I didn't seriously consider them as an option.
What we did with the SDK (i.e., specifying a local path/installing a local package) was also supposed to be a well-supported normal way of installing stuff with NPM but turned out to be NPM's neglected child.
I liked the local NPM install (symlink) option because it doesn't copy or transform the data - there's always a single source of truth.
With the tarball, I think we're effectively "copying" the data twice:
- The first step is "copy" + compression into the tarball.
- The second step is extracting the tarball into
node_modules
.
At this point there's three copies of the same code: the original code, the code in the tarball, and the extracted code. It seemed like a lot of steps that could go wrong or out of sync - the entire pipeline felt too long and complicated for what I was trying to do.
With a local install, there's always only a single copy, it felt cleaner and easier to work with.
waspc/libs/auth/src/sdk/jwt.ts
Outdated
): Promise<string> => { | ||
return createJWT(JWT_ALGORITHM, JWT_SECRET, data, options); | ||
}, | ||
validateJWT: async <Payload>(token: string): Promise<Payload> => { |
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.
There's nothing special about type arguments compared to regular ones - both types and values come from either the global scope or the function scope. If anything, values are even worse because they often come from locals inside the function.
So, unless we start calling value arguments aFoo
and aBar
, no prefixes for type arguments :)
BTW Payload
is a much better name than T
in most cases. We wouldn't call a variable holding a payload v
.
Just T
is fine for types whenever x
would be fine for a variable - a scope where we have nothing to communicate. In this case, I could go both ways.
For some reason, many programmers don't apply clean coding rules (e.g. proper naming) when it comes to types. That's probably a relict of when type systems were much less powerful and had special semantics compared to the rest of the code. But for a language like TypeScript, where half of the codebase is types, this only causes harm.
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.
Excellent work coming up with this system!
I went through everything except Haskell code. I do have some questions that I've layed out, ping me if you want to discuss them.
Once we sort this out, I'll go through everything again.
"./sdk/browser": { | ||
"types": "./dist/sdk-browser.d.ts", | ||
"import": "./dist/sdk-browser.js" | ||
}, |
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 don't use this terminology across our codebase.
Unfortunately, our terminology for this particular thing is all over the place: web app, react app, client... And I actually like browser best, so I'm not sure what to do here. The most consisten choice is probably naming it "web-app" (since that's the part of the codebase that uses 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.
We decide to use tsdown
as the bundler for our libraries and I liked their terminology quite a lot:
node
browser
neutral
It's more based on the platform rather than the place of usage. So I thought, okay, let's stick with no suffix for neutral
(most of our code) and let's add the /browser
suffix for browser specific code (stuff that won't be able to run on the server). I guess later on, we'd find that we might need the /node
suffix as well for server only code.
So the system we have in the end is:
@wasp.sh/<lib-name>/<place>/<platform>
where <place>
is sdk | server | web-app
and <platform>
is <empty> | browser | node
.
"import": "./dist/sdk.js" | ||
}, | ||
"./sdk/browser": { | ||
"types": "./dist/sdk-browser.d.ts", |
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.
Is the types
part necessary? I think it might be automatic.
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.
Without types
, npx @arethetypeswrong/cli -P
reports that resolution will fail when node16
resolution is used. I don't know if we care about that since it's our internal library, but I find it nice that our lib is as compliant as possible 😄
+ the default tsdown
template includes the types
: https://github.com/Gugustinette/create-tsdown/blob/main/templates/default/package.json
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.
It can be automatic but the interaction with exports
is a bit iffy. It's better to set it.
"check:type-exports": "npx @arethetypeswrong/cli -P", | ||
"check:types": "tsc --noEmit", | ||
"dev": "vitest dev", | ||
"prepare": "npm run build" |
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 have a prepare script that just calls the build script. How come?
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.
prepare
script is called by npm
when we call npm pack
- this way the package is always built before packaging.
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.
prepare
is the name that npm
expects, it can do anything. Here we're explicitly saying what it does to "prepare" the package is to build it.
waspc/libs/auth/tsconfig.json
Outdated
"verbatimModuleSyntax": true, | ||
"skipLibCheck": true | ||
}, | ||
"include": ["src", "tests/sdk/password.test.ts", "tests/sdk/jwt.test.ts"] |
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.
Why not just "tests"?
@@ -0,0 +1,20 @@ | |||
{ | |||
"compilerOptions": { |
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 did we decide on the options here? For example, how come lib
is 2023
? Are missing noEmit
?
Could we group options as we do in sdk/tsconfig.json? Since we'll have many libraries, I'd like our tsconfg files to be as standardized as possible. It would also be great if we had a "source of truth" for this, any ideas?
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 went with the default template for the tsdown
bundler, keeping with the theme "these are just JS libs" and didn't want to do anything special for Wasp in that department: https://github.com/Gugustinette/create-tsdown/blob/main/templates/default/tsconfig.json
In my mind, if tsdown
updates, we just follow their upgrade guides and don't need to worry about anything special that we introduced. Does that make sense?
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.
Franjo had the idea to extract the prettier configuration to its own package/repo. In my monorepo projects, I do that, and not only with prettier but tsconfigs, build utilities etc. In that way you don't need to have a bunch of options everywhere.
@@ -1,13 +1,13 @@ | |||
import { parseCookies } from "@wasp.sh/lib-auth/server"; |
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 don't know if this matters (probably not), but I'd expect our lib imports to come below "normal" imports like express.
|
||
import type { ProviderConfig } from 'wasp/auth/providers/types'; | ||
import { config } from 'wasp/server'; | ||
import type { ProviderConfig } from "wasp/auth/providers/types"; |
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.
Double quotes? Is this a formatting mistake?
@@ -1 +1,2 @@ | |||
packages | |||
Generator/libs/*.tgz |
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 mentioned this in a different thread, but why don't we ignore the entire libs directory and have the exact same setup as we do with packages?
data_libs_dir=$waspc_dir/data/Generator/libs | ||
|
||
# Cleanup old libs. | ||
rm -f "${data_libs_dir:?}"/*.tgz |
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.
The :?
check doesn't do anything. There's no way data_libs_dir
is unset. It could be wrong (e.g., if script_dir
is unset), but it's always set so :?
won't trigger.
|
||
for package in $(ls "$dir/../packages"); do | ||
package_dir="$dir/../packages/$package" | ||
for package_dir in "${waspc_dir:?}"/packages/*; 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.
The :?
doesn't do anything here. There's no way that waspc_dir
is unset. It's always at least /..
.
We should do this check with script_dir
instead.
Btw, I think this idiom also alolws setting an error message, that might come in handy :)
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.
Mid-level review (read through the files, but didn't read through all the old discussions, feel free to resolve stuff if it was already discussed), added some comments. I haven't tried running yet, I'm testing that and will send an approval once I've seen it in action.
|
||
depsMessage :: AppSpec -> String | ||
depsMessage appSpec = | ||
depsMessage :: AppSpec -> [WaspLib.WaspLib] -> String |
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 don't think we should be showing the libraries, they should be transparent and have no significative version number by themselves. And if I got it right, users should not be importing the libraries.
export const ForgotPasswordForm = () => { | ||
const { register, handleSubmit, reset, formState: { errors } } = useForm<{ email: string }>() | ||
const { isLoading, setErrorMessage, setSuccessMessage, setIsLoading } = useContext(AuthContext) | ||
const { isLoading, setErrorMessage, setSuccessMessage, setIsLoading } = useAuthContext() |
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 actually think it's good that he made this change, it's scoped enough to be a demonstration and a proof that it works, without big changes otherwise.
@@ -1,14 +1,13 @@ | |||
{{={= =}=}} | |||
import { useState, createContext, useMemo } from 'react' | |||
import { useState, useMemo, type CSSProperties } from 'react' |
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.
import { useState, useMemo, type CSSProperties } from 'react' | |
import { useState, useMemo } from 'react' |
function normalizePassword(password: string): string { | ||
return password.normalize("NFKC"); | ||
} | ||
export { hashPassword, verifyPassword } from "@wasp.sh/lib-auth/sdk"; |
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.
Agree!
|
||
getAllNpmDeps :: AppSpec -> Either String AllNpmDeps | ||
getAllNpmDeps spec = | ||
getAllNpmDeps :: AppSpec -> [WaspLib.WaspLib] -> Either String AllNpmDeps |
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.
It feels weird for me that we're passing this around as a parameter. In my mind it's either global (the static list of available libs), or a property of the AppSpec (which libraries we need for the current app).
"module": "preserve", | ||
"moduleResolution": "bundler", | ||
"resolveJsonModule": true, | ||
"types": ["node"], |
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.
Why? If they're set installed TypeScript just picks them up
"import": "./dist/sdk.js" | ||
}, | ||
"./sdk/browser": { | ||
"types": "./dist/sdk-browser.d.ts", |
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.
It can be automatic but the interaction with exports
is a bit iffy. It's better to set it.
"exports": { | ||
"./sdk": { | ||
"types": "./dist/sdk.d.ts", | ||
"import": "./dist/sdk.js" |
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're already saying "type": "module"
, we don't need to specify import
here too. I'd use default
in case some random tool forgets to set the import conditions.
waspc/libs/auth/package.json
Outdated
"build": "tsdown", | ||
"check": "npm run check:types && npm run check:coverage && npm run check:type-exports", | ||
"check:coverage": "vitest run --coverage", | ||
"check:type-exports": "npx @arethetypeswrong/cli -P", |
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.
Why do remote code execution 😁? Just install it as a dev dep.
"check:type-exports": "npx @arethetypeswrong/cli -P", | ||
"check:types": "tsc --noEmit", | ||
"dev": "vitest dev", | ||
"prepare": "npm run build" |
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.
prepare
is the name that npm
expects, it can do anything. Here we're explicitly saying what it does to "prepare" the package is to build it.
|
||
# Building | ||
WASP_PACKAGES_COMPILE="${SCRIPT_DIR}/tools/install_packages_to_data_dir.sh" | ||
WASP_LIBS_COMPILE="${SCRIPT_DIR}/tools/install_libs_to_data_dir.sh" |
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.
Should we also add a ./run build:libs
command like the packages one?
], | ||
optimizeDeps: { | ||
exclude: ['wasp'] | ||
exclude: {=& depsExcludedFromOptimization =} |
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.
exclude: {=& depsExcludedFromOptimization =} | |
exclude: {=& depsExcludedFromOptimization =} |
"tsconfig.tsbuildinfo", | ||
"dist" | ||
] | ||
&& not (isTgzFile filePath) |
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.
Has there been discussion about ignoring the tgz? Can you point me to it?
High-level overview
This PR:
waspc/libs
directorydata/libs
directory.wasp/out
alongside the SDK directory so the SDK can import the libsauth
library in thelibs
directory (named@wasp.sh/libs-auth
)tsdown
npm pack
and copy it into thedata
diroslo
./sdk
and./sdk/browser
to be able to separate server and browser exportsWaspLib
which is how we refer to the libraries in Haskell.tgz
files) and where to copy themWaspLib
(e.g.file:../../lib-1.0.0.tgz
)version
to be fixed to0.0.0
since it will be replaced with the lib checksum when copiedauth
library in the SDK and the serverjwt
,cookies
andpassword
helpers, these helpers depend on external deps e.g.oslo
and@node-rs/argon2
(native deps)./sdk/browser
entry to show we can split the codeNote
Note for reviewers: there are three sections:
auth
libraryauth
library is used in the SDKI'd suggest reviewing the
auth
library last since it's just a JS project, nothing new to see there.How to test it locally
./tools/install_packages_to_data_dir.sh
waspc/examples/todoApp
with thecabal run
or your alias of choice e.g.wrun
I've tested it in development and production build modes and it works as expected ✅
Known issues in development
You have to delete thenode_modules
and the@wasp.sh/libs-auth
entry frompackage-lock.json
to install the new development lib version that you built locally.EDIT: fixed by using a checksum of the library's
.tgz
checksum as the version which preventsnpm
from using a stale version. Also, I've excluded the libs from being optimized (and then becoming stale) by Vite in development mode.Left to do
.tgz
files. I'll do this in a separate PR to keep it easier to review this one. Ignoretgz
files in e2e tests #3078waspc/README.md
and inrun
scriptCloses #2936
Closes #3069