RhizzaDocs

Abra seu primeiro relatório

Emita um token no backend do host e monte o editor React com dados reais do seu produto.

Abrir como Markdown

1. Instale os dois lados da integração

O pacote Node faz a troca segura de credenciais no servidor. O pacote React renderiza o widget no navegador. Você precisa dos dois em uma aplicação Next.js completa.

shell
pnpm add @rhizzalab/report-react @rhizzalab/report-node

2. Emita o token no servidor

Crie uma Route Handler protegida pela autenticação do seu produto. @rhizzalab/report-node valida a requisição antes da rede e devolve erros tipados sem expor o segredo.

app/api/rhizzadocs/token/route.ts
import "server-only"

import { createReportPlatformClient } from "@rhizzalab/report-node"
import { NextResponse } from "next/server"

import { requireAuthenticatedUser } from "@/lib/auth"

export const runtime = "nodejs"

function requiredEnv(name: string): string {
  const value = process.env[name]
  if (!value) throw new Error("Variável ausente: " + name)
  return value
}

const reports = createReportPlatformClient({
  clientId: requiredEnv("RHIZZADOCS_CLIENT_ID"),
  clientSecret: requiredEnv("RHIZZADOCS_CLIENT_SECRET"),
  apiBaseUrl: process.env.RHIZZADOCS_API_URL,
})

export async function POST(request: Request) {
  // Esta função pertence ao seu host: valide a sessão antes da troca.
  const user = await requireAuthenticatedUser(request)

  const token = await reports.issueEditorToken({
    userId: user.id,
    workspaceId: user.companyId,
    reports: [
      {
        reportType: "acme.relatorio-mensal",
        scopes: ["editor:read", "templates:read", "export:pdf"],
      },
    ],
  })

  return NextResponse.json(token)
}

3. Monte o editor no cliente

Crie um único ReportClient, forneça-o por contexto e renderize o ReportEditor. O callback onAuthRequired é o ponto para pedir outro JWT sem colocar a credencial permanente no browser.

components/report-screen.tsx
"use client"

import {
  ReportEditor,
  ReportSdkProvider,
  createReportClient,
  type ReportEditorProps,
} from "@rhizzalab/report-react"
import { useCallback, useEffect, useMemo, useState } from "react"

type ReportScreenProps = Pick<
  ReportEditorProps,
  "data" | "documentKey" | "reportType"
>

export function ReportScreen(props: ReportScreenProps) {
  const client = useMemo(
    () =>
      createReportClient({
        apiBaseUrl: process.env.NEXT_PUBLIC_RHIZZADOCS_API_URL,
      }),
    [],
  )
  const [token, setToken] = useState<string | null>(null)
  const [error, setError] = useState<string | null>(null)

  const loadToken = useCallback(async () => {
    setError(null)
    try {
      const response = await fetch("/api/rhizzadocs/token", { method: "POST" })
      if (!response.ok) throw new Error("Não foi possível abrir o editor.")
      const body = (await response.json()) as { accessToken: string }
      setToken(body.accessToken)
    } catch (cause: unknown) {
      setError(cause instanceof Error ? cause.message : "Falha inesperada.")
    }
  }, [])

  useEffect(() => {
    void loadToken()
  }, [loadToken])

  if (error) return <p role="alert">{error}</p>
  if (!token) return <p aria-live="polite">Preparando o editor…</p>

  return (
    <ReportSdkProvider client={client}>
      <ReportEditor
        token={token}
        reportType={props.reportType}
        data={props.data}
        documentKey={props.documentKey}
        onAuthRequired={() => void loadToken()}
        onError={(editorError) => {
          if (editorError.code !== "AUTH_REQUIRED") {
            setError(editorError.message)
          }
        }}
      />
    </ReportSdkProvider>
  )
}

4. Passe os dados do host

O reportType aponta para uma definição publicada. data deve corresponder ao JSON Schema dessa definição. Com documentKey, o editor restaura e salva um documento de trabalho para aquela identidade de negócio.

app/reports/[id]/page.tsx
import { ReportScreen } from "@/components/report-screen"

export default async function ReportPage() {
  const report = await loadReport("report_42")

  return (
    <ReportScreen
      reportType="acme.relatorio-mensal"
      documentKey={report.id}
      data={{
        customer: report.customer,
        items: report.items,
        total: report.total,
      }}
    />
  )
}