@wener/console
Version:
Base console UI toolkit
119 lines (116 loc) • 3.73 kB
text/typescript
import { Client, fetchExchange } from '@urql/core';
import { devtoolsExchange } from '@urql/devtools';
import { cacheExchange, type CacheExchangeOpts, type KeyingConfig } from '@urql/exchange-graphcache';
import { persistedExchange } from '@urql/exchange-persisted';
import { retryExchange } from '@urql/exchange-retry';
import { ms } from '@wener/utils';
import { batchFetchExchange } from './batchFetchExchange';
export function createUrqlClient({
getToken,
url,
persisted = false,
batch = true,
schema,
cache,
resolveTypeNameFromKey,
}: {
url: string;
getToken?: () => string | undefined | null;
batch?: boolean;
persisted?: boolean;
schema?: any;
cache?: Partial<CacheExchangeOpts>;
resolveTypeNameFromKey?: (key: string) => string | null | undefined;
}): Client {
const client = new Client({
url,
fetchSubscriptions: true,
// requestPolicy: 'cache-and-network',
exchanges: [
process.env.NODE_ENV === 'development' && devtoolsExchange,
cacheExchange({
...cache,
schema,
keys: new Proxy({} as KeyingConfig, {
get(target, prop, receiver) {
if (typeof prop !== 'string') {
return null;
}
let preset = target[prop];
if (preset) {
return preset;
}
// console.log(`cacheExchange key: ${prop}`);
let getKey = (data: any) => data?.id;
if (prop.endsWith('Payload')) {
getKey = () => null;
}
return (target[prop] = getKey);
},
}),
resolvers: {
Query: {
node: (parent, args, cache, info) => {
let __typename;
let id = args.id;
if (typeof id === 'string' && resolveTypeNameFromKey) {
// const idType = id.split('_')[0];
// __typename = (
// {
// usr: 'User',
// } as Record<string, string>
// )[idType];
__typename = resolveTypeNameFromKey(id);
}
return __typename ? { __typename, id } : cache.resolve(parent as any, info.parentFieldKey);
},
},
...cache?.resolvers,
},
}),
// scalarExchange({
// schema: schema as any,
// scalars: {
// JSON(value) {
// if (value && typeof value === 'string') return JSON.parse(value);
// return value;
// },
// },
// }),
batch
? batchFetchExchange({
maxBatchSize: 1000,
// batchScheduleFn: (callback) => setTimeout(callback, 15),
})
: undefined,
persisted
? persistedExchange({
preferGetForPersistedQueries: true,
// enforcePersistedQueries: true,
enableForMutation: true,
// https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#normalized-caches-urql-and-apollo-client
generateHash: (_, document: any) => Promise.resolve(document['__meta__']?.['hash']),
})
: undefined,
retryExchange({
initialDelayMs: 1000,
maxDelayMs: ms('5m'),
maxNumberAttempts: Number.POSITIVE_INFINITY,
// 默认只重试网络错误
retryIf: (err) => Boolean(err && err.networkError),
}),
fetchExchange,
].filter(Boolean),
fetchOptions: () => {
let headers: Record<string, string> = {};
const token = getToken?.();
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
return {
headers,
};
},
});
return client;
}