Releases: wasp-lang/wasp
v0.10.1
v0.10.1
Bug fixes
- Fixed several TypeScript errors preventing the frontend build
v0.10.0
Breaking changes
- We changed
LoginForm
andSignupForm
to use a named export instead of a default export, this means you must use them like this:import { LoginForm } from '@wasp/auth/forms/Login'
import { SignupForm } from '@wasp/auth/Signup'
- We renamed
useAuth.js
touseAuth.ts
and you should import it like this:import useAuth from '@wasp/auth/useAuth'
(without the.js
extension) - We changed the type arguments for
useQuery
anduseAction
hooks. They now take two arguments (theError
type argument was removed):Input
- This type argument specifies the type for the request's payload.Output
- This type argument specifies the type for the resposne's payload.
Full-stack type safety for Operations
Frontend code can now infer correct payload/response types for Queries and Actions from their definitions on the server.
Define a Query on the server:
export const getTask: GetTaskInfo<Pick<Task, "id">, Task> =
async ({ id }, context) => {
// ...
}
Get properly typed functions and data on the frontend:
import { useQuery } from "@wasp/queries"
// Wasp knows the type of `getTask` thanks to your backend definition.
import getTask from "@wasp/queries/getTask"
export const TaskInfo = () => {
const {
// TypeScript knows `task` is a `Task | undefined` thanks to the
// backend definition.
data: task,
// TypeScript knows `isError` is a `boolean`.
isError,
// TypeScript knows `error` is of type `Error`.
error,
// TypeScript knows the second argument must be a `Pick<Task, "id">` thanks
// to the backend definition.
} = useQuery(getTask, { id: 1 })
if (isError) {
return <div> Error during fetching tasks: {error.message || "unknown"}</div>
}
// TypeScript forces you to perform this check.
return taskInfo === undefined ? (
<div>Waiting for info...</div>
) : (
<div>{taskInfo}</div>
)
}
The same feature is available for Actions.
Payloads compatible with Superjson
Client and the server can now communicate with richer payloads.
Return a Superjson-compatible object from your Operation:
type FooInfo = { foos: Foo[], message: string, queriedAt: Date }
const getFoos: GetFoo<void, FooInfo> = (_args, context) => {
const foos = context.entities.Foo.findMany()
return {
foos,
message: "Here are some foos!",
queriedAt: new Date(),
}
}
And seamlessly use it on the frontend:
import getfoos from "@wasp/queries/getTask"
const { data } = useQuery(getfoos)
const { foos, message, queriedAt } = data
// foos: Foo[]
// message: string
// queriedAt: Date
E-mail authentication
You can now use e-mail authentication in your Wasp app! This means that users can sign up and log in using their e-mail address. You get e-mail verification and password reset out of the box.
app MyApp {
// ...
auth: {
// ...
email: {
fromField: {
name: "ToDO App",
email: "[email protected]"
},
emailVerification: {
allowUnverifiedLogin: false,
getEmailContentFn: import { getVerificationEmailContent } from "@server/auth/email.js",
clientRoute: EmailVerificationRoute,
},
passwordReset: {
getEmailContentFn: import { getPasswordResetEmailContent } from "@server/auth/email.js",
clientRoute: PasswordResetRoute
},
},
}
}
You can only use one of e-mail or username & password authentication in your app. You can't use both at the same time.
Auth UI components
Wasp now provides a set of UI components for authentication. You can use them to quickly build a login and signup page for your app. The UI changes dynamically based on your Wasp config.
We provide LoginForm
, SignupForm
, ForgotPassworForm
, ResetPasswordForm
andVerifyEmailForm
components. You can import them from @wasp/auth/forms
like:
import { LoginForm } from '@wasp/auth/forms/Login'
import { SignupForm } from '@wasp/auth/forms/Signup'
import { ForgotPasswordForm } from '@wasp/auth/forms/ForgotPassword'
import { ResetPasswordForm } from '@wasp/auth/forms/ResetPassword'
import { VerifyEmailForm } from '@wasp/auth/forms/VerifyEmail'
Database seeding
You can now define JS/TS functions for seeding the database!
app MyApp {
// ...
db: {
seeds: [
import { devSeedSimple } from "@server/dbSeeds.js",
import { prodSeed } from "@server/dbSeeds.js",
]
}
}
import { createTask } from './actions.js'
export const devSeedSimple = async (prismaClient) => {
const { password, ...newUser } = await prismaClient.user.create({
username: "RiuTheDog", password: "bark1234"
})
await createTask(
{ description: "Chase the cat" },
{ user: newUser, entities: { Task: prismaClient.task } }
)
}
//...
Run wasp db seed
to run database seeding. If there is only one seed, it will run that one, or it will interactively ask you to pick one.
You can also do wasp db seed <name>
to run a seed with specific name: for example, for the case above, you could do wasp db seed prodSeed
.
The api
keyword for defining an arbitrary endpoint and URL
Need a specific endpoint, like /healthcheck
or /foo/callback
? Or need complete control of the response? Use an api
to define one by tying a JS function to any HTTP method and path! For example:
// main.wasp
api fooBar {
fn: import { foo } from "@server/apis.js",
entities: [Task],
httpRoute: (GET, "/foo/callback")
}
// server/api.ts
import { FooBar } from '@wasp/apis/types'
export const fooBar : FooBar = (req, res, context) => {
res.set('Access-Control-Allow-Origin', '*') // Example of modifying headers to override Wasp default CORS middleware.
res.json({ msg: `Hello, ${context.user?.username || "stranger"}!` })
}
E-mail sending support
Wasp now supports sending e-mails! You can use the emailSender
app property to configure the e-mail provider and optionally the defaultFrom
address. Then, you can use the send
function in your backend code to send e-mails.
// main.wasp
app MyApp {
emailSender: {
provider: SendGrid,
defaultFrom: {
name: "My App",
email: "[email protected]"
},
},
}
// server/actions.ts
import { emailSender } from '@wasp/email/index.js'
// In some action handler...
const info = await emailSender.send({
to: '[email protected]',
subject: 'Saying hello',
text: 'Hello world',
html: 'Hello <strong>world</strong>'
})
wasp start db
-> Wasp can now run your dev database for you with a single command
Moving from SQLite to PostgreSQL with Wasp can feel like increase in complexity, because suddenly you have to care about running your PostgreSQL database, providing connection URL for it via env var, and if you checkout somebody's else Wasp project, or your old Wasp project that you have no memory of any more, you also have to figure all that out.
To help with that, we now added wasp start db
, which runs a development database for you!
That it, all you need to do is run wasp start db
and you are good to go. No env var setting, no remembering how to run the db.
NOTE: Requires docker
to be installed and in PATH
, and docker daemon to be running.
wasp test client
-> Wasp can now test your web app code
By leveraging Vitest and some supporting libraries, Wasp now makes it super easy to add unit tests and React component tests to your frontend codebase.
pg-boss
upgraded to latest version (8.4.2)
This pg-boss
release fixes an issue where the node server would exit due to an unhandled exception when the DB connection was lost.
Bug fixes
- Starts the process of removing the coupling between
usernameAndPassword
and social logins. Now, youruserEntity
no longer requires ausername
orpassword
field if you only want to use Google/GitHub for auth.
v0.10.0-rc2
Fix type errors preventing build (#1118)
v0.10.0-rc1
Bump version in ChangeLog.md
v0.9.1-replitrc
Adds support for FE listening on multiple addresses (#1048)
v0.9.0
v0.9.0
BREAKING CHANGES
- All client files which use
JSX
need to have either the.jsx
or the.tsx
extension. This is because we now useVite
under the hood instead ofCreate React App
, andVite
requires these extensions to be present to process `JSX`` properly. - The Tailwind and PostCSS config files need to have the
.cjs
extension. These config files are CommonJS modules, and withVite
we are using ES modules by default.
Wasp now uses Vite instead of Create React App
We moved away from using Create React App for the client app. This means that dev startup time will be much faster and we are following the latest best practices for building web apps with React.
Express app
and http server
available in server setupFn
- Wasp now passes in a context to the server
setupFn
that contains Expressapp
and httpserver
objects. This can be used as an escape hatch for things like custom routes or WebSocket support.
v0.8.2
Non-breaking Changes
- The Dockerfile has been updated to build the server files during the Docker build stage instead of during server startup. This will reduce the memory footprint required for running apps.
Bug fixes
- Fixed a file lock error that kills CLI when changing entities with
wasp start
running on newer Macs.
Support for defining the web app's root component
You can now define a root component for your client app. This is useful if you want to wrap your app in a provider or have a common layout. You can define it in app.client.rootComponent
in your .wasp
file.
wasp deploy
CLI command added
We have made it much easier to deploy your Wasp apps via a new CLI command, wasp deploy
. 🚀 This release adds support for Fly.io, but we hope to add more hosting providers soon!
Importable Wasp Entity types (on frontend and backend)
You can now import and use the types of Wasp entities anywhere in your code.
Let's assume your Wasp file contains the following entity:
entity Task {=psl
id Int @id @default(autoincrement())
description String
isDone Boolean @default(false)
user User @relation(fields: [userId], references: [id])
userId Int
psl=}
Here's how you can access and use its type in a backend file:
import { Task } from '@wasp/entities/Task'
const getTasks = (args, context) => {
const tasks: Task[] = // ...
// ...
}
And here's how you can to the same in a frontend file:
// ...
import { useQuery } from '@wasp/queries'
import getTasks from '@wasp/queries/getTasks.js'
import { Task } from '@wasp/entities'
type TaskPayload = Pick<Task, "id">
const Todo = (props: any) => {
// The variable 'task' will now have the type Task.
const { data: task } = useQuery<TaskPayload, Task>(getTask, { id: taskId })
// ...
}
Automatically generated types for Queries and Actions
Wasp now automatically generates appropriate types for the operations specified
in your .wasp
file. This reduces duplication and eliminates possible errors
(i.e., no way to specify incorrect entities). Assuming your .wasp
file looks
like this:
query getTasks {
fn: import { getTasks } from "@server/queries.js",
entities: [Task]
}
You'll get the following feature:
import { Task } from '@wasp/entities'
import { GetTasks} from '@wasp/queries/types'
type Payload = Pick<Task, 'isDone'>;
// Use the type parameters to specify the Query's argument and return types.
const getTasks: GetTasks<Payload, Task[]> = (args, context) => {
// Thanks to the definition in your `.wasp` file, the compiler knows the type
// of `context` (and that it contains the `Task` entity).
//
// Thanks to the first type argument in `GetTasks`, the compiler knows `args`
// is of type `Payload`.
//
// Thanks to the second type argument in `GetTasks`, the compiler knows the
// function must return a value of type `Task[]`.
}
Uninstall command
If you want to uninstall Wasp from your system, you can now do so with:
wasp uninstall
It will remove all of the Wasp binaries and data from your system.
v0.8.1
Drop the npm version requirement (#1002)
v0.8.1-rc1
Adds `wasp deploy` CLI command for Fly.io (#961)
v0.8.0
BREAKING CHANGES
- Social auth had several breaking changes as we added a new provider (GitHub).
- Buttons and sign in URLs now have a different, standardized import name for each provider.
- Google exe:
import { SignInButton as GoogleSignInButton, signInUrl, logoUrl } from '@wasp/auth/helpers/Google'
- Google exe:
- Buttons themselves have been restyled to make them more uniform, and no longer take an optional
height
parameter. - Social config object now use a
clientID
property instead ofclientId
.
- Buttons and sign in URLs now have a different, standardized import name for each provider.
GitHub added as a social login
We have added GitHub as another social login option. It is as easy to use as Google, and only requires adding gitHub
to your app.auth.methods
plus two environment variables (GITHUB_CLIENT_ID
and GITHUB_CLIENT_SECRET
)! Check out the docs for more.