@basictech/react 0.8.0-beta.3 → 0.8.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@basictech/react",
3
- "version": "0.8.0-beta.3",
3
+ "version": "0.8.0-beta.4",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/readme.md CHANGED
@@ -23,11 +23,11 @@ export const schema = {
23
23
  type: "collection",
24
24
  fields: {
25
25
  title: { type: "string", indexed: true },
26
- completed: { type: "boolean", indexed: true }
27
- }
28
- }
29
- }
30
- }
26
+ completed: { type: "boolean", indexed: true },
27
+ },
28
+ },
29
+ },
30
+ };
31
31
  ```
32
32
 
33
33
  ### 2. Add the Provider
@@ -35,15 +35,15 @@ export const schema = {
35
35
  Wrap your app with `BasicProvider`:
36
36
 
37
37
  ```tsx
38
- import { BasicProvider } from '@basictech/react'
39
- import { schema } from './basic.config'
38
+ import { BasicProvider } from "@basictech/react";
39
+ import { schema } from "./basic.config";
40
40
 
41
41
  function App() {
42
42
  return (
43
43
  <BasicProvider schema={schema}>
44
44
  <YourApp />
45
45
  </BasicProvider>
46
- )
46
+ );
47
47
  }
48
48
  ```
49
49
 
@@ -52,23 +52,23 @@ function App() {
52
52
  Access auth and database in any component:
53
53
 
54
54
  ```tsx
55
- import { useBasic, useQuery } from '@basictech/react'
55
+ import { useBasic, useQuery } from "@basictech/react";
56
56
 
57
57
  function TodoList() {
58
- const { db, isSignedIn, signIn, signOut, user } = useBasic()
59
-
58
+ const { db, isSignedIn, signIn, signOut, user } = useBasic();
59
+
60
60
  // Live query - automatically updates when data changes
61
- const todos = useQuery(() => db.collection('todos').getAll())
61
+ const todos = useQuery(() => db.collection("todos").getAll());
62
62
 
63
63
  const addTodo = async () => {
64
- await db.collection('todos').add({
65
- title: 'New todo',
66
- completed: false
67
- })
68
- }
64
+ await db.collection("todos").add({
65
+ title: "New todo",
66
+ completed: false,
67
+ });
68
+ };
69
69
 
70
70
  if (!isSignedIn) {
71
- return <button onClick={signIn}>Sign In</button>
71
+ return <button onClick={signIn}>Sign In</button>;
72
72
  }
73
73
 
74
74
  return (
@@ -76,13 +76,13 @@ function TodoList() {
76
76
  <p>Welcome, {user?.email}</p>
77
77
  <button onClick={addTodo}>Add Todo</button>
78
78
  <ul>
79
- {todos?.map(todo => (
79
+ {todos?.map((todo) => (
80
80
  <li key={todo.id}>{todo.title}</li>
81
81
  ))}
82
82
  </ul>
83
83
  <button onClick={signOut}>Sign Out</button>
84
84
  </div>
85
- )
85
+ );
86
86
  }
87
87
  ```
88
88
 
@@ -96,21 +96,21 @@ Root provider component. Must wrap your entire app.
96
96
 
97
97
  ```tsx
98
98
  <BasicProvider
99
- schema={schema} // Required: Your Basic schema
100
- debug={false} // Optional: Enable console logging
101
- dbMode="sync" // Optional: "sync" (default) or "remote"
102
- devToolbar={false} // Optional: Floating dev status bar (localhost / dev / debug)
99
+ schema={schema} // Required: Your Basic schema
100
+ debug={false} // Optional: Enable console logging
101
+ dbMode="sync" // Optional: "sync" (default) or "remote"
102
+ devToolbar={false} // Optional: Floating dev status bar (localhost / dev / debug)
103
103
  />
104
104
  ```
105
105
 
106
106
  #### Props
107
107
 
108
- | Prop | Type | Default | Description |
109
- |------|------|---------|-------------|
110
- | `schema` | `object` | required | Schema with `project_id` and `tables` |
111
- | `debug` | `boolean` | `false` | Enable debug logging |
112
- | `dbMode` | `"sync" \| "remote"` | `"sync"` | Database mode |
113
- | `devToolbar` | `boolean` | `false` | Show the Basic dev toolbar (only when `localhost`, `NODE_ENV === "development"`, or `debug={true}`) |
108
+ | Prop | Type | Default | Description |
109
+ | ------------ | -------------------- | -------- | --------------------------------------------------------------------------------------------------- |
110
+ | `schema` | `object` | required | Schema with `project_id` and `tables` |
111
+ | `debug` | `boolean` | `false` | Enable debug logging |
112
+ | `dbMode` | `"sync" \| "remote"` | `"sync"` | Database mode |
113
+ | `devToolbar` | `boolean` | `false` | Show the Basic dev toolbar (only when `localhost`, `NODE_ENV === "development"`, or `debug={true}`) |
114
114
 
115
115
  #### Database Modes
116
116
 
@@ -126,40 +126,40 @@ Main hook for accessing auth and database.
126
126
  ```tsx
127
127
  const {
128
128
  // Auth state
129
- isReady, // boolean - SDK initialized
130
- isSignedIn, // boolean - User authenticated
131
- user, // { id, email, ... } | null
132
-
129
+ isReady, // boolean - SDK initialized
130
+ isSignedIn, // boolean - Session is valid
131
+ user, // { id, email, ... } | null (may be null briefly during profile refresh/recovery)
132
+
133
133
  // Auth methods
134
- signIn, // () => void - Redirect to login
135
- signOut, // () => void - Clear session
134
+ signIn, // () => void - Redirect to login
135
+ signOut, // () => void - Clear session
136
136
  signInWithCode, // (code, state?) => Promise - Manual OAuth
137
- getSignInUrl, // (redirectUri?) => string - Get OAuth URL
138
- getToken, // () => Promise<string> - Get access token
139
-
137
+ getSignInUrl, // (redirectUri?) => string - Get OAuth URL
138
+ getToken, // () => Promise<string> - Get access token
139
+
140
140
  // Database
141
- db, // Database instance
142
- dbStatus, // DBStatus - see below
143
- dbMode, // "sync" | "remote"
141
+ db, // Database instance
142
+ dbStatus, // DBStatus - see below
143
+ dbMode, // "sync" | "remote"
144
144
 
145
145
  // Dev / schema snapshot (for custom tooling)
146
- devInfo, // BasicSchemaDevInfo | null — local vs remote schema status
147
- refreshSchemaStatus, // () => Promise<void> — re-fetch schema status from API
148
- } = useBasic()
146
+ devInfo, // BasicSchemaDevInfo | null — local vs remote schema status
147
+ refreshSchemaStatus, // () => Promise<void> — re-fetch schema status from API
148
+ } = useBasic();
149
149
  ```
150
150
 
151
151
  #### `DBStatus` (sync connection state)
152
152
 
153
153
  When `dbMode === "sync"`, `dbStatus` is one of:
154
154
 
155
- | Value | Description |
156
- |-------|-------------|
157
- | `LOADING` | SDK initializing |
158
- | `OFFLINE` | Not connected |
159
- | `CONNECTING` | Connecting to sync server |
160
- | `ONLINE` | Connected and idle |
161
- | `SYNCING` | Syncing data |
162
- | `ERROR` | Sync error |
155
+ | Value | Description |
156
+ | ------------------ | ----------------------------------------------------------------------------------------------------------------- |
157
+ | `LOADING` | SDK initializing |
158
+ | `OFFLINE` | Not connected |
159
+ | `CONNECTING` | Connecting to sync server |
160
+ | `ONLINE` | Connected and idle |
161
+ | `SYNCING` | Syncing data |
162
+ | `ERROR` | Sync error |
163
163
  | `ERROR_WILL_RETRY` | Sync error but client will retry (e.g. expired token). Use this to show "Reconnecting…" or trigger token refresh. |
164
164
 
165
165
  Import the enum for comparisons: `import { useBasic, DBStatus } from '@basictech/react'`.
@@ -181,12 +181,12 @@ A small floating bar (similar in spirit to Next.js dev indicators) shows **auth*
181
181
  **Option B — place the component yourself** (must be under `BasicProvider`; respects the same visibility rules, or pass `debug` to force):
182
182
 
183
183
  ```tsx
184
- import { BasicDevToolbar } from '@basictech/react'
184
+ import { BasicDevToolbar } from "@basictech/react";
185
185
 
186
186
  <BasicProvider schema={schema}>
187
187
  <App />
188
188
  <BasicDevToolbar />
189
- </BasicProvider>
189
+ </BasicProvider>;
190
190
  ```
191
191
 
192
192
  The expanded panel includes **Refresh schema** (re-runs the remote schema check) and **Copy debug info** (JSON snapshot **without** raw access tokens). You can also read `devInfo` and call `refreshSchemaStatus()` from `useBasic()` for your own UI.
@@ -198,18 +198,18 @@ The expanded panel includes **Refresh schema** (re-runs the remote schema check)
198
198
  Live query hook - automatically re-renders when data changes.
199
199
 
200
200
  ```tsx
201
- import { useQuery } from '@basictech/react'
201
+ import { useQuery } from "@basictech/react";
202
202
 
203
203
  // Get all items
204
- const todos = useQuery(() => db.collection('todos').getAll())
204
+ const todos = useQuery(() => db.collection("todos").getAll());
205
205
 
206
206
  // With type safety
207
207
  interface Todo {
208
- id: string
209
- title: string
210
- completed: boolean
208
+ id: string;
209
+ title: string;
210
+ completed: boolean;
211
211
  }
212
- const todos = useQuery(() => db.collection<Todo>('todos').getAll())
212
+ const todos = useQuery(() => db.collection<Todo>("todos").getAll());
213
213
  ```
214
214
 
215
215
  > **Note:** Only works in `sync` mode. In `remote` mode, use manual fetching.
@@ -223,44 +223,44 @@ const todos = useQuery(() => db.collection<Todo>('todos').getAll())
223
223
  Access a collection by name.
224
224
 
225
225
  ```tsx
226
- const { db } = useBasic()
227
- const todos = db.collection('todos')
226
+ const { db } = useBasic();
227
+ const todos = db.collection("todos");
228
228
  ```
229
229
 
230
230
  #### Collection Methods
231
231
 
232
- | Method | Returns | Description |
233
- |--------|---------|-------------|
234
- | `getAll()` | `Promise<T[]>` | Get all records |
235
- | `get(id)` | `Promise<T \| null>` | Get one record by ID |
236
- | `add(data)` | `Promise<T>` | Create new record (returns with ID) |
237
- | `put(data)` | `Promise<T>` | Upsert record (requires ID) |
238
- | `update(id, data)` | `Promise<T \| null>` | Partial update |
239
- | `delete(id)` | `Promise<boolean>` | Delete record |
240
- | `filter(fn)` | `Promise<T[]>` | Filter with predicate |
232
+ | Method | Returns | Description |
233
+ | ------------------ | -------------------- | ----------------------------------- |
234
+ | `getAll()` | `Promise<T[]>` | Get all records |
235
+ | `get(id)` | `Promise<T \| null>` | Get one record by ID |
236
+ | `add(data)` | `Promise<T>` | Create new record (returns with ID) |
237
+ | `put(data)` | `Promise<T>` | Upsert record (requires ID) |
238
+ | `update(id, data)` | `Promise<T \| null>` | Partial update |
239
+ | `delete(id)` | `Promise<boolean>` | Delete record |
240
+ | `filter(fn)` | `Promise<T[]>` | Filter with predicate |
241
241
 
242
242
  #### Examples
243
243
 
244
244
  ```tsx
245
245
  // Create
246
- const todo = await db.collection('todos').add({
247
- title: 'Buy milk',
248
- completed: false
249
- })
250
- console.log(todo.id) // Auto-generated ID
246
+ const todo = await db.collection("todos").add({
247
+ title: "Buy milk",
248
+ completed: false,
249
+ });
250
+ console.log(todo.id); // Auto-generated ID
251
251
 
252
252
  // Read
253
- const allTodos = await db.collection('todos').getAll()
254
- const oneTodo = await db.collection('todos').get('some-id')
253
+ const allTodos = await db.collection("todos").getAll();
254
+ const oneTodo = await db.collection("todos").get("some-id");
255
255
 
256
256
  // Update
257
- await db.collection('todos').update('some-id', { completed: true })
257
+ await db.collection("todos").update("some-id", { completed: true });
258
258
 
259
259
  // Delete
260
- await db.collection('todos').delete('some-id')
260
+ await db.collection("todos").delete("some-id");
261
261
 
262
262
  // Filter
263
- const incomplete = await db.collection('todos').filter(t => !t.completed)
263
+ const incomplete = await db.collection("todos").filter((t) => !t.completed);
264
264
  ```
265
265
 
266
266
  ---
@@ -272,15 +272,15 @@ const incomplete = await db.collection('todos').filter(t => !t.completed)
272
272
  For custom OAuth handling (mobile apps, popups, etc.):
273
273
 
274
274
  ```tsx
275
- const { signInWithCode, getSignInUrl } = useBasic()
275
+ const { signInWithCode, getSignInUrl } = useBasic();
276
276
 
277
277
  // Get OAuth URL with custom redirect
278
- const url = getSignInUrl('myapp://callback')
278
+ const url = getSignInUrl("myapp://callback");
279
279
 
280
280
  // Exchange code for session
281
- const result = await signInWithCode(code, state)
281
+ const result = await signInWithCode(code, state);
282
282
  if (result.success) {
283
- console.log('Signed in!')
283
+ console.log("Signed in!");
284
284
  }
285
285
  ```
286
286
 
@@ -295,22 +295,24 @@ For server-rendered apps or when you don't need offline support:
295
295
  ```
296
296
 
297
297
  In remote mode:
298
+
298
299
  - Data is fetched via REST API
299
300
  - No IndexedDB storage
300
301
  - `useQuery` won't auto-update (use manual refresh)
301
302
  - Requires authentication for all operations
303
+ - Auth request failures are surfaced to the caller; recoverable 401s do not automatically sign the user out
302
304
 
303
305
  ### Error Handling
304
306
 
305
307
  ```tsx
306
- import { NotAuthenticatedError } from '@basictech/react'
308
+ import { NotAuthenticatedError } from "@basictech/react";
307
309
 
308
310
  try {
309
- await db.collection('todos').add({ title: 'Test' })
311
+ await db.collection("todos").add({ title: "Test" });
310
312
  } catch (error) {
311
313
  if (error instanceof NotAuthenticatedError) {
312
314
  // User needs to sign in
313
- signIn()
315
+ signIn();
314
316
  }
315
317
  }
316
318
  ```
@@ -323,21 +325,21 @@ Full TypeScript support with generics:
323
325
 
324
326
  ```tsx
325
327
  interface Todo {
326
- id: string
327
- title: string
328
- completed: boolean
329
- createdAt: number
328
+ id: string;
329
+ title: string;
330
+ completed: boolean;
331
+ createdAt: number;
330
332
  }
331
333
 
332
334
  // Type-safe collection
333
- const todos = db.collection<Todo>('todos')
335
+ const todos = db.collection<Todo>("todos");
334
336
 
335
337
  // All methods are typed
336
338
  const todo = await todos.add({
337
- title: 'Test',
339
+ title: "Test",
338
340
  completed: false,
339
- createdAt: Date.now()
340
- })
341
+ createdAt: Date.now(),
342
+ });
341
343
  // todo is typed as Todo
342
344
  ```
343
345