Seu primeiro plugin nativo

Nesta página

Um plugin nativo é um pacote npm que EmDash importa no mesmo processo do site Astro. Este tutorial cria um plugin que registra salvamentos de conteúdo, instala-o em um site e o registra em astro.config.mjs.

Use o formato nativo quando o plugin precisar de um recurso in-process como componentes de administração React, componentes de renderização Astro ou fragmentos de página confiáveis. Se hooks, rotas, storage e Block Kit cobrirem o recurso, comece com um plugin sandboxed. Escolher um formato de plugin compara os formatos.

Pré-requisitos

Comece com um site EmDash que use pnpm e possa executar seu servidor de desenvolvimento. O site já deve depender de emdash, que fornece o comando emdash usado abaixo.

Os comandos chamam o diretório do site de my-emdash-site e criam plugin-activity ao lado. Substitua my-emdash-site pelo nome do diretório do seu site.

Criar e registrar o pacote

  1. Gere um pacote nativo ao lado do site.

    pnpm exec emdash plugin init --native --name @example/plugin-activity --dir ../plugin-activity

    O comando remove o scope npm quando cria o ID do plugin. O nome do pacote é @example/plugin-activity, enquanto o ID do plugin é plugin-activity.

  2. Instale as dependências do pacote.

    cd ../plugin-activity
    pnpm install
  3. Substitua o src/index.ts gerado por um hook de salvamento de conteúdo.

    import { definePlugin } from "emdash";
    import type { PluginDescriptor } from "emdash";
    
    export interface ActivityPluginOptions {
        logUpdates?: boolean;
    }
    
    export function activityPlugin(
        options: ActivityPluginOptions = {},
    ): PluginDescriptor<ActivityPluginOptions> {
        return {
            id: "plugin-activity",
            version: "0.1.0",
            format: "native",
            entrypoint: "@example/plugin-activity",
            options,
        };
    }
    
    export function createPlugin(options: ActivityPluginOptions = {}) {
        return definePlugin({
            id: "plugin-activity",
            version: "0.1.0",
            capabilities: ["content:read"],
            hooks: {
                "content:afterSave": async (event, ctx) => {
                    if (!event.isNew && options.logUpdates === false) return;
    
                    ctx.log.info("Content saved", {
                        collection: event.collection,
                        contentId: event.content.id,
                        isNew: event.isNew,
                    });
                },
            },
        });
    }
    
    export default createPlugin;

    content:afterSave exige a capability content:read. EmDash ignora o hook quando essa capability está ausente.

  4. Compile o pacote.

    pnpm build
  5. Instale o pacote local no site.

    cd ../my-emdash-site
    pnpm add ../plugin-activity
  6. Registre a factory do descriptor na integração EmDash.

    import { defineConfig } from "astro/config";
    import emdash from "emdash/astro";
    import { activityPlugin } from "@example/plugin-activity";
    
    export default defineConfig({
        integrations: [
            emdash({
                plugins: [activityPlugin({ logUpdates: true })],
            }),
        ],
    });

    Descriptors nativos pertencem a plugins, não a sandboxed. EmDash rejeita um descriptor nativo no array sandboxed.

  7. Inicie o site e salve uma entrada no painel de administração.

    pnpm dev

    O log do servidor inclui Content saved com a collection, o ID do conteúdo e se a entrada foi criada.

Fronteira descriptor / runtime

A exportação do pacote tem dois trabalhos. EmDash usa cada um em uma etapa diferente:

  • A factory do descriptor, activityPlugin(), é executada enquanto o Astro avalia sua configuração. Ela retorna metadados serializáveis de tempo de build: id, version, format, entrypoint e options. Entry points React e Astro também pertencem a este descriptor.
  • A exportação nomeada createPlugin() é executada quando EmDash é inicializado. EmDash a importa de entrypoint, passa as options serializadas e espera um plugin resolvido de definePlugin().

A exportação nomeada createPlugin é obrigatória. Uma exportação padrão pode ser útil para consumidores do pacote, mas o loader nativo de EmDash importa createPlugin pelo nome.

Mantenha id e version idênticos no descriptor e em definePlugin(). Use um ID de plugin sem scope e em kebab-case como plugin-activity; mantenha o scope npm no nome do pacote e em entrypoint. Assim o ID continua utilizável como o único segmento de plugin nas URLs de rotas de API.

Identidade e versionamento do plugin lista as formas de ID e versão aceitas.

O comportamento de runtime pertence a definePlugin():

  • capabilities e allowedHosts
  • storage
  • hooks e routes
  • declarações de configurações, página, widget e Portable Text de admin

O descriptor carrega as entradas estáticas que o Astro deve importar ou expor em tempo de build. Os guias focados mostram quais campos de administração precisam de declarações de descriptor e runtime correspondentes.

Handlers de rotas nativas

Handlers de rotas nativas recebem um RouteContext. Ele combina entrada validada e dados da requisição com o PluginContext habitual:

routes: {
	status: {
		permission: "plugins:read",
		handler: async (ctx) => ({
			pluginId: ctx.plugin.id,
			callerId: ctx.user?.id ?? null,
		}),
	},
},

O handler sandboxed equivalente recebe (routeCtx, ctx) como dois argumentos. Autenticação, permissões, esquemas de entrada e URLs de rotas seguem no restante o contrato compartilhado das rotas de API.

Envolva uma rota nativa em definePluginRoute() quando ela declarar request.body; o helper infere ctx.input a partir do modo do body. Uma rota nativa com response: "raw" retorna pluginResponse(). Importe ambos os helpers de emdash. O guia compartilhado de rotas de API lista os modos de body, limites, política de resposta e padrões de compatibilidade.

Adicionar outra superfície