Skip to content

Commit

Permalink
Added support and tutorial for solid start (#412)
Browse files Browse the repository at this point in the history
* Updated tutorial till CRUD

* progress on solid

* Added solid start support and tutorial

* removed lint error

* Merge

* fixed stuff

* Updated some stuff

* removed lint

* updated todo
  • Loading branch information
noam-honig committed Apr 21, 2024
1 parent 5e444be commit 901a69e
Show file tree
Hide file tree
Showing 29 changed files with 6,080 additions and 1,146 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Remult uses **TypeScript entities** as a single source of truth for: ✅ CRUD +

**Remult supports all major databases**, including: PostgreSQL, MySQL, SQLite, MongoDB, MSSQL and Oracle.

**Remult is frontend and backend framework agnostic** and comes with adapters for Express, Fastify, Next.js, Nuxt, SvelteKit, Nest, Koa, Hapi and Hono.
**Remult is frontend and backend framework agnostic** and comes with adapters for Express, Fastify, Next.js, Nuxt, SvelteKit, SolidStart, Nest, Koa, Hapi and Hono.

Remult promotes a **consistent query syntax for both frontend and Backend code**:

Expand Down Expand Up @@ -93,7 +93,7 @@ _Example:_
// backend/index.ts

import express from 'express'
import { remultExpress } from 'remult/remult-express' // adapters for: Fastify, Next.js, Nuxt, SvelteKit, Nest, more...
import { remultExpress } from 'remult/remult-express' // adapters for: Fastify,Next.js, Nuxt, SvelteKit, SolidStart, Nest, more...
import { createPostgresDataProvider } from 'remult/postgres' // supported: PostgreSQL, MySQL, SQLite, MongoDB, MSSQL and Oracle
import { Product } from '../shared/product'

Expand Down Expand Up @@ -306,6 +306,7 @@ with a Node.js Express backend.
- [Tutorial with Vue](https://remult.dev/tutorials/vue/)
- [Tutorial with Next.js](https://remult.dev/tutorials/react-next/)
- [Tutorial with Sveltekit](https://remult.dev/tutorials/sveltekit/)
- [Tutorial with SolidStart](https://remult.dev/tutorials/react-next/)

## Demo

Expand Down
1 change: 1 addition & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const tutorials = [
path: 'react-next',
additionalItems: [], // [{ text: "Appendix: Server-side Rendering", link: '/tutorials/react-next/appendix-1-get-server-side-props' }]
},
{ title: 'SolidStart', path: 'solid-start' },
]

// https://vitepress.dev/reference/site-config
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export const { GET, POST, PUT, DELETE } = api

import { remultSveltekit } from 'remult/remult-sveltekit'

export const _api = remultNextApp({}) // [!code highlight]
export const _api = remultSveltekit({}) // [!code highlight]

export const { GET, POST, PUT, DELETE } = _api
```
Expand Down
50 changes: 50 additions & 0 deletions docs/docs/using-remult-in-custom-backend-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,56 @@ export const handle = sequence(

<!-- prettier-ignore-start -->

== SolidStart

You can use the `withRemult` method in specific routes

```ts
// src/routes/api/test.ts

import { remult } from 'remult'
import { Task } from '../../../shared/Task'
import { _api } from '../[...remult]/+server'

export function GET() {
return api.withRemult(event, async () =>
({ result: await remult.repo(Task).count() }),
)
}
```

You can also use the same method for any "use server" function
```ts
export function getCount(){
return api.withRemult(event, async () =>
({ result: await remult.repo(Task).count() }),
)
}
```

You can also define the withRemult as a hook, to make remult available throughout the application

```ts
// src/hooks.server.ts
import type { Handle } from '@sveltejs/kit'
import { sequence } from '@sveltejs/kit/hooks'
import { _api } from './routes/api/[...remult]/+server'

/**
* Handle remult server side
*/
const handleRemult: Handle = async ({ event, resolve }) => {
return await _api.withRemult(event, async () => await resolve(event))
}

export const handle = sequence(
// Handle remult server side
handleRemult,
)
```

<!-- prettier-ignore-start -->

== Hapi
```ts
import { type Plugin, server } from '@hapi/hapi'
Expand Down
Binary file added docs/public/remult-admin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/tutorials/angular/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ npm run build
npm run start
```

Now navigate to http://localhost3002 and test the application locally
Now navigate to http://localhost:3002 and test the application locally

## Deploy to Railway

Expand Down
8 changes: 4 additions & 4 deletions docs/tutorials/react-next/backend-methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ With the current state of the `setAllCompleted` function, each modified task bei

A simple way to prevent this is to expose an API endpoint for `setAllCompleted` requests, and run the same logic on the server instead of the client.

1. Create a new `TasksController` class, in the `shared` folder, and refactor the `for` loop from the `setAllCompleted` function of the 'Todo` function component into a new, `static`, `setAllCompleted` method in the `TasksController` class, which will run on the server.
1. Create a new `TasksController` class, in the `shared` folder, and refactor the `for` loop from the `setAllCompleted` function of the `Todo` function component into a new, `static`, `setAllCompleted` method in the `TasksController` class, which will run on the server.

```ts
// src/shared/TasksController.ts

import { BackendMethod, remult } from "remult"
import { Task } from "./Task"
import { BackendMethod, remult } from 'remult'
import { Task } from './Task'

export class TasksController {
@BackendMethod({ allowed: true })
Expand Down Expand Up @@ -77,7 +77,7 @@ export const api = remultNextApp({
})
```

3. Replace the `for` iteration in the `setAllCompleted` function of the 'Todo` component with a call to the `setAllCompleted` method in the `TasksController`.
3. Replace the `for` iteration in the `setAllCompleted` function of the `Todo` component with a call to the `setAllCompleted` method in the `TasksController`.

```tsx{4}
// src/components/todo.tsx
Expand Down
8 changes: 4 additions & 4 deletions docs/tutorials/react-next/crud.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Try adding a few tasks to see how it works

## Mark Tasks as completed

Modify the contents of the `tasks.map` iteration within the 'Todo` component to include the following `setCompleted` function and call it in the input's `onChange` event.
Modify the contents of the `tasks.map` iteration within the `Todo` component to include the following `setCompleted` function and call it in the input's `onChange` event.

```tsx{5-6,8-9,16}
// src/components/todo.tsx
Expand Down Expand Up @@ -100,7 +100,7 @@ Modify the contents of the `tasks.map` iteration within the 'Todo` component to

To make the tasks in the list updatable, we'll bind the `tasks` React state to `input` elements and add a _Save_ button to save the changes to the backend database.

Modify the contents of the `tasks.map` iteration within the 'Todo` component to include the following `setTitle` and `saveTask` functions and add an `input` and a save `button`.
Modify the contents of the `tasks.map` iteration within the `Todo` component to include the following `setTitle` and `saveTask` functions and add an `input` and a save `button`.

```tsx{11,13-19,28-29}
// src/components/todo.tsx
Expand Down Expand Up @@ -151,7 +151,7 @@ As you play with these `CRUD` capabilities, monitor the network tab and see that

Let's add a _Delete_ button next to the _Save_ button of each task in the list.

Add the highlighted `deleteTask` function and _Delete_ `button` Within the `tasks.map` iteration in the `return` section of the 'Todo` component.
Add the highlighted `deleteTask` function and _Delete_ `button` Within the `tasks.map` iteration in the `return` section of the `Todo` component.

```tsx{21-28,39}
// src/components/todo.tsx
Expand Down Expand Up @@ -197,4 +197,4 @@ Add the highlighted `deleteTask` function and _Delete_ `button` Within the `task
)
})
}
```
```
2 changes: 1 addition & 1 deletion docs/tutorials/react-next/sorting-filtering.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Since our database may eventually contain a lot of tasks, it make sense to use a

Let's limit the number of fetched tasks to `20`.

In the `useEffect` hook defined in the 'Todo` component, pass an `options` argument to the `find` method call and set its `limit` property to 20.
In the `useEffect` hook defined in the `Todo` component, pass an `options` argument to the `find` method call and set its `limit` property to 20.

```ts{9-13}
// src/components/todo.tsx
Expand Down
22 changes: 11 additions & 11 deletions docs/tutorials/react/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,34 +88,34 @@ npm i --save-dev @types/cookie-session
```ts
// src/server/auth.ts

import express, { Router } from "express"
import type { UserInfo } from "remult"
import express, { Router } from 'express'
import type { UserInfo } from 'remult'

const validUsers: UserInfo[] = [
{ id: "1", name: "Jane" },
{ id: "2", name: "Steve" }
{ id: '1', name: 'Jane' },
{ id: '2', name: 'Steve' },
]

export const auth = Router()

auth.use(express.json())

auth.post("/api/signIn", (req, res) => {
const user = validUsers.find(user => user.name === req.body.username)
auth.post('/api/signIn', (req, res) => {
const user = validUsers.find((user) => user.name === req.body.username)
if (user) {
req.session!["user"] = user
req.session!['user'] = user
res.json(user)
} else {
res.status(404).json("Invalid user, try 'Steve' or 'Jane'")
}
})

auth.post("/api/signOut", (req, res) => {
req.session!["user"] = null
res.json("signed out")
auth.post('/api/signOut', (req, res) => {
req.session!['user'] = null
res.json('signed out')
})

auth.get("/api/currentUser", (req, res) => res.json(req.session!["user"]))
auth.get('/api/currentUser', (req, res) => res.json(req.session!['user']))
```

- The (very) simplistic `signIn` endpoint accepts a request body with a `username` property, looks it up in a predefined dictionary of valid users and, if found, sets the user's information to the `user` property of the request's `session`.
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/react/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ npm run build
npm run start
```

Now navigate to http://localhost3002 and test the application locally
Now navigate to http://localhost:3002 and test the application locally

## Deploy to Railway

Expand Down
Loading

0 comments on commit 901a69e

Please sign in to comment.