fireproof-storage / fireproof

Realtime database, runs anywhere. Install Fireproof in your front-end app or edge function, and sync data via any backend.
https://fireproof.storage
Other
281 stars 16 forks source link

feat: adds solid-js support #53

Closed thedanchez closed 7 months ago

thedanchez commented 9 months ago

Summary

Say hello to @fireproof/solid-js -- the official SolidJS adapter for Fireproof.

Light up your data with an embedded live database for your SolidJS web app!

Overview

This PR adds support for SolidJS as a first-class citizen like React. The intent is to create another npm package @fireproof/solid-js that consumers can import like so:

import { createFireproof } from "@fireproof/solid-js"`

The SolidJS hook interface (prefixed with create per Solid conventions) mirror its React counterpart (prefixed with use) with some changes to adapt to Solid -- the main one being, you receive accessor functions instead of discrete values from the SolidJS hook as there are no re-renders in Solid as there are in React.

import { createFireproof } from "@fireproof/solid-js"`

type Todo = { text: string; date: number; completed: boolean };

// You can have a global database that any Solid component can import as an alternative to Context APIs
export const TodoDB = createFireproof('TodoDB');

function App() {
  // completedTodos is an accessor/getter function (i.e. completedTodos()) instead of a value
  const completedTodos = TodoDB.createLiveQuery<Todo>('completed', { limit: 10 })
  const [todo, setTodo, saveTodo] = TodoDB.createDocument<Todo>(() => ({
    text: '',
    date: Date.now(),
    completed: false,
  }));
}

Other thing to note is also making heavy use of JSDoc comments to provide as much guidance to consumers of the hooks and their usage to lift the DX a bit.

thedanchez commented 9 months ago

@jchris would love to get your thoughts on the direction of this PR as I used the existing react package as a springboard for all of this.

Also noticed some TODO comments that were lying around in that package under the useDocument/createDocument method.

Not sure if these need to be addressed in the underlying @fireproof/core package or if that's something to address at this layer.

jchris commented 9 months ago

Wow. Thanks for doing this. I haven't written solid yet (excited to try!) so I'll be relying on the community to review this. If there are quick steps to try it out in an app that would be super helpful. I'd also love to announce it on the blog when it is ready.

thedanchez commented 9 months ago

Wow. Thanks for doing this. I haven't written solid yet (excited to try!) so I'll be relying on the community to review this. If there are quick steps to try it out in an app that would be super helpful. I'd also love to announce it on the blog when it is ready.

Would be more than happy to show you around with Solid. I always tell people that if you know React, you can pick up Solid within a week. Many things they share in common and it's just about shifting your mental model a bit alongside embracing what Solid does for you out of the box.

My personal opinion as far as frontend libraries go -- Solid is what React should have been. You may hear some use the analogy "What Svelte is to Vue, Solid is to React" 🙂

Definitely intend to add an example Solid app to the repo showcasing things though!

thedanchez commented 8 months ago

This PR is dependent on https://github.com/fireproof-storage/fireproof/pull/64 -- so that should be merged first

jchris commented 8 months ago

is this ready to review again or are there pre-requisites still in flight?

thedanchez commented 8 months ago

is this ready to review again or are there pre-requisites still in flight?

Only thing missing is getting the tests working alongside fleshing out the examples a bit further showing off some more API use-cases 😄

thedanchez commented 8 months ago

@jchris I'm going about kicking the tires in the example Solid app and noticed an odd behavior when trying to use createLiveQuery. Not sure if it's a bug on the Solid API side or something more fundamental.

The issue is, whenever I navigate to the Todo link in the SolidJS example app, I don't get any results back from createLiveQuery when navigating to the page, even though I have documents stored. However, when I refresh the page while staying on the Todo link, I'm able to get results back.

Any thoughts on what could cause this? It doesn't look like the db.subscribe call invokes the refreshRows when navigating to the page for some reason.

jchris commented 8 months ago

I get this when I run the tests. Is it expected?

 FAIL  src/__tests__/createFireproof.test.tsx > HOOK: createFireproof > can use createLiveQuery
 FAIL  src/__tests__/createLiveQuery.test.tsx > HOOK: createLiveQuery > can be used as expected
Error: Unknown type, must be binary type
 ❯ Hasher.digest ../../node_modules/.pnpm/multiformats@12.1.3/node_modules/multiformats/src/hashes/hasher.js:47:13
 ❯ encode ../../node_modules/.pnpm/multiformats@12.1.3/node_modules/multiformats/src/block.js:182:29
 ❯ encodeEventBlock ../../node_modules/.pnpm/@web3-storage+pail@0.4.0/node_modules/@web3-storage/pail/src/clock/index.js:98:32
 ❯ Function.create ../../node_modules/.pnpm/@web3-storage+pail@0.4.0/node_modules/@web3-storage/pail/src/clock/index.js:68:12
 ❯ Module.put ../../node_modules/.pnpm/@web3-storage+pail@0.4.0/node_modules/@web3-storage/pail/src/crdt/index.js:30:36
 ❯ applyBulkUpdateToCrdt ../fireproof/src/database.ts:153:16
 ❯ ../fireproof/src/database.ts:949:26
 ❯ EncryptedBlockstore.transaction ../encrypted-blockstore/src/transaction.ts:773:18
 ❯ CRDT.bulk ../fireproof/src/database.ts:947:18
 ❯ ../fireproof/src/database.ts:1014:14
jchris commented 8 months ago

also getting:

[plugin:vite:import-analysis] Failed to resolve entry for package "@fireproof/solid-js". The package may have incorrect main/module/exports specified in its package.json.
/Users/jchris/Documents/GitHub/fireproof/examples/solid-js/src/pages/TodoList.tsx

could it be something about the binding on database().put(?

thedanchez commented 8 months ago

I get this when I run the tests. Is it expected?

 FAIL  src/__tests__/createFireproof.test.tsx > HOOK: createFireproof > can use createLiveQuery
 FAIL  src/__tests__/createLiveQuery.test.tsx > HOOK: createLiveQuery > can be used as expected
Error: Unknown type, must be binary type
 ❯ Hasher.digest ../../node_modules/.pnpm/multiformats@12.1.3/node_modules/multiformats/src/hashes/hasher.js:47:13
 ❯ encode ../../node_modules/.pnpm/multiformats@12.1.3/node_modules/multiformats/src/block.js:182:29
 ❯ encodeEventBlock ../../node_modules/.pnpm/@web3-storage+pail@0.4.0/node_modules/@web3-storage/pail/src/clock/index.js:98:32
 ❯ Function.create ../../node_modules/.pnpm/@web3-storage+pail@0.4.0/node_modules/@web3-storage/pail/src/clock/index.js:68:12
 ❯ Module.put ../../node_modules/.pnpm/@web3-storage+pail@0.4.0/node_modules/@web3-storage/pail/src/crdt/index.js:30:36
 ❯ applyBulkUpdateToCrdt ../fireproof/src/database.ts:153:16
 ❯ ../fireproof/src/database.ts:949:26
 ❯ EncryptedBlockstore.transaction ../encrypted-blockstore/src/transaction.ts:773:18
 ❯ CRDT.bulk ../fireproof/src/database.ts:947:18
 ❯ ../fireproof/src/database.ts:1014:14

Just updated the PR to resolve this error 🎉

Now I need to get the tests for createLiveQuery to pass

thedanchez commented 8 months ago

Also, forgot to put in the comments, but to get things going you have to run pnpm build before running pnpm test:solid or pnpm start:solid

jchris commented 8 months ago

I rebased it to main for you, feel free to rollback if that's a PITA

thedanchez commented 7 months ago

After this gets accepted and merged, I'll be looking to add another example app showing use of @fireproof/solid-js in a Solid Start project to make sure we cover all of our bases. Also definitely need to spruce up the README to cover the variety of configuration use-cases.