Receba novidades do Hedhog no seu e-mail
Novos lançamentos, receitas e breaking changes — sem spam.
Submódulo cms
layouts
Gerencia layouts de página reutilizáveis (um arranjo nomeado de regiões, como header/main/sidebar) que as páginas referenciam via layout_slug, além do CRUD sobre as regiões de cada layout.
Caminho de origem: libraries/cms/src/cms-layout.controller.ts, cms-layout.service.ts
Arquivo do módulo: cms.module.ts
Introdução
O submódulo Layouts é dono de `cms_layout` e de sua tabela filha `cms_layout_region`. Um layout tem um `type` (vertical, horizontal, grid, blog_post, custom), um `schema` e um `default_config` opcionais (ambos JSON de forma livre), um flag `is_active` e um nome/descrição traduzidos por locale, armazenados em uma tabela complementar `cms_layout_locale`. As regiões pertencem a exatamente um layout via `layout_id`, carregam um `code` que deve ser único dentro daquele layout (por exemplo, "header", "main", "sidebar"), uma `order`, um blob JSON `config` opcional e seu próprio nome/descrição traduzidos por locale em `cms_layout_region_locale`. O `layout_slug` de uma página é resolvido para `layout_id` no momento de criação/atualização da página pelo submódulo Pages, e toda instância de componente posicionada em uma página deve referenciar um dos códigos de região do próprio layout dessa página — é essa relação região/layout que o `saveComponents` do submódulo Pages valida.
A criação e a atualização, tanto de layouts quanto de regiões, seguem o mesmo padrão de duas etapas usado em todo o módulo CMS: a linha base é escrita primeiro e, em seguida, cada entrada do mapa `locale` sofre upsert — atualizada se já existir uma linha `cms_layout_locale`/`cms_layout_region_locale` para aquele locale, ou criada caso contrário — de modo que enviar uma tradução para apenas um locale nunca afeta os demais. Nem layouts nem regiões são excluídos logicamente: `DELETE /cms/layouts/:id` e `DELETE /cms/layouts/:id/regions/:regionId` emitem um `.delete()` físico do Prisma. As exclusões de região têm ainda escopo em seu layout pai (`layout_id` deve corresponder ao `:id` no caminho), de modo que um ID de região pertencente a um layout diferente retorna 404 em vez de excluir entre layouts.
Não há guarda explícita em `CmsLayoutService` contra a exclusão de um layout que páginas ainda referenciam — a proteção vem inteiramente do banco de dados: `cms_page.layout_id` é declarado `onDelete: RESTRICT` no YAML da tabela, de modo que tentar excluir um layout em uso se manifesta como uma falha bruta de restrição de foreign key, e não como um erro amigável no nível da aplicação. O formato da resposta também inclui um campo `pages_count`, destinado a mostrar quantas páginas usam um layout, mas as consultas Prisma subjacentes em `list()` e `getById()` não solicitam uma relação `_count` — `mapLayout()` lê `layout._count?.cms_page ?? 0`, que na prática é sempre `undefined`, de modo que `pages_count` atualmente reporta `0` para todos os layouts, independentemente do uso real.
Diferentemente de Pages, onde o `cms-editor` pode criar e atualizar conteúdo, todo endpoint de escrita deste submódulo (tanto de layouts quanto de regiões) é restrito apenas a `admin`/`admin-cms` — os editores de conteúdo podem ler os layouts para escolher um para uma página, mas não podem definir nem modificar layouts ou suas regiões.
Endpoints HTTP
9 endpoints
Listagem completa de layouts (não paginada), cada um com suas regiões incorporadas, ordenados por ID. Nomes/descrições são resolvidos para o locale da requisição (com fallback para a primeira tradução disponível).
- Query
- slug? — filter to a single layout by slug
Cria um novo layout e suas linhas de nome/descrição por locale.
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| slug | string | yes | — |
| type | CmsLayoutType (vertical | horizontal | grid | blog_post | custom) | no | Default: vertical |
| is_active | boolean | no | Default: true |
| schema | object | no | — |
| default_config | object | no | — |
| locale | Record<string, { name: string; description?: string }> | yes | e.g. { "en": { "name": "...", "description": "..." } } — upserts one locale row per key |
Obtém um único layout com suas regiões, localizado para o locale da requisição.
- Params
- id (int)
Atualiza um layout (mesmos campos da criação, todos opcionais). As entradas de locale sofrem upsert individualmente, deixando intactos os locales não informados.
- Params
- id (int)
Exclui fisicamente um layout. Não protegido no nível do serviço — falha com um erro de foreign key do banco de dados se alguma página ainda o referenciar (cms_page.layout_id é RESTRICT).
- Params
- id (int)
Lista as regiões de um layout, ordenadas pelo campo order, localizadas para o locale da requisição.
- Params
- id (int) — layout ID
Adiciona uma região a um layout e suas linhas de nome/descrição por locale.
- Params
- id (int) — layout ID
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| code | string | yes | Unique within the layout, e.g. "header", "main" |
| order | number | no | Default: 0 |
| config | object | no | — |
| locale | Record<string, { name: string; description?: string }> | yes | e.g. { "en": { "name": "...", "description": "..." } } — upserts one locale row per key |
Atualiza uma região (mesmos campos da criação, todos opcionais). Rejeita com 404 se regionId não pertencer ao layout id.
- Params
- id (int) — layout ID, regionId (int)
Exclui fisicamente uma região. Rejeita com 404 se regionId não pertencer ao layout id. Quaisquer linhas cms_page_component apontando para a região estão sujeitas à sua foreign key RESTRICT, de modo que excluir uma região ainda em uso por componentes de página falhará no nível do banco de dados.
- Params
- id (int) — layout ID, regionId (int)