wasp

The fastest way to develop full-stack web apps with React & Node.js.

MIT License

Stars
12K
Committers
81

Bot releases are visible (Hide)

wasp - v0.11.1-wasp-ai-3

Published by github-actions[bot] over 1 year ago

wasp - v0.11.1-wasp-ai-2

Published by github-actions[bot] over 1 year ago

wasp - v0.11.1-wasp-ai

Published by github-actions[bot] over 1 year ago

wasp - v0.11.0

Published by github-actions[bot] over 1 year ago

🎉 Big new features 🎉

  • Automatic CRUD backend generation
  • Public folder support
  • Type safe WebSocket support
  • Go to definition for imports in Wasp file

Check below for details on each of them!

⚠️ Breaking changes

  • Wasp's signup action import signup from '@wasp/auth/signup now accepts only the user entity fields relevant to the auth process (e.g. username and password).
    This ensures no unexpected data can be inserted into the database during signup, but it also means you can't any more set any user entity fields via signup action (e.g. age or address).
    Instead, those should be set in the separate step after signup, or via a custom signup action of your own.
  • Wasp now uses React 18! Check the following upgrade guide for details: https://react.dev/blog/2022/03/08/react-18-upgrade-guide .
    The most obvious difference you might notice is that your useEffect hooks run twice on component mount.
    This is due to the React 18's StrictMode, and it happens only during development, so it doesn't change the behaviour of your app in production.
    For more details on StrictMode, check https://react.dev/reference/react/StrictMode .
  • Updated most of the npm dependencies that Wasp app is generated with (e.g. axios), so you will also need to update those that both you and Wasp use.
    Wasp will inform you about this with a warning/error message during compilation so just follow instructions.

🎉 [New feature] Public directory support

Wasp now supports a public directory in the client directory!

main.wasp
src/
├── client/
|   ├── public/  # <-- NEW!
|   |   ├── favicon.ico
|   |   └── robots.txt
|   └── ...
└── ...

All the files in this directory will be copied as they are to the public directory in the build folder.
This is useful for adding static assets to your project, like favicons, robots.txt, etc.

🎉 [New feature] Type safe WebSocket support

Wasp now supports WebSockets! This will allow you to have a persistent, realtime connection between your client and server, which is great for chat apps, games, and more.
What's more, Wasp's WebSockets support full-stack type safety, so you can be sure that your client and server are communicating with strongly typed events.

Enable WebSockets in your project by adding the following to your main.wasp file:

app todoApp {
  // ...

  webSocket: {
    fn: import { webSocketFn } from "@server/webSocket.js",
    autoConnect: true, // optional, default: true
  },
}

Then implement it on the server with optional types:

import type { WebSocketDefinition } from '@wasp/webSocket'

export const webSocketFn: WebSocketFn = (io, context) => {
  io.on('connection', (socket) => {
    // ...
  })
}

type WebSocketFn = WebSocketDefinition<
  ClientToServerEvents,
  ServerToClientEvents
>

interface ServerToClientEvents {
  chatMessage: (msg: { id: string, username: string, text: string }) => void;
}

interface ClientToServerEvents {
  chatMessage: (msg: string) => void;
}

And use it on the client with automatic type inference:

import React, { useState } from 'react'
import {
  useSocket,
  useSocketListener,
  ServerToClientPayload,
} from '@wasp/webSocket'

export const ChatPage = () => {
  const [messageText, setMessageText] = useState<
    // We are using a helper type to get the payload type for the "chatMessage" event.
    ClientToServerPayload<'chatMessage'>
  >('')
  const [messages, setMessages] = useState<
    ServerToClientPayload<'chatMessage'>[]
  >([])
  // The "socket" instance is typed with the types you defined on the server.
  const { socket, isConnected } = useSocket()

  // This is a type-safe event handler: "chatMessage" event and its payload type
  // are defined on the server.
  useSocketListener('chatMessage', logMessage)

  function logMessage(msg: ServerToClientPayload<'chatMessage'>) {
    setMessages((priorMessages) => [msg, ...priorMessages])
  }

  function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault()
    // This is a type-safe event emitter: "chatMessage" event and its payload type
    // are defined on the server.
    socket.emit('chatMessage', messageText)
    // ...
  }

  // ...
}

🎉 [New feature] Automatic CRUD backend generation

You can tell Wasp to automatically generate server-side logic (Queries and Actions) for creating, reading, updating, and deleting a specific entity. As you change that entity, Wasp automatically regenerates the backend logic.

Example of a Task entity with automatic CRUD:

crud Tasks {
  entity: Task,
  operations: {
    getAll: {
      isPublic: true, // by default only logged in users can perform operations
    },
    get: {},
    create: {
      overrideFn: import { createTask } from "@server/tasks.js",
    },
    update: {},
    delete: {},
  },
}

This gives us the following operations: getAll, get, create, update and delete, which we can use in our client like this:

import { Tasks } from '@wasp/crud/Tasks'
import { useState } from 'react'

export const MainPage = () => {
  const { data: tasks, isLoading, error } = Tasks.getAll.useQuery()
  const createTask = Tasks.create.useAction()
  // ...

  function handleCreateTask() {
    createTask({ description: taskDescription, isDone: false })
    setTaskDescription('')
  }

  // ...
}

🎉 [New feature] IDE tooling improvements

Go to definition from wasp file + detection of invalid imports

query getRecipes {
  fn: import { getRecipes } from "@server/recipe.js",  // <- You can now click on this import!
  entities: [Recipe],
}

Wasp language server just got smarter regarding imports in wasp file!

  1. If there is no file to which import points, error is reported.
  2. If file doesn't contain symbol that we are importing, error is reported.
  3. Clicking on import statement now takes you to the code that is being imported.

We have more ideas in this direction on the way though!
A bit of a sneak peek of what is coming soon: if Wasp recognizes file / symbol is missing, it will offer to scaffold the code for you!

Autocompletion for dictionary keys

app RecipeApp {
  title: "My Recipes",
  wasp: { version: "^0.10.0" },
  auth: {
    methods: { usernameAndPassword: {} },
    █       // <- your cursor
  }
}

As per popular request, Wasp language server now recognizes when you are in dictionary and will offer possible key values for autocompletion!
For instance, in the code example above, it will offer completions such as onAuthFailedRedirectTo, userEntity, ... .
It will also show their types.

🐞 Bug fixes / 🔧 small improvements

  • Wasp now uses TypeScript to ensure all payloads sent to or from operations (queries and actions) are serializable.
  • Wasp starter templates now show description.
  • Wasp CLI now correctly exits with exit code 1 after compiler bug crash.
  • Added extra type info to middleware customization fn.
  • Upgraded most of the dependencies (with react-router and prisma upgrades coming soon).
  • Wasp CLI now always shows a nice error message when database is not accessible.
  • We now ensure that User entity's username field must have unique attribute.
  • Improved how Wasp CLI detects wrong/missing node + the error message it prints.

New Contributors

Full Changelog: https://github.com/wasp-lang/wasp/compare/v0.10.6...v0.11.0

wasp - v0.11.0-rc4

Published by github-actions[bot] over 1 year ago

What's Changed

New Contributors

Full Changelog: https://github.com/wasp-lang/wasp/compare/v0.10.6...v0.11.0-rc4

wasp - v0.11.0-rc3

Published by github-actions[bot] over 1 year ago

What's Changed

Full Changelog: https://github.com/wasp-lang/wasp/compare/v0.11.0-rc2...v0.11.0-rc3

wasp - v0.11.0-rc2

Published by github-actions[bot] over 1 year ago

What's Changed

Full Changelog: https://github.com/wasp-lang/wasp/compare/v0.11.0-rc1...v0.11.0-rc2

wasp - v0.11.0-rc1

Published by github-actions[bot] over 1 year ago

wasp - v0.10.6-react18-canary

Published by github-actions[bot] over 1 year ago

Same like v0.10.6, but with React upgraded from 17 to 18. For testing.

wasp - v0.10.6

Published by github-actions[bot] over 1 year ago

Bug fixes

  • wasp deploy fly launch now supports the latest flyctl launch toml file for the web client (which changed their default structure and port).

More wasp deploy fly options

wasp deploy fly now supports a --org option, as well as setting secrets during launch.

wasp - v0.10.5

Published by github-actions[bot] over 1 year ago

Bug fixes

  • Wasp CLI will now forward error exit codes. This will help when used in scripted contexts.
  • Wasp now renders only the first route that matches the current path in the browser.

Express middleware customization

We now offer the ability to customize Express middleware:

  • globally (impacting all actions, queries, and apis by default)
  • on a per-api basis
  • on a per-path basis (groups of apis)

Interactive new project creation

We now offer an interactive way to create a new project. You can run wasp new and follow the prompts to create a new project. This is the recommended way to create a new project. It will ask you for the project name and to choose one of the starter templates.

wasp - v0.10.4

Published by github-actions[bot] over 1 year ago

Bug fixes

  • Adds missing import for HttpError which prevent auth from working properly.
wasp - v0.10.3

Published by github-actions[bot] over 1 year ago

Bug fixes

  • Fixed a bug with circular imports in JS code which prevented database seeding from working properly.
wasp - v0.10.3-rc1

Published by github-actions[bot] over 1 year ago

wasp - v0.10.2

Published by github-actions[bot] over 1 year ago

Bug fixes

  • Fixed a bug where JS arrays weren't generated properly from Haskell code which caused issues with oAuth, operations and cache invalidation.
wasp - v0.10.1

Published by github-actions[bot] over 1 year ago

v0.10.1

Bug fixes

  • Fixed several TypeScript errors preventing the frontend build
wasp - v0.10.0

Published by github-actions[bot] over 1 year ago

Breaking changes

  • We changed LoginForm and SignupForm 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 to useAuth.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 and useAction hooks. They now take two arguments (the Error 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, your userEntity no longer requires a username or password field if you only want to use Google/GitHub for auth.
wasp - v0.10.0-rc2

Published by github-actions[bot] over 1 year ago

wasp - v0.10.0-rc1

Published by github-actions[bot] over 1 year ago

wasp - v0.9.1-replitrc

Published by github-actions[bot] over 1 year ago

Package Rankings
Top 5.63% on Proxy.golang.org
Badges
Extracted from project README
Discord
Related Projects