145 lines
6.3 KiB
JavaScript
145 lines
6.3 KiB
JavaScript
import { z } from "zod";
|
|
import { withAuth } from "../../auth/index.js";
|
|
import { withAuthParams } from "../helpers/authSchema.js";
|
|
import { handleToolError } from "../helpers/errorHandler.js";
|
|
import { pythonGet, pythonPost } from "../helpers/pythonServerClient.js";
|
|
import { getCurrentProjectInfo } from "../files/helpers.js";
|
|
import { canEditCode } from "../helpers/roleCheck.js";
|
|
|
|
/**
|
|
* Tools para leer/escribir el `middleWare` de hooks globales del layout.
|
|
*
|
|
* El middleware vive en `layout.json["hooks"][i].middleWare` y determina cuando
|
|
* un hook global se ejecuta automaticamente antes de renderizar paginas:
|
|
* - [] → solo cuando se llama explicitamente.
|
|
* - ["allurls"] → antes de cada URL del sitio.
|
|
* - ["<tableName>-<num>", ...] → solo antes de ciertos registros.
|
|
*/
|
|
|
|
function registerGetHookMiddlewareTool(server) {
|
|
server.tool(
|
|
"get_hook_middleware",
|
|
`Check which pages trigger a global hook as middleware. Middleware config determines whether the hook runs automatically BEFORE rendering specific pages (or all pages). Returns the list of middleware entries.
|
|
|
|
Use this when the user asks about hook behavior or to verify config before changing it.
|
|
|
|
hookEndPoint format: starts and ends with '/', with '/' as separator. E.g. file "hooks/hooks.parse_styles.php" → endPoint "/hooks/parse_styles/".
|
|
|
|
Returns:
|
|
- middleWare: [] → hook only runs on explicit call (<hook>, Twig filter, CmsApi).
|
|
- middleWare: ["allurls"] → runs before every page.
|
|
- middleWare: ["cms_apartados-8", ...] → runs before those specific records ("<tableName>-<num>").`,
|
|
withAuthParams({
|
|
hookEndPoint: z.string().describe('Hook endpoint path, e.g. "/hooks/parse_styles/"'),
|
|
}),
|
|
{ readOnlyHint: true, destructiveHint: false },
|
|
withAuth(async ({ hookEndPoint }, extra) => {
|
|
try {
|
|
const { projectSlug } = getCurrentProjectInfo();
|
|
const result = await pythonGet("/api/creator/hook-middleware", {
|
|
project: projectSlug,
|
|
endPoint: hookEndPoint,
|
|
});
|
|
if (!result?.success) {
|
|
return {
|
|
content: [{
|
|
type: "text",
|
|
text: JSON.stringify({
|
|
success: false,
|
|
error: result?.error || "No se pudo leer el middleware",
|
|
}),
|
|
}],
|
|
isError: true,
|
|
};
|
|
}
|
|
return {
|
|
content: [{
|
|
type: "text",
|
|
text: JSON.stringify({
|
|
success: true,
|
|
exists: !!result.exists,
|
|
middleWare: result.middleWare || [],
|
|
hookEndPoint,
|
|
}, null, 2),
|
|
}],
|
|
};
|
|
} catch (error) {
|
|
return handleToolError(error, "get_hook_middleware", { hookEndPoint });
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
function registerSetHookMiddlewareTool(server) {
|
|
server.tool(
|
|
"set_hook_middleware",
|
|
`Configure when a global hook runs automatically (middleware). This updates layout.json['hooks'][i].middleWare for the hook matching hookEndPoint.
|
|
|
|
Use this AFTER creating or editing a hook file (via acai-write) if the hook should execute BEFORE rendering specific pages. The hook file alone is not enough — the file exists but won't auto-run as middleware without this config.
|
|
|
|
middleWare values:
|
|
- [] → hook runs only when called explicitly (default for new hooks).
|
|
- ["allurls"] → runs before every page of the site.
|
|
- ["<tableName>-<num>", ...] → runs before specific records. Get num+tableName from the CMS records.
|
|
|
|
Examples:
|
|
- Redirect logic that must run on the homepage only: middleWare=["cms_apartados-2"] (assuming num=2 is home).
|
|
- Global analytics injection: middleWare=["allurls"].
|
|
- Just a reusable utility hook called from modules/twig: middleWare=[] (default).`,
|
|
withAuthParams({
|
|
hookEndPoint: z.string().describe('Hook endpoint path, e.g. "/hooks/parse_styles/"'),
|
|
middleWare: z.array(z.string()).describe('Array de strings. Vacio, ["allurls"], o ["<tableName>-<num>", ...]'),
|
|
}),
|
|
{ readOnlyHint: false, destructiveHint: false },
|
|
withAuth(async ({ hookEndPoint, middleWare }, extra) => {
|
|
try {
|
|
const { projectSlug } = getCurrentProjectInfo();
|
|
const result = await pythonPost("/api/creator/hook-middleware", {
|
|
project: projectSlug,
|
|
endPoint: hookEndPoint,
|
|
middleWare,
|
|
});
|
|
if (!result?.success) {
|
|
return {
|
|
content: [{
|
|
type: "text",
|
|
text: JSON.stringify({
|
|
success: false,
|
|
error: result?.error || "No se pudo guardar",
|
|
}),
|
|
}],
|
|
isError: true,
|
|
};
|
|
}
|
|
return {
|
|
content: [{
|
|
type: "text",
|
|
text: JSON.stringify({
|
|
success: true,
|
|
message: "Middleware actualizado",
|
|
middleWare: result.middleWare || [],
|
|
hookEndPoint,
|
|
}, null, 2),
|
|
}],
|
|
};
|
|
} catch (error) {
|
|
return handleToolError(error, "set_hook_middleware", { hookEndPoint, middleWare });
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Registra las tools de configuracion de hooks globales.
|
|
*
|
|
* `get_hook_middleware` es de solo lectura y se registra siempre. El set
|
|
* modifica el layout y solo se expone si el rol puede editar codigo — sigue
|
|
* el mismo criterio que otras tools de escritura (ver project/index.js).
|
|
*/
|
|
export function registerHookTools(server) {
|
|
registerGetHookMiddlewareTool(server);
|
|
if (canEditCode()) {
|
|
registerSetHookMiddlewareTool(server);
|
|
}
|
|
}
|