mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 15:00:57 +03:00
feature: modularized express routes for reusability, testability, composability and performance (#2030)
* transition GET /api/v1/apikey * transition POST /api/v1/apikey * transition PUT /api/v1/apikey/:id * transition DELETE /api/v1/apikey/:id * Enable e2e tests for api/v1/apikey routes * remove unused addChatflowsCount * Enable e2e tests for api/v1/variables routes * Enable Cypress in GitHub Action * Update main.yml * Update main.yml * Transition GET /api/v1/variables * Enable cypress on github workflow * Transition POST /api/v1/variables * Transition PUT /api/v1/variables * Transition DELETE /api/v1/variables * Transition GET /api/v1/variables * Transition GET /api/v1/chatflows * Transition GET /api/v1/chatflows/:id * Transition POST /api/v1/chatflows * Transition DELETE /api/v1/chatflows/:id * Transition PUT /api/v1/chatflows/:id * Transition GET /api/v1/chatflows/apikey/:apiKey * Transition GET /api/v1/credentials * Transition POST /api/v1/credentials * Transition GET /api/v1/credentials/:id * Transition PUT /api/v1/credentials/:id * Transition DELETE /api/v1/credentials/:id * Transition GET /api/v1/tools * Transition GET /api/v1/tools/:id * Transition POST /api/v1/tools * Transition PUT & DELETE /api/v1/tools/:id * Transition /api/v1/assistants routes * Transition /api/v1/nodes routes * Transition GET /api/v1/chatflows-streaming/:id & GET /api/v1/chatflows-uploads/:id * wip-all-routes * Transition GET /api/v1/public-chatflows/:id & /api/v1/public-chatbotConfig/:id * Remove ts-ignore annotations * Transition GET /api/v1/chatmessage/:id * Transition POST /api/v1/chatmessage/:id * delete /api/v1/chatmessage/:id * transition /api/v1/feedback/:id routes * transition /api/v1/stats/:id * Transition GET /api/v1/openai-assistants/:id * Transition GET /api/v1/openai-assistants * Transition POST /api/v1/openai-assistants-file * transition GET /api/v1/get-upload-path * transition GET /api/v1/get-upload-file * transition GET /api/v1/flow-config/:id * transition POST /api/v1/node-config * transition GET /api/v1/version * transition GET /api/v1/fetch-links * transition POST /api/v1/vector/upsert/:id * transition POST /api/v1/vector/internal-upsert/:id * transition POST /api/v1/load-prompt * Update index.ts * transition POST /api/v1/prompts-list * transition predictions * Update index.ts * transition GET /api/v1/marketplaces/templates * Router update modularity cleanup * extend request interface - express namespace * Update index.ts * add errorMiddleware * Add custom application error handler * Fix pnpm lock file * prediction return and vector upsert * Move the getUploadsConfig into its own file * Remove lint warnings * fix undefined variable value * Fix node-load-method api call * standardize the error message display * Apply review comment bugfixes * Update index.ts * standardize error message display in snack notifications * Error message standard in the UI * Rename flowXpressApp to appServer * Upload middleware fix and axios update * fix async await --------- Co-authored-by: Henry <hzj94@hotmail.com>
This commit is contained in:
committed by
GitHub
parent
ea255db15d
commit
957694a912
@@ -0,0 +1,142 @@
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import { INodeData } from '../../Interface'
|
||||
import { INodeOptionsValue, ICommonObject, handleEscapeCharacters } from 'flowise-components'
|
||||
import { databaseEntities } from '../../utils'
|
||||
import logger from '../../utils/logger'
|
||||
|
||||
// Get all component nodes
|
||||
const getAllNodes = async () => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = []
|
||||
for (const nodeName in appServer.nodesPool.componentNodes) {
|
||||
const clonedNode = cloneDeep(appServer.nodesPool.componentNodes[nodeName])
|
||||
dbResponse.push(clonedNode)
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: nodesService.getAllNodes - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Get specific component node via name
|
||||
const getNodeByName = async (nodeName: string) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
if (Object.prototype.hasOwnProperty.call(appServer.nodesPool.componentNodes, nodeName)) {
|
||||
const dbResponse = appServer.nodesPool.componentNodes[nodeName]
|
||||
return dbResponse
|
||||
} else {
|
||||
throw new Error(`Node ${nodeName} not found`)
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error: nodesService.getAllNodes - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns specific component node icon via name
|
||||
const getSingleNodeIcon = async (nodeName: string) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
if (Object.prototype.hasOwnProperty.call(appServer.nodesPool.componentNodes, nodeName)) {
|
||||
const nodeInstance = appServer.nodesPool.componentNodes[nodeName]
|
||||
if (nodeInstance.icon === undefined) {
|
||||
throw new Error(`Node ${nodeName} icon not found`)
|
||||
}
|
||||
|
||||
if (nodeInstance.icon.endsWith('.svg') || nodeInstance.icon.endsWith('.png') || nodeInstance.icon.endsWith('.jpg')) {
|
||||
const filepath = nodeInstance.icon
|
||||
return filepath
|
||||
} else {
|
||||
throw new Error(`Node ${nodeName} icon is missing icon`)
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Node ${nodeName} not found`)
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error: nodesService.getSingleNodeIcon - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getSingleNodeAsyncOptions = async (nodeName: string, requestBody: any): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const nodeData: INodeData = requestBody
|
||||
if (Object.prototype.hasOwnProperty.call(appServer.nodesPool.componentNodes, nodeName)) {
|
||||
try {
|
||||
const nodeInstance = appServer.nodesPool.componentNodes[nodeName]
|
||||
const methodName = nodeData.loadMethod || ''
|
||||
|
||||
const dbResponse: INodeOptionsValue[] = await nodeInstance.loadMethods![methodName]!.call(nodeInstance, nodeData, {
|
||||
appDataSource: appServer.AppDataSource,
|
||||
databaseEntities: databaseEntities
|
||||
})
|
||||
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
return []
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Node ${nodeName} not found`
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error: nodesService.getSingleNodeAsyncOptions - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// execute custom function node
|
||||
const executeCustomFunction = async (requestBody: any) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const body = requestBody
|
||||
const functionInputVariables = Object.fromEntries(
|
||||
[...(body?.javascriptFunction ?? '').matchAll(/\$([a-zA-Z0-9_]+)/g)].map((g) => [g[1], undefined])
|
||||
)
|
||||
const nodeData = { inputs: { functionInputVariables, ...body } }
|
||||
if (Object.prototype.hasOwnProperty.call(appServer.nodesPool.componentNodes, 'customFunction')) {
|
||||
try {
|
||||
const nodeInstanceFilePath = appServer.nodesPool.componentNodes['customFunction'].filePath as string
|
||||
const nodeModule = await import(nodeInstanceFilePath)
|
||||
const newNodeInstance = new nodeModule.nodeClass()
|
||||
|
||||
const options: ICommonObject = {
|
||||
appDataSource: appServer.AppDataSource,
|
||||
databaseEntities,
|
||||
logger
|
||||
}
|
||||
|
||||
const returnData = await newNodeInstance.init(nodeData, '', options)
|
||||
const dbResponse = typeof returnData === 'string' ? handleEscapeCharacters(returnData, true) : returnData
|
||||
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 500,
|
||||
msg: `Error running custom function: ${error}`
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Node customFunction not found`
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error: nodesService.executeCustomFunction - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getAllNodes,
|
||||
getNodeByName,
|
||||
getSingleNodeIcon,
|
||||
getSingleNodeAsyncOptions,
|
||||
executeCustomFunction
|
||||
}
|
||||
Reference in New Issue
Block a user