@mocoto/mahoraga 0.14.1 → 0.14.3

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 (306) hide show
  1. package/README.md +0 -34
  2. package/dist/analysts/architects/analyst-structure.js +20 -20
  3. package/dist/analysts/architects/archetypes-custom.js +16 -19
  4. package/dist/analysts/architects/detector-archetypes.js +43 -36
  5. package/dist/analysts/architects/orchestrator-archetypes.js +3 -3
  6. package/dist/analysts/architects/signals-project-advanced.js +26 -28
  7. package/dist/analysts/architects/signals-project.js +2 -2
  8. package/dist/analysts/architects/strategist-structure.js +47 -66
  9. package/dist/analysts/azure-pipelines/analysts/analyst-azure.js +41 -35
  10. package/dist/analysts/azure-pipelines/corrections/correction-azure.js +22 -19
  11. package/dist/analysts/azure-pipelines/detectors/detector-azure-performance.js +21 -18
  12. package/dist/analysts/azure-pipelines/detectors/detector-azure-security.js +25 -20
  13. package/dist/analysts/azure-pipelines/detectors/detector-azure-structure.js +39 -40
  14. package/dist/analysts/azure-pipelines/scorers/scorer-azure.js +10 -7
  15. package/dist/analysts/circleci/analysts/analyst-circleci.js +33 -27
  16. package/dist/analysts/circleci/corrections/correction-circleci.js +22 -20
  17. package/dist/analysts/circleci/detectors/detector-circleci-performance.js +23 -19
  18. package/dist/analysts/circleci/detectors/detector-circleci-security.js +78 -82
  19. package/dist/analysts/circleci/detectors/detector-circleci-structure.js +22 -22
  20. package/dist/analysts/converters/convert-registry.js +1 -1
  21. package/dist/analysts/converters/engines/converter-gha-to-gitlab.js +17 -15
  22. package/dist/analysts/converters/index.js +1 -1
  23. package/dist/analysts/corrections/analyst-quick-fixes.js +25 -28
  24. package/dist/analysts/corrections/analyst-scoring.js +24 -21
  25. package/dist/analysts/corrections/auto-fix-engine.js +1 -1
  26. package/dist/analysts/corrections/corrector-structure.js +43 -42
  27. package/dist/analysts/corrections/fix-alias-imports.js +10 -6
  28. package/dist/analysts/corrections/fix-md-fences.js +23 -23
  29. package/dist/analysts/corrections/map-reversion.js +56 -53
  30. package/dist/analysts/corrections/pruning.js +19 -16
  31. package/dist/analysts/corrections/quick-fixes/fix-any-to-proper-type.js +57 -61
  32. package/dist/analysts/corrections/quick-fixes/fix-unknown-to-specific-type.js +30 -30
  33. package/dist/analysts/corrections/reorganize-barrels.js +13 -13
  34. package/dist/analysts/corrections/rewrite-testes-aliases.js +23 -22
  35. package/dist/analysts/corrections/scoring-shared.js +19 -18
  36. package/dist/analysts/corrections/type-safety/context-analyzer.js +15 -10
  37. package/dist/analysts/corrections/type-safety/type-analyzer.js +3 -3
  38. package/dist/analysts/corrections/type-safety/type-validator.js +4 -3
  39. package/dist/analysts/corrections/type-safety/usage-analyzer.js +39 -42
  40. package/dist/analysts/css/analysts/analyst-css.js +42 -42
  41. package/dist/analysts/css/corrections/correction-css.js +19 -11
  42. package/dist/analysts/css/detectors/detector-css-best-practices.js +129 -118
  43. package/dist/analysts/css/scorers/scorer-css.js +23 -18
  44. package/dist/analysts/css-in-js/analysts/analyst-css-in-js.js +24 -17
  45. package/dist/analysts/css-in-js/corrections/correction-css-in-js.js +31 -16
  46. package/dist/analysts/css-in-js/detectors/detector-css-in-js-best-practices.js +28 -30
  47. package/dist/analysts/css-in-js/scorers/scorer-css-in-js.js +79 -54
  48. package/dist/analysts/css-in-js/shared.js +7 -0
  49. package/dist/analysts/detectors/detector-architecture.js +91 -85
  50. package/dist/analysts/detectors/detector-bugs-ml.js +29 -27
  51. package/dist/analysts/detectors/detector-code-fragile.js +41 -36
  52. package/dist/analysts/detectors/detector-dependencies.js +5 -5
  53. package/dist/analysts/detectors/detector-duplications.js +26 -26
  54. package/dist/analysts/detectors/detector-monorepo.js +51 -45
  55. package/dist/analysts/detectors/detector-performance.js +24 -17
  56. package/dist/analysts/detectors/detector-recommendation-architecture.js +40 -36
  57. package/dist/analysts/detectors/detector-security.js +43 -42
  58. package/dist/analysts/detectors/detector-structure.js +31 -28
  59. package/dist/analysts/github-actions/analysts/analyst-github-actions.js +5 -8
  60. package/dist/analysts/github-actions/detectors/detector-workflow-accessibility.js +1 -9
  61. package/dist/analysts/github-actions/detectors/detector-workflow-structure.js +1 -4
  62. package/dist/analysts/github-actions/detectors/detector-workflow-trigger-unsafe.js +6 -5
  63. package/dist/analysts/gitlab-ci/analysts/analyst-gitlab-ci.js +2 -2
  64. package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.js +0 -3
  65. package/dist/analysts/go/analysts/analyst-best-practices.js +2 -2
  66. package/dist/analysts/go/analysts/analyst-concurrency.js +1 -1
  67. package/dist/analysts/go/analysts/analyst-security.js +1 -1
  68. package/dist/analysts/go/detectors/detector-conventions.js +1 -1
  69. package/dist/analysts/html/analysts/analyst-html.js +10 -12
  70. package/dist/analysts/html/detectors/detector-html.js +3 -3
  71. package/dist/analysts/js-ts/analysts/analyst-commands-cli.js +22 -22
  72. package/dist/analysts/js-ts/analysts/analyst-functions-long.js +5 -5
  73. package/dist/analysts/js-ts/analysts/analyst-patterns-usage.js +6 -2
  74. package/dist/analysts/js-ts/detectors/detector-anti-patterns-async.js +84 -9
  75. package/dist/analysts/js-ts/detectors/detector-constructions-syntactic.js +33 -10
  76. package/dist/analysts/js-ts/detectors/detector-context-smart.js +6 -6
  77. package/dist/analysts/js-ts/detectors/detector-leaks-memory.js +1 -1
  78. package/dist/analysts/js-ts/detectors/detector-types-unsafe.js +33 -2
  79. package/dist/analysts/php/analysts/analyst-php.js +3 -3
  80. package/dist/analysts/php/detectors/detector-php-best-practices.js +5 -5
  81. package/dist/analysts/php/detectors/detector-php-security.js +5 -5
  82. package/dist/analysts/php/scorers/scorer-php.js +2 -2
  83. package/dist/analysts/plugins/detector-documentation.js +6 -6
  84. package/dist/analysts/plugins/detector-markdown.js +7 -7
  85. package/dist/analysts/python/analysts/analyst-python.js +2 -5
  86. package/dist/analysts/react/analysts/analyst-react-hooks.js +66 -9
  87. package/dist/analysts/react/analysts/analyst-react.js +46 -2
  88. package/dist/analysts/react/corrections/correction-react.js +41 -1
  89. package/dist/analysts/react/detectors/detector-react-best-practices.js +5 -5
  90. package/dist/analysts/react/scorers/scorer-react.js +36 -1
  91. package/dist/analysts/registry/autodiscovery.js +2 -2
  92. package/dist/analysts/rust/analysts/analyst-best-practices.js +42 -3
  93. package/dist/analysts/rust/analysts/analyst-memory.js +2 -2
  94. package/dist/analysts/rust/analysts/analyst-rust.js +52 -5
  95. package/dist/analysts/rust/analysts/analyst-security.js +29 -1
  96. package/dist/analysts/scorers/scorer.js +5 -5
  97. package/dist/analysts/shell/analysts/analyst-shell.js +81 -5
  98. package/dist/analysts/shell/corrections/correction-shell.js +34 -1
  99. package/dist/analysts/shell/detectors/detector-shell-security.js +88 -0
  100. package/dist/analysts/shell/scorers/scorer-shell.js +58 -1
  101. package/dist/analysts/strategists/operator-structure.js +5 -7
  102. package/dist/analysts/strategists/suggestions-contextuais.js +5 -2
  103. package/dist/analysts/svg/analysts/analyst-svg.js +1 -0
  104. package/dist/analysts/tailwind/analysts/analyst-tailwind.js +79 -55
  105. package/dist/analysts/tailwind/corrections/correction-tailwind.js +108 -9
  106. package/dist/analysts/tailwind/detectors/detector-tailwind-best-practices.js +122 -7
  107. package/dist/analysts/tailwind/scorers/scorer-tailwind.js +62 -11
  108. package/dist/analysts/xml/analysts/analyst-xml.js +2 -2
  109. package/dist/app/index.js +1 -0
  110. package/dist/bin/cli-bootstrap.js +6 -4
  111. package/dist/bin/index.js +6 -4
  112. package/dist/caretakers/scoring.js +1 -0
  113. package/dist/cli/commands/command-analysts.js +4 -3
  114. package/dist/cli/commands/command-azure.js +1 -1
  115. package/dist/cli/commands/command-circleci.js +1 -1
  116. package/dist/cli/commands/command-compliance.js +1 -1
  117. package/dist/cli/commands/command-diagnose.js +10 -13
  118. package/dist/cli/commands/command-fix-types.js +9 -32
  119. package/dist/cli/commands/command-formatters.js +2 -2
  120. package/dist/cli/commands/command-github-actions.js +1 -1
  121. package/dist/cli/commands/command-gitlab-ci.js +1 -1
  122. package/dist/cli/commands/command-guardian.js +1 -1
  123. package/dist/cli/commands/command-imports.js +6 -6
  124. package/dist/cli/commands/command-jenkins.js +1 -1
  125. package/dist/cli/commands/command-licenses.js +1 -1
  126. package/dist/cli/commands/command-marketplace.js +7 -7
  127. package/dist/cli/commands/command-names.js +3 -8
  128. package/dist/cli/commands/command-perf.js +7 -9
  129. package/dist/cli/commands/command-plugins.js +4 -4
  130. package/dist/cli/diagnostic/auto-fix.js +2 -2
  131. package/dist/cli/diagnostic/exporters/json-exporter.js +1 -1
  132. package/dist/cli/diagnostic/exporters/sharded-exporter.js +0 -3
  133. package/dist/cli/diagnostic/exporters/svg-optimization-exporter.js +1 -1
  134. package/dist/cli/diagnostic/filters.js +9 -9
  135. package/dist/cli/diagnostic/handlers/archetype-handler.js +3 -6
  136. package/dist/cli/diagnostic/handlers/auto-fix-handler.js +4 -4
  137. package/dist/cli/diagnostic/handlers/guardian-handler.js +1 -1
  138. package/dist/cli/diagnostic/processing-diagnostic.js +31 -35
  139. package/dist/cli/diagnostic/processing-helpers.js +2 -2
  140. package/dist/cli/handlers/fix-types-exporter.js +1 -4
  141. package/dist/cli/helpers/display-frame.js +5 -5
  142. package/dist/core/config/auto/auto-fix-config.js +0 -6
  143. package/dist/core/config/chalk-safe.js +6 -6
  144. package/dist/core/config/config.js +11 -13
  145. package/dist/core/config/conventions.js +1 -1
  146. package/dist/core/config/security.js +2 -2
  147. package/dist/core/execution/analysis-cache.js +5 -8
  148. package/dist/core/execution/ast-cache.js +1 -3
  149. package/dist/core/execution/executor.js +8 -21
  150. package/dist/core/execution/inquisitor.js +24 -21
  151. package/dist/core/execution/results.js +1 -0
  152. package/dist/core/execution/scanner.js +4 -4
  153. package/dist/core/messages/en/analysts/analyst-github-actions-messages.js +1 -1
  154. package/dist/core/messages/en/analysts/analyst-patterns-usage-messages.js +1 -0
  155. package/dist/core/messages/en/analysts/analyst-shell-messages.js +15 -0
  156. package/dist/core/messages/en/analysts/detector-constructions-syntactic-messages.js +6 -0
  157. package/dist/core/messages/en/analysts/detector-js-ts-messages.js +27 -0
  158. package/dist/core/messages/en/analysts/detector-react-messages.js +8 -0
  159. package/dist/core/messages/en/analysts/detector-shell-messages.js +17 -0
  160. package/dist/core/messages/en/analysts/detector-tailwind-messages.js +3 -3
  161. package/dist/core/messages/en/analysts/report-circleci-messages.js +7 -7
  162. package/dist/core/messages/en/caretakers/caretaker-messages.js +1 -7
  163. package/dist/core/messages/en/core/plugin-messages.js +31 -3
  164. package/dist/core/messages/en/log/log.js +4 -4
  165. package/dist/core/messages/en/ui/filter-config.js +1 -5
  166. package/dist/core/messages/i18n-system.js +3 -3
  167. package/dist/core/messages/index.js +3 -3
  168. package/dist/core/messages/ja/analysts/analyst-github-actions-messages.js +1 -1
  169. package/dist/core/messages/ja/analysts/analyst-patterns-usage-messages.js +1 -0
  170. package/dist/core/messages/ja/analysts/analyst-shell-messages.js +15 -0
  171. package/dist/core/messages/ja/analysts/detector-constructions-syntactic-messages.js +6 -0
  172. package/dist/core/messages/ja/analysts/detector-js-ts-messages.js +27 -0
  173. package/dist/core/messages/ja/analysts/detector-react-messages.js +8 -0
  174. package/dist/core/messages/ja/analysts/detector-shell-messages.js +17 -0
  175. package/dist/core/messages/ja/analysts/detector-tailwind-messages.js +3 -3
  176. package/dist/core/messages/ja/analysts/report-circleci-messages.js +7 -7
  177. package/dist/core/messages/ja/caretakers/caretaker-messages.js +1 -7
  178. package/dist/core/messages/ja/core/plugin-messages.js +31 -3
  179. package/dist/core/messages/ja/log/log.js +4 -4
  180. package/dist/core/messages/ja/ui/filter-config.js +1 -1
  181. package/dist/core/messages/pt/analysts/analyst-github-actions-messages.js +1 -1
  182. package/dist/core/messages/pt/analysts/analyst-patterns-usage-messages.js +1 -0
  183. package/dist/core/messages/pt/analysts/analyst-shell-messages.js +15 -0
  184. package/dist/core/messages/pt/analysts/detector-constructions-syntactic-messages.js +6 -0
  185. package/dist/core/messages/pt/analysts/detector-js-ts-messages.js +27 -0
  186. package/dist/core/messages/pt/analysts/detector-react-messages.js +8 -0
  187. package/dist/core/messages/pt/analysts/detector-shell-messages.js +17 -0
  188. package/dist/core/messages/pt/analysts/detector-tailwind-messages.js +3 -3
  189. package/dist/core/messages/pt/analysts/report-circleci-messages.js +7 -7
  190. package/dist/core/messages/pt/caretakers/caretaker-messages.js +1 -7
  191. package/dist/core/messages/pt/core/plugin-messages.js +31 -3
  192. package/dist/core/messages/pt/log/log-engine.js +6 -6
  193. package/dist/core/messages/pt/log/log.js +3 -3
  194. package/dist/core/messages/pt/ui/filter-config.js +1 -1
  195. package/dist/core/messages/shared/icons.js +3 -3
  196. package/dist/core/messages/zh/analysts/analyst-github-actions-messages.js +1 -1
  197. package/dist/core/messages/zh/analysts/analyst-patterns-usage-messages.js +1 -0
  198. package/dist/core/messages/zh/analysts/analyst-shell-messages.js +15 -0
  199. package/dist/core/messages/zh/analysts/detector-constructions-syntactic-messages.js +6 -0
  200. package/dist/core/messages/zh/analysts/detector-js-ts-messages.js +27 -0
  201. package/dist/core/messages/zh/analysts/detector-react-messages.js +8 -0
  202. package/dist/core/messages/zh/analysts/detector-shell-messages.js +17 -0
  203. package/dist/core/messages/zh/analysts/detector-tailwind-messages.js +3 -3
  204. package/dist/core/messages/zh/analysts/report-circleci-messages.js +7 -7
  205. package/dist/core/messages/zh/caretakers/caretaker-messages.js +1 -7
  206. package/dist/core/messages/zh/core/plugin-messages.js +31 -3
  207. package/dist/core/messages/zh/log/log.js +3 -3
  208. package/dist/core/messages/zh/ui/filter-config.js +1 -5
  209. package/dist/core/parsing/filters.js +3 -3
  210. package/dist/core/parsing/langs/json.js +1 -1
  211. package/dist/core/parsing/langs/python.js +1 -1
  212. package/dist/core/parsing/langs/typescript.js +1 -1
  213. package/dist/core/parsing/parser.js +3 -4
  214. package/dist/core/parsing/utils.js +1 -0
  215. package/dist/core/registry/file-registry.js +3 -2
  216. package/dist/core/registry/paths.js +3 -3
  217. package/dist/core/reporting/default-reporter.js +2 -2
  218. package/dist/core/schema/version.js +6 -6
  219. package/dist/core/workers/worker-executor.js +3 -3
  220. package/dist/core/workers/worker-pool.js +0 -0
  221. package/dist/guardian/baseline.js +1 -1
  222. package/dist/guardian/gpg.js +3 -1
  223. package/dist/guardian/integrity.js +2 -7
  224. package/dist/guardian/records.js +7 -1
  225. package/dist/guardian/result.js +1 -1
  226. package/dist/guardian/sentinel.js +7 -1
  227. package/dist/guardian/watcher-hidden.js +6 -1
  228. package/dist/licenses/fs-utils.js +5 -1
  229. package/dist/licenses/generate-notices.js +1 -1
  230. package/dist/licenses/index.js +1 -0
  231. package/dist/licenses/normalizer.js +10 -9
  232. package/dist/node.loader.js +224 -4
  233. package/dist/reports/analise-async-patterns.js +1 -1
  234. package/dist/reports/filter-smart.js +2 -5
  235. package/dist/reports/generator-report.js +7 -7
  236. package/dist/reports/report-archetypes.js +10 -10
  237. package/dist/reports/report-caretaker-health.js +2 -1
  238. package/dist/reports/report-patterns-usage.js +1 -1
  239. package/dist/sdk/analyzer.js +1 -1
  240. package/dist/shared/data-processing/fragment-report.js +11 -11
  241. package/dist/shared/data-processing/json.js +1 -1
  242. package/dist/shared/data-processing/occurrences.js +3 -2
  243. package/dist/shared/formatters/code-min-formatter.js +1 -1
  244. package/dist/shared/formatters/engines/prettier.js +1 -1
  245. package/dist/shared/formatters/engines/stylelint.js +43 -40
  246. package/dist/shared/formatters/formatter.js +8 -8
  247. package/dist/shared/formatters/formatters/code.js +3 -3
  248. package/dist/shared/formatters/formatters/css.js +2 -10
  249. package/dist/shared/formatters/formatters/dotfiles.js +1 -1
  250. package/dist/shared/formatters/formatters/html.js +1 -5
  251. package/dist/shared/formatters/formatters/json.js +0 -3
  252. package/dist/shared/formatters/formatters/markdown.js +19 -24
  253. package/dist/shared/formatters/formatters/properties.js +2 -2
  254. package/dist/shared/formatters/formatters/shell.js +1 -4
  255. package/dist/shared/formatters/formatters/sql.js +0 -3
  256. package/dist/shared/formatters/formatters/xml.js +5 -7
  257. package/dist/shared/formatters/formatters/yaml.js +2 -7
  258. package/dist/shared/formatters/index.js +1 -1
  259. package/dist/shared/helpers/framework-detector.js +6 -2
  260. package/dist/shared/helpers/json.js +1 -1
  261. package/dist/shared/helpers/magic-constants-whitelist.js +1 -1
  262. package/dist/shared/helpers/masking.js +17 -17
  263. package/dist/shared/helpers/reader-report.js +0 -12
  264. package/dist/shared/helpers/structural-hash.js +3 -2
  265. package/dist/shared/helpers/structure.js +1 -1
  266. package/dist/shared/marketplace/registry.js +1 -1
  267. package/dist/shared/marketplace/remote.js +4 -4
  268. package/dist/shared/persistence/persistence.js +13 -6
  269. package/dist/shared/plugins/core-plugin.js +5 -1
  270. package/dist/shared/plugins/registry.js +3 -2
  271. package/dist/types/analysts/tailwind-correction.js +2 -0
  272. package/dist/types/caretakers/imports-barrel.js +1 -0
  273. package/dist/types/caretakers/index.js +4 -0
  274. package/dist/types/caretakers/map-reversion.js +1 -0
  275. package/dist/types/caretakers/pruning.js +1 -0
  276. package/dist/types/caretakers/scoring.js +1 -0
  277. package/dist/types/common/analysts.js +1 -1
  278. package/dist/types/core/config/filters.js +1 -0
  279. package/dist/types/core/config/index.js +2 -0
  280. package/dist/types/core/execution/ambiente.js +1 -0
  281. package/dist/types/core/execution/linguagens.js +1 -0
  282. package/dist/types/core/execution/parse-errors.js +1 -0
  283. package/dist/types/core/execution/results.js +1 -0
  284. package/dist/types/core/execution/structure-json.js +1 -0
  285. package/dist/types/core/index.js +1 -0
  286. package/dist/types/core/messages/index.js +1 -0
  287. package/dist/types/core/messages/log.js +1 -0
  288. package/dist/types/core/parsing/babel-narrow.js +1 -0
  289. package/dist/types/core/parsing/index.js +1 -0
  290. package/dist/types/core/runtime.js +1 -0
  291. package/dist/types/guardian/index.js +2 -0
  292. package/dist/types/guardian/integrity.js +7 -0
  293. package/dist/types/guardian/snapshot.js +1 -0
  294. package/dist/types/index.js +4 -4
  295. package/dist/types/licenses/index.js +2 -0
  296. package/dist/types/processing/display.js +16 -13
  297. package/dist/types/processing/filters.js +8 -11
  298. package/dist/types/reports/compliance.js +1 -0
  299. package/dist/types/reports/streaming.js +1 -0
  300. package/dist/types/scripts/index.js +1 -0
  301. package/dist/types/scripts/migrar-aliases.js +1 -0
  302. package/dist/types/sdk/index.js +1 -0
  303. package/dist/types/shared/index.js +2 -0
  304. package/dist/types/vulnerabilities/index.js +2 -0
  305. package/dist/vulnerabilities/scanner.js +3 -2
  306. package/package.json +14 -20
@@ -16,9 +16,6 @@ export const detectorCircleCIEstrutura = {
16
16
  try {
17
17
  const doc = parseDocument(src);
18
18
  const config = doc.toJS();
19
- if (!config) {
20
- return ocorrencias;
21
- }
22
19
  const jobs = config;
23
20
  if (jobs.jobs) {
24
21
  for (const [jobName, job] of Object.entries(jobs.jobs)) {
@@ -91,7 +88,7 @@ export const detectorCircleCIEstrutura = {
91
88
  const commands = config.commands;
92
89
  if (commands) {
93
90
  for (const [_cmdName, cmdDef] of Object.entries(commands)) {
94
- if (cmdDef && !('parameters' in cmdDef)) {
91
+ if (!('parameters' in cmdDef)) {
95
92
  ocorrencias.push(criarOcorrencia({
96
93
  tipo: 'circleci-command-no-parameters',
97
94
  nivel: 'info',
@@ -130,23 +127,7 @@ export const detectorCircleCIEstrutura = {
130
127
  }
131
128
  // Orphaned job detection
132
129
  if (jobs.jobs && workflows) {
133
- const wfValues = Object.values(workflows);
134
- const usedJobs = new Set();
135
- for (const wf of wfValues) {
136
- if (wf && typeof wf === 'object') {
137
- const wfJobs = wf.jobs;
138
- if (Array.isArray(wfJobs)) {
139
- for (const wfJob of wfJobs) {
140
- if (typeof wfJob === 'string') {
141
- usedJobs.add(wfJob);
142
- }
143
- else if (wfJob && typeof wfJob === 'object') {
144
- Object.keys(wfJob).forEach(k => usedJobs.add(k));
145
- }
146
- }
147
- }
148
- }
149
- }
130
+ const usedJobs = collectUsedJobsFromWorkflows(Object.values(workflows));
150
131
  for (const jn of Object.keys(jobs.jobs)) {
151
132
  if (!usedJobs.has(jn)) {
152
133
  ocorrencias.push(criarOcorrencia({
@@ -162,7 +143,7 @@ export const detectorCircleCIEstrutura = {
162
143
  // Resource class pricing consideration
163
144
  if (jobs.jobs) {
164
145
  for (const [, job] of Object.entries(jobs.jobs)) {
165
- if (job && !('resource_class' in job) && job.steps && job.steps.length > 5) {
146
+ if (!('resource_class' in job) && job.steps && job.steps.length > 5) {
166
147
  ocorrencias.push(criarOcorrencia({
167
148
  tipo: 'circleci-resource-class-pricing',
168
149
  nivel: 'info',
@@ -220,3 +201,22 @@ export const detectorCircleCIEstrutura = {
220
201
  return ocorrencias;
221
202
  }
222
203
  };
204
+ function collectUsedJobsFromWorkflows(wfValues) {
205
+ const usedJobs = new Set();
206
+ for (const wf of wfValues) {
207
+ if (typeof wf === 'object' && wf !== null) {
208
+ const wfJobs = wf.jobs;
209
+ if (Array.isArray(wfJobs)) {
210
+ for (const wfJob of wfJobs) {
211
+ if (typeof wfJob === 'string') {
212
+ usedJobs.add(wfJob);
213
+ }
214
+ else if (typeof wfJob === 'object' && wfJob !== null) {
215
+ Object.keys(wfJob).forEach(k => usedJobs.add(k));
216
+ }
217
+ }
218
+ }
219
+ }
220
+ }
221
+ return usedJobs;
222
+ }
@@ -1,5 +1,5 @@
1
1
  import { ConversorGhaToGitlab } from './engines/converter-gha-to-gitlab.js';
2
2
  export const registroConversores = [new ConversorGhaToGitlab()];
3
3
  export function obterConversor(de, para) {
4
- return registroConversores.find(elem => elem.de.toLowerCase() === de.toLowerCase() && elem.para.toLowerCase() === para.toLowerCase());
4
+ return registroConversores?.find(elem => elem.de.toLowerCase() === de.toLowerCase() && elem.para.toLowerCase() === para.toLowerCase());
5
5
  }
@@ -10,6 +10,7 @@ export class ConversorGhaToGitlab extends ConversorBase {
10
10
  de = 'github-actions';
11
11
  para = 'gitlab-ci';
12
12
  async converter(conteudo) {
13
+ await Promise.resolve();
13
14
  const avisos = [];
14
15
  const erros = [];
15
16
  try {
@@ -49,21 +50,7 @@ export class ConversorGhaToGitlab extends ConversorBase {
49
50
  if (job.steps && Array.isArray(job.steps)) {
50
51
  const steps = job.steps;
51
52
  for (const step of steps) {
52
- if (step.run) {
53
- // Limpar comandos de run (remover multi-line pipe se necessário)
54
- const cmd = step.run.trim();
55
- gitlabJob.script.push(cmd);
56
- }
57
- else if (step.uses) {
58
- // Tratamento especial para checkout
59
- if (step.uses.includes('actions/checkout')) {
60
- gitlabJob.script.push('# Checkout automático pelo GitLab Runner');
61
- }
62
- else {
63
- avisos.push(`Job '${jobId}': Action '${step.uses}' detectada. Considere usar um componente equivalente do GitLab ou um script customizado.`);
64
- gitlabJob.script.push(`# TODO: Implementar lógica da action: ${step.uses}`);
65
- }
66
- }
53
+ processWorkflowStep(step, jobId, gitlabJob, avisos);
67
54
  }
68
55
  }
69
56
  // Mapear dependências (needs)
@@ -85,3 +72,18 @@ export class ConversorGhaToGitlab extends ConversorBase {
85
72
  }
86
73
  }
87
74
  }
75
+ function processWorkflowStep(step, jobId, gitlabJob, avisos) {
76
+ if (step.run) {
77
+ const cmd = step.run.trim();
78
+ gitlabJob.script.push(cmd);
79
+ }
80
+ else if (step.uses) {
81
+ if (step.uses.includes('actions/checkout')) {
82
+ gitlabJob.script.push('# Checkout automático pelo GitLab Runner');
83
+ }
84
+ else {
85
+ avisos.push(`Job '${jobId}': Action '${step.uses}' detectada. Considere usar um componente equivalente do GitLab ou um script customizado.`);
86
+ gitlabJob.script.push(`# TODO: Implementar lógica da action: ${step.uses}`);
87
+ }
88
+ }
89
+ }
@@ -10,5 +10,5 @@ export const registroConversores = [new ConversorGhaToGitlab()];
10
10
  * Busca um conversor compatível com as plataformas de origem e destino.
11
11
  */
12
12
  export function obterConversor(de, para) {
13
- return registroConversores.find(elem => elem.de.toLowerCase() === de.toLowerCase() && elem.para.toLowerCase() === para.toLowerCase());
13
+ return registroConversores?.find(elem => elem.de.toLowerCase() === de.toLowerCase() && elem.para.toLowerCase() === para.toLowerCase());
14
14
  }
@@ -24,39 +24,36 @@ export const analistaQuickFixes = {
24
24
  const uniqueFixes = quickFixes.filter((fix, index, arr) => arr.findIndex(arquivo => arquivo.id === fix.id) === index);
25
25
  for (const fixResultado of uniqueFixes) {
26
26
  for (const match of fixResultado.matches) {
27
- // Calcular linha aproximada do match
28
- const beforeMatch = src.substring(0, match.index ?? 0);
29
- const linha = beforeMatch.split('\n').length;
30
- // Gerar preview da correção
31
- const previewCorrecao = fixResultado.fix(match, src);
32
- const originalLine = src.split('\n')[linha - 1] || '';
33
- const fixedLine = previewCorrecao.split('\n')[linha - 1] || '';
34
- // Criar sugestão com preview mais detalhado
35
- const sugestao = [fixResultado.description, '', `[CHAVE-INGLESA] Correção sugerida:`, `[ERRO] Antes: ${originalLine.trim()}`, `[OK] Depois: ${fixedLine.trim()}`, '', `Confiança: ${fixResultado.confidence}%`, `Categoria: ${fixResultado.category}`, `ID do Fix: ${fixResultado.id}`].join('\n');
36
- // Mapear categoria para nível
37
- const nivel = mapearCategoriaNivel(fixResultado.category);
38
- // Criar ocorrência base
39
- const ocorrencia = criarOcorrencia({
40
- tipo: 'auto-fix-disponivel',
41
- nivel,
42
- mensagem: fixResultado.title,
43
- relPath,
44
- linha
45
- });
46
- // Adicionar campos extras como propriedades do objeto genérico
47
- const ocorrenciaGenerica = ocorrencia; // OcorrenciaGenerica allows extra properties
48
- ocorrenciaGenerica.sugestao = sugestao;
49
- ocorrenciaGenerica.quickFixId = fixResultado.id;
50
- ocorrenciaGenerica.confidence = fixResultado.confidence;
51
- ocorrenciaGenerica.category = fixResultado.category;
52
- ocorrenciaGenerica.matchIndex = match.index;
53
- ocorrenciaGenerica.matchLength = match[0].length;
54
- ocorrencias.push(ocorrencia);
27
+ processQuickFixMatch(match, fixResultado, src, relPath, ocorrencias);
55
28
  }
56
29
  }
57
30
  return ocorrencias;
58
31
  }
59
32
  };
33
+ function processQuickFixMatch(match, fixResultado, src, relPath, ocorrencias) {
34
+ const beforeMatch = src.substring(0, match.index ?? 0);
35
+ const linha = beforeMatch.split('\n').length;
36
+ const previewCorrecao = fixResultado.fix(match, src);
37
+ const originalLine = src.split('\n')[linha - 1] || '';
38
+ const fixedLine = previewCorrecao.split('\n')[linha - 1] || '';
39
+ const sugestao = [fixResultado.description, '', `[CHAVE-INGLESA] Correção sugerida:`, `[ERRO] Antes: ${originalLine.trim()}`, `[OK] Depois: ${fixedLine.trim()}`, '', `Confiança: ${fixResultado.confidence}%`, `Categoria: ${fixResultado.category}`, `ID do Fix: ${fixResultado.id}`].join('\n');
40
+ const nivel = mapearCategoriaNivel(fixResultado.category);
41
+ const ocorrencia = criarOcorrencia({
42
+ tipo: 'auto-fix-disponivel',
43
+ nivel,
44
+ mensagem: fixResultado.title,
45
+ relPath,
46
+ linha
47
+ });
48
+ const ocorrenciaGenerica = ocorrencia;
49
+ ocorrenciaGenerica.sugestao = sugestao;
50
+ ocorrenciaGenerica.quickFixId = fixResultado.id;
51
+ ocorrenciaGenerica.confidence = fixResultado.confidence;
52
+ ocorrenciaGenerica.category = fixResultado.category;
53
+ ocorrenciaGenerica.matchIndex = match.index;
54
+ ocorrenciaGenerica.matchLength = match[0].length;
55
+ ocorrencias.push(ocorrencia);
56
+ }
60
57
  function mapearCategoriaNivel(category) {
61
58
  switch (category) {
62
59
  case 'security':
@@ -42,32 +42,35 @@ export const analistaQuickFixes = {
42
42
  const uniqueFixes = quickFixes.filter((fix, index, arr) => arr.findIndex(arquivo => arquivo.id === fix.id) === index);
43
43
  for (const fixResultado of uniqueFixes) {
44
44
  for (const match of fixResultado.matches) {
45
- const linha = calcularLinha(src, match.index, match);
46
- const previewCorrecao = fixResultado.fix(match, src);
47
- const originalLine = src.split('\n')[linha - 1] || '';
48
- const fixedLine = previewCorrecao.split('\n')[linha - 1] || '';
49
- const sugestao = [fixResultado.description, '', `[CHAVE-INGLESA] Correção sugerida:`, `[ERRO] Antes: ${originalLine.trim()}`, `[OK] Depois: ${fixedLine.trim()}`, '', `Confiança: ${fixResultado.confidence}%`, `Categoria: ${fixResultado.category}`, `ID do Fix: ${fixResultado.id}`].join('\n');
50
- const nivel = mapearCategoriaNivel(fixResultado.category);
51
- const ocorrencia = criarOcorrencia({
52
- tipo: 'auto-fix-disponivel',
53
- nivel,
54
- mensagem: fixResultado.title,
55
- relPath,
56
- linha
57
- });
58
- const ocorrenciaGenerica = ocorrencia;
59
- ocorrenciaGenerica.sugestao = sugestao;
60
- ocorrenciaGenerica.quickFixId = fixResultado.id;
61
- ocorrenciaGenerica.confidence = fixResultado.confidence;
62
- ocorrenciaGenerica.category = fixResultado.category;
63
- ocorrenciaGenerica.matchIndex = match.index;
64
- ocorrenciaGenerica.matchLength = match[0].length;
65
- ocorrencias.push(ocorrencia);
45
+ processQuickFixMatchScoring(match, fixResultado, src, relPath, ocorrencias);
66
46
  }
67
47
  }
68
48
  return ocorrencias;
69
49
  }
70
50
  };
51
+ function processQuickFixMatchScoring(match, fixResultado, src, relPath, ocorrencias) {
52
+ const linha = calcularLinha(src, match.index, match);
53
+ const previewCorrecao = fixResultado.fix(match, src);
54
+ const originalLine = src.split('\n')[linha - 1] || '';
55
+ const fixedLine = previewCorrecao.split('\n')[linha - 1] || '';
56
+ const sugestao = [fixResultado.description, '', `[CHAVE-INGLESA] Correção sugerida:`, `[ERRO] Antes: ${originalLine.trim()}`, `[OK] Depois: ${fixedLine.trim()}`, '', `Confiança: ${fixResultado.confidence}%`, `Categoria: ${fixResultado.category}`, `ID do Fix: ${fixResultado.id}`].join('\n');
57
+ const nivel = mapearCategoriaNivel(fixResultado.category);
58
+ const ocorrencia = criarOcorrencia({
59
+ tipo: 'auto-fix-disponivel',
60
+ nivel,
61
+ mensagem: fixResultado.title,
62
+ relPath,
63
+ linha
64
+ });
65
+ const ocorrenciaGenerica = ocorrencia;
66
+ ocorrenciaGenerica.sugestao = sugestao;
67
+ ocorrenciaGenerica.quickFixId = fixResultado.id;
68
+ ocorrenciaGenerica.confidence = fixResultado.confidence;
69
+ ocorrenciaGenerica.category = fixResultado.category;
70
+ ocorrenciaGenerica.matchIndex = match.index;
71
+ ocorrenciaGenerica.matchLength = match[0].length;
72
+ ocorrencias.push(ocorrencia);
73
+ }
71
74
  // ─── analistaPontuacao ────────────────────────────────────────
72
75
  export const analistaPontuacao = {
73
76
  nome: 'pontuacao-fix',
@@ -83,7 +83,7 @@ export function aplicarCorrecaoArquivo(arquivo, ocorrencias, config) {
83
83
  /**
84
84
  * Aplica correções em múltiplos arquivos
85
85
  */
86
- export async function aplicarCorrecoesEmLote(porArquivo, config) {
86
+ export function aplicarCorrecoesEmLote(porArquivo, config) {
87
87
  const resultados = [];
88
88
  let sucesso = 0;
89
89
  let falhas = 0;
@@ -12,9 +12,10 @@ import { mapaReversao } from './map-reversion.js';
12
12
  const { log, logAuto, CorretorEstruturaExtraMensagens } = getMessages();
13
13
  export async function corrigirEstrutura(mapa, fileEntries, baseDir = process.cwd()) {
14
14
  // Captura dinâmica das configs (evita congelar valores em tempo de import)
15
- const CONCORRENCIA = (config.STRUCTURE_CONCURRENCY ?? 5);
15
+ const CONCORRENCIA = config.STRUCTURE_CONCURRENCY;
16
16
  const AUTO_CORRECAO = config.STRUCTURE_AUTO_FIX;
17
- const PLUGINS = config.STRUCTURE_PLUGINS ?? [];
17
+ const rawPlugins = config.STRUCTURE_PLUGINS ?? [];
18
+ const PLUGINS = Array.isArray(rawPlugins) ? rawPlugins.filter((p) => typeof p === 'string') : [];
18
19
  const ESTRUTURA_CAMADAS = config.ESTRUTURA_CAMADAS;
19
20
  const limit = pLimit(CONCORRENCIA);
20
21
  await Promise.all(mapa.map(entry => limit(async () => {
@@ -30,55 +31,21 @@ export async function corrigirEstrutura(mapa, fileEntries, baseDir = process.cwd
30
31
  log.info(CorretorEstruturaExtraMensagens.simular.replace('{arquivo}', arquivo).replace('{destino}', path.relative(baseDir, destino)));
31
32
  return;
32
33
  }
33
- try {
34
- await fs.mkdir(path.dirname(destino), {
35
- recursive: true
36
- });
37
- }
38
- catch (err) {
39
- const msg = err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err);
40
- logAuto.corretorErroCriarDiretorio(destino, msg);
41
- return;
42
- }
43
- try {
44
- // Usa flag 'wx' para escrita exclusiva - falha se o arquivo já existir,
45
- // eliminando a condição de corrida TOCTOU entre stat e write
46
- const conteudo = await fs.readFile(origem, 'utf-8');
47
- const { novoConteudo } = reescreverImports(conteudo, path.posix.normalize(arquivo.replace(/\\/g, '/')), path.posix.normalize(path.relative(baseDir, destino).replace(/\\/g, '/')));
48
- // Registra o move no mapa de reversão
49
- await mapaReversao.registrarMove(arquivo, path.relative(baseDir, destino), entry.motivo ?? 'Reorganização estrutural', conteudo, novoConteudo, true);
50
- try {
51
- await fs.writeFile(destino, novoConteudo, { encoding: 'utf-8', flag: 'wx' });
52
- }
53
- catch (err) {
54
- const code = err.code;
55
- if (code === 'EEXIST') {
56
- logAuto.corretorDestinoExiste(arquivo, path.relative(baseDir, destino));
57
- return;
58
- }
59
- throw err;
60
- }
61
- await fs.unlink(origem);
62
- log.sucesso(CorretorEstruturaExtraMensagens.movido.replace('{arquivo}', arquivo).replace('{destino}', path.relative(baseDir, destino)));
63
- }
64
- catch (err) {
65
- const msg = err && typeof err === 'object' && 'message' in err ? String((err).message) : String(err);
66
- logAuto.corretorErroMover(arquivo, msg);
67
- }
34
+ await moverArquivoComReversao(entry, origem, destino, baseDir, arquivo);
68
35
  })));
69
36
  for (const pluginRel of PLUGINS) {
70
37
  try {
71
- const resolvido = resolverPluginSeguro(baseDir, String(pluginRel));
38
+ const resolvido = resolverPluginSeguro(baseDir, pluginRel);
72
39
  if (resolvido.erro) {
73
- logAuto.pluginIgnorado(String(pluginRel), resolvido.erro);
40
+ logAuto.pluginIgnorado(pluginRel, resolvido.erro);
74
41
  continue;
75
42
  }
76
43
  const caminhoPlugin = resolvido.caminho;
77
44
  if (!caminhoPlugin) {
78
- logAuto.caminhoNaoResolvido(String(pluginRel));
45
+ logAuto.caminhoNaoResolvido(pluginRel);
79
46
  continue;
80
47
  }
81
- const pluginModule = await importarModuloSeguro(baseDir, String(pluginRel));
48
+ const pluginModule = await importarModuloSeguro(baseDir, pluginRel);
82
49
  let pluginFn;
83
50
  if (pluginModule && typeof pluginModule === 'object' && 'default' in pluginModule && typeof pluginModule.default === 'function') {
84
51
  pluginFn = pluginModule.default;
@@ -103,7 +70,41 @@ export async function corrigirEstrutura(mapa, fileEntries, baseDir = process.cwd
103
70
  else if (typeof err === 'string') {
104
71
  msg = err;
105
72
  }
106
- logAuto.pluginFalhou(String(pluginRel), msg);
73
+ logAuto.pluginFalhou(pluginRel, msg);
107
74
  }
108
75
  }
109
76
  }
77
+ async function moverArquivoComReversao(entry, origem, destino, baseDir, arquivo) {
78
+ try {
79
+ await fs.mkdir(path.dirname(destino), {
80
+ recursive: true
81
+ });
82
+ }
83
+ catch (err) {
84
+ const msg = err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err);
85
+ logAuto.corretorErroCriarDiretorio(destino, msg);
86
+ return;
87
+ }
88
+ try {
89
+ const conteudo = await fs.readFile(origem, 'utf-8');
90
+ const { novoConteudo } = reescreverImports(conteudo, path.posix.normalize(arquivo.replace(/\\/g, '/')), path.posix.normalize(path.relative(baseDir, destino).replace(/\\/g, '/')));
91
+ await mapaReversao.registrarMove(arquivo, path.relative(baseDir, destino), entry.motivo ?? 'Reorganização estrutural', conteudo, novoConteudo, true);
92
+ try {
93
+ await fs.writeFile(destino, novoConteudo, { encoding: 'utf-8', flag: 'wx' });
94
+ }
95
+ catch (err) {
96
+ const code = err.code;
97
+ if (code === 'EEXIST') {
98
+ logAuto.corretorDestinoExiste(arquivo, path.relative(baseDir, destino));
99
+ return;
100
+ }
101
+ throw err;
102
+ }
103
+ await fs.unlink(origem);
104
+ log.sucesso(CorretorEstruturaExtraMensagens.movido.replace('{arquivo}', arquivo).replace('{destino}', path.relative(baseDir, destino)));
105
+ }
106
+ catch (err) {
107
+ const msg = err && typeof err === 'object' && 'message' in err ? String((err).message) : String(err);
108
+ logAuto.corretorErroMover(arquivo, msg);
109
+ }
110
+ }
@@ -13,6 +13,15 @@ export function aplicarFixAliasImports(fileCaminho, content) {
13
13
  content: out
14
14
  };
15
15
  }
16
+ async function processTypeFileForAlias(fileCaminho) {
17
+ const src = await fs.readFile(fileCaminho, 'utf8');
18
+ const { changed: wasChanged, content } = aplicarFixAliasImports(fileCaminho, src);
19
+ if (wasChanged) {
20
+ await fs.writeFile(fileCaminho, content, 'utf8');
21
+ return 1;
22
+ }
23
+ return 0;
24
+ }
16
25
  export async function scanAndApplyFix(root) {
17
26
  let changed = 0;
18
27
  async function walk(dir) {
@@ -26,12 +35,7 @@ export async function scanAndApplyFix(root) {
26
35
  await walk(fileCaminho);
27
36
  }
28
37
  else if (entry.isFile() && fileCaminho.endsWith('.ts')) {
29
- const src = await fs.readFile(fileCaminho, 'utf8');
30
- const { changed: wasChanged, content } = aplicarFixAliasImports(fileCaminho, src);
31
- if (wasChanged) {
32
- await fs.writeFile(fileCaminho, content, 'utf8');
33
- changed++;
34
- }
38
+ changed += await processTypeFileForAlias(fileCaminho);
35
39
  }
36
40
  }
37
41
  }
@@ -48,33 +48,33 @@ export function fixFences(content) {
48
48
  }
49
49
  return out.join('\n');
50
50
  }
51
- export async function scanAndApplyFixMdFences(root) {
52
- let changed = 0;
53
- async function listMarkdown(dir) {
54
- const out = [];
55
- try {
56
- const entries = await fs.readdir(dir, {
57
- withFileTypes: true
58
- });
59
- for (const entry of entries) {
60
- const fullCaminho = path.join(dir, entry.name);
61
- if (entry.isDirectory()) {
62
- if (/^(node_modules|dist|coverage|pre-public|preview-mahoraga|\.git)$/i.test(entry.name)) {
63
- continue;
64
- }
65
- out.push(...(await listMarkdown(fullCaminho)));
66
- }
67
- else if (entry.isFile() && entry.name.toLowerCase().endsWith('.md')) {
68
- out.push(fullCaminho);
51
+ async function listMarkdownFiles(dir) {
52
+ const out = [];
53
+ try {
54
+ const entries = await fs.readdir(dir, {
55
+ withFileTypes: true
56
+ });
57
+ for (const entry of entries) {
58
+ const fullCaminho = path.join(dir, entry.name);
59
+ if (entry.isDirectory()) {
60
+ if (/^(node_modules|dist|coverage|pre-public|preview-mahoraga|\.git)$/i.test(entry.name)) {
61
+ continue;
69
62
  }
63
+ out.push(...(await listMarkdownFiles(fullCaminho)));
64
+ }
65
+ else if (entry.isFile() && entry.name.toLowerCase().endsWith('.md')) {
66
+ out.push(fullCaminho);
70
67
  }
71
- return out;
72
- }
73
- catch {
74
- return out;
75
68
  }
69
+ return out;
70
+ }
71
+ catch {
72
+ return out;
76
73
  }
77
- const files = await listMarkdown(root);
74
+ }
75
+ export async function scanAndApplyFixMdFences(root) {
76
+ let changed = 0;
77
+ const files = await listMarkdownFiles(root);
78
78
  for (const fileCaminho of files) {
79
79
  const rel = path.relative(root, fileCaminho).replace(/\\/g, '/');
80
80
  if (rel.startsWith('pre-public/') || rel.includes('/legado/')) {
@@ -41,7 +41,7 @@ export class GerenciadorMapaReversao {
41
41
  }
42
42
  };
43
43
  // Validação básica
44
- if (!this.mapa.moves || !Array.isArray(this.mapa.moves)) {
44
+ if (!Array.isArray(this.mapa.moves)) {
45
45
  throw new Error(messages.ExcecoesMensagens.mapaReversaoCorrompido);
46
46
  }
47
47
  logAuto.mapaReversaoCarregado(this.mapa.moves.length);
@@ -89,7 +89,7 @@ export class GerenciadorMapaReversao {
89
89
  // quando true, evita persistir o mapa no disco imediatamente (útil para chamadas em massa/tests)
90
90
  skipSalvar) {
91
91
  try {
92
- const id = `move_${Date.now()}_${Math.random().toString(CONSTANTES_MAPA.RADIX_36).substr(CONSTANTES_MAPA.ID_OFFSET, CONSTANTES_MAPA.ID_LENGTH)}`;
92
+ const id = `move_${Date.now()}_${Math.random().toString(CONSTANTES_MAPA.RADIX_36).slice(CONSTANTES_MAPA.ID_OFFSET, CONSTANTES_MAPA.ID_OFFSET + CONSTANTES_MAPA.ID_LENGTH)}`;
93
93
  const move = {
94
94
  id,
95
95
  timestamp: new Date().toISOString(),
@@ -172,57 +172,8 @@ export class GerenciadorMapaReversao {
172
172
  recursive: true
173
173
  });
174
174
  // Move o arquivo de volta
175
- if (move.importsReescritos && move.conteudoOriginal) {
176
- // Usa flag 'wx' para escrita exclusiva - falha se o arquivo já existir,
177
- // eliminando a condição de corrida TOCTOU entre stat e write
178
- try {
179
- await fs.writeFile(origemCaminho, move.conteudoOriginal, {
180
- encoding: 'utf-8',
181
- flag: 'wx'
182
- });
183
- }
184
- catch (err) {
185
- const code = err.code;
186
- if (code === 'EEXIST') {
187
- logAuto.mapaReversaoArquivoExisteOrigem(move.origem);
188
- return false;
189
- }
190
- if (err.code && err.code !== 'ENOENT') {
191
- logAuto.mapaReversaoErroReverter(err.message);
192
- return false;
193
- }
194
- throw err;
195
- }
196
- try {
197
- await fs.unlink(destinoCaminho);
198
- }
199
- catch (err) {
200
- if (err.code === 'ENOENT') {
201
- logAuto.mapaReversaoArquivoDestinoNaoEncontrado(move.destino);
202
- return false;
203
- }
204
- throw err;
205
- }
206
- log.sucesso(MapaReversaoExtraMensagens.arquivoRevertidoConteudo.replace('{destino}', move.destino).replace('{origem}', move.origem));
207
- }
208
- else {
209
- // Usa rename atômico - se destino não existir, falha com ENOENT
210
- try {
211
- await fs.rename(destinoCaminho, origemCaminho);
212
- }
213
- catch (err) {
214
- const code = err.code;
215
- if (code === 'ENOENT') {
216
- logAuto.mapaReversaoArquivoDestinoNaoEncontrado(move.destino);
217
- return false;
218
- }
219
- if (code === 'EEXIST') {
220
- logAuto.mapaReversaoArquivoExisteOrigem(move.origem);
221
- return false;
222
- }
223
- throw err;
224
- }
225
- log.sucesso(MapaReversaoExtraMensagens.arquivoRevertido.replace('{destino}', move.destino).replace('{origem}', move.origem));
175
+ if (!await this.reverterComConteudo(move, origemCaminho, destinoCaminho)) {
176
+ return false;
226
177
  }
227
178
  // Remove o move do mapa
228
179
  await this.removerMove(id);
@@ -295,6 +246,58 @@ export class GerenciadorMapaReversao {
295
246
  logAuto.mapaReversaoErroSalvar(err.message);
296
247
  }
297
248
  }
249
+ async reverterComConteudo(move, origemCaminho, destinoCaminho) {
250
+ if (move.importsReescritos && move.conteudoOriginal) {
251
+ try {
252
+ await fs.writeFile(origemCaminho, move.conteudoOriginal, {
253
+ encoding: 'utf-8',
254
+ flag: 'wx'
255
+ });
256
+ }
257
+ catch (err) {
258
+ const code = err.code;
259
+ if (code === 'EEXIST') {
260
+ logAuto.mapaReversaoArquivoExisteOrigem(move.origem);
261
+ return false;
262
+ }
263
+ if (err.code && err.code !== 'ENOENT') {
264
+ logAuto.mapaReversaoErroReverter(err.message);
265
+ return false;
266
+ }
267
+ throw err;
268
+ }
269
+ try {
270
+ await fs.unlink(destinoCaminho);
271
+ }
272
+ catch (err) {
273
+ if (err.code === 'ENOENT') {
274
+ logAuto.mapaReversaoArquivoDestinoNaoEncontrado(move.destino);
275
+ return false;
276
+ }
277
+ throw err;
278
+ }
279
+ log.sucesso(MapaReversaoExtraMensagens.arquivoRevertidoConteudo.replace('{destino}', move.destino).replace('{origem}', move.origem));
280
+ }
281
+ else {
282
+ try {
283
+ await fs.rename(destinoCaminho, origemCaminho);
284
+ }
285
+ catch (err) {
286
+ const code = err.code;
287
+ if (code === 'ENOENT') {
288
+ logAuto.mapaReversaoArquivoDestinoNaoEncontrado(move.destino);
289
+ return false;
290
+ }
291
+ if (code === 'EEXIST') {
292
+ logAuto.mapaReversaoArquivoExisteOrigem(move.origem);
293
+ return false;
294
+ }
295
+ throw err;
296
+ }
297
+ log.sucesso(MapaReversaoExtraMensagens.arquivoRevertido.replace('{destino}', move.destino).replace('{origem}', move.origem));
298
+ }
299
+ return true;
300
+ }
298
301
  }
299
302
  // Instância global
300
303
  export const mapaReversao = new GerenciadorMapaReversao();
@@ -91,21 +91,24 @@ function moverArquivosSimulado(lista, base) {
91
91
  async function moverArquivos(lista, base, historico) {
92
92
  const limitar = pLimit(CONCORRENCIA);
93
93
  await Promise.all(lista.map(pend => limitar(async () => {
94
- const src = path.join(base, pend.arquivo);
95
- const dest = path.join(base, DIR_ABANDONADOS, pend.arquivo);
96
- try {
97
- const fs = await import('node:fs');
98
- await ensureDir(dest);
99
- await fs.promises.rename(src, dest);
100
- historico.push({
101
- arquivo: pend.arquivo,
102
- movidoEm: new Date().toISOString(),
103
- motivo: pend.motivo
104
- });
105
- logAuto.podaArquivoMovido(pend.arquivo);
106
- }
107
- catch (err) {
108
- log.erro(`[ERRO] Falha ao mover ${pend.arquivo}: ${typeof err === 'object' && err && 'message' in err ? err.message : String(err)}`);
109
- }
94
+ await moverArquivoIndividual(pend, base, historico);
110
95
  })));
111
96
  }
97
+ async function moverArquivoIndividual(pend, base, historico) {
98
+ const src = path.join(base, pend.arquivo);
99
+ const dest = path.join(base, DIR_ABANDONADOS, pend.arquivo);
100
+ try {
101
+ const fs = await import('node:fs');
102
+ await ensureDir(dest);
103
+ await fs.promises.rename(src, dest);
104
+ historico.push({
105
+ arquivo: pend.arquivo,
106
+ movidoEm: new Date().toISOString(),
107
+ motivo: pend.motivo
108
+ });
109
+ logAuto.podaArquivoMovido(pend.arquivo);
110
+ }
111
+ catch (err) {
112
+ log.erro(`[ERRO] Falha ao mover ${pend.arquivo}: ${typeof err === 'object' && err && 'message' in err ? err.message : String(err)}`);
113
+ }
114
+ }