* Update an existing connector-sourced document with new content. * Updates in-place to avoid unique constraint violations on (connectorId, externalId).
( existingDocId: string, knowledgeBaseId: string, connectorId: string, connectorType: string, extDoc: ExternalDocument, kbOwner: KnowledgeBaseOwner, sourceConfig?: Record<string, unknown> )
| 1253 | * Updates in-place to avoid unique constraint violations on (connectorId, externalId). |
| 1254 | */ |
| 1255 | async function updateDocument( |
| 1256 | existingDocId: string, |
| 1257 | knowledgeBaseId: string, |
| 1258 | connectorId: string, |
| 1259 | connectorType: string, |
| 1260 | extDoc: ExternalDocument, |
| 1261 | kbOwner: KnowledgeBaseOwner, |
| 1262 | sourceConfig?: Record<string, unknown> |
| 1263 | ): Promise<DocumentData> { |
| 1264 | // Fetch old file URL before uploading replacement |
| 1265 | const existingRows = await db |
| 1266 | .select({ fileUrl: document.fileUrl }) |
| 1267 | .from(document) |
| 1268 | .where(eq(document.id, existingDocId)) |
| 1269 | .limit(1) |
| 1270 | const oldFileUrl = existingRows[0]?.fileUrl |
| 1271 | |
| 1272 | const contentBuffer = Buffer.from(extDoc.content, 'utf-8') |
| 1273 | const safeTitle = sanitizeStorageTitle(extDoc.title) |
| 1274 | const customKey = `kb/${Date.now()}-${existingDocId}-${safeTitle}.txt` |
| 1275 | |
| 1276 | const fileInfo = await StorageService.uploadFile({ |
| 1277 | file: contentBuffer, |
| 1278 | fileName: `${safeTitle}.txt`, |
| 1279 | contentType: 'text/plain', |
| 1280 | context: 'knowledge-base', |
| 1281 | customKey, |
| 1282 | preserveKey: true, |
| 1283 | metadata: kbOwnershipMetadata(kbOwner, `${safeTitle}.txt`), |
| 1284 | }) |
| 1285 | |
| 1286 | const fileUrl = `${getInternalApiBaseUrl()}${fileInfo.path}?context=knowledge-base` |
| 1287 | |
| 1288 | const tagValues = extDoc.metadata |
| 1289 | ? resolveTagMapping(connectorType, extDoc.metadata, sourceConfig) |
| 1290 | : undefined |
| 1291 | |
| 1292 | const processingFilename = `${safeTitle}.txt` |
| 1293 | |
| 1294 | try { |
| 1295 | await db.transaction(async (tx) => { |
| 1296 | const isActive = await isKnowledgeBaseActiveInTx(tx, knowledgeBaseId) |
| 1297 | if (!isActive) { |
| 1298 | throw new Error(`Knowledge base ${knowledgeBaseId} is deleted`) |
| 1299 | } |
| 1300 | |
| 1301 | await tx |
| 1302 | .update(document) |
| 1303 | .set({ |
| 1304 | filename: extDoc.title, |
| 1305 | fileUrl, |
| 1306 | storageKey: fileInfo.key, |
| 1307 | fileSize: contentBuffer.length, |
| 1308 | contentHash: extDoc.contentHash, |
| 1309 | sourceUrl: extDoc.sourceUrl ?? null, |
| 1310 | ...tagValues, |
| 1311 | processingStatus: 'pending', |
| 1312 | uploadedAt: new Date(), |
no test coverage detected