forlogic-core 1.16.3 → 1.16.5

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.
Files changed (134) hide show
  1. package/README.md +113 -109
  2. package/dist/README.md +113 -109
  3. package/dist/components/modules/AccessDeniedDialog.d.ts +41 -0
  4. package/dist/components/modules/ModuleAccessGuard.d.ts +3 -1
  5. package/dist/components/modules/ModuleOfferContent.d.ts +20 -0
  6. package/dist/components/modules/ModulesContent.d.ts +15 -0
  7. package/dist/components/modules/ModulesFooterCards.d.ts +6 -0
  8. package/dist/components/modules/index.d.ts +8 -0
  9. package/dist/components/modules/types.d.ts +2 -0
  10. package/dist/index.css +1 -1
  11. package/dist/index.css.map +1 -1
  12. package/dist/index.esm.js +1 -1
  13. package/dist/index.js +1 -1
  14. package/docs/DESIGN_SYSTEM.md +17 -32
  15. package/package.json +4 -2
  16. package/dist/assets/AccordionDoc-BnfxyOi9.js +0 -31
  17. package/dist/assets/ActionButtonDoc-b4F_J8gn.js +0 -47
  18. package/dist/assets/AlertDoc-PkiHguSJ.js +0 -37
  19. package/dist/assets/AppHeaderDoc-CsFMZGV0.js +0 -67
  20. package/dist/assets/AppSidebarDoc-Bg71N-zq.js +0 -196
  21. package/dist/assets/AuthDoc-DDm57y_J.js +0 -192
  22. package/dist/assets/AvatarDoc-C6wiZIZR.js +0 -11
  23. package/dist/assets/BadgeDoc-Bsg7cfm0.js +0 -36
  24. package/dist/assets/BaseFormDoc-DeIlV273.js +0 -169
  25. package/dist/assets/BodyContentDoc-Q3DGvyN9.js +0 -83
  26. package/dist/assets/BreadcrumbDoc-ChsVFjMF.js +0 -75
  27. package/dist/assets/ButtonDoc-C7Q31Bh3.js +0 -41
  28. package/dist/assets/ButtonGroupDoc-Bn5vhjBq.js +0 -7
  29. package/dist/assets/CalendarDoc-iVjNyxyr.js +0 -81
  30. package/dist/assets/CardDoc-D511dll7.js +0 -49
  31. package/dist/assets/ChartDoc-CQyYOEHL.js +0 -111
  32. package/dist/assets/CheckboxDoc-Cjsy4XAq.js +0 -55
  33. package/dist/assets/ColorPickerDoc-hnYJUWpF.js +0 -10
  34. package/dist/assets/ColorsFoundationDoc-B8Z4tAyZ.js +0 -13
  35. package/dist/assets/ComboTreeDoc-ChEbW4a3.js +0 -21
  36. package/dist/assets/ComboboxDoc-CHWeGE_F.js +0 -134
  37. package/dist/assets/ComponentDocTemplate-BtOCnlM2.js +0 -1
  38. package/dist/assets/ContextMenuDoc-C3mFO_Yx.js +0 -182
  39. package/dist/assets/ContextsDoc-ChEbQxom.js +0 -184
  40. package/dist/assets/CreateCrudPageDoc-C9tXisCF.js +0 -106
  41. package/dist/assets/CrudActionBarDoc-Cp1L4gpO.js +0 -112
  42. package/dist/assets/CrudGridDoc-D-kSFBAQ.js +0 -85
  43. package/dist/assets/CrudOverviewDoc-CeLBwg-B.js +0 -14
  44. package/dist/assets/CrudPrimitivesDoc-B2u1vZog.js +0 -164
  45. package/dist/assets/CrudTableDoc-CvV-II_X.js +0 -95
  46. package/dist/assets/DataListDoc-BLRii0jB.js +0 -13
  47. package/dist/assets/DesignSystemHome-TE0Ubaup.js +0 -1
  48. package/dist/assets/DialogDoc--LC5Jvat.js +0 -981
  49. package/dist/assets/DropdownMenuDoc-oPlEriRY.js +0 -175
  50. package/dist/assets/EmptyStateDoc-rNqfWKok.js +0 -35
  51. package/dist/assets/EnvironmentsDoc-CT7l5s2u.js +0 -96
  52. package/dist/assets/ErrorBoundaryDoc-rPHOUygA.js +0 -111
  53. package/dist/assets/ExampleCard-DfuMYM6E.js +0 -1
  54. package/dist/assets/FormDoc-B0L_QaCT.js +0 -81
  55. package/dist/assets/FoundationOverview-Dbb8rBsU.js +0 -1
  56. package/dist/assets/GridDoc-ifcGA2Yw.js +0 -28
  57. package/dist/assets/HooksDoc-CUOT_3Du.js +0 -665
  58. package/dist/assets/HoverCardDoc-CdTU2QkI.js +0 -31
  59. package/dist/assets/I18nDoc-CMEvFqsz.js +0 -232
  60. package/dist/assets/IconPickerDoc-DF9hEwnJ.js +0 -10
  61. package/dist/assets/IconsFoundationDoc-D4Y0wKbm.js +0 -33
  62. package/dist/assets/InputDoc-d_IL4dsq.js +0 -211
  63. package/dist/assets/LabelDoc-Dr64ISiJ.js +0 -42
  64. package/dist/assets/LeadershipDoc-BnrTuaeV.js +0 -416
  65. package/dist/assets/MediaDoc-CLuVprAr.js +0 -459
  66. package/dist/assets/MenubarDoc-CW7L4QJ4.js +0 -165
  67. package/dist/assets/ModulesDialogDoc-CUb_g4X-.js +0 -71
  68. package/dist/assets/NavigationMenuDoc-Csc0U6bV.js +0 -116
  69. package/dist/assets/OnboardingDialogDoc-3RtjNH1O.js +0 -55
  70. package/dist/assets/PaginationDoc-BGurD4xQ.js +0 -27
  71. package/dist/assets/PaginationDoc-DqFyou6O.js +0 -98
  72. package/dist/assets/PlacesDoc-Dyx8gsqb.js +0 -226
  73. package/dist/assets/PopoverDoc-DHF-ItUX.js +0 -64
  74. package/dist/assets/ProgressDoc-DXKV-fkI.js +0 -29
  75. package/dist/assets/QualiexUserFieldDoc-BbP7w-Pu.js +0 -149
  76. package/dist/assets/RadioGroupDoc-D845uweM.js +0 -57
  77. package/dist/assets/RadiusDoc-vN4tTsay.js +0 -7
  78. package/dist/assets/RequiredFieldsCounterDoc-TzR9r-U9.js +0 -58
  79. package/dist/assets/ResizableDoc-Bkfz_25O.js +0 -104
  80. package/dist/assets/RichTextEditorDoc-BUQrg7M8.js +0 -24
  81. package/dist/assets/ScrollAreaDoc-B6ODYHMX.js +0 -28
  82. package/dist/assets/SecurityDoc-Chbt6w1s.js +0 -204
  83. package/dist/assets/SelectDoc-BhcpBIAO.js +0 -80
  84. package/dist/assets/SeparatorDoc-C3fhatb0.js +0 -4
  85. package/dist/assets/ServicesDoc-_uao-HA_.js +0 -308
  86. package/dist/assets/ShadowsDoc-DpkO_TZQ.js +0 -9
  87. package/dist/assets/SignDoc-BJtnoT6I.js +0 -66
  88. package/dist/assets/SkeletonDoc-BZS07PJh.js +0 -54
  89. package/dist/assets/SliderDoc-D2ApV3XT.js +0 -41
  90. package/dist/assets/SpacingDoc-PNrU24B2.js +0 -12
  91. package/dist/assets/SplitButtonDoc-D5tUF2Ja.js +0 -53
  92. package/dist/assets/StepSelectorDoc-Cj0ALYar.js +0 -41
  93. package/dist/assets/SwitchDoc-DtsT8oh_.js +0 -56
  94. package/dist/assets/TableDoc-BC-jQnXu.js +0 -128
  95. package/dist/assets/TableOfContents-DBMJMbI4.js +0 -1
  96. package/dist/assets/TabsDoc-DtXJ0xY5.js +0 -42
  97. package/dist/assets/TextareaDoc-nuW5tqBQ.js +0 -46
  98. package/dist/assets/ToastDoc-D1aX5zda.js +0 -157
  99. package/dist/assets/ToggleDoc-ILass4CS.js +0 -51
  100. package/dist/assets/TooltipDoc-lPbdWe_9.js +0 -58
  101. package/dist/assets/TruncatedCellDoc-DOAzbF2F.js +0 -12
  102. package/dist/assets/TypographyFoundationDoc-3ZD-rQZw.js +0 -7
  103. package/dist/assets/UtilitiesDoc-D7lkYhuz.js +0 -145
  104. package/dist/assets/blocks-Jy49RoqJ.js +0 -1
  105. package/dist/assets/calendar-days-Cvf2zLJl.js +0 -1
  106. package/dist/assets/circle-plus-MnG9kjyq.js +0 -1
  107. package/dist/assets/circle-x-B9ouupla.js +0 -1
  108. package/dist/assets/crown-BweN5jpI.js +0 -1
  109. package/dist/assets/date-picker-ttyYeYvC.js +0 -1
  110. package/dist/assets/disabled-menu-item-WlpPOqxg.js +0 -1
  111. package/dist/assets/drawer-DvU6_eK5.js +0 -3
  112. package/dist/assets/file-pen-line-C0VV-QjF.js +0 -1
  113. package/dist/assets/git-branch-DCjGGwvF.js +0 -1
  114. package/dist/assets/globe-BdFDFP_k.js +0 -1
  115. package/dist/assets/grip-vertical-CgXp0oI-.js +0 -1
  116. package/dist/assets/hash-BAYi_wfk.js +0 -1
  117. package/dist/assets/index-BtX5DZqb.js +0 -310
  118. package/dist/assets/index-C1So5Sai.css +0 -1
  119. package/dist/assets/life-buoy-BydIgTyJ.js +0 -1
  120. package/dist/assets/lucide-react-ZIMhRYmb.js +0 -1
  121. package/dist/assets/monitor-B6txWJPg.js +0 -1
  122. package/dist/assets/package-DNe3FsCh.js +0 -1
  123. package/dist/assets/pen-CzTmQ16z.js +0 -1
  124. package/dist/assets/pin-CJJgLEBz.js +0 -1
  125. package/dist/assets/radio-group-Btv_BY60.js +0 -1
  126. package/dist/assets/server-XQDXtrjm.js +0 -1
  127. package/dist/assets/share-2-Dz_89MJb.js +0 -1
  128. package/dist/assets/step-selector-D0_Y1dow.js +0 -1
  129. package/dist/assets/text-align-start-WsHo7CNJ.js +0 -1
  130. package/dist/assets/trash-CeK-mWnM.js +0 -1
  131. package/dist/assets/useMockCrud-RV9z9n5x.js +0 -1
  132. package/dist/assets/user-check-CrbWcnPN.js +0 -1
  133. package/dist/assets/user-plus-Dce9DbqQ.js +0 -1
  134. package/dist/index.html +0 -35
@@ -1,204 +0,0 @@
1
- import{j as e,C as s,B as r,aq as n,aA as c,b7 as d,aC as l,bZ as o,ba as p,bB as m,bd as u}from"./index-BtX5DZqb.js";import{C as g}from"./ComponentDocTemplate-BtOCnlM2.js";import{S as f}from"./server-XQDXtrjm.js";import{G as x}from"./globe-BdFDFP_k.js";import"./ExampleCard-DfuMYM6E.js";import"./TableOfContents-DBMJMbI4.js";function h(){return e.jsx("div",{className:"space-y-6",children:e.jsxs("div",{className:"grid gap-4 md:grid-cols-2 lg:grid-cols-4",children:[e.jsxs(s,{className:"p-4 border-2",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-2",children:[e.jsx("div",{className:"p-2 rounded-lg bg-green-500/10",children:e.jsx(o,{className:"h-5 w-5 text-green-500"})}),e.jsx("h4",{className:"font-semibold",children:"CSP"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Content Security Policy para prevenir XSS e injeção de código"})]}),e.jsxs(s,{className:"p-4 border-2",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-2",children:[e.jsx("div",{className:"p-2 rounded-lg bg-blue-500/10",children:e.jsx(x,{className:"h-5 w-5 text-blue-500"})}),e.jsx("h4",{className:"font-semibold",children:"CORS"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Controle de origens confiáveis sem usar wildcards inseguros"})]}),e.jsxs(s,{className:"p-4 border-2",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-2",children:[e.jsx("div",{className:"p-2 rounded-lg bg-orange-500/10",children:e.jsx(m,{className:"h-5 w-5 text-orange-500"})}),e.jsx("h4",{className:"font-semibold",children:"HSTS"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Força HTTPS com preload e inclusão de subdomínios"})]}),e.jsxs(s,{className:"p-4 border-2",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-2",children:[e.jsx("div",{className:"p-2 rounded-lg bg-purple-500/10",children:e.jsx(u,{className:"h-5 w-5 text-purple-500"})}),e.jsx("h4",{className:"font-semibold",children:"Headers OWASP"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Headers recomendados pela OWASP para proteção adicional"})]})]})})}function v(){const i=[{name:"Strict-Transport-Security",value:"max-age=31536000; includeSubDomains; preload",desc:"Força HTTPS por 1 ano"},{name:"X-Content-Type-Options",value:"nosniff",desc:"Previne MIME sniffing"},{name:"X-Frame-Options",value:"DENY",desc:"Bloqueia iframe embedding"},{name:"X-XSS-Protection",value:"1; mode=block",desc:"Filtro XSS do navegador"},{name:"Referrer-Policy",value:"strict-origin-when-cross-origin",desc:"Controla vazamento de referrer"},{name:"Permissions-Policy",value:"camera=(), microphone=()...",desc:"Desabilita APIs sensíveis"}];return e.jsxs(s,{className:"p-4 bg-muted/50",children:[e.jsxs("h4",{className:"font-semibold mb-3 flex items-center gap-2",children:[e.jsx(f,{className:"h-4 w-4"}),"Headers de Segurança Aplicados"]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b",children:[e.jsx("th",{className:"text-left py-2 px-3 font-medium",children:"Header"}),e.jsx("th",{className:"text-left py-2 px-3 font-medium",children:"Valor"}),e.jsx("th",{className:"text-left py-2 px-3 font-medium",children:"Proteção"})]})}),e.jsx("tbody",{className:"divide-y",children:i.map((a,t)=>e.jsxs("tr",{children:[e.jsx("td",{className:"py-2 px-3",children:e.jsx("code",{className:"text-xs",children:a.name})}),e.jsx("td",{className:"py-2 px-3 text-muted-foreground text-xs font-mono",children:a.value}),e.jsx("td",{className:"py-2 px-3 text-muted-foreground text-xs",children:a.desc})]},t))})]})})]})}function j(){const i=[{name:"default-src",value:"'self'",prod:!0,dev:!0},{name:"script-src",value:"'self' + CDNs",prod:!0,dev:!0},{name:"style-src",value:"'self' + fonts",prod:!0,dev:!0},{name:"connect-src",value:"'self' + Supabase",prod:!0,dev:!0},{name:"img-src",value:"'self' data: https:",prod:!0,dev:!0},{name:"frame-ancestors",value:"'self' lovable.dev",prod:!0,dev:!0},{name:"upgrade-insecure-requests",value:"(automático)",prod:!0,dev:!1},{name:"require-trusted-types-for",value:"'script'",prod:!0,dev:!1}];return e.jsxs(s,{className:"p-4 space-y-3",children:[e.jsxs("h4",{className:"font-medium flex items-center gap-2",children:[e.jsx(p,{className:"h-4 w-4"}),"Diretivas CSP"]}),e.jsx("div",{className:"space-y-2",children:i.map((a,t)=>e.jsxs("div",{className:"flex items-center justify-between text-sm py-1 border-b last:border-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("code",{className:"text-xs bg-muted px-1 rounded",children:a.name}),e.jsx("span",{className:"text-muted-foreground text-xs",children:a.value})]}),e.jsxs("div",{className:"flex gap-1",children:[a.prod&&e.jsx(r,{variant:"secondary",className:"text-[10px]",children:"PROD"}),a.dev&&e.jsx(r,{variant:"outline",className:"text-[10px]",children:"DEV"})]})]},t))})]})}function O(){return e.jsx(g,{title:"Segurança (Vite Config)",description:"Plugin de segurança para Vite que aplica headers OWASP, CSP configurável, CORS seguro e proteções contra ataques comuns. Configuração centralizada para todos os projetos Forlogic.",installation:`// vite.config.ts
2
- import { defineConfig } from 'vite';
3
- import react from '@vitejs/plugin-react-swc';
4
- import path from 'path';
5
- import { createForlogicViteConfig } from 'forlogic-core/vite';
6
-
7
- const forlogicConfig = createForlogicViteConfig({
8
- security: {
9
- supabaseUrls: ['https://seu-projeto.supabase.co'],
10
- trustedOrigins: ['https://seu-app.com'],
11
- },
12
- });
13
-
14
- export default defineConfig(({ mode }) => {
15
- const isDev = mode === 'development';
16
- const baseConfig = forlogicConfig(isDev);
17
-
18
- return {
19
- ...baseConfig,
20
- plugins: [react(), ...baseConfig.plugins],
21
- resolve: {
22
- alias: {
23
- '@': path.resolve(__dirname, './src'),
24
- },
25
- },
26
- };
27
- });`,component:e.jsx(h,{}),usage:`// Importar do módulo /vite
28
- import {
29
- createForlogicViteConfig,
30
- createSecurityHeadersPlugin,
31
- defaultForlogicViteConfig
32
- } from 'forlogic-core/vite';
33
-
34
- // Opção 1: Configuração completa (recomendado)
35
- const forlogicConfig = createForlogicViteConfig({
36
- security: { ... },
37
- server: { port: 3000 },
38
- build: { sourcemap: true },
39
- });
40
-
41
- // Opção 2: Apenas plugin de segurança
42
- const securityPlugin = createSecurityHeadersPlugin(isDev, {
43
- supabaseUrls: ['https://xyz.supabase.co'],
44
- });
45
-
46
- // Opção 3: Configuração padrão mínima
47
- const baseConfig = defaultForlogicViteConfig(isDev);`,examples:[{title:"Headers de Segurança OWASP",description:"Headers aplicados automaticamente seguindo recomendações OWASP",preview:e.jsx(v,{}),code:`// Headers aplicados automaticamente pelo plugin:
48
-
49
- // HSTS - Força HTTPS por 1 ano
50
- 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload'
51
-
52
- // Previne MIME type sniffing
53
- 'X-Content-Type-Options': 'nosniff'
54
-
55
- // Bloqueia embedding em iframes (proteção clickjacking)
56
- 'X-Frame-Options': 'DENY'
57
-
58
- // Ativa filtro XSS do navegador
59
- 'X-XSS-Protection': '1; mode=block'
60
-
61
- // Controla vazamento de informações via referrer
62
- 'Referrer-Policy': 'strict-origin-when-cross-origin'
63
-
64
- // Desabilita APIs potencialmente perigosas
65
- 'Permissions-Policy': 'camera=(), microphone=(), geolocation=(), fullscreen=(self), payment=(), display-capture=()'`},{title:"Content Security Policy (CSP)",description:"Política de segurança de conteúdo configurável por ambiente",preview:e.jsx(j,{}),code:`// CSP gerado automaticamente baseado no ambiente
66
-
67
- // DESENVOLVIMENTO: Permite HMR e eval do Vite
68
- "script-src 'self' https://cdn.gpteng.co 'unsafe-inline' 'unsafe-eval'"
69
- "style-src 'self' https://fonts.googleapis.com 'unsafe-inline'"
70
-
71
- // PRODUÇÃO: CSP estrito
72
- "script-src 'self' https://cdn.gpteng.co"
73
- "style-src 'self' https://fonts.googleapis.com"
74
- "require-trusted-types-for 'script'"
75
- "upgrade-insecure-requests"
76
-
77
- // Customizar via opções:
78
- createForlogicViteConfig({
79
- security: {
80
- additionalScriptSrc: ['https://cdn.minha-lib.com'],
81
- additionalStyleSrc: ['https://fonts.custom.com'],
82
- additionalConnectSrc: ['https://api.terceiros.com'],
83
- cspReportUri: 'https://meu-app.com/csp-report',
84
- enableTrustedTypes: true,
85
- upgradeInsecureRequests: true,
86
- }
87
- });`},{title:"CORS Seguro",description:"Controle de origens sem usar wildcards (*) com credenciais",preview:e.jsxs(s,{className:"p-4 space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("h4",{className:"font-medium text-sm",children:"Origens Confiáveis Padrão:"}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(r,{variant:"secondary",children:"lovableproject.com"}),e.jsx(r,{variant:"secondary",children:"lovable.dev"}),e.jsx(r,{variant:"outline",children:"localhost:* (dev)"})]})]}),e.jsx(n,{}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("h4",{className:"font-medium text-sm",children:"Origens Customizadas:"}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(r,{children:"seu-app.com"}),e.jsx(r,{children:"admin.seu-app.com"})]})]})]}),code:`// CORS seguro - nunca usa '*' com credenciais
88
-
89
- createForlogicViteConfig({
90
- security: {
91
- trustedOrigins: [
92
- 'https://seu-app.com',
93
- 'https://admin.seu-app.com',
94
- 'https://*.subdominio.com', // Suporte a wildcards
95
- ],
96
- }
97
- });
98
-
99
- // Headers CORS aplicados quando origem é confiável:
100
- 'Access-Control-Allow-Origin': origin // Origem específica, nunca '*'
101
- 'Access-Control-Allow-Credentials': 'true'
102
- 'Access-Control-Allow-Methods': 'GET, POST, PUT, PATCH, DELETE, OPTIONS'
103
- 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type, x-csrf-token, x-nonce'
104
- 'Access-Control-Max-Age': '86400'
105
- 'Vary': 'Origin'
106
-
107
- // ⚠️ Origens não confiáveis são bloqueadas e logadas:
108
- // 🚨 CORS BLOCKED: Untrusted origin attempted access: https://malicious.com`},{title:"Opções Completas de Configuração",description:"Todas as opções disponíveis para personalização",preview:e.jsxs(s,{className:"p-4 space-y-3",children:[e.jsx("h4",{className:"font-medium",children:"ForlogicViteOptions:"}),e.jsxs("div",{className:"text-sm space-y-2",children:[e.jsxs("div",{className:"flex justify-between py-1 border-b",children:[e.jsx("code",{className:"text-xs",children:"security"}),e.jsx("span",{className:"text-muted-foreground text-xs",children:"SecurityHeadersOptions"})]}),e.jsxs("div",{className:"flex justify-between py-1 border-b",children:[e.jsx("code",{className:"text-xs",children:"server"}),e.jsx("span",{className:"text-muted-foreground text-xs",children:"{ host, port }"})]}),e.jsxs("div",{className:"flex justify-between py-1 border-b",children:[e.jsx("code",{className:"text-xs",children:"build"}),e.jsx("span",{className:"text-muted-foreground text-xs",children:"{ chunkSizeWarningLimit, sourcemap }"})]}),e.jsxs("div",{className:"flex justify-between py-1 border-b",children:[e.jsx("code",{className:"text-xs",children:"additionalPlugins"}),e.jsx("span",{className:"text-muted-foreground text-xs",children:"VitePlugin[]"})]}),e.jsxs("div",{className:"flex justify-between py-1",children:[e.jsx("code",{className:"text-xs",children:"disableSecurity"}),e.jsx("span",{className:"text-muted-foreground text-xs",children:"boolean (não recomendado)"})]})]})]}),code:`import { createForlogicViteConfig } from 'forlogic-core/vite';
109
-
110
- const forlogicConfig = createForlogicViteConfig({
111
- // Configurações de segurança
112
- security: {
113
- supabaseUrls: ['https://xyz.supabase.co'],
114
- trustedOrigins: ['https://meu-app.com'],
115
- additionalScriptSrc: [],
116
- additionalStyleSrc: [],
117
- additionalConnectSrc: ['https://api.terceiros.com'],
118
- cspReportUri: 'https://meu-app.com/csp-violations',
119
- enableTrustedTypes: true,
120
- upgradeInsecureRequests: true,
121
- },
122
-
123
- // Configurações do servidor dev
124
- server: {
125
- host: '::',
126
- port: 8080,
127
- },
128
-
129
- // Configurações de build
130
- build: {
131
- chunkSizeWarningLimit: 4000,
132
- sourcemap: true,
133
- },
134
-
135
- // Plugins Vite adicionais
136
- additionalPlugins: [],
137
-
138
- // ⚠️ Desabilitar segurança (NÃO RECOMENDADO)
139
- disableSecurity: false,
140
- });`},{title:"Exemplo Completo vite.config.ts",description:"Configuração completa pronta para uso em produção",preview:e.jsxs(c,{children:[e.jsx(d,{className:"h-4 w-4 text-green-500"}),e.jsx(l,{children:e.jsxs("div",{className:"space-y-1 text-sm",children:[e.jsx("p",{className:"font-medium",children:"Configuração pronta para produção:"}),e.jsx("p",{children:"• Headers OWASP aplicados automaticamente"}),e.jsx("p",{children:"• CSP estrito em produção"}),e.jsx("p",{children:"• CORS seguro sem wildcards"}),e.jsx("p",{children:"• Trusted Types habilitado"})]})})]}),code:`// vite.config.ts
141
- import { defineConfig } from 'vite';
142
- import react from '@vitejs/plugin-react-swc';
143
- import path from 'path';
144
- import { createForlogicViteConfig } from 'forlogic-core/vite';
145
-
146
- const forlogicConfig = createForlogicViteConfig({
147
- security: {
148
- supabaseUrls: [
149
- 'https://tskpcuganynhsppzoqgj.supabase.co',
150
- 'https://ccjfvpnndclajkleyqkc.supabase.co',
151
- ],
152
- trustedOrigins: [
153
- 'https://meu-app.lovable.app',
154
- 'https://meu-dominio.com',
155
- ],
156
- additionalConnectSrc: [
157
- 'https://api.qualiex.com',
158
- ],
159
- },
160
- });
161
-
162
- export default defineConfig(({ mode }) => {
163
- const isDev = mode === 'development';
164
- const baseConfig = forlogicConfig(isDev);
165
-
166
- return {
167
- ...baseConfig,
168
- plugins: [react(), ...baseConfig.plugins],
169
- resolve: {
170
- alias: {
171
- // ⚠️ IMPORTANTE: Usar path.resolve() para caminhos absolutos
172
- '@': path.resolve(__dirname, './src'),
173
- },
174
- },
175
- // Sobrescrever configurações se necessário
176
- server: {
177
- ...baseConfig.server,
178
- port: 3000, // Porta customizada
179
- },
180
- // Forçar re-bundle de dependências
181
- optimizeDeps: {
182
- force: true,
183
- },
184
- };
185
- });`},{title:"Apenas Plugin de Segurança",description:"Usar somente o plugin de headers sem a configuração completa",preview:e.jsxs(s,{className:"p-4 space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(o,{className:"h-5 w-5 text-green-500"}),e.jsx("span",{className:"font-medium",children:"createSecurityHeadersPlugin"})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Use quando você já tem uma configuração Vite e quer adicionar apenas os headers de segurança."})]}),code:`// vite.config.ts existente
186
- import { defineConfig } from 'vite';
187
- import react from '@vitejs/plugin-react-swc';
188
- import { createSecurityHeadersPlugin } from 'forlogic-core/vite';
189
-
190
- export default defineConfig(({ mode }) => {
191
- const isDev = mode === 'development';
192
-
193
- return {
194
- plugins: [
195
- react(),
196
- // Adicionar apenas o plugin de segurança
197
- createSecurityHeadersPlugin(isDev, {
198
- supabaseUrls: ['https://xyz.supabase.co'],
199
- trustedOrigins: ['https://meu-app.com'],
200
- }),
201
- ],
202
- // ... resto da sua configuração
203
- };
204
- });`}],props:[{name:"supabaseUrls",type:"string[]",default:"[]",description:"URLs do Supabase para permitir em connect-src."},{name:"trustedOrigins",type:"string[]",default:"[]",description:"Origens confiáveis para CORS (suporta wildcards *.dominio.com)."},{name:"additionalScriptSrc",type:"string[]",default:"[]",description:"CDNs e fontes de script adicionais para CSP."},{name:"additionalStyleSrc",type:"string[]",default:"[]",description:"Fontes de estilo adicionais (fontes, CSS CDNs)."},{name:"additionalConnectSrc",type:"string[]",default:"[]",description:"APIs e WebSockets adicionais para CSP."},{name:"cspReportUri",type:"string",default:"-",description:"URI para receber relatórios de violações CSP."},{name:"enableTrustedTypes",type:"boolean",default:"true",description:"Habilitar Trusted Types em produção (proteção XSS)."},{name:"upgradeInsecureRequests",type:"boolean",default:"true",description:"Atualizar automaticamente HTTP para HTTPS em produção."},{name:"server.host",type:"string",default:'"::"',description:"Host do servidor de desenvolvimento."},{name:"server.port",type:"number",default:"8080",description:"Porta do servidor de desenvolvimento."},{name:"build.sourcemap",type:"boolean",default:"true",description:"Gerar sourcemaps para debug."},{name:"build.chunkSizeWarningLimit",type:"number",default:"4000",description:"Limite de tamanho de chunk (KB) para avisos."},{name:"disableSecurity",type:"boolean",default:"false",description:"Desabilitar plugin de segurança (NÃO recomendado)."}],accessibility:["Os headers de segurança protegem usuários de ataques como XSS, clickjacking e MIME sniffing.","CSP estrito em produção previne execução de scripts maliciosos.","CORS seguro impede vazamento de dados para origens não autorizadas.","Trusted Types fornece proteção adicional contra injeção de DOM."],notes:['**IMPORTANTE**: O alias `@` deve ser configurado com `path.resolve(__dirname, "./src")` - caminhos relativos falham no build.',"Em **desenvolvimento**, CSP permite unsafe-inline e unsafe-eval para suportar HMR do Vite.","Em **produção**, CSP é estrito e inclui Trusted Types e upgrade-insecure-requests.","Origens não confiáveis são **logadas** no console para auditoria de segurança.","Use `cspReportUri` para receber relatórios de violações e monitorar ataques.","O plugin é aplicado apenas ao **servidor de desenvolvimento** - em produção, configure headers no seu servidor/CDN."]})}export{O as SecurityDoc};
@@ -1,80 +0,0 @@
1
- import{j as e,cX as t,cY as a,cZ as c,c_ as r,c$ as l,d0 as n,d1 as i,L as s}from"./index-BtX5DZqb.js";import{C as o}from"./ComponentDocTemplate-BtOCnlM2.js";import"./ExampleCard-DfuMYM6E.js";import"./TableOfContents-DBMJMbI4.js";function m(){return e.jsx(o,{title:"Select",description:"Exibe uma lista de opções para o usuário escolher—acionada por um botão.",component:e.jsxs(t,{children:[e.jsx(a,{className:"w-[180px]",children:e.jsx(c,{placeholder:"Select a fruit"})}),e.jsxs(r,{children:[e.jsx(l,{value:"apple",children:"Apple"}),e.jsx(l,{value:"banana",children:"Banana"}),e.jsx(l,{value:"orange",children:"Orange"})]})]}),usage:`import {
2
- Select,
3
- SelectContent,
4
- SelectItem,
5
- SelectTrigger,
6
- SelectValue,
7
- } from "forlogic-core"
8
-
9
- <Select>
10
- <SelectTrigger className="w-[180px]">
11
- <SelectValue placeholder="Theme" />
12
- </SelectTrigger>
13
- <SelectContent>
14
- <SelectItem value="light">Light</SelectItem>
15
- <SelectItem value="dark">Dark</SelectItem>
16
- </SelectContent>
17
- </Select>`,examples:[{title:"Select Básico",preview:e.jsxs(t,{children:[e.jsx(a,{className:"w-[280px]",children:e.jsx(c,{placeholder:"Select a fruit"})}),e.jsxs(r,{children:[e.jsx(l,{value:"apple",children:"Apple"}),e.jsx(l,{value:"banana",children:"Banana"}),e.jsx(l,{value:"orange",children:"Orange"}),e.jsx(l,{value:"grape",children:"Grape"})]})]}),code:`<Select>
18
- <SelectTrigger className="w-[280px]">
19
- <SelectValue placeholder="Select a fruit" />
20
- </SelectTrigger>
21
- <SelectContent>
22
- <SelectItem value="apple">Apple</SelectItem>
23
- <SelectItem value="banana">Banana</SelectItem>
24
- <SelectItem value="orange">Orange</SelectItem>
25
- </SelectContent>
26
- </Select>`},{title:"Com Grupos",preview:e.jsxs(t,{children:[e.jsx(a,{className:"w-[280px]",children:e.jsx(c,{placeholder:"Select a timezone"})}),e.jsxs(r,{children:[e.jsxs(n,{children:[e.jsx(i,{children:"North America"}),e.jsx(l,{value:"est",children:"Eastern Standard Time (EST)"}),e.jsx(l,{value:"cst",children:"Central Standard Time (CST)"}),e.jsx(l,{value:"pst",children:"Pacific Standard Time (PST)"})]}),e.jsxs(n,{children:[e.jsx(i,{children:"Europe"}),e.jsx(l,{value:"gmt",children:"Greenwich Mean Time (GMT)"}),e.jsx(l,{value:"cet",children:"Central European Time (CET)"})]})]})]}),code:`<Select>
27
- <SelectTrigger>
28
- <SelectValue placeholder="Select a timezone" />
29
- </SelectTrigger>
30
- <SelectContent>
31
- <SelectGroup>
32
- <SelectLabel>North America</SelectLabel>
33
- <SelectItem value="est">Eastern Standard Time (EST)</SelectItem>
34
- <SelectItem value="cst">Central Standard Time (CST)</SelectItem>
35
- </SelectGroup>
36
- <SelectGroup>
37
- <SelectLabel>Europe</SelectLabel>
38
- <SelectItem value="gmt">Greenwich Mean Time (GMT)</SelectItem>
39
- </SelectGroup>
40
- </SelectContent>
41
- </Select>`},{title:"Estados",preview:e.jsxs("div",{className:"space-y-4",children:[e.jsxs(t,{children:[e.jsx(a,{className:"w-[280px]",children:e.jsx(c,{placeholder:"Normal state"})}),e.jsxs(r,{children:[e.jsx(l,{value:"1",children:"Option 1"}),e.jsx(l,{value:"2",children:"Option 2"})]})]}),e.jsxs(t,{disabled:!0,children:[e.jsx(a,{className:"w-[280px]",children:e.jsx(c,{placeholder:"Disabled state"})}),e.jsx(r,{children:e.jsx(l,{value:"1",children:"Option 1"})})]})]}),code:`<Select>
42
- <SelectTrigger>
43
- <SelectValue placeholder="Normal state" />
44
- </SelectTrigger>
45
- <SelectContent>
46
- <SelectItem value="1">Option 1</SelectItem>
47
- </SelectContent>
48
- </Select>
49
-
50
- <Select disabled>
51
- <SelectTrigger>
52
- <SelectValue placeholder="Disabled state" />
53
- </SelectTrigger>
54
- <SelectContent>
55
- <SelectItem value="1">Option 1</SelectItem>
56
- </SelectContent>
57
- </Select>`},{title:"Com Label",preview:e.jsxs("div",{className:"space-y-2 w-[280px]",children:[e.jsx(s,{htmlFor:"country",children:"Country"}),e.jsxs(t,{children:[e.jsx(a,{id:"country",children:e.jsx(c,{placeholder:"Select your country"})}),e.jsxs(r,{children:[e.jsx(l,{value:"br",children:"Brazil"}),e.jsx(l,{value:"us",children:"United States"}),e.jsx(l,{value:"uk",children:"United Kingdom"}),e.jsx(l,{value:"ca",children:"Canada"})]})]})]}),code:`<div className="space-y-2">
58
- <Label htmlFor="country">Country</Label>
59
- <Select>
60
- <SelectTrigger id="country">
61
- <SelectValue placeholder="Select your country" />
62
- </SelectTrigger>
63
- <SelectContent>
64
- <SelectItem value="br">Brazil</SelectItem>
65
- <SelectItem value="us">United States</SelectItem>
66
- </SelectContent>
67
- </Select>
68
- </div>`},{title:"Casos de Uso - Form",preview:e.jsxs("div",{className:"space-y-4 w-[280px]",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(s,{htmlFor:"role",children:"User Role"}),e.jsxs(t,{children:[e.jsx(a,{id:"role",children:e.jsx(c,{placeholder:"Select a role"})}),e.jsxs(r,{children:[e.jsx(l,{value:"admin",children:"Administrator"}),e.jsx(l,{value:"user",children:"User"}),e.jsx(l,{value:"guest",children:"Guest"})]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(s,{htmlFor:"status",children:"Status"}),e.jsxs(t,{children:[e.jsx(a,{id:"status",children:e.jsx(c,{placeholder:"Select status"})}),e.jsxs(r,{children:[e.jsx(l,{value:"active",children:"Active"}),e.jsx(l,{value:"inactive",children:"Inactive"}),e.jsx(l,{value:"pending",children:"Pending"})]})]})]})]}),code:`<div className="space-y-2">
69
- <Label htmlFor="role">User Role</Label>
70
- <Select>
71
- <SelectTrigger id="role">
72
- <SelectValue placeholder="Select a role" />
73
- </SelectTrigger>
74
- <SelectContent>
75
- <SelectItem value="admin">Administrator</SelectItem>
76
- <SelectItem value="user">User</SelectItem>
77
- <SelectItem value="guest">Guest</SelectItem>
78
- </SelectContent>
79
- </Select>
80
- </div>`}],props:[{name:"defaultValue",type:"string",default:"-",description:"O valor selecionado padrão."},{name:"value",type:"string",default:"-",description:"O valor selecionado controlado."},{name:"onValueChange",type:"(value: string) => void",default:"-",description:"Manipulador de evento quando o valor muda."},{name:"disabled",type:"boolean",default:"false",description:"Se o select está desabilitado."},{name:"container (SelectContent)",type:"HTMLElement",default:"-",description:"Container HTML para portal (útil dentro de Dialog)."},{name:"collisionBoundary (SelectContent)",type:"HTMLElement",default:"-",description:"Elemento para detecção de colisão de posicionamento."}],accessibility:["Navegação completa por teclado","Busca por digitação antecipada","Segue o padrão de listbox WAI-ARIA","Anúncios para leitores de tela"],notes:["💡 Use `container` e `collisionBoundary` quando o Select estiver dentro de um Dialog para evitar problemas de scroll","💡 Para seleção com busca, considere usar `Combobox` ao invés de `Select`"]})}export{m as SelectDoc};
@@ -1,4 +0,0 @@
1
- import{j as e,aq as t}from"./index-BtX5DZqb.js";import{C as a}from"./ComponentDocTemplate-BtOCnlM2.js";import"./ExampleCard-DfuMYM6E.js";import"./TableOfContents-DBMJMbI4.js";function c(){return e.jsx(a,{title:"Separator",description:"Separa visual ou semanticamente o conteúdo.",component:e.jsxs("div",{className:"space-y-4 w-full max-w-md",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-medium",children:"Primitivos Radix"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Uma biblioteca de componentes UI de código aberto."})]}),e.jsx(t,{}),e.jsxs("div",{children:[e.jsx("h4",{className:"text-sm font-medium",children:"Recursos"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Acessível, customizável, código aberto."})]})]}),usage:`import { Separator } from "forlogic-core"
2
-
3
- <Separator />
4
- <Separator orientation="vertical" />`,examples:[{title:"Horizontal",preview:e.jsxs("div",{className:"w-full max-w-md space-y-2",children:[e.jsx("p",{className:"text-sm",children:"Conteúdo acima"}),e.jsx(t,{}),e.jsx("p",{className:"text-sm",children:"Conteúdo abaixo"})]}),code:"<Separator />"},{title:"Vertical",preview:e.jsxs("div",{className:"flex h-20 items-center gap-4",children:[e.jsx("p",{className:"text-sm",children:"Esquerda"}),e.jsx(t,{orientation:"vertical"}),e.jsx("p",{className:"text-sm",children:"Direita"})]}),code:'<Separator orientation="vertical" />'}],props:[{name:"orientation",type:'"horizontal" | "vertical"',default:'"horizontal"',description:"A orientação do separador."},{name:"decorative",type:"boolean",default:"true",description:"Se o separador é decorativo ou semântico."}],accessibility:["HTML semântico com role adequado","Pode ser decorativo ou estrutural","Atributos ARIA adequados"]})}export{c as SeparatorDoc};
@@ -1,308 +0,0 @@
1
- import{j as e}from"./index-BtX5DZqb.js";import{C as o}from"./ComponentDocTemplate-BtOCnlM2.js";import"./ExampleCard-DfuMYM6E.js";import"./TableOfContents-DBMJMbI4.js";const t=`import {
2
- // Services
3
- createService,
4
- emailService,
5
- errorService,
6
- // Qualiex Enrichment
7
- QualiexEnrichmentService,
8
- resolveFieldMappings,
9
- deriveNameField,
10
- deriveEmailField,
11
- deriveUsernameField,
12
- } from 'forlogic-core';`,d=`import { createService } from 'forlogic-core';
13
-
14
- // Definir tipos
15
- interface Employee {
16
- id: string;
17
- name: string;
18
- email: string;
19
- department_id: string;
20
- is_removed: boolean;
21
- created_at: string;
22
- updated_at: string;
23
- }
24
-
25
- interface EmployeeInsert {
26
- name: string;
27
- email: string;
28
- department_id: string;
29
- }
30
-
31
- interface EmployeeUpdate {
32
- name?: string;
33
- email?: string;
34
- department_id?: string;
35
- }
36
-
37
- // Criar serviço CRUD
38
- const employeeService = createService<Employee, EmployeeInsert, EmployeeUpdate>({
39
- tableName: 'employees',
40
- schemaName: 'common',
41
- searchFields: ['name', 'email'],
42
- selectFields: '*, departments(name)', // Joins automáticos
43
- enableQualiexEnrichment: true, // Enriquecer com dados do Qualiex
44
- userIdFields: ['id_user'], // Campos de usuário para enriquecimento
45
- });
46
-
47
- // Uso do serviço
48
- async function loadEmployees() {
49
- // Buscar com paginação e filtros
50
- const result = await employeeService.getAll({
51
- search: 'João',
52
- sortField: 'name',
53
- sortDirection: 'asc',
54
- page: 1,
55
- limit: 25,
56
- department_id: 'dept-123', // Filtro adicional
57
- });
58
-
59
- console.log(result.data); // Array de funcionários
60
- console.log(result.totalItems); // Total de registros
61
- console.log(result.hasNextPage); // Se há próxima página
62
- }
63
-
64
- // CRUD completo
65
- const employee = await employeeService.create({
66
- name: 'Maria Silva',
67
- email: 'maria@empresa.com',
68
- department_id: 'dept-123'
69
- });
70
-
71
- const updated = await employeeService.update(employee.id, {
72
- name: 'Maria Santos'
73
- });
74
-
75
- await employeeService.delete(employee.id); // Soft delete (is_removed = true)`,n=`import { emailService } from 'forlogic-core';
76
-
77
- // Enviar email de boas-vindas
78
- await emailService.sendEmail({
79
- templateCode: 'WELCOME',
80
- to: 'usuario@exemplo.com',
81
- variables: {
82
- userName: 'João Silva',
83
- activationLink: 'https://app.com/activate',
84
- companyName: 'Minha Empresa'
85
- }
86
- });
87
-
88
- // Enviar para múltiplos destinatários com cópia
89
- await emailService.sendEmail({
90
- templateCode: 'NOTIFICATION',
91
- to: ['usuario1@exemplo.com', 'usuario2@exemplo.com'],
92
- variables: {
93
- title: 'Novo documento disponível',
94
- message: 'Um novo documento foi compartilhado com você',
95
- actionUrl: 'https://app.com/documents/123',
96
- actionLabel: 'Ver Documento'
97
- },
98
- cc: ['gestor@exemplo.com'],
99
- bcc: ['admin@exemplo.com'],
100
- replyTo: 'suporte@empresa.com'
101
- });
102
-
103
- // Templates são cadastrados na tabela common.email_templates
104
- // Variáveis são substituídas automaticamente: {{userName}} -> João Silva`,l=`import { errorService } from 'forlogic-core';
105
-
106
- // Tratamento de erros com toast automático
107
- try {
108
- await fetchData();
109
- } catch (error) {
110
- errorService.handleError(error);
111
- // Exibe toast com título apropriado baseado no erro
112
- // Ex: "Sessão Expirada", "Erro de Conexão", "Erro de Autenticação"
113
- }
114
-
115
- // Tratamento silencioso (sem toast)
116
- try {
117
- await fetchData();
118
- } catch (error) {
119
- errorService.handleError(error, false); // showToast = false
120
- }
121
-
122
- // Notificação de sucesso
123
- errorService.success('Sucesso!', 'Dados salvos com sucesso');
124
-
125
- // Acessar histórico de erros
126
- const recentErrors = errorService.getErrors(); // Últimos 50 erros
127
- console.log(recentErrors);
128
-
129
- // Limpar histórico
130
- errorService.clearErrors();
131
-
132
- // Rate limiting automático: máximo 3 toasts por minuto`,m=`import { QualiexEnrichmentService } from 'forlogic-core';
133
-
134
- // Enriquecer entidades com dados de usuário do Qualiex
135
- // Adiciona automaticamente: nome, email, username dos usuários
136
-
137
- // Uso simples: lista de campos de ID
138
- const enrichedItems = await QualiexEnrichmentService.enrichWithUserData(items, {
139
- entityName: 'Avaliações',
140
- userIdFields: ['target_user_id', 'evaluator_user_id']
141
- });
142
- // Resultado: target_user_name, evaluator_user_name preenchidos automaticamente
143
-
144
- // Uso avançado: mapeamento customizado de campos
145
- const enrichedItems = await QualiexEnrichmentService.enrichWithUserData(items, {
146
- entityName: 'Avaliações',
147
- userFieldsMapping: [
148
- {
149
- idField: 'target_user_id',
150
- nameField: 'avaliado_nome',
151
- emailField: 'avaliado_email'
152
- },
153
- {
154
- idField: 'evaluator_user_id',
155
- nameField: 'avaliador_nome'
156
- }
157
- ]
158
- });
159
-
160
- // Características:
161
- // - Cache inteligente de 5 minutos por companyId
162
- // - Validação automática de tokens
163
- // - Resiliência: retorna entidades originais em caso de erro
164
- // - Suporta múltiplos campos de usuário por entidade`,c=`import {
165
- resolveFieldMappings,
166
- deriveNameField,
167
- deriveEmailField,
168
- deriveUsernameField
169
- } from 'forlogic-core';
170
-
171
- // Derivar nome do campo de saída baseado no campo de ID
172
- deriveNameField('target_user_id'); // → 'target_user_name'
173
- deriveNameField('id_user'); // → 'id_user_name'
174
- deriveNameField('id_user', '_nome'); // → 'id_user_nome' (sufixo customizado)
175
-
176
- deriveEmailField('target_user_id'); // → 'target_user_email'
177
- deriveUsernameField('target_user_id'); // → 'target_user_username'
178
-
179
- // Resolver mapeamentos automaticamente
180
- // Prioridade: userFieldsMapping > userIdFields > default
181
-
182
- // Uso com lista simples de campos
183
- const mappings = resolveFieldMappings(['target_user_id', 'evaluator_user_id']);
184
- // Resultado:
185
- // [
186
- // { idField: 'target_user_id', nameField: 'target_user_name', ... },
187
- // { idField: 'evaluator_user_id', nameField: 'evaluator_user_name', ... }
188
- // ]
189
-
190
- // Uso com mapeamento explícito
191
- const mappings = resolveFieldMappings(undefined, [
192
- { idField: 'id_user', nameField: 'responsible_name' }
193
- ]);
194
-
195
- // Default (sem parâmetros): id_user → responsible_name
196
- const mappings = resolveFieldMappings();
197
- // [{ idField: 'id_user', nameField: 'responsible_name' }]`,u=[{name:"createService<T, TInsert, TUpdate>(options)",type:"CrudService<T>",default:"-",description:"Factory para criar serviço CRUD completo com Supabase. Implementa soft delete e RLS."},{name:"options.tableName",type:"string",default:"-",description:"Nome da tabela no Supabase."},{name:"options.schemaName",type:"string",default:"'common'",description:"Schema do banco de dados."},{name:"options.searchFields",type:"string[]",default:"[]",description:"Campos para busca textual (ilike)."},{name:"options.selectFields",type:"string",default:"'*'",description:'Campos para select, suporta joins (ex: "*, categories(name)").'},{name:"options.enableQualiexEnrichment",type:"boolean",default:"false",description:"Se deve enriquecer dados com informações do Qualiex."},{name:"emailService.sendEmail(params)",type:"Promise<any>",default:"-",description:"Envia email usando template do banco de dados via edge function."},{name:"params.templateCode",type:"string",default:"-",description:"Código do template em common.email_templates."},{name:"params.to",type:"string | string[]",default:"-",description:"Destinatário(s) do email."},{name:"params.variables",type:"Record<string, any>",default:"-",description:"Variáveis para substituição no template ({{variableName}})."},{name:"errorService.handleError(error, showToast?)",type:"void",default:"showToast: true",description:"Trata erro e exibe toast com título apropriado. Rate limiting: máx 3/min."},{name:"errorService.success(title, description?)",type:"void",default:"-",description:"Exibe toast de sucesso."},{name:"errorService.getErrors()",type:"ErrorEntry[]",default:"-",description:"Retorna os últimos 50 erros registrados."},{name:"QualiexEnrichmentService.enrichWithUserData(entities, options)",type:"Promise<T[]>",default:"-",description:"Enriquece entidades com dados de usuários do Qualiex (nome, email, username). Cache de 5 min."},{name:"options.entityName",type:"string",default:"-",description:"Nome da entidade para logs de debug."},{name:"options.userIdFields",type:"string[]",default:"-",description:"Lista de campos de ID de usuário para enriquecer."},{name:"options.userFieldsMapping",type:"QualiexUserFieldMapping[]",default:"-",description:"Mapeamento customizado de campos (prioridade sobre userIdFields)."},{name:"deriveNameField(idField, suffix?)",type:"string",default:"suffix: '_name'",description:"Deriva campo de nome a partir do ID (ex: target_user_id → target_user_name)."},{name:"deriveEmailField(idField, suffix?)",type:"string",default:"suffix: '_email'",description:"Deriva campo de email a partir do ID (ex: target_user_id → target_user_email)."},{name:"deriveUsernameField(idField, suffix?)",type:"string",default:"suffix: '_username'",description:"Deriva campo de username a partir do ID."},{name:"resolveFieldMappings(userIdFields?, userFieldsMapping?)",type:"QualiexUserFieldMapping[]",default:"-",description:"Resolve mapeamentos com prioridade: userFieldsMapping > userIdFields > default."}];function a({title:i,description:r,code:s}){return e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-lg font-semibold",children:i}),e.jsx("p",{className:"text-sm text-muted-foreground",children:r})]}),e.jsx("pre",{className:"rounded-lg border bg-muted/50 p-4 overflow-x-auto",children:e.jsx("code",{className:"text-sm font-mono",children:s})})]})}function f(){const i=[{id:"exemplos",label:"Exemplos"},{id:"baseservice-createservice",label:"BaseService (createService)"},{id:"emailservice",label:"EmailService"},{id:"errorservice",label:"ErrorService"},{id:"qualiexenrichmentservice",label:"QualiexEnrichmentService"},{id:"qualiexenrichmentservice",label:"QualiexEnrichmentService"},{id:"qualiexfieldhelpers",label:"QualiexFieldHelpers"},{id:"tipos",label:"Tipos"}];return e.jsx(o,{title:"Services",description:"Serviços utilitários da biblioteca forlogic-core para operações CRUD, envio de emails, tratamento de erros e gerenciamento de traduções. Todos os serviços são singletons prontos para uso.",usage:t,props:u,tocItems:i,notes:["createService implementa soft delete automaticamente (is_removed = true).","createService valida token de autenticação antes de cada operação.","EmailService usa templates cadastrados em common.email_templates via edge function send-email.","ErrorService possui rate limiting: máximo 3 toasts por minuto para evitar spam.","createService suporta joins automáticos via selectFields.","QualiexEnrichmentService usa cache de 5 minutos por companyId para evitar chamadas desnecessárias.","QualiexEnrichmentService é resiliente: retorna entidades originais em caso de erro.",'QualiexFieldHelpers remove sufixo "_id" automaticamente antes de adicionar o novo sufixo.'],children:e.jsxs("div",{id:"exemplos",className:"space-y-8 scroll-mt-4",children:[e.jsx("h2",{className:"text-2xl font-semibold tracking-tight border-b pb-2",children:"Exemplos"}),e.jsx("div",{id:"baseservice-createservice",className:"scroll-mt-4",children:e.jsx(a,{title:"BaseService (createService)",description:"Factory para criar serviços CRUD completos com Supabase. Suporta paginação, busca, ordenação, filtros, joins e soft delete.",code:d})}),e.jsx("div",{id:"emailservice",className:"scroll-mt-4",children:e.jsx(a,{title:"EmailService",description:"Envia emails usando templates cadastrados no banco de dados. Suporta variáveis de substituição e múltiplos destinatários.",code:n})}),e.jsx("div",{id:"errorservice",className:"scroll-mt-4",children:e.jsx(a,{title:"ErrorService",description:"Tratamento centralizado de erros com toasts inteligentes e rate limiting. Mantém histórico dos últimos 50 erros.",code:l})}),e.jsx("div",{id:"qualiexenrichmentservice",className:"scroll-mt-4",children:e.jsx(a,{title:"QualiexEnrichmentService",description:"Enriquece entidades com dados de usuários do Qualiex (nome, email, username). Usa cache inteligente de 5 minutos por companyId.",code:m})}),e.jsx("div",{id:"qualiexfieldhelpers",className:"scroll-mt-4",children:e.jsx(a,{title:"QualiexFieldHelpers",description:"Utilitários para derivar automaticamente nomes de campos de saída baseado nos campos de ID de usuário.",code:c})}),e.jsx("div",{id:"tipos",className:"scroll-mt-4",children:e.jsx("h2",{className:"text-2xl font-semibold tracking-tight border-b pb-2",children:"Tipos"})}),e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"space-y-3",children:[e.jsx("h3",{className:"text-lg font-semibold",children:"QualiexUserFieldMapping"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Define o mapeamento entre um campo de ID de usuário e seus campos de saída correspondentes (nome, email, username)."}),e.jsx("pre",{className:"rounded-lg border bg-muted/50 p-4 overflow-x-auto",children:e.jsx("code",{className:"text-sm font-mono",children:`interface QualiexUserFieldMapping {
198
- /** Nome do campo de ID de usuário na entidade (ex: "target_user_id") */
199
- idField: string;
200
-
201
- /** Nome do campo de saída para o nome (ex: "target_user_name")
202
- * Default: idField + "_name" (remove "_id" se presente) */
203
- nameField?: string;
204
-
205
- /** Nome do campo de saída para o email (ex: "target_user_email")
206
- * Default: idField + "_email" (remove "_id" se presente) */
207
- emailField?: string;
208
-
209
- /** Nome do campo de saída para o username (ex: "target_user_username")
210
- * Default: idField + "_username" (remove "_id" se presente) */
211
- usernameField?: string;
212
- }
213
-
214
- // Exemplos de uso:
215
- const mappings: QualiexUserFieldMapping[] = [
216
- // Mapeamento simples (só nome)
217
- { idField: 'id_user', nameField: 'responsible_name' },
218
-
219
- // Mapeamento completo
220
- {
221
- idField: 'target_user_id',
222
- nameField: 'target_name',
223
- emailField: 'target_email',
224
- usernameField: 'target_username'
225
- },
226
-
227
- // Mapeamento parcial (nome e email)
228
- {
229
- idField: 'evaluator_user_id',
230
- nameField: 'evaluator_name',
231
- emailField: 'evaluator_email'
232
- }
233
- ];`})})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsx("h3",{className:"text-lg font-semibold",children:"QualiexEnrichmentConfig"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Configuração global de sufixos padrão para derivação automática de campos. Usado internamente pelo QualiexFieldHelpers."}),e.jsx("pre",{className:"rounded-lg border bg-muted/50 p-4 overflow-x-auto",children:e.jsx("code",{className:"text-sm font-mono",children:`interface QualiexEnrichmentConfig {
234
- /** Sufixo padrão para campos de nome (default: "_name") */
235
- userNameFieldSuffix?: string;
236
-
237
- /** Sufixo padrão para campos de email (default: "_email") */
238
- userEmailFieldSuffix?: string;
239
-
240
- /** Sufixo padrão para campos de username (default: "_username") */
241
- userUsernameFieldSuffix?: string;
242
- }
243
-
244
- // Exemplo de configuração customizada:
245
- const config: QualiexEnrichmentConfig = {
246
- userNameFieldSuffix: '_nome', // target_user_id → target_user_nome
247
- userEmailFieldSuffix: '_email', // target_user_id → target_user_email
248
- userUsernameFieldSuffix: '_login' // target_user_id → target_user_login
249
- };
250
-
251
- // Valores padrão:
252
- // - userNameFieldSuffix: '_name'
253
- // - userEmailFieldSuffix: '_email'
254
- // - userUsernameFieldSuffix: '_username'`})})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsx("h3",{className:"text-lg font-semibold",children:"QualiexUser"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Representa um usuário do sistema Qualiex. Retornado pelo hook useQualiexUsers e usado internamente pelo QualiexEnrichmentService."}),e.jsx("pre",{className:"rounded-lg border bg-muted/50 p-4 overflow-x-auto",children:e.jsx("code",{className:"text-sm font-mono",children:`interface QualiexUser {
255
- /** ID único do usuário (formato UUID) */
256
- id?: string;
257
-
258
- /** ID alternativo do usuário (alguns endpoints retornam neste campo) */
259
- userId?: string;
260
-
261
- /** Nome de usuário (login) */
262
- userName?: string;
263
-
264
- /** Email do usuário */
265
- userEmail?: string;
266
-
267
- /** Nome de exibição (nome completo) */
268
- displayName?: string;
269
-
270
- /** ID do local/unidade do usuário */
271
- placeId?: string | null;
272
-
273
- /** Nome do local/unidade do usuário */
274
- placeName?: string | null;
275
-
276
- /** ID do cargo/função do usuário */
277
- roleId?: string;
278
-
279
- /** Nome do cargo/função do usuário */
280
- roleName?: string;
281
-
282
- /** ID da empresa do usuário */
283
- companyId?: string;
284
-
285
- /** Nome da empresa do usuário */
286
- companyName?: string;
287
- }
288
-
289
- // Exemplo de uso com useQualiexUsers:
290
- import { useQualiexUsers } from 'forlogic-core';
291
-
292
- function UserSelector() {
293
- const { data: users, isLoading } = useQualiexUsers({ enabled: true });
294
-
295
- // users é QualiexUser[]
296
- return (
297
- <select>
298
- {users?.map(user => (
299
- <option key={user.id || user.userId} value={user.id || user.userId}>
300
- {user.displayName || user.userName} ({user.userEmail})
301
- </option>
302
- ))}
303
- </select>
304
- );
305
- }
306
-
307
- // Nota: A API retorna apenas usuários ativos (filterStatus='active').
308
- // O campo isActive foi removido pois a API não o fornece.`})})]})]})]})})}export{f as ServicesDoc};