Skip to content

Commit c1921e0

Browse files
committed
move subscription helpers from Executor to execute
1 parent 2cdaa64 commit c1921e0

File tree

2 files changed

+182
-174
lines changed

2 files changed

+182
-174
lines changed

src/execution/Executor.ts

Lines changed: 0 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ import { Computation } from './incremental/Computation.js';
6262
import { IncrementalPublisher } from './incremental/IncrementalPublisher.js';
6363
import { Queue } from './incremental/Queue.js';
6464
import type { Group, Stream, Task, Work } from './incremental/WorkQueue.js';
65-
import { mapAsyncIterable } from './mapAsyncIterable.js';
6665
import { ResolveInfo } from './ResolveInfo.js';
6766
import type { VariableValues } from './values.js';
6867
import { getArgumentValues, getDirectiveValues } from './values.js';
@@ -1749,172 +1748,6 @@ function handleStream(
17491748
exeContext.streams.push(itemStream);
17501749
}
17511750

1752-
export function mapSourceToResponse(
1753-
validatedExecutionArgs: ValidatedExecutionArgs,
1754-
resultOrStream: ExecutionResult | AsyncIterable<unknown>,
1755-
): AsyncGenerator<ExecutionResult, void, void> | ExecutionResult {
1756-
if (!isAsyncIterable(resultOrStream)) {
1757-
return resultOrStream;
1758-
}
1759-
1760-
// For each payload yielded from a subscription, map it over the normal
1761-
// GraphQL `execute` function, with `payload` as the rootValue.
1762-
// This implements the "MapSourceToResponseEvent" algorithm described in
1763-
// the GraphQL specification..
1764-
function mapFn(payload: unknown): PromiseOrValue<ExecutionResult> {
1765-
const perEventExecutionArgs: ValidatedExecutionArgs = {
1766-
...validatedExecutionArgs,
1767-
rootValue: payload,
1768-
};
1769-
return validatedExecutionArgs.perEventExecutor(perEventExecutionArgs);
1770-
}
1771-
1772-
const externalAbortSignal = validatedExecutionArgs.externalAbortSignal;
1773-
if (externalAbortSignal) {
1774-
const generator = mapAsyncIterable(resultOrStream, mapFn);
1775-
return {
1776-
...generator,
1777-
next: () => cancellablePromise(generator.next(), externalAbortSignal),
1778-
};
1779-
}
1780-
return mapAsyncIterable(resultOrStream, mapFn);
1781-
}
1782-
1783-
export function createSourceEventStreamImpl(
1784-
validatedExecutionArgs: ValidatedExecutionArgs,
1785-
): PromiseOrValue<AsyncIterable<unknown> | ExecutionResult> {
1786-
try {
1787-
const eventStream = executeSubscription(validatedExecutionArgs);
1788-
if (isPromise(eventStream)) {
1789-
return eventStream.then(undefined, (error: unknown) => ({
1790-
errors: [error as GraphQLError],
1791-
}));
1792-
}
1793-
1794-
return eventStream;
1795-
} catch (error) {
1796-
return { errors: [error] };
1797-
}
1798-
}
1799-
1800-
function executeSubscription(
1801-
validatedExecutionArgs: ValidatedExecutionArgs,
1802-
): PromiseOrValue<AsyncIterable<unknown>> {
1803-
const {
1804-
schema,
1805-
fragments,
1806-
rootValue,
1807-
contextValue,
1808-
operation,
1809-
variableValues,
1810-
hideSuggestions,
1811-
externalAbortSignal,
1812-
} = validatedExecutionArgs;
1813-
1814-
const rootType = schema.getSubscriptionType();
1815-
if (rootType == null) {
1816-
throw new GraphQLError(
1817-
'Schema is not configured to execute subscription operation.',
1818-
{ nodes: operation },
1819-
);
1820-
}
1821-
1822-
const { groupedFieldSet } = collectFields(
1823-
schema,
1824-
fragments,
1825-
variableValues,
1826-
rootType,
1827-
operation.selectionSet,
1828-
hideSuggestions,
1829-
);
1830-
1831-
const firstRootField = groupedFieldSet.entries().next().value as [
1832-
string,
1833-
FieldDetailsList,
1834-
];
1835-
const [responseName, fieldDetailsList] = firstRootField;
1836-
const firstFieldDetails = fieldDetailsList[0];
1837-
const firstNode = firstFieldDetails.node;
1838-
const fieldName = firstNode.name.value;
1839-
const fieldDef = schema.getField(rootType, fieldName);
1840-
1841-
if (!fieldDef) {
1842-
throw new GraphQLError(
1843-
`The subscription field "${fieldName}" is not defined.`,
1844-
{ nodes: toNodes(fieldDetailsList) },
1845-
);
1846-
}
1847-
1848-
const path = addPath(undefined, responseName, rootType.name);
1849-
const info = new ResolveInfo(
1850-
validatedExecutionArgs,
1851-
fieldDef,
1852-
fieldDetailsList,
1853-
rootType,
1854-
path,
1855-
() => ({ abortSignal: externalAbortSignal }),
1856-
);
1857-
1858-
try {
1859-
// Implements the "ResolveFieldEventStream" algorithm from GraphQL specification.
1860-
// It differs from "ResolveFieldValue" due to providing a different `resolveFn`.
1861-
1862-
// Build a JS object of arguments from the field.arguments AST, using the
1863-
// variables scope to fulfill any variable references.
1864-
const args = getArgumentValues(
1865-
fieldDef,
1866-
firstNode,
1867-
variableValues,
1868-
firstFieldDetails.fragmentVariableValues,
1869-
hideSuggestions,
1870-
);
1871-
1872-
// Call the `subscribe()` resolver or the default resolver to produce an
1873-
// AsyncIterable yielding raw payloads.
1874-
const resolveFn =
1875-
fieldDef.subscribe ?? validatedExecutionArgs.subscribeFieldResolver;
1876-
1877-
// The resolve function's optional third argument is a context value that
1878-
// is provided to every resolve function within an execution. It is commonly
1879-
// used to represent an authenticated user, or request-specific caches.
1880-
const result = resolveFn(rootValue, args, contextValue, info);
1881-
1882-
if (isPromise(result)) {
1883-
const promise = externalAbortSignal
1884-
? cancellablePromise(result, externalAbortSignal)
1885-
: result;
1886-
return promise
1887-
.then(assertEventStream)
1888-
.then(undefined, (error: unknown) => {
1889-
throw locatedError(
1890-
error,
1891-
toNodes(fieldDetailsList),
1892-
pathToArray(path),
1893-
);
1894-
});
1895-
}
1896-
return assertEventStream(result);
1897-
} catch (error) {
1898-
throw locatedError(error, toNodes(fieldDetailsList), pathToArray(path));
1899-
}
1900-
}
1901-
1902-
function assertEventStream(result: unknown): AsyncIterable<unknown> {
1903-
if (result instanceof Error) {
1904-
throw result;
1905-
}
1906-
1907-
// Assert field returned an event stream, otherwise yield an error.
1908-
if (!isAsyncIterable(result)) {
1909-
throw new GraphQLError(
1910-
'Subscription field must return Async Iterable. ' +
1911-
`Received: ${inspect(result)}.`,
1912-
);
1913-
}
1914-
1915-
return result;
1916-
}
1917-
19181751
/** @internal */
19191752
interface ExecutionGroup
19201753
extends Task<

0 commit comments

Comments
 (0)