Repository: FlowiseAI/Flowise
File: packages/server/src/index.ts (TypeScript)

Code before:
            const { graph, nodeDependencies } = constructGraphs(nodes, edges)

            const endingNodeId = getEndingNode(nodeDependencies, graph)
            if (!endingNodeId) return res.status(500).send(`Ending node ${endingNodeId} not found`)

            const endingNodeData = nodes.find((nd) => nd.id === endingNodeId)?.data
            if (!endingNodeData) return res.status(500).send(`Ending node ${endingNodeId} data not found`)

            if (endingNodeData && endingNodeData.category !== 'Chains' && endingNodeData.category !== 'Agents') {
                return res.status(500).send(`Ending node must be either a Chain or Agent`)
            }

            const obj = {
                isStreaming: isFlowValidForStream(nodes, endingNodeData)
            }
            return res.json(obj)
        })

        // ----------------------------------------
        // ChatMessage
        // ----------------------------------------

        // Get all chatmessages from chatflowid
        this.app.get(
            '/api/v1/chatmessage/:id',
            query('chatId').notEmpty().escape(),
            query('sortOrder').notEmpty().escape(),
            query('memoryType').notEmpty().escape(),
            query('sessionId').notEmpty().escape(),
            query('startDate').notEmpty().escape(),
            query('endDate').notEmpty().escape(),
            query('chatTypeFilter').notEmpty().escape(),
            async (req: Request, res: Response) => {
                const result = validationResult(req)
                if (!result.isEmpty()) {
                    return res.status(404).send(`Chatmessage not found`)
                }
                const sortOrder = req.query?.order as string | undefined
                const chatId = req.query?.chatId as string | undefined
                const memoryType = req.query?.memoryType as string | undefined
                const sessionId = req.query?.sessionId as string | undefined
                const startDate = req.query?.startDate as string | undefined
                const endDate = req.query?.endDate as string | undefined
                let chatTypeFilter = req.query?.chatType as chatType | undefined

                if (chatTypeFilter) {
                    try {
                        const chatTypeFilterArray = JSON.parse(chatTypeFilter)
                        if (chatTypeFilterArray.includes(chatType.EXTERNAL) && chatTypeFilterArray.includes(chatType.INTERNAL)) {
                            chatTypeFilter = undefined
                        } else if (chatTypeFilterArray.includes(chatType.EXTERNAL)) {

Review comment (bug):
all these query are optional. by declaring this as `notEmpty()`, a basic API call to get chat messages without these query will fail

Code after:
                startDate,
                endDate
            )
            return res.json(chatmessages)
        })

        // Get internal chatmessages from chatflowid
        this.app.get('/api/v1/internal-chatmessage/:id', async (req: Request, res: Response) => {
            const chatmessages = await this.getChatMessage(req.params.id, chatType.INTERNAL)
            return res.json(chatmessages)
        })

        // Add chatmessages for chatflowid
        this.app.post('/api/v1/chatmessage/:id', async (req: Request, res: Response) => {
            const body = req.body
            const results = await this.addChatMessage(body)
            return res.json(results)
        })

        // Delete all chatmessages from chatId
        this.app.delete('/api/v1/chatmessage/:id', async (req: Request, res: Response) => {
            const chatflowid = req.params.id
            const chatflow = await this.AppDataSource.getRepository(ChatFlow).findOneBy({
                id: chatflowid
            })
            if (!chatflow) {
                res.status(404).send(`Chatflow ${chatflowid} not found`)
                return
            }
            const chatId = (req.query?.chatId as string) ?? (await getChatId(chatflowid))
            const memoryType = req.query?.memoryType as string | undefined
            const sessionId = req.query?.sessionId as string | undefined
            const chatType = req.query?.chatType as string | undefined
            const isClearFromViewMessageDialog = req.query?.isClearFromViewMessageDialog as string | undefined

            const flowData = chatflow.flowData
            const parsedFlowData: IReactFlowObject = JSON.parse(flowData)
            const nodes = parsedFlowData.nodes

            if (isClearFromViewMessageDialog) {
                await clearSessionMemoryFromViewMessageDialog(
                    nodes,
                    this.nodesPool.componentNodes,
                    chatId,
                    this.AppDataSource,
                    sessionId,
                    memoryType
                )
            } else {
                await clearAllSessionMemory(nodes, this.nodesPool.componentNodes, chatId, this.AppDataSource, sessionId)
            }