@zeroin.earth/appwrite-graphql 23.0.0 → 23.0.2
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/README.md +148 -174
- package/dist/index.cjs +94 -94
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5172 -16525
- package/dist/index.d.ts +5172 -16525
- package/dist/index.js +94 -94
- package/dist/index.js.map +1 -1
- package/package.json +26 -5
- package/react-native/index.cjs +94 -94
- package/react-native/index.d.cts +5174 -16525
- package/react-native/index.d.ts +5602 -0
- package/react-native/index.js +989 -0
package/README.md
CHANGED
|
@@ -1,34 +1,31 @@
|
|
|
1
1
|
# Appwrite GraphQL
|
|
2
|
+
|
|
2
3
|
  
|
|
3
4
|
|
|
4
5
|
Appwrite is an open source, BaaS in the same vein as Supabase and Firebase, but geared more toward self-hosting.
|
|
5
6
|
|
|
6
7
|
This is a fully featured GraphQL library built with [@tanstack/react-query](https://github.com/TanStack/query) on top of the Appwrite web SDK and is fully typed. Think of this library as the abstract wrapper you would have made yourself, but we already did it for you.
|
|
7
8
|
|
|
8
|
-
## Getting Started
|
|
9
|
-
- [Installation](#installation)
|
|
10
|
-
- [Basic Usage](#usage)
|
|
11
|
-
|
|
12
9
|
## Features
|
|
13
10
|
|
|
14
11
|
- Dual build for both React and React Native
|
|
15
12
|
- Full Appwrite SDK v23 parity using React hooks
|
|
16
13
|
- [Optimistic Mutations](#optimistic-mutations)
|
|
17
|
-
|
|
14
|
+
- Documents only
|
|
18
15
|
- [Query Caching](#query-caching)
|
|
19
|
-
|
|
16
|
+
- [QueryKey Builder](#querykey-builder)
|
|
20
17
|
- [Offline-first Support](#offline-first-support)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
- [Built-in Offline Persisters](#built-in-offline-persisters) (localStorage, AsyncStorage)
|
|
19
|
+
- [Custom Offline Persister Support](#custom-offline-persister-support)
|
|
20
|
+
- [Conflict Resolution](#conflict-resolution)
|
|
24
21
|
- [SSR Support](#ssr-support)
|
|
25
22
|
- [Field Selection](#field-selection)
|
|
26
23
|
- [Suspense Queries](#suspense-queries)
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
- Documents
|
|
25
|
+
- Collections
|
|
29
26
|
- [Pagination Hooks](#pagination-hooks)
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
- Standard Pagination
|
|
28
|
+
- Infinite Scroll
|
|
32
29
|
- [Appwrite QueryBuilder](#appwrite-querybuilder)
|
|
33
30
|
- [React Query Devtools Support](#react-query-devtools-support)
|
|
34
31
|
|
|
@@ -48,9 +45,9 @@ bun add @zeroin.earth/appwrite-graphql
|
|
|
48
45
|
|
|
49
46
|
**React Native:**
|
|
50
47
|
|
|
51
|
-
-
|
|
52
|
-
- `@react-native-
|
|
53
|
-
-
|
|
48
|
+
- `react-native-appwrite` - `^0.25.0`
|
|
49
|
+
- `@react-native-async-storage/async-storage` - `^3.0.1`
|
|
50
|
+
- `@react-native-community/netinfo` - `^12.0.1`
|
|
54
51
|
|
|
55
52
|
## Usage
|
|
56
53
|
|
|
@@ -61,10 +58,7 @@ The library is designed to use a single wrapper, `<AppwriteProvider>`. There are
|
|
|
61
58
|
1. Basic (no offline-first support) - React
|
|
62
59
|
|
|
63
60
|
```tsx
|
|
64
|
-
import {
|
|
65
|
-
AppwriteProvider,
|
|
66
|
-
createAppwriteClient
|
|
67
|
-
} from '@zeroin.earth/appwrite-graphql'
|
|
61
|
+
import { AppwriteProvider, createAppwriteClient } from '@zeroin.earth/appwrite-graphql'
|
|
68
62
|
|
|
69
63
|
const client = createAppwriteClient({
|
|
70
64
|
endpoint: 'https://cloud.appwrite.io/v1',
|
|
@@ -72,11 +66,7 @@ const client = createAppwriteClient({
|
|
|
72
66
|
})
|
|
73
67
|
|
|
74
68
|
function App() {
|
|
75
|
-
return
|
|
76
|
-
<AppwriteProvider client={client}>
|
|
77
|
-
{/* your app */}
|
|
78
|
-
</AppwriteProvider>
|
|
79
|
-
)
|
|
69
|
+
return <AppwriteProvider client={client}>{/* your app */}</AppwriteProvider>
|
|
80
70
|
}
|
|
81
71
|
```
|
|
82
72
|
|
|
@@ -114,14 +104,9 @@ function App() {
|
|
|
114
104
|
|
|
115
105
|
```tsx
|
|
116
106
|
import AsyncStorage from '@react-native-async-storage/async-storage'
|
|
117
|
-
import {
|
|
118
|
-
AppwriteProvider,
|
|
119
|
-
createOfflineClient,
|
|
120
|
-
} from '@zeroin.earth/appwrite-graphql'
|
|
107
|
+
import { AppwriteProvider, createOfflineClient } from '@zeroin.earth/appwrite-graphql'
|
|
121
108
|
|
|
122
|
-
import {
|
|
123
|
-
reactNativeNetworkAdapter
|
|
124
|
-
} from '@zeroin.earth/appwrite-graphql/react-native'
|
|
109
|
+
import { reactNativeNetworkAdapter } from '@zeroin.earth/appwrite-graphql/react-native'
|
|
125
110
|
|
|
126
111
|
const { appwrite, queryClient, persister } = createOfflineClient({
|
|
127
112
|
endpoint: 'https://cloud.appwrite.io/v1',
|
|
@@ -132,11 +117,7 @@ const { appwrite, queryClient, persister } = createOfflineClient({
|
|
|
132
117
|
|
|
133
118
|
function App() {
|
|
134
119
|
return (
|
|
135
|
-
<AppwriteProvider
|
|
136
|
-
client={appwrite}
|
|
137
|
-
queryClient={queryClient}
|
|
138
|
-
persister={persister}
|
|
139
|
-
>
|
|
120
|
+
<AppwriteProvider client={appwrite} queryClient={queryClient} persister={persister}>
|
|
140
121
|
{/* your app */}
|
|
141
122
|
</AppwriteProvider>
|
|
142
123
|
)
|
|
@@ -154,9 +135,15 @@ import {
|
|
|
154
135
|
} from '@zeroin.earth/appwrite-graphql'
|
|
155
136
|
|
|
156
137
|
const myPersister: Persister = {
|
|
157
|
-
persistClient: async (client) => {
|
|
158
|
-
|
|
159
|
-
|
|
138
|
+
persistClient: async (client) => {
|
|
139
|
+
/* write to your storage */
|
|
140
|
+
},
|
|
141
|
+
restoreClient: async () => {
|
|
142
|
+
/* read from your storage */
|
|
143
|
+
},
|
|
144
|
+
removeClient: async () => {
|
|
145
|
+
/* clear your storage */
|
|
146
|
+
},
|
|
160
147
|
}
|
|
161
148
|
|
|
162
149
|
const { appwrite, queryClient, persister } = createOfflineClient({
|
|
@@ -168,11 +155,7 @@ const { appwrite, queryClient, persister } = createOfflineClient({
|
|
|
168
155
|
|
|
169
156
|
function App() {
|
|
170
157
|
return (
|
|
171
|
-
<AppwriteProvider
|
|
172
|
-
client={appwrite}
|
|
173
|
-
queryClient={queryClient}
|
|
174
|
-
persister={persister}
|
|
175
|
-
>
|
|
158
|
+
<AppwriteProvider client={appwrite} queryClient={queryClient} persister={persister}>
|
|
176
159
|
{/* your app */}
|
|
177
160
|
</AppwriteProvider>
|
|
178
161
|
)
|
|
@@ -182,10 +165,7 @@ function App() {
|
|
|
182
165
|
5. Offline - Imperative / non-React
|
|
183
166
|
|
|
184
167
|
```tsx
|
|
185
|
-
import {
|
|
186
|
-
createOfflineClient,
|
|
187
|
-
webNetworkAdapter,
|
|
188
|
-
} from '@zeroin.earth/appwrite-graphql'
|
|
168
|
+
import { createOfflineClient, webNetworkAdapter } from '@zeroin.earth/appwrite-graphql'
|
|
189
169
|
|
|
190
170
|
const client = createOfflineClient({
|
|
191
171
|
endpoint: 'https://cloud.appwrite.io/v1',
|
|
@@ -242,12 +222,9 @@ const person = useDocument<Person>(
|
|
|
242
222
|
During development, we started getting annoyed with keeping our query keys straight, so we built a factory you can use to perform manual cache eviction. We tried to keep the pattern as close to Appwrite's `Channels` as possible.
|
|
243
223
|
|
|
244
224
|
```tsx
|
|
245
|
-
import { Keys } from
|
|
225
|
+
import { Keys } from '@zeroin.earth/appwrite-graphql'
|
|
246
226
|
|
|
247
|
-
const queryKey = Keys.database(databaseId)
|
|
248
|
-
.collection(collectionId)
|
|
249
|
-
.document(documentId)
|
|
250
|
-
.key()
|
|
227
|
+
const queryKey = Keys.database(databaseId).collection(collectionId).document(documentId).key()
|
|
251
228
|
```
|
|
252
229
|
|
|
253
230
|
## Offline-first Support
|
|
@@ -267,11 +244,11 @@ const { appwrite, queryClient, persister } = createOfflineClient({
|
|
|
267
244
|
})
|
|
268
245
|
```
|
|
269
246
|
|
|
270
|
-
The above example will serialize the mutations to localStorage after a set `throttleTime` elapses (defaults to 1000ms). Once the `
|
|
247
|
+
The above example will serialize the mutations to localStorage after a set `throttleTime` elapses (defaults to 1000ms). Once the `networkAdapter` detects the device is online, the serialized mutations will instantly start replaying in order.
|
|
271
248
|
|
|
272
249
|
### Custom Offline Persister Support
|
|
273
250
|
|
|
274
|
-
Sometimes you want to bring your own persister, or just don't want to use localStorage or AsyncStorage. For this, you can build your own.
|
|
251
|
+
Sometimes you want to bring your own persister, or just don't want to use localStorage or AsyncStorage. For this, you can build your own. See [Provider example #4](#provider) above for a full example using a custom `Persister`.
|
|
275
252
|
|
|
276
253
|
### Conflict Resolution
|
|
277
254
|
|
|
@@ -283,7 +260,7 @@ createOfflineClient({
|
|
|
283
260
|
projectId: 'my-project',
|
|
284
261
|
storage: localStorage,
|
|
285
262
|
networkAdapter: webNetworkAdapter(),
|
|
286
|
-
conflictStrategy: 'last-write-wins'
|
|
263
|
+
conflictStrategy: 'last-write-wins',
|
|
287
264
|
})
|
|
288
265
|
```
|
|
289
266
|
|
|
@@ -296,7 +273,8 @@ createOfflineClient({
|
|
|
296
273
|
**custom**: A custom resolver function can be supplied with the following type:
|
|
297
274
|
|
|
298
275
|
```tsx
|
|
299
|
-
conflictStrategy: (
|
|
276
|
+
conflictStrategy: (context: ConflictContext) =>
|
|
277
|
+
Record<string, string | number | boolean | null> | 'abort'
|
|
300
278
|
```
|
|
301
279
|
|
|
302
280
|
- `abort` signals to drop the replaying mutation and change nothing.
|
|
@@ -310,47 +288,46 @@ We have exposed 3 of the most used queries Appwrite surfaces to be used in SSR p
|
|
|
310
288
|
- `getCollectionQuery`
|
|
311
289
|
|
|
312
290
|
```tsx
|
|
313
|
-
import * as React from
|
|
314
|
-
import {
|
|
315
|
-
dehydrate,
|
|
316
|
-
HydrationBoundary,
|
|
317
|
-
QueryClient,
|
|
318
|
-
} from "@tanstack/react-query";
|
|
291
|
+
import * as React from 'react'
|
|
292
|
+
import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query'
|
|
319
293
|
|
|
320
|
-
import {
|
|
321
|
-
|
|
294
|
+
import {
|
|
295
|
+
createAppwriteClient,
|
|
296
|
+
useCollection,
|
|
297
|
+
getCollectionQuery,
|
|
298
|
+
} from '@zeroin.earth/appwrite-graphql'
|
|
322
299
|
|
|
323
300
|
type PostType = {
|
|
324
|
-
title: string
|
|
325
|
-
image: string
|
|
326
|
-
description: string
|
|
327
|
-
}
|
|
301
|
+
title: string
|
|
302
|
+
image: string
|
|
303
|
+
description: string
|
|
304
|
+
}
|
|
328
305
|
|
|
329
306
|
// This could also be getServerSideProps
|
|
330
307
|
export async function getStaticProps() {
|
|
331
308
|
const appwriteClient = createAppwriteClient({
|
|
332
|
-
endpoint:
|
|
333
|
-
projectId:
|
|
334
|
-
})
|
|
309
|
+
endpoint: 'https://example.com/v1',
|
|
310
|
+
projectId: 'project-id',
|
|
311
|
+
})
|
|
335
312
|
|
|
336
|
-
const queryClient = new QueryClient()
|
|
313
|
+
const queryClient = new QueryClient()
|
|
337
314
|
|
|
338
315
|
// Perform the prefetching of the collection query on the server.
|
|
339
316
|
await queryClient.prefetchQuery(
|
|
340
317
|
getCollectionQuery<PostType>(appwriteClient, {
|
|
341
|
-
databaseId:
|
|
342
|
-
collectionId:
|
|
343
|
-
fields: [
|
|
318
|
+
databaseId: 'db1',
|
|
319
|
+
collectionId: 'col1',
|
|
320
|
+
fields: ['title', 'image', 'description'],
|
|
344
321
|
}),
|
|
345
|
-
)
|
|
322
|
+
)
|
|
346
323
|
|
|
347
|
-
// Dehydrate the query client state and pass it as a
|
|
324
|
+
// Dehydrate the query client state and pass it as a
|
|
348
325
|
// prop to the page component.
|
|
349
326
|
return {
|
|
350
327
|
props: {
|
|
351
328
|
dehydratedState: dehydrate(queryClient),
|
|
352
329
|
},
|
|
353
|
-
}
|
|
330
|
+
}
|
|
354
331
|
}
|
|
355
332
|
|
|
356
333
|
function Posts() {
|
|
@@ -358,10 +335,10 @@ function Posts() {
|
|
|
358
335
|
// cached data and not trigger a network request. If the cache is empty,
|
|
359
336
|
// it will fetch the data from the Appwrite server normally.
|
|
360
337
|
const { data } = useCollection<PostType>({
|
|
361
|
-
databaseId:
|
|
362
|
-
collectionId:
|
|
363
|
-
fields: [
|
|
364
|
-
})
|
|
338
|
+
databaseId: 'db1',
|
|
339
|
+
collectionId: 'col1',
|
|
340
|
+
fields: ['title', 'image', 'description'],
|
|
341
|
+
})
|
|
365
342
|
|
|
366
343
|
return (
|
|
367
344
|
<div>
|
|
@@ -373,7 +350,7 @@ function Posts() {
|
|
|
373
350
|
</div>
|
|
374
351
|
))}
|
|
375
352
|
</div>
|
|
376
|
-
)
|
|
353
|
+
)
|
|
377
354
|
}
|
|
378
355
|
|
|
379
356
|
// The dehydrated state from the server is passed to the HydrationBoundary,
|
|
@@ -384,7 +361,7 @@ export default function PostsRoute({ dehydratedState }) {
|
|
|
384
361
|
<HydrationBoundary state={dehydratedState}>
|
|
385
362
|
<Posts />
|
|
386
363
|
</HydrationBoundary>
|
|
387
|
-
)
|
|
364
|
+
)
|
|
388
365
|
}
|
|
389
366
|
```
|
|
390
367
|
|
|
@@ -399,18 +376,16 @@ The most used query hooks allow you to specify the fields returned by Appwrite t
|
|
|
399
376
|
|
|
400
377
|
```tsx
|
|
401
378
|
type Person = {
|
|
402
|
-
name: string
|
|
403
|
-
age: number
|
|
404
|
-
}
|
|
379
|
+
name: string
|
|
380
|
+
age: number
|
|
381
|
+
}
|
|
405
382
|
|
|
406
|
-
const person = useDocument<Person>(
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
},
|
|
413
|
-
);
|
|
383
|
+
const person = useDocument<Person>({
|
|
384
|
+
databaseId: 'db1',
|
|
385
|
+
collectionId: 'col1',
|
|
386
|
+
documentId: 'doc1',
|
|
387
|
+
fields: ['name', 'age'],
|
|
388
|
+
})
|
|
414
389
|
```
|
|
415
390
|
|
|
416
391
|
## Suspense Queries
|
|
@@ -430,34 +405,27 @@ We have included two pagination hooks out of the box
|
|
|
430
405
|
**With Pagination:**
|
|
431
406
|
|
|
432
407
|
```tsx
|
|
433
|
-
import * as React from
|
|
434
|
-
import { q, useCollectionWithPagination } from
|
|
408
|
+
import * as React from 'react'
|
|
409
|
+
import { q, useCollectionWithPagination } from '@zeroin.earth/appwrite-graphql'
|
|
435
410
|
|
|
436
411
|
type Item = {
|
|
437
|
-
_id: string
|
|
438
|
-
name: string
|
|
439
|
-
}
|
|
412
|
+
_id: string
|
|
413
|
+
name: string
|
|
414
|
+
}
|
|
440
415
|
|
|
441
416
|
export default function Test() {
|
|
442
|
-
const {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
.equal("name", ["John", "Jane"])
|
|
455
|
-
.createdBefore(new Date("2024-01-01").toDateString())
|
|
456
|
-
.orderAsc("name")
|
|
457
|
-
.build(),
|
|
458
|
-
limit: 10,
|
|
459
|
-
fields: ["name", "_id"],
|
|
460
|
-
});
|
|
417
|
+
const { documents, page, total, nextPage, previousPage, hasNextPage, hasPreviousPage } =
|
|
418
|
+
useCollectionWithPagination<Item>({
|
|
419
|
+
databaseId: 'your-database-id',
|
|
420
|
+
collectionId: 'your-collection-id',
|
|
421
|
+
queries: q<Item>()
|
|
422
|
+
.equal('name', ['John', 'Jane'])
|
|
423
|
+
.createdBefore(new Date('2024-01-01').toDateString())
|
|
424
|
+
.orderAsc('name')
|
|
425
|
+
.build(),
|
|
426
|
+
limit: 10,
|
|
427
|
+
fields: ['name', '_id'],
|
|
428
|
+
})
|
|
461
429
|
|
|
462
430
|
return (
|
|
463
431
|
<div>
|
|
@@ -478,35 +446,33 @@ export default function Test() {
|
|
|
478
446
|
<p>Page: {page}</p>
|
|
479
447
|
<p>Total: {total}</p>
|
|
480
448
|
</div>
|
|
481
|
-
)
|
|
449
|
+
)
|
|
482
450
|
}
|
|
483
451
|
```
|
|
484
452
|
|
|
485
453
|
**Infinite Scroll**:
|
|
486
454
|
|
|
487
455
|
```tsx
|
|
488
|
-
import * as React from
|
|
489
|
-
import { q, useInfiniteCollection } from
|
|
456
|
+
import * as React from 'react'
|
|
457
|
+
import { q, useInfiniteCollection } from '@zeroin.earth/appwrite-graphql'
|
|
490
458
|
|
|
491
459
|
type Item = {
|
|
492
|
-
_id: string
|
|
493
|
-
name: string
|
|
494
|
-
}
|
|
460
|
+
_id: string
|
|
461
|
+
name: string
|
|
462
|
+
}
|
|
495
463
|
|
|
496
464
|
export default function Test() {
|
|
497
|
-
const { documents, fetchNextPage, hasNextPage } = useInfiniteCollection<Item>(
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
},
|
|
509
|
-
);
|
|
465
|
+
const { documents, fetchNextPage, hasNextPage } = useInfiniteCollection<Item>({
|
|
466
|
+
databaseId: 'your-database-id',
|
|
467
|
+
collectionId: 'your-collection-id',
|
|
468
|
+
queries: q<Item>()
|
|
469
|
+
.equal('name', ['John', 'Jane'])
|
|
470
|
+
.createdBefore(new Date('2024-01-01').toDateString())
|
|
471
|
+
.orderAsc('name')
|
|
472
|
+
.build(),
|
|
473
|
+
limit: 25,
|
|
474
|
+
fields: ['name', '_id'],
|
|
475
|
+
})
|
|
510
476
|
|
|
511
477
|
return (
|
|
512
478
|
<div>
|
|
@@ -520,7 +486,7 @@ export default function Test() {
|
|
|
520
486
|
Load More...
|
|
521
487
|
</button>
|
|
522
488
|
</div>
|
|
523
|
-
)
|
|
489
|
+
)
|
|
524
490
|
}
|
|
525
491
|
```
|
|
526
492
|
|
|
@@ -531,32 +497,32 @@ Appwrite SDK includes a built-in Query factory, but we wanted to make something
|
|
|
531
497
|
Our QueryBuilder is type safe and exposes all underlying functions from the built-in version 1 for 1.
|
|
532
498
|
|
|
533
499
|
```tsx
|
|
534
|
-
import { q } from
|
|
500
|
+
import { q, useCollection } from '@zeroin.earth/appwrite-graphql'
|
|
535
501
|
|
|
536
502
|
type YourType = {
|
|
537
|
-
name: string
|
|
538
|
-
favNumber: number
|
|
539
|
-
favColor: string
|
|
540
|
-
favFood: string
|
|
541
|
-
}
|
|
503
|
+
name: string
|
|
504
|
+
favNumber: number
|
|
505
|
+
favColor: string
|
|
506
|
+
favFood: string
|
|
507
|
+
}
|
|
542
508
|
|
|
543
509
|
export function Profiles() {
|
|
544
510
|
const { documents, error, isLoading } = useCollection<YourType>({
|
|
545
|
-
databaseId:
|
|
546
|
-
collectionId:
|
|
511
|
+
databaseId: 'your-database-id',
|
|
512
|
+
collectionId: 'your-collection-id',
|
|
547
513
|
queries: q<YourType>()
|
|
548
514
|
.or(
|
|
549
|
-
(q) => q.equal(
|
|
550
|
-
(q) => q.equal(
|
|
515
|
+
(q) => q.equal('favColor', 'blue').greaterThan('favNumber', 18),
|
|
516
|
+
(q) => q.equal('favFood', 'pizza').lessThan('favNumber', 10),
|
|
551
517
|
(q) =>
|
|
552
518
|
q.and(
|
|
553
|
-
(q) => q.between(
|
|
554
|
-
(q) => q.startsWith(
|
|
519
|
+
(q) => q.between('favNumber', 5, 15),
|
|
520
|
+
(q) => q.startsWith('name', 'A'),
|
|
555
521
|
),
|
|
556
522
|
)
|
|
557
523
|
|
|
558
524
|
.build(),
|
|
559
|
-
})
|
|
525
|
+
})
|
|
560
526
|
|
|
561
527
|
return (
|
|
562
528
|
<div>
|
|
@@ -566,14 +532,14 @@ export function Profiles() {
|
|
|
566
532
|
<ul>
|
|
567
533
|
{documents.map((doc) => (
|
|
568
534
|
<li key={doc.$id}>
|
|
569
|
-
Name: {doc.name}, Fav Number: {doc.favNumber}, Fav Color:{
|
|
570
|
-
{doc.
|
|
535
|
+
Name: {doc.name}, Fav Number: {doc.favNumber}, Fav Color: {doc.favColor}, Fav Food:{' '}
|
|
536
|
+
{doc.favFood}
|
|
571
537
|
</li>
|
|
572
538
|
))}
|
|
573
539
|
</ul>
|
|
574
540
|
)}
|
|
575
541
|
</div>
|
|
576
|
-
)
|
|
542
|
+
)
|
|
577
543
|
}
|
|
578
544
|
```
|
|
579
545
|
|
|
@@ -583,44 +549,48 @@ React Query Devtools are bundled and ready to go. For any additional questions a
|
|
|
583
549
|
|
|
584
550
|
## Examples
|
|
585
551
|
|
|
552
|
+
### Login with email or OAuth
|
|
553
|
+
|
|
586
554
|
```ts
|
|
587
|
-
import { useLogin } from
|
|
555
|
+
import { useLogin } from '@zeroin.earth/appwrite-graphql'
|
|
588
556
|
|
|
589
557
|
export function LogIn() {
|
|
590
|
-
const router = useRouter()
|
|
558
|
+
const router = useRouter()
|
|
591
559
|
|
|
592
|
-
const { login, oAuthLogin } = useLogin()
|
|
560
|
+
const { login, oAuthLogin } = useLogin()
|
|
593
561
|
|
|
594
562
|
const onSubmit: SubmitHandler<Inputs> = async (data) => {
|
|
595
563
|
await login.mutateAsync(data, {
|
|
596
564
|
onSuccess: () => {
|
|
597
|
-
router.push(
|
|
565
|
+
router.push('/profile')
|
|
598
566
|
},
|
|
599
|
-
})
|
|
600
|
-
}
|
|
567
|
+
})
|
|
568
|
+
}
|
|
601
569
|
|
|
602
570
|
const loginWithGoogle = () => {
|
|
603
571
|
oAuthLogin.mutate({
|
|
604
|
-
provider:
|
|
605
|
-
success:
|
|
606
|
-
failure:
|
|
607
|
-
})
|
|
608
|
-
}
|
|
572
|
+
provider: 'google',
|
|
573
|
+
success: 'successUrl',
|
|
574
|
+
failure: 'failureUrl',
|
|
575
|
+
})
|
|
576
|
+
}
|
|
609
577
|
}
|
|
610
578
|
```
|
|
611
579
|
|
|
612
580
|
---
|
|
613
581
|
|
|
582
|
+
### Execute a server function
|
|
583
|
+
|
|
614
584
|
```ts
|
|
615
|
-
import { useFunction } from
|
|
585
|
+
import { useFunction } from '@zeroin.earth/appwrite-graphql'
|
|
616
586
|
|
|
617
587
|
export function Form() {
|
|
618
|
-
const { executeFunction } = useFunction()
|
|
588
|
+
const { executeFunction } = useFunction()
|
|
619
589
|
|
|
620
590
|
const onSubmit: SubmitHandler<Input> = async (data) => {
|
|
621
591
|
executeFunction.mutate(
|
|
622
592
|
{
|
|
623
|
-
functionId:
|
|
593
|
+
functionId: '6gibhbyy6tggdf',
|
|
624
594
|
body: {
|
|
625
595
|
message: {
|
|
626
596
|
...data,
|
|
@@ -629,10 +599,14 @@ export function Form() {
|
|
|
629
599
|
},
|
|
630
600
|
{
|
|
631
601
|
onSettled: () => {
|
|
632
|
-
setJustSignedUp(true)
|
|
602
|
+
setJustSignedUp(true)
|
|
633
603
|
},
|
|
634
604
|
},
|
|
635
|
-
)
|
|
636
|
-
}
|
|
605
|
+
)
|
|
606
|
+
}
|
|
637
607
|
}
|
|
638
608
|
```
|
|
609
|
+
|
|
610
|
+
## License
|
|
611
|
+
|
|
612
|
+
MIT
|