@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
JavaScript
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