| 'use client'; | |
| import { useEffect, useRef } from 'react'; | |
| import { artifactDefinitions } from './artifact'; | |
| import { initialArtifactData, useArtifact } from '@/hooks/use-artifact'; | |
| import { useDataStream } from './data-stream-provider'; | |
| export function DataStreamHandler() { | |
| const { dataStream } = useDataStream(); | |
| const { artifact, setArtifact, setMetadata } = useArtifact(); | |
| const lastProcessedIndex = useRef(-1); | |
| useEffect(() => { | |
| if (!dataStream?.length) return; | |
| const newDeltas = dataStream.slice(lastProcessedIndex.current + 1); | |
| lastProcessedIndex.current = dataStream.length - 1; | |
| newDeltas.forEach((delta) => { | |
| const artifactDefinition = artifactDefinitions.find( | |
| (artifactDefinition) => artifactDefinition.kind === artifact.kind, | |
| ); | |
| if (artifactDefinition?.onStreamPart) { | |
| artifactDefinition.onStreamPart({ | |
| streamPart: delta, | |
| setArtifact, | |
| setMetadata, | |
| }); | |
| } | |
| setArtifact((draftArtifact) => { | |
| if (!draftArtifact) { | |
| return { ...initialArtifactData, status: 'streaming' }; | |
| } | |
| switch (delta.type) { | |
| case 'data-id': | |
| return { | |
| ...draftArtifact, | |
| documentId: delta.data, | |
| status: 'streaming', | |
| }; | |
| case 'data-title': | |
| return { | |
| ...draftArtifact, | |
| title: delta.data, | |
| status: 'streaming', | |
| }; | |
| case 'data-kind': | |
| return { | |
| ...draftArtifact, | |
| kind: delta.data, | |
| status: 'streaming', | |
| }; | |
| case 'data-clear': | |
| return { | |
| ...draftArtifact, | |
| content: '', | |
| status: 'streaming', | |
| }; | |
| case 'data-finish': | |
| return { | |
| ...draftArtifact, | |
| status: 'idle', | |
| }; | |
| default: | |
| return draftArtifact; | |
| } | |
| }); | |
| }); | |
| }, [dataStream, setArtifact, setMetadata, artifact]); | |
| return null; | |
| } | |