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,69 @@
|
||||
import { addAPIKey, deleteAPIKey, getAPIKeys, updateAPIKey } from '../../utils/apiKey'
|
||||
import { addChatflowsCount } from '../../utils/addChatflowsCount'
|
||||
import { getApiKey } from '../../utils/apiKey'
|
||||
|
||||
const getAllApiKeys = async () => {
|
||||
try {
|
||||
const keys = await getAPIKeys()
|
||||
const dbResponse = await addChatflowsCount(keys)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: apikeyService.getAllApiKeys - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const createApiKey = async (keyName: string) => {
|
||||
try {
|
||||
const keys = await addAPIKey(keyName)
|
||||
const dbResponse = await addChatflowsCount(keys)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: apikeyService.createApiKey - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Update api key
|
||||
const updateApiKey = async (id: string, keyName: string) => {
|
||||
try {
|
||||
const keys = await updateAPIKey(id, keyName)
|
||||
const dbResponse = await addChatflowsCount(keys)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: apikeyService.updateApiKey - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const deleteApiKey = async (id: string) => {
|
||||
try {
|
||||
const keys = await deleteAPIKey(id)
|
||||
const dbResponse = await addChatflowsCount(keys)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: apikeyService.deleteApiKey - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const verifyApiKey = async (paramApiKey: string): Promise<any> => {
|
||||
try {
|
||||
const apiKey = await getApiKey(paramApiKey)
|
||||
if (!apiKey) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 401,
|
||||
msg: `Unauthorized`
|
||||
}
|
||||
}
|
||||
const dbResponse = 'OK'
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: apikeyService.verifyApiKey - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
createApiKey,
|
||||
deleteApiKey,
|
||||
getAllApiKeys,
|
||||
updateApiKey,
|
||||
verifyApiKey
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
import OpenAI from 'openai'
|
||||
import path from 'path'
|
||||
import * as fs from 'fs'
|
||||
import { uniqWith, isEqual } from 'lodash'
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import { Assistant } from '../../database/entities/Assistant'
|
||||
import { Credential } from '../../database/entities/Credential'
|
||||
import { getUserHome, decryptCredentialData, getAppVersion } from '../../utils'
|
||||
|
||||
const creatAssistant = async (requestBody: any): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
if (!requestBody.details) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 500,
|
||||
msg: `Invalid request body`
|
||||
}
|
||||
}
|
||||
const assistantDetails = JSON.parse(requestBody.details)
|
||||
try {
|
||||
const credential = await appServer.AppDataSource.getRepository(Credential).findOneBy({
|
||||
id: requestBody.credential
|
||||
})
|
||||
|
||||
if (!credential) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Credential ${requestBody.credential} not found`
|
||||
}
|
||||
}
|
||||
|
||||
// Decrpyt credentialData
|
||||
const decryptedCredentialData = await decryptCredentialData(credential.encryptedData)
|
||||
const openAIApiKey = decryptedCredentialData['openAIApiKey']
|
||||
if (!openAIApiKey) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `OpenAI ApiKey not found`
|
||||
}
|
||||
}
|
||||
const openai = new OpenAI({ apiKey: openAIApiKey })
|
||||
|
||||
let tools = []
|
||||
if (assistantDetails.tools) {
|
||||
for (const tool of assistantDetails.tools ?? []) {
|
||||
tools.push({
|
||||
type: tool
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (assistantDetails.uploadFiles) {
|
||||
// Base64 strings
|
||||
let files: string[] = []
|
||||
const fileBase64 = assistantDetails.uploadFiles
|
||||
if (fileBase64.startsWith('[') && fileBase64.endsWith(']')) {
|
||||
files = JSON.parse(fileBase64)
|
||||
} else {
|
||||
files = [fileBase64]
|
||||
}
|
||||
|
||||
const uploadedFiles = []
|
||||
for (const file of files) {
|
||||
const splitDataURI = file.split(',')
|
||||
const filename = splitDataURI.pop()?.split(':')[1] ?? ''
|
||||
const bf = Buffer.from(splitDataURI.pop() || '', 'base64')
|
||||
const filePath = path.join(getUserHome(), '.flowise', 'openai-assistant', filename)
|
||||
if (!fs.existsSync(path.join(getUserHome(), '.flowise', 'openai-assistant'))) {
|
||||
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
||||
}
|
||||
if (!fs.existsSync(filePath)) {
|
||||
fs.writeFileSync(filePath, bf)
|
||||
}
|
||||
|
||||
const createdFile = await openai.files.create({
|
||||
file: fs.createReadStream(filePath),
|
||||
purpose: 'assistants'
|
||||
})
|
||||
uploadedFiles.push(createdFile)
|
||||
|
||||
fs.unlinkSync(filePath)
|
||||
}
|
||||
assistantDetails.files = [...assistantDetails.files, ...uploadedFiles]
|
||||
}
|
||||
|
||||
if (!assistantDetails.id) {
|
||||
const newAssistant = await openai.beta.assistants.create({
|
||||
name: assistantDetails.name,
|
||||
description: assistantDetails.description,
|
||||
instructions: assistantDetails.instructions,
|
||||
model: assistantDetails.model,
|
||||
tools,
|
||||
file_ids: (assistantDetails.files ?? []).map((file: OpenAI.Files.FileObject) => file.id)
|
||||
})
|
||||
assistantDetails.id = newAssistant.id
|
||||
} else {
|
||||
const retrievedAssistant = await openai.beta.assistants.retrieve(assistantDetails.id)
|
||||
let filteredTools = uniqWith([...retrievedAssistant.tools, ...tools], isEqual)
|
||||
filteredTools = filteredTools.filter((tool) => !(tool.type === 'function' && !(tool as any).function))
|
||||
|
||||
await openai.beta.assistants.update(assistantDetails.id, {
|
||||
name: assistantDetails.name,
|
||||
description: assistantDetails.description ?? '',
|
||||
instructions: assistantDetails.instructions ?? '',
|
||||
model: assistantDetails.model,
|
||||
tools: filteredTools,
|
||||
file_ids: uniqWith(
|
||||
[...retrievedAssistant.file_ids, ...(assistantDetails.files ?? []).map((file: OpenAI.Files.FileObject) => file.id)],
|
||||
isEqual
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const newAssistantDetails = {
|
||||
...assistantDetails
|
||||
}
|
||||
if (newAssistantDetails.uploadFiles) delete newAssistantDetails.uploadFiles
|
||||
|
||||
requestBody.details = JSON.stringify(newAssistantDetails)
|
||||
} catch (error) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 500,
|
||||
msg: `Error creating new assistant: ${error}`
|
||||
}
|
||||
}
|
||||
const newAssistant = new Assistant()
|
||||
Object.assign(newAssistant, requestBody)
|
||||
|
||||
const assistant = await appServer.AppDataSource.getRepository(Assistant).create(newAssistant)
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Assistant).save(assistant)
|
||||
|
||||
await appServer.telemetry.sendTelemetry('assistant_created', {
|
||||
version: await getAppVersion(),
|
||||
assistantId: dbResponse.id
|
||||
})
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: assistantsService.creatTool - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const deleteAssistant = async (assistantId: string, isDeleteBoth: any): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const assistant = await appServer.AppDataSource.getRepository(Assistant).findOneBy({
|
||||
id: assistantId
|
||||
})
|
||||
if (!assistant) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Assistant ${assistantId} not found`
|
||||
}
|
||||
}
|
||||
try {
|
||||
const assistantDetails = JSON.parse(assistant.details)
|
||||
const credential = await appServer.AppDataSource.getRepository(Credential).findOneBy({
|
||||
id: assistant.credential
|
||||
})
|
||||
|
||||
if (!credential) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Credential ${assistant.credential} not found`
|
||||
}
|
||||
}
|
||||
|
||||
// Decrpyt credentialData
|
||||
const decryptedCredentialData = await decryptCredentialData(credential.encryptedData)
|
||||
const openAIApiKey = decryptedCredentialData['openAIApiKey']
|
||||
if (!openAIApiKey) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `OpenAI ApiKey not found`
|
||||
}
|
||||
}
|
||||
|
||||
const openai = new OpenAI({ apiKey: openAIApiKey })
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Assistant).delete({ id: assistantId })
|
||||
if (isDeleteBoth) await openai.beta.assistants.del(assistantDetails.id)
|
||||
return dbResponse
|
||||
} catch (error: any) {
|
||||
if (error.status === 404 && error.type === 'invalid_request_error') {
|
||||
return 'OK'
|
||||
} else {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 500,
|
||||
msg: `Error deleting assistant: ${error}`
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error: assistantsService.deleteTool - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getAllAssistants = async (): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Assistant).find()
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: assistantsService.getAllAssistants - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getAssistantById = async (assistantId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Assistant).findOneBy({
|
||||
id: assistantId
|
||||
})
|
||||
if (!dbResponse) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Assistant ${assistantId} not found`
|
||||
}
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: assistantsService.getAssistantById - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const updateAssistant = async (assistantId: string, requestBody: any): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const assistant = await appServer.AppDataSource.getRepository(Assistant).findOneBy({
|
||||
id: assistantId
|
||||
})
|
||||
|
||||
if (!assistant) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Assistant ${assistantId} not found`
|
||||
}
|
||||
}
|
||||
try {
|
||||
const openAIAssistantId = JSON.parse(assistant.details)?.id
|
||||
const body = requestBody
|
||||
const assistantDetails = JSON.parse(body.details)
|
||||
const credential = await appServer.AppDataSource.getRepository(Credential).findOneBy({
|
||||
id: body.credential
|
||||
})
|
||||
|
||||
if (!credential) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Credential ${body.credential} not found`
|
||||
}
|
||||
}
|
||||
|
||||
// Decrpyt credentialData
|
||||
const decryptedCredentialData = await decryptCredentialData(credential.encryptedData)
|
||||
const openAIApiKey = decryptedCredentialData['openAIApiKey']
|
||||
if (!openAIApiKey) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `OpenAI ApiKey not found`
|
||||
}
|
||||
}
|
||||
|
||||
const openai = new OpenAI({ apiKey: openAIApiKey })
|
||||
|
||||
let tools = []
|
||||
if (assistantDetails.tools) {
|
||||
for (const tool of assistantDetails.tools ?? []) {
|
||||
tools.push({
|
||||
type: tool
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (assistantDetails.uploadFiles) {
|
||||
// Base64 strings
|
||||
let files: string[] = []
|
||||
const fileBase64 = assistantDetails.uploadFiles
|
||||
if (fileBase64.startsWith('[') && fileBase64.endsWith(']')) {
|
||||
files = JSON.parse(fileBase64)
|
||||
} else {
|
||||
files = [fileBase64]
|
||||
}
|
||||
|
||||
const uploadedFiles = []
|
||||
for (const file of files) {
|
||||
const splitDataURI = file.split(',')
|
||||
const filename = splitDataURI.pop()?.split(':')[1] ?? ''
|
||||
const bf = Buffer.from(splitDataURI.pop() || '', 'base64')
|
||||
const filePath = path.join(getUserHome(), '.flowise', 'openai-assistant', filename)
|
||||
if (!fs.existsSync(path.join(getUserHome(), '.flowise', 'openai-assistant'))) {
|
||||
fs.mkdirSync(path.dirname(filePath), { recursive: true })
|
||||
}
|
||||
if (!fs.existsSync(filePath)) {
|
||||
fs.writeFileSync(filePath, bf)
|
||||
}
|
||||
|
||||
const createdFile = await openai.files.create({
|
||||
file: fs.createReadStream(filePath),
|
||||
purpose: 'assistants'
|
||||
})
|
||||
uploadedFiles.push(createdFile)
|
||||
|
||||
fs.unlinkSync(filePath)
|
||||
}
|
||||
assistantDetails.files = [...assistantDetails.files, ...uploadedFiles]
|
||||
}
|
||||
|
||||
const retrievedAssistant = await openai.beta.assistants.retrieve(openAIAssistantId)
|
||||
let filteredTools = uniqWith([...retrievedAssistant.tools, ...tools], isEqual)
|
||||
filteredTools = filteredTools.filter((tool) => !(tool.type === 'function' && !(tool as any).function))
|
||||
|
||||
await openai.beta.assistants.update(openAIAssistantId, {
|
||||
name: assistantDetails.name,
|
||||
description: assistantDetails.description,
|
||||
instructions: assistantDetails.instructions,
|
||||
model: assistantDetails.model,
|
||||
tools: filteredTools,
|
||||
file_ids: uniqWith(
|
||||
[...retrievedAssistant.file_ids, ...(assistantDetails.files ?? []).map((file: OpenAI.Files.FileObject) => file.id)],
|
||||
isEqual
|
||||
)
|
||||
})
|
||||
|
||||
const newAssistantDetails = {
|
||||
...assistantDetails,
|
||||
id: openAIAssistantId
|
||||
}
|
||||
if (newAssistantDetails.uploadFiles) delete newAssistantDetails.uploadFiles
|
||||
|
||||
const updateAssistant = new Assistant()
|
||||
body.details = JSON.stringify(newAssistantDetails)
|
||||
Object.assign(updateAssistant, body)
|
||||
|
||||
await appServer.AppDataSource.getRepository(Assistant).merge(assistant, updateAssistant)
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Assistant).save(assistant)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 500,
|
||||
msg: `Error updating assistant: ${error}`
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error: assistantsService.updateAssistant - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
creatAssistant,
|
||||
deleteAssistant,
|
||||
getAllAssistants,
|
||||
getAssistantById,
|
||||
updateAssistant
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
import { FindOptionsWhere } from 'typeorm'
|
||||
import path from 'path'
|
||||
import { chatType, IChatMessage } from '../../Interface'
|
||||
import { utilGetChatMessage } from '../../utils/getChatMessage'
|
||||
import { utilAddChatMessage } from '../../utils/addChatMesage'
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import { ChatMessageFeedback } from '../../database/entities/ChatMessageFeedback'
|
||||
import { getStoragePath } from 'flowise-components'
|
||||
import { deleteFolderRecursive } from '../../utils'
|
||||
import logger from '../../utils/logger'
|
||||
import { ChatMessage } from '../../database/entities/ChatMessage'
|
||||
|
||||
// Add chatmessages for chatflowid
|
||||
const createChatMessage = async (chatMessage: Partial<IChatMessage>) => {
|
||||
try {
|
||||
const dbResponse = await utilAddChatMessage(chatMessage)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatMessagesService.createChatMessage - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Get all chatmessages from chatflowid
|
||||
const getAllChatMessages = async (
|
||||
chatflowId: string,
|
||||
chatTypeFilter: chatType | undefined,
|
||||
sortOrder: string = 'ASC',
|
||||
chatId?: string,
|
||||
memoryType?: string,
|
||||
sessionId?: string,
|
||||
startDate?: string,
|
||||
endDate?: string,
|
||||
messageId?: string,
|
||||
feedback?: boolean
|
||||
): Promise<any> => {
|
||||
try {
|
||||
const dbResponse = await utilGetChatMessage(
|
||||
chatflowId,
|
||||
chatTypeFilter,
|
||||
sortOrder,
|
||||
chatId,
|
||||
memoryType,
|
||||
sessionId,
|
||||
startDate,
|
||||
endDate,
|
||||
messageId,
|
||||
feedback
|
||||
)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatMessagesService.getAllChatMessages - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Get internal chatmessages from chatflowid
|
||||
const getAllInternalChatMessages = async (
|
||||
chatflowId: string,
|
||||
chatTypeFilter: chatType | undefined,
|
||||
sortOrder: string = 'ASC',
|
||||
chatId?: string,
|
||||
memoryType?: string,
|
||||
sessionId?: string,
|
||||
startDate?: string,
|
||||
endDate?: string,
|
||||
messageId?: string,
|
||||
feedback?: boolean
|
||||
): Promise<any> => {
|
||||
try {
|
||||
const dbResponse = await utilGetChatMessage(
|
||||
chatflowId,
|
||||
chatTypeFilter,
|
||||
sortOrder,
|
||||
chatId,
|
||||
memoryType,
|
||||
sessionId,
|
||||
startDate,
|
||||
endDate,
|
||||
messageId,
|
||||
feedback
|
||||
)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatMessagesService.getAllInternalChatMessages - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const removeAllChatMessages = async (chatId: string, chatflowid: string, deleteOptions: FindOptionsWhere<ChatMessage>): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
|
||||
// remove all related feedback records
|
||||
const feedbackDeleteOptions: FindOptionsWhere<ChatMessageFeedback> = { chatId }
|
||||
await appServer.AppDataSource.getRepository(ChatMessageFeedback).delete(feedbackDeleteOptions)
|
||||
|
||||
// Delete all uploads corresponding to this chatflow/chatId
|
||||
if (chatId) {
|
||||
try {
|
||||
const directory = path.join(getStoragePath(), chatflowid, chatId)
|
||||
deleteFolderRecursive(directory)
|
||||
} catch (e) {
|
||||
logger.error(`[server]: Error deleting file storage for chatflow ${chatflowid}, chatId ${chatId}: ${e}`)
|
||||
}
|
||||
}
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(ChatMessage).delete(deleteOptions)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatMessagesService.removeAllChatMessages - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
createChatMessage,
|
||||
getAllChatMessages,
|
||||
getAllInternalChatMessages,
|
||||
removeAllChatMessages
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
import path from 'path'
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import { IChatFlow } from '../../Interface'
|
||||
import { ChatFlow } from '../../database/entities/ChatFlow'
|
||||
import {
|
||||
getAppVersion,
|
||||
getTelemetryFlowObj,
|
||||
deleteFolderRecursive,
|
||||
isFlowValidForStream,
|
||||
constructGraphs,
|
||||
getEndingNodes
|
||||
} from '../../utils'
|
||||
import logger from '../../utils/logger'
|
||||
import { getStoragePath } from 'flowise-components'
|
||||
import { IReactFlowObject } from '../../Interface'
|
||||
import { utilGetUploadsConfig } from '../../utils/getUploadsConfig'
|
||||
|
||||
// Check if chatflow valid for streaming
|
||||
const checkIfChatflowIsValidForStreaming = async (chatflowId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
//**
|
||||
const chatflow = await appServer.AppDataSource.getRepository(ChatFlow).findOneBy({
|
||||
id: chatflowId
|
||||
})
|
||||
if (!chatflow) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Chatflow ${chatflowId} not found`
|
||||
}
|
||||
}
|
||||
|
||||
/*** Get Ending Node with Directed Graph ***/
|
||||
const flowData = chatflow.flowData
|
||||
const parsedFlowData: IReactFlowObject = JSON.parse(flowData)
|
||||
const nodes = parsedFlowData.nodes
|
||||
const edges = parsedFlowData.edges
|
||||
const { graph, nodeDependencies } = constructGraphs(nodes, edges)
|
||||
|
||||
const endingNodeIds = getEndingNodes(nodeDependencies, graph)
|
||||
if (!endingNodeIds.length) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 500,
|
||||
msg: `Ending nodes not found`
|
||||
}
|
||||
}
|
||||
|
||||
const endingNodes = nodes.filter((nd) => endingNodeIds.includes(nd.id))
|
||||
|
||||
let isStreaming = false
|
||||
let isEndingNodeExists = endingNodes.find((node) => node.data?.outputs?.output === 'EndingNode')
|
||||
|
||||
for (const endingNode of endingNodes) {
|
||||
const endingNodeData = endingNode.data
|
||||
if (!endingNodeData) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 500,
|
||||
msg: `Ending node ${endingNode.id} data not found`
|
||||
}
|
||||
}
|
||||
|
||||
const isEndingNode = endingNodeData?.outputs?.output === 'EndingNode'
|
||||
|
||||
if (!isEndingNode) {
|
||||
if (
|
||||
endingNodeData &&
|
||||
endingNodeData.category !== 'Chains' &&
|
||||
endingNodeData.category !== 'Agents' &&
|
||||
endingNodeData.category !== 'Engine'
|
||||
) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 500,
|
||||
msg: `Ending node must be either a Chain or Agent`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isStreaming = isEndingNode ? false : isFlowValidForStream(nodes, endingNodeData)
|
||||
}
|
||||
|
||||
// Once custom function ending node exists, flow is always unavailable to stream
|
||||
const dbResponse = { isStreaming: isEndingNodeExists ? false : isStreaming }
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatflowsService.checkIfChatflowIsValidForStreaming - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if chatflow valid for uploads
|
||||
const checkIfChatflowIsValidForUploads = async (chatflowId: string): Promise<any> => {
|
||||
try {
|
||||
const dbResponse = await utilGetUploadsConfig(chatflowId)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatflowsService.checkIfChatflowIsValidForUploads - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const deleteChatflow = async (chatflowId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).delete({ id: chatflowId })
|
||||
try {
|
||||
// Delete all uploads corresponding to this chatflow
|
||||
const directory = path.join(getStoragePath(), chatflowId)
|
||||
deleteFolderRecursive(directory)
|
||||
} catch (e) {
|
||||
logger.error(`[server]: Error deleting file storage for chatflow ${chatflowId}: ${e}`)
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatflowsService.getAllChatflows - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getAllChatflows = async (): Promise<IChatFlow[]> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).find()
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatflowsService.getAllChatflows - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getChatflowByApiKey = async (apiKeyId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(ChatFlow)
|
||||
.createQueryBuilder('cf')
|
||||
.where('cf.apikeyid = :apikeyid', { apikeyid: apiKeyId })
|
||||
.orWhere('cf.apikeyid IS NULL')
|
||||
.orWhere('cf.apikeyid = ""')
|
||||
.orderBy('cf.name', 'ASC')
|
||||
.getMany()
|
||||
if (dbResponse.length < 1) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Chatflow not found in the database!`
|
||||
}
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatflowsService.getChatflowByApiKey - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getChatflowById = async (chatflowId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).findOneBy({
|
||||
id: chatflowId
|
||||
})
|
||||
if (!dbResponse) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Chatflow ${chatflowId} not found in the database!`
|
||||
}
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatflowsService.getAllChatflows - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const saveChatflow = async (newChatFlow: ChatFlow): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const newDbChatflow = await appServer.AppDataSource.getRepository(ChatFlow).create(newChatFlow)
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).save(newDbChatflow)
|
||||
await appServer.telemetry.sendTelemetry('chatflow_created', {
|
||||
version: await getAppVersion(),
|
||||
chatflowId: dbResponse.id,
|
||||
flowGraph: getTelemetryFlowObj(JSON.parse(dbResponse.flowData)?.nodes, JSON.parse(dbResponse.flowData)?.edges)
|
||||
})
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatflowsService.saveChatflow - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const updateChatflow = async (chatflow: ChatFlow, updateChatFlow: ChatFlow): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const newDbChatflow = await appServer.AppDataSource.getRepository(ChatFlow).merge(chatflow, updateChatFlow)
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).save(newDbChatflow)
|
||||
// chatFlowPool is initialized only when a flow is opened
|
||||
// if the user attempts to rename/update category without opening any flow, chatFlowPool will be undefined
|
||||
if (appServer.chatflowPool) {
|
||||
// Update chatflowpool inSync to false, to build flow from scratch again because data has been changed
|
||||
appServer.chatflowPool.updateInSync(chatflow.id, false)
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatflowsService.updateChatflow - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Get specific chatflow via id (PUBLIC endpoint, used when sharing chatbot link)
|
||||
const getSinglePublicChatflow = async (chatflowId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).findOneBy({
|
||||
id: chatflowId
|
||||
})
|
||||
if (dbResponse && dbResponse.isPublic) {
|
||||
return dbResponse
|
||||
} else if (dbResponse && !dbResponse.isPublic) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 401,
|
||||
msg: `Unauthorized`
|
||||
}
|
||||
}
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Chatflow ${chatflowId} not found`
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatflowsService.getSinglePublicChatflow - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Get specific chatflow chatbotConfig via id (PUBLIC endpoint, used to retrieve config for embedded chat)
|
||||
// Safe as public endpoint as chatbotConfig doesn't contain sensitive credential
|
||||
const getSinglePublicChatbotConfig = async (chatflowId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(ChatFlow).findOneBy({
|
||||
id: chatflowId
|
||||
})
|
||||
if (!dbResponse) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Chatflow ${chatflowId} not found`
|
||||
}
|
||||
}
|
||||
const uploadsConfig = await utilGetUploadsConfig(chatflowId)
|
||||
// even if chatbotConfig is not set but uploads are enabled
|
||||
// send uploadsConfig to the chatbot
|
||||
if (dbResponse.chatbotConfig || uploadsConfig) {
|
||||
try {
|
||||
const parsedConfig = dbResponse.chatbotConfig ? JSON.parse(dbResponse.chatbotConfig) : {}
|
||||
return { ...parsedConfig, uploads: uploadsConfig }
|
||||
} catch (e) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 500,
|
||||
msg: `Error parsing Chatbot Config for Chatflow ${chatflowId}`
|
||||
}
|
||||
}
|
||||
}
|
||||
return 'OK'
|
||||
} catch (error) {
|
||||
throw new Error(`Error: chatflowsService.getSinglePublicChatbotConfig - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
checkIfChatflowIsValidForStreaming,
|
||||
checkIfChatflowIsValidForUploads,
|
||||
deleteChatflow,
|
||||
getAllChatflows,
|
||||
getChatflowByApiKey,
|
||||
getChatflowById,
|
||||
saveChatflow,
|
||||
updateChatflow,
|
||||
getSinglePublicChatflow,
|
||||
getSinglePublicChatbotConfig
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
|
||||
// Get all component credentials
|
||||
const getAllComponentsCredentials = async (): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = []
|
||||
for (const credName in appServer.nodesPool.componentCredentials) {
|
||||
const clonedCred = cloneDeep(appServer.nodesPool.componentCredentials[credName])
|
||||
dbResponse.push(clonedCred)
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: componentsCredentialsService.getAllComponentsCredentials - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getComponentByName = async (credentialName: string) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
if (!credentialName.includes('&')) {
|
||||
if (Object.prototype.hasOwnProperty.call(appServer.nodesPool.componentCredentials, credentialName)) {
|
||||
return appServer.nodesPool.componentCredentials[credentialName]
|
||||
} else {
|
||||
throw new Error(
|
||||
`Error: componentsCredentialsService.getSingleComponentsCredential - Credential ${credentialName} not found`
|
||||
)
|
||||
}
|
||||
} else {
|
||||
const dbResponse = []
|
||||
for (const name of credentialName.split('&')) {
|
||||
if (Object.prototype.hasOwnProperty.call(appServer.nodesPool.componentCredentials, name)) {
|
||||
dbResponse.push(appServer.nodesPool.componentCredentials[name])
|
||||
} else {
|
||||
throw new Error(`Error: componentsCredentialsService.getSingleComponentsCredential - Credential ${name} not found`)
|
||||
}
|
||||
}
|
||||
return dbResponse
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error: componentsCredentialsService.getSingleComponentsCredential - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns specific component credential icon via name
|
||||
const getSingleComponentsCredentialIcon = async (credentialName: string) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
if (Object.prototype.hasOwnProperty.call(appServer.nodesPool.componentCredentials, credentialName)) {
|
||||
const credInstance = appServer.nodesPool.componentCredentials[credentialName]
|
||||
if (credInstance.icon === undefined) {
|
||||
throw new Error(`Credential ${credentialName} icon not found`)
|
||||
}
|
||||
|
||||
if (credInstance.icon.endsWith('.svg') || credInstance.icon.endsWith('.png') || credInstance.icon.endsWith('.jpg')) {
|
||||
const filepath = credInstance.icon
|
||||
return filepath
|
||||
} else {
|
||||
throw new Error(`Credential ${credentialName} icon is missing icon`)
|
||||
}
|
||||
} else {
|
||||
throw new Error(`Credential ${credentialName} not found`)
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error: componentsCredentialsService.getSingleComponentsCredentialIcon - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getAllComponentsCredentials,
|
||||
getComponentByName,
|
||||
getSingleComponentsCredentialIcon
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
import { omit } from 'lodash'
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import { Credential } from '../../database/entities/Credential'
|
||||
import { transformToCredentialEntity, decryptCredentialData } from '../../utils'
|
||||
import { ICredentialReturnResponse } from '../../Interface'
|
||||
|
||||
const createCredential = async (requestBody: any) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const newCredential = await transformToCredentialEntity(requestBody)
|
||||
const credential = await appServer.AppDataSource.getRepository(Credential).create(newCredential)
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Credential).save(credential)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: credentialsService.createCredential - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all credentials from chatflowid
|
||||
const deleteCredentials = async (credentialId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Credential).delete({ id: credentialId })
|
||||
if (!dbResponse) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Credential ${credentialId} not found`
|
||||
}
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: credentialsService.deleteCredential - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getAllCredentials = async (paramCredentialName: any) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
let dbResponse = []
|
||||
if (paramCredentialName) {
|
||||
if (Array.isArray(paramCredentialName)) {
|
||||
for (let i = 0; i < paramCredentialName.length; i += 1) {
|
||||
const name = paramCredentialName[i] as string
|
||||
const credentials = await appServer.AppDataSource.getRepository(Credential).findBy({
|
||||
credentialName: name
|
||||
})
|
||||
dbResponse.push(...credentials)
|
||||
}
|
||||
} else {
|
||||
const credentials = await appServer.AppDataSource.getRepository(Credential).findBy({
|
||||
credentialName: paramCredentialName as string
|
||||
})
|
||||
dbResponse = [...credentials]
|
||||
}
|
||||
} else {
|
||||
const credentials = await appServer.AppDataSource.getRepository(Credential).find()
|
||||
for (const credential of credentials) {
|
||||
dbResponse.push(omit(credential, ['encryptedData']))
|
||||
}
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: credentialsService.getAllCredentials - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getCredentialById = async (credentialId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const credential = await appServer.AppDataSource.getRepository(Credential).findOneBy({
|
||||
id: credentialId
|
||||
})
|
||||
if (!credential) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Credential ${credentialId} not found`
|
||||
}
|
||||
}
|
||||
// Decrpyt credentialData
|
||||
const decryptedCredentialData = await decryptCredentialData(
|
||||
credential.encryptedData,
|
||||
credential.credentialName,
|
||||
appServer.nodesPool.componentCredentials
|
||||
)
|
||||
const returnCredential: ICredentialReturnResponse = {
|
||||
...credential,
|
||||
plainDataObj: decryptedCredentialData
|
||||
}
|
||||
const dbResponse = omit(returnCredential, ['encryptedData'])
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: credentialsService.createCredential - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const updateCredential = async (credentialId: string, requestBody: any): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const credential = await appServer.AppDataSource.getRepository(Credential).findOneBy({
|
||||
id: credentialId
|
||||
})
|
||||
if (!credential) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Credential ${credentialId} not found`
|
||||
}
|
||||
}
|
||||
const updateCredential = await transformToCredentialEntity(requestBody)
|
||||
await appServer.AppDataSource.getRepository(Credential).merge(credential, updateCredential)
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Credential).save(credential)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: credentialsService.updateCredential - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
createCredential,
|
||||
deleteCredentials,
|
||||
getAllCredentials,
|
||||
getCredentialById,
|
||||
updateCredential
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { utilGetChatMessageFeedback } from '../../utils/getChatMessageFeedback'
|
||||
import { utilAddChatMessageFeedback } from '../../utils/addChatMessageFeedback'
|
||||
import { utilUpdateChatMessageFeedback } from '../../utils/updateChatMessageFeedback'
|
||||
import { IChatMessageFeedback } from '../../Interface'
|
||||
|
||||
// Get all chatmessage feedback from chatflowid
|
||||
const getAllChatMessageFeedback = async (
|
||||
chatflowid: string,
|
||||
chatId: string | undefined,
|
||||
sortOrder: string | undefined,
|
||||
startDate: string | undefined,
|
||||
endDate: string | undefined
|
||||
) => {
|
||||
try {
|
||||
const dbResponse = await utilGetChatMessageFeedback(chatflowid, chatId, sortOrder, startDate, endDate)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: feedbackService.getAllChatMessageFeedback - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Add chatmessage feedback for chatflowid
|
||||
const createChatMessageFeedbackForChatflow = async (requestBody: Partial<IChatMessageFeedback>): Promise<any> => {
|
||||
try {
|
||||
const dbResponse = await utilAddChatMessageFeedback(requestBody)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: feedbackService.createChatMessageFeedbackForChatflow - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Add chatmessage feedback for chatflowid
|
||||
const updateChatMessageFeedbackForChatflow = async (chatflowId: string, requestBody: Partial<IChatMessageFeedback>): Promise<any> => {
|
||||
try {
|
||||
const dbResponse = await utilUpdateChatMessageFeedback(chatflowId, requestBody)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: feedbackService.updateChatMessageFeedbackForChatflow - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getAllChatMessageFeedback,
|
||||
createChatMessageFeedbackForChatflow,
|
||||
updateChatMessageFeedbackForChatflow
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { webCrawl, xmlScrape } from 'flowise-components'
|
||||
|
||||
const getAllLinks = async (requestUrl: string, relativeLinksMethod: string, queryLimit: string): Promise<any> => {
|
||||
try {
|
||||
const url = decodeURIComponent(requestUrl)
|
||||
if (!relativeLinksMethod) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 500,
|
||||
msg: `Please choose a Relative Links Method in Additional Parameters!`
|
||||
}
|
||||
}
|
||||
const limit = parseInt(queryLimit)
|
||||
if (process.env.DEBUG === 'true') console.info(`Start ${relativeLinksMethod}`)
|
||||
const links: string[] = relativeLinksMethod === 'webCrawl' ? await webCrawl(url, limit) : await xmlScrape(url, limit)
|
||||
if (process.env.DEBUG === 'true') console.info(`Finish ${relativeLinksMethod}`)
|
||||
const dbResponse = {
|
||||
status: 'OK',
|
||||
links
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: fetchLinksService.getAllLinks - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getAllLinks
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { findAvailableConfigs } from '../../utils'
|
||||
import { IReactFlowObject } from '../../Interface'
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import chatflowsService from '../chatflows'
|
||||
|
||||
const getSingleFlowConfig = async (chatflowId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const chatflow = await chatflowsService.getChatflowById(chatflowId)
|
||||
if (!chatflow) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Chatflow ${chatflowId} not found in the database!`
|
||||
}
|
||||
}
|
||||
const flowData = chatflow.flowData
|
||||
const parsedFlowData: IReactFlowObject = JSON.parse(flowData)
|
||||
const nodes = parsedFlowData.nodes
|
||||
const dbResponse = findAvailableConfigs(nodes, appServer.nodesPool.componentCredentials)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: flowConfigService.getSingleFlowConfig - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getSingleFlowConfig
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Client } from 'langchainhub'
|
||||
import { parsePrompt } from '../../utils/hub'
|
||||
|
||||
const createPrompt = async (promptName: string): Promise<any> => {
|
||||
try {
|
||||
let hub = new Client()
|
||||
const prompt = await hub.pull(promptName)
|
||||
const templates = parsePrompt(prompt)
|
||||
const dbResponse = {
|
||||
status: 'OK',
|
||||
prompt: promptName,
|
||||
templates: templates
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: loadPromptsService.createPrompt - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
createPrompt
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import path from 'path'
|
||||
import * as fs from 'fs'
|
||||
|
||||
// Get all templates for marketplaces
|
||||
const getAllTemplates = async () => {
|
||||
try {
|
||||
let marketplaceDir = path.join(__dirname, '..', '..', '..', 'marketplaces', 'chatflows')
|
||||
let jsonsInDir = fs.readdirSync(marketplaceDir).filter((file) => path.extname(file) === '.json')
|
||||
let templates: any[] = []
|
||||
jsonsInDir.forEach((file, index) => {
|
||||
const filePath = path.join(__dirname, '..', '..', '..', 'marketplaces', 'chatflows', file)
|
||||
const fileData = fs.readFileSync(filePath)
|
||||
const fileDataObj = JSON.parse(fileData.toString())
|
||||
const template = {
|
||||
id: index,
|
||||
templateName: file.split('.json')[0],
|
||||
flowData: fileData.toString(),
|
||||
badge: fileDataObj?.badge,
|
||||
framework: fileDataObj?.framework,
|
||||
categories: fileDataObj?.categories,
|
||||
type: 'Chatflow',
|
||||
description: fileDataObj?.description || ''
|
||||
}
|
||||
templates.push(template)
|
||||
})
|
||||
|
||||
marketplaceDir = path.join(__dirname, '..', '..', '..', 'marketplaces', 'tools')
|
||||
jsonsInDir = fs.readdirSync(marketplaceDir).filter((file) => path.extname(file) === '.json')
|
||||
jsonsInDir.forEach((file, index) => {
|
||||
const filePath = path.join(__dirname, '..', '..', '..', 'marketplaces', 'tools', file)
|
||||
const fileData = fs.readFileSync(filePath)
|
||||
const fileDataObj = JSON.parse(fileData.toString())
|
||||
const template = {
|
||||
...fileDataObj,
|
||||
id: index,
|
||||
type: 'Tool',
|
||||
framework: fileDataObj?.framework,
|
||||
badge: fileDataObj?.badge,
|
||||
categories: '',
|
||||
templateName: file.split('.json')[0]
|
||||
}
|
||||
templates.push(template)
|
||||
})
|
||||
const sortedTemplates = templates.sort((a, b) => a.templateName.localeCompare(b.templateName))
|
||||
const FlowiseDocsQnAIndex = sortedTemplates.findIndex((tmp) => tmp.templateName === 'Flowise Docs QnA')
|
||||
if (FlowiseDocsQnAIndex > 0) {
|
||||
sortedTemplates.unshift(sortedTemplates.splice(FlowiseDocsQnAIndex, 1)[0])
|
||||
}
|
||||
const dbResponse = sortedTemplates
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: marketplacesService.getAllTemplates - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getAllTemplates
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { findAvailableConfigs } from '../../utils'
|
||||
import { IReactFlowNode } from '../../Interface'
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
|
||||
const getAllNodeConfigs = async (requestBody: any) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const nodes = [{ data: requestBody }] as IReactFlowNode[]
|
||||
const dbResponse = findAvailableConfigs(nodes, appServer.nodesPool.componentCredentials)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: nodeConfigsService.getAllNodeConfigs - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getAllNodeConfigs
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import OpenAI from 'openai'
|
||||
import { decryptCredentialData } from '../../utils'
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import { Credential } from '../../database/entities/Credential'
|
||||
|
||||
// ----------------------------------------
|
||||
// Assistants
|
||||
// ----------------------------------------
|
||||
|
||||
// List available assistants
|
||||
const getAllOpenaiAssistants = async (credentialId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const credential = await appServer.AppDataSource.getRepository(Credential).findOneBy({
|
||||
id: credentialId
|
||||
})
|
||||
if (!credential) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Credential ${credentialId} not found in the database!`
|
||||
}
|
||||
}
|
||||
// Decrpyt credentialData
|
||||
const decryptedCredentialData = await decryptCredentialData(credential.encryptedData)
|
||||
const openAIApiKey = decryptedCredentialData['openAIApiKey']
|
||||
if (!openAIApiKey) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `OpenAI ApiKey not found`
|
||||
}
|
||||
}
|
||||
const openai = new OpenAI({ apiKey: openAIApiKey })
|
||||
const retrievedAssistants = await openai.beta.assistants.list()
|
||||
const dbResponse = retrievedAssistants.data
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: openaiAssistantsService.getAllOpenaiAssistants - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Get assistant object
|
||||
const getSingleOpenaiAssistant = async (credentialId: string, assistantId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const credential = await appServer.AppDataSource.getRepository(Credential).findOneBy({
|
||||
id: credentialId
|
||||
})
|
||||
if (!credential) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Credential ${credentialId} not found in the database!`
|
||||
}
|
||||
}
|
||||
// Decrpyt credentialData
|
||||
const decryptedCredentialData = await decryptCredentialData(credential.encryptedData)
|
||||
const openAIApiKey = decryptedCredentialData['openAIApiKey']
|
||||
if (!openAIApiKey) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `OpenAI ApiKey not found`
|
||||
}
|
||||
}
|
||||
|
||||
const openai = new OpenAI({ apiKey: openAIApiKey })
|
||||
const dbResponse = await openai.beta.assistants.retrieve(assistantId)
|
||||
const resp = await openai.files.list()
|
||||
const existingFiles = resp.data ?? []
|
||||
if (dbResponse.file_ids && dbResponse.file_ids.length) {
|
||||
;(dbResponse as any).files = existingFiles.filter((file) => dbResponse.file_ids.includes(file.id))
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: openaiAssistantsService.getSingleOpenaiAssistant - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getAllOpenaiAssistants,
|
||||
getSingleOpenaiAssistant
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import axios from 'axios'
|
||||
|
||||
const createPromptsList = async (requestBody: any) => {
|
||||
try {
|
||||
const tags = requestBody.tags ? `tags=${requestBody.tags}` : ''
|
||||
// Default to 100, TODO: add pagination and use offset & limit
|
||||
const url = `https://api.hub.langchain.com/repos/?limit=100&${tags}has_commits=true&sort_field=num_likes&sort_direction=desc&is_archived=false`
|
||||
const resp = await axios.get(url)
|
||||
if (resp.data.repos) {
|
||||
return {
|
||||
status: 'OK',
|
||||
repos: resp.data.repos
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return { status: 'ERROR', repos: [] }
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
createPromptsList
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { chatType } from '../../Interface'
|
||||
import { ChatMessage } from '../../database/entities/ChatMessage'
|
||||
import { utilGetChatMessage } from '../../utils/getChatMessage'
|
||||
import { ChatMessageFeedback } from '../../database/entities/ChatMessageFeedback'
|
||||
|
||||
// get stats for showing in chatflow
|
||||
const getChatflowStats = async (
|
||||
chatflowid: string,
|
||||
chatTypeFilter: chatType | undefined,
|
||||
startDate?: string,
|
||||
endDate?: string,
|
||||
messageId?: string,
|
||||
feedback?: boolean
|
||||
): Promise<any> => {
|
||||
try {
|
||||
const chatmessages = (await utilGetChatMessage(
|
||||
chatflowid,
|
||||
chatTypeFilter,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
startDate,
|
||||
endDate,
|
||||
messageId,
|
||||
feedback
|
||||
)) as Array<ChatMessage & { feedback?: ChatMessageFeedback }>
|
||||
const totalMessages = chatmessages.length
|
||||
const totalFeedback = chatmessages.filter((message) => message?.feedback).length
|
||||
const positiveFeedback = chatmessages.filter((message) => message?.feedback?.rating === 'THUMBS_UP').length
|
||||
const dbResponse = {
|
||||
totalMessages,
|
||||
totalFeedback,
|
||||
positiveFeedback
|
||||
}
|
||||
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: statsService.getChatflowStats - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getChatflowStats
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
|
||||
const createEvent = async (eventInfo: any) => {
|
||||
const appServer = getRunningExpressApp()
|
||||
await appServer.telemetry.sendTelemetry(eventInfo.name, eventInfo.data)
|
||||
}
|
||||
|
||||
export default {
|
||||
createEvent
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import { Tool } from '../../database/entities/Tool'
|
||||
import { getAppVersion } from '../../utils'
|
||||
|
||||
const creatTool = async (requestBody: any): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const newTool = new Tool()
|
||||
Object.assign(newTool, requestBody)
|
||||
const tool = await appServer.AppDataSource.getRepository(Tool).create(newTool)
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Tool).save(tool)
|
||||
await appServer.telemetry.sendTelemetry('tool_created', {
|
||||
version: await getAppVersion(),
|
||||
toolId: dbResponse.id,
|
||||
toolName: dbResponse.name
|
||||
})
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: toolsService.creatTool - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const deleteTool = async (toolId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Tool).delete({
|
||||
id: toolId
|
||||
})
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: toolsService.deleteTool - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getAllTools = async (): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Tool).find()
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: toolsService.getAllTools - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getToolById = async (toolId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Tool).findOneBy({
|
||||
id: toolId
|
||||
})
|
||||
if (!dbResponse) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Tool ${toolId} not found`
|
||||
}
|
||||
}
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: toolsService.getToolById - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const updateTool = async (toolId: string, toolBody: any): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const tool = await appServer.AppDataSource.getRepository(Tool).findOneBy({
|
||||
id: toolId
|
||||
})
|
||||
if (!tool) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: `Tool ${toolId} not found`
|
||||
}
|
||||
}
|
||||
const updateTool = new Tool()
|
||||
Object.assign(updateTool, toolBody)
|
||||
await appServer.AppDataSource.getRepository(Tool).merge(tool, updateTool)
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Tool).save(tool)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: toolsService.getToolById - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
creatTool,
|
||||
deleteTool,
|
||||
getAllTools,
|
||||
getToolById,
|
||||
updateTool
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
|
||||
import { Variable } from '../../database/entities/Variable'
|
||||
|
||||
const createVariable = async (newVariable: Variable) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const variable = await appServer.AppDataSource.getRepository(Variable).create(newVariable)
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Variable).save(variable)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: variablesServices.createVariable - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const deleteVariable = async (variableId: string): Promise<any> => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Variable).delete({ id: variableId })
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: variablesServices.createVariable - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getAllVariables = async () => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Variable).find()
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: variablesServices.getAllVariables - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const getVariableById = async (variableId: string) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Variable).findOneBy({
|
||||
id: variableId
|
||||
})
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: variablesServices.getVariableById - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
const updateVariable = async (variable: Variable, updatedVariable: Variable) => {
|
||||
try {
|
||||
const appServer = getRunningExpressApp()
|
||||
const tmpUpdatedVariable = await appServer.AppDataSource.getRepository(Variable).merge(variable, updatedVariable)
|
||||
const dbResponse = await appServer.AppDataSource.getRepository(Variable).save(tmpUpdatedVariable)
|
||||
return dbResponse
|
||||
} catch (error) {
|
||||
throw new Error(`Error: variablesServices.updateVariable - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
createVariable,
|
||||
deleteVariable,
|
||||
getAllVariables,
|
||||
getVariableById,
|
||||
updateVariable
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Request, Response } from 'express'
|
||||
import { upsertVector } from '../../utils/upsertVector'
|
||||
|
||||
const upsertVectorMiddleware = async (req: Request, res: Response, isInternal: boolean = false) => {
|
||||
try {
|
||||
await upsertVector(req, res, isInternal)
|
||||
} catch (error) {
|
||||
throw new Error(`Error: vectorsService.getRateLimiter - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
upsertVectorMiddleware
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import path from 'path'
|
||||
import * as fs from 'fs'
|
||||
|
||||
const getVersion = async () => {
|
||||
try {
|
||||
const getPackageJsonPath = (): string => {
|
||||
const checkPaths = [
|
||||
path.join(__dirname, '..', 'package.json'),
|
||||
path.join(__dirname, '..', '..', 'package.json'),
|
||||
path.join(__dirname, '..', '..', '..', 'package.json'),
|
||||
path.join(__dirname, '..', '..', '..', '..', 'package.json'),
|
||||
path.join(__dirname, '..', '..', '..', '..', '..', 'package.json')
|
||||
]
|
||||
for (const checkPath of checkPaths) {
|
||||
if (fs.existsSync(checkPath)) {
|
||||
return checkPath
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
const packagejsonPath = getPackageJsonPath()
|
||||
if (!packagejsonPath) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 404,
|
||||
msg: 'Version not found'
|
||||
}
|
||||
}
|
||||
try {
|
||||
const content = await fs.promises.readFile(packagejsonPath, 'utf8')
|
||||
const parsedContent = JSON.parse(content)
|
||||
return {
|
||||
version: parsedContent.version
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
executionError: true,
|
||||
status: 500,
|
||||
msg: `Version not found: ${error}`
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(`Error: versionService.getVersion - ${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getVersion
|
||||
}
|
||||
Reference in New Issue
Block a user