react-fate 1.3.0 → 1.3.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 +179 -1
- package/docs/api/functions/FateClient.md +1 -1
- package/docs/api/functions/useFateClient.md +2 -2
- package/docs/api/functions/useListView.md +1 -1
- package/docs/api/functions/useLiveListView.md +1 -1
- package/docs/api/functions/useLiveView.md +2 -2
- package/docs/api/functions/useRequest.md +2 -2
- package/docs/api/functions/useView.md +3 -3
- package/docs/integrations/cloudflare.md +19 -1
- package/docs/integrations/void.md +17 -1
- package/lib/index.mjs +2 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2676,7 +2676,23 @@ _And you are all set. Happy building!_
|
|
|
2676
2676
|
Use this integration when your app runs on Void and you want the example app's
|
|
2677
2677
|
setup without copying its adapter glue.
|
|
2678
2678
|
|
|
2679
|
-
###
|
|
2679
|
+
### New Project
|
|
2680
|
+
|
|
2681
|
+
For a new Void app, start from the Void template. It includes the client, Void routes, Drizzle setup, live transport, auth wiring, and generated fate client setup.
|
|
2682
|
+
|
|
2683
|
+
```sh
|
|
2684
|
+
vp create fate my-app --template void
|
|
2685
|
+
```
|
|
2686
|
+
|
|
2687
|
+
Use Vue instead of React with:
|
|
2688
|
+
|
|
2689
|
+
```sh
|
|
2690
|
+
vp create fate my-app --template void --framework vue
|
|
2691
|
+
```
|
|
2692
|
+
|
|
2693
|
+
### Existing Project
|
|
2694
|
+
|
|
2695
|
+
For an existing Void project, add the packages directly:
|
|
2680
2696
|
|
|
2681
2697
|
::: code-group
|
|
2682
2698
|
|
|
@@ -2919,6 +2935,168 @@ falls back to the in-memory live bus for the current request context.
|
|
|
2919
2935
|
The live transport is best-effort and does not replay missed events after a
|
|
2920
2936
|
client reconnects. This matches fate's default in-memory live event bus.
|
|
2921
2937
|
|
|
2938
|
+
## Cloudflare Integration
|
|
2939
|
+
|
|
2940
|
+
`cf-fate` is the first-class Cloudflare Workers adapter for Fate native HTTP transport and live views.
|
|
2941
|
+
|
|
2942
|
+
Use it when your backend runs directly on Cloudflare Workers and you want fate live views without adopting the Void platform.
|
|
2943
|
+
|
|
2944
|
+
### New Project
|
|
2945
|
+
|
|
2946
|
+
For a new Cloudflare Workers app, start from the Cloudflare template. It includes the client, Worker server, D1 migrations, Wrangler config, Durable Object live transport, auth wiring, and generated fate client setup.
|
|
2947
|
+
|
|
2948
|
+
```sh
|
|
2949
|
+
vp create fate my-app --template cloudflare
|
|
2950
|
+
```
|
|
2951
|
+
|
|
2952
|
+
Use Vue instead of React with:
|
|
2953
|
+
|
|
2954
|
+
```sh
|
|
2955
|
+
vp create fate my-app --template cloudflare --framework vue
|
|
2956
|
+
```
|
|
2957
|
+
|
|
2958
|
+
### Existing Project
|
|
2959
|
+
|
|
2960
|
+
For an existing Cloudflare Workers project, add the packages directly:
|
|
2961
|
+
|
|
2962
|
+
```sh
|
|
2963
|
+
pnpm add @nkzw/fate react-fate cf-fate drizzle-orm
|
|
2964
|
+
pnpm add -D wrangler
|
|
2965
|
+
```
|
|
2966
|
+
|
|
2967
|
+
For Vue clients, replace `react-fate` with `vue-fate`.
|
|
2968
|
+
|
|
2969
|
+
### Server Setup
|
|
2970
|
+
|
|
2971
|
+
Create a Cloudflare live stream and pass its Fate live facade to `createFateServer`.
|
|
2972
|
+
|
|
2973
|
+
```ts
|
|
2974
|
+
// src/fate/live.ts
|
|
2975
|
+
import { defineCloudflareFateLiveStream } from 'cf-fate/server';
|
|
2976
|
+
|
|
2977
|
+
export const fateStream = defineCloudflareFateLiveStream({
|
|
2978
|
+
allowAnonymousControl: true,
|
|
2979
|
+
binding: 'FATE_LIVE',
|
|
2980
|
+
id: 'fate',
|
|
2981
|
+
});
|
|
2982
|
+
```
|
|
2983
|
+
|
|
2984
|
+
```ts
|
|
2985
|
+
// src/fate/server.ts
|
|
2986
|
+
import { createFateServer } from '@nkzw/fate/server';
|
|
2987
|
+
import { createCloudflareFateLive } from 'cf-fate/server';
|
|
2988
|
+
|
|
2989
|
+
export const fateLive = createCloudflareFateLive();
|
|
2990
|
+
export const { live } = fateLive;
|
|
2991
|
+
|
|
2992
|
+
export const fateServer = createFateServer({
|
|
2993
|
+
live,
|
|
2994
|
+
// context,
|
|
2995
|
+
// roots,
|
|
2996
|
+
// sources,
|
|
2997
|
+
});
|
|
2998
|
+
```
|
|
2999
|
+
|
|
3000
|
+
Publish from mutations through the normal Fate live bus:
|
|
3001
|
+
|
|
3002
|
+
```ts
|
|
3003
|
+
live.update('Post', postId, { changed: ['likes'] });
|
|
3004
|
+
live.connection('Post.comments', { id: postId }).appendNode('Comment', commentId);
|
|
3005
|
+
```
|
|
3006
|
+
|
|
3007
|
+
### Worker Routes
|
|
3008
|
+
|
|
3009
|
+
Expose one route for Fate RPC and one route for the SSE live stream.
|
|
3010
|
+
|
|
3011
|
+
```ts
|
|
3012
|
+
import {
|
|
3013
|
+
createCloudflareFateLiveDurableObject,
|
|
3014
|
+
defineCloudflareFateLiveRoute,
|
|
3015
|
+
defineCloudflareFateRoute,
|
|
3016
|
+
} from 'cf-fate/server';
|
|
3017
|
+
import { fateStream } from './fate/live';
|
|
3018
|
+
import { fateLive, fateServer } from './fate/server';
|
|
3019
|
+
|
|
3020
|
+
const fateRoute = defineCloudflareFateRoute(fateServer, fateLive, { stream: fateStream });
|
|
3021
|
+
const fateLiveRoute = defineCloudflareFateLiveRoute(fateStream);
|
|
3022
|
+
|
|
3023
|
+
export const FateLiveDurableObject = createCloudflareFateLiveDurableObject({
|
|
3024
|
+
binding: 'FATE_LIVE',
|
|
3025
|
+
});
|
|
3026
|
+
|
|
3027
|
+
export default {
|
|
3028
|
+
fetch(request, env, ctx) {
|
|
3029
|
+
const url = new URL(request.url);
|
|
3030
|
+
if (url.pathname === '/fate') {
|
|
3031
|
+
return fateRoute.fetch(request, env, ctx);
|
|
3032
|
+
}
|
|
3033
|
+
if (url.pathname === '/fate-live') {
|
|
3034
|
+
return fateLiveRoute.fetch(request, env, ctx);
|
|
3035
|
+
}
|
|
3036
|
+
return new Response('Not Found', { status: 404 });
|
|
3037
|
+
},
|
|
3038
|
+
};
|
|
3039
|
+
```
|
|
3040
|
+
|
|
3041
|
+
### Wrangler
|
|
3042
|
+
|
|
3043
|
+
Add a Durable Object binding and migration. `cf-fate` uses `node:async_hooks`, so the Worker must enable Node compatibility.
|
|
3044
|
+
|
|
3045
|
+
```jsonc
|
|
3046
|
+
{
|
|
3047
|
+
"compatibility_flags": ["nodejs_compat"],
|
|
3048
|
+
"durable_objects": {
|
|
3049
|
+
"bindings": [
|
|
3050
|
+
{
|
|
3051
|
+
"name": "FATE_LIVE",
|
|
3052
|
+
"class_name": "FateLiveDurableObject",
|
|
3053
|
+
},
|
|
3054
|
+
],
|
|
3055
|
+
},
|
|
3056
|
+
"migrations": [
|
|
3057
|
+
{
|
|
3058
|
+
"tag": "fate-live-v1",
|
|
3059
|
+
"new_sqlite_classes": ["FateLiveDurableObject"],
|
|
3060
|
+
},
|
|
3061
|
+
],
|
|
3062
|
+
}
|
|
3063
|
+
```
|
|
3064
|
+
|
|
3065
|
+
### Client
|
|
3066
|
+
|
|
3067
|
+
Use the Cloudflare transport in the Fate Vite plugin:
|
|
3068
|
+
|
|
3069
|
+
```ts
|
|
3070
|
+
import { fate } from 'react-fate/vite';
|
|
3071
|
+
|
|
3072
|
+
fate({
|
|
3073
|
+
module: './src/fate/server.ts',
|
|
3074
|
+
transport: 'cloudflare',
|
|
3075
|
+
});
|
|
3076
|
+
```
|
|
3077
|
+
|
|
3078
|
+
Then point the generated client at the Worker endpoints:
|
|
3079
|
+
|
|
3080
|
+
```tsx
|
|
3081
|
+
import { FateClient } from 'react-fate';
|
|
3082
|
+
import { createFateClient } from 'react-fate/client';
|
|
3083
|
+
|
|
3084
|
+
const fate = createFateClient({
|
|
3085
|
+
liveUrl: 'http://localhost:8787/fate-live',
|
|
3086
|
+
url: 'http://localhost:8787/fate',
|
|
3087
|
+
});
|
|
3088
|
+
|
|
3089
|
+
export function App({ children }) {
|
|
3090
|
+
return <FateClient client={fate}>{children}</FateClient>;
|
|
3091
|
+
}
|
|
3092
|
+
```
|
|
3093
|
+
|
|
3094
|
+
### Semantics
|
|
3095
|
+
|
|
3096
|
+
`cf-fate` uses one browser `EventSource` per Fate client and multiplexes entity and connection topics over that stream. Durable Objects keep connection and topic subscription state so later requests, mutations, scheduled handlers, and queue consumers can publish to already-connected clients.
|
|
3097
|
+
|
|
3098
|
+
Delivery is at-most-once. Events are ordered within one topic, but events are not durably replayed after a disconnect. Use authoritative refetching or application-owned replay storage if missed events must be recovered.
|
|
3099
|
+
|
|
2922
3100
|
## Frequently Asked Questions
|
|
2923
3101
|
|
|
2924
3102
|
### Is this serious software?
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **FateClient**(`__namedParameters`): `Element`
|
|
4
4
|
|
|
5
|
-
Defined in: [packages/react-fate/src/context.tsx:17](https://github.com/nkzw-tech/fate/blob/
|
|
5
|
+
Defined in: [packages/react-fate/src/context.tsx:17](https://github.com/nkzw-tech/fate/blob/bdff68417591ff0372c03c214bbc7c722cdf13a2/packages/react-fate/src/context.tsx#L17)
|
|
6
6
|
|
|
7
7
|
Provider component that supplies a configured `FateClient` to React hooks.
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **useFateClient**\<`T`\>(): `FateClient`\<`T`\[`0`\], `T`\[`1`\]\>
|
|
4
4
|
|
|
5
|
-
Defined in: [packages/react-fate/src/context.tsx:30](https://github.com/nkzw-tech/fate/blob/
|
|
5
|
+
Defined in: [packages/react-fate/src/context.tsx:30](https://github.com/nkzw-tech/fate/blob/bdff68417591ff0372c03c214bbc7c722cdf13a2/packages/react-fate/src/context.tsx#L30)
|
|
6
6
|
|
|
7
7
|
Returns the nearest `FateClient` from context.
|
|
8
8
|
|
|
@@ -10,7 +10,7 @@ Returns the nearest `FateClient` from context.
|
|
|
10
10
|
|
|
11
11
|
### T
|
|
12
12
|
|
|
13
|
-
`T` *extends* \[\{ `categories`: `RootDefinition`\<`"Category"`,
|
|
13
|
+
`T` *extends* \[\{ `categories`: `RootDefinition`\<`"Category"`, \{ `items`: `object`[]; `pagination`: `ConnectionPagination`; \}\>; `category`: `RootDefinition`\<`"Category"`, `unknown`\>; `comment`: `RootDefinition`\<`"Comment"`, `unknown`\>; `commentSearch`: `RootDefinition`\<`"Comment"`, \{ `items`: `object`[]; `pagination`: `ConnectionPagination`; \}\>; `event`: `RootDefinition`\<`"Event"`, `unknown`\>; `events`: `RootDefinition`\<`"Event"`, \{ `items`: `object`[]; `pagination`: `ConnectionPagination`; \}\>; `post`: `RootDefinition`\<`"Post"`, `unknown`\>; `posts`: `RootDefinition`\<`"Post"`, \{ `items`: `object`[]; `pagination`: `ConnectionPagination`; \}\>; `viewer`: `RootDefinition`\<`"User"`, `User` \| `null`\>; \}, \{ `comment.add`: `MutationDefinition`\<`Comment`, \{ `args?`: `unknown`; `content`: `string`; `postId`: `string`; `select`: `string`[]; \}, \{ `author?`: \{ `banExpires`: `string` \| `null`; `banned`: `boolean` \| `null`; `banReason`: `string` \| `null`; `createdAt`: `string`; `displayUsername`: `string` \| `null`; `email`: `string`; `emailVerified`: `boolean`; `id`: `string`; `image`: `string` \| `null`; `name`: `string`; `password`: `string` \| `null`; `role`: `string`; `updatedAt`: `string`; `username`: `string` \| `null`; \} \| `null`; `authorId`: `string` \| `null`; `content`: `string`; `createdAt`: `string`; `id`: `string`; `post?`: \{ `authorId`: `string`; `categoryId`: `string` \| `null`; `commentCount`: `number`; `content`: `string`; `createdAt`: `string`; `id`: `string`; `likes`: `number`; `title`: `string`; `updatedAt`: `string`; \}; `postId`: `string`; \}\>; `comment.delete`: `MutationDefinition`\<`Comment`, \{ `args?`: `unknown`; `id`: `string`; `select?`: `string`[]; \}, \{ `author?`: \{ `banExpires`: `string` \| `null`; `banned`: `boolean` \| `null`; `banReason`: `string` \| `null`; `createdAt`: `string`; `displayUsername`: `string` \| `null`; `email`: `string`; `emailVerified`: `boolean`; `id`: `string`; `image`: `string` \| `null`; `name`: `string`; `password`: `string` \| `null`; `role`: `string`; `updatedAt`: `string`; `username`: `string` \| `null`; \} \| `null`; `authorId`: `string` \| `null`; `content`: `string`; `createdAt`: `string`; `id`: `string`; `post?`: \{ `authorId`: `string`; `categoryId`: `string` \| `null`; `commentCount`: `number`; `content`: `string`; `createdAt`: `string`; `id`: `string`; `likes`: `number`; `title`: `string`; `updatedAt`: `string`; \}; `postId`: `string`; \}\>; `post.add`: `MutationDefinition`\<`Post`, \{ `args?`: `unknown`; `content`: `string`; `select`: `string`[]; `title`: `string`; \}, `Post`\>; `post.like`: `MutationDefinition`\<`Post`, \{ `args?`: `unknown`; `error?`: `"boundary"` \| `"callSite"`; `id`: `string`; `select`: `string`[]; `slow?`: `boolean`; \}, `Post`\>; `post.unlike`: `MutationDefinition`\<`Post`, \{ `args?`: `unknown`; `id`: `string`; `select`: `string`[]; \}, `Post`\>; `user.update`: `MutationDefinition`\<`User`, \{ `args?`: `unknown`; `name`: `string`; `select`: `string`[]; \}, `Record`\<`string`, `unknown`\>\>; \}\] = \[\{ `categories`: `RootDefinition`\<`"Category"`, \{ `items`: `object`[]; `pagination`: `ConnectionPagination`; \}\>; `category`: `RootDefinition`\<`"Category"`, `unknown`\>; `comment`: `RootDefinition`\<`"Comment"`, `unknown`\>; `commentSearch`: `RootDefinition`\<`"Comment"`, \{ `items`: `object`[]; `pagination`: `ConnectionPagination`; \}\>; `event`: `RootDefinition`\<`"Event"`, `unknown`\>; `events`: `RootDefinition`\<`"Event"`, \{ `items`: `object`[]; `pagination`: `ConnectionPagination`; \}\>; `post`: `RootDefinition`\<`"Post"`, `unknown`\>; `posts`: `RootDefinition`\<`"Post"`, \{ `items`: `object`[]; `pagination`: `ConnectionPagination`; \}\>; `viewer`: `RootDefinition`\<`"User"`, `User` \| `null`\>; \}, \{ `comment.add`: `MutationDefinition`\<`Comment`, \{ `args?`: `unknown`; `content`: `string`; `postId`: `string`; `select`: `string`[]; \}, \{ `author?`: \{ `banExpires`: `string` \| `null`; `banned`: `boolean` \| `null`; `banReason`: `string` \| `null`; `createdAt`: `string`; `displayUsername`: `string` \| `null`; `email`: `string`; `emailVerified`: `boolean`; `id`: `string`; `image`: `string` \| `null`; `name`: `string`; `password`: `string` \| `null`; `role`: `string`; `updatedAt`: `string`; `username`: `string` \| `null`; \} \| `null`; `authorId`: `string` \| `null`; `content`: `string`; `createdAt`: `string`; `id`: `string`; `post?`: \{ `authorId`: `string`; `categoryId`: `string` \| `null`; `commentCount`: `number`; `content`: `string`; `createdAt`: `string`; `id`: `string`; `likes`: `number`; `title`: `string`; `updatedAt`: `string`; \}; `postId`: `string`; \}\>; `comment.delete`: `MutationDefinition`\<`Comment`, \{ `args?`: `unknown`; `id`: `string`; `select?`: `string`[]; \}, \{ `author?`: \{ `banExpires`: `string` \| `null`; `banned`: `boolean` \| `null`; `banReason`: `string` \| `null`; `createdAt`: `string`; `displayUsername`: `string` \| `null`; `email`: `string`; `emailVerified`: `boolean`; `id`: `string`; `image`: `string` \| `null`; `name`: `string`; `password`: `string` \| `null`; `role`: `string`; `updatedAt`: `string`; `username`: `string` \| `null`; \} \| `null`; `authorId`: `string` \| `null`; `content`: `string`; `createdAt`: `string`; `id`: `string`; `post?`: \{ `authorId`: `string`; `categoryId`: `string` \| `null`; `commentCount`: `number`; `content`: `string`; `createdAt`: `string`; `id`: `string`; `likes`: `number`; `title`: `string`; `updatedAt`: `string`; \}; `postId`: `string`; \}\>; `post.add`: `MutationDefinition`\<`Post`, \{ `args?`: `unknown`; `content`: `string`; `select`: `string`[]; `title`: `string`; \}, `Post`\>; `post.like`: `MutationDefinition`\<`Post`, \{ `args?`: `unknown`; `error?`: `"boundary"` \| `"callSite"`; `id`: `string`; `select`: `string`[]; `slow?`: `boolean`; \}, `Post`\>; `post.unlike`: `MutationDefinition`\<`Post`, \{ `args?`: `unknown`; `id`: `string`; `select`: `string`[]; \}, `Post`\>; `user.update`: `MutationDefinition`\<`User`, \{ `args?`: `unknown`; `name`: `string`; `select`: `string`[]; \}, `Record`\<`string`, `unknown`\>\>; \}\]
|
|
14
14
|
|
|
15
15
|
## Returns
|
|
16
16
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **useListView**\<`C`\>(`selection`, `connection`): \[`ConnectionItems`\<`ResolvedConnection`\<`C`\>\>, `LoadMoreFn` \| `null`, `LoadMoreFn` \| `null`\]
|
|
4
4
|
|
|
5
|
-
Defined in: [packages/react-fate/src/useListView.tsx:19](https://github.com/nkzw-tech/fate/blob/
|
|
5
|
+
Defined in: [packages/react-fate/src/useListView.tsx:19](https://github.com/nkzw-tech/fate/blob/bdff68417591ff0372c03c214bbc7c722cdf13a2/packages/react-fate/src/useListView.tsx#L19)
|
|
6
6
|
|
|
7
7
|
Subscribes to a connection field, returning the current items and pagination
|
|
8
8
|
helpers to load the next or previous page.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **useLiveListView**\<`C`\>(`selection`, `connection`): \[`ConnectionItems`\<`ResolvedConnection`\<`C`\>\>, `LoadMoreFn` \| `null`, `LoadMoreFn` \| `null`\]
|
|
4
4
|
|
|
5
|
-
Defined in: [packages/react-fate/src/useLiveListView.tsx:19](https://github.com/nkzw-tech/fate/blob/
|
|
5
|
+
Defined in: [packages/react-fate/src/useLiveListView.tsx:19](https://github.com/nkzw-tech/fate/blob/bdff68417591ff0372c03c214bbc7c722cdf13a2/packages/react-fate/src/useLiveListView.tsx#L19)
|
|
6
6
|
|
|
7
7
|
Subscribes to a connection field, returning live-updating items and pagination
|
|
8
8
|
helpers to load the next or previous page.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
> **useLiveView**\<`V`, `R`\>(`view`, `ref`): `R` *extends* `null` ? `null` : `Readonly`\<`ViewSelection`\<`V`\> *extends* `Selection`\<`ViewEntityWithTypename`\<`V`\>\> ? `Mask`\<`ViewEntityWithTypename`\<`V`\>, \{ \[K in string \| number \| symbol as K extends "\_\_typename" ? never : K\]?: DeferrableSelectionFieldValue\<ViewEntityWithTypename\<V\>, K\> \} & `object` & `SelectionViewSpread`\<`ViewEntityWithTypename`\<`V`\>\> & `ViewSelection`\<`V`\>\> : `ViewEntityWithTypename`\<`V`\> & `object`\>
|
|
6
6
|
|
|
7
|
-
Defined in: [packages/react-fate/src/useLiveView.tsx:27](https://github.com/nkzw-tech/fate/blob/
|
|
7
|
+
Defined in: [packages/react-fate/src/useLiveView.tsx:27](https://github.com/nkzw-tech/fate/blob/bdff68417591ff0372c03c214bbc7c722cdf13a2/packages/react-fate/src/useLiveView.tsx#L27)
|
|
8
8
|
|
|
9
9
|
Resolves a reference against a view and subscribes to live server updates for
|
|
10
10
|
that selection.
|
|
@@ -43,7 +43,7 @@ const post = useLiveView(PostView, postRef);
|
|
|
43
43
|
|
|
44
44
|
> **useLiveView**\<`V`, `R`\>(`view`, `ref`): `R` *extends* `null` ? `null` : `Readonly`\<`ViewSelection`\<`V`\> *extends* `Selection`\<`ViewEntityWithTypename`\<`V`\>\> ? `Mask`\<`ViewEntityWithTypename`\<`V`\>, \{ \[K in string \| number \| symbol as K extends "\_\_typename" ? never : K\]?: DeferrableSelectionFieldValue\<ViewEntityWithTypename\<V\>, K\> \} & `object` & `SelectionViewSpread`\<`ViewEntityWithTypename`\<`V`\>\> & `ViewSelection`\<`V`\>\> : `ViewEntityWithTypename`\<`V`\> & `object`\>
|
|
45
45
|
|
|
46
|
-
Defined in: [packages/react-fate/src/useLiveView.tsx:31](https://github.com/nkzw-tech/fate/blob/
|
|
46
|
+
Defined in: [packages/react-fate/src/useLiveView.tsx:31](https://github.com/nkzw-tech/fate/blob/bdff68417591ff0372c03c214bbc7c722cdf13a2/packages/react-fate/src/useLiveView.tsx#L31)
|
|
47
47
|
|
|
48
48
|
Resolves a reference against a view and subscribes to live server updates for
|
|
49
49
|
that selection.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **useRequest**\<`R`, `O`\>(`request`, `options?`): `RequestResult`\<`O`, `R`\>
|
|
4
4
|
|
|
5
|
-
Defined in: [packages/react-fate/src/useRequest.tsx:25](https://github.com/nkzw-tech/fate/blob/
|
|
5
|
+
Defined in: [packages/react-fate/src/useRequest.tsx:25](https://github.com/nkzw-tech/fate/blob/bdff68417591ff0372c03c214bbc7c722cdf13a2/packages/react-fate/src/useRequest.tsx#L25)
|
|
6
6
|
|
|
7
7
|
Declares the data a screen needs and kicks off fetching, suspending while the
|
|
8
8
|
request resolves.
|
|
@@ -15,7 +15,7 @@ request resolves.
|
|
|
15
15
|
|
|
16
16
|
### O
|
|
17
17
|
|
|
18
|
-
`O` *extends* `FateRoots` = \{ `categories`: `RootDefinition`\<`"Category"`,
|
|
18
|
+
`O` *extends* `FateRoots` = \{ `categories`: `RootDefinition`\<`"Category"`, \{ `items`: `object`[]; `pagination`: `ConnectionPagination`; \}\>; `category`: `RootDefinition`\<`"Category"`, `unknown`\>; `comment`: `RootDefinition`\<`"Comment"`, `unknown`\>; `commentSearch`: `RootDefinition`\<`"Comment"`, \{ `items`: `object`[]; `pagination`: `ConnectionPagination`; \}\>; `event`: `RootDefinition`\<`"Event"`, `unknown`\>; `events`: `RootDefinition`\<`"Event"`, \{ `items`: `object`[]; `pagination`: `ConnectionPagination`; \}\>; `post`: `RootDefinition`\<`"Post"`, `unknown`\>; `posts`: `RootDefinition`\<`"Post"`, \{ `items`: `object`[]; `pagination`: `ConnectionPagination`; \}\>; `viewer`: `RootDefinition`\<`"User"`, `User` \| `null`\>; \}
|
|
19
19
|
|
|
20
20
|
## Parameters
|
|
21
21
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
> **useView**\<`V`, `R`\>(`view`, `ref`): `R` *extends* `null` ? `null` : `Readonly`\<`ViewSelection`\<`V`\> *extends* `Selection`\<`ViewEntityWithTypename`\<`V`\>\> ? `Mask`\<`ViewEntityWithTypename`\<`V`\>, \{ \[K in string \| number \| symbol as K extends "\_\_typename" ? never : K\]?: DeferrableSelectionFieldValue\<ViewEntityWithTypename\<V\>, K\> \} & `object` & `SelectionViewSpread`\<`ViewEntityWithTypename`\<`V`\>\> & `ViewSelection`\<`V`\>\> : `ViewEntityWithTypename`\<`V`\> & `object`\>
|
|
6
6
|
|
|
7
|
-
Defined in: [packages/react-fate/src/useView.tsx:40](https://github.com/nkzw-tech/fate/blob/
|
|
7
|
+
Defined in: [packages/react-fate/src/useView.tsx:40](https://github.com/nkzw-tech/fate/blob/bdff68417591ff0372c03c214bbc7c722cdf13a2/packages/react-fate/src/useView.tsx#L40)
|
|
8
8
|
|
|
9
9
|
Resolves a reference against a view and subscribes to updates for that selection.
|
|
10
10
|
|
|
@@ -42,7 +42,7 @@ const post = useView(PostView, postRef);
|
|
|
42
42
|
|
|
43
43
|
> **useView**\<`V`, `R`\>(`view`, `ref`): `R` *extends* `null` ? `null` : `Readonly`\<`ViewSelection`\<`V`\> *extends* `Selection`\<`ViewEntityWithTypename`\<`V`\>\> ? `Mask`\<`ViewEntityWithTypename`\<`V`\>, \{ \[K in string \| number \| symbol as K extends "\_\_typename" ? never : K\]?: DeferrableSelectionFieldValue\<ViewEntityWithTypename\<V\>, K\> \} & `object` & `SelectionViewSpread`\<`ViewEntityWithTypename`\<`V`\>\> & `ViewSelection`\<`V`\>\> : `ViewEntityWithTypename`\<`V`\> & `object`\>
|
|
44
44
|
|
|
45
|
-
Defined in: [packages/react-fate/src/useView.tsx:44](https://github.com/nkzw-tech/fate/blob/
|
|
45
|
+
Defined in: [packages/react-fate/src/useView.tsx:44](https://github.com/nkzw-tech/fate/blob/bdff68417591ff0372c03c214bbc7c722cdf13a2/packages/react-fate/src/useView.tsx#L44)
|
|
46
46
|
|
|
47
47
|
Resolves a reference against a view and subscribes to updates for that selection.
|
|
48
48
|
|
|
@@ -80,7 +80,7 @@ const post = useView(PostView, postRef);
|
|
|
80
80
|
|
|
81
81
|
> **useView**\<`V`\>(`view`, `ref`): `Readonly`\<`ViewSelection`\<`V`\> *extends* `Selection`\<`ViewEntityWithTypename`\<`V`\>\> ? `Mask`\<`ViewEntityWithTypename`\<`V`\>, \{ \[K in string \| number \| symbol as K extends "\_\_typename" ? never : K\]?: DeferrableSelectionFieldValue\<ViewEntityWithTypename\<V\>, K\> \} & `object` & `SelectionViewSpread`\<`ViewEntityWithTypename`\<`V`\>\> & `ViewSelection`\<`V`\>\> : `ViewEntityWithTypename`\<`V`\> & `object`\> \| `null`
|
|
82
82
|
|
|
83
|
-
Defined in: [packages/react-fate/src/useView.tsx:48](https://github.com/nkzw-tech/fate/blob/
|
|
83
|
+
Defined in: [packages/react-fate/src/useView.tsx:48](https://github.com/nkzw-tech/fate/blob/bdff68417591ff0372c03c214bbc7c722cdf13a2/packages/react-fate/src/useView.tsx#L48)
|
|
84
84
|
|
|
85
85
|
Resolves a reference against a view and subscribes to updates for that selection.
|
|
86
86
|
|
|
@@ -4,13 +4,31 @@
|
|
|
4
4
|
|
|
5
5
|
Use it when your backend runs directly on Cloudflare Workers and you want fate live views without adopting the Void platform.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## New Project
|
|
8
|
+
|
|
9
|
+
For a new Cloudflare Workers app, start from the Cloudflare template. It includes the client, Worker server, D1 migrations, Wrangler config, Durable Object live transport, auth wiring, and generated fate client setup.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
vp create fate my-app --template cloudflare
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Use Vue instead of React with:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
vp create fate my-app --template cloudflare --framework vue
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Existing Project
|
|
22
|
+
|
|
23
|
+
For an existing Cloudflare Workers project, add the packages directly:
|
|
8
24
|
|
|
9
25
|
```sh
|
|
10
26
|
pnpm add @nkzw/fate react-fate cf-fate drizzle-orm
|
|
11
27
|
pnpm add -D wrangler
|
|
12
28
|
```
|
|
13
29
|
|
|
30
|
+
For Vue clients, replace `react-fate` with `vue-fate`.
|
|
31
|
+
|
|
14
32
|
## Server Setup
|
|
15
33
|
|
|
16
34
|
Create a Cloudflare live stream and pass its Fate live facade to `createFateServer`.
|
|
@@ -5,7 +5,23 @@
|
|
|
5
5
|
Use this integration when your app runs on Void and you want the example app's
|
|
6
6
|
setup without copying its adapter glue.
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## New Project
|
|
9
|
+
|
|
10
|
+
For a new Void app, start from the Void template. It includes the client, Void routes, Drizzle setup, live transport, auth wiring, and generated fate client setup.
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
vp create fate my-app --template void
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Use Vue instead of React with:
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
vp create fate my-app --template void --framework vue
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Existing Project
|
|
23
|
+
|
|
24
|
+
For an existing Void project, add the packages directly:
|
|
9
25
|
|
|
10
26
|
::: code-group
|
|
11
27
|
|
package/lib/index.mjs
CHANGED
|
@@ -72,7 +72,8 @@ function useView(view, ref) {
|
|
|
72
72
|
return thenable;
|
|
73
73
|
}
|
|
74
74
|
mergedSnapshotRef.current = null;
|
|
75
|
-
|
|
75
|
+
const value = snapshot.value;
|
|
76
|
+
snapshotRef.current = value;
|
|
76
77
|
return snapshot;
|
|
77
78
|
}
|
|
78
79
|
mergedSnapshotRef.current = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-fate",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "fate is a modern data client for React.",
|
|
5
5
|
"homepage": "https://github.com/nkzw-tech/fate",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@nkzw/fate": "^1.3.
|
|
43
|
+
"@nkzw/fate": "^1.3.2"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@types/react": "^19.2.
|
|
46
|
+
"@types/react": "^19.2.17",
|
|
47
47
|
"@types/react-dom": "^19.2.3",
|
|
48
48
|
"react": "^19.2.7",
|
|
49
49
|
"react-dom": "^19.2.7"
|