diff --git a/examples/custom-fragments/README.md b/examples/custom-fragments/README.md
new file mode 100644
index 000000000..78a035b54
--- /dev/null
+++ b/examples/custom-fragments/README.md
@@ -0,0 +1,3 @@
+# Custom Fragments
+
+[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/lens-protocol/lens-sdk/tree/next/examples/custom-fragments)
diff --git a/examples/custom-fragments/index.html b/examples/custom-fragments/index.html
new file mode 100644
index 000000000..b4529522a
--- /dev/null
+++ b/examples/custom-fragments/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+ Custom Fragments
+ Loading...
+
+
+
diff --git a/examples/custom-fragments/index.ts b/examples/custom-fragments/index.ts
new file mode 100644
index 000000000..5d516eb87
--- /dev/null
+++ b/examples/custom-fragments/index.ts
@@ -0,0 +1,41 @@
+import 'viem/window';
+
+import {
+ type FragmentOf,
+ PublicClient,
+ evmAddress,
+ graphql,
+ testnet as protocolTestnet,
+} from '@lens-protocol/client';
+import { fetchAccount } from '@lens-protocol/client/actions';
+
+const MyAccountFragment = graphql(
+ `fragment Account on Account {
+ __typename
+ address
+ username {
+ value
+ }
+ metadata {
+ __typename
+ name
+ picture
+ }
+ }`,
+);
+
+type MyAccount = FragmentOf;
+
+const client = PublicClient.create({
+ environment: protocolTestnet,
+ accountFragment: MyAccountFragment,
+});
+
+const account: MyAccount | null = await fetchAccount(client, {
+ address: evmAddress('0x57b62a1571F4F09CDB4C3d93dA542bfe142D9F81'),
+}).unwrapOr(null);
+
+export default [
+ `${account?.username?.value}
`,
+ `${JSON.stringify(account, null, 2)}
`,
+];
diff --git a/examples/custom-fragments/package.json b/examples/custom-fragments/package.json
new file mode 100644
index 000000000..dea64d2e6
--- /dev/null
+++ b/examples/custom-fragments/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "example-custom-fragments",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "vite"
+ },
+ "dependencies": {
+ "@lens-network/sdk": "canary",
+ "@lens-protocol/client": "file:../../packages/client",
+ "@lens-protocol/metadata": "next",
+ "@lens-protocol/storage-node-client": "next",
+ "viem": "^2.21.55"
+ },
+ "devDependencies": {
+ "typescript": "^5.6.3",
+ "vite": "^5.4.11"
+ }
+}
diff --git a/examples/custom-fragments/tsconfig.json b/examples/custom-fragments/tsconfig.json
new file mode 100644
index 000000000..6da89b87d
--- /dev/null
+++ b/examples/custom-fragments/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "lib": ["ESNext", "DOM"],
+ "module": "ESNext",
+ "moduleResolution": "Bundler",
+ "strict": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "esModuleInterop": true,
+ "noEmit": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noImplicitReturns": true,
+ "skipLibCheck": true
+ },
+ "include": ["./"]
+}
diff --git a/packages/client/src/actions/account.ts b/packages/client/src/actions/account.ts
index 4606b3204..8b043fa55 100644
--- a/packages/client/src/actions/account.ts
+++ b/packages/client/src/actions/account.ts
@@ -33,12 +33,10 @@ import type {
import {
AccountFeedsStatsQuery,
AccountGraphsStatsQuery,
- AccountQuery,
AccountStatsQuery,
AccountsAvailableQuery,
AccountsBlockedQuery,
AccountsBulkQuery,
- AccountsQuery,
BlockMutation,
CreateAccountWithUsernameMutation,
EnableSignlessMutation,
@@ -50,10 +48,13 @@ import {
UnblockMutation,
UndoRecommendAccountMutation,
UnmuteAccountMutation,
+ accountQuery,
+ accountsQuery,
} from '@lens-protocol/graphql';
import type { ResultAsync } from '@lens-protocol/types';
import type { AnyClient, SessionClient } from '../clients';
+import type { Context } from '../context';
import type { UnauthenticatedError, UnexpectedError } from '../errors';
/**
@@ -71,11 +72,11 @@ import type { UnauthenticatedError, UnexpectedError } from '../errors';
* @param request - The Account query request.
* @returns The Account or `null` if it does not exist.
*/
-export function fetchAccount(
- client: AnyClient,
+export function fetchAccount(
+ client: AnyClient>,
request: AccountRequest,
-): ResultAsync {
- return client.query(AccountQuery, { request });
+): ResultAsync {
+ return client.query(accountQuery(client.context.accountFragment), { request });
}
/**
@@ -84,18 +85,24 @@ export function fetchAccount(
* Using a {@link SessionClient} will yield {@link Account#operations} specific to the authenticated Account.
*
* ```ts
- * const result = await fetchAccounts(anyClient);
+ * const result = await fetchAccounts(anyClient, {
+ * filter: {
+ * searchBy: {
+ * localNameQuery: 'stani',
+ * }
+ * }
+ * });
* ```
*
* @param client - Any Lens client.
* @param request - The query request.
* @returns The list of accounts.
*/
-export function fetchAccounts(
- client: AnyClient,
+export function fetchAccounts(
+ client: AnyClient>,
request: AccountsRequest = {},
-): ResultAsync | null, UnexpectedError> {
- return client.query(AccountsQuery, { request });
+): ResultAsync | null, UnexpectedError> {
+ return client.query(accountsQuery(client.context.accountFragment), { request });
}
/**
diff --git a/packages/client/src/clients.ts b/packages/client/src/clients.ts
index 35f592578..669f5a440 100644
--- a/packages/client/src/clients.ts
+++ b/packages/client/src/clients.ts
@@ -32,7 +32,7 @@ import { type AuthConfig, authExchange } from '@urql/exchange-auth';
import { type AuthenticatedUser, authenticatedUser } from './AuthenticatedUser';
import { switchAccount, transactionStatus } from './actions';
import type { ClientConfig } from './config';
-import { type Context, configureContext } from './context';
+import { type Context, type ContextFrom, configureContext } from './context';
import {
AuthenticationError,
GraphQLErrorCode,
@@ -151,7 +151,9 @@ export class PublicClient extends AbstractCl
* @param options - The options to configure the client.
* @returns The new instance of the client.
*/
- static create(options: ClientConfig): PublicClient {
+ static create(
+ options: TConfig,
+ ): PublicClient> {
return new PublicClient(configureContext(options));
}
diff --git a/packages/client/src/config.ts b/packages/client/src/config.ts
index 2e743c545..540bb8121 100644
--- a/packages/client/src/config.ts
+++ b/packages/client/src/config.ts
@@ -1,10 +1,12 @@
import type { EnvironmentConfig } from '@lens-protocol/env';
+import type { Account } from '@lens-protocol/graphql';
+import type { FragmentDocumentFor } from '@lens-protocol/graphql';
import type { IStorageProvider } from '@lens-protocol/storage';
/**
* The client configuration.
*/
-export type ClientConfig = {
+export type ClientConfig = {
/**
* The environment configuration to use (e.g. `mainnet`, `testnet`).
*/
@@ -27,11 +29,16 @@ export type ClientConfig = {
* Use this to set the `Origin` header for requests from non-browser environments.
*/
origin?: string;
-
/**
* The storage provider to use.
*
* @defaultValue {@link InMemoryStorageProvider}
*/
storage?: IStorageProvider;
+ /**
+ * The Account Fragment to use.
+ *
+ * @defaultValue {@link AccountFragment}
+ */
+ accountFragment?: FragmentDocumentFor;
};
diff --git a/packages/client/src/context.ts b/packages/client/src/context.ts
index 995d799f3..7c0623a56 100644
--- a/packages/client/src/context.ts
+++ b/packages/client/src/context.ts
@@ -1,27 +1,40 @@
import type { EnvironmentConfig } from '@lens-protocol/env';
+import { type Account, AccountFragment } from '@lens-protocol/graphql';
+import type { FragmentDocumentFor } from '@lens-protocol/graphql';
import { type IStorageProvider, InMemoryStorageProvider } from '@lens-protocol/storage';
import type { ClientConfig } from './config';
/**
* @internal
*/
-export type Context = {
+export type Context = {
environment: EnvironmentConfig;
cache: boolean;
debug: boolean;
origin?: string;
storage: IStorageProvider;
+ accountFragment: FragmentDocumentFor;
};
/**
* @internal
*/
-export function configureContext(from: ClientConfig): Context {
+export type ContextFrom = TConfig extends ClientConfig
+ ? Context
+ : never;
+
+/**
+ * @internal
+ */
+export function configureContext(
+ from: TConfig,
+): ContextFrom {
return {
environment: from.environment,
cache: from.cache ?? false,
debug: from.debug ?? false,
origin: from.origin,
storage: from.storage ?? new InMemoryStorageProvider(),
- };
+ accountFragment: from.accountFragment ?? AccountFragment,
+ } as ContextFrom;
}
diff --git a/packages/graphql/src/accounts/account.ts b/packages/graphql/src/accounts/account.ts
index 4be974022..1019bd162 100644
--- a/packages/graphql/src/accounts/account.ts
+++ b/packages/graphql/src/accounts/account.ts
@@ -1,5 +1,7 @@
import type { FragmentOf } from 'gql.tada';
+import type { Paginated } from '../common';
import {
+ type Account,
AccountAvailableFragment,
AccountBlockedFragment,
AccountFragment,
@@ -8,23 +10,37 @@ import {
SponsoredTransactionRequestFragment,
TransactionWillFailFragment,
} from '../fragments';
-import { type RequestOf, graphql } from '../graphql';
-
-export const AccountQuery = graphql(
- `query Account($request: AccountRequest!) {
+import {
+ type FragmentDocumentFor,
+ type RequestOf,
+ type RequestTypeOf,
+ type StandardDocumentNode,
+ graphql,
+} from '../graphql';
+
+export type AccountRequest = RequestTypeOf<'AccountRequest'>;
+export function accountQuery(
+ fragment: FragmentDocumentFor,
+): StandardDocumentNode {
+ return graphql(
+ `query Account($request: AccountRequest!) {
value: account(request: $request) {
...Account
}
}`,
- [AccountFragment],
-);
-export type AccountRequest = RequestOf;
-
-export const AccountsQuery = graphql(
- `query Accounts($request: AccountsRequest!) {
+ [fragment],
+ ) as StandardDocumentNode;
+}
+
+export type AccountsRequest = RequestTypeOf<'AccountsRequest'>;
+export function accountsQuery(
+ fragment: FragmentDocumentFor,
+): StandardDocumentNode, AccountsRequest> {
+ return graphql(
+ `query Accounts($request: AccountsRequest!) {
value: accounts(request: $request) {
__typename
- items{
+ items {
...Account
}
pageInfo {
@@ -32,9 +48,9 @@ export const AccountsQuery = graphql(
}
}
}`,
- [AccountFragment, PaginatedResultInfoFragment],
-);
-export type AccountsRequest = RequestOf;
+ [fragment, PaginatedResultInfoFragment],
+ ) as StandardDocumentNode;
+}
export const AccountsBulkQuery = graphql(
`query AccountsBulk($request: AccountsBulkRequest!) {
diff --git a/packages/graphql/src/fragments/account.ts b/packages/graphql/src/fragments/account.ts
index 42e1a10ab..112ed209d 100644
--- a/packages/graphql/src/fragments/account.ts
+++ b/packages/graphql/src/fragments/account.ts
@@ -48,9 +48,15 @@ export const AccountFragment = graphql(
`fragment Account on Account {
__typename
address
- owner
- score
- createdAt
+ }`,
+ [],
+);
+export type Account = FragmentOf;
+
+export const FullAccountFragment = graphql(
+ `fragment Account on Account {
+ __typename
+ address
username{
...Username
}
@@ -63,7 +69,7 @@ export const AccountFragment = graphql(
}`,
[AccountMetadataFragment, LoggedInAccountOperationsFragment, UsernameFragment],
);
-export type Account = FragmentOf;
+export type FullAccount = FragmentOf;
const AccountManagerPermissionsFragment = graphql(
`fragment AccountManagerPermissions on AccountManagerPermissions {
diff --git a/packages/graphql/src/graphql.ts b/packages/graphql/src/graphql.ts
index 299cbdd0a..00a66a240 100644
--- a/packages/graphql/src/graphql.ts
+++ b/packages/graphql/src/graphql.ts
@@ -164,6 +164,8 @@ export const graphql = initGraphQLTada<{
};
}>();
+export type { FragmentOf, TadaDocumentNode };
+
/**
* @internal
*/
@@ -205,7 +207,12 @@ export type FragmentDocumentFor = TGqlNode extends
>
: never;
-export type RequestFrom = RequestOf>;
+/**
+ * @internal
+ */
+export type RequestTypeOf = RequestOf<
+ GetDocumentNode<`query Named($request: ${Name}) {}`, FragmentShape[]>
+>;
// biome-ignore lint/suspicious/noExplicitAny: simplifies necessary type assertions
export type StandardDocumentNode = TadaDocumentNode<