@settlemint/sdk-thegraph 2.5.4-pr0ee48561 → 2.5.4
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/dist/browser/thegraph.d.ts +2 -2
- package/dist/browser/thegraph.js +20 -21
- package/dist/browser/thegraph.js.map +1 -1
- package/dist/thegraph.cjs +19 -20
- package/dist/thegraph.cjs.map +1 -1
- package/dist/thegraph.d.cts +2 -2
- package/dist/thegraph.d.ts +2 -2
- package/dist/thegraph.js +20 -21
- package/dist/thegraph.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* SettleMint The Graph SDK - Indexing Protocol */
|
|
2
2
|
import { AbstractSetupSchema, FragmentOf, ResultOf, TadaDocumentNode, VariablesOf, initGraphQLTada, readFragment } from "gql.tada";
|
|
3
|
-
import { GraphQLClient,
|
|
3
|
+
import { GraphQLClient, Variables } from "graphql-request";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
|
|
6
6
|
//#region src/utils/pagination.d.ts
|
|
@@ -13,7 +13,7 @@ import { z } from "zod";
|
|
|
13
13
|
* @internal Used internally by createTheGraphClient
|
|
14
14
|
*/
|
|
15
15
|
declare function createTheGraphClientWithPagination(theGraphClient: Pick<GraphQLClient, "request">): {
|
|
16
|
-
readonly query: <TResult, TVariables extends Variables>(
|
|
16
|
+
readonly query: <TResult, TVariables extends Variables>(document: TadaDocumentNode<TResult, TVariables>, variables: Omit<TVariables, "skip" | "first">) => Promise<TResult>;
|
|
17
17
|
};
|
|
18
18
|
//#endregion
|
|
19
19
|
//#region src/thegraph.d.ts
|
package/dist/browser/thegraph.js
CHANGED
|
@@ -7,7 +7,7 @@ import { GraphQLClient } from "graphql-request";
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import { sortBy } from "es-toolkit";
|
|
9
9
|
import { get, isArray, isEmpty, set } from "es-toolkit/compat";
|
|
10
|
-
import { Kind,
|
|
10
|
+
import { Kind, visit } from "graphql";
|
|
11
11
|
|
|
12
12
|
//#region src/utils/pagination.ts
|
|
13
13
|
const THE_GRAPH_LIMIT = 500;
|
|
@@ -28,8 +28,7 @@ const FETCH_ALL_DIRECTIVE = "fetchAll";
|
|
|
28
28
|
*/
|
|
29
29
|
function stripFetchAllDirective(document) {
|
|
30
30
|
const fetchAllFields = new Set();
|
|
31
|
-
const
|
|
32
|
-
const strippedDocument = visit(documentNode, { Field(node) {
|
|
31
|
+
const strippedDocument = visit(document, { Field(node) {
|
|
33
32
|
if (node.directives && node.directives.length > 0) {
|
|
34
33
|
const hasFetchAll = node.directives.some((dir) => dir.name.value === FETCH_ALL_DIRECTIVE);
|
|
35
34
|
if (hasFetchAll) {
|
|
@@ -92,26 +91,38 @@ function extractFetchAllFields(document, variables, fetchAllFields) {
|
|
|
92
91
|
if (node.name.value.startsWith("__")) {
|
|
93
92
|
return;
|
|
94
93
|
}
|
|
94
|
+
let hasFirstArg = false;
|
|
95
|
+
let hasSkipArg = false;
|
|
95
96
|
let firstValue;
|
|
96
97
|
let skipValue;
|
|
98
|
+
let firstValueIsDefault = false;
|
|
97
99
|
const otherArgs = [];
|
|
98
100
|
if (node.arguments) {
|
|
99
101
|
for (const arg of node.arguments) {
|
|
100
102
|
if (arg.name.value === FIRST_ARG) {
|
|
103
|
+
hasFirstArg = true;
|
|
101
104
|
if (arg.value.kind === Kind.INT) {
|
|
102
105
|
firstValue = Number.parseInt(arg.value.value);
|
|
103
106
|
} else if (arg.value.kind === Kind.VARIABLE && variables) {
|
|
104
107
|
const varName = arg.value.name.value;
|
|
105
108
|
const varValue = variables[varName];
|
|
106
109
|
firstValue = typeof varValue === "number" ? varValue : undefined;
|
|
110
|
+
if (firstValue === undefined && varName === arg.value.name.value) {
|
|
111
|
+
firstValue = THE_GRAPH_LIMIT;
|
|
112
|
+
firstValueIsDefault = true;
|
|
113
|
+
}
|
|
107
114
|
}
|
|
108
115
|
} else if (arg.name.value === SKIP_ARG) {
|
|
116
|
+
hasSkipArg = true;
|
|
109
117
|
if (arg.value.kind === Kind.INT) {
|
|
110
118
|
skipValue = Number.parseInt(arg.value.value);
|
|
111
119
|
} else if (arg.value.kind === Kind.VARIABLE && variables) {
|
|
112
120
|
const varName = arg.value.name.value;
|
|
113
121
|
const varValue = variables[varName];
|
|
114
122
|
skipValue = typeof varValue === "number" ? varValue : undefined;
|
|
123
|
+
if (skipValue === undefined && varName === arg.value.name.value) {
|
|
124
|
+
skipValue = 0;
|
|
125
|
+
}
|
|
115
126
|
}
|
|
116
127
|
} else {
|
|
117
128
|
otherArgs.push(arg);
|
|
@@ -129,12 +140,13 @@ function extractFetchAllFields(document, variables, fetchAllFields) {
|
|
|
129
140
|
path: [...pathStack],
|
|
130
141
|
fieldName: node.name.value,
|
|
131
142
|
alias: node.alias?.value,
|
|
132
|
-
|
|
133
|
-
|
|
143
|
+
hasFirstArg,
|
|
144
|
+
firstValue: hasFetchAllDirective && !hasFirstArg ? THE_GRAPH_LIMIT : firstValue,
|
|
145
|
+
skipValue: hasFetchAllDirective && !hasSkipArg ? 0 : skipValue,
|
|
134
146
|
otherArgs,
|
|
135
147
|
selections: node.selectionSet?.selections,
|
|
136
148
|
hasFetchAllDirective,
|
|
137
|
-
firstValueIsDefault
|
|
149
|
+
firstValueIsDefault
|
|
138
150
|
});
|
|
139
151
|
}
|
|
140
152
|
},
|
|
@@ -271,16 +283,7 @@ function createTheGraphClientWithPagination(theGraphClient) {
|
|
|
271
283
|
}
|
|
272
284
|
return results;
|
|
273
285
|
}
|
|
274
|
-
return { async query(
|
|
275
|
-
let document;
|
|
276
|
-
let variables;
|
|
277
|
-
if (isRequestOptions(documentOrOptions)) {
|
|
278
|
-
document = documentOrOptions.document;
|
|
279
|
-
variables = documentOrOptions.variables;
|
|
280
|
-
} else {
|
|
281
|
-
document = documentOrOptions;
|
|
282
|
-
variables = variablesRaw ?? {};
|
|
283
|
-
}
|
|
286
|
+
return { async query(document, variables) {
|
|
284
287
|
const { document: processedDocument, fetchAllFields } = stripFetchAllDirective(document);
|
|
285
288
|
const listFields = extractFetchAllFields(processedDocument, variables, fetchAllFields);
|
|
286
289
|
if (listFields.length === 0) {
|
|
@@ -305,9 +308,6 @@ function createTheGraphClientWithPagination(theGraphClient) {
|
|
|
305
308
|
return result;
|
|
306
309
|
} };
|
|
307
310
|
}
|
|
308
|
-
function isRequestOptions(args) {
|
|
309
|
-
return typeof args === "object" && args !== null && "document" in args && "variables" in args;
|
|
310
|
-
}
|
|
311
311
|
|
|
312
312
|
//#endregion
|
|
313
313
|
//#region src/thegraph.ts
|
|
@@ -398,8 +398,7 @@ function createTheGraphClient(options, clientOptions) {
|
|
|
398
398
|
...clientOptions,
|
|
399
399
|
headers: appendHeaders(clientOptions?.headers, { "x-auth-token": validatedOptions.accessToken })
|
|
400
400
|
});
|
|
401
|
-
const
|
|
402
|
-
const paginatedClient = createTheGraphClientWithPagination({ request: originalRequest });
|
|
401
|
+
const paginatedClient = createTheGraphClientWithPagination(client);
|
|
403
402
|
client.request = paginatedClient.query;
|
|
404
403
|
return {
|
|
405
404
|
client,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thegraph.js","names":["document: DocumentNode | RequestDocument","target: unknown","source: unknown","result: Record<string, unknown>","document: DocumentNode","variables?: Variables","fetchAllFields?: Set<string>","fields: ListField[]","pathStack: string[]","firstValue: number | undefined","skipValue: number | undefined","otherArgs: ArgumentNode[]","targetField: ListField","skip: number","first: number","newArgs: ArgumentNode[]","listFields: ListField[]","variables: Variables | undefined","filtered: Variables","theGraphClient: Pick<GraphQLClient, \"request\">","field: ListField","results: unknown[]","documentOrOptions: TadaDocumentNode<TResult, TVariables> | RequestDocument | RequestOptions<TVariables, TResult>","variablesRaw?: Omit<TVariables, \"skip\" | \"first\">","document: TadaDocumentNode<TResult, TVariables> | RequestDocument","variables: Omit<TVariables, \"skip\" | \"first\">","args: unknown","options: ClientOptions","instance","clientOptions?: RequestConfig"],"sources":["../../src/utils/pagination.ts","../../src/thegraph.ts"],"sourcesContent":["import { sortBy } from \"es-toolkit\";\nimport { get, isArray, isEmpty, set } from \"es-toolkit/compat\";\nimport type { TadaDocumentNode } from \"gql.tada\";\nimport { type ArgumentNode, type DocumentNode, Kind, parse, type SelectionNode, visit } from \"graphql\";\nimport type { GraphQLClient, RequestDocument, RequestOptions, Variables } from \"graphql-request\";\n\n// Constants for TheGraph limits\nconst THE_GRAPH_LIMIT = 500;\nconst FIRST_ARG = \"first\";\nconst SKIP_ARG = \"skip\";\nconst FETCH_ALL_DIRECTIVE = \"fetchAll\";\n\ninterface ListField {\n path: string[];\n fieldName: string;\n alias?: string;\n firstValue?: number;\n skipValue?: number;\n otherArgs: ArgumentNode[];\n selections?: ReadonlyArray<SelectionNode>;\n hasFetchAllDirective?: boolean;\n firstValueIsDefault?: boolean; // Track if first value was defaulted\n}\n\n/**\n * Detects and strips @fetchAll directives from a GraphQL document\n *\n * @param {DocumentNode} document - The GraphQL document to process\n * @returns {Object} Processed document and list of fields with @fetchAll\n *\n * @remarks\n * This function:\n * - Identifies fields decorated with @fetchAll directive\n * - Removes the directive from the AST (The Graph doesn't recognize it)\n * - Returns both the cleaned document and a list of fields to auto-paginate\n */\nfunction stripFetchAllDirective(document: DocumentNode | RequestDocument): {\n document: DocumentNode;\n fetchAllFields: Set<string>;\n} {\n const fetchAllFields = new Set<string>();\n const documentNode = typeof document === \"string\" ? parse(document) : document;\n const strippedDocument = visit(documentNode, {\n Field(node) {\n // Check if this field has the @fetchAll directive\n if (node.directives && node.directives.length > 0) {\n const hasFetchAll = node.directives.some((dir) => dir.name.value === FETCH_ALL_DIRECTIVE);\n\n if (hasFetchAll) {\n const fieldIdentifier = node.alias?.value || node.name.value;\n fetchAllFields.add(fieldIdentifier);\n\n // Return a new node without the @fetchAll directive\n return {\n ...node,\n directives: node.directives.filter((dir) => dir.name.value !== FETCH_ALL_DIRECTIVE),\n };\n }\n }\n\n return node;\n },\n });\n\n return {\n document: strippedDocument,\n fetchAllFields,\n };\n}\n\n/**\n * Custom merge function for deep object merging with special handling for lists\n *\n * @param {unknown} target - The target object or value to merge into\n * @param {unknown} source - The source object or value to merge from\n * @returns {unknown} Merged result with preservation of arrays and specific merge logic\n *\n * @remarks\n * Key behaviors:\n * - Preserves existing arrays without merging\n * - Handles null and undefined values\n * - Performs deep merge for nested objects\n * - Prioritizes source values for primitives\n *\n */\nfunction customMerge(target: unknown, source: unknown): unknown {\n if (source == null) return target;\n if (target == null) return source;\n\n // If source is an array, return it, don't merge arrays\n if (isArray(source)) {\n return source;\n }\n\n if (typeof target !== \"object\" || typeof source !== \"object\") {\n return source;\n }\n\n // Manually merge objects to ensure arrays are preserved\n const targetObj = target as Record<string, unknown>;\n const sourceObj = source as Record<string, unknown>;\n const result: Record<string, unknown> = { ...targetObj };\n\n for (const key in sourceObj) {\n if (Object.hasOwn(sourceObj, key)) {\n result[key] = key in result ? customMerge(result[key], sourceObj[key]) : sourceObj[key];\n }\n }\n\n return result;\n}\n\n// Extract all fields that have @fetchAll directive\nfunction extractFetchAllFields(\n document: DocumentNode,\n variables?: Variables,\n fetchAllFields?: Set<string>,\n): ListField[] {\n const fields: ListField[] = [];\n const pathStack: string[] = [];\n\n visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Skip meta fields\n if (node.name.value.startsWith(\"__\")) {\n return;\n }\n\n // Check if this field has pagination arguments (first or skip)\n let firstValue: number | undefined;\n let skipValue: number | undefined;\n const otherArgs: ArgumentNode[] = [];\n\n if (node.arguments) {\n for (const arg of node.arguments) {\n if (arg.name.value === FIRST_ARG) {\n if (arg.value.kind === Kind.INT) {\n firstValue = Number.parseInt(arg.value.value);\n } else if (arg.value.kind === Kind.VARIABLE && variables) {\n const varName = arg.value.name.value;\n const varValue = (variables as Record<string, unknown>)[varName];\n firstValue = typeof varValue === \"number\" ? varValue : undefined;\n }\n } else if (arg.name.value === SKIP_ARG) {\n if (arg.value.kind === Kind.INT) {\n skipValue = Number.parseInt(arg.value.value);\n } else if (arg.value.kind === Kind.VARIABLE && variables) {\n const varName = arg.value.name.value;\n const varValue = (variables as Record<string, unknown>)[varName];\n skipValue = typeof varValue === \"number\" ? varValue : undefined;\n }\n } else {\n otherArgs.push(arg);\n }\n }\n }\n\n // Check if this field has @fetchAll directive\n const fieldIdentifierForDirective = node.alias?.value || node.name.value;\n const hasFetchAllDirective = fetchAllFields?.has(fieldIdentifierForDirective);\n\n if (hasFetchAllDirective) {\n // Do not allow nesting @fetchAll fields\n const parentFetchAllField = fields.find((field) => pathStack.join(\",\").startsWith(field.path.join(\",\")));\n if (parentFetchAllField) {\n throw new Error(\n `Nesting of @fetchAll directive is not supported: ${pathStack.join(\".\")} is a child of ${parentFetchAllField.path.join(\".\")}`,\n );\n }\n fields.push({\n path: [...pathStack],\n fieldName: node.name.value,\n alias: node.alias?.value,\n firstValue: hasFetchAllDirective && (firstValue ?? THE_GRAPH_LIMIT),\n skipValue: hasFetchAllDirective && (skipValue ?? 0),\n otherArgs,\n selections: node.selectionSet?.selections,\n hasFetchAllDirective,\n firstValueIsDefault: hasFetchAllDirective ? firstValue === undefined : false,\n });\n }\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n\n return fields;\n}\n\n// Create a query for a single field with specific pagination\nfunction createSingleFieldQuery(\n document: DocumentNode,\n targetField: ListField,\n skip: number,\n first: number,\n): DocumentNode {\n const targetPath = [...targetField.path];\n const pathStack: string[] = [];\n\n return visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Check if we're on the path to target field\n const onPath = pathStack.every((segment, i) => i >= targetPath.length || segment === targetPath[i]);\n\n if (!onPath) {\n pathStack.pop();\n return null; // Remove fields not on path\n }\n\n // If this is our target field, update pagination\n const isTarget =\n pathStack.length === targetPath.length && pathStack.every((segment, i) => segment === targetPath[i]);\n\n if (isTarget) {\n const newArgs: ArgumentNode[] = [...targetField.otherArgs];\n\n // Add pagination arguments\n newArgs.push(\n {\n kind: Kind.ARGUMENT,\n name: { kind: Kind.NAME, value: FIRST_ARG },\n value: { kind: Kind.INT, value: first.toString() },\n },\n {\n kind: Kind.ARGUMENT,\n name: { kind: Kind.NAME, value: SKIP_ARG },\n value: { kind: Kind.INT, value: skip.toString() },\n },\n );\n\n return { ...node, arguments: newArgs };\n }\n\n return undefined;\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n}\n\n// Create query without list fields\nfunction createNonListQuery(document: DocumentNode, listFields: ListField[]): DocumentNode | null {\n let hasFields = false;\n const pathStack: string[] = [];\n\n const filtered = visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Check if this field is a list field\n const isList = listFields.some(\n (field) =>\n field.path.length === pathStack.length && field.path.every((segment, i) => segment === pathStack[i]),\n );\n\n if (isList) {\n pathStack.pop();\n return null;\n }\n\n hasFields = true;\n return undefined;\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n\n return hasFields ? filtered : null;\n}\n\n// Filter variables to only include used ones\nfunction filterVariables(variables: Variables | undefined, document: DocumentNode): Variables | undefined {\n if (!variables) return undefined;\n\n const usedVariables = new Set<string>();\n\n visit(document, {\n Variable: (node) => {\n usedVariables.add(node.name.value);\n },\n });\n\n const filtered: Variables = {};\n const varsObj = variables as Record<string, unknown>;\n for (const key of usedVariables) {\n if (key in varsObj) {\n (filtered as Record<string, unknown>)[key] = varsObj[key];\n }\n }\n\n return isEmpty(filtered) ? undefined : filtered;\n}\n\n/**\n * Creates a TheGraph client that supports pagination for list fields\n *\n * @param theGraphClient - The GraphQL client to use for requests\n * @returns A TheGraph client that supports pagination for list fields\n * @internal Used internally by createTheGraphClient\n */\nexport function createTheGraphClientWithPagination(theGraphClient: Pick<GraphQLClient, \"request\">) {\n // Execute pagination for a list field\n async function executeListFieldPagination(\n document: DocumentNode,\n variables: Variables | undefined,\n field: ListField,\n ): Promise<unknown[]> {\n const results: unknown[] = [];\n let currentSkip = field.skipValue || 0;\n let hasMore = true;\n\n // For fields with pagination arguments, always attempt to fetch data\n // and continue if we get a full page (indicating more data might exist)\n const batchSize = Math.min(field.firstValue || THE_GRAPH_LIMIT, THE_GRAPH_LIMIT);\n\n while (hasMore) {\n const query = createSingleFieldQuery(document, field, currentSkip, batchSize);\n const existingVariables = filterVariables(variables, query) ?? {};\n const response = await theGraphClient.request(query, {\n ...existingVariables,\n first: batchSize,\n skip: currentSkip,\n });\n\n // Use array path format for es-toolkit's get function\n const data = get(response, field.path) ?? get(response, field.fieldName);\n\n const parentPath = field.path.slice(0, -1);\n const parentData = get(response, parentPath);\n if (isArray(parentData) && parentData.length > 0) {\n throw new Error(\n `Response is an array, but expected a single object for field ${parentPath.join(\".\")}. The @fetchAll directive is not supported inside a query that returns a list of items.`,\n );\n }\n\n if (isArray(data) && data.length > 0) {\n results.push(...data);\n\n // Continue fetching if:\n // 1. We have @fetchAll directive (fetch everything)\n // 2. We have an explicit first value > THE_GRAPH_LIMIT and haven't reached it\n // 3. We have a defaulted first value and got a full batch (treating it as \"no explicit value\")\n // 4. We have no first value and got a full batch\n if (field.hasFetchAllDirective) {\n // With @fetchAll, continue if we got a full batch\n hasMore = data.length === batchSize;\n } else if (field.firstValue && !field.firstValueIsDefault) {\n // With explicit first value (not defaulted), only continue if:\n // - We haven't reached the requested amount yet\n // - We got a full batch (indicating more data might exist)\n hasMore = data.length === batchSize && results.length < field.firstValue;\n } else {\n // When first is not specified or was defaulted (using default batch size),\n // continue if we got a full batch (standard TheGraph pagination behavior)\n hasMore = data.length === batchSize;\n }\n } else {\n hasMore = false;\n }\n\n currentSkip += batchSize;\n }\n\n return results;\n }\n\n return {\n async query<TResult, TVariables extends Variables>(\n documentOrOptions: TadaDocumentNode<TResult, TVariables> | RequestDocument | RequestOptions<TVariables, TResult>,\n variablesRaw?: Omit<TVariables, \"skip\" | \"first\">,\n ): Promise<TResult> {\n let document: TadaDocumentNode<TResult, TVariables> | RequestDocument;\n let variables: Omit<TVariables, \"skip\" | \"first\">;\n\n if (isRequestOptions(documentOrOptions)) {\n document = documentOrOptions.document;\n variables = documentOrOptions.variables as TVariables;\n } else {\n document = documentOrOptions;\n variables = variablesRaw ?? ({} as TVariables);\n }\n\n // First, detect and strip @fetchAll directives\n const { document: processedDocument, fetchAllFields } = stripFetchAllDirective(document);\n\n // Extract all list fields (including those with @fetchAll)\n const listFields = extractFetchAllFields(processedDocument, variables, fetchAllFields);\n\n // If no list fields, execute normally\n if (listFields.length === 0) {\n return theGraphClient.request(processedDocument, variables as Variables);\n }\n\n // Execute paginated queries for all list fields\n const result: Record<string, unknown> = {};\n\n // Sort fields by depth to handle nested fields correctly\n const sortedFields = sortBy(listFields, [(field) => field.path.length]);\n\n // Process list fields in parallel for better performance\n const fieldDataPromises = sortedFields.map(async (field) => ({\n field,\n data: await executeListFieldPagination(processedDocument, variables, field),\n }));\n\n const fieldResults = await Promise.all(fieldDataPromises);\n\n // Set results in order\n for (const { field, data } of fieldResults) {\n // Use array path format for es-toolkit's set function\n set(result, field.path, data);\n }\n\n // Execute non-list fields (single entity queries)\n const nonListQuery = createNonListQuery(processedDocument, listFields);\n\n if (nonListQuery) {\n const nonListResult = await theGraphClient.request(\n nonListQuery,\n filterVariables(variables, nonListQuery) ?? {},\n );\n\n // Merge results, preserving list data\n const merged = customMerge(nonListResult, result);\n return merged as TResult;\n }\n\n return result as TResult;\n },\n } as const;\n}\n\nfunction isRequestOptions(args: unknown): args is RequestOptions<Variables, unknown> {\n return typeof args === \"object\" && args !== null && \"document\" in args && \"variables\" in args;\n}\n","import { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { ensureServer } from \"@settlemint/sdk-utils/runtime\";\nimport { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from \"@settlemint/sdk-utils/validation\";\nimport { type AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport { GraphQLClient } from \"graphql-request\";\nimport { z } from \"zod\";\nimport { createTheGraphClientWithPagination } from \"./utils/pagination.js\";\n\n/**\n * Type definition for GraphQL client configuration options\n */\nexport type RequestConfig = ConstructorParameters<typeof GraphQLClient>[1];\n\n/**\n * Schema for validating client options for the TheGraph client.\n */\nexport const ClientOptionsSchema = z.object({\n instances: z.array(UrlOrPathSchema),\n accessToken: ApplicationAccessTokenSchema.optional(),\n subgraphName: z.string(),\n cache: z.enum([\"default\", \"force-cache\", \"no-cache\", \"no-store\", \"only-if-cached\", \"reload\"]).optional(),\n});\n\n/**\n * Type definition for client options derived from the ClientOptionsSchema\n */\nexport type ClientOptions = z.infer<typeof ClientOptionsSchema>;\n\n/**\n * Constructs the full URL for TheGraph GraphQL API based on the provided options\n *\n * @param options - The client options for configuring TheGraph client\n * @returns The complete GraphQL API URL as a string\n * @throws Will throw an error if no matching instance is found for the specified subgraph\n */\nfunction getFullUrl(options: ClientOptions): string {\n const instance = options.instances.find((instance) => instance.endsWith(`/${options.subgraphName}`));\n if (!instance) {\n throw new Error(`Instance for subgraph ${options.subgraphName} not found`);\n }\n return new URL(instance).toString();\n}\n\n/**\n * Creates a TheGraph GraphQL client with proper type safety using gql.tada\n *\n * @param options - Configuration options for the client including instance URLs,\n * access token and subgraph name\n * @param clientOptions - Optional GraphQL client configuration options\n * @returns An object containing:\n * - client: The configured GraphQL client instance\n * - graphql: The initialized gql.tada function for type-safe queries\n * @throws Will throw an error if the options fail validation against ClientOptionsSchema\n * @example\n * import { createTheGraphClient } from '@settlemint/sdk-thegraph';\n * import type { introspection } from '@schemas/the-graph-env-kits';\n * import { createLogger, requestLogger } from '@settlemint/sdk-utils/logging';\n *\n * const logger = createLogger();\n *\n * const { client, graphql } = createTheGraphClient<{\n * introspection: introspection;\n * disableMasking: true;\n * scalars: {\n * Bytes: string;\n * Int8: string;\n * BigInt: string;\n * BigDecimal: string;\n * Timestamp: string;\n * };\n * }>({\n * instances: JSON.parse(process.env.SETTLEMINT_THEGRAPH_SUBGRAPHS_ENDPOINTS || '[]'),\n * accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,\n * subgraphName: 'kits'\n * }, {\n * fetch: requestLogger(logger, \"the-graph-kits\", fetch) as typeof fetch,\n * });\n *\n * // Making GraphQL queries\n * const query = graphql(`\n * query SearchAssets {\n * assets @fetchAll {\n * id\n * name\n * symbol\n * }\n * }\n * `);\n *\n * const result = await client.request(query);\n */\nexport function createTheGraphClient<const Setup extends AbstractSetupSchema>(\n options: ClientOptions,\n clientOptions?: RequestConfig,\n): {\n client: GraphQLClient;\n graphql: initGraphQLTada<Setup>;\n} {\n ensureServer();\n const validatedOptions = validate(ClientOptionsSchema, options);\n const graphql = initGraphQLTada<Setup>();\n const fullUrl = getFullUrl(validatedOptions);\n\n const client = new GraphQLClient(fullUrl, {\n ...clientOptions,\n headers: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n });\n const originalRequest = client.request.bind(client);\n const paginatedClient = createTheGraphClientWithPagination({\n request: originalRequest,\n });\n client.request = paginatedClient.query;\n return {\n client,\n graphql,\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport { createTheGraphClientWithPagination } from \"./utils/pagination.js\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"thegraph.js","names":["document: DocumentNode","target: unknown","source: unknown","result: Record<string, unknown>","variables?: Variables","fetchAllFields?: Set<string>","fields: ListField[]","pathStack: string[]","firstValue: number | undefined","skipValue: number | undefined","otherArgs: ArgumentNode[]","targetField: ListField","skip: number","first: number","newArgs: ArgumentNode[]","listFields: ListField[]","variables: Variables | undefined","filtered: Variables","theGraphClient: Pick<GraphQLClient, \"request\">","field: ListField","results: unknown[]","document: TadaDocumentNode<TResult, TVariables>","variables: Omit<TVariables, \"skip\" | \"first\">","options: ClientOptions","instance","clientOptions?: RequestConfig"],"sources":["../../src/utils/pagination.ts","../../src/thegraph.ts"],"sourcesContent":["import { sortBy } from \"es-toolkit\";\nimport { get, isArray, isEmpty, set } from \"es-toolkit/compat\";\nimport type { TadaDocumentNode } from \"gql.tada\";\nimport { type ArgumentNode, type DocumentNode, Kind, type SelectionNode, visit } from \"graphql\";\nimport type { GraphQLClient, Variables } from \"graphql-request\";\n\n// Constants for TheGraph limits\nconst THE_GRAPH_LIMIT = 500;\nconst FIRST_ARG = \"first\";\nconst SKIP_ARG = \"skip\";\nconst FETCH_ALL_DIRECTIVE = \"fetchAll\";\n\ninterface ListField {\n path: string[];\n fieldName: string;\n alias?: string;\n hasFirstArg: boolean;\n firstValue?: number;\n skipValue?: number;\n otherArgs: ArgumentNode[];\n selections?: ReadonlyArray<SelectionNode>;\n hasFetchAllDirective?: boolean;\n firstValueIsDefault?: boolean; // Track if first value was defaulted\n}\n\n/**\n * Detects and strips @fetchAll directives from a GraphQL document\n *\n * @param {DocumentNode} document - The GraphQL document to process\n * @returns {Object} Processed document and list of fields with @fetchAll\n *\n * @remarks\n * This function:\n * - Identifies fields decorated with @fetchAll directive\n * - Removes the directive from the AST (The Graph doesn't recognize it)\n * - Returns both the cleaned document and a list of fields to auto-paginate\n */\nfunction stripFetchAllDirective(document: DocumentNode): {\n document: DocumentNode;\n fetchAllFields: Set<string>;\n} {\n const fetchAllFields = new Set<string>();\n\n const strippedDocument = visit(document, {\n Field(node) {\n // Check if this field has the @fetchAll directive\n if (node.directives && node.directives.length > 0) {\n const hasFetchAll = node.directives.some((dir) => dir.name.value === FETCH_ALL_DIRECTIVE);\n\n if (hasFetchAll) {\n const fieldIdentifier = node.alias?.value || node.name.value;\n fetchAllFields.add(fieldIdentifier);\n\n // Return a new node without the @fetchAll directive\n return {\n ...node,\n directives: node.directives.filter((dir) => dir.name.value !== FETCH_ALL_DIRECTIVE),\n };\n }\n }\n\n return node;\n },\n });\n\n return {\n document: strippedDocument,\n fetchAllFields,\n };\n}\n\n/**\n * Custom merge function for deep object merging with special handling for lists\n *\n * @param {unknown} target - The target object or value to merge into\n * @param {unknown} source - The source object or value to merge from\n * @returns {unknown} Merged result with preservation of arrays and specific merge logic\n *\n * @remarks\n * Key behaviors:\n * - Preserves existing arrays without merging\n * - Handles null and undefined values\n * - Performs deep merge for nested objects\n * - Prioritizes source values for primitives\n *\n */\nfunction customMerge(target: unknown, source: unknown): unknown {\n if (source == null) return target;\n if (target == null) return source;\n\n // If source is an array, return it, don't merge arrays\n if (isArray(source)) {\n return source;\n }\n\n if (typeof target !== \"object\" || typeof source !== \"object\") {\n return source;\n }\n\n // Manually merge objects to ensure arrays are preserved\n const targetObj = target as Record<string, unknown>;\n const sourceObj = source as Record<string, unknown>;\n const result: Record<string, unknown> = { ...targetObj };\n\n for (const key in sourceObj) {\n if (Object.hasOwn(sourceObj, key)) {\n result[key] = key in result ? customMerge(result[key], sourceObj[key]) : sourceObj[key];\n }\n }\n\n return result;\n}\n\n// Extract all fields that have @fetchAll directive\nfunction extractFetchAllFields(\n document: DocumentNode,\n variables?: Variables,\n fetchAllFields?: Set<string>,\n): ListField[] {\n const fields: ListField[] = [];\n const pathStack: string[] = [];\n\n visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Skip meta fields\n if (node.name.value.startsWith(\"__\")) {\n return;\n }\n\n // Check if this field has pagination arguments (first or skip)\n let hasFirstArg = false;\n let hasSkipArg = false;\n let firstValue: number | undefined;\n let skipValue: number | undefined;\n let firstValueIsDefault = false;\n const otherArgs: ArgumentNode[] = [];\n\n if (node.arguments) {\n for (const arg of node.arguments) {\n if (arg.name.value === FIRST_ARG) {\n hasFirstArg = true;\n if (arg.value.kind === Kind.INT) {\n firstValue = Number.parseInt(arg.value.value);\n } else if (arg.value.kind === Kind.VARIABLE && variables) {\n const varName = arg.value.name.value;\n const varValue = (variables as Record<string, unknown>)[varName];\n firstValue = typeof varValue === \"number\" ? varValue : undefined;\n // If variable is defined in query but not passed in input, check if it's a standard pagination variable\n if (firstValue === undefined && varName === arg.value.name.value) {\n firstValue = THE_GRAPH_LIMIT; // Default to THE_GRAPH_LIMIT\n firstValueIsDefault = true; // Mark that this was defaulted\n }\n }\n } else if (arg.name.value === SKIP_ARG) {\n hasSkipArg = true;\n if (arg.value.kind === Kind.INT) {\n skipValue = Number.parseInt(arg.value.value);\n } else if (arg.value.kind === Kind.VARIABLE && variables) {\n const varName = arg.value.name.value;\n const varValue = (variables as Record<string, unknown>)[varName];\n skipValue = typeof varValue === \"number\" ? varValue : undefined;\n // If variable is defined in query but not passed in input, check if it's a standard pagination variable\n if (skipValue === undefined && varName === arg.value.name.value) {\n skipValue = 0; // Default to 0\n }\n }\n } else {\n otherArgs.push(arg);\n }\n }\n }\n\n // Check if this field has @fetchAll directive\n const fieldIdentifierForDirective = node.alias?.value || node.name.value;\n const hasFetchAllDirective = fetchAllFields?.has(fieldIdentifierForDirective);\n\n if (hasFetchAllDirective) {\n // Do not allow nesting @fetchAll fields\n const parentFetchAllField = fields.find((field) => pathStack.join(\",\").startsWith(field.path.join(\",\")));\n if (parentFetchAllField) {\n throw new Error(\n `Nesting of @fetchAll directive is not supported: ${pathStack.join(\".\")} is a child of ${parentFetchAllField.path.join(\".\")}`,\n );\n }\n fields.push({\n path: [...pathStack],\n fieldName: node.name.value,\n alias: node.alias?.value,\n hasFirstArg,\n firstValue: hasFetchAllDirective && !hasFirstArg ? THE_GRAPH_LIMIT : firstValue,\n skipValue: hasFetchAllDirective && !hasSkipArg ? 0 : skipValue,\n otherArgs,\n selections: node.selectionSet?.selections,\n hasFetchAllDirective,\n firstValueIsDefault,\n });\n }\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n\n return fields;\n}\n\n// Create a query for a single field with specific pagination\nfunction createSingleFieldQuery(\n document: DocumentNode,\n targetField: ListField,\n skip: number,\n first: number,\n): DocumentNode {\n const targetPath = [...targetField.path];\n const pathStack: string[] = [];\n\n return visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Check if we're on the path to target field\n const onPath = pathStack.every((segment, i) => i >= targetPath.length || segment === targetPath[i]);\n\n if (!onPath) {\n pathStack.pop();\n return null; // Remove fields not on path\n }\n\n // If this is our target field, update pagination\n const isTarget =\n pathStack.length === targetPath.length && pathStack.every((segment, i) => segment === targetPath[i]);\n\n if (isTarget) {\n const newArgs: ArgumentNode[] = [...targetField.otherArgs];\n\n // Add pagination arguments\n newArgs.push(\n {\n kind: Kind.ARGUMENT,\n name: { kind: Kind.NAME, value: FIRST_ARG },\n value: { kind: Kind.INT, value: first.toString() },\n },\n {\n kind: Kind.ARGUMENT,\n name: { kind: Kind.NAME, value: SKIP_ARG },\n value: { kind: Kind.INT, value: skip.toString() },\n },\n );\n\n return { ...node, arguments: newArgs };\n }\n\n return undefined;\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n}\n\n// Create query without list fields\nfunction createNonListQuery(document: DocumentNode, listFields: ListField[]): DocumentNode | null {\n let hasFields = false;\n const pathStack: string[] = [];\n\n const filtered = visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Check if this field is a list field\n const isList = listFields.some(\n (field) =>\n field.path.length === pathStack.length && field.path.every((segment, i) => segment === pathStack[i]),\n );\n\n if (isList) {\n pathStack.pop();\n return null;\n }\n\n hasFields = true;\n return undefined;\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n\n return hasFields ? filtered : null;\n}\n\n// Filter variables to only include used ones\nfunction filterVariables(variables: Variables | undefined, document: DocumentNode): Variables | undefined {\n if (!variables) return undefined;\n\n const usedVariables = new Set<string>();\n\n visit(document, {\n Variable: (node) => {\n usedVariables.add(node.name.value);\n },\n });\n\n const filtered: Variables = {};\n const varsObj = variables as Record<string, unknown>;\n for (const key of usedVariables) {\n if (key in varsObj) {\n (filtered as Record<string, unknown>)[key] = varsObj[key];\n }\n }\n\n return isEmpty(filtered) ? undefined : filtered;\n}\n\n/**\n * Creates a TheGraph client that supports pagination for list fields\n *\n * @param theGraphClient - The GraphQL client to use for requests\n * @returns A TheGraph client that supports pagination for list fields\n * @internal Used internally by createTheGraphClient\n */\nexport function createTheGraphClientWithPagination(theGraphClient: Pick<GraphQLClient, \"request\">) {\n // Execute pagination for a list field\n async function executeListFieldPagination(\n document: DocumentNode,\n variables: Variables | undefined,\n field: ListField,\n ): Promise<unknown[]> {\n const results: unknown[] = [];\n let currentSkip = field.skipValue || 0;\n let hasMore = true;\n\n // For fields with pagination arguments, always attempt to fetch data\n // and continue if we get a full page (indicating more data might exist)\n const batchSize = Math.min(field.firstValue || THE_GRAPH_LIMIT, THE_GRAPH_LIMIT);\n\n while (hasMore) {\n const query = createSingleFieldQuery(document, field, currentSkip, batchSize);\n const existingVariables = filterVariables(variables, query) ?? {};\n const response = await theGraphClient.request(query, {\n ...existingVariables,\n first: batchSize,\n skip: currentSkip,\n });\n\n // Use array path format for es-toolkit's get function\n const data = get(response, field.path) ?? get(response, field.fieldName);\n\n const parentPath = field.path.slice(0, -1);\n const parentData = get(response, parentPath);\n if (isArray(parentData) && parentData.length > 0) {\n throw new Error(\n `Response is an array, but expected a single object for field ${parentPath.join(\".\")}. The @fetchAll directive is not supported inside a query that returns a list of items.`,\n );\n }\n\n if (isArray(data) && data.length > 0) {\n results.push(...data);\n\n // Continue fetching if:\n // 1. We have @fetchAll directive (fetch everything)\n // 2. We have an explicit first value > THE_GRAPH_LIMIT and haven't reached it\n // 3. We have a defaulted first value and got a full batch (treating it as \"no explicit value\")\n // 4. We have no first value and got a full batch\n if (field.hasFetchAllDirective) {\n // With @fetchAll, continue if we got a full batch\n hasMore = data.length === batchSize;\n } else if (field.firstValue && !field.firstValueIsDefault) {\n // With explicit first value (not defaulted), only continue if:\n // - We haven't reached the requested amount yet\n // - We got a full batch (indicating more data might exist)\n hasMore = data.length === batchSize && results.length < field.firstValue;\n } else {\n // When first is not specified or was defaulted (using default batch size),\n // continue if we got a full batch (standard TheGraph pagination behavior)\n hasMore = data.length === batchSize;\n }\n } else {\n hasMore = false;\n }\n\n currentSkip += batchSize;\n }\n\n return results;\n }\n\n return {\n async query<TResult, TVariables extends Variables>(\n document: TadaDocumentNode<TResult, TVariables>,\n variables: Omit<TVariables, \"skip\" | \"first\">,\n ): Promise<TResult> {\n // First, detect and strip @fetchAll directives\n const { document: processedDocument, fetchAllFields } = stripFetchAllDirective(document);\n\n // Extract all list fields (including those with @fetchAll)\n const listFields = extractFetchAllFields(processedDocument, variables, fetchAllFields);\n\n // If no list fields, execute normally\n if (listFields.length === 0) {\n return theGraphClient.request(processedDocument, variables as Variables);\n }\n\n // Execute paginated queries for all list fields\n const result: Record<string, unknown> = {};\n\n // Sort fields by depth to handle nested fields correctly\n const sortedFields = sortBy(listFields, [(field) => field.path.length]);\n\n // Process list fields in parallel for better performance\n const fieldDataPromises = sortedFields.map(async (field) => ({\n field,\n data: await executeListFieldPagination(processedDocument, variables, field),\n }));\n\n const fieldResults = await Promise.all(fieldDataPromises);\n\n // Set results in order\n for (const { field, data } of fieldResults) {\n // Use array path format for es-toolkit's set function\n set(result, field.path, data);\n }\n\n // Execute non-list fields (single entity queries)\n const nonListQuery = createNonListQuery(processedDocument, listFields);\n\n if (nonListQuery) {\n const nonListResult = await theGraphClient.request(\n nonListQuery,\n filterVariables(variables, nonListQuery) ?? {},\n );\n\n // Merge results, preserving list data\n const merged = customMerge(nonListResult, result);\n return merged as TResult;\n }\n\n return result as TResult;\n },\n } as const;\n}\n","import { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { ensureServer } from \"@settlemint/sdk-utils/runtime\";\nimport { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from \"@settlemint/sdk-utils/validation\";\nimport { type AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport { GraphQLClient } from \"graphql-request\";\nimport { z } from \"zod\";\nimport { createTheGraphClientWithPagination } from \"./utils/pagination.js\";\n\n/**\n * Type definition for GraphQL client configuration options\n */\nexport type RequestConfig = ConstructorParameters<typeof GraphQLClient>[1];\n\n/**\n * Schema for validating client options for the TheGraph client.\n */\nexport const ClientOptionsSchema = z.object({\n instances: z.array(UrlOrPathSchema),\n accessToken: ApplicationAccessTokenSchema.optional(),\n subgraphName: z.string(),\n cache: z.enum([\"default\", \"force-cache\", \"no-cache\", \"no-store\", \"only-if-cached\", \"reload\"]).optional(),\n});\n\n/**\n * Type definition for client options derived from the ClientOptionsSchema\n */\nexport type ClientOptions = z.infer<typeof ClientOptionsSchema>;\n\n/**\n * Constructs the full URL for TheGraph GraphQL API based on the provided options\n *\n * @param options - The client options for configuring TheGraph client\n * @returns The complete GraphQL API URL as a string\n * @throws Will throw an error if no matching instance is found for the specified subgraph\n */\nfunction getFullUrl(options: ClientOptions): string {\n const instance = options.instances.find((instance) => instance.endsWith(`/${options.subgraphName}`));\n if (!instance) {\n throw new Error(`Instance for subgraph ${options.subgraphName} not found`);\n }\n return new URL(instance).toString();\n}\n\n/**\n * Creates a TheGraph GraphQL client with proper type safety using gql.tada\n *\n * @param options - Configuration options for the client including instance URLs,\n * access token and subgraph name\n * @param clientOptions - Optional GraphQL client configuration options\n * @returns An object containing:\n * - client: The configured GraphQL client instance\n * - graphql: The initialized gql.tada function for type-safe queries\n * @throws Will throw an error if the options fail validation against ClientOptionsSchema\n * @example\n * import { createTheGraphClient } from '@settlemint/sdk-thegraph';\n * import type { introspection } from '@schemas/the-graph-env-kits';\n * import { createLogger, requestLogger } from '@settlemint/sdk-utils/logging';\n *\n * const logger = createLogger();\n *\n * const { client, graphql } = createTheGraphClient<{\n * introspection: introspection;\n * disableMasking: true;\n * scalars: {\n * Bytes: string;\n * Int8: string;\n * BigInt: string;\n * BigDecimal: string;\n * Timestamp: string;\n * };\n * }>({\n * instances: JSON.parse(process.env.SETTLEMINT_THEGRAPH_SUBGRAPHS_ENDPOINTS || '[]'),\n * accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,\n * subgraphName: 'kits'\n * }, {\n * fetch: requestLogger(logger, \"the-graph-kits\", fetch) as typeof fetch,\n * });\n *\n * // Making GraphQL queries\n * const query = graphql(`\n * query SearchAssets {\n * assets @fetchAll {\n * id\n * name\n * symbol\n * }\n * }\n * `);\n *\n * const result = await client.request(query);\n */\nexport function createTheGraphClient<const Setup extends AbstractSetupSchema>(\n options: ClientOptions,\n clientOptions?: RequestConfig,\n): {\n client: GraphQLClient;\n graphql: initGraphQLTada<Setup>;\n} {\n ensureServer();\n const validatedOptions = validate(ClientOptionsSchema, options);\n const graphql = initGraphQLTada<Setup>();\n const fullUrl = getFullUrl(validatedOptions);\n\n const client = new GraphQLClient(fullUrl, {\n ...clientOptions,\n headers: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n });\n const paginatedClient = createTheGraphClientWithPagination(client);\n client.request = paginatedClient.query as typeof client.request;\n return {\n client,\n graphql,\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport { createTheGraphClientWithPagination } from \"./utils/pagination.js\";\n"],"mappings":"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"}
|
package/dist/thegraph.cjs
CHANGED
|
@@ -51,8 +51,7 @@ const FETCH_ALL_DIRECTIVE = "fetchAll";
|
|
|
51
51
|
*/
|
|
52
52
|
function stripFetchAllDirective(document) {
|
|
53
53
|
const fetchAllFields = new Set();
|
|
54
|
-
const
|
|
55
|
-
const strippedDocument = (0, graphql.visit)(documentNode, { Field(node) {
|
|
54
|
+
const strippedDocument = (0, graphql.visit)(document, { Field(node) {
|
|
56
55
|
if (node.directives && node.directives.length > 0) {
|
|
57
56
|
const hasFetchAll = node.directives.some((dir) => dir.name.value === FETCH_ALL_DIRECTIVE);
|
|
58
57
|
if (hasFetchAll) {
|
|
@@ -115,26 +114,38 @@ function extractFetchAllFields(document, variables, fetchAllFields) {
|
|
|
115
114
|
if (node.name.value.startsWith("__")) {
|
|
116
115
|
return;
|
|
117
116
|
}
|
|
117
|
+
let hasFirstArg = false;
|
|
118
|
+
let hasSkipArg = false;
|
|
118
119
|
let firstValue;
|
|
119
120
|
let skipValue;
|
|
121
|
+
let firstValueIsDefault = false;
|
|
120
122
|
const otherArgs = [];
|
|
121
123
|
if (node.arguments) {
|
|
122
124
|
for (const arg of node.arguments) {
|
|
123
125
|
if (arg.name.value === FIRST_ARG) {
|
|
126
|
+
hasFirstArg = true;
|
|
124
127
|
if (arg.value.kind === graphql.Kind.INT) {
|
|
125
128
|
firstValue = Number.parseInt(arg.value.value);
|
|
126
129
|
} else if (arg.value.kind === graphql.Kind.VARIABLE && variables) {
|
|
127
130
|
const varName = arg.value.name.value;
|
|
128
131
|
const varValue = variables[varName];
|
|
129
132
|
firstValue = typeof varValue === "number" ? varValue : undefined;
|
|
133
|
+
if (firstValue === undefined && varName === arg.value.name.value) {
|
|
134
|
+
firstValue = THE_GRAPH_LIMIT;
|
|
135
|
+
firstValueIsDefault = true;
|
|
136
|
+
}
|
|
130
137
|
}
|
|
131
138
|
} else if (arg.name.value === SKIP_ARG) {
|
|
139
|
+
hasSkipArg = true;
|
|
132
140
|
if (arg.value.kind === graphql.Kind.INT) {
|
|
133
141
|
skipValue = Number.parseInt(arg.value.value);
|
|
134
142
|
} else if (arg.value.kind === graphql.Kind.VARIABLE && variables) {
|
|
135
143
|
const varName = arg.value.name.value;
|
|
136
144
|
const varValue = variables[varName];
|
|
137
145
|
skipValue = typeof varValue === "number" ? varValue : undefined;
|
|
146
|
+
if (skipValue === undefined && varName === arg.value.name.value) {
|
|
147
|
+
skipValue = 0;
|
|
148
|
+
}
|
|
138
149
|
}
|
|
139
150
|
} else {
|
|
140
151
|
otherArgs.push(arg);
|
|
@@ -152,12 +163,13 @@ function extractFetchAllFields(document, variables, fetchAllFields) {
|
|
|
152
163
|
path: [...pathStack],
|
|
153
164
|
fieldName: node.name.value,
|
|
154
165
|
alias: node.alias?.value,
|
|
155
|
-
|
|
156
|
-
|
|
166
|
+
hasFirstArg,
|
|
167
|
+
firstValue: hasFetchAllDirective && !hasFirstArg ? THE_GRAPH_LIMIT : firstValue,
|
|
168
|
+
skipValue: hasFetchAllDirective && !hasSkipArg ? 0 : skipValue,
|
|
157
169
|
otherArgs,
|
|
158
170
|
selections: node.selectionSet?.selections,
|
|
159
171
|
hasFetchAllDirective,
|
|
160
|
-
firstValueIsDefault
|
|
172
|
+
firstValueIsDefault
|
|
161
173
|
});
|
|
162
174
|
}
|
|
163
175
|
},
|
|
@@ -294,16 +306,7 @@ function createTheGraphClientWithPagination(theGraphClient) {
|
|
|
294
306
|
}
|
|
295
307
|
return results;
|
|
296
308
|
}
|
|
297
|
-
return { async query(
|
|
298
|
-
let document;
|
|
299
|
-
let variables;
|
|
300
|
-
if (isRequestOptions(documentOrOptions)) {
|
|
301
|
-
document = documentOrOptions.document;
|
|
302
|
-
variables = documentOrOptions.variables;
|
|
303
|
-
} else {
|
|
304
|
-
document = documentOrOptions;
|
|
305
|
-
variables = variablesRaw ?? {};
|
|
306
|
-
}
|
|
309
|
+
return { async query(document, variables) {
|
|
307
310
|
const { document: processedDocument, fetchAllFields } = stripFetchAllDirective(document);
|
|
308
311
|
const listFields = extractFetchAllFields(processedDocument, variables, fetchAllFields);
|
|
309
312
|
if (listFields.length === 0) {
|
|
@@ -328,9 +331,6 @@ function createTheGraphClientWithPagination(theGraphClient) {
|
|
|
328
331
|
return result;
|
|
329
332
|
} };
|
|
330
333
|
}
|
|
331
|
-
function isRequestOptions(args) {
|
|
332
|
-
return typeof args === "object" && args !== null && "document" in args && "variables" in args;
|
|
333
|
-
}
|
|
334
334
|
|
|
335
335
|
//#endregion
|
|
336
336
|
//#region src/thegraph.ts
|
|
@@ -421,8 +421,7 @@ function createTheGraphClient(options, clientOptions) {
|
|
|
421
421
|
...clientOptions,
|
|
422
422
|
headers: (0, __settlemint_sdk_utils_http.appendHeaders)(clientOptions?.headers, { "x-auth-token": validatedOptions.accessToken })
|
|
423
423
|
});
|
|
424
|
-
const
|
|
425
|
-
const paginatedClient = createTheGraphClientWithPagination({ request: originalRequest });
|
|
424
|
+
const paginatedClient = createTheGraphClientWithPagination(client);
|
|
426
425
|
client.request = paginatedClient.query;
|
|
427
426
|
return {
|
|
428
427
|
client,
|
package/dist/thegraph.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thegraph.cjs","names":["document: DocumentNode | RequestDocument","target: unknown","source: unknown","result: Record<string, unknown>","document: DocumentNode","variables?: Variables","fetchAllFields?: Set<string>","fields: ListField[]","pathStack: string[]","firstValue: number | undefined","skipValue: number | undefined","otherArgs: ArgumentNode[]","Kind","targetField: ListField","skip: number","first: number","newArgs: ArgumentNode[]","listFields: ListField[]","variables: Variables | undefined","filtered: Variables","theGraphClient: Pick<GraphQLClient, \"request\">","field: ListField","results: unknown[]","documentOrOptions: TadaDocumentNode<TResult, TVariables> | RequestDocument | RequestOptions<TVariables, TResult>","variablesRaw?: Omit<TVariables, \"skip\" | \"first\">","document: TadaDocumentNode<TResult, TVariables> | RequestDocument","variables: Omit<TVariables, \"skip\" | \"first\">","args: unknown","UrlOrPathSchema","options: ClientOptions","instance","clientOptions?: RequestConfig","graphql","GraphQLClient"],"sources":["../src/utils/pagination.ts","../src/thegraph.ts"],"sourcesContent":["import { sortBy } from \"es-toolkit\";\nimport { get, isArray, isEmpty, set } from \"es-toolkit/compat\";\nimport type { TadaDocumentNode } from \"gql.tada\";\nimport { type ArgumentNode, type DocumentNode, Kind, parse, type SelectionNode, visit } from \"graphql\";\nimport type { GraphQLClient, RequestDocument, RequestOptions, Variables } from \"graphql-request\";\n\n// Constants for TheGraph limits\nconst THE_GRAPH_LIMIT = 500;\nconst FIRST_ARG = \"first\";\nconst SKIP_ARG = \"skip\";\nconst FETCH_ALL_DIRECTIVE = \"fetchAll\";\n\ninterface ListField {\n path: string[];\n fieldName: string;\n alias?: string;\n firstValue?: number;\n skipValue?: number;\n otherArgs: ArgumentNode[];\n selections?: ReadonlyArray<SelectionNode>;\n hasFetchAllDirective?: boolean;\n firstValueIsDefault?: boolean; // Track if first value was defaulted\n}\n\n/**\n * Detects and strips @fetchAll directives from a GraphQL document\n *\n * @param {DocumentNode} document - The GraphQL document to process\n * @returns {Object} Processed document and list of fields with @fetchAll\n *\n * @remarks\n * This function:\n * - Identifies fields decorated with @fetchAll directive\n * - Removes the directive from the AST (The Graph doesn't recognize it)\n * - Returns both the cleaned document and a list of fields to auto-paginate\n */\nfunction stripFetchAllDirective(document: DocumentNode | RequestDocument): {\n document: DocumentNode;\n fetchAllFields: Set<string>;\n} {\n const fetchAllFields = new Set<string>();\n const documentNode = typeof document === \"string\" ? parse(document) : document;\n const strippedDocument = visit(documentNode, {\n Field(node) {\n // Check if this field has the @fetchAll directive\n if (node.directives && node.directives.length > 0) {\n const hasFetchAll = node.directives.some((dir) => dir.name.value === FETCH_ALL_DIRECTIVE);\n\n if (hasFetchAll) {\n const fieldIdentifier = node.alias?.value || node.name.value;\n fetchAllFields.add(fieldIdentifier);\n\n // Return a new node without the @fetchAll directive\n return {\n ...node,\n directives: node.directives.filter((dir) => dir.name.value !== FETCH_ALL_DIRECTIVE),\n };\n }\n }\n\n return node;\n },\n });\n\n return {\n document: strippedDocument,\n fetchAllFields,\n };\n}\n\n/**\n * Custom merge function for deep object merging with special handling for lists\n *\n * @param {unknown} target - The target object or value to merge into\n * @param {unknown} source - The source object or value to merge from\n * @returns {unknown} Merged result with preservation of arrays and specific merge logic\n *\n * @remarks\n * Key behaviors:\n * - Preserves existing arrays without merging\n * - Handles null and undefined values\n * - Performs deep merge for nested objects\n * - Prioritizes source values for primitives\n *\n */\nfunction customMerge(target: unknown, source: unknown): unknown {\n if (source == null) return target;\n if (target == null) return source;\n\n // If source is an array, return it, don't merge arrays\n if (isArray(source)) {\n return source;\n }\n\n if (typeof target !== \"object\" || typeof source !== \"object\") {\n return source;\n }\n\n // Manually merge objects to ensure arrays are preserved\n const targetObj = target as Record<string, unknown>;\n const sourceObj = source as Record<string, unknown>;\n const result: Record<string, unknown> = { ...targetObj };\n\n for (const key in sourceObj) {\n if (Object.hasOwn(sourceObj, key)) {\n result[key] = key in result ? customMerge(result[key], sourceObj[key]) : sourceObj[key];\n }\n }\n\n return result;\n}\n\n// Extract all fields that have @fetchAll directive\nfunction extractFetchAllFields(\n document: DocumentNode,\n variables?: Variables,\n fetchAllFields?: Set<string>,\n): ListField[] {\n const fields: ListField[] = [];\n const pathStack: string[] = [];\n\n visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Skip meta fields\n if (node.name.value.startsWith(\"__\")) {\n return;\n }\n\n // Check if this field has pagination arguments (first or skip)\n let firstValue: number | undefined;\n let skipValue: number | undefined;\n const otherArgs: ArgumentNode[] = [];\n\n if (node.arguments) {\n for (const arg of node.arguments) {\n if (arg.name.value === FIRST_ARG) {\n if (arg.value.kind === Kind.INT) {\n firstValue = Number.parseInt(arg.value.value);\n } else if (arg.value.kind === Kind.VARIABLE && variables) {\n const varName = arg.value.name.value;\n const varValue = (variables as Record<string, unknown>)[varName];\n firstValue = typeof varValue === \"number\" ? varValue : undefined;\n }\n } else if (arg.name.value === SKIP_ARG) {\n if (arg.value.kind === Kind.INT) {\n skipValue = Number.parseInt(arg.value.value);\n } else if (arg.value.kind === Kind.VARIABLE && variables) {\n const varName = arg.value.name.value;\n const varValue = (variables as Record<string, unknown>)[varName];\n skipValue = typeof varValue === \"number\" ? varValue : undefined;\n }\n } else {\n otherArgs.push(arg);\n }\n }\n }\n\n // Check if this field has @fetchAll directive\n const fieldIdentifierForDirective = node.alias?.value || node.name.value;\n const hasFetchAllDirective = fetchAllFields?.has(fieldIdentifierForDirective);\n\n if (hasFetchAllDirective) {\n // Do not allow nesting @fetchAll fields\n const parentFetchAllField = fields.find((field) => pathStack.join(\",\").startsWith(field.path.join(\",\")));\n if (parentFetchAllField) {\n throw new Error(\n `Nesting of @fetchAll directive is not supported: ${pathStack.join(\".\")} is a child of ${parentFetchAllField.path.join(\".\")}`,\n );\n }\n fields.push({\n path: [...pathStack],\n fieldName: node.name.value,\n alias: node.alias?.value,\n firstValue: hasFetchAllDirective && (firstValue ?? THE_GRAPH_LIMIT),\n skipValue: hasFetchAllDirective && (skipValue ?? 0),\n otherArgs,\n selections: node.selectionSet?.selections,\n hasFetchAllDirective,\n firstValueIsDefault: hasFetchAllDirective ? firstValue === undefined : false,\n });\n }\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n\n return fields;\n}\n\n// Create a query for a single field with specific pagination\nfunction createSingleFieldQuery(\n document: DocumentNode,\n targetField: ListField,\n skip: number,\n first: number,\n): DocumentNode {\n const targetPath = [...targetField.path];\n const pathStack: string[] = [];\n\n return visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Check if we're on the path to target field\n const onPath = pathStack.every((segment, i) => i >= targetPath.length || segment === targetPath[i]);\n\n if (!onPath) {\n pathStack.pop();\n return null; // Remove fields not on path\n }\n\n // If this is our target field, update pagination\n const isTarget =\n pathStack.length === targetPath.length && pathStack.every((segment, i) => segment === targetPath[i]);\n\n if (isTarget) {\n const newArgs: ArgumentNode[] = [...targetField.otherArgs];\n\n // Add pagination arguments\n newArgs.push(\n {\n kind: Kind.ARGUMENT,\n name: { kind: Kind.NAME, value: FIRST_ARG },\n value: { kind: Kind.INT, value: first.toString() },\n },\n {\n kind: Kind.ARGUMENT,\n name: { kind: Kind.NAME, value: SKIP_ARG },\n value: { kind: Kind.INT, value: skip.toString() },\n },\n );\n\n return { ...node, arguments: newArgs };\n }\n\n return undefined;\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n}\n\n// Create query without list fields\nfunction createNonListQuery(document: DocumentNode, listFields: ListField[]): DocumentNode | null {\n let hasFields = false;\n const pathStack: string[] = [];\n\n const filtered = visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Check if this field is a list field\n const isList = listFields.some(\n (field) =>\n field.path.length === pathStack.length && field.path.every((segment, i) => segment === pathStack[i]),\n );\n\n if (isList) {\n pathStack.pop();\n return null;\n }\n\n hasFields = true;\n return undefined;\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n\n return hasFields ? filtered : null;\n}\n\n// Filter variables to only include used ones\nfunction filterVariables(variables: Variables | undefined, document: DocumentNode): Variables | undefined {\n if (!variables) return undefined;\n\n const usedVariables = new Set<string>();\n\n visit(document, {\n Variable: (node) => {\n usedVariables.add(node.name.value);\n },\n });\n\n const filtered: Variables = {};\n const varsObj = variables as Record<string, unknown>;\n for (const key of usedVariables) {\n if (key in varsObj) {\n (filtered as Record<string, unknown>)[key] = varsObj[key];\n }\n }\n\n return isEmpty(filtered) ? undefined : filtered;\n}\n\n/**\n * Creates a TheGraph client that supports pagination for list fields\n *\n * @param theGraphClient - The GraphQL client to use for requests\n * @returns A TheGraph client that supports pagination for list fields\n * @internal Used internally by createTheGraphClient\n */\nexport function createTheGraphClientWithPagination(theGraphClient: Pick<GraphQLClient, \"request\">) {\n // Execute pagination for a list field\n async function executeListFieldPagination(\n document: DocumentNode,\n variables: Variables | undefined,\n field: ListField,\n ): Promise<unknown[]> {\n const results: unknown[] = [];\n let currentSkip = field.skipValue || 0;\n let hasMore = true;\n\n // For fields with pagination arguments, always attempt to fetch data\n // and continue if we get a full page (indicating more data might exist)\n const batchSize = Math.min(field.firstValue || THE_GRAPH_LIMIT, THE_GRAPH_LIMIT);\n\n while (hasMore) {\n const query = createSingleFieldQuery(document, field, currentSkip, batchSize);\n const existingVariables = filterVariables(variables, query) ?? {};\n const response = await theGraphClient.request(query, {\n ...existingVariables,\n first: batchSize,\n skip: currentSkip,\n });\n\n // Use array path format for es-toolkit's get function\n const data = get(response, field.path) ?? get(response, field.fieldName);\n\n const parentPath = field.path.slice(0, -1);\n const parentData = get(response, parentPath);\n if (isArray(parentData) && parentData.length > 0) {\n throw new Error(\n `Response is an array, but expected a single object for field ${parentPath.join(\".\")}. The @fetchAll directive is not supported inside a query that returns a list of items.`,\n );\n }\n\n if (isArray(data) && data.length > 0) {\n results.push(...data);\n\n // Continue fetching if:\n // 1. We have @fetchAll directive (fetch everything)\n // 2. We have an explicit first value > THE_GRAPH_LIMIT and haven't reached it\n // 3. We have a defaulted first value and got a full batch (treating it as \"no explicit value\")\n // 4. We have no first value and got a full batch\n if (field.hasFetchAllDirective) {\n // With @fetchAll, continue if we got a full batch\n hasMore = data.length === batchSize;\n } else if (field.firstValue && !field.firstValueIsDefault) {\n // With explicit first value (not defaulted), only continue if:\n // - We haven't reached the requested amount yet\n // - We got a full batch (indicating more data might exist)\n hasMore = data.length === batchSize && results.length < field.firstValue;\n } else {\n // When first is not specified or was defaulted (using default batch size),\n // continue if we got a full batch (standard TheGraph pagination behavior)\n hasMore = data.length === batchSize;\n }\n } else {\n hasMore = false;\n }\n\n currentSkip += batchSize;\n }\n\n return results;\n }\n\n return {\n async query<TResult, TVariables extends Variables>(\n documentOrOptions: TadaDocumentNode<TResult, TVariables> | RequestDocument | RequestOptions<TVariables, TResult>,\n variablesRaw?: Omit<TVariables, \"skip\" | \"first\">,\n ): Promise<TResult> {\n let document: TadaDocumentNode<TResult, TVariables> | RequestDocument;\n let variables: Omit<TVariables, \"skip\" | \"first\">;\n\n if (isRequestOptions(documentOrOptions)) {\n document = documentOrOptions.document;\n variables = documentOrOptions.variables as TVariables;\n } else {\n document = documentOrOptions;\n variables = variablesRaw ?? ({} as TVariables);\n }\n\n // First, detect and strip @fetchAll directives\n const { document: processedDocument, fetchAllFields } = stripFetchAllDirective(document);\n\n // Extract all list fields (including those with @fetchAll)\n const listFields = extractFetchAllFields(processedDocument, variables, fetchAllFields);\n\n // If no list fields, execute normally\n if (listFields.length === 0) {\n return theGraphClient.request(processedDocument, variables as Variables);\n }\n\n // Execute paginated queries for all list fields\n const result: Record<string, unknown> = {};\n\n // Sort fields by depth to handle nested fields correctly\n const sortedFields = sortBy(listFields, [(field) => field.path.length]);\n\n // Process list fields in parallel for better performance\n const fieldDataPromises = sortedFields.map(async (field) => ({\n field,\n data: await executeListFieldPagination(processedDocument, variables, field),\n }));\n\n const fieldResults = await Promise.all(fieldDataPromises);\n\n // Set results in order\n for (const { field, data } of fieldResults) {\n // Use array path format for es-toolkit's set function\n set(result, field.path, data);\n }\n\n // Execute non-list fields (single entity queries)\n const nonListQuery = createNonListQuery(processedDocument, listFields);\n\n if (nonListQuery) {\n const nonListResult = await theGraphClient.request(\n nonListQuery,\n filterVariables(variables, nonListQuery) ?? {},\n );\n\n // Merge results, preserving list data\n const merged = customMerge(nonListResult, result);\n return merged as TResult;\n }\n\n return result as TResult;\n },\n } as const;\n}\n\nfunction isRequestOptions(args: unknown): args is RequestOptions<Variables, unknown> {\n return typeof args === \"object\" && args !== null && \"document\" in args && \"variables\" in args;\n}\n","import { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { ensureServer } from \"@settlemint/sdk-utils/runtime\";\nimport { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from \"@settlemint/sdk-utils/validation\";\nimport { type AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport { GraphQLClient } from \"graphql-request\";\nimport { z } from \"zod\";\nimport { createTheGraphClientWithPagination } from \"./utils/pagination.js\";\n\n/**\n * Type definition for GraphQL client configuration options\n */\nexport type RequestConfig = ConstructorParameters<typeof GraphQLClient>[1];\n\n/**\n * Schema for validating client options for the TheGraph client.\n */\nexport const ClientOptionsSchema = z.object({\n instances: z.array(UrlOrPathSchema),\n accessToken: ApplicationAccessTokenSchema.optional(),\n subgraphName: z.string(),\n cache: z.enum([\"default\", \"force-cache\", \"no-cache\", \"no-store\", \"only-if-cached\", \"reload\"]).optional(),\n});\n\n/**\n * Type definition for client options derived from the ClientOptionsSchema\n */\nexport type ClientOptions = z.infer<typeof ClientOptionsSchema>;\n\n/**\n * Constructs the full URL for TheGraph GraphQL API based on the provided options\n *\n * @param options - The client options for configuring TheGraph client\n * @returns The complete GraphQL API URL as a string\n * @throws Will throw an error if no matching instance is found for the specified subgraph\n */\nfunction getFullUrl(options: ClientOptions): string {\n const instance = options.instances.find((instance) => instance.endsWith(`/${options.subgraphName}`));\n if (!instance) {\n throw new Error(`Instance for subgraph ${options.subgraphName} not found`);\n }\n return new URL(instance).toString();\n}\n\n/**\n * Creates a TheGraph GraphQL client with proper type safety using gql.tada\n *\n * @param options - Configuration options for the client including instance URLs,\n * access token and subgraph name\n * @param clientOptions - Optional GraphQL client configuration options\n * @returns An object containing:\n * - client: The configured GraphQL client instance\n * - graphql: The initialized gql.tada function for type-safe queries\n * @throws Will throw an error if the options fail validation against ClientOptionsSchema\n * @example\n * import { createTheGraphClient } from '@settlemint/sdk-thegraph';\n * import type { introspection } from '@schemas/the-graph-env-kits';\n * import { createLogger, requestLogger } from '@settlemint/sdk-utils/logging';\n *\n * const logger = createLogger();\n *\n * const { client, graphql } = createTheGraphClient<{\n * introspection: introspection;\n * disableMasking: true;\n * scalars: {\n * Bytes: string;\n * Int8: string;\n * BigInt: string;\n * BigDecimal: string;\n * Timestamp: string;\n * };\n * }>({\n * instances: JSON.parse(process.env.SETTLEMINT_THEGRAPH_SUBGRAPHS_ENDPOINTS || '[]'),\n * accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,\n * subgraphName: 'kits'\n * }, {\n * fetch: requestLogger(logger, \"the-graph-kits\", fetch) as typeof fetch,\n * });\n *\n * // Making GraphQL queries\n * const query = graphql(`\n * query SearchAssets {\n * assets @fetchAll {\n * id\n * name\n * symbol\n * }\n * }\n * `);\n *\n * const result = await client.request(query);\n */\nexport function createTheGraphClient<const Setup extends AbstractSetupSchema>(\n options: ClientOptions,\n clientOptions?: RequestConfig,\n): {\n client: GraphQLClient;\n graphql: initGraphQLTada<Setup>;\n} {\n ensureServer();\n const validatedOptions = validate(ClientOptionsSchema, options);\n const graphql = initGraphQLTada<Setup>();\n const fullUrl = getFullUrl(validatedOptions);\n\n const client = new GraphQLClient(fullUrl, {\n ...clientOptions,\n headers: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n });\n const originalRequest = client.request.bind(client);\n const paginatedClient = createTheGraphClientWithPagination({\n request: originalRequest,\n });\n client.request = paginatedClient.query;\n return {\n client,\n graphql,\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport { createTheGraphClientWithPagination } from \"./utils/pagination.js\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"thegraph.cjs","names":["document: DocumentNode","target: unknown","source: unknown","result: Record<string, unknown>","variables?: Variables","fetchAllFields?: Set<string>","fields: ListField[]","pathStack: string[]","firstValue: number | undefined","skipValue: number | undefined","otherArgs: ArgumentNode[]","Kind","targetField: ListField","skip: number","first: number","newArgs: ArgumentNode[]","listFields: ListField[]","variables: Variables | undefined","filtered: Variables","theGraphClient: Pick<GraphQLClient, \"request\">","field: ListField","results: unknown[]","document: TadaDocumentNode<TResult, TVariables>","variables: Omit<TVariables, \"skip\" | \"first\">","UrlOrPathSchema","options: ClientOptions","instance","clientOptions?: RequestConfig","graphql","GraphQLClient"],"sources":["../src/utils/pagination.ts","../src/thegraph.ts"],"sourcesContent":["import { sortBy } from \"es-toolkit\";\nimport { get, isArray, isEmpty, set } from \"es-toolkit/compat\";\nimport type { TadaDocumentNode } from \"gql.tada\";\nimport { type ArgumentNode, type DocumentNode, Kind, type SelectionNode, visit } from \"graphql\";\nimport type { GraphQLClient, Variables } from \"graphql-request\";\n\n// Constants for TheGraph limits\nconst THE_GRAPH_LIMIT = 500;\nconst FIRST_ARG = \"first\";\nconst SKIP_ARG = \"skip\";\nconst FETCH_ALL_DIRECTIVE = \"fetchAll\";\n\ninterface ListField {\n path: string[];\n fieldName: string;\n alias?: string;\n hasFirstArg: boolean;\n firstValue?: number;\n skipValue?: number;\n otherArgs: ArgumentNode[];\n selections?: ReadonlyArray<SelectionNode>;\n hasFetchAllDirective?: boolean;\n firstValueIsDefault?: boolean; // Track if first value was defaulted\n}\n\n/**\n * Detects and strips @fetchAll directives from a GraphQL document\n *\n * @param {DocumentNode} document - The GraphQL document to process\n * @returns {Object} Processed document and list of fields with @fetchAll\n *\n * @remarks\n * This function:\n * - Identifies fields decorated with @fetchAll directive\n * - Removes the directive from the AST (The Graph doesn't recognize it)\n * - Returns both the cleaned document and a list of fields to auto-paginate\n */\nfunction stripFetchAllDirective(document: DocumentNode): {\n document: DocumentNode;\n fetchAllFields: Set<string>;\n} {\n const fetchAllFields = new Set<string>();\n\n const strippedDocument = visit(document, {\n Field(node) {\n // Check if this field has the @fetchAll directive\n if (node.directives && node.directives.length > 0) {\n const hasFetchAll = node.directives.some((dir) => dir.name.value === FETCH_ALL_DIRECTIVE);\n\n if (hasFetchAll) {\n const fieldIdentifier = node.alias?.value || node.name.value;\n fetchAllFields.add(fieldIdentifier);\n\n // Return a new node without the @fetchAll directive\n return {\n ...node,\n directives: node.directives.filter((dir) => dir.name.value !== FETCH_ALL_DIRECTIVE),\n };\n }\n }\n\n return node;\n },\n });\n\n return {\n document: strippedDocument,\n fetchAllFields,\n };\n}\n\n/**\n * Custom merge function for deep object merging with special handling for lists\n *\n * @param {unknown} target - The target object or value to merge into\n * @param {unknown} source - The source object or value to merge from\n * @returns {unknown} Merged result with preservation of arrays and specific merge logic\n *\n * @remarks\n * Key behaviors:\n * - Preserves existing arrays without merging\n * - Handles null and undefined values\n * - Performs deep merge for nested objects\n * - Prioritizes source values for primitives\n *\n */\nfunction customMerge(target: unknown, source: unknown): unknown {\n if (source == null) return target;\n if (target == null) return source;\n\n // If source is an array, return it, don't merge arrays\n if (isArray(source)) {\n return source;\n }\n\n if (typeof target !== \"object\" || typeof source !== \"object\") {\n return source;\n }\n\n // Manually merge objects to ensure arrays are preserved\n const targetObj = target as Record<string, unknown>;\n const sourceObj = source as Record<string, unknown>;\n const result: Record<string, unknown> = { ...targetObj };\n\n for (const key in sourceObj) {\n if (Object.hasOwn(sourceObj, key)) {\n result[key] = key in result ? customMerge(result[key], sourceObj[key]) : sourceObj[key];\n }\n }\n\n return result;\n}\n\n// Extract all fields that have @fetchAll directive\nfunction extractFetchAllFields(\n document: DocumentNode,\n variables?: Variables,\n fetchAllFields?: Set<string>,\n): ListField[] {\n const fields: ListField[] = [];\n const pathStack: string[] = [];\n\n visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Skip meta fields\n if (node.name.value.startsWith(\"__\")) {\n return;\n }\n\n // Check if this field has pagination arguments (first or skip)\n let hasFirstArg = false;\n let hasSkipArg = false;\n let firstValue: number | undefined;\n let skipValue: number | undefined;\n let firstValueIsDefault = false;\n const otherArgs: ArgumentNode[] = [];\n\n if (node.arguments) {\n for (const arg of node.arguments) {\n if (arg.name.value === FIRST_ARG) {\n hasFirstArg = true;\n if (arg.value.kind === Kind.INT) {\n firstValue = Number.parseInt(arg.value.value);\n } else if (arg.value.kind === Kind.VARIABLE && variables) {\n const varName = arg.value.name.value;\n const varValue = (variables as Record<string, unknown>)[varName];\n firstValue = typeof varValue === \"number\" ? varValue : undefined;\n // If variable is defined in query but not passed in input, check if it's a standard pagination variable\n if (firstValue === undefined && varName === arg.value.name.value) {\n firstValue = THE_GRAPH_LIMIT; // Default to THE_GRAPH_LIMIT\n firstValueIsDefault = true; // Mark that this was defaulted\n }\n }\n } else if (arg.name.value === SKIP_ARG) {\n hasSkipArg = true;\n if (arg.value.kind === Kind.INT) {\n skipValue = Number.parseInt(arg.value.value);\n } else if (arg.value.kind === Kind.VARIABLE && variables) {\n const varName = arg.value.name.value;\n const varValue = (variables as Record<string, unknown>)[varName];\n skipValue = typeof varValue === \"number\" ? varValue : undefined;\n // If variable is defined in query but not passed in input, check if it's a standard pagination variable\n if (skipValue === undefined && varName === arg.value.name.value) {\n skipValue = 0; // Default to 0\n }\n }\n } else {\n otherArgs.push(arg);\n }\n }\n }\n\n // Check if this field has @fetchAll directive\n const fieldIdentifierForDirective = node.alias?.value || node.name.value;\n const hasFetchAllDirective = fetchAllFields?.has(fieldIdentifierForDirective);\n\n if (hasFetchAllDirective) {\n // Do not allow nesting @fetchAll fields\n const parentFetchAllField = fields.find((field) => pathStack.join(\",\").startsWith(field.path.join(\",\")));\n if (parentFetchAllField) {\n throw new Error(\n `Nesting of @fetchAll directive is not supported: ${pathStack.join(\".\")} is a child of ${parentFetchAllField.path.join(\".\")}`,\n );\n }\n fields.push({\n path: [...pathStack],\n fieldName: node.name.value,\n alias: node.alias?.value,\n hasFirstArg,\n firstValue: hasFetchAllDirective && !hasFirstArg ? THE_GRAPH_LIMIT : firstValue,\n skipValue: hasFetchAllDirective && !hasSkipArg ? 0 : skipValue,\n otherArgs,\n selections: node.selectionSet?.selections,\n hasFetchAllDirective,\n firstValueIsDefault,\n });\n }\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n\n return fields;\n}\n\n// Create a query for a single field with specific pagination\nfunction createSingleFieldQuery(\n document: DocumentNode,\n targetField: ListField,\n skip: number,\n first: number,\n): DocumentNode {\n const targetPath = [...targetField.path];\n const pathStack: string[] = [];\n\n return visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Check if we're on the path to target field\n const onPath = pathStack.every((segment, i) => i >= targetPath.length || segment === targetPath[i]);\n\n if (!onPath) {\n pathStack.pop();\n return null; // Remove fields not on path\n }\n\n // If this is our target field, update pagination\n const isTarget =\n pathStack.length === targetPath.length && pathStack.every((segment, i) => segment === targetPath[i]);\n\n if (isTarget) {\n const newArgs: ArgumentNode[] = [...targetField.otherArgs];\n\n // Add pagination arguments\n newArgs.push(\n {\n kind: Kind.ARGUMENT,\n name: { kind: Kind.NAME, value: FIRST_ARG },\n value: { kind: Kind.INT, value: first.toString() },\n },\n {\n kind: Kind.ARGUMENT,\n name: { kind: Kind.NAME, value: SKIP_ARG },\n value: { kind: Kind.INT, value: skip.toString() },\n },\n );\n\n return { ...node, arguments: newArgs };\n }\n\n return undefined;\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n}\n\n// Create query without list fields\nfunction createNonListQuery(document: DocumentNode, listFields: ListField[]): DocumentNode | null {\n let hasFields = false;\n const pathStack: string[] = [];\n\n const filtered = visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Check if this field is a list field\n const isList = listFields.some(\n (field) =>\n field.path.length === pathStack.length && field.path.every((segment, i) => segment === pathStack[i]),\n );\n\n if (isList) {\n pathStack.pop();\n return null;\n }\n\n hasFields = true;\n return undefined;\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n\n return hasFields ? filtered : null;\n}\n\n// Filter variables to only include used ones\nfunction filterVariables(variables: Variables | undefined, document: DocumentNode): Variables | undefined {\n if (!variables) return undefined;\n\n const usedVariables = new Set<string>();\n\n visit(document, {\n Variable: (node) => {\n usedVariables.add(node.name.value);\n },\n });\n\n const filtered: Variables = {};\n const varsObj = variables as Record<string, unknown>;\n for (const key of usedVariables) {\n if (key in varsObj) {\n (filtered as Record<string, unknown>)[key] = varsObj[key];\n }\n }\n\n return isEmpty(filtered) ? undefined : filtered;\n}\n\n/**\n * Creates a TheGraph client that supports pagination for list fields\n *\n * @param theGraphClient - The GraphQL client to use for requests\n * @returns A TheGraph client that supports pagination for list fields\n * @internal Used internally by createTheGraphClient\n */\nexport function createTheGraphClientWithPagination(theGraphClient: Pick<GraphQLClient, \"request\">) {\n // Execute pagination for a list field\n async function executeListFieldPagination(\n document: DocumentNode,\n variables: Variables | undefined,\n field: ListField,\n ): Promise<unknown[]> {\n const results: unknown[] = [];\n let currentSkip = field.skipValue || 0;\n let hasMore = true;\n\n // For fields with pagination arguments, always attempt to fetch data\n // and continue if we get a full page (indicating more data might exist)\n const batchSize = Math.min(field.firstValue || THE_GRAPH_LIMIT, THE_GRAPH_LIMIT);\n\n while (hasMore) {\n const query = createSingleFieldQuery(document, field, currentSkip, batchSize);\n const existingVariables = filterVariables(variables, query) ?? {};\n const response = await theGraphClient.request(query, {\n ...existingVariables,\n first: batchSize,\n skip: currentSkip,\n });\n\n // Use array path format for es-toolkit's get function\n const data = get(response, field.path) ?? get(response, field.fieldName);\n\n const parentPath = field.path.slice(0, -1);\n const parentData = get(response, parentPath);\n if (isArray(parentData) && parentData.length > 0) {\n throw new Error(\n `Response is an array, but expected a single object for field ${parentPath.join(\".\")}. The @fetchAll directive is not supported inside a query that returns a list of items.`,\n );\n }\n\n if (isArray(data) && data.length > 0) {\n results.push(...data);\n\n // Continue fetching if:\n // 1. We have @fetchAll directive (fetch everything)\n // 2. We have an explicit first value > THE_GRAPH_LIMIT and haven't reached it\n // 3. We have a defaulted first value and got a full batch (treating it as \"no explicit value\")\n // 4. We have no first value and got a full batch\n if (field.hasFetchAllDirective) {\n // With @fetchAll, continue if we got a full batch\n hasMore = data.length === batchSize;\n } else if (field.firstValue && !field.firstValueIsDefault) {\n // With explicit first value (not defaulted), only continue if:\n // - We haven't reached the requested amount yet\n // - We got a full batch (indicating more data might exist)\n hasMore = data.length === batchSize && results.length < field.firstValue;\n } else {\n // When first is not specified or was defaulted (using default batch size),\n // continue if we got a full batch (standard TheGraph pagination behavior)\n hasMore = data.length === batchSize;\n }\n } else {\n hasMore = false;\n }\n\n currentSkip += batchSize;\n }\n\n return results;\n }\n\n return {\n async query<TResult, TVariables extends Variables>(\n document: TadaDocumentNode<TResult, TVariables>,\n variables: Omit<TVariables, \"skip\" | \"first\">,\n ): Promise<TResult> {\n // First, detect and strip @fetchAll directives\n const { document: processedDocument, fetchAllFields } = stripFetchAllDirective(document);\n\n // Extract all list fields (including those with @fetchAll)\n const listFields = extractFetchAllFields(processedDocument, variables, fetchAllFields);\n\n // If no list fields, execute normally\n if (listFields.length === 0) {\n return theGraphClient.request(processedDocument, variables as Variables);\n }\n\n // Execute paginated queries for all list fields\n const result: Record<string, unknown> = {};\n\n // Sort fields by depth to handle nested fields correctly\n const sortedFields = sortBy(listFields, [(field) => field.path.length]);\n\n // Process list fields in parallel for better performance\n const fieldDataPromises = sortedFields.map(async (field) => ({\n field,\n data: await executeListFieldPagination(processedDocument, variables, field),\n }));\n\n const fieldResults = await Promise.all(fieldDataPromises);\n\n // Set results in order\n for (const { field, data } of fieldResults) {\n // Use array path format for es-toolkit's set function\n set(result, field.path, data);\n }\n\n // Execute non-list fields (single entity queries)\n const nonListQuery = createNonListQuery(processedDocument, listFields);\n\n if (nonListQuery) {\n const nonListResult = await theGraphClient.request(\n nonListQuery,\n filterVariables(variables, nonListQuery) ?? {},\n );\n\n // Merge results, preserving list data\n const merged = customMerge(nonListResult, result);\n return merged as TResult;\n }\n\n return result as TResult;\n },\n } as const;\n}\n","import { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { ensureServer } from \"@settlemint/sdk-utils/runtime\";\nimport { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from \"@settlemint/sdk-utils/validation\";\nimport { type AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport { GraphQLClient } from \"graphql-request\";\nimport { z } from \"zod\";\nimport { createTheGraphClientWithPagination } from \"./utils/pagination.js\";\n\n/**\n * Type definition for GraphQL client configuration options\n */\nexport type RequestConfig = ConstructorParameters<typeof GraphQLClient>[1];\n\n/**\n * Schema for validating client options for the TheGraph client.\n */\nexport const ClientOptionsSchema = z.object({\n instances: z.array(UrlOrPathSchema),\n accessToken: ApplicationAccessTokenSchema.optional(),\n subgraphName: z.string(),\n cache: z.enum([\"default\", \"force-cache\", \"no-cache\", \"no-store\", \"only-if-cached\", \"reload\"]).optional(),\n});\n\n/**\n * Type definition for client options derived from the ClientOptionsSchema\n */\nexport type ClientOptions = z.infer<typeof ClientOptionsSchema>;\n\n/**\n * Constructs the full URL for TheGraph GraphQL API based on the provided options\n *\n * @param options - The client options for configuring TheGraph client\n * @returns The complete GraphQL API URL as a string\n * @throws Will throw an error if no matching instance is found for the specified subgraph\n */\nfunction getFullUrl(options: ClientOptions): string {\n const instance = options.instances.find((instance) => instance.endsWith(`/${options.subgraphName}`));\n if (!instance) {\n throw new Error(`Instance for subgraph ${options.subgraphName} not found`);\n }\n return new URL(instance).toString();\n}\n\n/**\n * Creates a TheGraph GraphQL client with proper type safety using gql.tada\n *\n * @param options - Configuration options for the client including instance URLs,\n * access token and subgraph name\n * @param clientOptions - Optional GraphQL client configuration options\n * @returns An object containing:\n * - client: The configured GraphQL client instance\n * - graphql: The initialized gql.tada function for type-safe queries\n * @throws Will throw an error if the options fail validation against ClientOptionsSchema\n * @example\n * import { createTheGraphClient } from '@settlemint/sdk-thegraph';\n * import type { introspection } from '@schemas/the-graph-env-kits';\n * import { createLogger, requestLogger } from '@settlemint/sdk-utils/logging';\n *\n * const logger = createLogger();\n *\n * const { client, graphql } = createTheGraphClient<{\n * introspection: introspection;\n * disableMasking: true;\n * scalars: {\n * Bytes: string;\n * Int8: string;\n * BigInt: string;\n * BigDecimal: string;\n * Timestamp: string;\n * };\n * }>({\n * instances: JSON.parse(process.env.SETTLEMINT_THEGRAPH_SUBGRAPHS_ENDPOINTS || '[]'),\n * accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,\n * subgraphName: 'kits'\n * }, {\n * fetch: requestLogger(logger, \"the-graph-kits\", fetch) as typeof fetch,\n * });\n *\n * // Making GraphQL queries\n * const query = graphql(`\n * query SearchAssets {\n * assets @fetchAll {\n * id\n * name\n * symbol\n * }\n * }\n * `);\n *\n * const result = await client.request(query);\n */\nexport function createTheGraphClient<const Setup extends AbstractSetupSchema>(\n options: ClientOptions,\n clientOptions?: RequestConfig,\n): {\n client: GraphQLClient;\n graphql: initGraphQLTada<Setup>;\n} {\n ensureServer();\n const validatedOptions = validate(ClientOptionsSchema, options);\n const graphql = initGraphQLTada<Setup>();\n const fullUrl = getFullUrl(validatedOptions);\n\n const client = new GraphQLClient(fullUrl, {\n ...clientOptions,\n headers: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n });\n const paginatedClient = createTheGraphClientWithPagination(client);\n client.request = paginatedClient.query as typeof client.request;\n return {\n client,\n graphql,\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport { createTheGraphClientWithPagination } from \"./utils/pagination.js\";\n"],"mappings":"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"}
|
package/dist/thegraph.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* SettleMint The Graph SDK - Indexing Protocol */
|
|
2
2
|
import { AbstractSetupSchema, FragmentOf, ResultOf, TadaDocumentNode, VariablesOf, initGraphQLTada, readFragment } from "gql.tada";
|
|
3
|
-
import { GraphQLClient,
|
|
3
|
+
import { GraphQLClient, Variables } from "graphql-request";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
|
|
6
6
|
//#region src/utils/pagination.d.ts
|
|
@@ -13,7 +13,7 @@ import { z } from "zod";
|
|
|
13
13
|
* @internal Used internally by createTheGraphClient
|
|
14
14
|
*/
|
|
15
15
|
declare function createTheGraphClientWithPagination(theGraphClient: Pick<GraphQLClient, "request">): {
|
|
16
|
-
readonly query: <TResult, TVariables extends Variables>(
|
|
16
|
+
readonly query: <TResult, TVariables extends Variables>(document: TadaDocumentNode<TResult, TVariables>, variables: Omit<TVariables, "skip" | "first">) => Promise<TResult>;
|
|
17
17
|
};
|
|
18
18
|
//#endregion
|
|
19
19
|
//#region src/thegraph.d.ts
|
package/dist/thegraph.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* SettleMint The Graph SDK - Indexing Protocol */
|
|
2
2
|
import { AbstractSetupSchema, FragmentOf, ResultOf, TadaDocumentNode, VariablesOf, initGraphQLTada, readFragment } from "gql.tada";
|
|
3
|
-
import { GraphQLClient,
|
|
3
|
+
import { GraphQLClient, Variables } from "graphql-request";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
|
|
6
6
|
//#region src/utils/pagination.d.ts
|
|
@@ -13,7 +13,7 @@ import { z } from "zod";
|
|
|
13
13
|
* @internal Used internally by createTheGraphClient
|
|
14
14
|
*/
|
|
15
15
|
declare function createTheGraphClientWithPagination(theGraphClient: Pick<GraphQLClient, "request">): {
|
|
16
|
-
readonly query: <TResult, TVariables extends Variables>(
|
|
16
|
+
readonly query: <TResult, TVariables extends Variables>(document: TadaDocumentNode<TResult, TVariables>, variables: Omit<TVariables, "skip" | "first">) => Promise<TResult>;
|
|
17
17
|
};
|
|
18
18
|
//#endregion
|
|
19
19
|
//#region src/thegraph.d.ts
|
package/dist/thegraph.js
CHANGED
|
@@ -7,7 +7,7 @@ import { GraphQLClient } from "graphql-request";
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
import { sortBy } from "es-toolkit";
|
|
9
9
|
import { get, isArray, isEmpty, set } from "es-toolkit/compat";
|
|
10
|
-
import { Kind,
|
|
10
|
+
import { Kind, visit } from "graphql";
|
|
11
11
|
|
|
12
12
|
//#region src/utils/pagination.ts
|
|
13
13
|
const THE_GRAPH_LIMIT = 500;
|
|
@@ -28,8 +28,7 @@ const FETCH_ALL_DIRECTIVE = "fetchAll";
|
|
|
28
28
|
*/
|
|
29
29
|
function stripFetchAllDirective(document) {
|
|
30
30
|
const fetchAllFields = new Set();
|
|
31
|
-
const
|
|
32
|
-
const strippedDocument = visit(documentNode, { Field(node) {
|
|
31
|
+
const strippedDocument = visit(document, { Field(node) {
|
|
33
32
|
if (node.directives && node.directives.length > 0) {
|
|
34
33
|
const hasFetchAll = node.directives.some((dir) => dir.name.value === FETCH_ALL_DIRECTIVE);
|
|
35
34
|
if (hasFetchAll) {
|
|
@@ -92,26 +91,38 @@ function extractFetchAllFields(document, variables, fetchAllFields) {
|
|
|
92
91
|
if (node.name.value.startsWith("__")) {
|
|
93
92
|
return;
|
|
94
93
|
}
|
|
94
|
+
let hasFirstArg = false;
|
|
95
|
+
let hasSkipArg = false;
|
|
95
96
|
let firstValue;
|
|
96
97
|
let skipValue;
|
|
98
|
+
let firstValueIsDefault = false;
|
|
97
99
|
const otherArgs = [];
|
|
98
100
|
if (node.arguments) {
|
|
99
101
|
for (const arg of node.arguments) {
|
|
100
102
|
if (arg.name.value === FIRST_ARG) {
|
|
103
|
+
hasFirstArg = true;
|
|
101
104
|
if (arg.value.kind === Kind.INT) {
|
|
102
105
|
firstValue = Number.parseInt(arg.value.value);
|
|
103
106
|
} else if (arg.value.kind === Kind.VARIABLE && variables) {
|
|
104
107
|
const varName = arg.value.name.value;
|
|
105
108
|
const varValue = variables[varName];
|
|
106
109
|
firstValue = typeof varValue === "number" ? varValue : undefined;
|
|
110
|
+
if (firstValue === undefined && varName === arg.value.name.value) {
|
|
111
|
+
firstValue = THE_GRAPH_LIMIT;
|
|
112
|
+
firstValueIsDefault = true;
|
|
113
|
+
}
|
|
107
114
|
}
|
|
108
115
|
} else if (arg.name.value === SKIP_ARG) {
|
|
116
|
+
hasSkipArg = true;
|
|
109
117
|
if (arg.value.kind === Kind.INT) {
|
|
110
118
|
skipValue = Number.parseInt(arg.value.value);
|
|
111
119
|
} else if (arg.value.kind === Kind.VARIABLE && variables) {
|
|
112
120
|
const varName = arg.value.name.value;
|
|
113
121
|
const varValue = variables[varName];
|
|
114
122
|
skipValue = typeof varValue === "number" ? varValue : undefined;
|
|
123
|
+
if (skipValue === undefined && varName === arg.value.name.value) {
|
|
124
|
+
skipValue = 0;
|
|
125
|
+
}
|
|
115
126
|
}
|
|
116
127
|
} else {
|
|
117
128
|
otherArgs.push(arg);
|
|
@@ -129,12 +140,13 @@ function extractFetchAllFields(document, variables, fetchAllFields) {
|
|
|
129
140
|
path: [...pathStack],
|
|
130
141
|
fieldName: node.name.value,
|
|
131
142
|
alias: node.alias?.value,
|
|
132
|
-
|
|
133
|
-
|
|
143
|
+
hasFirstArg,
|
|
144
|
+
firstValue: hasFetchAllDirective && !hasFirstArg ? THE_GRAPH_LIMIT : firstValue,
|
|
145
|
+
skipValue: hasFetchAllDirective && !hasSkipArg ? 0 : skipValue,
|
|
134
146
|
otherArgs,
|
|
135
147
|
selections: node.selectionSet?.selections,
|
|
136
148
|
hasFetchAllDirective,
|
|
137
|
-
firstValueIsDefault
|
|
149
|
+
firstValueIsDefault
|
|
138
150
|
});
|
|
139
151
|
}
|
|
140
152
|
},
|
|
@@ -271,16 +283,7 @@ function createTheGraphClientWithPagination(theGraphClient) {
|
|
|
271
283
|
}
|
|
272
284
|
return results;
|
|
273
285
|
}
|
|
274
|
-
return { async query(
|
|
275
|
-
let document;
|
|
276
|
-
let variables;
|
|
277
|
-
if (isRequestOptions(documentOrOptions)) {
|
|
278
|
-
document = documentOrOptions.document;
|
|
279
|
-
variables = documentOrOptions.variables;
|
|
280
|
-
} else {
|
|
281
|
-
document = documentOrOptions;
|
|
282
|
-
variables = variablesRaw ?? {};
|
|
283
|
-
}
|
|
286
|
+
return { async query(document, variables) {
|
|
284
287
|
const { document: processedDocument, fetchAllFields } = stripFetchAllDirective(document);
|
|
285
288
|
const listFields = extractFetchAllFields(processedDocument, variables, fetchAllFields);
|
|
286
289
|
if (listFields.length === 0) {
|
|
@@ -305,9 +308,6 @@ function createTheGraphClientWithPagination(theGraphClient) {
|
|
|
305
308
|
return result;
|
|
306
309
|
} };
|
|
307
310
|
}
|
|
308
|
-
function isRequestOptions(args) {
|
|
309
|
-
return typeof args === "object" && args !== null && "document" in args && "variables" in args;
|
|
310
|
-
}
|
|
311
311
|
|
|
312
312
|
//#endregion
|
|
313
313
|
//#region src/thegraph.ts
|
|
@@ -398,8 +398,7 @@ function createTheGraphClient(options, clientOptions) {
|
|
|
398
398
|
...clientOptions,
|
|
399
399
|
headers: appendHeaders(clientOptions?.headers, { "x-auth-token": validatedOptions.accessToken })
|
|
400
400
|
});
|
|
401
|
-
const
|
|
402
|
-
const paginatedClient = createTheGraphClientWithPagination({ request: originalRequest });
|
|
401
|
+
const paginatedClient = createTheGraphClientWithPagination(client);
|
|
403
402
|
client.request = paginatedClient.query;
|
|
404
403
|
return {
|
|
405
404
|
client,
|
package/dist/thegraph.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thegraph.js","names":["document: DocumentNode | RequestDocument","target: unknown","source: unknown","result: Record<string, unknown>","document: DocumentNode","variables?: Variables","fetchAllFields?: Set<string>","fields: ListField[]","pathStack: string[]","firstValue: number | undefined","skipValue: number | undefined","otherArgs: ArgumentNode[]","targetField: ListField","skip: number","first: number","newArgs: ArgumentNode[]","listFields: ListField[]","variables: Variables | undefined","filtered: Variables","theGraphClient: Pick<GraphQLClient, \"request\">","field: ListField","results: unknown[]","documentOrOptions: TadaDocumentNode<TResult, TVariables> | RequestDocument | RequestOptions<TVariables, TResult>","variablesRaw?: Omit<TVariables, \"skip\" | \"first\">","document: TadaDocumentNode<TResult, TVariables> | RequestDocument","variables: Omit<TVariables, \"skip\" | \"first\">","args: unknown","options: ClientOptions","instance","clientOptions?: RequestConfig"],"sources":["../src/utils/pagination.ts","../src/thegraph.ts"],"sourcesContent":["import { sortBy } from \"es-toolkit\";\nimport { get, isArray, isEmpty, set } from \"es-toolkit/compat\";\nimport type { TadaDocumentNode } from \"gql.tada\";\nimport { type ArgumentNode, type DocumentNode, Kind, parse, type SelectionNode, visit } from \"graphql\";\nimport type { GraphQLClient, RequestDocument, RequestOptions, Variables } from \"graphql-request\";\n\n// Constants for TheGraph limits\nconst THE_GRAPH_LIMIT = 500;\nconst FIRST_ARG = \"first\";\nconst SKIP_ARG = \"skip\";\nconst FETCH_ALL_DIRECTIVE = \"fetchAll\";\n\ninterface ListField {\n path: string[];\n fieldName: string;\n alias?: string;\n firstValue?: number;\n skipValue?: number;\n otherArgs: ArgumentNode[];\n selections?: ReadonlyArray<SelectionNode>;\n hasFetchAllDirective?: boolean;\n firstValueIsDefault?: boolean; // Track if first value was defaulted\n}\n\n/**\n * Detects and strips @fetchAll directives from a GraphQL document\n *\n * @param {DocumentNode} document - The GraphQL document to process\n * @returns {Object} Processed document and list of fields with @fetchAll\n *\n * @remarks\n * This function:\n * - Identifies fields decorated with @fetchAll directive\n * - Removes the directive from the AST (The Graph doesn't recognize it)\n * - Returns both the cleaned document and a list of fields to auto-paginate\n */\nfunction stripFetchAllDirective(document: DocumentNode | RequestDocument): {\n document: DocumentNode;\n fetchAllFields: Set<string>;\n} {\n const fetchAllFields = new Set<string>();\n const documentNode = typeof document === \"string\" ? parse(document) : document;\n const strippedDocument = visit(documentNode, {\n Field(node) {\n // Check if this field has the @fetchAll directive\n if (node.directives && node.directives.length > 0) {\n const hasFetchAll = node.directives.some((dir) => dir.name.value === FETCH_ALL_DIRECTIVE);\n\n if (hasFetchAll) {\n const fieldIdentifier = node.alias?.value || node.name.value;\n fetchAllFields.add(fieldIdentifier);\n\n // Return a new node without the @fetchAll directive\n return {\n ...node,\n directives: node.directives.filter((dir) => dir.name.value !== FETCH_ALL_DIRECTIVE),\n };\n }\n }\n\n return node;\n },\n });\n\n return {\n document: strippedDocument,\n fetchAllFields,\n };\n}\n\n/**\n * Custom merge function for deep object merging with special handling for lists\n *\n * @param {unknown} target - The target object or value to merge into\n * @param {unknown} source - The source object or value to merge from\n * @returns {unknown} Merged result with preservation of arrays and specific merge logic\n *\n * @remarks\n * Key behaviors:\n * - Preserves existing arrays without merging\n * - Handles null and undefined values\n * - Performs deep merge for nested objects\n * - Prioritizes source values for primitives\n *\n */\nfunction customMerge(target: unknown, source: unknown): unknown {\n if (source == null) return target;\n if (target == null) return source;\n\n // If source is an array, return it, don't merge arrays\n if (isArray(source)) {\n return source;\n }\n\n if (typeof target !== \"object\" || typeof source !== \"object\") {\n return source;\n }\n\n // Manually merge objects to ensure arrays are preserved\n const targetObj = target as Record<string, unknown>;\n const sourceObj = source as Record<string, unknown>;\n const result: Record<string, unknown> = { ...targetObj };\n\n for (const key in sourceObj) {\n if (Object.hasOwn(sourceObj, key)) {\n result[key] = key in result ? customMerge(result[key], sourceObj[key]) : sourceObj[key];\n }\n }\n\n return result;\n}\n\n// Extract all fields that have @fetchAll directive\nfunction extractFetchAllFields(\n document: DocumentNode,\n variables?: Variables,\n fetchAllFields?: Set<string>,\n): ListField[] {\n const fields: ListField[] = [];\n const pathStack: string[] = [];\n\n visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Skip meta fields\n if (node.name.value.startsWith(\"__\")) {\n return;\n }\n\n // Check if this field has pagination arguments (first or skip)\n let firstValue: number | undefined;\n let skipValue: number | undefined;\n const otherArgs: ArgumentNode[] = [];\n\n if (node.arguments) {\n for (const arg of node.arguments) {\n if (arg.name.value === FIRST_ARG) {\n if (arg.value.kind === Kind.INT) {\n firstValue = Number.parseInt(arg.value.value);\n } else if (arg.value.kind === Kind.VARIABLE && variables) {\n const varName = arg.value.name.value;\n const varValue = (variables as Record<string, unknown>)[varName];\n firstValue = typeof varValue === \"number\" ? varValue : undefined;\n }\n } else if (arg.name.value === SKIP_ARG) {\n if (arg.value.kind === Kind.INT) {\n skipValue = Number.parseInt(arg.value.value);\n } else if (arg.value.kind === Kind.VARIABLE && variables) {\n const varName = arg.value.name.value;\n const varValue = (variables as Record<string, unknown>)[varName];\n skipValue = typeof varValue === \"number\" ? varValue : undefined;\n }\n } else {\n otherArgs.push(arg);\n }\n }\n }\n\n // Check if this field has @fetchAll directive\n const fieldIdentifierForDirective = node.alias?.value || node.name.value;\n const hasFetchAllDirective = fetchAllFields?.has(fieldIdentifierForDirective);\n\n if (hasFetchAllDirective) {\n // Do not allow nesting @fetchAll fields\n const parentFetchAllField = fields.find((field) => pathStack.join(\",\").startsWith(field.path.join(\",\")));\n if (parentFetchAllField) {\n throw new Error(\n `Nesting of @fetchAll directive is not supported: ${pathStack.join(\".\")} is a child of ${parentFetchAllField.path.join(\".\")}`,\n );\n }\n fields.push({\n path: [...pathStack],\n fieldName: node.name.value,\n alias: node.alias?.value,\n firstValue: hasFetchAllDirective && (firstValue ?? THE_GRAPH_LIMIT),\n skipValue: hasFetchAllDirective && (skipValue ?? 0),\n otherArgs,\n selections: node.selectionSet?.selections,\n hasFetchAllDirective,\n firstValueIsDefault: hasFetchAllDirective ? firstValue === undefined : false,\n });\n }\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n\n return fields;\n}\n\n// Create a query for a single field with specific pagination\nfunction createSingleFieldQuery(\n document: DocumentNode,\n targetField: ListField,\n skip: number,\n first: number,\n): DocumentNode {\n const targetPath = [...targetField.path];\n const pathStack: string[] = [];\n\n return visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Check if we're on the path to target field\n const onPath = pathStack.every((segment, i) => i >= targetPath.length || segment === targetPath[i]);\n\n if (!onPath) {\n pathStack.pop();\n return null; // Remove fields not on path\n }\n\n // If this is our target field, update pagination\n const isTarget =\n pathStack.length === targetPath.length && pathStack.every((segment, i) => segment === targetPath[i]);\n\n if (isTarget) {\n const newArgs: ArgumentNode[] = [...targetField.otherArgs];\n\n // Add pagination arguments\n newArgs.push(\n {\n kind: Kind.ARGUMENT,\n name: { kind: Kind.NAME, value: FIRST_ARG },\n value: { kind: Kind.INT, value: first.toString() },\n },\n {\n kind: Kind.ARGUMENT,\n name: { kind: Kind.NAME, value: SKIP_ARG },\n value: { kind: Kind.INT, value: skip.toString() },\n },\n );\n\n return { ...node, arguments: newArgs };\n }\n\n return undefined;\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n}\n\n// Create query without list fields\nfunction createNonListQuery(document: DocumentNode, listFields: ListField[]): DocumentNode | null {\n let hasFields = false;\n const pathStack: string[] = [];\n\n const filtered = visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Check if this field is a list field\n const isList = listFields.some(\n (field) =>\n field.path.length === pathStack.length && field.path.every((segment, i) => segment === pathStack[i]),\n );\n\n if (isList) {\n pathStack.pop();\n return null;\n }\n\n hasFields = true;\n return undefined;\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n\n return hasFields ? filtered : null;\n}\n\n// Filter variables to only include used ones\nfunction filterVariables(variables: Variables | undefined, document: DocumentNode): Variables | undefined {\n if (!variables) return undefined;\n\n const usedVariables = new Set<string>();\n\n visit(document, {\n Variable: (node) => {\n usedVariables.add(node.name.value);\n },\n });\n\n const filtered: Variables = {};\n const varsObj = variables as Record<string, unknown>;\n for (const key of usedVariables) {\n if (key in varsObj) {\n (filtered as Record<string, unknown>)[key] = varsObj[key];\n }\n }\n\n return isEmpty(filtered) ? undefined : filtered;\n}\n\n/**\n * Creates a TheGraph client that supports pagination for list fields\n *\n * @param theGraphClient - The GraphQL client to use for requests\n * @returns A TheGraph client that supports pagination for list fields\n * @internal Used internally by createTheGraphClient\n */\nexport function createTheGraphClientWithPagination(theGraphClient: Pick<GraphQLClient, \"request\">) {\n // Execute pagination for a list field\n async function executeListFieldPagination(\n document: DocumentNode,\n variables: Variables | undefined,\n field: ListField,\n ): Promise<unknown[]> {\n const results: unknown[] = [];\n let currentSkip = field.skipValue || 0;\n let hasMore = true;\n\n // For fields with pagination arguments, always attempt to fetch data\n // and continue if we get a full page (indicating more data might exist)\n const batchSize = Math.min(field.firstValue || THE_GRAPH_LIMIT, THE_GRAPH_LIMIT);\n\n while (hasMore) {\n const query = createSingleFieldQuery(document, field, currentSkip, batchSize);\n const existingVariables = filterVariables(variables, query) ?? {};\n const response = await theGraphClient.request(query, {\n ...existingVariables,\n first: batchSize,\n skip: currentSkip,\n });\n\n // Use array path format for es-toolkit's get function\n const data = get(response, field.path) ?? get(response, field.fieldName);\n\n const parentPath = field.path.slice(0, -1);\n const parentData = get(response, parentPath);\n if (isArray(parentData) && parentData.length > 0) {\n throw new Error(\n `Response is an array, but expected a single object for field ${parentPath.join(\".\")}. The @fetchAll directive is not supported inside a query that returns a list of items.`,\n );\n }\n\n if (isArray(data) && data.length > 0) {\n results.push(...data);\n\n // Continue fetching if:\n // 1. We have @fetchAll directive (fetch everything)\n // 2. We have an explicit first value > THE_GRAPH_LIMIT and haven't reached it\n // 3. We have a defaulted first value and got a full batch (treating it as \"no explicit value\")\n // 4. We have no first value and got a full batch\n if (field.hasFetchAllDirective) {\n // With @fetchAll, continue if we got a full batch\n hasMore = data.length === batchSize;\n } else if (field.firstValue && !field.firstValueIsDefault) {\n // With explicit first value (not defaulted), only continue if:\n // - We haven't reached the requested amount yet\n // - We got a full batch (indicating more data might exist)\n hasMore = data.length === batchSize && results.length < field.firstValue;\n } else {\n // When first is not specified or was defaulted (using default batch size),\n // continue if we got a full batch (standard TheGraph pagination behavior)\n hasMore = data.length === batchSize;\n }\n } else {\n hasMore = false;\n }\n\n currentSkip += batchSize;\n }\n\n return results;\n }\n\n return {\n async query<TResult, TVariables extends Variables>(\n documentOrOptions: TadaDocumentNode<TResult, TVariables> | RequestDocument | RequestOptions<TVariables, TResult>,\n variablesRaw?: Omit<TVariables, \"skip\" | \"first\">,\n ): Promise<TResult> {\n let document: TadaDocumentNode<TResult, TVariables> | RequestDocument;\n let variables: Omit<TVariables, \"skip\" | \"first\">;\n\n if (isRequestOptions(documentOrOptions)) {\n document = documentOrOptions.document;\n variables = documentOrOptions.variables as TVariables;\n } else {\n document = documentOrOptions;\n variables = variablesRaw ?? ({} as TVariables);\n }\n\n // First, detect and strip @fetchAll directives\n const { document: processedDocument, fetchAllFields } = stripFetchAllDirective(document);\n\n // Extract all list fields (including those with @fetchAll)\n const listFields = extractFetchAllFields(processedDocument, variables, fetchAllFields);\n\n // If no list fields, execute normally\n if (listFields.length === 0) {\n return theGraphClient.request(processedDocument, variables as Variables);\n }\n\n // Execute paginated queries for all list fields\n const result: Record<string, unknown> = {};\n\n // Sort fields by depth to handle nested fields correctly\n const sortedFields = sortBy(listFields, [(field) => field.path.length]);\n\n // Process list fields in parallel for better performance\n const fieldDataPromises = sortedFields.map(async (field) => ({\n field,\n data: await executeListFieldPagination(processedDocument, variables, field),\n }));\n\n const fieldResults = await Promise.all(fieldDataPromises);\n\n // Set results in order\n for (const { field, data } of fieldResults) {\n // Use array path format for es-toolkit's set function\n set(result, field.path, data);\n }\n\n // Execute non-list fields (single entity queries)\n const nonListQuery = createNonListQuery(processedDocument, listFields);\n\n if (nonListQuery) {\n const nonListResult = await theGraphClient.request(\n nonListQuery,\n filterVariables(variables, nonListQuery) ?? {},\n );\n\n // Merge results, preserving list data\n const merged = customMerge(nonListResult, result);\n return merged as TResult;\n }\n\n return result as TResult;\n },\n } as const;\n}\n\nfunction isRequestOptions(args: unknown): args is RequestOptions<Variables, unknown> {\n return typeof args === \"object\" && args !== null && \"document\" in args && \"variables\" in args;\n}\n","import { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { ensureServer } from \"@settlemint/sdk-utils/runtime\";\nimport { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from \"@settlemint/sdk-utils/validation\";\nimport { type AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport { GraphQLClient } from \"graphql-request\";\nimport { z } from \"zod\";\nimport { createTheGraphClientWithPagination } from \"./utils/pagination.js\";\n\n/**\n * Type definition for GraphQL client configuration options\n */\nexport type RequestConfig = ConstructorParameters<typeof GraphQLClient>[1];\n\n/**\n * Schema for validating client options for the TheGraph client.\n */\nexport const ClientOptionsSchema = z.object({\n instances: z.array(UrlOrPathSchema),\n accessToken: ApplicationAccessTokenSchema.optional(),\n subgraphName: z.string(),\n cache: z.enum([\"default\", \"force-cache\", \"no-cache\", \"no-store\", \"only-if-cached\", \"reload\"]).optional(),\n});\n\n/**\n * Type definition for client options derived from the ClientOptionsSchema\n */\nexport type ClientOptions = z.infer<typeof ClientOptionsSchema>;\n\n/**\n * Constructs the full URL for TheGraph GraphQL API based on the provided options\n *\n * @param options - The client options for configuring TheGraph client\n * @returns The complete GraphQL API URL as a string\n * @throws Will throw an error if no matching instance is found for the specified subgraph\n */\nfunction getFullUrl(options: ClientOptions): string {\n const instance = options.instances.find((instance) => instance.endsWith(`/${options.subgraphName}`));\n if (!instance) {\n throw new Error(`Instance for subgraph ${options.subgraphName} not found`);\n }\n return new URL(instance).toString();\n}\n\n/**\n * Creates a TheGraph GraphQL client with proper type safety using gql.tada\n *\n * @param options - Configuration options for the client including instance URLs,\n * access token and subgraph name\n * @param clientOptions - Optional GraphQL client configuration options\n * @returns An object containing:\n * - client: The configured GraphQL client instance\n * - graphql: The initialized gql.tada function for type-safe queries\n * @throws Will throw an error if the options fail validation against ClientOptionsSchema\n * @example\n * import { createTheGraphClient } from '@settlemint/sdk-thegraph';\n * import type { introspection } from '@schemas/the-graph-env-kits';\n * import { createLogger, requestLogger } from '@settlemint/sdk-utils/logging';\n *\n * const logger = createLogger();\n *\n * const { client, graphql } = createTheGraphClient<{\n * introspection: introspection;\n * disableMasking: true;\n * scalars: {\n * Bytes: string;\n * Int8: string;\n * BigInt: string;\n * BigDecimal: string;\n * Timestamp: string;\n * };\n * }>({\n * instances: JSON.parse(process.env.SETTLEMINT_THEGRAPH_SUBGRAPHS_ENDPOINTS || '[]'),\n * accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,\n * subgraphName: 'kits'\n * }, {\n * fetch: requestLogger(logger, \"the-graph-kits\", fetch) as typeof fetch,\n * });\n *\n * // Making GraphQL queries\n * const query = graphql(`\n * query SearchAssets {\n * assets @fetchAll {\n * id\n * name\n * symbol\n * }\n * }\n * `);\n *\n * const result = await client.request(query);\n */\nexport function createTheGraphClient<const Setup extends AbstractSetupSchema>(\n options: ClientOptions,\n clientOptions?: RequestConfig,\n): {\n client: GraphQLClient;\n graphql: initGraphQLTada<Setup>;\n} {\n ensureServer();\n const validatedOptions = validate(ClientOptionsSchema, options);\n const graphql = initGraphQLTada<Setup>();\n const fullUrl = getFullUrl(validatedOptions);\n\n const client = new GraphQLClient(fullUrl, {\n ...clientOptions,\n headers: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n });\n const originalRequest = client.request.bind(client);\n const paginatedClient = createTheGraphClientWithPagination({\n request: originalRequest,\n });\n client.request = paginatedClient.query;\n return {\n client,\n graphql,\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport { createTheGraphClientWithPagination } from \"./utils/pagination.js\";\n"],"mappings":";;;;;;;;;;;;AAOA,MAAM,kBAAkB;AACxB,MAAM,YAAY;AAClB,MAAM,WAAW;AACjB,MAAM,sBAAsB;;;;;;;;;;;;;AA0B5B,SAAS,uBAAuBA,UAG9B;CACA,MAAM,iBAAiB,IAAI;CAC3B,MAAM,sBAAsB,aAAa,WAAW,MAAM,SAAS,GAAG;CACtE,MAAM,mBAAmB,MAAM,cAAc,EAC3C,MAAM,MAAM;AAEV,MAAI,KAAK,cAAc,KAAK,WAAW,SAAS,GAAG;GACjD,MAAM,cAAc,KAAK,WAAW,KAAK,CAAC,QAAQ,IAAI,KAAK,UAAU,oBAAoB;AAEzF,OAAI,aAAa;IACf,MAAM,kBAAkB,KAAK,OAAO,SAAS,KAAK,KAAK;AACvD,mBAAe,IAAI,gBAAgB;AAGnC,WAAO;KACL,GAAG;KACH,YAAY,KAAK,WAAW,OAAO,CAAC,QAAQ,IAAI,KAAK,UAAU,oBAAoB;IACpF;GACF;EACF;AAED,SAAO;CACR,EACF,EAAC;AAEF,QAAO;EACL,UAAU;EACV;CACD;AACF;;;;;;;;;;;;;;;;AAiBD,SAAS,YAAYC,QAAiBC,QAA0B;AAC9D,KAAI,UAAU,KAAM,QAAO;AAC3B,KAAI,UAAU,KAAM,QAAO;AAG3B,KAAI,QAAQ,OAAO,EAAE;AACnB,SAAO;CACR;AAED,YAAW,WAAW,mBAAmB,WAAW,UAAU;AAC5D,SAAO;CACR;CAGD,MAAM,YAAY;CAClB,MAAM,YAAY;CAClB,MAAMC,SAAkC,EAAE,GAAG,UAAW;AAExD,MAAK,MAAM,OAAO,WAAW;AAC3B,MAAI,OAAO,OAAO,WAAW,IAAI,EAAE;AACjC,UAAO,OAAO,OAAO,SAAS,YAAY,OAAO,MAAM,UAAU,KAAK,GAAG,UAAU;EACpF;CACF;AAED,QAAO;AACR;AAGD,SAAS,sBACPC,UACAC,WACAC,gBACa;CACb,MAAMC,SAAsB,CAAE;CAC9B,MAAMC,YAAsB,CAAE;AAE9B,OAAM,UAAU,EACd,OAAO;EACL,OAAO,CAAC,SAAS;GACf,MAAM,kBAAkB,KAAK,OAAO,SAAS,KAAK,KAAK;AACvD,aAAU,KAAK,gBAAgB;AAG/B,OAAI,KAAK,KAAK,MAAM,WAAW,KAAK,EAAE;AACpC;GACD;GAGD,IAAIC;GACJ,IAAIC;GACJ,MAAMC,YAA4B,CAAE;AAEpC,OAAI,KAAK,WAAW;AAClB,SAAK,MAAM,OAAO,KAAK,WAAW;AAChC,SAAI,IAAI,KAAK,UAAU,WAAW;AAChC,UAAI,IAAI,MAAM,SAAS,KAAK,KAAK;AAC/B,oBAAa,OAAO,SAAS,IAAI,MAAM,MAAM;MAC9C,WAAU,IAAI,MAAM,SAAS,KAAK,YAAY,WAAW;OACxD,MAAM,UAAU,IAAI,MAAM,KAAK;OAC/B,MAAM,WAAY,UAAsC;AACxD,2BAAoB,aAAa,WAAW,WAAW;MACxD;KACF,WAAU,IAAI,KAAK,UAAU,UAAU;AACtC,UAAI,IAAI,MAAM,SAAS,KAAK,KAAK;AAC/B,mBAAY,OAAO,SAAS,IAAI,MAAM,MAAM;MAC7C,WAAU,IAAI,MAAM,SAAS,KAAK,YAAY,WAAW;OACxD,MAAM,UAAU,IAAI,MAAM,KAAK;OAC/B,MAAM,WAAY,UAAsC;AACxD,0BAAmB,aAAa,WAAW,WAAW;MACvD;KACF,OAAM;AACL,gBAAU,KAAK,IAAI;KACpB;IACF;GACF;GAGD,MAAM,8BAA8B,KAAK,OAAO,SAAS,KAAK,KAAK;GACnE,MAAM,uBAAuB,gBAAgB,IAAI,4BAA4B;AAE7E,OAAI,sBAAsB;IAExB,MAAM,sBAAsB,OAAO,KAAK,CAAC,UAAU,UAAU,KAAK,IAAI,CAAC,WAAW,MAAM,KAAK,KAAK,IAAI,CAAC,CAAC;AACxG,QAAI,qBAAqB;AACvB,WAAM,IAAI,OACP,mDAAmD,UAAU,KAAK,IAAI,CAAC,iBAAiB,oBAAoB,KAAK,KAAK,IAAI,CAAC;IAE/H;AACD,WAAO,KAAK;KACV,MAAM,CAAC,GAAG,SAAU;KACpB,WAAW,KAAK,KAAK;KACrB,OAAO,KAAK,OAAO;KACnB,YAAY,yBAAyB,cAAc;KACnD,WAAW,yBAAyB,aAAa;KACjD;KACA,YAAY,KAAK,cAAc;KAC/B;KACA,qBAAqB,uBAAuB,eAAe,YAAY;IACxE,EAAC;GACH;EACF;EACD,OAAO,MAAM;AACX,aAAU,KAAK;EAChB;CACF,EACF,EAAC;AAEF,QAAO;AACR;AAGD,SAAS,uBACPP,UACAQ,aACAC,MACAC,OACc;CACd,MAAM,aAAa,CAAC,GAAG,YAAY,IAAK;CACxC,MAAMN,YAAsB,CAAE;AAE9B,QAAO,MAAM,UAAU,EACrB,OAAO;EACL,OAAO,CAAC,SAAS;GACf,MAAM,kBAAkB,KAAK,OAAO,SAAS,KAAK,KAAK;AACvD,aAAU,KAAK,gBAAgB;GAG/B,MAAM,SAAS,UAAU,MAAM,CAAC,SAAS,MAAM,KAAK,WAAW,UAAU,YAAY,WAAW,GAAG;AAEnG,QAAK,QAAQ;AACX,cAAU,KAAK;AACf,WAAO;GACR;GAGD,MAAM,WACJ,UAAU,WAAW,WAAW,UAAU,UAAU,MAAM,CAAC,SAAS,MAAM,YAAY,WAAW,GAAG;AAEtG,OAAI,UAAU;IACZ,MAAMO,UAA0B,CAAC,GAAG,YAAY,SAAU;AAG1D,YAAQ,KACN;KACE,MAAM,KAAK;KACX,MAAM;MAAE,MAAM,KAAK;MAAM,OAAO;KAAW;KAC3C,OAAO;MAAE,MAAM,KAAK;MAAK,OAAO,MAAM,UAAU;KAAE;IACnD,GACD;KACE,MAAM,KAAK;KACX,MAAM;MAAE,MAAM,KAAK;MAAM,OAAO;KAAU;KAC1C,OAAO;MAAE,MAAM,KAAK;MAAK,OAAO,KAAK,UAAU;KAAE;IAClD,EACF;AAED,WAAO;KAAE,GAAG;KAAM,WAAW;IAAS;GACvC;AAED,UAAO;EACR;EACD,OAAO,MAAM;AACX,aAAU,KAAK;EAChB;CACF,EACF,EAAC;AACH;AAGD,SAAS,mBAAmBX,UAAwBY,YAA8C;CAChG,IAAI,YAAY;CAChB,MAAMR,YAAsB,CAAE;CAE9B,MAAM,WAAW,MAAM,UAAU,EAC/B,OAAO;EACL,OAAO,CAAC,SAAS;GACf,MAAM,kBAAkB,KAAK,OAAO,SAAS,KAAK,KAAK;AACvD,aAAU,KAAK,gBAAgB;GAG/B,MAAM,SAAS,WAAW,KACxB,CAAC,UACC,MAAM,KAAK,WAAW,UAAU,UAAU,MAAM,KAAK,MAAM,CAAC,SAAS,MAAM,YAAY,UAAU,GAAG,CACvG;AAED,OAAI,QAAQ;AACV,cAAU,KAAK;AACf,WAAO;GACR;AAED,eAAY;AACZ,UAAO;EACR;EACD,OAAO,MAAM;AACX,aAAU,KAAK;EAChB;CACF,EACF,EAAC;AAEF,QAAO,YAAY,WAAW;AAC/B;AAGD,SAAS,gBAAgBS,WAAkCb,UAA+C;AACxG,MAAK,UAAW,QAAO;CAEvB,MAAM,gBAAgB,IAAI;AAE1B,OAAM,UAAU,EACd,UAAU,CAAC,SAAS;AAClB,gBAAc,IAAI,KAAK,KAAK,MAAM;CACnC,EACF,EAAC;CAEF,MAAMc,WAAsB,CAAE;CAC9B,MAAM,UAAU;AAChB,MAAK,MAAM,OAAO,eAAe;AAC/B,MAAI,OAAO,SAAS;AAClB,GAAC,SAAqC,OAAO,QAAQ;EACtD;CACF;AAED,QAAO,QAAQ,SAAS,GAAG,YAAY;AACxC;;;;;;;;AASD,SAAgB,mCAAmCC,gBAAgD;CAEjG,eAAe,2BACbf,UACAa,WACAG,OACoB;EACpB,MAAMC,UAAqB,CAAE;EAC7B,IAAI,cAAc,MAAM,aAAa;EACrC,IAAI,UAAU;EAId,MAAM,YAAY,KAAK,IAAI,MAAM,cAAc,iBAAiB,gBAAgB;AAEhF,SAAO,SAAS;GACd,MAAM,QAAQ,uBAAuB,UAAU,OAAO,aAAa,UAAU;GAC7E,MAAM,oBAAoB,gBAAgB,WAAW,MAAM,IAAI,CAAE;GACjE,MAAM,WAAW,MAAM,eAAe,QAAQ,OAAO;IACnD,GAAG;IACH,OAAO;IACP,MAAM;GACP,EAAC;GAGF,MAAM,OAAO,IAAI,UAAU,MAAM,KAAK,IAAI,IAAI,UAAU,MAAM,UAAU;GAExE,MAAM,aAAa,MAAM,KAAK,MAAM,IAAI,EAAE;GAC1C,MAAM,aAAa,IAAI,UAAU,WAAW;AAC5C,OAAI,QAAQ,WAAW,IAAI,WAAW,SAAS,GAAG;AAChD,UAAM,IAAI,OACP,+DAA+D,WAAW,KAAK,IAAI,CAAC;GAExF;AAED,OAAI,QAAQ,KAAK,IAAI,KAAK,SAAS,GAAG;AACpC,YAAQ,KAAK,GAAG,KAAK;AAOrB,QAAI,MAAM,sBAAsB;AAE9B,eAAU,KAAK,WAAW;IAC3B,WAAU,MAAM,eAAe,MAAM,qBAAqB;AAIzD,eAAU,KAAK,WAAW,aAAa,QAAQ,SAAS,MAAM;IAC/D,OAAM;AAGL,eAAU,KAAK,WAAW;IAC3B;GACF,OAAM;AACL,cAAU;GACX;AAED,kBAAe;EAChB;AAED,SAAO;CACR;AAED,QAAO,EACL,MAAM,MACJC,mBACAC,cACkB;EAClB,IAAIC;EACJ,IAAIC;AAEJ,MAAI,iBAAiB,kBAAkB,EAAE;AACvC,cAAW,kBAAkB;AAC7B,eAAY,kBAAkB;EAC/B,OAAM;AACL,cAAW;AACX,eAAY,gBAAiB,CAAE;EAChC;EAGD,MAAM,EAAE,UAAU,mBAAmB,gBAAgB,GAAG,uBAAuB,SAAS;EAGxF,MAAM,aAAa,sBAAsB,mBAAmB,WAAW,eAAe;AAGtF,MAAI,WAAW,WAAW,GAAG;AAC3B,UAAO,eAAe,QAAQ,mBAAmB,UAAuB;EACzE;EAGD,MAAMtB,SAAkC,CAAE;EAG1C,MAAM,eAAe,OAAO,YAAY,CAAC,CAAC,UAAU,MAAM,KAAK,MAAO,EAAC;EAGvE,MAAM,oBAAoB,aAAa,IAAI,OAAO,WAAW;GAC3D;GACA,MAAM,MAAM,2BAA2B,mBAAmB,WAAW,MAAM;EAC5E,GAAE;EAEH,MAAM,eAAe,MAAM,QAAQ,IAAI,kBAAkB;AAGzD,OAAK,MAAM,EAAE,OAAO,MAAM,IAAI,cAAc;AAE1C,OAAI,QAAQ,MAAM,MAAM,KAAK;EAC9B;EAGD,MAAM,eAAe,mBAAmB,mBAAmB,WAAW;AAEtE,MAAI,cAAc;GAChB,MAAM,gBAAgB,MAAM,eAAe,QACzC,cACA,gBAAgB,WAAW,aAAa,IAAI,CAAE,EAC/C;GAGD,MAAM,SAAS,YAAY,eAAe,OAAO;AACjD,UAAO;EACR;AAED,SAAO;CACR,EACF;AACF;AAED,SAAS,iBAAiBuB,MAA2D;AACnF,eAAc,SAAS,YAAY,SAAS,QAAQ,cAAc,QAAQ,eAAe;AAC1F;;;;;;;AClbD,MAAa,sBAAsB,EAAE,OAAO;CAC1C,WAAW,EAAE,MAAM,gBAAgB;CACnC,aAAa,6BAA6B,UAAU;CACpD,cAAc,EAAE,QAAQ;CACxB,OAAO,EAAE,KAAK;EAAC;EAAW;EAAe;EAAY;EAAY;EAAkB;CAAS,EAAC,CAAC,UAAU;AACzG,EAAC;;;;;;;;AAcF,SAAS,WAAWC,SAAgC;CAClD,MAAM,WAAW,QAAQ,UAAU,KAAK,CAACC,eAAa,WAAS,UAAU,GAAG,QAAQ,aAAa,EAAE,CAAC;AACpG,MAAK,UAAU;AACb,QAAM,IAAI,OAAO,wBAAwB,QAAQ,aAAa;CAC/D;AACD,QAAO,IAAI,IAAI,UAAU,UAAU;AACpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDD,SAAgB,qBACdD,SACAE,eAIA;AACA,eAAc;CACd,MAAM,mBAAmB,SAAS,qBAAqB,QAAQ;CAC/D,MAAM,UAAU,iBAAwB;CACxC,MAAM,UAAU,WAAW,iBAAiB;CAE5C,MAAM,SAAS,IAAI,cAAc,SAAS;EACxC,GAAG;EACH,SAAS,cAAc,eAAe,SAAS,EAAE,gBAAgB,iBAAiB,YAAa,EAAC;CACjG;CACD,MAAM,kBAAkB,OAAO,QAAQ,KAAK,OAAO;CACnD,MAAM,kBAAkB,mCAAmC,EACzD,SAAS,gBACV,EAAC;AACF,QAAO,UAAU,gBAAgB;AACjC,QAAO;EACL;EACA;CACD;AACF"}
|
|
1
|
+
{"version":3,"file":"thegraph.js","names":["document: DocumentNode","target: unknown","source: unknown","result: Record<string, unknown>","variables?: Variables","fetchAllFields?: Set<string>","fields: ListField[]","pathStack: string[]","firstValue: number | undefined","skipValue: number | undefined","otherArgs: ArgumentNode[]","targetField: ListField","skip: number","first: number","newArgs: ArgumentNode[]","listFields: ListField[]","variables: Variables | undefined","filtered: Variables","theGraphClient: Pick<GraphQLClient, \"request\">","field: ListField","results: unknown[]","document: TadaDocumentNode<TResult, TVariables>","variables: Omit<TVariables, \"skip\" | \"first\">","options: ClientOptions","instance","clientOptions?: RequestConfig"],"sources":["../src/utils/pagination.ts","../src/thegraph.ts"],"sourcesContent":["import { sortBy } from \"es-toolkit\";\nimport { get, isArray, isEmpty, set } from \"es-toolkit/compat\";\nimport type { TadaDocumentNode } from \"gql.tada\";\nimport { type ArgumentNode, type DocumentNode, Kind, type SelectionNode, visit } from \"graphql\";\nimport type { GraphQLClient, Variables } from \"graphql-request\";\n\n// Constants for TheGraph limits\nconst THE_GRAPH_LIMIT = 500;\nconst FIRST_ARG = \"first\";\nconst SKIP_ARG = \"skip\";\nconst FETCH_ALL_DIRECTIVE = \"fetchAll\";\n\ninterface ListField {\n path: string[];\n fieldName: string;\n alias?: string;\n hasFirstArg: boolean;\n firstValue?: number;\n skipValue?: number;\n otherArgs: ArgumentNode[];\n selections?: ReadonlyArray<SelectionNode>;\n hasFetchAllDirective?: boolean;\n firstValueIsDefault?: boolean; // Track if first value was defaulted\n}\n\n/**\n * Detects and strips @fetchAll directives from a GraphQL document\n *\n * @param {DocumentNode} document - The GraphQL document to process\n * @returns {Object} Processed document and list of fields with @fetchAll\n *\n * @remarks\n * This function:\n * - Identifies fields decorated with @fetchAll directive\n * - Removes the directive from the AST (The Graph doesn't recognize it)\n * - Returns both the cleaned document and a list of fields to auto-paginate\n */\nfunction stripFetchAllDirective(document: DocumentNode): {\n document: DocumentNode;\n fetchAllFields: Set<string>;\n} {\n const fetchAllFields = new Set<string>();\n\n const strippedDocument = visit(document, {\n Field(node) {\n // Check if this field has the @fetchAll directive\n if (node.directives && node.directives.length > 0) {\n const hasFetchAll = node.directives.some((dir) => dir.name.value === FETCH_ALL_DIRECTIVE);\n\n if (hasFetchAll) {\n const fieldIdentifier = node.alias?.value || node.name.value;\n fetchAllFields.add(fieldIdentifier);\n\n // Return a new node without the @fetchAll directive\n return {\n ...node,\n directives: node.directives.filter((dir) => dir.name.value !== FETCH_ALL_DIRECTIVE),\n };\n }\n }\n\n return node;\n },\n });\n\n return {\n document: strippedDocument,\n fetchAllFields,\n };\n}\n\n/**\n * Custom merge function for deep object merging with special handling for lists\n *\n * @param {unknown} target - The target object or value to merge into\n * @param {unknown} source - The source object or value to merge from\n * @returns {unknown} Merged result with preservation of arrays and specific merge logic\n *\n * @remarks\n * Key behaviors:\n * - Preserves existing arrays without merging\n * - Handles null and undefined values\n * - Performs deep merge for nested objects\n * - Prioritizes source values for primitives\n *\n */\nfunction customMerge(target: unknown, source: unknown): unknown {\n if (source == null) return target;\n if (target == null) return source;\n\n // If source is an array, return it, don't merge arrays\n if (isArray(source)) {\n return source;\n }\n\n if (typeof target !== \"object\" || typeof source !== \"object\") {\n return source;\n }\n\n // Manually merge objects to ensure arrays are preserved\n const targetObj = target as Record<string, unknown>;\n const sourceObj = source as Record<string, unknown>;\n const result: Record<string, unknown> = { ...targetObj };\n\n for (const key in sourceObj) {\n if (Object.hasOwn(sourceObj, key)) {\n result[key] = key in result ? customMerge(result[key], sourceObj[key]) : sourceObj[key];\n }\n }\n\n return result;\n}\n\n// Extract all fields that have @fetchAll directive\nfunction extractFetchAllFields(\n document: DocumentNode,\n variables?: Variables,\n fetchAllFields?: Set<string>,\n): ListField[] {\n const fields: ListField[] = [];\n const pathStack: string[] = [];\n\n visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Skip meta fields\n if (node.name.value.startsWith(\"__\")) {\n return;\n }\n\n // Check if this field has pagination arguments (first or skip)\n let hasFirstArg = false;\n let hasSkipArg = false;\n let firstValue: number | undefined;\n let skipValue: number | undefined;\n let firstValueIsDefault = false;\n const otherArgs: ArgumentNode[] = [];\n\n if (node.arguments) {\n for (const arg of node.arguments) {\n if (arg.name.value === FIRST_ARG) {\n hasFirstArg = true;\n if (arg.value.kind === Kind.INT) {\n firstValue = Number.parseInt(arg.value.value);\n } else if (arg.value.kind === Kind.VARIABLE && variables) {\n const varName = arg.value.name.value;\n const varValue = (variables as Record<string, unknown>)[varName];\n firstValue = typeof varValue === \"number\" ? varValue : undefined;\n // If variable is defined in query but not passed in input, check if it's a standard pagination variable\n if (firstValue === undefined && varName === arg.value.name.value) {\n firstValue = THE_GRAPH_LIMIT; // Default to THE_GRAPH_LIMIT\n firstValueIsDefault = true; // Mark that this was defaulted\n }\n }\n } else if (arg.name.value === SKIP_ARG) {\n hasSkipArg = true;\n if (arg.value.kind === Kind.INT) {\n skipValue = Number.parseInt(arg.value.value);\n } else if (arg.value.kind === Kind.VARIABLE && variables) {\n const varName = arg.value.name.value;\n const varValue = (variables as Record<string, unknown>)[varName];\n skipValue = typeof varValue === \"number\" ? varValue : undefined;\n // If variable is defined in query but not passed in input, check if it's a standard pagination variable\n if (skipValue === undefined && varName === arg.value.name.value) {\n skipValue = 0; // Default to 0\n }\n }\n } else {\n otherArgs.push(arg);\n }\n }\n }\n\n // Check if this field has @fetchAll directive\n const fieldIdentifierForDirective = node.alias?.value || node.name.value;\n const hasFetchAllDirective = fetchAllFields?.has(fieldIdentifierForDirective);\n\n if (hasFetchAllDirective) {\n // Do not allow nesting @fetchAll fields\n const parentFetchAllField = fields.find((field) => pathStack.join(\",\").startsWith(field.path.join(\",\")));\n if (parentFetchAllField) {\n throw new Error(\n `Nesting of @fetchAll directive is not supported: ${pathStack.join(\".\")} is a child of ${parentFetchAllField.path.join(\".\")}`,\n );\n }\n fields.push({\n path: [...pathStack],\n fieldName: node.name.value,\n alias: node.alias?.value,\n hasFirstArg,\n firstValue: hasFetchAllDirective && !hasFirstArg ? THE_GRAPH_LIMIT : firstValue,\n skipValue: hasFetchAllDirective && !hasSkipArg ? 0 : skipValue,\n otherArgs,\n selections: node.selectionSet?.selections,\n hasFetchAllDirective,\n firstValueIsDefault,\n });\n }\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n\n return fields;\n}\n\n// Create a query for a single field with specific pagination\nfunction createSingleFieldQuery(\n document: DocumentNode,\n targetField: ListField,\n skip: number,\n first: number,\n): DocumentNode {\n const targetPath = [...targetField.path];\n const pathStack: string[] = [];\n\n return visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Check if we're on the path to target field\n const onPath = pathStack.every((segment, i) => i >= targetPath.length || segment === targetPath[i]);\n\n if (!onPath) {\n pathStack.pop();\n return null; // Remove fields not on path\n }\n\n // If this is our target field, update pagination\n const isTarget =\n pathStack.length === targetPath.length && pathStack.every((segment, i) => segment === targetPath[i]);\n\n if (isTarget) {\n const newArgs: ArgumentNode[] = [...targetField.otherArgs];\n\n // Add pagination arguments\n newArgs.push(\n {\n kind: Kind.ARGUMENT,\n name: { kind: Kind.NAME, value: FIRST_ARG },\n value: { kind: Kind.INT, value: first.toString() },\n },\n {\n kind: Kind.ARGUMENT,\n name: { kind: Kind.NAME, value: SKIP_ARG },\n value: { kind: Kind.INT, value: skip.toString() },\n },\n );\n\n return { ...node, arguments: newArgs };\n }\n\n return undefined;\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n}\n\n// Create query without list fields\nfunction createNonListQuery(document: DocumentNode, listFields: ListField[]): DocumentNode | null {\n let hasFields = false;\n const pathStack: string[] = [];\n\n const filtered = visit(document, {\n Field: {\n enter: (node) => {\n const fieldIdentifier = node.alias?.value || node.name.value;\n pathStack.push(fieldIdentifier);\n\n // Check if this field is a list field\n const isList = listFields.some(\n (field) =>\n field.path.length === pathStack.length && field.path.every((segment, i) => segment === pathStack[i]),\n );\n\n if (isList) {\n pathStack.pop();\n return null;\n }\n\n hasFields = true;\n return undefined;\n },\n leave: () => {\n pathStack.pop();\n },\n },\n });\n\n return hasFields ? filtered : null;\n}\n\n// Filter variables to only include used ones\nfunction filterVariables(variables: Variables | undefined, document: DocumentNode): Variables | undefined {\n if (!variables) return undefined;\n\n const usedVariables = new Set<string>();\n\n visit(document, {\n Variable: (node) => {\n usedVariables.add(node.name.value);\n },\n });\n\n const filtered: Variables = {};\n const varsObj = variables as Record<string, unknown>;\n for (const key of usedVariables) {\n if (key in varsObj) {\n (filtered as Record<string, unknown>)[key] = varsObj[key];\n }\n }\n\n return isEmpty(filtered) ? undefined : filtered;\n}\n\n/**\n * Creates a TheGraph client that supports pagination for list fields\n *\n * @param theGraphClient - The GraphQL client to use for requests\n * @returns A TheGraph client that supports pagination for list fields\n * @internal Used internally by createTheGraphClient\n */\nexport function createTheGraphClientWithPagination(theGraphClient: Pick<GraphQLClient, \"request\">) {\n // Execute pagination for a list field\n async function executeListFieldPagination(\n document: DocumentNode,\n variables: Variables | undefined,\n field: ListField,\n ): Promise<unknown[]> {\n const results: unknown[] = [];\n let currentSkip = field.skipValue || 0;\n let hasMore = true;\n\n // For fields with pagination arguments, always attempt to fetch data\n // and continue if we get a full page (indicating more data might exist)\n const batchSize = Math.min(field.firstValue || THE_GRAPH_LIMIT, THE_GRAPH_LIMIT);\n\n while (hasMore) {\n const query = createSingleFieldQuery(document, field, currentSkip, batchSize);\n const existingVariables = filterVariables(variables, query) ?? {};\n const response = await theGraphClient.request(query, {\n ...existingVariables,\n first: batchSize,\n skip: currentSkip,\n });\n\n // Use array path format for es-toolkit's get function\n const data = get(response, field.path) ?? get(response, field.fieldName);\n\n const parentPath = field.path.slice(0, -1);\n const parentData = get(response, parentPath);\n if (isArray(parentData) && parentData.length > 0) {\n throw new Error(\n `Response is an array, but expected a single object for field ${parentPath.join(\".\")}. The @fetchAll directive is not supported inside a query that returns a list of items.`,\n );\n }\n\n if (isArray(data) && data.length > 0) {\n results.push(...data);\n\n // Continue fetching if:\n // 1. We have @fetchAll directive (fetch everything)\n // 2. We have an explicit first value > THE_GRAPH_LIMIT and haven't reached it\n // 3. We have a defaulted first value and got a full batch (treating it as \"no explicit value\")\n // 4. We have no first value and got a full batch\n if (field.hasFetchAllDirective) {\n // With @fetchAll, continue if we got a full batch\n hasMore = data.length === batchSize;\n } else if (field.firstValue && !field.firstValueIsDefault) {\n // With explicit first value (not defaulted), only continue if:\n // - We haven't reached the requested amount yet\n // - We got a full batch (indicating more data might exist)\n hasMore = data.length === batchSize && results.length < field.firstValue;\n } else {\n // When first is not specified or was defaulted (using default batch size),\n // continue if we got a full batch (standard TheGraph pagination behavior)\n hasMore = data.length === batchSize;\n }\n } else {\n hasMore = false;\n }\n\n currentSkip += batchSize;\n }\n\n return results;\n }\n\n return {\n async query<TResult, TVariables extends Variables>(\n document: TadaDocumentNode<TResult, TVariables>,\n variables: Omit<TVariables, \"skip\" | \"first\">,\n ): Promise<TResult> {\n // First, detect and strip @fetchAll directives\n const { document: processedDocument, fetchAllFields } = stripFetchAllDirective(document);\n\n // Extract all list fields (including those with @fetchAll)\n const listFields = extractFetchAllFields(processedDocument, variables, fetchAllFields);\n\n // If no list fields, execute normally\n if (listFields.length === 0) {\n return theGraphClient.request(processedDocument, variables as Variables);\n }\n\n // Execute paginated queries for all list fields\n const result: Record<string, unknown> = {};\n\n // Sort fields by depth to handle nested fields correctly\n const sortedFields = sortBy(listFields, [(field) => field.path.length]);\n\n // Process list fields in parallel for better performance\n const fieldDataPromises = sortedFields.map(async (field) => ({\n field,\n data: await executeListFieldPagination(processedDocument, variables, field),\n }));\n\n const fieldResults = await Promise.all(fieldDataPromises);\n\n // Set results in order\n for (const { field, data } of fieldResults) {\n // Use array path format for es-toolkit's set function\n set(result, field.path, data);\n }\n\n // Execute non-list fields (single entity queries)\n const nonListQuery = createNonListQuery(processedDocument, listFields);\n\n if (nonListQuery) {\n const nonListResult = await theGraphClient.request(\n nonListQuery,\n filterVariables(variables, nonListQuery) ?? {},\n );\n\n // Merge results, preserving list data\n const merged = customMerge(nonListResult, result);\n return merged as TResult;\n }\n\n return result as TResult;\n },\n } as const;\n}\n","import { appendHeaders } from \"@settlemint/sdk-utils/http\";\nimport { ensureServer } from \"@settlemint/sdk-utils/runtime\";\nimport { ApplicationAccessTokenSchema, UrlOrPathSchema, validate } from \"@settlemint/sdk-utils/validation\";\nimport { type AbstractSetupSchema, initGraphQLTada } from \"gql.tada\";\nimport { GraphQLClient } from \"graphql-request\";\nimport { z } from \"zod\";\nimport { createTheGraphClientWithPagination } from \"./utils/pagination.js\";\n\n/**\n * Type definition for GraphQL client configuration options\n */\nexport type RequestConfig = ConstructorParameters<typeof GraphQLClient>[1];\n\n/**\n * Schema for validating client options for the TheGraph client.\n */\nexport const ClientOptionsSchema = z.object({\n instances: z.array(UrlOrPathSchema),\n accessToken: ApplicationAccessTokenSchema.optional(),\n subgraphName: z.string(),\n cache: z.enum([\"default\", \"force-cache\", \"no-cache\", \"no-store\", \"only-if-cached\", \"reload\"]).optional(),\n});\n\n/**\n * Type definition for client options derived from the ClientOptionsSchema\n */\nexport type ClientOptions = z.infer<typeof ClientOptionsSchema>;\n\n/**\n * Constructs the full URL for TheGraph GraphQL API based on the provided options\n *\n * @param options - The client options for configuring TheGraph client\n * @returns The complete GraphQL API URL as a string\n * @throws Will throw an error if no matching instance is found for the specified subgraph\n */\nfunction getFullUrl(options: ClientOptions): string {\n const instance = options.instances.find((instance) => instance.endsWith(`/${options.subgraphName}`));\n if (!instance) {\n throw new Error(`Instance for subgraph ${options.subgraphName} not found`);\n }\n return new URL(instance).toString();\n}\n\n/**\n * Creates a TheGraph GraphQL client with proper type safety using gql.tada\n *\n * @param options - Configuration options for the client including instance URLs,\n * access token and subgraph name\n * @param clientOptions - Optional GraphQL client configuration options\n * @returns An object containing:\n * - client: The configured GraphQL client instance\n * - graphql: The initialized gql.tada function for type-safe queries\n * @throws Will throw an error if the options fail validation against ClientOptionsSchema\n * @example\n * import { createTheGraphClient } from '@settlemint/sdk-thegraph';\n * import type { introspection } from '@schemas/the-graph-env-kits';\n * import { createLogger, requestLogger } from '@settlemint/sdk-utils/logging';\n *\n * const logger = createLogger();\n *\n * const { client, graphql } = createTheGraphClient<{\n * introspection: introspection;\n * disableMasking: true;\n * scalars: {\n * Bytes: string;\n * Int8: string;\n * BigInt: string;\n * BigDecimal: string;\n * Timestamp: string;\n * };\n * }>({\n * instances: JSON.parse(process.env.SETTLEMINT_THEGRAPH_SUBGRAPHS_ENDPOINTS || '[]'),\n * accessToken: process.env.SETTLEMINT_ACCESS_TOKEN,\n * subgraphName: 'kits'\n * }, {\n * fetch: requestLogger(logger, \"the-graph-kits\", fetch) as typeof fetch,\n * });\n *\n * // Making GraphQL queries\n * const query = graphql(`\n * query SearchAssets {\n * assets @fetchAll {\n * id\n * name\n * symbol\n * }\n * }\n * `);\n *\n * const result = await client.request(query);\n */\nexport function createTheGraphClient<const Setup extends AbstractSetupSchema>(\n options: ClientOptions,\n clientOptions?: RequestConfig,\n): {\n client: GraphQLClient;\n graphql: initGraphQLTada<Setup>;\n} {\n ensureServer();\n const validatedOptions = validate(ClientOptionsSchema, options);\n const graphql = initGraphQLTada<Setup>();\n const fullUrl = getFullUrl(validatedOptions);\n\n const client = new GraphQLClient(fullUrl, {\n ...clientOptions,\n headers: appendHeaders(clientOptions?.headers, { \"x-auth-token\": validatedOptions.accessToken }),\n });\n const paginatedClient = createTheGraphClientWithPagination(client);\n client.request = paginatedClient.query as typeof client.request;\n return {\n client,\n graphql,\n };\n}\n\nexport type { FragmentOf, ResultOf, VariablesOf } from \"gql.tada\";\nexport { readFragment } from \"gql.tada\";\nexport { createTheGraphClientWithPagination } from \"./utils/pagination.js\";\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@settlemint/sdk-thegraph",
|
|
3
3
|
"description": "TheGraph integration module for SettleMint SDK, enabling querying and indexing of blockchain data through subgraphs",
|
|
4
|
-
"version": "2.5.4
|
|
4
|
+
"version": "2.5.4",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
7
7
|
"license": "FSL-1.1-MIT",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@settlemint/sdk-utils": "2.5.4
|
|
56
|
+
"@settlemint/sdk-utils": "2.5.4",
|
|
57
57
|
"es-toolkit": "^1",
|
|
58
58
|
"gql.tada": "^1",
|
|
59
59
|
"graphql": "^16",
|