forlogic-core 1.12.1 → 1.12.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.
@@ -0,0 +1,238 @@
1
+ #!/usr/bin/env node
2
+ #!/usr/bin/env node
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+
6
+ const LIB_UI_COMPONENTS = [
7
+ // Layout components
8
+ "accordion",
9
+ "alert",
10
+ "alert-dialog",
11
+ "avatar",
12
+ "breadcrumb",
13
+ "button",
14
+ "button-group",
15
+ "badge",
16
+ "calendar",
17
+ "card",
18
+ "checkbox",
19
+ "collapsible",
20
+ "color-picker",
21
+ "command",
22
+ "context-menu",
23
+ "combobox",
24
+ "data-list",
25
+ "date-picker",
26
+ "dialog",
27
+ "drawer",
28
+ "dropdown-menu",
29
+ "empty-state",
30
+ "form",
31
+ "grid",
32
+ "hover-card",
33
+ "icon-picker",
34
+ "input",
35
+ "input-group",
36
+ "label",
37
+ "loading-state",
38
+ "menubar",
39
+ "navigation-menu",
40
+ "page-breadcrumb",
41
+ "pagination",
42
+ "popover",
43
+ "progress",
44
+ "radio-group",
45
+ "resizable",
46
+ "rich-text-editor",
47
+ "scroll-area",
48
+ "select",
49
+ "separator",
50
+ "sheet",
51
+ "sidebar",
52
+ "skeleton",
53
+ "skeleton-variants",
54
+ "slider",
55
+ "sonner",
56
+ "spinner",
57
+ "split-button",
58
+ "stack",
59
+ "switch",
60
+ "tab-page-layout",
61
+ "table",
62
+ "table-resize-handle",
63
+ "tabs",
64
+ "textarea",
65
+ "toggle",
66
+ "toggle-group",
67
+ "tooltip",
68
+ "truncated-cell",
69
+ "typography",
70
+ "action-button",
71
+ "chart"
72
+ ];
73
+ const LIB_HOOKS = [
74
+ "useDebounce",
75
+ "useActiveModules",
76
+ "usePageTitle",
77
+ "usePermissionQuery",
78
+ "useSidebarResize",
79
+ "useColumnResize",
80
+ "useRowResize",
81
+ "useI18nFormatters"
82
+ ];
83
+ const LIB_SERVICES = [
84
+ "BaseService",
85
+ "ErrorService",
86
+ "EmailService",
87
+ "QualiexEnrichmentService",
88
+ "TranslationService"
89
+ ];
90
+ const DIRECTORIES_TO_CHECK = [
91
+ "src/components/ui",
92
+ "src/lib",
93
+ "src/utils",
94
+ "src/hooks",
95
+ "src/services",
96
+ "components/ui",
97
+ "lib"
98
+ ];
99
+ function kebabToPascal(str) {
100
+ return str.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
101
+ }
102
+ function normalizeFileName(fileName) {
103
+ return fileName.replace(/\.(tsx?|jsx?)$/, "").toLowerCase().replace(/[-_]/g, "-");
104
+ }
105
+ function findDuplicateComponents(projectRoot) {
106
+ const results = [];
107
+ for (const dir of DIRECTORIES_TO_CHECK) {
108
+ const fullPath = path.join(projectRoot, dir);
109
+ if (!fs.existsSync(fullPath)) {
110
+ continue;
111
+ }
112
+ const files = fs.readdirSync(fullPath);
113
+ for (const file of files) {
114
+ const filePath = path.join(fullPath, file);
115
+ const stat = fs.statSync(filePath);
116
+ if (stat.isDirectory()) {
117
+ continue;
118
+ }
119
+ const normalizedName = normalizeFileName(file);
120
+ if (dir.includes("components/ui") || dir.includes("components\\ui")) {
121
+ const match = LIB_UI_COMPONENTS.find(
122
+ (comp) => normalizedName === comp || normalizedName === comp.replace(/-/g, "") || normalizedName.includes(comp)
123
+ );
124
+ if (match) {
125
+ results.push({
126
+ type: "error",
127
+ file: path.relative(projectRoot, filePath),
128
+ message: `Componente "${kebabToPascal(match)}" j\xE1 existe na forlogic-core`,
129
+ suggestion: `import { ${kebabToPascal(match)} } from 'forlogic-core';`
130
+ });
131
+ }
132
+ }
133
+ if (normalizedName === "utils" || normalizedName === "cn") {
134
+ results.push({
135
+ type: "error",
136
+ file: path.relative(projectRoot, filePath),
137
+ message: "Utilit\xE1rios (cn, etc.) j\xE1 existem na forlogic-core",
138
+ suggestion: `import { cn } from 'forlogic-core';`
139
+ });
140
+ }
141
+ for (const hook of LIB_HOOKS) {
142
+ if (normalizedName.toLowerCase() === hook.toLowerCase().replace("use", "use-")) {
143
+ results.push({
144
+ type: "error",
145
+ file: path.relative(projectRoot, filePath),
146
+ message: `Hook "${hook}" j\xE1 existe na forlogic-core`,
147
+ suggestion: `import { ${hook} } from 'forlogic-core';`
148
+ });
149
+ }
150
+ }
151
+ for (const service of LIB_SERVICES) {
152
+ if (normalizedName.toLowerCase().includes(service.toLowerCase().replace("service", ""))) {
153
+ results.push({
154
+ type: "warning",
155
+ file: path.relative(projectRoot, filePath),
156
+ message: `Service similar a "${service}" pode existir na forlogic-core`,
157
+ suggestion: `Verifique se pode usar: import { ${service} } from 'forlogic-core';`
158
+ });
159
+ }
160
+ }
161
+ }
162
+ }
163
+ return results;
164
+ }
165
+ function checkForShadcnConfig(projectRoot) {
166
+ const results = [];
167
+ const componentsJsonPath = path.join(projectRoot, "components.json");
168
+ if (fs.existsSync(componentsJsonPath)) {
169
+ const content = fs.readFileSync(componentsJsonPath, "utf-8");
170
+ const config = JSON.parse(content);
171
+ if (config.aliases?.components?.includes("src/components")) {
172
+ results.push({
173
+ type: "warning",
174
+ file: "components.json",
175
+ message: "shadcn/ui configurado para criar componentes em src/components/ui",
176
+ suggestion: "Use componentes da forlogic-core ao inv\xE9s de adicionar via shadcn CLI"
177
+ });
178
+ }
179
+ }
180
+ return results;
181
+ }
182
+ function printResults(results) {
183
+ const errors = results.filter((r) => r.type === "error");
184
+ const warnings = results.filter((r) => r.type === "warning");
185
+ console.log("\n");
186
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
187
+ console.log(" \u{1F50D} VALIDA\xC7\xC3O LIB-FIRST - forlogic-core");
188
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
189
+ if (results.length === 0) {
190
+ console.log(" \u2705 Nenhuma duplica\xE7\xE3o encontrada!\n");
191
+ console.log(" Seu projeto est\xE1 seguindo a regra Lib-First corretamente.\n");
192
+ return;
193
+ }
194
+ if (errors.length > 0) {
195
+ console.log(` \u274C ERROS (${errors.length}):
196
+ `);
197
+ console.log(" Componentes locais que DEVEM ser removidos:\n");
198
+ for (const error of errors) {
199
+ console.log(` \u{1F4C1} ${error.file}`);
200
+ console.log(` \u26A0\uFE0F ${error.message}`);
201
+ console.log(` \u{1F4A1} ${error.suggestion}
202
+ `);
203
+ }
204
+ }
205
+ if (warnings.length > 0) {
206
+ console.log(` \u26A0\uFE0F AVISOS (${warnings.length}):
207
+ `);
208
+ for (const warning of warnings) {
209
+ console.log(` \u{1F4C1} ${warning.file}`);
210
+ console.log(` \u2139\uFE0F ${warning.message}`);
211
+ console.log(` \u{1F4A1} ${warning.suggestion}
212
+ `);
213
+ }
214
+ }
215
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
216
+ console.log(` \u{1F4CA} RESUMO: ${errors.length} erros, ${warnings.length} avisos`);
217
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
218
+ if (errors.length > 0) {
219
+ console.log(" \u{1F4D6} Documenta\xE7\xE3o: https://github.com/forlogic/forlogic-core#lib-first\n");
220
+ console.log(" \u{1F4A1} A\xE7\xF5es recomendadas:");
221
+ console.log(" 1. Remova os arquivos duplicados listados acima");
222
+ console.log(" 2. Atualize os imports para usar forlogic-core");
223
+ console.log(" 3. Execute novamente: npx forlogic-core-validate\n");
224
+ }
225
+ }
226
+ function main() {
227
+ const projectRoot = process.cwd();
228
+ console.log(`
229
+ \u{1F4C2} Analisando projeto: ${projectRoot}
230
+ `);
231
+ const duplicates = findDuplicateComponents(projectRoot);
232
+ const configWarnings = checkForShadcnConfig(projectRoot);
233
+ const allResults = [...duplicates, ...configWarnings];
234
+ printResults(allResults);
235
+ const hasErrors = allResults.some((r) => r.type === "error");
236
+ process.exit(hasErrors ? 1 : 0);
237
+ }
238
+ main();