mirror of
https://github.com/wasp-lang/wasp.git
synced 2024-12-24 17:44:21 +03:00
Minor grammar and spelling fixes in docs (#662)
* Minor spelling/grammar fixes in getting-started.md * minor grammar/spelling fixes in new project * minor spelling/grammar fixes in task-entity.md * minor spelling/grammar fixes to listing-tasks.md * minor spelling/grammar fixes in creating-tasks.md * minor spelling/grammar fixes in updating-tasks.md * corrections to auth.md * minor fixes to dependencies.md * fixes to the-end.md * fix link * typo
This commit is contained in:
parent
9f7d212b8c
commit
0c3db966c0
@ -57,11 +57,11 @@ We recommend using [nvm](https://github.com/nvm-sh/nvm) for managing your Node.j
|
||||
|
||||
Why does Wasp require this specific `node` range and doesn't support a newer version x.y.z?
|
||||
|
||||
At Wasp, we focus on supporting the latest LTS ("long-term-support") Node.js version, since it guarantees stability and active maintainance, which is why official Node.js team recommends it for usage in production.
|
||||
At Wasp, we focus on supporting the latest LTS ("long-term-support") Node.js version, since it guarantees stability and active maintainance, which is why the official Node.js team recommends it for usage in production.
|
||||
Therefore, a specific Wasp release will usually require the version of Node.js that was LTS at that point of time.
|
||||
Check out https://nodejs.org/en/about/releases/ for more details about Node.js releases.
|
||||
|
||||
Sometimes we will make an exception to that and additionaly limit the Node.js version or postpone switching to the latest LTS if there are certain issues with new Node.js version, in which case we will catch up once those are resolved on Node.js side or we find a workaround on Wasp side.
|
||||
Sometimes we will make an exception to that and additionally limit the Node.js version or postpone switching to the latest LTS if there are certain issues with new Node.js version, in which case we will catch up once those are resolved on Node.js side or we find a workaround on Wasp side.
|
||||
|
||||
:::
|
||||
|
||||
@ -100,7 +100,7 @@ In the meantime, the best way to start using Wasp on Windows is by using [WSL](h
|
||||
<TabItem value='source'>
|
||||
<div style={{borderLeft: 'solid 6px #bf9900', paddingLeft: '10px'}} >
|
||||
|
||||
If installer is not working for you or your OS is not supported, you can try building Wasp from source.
|
||||
If the installer is not working for you or your OS is not supported, you can try building Wasp from source.
|
||||
|
||||
To install from source, you need to clone the [wasp repo](https://github.com/wasp-lang/wasp), install [cabal](https://cabal.readthedocs.io/en/stable/getting-started.html) on your machine and then run `cabal install` from the `waspc/` dir.
|
||||
|
||||
|
@ -56,7 +56,7 @@ What this means for us is that Wasp now offers us:
|
||||
|
||||
This is a very high-level API for auth which makes it very easy to get started quickly, but is
|
||||
not very flexible. If you require more control (e.g. want to execute some custom code on the server
|
||||
during signup, check out [lower-level auth API](/docs/language/features#lower-level-api).
|
||||
during signup, check out the [lower-level auth API](/docs/language/features#lower-level-api).
|
||||
|
||||
Ok, that was easy!
|
||||
|
||||
@ -66,7 +66,7 @@ To recap, so far we have defined:
|
||||
|
||||
## Adding Login and Signup pages
|
||||
|
||||
When we defined `app.auth` we got login and signup forms generated for us, but now we have to use them in their pages. In our `main.wasp` file we'll add the following:
|
||||
When we defined `app.auth` we got login and signup forms generated for us, but now we have to create Login and Signup pages that use them. In our `main.wasp` file we'll add the following:
|
||||
|
||||
```c title="main.wasp"
|
||||
// ...
|
||||
@ -105,7 +105,7 @@ const LoginPage = () => {
|
||||
export default LoginPage
|
||||
```
|
||||
|
||||
Signup page is very similar to the login one:
|
||||
The Signup page is very similar to the login one:
|
||||
|
||||
```jsx title="ext/SignupPage.js"
|
||||
import React from 'react'
|
||||
@ -131,7 +131,7 @@ export default SignupPage
|
||||
|
||||
## Updating `MainPage` page to check if user is authenticated
|
||||
|
||||
Now, let's see how are we going to handle the situation when user is not logged in.
|
||||
Now, let's see how we're going to handle the situation when user is not logged in.
|
||||
`MainPage` page is a private page and we want users to be able to see it only if they are authenticated.
|
||||
There is a specific Wasp feature that allows us to achieve this in a simple way:
|
||||
|
||||
@ -143,8 +143,8 @@ page MainPage {
|
||||
}
|
||||
```
|
||||
|
||||
With `authRequired: true` we declared that page `MainPage` is accessible only to the authenticated users.
|
||||
If an unauthenticated user tries to access route `/` where our page `MainPage` is, they will be redirected to `/login` as specified with `onAuthFailedRedirectTo` property in `app.auth`.
|
||||
With `authRequired: true` we declared that page `MainPage` is accessible only to authenticated users.
|
||||
If an unauthenticated user tries to access route `/` where our page `MainPage` is, they will be redirected to `/login` as specified with the `onAuthFailedRedirectTo` property in `app.auth`.
|
||||
|
||||
Also, when `authRequired` is set to `true`, the React component of a page (specified by `component` property within `page`) will be provided `user` object as a prop. It can be accessed like this:
|
||||
|
||||
@ -161,7 +161,7 @@ Now, we can again run
|
||||
wasp start
|
||||
```
|
||||
|
||||
Try going to `/` in our web app -> it will now ask you to log in, and if you follow the link, you will end up at `/login`.
|
||||
Try going to `/` in our web app. It will now redirect you to `/login`, where you'll be asked to authenticate.
|
||||
Once you log in or sign up, you will be sent back to `/` and you will see the todo list.
|
||||
|
||||
Let's now see how things look in the database! Run:
|
||||
@ -175,12 +175,12 @@ wasp db studio
|
||||
|
||||
We see there is a user and that its password is already hashed! Wasp took care of this for us.
|
||||
|
||||
However, you will notice, if you try logging in with different users and creating tasks, that all users are still sharing tasks.
|
||||
That is because we did not yet update queries and actions to work only on current user's tasks, so let's do that next!
|
||||
However, you will notice that if you try logging in with different users and creating tasks, all users are still sharing tasks.
|
||||
That is because we did not yet update queries and actions to work only on the current user's tasks, so let's do that next!
|
||||
|
||||
## Defining User-Task relation in entities
|
||||
|
||||
First, let's define User-Task (one-to-many) relation (check [prisma docs on relations](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/relations)):
|
||||
First, let's define a one-to-many relation between User and Task (check the [prisma docs on relations](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/relations)):
|
||||
```c {6,13-14} title="main.wasp"
|
||||
// ...
|
||||
entity User {=psl
|
||||
@ -200,7 +200,7 @@ psl=}
|
||||
// ...
|
||||
```
|
||||
|
||||
We modified entities by adding User-Task relation, so let's run
|
||||
We modified entities by adding the User-Task relation, so let's run
|
||||
```shell-session
|
||||
wasp db migrate-dev
|
||||
```
|
||||
@ -208,14 +208,14 @@ to create a database schema migration and apply it to the database.
|
||||
|
||||
:::note
|
||||
We made `user` and `userId` in `Task` optional (via `?`) because that allows us to keep the existing tasks, which don't have a user assigned, in the database.
|
||||
This is not recommended because it allows unwanted state in the database (what is the purpose of the task not belonging to anybody?) and normally we would not make these fields optional.
|
||||
This is not recommended because it allows an unwanted state in the database (what is the purpose of the task not belonging to anybody?) and normally we would not make these fields optional.
|
||||
Instead, we would do a data migration to take care of those tasks, even if it means just deleting them all.
|
||||
However, for this tutorial, for the sake of simplicity, we will stick with this.
|
||||
:::
|
||||
|
||||
## Updating operations to forbid access to non-authenticated users
|
||||
|
||||
Next, let's update the queries and actions to forbid access to non-authenticated users and to operate only on currently logged in user's tasks:
|
||||
Next, let's update the queries and actions to forbid access to non-authenticated users and to operate only on the currently logged in user's tasks:
|
||||
```js {1,4,6} title="ext/queries.js"
|
||||
import HttpError from '@wasp/core/HttpError.js'
|
||||
|
||||
@ -291,4 +291,4 @@ const MainPage = () => {
|
||||
}
|
||||
```
|
||||
|
||||
This is it, we have working authentication system and our app is multi-user!
|
||||
This is it, we have a working authentication system, and our Todo app is multi-user!
|
||||
|
@ -13,13 +13,13 @@ Enter the created directory and run:
|
||||
cd TodoApp
|
||||
wasp start
|
||||
```
|
||||
You have just ran your app in the development mode!
|
||||
You have just run your app in the development mode!
|
||||
|
||||
:::note
|
||||
`wasp start` might take a little bit longer, due to the first time setup.
|
||||
:::
|
||||
|
||||
You will be seeing a lot of different output from client, server and database setting themselves up.
|
||||
You will be seeing a lot of different output from the client, server and database setting themselves up.
|
||||
Once ready, a new tab should open in your browser at `http://localhost:3000`, with simple placeholder page:
|
||||
|
||||
<img alt="Screenshot of new Wasp app"
|
||||
@ -28,7 +28,7 @@ Once ready, a new tab should open in your browser at `http://localhost:3000`, wi
|
||||
height="400px"
|
||||
/>
|
||||
|
||||
We just set the foundations of our app! We don't have yet the features to show it, but Wasp already generated for us full front-end and back-end code of the app. Take a peek at `TodoApp/.wasp/out` if you are curious and see how it looks like!
|
||||
We just set the foundations of our app! We don't have yet the features to show it, but Wasp has already generated for us the full front-end and back-end code of the app. Take a peek at `TodoApp/.wasp/out` if you are curious and see how it looks like!
|
||||
|
||||
## Taking a closer look at the code
|
||||
|
||||
@ -44,7 +44,7 @@ TodoApp/
|
||||
└── .wasproot
|
||||
```
|
||||
|
||||
Let's start with `main.wasp` file which introduces 3 new concepts:
|
||||
Let's start with the `main.wasp` file, which introduces 3 new concepts:
|
||||
[app](language/features.md#app),
|
||||
[page](language/features.md#page) and
|
||||
[route](language/features.md#route).
|
||||
@ -75,7 +75,7 @@ const MainPage = () => {
|
||||
}
|
||||
export default MainPage
|
||||
```
|
||||
As we can see, this is just a simple functional React component using css and wasp logo that are next to it.
|
||||
As we can see, this is just a simple functional React component, using the CSS and Wasp logo files that are next to it.
|
||||
|
||||
This is all the code!
|
||||
Wasp in the background takes care of everything else needed to define, build and run a web app.
|
||||
@ -98,7 +98,7 @@ const MainPage = () => {
|
||||
export default MainPage
|
||||
```
|
||||
|
||||
At this point, you should be seeing smth like
|
||||
At this point, you should be seeing something like
|
||||
|
||||
<img alt="Todo App - Hello World"
|
||||
src={useBaseUrl('img/todo-app-hello-world.png')}
|
||||
|
@ -4,9 +4,9 @@ title: "Creating tasks"
|
||||
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
|
||||
To enable creation of new tasks, we will need two things:
|
||||
1. Wasp action that creates a new task.
|
||||
2. React form that calls that action with the new task's data.
|
||||
To enable the creation of new tasks, we will need two things:
|
||||
1. a Wasp action that creates a new task.
|
||||
2. a React form that calls that action with the new task's data.
|
||||
|
||||
## Action
|
||||
Creating an action is very similar to creating a query.
|
||||
@ -35,7 +35,7 @@ export const createTask = async (args, context) => {
|
||||
```
|
||||
|
||||
:::tip
|
||||
We put JS function in new file `ext/actions.js`, but we could have put it anywhere we wanted, there are no limitations here, as long as the import statement in Wasp file is correct and it is inside `ext/` dir.
|
||||
We put the JS function in a new file `ext/actions.js`, but we could have put it anywhere we wanted! There are no limitations here, as long as the import statement in the Wasp file is correct and it is inside the `ext/` dir.
|
||||
:::
|
||||
|
||||
## React form
|
||||
@ -110,7 +110,7 @@ Here we call our action directly (no hooks) because we don't need any reactivity
|
||||
|
||||
That's it!
|
||||
Try creating a "Build a Todo App in Wasp" task and see it appear in the list below.
|
||||
Task is created on the server and also saved in the database. Try refreshing the page or opening it in another browser - you'll see the tasks are still here!
|
||||
The task is created on the server and also saved in the database. Try refreshing the page or opening it in another browser - you'll see the tasks are still here!
|
||||
|
||||
<img alt="Todo App - creating new task"
|
||||
src={useBaseUrl('img/todo-app-new-task.png')}
|
||||
@ -118,9 +118,9 @@ Task is created on the server and also saved in the database. Try refreshing the
|
||||
/>
|
||||
|
||||
## Side note: Automatic invalidation/updating of queries
|
||||
You will notice that when you create a new task, the list of tasks is automatically updated with that new task, although we have written no code to take care of that! Normally, you would have to do this explicitly, e.g. with react-query you would invalidate the `getTasks` query via its key, or would call its `refetch()` method.
|
||||
You will notice that when you create a new task, the list of tasks is automatically updated with that new task, although we have written no code to take care of that! Normally, you would have to do this explicitly, e.g. with `react-query` you would invalidate the `getTasks` query via its key, or would call its `refetch()` method.
|
||||
|
||||
The reason why `getTasks` query automatically updates when `createTask` action is executed is because Wasp is aware that both of them are working with `Task` entity, and therefore assumes that action that operates on `Task` (in this case `createTask`) might have changed the result of `getTasks` query. Therefore, in the background, Wasp nudges `getTasks` query to update. This means that **out of the box, Wasp will make sure that all your queries that deal with entities are always in sync with any changes that the actions might have done**.
|
||||
The reason why the `getTasks` query automatically updates when the `createTask` action is executed is because Wasp is aware that both of them are working with the `Task` entity, and therefore assumes that action that operates on `Task` (in this case `createTask`) might have changed the result of the `getTasks` query. Therefore, in the background, Wasp nudges the `getTasks` query to update. This means that **out of the box, Wasp will make sure that all your queries that deal with entities are always in sync with any changes that the actions might have done**.
|
||||
|
||||
:::note
|
||||
While this kind of approach to automatic invalidation of queries is very convenient, it is in some situations wasteful and could become a performance bottleneck as an app grows. In that case, you will be able to override this default behaviour and instead provide more detailed (and performant) instructions on how the specific action should affect queries. This is not yet implemented, but is something we plan to do and you can track the progress [here](https://github.com/wasp-lang/wasp/issues/63) (or even contribute!).
|
||||
|
@ -6,9 +6,9 @@ import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
|
||||
What is a Todo app without some clocks!? Well, still a Todo app, but certainly not as fun as one with the clocks!
|
||||
|
||||
So, let's add a couple of clocks to our app, to help us track time while we perform our tasks (and to demonstrate `app.dependencies` feature).
|
||||
So, let's add a couple of clocks to our app, to help us track time while we perform our tasks (and to demonstrate the `app.dependencies` feature).
|
||||
|
||||
For this, we will use `react-clock` library from NPM. We can add it to our project as a [dependency](language/features.md#dependencies) like this:
|
||||
For this, we will use the `react-clock` library from NPM. We can add it to our project as a [dependency](language/features.md#dependencies) like this:
|
||||
```c {6-8} title="main.wasp"
|
||||
app TodoApp {
|
||||
title: "Todo app",
|
||||
@ -21,11 +21,11 @@ app TodoApp {
|
||||
}
|
||||
```
|
||||
|
||||
Run (if it is already running, stop it first and then run it again)
|
||||
Run
|
||||
```shell-session
|
||||
wasp start
|
||||
```
|
||||
to have Wasp download and install new dependency (that happens on start of `wasp start`).
|
||||
to have Wasp download and install the new dependency. If `wasp start` is already running, Wasp will detect the dependency change, and restart automatically.
|
||||
|
||||
Next, let's create a new component `Clocks` where we can play with the clocks.
|
||||
```jsx title="ext/Clocks.js"
|
||||
|
@ -51,13 +51,13 @@ Query function parameters:
|
||||
- `context`: `object`, additional stuff provided by Wasp.
|
||||
|
||||
|
||||
Since we declared in `main.wasp` that our query uses entity Task, Wasp injected [Prisma client](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/crud) for entity Task as `context.entities.Task` - we used it above to fetch all the tasks from the database.
|
||||
Since we declared in `main.wasp` that our query uses entity Task, Wasp injected a [Prisma client](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/crud) for entity Task as `context.entities.Task` - we used it above to fetch all the tasks from the database.
|
||||
|
||||
:::info
|
||||
Queries and actions are NodeJS functions that are executed on the server.
|
||||
:::
|
||||
|
||||
## Invoking query from React
|
||||
## Invoking the query from React
|
||||
|
||||
Finally, let's use the query we just created, `getTasks`, in our React component to list the tasks:
|
||||
|
||||
@ -100,11 +100,11 @@ export default MainPage
|
||||
|
||||
All of this is just regular React, except for the two special `@wasp` imports:
|
||||
- `import getTasks from '@wasp/queries/getTasks'`: provides us with our freshly defined Wasp query.
|
||||
- `import { useQuery } from '@wasp/queries'`: provides us with Wasp's [useQuery](language/features.md#usequery) React hook which is actually just a thin wrapper over [react-query](https://github.com/tannerlinsley/react-query) [useQuery](https://react-query.tanstack.com/docs/guides/queries) hook, behaving very similarly while offering some extra integration with Wasp.
|
||||
- `import { useQuery } from '@wasp/queries'`: provides us with Wasp's [useQuery](language/features.md#usequery) React hook which is actually just a thin wrapper over [react-query](https://github.com/tannerlinsley/react-query)'s [useQuery](https://react-query.tanstack.com/docs/guides/queries) hook, behaving very similarly while offering some extra integration with Wasp.
|
||||
|
||||
While we could call query directly as `getTasks()`, calling it as `useQuery(getTasks)` gives us the reactivity (React component gets re-rendered if result of the query changes).
|
||||
While we could call query directly as `getTasks()`, calling it as `useQuery(getTasks)` gives us reactivity- the React component gets re-rendered if the result of the query changes.
|
||||
|
||||
With these changes, you should be seeing text "No tasks" on the screen:
|
||||
With these changes, you should be seeing the text "No tasks" on the screen:
|
||||
|
||||
<img alt="Todo App - No Tasks"
|
||||
src={useBaseUrl('img/todo-app-no-tasks.png')}
|
||||
|
@ -6,7 +6,7 @@ import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
|
||||
[Entities](language/features.md#entity) are one of the very central concepts in Wasp, and they mainly play the role of data models.
|
||||
|
||||
Since our TodoApp is all about tasks, we will define Task entity in Wasp:
|
||||
Since our TodoApp is all about tasks, we will define a Task entity in Wasp:
|
||||
```c title="main.wasp"
|
||||
// ...
|
||||
|
||||
@ -17,7 +17,7 @@ entity Task {=psl
|
||||
psl=}
|
||||
```
|
||||
|
||||
Since Wasp uses [Prisma](https://www.prisma.io) as a database, definition of an entity comes down to defining a [Prisma model](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/data-model/), using PSL (Prisma Schema Language) inside the `{=psl psl=}` tags.
|
||||
Since Wasp uses [Prisma](https://www.prisma.io) as a database, the definition of an entity comes down to defining a [Prisma model](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/data-model/), using PSL (Prisma Schema Language) inside the `{=psl psl=}` tags.
|
||||
|
||||
After this change and before running `wasp start`, we first need to run:
|
||||
```shell-session
|
||||
|
@ -13,14 +13,14 @@ We did it! For all those that followed the instructions closely and created "Bui
|
||||
|
||||
You can check out the whole code of the app that we just built [here](https://github.com/wasp-lang/wasp/tree/main/examples/tutorials/TodoApp).
|
||||
|
||||
If you are interested in what is Wasp actually generating in the background, you can check `.wasp/out/` directory in your project.
|
||||
If you are interested in what is Wasp actually generating in the background, you can check the `.wasp/out/` directory in your project.
|
||||
|
||||
## Where next?
|
||||
|
||||
Well, you could check the "Language" section of the docs for more details on specific parts of Wasp.
|
||||
Well, you could check [the "Language" section](language/overview.md) of the docs for more details on specific parts of Wasp.
|
||||
Or, you could try to build something on your own with Wasp!
|
||||
|
||||
You are likely to find that some feature that you want is missing, since Wasp is still in Alpha.
|
||||
In that case, please write to us on [Discord](https://discord.gg/rzdnErX) or create an issue on [Github](https://github.com/wasp-lang/wasp), so we can learn which features to add next.
|
||||
Even beter, if you would like to contribute or help building the feature, let us know!
|
||||
Even better, if you would like to contribute or help building the feature, let us know!
|
||||
You can find more details on contributing [here](contributing.md).
|
||||
|
@ -4,17 +4,17 @@ title: "Updating tasks"
|
||||
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
|
||||
Todo app isn't done if you can't mark a task as done!
|
||||
The Todo app isn't done if you can't mark a task as done!
|
||||
|
||||
For that, we will need to do two things:
|
||||
1. Implement Wasp action that updates the task.
|
||||
1. Implement a Wasp action that updates the task.
|
||||
2. Modify our React code so it calls that action.
|
||||
|
||||
## Action
|
||||
|
||||
### Wasp declaration
|
||||
|
||||
We declare Wasp action:
|
||||
We declare a Wasp action:
|
||||
```c title="main.wasp"
|
||||
// ...
|
||||
|
||||
@ -26,7 +26,7 @@ action updateTask {
|
||||
|
||||
### JS implementation
|
||||
|
||||
We define JS implementation of Wasp action in `ext/actions.js`:
|
||||
We define the JS implementation of the Wasp action in `ext/actions.js`:
|
||||
```js title="ext/actions.js"
|
||||
// ...
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user