{"version":3,"file":"index.mjs","names":[],"sources":["../../../../../src/astro/routes/api/widget-areas/index.ts"],"sourcesContent":["/**\n * Widget areas list and create endpoints\n *\n * GET  /_emdash/api/widget-areas - List all widget areas\n * POST /_emdash/api/widget-areas - Create widget area\n */\n\nimport type { APIRoute } from \"astro\";\nimport { ulid } from \"ulidx\";\n\nimport { requirePerm } from \"#api/authorize.js\";\nimport { apiError, apiSuccess, handleError } from \"#api/error.js\";\nimport { isParseError, parseBody } from \"#api/parse.js\";\nimport { createWidgetAreaBody } from \"#api/schemas.js\";\nimport { rowToWidget } from \"#widgets/index.js\";\nimport type { WidgetRow } from \"#widgets/types.js\";\n\nexport const prerender = false;\n\nexport const GET: APIRoute = async ({ locals }) => {\n\tconst { emdash, user } = locals;\n\tconst db = emdash.db;\n\n\tconst denied = requirePerm(user, \"widgets:read\");\n\tif (denied) return denied;\n\n\ttry {\n\t\tconst areas = await db\n\t\t\t.selectFrom(\"_emdash_widget_areas\")\n\t\t\t.selectAll()\n\t\t\t.orderBy(\"name\", \"asc\")\n\t\t\t.execute();\n\n\t\t// Get widgets for each area (needed for drag-and-drop reordering in admin UI)\n\t\tconst areasWithWidgets = await Promise.all(\n\t\t\tareas.map(async (area) => {\n\t\t\t\tconst widgets = await db\n\t\t\t\t\t.selectFrom(\"_emdash_widgets\")\n\t\t\t\t\t.selectAll()\n\t\t\t\t\t.$castTo<WidgetRow>()\n\t\t\t\t\t.where(\"area_id\", \"=\", area.id)\n\t\t\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t\t\t.execute();\n\n\t\t\t\treturn {\n\t\t\t\t\t...area,\n\t\t\t\t\twidgets: widgets.map((row) => rowToWidget(row)),\n\t\t\t\t\twidgetCount: widgets.length,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\n\t\treturn apiSuccess({ items: areasWithWidgets });\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to fetch widget areas\", \"WIDGET_AREA_LIST_ERROR\");\n\t}\n};\n\nexport const POST: APIRoute = async ({ request, locals }) => {\n\tconst { emdash, user } = locals;\n\tconst db = emdash.db;\n\n\tconst denied = requirePerm(user, \"widgets:manage\");\n\tif (denied) return denied;\n\n\ttry {\n\t\tconst body = await parseBody(request, createWidgetAreaBody);\n\t\tif (isParseError(body)) return body;\n\n\t\t// Check if area name already exists\n\t\tconst existing = await db\n\t\t\t.selectFrom(\"_emdash_widget_areas\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"name\", \"=\", body.name)\n\t\t\t.executeTakeFirst();\n\n\t\tif (existing) {\n\t\t\treturn apiError(\"CONFLICT\", `Widget area with name \"${body.name}\" already exists`, 409);\n\t\t}\n\n\t\tconst id = ulid();\n\t\tawait db\n\t\t\t.insertInto(\"_emdash_widget_areas\")\n\t\t\t.values({\n\t\t\t\tid,\n\t\t\t\tname: body.name,\n\t\t\t\tlabel: body.label,\n\t\t\t\tdescription: body.description ?? null,\n\t\t\t})\n\t\t\t.execute();\n\n\t\tconst area = await db\n\t\t\t.selectFrom(\"_emdash_widget_areas\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirstOrThrow();\n\n\t\treturn apiSuccess(area, 201);\n\t} catch (error) {\n\t\treturn handleError(error, \"Failed to create widget area\", \"WIDGET_AREA_CREATE_ERROR\");\n\t}\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,MAAa,YAAY;AAEzB,MAAa,MAAgB,OAAO,EAAE,aAAa;CAClD,MAAM,EAAE,QAAQ,SAAS;CACzB,MAAM,KAAK,OAAO;CAElB,MAAM,SAAS,YAAY,MAAM,eAAe;AAChD,KAAI,OAAQ,QAAO;AAEnB,KAAI;EACH,MAAM,QAAQ,MAAM,GAClB,WAAW,uBAAuB,CAClC,WAAW,CACX,QAAQ,QAAQ,MAAM,CACtB,SAAS;AAqBX,SAAO,WAAW,EAAE,OAlBK,MAAM,QAAQ,IACtC,MAAM,IAAI,OAAO,SAAS;GACzB,MAAM,UAAU,MAAM,GACpB,WAAW,kBAAkB,CAC7B,WAAW,CACX,SAAoB,CACpB,MAAM,WAAW,KAAK,KAAK,GAAG,CAC9B,QAAQ,cAAc,MAAM,CAC5B,SAAS;AAEX,UAAO;IACN,GAAG;IACH,SAAS,QAAQ,KAAK,QAAQ,YAAY,IAAI,CAAC;IAC/C,aAAa,QAAQ;IACrB;IACA,CACF,EAE4C,CAAC;UACtC,OAAO;AACf,SAAO,YAAY,OAAO,gCAAgC,yBAAyB;;;AAIrF,MAAa,OAAiB,OAAO,EAAE,SAAS,aAAa;CAC5D,MAAM,EAAE,QAAQ,SAAS;CACzB,MAAM,KAAK,OAAO;CAElB,MAAM,SAAS,YAAY,MAAM,iBAAiB;AAClD,KAAI,OAAQ,QAAO;AAEnB,KAAI;EACH,MAAM,OAAO,MAAM,UAAU,SAAS,qBAAqB;AAC3D,MAAI,aAAa,KAAK,CAAE,QAAO;AAS/B,MANiB,MAAM,GACrB,WAAW,uBAAuB,CAClC,OAAO,KAAK,CACZ,MAAM,QAAQ,KAAK,KAAK,KAAK,CAC7B,kBAAkB,CAGnB,QAAO,SAAS,YAAY,0BAA0B,KAAK,KAAK,mBAAmB,IAAI;EAGxF,MAAM,KAAK,MAAM;AACjB,QAAM,GACJ,WAAW,uBAAuB,CAClC,OAAO;GACP;GACA,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,aAAa,KAAK,eAAe;GACjC,CAAC,CACD,SAAS;AAQX,SAAO,WANM,MAAM,GACjB,WAAW,uBAAuB,CAClC,WAAW,CACX,MAAM,MAAM,KAAK,GAAG,CACpB,yBAAyB,EAEH,IAAI;UACpB,OAAO;AACf,SAAO,YAAY,OAAO,gCAAgC,2BAA2B"}