UNPKG

@graphiql/react

Version:

[Changelog](https://github.com/graphql/graphiql/blob/main/packages/graphiql-react/CHANGELOG.md) | [API Docs](https://graphiql-test.netlify.app/typedoc/modules/graphiql_react.html) | [NPM](https://www.npmjs.com/package/@graphiql/react)

327 lines (326 loc) 9.64 kB
import { formatResult, isObservable, formatError, isAsyncIterable, fillLeafs } from "@graphiql/toolkit"; import { print } from "graphql"; import { getFragmentDependenciesForAST } from "graphql-language-service"; import setValue from "set-value"; import getValue from "get-value"; import { tryParseJSONC } from "../utility/jsonc.js"; import { Range } from "monaco-editor/esm/vs/editor/common/core/range.js"; const createExecutionSlice = (initial) => (set, get) => { function getAutoCompleteLeafs() { const { queryEditor, schema, getDefaultFieldNames } = get(); if (!queryEditor) { return; } const query = queryEditor.getValue(); const { insertions, result = "" } = fillLeafs(schema, query, getDefaultFieldNames); if (!insertions.length) { return result; } const model = queryEditor.getModel(); const selection = queryEditor.getSelection(); const cursorIndex = model.getOffsetAt(selection.getPosition()); model.setValue(result); let added = 0; const decorations = insertions.map(({ index, string }) => { const start = model.getPositionAt(index + added); const end = model.getPositionAt(index + (added += string.length)); return { range: new Range(start.lineNumber, start.column, end.lineNumber, end.column), options: { className: "auto-inserted-leaf", hoverMessage: { value: "Automatically added leaf fields" }, isWholeLine: false } }; }); const decorationCollection = queryEditor.createDecorationsCollection([]); decorationCollection.set(decorations); setTimeout(() => { decorationCollection.clear(); }, 7e3); let newCursorIndex = cursorIndex; for (const { index, string } of insertions) { if (index < cursorIndex) { newCursorIndex += string.length; } } const newCursorPosition = model.getPositionAt(newCursorIndex); queryEditor.setPosition(newCursorPosition); return result; } return { ...initial, isFetching: false, subscription: null, queryId: 0, actions: { stop() { set(({ subscription }) => { subscription == null ? void 0 : subscription.unsubscribe(); return { isFetching: false, subscription: null }; }); }, async run() { const { externalFragments, headerEditor, queryEditor, responseEditor, variableEditor, actions, operationName, documentAST, subscription, overrideOperationName, queryId, fetcher } = get(); if (!queryEditor || !responseEditor) { return; } if (subscription) { actions.stop(); return; } function setResponse(value) { responseEditor == null ? void 0 : responseEditor.setValue(value); actions.updateActiveTabValues({ response: value }); } function setError(error, editor) { if (!editor) { return; } const name = editor === variableEditor ? "Variables" : "Request headers"; setResponse(formatError({ message: `${name} ${error.message}` })); } const newQueryId = queryId + 1; set({ queryId: newQueryId }); let query = getAutoCompleteLeafs() || queryEditor.getValue(); let variables; try { variables = tryParseJSONC(variableEditor == null ? void 0 : variableEditor.getValue()); } catch (error) { setError(error, variableEditor); return; } let headers; try { headers = tryParseJSONC(headerEditor == null ? void 0 : headerEditor.getValue()); } catch (error) { setError(error, headerEditor); return; } const fragmentDependencies = documentAST ? getFragmentDependenciesForAST(documentAST, externalFragments) : []; if (fragmentDependencies.length) { query += "\n" + fragmentDependencies.map((node) => print(node)).join("\n"); } setResponse(""); set({ isFetching: true }); try { const fullResponse = {}; const handleResponse = (result) => { if (newQueryId !== get().queryId) { return; } let maybeMultipart = Array.isArray(result) ? result : false; if (!maybeMultipart && typeof result === "object" && "hasNext" in result) { maybeMultipart = [result]; } if (maybeMultipart) { for (const part of maybeMultipart) { mergeIncrementalResult(fullResponse, part); } set({ isFetching: false }); setResponse(formatResult(fullResponse)); } else { set({ isFetching: false }); setResponse(formatResult(result)); } }; const opName = overrideOperationName ?? operationName; const fetch = fetcher({ query, variables, operationName: opName }, { headers, documentAST }); const value = await fetch; if (isObservable(value)) { const newSubscription = value.subscribe({ next(result) { handleResponse(result); }, error(error) { set({ isFetching: false }); setResponse(formatError(error)); set({ subscription: null }); }, complete() { set({ isFetching: false, subscription: null }); } }); set({ subscription: newSubscription }); } else if (isAsyncIterable(value)) { const newSubscription = { unsubscribe: () => { var _a, _b; return (_b = (_a = value[Symbol.asyncIterator]()).return) == null ? void 0 : _b.call(_a); } }; set({ subscription: newSubscription }); for await (const result of value) { handleResponse(result); } set({ isFetching: false, subscription: null }); } else { handleResponse(value); } } catch (error) { set({ isFetching: false }); setResponse(formatError(error)); set({ subscription: null }); } } } }; }; const pathsMap = /* @__PURE__ */ new WeakMap(); function mergeIncrementalResult(executionResult, incrementalResult) { var _a, _b, _c; let path = ["data", ...incrementalResult.path ?? []]; for (const result of [executionResult, incrementalResult]) { if (result.pending) { let paths = pathsMap.get(executionResult); if (paths === void 0) { paths = /* @__PURE__ */ new Map(); pathsMap.set(executionResult, paths); } for (const { id: id2, path: pendingPath } of result.pending) { paths.set(id2, ["data", ...pendingPath]); } } } const { items, data, id } = incrementalResult; if (items) { if (id) { path = (_a = pathsMap.get(executionResult)) == null ? void 0 : _a.get(id); if (path === void 0) { throw new Error("Invalid incremental delivery format."); } const list = getValue(executionResult, path.join(".")); list.push(...items); } else { path = ["data", ...incrementalResult.path ?? []]; for (const item of items) { setValue(executionResult, path.join("."), item); path[path.length - 1]++; } } } if (data) { if (id) { path = (_b = pathsMap.get(executionResult)) == null ? void 0 : _b.get(id); if (path === void 0) { throw new Error("Invalid incremental delivery format."); } const { subPath } = incrementalResult; if (subPath !== void 0) { path = [...path, ...subPath]; } } setValue(executionResult, path.join("."), data, { merge: true }); } if (incrementalResult.errors) { executionResult.errors || (executionResult.errors = []); executionResult.errors.push(...incrementalResult.errors); } if (incrementalResult.extensions) { setValue(executionResult, "extensions", incrementalResult.extensions, { merge: true }); } if (incrementalResult.incremental) { for (const incrementalSubResult of incrementalResult.incremental) { mergeIncrementalResult(executionResult, incrementalSubResult); } } if (incrementalResult.completed) { for (const { id: completedId, errors } of incrementalResult.completed) { (_c = pathsMap.get(executionResult)) == null ? void 0 : _c.delete(completedId); if (errors) { executionResult.errors || (executionResult.errors = []); executionResult.errors.push(...errors); } } } } export { createExecutionSlice }; //# sourceMappingURL=execution.js.map