diff --git a/src/content/doc-sdk-javascript/frameworks/react.mdx b/src/content/doc-sdk-javascript/frameworks/react.mdx index 50fe901f5..bdaded514 100644 --- a/src/content/doc-sdk-javascript/frameworks/react.mdx +++ b/src/content/doc-sdk-javascript/frameworks/react.mdx @@ -5,10 +5,23 @@ title: React | JavaScript | SDK | Frameworks description: The SurrealDB SDK for JavaScript can also be used in your React applications to interact with your SurrealDB instance. --- +import LightReact from "@img/icon/light/reactjs.png"; +import DarkReact from "@img/icon/dark/reactjs.png"; + import Image from "@components/Image.astro"; import Tabs from "@components/Tabs/Tabs.astro"; import TabItem from "@components/Tabs/TabItem.astro"; + + # React [React](https://react.dev/) is a popular JavaScript library for building user interfaces. The SurrealDB SDK for JavaScript can also be used in your React applications to interact with your SurrealDB instance. diff --git a/src/content/doc-sdk-javascript/frameworks/solidjs.mdx b/src/content/doc-sdk-javascript/frameworks/solidjs.mdx new file mode 100644 index 000000000..0a1419a25 --- /dev/null +++ b/src/content/doc-sdk-javascript/frameworks/solidjs.mdx @@ -0,0 +1,397 @@ +--- +sidebar_position: 1 +sidebar_label: SolidJS +title: SolidJS | JavaScript | SDK | Frameworks +description: The SurrealDB SDK for JavaScript can also be used in your SolidJS applications to interact with your SurrealDB Instance. +--- + +import LightSolid from "@img/icon/light/solidjs.png"; +import DarkSolid from "@img/icon/dark/solidjs.png"; + +import Image from "@components/Image.astro"; +import Tabs from "@components/Tabs/Tabs.astro"; +import TabItem from "@components/Tabs/TabItem.astro"; + + + +# SolidJS + +[SolidJS](https://docs.solidjs.com/) is a modern JavaScript framework designed to build responsive and high-performing user interfaces (UI). It prioritizes a simple and predictable development experience, making it a great choice for developers of all skill levels. + +The SurrealDB SDK for JavaScript can also be used in your SolidJS applications to interact with your SurrealDB Instance. + +In this guide, we will walk you through setting up and querying your first project with the SurrealDB SDK for SolidJS. + +## Prerequisites + +This guide assumes the following: +- You have a basic understanding of SolidJS. +- You have installed SurrealDB on your machine + +## Setup + +### Install the SDK + +First, install the [SurrealDB SDK](https://npmjs.com/package/surrealdb) using your favorite package manager: + + + + ```bash + bun install surrealdb + ``` + + + ```bash + npm install --save surrealdb + ``` + + + ```bash + yarn add surrealdb + ``` + + + ```bash + pnpm install surrealdb + ``` + + + +> [!IMPORTANT] +> The SurrealDB SDK for JavaScript is also available in the JSR registry as [`@surrealdb/surrealdb`](https://jsr.io/@surrealdb/surrealdb). + +## Initialize the SDK + +After installing the SDK, import it into your project. We recommend initializing the SDK in a [Context Provider](https://solidjs.com/docs/components/context) in order to expose it throughout your application. This makes the client accessible anywhere in your component tree, simplifies cleanup, and provides built-in state management for connection success or failure. + +### 1. Install Required Packages + +In addition to `surrealdb`, we recommend using [@tanstack/solid-query](https://tanstack.com/query/latest) for managing manage the asynchronous connection state to the SurrealDB database. + +Specifically, `createMutation` to create a managed mutation that handles the connection lifecycle. It provides built-in state management for the async operation, automatically tracking loading states (isError, error), and provides utilities like reset to handle errors and retry operations if needed. + +You can install the package using your favorite package manager: + + + + ```bash + bun install @tanstack/solid-query + ``` + + + ```bash + npm install --save @tanstack/solid-query + ``` + + + ```bash + yarn add @tanstack/solid-query + ``` + + + ```bash + pnpm install @tanstack/solid-query + ``` + + + +### 2. Creating the Context Provider + +The best way to manage the connection state is to create a context provider that will handle the connection and provide the client to the rest of the application. In SolidJS, we can use the `createContext` function to create a context and the `createStore` function to manage the state. + +First, create a new file, e.g., `SurrealProvider.tsx`, which will contain the context provider and hooks for accessing the SurrealDB client. You can copy the following code, which takes care of managing the connection. + +Feel free to make any changes to fit your project structure and coding style. + +> [!NOTE] +> We do recommend adding this in a `lib/providers` directory, but you can place it wherever you see fit. + +```ts title= "src/lib/providers/SurrealProvider.tsx" +import { + useContext, + createContext, + JSX, + createSignal, + createEffect, + onCleanup, + Accessor, + onMount +} from "solid-js"; +import Surreal from "surrealdb"; +import { createMutation } from "@tanstack/solid-query"; +import { createStore } from "solid-js/store"; + +interface SurrealProviderProps { + children: JSX.Element; + /** The database endpoint URL */ + endpoint: string; + /** Optional existing Surreal client */ + client?: Surreal; + /* Optional connection parameters */ + params?: Parameters[1]; + /** Auto connect on component mount, defaults to true */ + autoConnect?: boolean; +} + +interface SurrealProviderState { + /** The Surreal instance */ + client: Accessor; + /** Whether the connection is pending */ + isConnecting: Accessor; + /** Whether the connection was successfully established */ + isSuccess: Accessor; + /** Whether the connection rejected in an error */ + isError: Accessor; + /** The connection error, if present */ + error: Accessor; + /** Connect to the Surreal instance */ + connect: () => Promise; + /** Close the Surreal instance */ + close: () => Promise; +} + +// Store interface to track the Surreal instance and connection status +interface SurrealProviderStore { + instance: Surreal; + status: "connecting" | "connected" | "disconnected"; +} + +const SurrealContext = createContext(); + +export function SurrealProvider(props: SurrealProviderProps) { + // Initialize store with either provided client or new instance + const [store, setStore] = createStore({ + instance: props.client ?? new Surreal(), + status: "disconnected" + }); + + // Use TanStack Query's mutation hook to manage the async connection state + const { + mutateAsync, + isError, + error, + reset + } = createMutation(() => ({ + mutationFn: async () => { + setStore("status", "connecting"); + await store.instance.connect(props.endpoint, props.params); + } + })); + + // Effect to handle auto-connection and cleanup + createEffect(() => { + // Connect automatically if autoConnect is true + if(props.autoConnect) { + mutateAsync(); + } + + // Cleanup function to reset mutation state and close connection + onCleanup(() => { + reset(); + store.instance.close(); + }); + }); + + // Subscribe to connection events when component mounts + onMount(() => { + // Update store status when connection is established + store.instance.emitter.subscribe("connected", () => { + setStore("status", "connected"); + }); + + // Update store status when connection is lost + store.instance.emitter.subscribe("disconnected", () => { + setStore("status", "disconnected"); + }); + }); + + // Create the value object that will be provided through context + const providerValue: SurrealProviderState = { + client: () => store.instance, + close: () => store.instance.close(), + connect: mutateAsync, + error: () => error, + isConnecting: () => store.status === "connecting", + isError: () => isError, + isSuccess: () => store.status === "connected" + }; + + return ( + + {props.children} + + ); +} + +// Custom hook to access the SurrealDB context +export function useSurreal(): SurrealProviderState { + const context = useContext(SurrealContext); + + // Ensure the hook is used within a provider + if(!context) { + throw new Error("useSurreal must be used within a SurrealProvider"); + } + + return context; +} +``` + +### 3. Wrap Your Application with the Provider + +After creating the SurrealProvider, you'll need to wrap your application's root component with it. Here's an example of how to set up your `App.tsx` component with the necessary providers. We're using both the `QueryClientProvider` for managing async state and our custom `SurrealProvider` for database connectivity, along with routing and authentication setup: + +```tsx title="src/App.tsx" +import type { Component } from 'solid-js'; +import { Router, Route } from "@solidjs/router"; +import { SurrealProvider } from './lib/providers/SurrealProvider'; +import { QueryClientProvider } from '@tanstack/solid-query'; +import { tanstackClient } from './lib/query-client'; +import { AuthProvider } from './lib/providers/auth'; +import { AppLayout } from './components/layout/app'; + + +const App: Component = () => { + return ( + + + + + + ... your routes here + + + + + + ); +}; + +export default App; +``` + +### 4. Use the `useSurreal` Hook in Your Components + +Now you can use the `useSurreal` hook in your components to access the SurrealDB client. For example, you can create an `AuthProvider` to handle authentication and user management. + +```ts title="src/lib/providers/AuthProvider.tsx" +import { Accessor, createContext, ParentProps, useContext } from "solid-js"; +import { createStore } from "solid-js/store"; +import { useSurreal } from "../lib/providers/SurrealProvider"; + +interface AuthProviderState { + user: Accessor; + login: (email: string, password: string) => Promise; + register: (data: Omit) => Promise; + logout: () => Promise; +} + +interface AuthProviderStore { + user: UserRecord | undefined; + status: "idle" | "signing-in" | "signing-up" | "signing-out" | "signed-in" | "signed-up"; +} + +const AuthContext = createContext(); + +export function AuthProvider(props: ParentProps) { + + const { + client, + close, + connect + } = useSurreal(); + + const [store, setStore] = createStore({ + user: undefined, + status: "idle" + }); + + const login = async (email: string, password: string) => { + const db = client(); + + setStore("status", "signing-in"); + + await db.signin({ + access: "user", + namespace: "surrealdb", + database: "pollwebapp", + variables: { + email: email, + pass: password + } + }); + + setStore("status", "signed-up"); + }; + + const register = async (data: Omit) => { + const db = client(); + + setStore("status", "signing-up"); + + await db.signup({ + access: "user", + namespace: "surrealdb", + database: "pollwebapp", + variables: data + }); + + setStore("status", "signed-up"); + }; + + const logout = async () => { + + setStore("status", "signing-out"); + + await close(); + await connect(); + + setStore("status", "idle"); + }; + + const providerValue: AuthProviderState = { + user: () => store.user, + login, + register, + logout + }; + + return ( + + {props.children} + + ); +} + +export function useAuth(): AuthProviderState { + const ctx = useContext(AuthContext); + + if(!ctx) { + throw new Error("useAuth must be used within an AuthProvider"); + } + + return ctx; +} +``` + +## Next steps + +Now that you have SurrealDB integrated into your SolidJS project, you're ready to start building! To learn more about interacting with your database: + +- Explore the [JavaScript SDK reference](/docs/sdk/javascript/methods) for a complete list of available methods and features +- See SurrealDB in action by checking out our SolidJS example projects in the [examples section](/docs/sdk/javascript#example-projects) +- Join our [Discord community](https://discord.com/invite/surrealdb) to connect with other developers building with SolidJS and SurrealDB \ No newline at end of file diff --git a/src/content/doc-sdk-javascript/index.mdx b/src/content/doc-sdk-javascript/index.mdx index a9a25cd42..b377c3b66 100644 --- a/src/content/doc-sdk-javascript/index.mdx +++ b/src/content/doc-sdk-javascript/index.mdx @@ -97,6 +97,15 @@ To contribute to the SDK code, submit an Issue or Pull Request in the [surrealdb dark: DarkReact, }} /> + -