This repository was archived by the owner on Dec 25, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
This repository was archived by the owner on Dec 25, 2025. It is now read-only.
Abstract client interface #123
Copy link
Copy link
Open
Labels
featureNew feature or requestNew feature or requestpackage:coreRelated to @fabrix-framework/fabrixRelated to @fabrix-framework/fabrix
Description
#76 is related to this issue.
Is your feature request related to a problem? Please describe.
Currently, fabrix internally sticks with urql to execute GraphQL queries.
However, it would be nicer for users to let them select a client library whatever they want to use.
Describe the solution you'd like
Abstract out the current implementation of data fetching into an interface like this:
type FetcherProps = {
query: DocumentNode | string;
variables?: Record<string, unknown>;
};
type FabrixRequestResult = {
data: FabrixComponentData | undefined;
error: Error | undefined;
};
interface FabrixClient {
getClient(): {
mutate: (props: FetcherProps) => Promise<FabrixRequestResult>;
query: (props: FetcherProps) => Promise<FabrixRequestResult>;
};
getFetcherComponent(): (
props: FetcherProps & {
children: (props: { data: FabrixComponentData | undefined }) => ReactNode;
},
) => ReactNode;
}With this interface, we can add urql implementation:
export class URQLClient implements FabrixClient {
private client: UrqlClient;
constructor(private readonly url: string) {
this.client = new UrqlClient({
url,
exchanges: [
cacheExchange,
removeDirectivesExchange(["fabrixView", "fabrixList", "fabrixForm"]),
addTypenameFieldExchange,
removeTypenameFromVariableExchange,
fetchExchange,
],
});
}
getClient() {
return {
mutate: async (props: FetcherProps) => {
const r = await this.client.mutation<FabrixComponentData>(
props.query,
props.variables,
);
return {
data: r.data,
error: r.error,
};
},
query: async (props: FetcherProps) => {
const r = await this.client.query<FabrixComponentData>(
props.query,
props.variables,
);
return {
data: r.data,
error: r.error,
};
},
};
}
getFetcherComponent() {
return (
props: FetcherProps & {
children: (props: {
data: FabrixComponentData | undefined;
}) => ReactNode;
},
) => {
const [{ data, fetching, error }] = useQuery<FabrixComponentData>({
query: props.query,
variables: props.variables,
});
if (fetching || !data) {
return <Loader />;
}
if (error) {
throw error;
}
return props.children({ data });
};
}
}I am feeling that this design potentially resolves #90 as well.
Users can create implementation with Suspense enabled, or do the same in getFetcherComponent.
Describe alternatives you've considered
N/A
Additional context
N/A
Metadata
Metadata
Assignees
Labels
featureNew feature or requestNew feature or requestpackage:coreRelated to @fabrix-framework/fabrixRelated to @fabrix-framework/fabrix