fayzfayz sdk

Rodando local com dados de exemplo

O backend: { provider: "mock" } deixa o app rodar sem env — mas "modo mock" não significa "modo populado". Os providers mock nascem vazios: você abre a agenda e não há agendamentos, abre o financeiro e não há lançamentos. A promessa de "dados de exemplo" só se cumpre quando você semeia o provider na construção. Esta página é o mapa direto dos seams de seed, mais dois detalhes que mordem quem consome os pacotes publicados: o dashboard em mock e o FAYZ_SDK_SOURCE.

Isto é sobre o segundo caminho de consumo — código que importa os pacotes @fayz-ai/* publicados e monta o app em src/ (via defineSaas / plugin factories), não o app manifesto-primeiro que a plataforma renderiza. Se você está no fluxo do Quickstart, o mock populado é responsabilidade da plataforma; aqui você faz na mão.

Por que o mock nasce vazio

Um provider mock é uma implementação em memória do contrato de dados de um plugin. Ele existe para o app compilar e rodar sem backend — não para adivinhar que loja você está construindo. Sem seed, a lista está vazia por design. Semear é passar os objetos de domínio na construção do provider; a partir daí o mock os trata como o "banco" existente (cria, edita, filtra em cima deles).

Há quatro seams, do mais específico (um plugin) ao mais genérico (uma entidade CRUD).

Agenda: createMockAgendaProvider({ seed })

createMockAgendaProvider aceita um MockAgendaSeed (de @fayz-ai/plugin-agenda). Você passa o provider semeado para a factory do plugin via dataProvider:

import { createAgendaPlugin, createMockAgendaProvider } from '@fayz-ai/plugin-agenda'
import type { MockAgendaSeed } from '@fayz-ai/plugin-agenda'

const seed: MockAgendaSeed = {
  professionals: [
    { id: 'p1', name: 'Ana', /* … */ },
  ],
  bookings: [
    { id: 'b1', professionalId: 'p1', startsAt: '2026-07-20T14:00:00Z', /* … */ },
  ],
  // schedules? também aceito; qualquer coleção omitida cai no exemplo embutido
}

export const agenda = createAgendaPlugin({
  dataProvider: createMockAgendaProvider({ seed }),
})

Atalho: createMockAgendaProvider() sem seed já traz um exemplo pronto — uma agenda estilo salão com profissionais e horários embutidos. É o jeito mais rápido de ver a agenda populada; use o seed só quando quiser dados do seu próprio cenário (uma clínica, um estúdio). Qualquer coleção que você omitir no seed cai de volta nesse exemplo embutido.

Financeiro: createMockFinancialProvider({ seed })

Mesma forma para o financeiro. O MockFinancialSeed (de @fayz-ai/plugin-financial) pré-popula o ledger — faturas, movimentos, contas, métodos de pagamento:

import { createFinancialPlugin, createMockFinancialProvider } from '@fayz-ai/plugin-financial'
import type { MockFinancialSeed } from '@fayz-ai/plugin-financial'

const seed: MockFinancialSeed = {
  invoices: [ /* … */ ],
  movements: [ /* … */ ],
  // bankAccounts? cai em duas contas padrão quando ausente; o resto fica vazio se omitido
}

export const financial = createFinancialPlugin({
  dataProvider: createMockFinancialProvider({ seed }),
})

Diferente da agenda, o financeiro não inventa faturas/movimentos quando o seed é omitido — as coleções ficam vazias (exceto bankAccounts, que cai em duas contas padrão). Se quer o módulo populado, passe o seed.

Uma entidade qualquer: createMockProvider(entityDef, initialData)

Para CRUD genérico — um plugin próprio, uma entidade sua — @fayz-ai/core expõe createMockProvider. O segundo argumento é o array inicial:

import { createMockProvider } from '@fayz-ai/core'

const provider = createMockProvider(clientEntityDef, [
  { id: 'c1', name: 'Cliente Exemplo', email: 'exemplo@teste.com' },
  { id: 'c2', name: 'Outro Cliente', email: 'outro@teste.com' },
])

O primeiro argumento pode ser o EntityDef (de onde ele deriva os campos pesquisáveis e a ordenação padrão) ou só um array de chaves pesquisáveis. initialData default é [] — por isso o vazio.

Uma página CRUD do SaaS: createCrudPage(entity, { mockData })

No nível de página, createCrudPage (de @fayz-ai/saas) aceita mockData direto nas opções — útil quando você monta uma tela de listagem sem provider explícito:

import { createCrudPage } from '@fayz-ai/saas'

const ClientsPage = createCrudPage(clientEntity, {
  mockData: [
    { id: 'c1', name: 'Cliente Exemplo' },
    { id: 'c2', name: 'Outro Cliente' },
  ],
})

O dashboard em mock mostra zeros

O plugin-dashboard lê o Supabase direto para compor seus KPIs — ele não passa pelos providers mock dos outros plugins. Em modo mock, sem Supabase configurado, os cards vêm zerados. Semear a agenda ou o financeiro não muda isso: o dashboard não enxerga esses seeds.

A saída honesta é não contar com o dashboard embutido em modo mock, e sim registrar widgets custom com compute que derivam dos mesmos seeds. Um widget do tipo KPI aceita um compute?: () => Promise<KpiValue> — você calcula o número a partir dos seus dados de exemplo:

// um widget que deriva o número dos seeds, em vez de ler o Supabase
{
  id: 'custom:faturas-abertas',
  compute: async () => ({ value: seed.invoices.filter((i) => i.status === 'open').length }),
}

Assim o painel reflete o cenário mock em vez de mostrar zeros. Quando você trocar para o backend Supabase real, o dashboard embutido passa a computar de verdade e esses widgets custom viram opcionais.

FAYZ_SDK_SOURCE: fixe os pacotes publicados

O helper fayzVite (de @fayz-ai/sdk/vite) tem um comportamento de conveniência para o monorepo: se um checkout do fayz-sdk existir ao lado do app (em ../../fayz-sdk), ele aliassa os imports @fayz-ai/* para o código-fonte local desse monorepo, não para o node_modules. Ótimo para quem desenvolve o SDK; uma armadilha para um app standalone que só quer consumir os pacotes publicados — de repente o app roda contra fonte não publicada que por acaso está no disco.

O controle é a env FAYZ_SDK_SOURCE. Um app standalone deve fixá-la em published nos scripts, garantindo que ele sempre resolva os pacotes de node_modules:

{
  "scripts": {
    "dev": "FAYZ_SDK_SOURCE=published vite",
    "build": "FAYZ_SDK_SOURCE=published vite build"
  }
}

Com FAYZ_SDK_SOURCE=published, o fayzVite ignora qualquer checkout vizinho e usa exatamente as versões dos seus dependencies — que é o que você quer ao testar o app como um dev externo testaria.


Próximo: o segundo caminho de consumo em Headless.