npm package: @fluig-kit/ecm
Description: O **Fluig Kit** é um conjunto moderno de ferramentas e bibliotecas criado para **substituir o desenvolvimento legado baseado em jQuery e FreeMarker** no TOTVS Fluig.
Latest version: 1.0.25


## 🚀 Fluig Kit — Desenvolvimento ECM_WORKFLOW e WCM com React


O **Fluig Kit** é um conjunto moderno de ferramentas e bibliotecas criado para **substituir o desenvolvimento legado baseado em jQuery e FreeMarker** no TOTVS Fluig.

Ele permite a criação de **formulários ECM Workflow** e **Widgets WCM** utilizando tecnologias modernas como **React, Vite, TypeScript, React Hook Form e Zod**, oferecendo uma arquitetura **previsível, escalável e fácil de manter**.

Além disso, possibilita a integração com **qualquer biblioteca do ecossistema React**, ampliando a flexibilidade e o poder de personalização das soluções.

## 🎯 Objetivos do Fluig Kit

- Modernizar o desenvolvimento de formulários Fluig
- Eliminar dependência direta de jQuery e FreeMarker
- Facilitar validações, regras de negócio e controle de estado
- Melhorar a experiência de desenvolvimento (DX)
- Permitir desenvolvimento local com simulação fiel do Fluig

## 📦 Estrutura dos Pacotes (Monorepo)

O kit é organizado em múltiplos pacotes, cada um com uma responsabilidade clara:

#### `@fluig-kit/core`
Núcleo da aplicação.
Responsabilidades:
- Cliente HTTP (`apiClient`)
- Logger de debug (`DebugLogger`)
- Comunicação com o Fluig via `parentProxy`
  - Em produção: `window.top`
  - Em desenvolvimento: Proxy Local + Extensão
---
#### `@fluig-kit/ecm`
Camada específica para **ECM / Workflow**.
Inclui:
- `FluigWorkflowForm`
- Hooks (`useFluigApi`, `useSection`, etc.)
- Integração com React Hook Form
- Controle de ciclo de vida do Fluig
---
#### `@fluig-kit/cli`
Ferramenta de linha de comando para desenvolvimento local.
Funções:
- Sobe um **Proxy Local**
- Resolve problemas de **CORS**
- Assina requisições com **OAuth 1.0a**
- Simula chamadas para `window.parent` e `window.top`
---
#### `@fluig-kit/extension`
Extensão do Google Chrome.
Funções:
- Ponte de autenticação entre o **localhost** e o Fluig
- Executa chamadas no contexto real da aba do Fluig
- Comunicação via **WebSocket** com o Proxy Local

## 🛠️ Configuração do Ambiente
#### 1️⃣ Variáveis de Ambiente (`.env`)

Crie um arquivo `.env` na raiz do projeto React:

```env
# URL base do ambiente Fluig
VITE_FLUIG_BASE_URL=https://SEUDOMINIO.fluig.cloudtotvs.com.br

# Credenciais OAuth (Fluig > Painel de Controle > OAuth Application)
CONSUMER_KEY=SEU_CONSUMER_KEY
CONSUMER_SECRET=SEU_CONSUMER_SECRET
ACCESS_TOKEN=SEU_ACCESS_TOKEN
TOKEN_SECRET=SEU_TOKEN_SECRET
```

Essas variáveis são usadas **exclusivamente pelo Proxy Local** para assinar as requisições.

---

#### 2️⃣ Instalação da Extensão do Chrome
Passos:
1. Execute:
   ```
   npm run dev
   ```
2. No Chrome, abra:
   ```
   chrome://extensions
   ```
3. Ative **Modo do Desenvolvedor**
4. Clique em **Carregar sem compactação**
5. Selecione a pasta `.fluig-extension` gerada na **raiz** do projeto

>⚠️ A extensão injeta um script no Fluig para permitir comunicação segura com o localhost.


## 💻 Desenvolvimento do Formulário

#### Inicialização da Aplicação (`App.jsx`)
O app deve ser envolvido pelos **Providers do Fluig Kit**:
```jsx
import React from "react";
import { createRoot } from "react-dom/client";
import {
  FluigApiProvider,
  FluigRuntimeProvider,
  SchemaRegistryProvider,
  FluigWorkflowForm
} from "@fluig-kit/ecm";

import { schemaBase } from "./form/schemas/schema";
import { WORKFLOW_STRUCTURE, SECTIONS_REGISTRY } from "./config/workflow";

const DEV_CONFIG = {
  enabled: true,
  activityId: 5,
  showDebugLogs: true
};

const CONFIG_API = {
  baseURL: import.meta.env.VITE_FLUIG_BASE_URL,
  localProxyURL: "http://localhost:4000/fluig-proxy-api"
};

createRoot(document.getElementById("root")).render(
  <FluigRuntimeProvider devConfig={DEV_CONFIG}>
    <FluigApiProvider config={CONFIG_API}>
      <SchemaRegistryProvider baseSchema={schemaBase}>
        <FluigWorkflowForm
          workflowStructure={WORKFLOW_STRUCTURE}
          sectionsRegistry={SECTIONS_REGISTRY}
        />
      </SchemaRegistryProvider>
    </FluigApiProvider>
  </FluigRuntimeProvider>
);
```

## 🧱 Seções do Formulário (`Section`)

Uma **Section** representa um bloco lógico do formulário e controla:
- Visibilidade
- ReadOnly
- Regras por atividade

```jsx
import { Section, useSection } from "@fluig-kit/ecm";
import { Input } from "@diefra/fluig-ui";
import { useWatch } from "react-hook-form";

function EngCargoContent() {
  const { form } = useSection();
  const salario = useWatch({ control: form.control, name: "SALARIO" });

  return (
    <div className="row">
      <div className="col-md-6">
        <Input name="NOMECARGO" label="Nome do Cargo" />
      </div>
      <div className="col-md-6">
        <Input name="SALARIO" label="Salário" type="monetary" />
      </div>
    </div>
  );
}

export default function EngCargo(props) {
  return (
    <Section id="EngCargo" className="well" {...props}>
      <EngCargoContent />
    </Section>
  );
}
```

## ⚙️ Configuração do Workflow (`workflow.ts`)

Define o comportamento do formulário por atividade.

#### Conceitos principais

- **Sections**: controlam blocos inteiros
- **Fields**: controlam campos individuais
- **Rules**: regras condicionais

```ts
export const WORKFLOW_STRUCTURE = {
  0: {
    sections: {
      active: ["InfSolicitante", "EngCargo"],
      hidden: ["AprovacaoRH"]
    },
    fields: {
      active: ["NOMECARGO"]
    }
  },

  5: {
    sections: {
      active: ["AprovacaoRH"],
      readonly: ["InfSolicitante", "EngCargo"]
    },
    fields: {
      active: ["PARECER_RH"],
      rules: [
        {
          target: ["OBS_REPROVACAO"],
          when: { field: "PARECER_RH", equals: "REPROVAR" },
          type: "active"
        }
      ]
    }
  }
};
```

## 📡 Consumo da API Fluig (`useFluigApi`)

```jsx
import { useFluigApi } from "@fluig-kit/ecm";
import { useEffect, useState } from "react";

export function useUsuarios() {
  const api = useFluigApi();
  const [users, setUsers] = useState([]);

  useEffect(() => {
    async function fetchUsers() {
      const res = await api.get("/api/public/2.0/users/list/ACTIVE");
      setUsers(res.content);
    }
    fetchUsers();
  }, [api]);

  return users;
}
```

O hook decide automaticamente:
- **Localhost** → Proxy OAuth
- **Produção** → Cookie de sessão

## 🔄 Movimentação do Workflow

```jsx
import { useSection } from "@fluig-kit/ecm";

function MinhaAprovacao() {
  const { next } = useSection();

  return (
    <button onClick={() => next(15)}>
      Aprovar
    </button>
  );
}
```
## 🏗️ Geração de HTML e Build (generateHtmlTemplate)

O Fluig não executa React nativamente no salvamento do formulário, ele busca campos HTML.
```html
<input name="NOME_DO_CAMPO">
```

A função generateHtmlTemplate gera um HTML estático com inputs ocultos (type="hidden") baseados nos seus Schemas Zod.

Script de Build (build.cjs)
Crie este script na raiz para gerar o form.html final:

```js
const fs = require("fs");
const path = require("path");
const { generateHtmlTemplate } = require("@fluig-kit/ecm");

// EXEMPLO SECTIONS_REGISTRY
// export const SECTIONS_REGISTRY = {
//  InfSolicitante: { Component: InfSolicitante, schema: schemaSolicitante },
//  EngCargo: { Component: EngCargo, schema: schemaEngCargo },
//  InfVaga: { Component: InfVaga, schema: schemaInfVaga },
//  ...
//}

try {
  // 1. Extrai schemas Zod
  const schemas = Object.values(SECTIONS_REGISTRY).map((s) => s.schema).filter(Boolean);

  // 2. Gera HTML com inputs hidden
  const finalHtml = generateHtmlTemplate(schemas);

  // 3. Salva o arquivo
  const distPath = path.resolve(__dirname, "./dist/form.html");
  fs.mkdirSync(path.dirname(distPath), { recursive: true });
  fs.writeFileSync(distPath, finalHtml);
  
  console.log("✅ form.html gerado com sucesso!");
} catch (error) {
  console.error("❌ Erro:", error);
  process.exit(1);
}
```
Atualize o package.json:

```JSON
"scripts": {
  "build": "vite build && node build.cjs"
}
````
---
Desenvolvido por © **[Ketson Kersen](https://github.com/ketsonkersen)**