import { z } from "zod";
import { strapiClient } from "../services/strapi-client.js";
export const batchUpdateToolSchema = z.object({
contentType: z
.string()
.describe('Nombre PLURAL del content type (ej: "products", "articles")'),
entries: z
.array(
z.object({
documentId: z.string().describe("documentId de la entrada a actualizar"),
data: z
.record(z.any())
.describe(
"Datos a actualizar (actualización parcial). Solo incluye los campos que quieres cambiar. " +
"IMPORTANTE para campos media: usar ID numérico (no documentId). " +
"Ejemplo: image: 3 (no image: 'uka5h08v4osgn1w0g89m43z8'). " +
"Obtén IDs numéricos de strapi-search-media o strapi-get-media."
),
populate: z
.array(z.string())
.optional()
.describe("Relaciones a poblar"),
locale: z
.string()
.optional()
.describe(
'Locale para actualizar una localización específica en i18n (ej: "en", "es", "ca")'
),
})
)
.min(1)
.describe(
"Array de entradas a actualizar. Cada entrada contiene documentId, data, populate (opcional), y locale (opcional)"
),
continueOnError: z
.boolean()
.optional()
.default(true)
.describe(
"Continuar actualizando otras entradas si alguna falla (default: true)"
),
});
export const batchUpdateToolHandler = async (params: {
contentType: string;
entries: Array<{
documentId: string;
data: Record<string, any>;
populate?: string[];
locale?: string;
}>;
continueOnError?: boolean;
}) => {
try {
console.error(
`[BATCH UPDATE TOOL] Updating ${params.entries.length} entries in ${params.contentType}`
);
const results = {
total: params.entries.length,
successful: 0,
failed: 0,
entries: [] as Array<{
index: number;
documentId: string;
success: boolean;
error?: string;
}>,
};
// Procesar en paralelo
const promises = params.entries.map((entry, index) =>
(async () => {
try {
console.error(
`[BATCH UPDATE TOOL] Updating entry ${index + 1}/${
params.entries.length
} (${entry.documentId})${entry.locale ? ` (locale: ${entry.locale})` : ""}`
);
const result = await strapiClient.update({
contentType: params.contentType,
documentId: entry.documentId,
data: entry.data,
populate: entry.populate,
locale: entry.locale,
});
results.successful++;
results.entries.push({
index,
documentId: entry.documentId,
success: true,
});
console.error(
`[BATCH UPDATE TOOL] Entry ${index + 1} updated successfully: ${entry.documentId}`
);
} catch (error) {
results.failed++;
const errorMessage =
error instanceof Error ? error.message : "Unknown error";
results.entries.push({
index,
documentId: entry.documentId,
success: false,
error: errorMessage,
});
console.error(
`[BATCH UPDATE TOOL ERROR] Entry ${index + 1} (${entry.documentId}) failed: ${errorMessage}`
);
// Si continueOnError es false, relanzar el error
if (!params.continueOnError) {
throw error;
}
}
})()
);
// Esperar a que todas las promesas se completen
await Promise.all(promises);
const summary =
results.successful === params.entries.length
? "✅ All entries updated successfully"
: `⚠️ Updated ${results.successful}/${params.entries.length} entries (${results.failed} failed)`;
return {
content: [
{
type: "text" as const,
text: `${summary}\n\n${JSON.stringify(results, null, 2)}`,
},
],
structuredContent: results,
};
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : "Unknown error";
console.error(`[BATCH UPDATE TOOL ERROR] ${errorMessage}`);
return {
content: [
{
type: "text" as const,
text: `Error in batch update operation for ${params.contentType}:\n\n${errorMessage}`,
},
],
isError: true,
};
}
};