| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Logux is a new way to connect client and server. Instead of sending HTTP requests (e.g., AJAX and GraphQL) it synchronizes log of operations between client, server, and other clients.
This repository contains Logux base components to build web client:
Check demo page for widget UI.
Logux Client is built by Evil Martians, an American design and engineering consultancy for developer tools, AI, and cybersecurity startups.
npm install @logux/core @logux/client nanostoresSee documentation for Logux API.
import { CrossTabClient, badge, badgeEn, log } from '@logux/client'
import { badgeStyles } from '@logux/client/badge/styles'
let userId = document.querySelector('meta[name=user]').content
let token = document.querySelector('meta[name=token]').content
const client = new CrossTabClient({
subprotocol: 1,
server: 'wss://example.com:1337',
userId,
token
})
badge(client, { messages: badgeEn, styles: badgeStyles })
log(client)
client.start()@logux/client/db keeps CRDT tables in a local SQL database (like SQLite in the browser) filled from Logux log. All changes are synchronized as Logux actions, and edit conflicts are resolved with per-field last write wins.
It needs Nano Stores SQL database:
npm install @nanostores/sqlimport { openDb } from '@nanostores/sql'
import { sqlocalDriver } from '@nanostores/sql/sqlocal'
import {
bigint,
createCrdtDatabase,
number,
optional,
string
} from '@logux/client/db'
let db = openDb(sqlocalDriver('app.sqlite'))
let crdt = createCrdtDatabase(client, db, {
migrating(done) {
// Show “Migrating database” loader until done promise
},
async repeat() {
// Ask server to the full client log
// Remove if you store the whole lo locally
}
})
// The third argument defines indexes: a column, an array of columns,
// `{ columns, unique }`, or the whole `CREATE INDEX` statement in `{ sql }`
let user = crdt.table(
'user',
{
age: optional(number()),
createdAt: bigint({ default: () => Date.now() }),
name: string()
},
['name', ['age', 'createdAt DESC']]
)
await crdt.ready
let id = await user.create({ name: 'Ann' })
await user.update(id, { age: 30 })
let $adults = user.select`WHERE "age" >= ${18} ORDER BY "name"`
// Arrays create batch actions, applied in a single SQL query
let ids = await user.create([{ name: 'Ben' }, { name: 'Cat' }])
await user.update(ids, { age: 20 })
await user.delete(ids)Custom actions are applied to the database by your callback. Action types in the callback come from defineAction():
import { defineAction } from '@logux/actions'
let userRenamed = defineAction<{
id: string
name: string
type: 'user/renamed'
}>('user/renamed')
let renameUser = crdt.action(userRenamed, async (tx, action, meta) => {
// change() keeps per-field last write wins, unlike your own UPDATE
await user.change(tx, action.id, { name: action.name }, meta)
})
await renameUser({ id, name: 'New' })The same database can keep the Logux log itself:
import { CrossTabClient } from '@logux/client'
import { SqlLogStore } from '@logux/client/db'
const client = new CrossTabClient({
…,
store: new SqlLogStore(db)
})encryptActions() encrypts actions before sending them to the server, so the server can’t read users’ data. Pass a password or an AES CryptoKey and list action types to be kept unencrypted.
import { encryptActions } from '@logux/client'
encryptActions(client, localStorage.getItem('userPassword'), {
ignore: ['server/public']
})| Back | FazBrowse Home | New Git URL |