"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { OperationType: () => import_graphql7.OperationTypeNode, RequestManager: () => RequestManager, buildCombinedExecutor: () => buildCombinedExecutor, buildFetchExecutor: () => buildFetchExecutor, buildMockExecutor: () => buildMockExecutor, buildWebSocketExecutor: () => buildWebSocketExecutor, createNormalizedCache: () => createNormalizedCache, createQueryKey: () => createQueryKey, isQueryKey: () => isQueryKey, makeBatchedExecutor: () => import_batch_execute.createBatchingExecutor }); module.exports = __toCommonJS(src_exports); // src/cache/query-key.ts var import_graphql4 = require("graphql"); // src/schema/query.ts var import_graphql2 = require("graphql"); // src/schema/transform.ts var import_graphql = require("graphql"); var withTypename = (document) => (0, import_graphql.visit)(document, { SelectionSet: { enter: (node, _, parent) => { if (!node.selections) { return; } if (isOperationDefinitionNode(parent)) { return; } if (node.selections.some(isEntityTypeInformationNode)) { return; } return { ...node, selections: node.selections.concat({ kind: import_graphql.Kind.FIELD, name: { kind: import_graphql.Kind.NAME, value: "__typename" } }) }; } } }); var isEntityTypeInformationNode = (node) => { return node.kind === import_graphql.Kind.FIELD && node.name.kind === import_graphql.Kind.NAME && node.name.value === "__typename"; }; var isOperationDefinitionNode = (node) => !Array.isArray(node) && node?.kind === import_graphql.Kind.OPERATION_DEFINITION; // src/schema/query.ts var toOperationInformation = (document) => { const operations = []; (0, import_graphql2.visit)(document, { OperationDefinition: { enter: (node) => { const operationInformation = { operation: node.operation, name: node.name?.value, selections: node.selectionSet.selections.filter(isFieldNode).reduce( (acc, fieldNode) => ({ ...acc, [fieldNode.name.value]: { arguments: fieldNode.arguments?.map( (argument) => argument.name.value ) ?? [] } }), /* @__PURE__ */ Object.create(null) ) }; operations.push(operationInformation); } } }); return operations; }; var isFieldNode = (x) => x.kind === import_graphql2.Kind.FIELD && !isEntityTypeInformationNode(x); // src/cache/normalize.ts var normalizeAndCache = (queryKey, pluckedData, store) => { const cacheValue = Object.fromEntries( Object.entries(pluckedData).map(([field, maybeKey]) => [ field, // Note: Needs to be a getter so when we get responses to different // requests which share entities, they all reference the same thing toGetterOrValue(store, maybeKey) ]) ); store.set(queryKey.toString(), cacheValue); }; var toSelections = (operations) => operations.flatMap((operation) => Object.entries(operation.selections)); var toGetterOrValue = (store, maybeKey) => () => { if (Array.isArray(maybeKey)) { return maybeKey.map( (keyOrValue) => store.has(keyOrValue) ? store.get(keyOrValue) : keyOrValue ); } return store.has(maybeKey) ? store.get(maybeKey) : maybeKey; }; // src/schema/expected-fields.ts var import_graphql3 = require("graphql"); var import_mergeWith = __toESM(require("lodash/mergeWith"), 1); var toBlankResponse = (query) => { let previousDepth; let currentDepth; const fragments = /* @__PURE__ */ new Map(); let fragmentFields = /* @__PURE__ */ Object.create(null); previousDepth = fragmentFields; currentDepth = fragmentFields; (0, import_graphql3.visit)(query, { OperationDefinition: () => null, Field: { enter: (node) => { if (node.selectionSet) { previousDepth = currentDepth; const nextDepth = /* @__PURE__ */ Object.create(null); currentDepth[node.name.value] = nextDepth; currentDepth = nextDepth; } else { currentDepth[node.name.value] = ""; } }, leave: (node) => { if (node.selectionSet) { currentDepth = previousDepth; } } }, FragmentDefinition: { leave: (node) => { fragments.set(node.name.value, fragmentFields); fragmentFields = /* @__PURE__ */ Object.create(null); } } }); const json = /* @__PURE__ */ Object.create(null); previousDepth = json; currentDepth = json; (0, import_graphql3.visit)(query, { Field: { enter: (node) => { if (node.selectionSet) { previousDepth = currentDepth; const nextDepth = /* @__PURE__ */ Object.create(null); currentDepth[node.name.value] = nextDepth; currentDepth = nextDepth; } else { currentDepth[node.name.value] = ""; } }, leave: (node) => { if (node.selectionSet) { currentDepth = previousDepth; previousDepth = json; } } }, FragmentDefinition: () => null, FragmentSpread: (node) => { Object.assign(currentDepth, fragments.get(node.name.value)); }, InlineFragment: { enter: (node) => { const fieldName = Object.keys( fragments.get(node.typeCondition?.name.value) ).at(0); const nextDepth = /* @__PURE__ */ Object.create(null); previousDepth = currentDepth; currentDepth[fieldName] = nextDepth; currentDepth = nextDepth; }, leave: () => { currentDepth = previousDepth; } } }); return json; }; var toEmptyRecordDeep = (record) => (0, import_mergeWith.default)(/* @__PURE__ */ Object.create(null), record, (_, value) => { if (value && typeof value === "object" && !Array.isArray(value)) { return; } return ""; }); // src/cache/query-key.ts var SUFFIX = Math.random().toString(36).substring(2); var createQueryKey = ({ document, variables }) => new QueryKey2({ document, variables }); var isQueryKey = (x) => x instanceof QueryKey2; var QueryKey2 = class { expectedResponse; #key; constructor({ document, variables }) { this.expectedResponse = toBlankResponse(document); this.#key = toSelections( toOperationInformation(document).filter( (operation) => operation.operation === import_graphql4.OperationTypeNode.QUERY ) ).map( ([field, meta]) => [ field, meta.arguments.reduce( (acc, arg) => (acc.set(arg, variables?.[arg]), acc), new URLSearchParams() ).toString(), SUFFIX ].filter(Boolean).join(":") ).join("|"); } toString() { return this.#key; } }; // src/cache/pluck.ts var import_merge = __toESM(require("lodash/merge"), 1); // src/loop-recur/index.ts var recur = (...values) => ({ type: recur, values }); var loop = (f) => { let acc = f(); while (acc?.type === recur) { acc = f(...acc.values); } return acc; }; // src/cache/pluck.ts var makePluck = (typePolicies) => { const storeEntityReference = (entity, store) => { const keys = /* @__PURE__ */ new Set(); return loop( ([currentItem, ...rest] = [ { parent: null, parentProperty: null, entity } ], entityKey) => { if (!isEntity(currentItem?.entity) && !rest.length) { return entityKey; } if (!isEntity(currentItem?.entity) && rest.length) { return recur(rest, entityKey); } const { parent, parentProperty, entity: currentEntity } = currentItem; const type = currentEntity.__typename; const pickKey = typePolicies[type]?.key ?? typePolicies["*"].key; const key = pickKey(currentEntity, type); if (keys.has(key)) { throw new Error( `Entity with key \`${key}\` circularly references itself` ); } keys.add(key); const merge = typePolicies[type]?.merge ?? import_merge.default; const previous = store.has(key) ? store.get(key) : null; const next = currentEntity; if (previous && next) { merge(previous, next); if (parent && parentProperty) { parent[parentProperty] = previous; } } else { store.set(key, next); } const entityReferences = Object.entries(currentEntity).flatMap( ([key2, value]) => { if (Array.isArray(value)) { return value.map((entity2, idx) => ({ parent: value, parentProperty: `${idx}`, entity: entity2 })); } return { parent: currentEntity, parentProperty: key2, entity: value }; } ); return recur([...rest, ...entityReferences], entityKey ?? key); } ); }; const pluck = (data, store) => loop( ([rootField, ...rest] = Object.entries(data), acc = /* @__PURE__ */ Object.create(null)) => { if (!rootField) { return acc; } const [property, value] = rootField; if (Array.isArray(value) && value.some(isEntity)) { acc[property] = value.map( (value2) => isEntity(value2) ? storeEntityReference(value2, store) : value2 ); return recur(rest, acc); } if (!isEntity(value)) { acc[property] = value; return recur(rest, acc); } const entityReference = storeEntityReference(value, store); acc[property] = entityReference; return recur(rest, acc); } ); return pluck; }; var isEntity = (x) => x && typeof x === "object" && x["__typename"]; // src/cache/normalized-cache.ts var import_isMatchWith = __toESM(require("lodash/isMatchWith"), 1); var createNormalizedCache = ({ typePolicies }) => new NormalizedCache(typePolicies); var NormalizedCache = class { #store = /* @__PURE__ */ new Map(); #pluck; constructor(typePolicies) { this.#pluck = makePluck(typePolicies); } get _target_() { return this.#store; } get size() { return this.#store.size; } has(key) { return this.#store.has(key.toString()); } set(key, value) { if (isQueryKey(key)) { return void normalizeAndCache(key, this.#pluck(value, this), this); } if (value && typeof value === "object") { return void this.#store.set(key.toString(), new WeakRef(value)); } return void this.#store.set(key.toString(), value); } get(key) { if (!this.#store.has(key.toString())) return null; if (isQueryKey(key)) { const value2 = this.#store.get(key.toString()); const unwrapped = value2.deref(); if (!unwrapped) { this.#store.delete(key.toString()); return null; } const withEntities = Object.fromEntries( Object.entries(unwrapped).map(([key2, value3]) => [ key2, typeof value3 === "function" ? value3() : value3 ]) ); const expectedResponse = key.expectedResponse; if (!(0, import_isMatchWith.default)( toEmptyRecordDeep(withEntities), expectedResponse, (blankValue, expectedValue) => { if (blankValue === "" && typeof expectedValue === "object") { return true; } } )) { return null; } return withEntities; } const value = this.#store.get(key.toString()); if (value instanceof WeakRef) { const unwrapped = value.deref(); if (!unwrapped) { this.#store.delete(key.toString()); return null; } return unwrapped; } return value; } delete(queryKey) { this.#store.delete(queryKey.toString()); } }; // src/executor/index.ts var import_graphql5 = require("graphql"); var import_utils = require("@graphql-tools/utils"); var import_mock = require("@graphql-tools/mock"); var import_graphql6 = require("graphql"); var import_schema = require("@graphql-tools/schema"); var import_executor_http = require("@graphql-tools/executor-http"); var import_executor_graphql_ws = require("@graphql-tools/executor-graphql-ws"); var buildCombinedExecutor = (options) => { return async (executorRequest) => { const operationType = executorRequest.operationType; const executor = options[operationType]; const { onChange: _onChange, ...request } = executorRequest; const result = await executor({ ...request, document: withTypename(executorRequest.document) }); if ((0, import_utils.isAsyncIterable)(result)) { const consumeResult = async () => { for await (const value of result) { executorRequest.onChange?.(value); } }; if (executorRequest.onChange) { consumeResult(); } return result; } if (result.errors) { throw new AggregateError(result.errors); } return result.data ?? result; }; }; var buildFetchExecutor = (options) => { return async (executorRequest) => { const abortableFetch = new Proxy(fetch, { apply: (fetch2, thisArg, args) => { const fetchOptions = { ...args.at(1), signal: executorRequest?.signal }; return Reflect.apply(fetch2, thisArg, [args[0], fetchOptions]); } }); const executor = (0, import_executor_http.buildHTTPExecutor)({ ...options, fetch: abortableFetch }); const result = await executor(executorRequest); if ((0, import_utils.isAsyncIterable)(result)) { const consumeResult = async () => { for await (const value of result) { executorRequest.onChange?.(value); } }; if (executorRequest.onChange) { consumeResult(); } return result; } if (result.errors) { throw new AggregateError(result.errors); } return result.data; }; }; var buildWebSocketExecutor = (clientOptionsOrClient) => { const executor = (0, import_executor_graphql_ws.buildGraphQLWSExecutor)(clientOptionsOrClient); return async (executorRequest) => { const result = await executor(executorRequest); if ((0, import_utils.isAsyncIterable)(result)) { const consumeResult = async () => { for await (const value of result) { executorRequest.onChange?.(value); } }; consumeResult(); return result; } }; }; var buildMockExecutor = ({ typeDefs, store, mocks, typePolicies, resolvers, preserveResolvers, onFetchResponse }) => { const schema = (0, import_schema.makeExecutableSchema)({ typeDefs }); const schemaWithMocks = (0, import_mock.addMocksToSchema)({ schema, store, mocks, typePolicies, resolvers, preserveResolvers }); const server = (0, import_mock.mockServer)( schemaWithMocks, mocks ?? /* @__PURE__ */ Object.create(null), preserveResolvers ); return async (executorRequest) => { const result = await server.query( (0, import_graphql6.print)(executorRequest.document), executorRequest.variables ); if (result.errors) { throw new AggregateError(result.errors); } onFetchResponse?.(result.data); return result.data; }; }; // src/executor/types.ts var import_utils2 = require("@graphql-tools/utils"); // src/executor/request-manager.ts var import_isMatch = __toESM(require("lodash/isMatch"), 1); var RequestManager = class _RequestManager { #requests; static #instance; constructor() { this.#requests = /* @__PURE__ */ new Map(); } static get instance() { if (!_RequestManager.#instance) { _RequestManager.#instance = new _RequestManager(); } return _RequestManager.#instance; } has(queryKey) { const hasExistingRequest = this.#requests.has(queryKey.toString()); if (!hasExistingRequest) { return false; } const existingRequestDetails = this.#requests.get(queryKey.toString()); if (isQueryKey(queryKey)) { return Boolean( existingRequestDetails?.some( (request) => ( // All we care about is field selections, not necessarily whether it // is a list of entities so with lists of entities this is fine (0, import_isMatch.default)( request.queryKey.expectedResponse, queryKey.expectedResponse ) ) ) ); } return true; } get(queryKey) { const existingRequestDetails = this.#requests.get(queryKey.toString()); if (isQueryKey(queryKey)) { return existingRequestDetails?.find( (request) => (0, import_isMatch.default)( request.queryKey.expectedResponse, queryKey.expectedResponse ) )?.value; } return existingRequestDetails?.at(0)?.value; } set(queryKey, value) { const existingRequestDetails = this.#requests.has(queryKey.toString()) ? this.#requests.get(queryKey.toString()) : []; existingRequestDetails.push({ queryKey, value }); this.#requests.set(queryKey.toString(), existingRequestDetails); } delete(queryKey) { const existingRequestDetails = this.#requests.has(queryKey.toString()) ? this.#requests.get(queryKey.toString()) : []; if (isQueryKey(queryKey)) { const filteredRequestDetails = existingRequestDetails.filter( (request) => JSON.stringify(request.queryKey.expectedResponse) !== JSON.stringify(queryKey.expectedResponse) ); this.#requests.set(queryKey.toString(), filteredRequestDetails); } this.#requests.delete(queryKey.toString()); } }; // src/index.ts var import_batch_execute = require("@graphql-tools/batch-execute"); var import_graphql7 = require("graphql"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { OperationType, RequestManager, buildCombinedExecutor, buildFetchExecutor, buildMockExecutor, buildWebSocketExecutor, createNormalizedCache, createQueryKey, isQueryKey, makeBatchedExecutor }); //# sourceMappingURL=index.cjs.map