vue-fate 1.7.7 → 1.9.0
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 +176 -12
- package/docs/api/index.md +3 -0
- package/docs/api/react-fate/src/functions/alias.md +57 -0
- package/docs/api/react-fate/src/functions/clientRoot.md +31 -0
- package/docs/api/react-fate/src/functions/clientValueRoot.md +19 -0
- package/docs/api/react-fate/src/functions/createClient.md +25 -0
- package/docs/api/react-fate/src/functions/createGraphQLTransport.md +21 -0
- package/docs/api/react-fate/src/functions/createHTTPTransport.md +51 -0
- package/docs/api/react-fate/src/functions/createTRPCTransport.md +50 -0
- package/docs/api/react-fate/src/functions/defer.md +21 -0
- package/docs/api/react-fate/src/functions/graphqlMutation.md +39 -0
- package/docs/api/react-fate/src/functions/graphqlValueMutation.md +35 -0
- package/docs/api/react-fate/src/functions/graphqlValueRoot.md +31 -0
- package/docs/api/react-fate/src/functions/mutation.md +32 -0
- package/docs/api/react-fate/src/functions/valueMutation.md +19 -0
- package/docs/api/react-fate/src/functions/view.md +26 -0
- package/docs/api/react-fate/src/functions/when.md +31 -0
- package/docs/api/react-fate/src/interfaces/Persistence.md +5 -0
- package/docs/api/react-fate/src/interfaces/PersistenceSession.md +109 -0
- package/docs/api/react-fate/src/type-aliases/AliasedSelection.md +15 -0
- package/docs/api/react-fate/src/type-aliases/AliasedView.md +11 -0
- package/docs/api/react-fate/src/type-aliases/ConditionalSelection.md +15 -0
- package/docs/api/react-fate/src/type-aliases/ConnectionRef.md +13 -0
- package/docs/api/react-fate/src/type-aliases/Deferred.md +19 -0
- package/docs/api/react-fate/src/type-aliases/FateDehydratedState.md +11 -0
- package/docs/api/react-fate/src/type-aliases/GraphQLMutationDefinition.md +19 -0
- package/docs/api/react-fate/src/type-aliases/GraphQLMutationInput.md +11 -0
- package/docs/api/react-fate/src/type-aliases/GraphQLMutationMap.md +11 -0
- package/docs/api/react-fate/src/type-aliases/GraphQLMutationOutput.md +11 -0
- package/docs/api/react-fate/src/type-aliases/GraphQLRootInput.md +11 -0
- package/docs/api/react-fate/src/type-aliases/GraphQLRootOutput.md +11 -0
- package/docs/api/react-fate/src/type-aliases/GraphQLSelectedResult.md +21 -0
- package/docs/api/react-fate/src/type-aliases/GraphQLTransportOptions.md +151 -0
- package/docs/api/react-fate/src/type-aliases/GraphQLValueRootDefinition.md +33 -0
- package/docs/api/react-fate/src/type-aliases/HydrateOptions.md +7 -0
- package/docs/api/react-fate/src/type-aliases/HydrationLimits.md +7 -0
- package/docs/api/react-fate/src/type-aliases/InferFateAPI.md +11 -0
- package/docs/api/react-fate/src/type-aliases/Pagination.md +39 -0
- package/docs/api/react-fate/src/type-aliases/ParameterizedView.md +19 -0
- package/docs/api/react-fate/src/type-aliases/PersistenceSnapshot.md +5 -0
- package/docs/api/react-fate/src/type-aliases/ViewRef.md +13 -0
- package/docs/api/react-fate/src/variables/toEntityId.md +21 -0
- package/docs/api/vue-fate/functions/createFatePlugin.md +15 -0
- package/docs/api/vue-fate/functions/provideFateClient.md +15 -0
- package/docs/api/vue-fate/functions/useFateClient.md +17 -0
- package/docs/api/vue-fate/functions/useListView.md +27 -0
- package/docs/api/vue-fate/functions/useLiveListView.md +27 -0
- package/docs/api/vue-fate/functions/useLiveView.md +93 -0
- package/docs/api/vue-fate/functions/useRequest.md +31 -0
- package/docs/api/vue-fate/functions/useView.md +93 -0
- package/docs/api/vue-fate/index.md +271 -0
- package/docs/api/vue-fate/type-aliases/ListViewState.md +45 -0
- package/docs/api/vue-fate/type-aliases/RequestResource.md +71 -0
- package/docs/api/vue-fate/type-aliases/ViewResource.md +45 -0
- package/docs/api/vue-fate/variables/FateClient.md +7 -0
- package/docs/api/vue-fate/variables/FateClientKey.md +5 -0
- package/docs/guide/actions.md +305 -0
- package/docs/guide/core-concepts.md +22 -0
- package/docs/guide/deferred-views.md +62 -0
- package/docs/guide/getting-started.md +71 -0
- package/docs/guide/list-views.md +88 -0
- package/docs/guide/live-views.md +258 -0
- package/docs/guide/persistence.md +321 -0
- package/docs/guide/requests.md +331 -0
- package/docs/guide/views.md +368 -0
- package/docs/guide/vue.md +256 -0
- package/docs/guide/why-fate.md +40 -0
- package/docs/index.md +5 -0
- package/docs/integrations/cloudflare.md +43 -0
- package/docs/integrations/graphql.md +545 -0
- package/docs/integrations/server.md +731 -0
- package/docs/integrations/void.md +279 -0
- package/lib/client.mjs +1 -2
- package/lib/index.d.mts +2 -2
- package/lib/index.mjs +13 -6
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -437,8 +437,8 @@ ViewRefs carry a set of view names they can resolve. `useView` throws if a ref d
|
|
|
437
437
|
A view can take parameters. Define the selection with a function, then bind its parameters where you request or compose the view:
|
|
438
438
|
|
|
439
439
|
```tsx
|
|
440
|
-
import { alias, useRequest, useView, view, when, type ViewRef } from 'react-fate';
|
|
441
440
|
import type { User } from '@your-org/server/views';
|
|
441
|
+
import { alias, useRequest, useView, view, when, type ViewRef } from 'react-fate';
|
|
442
442
|
|
|
443
443
|
const AccountView = view<User>()({ email: true });
|
|
444
444
|
|
|
@@ -616,6 +616,43 @@ const { posts } = useRequest(
|
|
|
616
616
|
);
|
|
617
617
|
```
|
|
618
618
|
|
|
619
|
+
### Timeouts and cancellation
|
|
620
|
+
|
|
621
|
+
Read requests accept an optional `timeout` in milliseconds and an `AbortSignal`:
|
|
622
|
+
|
|
623
|
+
```tsx
|
|
624
|
+
const result = useRequest(request, { timeout: 10_000 });
|
|
625
|
+
const refetch = useRefetch(request, { timeout: 10_000 });
|
|
626
|
+
|
|
627
|
+
const controller = new AbortController();
|
|
628
|
+
await client.request(request, { timeout: 10_000, signal: controller.signal });
|
|
629
|
+
// From another event handler: controller.abort();
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
The default has no deadline. A timeout rejects with an error named `TimeoutError`;
|
|
633
|
+
external cancellation rejects with `signal.reason` (normally an `AbortError`).
|
|
634
|
+
The deadline starts when the read starts, includes persistence initialization,
|
|
635
|
+
and stays fixed across equivalent Suspense rerenders. Use a stable signal when
|
|
636
|
+
passing one to a hook. An already-aborted signal prevents a new fetch.
|
|
637
|
+
|
|
638
|
+
Each imperative caller has its own deadline. Identical pending reads can share
|
|
639
|
+
work, but cancelling one caller keeps that work alive for the others. Batched HTTP
|
|
640
|
+
and GraphQL requests abort their shared fetch only when every operation cancels.
|
|
641
|
+
Cancelled operations cannot write late network results to the cache. Custom
|
|
642
|
+
transports receive the signal in their optional read context and should forward
|
|
643
|
+
it to their network implementation; fate still rejects and ignores their late
|
|
644
|
+
results if they do not support cancellation. The tRPC adapter passes the signal
|
|
645
|
+
in the resolver's second argument, matching tRPC query options.
|
|
646
|
+
|
|
647
|
+
`useRequest` sends initial failures to your error boundary. Handle errors from
|
|
648
|
+
`useRefetch` or `client.request` in the calling event handler; these failures
|
|
649
|
+
preserve existing data. An explicit retry starts a new deadline. The same options
|
|
650
|
+
work with `useRequestState`, `client.observeRequest`, and Vue `useRequest`.
|
|
651
|
+
For `stale-while-revalidate`, cached data returns immediately while the deadline
|
|
652
|
+
bounds the background refresh. These controls apply to the request's initial
|
|
653
|
+
reads; later view reads, deferred fields, pagination, live streams, and mutations
|
|
654
|
+
have separate lifetimes and do not inherit them.
|
|
655
|
+
|
|
619
656
|
### Cache Lifetime
|
|
620
657
|
|
|
621
658
|
fate stores records in a normalized cache keyed by `__typename` and `id`. Lists and root queries point at those records, and views read from the normalized cache. When a `useRequest` call is mounted, fate retains the request so the records and lists needed by that screen stay in memory. When the component unmounts, the request is released and fate schedules garbage collection.
|
|
@@ -793,6 +830,30 @@ one operation. Selection path segments and corresponding argument keys then use
|
|
|
793
830
|
GraphQL performs that conversion automatically. Applications consume the declared
|
|
794
831
|
result names, never the encoded transport names.
|
|
795
832
|
|
|
833
|
+
### Imperative refresh with Suspense
|
|
834
|
+
|
|
835
|
+
In React, use `useRefetch` alongside `useRequest` to refresh the same request from
|
|
836
|
+
an event handler without changing the Suspense hook's return value:
|
|
837
|
+
|
|
838
|
+
```tsx
|
|
839
|
+
import { useRefetch, useRequest } from 'react-fate';
|
|
840
|
+
|
|
841
|
+
const request = { viewer: { view: UserView } };
|
|
842
|
+
const { viewer } = useRequest(request);
|
|
843
|
+
const refetch = useRefetch(request);
|
|
844
|
+
|
|
845
|
+
// In an event handler or React Action:
|
|
846
|
+
await refetch();
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
Calling the hook does not fetch or subscribe. Its callback forces a network
|
|
850
|
+
request and returns its typed result, rejecting on failure so the caller can
|
|
851
|
+
handle the error. Existing cached data stays available while refreshing. Cache
|
|
852
|
+
updates notify subscribed views and requests, including changed root results.
|
|
853
|
+
Equivalent inline requests preserve the callback's identity. The optional second
|
|
854
|
+
argument accepts `persist` options; the request mode is always `network-only`.
|
|
855
|
+
Entity refreshes use the configured refetch query when one exists, across transports.
|
|
856
|
+
|
|
796
857
|
## Deferred Views
|
|
797
858
|
|
|
798
859
|
Use `defer` when a field should not block the parent view. The parent view receives a deferred handle immediately after the eager fields are available, and the component that reads that handle with `useView`, `useListView`, or `useLiveListView` decides which `Suspense` boundary handles the loading state.
|
|
@@ -930,6 +991,8 @@ const CommentConnectionView = {
|
|
|
930
991
|
|
|
931
992
|
When `loadNext` runs, fate sends the next cursor as `after` and keeps the page size in `first`. When `loadPrevious` runs, fate sends the previous cursor as `before` and uses `last` for the page size. This lets the server distinguish forward and backward pagination while keeping the component API small.
|
|
932
993
|
|
|
994
|
+
Concurrent loads with the same connection, selection, arguments, and cursor share pending work. A failed load rejects its callers and can be retried. Late pages preserve newer confirmed fields and deletions, and cannot restore a page window replaced by a newer refresh. Forward and backward pages can still extend opposite ends of the same list concurrently.
|
|
995
|
+
|
|
933
996
|
Additional arguments on a root request are scoped to that root list:
|
|
934
997
|
|
|
935
998
|
```tsx
|
|
@@ -1391,8 +1454,8 @@ export const fate = createFateServer({
|
|
|
1391
1454
|
The equivalent tRPC mutation lives in your router and returns the selected shape that the client asked for:
|
|
1392
1455
|
|
|
1393
1456
|
```tsx
|
|
1394
|
-
import { z } from 'zod';
|
|
1395
1457
|
import { connectionArgs, createResolver } from '@nkzw/fate/server';
|
|
1458
|
+
import { z } from 'zod';
|
|
1396
1459
|
import { procedure, router } from '../init.ts';
|
|
1397
1460
|
import { postDataView, PostItem } from '../views.ts';
|
|
1398
1461
|
|
|
@@ -1525,8 +1588,8 @@ vp add @nkzw/fate-indexeddb
|
|
|
1525
1588
|
Then pass `persistence` when creating the client:
|
|
1526
1589
|
|
|
1527
1590
|
```tsx
|
|
1528
|
-
import { createPersistence } from '@nkzw/fate/persistence';
|
|
1529
1591
|
import { createIndexedDBStorage } from '@nkzw/fate-indexeddb';
|
|
1592
|
+
import { createPersistence } from '@nkzw/fate/persistence';
|
|
1530
1593
|
import { createFateClient } from 'react-fate/client';
|
|
1531
1594
|
|
|
1532
1595
|
const fate = createFateClient({
|
|
@@ -1863,9 +1926,9 @@ If your server lives in a separate package, install `@nkzw/fate` there as a runt
|
|
|
1863
1926
|
Use the Vue adapter's Vite plugin in the client app:
|
|
1864
1927
|
|
|
1865
1928
|
```ts
|
|
1866
|
-
import { fate } from 'vue-fate/vite';
|
|
1867
|
-
import { defineConfig } from 'vite';
|
|
1868
1929
|
import vue from '@vitejs/plugin-vue';
|
|
1930
|
+
import { defineConfig } from 'vite';
|
|
1931
|
+
import { fate } from 'vue-fate/vite';
|
|
1869
1932
|
|
|
1870
1933
|
export default defineConfig({
|
|
1871
1934
|
plugins: [
|
|
@@ -2213,8 +2276,8 @@ export default defineConfig({
|
|
|
2213
2276
|
|
|
2214
2277
|
```ts [Vue]
|
|
2215
2278
|
import vue from '@vitejs/plugin-vue';
|
|
2216
|
-
import { fate } from 'vue-fate/vite';
|
|
2217
2279
|
import { defineConfig } from 'vite';
|
|
2280
|
+
import { fate } from 'vue-fate/vite';
|
|
2218
2281
|
|
|
2219
2282
|
export default defineConfig({
|
|
2220
2283
|
plugins: [
|
|
@@ -2289,7 +2352,7 @@ const fate = createFateClient({
|
|
|
2289
2352
|
});
|
|
2290
2353
|
```
|
|
2291
2354
|
|
|
2292
|
-
GraphQL
|
|
2355
|
+
GraphQL queries issued in the same microtask are batched into a single document with aliased fields. Mutations use separate requests so a non-null failure cannot skip another mutation or discard its result. Mutations queued in the same microtask execute in invocation order, and a failed mutation does not prevent the next one from executing. The transport does not automatically retry mutations.
|
|
2293
2356
|
|
|
2294
2357
|
Deferred view fields work with the GraphQL transport through the same normalized cache flow as native HTTP: the eager query omits `defer(...)` fields, and `useView`, `useListView`, or `useLiveListView` fetches the missing selection through `nodes(ids:)` when the deferred handle is read. GraphQL `@defer` is the natural wire format for this feature, but fate's GraphQL transport currently expects one JSON result per operation and does not consume incremental multipart patches yet.
|
|
2295
2358
|
|
|
@@ -2318,6 +2381,52 @@ Nested pagination uses the owner ID only for the mapped query field. Pagination
|
|
|
2318
2381
|
|
|
2319
2382
|
Choose fields with the appropriate authorization rules for the consuming views. The adapter does not switch between public and authenticated lookup fields automatically.
|
|
2320
2383
|
|
|
2384
|
+
#### Refetching through existing queries
|
|
2385
|
+
|
|
2386
|
+
An entity's cache identity does not need to be its lookup argument. With a schema, configure ordinary entity query roots directly and assign a refetch recipe:
|
|
2387
|
+
|
|
2388
|
+
```tsx
|
|
2389
|
+
export const fateGraphQL = {
|
|
2390
|
+
schema,
|
|
2391
|
+
nodes: false,
|
|
2392
|
+
roots: {
|
|
2393
|
+
user: { type: 'User' },
|
|
2394
|
+
viewer: { type: 'User' },
|
|
2395
|
+
},
|
|
2396
|
+
refetch: {
|
|
2397
|
+
User: {
|
|
2398
|
+
root: 'user',
|
|
2399
|
+
args: { username: { field: 'username' } },
|
|
2400
|
+
},
|
|
2401
|
+
},
|
|
2402
|
+
};
|
|
2403
|
+
```
|
|
2404
|
+
|
|
2405
|
+
Here `user` maps to `Query.user(username:)`. Aliased root names can specify their GraphQL `field` as usual. Codegen checks the root's return type, required arguments, projected field types, nullability, and constants. A recipe references a single entity query, not a connection or embedded value root. Existing data-view root declarations remain supported.
|
|
2406
|
+
|
|
2407
|
+
Fate automatically selects `username` whenever this entity appears in a query, connection, or mutation response. The locator stays inside the normalized cache and does not appear in a component's masked view unless selected. Entity reads, deferred selections, explicit ID requests, and nested pagination use the recipe instead of `byId` or `nodes`. Matching pending refetches deduplicate, and GraphQL batches distinct lookups using aliases. Legacy `byId` mappings continue working for types without a recipe.
|
|
2408
|
+
|
|
2409
|
+
References retain their stable `(typename, id)` identity. Fate constructs lookup arguments from **confirmed** cached values, so optimistic renames cannot redirect a lookup. The returned identity must match before any normalization occurs. Missing results report `FateRequestError('NOT_FOUND')` without deleting the cached record. A username changed elsewhere may require refreshing an authoritative parent or viewer query. A cold ID without its locator reports an actionable error instead of falling back to an ID lookup. Recipes with no field dependencies, such as a viewer query, can fetch cold identities but still check the result's identity.
|
|
2410
|
+
|
|
2411
|
+
Arguments use `{ field: 'username' }` for scalar field projections, `{ value: ... }` for JSON constants, and `{ object: { ... } }` for nested input objects. The explicit object wrapper also supports input fields literally named `field`, `value`, or `object`. For example:
|
|
2412
|
+
|
|
2413
|
+
```tsx
|
|
2414
|
+
args: {
|
|
2415
|
+
input: {
|
|
2416
|
+
object: {
|
|
2417
|
+
tenant: { value: 'public' },
|
|
2418
|
+
username: { field: 'username' },
|
|
2419
|
+
},
|
|
2420
|
+
},
|
|
2421
|
+
}
|
|
2422
|
+
```
|
|
2423
|
+
|
|
2424
|
+
Use `RefetchArguments<User, GraphQLFieldArguments['Query']['user']>` from `@nkzw/fate` to type-check projections while authoring a recipe. Projected `id` fields use the GraphQL transport's node ID encoder during automatic refetches; ordinary root arguments retain their existing wire representation.
|
|
2425
|
+
|
|
2426
|
+
Implicit locators are retained and persisted with their entities. Adding or changing a recipe does not change mutation-journal compatibility; restored cache records missing required locator coverage are refreshed through their requested root. Existing server refetch endpoints can remain available to older deployed clients.
|
|
2427
|
+
|
|
2428
|
+
For other transports, put the same recipe in `TypeConfig.refetch`. Implement `fetchQuery`; Fate adds implicit scalar selections to entity reads and entity mutation calls. Query transports receive an optional fourth `{ refetch: typeName }` context on automatic entity lookups. GraphQL also adds locator selections inside embedded results and concrete interface results.
|
|
2429
|
+
|
|
2321
2430
|
### Object IDs
|
|
2322
2431
|
|
|
2323
2432
|
The transport converts between fate entity IDs and GraphQL node IDs. By default, it sends IDs as `${type}-${id}` and strips that prefix from returned IDs. Override this if your schema uses Relay global IDs, raw database IDs, or another encoding:
|
|
@@ -2500,6 +2609,40 @@ For example, given `maps(biome: Biome)`, an argument `{ biome: 'Grassland' }` is
|
|
|
2500
2609
|
|
|
2501
2610
|
The generated client enforces root arguments in `client.request` and the React/Vue `useRequest` adapters. Mutation inputs are derived from the schema using the configured `inputArg`, replacing the manually declared input type for generated clients. Non-null arguments are required unless the schema supplies a default. Omitting an optional/defaulted value preserves its server default; explicit `null` remains distinct.
|
|
2502
2611
|
|
|
2612
|
+
Schema-aware generation also writes `.fate/schema.generated.ts`. Import its types directly in the mapping module or application code; these imports are erased, so generation works before that file exists on a clean checkout:
|
|
2613
|
+
|
|
2614
|
+
```tsx
|
|
2615
|
+
import type { GraphQLEntities } from '../.fate/schema.generated.ts';
|
|
2616
|
+
|
|
2617
|
+
type User = GraphQLEntities['User'];
|
|
2618
|
+
|
|
2619
|
+
const UserCardView = view<User>()({
|
|
2620
|
+
displayName: true,
|
|
2621
|
+
username: true,
|
|
2622
|
+
});
|
|
2623
|
+
```
|
|
2624
|
+
|
|
2625
|
+
`GraphQLTypes` describes the GraphQL schema's output shapes, including discriminated interfaces and unions. `GraphQLEntities` describes selectable Fate shapes: connection fields expose their node arrays for view composition. `GraphQLResponses` describes transport normalization, where connections become `{ items, pagination }`. These are available schema fields, not promises that every response contains every field. Generating a union type does not add new runtime selection capabilities to the transport.
|
|
2626
|
+
|
|
2627
|
+
Schema-backed mappings can expose entity queries and Relay-style connection roots
|
|
2628
|
+
without client `dataView` declarations. Types and mutation arguments come from the schema:
|
|
2629
|
+
|
|
2630
|
+
```tsx
|
|
2631
|
+
export const fateGraphQL = {
|
|
2632
|
+
schema,
|
|
2633
|
+
roots: { posts: {}, viewer: {} },
|
|
2634
|
+
mutations: { 'post.like': { entity: 'Post', field: 'postLike' } },
|
|
2635
|
+
} as const;
|
|
2636
|
+
```
|
|
2637
|
+
|
|
2638
|
+
Use `field` when an application root name differs from the schema query field.
|
|
2639
|
+
Existing server data views may still implement resolvers and live updates; they
|
|
2640
|
+
are independent of these generated GraphQL contracts.
|
|
2641
|
+
|
|
2642
|
+
With a schema, generated clients derive root and mutation output contracts from that schema rather than handwritten mapping generics. Direct mutation calls infer their unmasked results from the supplied `view` or `select`, including nested selections and nullable results. Without a selection, entity results promise only automatic identity fields. Mutation responses are not masked `ViewData` and do not carry view tags. React action state has one result contract across dispatches with different selections, so entity action results promise identity rather than dispatch-specific fields.
|
|
2643
|
+
|
|
2644
|
+
Custom scalars default to `unknown`. Configure their TypeScript wire representations with `fateGraphQL.scalars`, for example `DateTime: 'string'`, or `{ input: 'string', output: 'string' }` when specifying both sides. A mapping changes types only; it does not decode values into JavaScript classes. For independent build tooling, `createGraphQLSchemaSource(schema, scalars)` from `@nkzw/fate/vite` generates the same contracts without loading a client mapping.
|
|
2645
|
+
|
|
2503
2646
|
Generation also exports `GraphQLInputs`, `GraphQLFieldArguments`, and `GraphQLSelectionArguments` from `.fate/client.generated.ts`. Use field contracts to check arguments inside reusable views:
|
|
2504
2647
|
|
|
2505
2648
|
```tsx
|
|
@@ -2532,6 +2675,27 @@ fate does not write it to the cache. Successful sibling operations in the same
|
|
|
2532
2675
|
batch still resolve normally, including legitimate `null` results. Mutation
|
|
2533
2676
|
functions retain their `{ result, error }` result contract.
|
|
2534
2677
|
|
|
2678
|
+
For actions and mutations without durable delivery, GraphQL execution errors are
|
|
2679
|
+
returned as `{ error, result: undefined }` so the caller can handle domain errors
|
|
2680
|
+
using `error.errors` and `error.extensions`. Optimistic changes roll back, and
|
|
2681
|
+
partial data never enters the cache. Query errors still reject normally.
|
|
2682
|
+
|
|
2683
|
+
Fate recognizes standard `extensions.code` values such as `BAD_USER_INPUT`,
|
|
2684
|
+
`CONFLICT`, and `INTERNAL_SERVER_ERROR`, as well as numeric
|
|
2685
|
+
`extensions.http.status` values. HTTP failures and these extension statuses follow
|
|
2686
|
+
the existing action error policy: validation and conflict errors are handled at
|
|
2687
|
+
the call site; authentication, authorization, and server failures throw. If any
|
|
2688
|
+
error in a response requires a boundary, the entire mutation throws its original
|
|
2689
|
+
`GraphQLRequestError`. The error's `status` remains the original HTTP status,
|
|
2690
|
+
including `200` for execution errors.
|
|
2691
|
+
|
|
2692
|
+
Malformed successful responses have `error.kind === 'protocol'` and throw, as do network
|
|
2693
|
+
failures. For durable delivery, an execution error without a recognized status
|
|
2694
|
+
remains retryable; fate does not infer terminal rejection from an error message or
|
|
2695
|
+
a custom code. Return a standard code or `extensions.http.status` to identify a
|
|
2696
|
+
terminal client rejection. This preserves pending writes when a server failure's
|
|
2697
|
+
outcome is unknown.
|
|
2698
|
+
|
|
2535
2699
|
## Server Integration
|
|
2536
2700
|
|
|
2537
2701
|
Until now, we have focused on the client-side API of fate. You'll need a backend that can be wired into fate's typed request model so the Vite plugin can connect the typed fate APIs to your app. _fate_ currently ships three integration paths:
|
|
@@ -2737,8 +2901,8 @@ export default defineConfig({
|
|
|
2737
2901
|
|
|
2738
2902
|
```ts [Vue]
|
|
2739
2903
|
import vue from '@vitejs/plugin-vue';
|
|
2740
|
-
import { fate } from 'vue-fate/vite';
|
|
2741
2904
|
import { defineConfig } from 'vite';
|
|
2905
|
+
import { fate } from 'vue-fate/vite';
|
|
2742
2906
|
|
|
2743
2907
|
export default defineConfig({
|
|
2744
2908
|
plugins: [
|
|
@@ -2877,8 +3041,8 @@ Pass the `Root` export from `views.ts` to fate in your tRPC `init.ts` file. fate
|
|
|
2877
3041
|
Use `createPrismaFate` from `@nkzw/fate/server/prisma` next to your tRPC helpers. By default, fate reads Prisma delegates from `ctx.prisma` using each data view's type name:
|
|
2878
3042
|
|
|
2879
3043
|
```tsx
|
|
2880
|
-
import { initTRPC } from '@trpc/server';
|
|
2881
3044
|
import { createPrismaFate } from '@nkzw/fate/server/prisma';
|
|
3045
|
+
import { initTRPC } from '@trpc/server';
|
|
2882
3046
|
import type { AppContext } from './context.ts';
|
|
2883
3047
|
import { Root } from './views.ts';
|
|
2884
3048
|
|
|
@@ -2926,8 +3090,8 @@ return plan.resolve(post);
|
|
|
2926
3090
|
Use `createDrizzleFate` from `@nkzw/fate/server/drizzle`. fate matches data view type names to Drizzle tables from your schema. The `db` option can be a Drizzle database object or a function that receives your tRPC context and returns a request-scoped database object:
|
|
2927
3091
|
|
|
2928
3092
|
```tsx
|
|
2929
|
-
import { initTRPC } from '@trpc/server';
|
|
2930
3093
|
import { createDrizzleFate } from '@nkzw/fate/server/drizzle';
|
|
3094
|
+
import { initTRPC } from '@trpc/server';
|
|
2931
3095
|
import db from '../drizzle/db.ts';
|
|
2932
3096
|
import schema from '../drizzle/schema.ts';
|
|
2933
3097
|
import type { AppContext } from './context.ts';
|
|
@@ -3168,8 +3332,8 @@ export default defineConfig({
|
|
|
3168
3332
|
|
|
3169
3333
|
```ts [Vue]
|
|
3170
3334
|
import vue from '@vitejs/plugin-vue';
|
|
3171
|
-
import { fate } from 'vue-fate/vite';
|
|
3172
3335
|
import { defineConfig } from 'vite';
|
|
3336
|
+
import { fate } from 'vue-fate/vite';
|
|
3173
3337
|
|
|
3174
3338
|
export default defineConfig({
|
|
3175
3339
|
plugins: [
|
|
@@ -3327,9 +3491,9 @@ export default defineConfig({
|
|
|
3327
3491
|
|
|
3328
3492
|
```ts [Vue]
|
|
3329
3493
|
import { voidVue } from '@void/vue/plugin';
|
|
3330
|
-
import { fate } from 'vue-fate/vite';
|
|
3331
3494
|
import { defineConfig } from 'vite-plus';
|
|
3332
3495
|
import { voidPlugin } from 'void';
|
|
3496
|
+
import { fate } from 'vue-fate/vite';
|
|
3333
3497
|
|
|
3334
3498
|
export default defineConfig({
|
|
3335
3499
|
plugins: [
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Function: alias()
|
|
2
|
+
|
|
3
|
+
## Call Signature
|
|
4
|
+
|
|
5
|
+
> **alias**\<`V`\>(`view`): [`AliasedView`](../type-aliases/AliasedView.md)\<`V`\>
|
|
6
|
+
|
|
7
|
+
Defined in: fate/lib/refetch-BQzdlxXW.d.mts:15
|
|
8
|
+
|
|
9
|
+
Select a same-entity view under a named ref.
|
|
10
|
+
|
|
11
|
+
### Type Parameters
|
|
12
|
+
|
|
13
|
+
#### V
|
|
14
|
+
|
|
15
|
+
`V` *extends* `View`\<`any`, `any`\>
|
|
16
|
+
|
|
17
|
+
### Parameters
|
|
18
|
+
|
|
19
|
+
#### view
|
|
20
|
+
|
|
21
|
+
`V`
|
|
22
|
+
|
|
23
|
+
### Returns
|
|
24
|
+
|
|
25
|
+
[`AliasedView`](../type-aliases/AliasedView.md)\<`V`\>
|
|
26
|
+
|
|
27
|
+
## Call Signature
|
|
28
|
+
|
|
29
|
+
> **alias**\<`Field`, `S`\>(`field`, `selection`): [`AliasedSelection`](../type-aliases/AliasedSelection.md)\<`Field`, `S`\>
|
|
30
|
+
|
|
31
|
+
Defined in: fate/lib/refetch-BQzdlxXW.d.mts:17
|
|
32
|
+
|
|
33
|
+
Select a schema field under a different result name, with its own arguments.
|
|
34
|
+
|
|
35
|
+
### Type Parameters
|
|
36
|
+
|
|
37
|
+
#### Field
|
|
38
|
+
|
|
39
|
+
`Field` *extends* `string`
|
|
40
|
+
|
|
41
|
+
#### S
|
|
42
|
+
|
|
43
|
+
`S`
|
|
44
|
+
|
|
45
|
+
### Parameters
|
|
46
|
+
|
|
47
|
+
#### field
|
|
48
|
+
|
|
49
|
+
`Field`
|
|
50
|
+
|
|
51
|
+
#### selection
|
|
52
|
+
|
|
53
|
+
`S`
|
|
54
|
+
|
|
55
|
+
### Returns
|
|
56
|
+
|
|
57
|
+
[`AliasedSelection`](../type-aliases/AliasedSelection.md)\<`Field`, `S`\>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Function: clientRoot()
|
|
2
|
+
|
|
3
|
+
> **clientRoot**\<`Result`, `Type`, `Args`\>(`type`): `RootDefinition`\<`Type`, `Result`, `Args`\>
|
|
4
|
+
|
|
5
|
+
Defined in: fate/lib/index.d.mts:67
|
|
6
|
+
|
|
7
|
+
Defines a root query for an entity type, capturing the response shape.
|
|
8
|
+
|
|
9
|
+
## Type Parameters
|
|
10
|
+
|
|
11
|
+
### Result
|
|
12
|
+
|
|
13
|
+
`Result`
|
|
14
|
+
|
|
15
|
+
### Type
|
|
16
|
+
|
|
17
|
+
`Type` *extends* `string`
|
|
18
|
+
|
|
19
|
+
### Args
|
|
20
|
+
|
|
21
|
+
`Args` = `AnyRecord`
|
|
22
|
+
|
|
23
|
+
## Parameters
|
|
24
|
+
|
|
25
|
+
### type
|
|
26
|
+
|
|
27
|
+
`Type`
|
|
28
|
+
|
|
29
|
+
## Returns
|
|
30
|
+
|
|
31
|
+
`RootDefinition`\<`Type`, `Result`, `Args`\>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Function: clientValueRoot()
|
|
2
|
+
|
|
3
|
+
> **clientValueRoot**\<`Result`, `Args`\>(): `RootDefinition`\<`"__value__"`, `Result`, `Args`\>
|
|
4
|
+
|
|
5
|
+
Defined in: fate/lib/index.d.mts:68
|
|
6
|
+
|
|
7
|
+
## Type Parameters
|
|
8
|
+
|
|
9
|
+
### Result
|
|
10
|
+
|
|
11
|
+
`Result`
|
|
12
|
+
|
|
13
|
+
### Args
|
|
14
|
+
|
|
15
|
+
`Args` = `AnyRecord`
|
|
16
|
+
|
|
17
|
+
## Returns
|
|
18
|
+
|
|
19
|
+
`RootDefinition`\<`"__value__"`, `Result`, `Args`\>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Function: createClient()
|
|
2
|
+
|
|
3
|
+
> **createClient**\<`T`, `HydrationScope`\>(`options`): `FateClient`\<`T`\[`0`\], `T`\[`1`\], `HydrationScope`\>
|
|
4
|
+
|
|
5
|
+
Defined in: fate/lib/refetch-BQzdlxXW.d.mts:1368
|
|
6
|
+
|
|
7
|
+
## Type Parameters
|
|
8
|
+
|
|
9
|
+
### T
|
|
10
|
+
|
|
11
|
+
`T` *extends* \[`FateRoots`, `FateMutations`\] = \[`Record`\<`never`, `RootDefinition`\<`any`, `any`, `AnyRecord`\>\>, `Record`\<`never`, `MutationDefinition`\<`any`, `any`, `any`\>\>\]
|
|
12
|
+
|
|
13
|
+
### HydrationScope
|
|
14
|
+
|
|
15
|
+
`HydrationScope` *extends* `string` = `string`
|
|
16
|
+
|
|
17
|
+
## Parameters
|
|
18
|
+
|
|
19
|
+
### options
|
|
20
|
+
|
|
21
|
+
`FateClientOptions`\<`T`\[`0`\], `T`\[`1`\], `HydrationScope`\>
|
|
22
|
+
|
|
23
|
+
## Returns
|
|
24
|
+
|
|
25
|
+
`FateClient`\<`T`\[`0`\], `T`\[`1`\], `HydrationScope`\>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Function: createGraphQLTransport()
|
|
2
|
+
|
|
3
|
+
> **createGraphQLTransport**\<`Mutations`\>(`__namedParameters`): `Transport`\<`Mutations`\>
|
|
4
|
+
|
|
5
|
+
Defined in: fate/lib/graphqlTransport-CMeWu4PI.d.mts:89
|
|
6
|
+
|
|
7
|
+
## Type Parameters
|
|
8
|
+
|
|
9
|
+
### Mutations
|
|
10
|
+
|
|
11
|
+
`Mutations` *extends* `TransportMutations` = `EmptyTransportMutations`
|
|
12
|
+
|
|
13
|
+
## Parameters
|
|
14
|
+
|
|
15
|
+
### \_\_namedParameters
|
|
16
|
+
|
|
17
|
+
[`GraphQLTransportOptions`](../type-aliases/GraphQLTransportOptions.md)\<`Mutations`\>
|
|
18
|
+
|
|
19
|
+
## Returns
|
|
20
|
+
|
|
21
|
+
`Transport`\<`Mutations`\>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Function: createHTTPTransport()
|
|
2
|
+
|
|
3
|
+
> **createHTTPTransport**\<`API`, `Mutations`\>(`__namedParameters`): `Transport`\<`Mutations`\>
|
|
4
|
+
|
|
5
|
+
Defined in: fate/lib/index.d.mts:53
|
|
6
|
+
|
|
7
|
+
## Type Parameters
|
|
8
|
+
|
|
9
|
+
### API
|
|
10
|
+
|
|
11
|
+
`API` *extends* `FateAPIShape`
|
|
12
|
+
|
|
13
|
+
### Mutations
|
|
14
|
+
|
|
15
|
+
`Mutations` *extends* `TransportMutations` = `MutationMapFromAPI`\<`API`\>
|
|
16
|
+
|
|
17
|
+
## Parameters
|
|
18
|
+
|
|
19
|
+
### \_\_namedParameters
|
|
20
|
+
|
|
21
|
+
#### eventSource?
|
|
22
|
+
|
|
23
|
+
`EventSourceConstructor`
|
|
24
|
+
|
|
25
|
+
#### fetch?
|
|
26
|
+
|
|
27
|
+
`FetchLike`
|
|
28
|
+
|
|
29
|
+
#### headers?
|
|
30
|
+
|
|
31
|
+
`HeadersFactory`
|
|
32
|
+
|
|
33
|
+
#### live?
|
|
34
|
+
|
|
35
|
+
`boolean` \| `LiveConnector`
|
|
36
|
+
|
|
37
|
+
#### liveRetryMs?
|
|
38
|
+
|
|
39
|
+
`number`
|
|
40
|
+
|
|
41
|
+
#### liveUrl?
|
|
42
|
+
|
|
43
|
+
`string` \| `URL`
|
|
44
|
+
|
|
45
|
+
#### url
|
|
46
|
+
|
|
47
|
+
`string` \| `URL`
|
|
48
|
+
|
|
49
|
+
## Returns
|
|
50
|
+
|
|
51
|
+
`Transport`\<`Mutations`\>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Function: createTRPCTransport()
|
|
2
|
+
|
|
3
|
+
> **createTRPCTransport**\<`AppRouter`, `Mutations`\>(`__namedParameters`): `Transport`\<`MutationMapFromResolvers`\<`Mutations`\>\>
|
|
4
|
+
|
|
5
|
+
Defined in: fate/lib/refetch-BQzdlxXW.d.mts:993
|
|
6
|
+
|
|
7
|
+
Builds a `Transport` backed by a tRPC client using the configured resolvers
|
|
8
|
+
for by-id queries, lists, and mutations.
|
|
9
|
+
|
|
10
|
+
## Type Parameters
|
|
11
|
+
|
|
12
|
+
### AppRouter
|
|
13
|
+
|
|
14
|
+
`AppRouter` *extends* `AnyRouter`
|
|
15
|
+
|
|
16
|
+
### Mutations
|
|
17
|
+
|
|
18
|
+
`Mutations` *extends* `TRPCMutationResolvers`\<`AppRouter`\> = `EmptyMutationResolvers`\<`AppRouter`\>
|
|
19
|
+
|
|
20
|
+
## Parameters
|
|
21
|
+
|
|
22
|
+
### \_\_namedParameters
|
|
23
|
+
|
|
24
|
+
#### byId
|
|
25
|
+
|
|
26
|
+
`TRPCByIdResolvers`\<`AppRouter`\>
|
|
27
|
+
|
|
28
|
+
#### client
|
|
29
|
+
|
|
30
|
+
`TRPCClient`\<`AppRouter`\>
|
|
31
|
+
|
|
32
|
+
#### lists?
|
|
33
|
+
|
|
34
|
+
`TRPCListResolvers`\<`AppRouter`\>
|
|
35
|
+
|
|
36
|
+
#### mutateDurably?
|
|
37
|
+
|
|
38
|
+
\<`K`\>(`proc`, `input`, `select`, `identity`, `selectionArgs?`) => `Promise`\<`MutationMapFromResolvers`\<`Mutations`\>\[`K`\]\[`"output"`\]\>
|
|
39
|
+
|
|
40
|
+
#### mutations?
|
|
41
|
+
|
|
42
|
+
`Mutations`
|
|
43
|
+
|
|
44
|
+
#### queries?
|
|
45
|
+
|
|
46
|
+
`TRPCQueryResolvers`\<`AppRouter`\>
|
|
47
|
+
|
|
48
|
+
## Returns
|
|
49
|
+
|
|
50
|
+
`Transport`\<`MutationMapFromResolvers`\<`Mutations`\>\>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Function: defer()
|
|
2
|
+
|
|
3
|
+
> **defer**\<`S`\>(`selection`): `DeferredSelection`\<`S`\>
|
|
4
|
+
|
|
5
|
+
Defined in: fate/lib/index.d.mts:7
|
|
6
|
+
|
|
7
|
+
## Type Parameters
|
|
8
|
+
|
|
9
|
+
### S
|
|
10
|
+
|
|
11
|
+
`S`
|
|
12
|
+
|
|
13
|
+
## Parameters
|
|
14
|
+
|
|
15
|
+
### selection
|
|
16
|
+
|
|
17
|
+
`S`
|
|
18
|
+
|
|
19
|
+
## Returns
|
|
20
|
+
|
|
21
|
+
`DeferredSelection`\<`S`\>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Function: graphqlMutation()
|
|
2
|
+
|
|
3
|
+
> **graphqlMutation**\<`T`, `Input`, `Output`\>(`entity`, `options`): [`GraphQLMutationDefinition`](../type-aliases/GraphQLMutationDefinition.md)\<`T`, `Input`, `Output`\>
|
|
4
|
+
|
|
5
|
+
Defined in: fate/lib/graphqlTransport-CMeWu4PI.d.mts:78
|
|
6
|
+
|
|
7
|
+
## Type Parameters
|
|
8
|
+
|
|
9
|
+
### T
|
|
10
|
+
|
|
11
|
+
`T` *extends* `Entity`
|
|
12
|
+
|
|
13
|
+
### Input
|
|
14
|
+
|
|
15
|
+
`Input`
|
|
16
|
+
|
|
17
|
+
### Output
|
|
18
|
+
|
|
19
|
+
`Output`
|
|
20
|
+
|
|
21
|
+
## Parameters
|
|
22
|
+
|
|
23
|
+
### entity
|
|
24
|
+
|
|
25
|
+
`T`\[`"__typename"`\]
|
|
26
|
+
|
|
27
|
+
### options
|
|
28
|
+
|
|
29
|
+
#### field
|
|
30
|
+
|
|
31
|
+
`string`
|
|
32
|
+
|
|
33
|
+
#### inputArg?
|
|
34
|
+
|
|
35
|
+
`string` \| `false`
|
|
36
|
+
|
|
37
|
+
## Returns
|
|
38
|
+
|
|
39
|
+
[`GraphQLMutationDefinition`](../type-aliases/GraphQLMutationDefinition.md)\<`T`, `Input`, `Output`\>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Function: graphqlValueMutation()
|
|
2
|
+
|
|
3
|
+
> **graphqlValueMutation**\<`Input`, `Output`\>(`options`): [`GraphQLMutationDefinition`](../type-aliases/GraphQLMutationDefinition.md)\<\{ `__typename`: `"__value__"`; \}, `Input`, `Output`\>
|
|
4
|
+
|
|
5
|
+
Defined in: fate/lib/graphqlTransport-CMeWu4PI.d.mts:82
|
|
6
|
+
|
|
7
|
+
## Type Parameters
|
|
8
|
+
|
|
9
|
+
### Input
|
|
10
|
+
|
|
11
|
+
`Input`
|
|
12
|
+
|
|
13
|
+
### Output
|
|
14
|
+
|
|
15
|
+
`Output`
|
|
16
|
+
|
|
17
|
+
## Parameters
|
|
18
|
+
|
|
19
|
+
### options
|
|
20
|
+
|
|
21
|
+
#### field
|
|
22
|
+
|
|
23
|
+
`string`
|
|
24
|
+
|
|
25
|
+
#### inputArg?
|
|
26
|
+
|
|
27
|
+
`string` \| `false`
|
|
28
|
+
|
|
29
|
+
#### type?
|
|
30
|
+
|
|
31
|
+
`string`
|
|
32
|
+
|
|
33
|
+
## Returns
|
|
34
|
+
|
|
35
|
+
[`GraphQLMutationDefinition`](../type-aliases/GraphQLMutationDefinition.md)\<\{ `__typename`: `"__value__"`; \}, `Input`, `Output`\>
|