npm.io
4.0.372 • Published yesterday

prostgles-client

Licence
MIT
Version
4.0.372
Deps
2
Size
344 kB
Vulns
0
Weekly
0
Stars
1

prostgles-client

Isomorphic TypeScript client for PostgreSQL

GitHub license npm version Known Vulnerabilities Tests

Features

  • Real-time data synchronization - Subscribe to database changes with WebSocket support
  • End-to-end type safety - Auto-generated TypeScript types from your database schema
  • React hooks - First-class React support with useFind, useSubscribe and useSync
  • Isomorphic - Works in Node.js and browsers
  • Zero boilerplate - Direct database access without writing SQL
  • Relational queries - Join tables with intuitive syntax

Installation

npm/yarn

$ npm install prostgles-client socket.io-client

CDN

<head>
  <script
    src="https://unpkg.com/socket.io-client@3.0.3/dist/socket.io.min.js"
    type="text/javascript"
  ></script>
  <script
    src="https://unpkg.com/prostgles-client@latest/dist/index.js"
    type="text/javascript"
  ></script>
</head>

Quick Start

React hooks

Subscribe to data changes with automatic re-renders:

import { useProstglesClient } from "prostgles-client/dist/prostgles";
import type { DBGeneratedSchema } from "@common/DBGeneratedSchema";

const App = () => {
  const client = useProstglesClient<DBGeneratedSchema>({ socketOptions: { path: "/ws-api" } });

  if(client.isLoading) return "Loading...";
  if(client.hasError) return <>Error: {client.error}</>;

  return <UserPosts dbo={client.dbo} />
}

const UserPosts = ({ dbo }: { dbo:  }) => {

  const { data: user, isLoading } = dbo.users.useSubscribeOne(
    { id: 1 },
    {
      select: {
        id: 1,
        first_name: 1,
        email: 1,
        latest_posts: {
          $leftJoin: ["posts"],
          orderBy: { created: -1 }
        }
      }
    }
  );

  if(isLoading) return "Loading ..."

  return (
    <div>
      <h1>{user.first_name}</h1>
      <p>{user.email}</p>
      <h2>Latest Posts</h2>
      <ul>
        {user.latest_posts.map(post => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}
Vanilla JavaScript
prostgles({
  socket: io(),
  onReady: async (db) => {
    const latest_posts = await db.posts.find({}, { orderBy: { created: -1 } });

    // Insert data
    await dbo.posts.insert({
      title: "Hello World",
      content: "My first post",
      published: true,
    });
  },
});

Type Safety

Paired with prostgles-server, types are automatically generated from your database schema:

Learn more in the Prostgles documentation.

API Overview

Query Methods
  • find() - Fetch multiple records
  • findOne() - Fetch a single record
  • useFind() - React hook for find()
  • useFindOne() - React hook for findOne()
  • count() - Count records
  • useCount() - React hook for count()
  • insert() - Insert new records
  • update() - Update existing records
  • delete() - Delete records
  • upsert() - Insert or update records
Real-time Methods
  • subscribe() - Subscribe to multiple records
  • subscribeOne() - Subscribe to a single record
  • sync() - Two-way sync for multiple records (local changes pushed to server)
  • syncOne() - Two-way sync for a single record (local changes pushed to server)
  • useSubscribe() - React hook for subscribe()
  • useSubscribeOne() - React hook for subscribeOne()
  • useSync() - React hook for sync()
  • useSyncOne() - React hook for syncOne()
Sync vs Subscribe

The key difference between sync and subscribe methods:

  • Subscribe (subscribe, subscribeOne) - One-way data flow from server to client. Receives updates when data changes on the server.
  • Sync (sync, syncOne) - Two-way data flow. Allows local optimistic updates that are automatically synced back to the server, while also receiving server updates.
// Sync: locally modified data is propagated instantly to the client
const { data: draftPost, isLoading } = dbo.posts.useSyncOne(
  { published: false },
  { handlesOnData: true },
);
if (isLoading) return "Loading...";
if (!draftPost) {
  return <button onClick={() => dbo.posts.insert({ published: false })}>Create new post</button>;
}
return (
  <form>
    <input
      type="text"
      placeholder="Title"
      value={draftPost.title}
      onChange={(e) => draftPost.$update({ title: e.target.value })}
    />
    <input
      type="text"
      placeholder="Content"
      value={draftPost.content}
      onChange={(e) => draftPost.$update({ content: e.target.value })}
    />
    <button onClick={() => draftPost.$update({ published: true })}>Publish</button>
  </form>
);

Documentation

Full API Documentation Examples Server Setup Guide

License

MIT

Keywords