> ## Documentation Index
> Fetch the complete documentation index at: https://docs.easygoal.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Setup & Instalação

> Como instalar os packages @easygoal/ui e @easygoal/auth e configurar o ambiente local.

## Instalando os packages

Há três formas de instalar os packages do monorepo. Escolha a que se encaixa melhor no seu contexto.

<Tabs>
  <Tab title="Via GitHub (recomendado)">
    A forma mais simples enquanto os packages não são publicados no npm. Instala diretamente de um commit, branch ou tag do GitHub.

    ```bash theme={null}
    # Instalar pelo branch main
    npm install "https://github.com/Easy-Goal/easygoal-ui#main"

    # Instalar uma versão específica (tag)
    npm install github:easygoal/easygoal-ui#v0.1.0
    ```

    O npm resolve o package usando o `package.json` na raiz. Para instalar um sub-package específico do monorepo, aponte para o diretório correto via `package.json#exports` ou use um path local.

    <Note>
      Para instalar os packages via GitHub, adicione ao `package.json` do seu projeto:

      ```json theme={null}
      {
        "dependencies": {
          "@easygoal/packages": "github:Easy-Goal/easygoal-monorepo"
        }
      }
      ```

      Em seguida rode `npm install` ou `pnpm install`.
    </Note>
  </Tab>

  <Tab title="Via path local">
    Ideal durante desenvolvimento quando você tem o monorepo clonado localmente.

    ```bash theme={null}
    # Clonar o monorepo
    git clone https://github.com/Easy-Goal/easygoal-monorepo.git ~/projects/easy/easygoal-monorepo

    # No projeto onde vai usar
    cd ~/projects/easy/app-front

    # Instalar os packages pelo path relativo
    npm install ../easygoal-monorepo/packages/ui
    npm install ../easygoal-monorepo/packages/auth
    ```

    <Tip>
      Com pnpm, use o protocolo `workspace:` se você trabalhar com os projetos dentro do mesmo workspace, ou `link:` para paths locais fora do workspace:

      ```bash theme={null}
      pnpm add link:../easygoal-monorepo/packages/ui
      pnpm add link:../easygoal-monorepo/packages/auth
      ```
    </Tip>

    Rode o build do package em modo watch em um terminal separado:

    ```bash theme={null}
    cd ~/projects/easy/easygoal-monorepo
    pnpm build:ui   # ou pnpm build:auth
    # modo watch:
    pnpm --filter @easygoal/ui run dev
    ```
  </Tab>

  <Tab title="Via npm (futuro)">
    Quando os packages forem publicados no npm (ou no GitHub Packages):

    ```bash theme={null}
    # npm público
    npm install @easygoal/ui @easygoal/auth

    # GitHub Packages (registry privado)
    npm install @easygoal/ui @easygoal/auth \
      --registry https://npm.pkg.github.com
    ```

    Para GitHub Packages, adicione um `.npmrc` na raiz do projeto:

    ```ini theme={null}
    # .npmrc
    @easygoal:registry=https://npm.pkg.github.com
    //npm.pkg.github.com/:_authToken=${NPM_TOKEN}
    ```

    E defina `NPM_TOKEN` com um Personal Access Token (PAT) do GitHub com permissão `read:packages`.
  </Tab>
</Tabs>

***

## Usando @easygoal/ui

```tsx theme={null}
import { Logo, colors } from "@easygoal/packages/ui";

// Logo no tema escuro (texto branco, ícone laranja)
<Logo variant="dark" width={133} />

// Logo no tema claro (texto escuro, ícone laranja)
<Logo variant="light" width={100} />

// Tokens de cor
const bg = colors.background;   // "#0F1729"
const accent = colors.primary;  // "#F97316"
```

Importando apenas os tokens (sem carregar o componente React):

```ts theme={null}
import { colors, cssVars } from "@easygoal/packages/ui/tokens";
```

***

## Usando @easygoal/auth

O `@easygoal/auth` é específico para projetos **Next.js + Supabase** que integram com o SSO Easy Goal.

### 1. EgSessionProvider (layout raiz)

```tsx theme={null}
// app/layout.tsx
import { EgSessionProvider } from "@easygoal/packages/auth";
import { createClient } from "@/utils/supabase/client";

export default function RootLayout({ children }) {
  return (
    <EgSessionProvider
      config={{
        loginUrl: process.env.NEXT_PUBLIC_SSO_URL!,
        appUrl: process.env.NEXT_PUBLIC_APP_URL!,
      }}
      supabaseClient={createClient()}
    >
      {children}
    </EgSessionProvider>
  );
}
```

### 2. Callback route

```ts theme={null}
// app/auth/callback/route.ts
import { createCallbackRoute } from "@easygoal/packages/auth";

export const GET = createCallbackRoute({
  supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL!,
  supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
  ssoUrl: process.env.NEXT_PUBLIC_SSO_URL,
  appUrl: process.env.NEXT_PUBLIC_APP_URL,
});
```

### 3. Middleware

```ts theme={null}
// middleware.ts
import { updateSession, defaultMatcherConfig } from "@easygoal/packages/auth";
import type { NextRequest } from "next/server";

export async function middleware(request: NextRequest) {
  return updateSession(request, {
    supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL!,
    supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
  });
}

export const config = defaultMatcherConfig;
```

### 4. Hook de sessão

```tsx theme={null}
"use client";
import { useAuthSession } from "@easygoal/packages/auth";

export function Header() {
  const { session, signOut, isReady } = useAuthSession();

  if (!isReady) return null;

  return (
    <header>
      <span>{session?.user.email}</span>
      <button onClick={signOut}>Sair</button>
    </header>
  );
}
```

***

## Rodando o monorepo localmente

```bash theme={null}
# Pré-requisito: pnpm
npm install -g pnpm

# Clonar
git clone https://github.com/Easy-Goal/easygoal-monorepo.git
cd easygoal-monorepo

# Instalar dependências de todos os packages
pnpm install

# Build de tudo
pnpm build

# Build individual
pnpm build:ui
pnpm build:auth

# Watch mode (desenvolvimento)
pnpm --filter @easygoal/ui run dev
pnpm --filter @easygoal/auth run dev
```

***

## Integração de Webhooks

Para aceitar webhooks em múltiplas linguagens, o SSO expõe `POST /api/webhook/payment` e valida a assinatura HMAC SHA256:

<Tabs>
  <Tab title="Node.js">
    ```ts theme={null}
    import { createHmac, timingSafeEqual } from 'crypto';

    function verifyWebhook(rawBody: string, signature: string, secret: string): boolean {
      const expected = createHmac('sha256', secret)
        .update(rawBody)
        .digest('hex');

      const sigBuf = Buffer.from(signature, 'hex');
      const expBuf = Buffer.from(expected, 'hex');

      return sigBuf.length === expBuf.length && timingSafeEqual(sigBuf, expBuf);
    }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import hmac, hashlib

    def verify_webhook(raw_body: str, signature: str, secret: str) -> bool:
        expected = hmac.new(
            secret.encode(), raw_body.encode(), hashlib.sha256
        ).hexdigest()
        return hmac.compare_digest(signature, expected)
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    import ("crypto/hmac"; "crypto/sha256"; "encoding/hex")

    func verifyWebhook(rawBody, signature, secret string) bool {
        mac := hmac.New(sha256.New, []byte(secret))
        mac.Write([]byte(rawBody))
        expected := hex.EncodeToString(mac.Sum(nil))
        return hmac.Equal([]byte(signature), []byte(expected))
    }
    ```
  </Tab>
</Tabs>
