Skip to content

Commit

Permalink
example: working 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 3f4ec4d commit 7f6f140
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 12 deletions.
4 changes: 2 additions & 2 deletions examples/write-patterns/patterns/4-through-the-db/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ await pglite.electric.syncShapeToTable({
url: `${ELECTRIC_URL}/v1/shape`,
table: 'todos',
},
shapeKey: 'todos',
shapeKey: 'p4_todos',
table: 'p4_todos_synced',
primaryKey: ['id'],
})
Expand Down Expand Up @@ -110,7 +110,7 @@ function ThroughTheDB() {
<div id="optimistic-state" className="example">
<h3>
<span className="title">
4. Through the DB sync
4. Through the DB
</span>
</h3>
<ul>
Expand Down
2 changes: 2 additions & 0 deletions examples/write-patterns/patterns/4-through-the-db/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export default class LocalChangeSynchronizer {
console.log('start')

this.#unsubscribe = await this.#db.listen('p4_changes', this.handle.bind(this))

this.process()
}

/*
Expand Down
14 changes: 8 additions & 6 deletions examples/write-patterns/shared/app/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { PGlite } from '@electric-sql/pglite'
import { PGliteWithLive, live } from '@electric-sql/pglite/live'
import { electricSync } from '@electric-sql/pglite-sync'

const pglite: PGliteWithLive = await PGlite.create({
extensions: {
electric: electricSync(),
live,
},
})
const pglite: PGliteWithLive = await PGlite.create(
'idb://electric-write-patterns', {
extensions: {
electric: electricSync(),
live
}
}
)

export default pglite
71 changes: 68 additions & 3 deletions examples/write-patterns/shared/backend/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const idSchema = z.string().uuid()
const createSchema = z.object({
id: z.string().uuid(),
title: z.string(),
created_at: z.string(),
created_at: z.string()
})
const updateSchema = z.object({
completed: z.boolean()
Expand All @@ -37,7 +37,11 @@ const createTodo = async (id, title, created_at) => {
VALUES ($1, $2, false, $3)
`

const params = [id, title, created_at]
const params = [
id,
title,
created_at
]

return await db.query(sql, params)
}
Expand All @@ -63,7 +67,7 @@ const deleteTodo = async (id) => {
return await db.query(sql, params)
}

// Expose the API.
// Expose the shared REST API to create, update and delete todos.

app.post(`/todos`, async (req, res) => {
let data
Expand Down Expand Up @@ -123,6 +127,67 @@ app.delete(`/todos/:id`, async (req, res) => {
return res.status(200).json({ status: 'OK' })
})

// And expose a `POST /changes` route specifically to support the
// through the DB sync pattern.

const transactionsSchema = z.array(
z.object({
id: z.string(),
changes: z.array(
z.object({
operation: z.string(),
value: z.object({
id: z.string().uuid(),
title: z.string().optional(),
completed: z.boolean().optional(),
created_at: z.string().optional()
})
})
)
})
)

app.post(`/changes`, async (req, res) => {
let data
try {
data = transactionsSchema.parse(req.body)
}
catch (err) {
return res.status(400).json({ errors: err.errors })
}

try {
await db.query('BEGIN')

data.forEach((tx) => {
tx.changes.forEach(({operation, value}) => {
switch (operation) {
case 'insert':
createTodo(value.id, value.title, value.created_at)
break

case 'update':
updateTodo(value.id, value.completed)
break

case 'delete':
deleteTodo(value.id)
break
}
})
})

await db.query('COMMIT')
}
catch (err) {
await db.query('ROLLBACK')

return res.status(500).json({ errors: err })
}

return res.status(200).json({ status: 'OK' })
})

// Start the server
app.listen(PORT, () => {
console.log(`Server listening at http://localhost:${PORT}`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS todos (
created_at TIMESTAMP WITH TIME ZONE NOT NULL
);

-- Insert a todo to get started.
-- Insert some todos to get started.
INSERT INTO todos (
id,
title,
Expand Down

0 comments on commit 7f6f140

Please sign in to comment.