@silasfmartins/testhub 1.0.0

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 (296) hide show
  1. package/.github/copilot-instructions.md +520 -0
  2. package/biome.json +37 -0
  3. package/dist/index.d.ts +45 -0
  4. package/dist/index.js +169 -0
  5. package/dist/scripts/consumer-postinstall.d.ts +15 -0
  6. package/dist/scripts/consumer-postinstall.js +785 -0
  7. package/dist/scripts/generate-docs.d.ts +16 -0
  8. package/dist/scripts/generate-docs.js +1363 -0
  9. package/dist/scripts/generate-index.d.ts +2 -0
  10. package/dist/scripts/generate-index.js +314 -0
  11. package/dist/scripts/init-api.d.ts +2 -0
  12. package/dist/scripts/init-api.js +525 -0
  13. package/dist/scripts/init-banco.d.ts +2 -0
  14. package/dist/scripts/init-banco.js +347 -0
  15. package/dist/scripts/init-frontend.d.ts +2 -0
  16. package/dist/scripts/init-frontend.js +627 -0
  17. package/dist/scripts/init-mobile.d.ts +2 -0
  18. package/dist/scripts/init-mobile.js +481 -0
  19. package/dist/scripts/init-scenarios.d.ts +2 -0
  20. package/dist/scripts/init-scenarios.js +846 -0
  21. package/dist/scripts/init-ssh.d.ts +2 -0
  22. package/dist/scripts/init-ssh.js +639 -0
  23. package/dist/scripts/package-versions.d.ts +57 -0
  24. package/dist/scripts/package-versions.js +768 -0
  25. package/dist/scripts/postinstall.d.ts +1 -0
  26. package/dist/scripts/postinstall.js +527 -0
  27. package/dist/scripts/robust-build.d.ts +7 -0
  28. package/dist/scripts/robust-build.js +88 -0
  29. package/dist/scripts/setup-local-packages.d.ts +31 -0
  30. package/dist/scripts/setup-local-packages.js +237 -0
  31. package/dist/scripts/smart-override.d.ts +2 -0
  32. package/dist/scripts/smart-override.js +1360 -0
  33. package/dist/scripts/sync-configs.d.ts +27 -0
  34. package/dist/scripts/sync-configs.js +248 -0
  35. package/dist/scripts/test-biome-parse.d.ts +5 -0
  36. package/dist/scripts/test-biome-parse.js +84 -0
  37. package/dist/scripts/ultracite-setup.d.ts +4 -0
  38. package/dist/scripts/ultracite-setup.js +310 -0
  39. package/dist/scripts/update-all-init-scripts.d.ts +2 -0
  40. package/dist/scripts/update-all-init-scripts.js +52 -0
  41. package/dist/scripts/update-biome-schema.d.ts +15 -0
  42. package/dist/scripts/update-biome-schema.js +124 -0
  43. package/dist/src/AutoCoreFacade.d.ts +145 -0
  44. package/dist/src/AutoCoreFacade.js +217 -0
  45. package/dist/src/api/ApiActions.d.ts +297 -0
  46. package/dist/src/api/ApiActions.js +1905 -0
  47. package/dist/src/api/Certificate.d.ts +60 -0
  48. package/dist/src/api/Certificate.js +79 -0
  49. package/dist/src/api/JsonResponse.d.ts +116 -0
  50. package/dist/src/api/JsonResponse.js +206 -0
  51. package/dist/src/appium/DeviceFarmViewer.d.ts +79 -0
  52. package/dist/src/appium/DeviceFarmViewer.js +1083 -0
  53. package/dist/src/appium/MobileActions.d.ts +347 -0
  54. package/dist/src/appium/MobileActions.js +1632 -0
  55. package/dist/src/appium/MobileConnection.d.ts +160 -0
  56. package/dist/src/appium/MobileConnection.js +772 -0
  57. package/dist/src/config/envLoader.d.ts +123 -0
  58. package/dist/src/config/envLoader.js +361 -0
  59. package/dist/src/config/jest-safe-setup.d.ts +19 -0
  60. package/dist/src/config/jest-safe-setup.js +369 -0
  61. package/dist/src/config/timeouts.d.ts +32 -0
  62. package/dist/src/config/timeouts.js +38 -0
  63. package/dist/src/desktop/DesktopActions.d.ts +46 -0
  64. package/dist/src/desktop/DesktopActions.js +398 -0
  65. package/dist/src/desktop/DesktopConnection.d.ts +32 -0
  66. package/dist/src/desktop/DesktopConnection.js +84 -0
  67. package/dist/src/domain/entities/TestExecution.d.ts +117 -0
  68. package/dist/src/domain/entities/TestExecution.js +150 -0
  69. package/dist/src/domain/entities/TestReport.d.ts +114 -0
  70. package/dist/src/domain/entities/TestReport.js +179 -0
  71. package/dist/src/domain/repositories/ITestRepository.d.ts +196 -0
  72. package/dist/src/domain/repositories/ITestRepository.js +14 -0
  73. package/dist/src/domain/schemas/ValidationSchemas.d.ts +159 -0
  74. package/dist/src/domain/schemas/ValidationSchemas.js +181 -0
  75. package/dist/src/functions/errors/BaseError.d.ts +78 -0
  76. package/dist/src/functions/errors/BaseError.js +245 -0
  77. package/dist/src/functions/errors/ConfigurationError.d.ts +16 -0
  78. package/dist/src/functions/errors/ConfigurationError.js +48 -0
  79. package/dist/src/functions/errors/ErrorCatalog.d.ts +148 -0
  80. package/dist/src/functions/errors/ErrorCatalog.js +157 -0
  81. package/dist/src/functions/errors/GlobalErrorHandler.d.ts +101 -0
  82. package/dist/src/functions/errors/GlobalErrorHandler.js +281 -0
  83. package/dist/src/functions/errors/IntegrationError.d.ts +17 -0
  84. package/dist/src/functions/errors/IntegrationError.js +51 -0
  85. package/dist/src/functions/errors/SecurityError.d.ts +14 -0
  86. package/dist/src/functions/errors/SecurityError.js +42 -0
  87. package/dist/src/functions/errors/SystemError.d.ts +12 -0
  88. package/dist/src/functions/errors/SystemError.js +36 -0
  89. package/dist/src/functions/errors/ValidationError.d.ts +14 -0
  90. package/dist/src/functions/errors/ValidationError.js +61 -0
  91. package/dist/src/functions/errors/index.d.ts +12 -0
  92. package/dist/src/functions/errors/index.js +13 -0
  93. package/dist/src/global-setup.d.ts +1 -0
  94. package/dist/src/global-setup.js +1037 -0
  95. package/dist/src/helpers/BancoActions.d.ts +188 -0
  96. package/dist/src/helpers/BancoActions.js +581 -0
  97. package/dist/src/helpers/EnviromentHelper.d.ts +17 -0
  98. package/dist/src/helpers/EnviromentHelper.js +66 -0
  99. package/dist/src/helpers/ParallelExecutionHelper.d.ts +183 -0
  100. package/dist/src/helpers/ParallelExecutionHelper.js +375 -0
  101. package/dist/src/helpers/SyncSignal.d.ts +15 -0
  102. package/dist/src/helpers/SyncSignal.js +44 -0
  103. package/dist/src/hubdocs/CategoryDetector.d.ts +83 -0
  104. package/dist/src/hubdocs/CategoryDetector.js +401 -0
  105. package/dist/src/hubdocs/DirectStatementInterceptor.d.ts +54 -0
  106. package/dist/src/hubdocs/DirectStatementInterceptor.js +243 -0
  107. package/dist/src/hubdocs/ExecutionTracker.d.ts +107 -0
  108. package/dist/src/hubdocs/ExecutionTracker.js +702 -0
  109. package/dist/src/hubdocs/HubDocs.d.ts +395 -0
  110. package/dist/src/hubdocs/HubDocs.js +3586 -0
  111. package/dist/src/hubdocs/StatementMethodFilter.d.ts +71 -0
  112. package/dist/src/hubdocs/StatementMethodFilter.js +618 -0
  113. package/dist/src/hubdocs/StatementTracker.d.ts +417 -0
  114. package/dist/src/hubdocs/StatementTracker.js +2419 -0
  115. package/dist/src/hubdocs/SwaggerGenerator.d.ts +59 -0
  116. package/dist/src/hubdocs/SwaggerGenerator.js +405 -0
  117. package/dist/src/hubdocs/index.d.ts +9 -0
  118. package/dist/src/hubdocs/index.js +9 -0
  119. package/dist/src/hubdocs/types.d.ts +114 -0
  120. package/dist/src/hubdocs/types.js +5 -0
  121. package/dist/src/infrastructure/DependencyContainer.d.ts +142 -0
  122. package/dist/src/infrastructure/DependencyContainer.js +250 -0
  123. package/dist/src/infrastructure/adapters/AppiumAdapter.d.ts +168 -0
  124. package/dist/src/infrastructure/adapters/AppiumAdapter.js +468 -0
  125. package/dist/src/infrastructure/adapters/OracleAdapter.d.ts +150 -0
  126. package/dist/src/infrastructure/adapters/OracleAdapter.js +388 -0
  127. package/dist/src/infrastructure/adapters/PlaywrightAdapter.d.ts +192 -0
  128. package/dist/src/infrastructure/adapters/PlaywrightAdapter.js +382 -0
  129. package/dist/src/infrastructure/adapters/SSHAdapter.d.ts +141 -0
  130. package/dist/src/infrastructure/adapters/SSHAdapter.js +428 -0
  131. package/dist/src/interfaces.d.ts +501 -0
  132. package/dist/src/interfaces.js +25 -0
  133. package/dist/src/internal/fakes/__fake-actions__.d.ts +17 -0
  134. package/dist/src/internal/fakes/__fake-actions__.js +21 -0
  135. package/dist/src/internal/fakes/__forbidden__.d.ts +10 -0
  136. package/dist/src/internal/fakes/__forbidden__.js +18 -0
  137. package/dist/src/internal/fakes/__honeypot__.d.ts +15 -0
  138. package/dist/src/internal/fakes/__honeypot__.js +24 -0
  139. package/dist/src/octane/OctaneReporter.d.ts +13 -0
  140. package/dist/src/octane/OctaneReporter.js +61 -0
  141. package/dist/src/playwright/CryptoActions.d.ts +20 -0
  142. package/dist/src/playwright/CryptoActions.js +75 -0
  143. package/dist/src/playwright/EnhancedWebActions.d.ts +7 -0
  144. package/dist/src/playwright/EnhancedWebActions.js +65 -0
  145. package/dist/src/playwright/WebActions.d.ts +1599 -0
  146. package/dist/src/playwright/WebActions.js +11788 -0
  147. package/dist/src/playwright/actions/ActionTimeline.d.ts +36 -0
  148. package/dist/src/playwright/actions/ActionTimeline.js +101 -0
  149. package/dist/src/playwright/actions/RecoveryQueue.d.ts +82 -0
  150. package/dist/src/playwright/actions/RecoveryQueue.js +130 -0
  151. package/dist/src/playwright/actions/SelectorCache.d.ts +53 -0
  152. package/dist/src/playwright/actions/SelectorCache.js +96 -0
  153. package/dist/src/playwright/actions/index.d.ts +13 -0
  154. package/dist/src/playwright/actions/index.js +14 -0
  155. package/dist/src/playwright/actions/types.d.ts +147 -0
  156. package/dist/src/playwright/actions/types.js +5 -0
  157. package/dist/src/playwright/fixtures.d.ts +112 -0
  158. package/dist/src/playwright/fixtures.js +718 -0
  159. package/dist/src/playwright/network-logs-reporter.d.ts +7 -0
  160. package/dist/src/playwright/network-logs-reporter.js +66 -0
  161. package/dist/src/playwright/registerRecoveryWrappers.d.ts +1 -0
  162. package/dist/src/playwright/registerRecoveryWrappers.js +54 -0
  163. package/dist/src/security/BuildSecurity.d.ts +12 -0
  164. package/dist/src/security/BuildSecurity.js +138 -0
  165. package/dist/src/security/EulaProtection.d.ts +70 -0
  166. package/dist/src/security/EulaProtection.js +155 -0
  167. package/dist/src/security/HoneypotManager.d.ts +46 -0
  168. package/dist/src/security/HoneypotManager.js +234 -0
  169. package/dist/src/security/KeysManager.d.ts +36 -0
  170. package/dist/src/security/KeysManager.js +158 -0
  171. package/dist/src/security/ProofOfWorkIntegration.d.ts +64 -0
  172. package/dist/src/security/ProofOfWorkIntegration.js +206 -0
  173. package/dist/src/security/SecurityValidation.d.ts +21 -0
  174. package/dist/src/security/SecurityValidation.js +163 -0
  175. package/dist/src/security/SourceMapProtection.d.ts +55 -0
  176. package/dist/src/security/SourceMapProtection.js +220 -0
  177. package/dist/src/security/protector.d.ts +1 -0
  178. package/dist/src/security/protector.js +97 -0
  179. package/dist/src/ssh/SSHActions.d.ts +262 -0
  180. package/dist/src/ssh/SSHActions.js +790 -0
  181. package/dist/src/ssh/SSHClient.d.ts +99 -0
  182. package/dist/src/ssh/SSHClient.js +409 -0
  183. package/dist/src/statements/BaseStatement.d.ts +38 -0
  184. package/dist/src/statements/BaseStatement.js +78 -0
  185. package/dist/src/testContext/AuthStateManager.d.ts +93 -0
  186. package/dist/src/testContext/AuthStateManager.js +256 -0
  187. package/dist/src/testContext/CoverageManager.d.ts +198 -0
  188. package/dist/src/testContext/CoverageManager.js +917 -0
  189. package/dist/src/testContext/TestAnnotations.d.ts +476 -0
  190. package/dist/src/testContext/TestAnnotations.js +2647 -0
  191. package/dist/src/testContext/TestContext.d.ts +138 -0
  192. package/dist/src/testContext/TestContext.js +369 -0
  193. package/dist/src/testContext/UnifiedHtmlGenerator.d.ts +7 -0
  194. package/dist/src/testContext/UnifiedHtmlGenerator.js +264 -0
  195. package/dist/src/testContext/UnifiedReportManager.d.ts +211 -0
  196. package/dist/src/testContext/UnifiedReportManager.js +1206 -0
  197. package/dist/src/testhub/DynamicConfigManager.d.ts +121 -0
  198. package/dist/src/testhub/DynamicConfigManager.js +320 -0
  199. package/dist/src/testhub/SystemsManager.d.ts +119 -0
  200. package/dist/src/testhub/SystemsManager.js +365 -0
  201. package/dist/src/testhub/TestHubClient.d.ts +335 -0
  202. package/dist/src/testhub/TestHubClient.js +1215 -0
  203. package/dist/src/testhub/TestHubReporter.d.ts +62 -0
  204. package/dist/src/testhub/TestHubReporter.js +576 -0
  205. package/dist/src/testhub/TestHubVars.d.ts +116 -0
  206. package/dist/src/testhub/TestHubVars.js +273 -0
  207. package/dist/src/utils/ActionInterceptor.d.ts +59 -0
  208. package/dist/src/utils/ActionInterceptor.js +741 -0
  209. package/dist/src/utils/ArtifactsCompressor.d.ts +43 -0
  210. package/dist/src/utils/ArtifactsCompressor.js +181 -0
  211. package/dist/src/utils/AutoLogsFinal.d.ts +47 -0
  212. package/dist/src/utils/AutoLogsFinal.js +148 -0
  213. package/dist/src/utils/CodeGenSession.d.ts +114 -0
  214. package/dist/src/utils/CodeGenSession.js +264 -0
  215. package/dist/src/utils/ConfigLogger.d.ts +133 -0
  216. package/dist/src/utils/ConfigLogger.js +611 -0
  217. package/dist/src/utils/CustomReporter.d.ts +22 -0
  218. package/dist/src/utils/CustomReporter.js +352 -0
  219. package/dist/src/utils/DataStore.d.ts +171 -0
  220. package/dist/src/utils/DataStore.js +484 -0
  221. package/dist/src/utils/DatabaseInterceptor.d.ts +19 -0
  222. package/dist/src/utils/DatabaseInterceptor.js +295 -0
  223. package/dist/src/utils/DateHelper.d.ts +16 -0
  224. package/dist/src/utils/DateHelper.js +120 -0
  225. package/dist/src/utils/DateValidator.d.ts +4 -0
  226. package/dist/src/utils/DateValidator.js +51 -0
  227. package/dist/src/utils/DocumentGenerator.d.ts +35 -0
  228. package/dist/src/utils/DocumentGenerator.js +129 -0
  229. package/dist/src/utils/EvidenceCapture.d.ts +90 -0
  230. package/dist/src/utils/EvidenceCapture.js +600 -0
  231. package/dist/src/utils/EvidenceReportGenerator.d.ts +70 -0
  232. package/dist/src/utils/EvidenceReportGenerator.js +799 -0
  233. package/dist/src/utils/FrameManagementUtil.d.ts +42 -0
  234. package/dist/src/utils/FrameManagementUtil.js +75 -0
  235. package/dist/src/utils/GlobalStatementsInterceptor.d.ts +1 -0
  236. package/dist/src/utils/GlobalStatementsInterceptor.js +1 -0
  237. package/dist/src/utils/HTMLTemplate.d.ts +1 -0
  238. package/dist/src/utils/HTMLTemplate.js +1034 -0
  239. package/dist/src/utils/InterceptacaoMagica.d.ts +23 -0
  240. package/dist/src/utils/InterceptacaoMagica.js +365 -0
  241. package/dist/src/utils/LogSanitizer.d.ts +35 -0
  242. package/dist/src/utils/LogSanitizer.js +110 -0
  243. package/dist/src/utils/Logger.d.ts +65 -0
  244. package/dist/src/utils/Logger.js +284 -0
  245. package/dist/src/utils/McpLocalClient.d.ts +141 -0
  246. package/dist/src/utils/McpLocalClient.js +871 -0
  247. package/dist/src/utils/PDFEvidenceGenerator.d.ts +20 -0
  248. package/dist/src/utils/PDFEvidenceGenerator.js +156 -0
  249. package/dist/src/utils/SpecFileAnalyzer.d.ts +35 -0
  250. package/dist/src/utils/SpecFileAnalyzer.js +209 -0
  251. package/dist/src/utils/StatementInterceptor.d.ts +18 -0
  252. package/dist/src/utils/StatementInterceptor.js +87 -0
  253. package/dist/src/utils/StatementLogger.d.ts +33 -0
  254. package/dist/src/utils/StatementLogger.js +113 -0
  255. package/dist/src/utils/StatementsInterceptor.d.ts +1 -0
  256. package/dist/src/utils/StatementsInterceptor.js +1 -0
  257. package/dist/src/utils/TeamsFlushHook.d.ts +17 -0
  258. package/dist/src/utils/TeamsFlushHook.js +168 -0
  259. package/dist/src/utils/TerminalLogCapture.d.ts +158 -0
  260. package/dist/src/utils/TerminalLogCapture.js +531 -0
  261. package/dist/src/utils/TestMethodLogger.d.ts +70 -0
  262. package/dist/src/utils/TestMethodLogger.js +95 -0
  263. package/dist/src/utils/UnifiedTeardown.d.ts +4 -0
  264. package/dist/src/utils/UnifiedTeardown.js +400 -0
  265. package/dist/src/utils/XPathCatalog.d.ts +152 -0
  266. package/dist/src/utils/XPathCatalog.js +350 -0
  267. package/dist/src/utils/generators.d.ts +90 -0
  268. package/dist/src/utils/generators.js +167 -0
  269. package/dist/src/utils/testRecovery/ResilientPlaywright.d.ts +152 -0
  270. package/dist/src/utils/testRecovery/ResilientPlaywright.js +715 -0
  271. package/dist/src/utils/testRecovery/TestRecoveryClient.d.ts +801 -0
  272. package/dist/src/utils/testRecovery/TestRecoveryClient.js +1415 -0
  273. package/dist/src/utils/testRecovery/autoFixCode.d.ts +65 -0
  274. package/dist/src/utils/testRecovery/autoFixCode.js +32 -0
  275. package/dist/vitest.config.d.ts +2 -0
  276. package/dist/vitest.config.js +59 -0
  277. package/dist/wdio.conf.d.ts +1 -0
  278. package/dist/wdio.conf.js +420 -0
  279. package/package.json +137 -0
  280. package/protect-loader.mjs +643 -0
  281. package/scripts/consumer-postinstall.ts +975 -0
  282. package/scripts/generate-index.ts +343 -0
  283. package/scripts/init-api.ts +613 -0
  284. package/scripts/init-banco.ts +437 -0
  285. package/scripts/init-frontend.ts +727 -0
  286. package/scripts/init-mobile.ts +558 -0
  287. package/scripts/init-scenarios.ts +925 -0
  288. package/scripts/init-ssh.ts +734 -0
  289. package/scripts/package-versions.ts +978 -0
  290. package/scripts/postinstall.ts +605 -0
  291. package/scripts/smart-override.ts +1675 -0
  292. package/scripts/sync-configs.ts +302 -0
  293. package/scripts/ultracite-setup.ts +370 -0
  294. package/src/types/globals.d.ts +48 -0
  295. package/tsconfig.json +29 -0
  296. package/types/autocore-sync-signal.d.ts +10 -0
@@ -0,0 +1,1360 @@
1
+ #!/usr/bin/env node
2
+ // @ts-nocheck
3
+ /**
4
+ * 🔧 Smart Override para TypeScript puro
5
+ * Versão otimizada para desenvolvimento TypeScript sem dependências externas
6
+ */
7
+ import { execSync } from 'node:child_process';
8
+ import * as fs from 'node:fs';
9
+ import * as os from 'node:os';
10
+ import * as path from 'node:path';
11
+ const LOCAL_REGISTRY = path.join(os.homedir(), '.rbqa-local-packages.json');
12
+ const WATCH_REGISTRY = path.join(os.homedir(), '.rbqa-watch-registry.json');
13
+ // 🔒 Pacotes que PREFERENCIALMENTE usam Azure (quando disponível)
14
+ // Se o pacote não existir no Azure ainda, usará versão local automaticamente
15
+ const PREFER_AZURE_PACKAGES = new Set([
16
+ '@silasfmartins/testhub', // AutoCore prefere Azure, mas usa local se não existir
17
+ ]);
18
+ // 🎯 Função para verificar se é um pacote scoped (começa com @)
19
+ // Reconhece: @rbqa/*, @sfa/*, @org/*, etc.
20
+ function isScopedPackage(name) {
21
+ return name.startsWith('@') && name.includes('/');
22
+ }
23
+ class SmartOverride {
24
+ buildMetrics = {
25
+ startTime: Date.now(),
26
+ compiledFiles: 0,
27
+ buildSize: '0 KB',
28
+ success: false,
29
+ errors: [],
30
+ warnings: [],
31
+ };
32
+ getLocalRegistry() {
33
+ try {
34
+ if (fs.existsSync(LOCAL_REGISTRY)) {
35
+ return JSON.parse(fs.readFileSync(LOCAL_REGISTRY, 'utf8'));
36
+ }
37
+ }
38
+ catch { }
39
+ return {};
40
+ }
41
+ saveLocalRegistry(registry) {
42
+ fs.writeFileSync(LOCAL_REGISTRY, JSON.stringify(registry, null, 2));
43
+ }
44
+ getWatchRegistry() {
45
+ try {
46
+ if (fs.existsSync(WATCH_REGISTRY)) {
47
+ return JSON.parse(fs.readFileSync(WATCH_REGISTRY, 'utf8'));
48
+ }
49
+ }
50
+ catch { }
51
+ return {};
52
+ }
53
+ saveWatchRegistry(registry) {
54
+ fs.writeFileSync(WATCH_REGISTRY, JSON.stringify(registry, null, 2));
55
+ }
56
+ /**
57
+ * Calcula o tamanho de um diretório recursivamente
58
+ */
59
+ calculateDirectorySize(dirPath) {
60
+ let totalSize = 0;
61
+ try {
62
+ const items = fs.readdirSync(dirPath, { withFileTypes: true });
63
+ for (const item of items) {
64
+ const itemPath = path.join(dirPath, item.name);
65
+ if (item.isDirectory()) {
66
+ totalSize += this.calculateDirectorySize(itemPath);
67
+ }
68
+ else if (item.isFile()) {
69
+ totalSize += fs.statSync(itemPath).size;
70
+ }
71
+ }
72
+ }
73
+ catch (error) {
74
+ // Ignora erros de acesso a arquivos
75
+ }
76
+ return totalSize;
77
+ }
78
+ /**
79
+ * Formata tamanho em bytes para uma string legível
80
+ */
81
+ formatSize(bytes) {
82
+ const units = ['B', 'KB', 'MB', 'GB'];
83
+ let size = bytes;
84
+ let unitIndex = 0;
85
+ while (size >= 1024 && unitIndex < units.length - 1) {
86
+ size /= 1024;
87
+ unitIndex++;
88
+ }
89
+ return `${size.toFixed(size < 10 ? 1 : 0)} ${units[unitIndex]}`;
90
+ }
91
+ /**
92
+ * Conta arquivos compilados no diretório dist
93
+ */
94
+ countCompiledFiles(distPath) {
95
+ let count = 0;
96
+ try {
97
+ const items = fs.readdirSync(distPath, { withFileTypes: true });
98
+ for (const item of items) {
99
+ const itemPath = path.join(distPath, item.name);
100
+ if (item.isDirectory()) {
101
+ count += this.countCompiledFiles(itemPath);
102
+ }
103
+ else if (item.isFile() &&
104
+ (item.name.endsWith('.js') || item.name.endsWith('.d.ts'))) {
105
+ count++;
106
+ }
107
+ }
108
+ }
109
+ catch (error) {
110
+ // Ignora erros
111
+ }
112
+ return count;
113
+ }
114
+ /**
115
+ * Formata duração em milissegundos para string legível
116
+ */
117
+ formatDuration(ms) {
118
+ if (ms < 1000) {
119
+ return `${ms}ms`;
120
+ }
121
+ if (ms < 60_000) {
122
+ return `${(ms / 1000).toFixed(1)}s`;
123
+ }
124
+ const minutes = Math.floor(ms / 60_000);
125
+ const seconds = ((ms % 60_000) / 1000).toFixed(1);
126
+ return `${minutes}m ${seconds}s`;
127
+ }
128
+ /**
129
+ * Exibe banner de início do build
130
+ */
131
+ showBuildStartBanner(packageName, version) {
132
+ const line = '═'.repeat(80);
133
+ console.log(`\n${line}`);
134
+ console.log(`🏗️ INICIANDO BUILD - ${packageName}@${version}`);
135
+ console.log(`${line}`);
136
+ console.log(`📅 Timestamp: ${new Date().toLocaleString('pt-BR')}`);
137
+ console.log(`🖥️ Sistema: ${os.platform()} ${os.arch()}`);
138
+ console.log(`⚡ Node.js: ${process.version}`);
139
+ console.log(`📂 Diretório: ${process.cwd()}`);
140
+ console.log(`${line}\n`);
141
+ }
142
+ /**
143
+ * Exibe resumo detalhado do build
144
+ */
145
+ showBuildSummary(packageName, version) {
146
+ this.buildMetrics.endTime = Date.now();
147
+ this.buildMetrics.duration =
148
+ this.buildMetrics.endTime - this.buildMetrics.startTime;
149
+ const line = '═'.repeat(80);
150
+ const statusIcon = this.buildMetrics.success ? '✅' : '❌';
151
+ const statusText = this.buildMetrics.success ? 'SUCESSO' : 'FALHOU';
152
+ console.log(`\n${line}`);
153
+ console.log(`${statusIcon} BUILD ${statusText} - ${packageName}@${version}`);
154
+ console.log(`${line}`);
155
+ // Métricas principais
156
+ console.log(`⏱️ Duração total: ${this.formatDuration(this.buildMetrics.duration)}`);
157
+ console.log(`📁 Arquivos compilados: ${this.buildMetrics.compiledFiles}`);
158
+ console.log(`📦 Tamanho do build: ${this.buildMetrics.buildSize}`);
159
+ console.log(`🕐 Concluído em: ${new Date().toLocaleString('pt-BR')}`);
160
+ // Performance
161
+ const filesPerSecond = this.buildMetrics.compiledFiles / (this.buildMetrics.duration / 1000);
162
+ console.log(`⚡ Performance: ${filesPerSecond.toFixed(1)} arquivos/segundo`);
163
+ // Status de erros e warnings
164
+ if (this.buildMetrics.errors.length > 0) {
165
+ console.log(`❌ Erros: ${this.buildMetrics.errors.length}`);
166
+ this.buildMetrics.errors.forEach((error) => {
167
+ console.log(` • ${error}`);
168
+ });
169
+ }
170
+ if (this.buildMetrics.warnings.length > 0) {
171
+ console.log(`⚠️ Warnings: ${this.buildMetrics.warnings.length}`);
172
+ this.buildMetrics.warnings.forEach((warning) => {
173
+ console.log(` • ${warning}`);
174
+ });
175
+ }
176
+ if (this.buildMetrics.errors.length === 0 &&
177
+ this.buildMetrics.warnings.length === 0) {
178
+ console.log('✨ Build limpo: sem erros ou warnings');
179
+ }
180
+ console.log(`${line}\n`);
181
+ // Mostrar próximos passos se sucesso
182
+ if (this.buildMetrics.success) {
183
+ console.log('📋 PRÓXIMOS PASSOS:');
184
+ console.log(' • Pacote registrado no registro local');
185
+ console.log(' • Outros projetos detectarão automaticamente as mudanças');
186
+ console.log(` • Use 'smart-override status' para verificar dependências`);
187
+ console.log(` • Use 'smart-override remove' para voltar às versões do Azure\n`);
188
+ }
189
+ }
190
+ /**
191
+ * Registra um pacote após build e atualiza projetos dependentes
192
+ */
193
+ register() {
194
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
195
+ if (!fs.existsSync(packageJsonPath)) {
196
+ console.log('❌ package.json não encontrado no diretório atual');
197
+ return;
198
+ }
199
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
200
+ const distPath = path.join(process.cwd(), 'dist');
201
+ // Exibir banner de início
202
+ this.showBuildStartBanner(packageJson.name, packageJson.version);
203
+ console.log('🔍 Verificando estrutura do projeto...');
204
+ if (!fs.existsSync(distPath)) {
205
+ console.log('❌ Pasta dist não encontrada');
206
+ console.log('💡 Execute o build do TypeScript primeiro: npm run build ou tsc');
207
+ this.buildMetrics.errors.push('Pasta dist não encontrada');
208
+ this.showBuildSummary(packageJson.name, packageJson.version);
209
+ return;
210
+ }
211
+ // Coletar métricas do build
212
+ console.log('📊 Coletando métricas do build...');
213
+ this.buildMetrics.compiledFiles = this.countCompiledFiles(distPath);
214
+ const distSize = this.calculateDirectorySize(distPath);
215
+ this.buildMetrics.buildSize = this.formatSize(distSize);
216
+ console.log(` • Arquivos compilados: ${this.buildMetrics.compiledFiles}`);
217
+ console.log(` • Tamanho do build: ${this.buildMetrics.buildSize}`);
218
+ // Verificar arquivos essenciais
219
+ console.log('🔎 Verificando arquivos essenciais...');
220
+ const essentialFiles = ['dist/index.js', 'dist/index.d.ts'];
221
+ const missingFiles = essentialFiles.filter((file) => !fs.existsSync(path.join(process.cwd(), file)));
222
+ if (missingFiles.length > 0) {
223
+ console.log(`⚠️ Arquivos essenciais ausentes: ${missingFiles.join(', ')}`);
224
+ this.buildMetrics.warnings.push(`Arquivos ausentes: ${missingFiles.join(', ')}`);
225
+ }
226
+ else {
227
+ console.log('✅ Todos os arquivos essenciais presentes');
228
+ }
229
+ // Registrar no registry local
230
+ console.log('📝 Registrando no registry local...');
231
+ const registry = this.getLocalRegistry();
232
+ const buildDetails = {
233
+ compiledFiles: this.buildMetrics.compiledFiles,
234
+ buildSize: this.buildMetrics.buildSize,
235
+ nodeVersion: process.version,
236
+ timestamp: new Date().toISOString(),
237
+ };
238
+ registry[packageJson.name] = {
239
+ name: packageJson.name,
240
+ version: packageJson.version,
241
+ path: process.cwd(),
242
+ lastBuild: Date.now(),
243
+ buildDuration: this.buildMetrics.duration,
244
+ buildDetails,
245
+ };
246
+ this.saveLocalRegistry(registry);
247
+ this.buildMetrics.success = true;
248
+ console.log('✅ Pacote registrado com sucesso');
249
+ // Registrar este projeto como "watchable" pelos outros
250
+ this.registerAsWatchableProject(packageJson.name);
251
+ // Verificar e notificar projetos dependentes
252
+ this.notifyDependentProjects(packageJson.name);
253
+ // Exibir resumo final
254
+ this.showBuildSummary(packageJson.name, packageJson.version);
255
+ }
256
+ /**
257
+ * Registra o projeto atual como um que pode ser "observado" por outros
258
+ */
259
+ registerAsWatchableProject(packageName) {
260
+ const watchRegistry = this.getWatchRegistry();
261
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
262
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
263
+ const dependencies = {
264
+ ...packageJson.dependencies,
265
+ ...packageJson.devDependencies,
266
+ };
267
+ watchRegistry[packageName] = {
268
+ name: packageName,
269
+ path: process.cwd(),
270
+ lastChecked: Date.now(),
271
+ dependencies: Object.keys(dependencies)
272
+ .filter((dep) => isScopedPackage(dep))
273
+ .reduce((acc, dep) => {
274
+ acc[dep] = dependencies[dep];
275
+ return acc;
276
+ }, {}),
277
+ };
278
+ this.saveWatchRegistry(watchRegistry);
279
+ }
280
+ /**
281
+ * Notifica e atualiza automaticamente projetos que dependem do pacote atual
282
+ */
283
+ notifyDependentProjects(packageName) {
284
+ console.log('🔗 Verificando projetos dependentes para atualização automática...');
285
+ const watchRegistry = this.getWatchRegistry();
286
+ const localRegistry = this.getLocalRegistry();
287
+ const currentPackage = localRegistry[packageName];
288
+ if (!currentPackage)
289
+ return;
290
+ let updatedProjects = 0;
291
+ // Percorrer todos os projetos registrados
292
+ Object.values(watchRegistry).forEach((watchedProject) => {
293
+ if (watchedProject.name === packageName)
294
+ return; // Pular o próprio projeto
295
+ // Verificar se este projeto depende do pacote que acabou de ser buildado
296
+ if (watchedProject.dependencies[packageName]) {
297
+ const requiredVersion = watchedProject.dependencies[packageName].replace(/[\^~]/, '');
298
+ const versionComparison = this.compareVersions(currentPackage.version, requiredVersion);
299
+ if (versionComparison >= 0) {
300
+ console.log(` 🎯 Atualizando ${watchedProject.name}...`);
301
+ // Aplicar override no projeto dependente
302
+ if (this.applyOverrideToProject(watchedProject, packageName, currentPackage)) {
303
+ updatedProjects++;
304
+ console.log(` ✅ ${watchedProject.name} atualizado com ${packageName}@${currentPackage.version}`);
305
+ }
306
+ else {
307
+ console.log(` ℹ️ ${watchedProject.name} já está atualizado`);
308
+ }
309
+ }
310
+ else {
311
+ console.log(` ⚠️ ${watchedProject.name} requer v${requiredVersion}, mas local é v${currentPackage.version}`);
312
+ }
313
+ }
314
+ });
315
+ if (updatedProjects > 0) {
316
+ console.log(`\n🎉 ${updatedProjects} projeto(s) atualizado(s) automaticamente!`);
317
+ console.log('💡 Os projetos atualizados agora usam sua versão local mais recente');
318
+ }
319
+ else {
320
+ console.log(' • Nenhum projeto dependente precisou de atualização');
321
+ }
322
+ }
323
+ /**
324
+ * Aplica override em um projeto específico
325
+ */
326
+ applyOverrideToProject(watchedProject, packageName, localPkg) {
327
+ const nodeModulesPath = path.join(watchedProject.path, 'node_modules', packageName);
328
+ // Verificar se o projeto ainda existe
329
+ if (!fs.existsSync(watchedProject.path))
330
+ return false;
331
+ // Verificar se já está aplicado e é a mesma versão
332
+ const overrideMarker = path.join(nodeModulesPath, '.local-override.json');
333
+ if (fs.existsSync(overrideMarker)) {
334
+ try {
335
+ const existing = JSON.parse(fs.readFileSync(overrideMarker, 'utf8'));
336
+ if (existing.lastBuild >= localPkg.lastBuild) {
337
+ return false; // Já está atualizado
338
+ }
339
+ }
340
+ catch { }
341
+ }
342
+ try {
343
+ // Remove versão atual do node_modules
344
+ if (fs.existsSync(nodeModulesPath)) {
345
+ if (process.platform === 'win32') {
346
+ execSync(`rmdir /s /q "${nodeModulesPath}"`, {
347
+ stdio: 'pipe',
348
+ timeout: 10_000,
349
+ });
350
+ }
351
+ else {
352
+ execSync(`rm -rf "${nodeModulesPath}"`, {
353
+ stdio: 'pipe',
354
+ timeout: 10_000,
355
+ });
356
+ }
357
+ }
358
+ // Cria diretório
359
+ fs.mkdirSync(nodeModulesPath, { recursive: true });
360
+ // Copia arquivos essenciais
361
+ this.copyFiles(localPkg.path, nodeModulesPath);
362
+ // Marca como override
363
+ fs.writeFileSync(overrideMarker, JSON.stringify({
364
+ source: localPkg.path,
365
+ version: localPkg.version,
366
+ lastBuild: localPkg.lastBuild,
367
+ appliedAt: Date.now(),
368
+ buildDetails: localPkg.buildDetails,
369
+ autoApplied: true, // Marca que foi aplicado automaticamente
370
+ }, null, 2));
371
+ return true;
372
+ }
373
+ catch (error) {
374
+ return false;
375
+ }
376
+ }
377
+ /**
378
+ * Verifica e aplica overrides locais (versão melhorada)
379
+ */
380
+ check() {
381
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
382
+ if (!fs.existsSync(packageJsonPath)) {
383
+ console.log('❌ package.json não encontrado');
384
+ return;
385
+ }
386
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
387
+ const dependencies = {
388
+ ...packageJson.dependencies,
389
+ ...packageJson.devDependencies,
390
+ };
391
+ const registry = this.getLocalRegistry();
392
+ console.log('\n🔍 Verificando dependências locais...');
393
+ console.log(`📦 Projeto: ${packageJson.name}@${packageJson.version}`);
394
+ const scopedDeps = Object.keys(dependencies).filter((dep) => isScopedPackage(dep));
395
+ if (scopedDeps.length === 0) {
396
+ console.log('ℹ️ Nenhuma dependência scoped (@) encontrada');
397
+ return;
398
+ }
399
+ console.log(`🎯 Dependências scoped encontradas: ${scopedDeps.length}`);
400
+ // 🆕 ATUALIZAR O REGISTRY LOCAL COM AS VERSÕES DO PACKAGE.JSON
401
+ console.log('\n🔄 Atualizando registry local com versões do package.json...');
402
+ let updatedRegistry = false;
403
+ scopedDeps.forEach((depName) => {
404
+ const requiredVersion = dependencies[depName].replace(/[\^~]/, '');
405
+ // Se o pacote não existe no registry local, tentar encontrá-lo
406
+ if (!registry[depName]) {
407
+ // Procurar pelo pacote nos node_modules
408
+ const nodeModulesPath = path.join(process.cwd(), 'node_modules', depName);
409
+ if (fs.existsSync(nodeModulesPath)) {
410
+ const depPackageJson = path.join(nodeModulesPath, 'package.json');
411
+ if (fs.existsSync(depPackageJson)) {
412
+ try {
413
+ const depPkg = JSON.parse(fs.readFileSync(depPackageJson, 'utf8'));
414
+ // Adicionar ao registry local
415
+ registry[depName] = {
416
+ name: depName,
417
+ version: depPkg.version,
418
+ path: nodeModulesPath,
419
+ lastBuild: Date.now(),
420
+ buildDetails: {
421
+ timestamp: new Date().toISOString(),
422
+ nodeVersion: process.version,
423
+ },
424
+ };
425
+ updatedRegistry = true;
426
+ console.log(` ✅ Adicionado ao registry: ${depName}@${depPkg.version}`);
427
+ }
428
+ catch (parseError) {
429
+ console.log(` ⚠️ Erro ao ler package.json de ${depName} (arquivo corrompido ou com conflitos de merge)`);
430
+ }
431
+ }
432
+ }
433
+ }
434
+ else {
435
+ // Atualizar versão se diferente
436
+ const currentVersion = registry[depName].version;
437
+ if (currentVersion !== requiredVersion) {
438
+ const nodeModulesPath = path.join(process.cwd(), 'node_modules', depName);
439
+ if (fs.existsSync(nodeModulesPath)) {
440
+ const depPackageJson = path.join(nodeModulesPath, 'package.json');
441
+ if (fs.existsSync(depPackageJson)) {
442
+ try {
443
+ const depPkg = JSON.parse(fs.readFileSync(depPackageJson, 'utf8'));
444
+ registry[depName].version = depPkg.version;
445
+ registry[depName].lastBuild = Date.now();
446
+ updatedRegistry = true;
447
+ console.log(` 🔄 Atualizado: ${depName} v${currentVersion} → v${depPkg.version}`);
448
+ }
449
+ catch (parseError) {
450
+ console.log(` ⚠️ Erro ao ler package.json de ${depName} (arquivo corrompido ou com conflitos de merge)`);
451
+ }
452
+ }
453
+ }
454
+ }
455
+ }
456
+ });
457
+ // Salvar registry atualizado
458
+ if (updatedRegistry) {
459
+ fs.writeFileSync(LOCAL_REGISTRY, JSON.stringify(registry, null, 2));
460
+ console.log('✅ Registry local atualizado');
461
+ }
462
+ let appliedCount = 0;
463
+ let skippedCount = 0;
464
+ let alreadyInstalledCount = 0;
465
+ console.log('\n📦 Sincronizando dependências scoped (@)...');
466
+ console.log(' 🔒 Framework (@silasfmartins/testhub): sempre do Azure DevOps');
467
+ console.log(' 📦 Outros pacotes (@rbqa/*, @sfa/*, etc.): versão local prevalece sobre Azure\n');
468
+ for (const depName of scopedDeps) {
469
+ const requiredVersionRaw = dependencies[depName];
470
+ const requiredVersion = requiredVersionRaw.replace(/[\^~]/, '');
471
+ console.log(`\n 📋 ${depName}`);
472
+ console.log(` 📄 Versão no package.json: ${requiredVersionRaw}`);
473
+ // Verificar versão instalada atualmente
474
+ const nodeModulesPath = path.join(process.cwd(), 'node_modules', depName);
475
+ let installedVersion = null;
476
+ let hasLocalOverride = false;
477
+ if (fs.existsSync(nodeModulesPath)) {
478
+ const depPkgPath = path.join(nodeModulesPath, 'package.json');
479
+ const overrideMarker = path.join(nodeModulesPath, '.local-override.json');
480
+ if (fs.existsSync(depPkgPath)) {
481
+ try {
482
+ const depPkg = JSON.parse(fs.readFileSync(depPkgPath, 'utf8'));
483
+ installedVersion = depPkg.version;
484
+ }
485
+ catch (parseError) {
486
+ console.log(` ⚠️ Erro ao ler package.json (arquivo corrompido ou com conflitos de merge)`);
487
+ console.log(` 💡 Tente: rm -rf node_modules/${depName} && npm install`);
488
+ }
489
+ }
490
+ hasLocalOverride = fs.existsSync(overrideMarker);
491
+ }
492
+ if (installedVersion) {
493
+ console.log(` 📦 Versão instalada: ${installedVersion}${hasLocalOverride ? ' (LOCAL)' : ' (AZURE)'}`);
494
+ }
495
+ // 🔒 FRAMEWORK (@silasfmartins/testhub): SEMPRE instalar do Azure DevOps
496
+ if (PREFER_AZURE_PACKAGES.has(depName)) {
497
+ console.log(` 🔒 FRAMEWORK: garantindo instalação do Azure DevOps`);
498
+ // Verificar se já está na versão correta (do Azure, sem override local)
499
+ if (installedVersion && !hasLocalOverride) {
500
+ const versionMatch = this.compareVersions(installedVersion, requiredVersion) >= 0;
501
+ if (versionMatch) {
502
+ console.log(` ✅ Framework já está na versão correta (${installedVersion})`);
503
+ alreadyInstalledCount++;
504
+ continue;
505
+ }
506
+ }
507
+ // Remover override local se existir (framework SEMPRE vem do Azure)
508
+ if (hasLocalOverride) {
509
+ console.log(` 🗑️ Removendo override local (framework deve vir do Azure)...`);
510
+ try {
511
+ if (process.platform === 'win32') {
512
+ execSync(`rmdir /s /q "${nodeModulesPath}"`, { stdio: 'pipe', timeout: 10000 });
513
+ }
514
+ else {
515
+ execSync(`rm -rf "${nodeModulesPath}"`, { stdio: 'pipe', timeout: 10000 });
516
+ }
517
+ }
518
+ catch (e) {
519
+ // Ignorar erro de remoção
520
+ }
521
+ }
522
+ // Instalar a versão do package.json do Azure
523
+ console.log(` 🔄 Instalando ${depName}@${requiredVersion} do Azure DevOps...`);
524
+ if (this.installFromAzure(depName, requiredVersion)) {
525
+ appliedCount++;
526
+ console.log(` ✅ Framework instalado com sucesso: ${depName}@${requiredVersion}`);
527
+ }
528
+ else {
529
+ skippedCount++;
530
+ console.log(` ❌ Falha ao instalar framework do Azure`);
531
+ console.log(` 💡 Verifique sua conexão com o Azure DevOps`);
532
+ }
533
+ continue;
534
+ }
535
+ // 📦 OUTROS PACOTES SCOPED (@rbqa/*, @sfa/*, etc.): versão LOCAL prevalece sobre Azure
536
+ // Verificar se tem versão local disponível no registry
537
+ const localPkg = registry[depName];
538
+ if (localPkg) {
539
+ // Tem versão local disponível
540
+ console.log(` 🔗 Versão local disponível: ${localPkg.version}`);
541
+ // Verificar se a versão local atende ao requisito
542
+ const localMeetsRequirement = this.compareVersions(localPkg.version, requiredVersion) >= 0;
543
+ if (localMeetsRequirement) {
544
+ // Versão local atende - usar LOCAL (prevalece sobre Azure)
545
+ if (hasLocalOverride && installedVersion === localPkg.version) {
546
+ console.log(` ✅ Versão local já está aplicada (${localPkg.version})`);
547
+ alreadyInstalledCount++;
548
+ }
549
+ else {
550
+ console.log(` 🔗 Aplicando versão LOCAL (prevalece sobre Azure)...`);
551
+ if (this.applyOverride(depName, localPkg)) {
552
+ appliedCount++;
553
+ console.log(` ✅ Versão local aplicada: ${depName}@${localPkg.version}`);
554
+ }
555
+ else {
556
+ alreadyInstalledCount++;
557
+ console.log(` ✅ Versão local já está atualizada`);
558
+ }
559
+ }
560
+ }
561
+ else {
562
+ // Versão local não atende - verificar Azure
563
+ console.log(` ⚠️ Versão local (${localPkg.version}) não atende requisito (${requiredVersion})`);
564
+ const existsInAzure = this.checkIfExistsInAzure(depName);
565
+ if (existsInAzure) {
566
+ console.log(` 🔄 Instalando ${depName}@${requiredVersion} do Azure DevOps...`);
567
+ if (this.installFromAzure(depName, requiredVersion)) {
568
+ appliedCount++;
569
+ console.log(` ✅ Instalado do Azure: ${depName}@${requiredVersion}`);
570
+ }
571
+ else {
572
+ skippedCount++;
573
+ console.log(` ❌ Falha ao instalar do Azure`);
574
+ }
575
+ }
576
+ else {
577
+ skippedCount++;
578
+ console.log(` ❌ Versão não disponível (nem local, nem Azure)`);
579
+ }
580
+ }
581
+ }
582
+ else {
583
+ // Não tem versão local - verificar se já está instalado ou buscar no Azure
584
+ if (installedVersion) {
585
+ const installedMeetsRequirement = this.compareVersions(installedVersion, requiredVersion) >= 0;
586
+ if (installedMeetsRequirement) {
587
+ console.log(` ✅ Já está instalado na versão correta (${installedVersion})`);
588
+ alreadyInstalledCount++;
589
+ continue;
590
+ }
591
+ }
592
+ // Buscar no Azure
593
+ const existsInAzure = this.checkIfExistsInAzure(depName);
594
+ if (existsInAzure) {
595
+ console.log(` ☁️ Instalando ${depName}@${requiredVersion} do Azure DevOps...`);
596
+ if (this.installFromAzure(depName, requiredVersion)) {
597
+ appliedCount++;
598
+ console.log(` ✅ Instalado do Azure: ${depName}@${requiredVersion}`);
599
+ }
600
+ else {
601
+ skippedCount++;
602
+ console.log(` ❌ Falha ao instalar do Azure`);
603
+ }
604
+ }
605
+ else {
606
+ if (installedVersion) {
607
+ console.log(` ℹ️ Mantendo versão instalada: ${installedVersion}`);
608
+ alreadyInstalledCount++;
609
+ }
610
+ else {
611
+ skippedCount++;
612
+ console.log(` ❌ Pacote não encontrado (nem local, nem Azure)`);
613
+ console.log(` 💡 Execute 'npm run build' no projeto da dependência`);
614
+ }
615
+ }
616
+ }
617
+ }
618
+ // Registrar este projeto para futuras atualizações automáticas
619
+ this.registerAsWatchableProject(packageJson.name);
620
+ // Resumo final
621
+ console.log('\n' + '═'.repeat(60));
622
+ console.log('📊 RESUMO DA SINCRONIZAÇÃO:');
623
+ console.log(` ✅ Sincronizados: ${appliedCount}`);
624
+ console.log(` ✔️ Já na versão correta: ${alreadyInstalledCount}`);
625
+ console.log(` ❌ Falhas: ${skippedCount}`);
626
+ console.log(` 📦 Total de dependências scoped: ${scopedDeps.length}`);
627
+ if (appliedCount > 0) {
628
+ console.log(`\n🎯 ${appliedCount} pacote(s) sincronizado(s)`);
629
+ }
630
+ if (alreadyInstalledCount > 0) {
631
+ console.log(`✅ ${alreadyInstalledCount} pacote(s) já estavam corretos`);
632
+ }
633
+ if (skippedCount > 0) {
634
+ console.log(`\n⚠️ ${skippedCount} pacote(s) com problema`);
635
+ console.log(' 💡 Verifique sua conexão com o Azure DevOps');
636
+ console.log(' 💡 Tente: npm cache clean --force && npm install');
637
+ }
638
+ if (appliedCount === 0 && skippedCount === 0) {
639
+ console.log('\n✨ Todas as dependências já estão sincronizadas!');
640
+ }
641
+ console.log('═'.repeat(60));
642
+ }
643
+ /**
644
+ * 🔍 Verifica se um pacote existe no Azure DevOps (sem falhar o build)
645
+ */
646
+ checkIfExistsInAzure(packageName) {
647
+ try {
648
+ // Tentar verificar se o pacote existe no registry do Azure
649
+ const result = execSync(`npm view ${packageName} version`, {
650
+ stdio: 'pipe',
651
+ timeout: 10000,
652
+ });
653
+ return result.toString().trim().length > 0;
654
+ }
655
+ catch (error) {
656
+ // Se der erro 404 ou timeout, assume que não existe
657
+ return false;
658
+ }
659
+ }
660
+ /**
661
+ * 🔍 Obtém a versão mais recente disponível no Azure DevOps
662
+ */
663
+ getLatestAzureVersion(packageName) {
664
+ try {
665
+ const result = execSync(`npm view ${packageName} version`, {
666
+ stdio: 'pipe',
667
+ timeout: 15000,
668
+ });
669
+ return result.toString().trim() || null;
670
+ }
671
+ catch (error) {
672
+ return null;
673
+ }
674
+ }
675
+ /**
676
+ * 🔧 Instala um pacote do Azure DevOps
677
+ */
678
+ installFromAzure(packageName, version) {
679
+ const versionSpec = version ? `${packageName}@${version}` : `${packageName}@latest`;
680
+ try {
681
+ // 🔧 Usar --ignore-scripts para evitar erros de postinstall em sub-dependências
682
+ // Também usar --prefer-online para garantir que busca a versão correta do Azure
683
+ console.log(` ℹ️ Instalando com --ignore-scripts para evitar conflitos...`);
684
+ execSync(`npm install ${versionSpec} --prefer-online --ignore-scripts`, {
685
+ stdio: 'inherit',
686
+ cwd: process.cwd(),
687
+ timeout: 180000, // 3 minutos de timeout
688
+ });
689
+ return true;
690
+ }
691
+ catch (error) {
692
+ // Tentar com --force e --ignore-scripts se falhou
693
+ console.log(` 🔄 Tentando com --force --ignore-scripts...`);
694
+ try {
695
+ execSync(`npm install ${versionSpec} --force --ignore-scripts`, {
696
+ stdio: 'inherit',
697
+ cwd: process.cwd(),
698
+ timeout: 180000,
699
+ });
700
+ return true;
701
+ }
702
+ catch (retryError) {
703
+ console.error(` ❌ Falha ao instalar ${versionSpec}`);
704
+ console.log(` 💡 Tente manualmente: npm install ${versionSpec} --force --ignore-scripts`);
705
+ return false;
706
+ }
707
+ }
708
+ }
709
+ compareVersions(v1, v2) {
710
+ const parts1 = v1.split('.').map(Number);
711
+ const parts2 = v2.split('.').map(Number);
712
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
713
+ const a = parts1[i] || 0;
714
+ const b = parts2[i] || 0;
715
+ if (a > b)
716
+ return 1;
717
+ if (a < b)
718
+ return -1;
719
+ }
720
+ return 0;
721
+ }
722
+ applyOverride(packageName, localPkg) {
723
+ const nodeModulesPath = path.join(process.cwd(), 'node_modules', packageName);
724
+ // Verificar se o local ainda existe e é mais recente
725
+ if (!fs.existsSync(localPkg.path))
726
+ return false;
727
+ const localDistPath = path.join(localPkg.path, 'dist');
728
+ if (!fs.existsSync(localDistPath))
729
+ return false;
730
+ // Verificar se já está aplicado e é a mesma versão
731
+ const overrideMarker = path.join(nodeModulesPath, '.local-override.json');
732
+ if (fs.existsSync(overrideMarker)) {
733
+ const existing = JSON.parse(fs.readFileSync(overrideMarker, 'utf8'));
734
+ if (existing.lastBuild >= localPkg.lastBuild) {
735
+ return false; // Já está atualizado
736
+ }
737
+ }
738
+ try {
739
+ // Remove versão atual do node_modules
740
+ if (fs.existsSync(nodeModulesPath)) {
741
+ if (process.platform === 'win32') {
742
+ execSync(`rmdir /s /q "${nodeModulesPath}"`, {
743
+ stdio: 'pipe',
744
+ timeout: 10_000,
745
+ });
746
+ }
747
+ else {
748
+ execSync(`rm -rf "${nodeModulesPath}"`, {
749
+ stdio: 'pipe',
750
+ timeout: 10_000,
751
+ });
752
+ }
753
+ }
754
+ // Cria diretório
755
+ fs.mkdirSync(nodeModulesPath, { recursive: true });
756
+ // Copia arquivos essenciais
757
+ this.copyFiles(localPkg.path, nodeModulesPath);
758
+ // Marca como override
759
+ fs.writeFileSync(overrideMarker, JSON.stringify({
760
+ source: localPkg.path,
761
+ version: localPkg.version,
762
+ lastBuild: localPkg.lastBuild,
763
+ appliedAt: Date.now(),
764
+ buildDetails: localPkg.buildDetails,
765
+ }, null, 2));
766
+ return true;
767
+ }
768
+ catch (error) {
769
+ return false;
770
+ }
771
+ }
772
+ copyFiles(source, destination) {
773
+ // Copiar arquivos essenciais
774
+ const filesToCopy = ['package.json', 'README.md'];
775
+ const dirsToCopy = ['dist'];
776
+ filesToCopy.forEach((file) => {
777
+ const srcFile = path.join(source, file);
778
+ const destFile = path.join(destination, file);
779
+ if (fs.existsSync(srcFile)) {
780
+ fs.copyFileSync(srcFile, destFile);
781
+ }
782
+ });
783
+ dirsToCopy.forEach((dir) => {
784
+ const srcDir = path.join(source, dir);
785
+ const destDir = path.join(destination, dir);
786
+ if (fs.existsSync(srcDir)) {
787
+ try {
788
+ if (process.platform === 'win32') {
789
+ execSync(`xcopy "${srcDir}" "${destDir}" /E /I /Y /Q`, {
790
+ stdio: 'pipe',
791
+ timeout: 15_000,
792
+ });
793
+ }
794
+ else {
795
+ execSync(`cp -r "${srcDir}" "${destDir}"`, {
796
+ stdio: 'pipe',
797
+ timeout: 15_000,
798
+ });
799
+ }
800
+ }
801
+ catch (error) {
802
+ console.warn(`Aviso: Erro ao copiar diretório ${dir}`);
803
+ }
804
+ }
805
+ });
806
+ }
807
+ /**
808
+ * Remove todos os overrides locais (versão melhorada com suporte a pacotes locais)
809
+ */
810
+ remove() {
811
+ console.log('\n🔄 Removendo overrides locais...');
812
+ const nodeModulesPath = path.join(process.cwd(), 'node_modules');
813
+ if (!fs.existsSync(nodeModulesPath)) {
814
+ console.log('📂 Diretório node_modules não encontrado');
815
+ return;
816
+ }
817
+ const packages = fs
818
+ .readdirSync(nodeModulesPath)
819
+ .filter((dir) => dir.startsWith('@'))
820
+ .filter((dir) => fs.existsSync(path.join(nodeModulesPath, dir, '.local-override.json')));
821
+ if (packages.length === 0) {
822
+ console.log('ℹ️ Nenhum override local encontrado');
823
+ return;
824
+ }
825
+ console.log(`🎯 Encontrados ${packages.length} override(s) para remover:`);
826
+ const startTime = Date.now();
827
+ let removedCount = 0;
828
+ const localOnlyPackages = [];
829
+ // Verificar quais pacotes existem apenas localmente
830
+ console.log('\n🔍 Verificando disponibilidade no Azure DevOps...');
831
+ packages.forEach((pkg) => {
832
+ if (this.checkIfExistsInAzure(pkg)) {
833
+ console.log(` ✅ ${pkg} - Disponível no Azure`);
834
+ }
835
+ else {
836
+ localOnlyPackages.push(pkg);
837
+ console.log(` 💡 ${pkg} - Existe APENAS localmente`);
838
+ }
839
+ });
840
+ if (localOnlyPackages.length > 0) {
841
+ console.log(`\n⚠️ ATENÇÃO: ${localOnlyPackages.length} pacote(s) existe(m) APENAS localmente:`);
842
+ localOnlyPackages.forEach((pkg) => {
843
+ console.log(` • ${pkg}`);
844
+ });
845
+ console.log('\n❌ Não é possível remover overrides desses pacotes!');
846
+ console.log('💡 Esses pacotes não estão publicados no Azure DevOps.');
847
+ console.log('💡 Mantenha os overrides locais ou publique-os no Azure primeiro.');
848
+ // Filtrar apenas pacotes que podem ser removidos
849
+ const packagesToRemove = packages.filter((pkg) => !localOnlyPackages.includes(pkg));
850
+ if (packagesToRemove.length === 0) {
851
+ console.log('\n📦 Nenhum pacote pode ser removido (todos são apenas locais).');
852
+ console.log('═'.repeat(60));
853
+ return;
854
+ }
855
+ console.log(`\n🔄 Removendo apenas pacotes disponíveis no Azure (${packagesToRemove.length})...`);
856
+ }
857
+ else {
858
+ const packagesToRemove = packages;
859
+ }
860
+ const packagesToRemove = packages.filter((pkg) => !localOnlyPackages.includes(pkg));
861
+ packagesToRemove.forEach((pkg) => {
862
+ const pkgPath = path.join(nodeModulesPath, pkg);
863
+ console.log(` 🗑️ Removendo ${pkg}...`);
864
+ try {
865
+ if (process.platform === 'win32') {
866
+ execSync(`rmdir /s /q "${pkgPath}"`, { stdio: 'pipe', timeout: 5000 });
867
+ }
868
+ else {
869
+ execSync(`rm -rf "${pkgPath}"`, { stdio: 'pipe', timeout: 5000 });
870
+ }
871
+ removedCount++;
872
+ console.log(' ✅ Removido com sucesso');
873
+ }
874
+ catch (error) {
875
+ console.log(` ⚠️ Erro ao remover: ${pkg}`);
876
+ }
877
+ });
878
+ if (removedCount > 0) {
879
+ console.log(`\n📦 Reinstalando ${removedCount} dependência(s) do Azure DevOps...`);
880
+ const installStart = Date.now();
881
+ try {
882
+ // Instalar apenas os pacotes que foram removidos (que existem no Azure)
883
+ const packagesToInstall = packagesToRemove.join(' ');
884
+ execSync(`npm install ${packagesToInstall} --force`, {
885
+ stdio: 'inherit',
886
+ });
887
+ const installTime = Date.now() - installStart;
888
+ console.log('\n✅ Processo concluído com sucesso!');
889
+ console.log('📊 Resumo:');
890
+ console.log(` • Overrides removidos: ${removedCount}`);
891
+ console.log(` • Mantidos (apenas local): ${localOnlyPackages.length}`);
892
+ console.log(` • Tempo de remoção: ${this.formatDuration(Date.now() - startTime)}`);
893
+ console.log(` • Tempo de reinstalação: ${this.formatDuration(installTime)}`);
894
+ console.log(' • Pacotes do Azure reinstalados com sucesso');
895
+ if (localOnlyPackages.length > 0) {
896
+ console.log('\n💡 Pacotes mantidos localmente:');
897
+ localOnlyPackages.forEach((pkg) => {
898
+ console.log(` • ${pkg} - Não disponível no Azure`);
899
+ });
900
+ }
901
+ }
902
+ catch (error) {
903
+ console.log(`❌ Erro durante reinstalação: ${error}`);
904
+ console.log('💡 Alguns pacotes podem não existir no Azure DevOps.');
905
+ console.log(` Execute 'npm install' manualmente para resolver.`);
906
+ }
907
+ }
908
+ else {
909
+ console.log('\n⚠️ Nenhum pacote foi removido.');
910
+ console.log('📦 Todos os pacotes com override existem apenas localmente.');
911
+ }
912
+ console.log('═'.repeat(60));
913
+ }
914
+ /**
915
+ * Mostra status dos overrides (versão melhorada)
916
+ */
917
+ status() {
918
+ console.log('\n📊 STATUS DAS DEPENDÊNCIAS SCOPED (@):');
919
+ console.log('═'.repeat(70));
920
+ const nodeModulesPath = path.join(process.cwd(), 'node_modules');
921
+ if (!fs.existsSync(nodeModulesPath)) {
922
+ console.log('📂 Diretório node_modules não encontrado');
923
+ return;
924
+ }
925
+ const packages = fs
926
+ .readdirSync(nodeModulesPath)
927
+ .filter((dir) => dir.startsWith('@'));
928
+ if (packages.length === 0) {
929
+ console.log('📦 Nenhuma dependência scoped (@) encontrada');
930
+ return;
931
+ }
932
+ let localCount = 0;
933
+ let azureCount = 0;
934
+ let autoUpdatedCount = 0;
935
+ packages.forEach((pkg) => {
936
+ const pkgPath = path.join(nodeModulesPath, pkg);
937
+ const overrideFile = path.join(pkgPath, '.local-override.json');
938
+ if (fs.existsSync(overrideFile)) {
939
+ localCount++;
940
+ try {
941
+ const override = JSON.parse(fs.readFileSync(overrideFile, 'utf8'));
942
+ const age = Math.round((Date.now() - override.appliedAt) / 1000 / 60);
943
+ const autoApplied = override.autoApplied ? ' (AUTO)' : '';
944
+ if (override.autoApplied)
945
+ autoUpdatedCount++;
946
+ console.log(`🔗 ${pkg}@${override.version} (LOCAL${autoApplied})`);
947
+ console.log(` 📅 Aplicado há ${age} minuto(s)`);
948
+ if (override.buildDetails) {
949
+ console.log(` 📊 Build: ${override.buildDetails.buildSize}, ${override.buildDetails.compiledFiles} arquivos`);
950
+ console.log(` 🕐 Compilado: ${new Date(override.buildDetails.timestamp).toLocaleString('pt-BR')}`);
951
+ }
952
+ console.log(` 📂 Origem: ${override.source}`);
953
+ if (override.autoApplied) {
954
+ console.log(' 🤖 Atualização automática ativada');
955
+ }
956
+ }
957
+ catch {
958
+ console.log(`🔗 ${pkg} (LOCAL - erro ao ler detalhes)`);
959
+ }
960
+ console.log('');
961
+ }
962
+ else {
963
+ azureCount++;
964
+ const packageJsonPath = path.join(pkgPath, 'package.json');
965
+ if (fs.existsSync(packageJsonPath)) {
966
+ try {
967
+ const pkgJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
968
+ console.log(`☁️ ${pkg}@${pkgJson.version} (AZURE DEVOPS)`);
969
+ }
970
+ catch {
971
+ console.log(`☁️ ${pkg} (AZURE DEVOPS - erro ao ler versão)`);
972
+ }
973
+ }
974
+ }
975
+ });
976
+ console.log('═'.repeat(70));
977
+ console.log('📋 RESUMO:');
978
+ console.log(` 🔗 Dependências locais: ${localCount}`);
979
+ console.log(` 🤖 Atualizações automáticas: ${autoUpdatedCount}`);
980
+ console.log(` ☁️ Dependências Azure: ${azureCount}`);
981
+ console.log(` 📦 Total: ${packages.length}`);
982
+ if (localCount > 0) {
983
+ console.log('\n💡 DICAS:');
984
+ console.log(` • Use 'smart-override remove' para voltar às versões do Azure`);
985
+ console.log(' • Dependências com (AUTO) são atualizadas automaticamente');
986
+ console.log(' • Builds locais têm prioridade sobre versões do registry');
987
+ }
988
+ console.log('═'.repeat(70));
989
+ }
990
+ /**
991
+ * Atualiza o registry local com a versão atual do package.json
992
+ */
993
+ updateLocalRegistry() {
994
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
995
+ if (!fs.existsSync(packageJsonPath)) {
996
+ console.log('⚠️ package.json não encontrado');
997
+ return;
998
+ }
999
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
1000
+ const registry = this.getLocalRegistry();
1001
+ // Verificar se é um pacote scoped (@org/nome)
1002
+ if (!isScopedPackage(packageJson.name)) {
1003
+ console.log('⚠️ Este não é um pacote scoped (@org/nome)');
1004
+ return;
1005
+ }
1006
+ const distPath = path.join(process.cwd(), 'dist');
1007
+ const hasDistFolder = fs.existsSync(distPath);
1008
+ // Atualizar ou criar entrada no registry
1009
+ const existingEntry = registry[packageJson.name];
1010
+ registry[packageJson.name] = {
1011
+ name: packageJson.name,
1012
+ version: packageJson.version,
1013
+ path: process.cwd(),
1014
+ lastBuild: existingEntry?.lastBuild || Date.now(),
1015
+ buildDuration: existingEntry?.buildDuration,
1016
+ buildDetails: existingEntry?.buildDetails || {
1017
+ compiledFiles: hasDistFolder ? this.countCompiledFiles(distPath) : 0,
1018
+ buildSize: hasDistFolder
1019
+ ? this.formatSize(this.calculateDirectorySize(distPath))
1020
+ : '0 KB',
1021
+ nodeVersion: process.version,
1022
+ timestamp: new Date().toISOString(),
1023
+ },
1024
+ };
1025
+ this.saveLocalRegistry(registry);
1026
+ console.log(`✅ Registry local atualizado: ${packageJson.name}@${packageJson.version}`);
1027
+ }
1028
+ /**
1029
+ * Comando para sincronizar manualmente todos os projetos
1030
+ * Agora também instala do Azure DevOps quando necessário
1031
+ */
1032
+ sync() {
1033
+ console.log('\n🔄 SINCRONIZAÇÃO MANUAL DE PROJETOS:');
1034
+ console.log('═'.repeat(70));
1035
+ // Primeiro, atualizar o registry local com a versão atual
1036
+ this.updateLocalRegistry();
1037
+ console.log(); // linha em branco
1038
+ // Verificar dependências do projeto ATUAL primeiro
1039
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
1040
+ if (fs.existsSync(packageJsonPath)) {
1041
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
1042
+ const dependencies = {
1043
+ ...packageJson.dependencies,
1044
+ ...packageJson.devDependencies,
1045
+ };
1046
+ const scopedDeps = Object.keys(dependencies).filter((dep) => isScopedPackage(dep));
1047
+ if (scopedDeps.length > 0) {
1048
+ console.log(`📦 Sincronizando dependências do projeto atual: ${packageJson.name}`);
1049
+ console.log(`🎯 Dependências scoped encontradas: ${scopedDeps.length}`);
1050
+ console.log();
1051
+ let installedFromAzure = 0;
1052
+ let localApplied = 0;
1053
+ let upToDate = 0;
1054
+ let failed = 0;
1055
+ const localRegistry = this.getLocalRegistry();
1056
+ for (const depName of scopedDeps) {
1057
+ const requiredVersion = dependencies[depName].replace(/[\^~]/, '');
1058
+ console.log(`\n 📋 ${depName}@${requiredVersion}`);
1059
+ // Verificar versão instalada atualmente
1060
+ const nodeModulesPath = path.join(process.cwd(), 'node_modules', depName);
1061
+ let installedVersion = null;
1062
+ let hasLocalOverride = false;
1063
+ if (fs.existsSync(nodeModulesPath)) {
1064
+ const depPkgPath = path.join(nodeModulesPath, 'package.json');
1065
+ const overrideMarker = path.join(nodeModulesPath, '.local-override.json');
1066
+ if (fs.existsSync(depPkgPath)) {
1067
+ try {
1068
+ const depPkg = JSON.parse(fs.readFileSync(depPkgPath, 'utf8'));
1069
+ installedVersion = depPkg.version;
1070
+ }
1071
+ catch (parseError) {
1072
+ console.log(` ⚠️ Erro ao ler package.json (arquivo corrompido ou com conflitos de merge)`);
1073
+ console.log(` 💡 Tente: rm -rf node_modules/${depName} && npm install`);
1074
+ }
1075
+ }
1076
+ hasLocalOverride = fs.existsSync(overrideMarker);
1077
+ }
1078
+ // Verificar se o pacote prefere Azure
1079
+ const prefersAzure = PREFER_AZURE_PACKAGES.has(depName);
1080
+ // Obter versão mais recente do Azure
1081
+ console.log(` 🔍 Verificando Azure DevOps...`);
1082
+ const azureVersion = this.getLatestAzureVersion(depName);
1083
+ if (azureVersion) {
1084
+ console.log(` ☁️ Versão Azure: ${azureVersion}`);
1085
+ if (installedVersion) {
1086
+ console.log(` 📦 Versão instalada: ${installedVersion}${hasLocalOverride ? ' (LOCAL)' : ''}`);
1087
+ }
1088
+ // Comparar versões
1089
+ const azureIsNewer = installedVersion
1090
+ ? this.compareVersions(azureVersion, installedVersion) > 0
1091
+ : true;
1092
+ const azureMatchesRequired = this.compareVersions(azureVersion, requiredVersion) >= 0;
1093
+ // Lógica de decisão
1094
+ if (prefersAzure || azureIsNewer) {
1095
+ if (azureMatchesRequired) {
1096
+ if (!installedVersion || azureIsNewer) {
1097
+ console.log(` ⬆️ Nova versão disponível no Azure!`);
1098
+ // Remover override local se existir
1099
+ if (hasLocalOverride) {
1100
+ console.log(` 🗑️ Removendo override local...`);
1101
+ try {
1102
+ if (process.platform === 'win32') {
1103
+ execSync(`rmdir /s /q "${nodeModulesPath}"`, { stdio: 'pipe', timeout: 10000 });
1104
+ }
1105
+ else {
1106
+ execSync(`rm -rf "${nodeModulesPath}"`, { stdio: 'pipe', timeout: 10000 });
1107
+ }
1108
+ }
1109
+ catch (e) {
1110
+ // Ignorar erro de remoção
1111
+ }
1112
+ }
1113
+ // Instalar do Azure
1114
+ if (this.installFromAzure(depName, azureVersion)) {
1115
+ installedFromAzure++;
1116
+ }
1117
+ else {
1118
+ failed++;
1119
+ }
1120
+ }
1121
+ else {
1122
+ console.log(` ✅ Já está na versão mais recente do Azure`);
1123
+ upToDate++;
1124
+ }
1125
+ }
1126
+ else {
1127
+ console.log(` ⚠️ Versão Azure (${azureVersion}) não atende requisito (${requiredVersion})`);
1128
+ // Verificar se há versão local compatível
1129
+ if (localRegistry[depName]) {
1130
+ const localPkg = localRegistry[depName];
1131
+ if (this.compareVersions(localPkg.version, requiredVersion) >= 0) {
1132
+ console.log(` 💡 Usando versão local: ${localPkg.version}`);
1133
+ if (this.applyOverride(depName, localPkg)) {
1134
+ localApplied++;
1135
+ }
1136
+ else {
1137
+ upToDate++;
1138
+ }
1139
+ }
1140
+ else {
1141
+ console.log(` ❌ Nenhuma versão compatível disponível`);
1142
+ failed++;
1143
+ }
1144
+ }
1145
+ else {
1146
+ console.log(` ❌ Nenhuma versão local disponível`);
1147
+ failed++;
1148
+ }
1149
+ }
1150
+ }
1151
+ else if (!prefersAzure && localRegistry[depName]) {
1152
+ // Pacote não prefere Azure e tem versão local
1153
+ const localPkg = localRegistry[depName];
1154
+ const localVersion = localPkg.version;
1155
+ console.log(` 🔗 Versão local disponível: ${localVersion}`);
1156
+ if (this.compareVersions(localVersion, requiredVersion) >= 0) {
1157
+ if (this.applyOverride(depName, localPkg)) {
1158
+ console.log(` ✅ Override local aplicado`);
1159
+ localApplied++;
1160
+ }
1161
+ else {
1162
+ console.log(` ℹ️ Override local já está atualizado`);
1163
+ upToDate++;
1164
+ }
1165
+ }
1166
+ else {
1167
+ // Versão local desatualizada, instalar do Azure
1168
+ console.log(` ⚠️ Versão local desatualizada, instalando do Azure...`);
1169
+ if (this.installFromAzure(depName, azureVersion)) {
1170
+ installedFromAzure++;
1171
+ }
1172
+ else {
1173
+ failed++;
1174
+ }
1175
+ }
1176
+ }
1177
+ else {
1178
+ // Não tem versão local e Azure está ok
1179
+ if (!installedVersion || azureIsNewer) {
1180
+ if (this.installFromAzure(depName, azureVersion)) {
1181
+ installedFromAzure++;
1182
+ }
1183
+ else {
1184
+ failed++;
1185
+ }
1186
+ }
1187
+ else {
1188
+ upToDate++;
1189
+ }
1190
+ }
1191
+ }
1192
+ else {
1193
+ console.log(` ⚠️ Não encontrado no Azure DevOps`);
1194
+ // Tentar usar versão local
1195
+ if (localRegistry[depName]) {
1196
+ const localPkg = localRegistry[depName];
1197
+ console.log(` 💡 Usando versão local: ${localPkg.version}`);
1198
+ if (this.compareVersions(localPkg.version, requiredVersion) >= 0) {
1199
+ if (this.applyOverride(depName, localPkg)) {
1200
+ localApplied++;
1201
+ }
1202
+ else {
1203
+ upToDate++;
1204
+ }
1205
+ }
1206
+ else {
1207
+ console.log(` ❌ Versão local incompatível`);
1208
+ failed++;
1209
+ }
1210
+ }
1211
+ else if (installedVersion) {
1212
+ console.log(` ℹ️ Mantendo versão instalada: ${installedVersion}`);
1213
+ upToDate++;
1214
+ }
1215
+ else {
1216
+ console.log(` ❌ Pacote não encontrado (nem Azure, nem local)`);
1217
+ failed++;
1218
+ }
1219
+ }
1220
+ }
1221
+ // Resumo do projeto atual
1222
+ console.log('\n' + '═'.repeat(70));
1223
+ console.log('📊 RESUMO DA SINCRONIZAÇÃO:');
1224
+ console.log(` ☁️ Instalados do Azure: ${installedFromAzure}`);
1225
+ console.log(` 🔗 Overrides locais aplicados: ${localApplied}`);
1226
+ console.log(` ✅ Já atualizados: ${upToDate}`);
1227
+ console.log(` ❌ Falhas: ${failed}`);
1228
+ console.log(` 📦 Total de dependências scoped: ${scopedDeps.length}`);
1229
+ console.log(` 🕐 Concluído em: ${new Date().toLocaleString('pt-BR')}`);
1230
+ if (failed > 0) {
1231
+ console.log('\n⚠️ AÇÕES RECOMENDADAS PARA FALHAS:');
1232
+ console.log(' 1. Verifique sua conexão com o Azure DevOps');
1233
+ console.log(' 2. Execute: npm cache clean --force');
1234
+ console.log(' 3. Tente: npm install --force');
1235
+ console.log(' 4. Verifique o arquivo .npmrc para configurações de registry');
1236
+ }
1237
+ if (installedFromAzure > 0) {
1238
+ console.log('\n✨ Pacotes atualizados do Azure DevOps com sucesso!');
1239
+ }
1240
+ console.log('═'.repeat(70));
1241
+ return;
1242
+ }
1243
+ }
1244
+ // Fallback: comportamento antigo para projetos registrados
1245
+ const watchRegistry = this.getWatchRegistry();
1246
+ const localRegistry = this.getLocalRegistry();
1247
+ if (Object.keys(watchRegistry).length === 0) {
1248
+ console.log('📂 Nenhum projeto registrado para sincronização');
1249
+ console.log('💡 Execute npm run build em alguns projetos primeiro');
1250
+ return;
1251
+ }
1252
+ console.log(`🎯 Projetos registrados: ${Object.keys(watchRegistry).length}`);
1253
+ console.log(`📦 Pacotes locais disponíveis: ${Object.keys(localRegistry).length}`);
1254
+ let totalUpdated = 0;
1255
+ // Para cada projeto registrado
1256
+ Object.values(watchRegistry).forEach((project) => {
1257
+ console.log(`\n📋 Verificando ${project.name}...`);
1258
+ let projectUpdated = 0;
1259
+ // Para cada dependência scoped do projeto
1260
+ Object.keys(project.dependencies).forEach((depName) => {
1261
+ if (localRegistry[depName]) {
1262
+ const localPkg = localRegistry[depName];
1263
+ const requiredVersion = project.dependencies[depName].replace(/[\^~]/, '');
1264
+ const versionComparison = this.compareVersions(localPkg.version, requiredVersion);
1265
+ if (versionComparison >= 0) {
1266
+ if (this.applyOverrideToProject(project, depName, localPkg)) {
1267
+ console.log(` ✅ ${depName}@${localPkg.version} aplicado`);
1268
+ projectUpdated++;
1269
+ totalUpdated++;
1270
+ }
1271
+ else {
1272
+ console.log(` ℹ️ ${depName}@${localPkg.version} já atualizado`);
1273
+ }
1274
+ }
1275
+ else {
1276
+ console.log(` ⚠️ ${depName}: local v${localPkg.version} < required v${requiredVersion}`);
1277
+ }
1278
+ }
1279
+ });
1280
+ if (projectUpdated === 0) {
1281
+ console.log(' 📦 Nenhuma atualização necessária');
1282
+ }
1283
+ });
1284
+ console.log('\n' + '═'.repeat(70));
1285
+ console.log('📊 RESUMO DA SINCRONIZAÇÃO:');
1286
+ console.log(` 🔄 Projetos verificados: ${Object.keys(watchRegistry).length}`);
1287
+ console.log(` ✅ Atualizações aplicadas: ${totalUpdated}`);
1288
+ console.log(` 🕐 Concluído em: ${new Date().toLocaleString('pt-BR')}`);
1289
+ console.log('═'.repeat(70));
1290
+ }
1291
+ }
1292
+ // CLI
1293
+ const command = process.argv[2];
1294
+ const override = new SmartOverride();
1295
+ switch (command) {
1296
+ case 'register':
1297
+ override.register();
1298
+ break;
1299
+ case 'check':
1300
+ override.check();
1301
+ break;
1302
+ case 'remove':
1303
+ override.remove();
1304
+ break;
1305
+ case 'status':
1306
+ override.status();
1307
+ break;
1308
+ case 'sync':
1309
+ await (async () => {
1310
+ await override.sync();
1311
+ try {
1312
+ // Atualizar package-lock.json imediatamente para evitar inconsistências
1313
+ console.log('\n🔄 Atualizando package-lock.json (npm install --package-lock-only) ...');
1314
+ execSync('npm install --package-lock-only', { stdio: 'inherit', timeout: 120_000 });
1315
+ console.log('✅ package-lock.json atualizado com sucesso');
1316
+ }
1317
+ catch (err) {
1318
+ console.warn('⚠️ Falha ao atualizar package-lock.json automaticamente:', err?.message || err);
1319
+ console.log('💡 Você pode atualizar manualmente executando: npm install --package-lock-only');
1320
+ }
1321
+ })();
1322
+ break;
1323
+ default:
1324
+ console.log('\n📖 USO DO SMART OVERRIDE:');
1325
+ console.log('═'.repeat(60));
1326
+ console.log('npx autocore-sync check - Sincroniza dependências scoped (@)');
1327
+ console.log('npx autocore-sync status - Mostra status das dependências');
1328
+ console.log('npx autocore-sync remove - Remove overrides locais');
1329
+ console.log('npx autocore-sync sync - Sincroniza todos os projetos');
1330
+ console.log('═'.repeat(60));
1331
+ console.log('\n💡 COMANDO RECOMENDADO NO package.json:');
1332
+ console.log('');
1333
+ console.log(' "sync": "npx autocore-sync-configs && npx autocore-sync check"');
1334
+ console.log('');
1335
+ console.log('═'.repeat(60));
1336
+ console.log('\n🎯 COMANDOS PARA USUÁRIOS:');
1337
+ console.log('');
1338
+ console.log('📦 Para sincronizar dependências:');
1339
+ console.log(' npm run sync - Sincroniza configs e dependências');
1340
+ console.log(' npx autocore-sync check - Sincroniza dependências scoped (@)');
1341
+ console.log(' npx autocore-sync status - Mostra dependências atuais');
1342
+ console.log('');
1343
+ console.log('🔧 COMANDOS DE MANUTENÇÃO:');
1344
+ console.log(' npx autocore-sync remove - Remove overrides locais');
1345
+ console.log(' npm install --force - Reinstala dependências limpas');
1346
+ console.log('');
1347
+ console.log('═'.repeat(60));
1348
+ console.log('\n🚀 EXEMPLOS DE USO:');
1349
+ console.log('');
1350
+ console.log('# Sincronizar tudo (configurações + dependências):');
1351
+ console.log('npm run sync');
1352
+ console.log('');
1353
+ console.log('# Ver status das dependências:');
1354
+ console.log('npx autocore-sync status');
1355
+ console.log('');
1356
+ console.log('# Voltar para versões do Azure DevOps:');
1357
+ console.log('npx autocore-sync remove');
1358
+ console.log('');
1359
+ console.log('═'.repeat(60));
1360
+ }