diff --git a/tanstack-query/.eslintrc.cjs b/tanstack-query/.eslintrc.cjs
new file mode 100644
index 0000000..d6c9537
--- /dev/null
+++ b/tanstack-query/.eslintrc.cjs
@@ -0,0 +1,18 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true },
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:react-hooks/recommended',
+ ],
+ ignorePatterns: ['dist', '.eslintrc.cjs'],
+ parser: '@typescript-eslint/parser',
+ plugins: ['react-refresh'],
+ rules: {
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ },
+}
diff --git a/tanstack-query/README.md b/tanstack-query/README.md
new file mode 100644
index 0000000..8993943
--- /dev/null
+++ b/tanstack-query/README.md
@@ -0,0 +1,34 @@
+# How to Use SurrealDB with Tanstack Query
+
+This tutorial will guide you through the steps to integrate SurrealDB with a React application using Tanstack Query (formerly React Query). We'll cover setting up the database, fetching data, and displaying it in a React component.
+
+## Prerequisites
+
+- Node.js and npm installed
+- Basic knowledge of React and TypeScript
+- SurrealDB installed
+
+## Step 1: Setting Up SurrealDB
+
+First, ensure that SurrealDB is installed and running.
+
+```bash
+surreal start --user root --pass root
+```
+
+## Step 2: Create the React Application
+
+Create a new React application using Create React App with TypeScript. In this example we use Vite.
+
+```bash
+npm create vite@latest surrealdb-query --template react-ts
+cd surrealdb-query
+```
+
+## Step 3: Install Dependencies
+
+Install Tanstack Query (React Query) and SurrealDB client.
+
+```bash
+npm install @tanstack/react-query surrealdb.js
+```
\ No newline at end of file
diff --git a/tanstack-query/bun.lockb b/tanstack-query/bun.lockb
new file mode 100755
index 0000000..51e16da
Binary files /dev/null and b/tanstack-query/bun.lockb differ
diff --git a/tanstack-query/index.html b/tanstack-query/index.html
new file mode 100644
index 0000000..0487cef
--- /dev/null
+++ b/tanstack-query/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ SurrealDB Query
+
+
+
+
+
+
diff --git a/tanstack-query/package.json b/tanstack-query/package.json
new file mode 100644
index 0000000..b77da41
--- /dev/null
+++ b/tanstack-query/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "surrealdb-query",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@tanstack/react-query": "^5.51.16",
+ "@tanstack/react-query-devtools": "^5.51.16",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "surrealdb.js": "^1.0.0-beta.9"
+ },
+ "devDependencies": {
+ "@types/react": "^18.3.3",
+ "@types/react-dom": "^18.3.0",
+ "@typescript-eslint/eslint-plugin": "^7.15.0",
+ "@typescript-eslint/parser": "^7.15.0",
+ "@vitejs/plugin-react": "^4.3.1",
+ "eslint": "^8.57.0",
+ "eslint-plugin-react-hooks": "^4.6.2",
+ "eslint-plugin-react-refresh": "^0.4.7",
+ "typescript": "^5.2.2",
+ "vite": "^5.3.4"
+ }
+}
diff --git a/tanstack-query/public/vite.svg b/tanstack-query/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/tanstack-query/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tanstack-query/src/App.css b/tanstack-query/src/App.css
new file mode 100644
index 0000000..027945e
--- /dev/null
+++ b/tanstack-query/src/App.css
@@ -0,0 +1,6 @@
+#root {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
\ No newline at end of file
diff --git a/tanstack-query/src/App.tsx b/tanstack-query/src/App.tsx
new file mode 100644
index 0000000..c19e0c9
--- /dev/null
+++ b/tanstack-query/src/App.tsx
@@ -0,0 +1,68 @@
+import React from 'react';
+import { useQuery } from '@tanstack/react-query';
+import { initDb, getAllPosts } from './db';
+
+interface Post {
+ id: string;
+ title: string;
+ content: string;
+}
+
+const fetchAllPosts = async (): Promise => {
+ await initDb();
+ const posts = await getAllPosts();
+ if (!posts || posts.length === 0) {
+ throw new Error('No posts found');
+ }
+ return posts;
+};
+
+const fetchPostByTitle = async (title: string): Promise => {
+ await initDb();
+ const posts = await getAllPosts();
+ const post = posts.find(p => p.title === title);
+ if (!post) {
+ throw new Error(`No post found with title ${title}`);
+ }
+ return post;
+};
+
+const App: React.FC = () => {
+ const { data: posts, isLoading: isLoadingPosts, error: postsError } = useQuery({
+ queryKey: ['posts'],
+ queryFn: fetchAllPosts,
+ });
+
+ const { data: post, isLoading: isLoadingPost, error: postError } = useQuery({
+ queryKey: ['postByTitle', 'Hello from SurrealDB'],
+ queryFn: () => fetchPostByTitle('Hello from SurrealDB'),
+ });
+
+ if (isLoadingPosts || isLoadingPost) return Loading...
;
+ if (postsError) return Error loading posts: {postsError.message}
;
+ if (postError) return Error loading post: {postError.message}
;
+
+ return (
+
+
Fetching All Posts
+
+ {posts?.map(post => (
+ -
+
{post.title}
+ {post.content}
+
+ ))}
+
+
+
Post by Title
+ {post && (
+
+
{post.title}
+
{post.content}
+
+ )}
+
+ );
+};
+
+export default App;
diff --git a/tanstack-query/src/assets/react.svg b/tanstack-query/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/tanstack-query/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tanstack-query/src/db.ts b/tanstack-query/src/db.ts
new file mode 100644
index 0000000..2ebc1b9
--- /dev/null
+++ b/tanstack-query/src/db.ts
@@ -0,0 +1,47 @@
+import Surreal from 'surrealdb.js';
+
+let db: Surreal | undefined;
+
+export async function initDb(): Promise {
+ if (db) return db;
+ db = new Surreal();
+ try {
+ await db.connect("http://127.0.0.1:8000/rpc");
+ await db.use({ namespace: "test", database: "test" });
+ await db.signin({ username: 'root', password: 'root' })
+
+ await db.query(`
+ CREATE post CONTENT {
+ title: 'Hello from SurrealDB',
+ content: 'This is a hello from SurrealDB'
+ };
+ CREATE post CONTENT {
+ title: 'SurrealDB is Awesome',
+ content: 'This is a post about SurrealDB'
+ };
+ `);
+
+ return db;
+ } catch (err) {
+ console.error("Failed to connect to SurrealDB:", err);
+ throw err;
+ }
+}
+
+interface Post {
+ id: string;
+ title: string;
+ content: string;
+}
+
+export const getAllPosts = async (): Promise => {
+ const posts = await db?.select('post');
+ if (!posts) {
+ throw new Error("Failed to fetch posts");
+ }
+ return posts.map(post => ({
+ id: post.id as unknown as string,
+ title: post.title as string,
+ content: post.content as string,
+ })) as Post[];
+};
diff --git a/tanstack-query/src/index.css b/tanstack-query/src/index.css
new file mode 100644
index 0000000..6119ad9
--- /dev/null
+++ b/tanstack-query/src/index.css
@@ -0,0 +1,68 @@
+:root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/tanstack-query/src/main.tsx b/tanstack-query/src/main.tsx
new file mode 100644
index 0000000..803b470
--- /dev/null
+++ b/tanstack-query/src/main.tsx
@@ -0,0 +1,17 @@
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import App from './App.tsx'
+import './index.css'
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
+import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
+
+const queryClient = new QueryClient()
+
+ReactDOM.createRoot(document.getElementById('root')!).render(
+
+
+
+
+
+ ,
+)
diff --git a/tanstack-query/src/vite-env.d.ts b/tanstack-query/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/tanstack-query/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/tanstack-query/tsconfig.app.json b/tanstack-query/tsconfig.app.json
new file mode 100644
index 0000000..d739292
--- /dev/null
+++ b/tanstack-query/tsconfig.app.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noFallthroughCasesInSwitch": true
+ },
+ "include": ["src"]
+}
diff --git a/tanstack-query/tsconfig.json b/tanstack-query/tsconfig.json
new file mode 100644
index 0000000..ea9d0cd
--- /dev/null
+++ b/tanstack-query/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "files": [],
+ "references": [
+ {
+ "path": "./tsconfig.app.json"
+ },
+ {
+ "path": "./tsconfig.node.json"
+ }
+ ]
+}
diff --git a/tanstack-query/tsconfig.node.json b/tanstack-query/tsconfig.node.json
new file mode 100644
index 0000000..3afdd6e
--- /dev/null
+++ b/tanstack-query/tsconfig.node.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "composite": true,
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "noEmit": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/tanstack-query/vite.config.ts b/tanstack-query/vite.config.ts
new file mode 100644
index 0000000..5a33944
--- /dev/null
+++ b/tanstack-query/vite.config.ts
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})