这是indexloc提供的服务,不要输入任何密码
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions types/relay-runtime/experimental.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
import { DataID } from "./lib/util/RelayRuntimeTypes";

export { resolverDataInjector } from "./lib/store/live-resolvers/resolverDataInjector";
export { observeFragment } from "./lib/store/observeFragmentExperimental";
export { observeQuery } from "./lib/store/observeQueryExperimental";
export { waitForFragmentData } from "./lib/store/waitForFragmentExperimental";

export type IdOf<_A extends string, Typename extends undefined | string = undefined> = Typename extends undefined
? { id: DataID }
: { id: DataID; __typename: Typename };

interface ErrorResult<E> {
ok: false;
errors: readonly E[];
}

interface OkayResult<T> {
ok: true;
value: T;
}

// The type returned by fields annotated with `@catch`
export type Result<T, E> = OkayResult<T> | ErrorResult<E>;

export function isValueResult<T = unknown>(input: Result<T, unknown>): input is OkayResult<T>;

export function isErrorResult<E = unknown>(input: Result<unknown, E>): input is ErrorResult<E>;
15 changes: 2 additions & 13 deletions types/relay-runtime/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export { RelayModernRecord as Record } from "./lib/store/RelayModernRecord";
export { default as Store } from "./lib/store/RelayModernStore";
export { RelayRecordSource as RecordSource } from "./lib/store/RelayRecordSource";

export { type IdOf, isErrorResult, isValueResult, type Result } from "./experimental";
export { createFragmentSpecResolver } from "./lib/store/createFragmentSpecResolver";
export { readInlineData } from "./lib/store/readInlineData";
export { createOperationDescriptor, createRequestDescriptor } from "./lib/store/RelayModernOperationDescriptor";
Expand Down Expand Up @@ -185,6 +186,7 @@ export {
ROOT_TYPE,
TYPENAME_KEY,
} from "./lib/store/RelayStoreUtils";
export { readFragment } from "./lib/store/ResolverFragments";

// Extensions
import RelayDefaultHandlerProvider from "./lib/handlers/RelayDefaultHandlerProvider";
Expand Down Expand Up @@ -267,16 +269,3 @@ export type FragmentRefs<Refs extends string> = {

// This is a utility type for converting from a data type to a fragment reference that will resolve to that data type.
export type FragmentRef<Fragment> = Fragment extends _RefType<infer U> ? _FragmentRefs<U> : never;

interface ErrorResult<Error> {
ok: false;
errors: readonly Error[];
}

interface OkayResult<T> {
ok: true;
value: T;
}

// The type returned by fields annotated with `@catch`
export type Result<T, Error> = OkayResult<T> | ErrorResult<Error>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { GraphQLTaggedNode } from "../../query/RelayModernGraphQLTag";
import type { FragmentType } from "../RelayStoreTypes";

/**
* This a higher order function that returns a relay resolver that can read the data for
* the fragment`.
*
* - fragment: contains fragment Reader AST with resolver's data dependencies.
* - resolverFn: original resolver function that expects a data from the fragment
* - (optional) fieldName: individual field that needs to be read out of the fragment.
*
* This will not call the `resolverFn` if the fragment data for it is null/undefined.
* The compiler generates calls to this function, ensuring the correct set of arguments.
*/
export function resolverDataInjector(
fragment: GraphQLTaggedNode,
_resolverFn: unknown,
fieldName?: string,
isRequiredField?: boolean,
): (fragmentKey: FragmentType, args: unknown) => unknown;
2 changes: 1 addition & 1 deletion types/relay-runtime/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"name": "@types/relay-runtime",
"version": "19.0.9999",
"version": "20.1.9999",
"projects": [
"https://github.com/facebook/relay",
"https://facebook.github.io/relay"
Expand Down
85 changes: 82 additions & 3 deletions types/relay-runtime/relay-runtime-tests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ import {
getRefetchMetadata,
getRequest,
graphql,
isErrorResult,
isPromise,
isValueResult,
LiveState,
Network,
PreloadableConcreteRequest,
PreloadableQueryRegistry,
QueryResponseCache,
ReaderFragment,
ReaderInlineDataFragment,
readFragment,
readInlineData,
RecordProxy,
RecordSource,
Expand All @@ -35,7 +38,13 @@ import {
suspenseSentinel,
Variables,
} from "relay-runtime";
import { observeFragment, observeQuery, waitForFragmentData } from "relay-runtime/experimental";
import {
IdOf,
observeFragment,
observeQuery,
resolverDataInjector,
waitForFragmentData,
} from "relay-runtime/experimental";

import type { HandlerProvider } from "relay-runtime/lib/handlers/RelayDefaultHandlerProvider";
import * as multiActorEnvironment from "relay-runtime/multi-actor-environment";
Expand Down Expand Up @@ -701,8 +710,6 @@ function multiActors() {
// Relay Resolvers
// ~~~~~~~~~~~~~~~~~~~~~~~

const { readFragment } = __internal.ResolverFragments;

// Regular fragment.
interface UserComponent_user {
readonly id: string;
Expand Down Expand Up @@ -921,6 +928,20 @@ export function handleResult<T, E>(result: Result<T, E>) {
}
}

// eslint-disable-next-line @definitelytyped/no-unnecessary-generics
export function handleValueResult<T, E>(result: Result<T, E>) {
if (isValueResult(result)) {
const value: T = result.value;
}
}

// eslint-disable-next-line @definitelytyped/no-unnecessary-generics
export function handleErrorResult<T, E>(result: Result<T, E>) {
if (isErrorResult(result)) {
const errors: readonly E[] = result.errors;
}
}

// ~~~~~~~~~~~~~~~~~~
// Metadata
// ~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -1048,3 +1069,61 @@ function observeQueryTest() {

subscription.unsubscribe();
}

// ~~~~~~~~~~~~~~~~~~
// resolverDataInjector
// ~~~~~~~~~~~~~~~~~~

const MyResolverType__id_graphql: ReaderFragment = {
"argumentDefinitions": [],
"kind": "Fragment",
"metadata": null,
"name": "MyResolverType__id",
"selections": [
{
"kind": "ClientExtension",
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null,
},
],
},
],
"type": "MyResolverType",
"abstractKey": null,
};

interface MyResolverType {
id: string;
}

function myResolverTypeRelayModelInstanceResolver(id: DataID): MyResolverType {
return {
id,
};
}

export const resolverModule = resolverDataInjector(
MyResolverType__id_graphql,
myResolverTypeRelayModelInstanceResolver,
"id",
true,
);

// ~~~~~~~~~~~~~~~~~~
// Client edge resolver
// ~~~~~~~~~~~~~~~~~~

export function myDog(): IdOf<"Dog"> {
return { id: "5" };
}

type AnimalTypenames = "Cat" | "Dog";

export function myAnimal(): IdOf<"Animal", AnimalTypenames> {
return Math.random() > 0.5 ? { id: "5", __typename: "Dog" } : { id: "6", __typename: "Cat" };
}