Skip to content

Commit

Permalink
example: debug through-the-db pattern.
Browse files Browse the repository at this point in the history
  • Loading branch information
thruflo committed Dec 3, 2024
1 parent ed5b394 commit 3f4ec4d
Show file tree
Hide file tree
Showing 9 changed files with 437 additions and 64 deletions.
12 changes: 3 additions & 9 deletions examples/write-patterns/patterns/3-combine-on-read/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import React, { useState } from 'react'
import { v4 as uuidv4 } from 'uuid'

import { PGlite } from '@electric-sql/pglite'
import { PGliteWithLive, live } from '@electric-sql/pglite/live'
import {
PGliteProvider,
useLiveQuery,
usePGlite,
} from '@electric-sql/pglite-react'
import { electricSync } from '@electric-sql/pglite-sync'

import api from '../../shared/app/client'
import pglite from '../../shared/app/db'

import localSchemaMigrations from './local-schema.sql?raw'

const ELECTRIC_URL = import.meta.env.ELECTRIC_URL || 'http://localhost:3000'
Expand All @@ -22,14 +21,9 @@ type Todo = {
created_at: Date
}

const pglite: PGliteWithLive = await PGlite.create({
extensions: {
electric: electricSync(),
live,
},
})
await pglite.exec(localSchemaMigrations)

// This starts the read path sync using Electric.
await pglite.electric.syncShapeToTable({
shape: {
url: `${ELECTRIC_URL}/v1/shape`,
Expand Down
147 changes: 147 additions & 0 deletions examples/write-patterns/patterns/4-through-the-db/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import React from 'react'
import { v4 as uuidv4 } from 'uuid'

import {
PGliteProvider,
useLiveQuery,
usePGlite,
} from '@electric-sql/pglite-react'

import pglite from '../../shared/app/db'

import SyncChanges from './sync'
import localSchemaMigrations from './local-schema.sql?raw'

const ELECTRIC_URL = import.meta.env.ELECTRIC_URL || 'http://localhost:3000'

type Todo = {
id: string
title: string
completed: boolean
created_at: Date
}

// Note that the resources defined in the schema for this pattern
// are all suffixed with `p4_`.
await pglite.exec(localSchemaMigrations)

// This starts the read path sync using Electric.
await pglite.electric.syncShapeToTable({
shape: {
url: `${ELECTRIC_URL}/v1/shape`,
table: 'todos',
},
shapeKey: 'todos',
table: 'p4_todos_synced',
primaryKey: ['id'],
})

// This starts the write path sync of changes captured in the triggers from
// writes to the local DB.
const syncChanges = new SyncChanges(pglite)
syncChanges.start()

export default function Wrapper() {
return (
<PGliteProvider db={pglite}>
<ThroughTheDB />
</PGliteProvider>
)
}

function ThroughTheDB() {
const db = usePGlite()
const results = useLiveQuery<Todo>('SELECT * FROM p4_todos ORDER BY created_at')

async function createTodo(event: React.FormEvent) {
event.preventDefault()

const form = event.target as HTMLFormElement
const formData = new FormData(form)
const title = formData.get('todo') as string

await db.sql`
INSERT INTO p4_todos (
id,
title,
completed,
created_at
)
VALUES (
${uuidv4()},
${title},
${false},
${new Date()}
)
`

form.reset()
}

async function updateTodo(todo: Todo) {
const { id, completed } = todo

await db.sql`
UPDATE p4_todos
SET completed = ${!completed}
WHERE id = ${id}
`
}

async function deleteTodo(event: React.MouseEvent, todo: Todo) {
event.preventDefault()

await db.sql`
DELETE FROM p4_todos
WHERE id = ${todo.id}
`
}

if (results === undefined) {
return <div className="loading">Loading &hellip;</div>
}

const todos = results.rows

// The template below the heading is identical to the other patterns.

// prettier-ignore
return (
<div id="optimistic-state" className="example">
<h3>
<span className="title">
4. Through the DB sync
</span>
</h3>
<ul>
{todos.map((todo: Todo) => (
<li key={todo.id}>
<label>
<input type="checkbox" checked={todo.completed}
onChange={() => updateTodo(todo)}
/>
<span className={`title ${ todo.completed ? 'completed' : '' }`}>
{ todo.title }
</span>
</label>
<a href="#delete" className="close"
onClick={(event) => deleteTodo(event, todo)}>
&#x2715;</a>
</li>
))}
{todos.length === 0 && (
<li>All done 🎉</li>
)}
</ul>
<form onSubmit={createTodo}>
<input type="text" name="todo"
placeholder="Type here &hellip;"
required
/>
<button type="submit">
Add
</button>
</form>
</div>
)
}
Loading

0 comments on commit 3f4ec4d

Please sign in to comment.