{"version":3,"file":"IncrementalPublisher.js","sourceRoot":"","sources":["../../../src/execution/incremental/IncrementalPublisher.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ObjMap } from '../../jsutils/ObjMap.ts';\nimport { pathToArray } from '../../jsutils/Path.ts';\n\nimport { ensureGraphQLError } from '../../error/ensureGraphQLError.ts';\nimport type { GraphQLError } from '../../error/GraphQLError.ts';\n\nimport { mapAsyncIterable } from '../mapAsyncIterable.ts';\nimport { withConcurrentAbruptClose } from '../withConcurrentAbruptClose.ts';\n\nimport type {\n  CompletedResult,\n  DeliveryGroup,\n  ExecutionGroupValue,\n  ExperimentalIncrementalExecutionResults,\n  IncrementalDeferResult,\n  IncrementalResult,\n  IncrementalWork,\n  InitialIncrementalExecutionResult,\n  ItemStream,\n  PendingResult,\n  StreamItemValue,\n  SubsequentIncrementalExecutionResult,\n} from './IncrementalExecutor.ts';\nimport type { WorkQueueEvent } from './WorkQueue.ts';\nimport { createWorkQueue } from './WorkQueue.ts';\n\ninterface SubsequentIncrementalExecutionResultContext {\n  pending: Array<PendingResult>;\n  incremental: Array<IncrementalResult>;\n  completed: Array<CompletedResult>;\n  hasNext: boolean;\n}\n\n/** @internal */\nexport class IncrementalPublisher {\n  private _ids: Map<DeliveryGroup | ItemStream, string>;\n  private _nextId: number;\n\n  constructor() {\n    this._ids = new Map();\n    this._nextId = 0;\n  }\n\n  buildResponse(\n    data: ObjMap<unknown>,\n    errors: ReadonlyArray<GraphQLError>,\n    work: IncrementalWork,\n    abortSignal: AbortSignal | undefined,\n    onFinished: () => void,\n  ): ExperimentalIncrementalExecutionResults {\n    const { initialGroups, initialStreams, events } = createWorkQueue<\n      ExecutionGroupValue,\n      StreamItemValue,\n      DeliveryGroup,\n      ItemStream\n    >(work);\n\n    function abort(): void {\n      subsequentResults.throw(abortSignal?.reason).catch(() => {\n        // Ignore errors\n      });\n    }\n\n    if (abortSignal) {\n      abortSignal.addEventListener('abort', abort);\n    }\n    const onWorkQueueFinished = () => {\n      onFinished();\n      abortSignal?.removeEventListener('abort', abort);\n    };\n\n    const pending = this._toPendingResults(initialGroups, initialStreams);\n\n    const initialResult: InitialIncrementalExecutionResult = errors.length\n      ? { errors, data, pending, hasNext: true }\n      : { data, pending, hasNext: true };\n\n    const subsequentResults = withConcurrentAbruptClose(\n      mapAsyncIterable(events, (batch) =>\n        this._handleBatch(batch, onWorkQueueFinished),\n      ),\n      () => onWorkQueueFinished(),\n    );\n\n    return {\n      initialResult,\n      subsequentResults,\n    };\n  }\n\n  private _ensureId(\n    deferredFragmentOrStream: DeliveryGroup | ItemStream,\n  ): string {\n    let id = this._ids.get(deferredFragmentOrStream);\n    if (id !== undefined) {\n      return id;\n    }\n    id = String(this._nextId++);\n    this._ids.set(deferredFragmentOrStream, id);\n    return id;\n  }\n\n  private _toPendingResults(\n    newGroups: ReadonlyArray<DeliveryGroup>,\n    newStreams: ReadonlyArray<ItemStream>,\n  ): Array<PendingResult> {\n    const pendingResults: Array<PendingResult> = [];\n    for (const collection of [newGroups, newStreams]) {\n      for (const node of collection) {\n        const id = this._ensureId(node);\n        const pendingResult: PendingResult = {\n          id,\n          path: pathToArray(node.path),\n        };\n        if (node.label !== undefined) {\n          pendingResult.label = node.label;\n        }\n        pendingResults.push(pendingResult);\n      }\n    }\n    return pendingResults;\n  }\n\n  private _handleBatch(\n    batch: ReadonlyArray<\n      WorkQueueEvent<\n        ExecutionGroupValue,\n        StreamItemValue,\n        DeliveryGroup,\n        ItemStream\n      >\n    >,\n    onWorkQueueFinished: (() => void) | undefined,\n  ): SubsequentIncrementalExecutionResult {\n    const context: SubsequentIncrementalExecutionResultContext = {\n      pending: [],\n      incremental: [],\n      completed: [],\n      hasNext: true,\n    };\n\n    for (const event of batch) {\n      this._handleWorkQueueEvent(event, context, onWorkQueueFinished);\n    }\n\n    const { incremental, completed, pending, hasNext } = context;\n\n    const result: SubsequentIncrementalExecutionResult = { hasNext };\n    if (pending.length > 0) {\n      result.pending = pending;\n    }\n    if (incremental.length > 0) {\n      result.incremental = incremental;\n    }\n    if (completed.length > 0) {\n      result.completed = completed;\n    }\n\n    return result;\n  }\n\n  private _handleWorkQueueEvent(\n    event: WorkQueueEvent<\n      ExecutionGroupValue,\n      StreamItemValue,\n      DeliveryGroup,\n      ItemStream\n    >,\n    context: SubsequentIncrementalExecutionResultContext,\n    onWorkQueueFinished: (() => void) | undefined,\n  ): void {\n    switch (event.kind) {\n      case 'GROUP_VALUES': {\n        const group = event.group;\n        const id = this._ensureId(group);\n        for (const value of event.values) {\n          const { bestId, subPath } = this._getBestIdAndSubPath(\n            id,\n            group,\n            value,\n          );\n          const incrementalEntry: IncrementalDeferResult = {\n            id: bestId,\n            data: value.data,\n          };\n          if (value.errors !== undefined) {\n            incrementalEntry.errors = value.errors;\n          }\n          if (subPath !== undefined) {\n            incrementalEntry.subPath = subPath;\n          }\n          context.incremental.push(incrementalEntry);\n        }\n        break;\n      }\n      case 'GROUP_SUCCESS': {\n        const group = event.group;\n        const id = this._ensureId(group);\n        context.completed.push({ id });\n        this._ids.delete(group);\n        if (event.newGroups.length > 0 || event.newStreams.length > 0) {\n          context.pending.push(\n            ...this._toPendingResults(event.newGroups, event.newStreams),\n          );\n        }\n        break;\n      }\n      case 'GROUP_FAILURE': {\n        const { group, error } = event;\n        const id = this._ensureId(group);\n        context.completed.push({\n          id,\n          errors: [ensureGraphQLError(error)],\n        });\n        this._ids.delete(group);\n        break;\n      }\n      case 'STREAM_VALUES': {\n        const stream = event.stream;\n        const id = this._ensureId(stream);\n        const { values, newGroups, newStreams } = event;\n        const items: Array<unknown> = [];\n        const errors: Array<GraphQLError> = [];\n        for (const value of values) {\n          items.push(value.item);\n          if (value.errors !== undefined) {\n            errors.push(...value.errors);\n          }\n        }\n        context.incremental.push(\n          errors.length > 0 ? { id, items, errors } : { id, items },\n        );\n        if (newGroups.length > 0 || newStreams.length > 0) {\n          context.pending.push(\n            ...this._toPendingResults(newGroups, newStreams),\n          );\n        }\n        break;\n      }\n      case 'STREAM_SUCCESS': {\n        const stream = event.stream;\n        context.completed.push({\n          id: this._ensureId(stream),\n        });\n        this._ids.delete(stream);\n        break;\n      }\n      case 'STREAM_FAILURE': {\n        const stream = event.stream;\n        context.completed.push({\n          id: this._ensureId(stream),\n          errors: [ensureGraphQLError(event.error)],\n        });\n        this._ids.delete(stream);\n        break;\n      }\n      case 'WORK_QUEUE_TERMINATION': {\n        onWorkQueueFinished?.();\n        context.hasNext = false;\n        break;\n      }\n    }\n  }\n\n  private _getBestIdAndSubPath(\n    initialId: string,\n    initialDeferredFragmentRecord: DeliveryGroup,\n    executionGroupValue: ExecutionGroupValue,\n  ): { bestId: string; subPath: ReadonlyArray<string | number> | undefined } {\n    let maxLength = pathToArray(initialDeferredFragmentRecord.path).length;\n    let bestId = initialId;\n\n    for (const deliveryGroup of executionGroupValue.deliveryGroups) {\n      if (deliveryGroup === initialDeferredFragmentRecord) {\n        continue;\n      }\n      const id = this._ids.get(deliveryGroup);\n      // TODO: Investigate why there is no coverage gap using node native test coverage.\n      if (id === undefined) {\n        continue;\n      }\n      const path = pathToArray(deliveryGroup.path);\n      const length = path.length;\n      if (length > maxLength) {\n        maxLength = length;\n        bestId = id;\n      }\n    }\n    const subPath = executionGroupValue.path.slice(maxLength);\n    return {\n      bestId,\n      subPath: subPath.length > 0 ? subPath : undefined,\n    };\n  }\n}\n"]}