fayzfayz sdk

06 · Seu próprio plugin

Ligar plugins do catálogo é ótimo, mas em algum momento você quer uma capacidade que só existe no seu produto. O incubator é o caminho: um plugin app-local que segue o mesmo contrato dos plugins oficiais. É o passo que transforma você de usuário do SDK em autor.

Gere o plugin

npx @fayz-ai/cli create plugin fidelidade
✓ Created app-local plugin "src/plugins/fidelidade"

  Add createFidelidadePlugin() to your app's plugins array (see src/plugins/fidelidade/README.md).
  Run "fayz doctor" to check boundaries.

O que foi criado em src/plugins/fidelidade/:

ArquivoPapel
index.tsO PluginManifest: id, navegação, rotas e a página. O mesmo contrato de um @fayz-ai/plugin-*.
data/types.tsO contrato de dados (FidelidadeDataProvider) que todo backend implementa.
data/mock.tsProvider mock — o plugin já roda sem banco.
data/supabase.tsProvider real, passando pelo boundary do Fayz (getSupabaseClientOptional), nunca importando o SDK do Supabase direto.
schema/index.tsOnde as migrations do plugin vivem.
README.mdComo fiar o plugin e a checklist de graduação para oficial.

O contrato é o mesmo dos oficiais

O index.ts exporta uma factory que devolve um PluginManifest — id, navigation, routes e uma página. Ele escolhe o provider automaticamente (Supabase quando há backend, mock caso contrário) via createSafeDataProvider:

export function createFidelidadePlugin(options?: FidelidadePluginOptions): PluginManifest {
  const provider =
    options?.dataProvider ??
    createSafeDataProvider(
      () => createSupabaseFidelidadeProvider(),
      () => createMockFidelidadeProvider(),
    )
  // ...
  return {
    id: 'fidelidade',
    name: 'Fidelidade',
    navigation: [{ section: 'main', label: 'Fidelidade', route: '/fidelidade', icon: 'Puzzle' }],
    routes: [{ path: '/fidelidade', component: Page }],
  }
}

Para ligá-lo, adicione createFidelidadePlugin() ao array de plugins da config do app (veja o README.md do plugin). E confira os limites com o doctor:

npx @fayz-ai/cli doctor

✓ Você deve ver: a pasta src/plugins/fidelidade/ com os seis arquivos, e o doctor com 0 error(s). O data/supabase.ts já usa getSupabaseClientOptional — se você importasse @supabase/supabase-js direto, o doctor acusaria a quebra de boundary.

Onde vão as migrations

As tabelas do seu plugin vivem em schema/index.ts e são referenciadas no manifesto via migrations: [...]:

migrations: [{ id: 'fidelidade-0001', version: '0.1.0', sql: '<create table ...>' }]

Quando você rodar fayz db apply, o passo incubator (o último da ordem) aplica essas migrations junto com o resto — foi por isso que a ordem spine → drizzle → seed → plugins → incubator importa.

De incubator a oficial

Promover um plugin app-local para um pacote @fayz-ai/plugin-* oficial é empacotamento, não reescrita: o manifesto não muda, você só move a pasta. O README.md gerado traz a checklist completa de graduação (contrato validado, teste de capacidade, permissões, i18n, boundary limpo). O mesmo contrato que você seguiu aqui é o que os plugins do catálogo seguem.


← Anterior: 05 · Dados reais com Supabase · Próximo: 07 · Publicar →