forlogic-core 1.5.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,1131 +1,36 @@
1
- # 🧱 forlogic-core - Sistema CRUD Ultra-Simplificado
1
+ # 🧱 Documentação exclusiva para este projeto
2
2
 
3
- > **Biblioteca modular React + TypeScript + Supabase para gestão empresarial com autenticação dupla JWT e integração Qualiex**
4
-
5
- [![npm version](https://badge.fury.io/js/%40qualiex%2Fcore.svg)](https://badge.fury.io/js/%40qualiex%2Fcore)
6
- [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
7
- [![React](https://img.shields.io/badge/React-18+-61dafb.svg)](https://reactjs.org/)
8
-
9
- ---
10
-
11
- ## 📦 Instalação
12
-
13
- ```bash
14
- npm install forlogic-core
15
- ```
16
-
17
- ### Dependências Peer (Obrigatórias)
18
-
19
- ```bash
20
- npm install react react-dom react-router-dom
21
- ```
22
-
23
- ### Configuração Inicial
24
-
25
- ```tsx
26
- // main.tsx ou App.tsx
27
- import { setupQualiexCore } from 'forlogic-core';
28
- import 'forlogic-core/index.css';
29
-
30
- setupQualiexCore({
31
- supabaseUrl: 'your-supabase-url',
32
- supabaseKey: 'your-supabase-anon-key',
33
- qualiexBaseUrl: 'your-qualiex-url'
34
- });
35
- ```
36
-
37
- ### Uso Básico
38
-
39
- ```tsx
40
- import { createSimpleService, createCrudPage, generateCrudConfig } from 'forlogic-core';
41
-
42
- // 1. Create service
43
- const service = createSimpleService<MyEntity>({ tableName: 'my_entities' });
44
-
45
- // 2. Generate config
46
- const config = generateCrudConfig('My Entities', { name: '', email: '' });
47
-
48
- // 3. Create page
49
- export const MyPage = createCrudPage({ service, config });
50
- ```
51
-
52
- ---
53
-
54
- ## 🚀 Stack Tecnológico
55
-
56
- | Tecnologia | Versão | Propósito |
57
- |------------|---------|-----------|
58
- | **React** | 18+ | Framework UI |
59
- | **TypeScript** | 5+ | Type Safety |
60
- | **Tailwind CSS** | 3+ | Styling System |
61
- | **Supabase** | 2+ | Backend BaaS |
62
- | **React Query** | 5+ | Estado e Cache |
63
- | **React Hook Form** | 7+ | Formulários |
64
- | **Zod** | 3+ | Validação |
65
- | **shadcn/ui** | Latest | Componentes Base |
66
- | **Radix UI** | Latest | Primitivos Acessíveis |
67
-
68
- ---
69
-
70
- ## 🏗️ Arquitetura do Projeto
71
-
72
- ### Sistema de Importação Direta (Zero Barrel Exports)
73
-
74
- ```
75
- forlogic-core/
76
- ├── 🔐 auth/ # Sistema de Autenticação
77
- │ ├── components/
78
- │ │ ├── ProtectedRoute.tsx # Rota protegida por auth
79
- │ │ └── UserInfo.tsx # Informações do usuário
80
- │ ├── contexts/
81
- │ │ └── AuthContext.tsx # Context de autenticação
82
- │ ├── pages/
83
- │ │ └── CallbackPage.tsx # Callback OAuth
84
- │ └── services/
85
- │ ├── AuthService.ts # Lógica de autenticação
86
- │ └── TokenManager.ts # Gestão de tokens JWT
87
-
88
- ├── 🗂️ crud/ # Sistema CRUD Genérico
89
- │ ├── components/
90
- │ │ ├── ActionMenuItems.tsx # Itens do menu de ações
91
- │ │ ├── BaseForm.tsx # Formulário base configurável
92
- │ │ ├── CrudCards.tsx # Cards responsivos para mobile
93
- │ │ ├── CrudForm.tsx # Wrapper CRUD simples
94
- │ │ ├── CrudTable.tsx # Tabela CRUD responsiva
95
- │ │ ├── FilterBar.tsx # Barra de filtros e busca
96
- │ │ ├── TableFooter.tsx # Rodapé com paginação
97
- │ │ └── TableRowActions.tsx # Ações de linha da tabela
98
- │ └── hooks/
99
- │ ├── useCrud.ts # Hook principal para CRUD
100
- │ └── useBaseForm.ts # Hook para formulários
101
-
102
- ├── 🎨 components/ # Componentes Globais
103
- │ ├── layout/
104
- │ │ ├── AppHeader.tsx # Cabeçalho da aplicação
105
- │ │ └── AppSidebar.tsx # Sidebar de navegação
106
- │ └── ui/ # Componentes UI (shadcn/ui)
107
- │ ├── button.tsx # Sistema de botões
108
- │ ├── card.tsx # Sistema de cards
109
- │ ├── form.tsx # Componentes de formulário
110
- │ ├── input.tsx # Inputs customizados
111
- │ ├── table.tsx # Tabelas responsivas
112
- │ ├── toast.tsx # Notificações toast
113
- │ └── [50+ componentes] # Biblioteca completa
114
-
115
- ├── 🔌 supabase/ # Configuração Supabase da Lib
116
- │ ├── SupabaseSingleton.ts # Cliente Singleton customizado
117
- │ └── types.ts # Tipos do banco de dados
118
- │ └── qualiex/
119
- │ ├── components/
120
- │ │ ├── QualiexUserField.tsx # Campo de usuário Qualiex
121
- │ │ └── QualiexResponsibleSelectField.tsx
122
- │ ├── services/
123
- │ │ └── qualiexApi.ts # API client Qualiex
124
- │ ├── hooks/
125
- │ │ └── useQualiexUsers.ts # Hook para usuários
126
- │ └── types/
127
- │ └── qualiexTypes.ts # Tipos da API Qualiex
128
-
129
- ├── 🔧 services/ # Serviços Base
130
- │ ├── BaseService.ts # Service CRUD genérico
131
- │ ├── ErrorService.ts # Tratamento de erros
132
- │ └── QualiexEnrichmentService.ts # Enriquecimento de dados
133
-
134
- ├── 🧰 hooks/ # Hooks Globais
135
- │ ├── useActiveModules.ts # Módulos ativos
136
- │ ├── useDebounce.ts # Debounce de busca
137
- │ ├── usePageTitle.ts # Título da página
138
- │ └── use-toast.ts # Sistema de toast
139
-
140
- ├── 🛠️ utils/ # Utilitários
141
- │ └── index.ts # Funções auxiliares
142
-
143
- ├── ⚙️ config/ # Configurações
144
- │ └── index.ts # Config centralizada
145
-
146
- └── 📄 types.ts # Tipos Globais
147
- ```
148
-
149
- **✅ Princípios**: Imports diretos, componentes pequenos, zero over-engineering
150
-
151
- ### 🔧 Configuração Customizada do Supabase
152
-
153
- Este projeto utiliza uma configuração customizada do Supabase através do `SupabaseSingleton` ao invés do cliente padrão do Lovable.
154
-
155
- **📖 Documentação completa**: [Arquitetura Supabase da Lib](./docs/SUPABASE_LIB_ARCHITECTURE.md)
156
-
157
- **Vantagens:**
158
- - ✅ Gestão automática de tokens JWT
159
- - ✅ Integração com sistema multi-tenant (alias)
160
- - ✅ Performance otimizada com Singleton Pattern
161
- - ✅ Headers dinâmicos para autenticação
162
- - ✅ Compatibilidade com sistema de tokens triplos
163
-
164
- ```tsx
165
- // ✅ Forma correta de usar o Supabase
166
- import { getSupabaseClient } from '@/lib/supabase/SupabaseSingleton';
167
-
168
- const supabase = getSupabaseClient();
169
- ```
3
+ > **Sistema empresarial com React + TypeScript + Supabase**
170
4
 
171
5
  ---
172
6
 
173
- ## 🔐 Sistema de Autenticação Dupla
174
-
175
- ### Arquitetura de Tokens JWT
176
-
177
- ```mermaid
178
- sequenceDiagram
179
- participant U as Usuário
180
- participant Q as Qualiex OAuth
181
- participant E as Edge Function
182
- participant S as Supabase
183
- participant A as App
184
-
185
- U->>Q: Login OAuth
186
- Q->>U: access_token + id_token
187
- U->>E: validate-token(access_token)
188
- E->>Q: Valida token
189
- E->>S: Gera supabase_token
190
- E->>U: supabase_token
191
- U->>A: Login com 3 tokens
192
- ```
193
-
194
- ### Tokens Gerenciados
195
-
196
- | Token | Função | Storage | Duração |
197
- |-------|--------|---------|---------|
198
- | `access_token` | API Qualiex | localStorage | 1h |
199
- | `id_token` | Dados do usuário | localStorage | 1h |
200
- | `supabase_token` | Acesso RLS | localStorage | 1h |
201
- | `refresh_token` | Renovação | httpOnly cookie | 7d |
202
-
203
- ### Edge Functions
204
-
205
- ```
206
- supabase/functions/
207
- ├── validate-token/ # Produção: Validação completa
208
- │ └── index.ts # - Valida no Qualiex
209
- │ # - Gera token Supabase
210
- │ # - Retorna dados do usuário
211
- └── dev-tokens/ # Desenvolvimento: Tokens mock
212
- └── index.ts # - Bypass OAuth em dev
213
- # - Gera tokens válidos
214
- # - Acelera desenvolvimento
215
- ```
216
-
217
- ### Fluxo de Unidades/Empresas
218
-
219
- ```tsx
220
- // Contexto de autenticação com multi-tenancy
221
- const { user, companies, selectedUnit, switchUnit } = useAuth();
222
-
223
- // Trocar entre empresas do usuário
224
- await switchUnit(companyAlias);
225
- ```
226
-
227
- **🔒 Segurança**: RLS por alias + JWT claims + refresh automático
228
-
229
- ---
230
-
231
- ## 🗄️ Banco de Dados e RLS
232
-
233
- ### Estrutura Padrão de Tabela
234
-
235
- ```sql
236
- -- Tabela modelo compatível com o sistema
237
- CREATE TABLE schema_module.your_table (
238
- -- 🔑 Campos obrigatórios do sistema
239
- id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
240
- alias TEXT NOT NULL, -- Multi-tenancy RLS
241
-
242
- -- 📝 Campos de negócio (personalizáveis)
243
- title TEXT NOT NULL,
244
- description TEXT,
245
- url_field TEXT,
246
- date_field TIMESTAMP WITH TIME ZONE,
247
- color TEXT,
248
- icon_name TEXT,
249
- id_user TEXT, -- ID responsável (Qualiex)
250
-
251
- -- 🎛️ Campos de controle (obrigatórios)
252
- is_actived BOOLEAN DEFAULT true, -- Status ativo/inativo
253
- is_removed BOOLEAN DEFAULT false, -- Soft delete
254
- created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
255
- updated_at TIMESTAMP WITH TIME ZONE DEFAULT now()
256
- );
257
-
258
- -- 🔒 Trigger para updated_at
259
- CREATE TRIGGER update_your_table_updated_at
260
- BEFORE UPDATE ON schema_module.your_table
261
- FOR EACH ROW
262
- EXECUTE FUNCTION schema_module.update_updated_at_column();
263
- ```
264
-
265
- ### Políticas RLS Multi-Tenant
266
-
267
- ```sql
268
- -- 🔒 Habilitar Row Level Security
269
- ALTER TABLE schema_module.your_table ENABLE ROW LEVEL SECURITY;
7
+ ## ⚙️ Configuração deste Projeto
270
8
 
271
- -- 👀 SELECT: Ver dados da empresa
272
- CREATE POLICY "Users can view company data" ON schema_module.your_table
273
- FOR SELECT USING (
274
- ((SELECT auth.jwt()) ->> 'alias') = alias
275
- );
276
-
277
- -- ➕ INSERT: Inserir com alias da empresa
278
- CREATE POLICY "Users can insert company data" ON schema_module.your_table
279
- FOR INSERT WITH CHECK (
280
- ((SELECT auth.jwt()) ->> 'alias') = alias
281
- );
282
-
283
- -- ✏️ UPDATE: Atualizar dados da empresa
284
- CREATE POLICY "Users can update company data" ON schema_module.your_table
285
- FOR UPDATE USING (
286
- ((SELECT auth.jwt()) ->> 'alias') = alias
287
- );
288
-
289
- -- ⚠️ IMPORTANTE: NÃO criar política DELETE
290
- -- Sistema usa soft delete (is_removed = true)
291
- ```
292
-
293
- ### Template SQL Completo
294
-
295
- ```sql
296
- -- Copie este template para criar novas tabelas
297
- \i 'docs/templates/rls-policies.sql'
298
- ```
299
-
300
- **🛡️ Segurança**: Isolamento automático por empresa via RLS
301
-
302
- ---
303
-
304
- ## 🧠 Sistema CRUD Simplificado
305
-
306
- ### BaseService - CRUD Automático
307
-
308
- ```typescript
309
- // Criar service em 3 linhas
310
- import { createService } from 'forlogic-core';
311
- import type { MyEntity } from '@/types';
312
-
313
- export const MyService = createService<MyEntity>({
314
- tableName: 'my_table',
315
- searchFields: ['title', 'description'], // Campos de busca
316
- schemaName: 'schema_module', // Schema do banco
317
- entityName: 'MinhaEntidade' // Para enrichment Qualiex
318
- });
319
-
320
- // Pronto! Service com todas as operações CRUD:
321
- // - MyService.getAll() - Listar com paginação e busca
322
- // - MyService.create() - Criar com RLS automático
323
- // - MyService.update() - Atualizar com validação
324
- // - MyService.delete() - Soft delete (is_removed = true)
325
- ```
326
-
327
- ### Hook CRUD - Gerenciamento de Estado
328
-
329
- ```tsx
330
- import { useCrud } from 'forlogic-core';
331
-
332
- function MyComponent() {
333
- const manager = useCrud({
334
- queryKey: 'my-entities', // Cache key única
335
- service: MyService, // Service criado acima
336
- entityName: 'Item', // Nome singular
337
- pageSize: 25 // Itens por página (opcional)
338
- });
339
-
340
- // Estado disponível:
341
- const {
342
- entities, // Dados da página atual
343
- pagination, // Info de paginação
344
- isLoading, // Estado de carregamento
345
- searchTerm, // Termo de busca atual
346
-
347
- // Operações:
348
- createEntity, // Criar novo
349
- updateEntity, // Atualizar existente
350
- deleteEntity, // Soft delete
351
- refetch, // Recarregar dados
352
- handleSearch, // Buscar (debounced)
353
- handlePageChange, // Mudar página
354
- } = manager;
355
-
356
- return (
357
- <div>
358
- <input
359
- onChange={(e) => handleSearch(e.target.value)}
360
- placeholder="Buscar..."
361
- />
362
-
363
- {entities.map(item => (
364
- <div key={item.id}>
365
- <h3>{item.title}</h3>
366
- <button onClick={() => deleteEntity(item.id)}>
367
- Remover
368
- </button>
369
- </div>
370
- ))}
371
-
372
- <button onClick={() => handlePageChange(pagination.currentPage + 1)}>
373
- Próxima página
374
- </button>
375
- </div>
376
- );
377
- }
378
- ```
379
-
380
- **⚡ Performance**: React Query + debounce + paginação server-side
381
-
382
- ---
383
-
384
- ## 🎨 Sistema de Formulários
385
-
386
- ### Configuração Declarativa
387
-
388
- ```tsx
389
- // Definir formulário por configuração (zero JSX manual)
390
- const formSections = [
391
- {
392
- id: 'general',
393
- title: 'Informações Gerais',
394
- description: 'Dados principais do item',
395
- fields: [
396
- {
397
- name: 'title',
398
- label: 'Título',
399
- type: 'text',
400
- required: true,
401
- placeholder: 'Digite o título...'
402
- },
403
- {
404
- name: 'description',
405
- label: 'Descrição',
406
- type: 'textarea',
407
- rows: 4
408
- },
409
- {
410
- name: 'date_field',
411
- label: 'Data',
412
- type: 'date',
413
- required: true
414
- }
415
- ]
416
- },
417
- {
418
- id: 'advanced',
419
- title: 'Configurações Avançadas',
420
- condition: (formData) => formData.userType === 'admin', // Seção condicional
421
- fields: [
422
- {
423
- name: 'color',
424
- label: 'Cor do tema',
425
- type: 'color-picker'
426
- },
427
- {
428
- name: 'icon_name',
429
- label: 'Ícone',
430
- type: 'icon-picker'
431
- },
432
- {
433
- name: 'id_user',
434
- label: 'Responsável',
435
- type: 'simple-qualiex-user-field' // Campo integrado Qualiex
436
- }
437
- ]
438
- }
439
- ];
440
- ```
441
-
442
- ### Tipos de Campo Disponíveis
443
-
444
- #### 📝 Campos Básicos
445
- | Tipo | Descrição | Props Extras |
446
- |------|-----------|--------------|
447
- | `text` | Entrada de texto | `placeholder`, `maxLength` |
448
- | `textarea` | Área de texto | `rows`, `placeholder` |
449
- | `email` | E-mail com validação | `placeholder` |
450
- | `password` | Senha oculta | `placeholder` |
451
- | `number` | Número | `step`, `min`, `max` |
452
- | `date` | Data | `min`, `max` |
453
- | `datetime-local` | Data e hora | - |
454
- | `url` | URL com validação | `placeholder` |
455
-
456
- #### 🎯 Campos de Seleção
457
- | Tipo | Descrição | Props Extras |
458
- |------|-----------|--------------|
459
- | `select` | Seleção única | `options: [{label, value}]` |
460
- | `multiselect` | Seleção múltipla | `options`, `maxSelections` |
461
- | `checkbox` | Checkbox | `defaultValue: boolean` |
462
- | `radio` | Grupo de rádio | `options: [{label, value}]` |
463
-
464
- #### 🎨 Campos Visuais
465
- | Tipo | Descrição | Props Extras |
466
- |------|-----------|--------------|
467
- | `color` | Cor (input nativo) | - |
468
- | `color-picker` | Seletor de cores avançado | `presetColors` |
469
- | `icon-picker` | Seletor de ícones Lucide | `categories` |
470
-
471
- #### 🔌 Campos Integrados Qualiex
472
- | Tipo | Descrição | Props Extras |
473
- |------|-----------|--------------|
474
- | `simple-qualiex-user-field` | Usuário simples | - |
475
- | `user-select` | Seletor de usuário avançado | `multiple` |
476
- | `single-responsible-select` | Responsável único | - |
477
-
478
- #### 🔧 Campos Especiais
479
- | Tipo | Descrição | Props Extras |
480
- |------|-----------|--------------|
481
- | `group` | Agrupamento de campos | `fields: FormField[]` |
482
- | `divider` | Separador visual | `label` |
483
-
484
- ### Recursos Avançados
485
-
486
- #### 💡 Campos Computados
487
- ```tsx
488
- {
489
- name: 'fullName',
490
- label: 'Nome Completo',
491
- type: 'text',
492
- computedValue: (formData) => `${formData.firstName} ${formData.lastName}`,
493
- disabled: true
494
- }
495
- ```
496
-
497
- #### 🔗 Dependências entre Campos
498
- ```tsx
499
- {
500
- name: 'endDate',
501
- label: 'Data Final',
502
- type: 'date',
503
- dependsOn: 'startDate',
504
- validation: (value, formData) => {
505
- if (value < formData.startDate) {
506
- return 'Data final deve ser após a inicial';
507
- }
508
- }
509
- }
510
- ```
511
-
512
- #### ✅ Validação Customizada
513
- ```tsx
514
- {
515
- name: 'cpf',
516
- label: 'CPF',
517
- type: 'text',
518
- validation: {
519
- pattern: /^\d{3}\.\d{3}\.\d{3}-\d{2}$/,
520
- message: 'CPF deve estar no formato 000.000.000-00',
521
- custom: (value) => {
522
- if (!isValidCPF(value)) return 'CPF inválido';
523
- }
524
- }
525
- }
526
- ```
527
-
528
- #### 🔄 Callbacks de Mudança
529
- ```tsx
530
- {
531
- name: 'category',
532
- label: 'Categoria',
533
- type: 'select',
534
- options: categories,
535
- onValueChange: (value, formData, setValue) => {
536
- // Recarregar subcategorias baseado na categoria
537
- loadSubcategories(value).then(subs => {
538
- setValue('subcategory', null); // Reset subcategoria
539
- // Atualizar opções de subcategoria
540
- });
541
- }
542
- }
543
- ```
544
-
545
- ---
546
-
547
- ## 📊 Sistema de Tabelas e Cards
548
-
549
- ### Página CRUD Simplificada
550
-
551
- ### Exemplo Completo
552
-
553
- ```tsx
554
- import { createSimpleService, createCrudPage, generateCrudConfig } from 'forlogic-core';
555
- import { Package } from 'lucide-react';
556
-
557
- interface Product {
558
- id: string;
559
- name: string;
560
- price: number;
561
- category: string;
562
- description?: string;
563
- created_at?: Date;
564
- updated_at?: Date;
565
- }
566
-
567
- const productService = createSimpleService<Product>({
568
- tableName: 'products'
569
- });
570
-
571
- const config = generateCrudConfig<Product>(
572
- 'Produtos',
573
- { name: '', price: 0, category: 'electronics' },
574
- {
575
- icon: Package,
576
- columns: [
577
- { key: 'name', label: 'Nome', type: 'text' as const, required: true },
578
- { key: 'price', label: 'Preço', type: 'number' as const, required: true },
579
- { key: 'category', label: 'Categoria', type: 'select' as const, options: [
580
- { value: 'electronics', label: 'Eletrônicos' },
581
- { value: 'clothing', label: 'Roupas' },
582
- { value: 'books', label: 'Livros' }
583
- ]}
584
- ]
585
- }
586
- );
587
-
588
- export const ProductsPage = createCrudPage({
589
- service: productService,
590
- config
591
- });
592
- ```
593
-
594
- ### Responsividade Automática
595
-
596
- - **Desktop (≥768px)**: Tabela completa com ordenação
597
- - **Mobile (<768px)**: Cards otimizados para toque
598
- - **Transição suave**: Mudança automática no breakpoint
599
-
600
- ---
9
+ ### 🗄️ Schema do Banco
601
10
 
602
- ## 🔌 Integração Qualiex
11
+ Schema padrão deste projeto: **`central`**
603
12
 
604
- ### API de Usuários
13
+ ## 🤖 Instruções para IA (Lovable)
605
14
 
606
- ```tsx
607
- import { qualiexApi, useQualiexUsers } from 'forlogic-core';
15
+ ⚠️ **CONSULTAR SEMPRE antes de qualquer modificação:**
608
16
 
609
- // Hook para buscar usuários
610
- function MyComponent() {
611
- const { users, loading, error } = useQualiexUsers();
612
-
613
- return (
614
- <select>
615
- {users.map(user => (
616
- <option key={user.userId} value={user.userId}>
617
- {user.userName} ({user.userEmail})
618
- </option>
619
- ))}
620
- </select>
621
- );
622
- }
623
-
624
- // API direta
625
- const users = await qualiexApi.fetchUsers(alias, companyId);
626
- // Retorna: QualiexUser[] { userId, userName, userEmail }
627
- ```
628
-
629
- ### Enriquecimento Automático
630
-
631
- ```typescript
632
- // Service com enrichment automático
633
- export const TaskService = createService<Task>({
634
- tableName: 'tasks',
635
- searchFields: ['title'],
636
- entityName: 'Task' // Nome da entidade no Qualiex
637
- });
638
-
639
- // Dados enriquecidos automaticamente:
640
- // id_user "123" → responsible_name "João Silva"
641
- // Busca automática na API Qualiex quando necessário
642
- ```
643
-
644
- ---
645
-
646
- ## 🎯 Exemplos Práticos
647
-
648
- ### 1. CRUD de Produtos
649
-
650
- ```tsx
651
- // types.ts
652
- export interface Product {
653
- id: string;
654
- alias: string;
655
- name: string;
656
- description?: string;
657
- price: number;
658
- category_id: string;
659
- id_user: string; // Responsável
660
- is_actived: boolean;
661
- is_removed: boolean;
662
- created_at: string;
663
- updated_at: string;
664
-
665
- // Campos enriquecidos
666
- responsible_name?: string;
667
- category_name?: string;
668
- }
669
-
670
- // ProductService.ts
671
- import { createService } from 'forlogic-core';
672
-
673
- export const ProductService = createService<Product>({
674
- tableName: 'products',
675
- searchFields: ['name', 'description'],
676
- schemaName: 'schema_module',
677
- entityName: 'Product'
678
- });
679
-
680
- ```
681
-
682
- ---
683
-
684
- ### 2. Formulário de Contato Avançado
685
-
686
- ```tsx
687
- import { BaseForm } from 'forlogic-core';
688
-
689
- export function ContactForm({ open, onClose, onSubmit }) {
690
- const sections = [
691
- {
692
- id: 'personal',
693
- title: 'Dados Pessoais',
694
- fields: [
695
- {
696
- name: 'name',
697
- label: 'Nome Completo',
698
- type: 'text',
699
- required: true
700
- },
701
- {
702
- name: 'email',
703
- label: 'E-mail',
704
- type: 'email',
705
- required: true,
706
- validation: {
707
- pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
708
- message: 'E-mail inválido'
709
- }
710
- },
711
- {
712
- name: 'phone',
713
- label: 'Telefone',
714
- type: 'text',
715
- validation: {
716
- custom: (value) => {
717
- if (value && !isValidPhone(value)) {
718
- return 'Telefone inválido';
719
- }
720
- }
721
- }
722
- }
723
- ]
724
- },
725
- {
726
- id: 'preferences',
727
- title: 'Preferências',
728
- fields: [
729
- {
730
- name: 'contactMethod',
731
- label: 'Método de Contato Preferido',
732
- type: 'select',
733
- options: [
734
- { label: 'E-mail', value: 'email' },
735
- { label: 'Telefone', value: 'phone' },
736
- { label: 'WhatsApp', value: 'whatsapp' }
737
- ],
738
- onValueChange: (value, formData, setValue) => {
739
- if (value === 'whatsapp' && !formData.phone) {
740
- // Foco automático no campo telefone
741
- document.querySelector('[name="phone"]')?.focus();
742
- }
743
- }
744
- },
745
- {
746
- name: 'newsletter',
747
- label: 'Receber newsletter',
748
- type: 'checkbox',
749
- defaultValue: true
750
- }
751
- ]
752
- }
753
- ];
754
-
755
- return (
756
- <BaseForm
757
- open={open}
758
- title="Novo Contato"
759
- sections={sections}
760
- onSubmit={onSubmit}
761
- onCancel={onClose}
762
- submitText="Salvar Contato"
763
- />
764
- );
765
- }
766
- ```
767
-
768
- ---
769
-
770
- ## 🔒 Segurança e Performance
771
-
772
- ### Implementações de Segurança
773
-
774
- | Recurso | Implementação | Benefício |
775
- |---------|---------------|-----------|
776
- | **RLS Multi-tenant** | Política por `alias` | Isolamento total entre empresas |
777
- | **Soft Delete** | `is_removed = true` | Auditoria e recuperação |
778
- | **JWT Refresh** | Renovação automática | Sessões seguras |
779
- | **Input Validation** | Zod + client-side | Prevenção de dados inválidos |
780
- | **XSS Protection** | Sanitização automática | Prevenção de ataques |
781
-
782
- ### Otimizações de Performance
783
-
784
- | Recurso | Configuração | Impacto |
785
- |---------|--------------|---------|
786
- | **React Query Cache** | 10 min | -80% requests |
787
- | **Search Debounce** | 500ms | -90% queries |
788
- | **Paginação Server** | 25 itens | Escalabilidade |
789
- | **Lazy Loading** | Componentes | Menor bundle |
790
- | **Bundle Splitting** | Por rota | Carregamento rápido |
791
-
792
- ### Métricas Automáticas
793
-
794
- ```typescript
795
- // Configuração de performance (opcional)
796
- setupQualiexCore({
797
- // ... outras configs
798
- performance: {
799
- cacheTime: 10 * 60 * 1000, // 10 minutos
800
- staleTime: 5 * 60 * 1000, // 5 minutos
801
- debounceDelay: 500, // 500ms
802
- pageSize: 25, // 25 itens por página
803
- enableMetrics: true // Métricas automáticas
804
- }
805
- });
806
- ```
807
-
808
- ---
809
-
810
- ## 📚 Documentação Técnica
811
-
812
- ### Estrutura de Dados
813
-
814
- ```typescript
815
- // Tipos base do sistema
816
- export interface BaseEntity {
817
- id: string;
818
- alias: string;
819
- is_actived: boolean;
820
- is_removed: boolean;
821
- created_at: string;
822
- updated_at: string;
823
- }
824
-
825
- export interface PaginationInfo {
826
- currentPage: number;
827
- totalPages: number;
828
- totalItems: number;
829
- pageSize: number;
830
- hasNext: boolean;
831
- hasPrev: boolean;
832
- }
833
-
834
- export interface CrudManager<T> {
835
- entities: T[];
836
- pagination: PaginationInfo;
837
- isLoading: boolean;
838
- searchTerm: string;
839
- createEntity: (data: Partial<T>) => Promise<void>;
840
- updateEntity: (id: string, data: Partial<T>) => Promise<void>;
841
- deleteEntity: (id: string) => Promise<void>;
842
- refetch: () => void;
843
- handleSearch: (term: string) => void;
844
- handlePageChange: (page: number) => void;
845
- }
846
- ```
847
-
848
- ### Políticas RLS Template
849
-
850
- ```sql
851
- -- Template completo para novas tabelas
852
- -- docs/templates/rls-policies.sql
853
-
854
- -- Criar tabela
855
- CREATE TABLE schema_module.{table_name} (
856
- id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
857
- alias TEXT NOT NULL,
858
-
859
- -- Campos customizados aqui
860
- title TEXT NOT NULL,
861
- description TEXT,
862
-
863
- -- Campos de controle
864
- is_actived BOOLEAN DEFAULT true,
865
- is_removed BOOLEAN DEFAULT false,
866
- created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
867
- updated_at TIMESTAMP WITH TIME ZONE DEFAULT now()
868
- );
869
-
870
- -- RLS
871
- ALTER TABLE schema_module.{table_name} ENABLE ROW LEVEL SECURITY;
872
-
873
- -- Políticas padrão
874
- CREATE POLICY "view_company_data" ON schema_module.{table_name}
875
- FOR SELECT USING (
876
- ((SELECT auth.jwt()) ->> 'alias') = alias
877
- AND is_removed = false
878
- );
879
-
880
- CREATE POLICY "insert_company_data" ON schema_module.{table_name}
881
- FOR INSERT WITH CHECK (
882
- ((SELECT auth.jwt()) ->> 'alias') = alias
883
- );
884
-
885
- CREATE POLICY "update_company_data" ON schema_module.{table_name}
886
- FOR UPDATE USING (
887
- ((SELECT auth.jwt()) ->> 'alias') = alias
888
- );
889
-
890
- -- Trigger updated_at
891
- CREATE TRIGGER update_{table_name}_updated_at
892
- BEFORE UPDATE ON schema_module.{table_name}
893
- FOR EACH ROW
894
- EXECUTE FUNCTION schema_module.update_updated_at_column();
895
- ```
896
-
897
- ### Edge Functions
898
-
899
- ```typescript
900
- // validate-token/index.ts
901
- import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
902
-
903
- serve(async (req) => {
904
- const { access_token } = await req.json();
905
-
906
- // Validar token no Qualiex
907
- const userInfo = await validateWithQualiex(access_token);
908
-
909
- // Gerar token Supabase
910
- const supabaseToken = await generateSupabaseToken(userInfo);
911
-
912
- return new Response(
913
- JSON.stringify({
914
- supabase_token: supabaseToken,
915
- user: userInfo
916
- }),
917
- { headers: { 'Content-Type': 'application/json' } }
918
- );
919
- });
920
- ```
921
-
922
- ---
923
-
924
- ## 🚀 Guia de Migração
925
-
926
- ### De Sistemas Legados
927
-
928
- ```typescript
929
- // ANTES: Código manual complexo
930
- const [data, setData] = useState([]);
931
- const [loading, setLoading] = useState(false);
932
- const [search, setSearch] = useState('');
933
-
934
- useEffect(() => {
935
- loadData();
936
- }, [search]);
937
-
938
- const loadData = async () => {
939
- setLoading(true);
940
- try {
941
- const result = await api.getData({ search });
942
- setData(result);
943
- } finally {
944
- setLoading(false);
945
- }
946
- };
947
-
948
- // DEPOIS: Hook simplificado
949
- const manager = useCrud({
950
- queryKey: 'my-data',
951
- service: MyService,
952
- entityName: 'Item'
953
- });
954
-
955
- // Pronto! Todas as funcionalidades automáticas
956
- ```
957
-
958
- ### Checklist de Migração
959
-
960
- - [ ] ✅ Criar tabela com estrutura padrão
961
- - [ ] ✅ Configurar políticas RLS
962
- - [ ] ✅ Criar service com `createService()`
963
- - [ ] ✅ Substituir código manual por `useCrud()`
964
- - [ ] ✅ Configurar formulários declarativos
965
- - [ ] ✅ Testar operações CRUD
966
- - [ ] ✅ Verificar responsividade
967
- - [ ] ✅ Configurar integração Qualiex (se necessário)
968
-
969
- ---
970
-
971
- ## 🛠️ Desenvolvimento
972
-
973
- ### Comandos de Build
974
-
975
- ```bash
976
- # Desenvolvimento da lib
977
- npm run dev
978
-
979
- # Build da biblioteca
980
- npm run build:lib
981
- # ou
982
- ./build-and-publish.sh build
983
-
984
- # Publicar versão
985
- ./build-and-publish.sh patch # 1.0.0 → 1.0.1
986
- ./build-and-publish.sh minor # 1.0.0 → 1.1.0
987
- ./build-and-publish.sh major # 1.0.0 → 2.0.0
988
-
989
- # Teste de publicação
990
- ./build-and-publish.sh dry-run
991
- ```
992
-
993
- ### Estrutura de Build
994
-
995
- ```
996
- dist/ # Saída da build
997
- ├── index.js # CommonJS
998
- ├── index.esm.js # ES Modules
999
- ├── index.d.ts # Types
1000
- ├── index.css # CSS incluído
1001
- ├── package.json # Package da lib
1002
- └── README.md # Esta documentação
1003
- ```
1004
-
1005
- ### Scripts Personalizados
1006
-
1007
- ```javascript
1008
- // scripts/build-lib.js - Build customizado
1009
- // scripts/publish-lib.js - Publicação automatizada
1010
- // build-and-publish.sh - Wrapper para comandos
1011
- ```
1012
-
1013
- ---
1014
-
1015
- ## 🎯 Princípios de Desenvolvimento
1016
-
1017
- ### ✅ SEMPRE Fazer
1018
-
1019
- - **Imports diretos**: `import { Component } from 'forlogic-core'`
1020
- - **Componentes pequenos**: Máximo 100 linhas
1021
- - **RLS ativado**: Todas as tabelas com políticas
1022
- - **Soft delete**: `is_removed = true`
1023
- - **Props inline**: Evitar interfaces desnecessárias
1024
- - **Configuração declarativa**: Formulários por config
1025
-
1026
- ### ❌ NUNCA Fazer
1027
-
1028
- - Barrel exports (`index.ts` desnecessários)
1029
- - Over-engineering (YAGNI)
1030
- - DELETE físico no banco
1031
- - Componentes monolíticos
1032
- - Props drilling excessivo
1033
- - Ignorar políticas RLS
1034
-
1035
- ### 🔥 Filosofia
1036
-
1037
- > **"Máxima produtividade com mínima complexidade"**
1038
-
1039
- - ⚡ **Performance**: React Query + otimizações automáticas
1040
- - 🔒 **Segurança**: RLS + JWT + validação
1041
- - 📱 **Responsividade**: Mobile-first automático
1042
- - 🔧 **DX**: Zero config, máxima simplicidade
1043
- - 🎨 **Design**: Sistema consistente e acessível
1044
-
1045
- ---
1046
-
1047
- ## 📋 Troubleshooting
1048
-
1049
- ### Problemas Comuns
1050
-
1051
- **❌ Erro: "RLS policy violation"**
1052
- ```sql
1053
- -- Verificar se as políticas estão corretas
1054
- SELECT schemaname, tablename, policyname
1055
- FROM pg_policies
1056
- WHERE tablename = 'your_table';
1057
- ```
1058
-
1059
- **❌ Erro: "Cannot read property of undefined"**
1060
- ```typescript
1061
- // Verificar se o serviço foi configurado corretamente
1062
- export const MyService = createService<MyEntity>({
1063
- tableName: 'correct_table_name', // ← Verificar nome
1064
- schemaName: 'schema_module', // ← Verificar schema
1065
- // ...
1066
- });
1067
- ```
1068
-
1069
- **❌ Formulário não aparece**
1070
- ```tsx
1071
- // Verificar se as seções estão configuradas
1072
- const formSections = [
1073
- {
1074
- id: 'section1', // ← ID obrigatório
1075
- title: 'Título', // ← Título obrigatório
1076
- fields: [ // ← Array de campos obrigatório
1077
- {
1078
- name: 'field1', // ← Nome obrigatório
1079
- label: 'Label', // ← Label obrigatório
1080
- type: 'text' // ← Tipo obrigatório
1081
- }
1082
- ]
1083
- }
1084
- ];
1085
- ```
1086
-
1087
- ### Debug Mode
1088
-
1089
- ```typescript
1090
- // Ativar logs detalhados
1091
- setupQualiexCore({
1092
- // ... outras configs
1093
- debug: true // Logs no console
1094
- });
1095
- ```
1096
-
1097
- ---
1098
-
1099
- ## 📞 Suporte
1100
-
1101
- ### Recursos
1102
-
1103
- - 📖 **Documentação**: Este README
1104
- - 🔧 **Exemplos**: `/src/examples/`
1105
- - 🐛 **Issues**: GitHub Issues
1106
- - 💬 **Suporte**: Equipe ForLogic
1107
-
1108
- ### Atualizações
1109
-
1110
- ```bash
1111
- # Verificar versão atual
1112
- npm list forlogic-core
1113
-
1114
- # Atualizar para última versão
1115
- npm update forlogic-core
1116
-
1117
- # Migração automática
1118
- npx forlogic-core migrate
1119
- ```
1120
-
1121
- ---
17
+ 1. **README.md da lib**: Acesse via `node_modules/forlogic-core/dist/README.md` - Instalação e Quick Start
18
+ 2. **AI_RULES.md**: Acesse via `node_modules/forlogic-core/dist/docs/AI_RULES.md` - **REGRAS CRÍTICAS**
19
+ 3. **Templates**: Acesse via `node_modules/forlogic-core/dist/docs/templates/` - Códigos prontos
20
+ 4. **Hub da Docs**: Acesse via `node_modules/forlogic-core/dist/docs/README.md` - Navegação completa
1122
21
 
1123
- ## 📄 Licença
22
+ **NUNCA recriar:**
23
+ - ❌ Integração Qualiex (já existe na lib)
24
+ - ❌ Integração Supabase (já existe na lib)
25
+ - ❌ Sistema CRUD (usar `createCrudPage` da lib)
26
+ - ❌ Componentes base (importar de `forlogic-core`)
1124
27
 
1125
- MIT License - ForLogic © 2025
28
+ **SEMPRE verificar:**
29
+ - ✅ Schema padrão do projeto
30
+ - ✅ Templates disponíveis antes de criar do zero
1126
31
 
1127
32
  ---
1128
33
 
1129
- **✨ Sistema ultra-simplificado para máxima produtividade empresarial**
34
+ ## 📝 Licença
1130
35
 
1131
- *Arquitetura pensada para desenvolvedores que valorizam simplicidade, performance e segurança.*
36
+ MIT License - ForLogic © 2025