{"version":3,"file":"_hookName_.mjs","names":[],"sources":["../../../../../../../src/astro/routes/api/admin/hooks/exclusive/[hookName].ts"],"sourcesContent":["/**\n * Exclusive hook selection endpoint\n *\n * PUT /_emdash/api/admin/hooks/exclusive/:hookName\n *\n * Sets or clears the selected provider for an exclusive hook.\n * Body: { pluginId: string | null }\n * Requires settings:manage permission.\n */\n\nimport type { APIRoute } from \"astro\";\nimport { z } from \"zod\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError, apiSuccess, handleError } from \"#api/error.js\";\nimport { isParseError, parseBody } from \"#api/parse.js\";\nimport { OptionsRepository } from \"#db/repositories/options.js\";\n\nexport const prerender = false;\n\n/** Hook name format: namespace:action (e.g., \"content:beforeSave\") */\nconst HOOK_NAME_RE = /^[a-z]+:[a-zA-Z]+$/;\n\nconst setSelectionSchema = z.object({\n\tpluginId: z.string().min(1).nullable(),\n});\n\nexport const PUT: APIRoute = async ({ params, request, locals }) => {\n\tconst { emdash, user } = locals;\n\n\tif (!emdash?.db) {\n\t\treturn apiError(\"NOT_CONFIGURED\", \"EmDash is not initialized\", 500);\n\t}\n\n\tconst denied = requirePerm(user, \"settings:manage\");\n\tif (denied) return denied;\n\n\tconst hookName = params.hookName;\n\tif (!hookName) {\n\t\treturn apiError(\"VALIDATION_ERROR\", \"Hook name is required\", 400);\n\t}\n\n\t// Validate hook name format: must be namespace:action (e.g., \"content:beforeSave\")\n\tif (!HOOK_NAME_RE.test(hookName)) {\n\t\treturn apiError(\"VALIDATION_ERROR\", \"Invalid hook name format\", 400);\n\t}\n\n\ttry {\n\t\tconst pipeline = emdash.hooks;\n\n\t\t// Verify this is actually an exclusive hook\n\t\tif (!pipeline.isExclusiveHook(hookName)) {\n\t\t\treturn apiError(\"NOT_FOUND\", `Hook '${hookName}' is not a registered exclusive hook`, 404);\n\t\t}\n\n\t\tconst body = await parseBody(request, setSelectionSchema);\n\t\tif (isParseError(body)) return body;\n\n\t\tconst optionsRepo = new OptionsRepository(emdash.db);\n\t\tconst optionKey = `emdash:exclusive_hook:${hookName}`;\n\n\t\tif (body.pluginId === null) {\n\t\t\t// Clear the selection\n\t\t\tawait optionsRepo.delete(optionKey);\n\t\t\tpipeline.clearExclusiveSelection(hookName);\n\t\t} else {\n\t\t\t// Validate that the pluginId is an actual provider for this hook\n\t\t\tconst providers = pipeline.getExclusiveHookProviders(hookName);\n\t\t\tconst isValidProvider = providers.some(\n\t\t\t\t(p: { pluginId: string }) => p.pluginId === body.pluginId,\n\t\t\t);\n\t\t\tif (!isValidProvider) {\n\t\t\t\treturn apiError(\n\t\t\t\t\t\"VALIDATION_ERROR\",\n\t\t\t\t\t`Plugin '${body.pluginId}' is not a provider for hook '${hookName}'`,\n\t\t\t\t\t400,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tawait optionsRepo.set(optionKey, body.pluginId);\n\t\t\tpipeline.setExclusiveSelection(hookName, body.pluginId);\n\t\t}\n\n\t\treturn apiSuccess({\n\t\t\thookName,\n\t\t\tselectedPluginId: body.pluginId,\n\t\t});\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to set exclusive hook selection\", \"EXCLUSIVE_HOOK_SET_ERROR\");\n\t}\n};\n"],"mappings":";;;;;;;;;AAkBA,MAAa,YAAY;;AAGzB,MAAM,eAAe;AAErB,MAAM,qBAAqB,EAAE,OAAO,EACnC,UAAU,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU,EACtC,CAAC;AAEF,MAAa,MAAgB,OAAO,EAAE,QAAQ,SAAS,aAAa;CACnE,MAAM,EAAE,QAAQ,SAAS;AAEzB,KAAI,CAAC,QAAQ,GACZ,QAAO,SAAS,kBAAkB,6BAA6B,IAAI;CAGpE,MAAM,SAAS,YAAY,MAAM,kBAAkB;AACnD,KAAI,OAAQ,QAAO;CAEnB,MAAM,WAAW,OAAO;AACxB,KAAI,CAAC,SACJ,QAAO,SAAS,oBAAoB,yBAAyB,IAAI;AAIlE,KAAI,CAAC,aAAa,KAAK,SAAS,CAC/B,QAAO,SAAS,oBAAoB,4BAA4B,IAAI;AAGrE,KAAI;EACH,MAAM,WAAW,OAAO;AAGxB,MAAI,CAAC,SAAS,gBAAgB,SAAS,CACtC,QAAO,SAAS,aAAa,SAAS,SAAS,uCAAuC,IAAI;EAG3F,MAAM,OAAO,MAAM,UAAU,SAAS,mBAAmB;AACzD,MAAI,aAAa,KAAK,CAAE,QAAO;EAE/B,MAAM,cAAc,IAAI,kBAAkB,OAAO,GAAG;EACpD,MAAM,YAAY,yBAAyB;AAE3C,MAAI,KAAK,aAAa,MAAM;AAE3B,SAAM,YAAY,OAAO,UAAU;AACnC,YAAS,wBAAwB,SAAS;SACpC;AAMN,OAAI,CAJc,SAAS,0BAA0B,SAAS,CAC5B,MAChC,MAA4B,EAAE,aAAa,KAAK,SACjD,CAEA,QAAO,SACN,oBACA,WAAW,KAAK,SAAS,gCAAgC,SAAS,IAClE,IACA;AAGF,SAAM,YAAY,IAAI,WAAW,KAAK,SAAS;AAC/C,YAAS,sBAAsB,UAAU,KAAK,SAAS;;AAGxD,SAAO,WAAW;GACjB;GACA,kBAAkB,KAAK;GACvB,CAAC;UACM,OAAO;AACf,SAAO,YAAY,OAAO,0CAA0C,2BAA2B"}