-
Notifications
You must be signed in to change notification settings - Fork 194
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: flesh out getting started guide/tutorial in README (#99)
This also has some fixes/improvements to the basic & todo example to make them work + add READMEs e.g. `DELETE` wasn't being handled correctly in `Shape` 😱 @icehaunter I quickly added a test but didn't really verify it was properly testing it if you could double-check. --------- Co-authored-by: Ilia Borovitinov <[email protected]>
- Loading branch information
1 parent
f170484
commit 6fdb1b2
Showing
21 changed files
with
1,517 additions
and
860 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@electric-sql/next": patch | ||
"@electric-sql/react": patch | ||
--- | ||
|
||
chore: updated testing fixtures |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@core/sync-service": patch | ||
--- | ||
|
||
feat: include ElectricSQL version header |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,34 @@ | ||
version: "3.1" | ||
version: "3.3" | ||
name: "electric_example-${PROJECT_NAME:-default}" | ||
|
||
services: | ||
postgres: | ||
image: postgres:14-alpine | ||
image: postgres:16-alpine | ||
environment: | ||
POSTGRES_DB: electric | ||
POSTGRES_USER: postgres | ||
POSTGRES_PASSWORD: password | ||
ports: | ||
- "54321:5432" | ||
- 54321:5432 | ||
volumes: | ||
- ./postgres.conf:/etc/postgresql.conf:ro | ||
- ./postgres.conf:/etc/postgresql/postgresql.conf:ro | ||
tmpfs: | ||
- /var/lib/postgresql/data | ||
- /tmp | ||
entrypoint: | ||
- docker-entrypoint.sh | ||
command: | ||
- postgres | ||
- -c | ||
- config_file=/etc/postgresql.conf | ||
- config_file=/etc/postgresql/postgresql.conf | ||
extra_hosts: | ||
- "host.docker.internal:host-gateway" | ||
|
||
backend: | ||
image: electricsql/next:example | ||
image: electricsql/electric-next:example | ||
environment: | ||
DATABASE_URL: postgresql://postgres:password@host.docker.internal:54321/electric | ||
DATABASE_URL: postgresql://postgres:password@postgres:5432/electric | ||
ports: | ||
- "3000:3000" | ||
build: | ||
context: ../packages/sync-service/ | ||
context: ../packages/sync-service/ | ||
depends_on: | ||
- postgres |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,68 +10,100 @@ See James' blog post for more background on the change: https://next.electric-sq | |
|
||
## Getting Started | ||
|
||
1. Install the TypeScript client and React integrations | ||
`npm install @electric-sql/next @electric-sql/react` | ||
#### Create a new React app | ||
|
||
2. Run Docker Compose similar to the following to setup Postgres and Electric | ||
`npm create vite@latest my-first-electric-app -- --template react-ts` | ||
|
||
#### Setup Docker Compose to run Postgres and Electric | ||
|
||
`docker-compose.yaml` | ||
|
||
```docker | ||
version: "3.8" | ||
name: "todomvc" | ||
configs: | ||
postgres_config: | ||
file: "./postgres/postgres.conf" | ||
volumes: | ||
pg_data: | ||
name: "my-first-electric-service" | ||
services: | ||
postgres: | ||
image: postgres:16-alpine | ||
environment: | ||
POSTGRES_DB: electric | ||
POSTGRES_USER: postgres | ||
POSTGRES_PASSWORD: pg_password | ||
POSTGRES_PASSWORD: password | ||
ports: | ||
- 55321:5432 | ||
volumes: | ||
- ./postgres.conf:/etc/postgresql/postgresql.conf:ro | ||
command: | ||
- postgres | ||
- -c | ||
- config_file=/etc/postgresql.conf | ||
configs: | ||
- source: postgres_config | ||
target: /etc/postgresql.conf | ||
healthcheck: | ||
test: ["CMD-SHELL", "pg_isready -U postgres"] | ||
- config_file=/etc/postgresql/postgresql.conf | ||
extra_hosts: | ||
- "host.docker.internal:host-gateway" | ||
ports: | ||
- 5632:5432 | ||
volumes: | ||
- pg_data:/var/lib/postgresql/data | ||
# TODO add Electric image | ||
electric: | ||
image: electricsql/next:example | ||
environment: | ||
DATABASE_URL: postgresql://postgres:[email protected]:55321/electric | ||
ports: | ||
- "3000:3000" | ||
build: | ||
context: ~/programs/electric-next/packages/sync-service/ | ||
``` | ||
|
||
Add a `postgresql.conf` file. | ||
Add a `postgres.conf` file. | ||
|
||
``` | ||
listen_addresses = '*' | ||
wal_level = 'logical' | ||
``` | ||
|
||
3. Try a curl command | ||
`curl http://localhost:3000/v1/shape/{table}` | ||
#### Start Docker | ||
|
||
`docker compose -f ./docker-compose.yaml up` | ||
|
||
#### Try a curl command against Electric's HTTP API | ||
|
||
`curl -i http://localhost:3000/v1/shape/foo?offset=-1` | ||
|
||
This request asks for a shape composed of the entire `foo` table. | ||
|
||
A bit of explanation about the URL structure — `/v1/shape/` are standard | ||
segments. `foo` is the name of the root table of the shape (and is required). | ||
`offset=-1` means we're asking for the entire log of the Shape as we don't have | ||
any of the log cached locally yet. If we had previously fetched the shape and | ||
wanted to see if there was any updates, we'd set the offset of the last log | ||
message we'd got the first time. | ||
|
||
You should get a response like this: | ||
|
||
```bash | ||
HTTP/1.1 400 Bad Request | ||
date: Wed, 17 Jul 2024 20:30:31 GMT | ||
content-length: 62 | ||
vary: accept-encoding | ||
cache-control: max-age=0, private, must-revalidate | ||
x-request-id: F-MaJcF9A--cg9QAAAeF | ||
access-control-allow-origin: * | ||
access-control-expose-headers: * | ||
access-control-allow-methods: GET, POST, OPTIONS | ||
Server: ElectricSQL/0.0.1 | ||
content-type: application/json; charset=utf-8 | ||
|
||
{"offset":["can't be blank"],"root_table":["table not found"]}% | ||
``` | ||
|
||
Start Docker: `docker compose -f ./docker-compose.yaml up` | ||
So it didn't work! Which makes sense... as it's a empty database without any tables or data. Let's fix that. | ||
|
||
3. Create a table and insert some data: | ||
#### Create a table and insert some data | ||
|
||
Use your favorite Postgres client to connect to Postgres e.g. with [psql](https://www.postgresql.org/docs/current/app-psql.html) | ||
you run: `psql postgresql://postgres:password@localhost:55321/electric` | ||
|
||
```sql | ||
CREATE TABLE foo ( | ||
id INT PRIMARY KEY AUTO_INCREMENT, -- Unique identifier, auto-incrementing | ||
name VARCHAR(255), -- Text field for names (adjust size as needed) | ||
value FLOAT -- Numeric value (can be decimal) | ||
id SERIAL PRIMARY KEY, | ||
name VARCHAR(255), | ||
value FLOAT | ||
); | ||
|
||
INSERT INTO foo (name, value) VALUES | ||
|
@@ -82,37 +114,92 @@ INSERT INTO foo (name, value) VALUES | |
('Eve', 0); | ||
``` | ||
|
||
4. Try a curl command to Electric's HTTP API: | ||
#### Now try the curl command again | ||
|
||
`curl http://localhost:3000/shape/foo?offset=-1` | ||
|
||
Success! You should see the data you just put into Postgres in the shape response: | ||
|
||
```bash | ||
HTTP/1.1 200 OK | ||
date: Wed, 17 Jul 2024 20:38:07 GMT | ||
content-length: 643 | ||
vary: accept-encoding | ||
cache-control: max-age=60, stale-while-revalidate=300 | ||
x-request-id: F-Maj_CikDKfZTIAAAAh | ||
access-control-allow-origin: * | ||
access-control-expose-headers: * | ||
access-control-allow-methods: GET, POST, OPTIONS | ||
Server: ElectricSQL/0.0.1 | ||
content-type: application/json; charset=utf-8 | ||
x-electric-shape-id: 3833821-1721248688126 | ||
x-electric-chunk-last-offset: 0_0 | ||
etag: 3833821-1721248688126:-1:0_0 | ||
|
||
[{"offset":"0_0","value":{"id":1,"name":"Alice","value":3.14},"key":"\"public\".\"foo\"/1","headers":{"action" | ||
:"insert"}},{"offset":"0_0","value":{"id":2,"name":"Bob","value":2.71},"key":"\"public\".\"foo\"/2","headers": | ||
{"action":"insert"}},{"offset":"0_0","value":{"id":3,"name":"Charlie","value":-1.618},"key":"\"public\".\"foo\ | ||
"/3","headers":{"action":"insert"}},{"offset":"0_0","value":{"id":4,"name":"David","value":1.414},"key":"\"pub | ||
lic\".\"foo\"/4","headers":{"action":"insert"}},{"offset":"0_0","value":{"id":5,"name":"Eve","value":0.0},"key | ||
":"\"public\".\"foo\"/5","headers":{"action":"insert"}},{"headers":{"control":"up-to-date"}}]% | ||
``` | ||
#### Now let's fetch the same shape to use in our React app | ||
Install the Electric React package: | ||
`npm install @electric-sql/react` | ||
`curl http://localhost:3000/shape/foo` | ||
5. Add to React app | ||
Wrap your root in `src/main.tsx` with the `ShapesProvider`: | ||
Add the Shapes provider | ||
```tsx | ||
import { ShapesProvider } from "@electric-sql/react" | ||
ReactDOM.createRoot(document.getElementById(`root`)!).render( | ||
<ShapesProvider> | ||
<App /> | ||
</ShapesProvider> | ||
ReactDOM.createRoot(document.getElementById('root')!).render( | ||
<React.StrictMode> | ||
<ShapesProvider> | ||
<App /> | ||
</ShapesProvider> | ||
</React.StrictMode>, | ||
) | ||
``` | ||
Add `useShape` to a component | ||
Replace `App.tsx` with the following: | ||
```tsx | ||
import { useShape } from "@electric-sql/react" | ||
import { useShape } from "@electric-sql/react"; | ||
function Component { | ||
function Component() { | ||
const { data: fooData } = useShape({ | ||
shape: { table: `foo` }, | ||
baseUrl: `http://localhost:3000`, | ||
}) | ||
}); | ||
return JSON.stringify(foo, null, 4) | ||
return JSON.stringify(fooData, null, 4); | ||
} | ||
export default Component; | ||
``` | ||
Finally run the dev server to see it all in action! | ||
`npm run dev` | ||
You should see something like: | ||
<img width="699" alt="Screenshot 2024-07-17 at 2 49 28 PM" src="https://github.com/user-attachments/assets/cda36897-2db9-4f6c-86bb-99e7e325a490"> | ||
#### Postgres as a real-time database | ||
Go back to your postgres client and update a row. It'll instantly be synced to your component! | ||
```sql | ||
UPDATE foo SET name = 'James' WHERE id = 2; | ||
``` | ||
Congradulations! You've now built your first Electric app! | ||
## HTTP API Documentation | ||
The HTTP API documentation is defined through an OpenAPI 3.1.0 specification found in `docs/electric-api.yaml`. Documentation for the API can be generated with `npm run docs:generate`. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,22 @@ | ||
# TODO | ||
# Basic example | ||
|
||
## Setup | ||
|
||
1. Make sure you've installed all dependencies for the monorepo and built packages | ||
|
||
From the root directory: | ||
|
||
- `pnpm i` | ||
- `pnpm run -r build` | ||
|
||
2. Start the docker containers | ||
|
||
`pnpm run backend:up` | ||
|
||
3. Start the dev server | ||
|
||
`pnpm run dev` | ||
|
||
4. When done, tear down the backend containers so you can run other examples | ||
|
||
`pnpm run backend:down` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.