Skip to content

Commit

Permalink
WIP PGlite driver and example
Browse files Browse the repository at this point in the history
  • Loading branch information
samwillis committed Apr 4, 2024
1 parent 2a25ca7 commit 2056e6f
Show file tree
Hide file tree
Showing 27 changed files with 7,660 additions and 156 deletions.
8 changes: 7 additions & 1 deletion clients/typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"./vuejs": "./dist/frameworks/vuejs/index.js",
"./wa-sqlite": "./dist/drivers/wa-sqlite/index.js",
"./tauri": "./dist/drivers/tauri-sqlite/index.js",
"./pglite": "./dist/drivers/pglite/index.js",
"./config": "./dist/config/index.js",
"./debug": "./dist/util/debug/index.js",
"./client/model": "./dist/client/model/index.js",
Expand Down Expand Up @@ -101,6 +102,9 @@
"tauri-postgres": [
"./dist/drivers/tauri-postgres/index.d.ts"
],
"pglite": [
"./dist/drivers/pglite/index.d.ts"
],
"vuejs": [
"./dist/frameworks/vuejs/index.d.ts"
],
Expand Down Expand Up @@ -207,6 +211,7 @@
"zod": "3.21.1"
},
"devDependencies": {
"@electric-sql/pglite": "^0.1.1",
"@electric-sql/prisma-generator": "workspace:*",
"@op-engineering/op-sqlite": ">= 2.0.16",
"@tauri-apps/plugin-sql": "2.0.0-alpha.5",
Expand Down Expand Up @@ -261,8 +266,9 @@
"web-worker": "^1.2.0"
},
"peerDependencies": {
"@op-engineering/op-sqlite": ">= 2.0.16",
"@capacitor-community/sqlite": ">= 5.6.2",
"@electric-sql/pglite": ">= 0.1.1",
"@op-engineering/op-sqlite": ">= 2.0.16",
"@tauri-apps/plugin-sql": "2.0.0-alpha.5",
"embedded-postgres": "16.1.1-beta.9",
"expo-sqlite": ">= 13.0.0",
Expand Down
30 changes: 30 additions & 0 deletions clients/typescript/src/drivers/pglite/adapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Database } from './database'
import { Row } from '../../util/types'
import { Statement } from '../../util'
import { SerialDatabaseAdapter as GenericDatabaseAdapter } from '../generic'
import { RunResult } from '../../electric/adapter'

export class DatabaseAdapter extends GenericDatabaseAdapter {
readonly db: Database

constructor(db: Database) {
super()
this.db = db
}

async _run(statement: Statement): Promise<RunResult> {
console.log('_run:', statement.sql)
const res = await this.db.query(statement.sql, statement.args)
console.log('res:', res)
return {
rowsAffected: res.affectedRows ?? 0,
}
}

async _query(statement: Statement): Promise<Row[]> {
console.log('_query:', statement.sql)
const ret = (await this.db.query<Row>(statement.sql, statement.args)).rows
console.log('ret:', ret)
return ret
}
}
10 changes: 10 additions & 0 deletions clients/typescript/src/drivers/pglite/database.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { PGlite } from '@electric-sql/pglite'

// A bit of a hack, but that lets us reference the actual types of the library
type OriginalDatabase = PGlite

// The relevant subset of the SQLitePlugin database client API
// that we need to ensure the client we're electrifying provides.
export interface Database
extends Pick<OriginalDatabase, 'exec' | 'query' | 'dataDir'> {
}
45 changes: 45 additions & 0 deletions clients/typescript/src/drivers/pglite/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { DatabaseAdapter as DatabaseAdapterI } from '../../electric/adapter'
import { DatabaseAdapter } from './adapter'
import { Database } from './database'
import { ElectricConfig } from '../../config'
import { electrify as baseElectrify, ElectrifyOptions } from '../../electric'
import { WebSocketWeb } from '../../sockets/web'
import { ElectricClient, DbSchema } from '../../client/model'
import { PgBundleMigrator } from '../../migrators/bundle'

export { DatabaseAdapter }
export type { Database }

export const electrify = async <T extends Database, DB extends DbSchema<any>>(
db: T,
dbDescription: DB,
config: ElectricConfig,
opts?: ElectrifyOptions
): Promise<ElectricClient<DB>> => {
const dbName = db.dataDir?.split('/').pop() ?? 'memory'
const adapter = opts?.adapter || new DatabaseAdapter(db)
const migrator =
opts?.migrator || new PgBundleMigrator(adapter, dbDescription.pgMigrations)
const socketFactory = opts?.socketFactory || WebSocketWeb
const prepare = async (_connection: DatabaseAdapterI) => undefined

const configWithDialect = {
...config,
dialect: 'Postgres',
} as const

const client = await baseElectrify(
dbName,
dbDescription,
adapter,
socketFactory,
configWithDialect,
{
migrator,
prepare,
...opts,
}
)

return client
}
3 changes: 3 additions & 0 deletions examples/web-pglite/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ELECTRIC_SERVICE=http://localhost:5133
ELECTRIC_PG_PROXY_PORT=65432
ELECTRIC_IMAGE=electric:local-build
18 changes: 18 additions & 0 deletions examples/web-pglite/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
31 changes: 31 additions & 0 deletions examples/web-pglite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

# Wasm
public/wa-sqlite-async.wasm

# Env files
.env.local
.env.*.local
87 changes: 87 additions & 0 deletions examples/web-pglite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<a href="https://electric-sql.com">
<picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/electric-sql/meta/main/identity/ElectricSQL-logo-light-trans.svg"
/>
<source media="(prefers-color-scheme: light)"
srcset="https://raw.githubusercontent.com/electric-sql/meta/main/identity/ElectricSQL-logo-black.svg"
/>
<img alt="ElectricSQL logo"
src="https://raw.githubusercontent.com/electric-sql/meta/main/identity/ElectricSQL-logo-black.svg"
/>
</picture>
</a>

# ElectricSQL - Web example

This is an example web application using ElectricSQL in the browser with [wa-sqlite](https://github.com/rhashimoto/wa-sqlite).

## Instructions

Clone the [electric-sql/electric](https://github.com/electric-sql/electric) mono-repo and change directory into this example folder:

```sh
git clone https://github.com/electric-sql/electric
cd electric/examples/web-wa-sqlite
```

## Pre-reqs

You need [NodeJS >= 16.11 and Docker Compose v2](https://electric-sql.com/docs/usage/installation/prereqs).
```
## Install
Install the dependencies:
```sh
npm install
```

## Setup

Start Postgres and Electric using Docker (see [running the examples](https://electric-sql.com/docs/examples/notes/running) for more options):

```shell
npm run backend:up
# Or `npm run backend:start` to foreground
```

Note that, if useful, you can connect to Postgres using:

```shell
npm run db:psql
```

Setup your [database schema](https://electric-sql.com/docs/usage/data-modelling):

```shell
npm run db:migrate
```

Generate your [type-safe client](https://electric-sql.com/docs/usage/data-access/client):

```shell
npm run client:generate
# or `yarn client:watch`` to re-generate whenever the DB schema changes
```

## Run

Start your app:

```sh
npm run dev
```

Open [localhost:5173](http://localhost:5173) in your web browser.

## Develop

`./src/Example.tsx` has the main example code. For more information see the:

- [Documentation](https://electric-sql.com/docs)
- [Quickstart](https://electric-sql.com/docs/quickstart)
- [Usage guide](https://electric-sql.com/docs/usage)

If you need help [let us know on Discord](https://discord.electric-sql.com).
19 changes: 19 additions & 0 deletions examples/web-pglite/db/migrations/01-create_items_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* This is an example of an SQL DDL migration. It creates an `items` table and
* then calls an `electric.electrify` procedure to expose the table to the
* ElectricSQL replication machinery.
*
* Note that these statements are applied directly to the *Postgres* database.
* Electric then handles keeping the local SQLite database schema in sync with
* the electrified subset of your Postgres database schema.
*
* See https://electric-sql.com/docs/usage/data-modelling for more information.
*/

-- Create a simple items table.
CREATE TABLE IF NOT EXISTS items (
value TEXT PRIMARY KEY NOT NULL
);

--
-- Electrify the items table
ALTER TABLE items ENABLE ELECTRIC;
13 changes: 13 additions & 0 deletions examples/web-pglite/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Web Example - ElectricSQL</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading

0 comments on commit 2056e6f

Please sign in to comment.