npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@aboviq/powersync-solid

v0.2.1

Published

SolidJS helpers, components and hooks for PowerSync

Downloads

112

Readme

@aboviq/powersync-solid

pnpm

The @aboviq/powersync-solid package provides SolidJS hooks and helpers for use with the JavaScript Web SDK. These hooks are designed to support reactivity, and can be used to automatically re-render SolidJS components when query results update or to access PowerSync connectivity status changes.

Quick start

Install it:

npm i @aboviq/powersync-solid
# or
yarn add @aboviq/powersync-solid
# or
pnpm add @aboviq/powersync-solid

Usage

Follow the instructions in the JavaScript Web SDK docs, then setup the PowerSyncContext provider:

import { PowerSyncContext } from '@aboviq/powersync-solid';
import { db } from './db'; // <- the PowerSync database instance
import ListsView from './ListsView';

export default function App() {
  return (
    <PowerSyncContext.Provider value={db}>
      <ListsView />
    </PowerSyncContext.Provider>
  );
}

Then use the hooks and helpers in your components:

// ListsView.tsx
import { useQuery } from '@aboviq/powersync-solid';

export default function ListsView() {
  const [lists] = useQuery('SELECT * FROM lists');

  return (
    <div>
      <Show when={lists.loading}>
        <p>Loading...</p>
      </Show>
      <Switch>
        <Match when={lists.error}>
          <span>Error: {lists.error}</span>
        </Match>
        <Match when={lists()}>
          <div>{JSON.stringify(lists())}</div>
        </Match>
      </Switch>
    </div>
  );
}
// Status.tsx
import { useStatus } from '@aboviq/powersync-solid';

export default function Status() {
  const status = useStatus();

  return (
    <p>
      <Show when={status().connected} fallback="Offline">
        Online
      </Show>{' '}
      (last sync: {status().lastSyncedAt?.toLocaleDateString() ?? 'n/a'})
    </p>
  );
}

Note: the useQuery has the same return type as SolidJS's createResource hook.

Watched Queries

The useQuery hook is designed to automatically re-render the component when any of the following change:

  • PowerSync's connection status (can be easily accessed via the useStatus hook)
  • The query result changes (e.g. when a new record is inserted, updated, or deleted)
  • The query itself changes (e.g. when a query signal is used that is updated with new state)
  • The query's parameters change (e.g. when any parameter is a signal and it's updated with new state)

Example - a reactive query

import { useQuery } from '@aboviq/powersync-solid';

export default function ListsView() {
  const [sortOrder, setSortOrder] = createSignal('ASC');
  const [lists] = useQuery(() => `SELECT * FROM lists ORDER BY name ${sortOrder()}`);

  const toggleSortOrder = () => {
    setSortOrder((sortOrder) => (sortOrder === 'ASC' ? 'DESC' : 'ASC'));
  };

  return (
    <div>
      <Show when={lists.loading}>
        <p>Loading...</p>
      </Show>
      <Switch>
        <Match when={lists.error}>
          <span>Error: {lists.error}</span>
        </Match>
        <Match when={lists()}>
          <button onClick={toggleSortOrder}>Toggle sort order</button>
          <div>{JSON.stringify(lists())}</div>
        </Match>
      </Switch>
    </div>
  );
}

Example - reactive parameters

import { useQuery } from '@aboviq/powersync-solid';

export default function ListsView() {
  const [page, setPage] = createSignal(1);
  const offet = () => (page() - 1) * 10;
  const [lists] = useQuery('SELECT * FROM lists LIMIT 10 OFFSET ?', [offset]);

  const previousPage = () => {
    setPage((page) => page - 1);
  };

  const nextPage = () => {
    setPage((page) => page + 1);
  };

  return (
    <div>
      <Show when={lists.loading}>
        <p>Loading...</p>
      </Show>
      <Switch>
        <Match when={lists.error}>
          <span>Error: {lists.error}</span>
        </Match>
        <Match when={lists()}>
          <button disabled={page() > 1} onClick={previousPage}>
            Previous page
          </button>
          <button disabled={lists()?.length !== 10} onClick={nextPage}>
            Next page
          </button>
          <div>{JSON.stringify(lists())}</div>
        </Match>
      </Switch>
    </div>
  );
}

Using with an ORM

Example - using Kysely

Set up the Kysely database instance according to the PowerSync Kysely ORM docs.

This will also give you automatic TypeScript type inference for your queries.

import { useQuery } from '@aboviq/powersync-solid';
import { db } from './db'; // <- the file where you have configured your Kysely instance

export default function ListsView() {
  const [lists] = useQuery(db.selectFrom('lists').selectAll('lists'));

  return (
    <div>
      <Show when={lists.loading}>
        <p>Loading...</p>
      </Show>
      <Switch>
        <Match when={lists.error}>
          <span>Error: {lists.error}</span>
        </Match>
        <Match when={lists()}>
          <div>{JSON.stringify(lists())}</div>
        </Match>
      </Switch>
    </div>
  );
}

Example - using Kysely with reactive parameters

To use reactive parameters with Kysely, you can pass a function that returns the query to useQuery.

import { useQuery } from '@aboviq/powersync-solid';
import { db } from './db'; // <- the file where you have configured your Kysely instance

export default function ListsView() {
  const [page, setPage] = createSignal(1);
  const [lists] = useQuery(() =>
    db
      .selectFrom('lists')
      .selectAll('lists')
      .limit(10)
      .offset((page() - 1) * 10),
  );

  const previousPage = () => {
    setPage((page) => page - 1);
  };

  const nextPage = () => {
    setPage((page) => page + 1);
  };

  return (
    <div>
      <Show when={lists.loading}>
        <p>Loading...</p>
      </Show>
      <Switch>
        <Match when={lists.error}>
          <span>Error: {lists.error}</span>
        </Match>
        <Match when={lists()}>
          <button disabled={page() > 1} onClick={previousPage}>
            Previous page
          </button>
          <button disabled={lists()?.length !== 10} onClick={nextPage}>
            Next page
          </button>
          <div>{JSON.stringify(lists())}</div>
        </Match>
      </Switch>
    </div>
  );
}

TypeScript types without an ORM

If you're not using an ORM, you can still get TypeScript types for your queries by using the useQuery hook with a type parameter.

import { useQuery } from '@aboviq/powersync-solid';
import type { ListRecord } from './schema'; // <- the file where you have defined your PowerSync database schema

export default function ListsView() {
  const [lists] = useQuery<ListRecord>('SELECT * FROM lists');

  return (
    <div>
      <Show when={lists.loading}>
        <p>Loading...</p>
      </Show>
      <Switch>
        <Match when={lists.error}>
          <span>Error: {lists.error}</span>
        </Match>
        <Match when={lists()}>
          <div>{JSON.stringify(lists())}</div>
        </Match>
      </Switch>
    </div>
  );
}

License

powersync-solid is licensed under the MIT license. See LICENSE for the full license text.