@empline/preflight 1.1.11 → 1.1.13

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 (709) hide show
  1. package/dist/checks/consolidated/auth-storage-state.d.ts +3 -0
  2. package/dist/checks/consolidated/auth-storage-state.d.ts.map +1 -0
  3. package/dist/checks/consolidated/auth-storage-state.js +146 -0
  4. package/dist/checks/consolidated/auth-storage-state.js.map +1 -0
  5. package/dist/checks/consolidated/business.d.ts +50 -0
  6. package/dist/checks/consolidated/business.d.ts.map +1 -0
  7. package/dist/checks/consolidated/business.js +252 -0
  8. package/dist/checks/consolidated/business.js.map +1 -0
  9. package/dist/checks/consolidated/caching-strategy.d.ts +104 -0
  10. package/dist/checks/consolidated/caching-strategy.d.ts.map +1 -0
  11. package/dist/checks/consolidated/caching-strategy.js +725 -0
  12. package/dist/checks/consolidated/caching-strategy.js.map +1 -0
  13. package/dist/checks/consolidated/code-quality.d.ts +83 -0
  14. package/dist/checks/consolidated/code-quality.d.ts.map +1 -0
  15. package/dist/checks/consolidated/code-quality.js +445 -0
  16. package/dist/checks/consolidated/code-quality.js.map +1 -0
  17. package/dist/checks/consolidated/console-statements.d.ts +32 -0
  18. package/dist/checks/consolidated/console-statements.d.ts.map +1 -0
  19. package/dist/checks/consolidated/console-statements.js +304 -0
  20. package/dist/checks/consolidated/console-statements.js.map +1 -0
  21. package/dist/checks/consolidated/css-advanced-validation.d.ts +24 -0
  22. package/dist/checks/consolidated/css-advanced-validation.d.ts.map +1 -0
  23. package/dist/checks/consolidated/css-advanced-validation.js +415 -0
  24. package/dist/checks/consolidated/css-advanced-validation.js.map +1 -0
  25. package/dist/checks/consolidated/css-organization.d.ts +14 -0
  26. package/dist/checks/consolidated/css-organization.d.ts.map +1 -0
  27. package/dist/checks/consolidated/css-organization.js +432 -0
  28. package/dist/checks/consolidated/css-organization.js.map +1 -0
  29. package/dist/checks/consolidated/css-runtime-validation.d.ts +22 -0
  30. package/dist/checks/consolidated/css-runtime-validation.d.ts.map +1 -0
  31. package/dist/checks/consolidated/css-runtime-validation.js +330 -0
  32. package/dist/checks/consolidated/css-runtime-validation.js.map +1 -0
  33. package/dist/checks/consolidated/css-variable-validation.d.ts +17 -0
  34. package/dist/checks/consolidated/css-variable-validation.d.ts.map +1 -0
  35. package/dist/checks/consolidated/css-variable-validation.js +412 -0
  36. package/dist/checks/consolidated/css-variable-validation.js.map +1 -0
  37. package/dist/checks/consolidated/dark-mode-consistency.d.ts +23 -0
  38. package/dist/checks/consolidated/dark-mode-consistency.d.ts.map +1 -0
  39. package/dist/checks/consolidated/dark-mode-consistency.js +291 -0
  40. package/dist/checks/consolidated/dark-mode-consistency.js.map +1 -0
  41. package/dist/checks/consolidated/database.d.ts +95 -0
  42. package/dist/checks/consolidated/database.d.ts.map +1 -0
  43. package/dist/checks/consolidated/database.js +427 -0
  44. package/dist/checks/consolidated/database.js.map +1 -0
  45. package/dist/checks/consolidated/e2e-checks.d.ts +52 -0
  46. package/dist/checks/consolidated/e2e-checks.d.ts.map +1 -0
  47. package/dist/checks/consolidated/e2e-checks.js +157 -0
  48. package/dist/checks/consolidated/e2e-checks.js.map +1 -0
  49. package/dist/checks/consolidated/e2e-regression-coverage.d.ts +14 -0
  50. package/dist/checks/consolidated/e2e-regression-coverage.d.ts.map +1 -0
  51. package/dist/checks/consolidated/e2e-regression-coverage.js +151 -0
  52. package/dist/checks/consolidated/e2e-regression-coverage.js.map +1 -0
  53. package/dist/checks/consolidated/e2e-validation.d.ts +137 -0
  54. package/dist/checks/consolidated/e2e-validation.d.ts.map +1 -0
  55. package/dist/checks/consolidated/e2e-validation.js +1001 -0
  56. package/dist/checks/consolidated/e2e-validation.js.map +1 -0
  57. package/dist/checks/consolidated/enterprise-baseline.d.ts +9 -0
  58. package/dist/checks/consolidated/enterprise-baseline.d.ts.map +1 -0
  59. package/dist/checks/consolidated/enterprise-baseline.js +277 -0
  60. package/dist/checks/consolidated/enterprise-baseline.js.map +1 -0
  61. package/dist/checks/consolidated/generate-pageload-config.d.ts +6 -0
  62. package/dist/checks/consolidated/generate-pageload-config.d.ts.map +1 -0
  63. package/dist/checks/consolidated/generate-pageload-config.js +161 -0
  64. package/dist/checks/consolidated/generate-pageload-config.js.map +1 -0
  65. package/dist/checks/consolidated/hardened-checks.d.ts +276 -0
  66. package/dist/checks/consolidated/hardened-checks.d.ts.map +1 -0
  67. package/dist/checks/consolidated/hardened-checks.js +3056 -0
  68. package/dist/checks/consolidated/hardened-checks.js.map +1 -0
  69. package/dist/checks/consolidated/homepage-ux.d.ts +12 -0
  70. package/dist/checks/consolidated/homepage-ux.d.ts.map +1 -0
  71. package/dist/checks/consolidated/homepage-ux.js +242 -0
  72. package/dist/checks/consolidated/homepage-ux.js.map +1 -0
  73. package/dist/checks/consolidated/images.d.ts +76 -0
  74. package/dist/checks/consolidated/images.d.ts.map +1 -0
  75. package/dist/checks/consolidated/images.js +311 -0
  76. package/dist/checks/consolidated/images.js.map +1 -0
  77. package/dist/checks/consolidated/import-cycles.d.ts +63 -0
  78. package/dist/checks/consolidated/import-cycles.d.ts.map +1 -0
  79. package/dist/checks/consolidated/import-cycles.js +291 -0
  80. package/dist/checks/consolidated/import-cycles.js.map +1 -0
  81. package/dist/checks/consolidated/imports.d.ts +112 -0
  82. package/dist/checks/consolidated/imports.d.ts.map +1 -0
  83. package/dist/checks/consolidated/imports.js +977 -0
  84. package/dist/checks/consolidated/imports.js.map +1 -0
  85. package/dist/checks/consolidated/inline-style-conflicts.d.ts +21 -0
  86. package/dist/checks/consolidated/inline-style-conflicts.d.ts.map +1 -0
  87. package/dist/checks/consolidated/inline-style-conflicts.js +300 -0
  88. package/dist/checks/consolidated/inline-style-conflicts.js.map +1 -0
  89. package/dist/checks/consolidated/lib-organization.d.ts +12 -0
  90. package/dist/checks/consolidated/lib-organization.d.ts.map +1 -0
  91. package/dist/checks/consolidated/lib-organization.js +419 -0
  92. package/dist/checks/consolidated/lib-organization.js.map +1 -0
  93. package/dist/checks/consolidated/n-plus-one.d.ts +63 -0
  94. package/dist/checks/consolidated/n-plus-one.d.ts.map +1 -0
  95. package/dist/checks/consolidated/n-plus-one.js +331 -0
  96. package/dist/checks/consolidated/n-plus-one.js.map +1 -0
  97. package/dist/checks/consolidated/nextjs.d.ts +51 -0
  98. package/dist/checks/consolidated/nextjs.d.ts.map +1 -0
  99. package/dist/checks/consolidated/nextjs.js +205 -0
  100. package/dist/checks/consolidated/nextjs.js.map +1 -0
  101. package/dist/checks/consolidated/organization.d.ts +54 -0
  102. package/dist/checks/consolidated/organization.d.ts.map +1 -0
  103. package/dist/checks/consolidated/organization.js +158 -0
  104. package/dist/checks/consolidated/organization.js.map +1 -0
  105. package/dist/checks/consolidated/pageload.d.ts +12 -0
  106. package/dist/checks/consolidated/pageload.d.ts.map +1 -0
  107. package/dist/checks/consolidated/pageload.js +138 -0
  108. package/dist/checks/consolidated/pageload.js.map +1 -0
  109. package/dist/checks/consolidated/performance.d.ts +112 -0
  110. package/dist/checks/consolidated/performance.d.ts.map +1 -0
  111. package/dist/checks/consolidated/performance.js +1546 -0
  112. package/dist/checks/consolidated/performance.js.map +1 -0
  113. package/dist/checks/consolidated/quality.d.ts +52 -0
  114. package/dist/checks/consolidated/quality.d.ts.map +1 -0
  115. package/dist/checks/consolidated/quality.js +253 -0
  116. package/dist/checks/consolidated/quality.js.map +1 -0
  117. package/dist/checks/consolidated/react.d.ts +48 -0
  118. package/dist/checks/consolidated/react.d.ts.map +1 -0
  119. package/dist/checks/consolidated/react.js +203 -0
  120. package/dist/checks/consolidated/react.js.map +1 -0
  121. package/dist/checks/consolidated/regression-hygiene.d.ts +17 -0
  122. package/dist/checks/consolidated/regression-hygiene.d.ts.map +1 -0
  123. package/dist/checks/consolidated/regression-hygiene.js +242 -0
  124. package/dist/checks/consolidated/regression-hygiene.js.map +1 -0
  125. package/dist/checks/consolidated/regression.d.ts +20 -0
  126. package/dist/checks/consolidated/regression.d.ts.map +1 -0
  127. package/dist/checks/consolidated/regression.js +121 -0
  128. package/dist/checks/consolidated/regression.js.map +1 -0
  129. package/dist/checks/consolidated/runtime.d.ts +53 -0
  130. package/dist/checks/consolidated/runtime.d.ts.map +1 -0
  131. package/dist/checks/consolidated/runtime.js +160 -0
  132. package/dist/checks/consolidated/runtime.js.map +1 -0
  133. package/dist/checks/consolidated/script-performance.d.ts +17 -0
  134. package/dist/checks/consolidated/script-performance.d.ts.map +1 -0
  135. package/dist/checks/consolidated/script-performance.js +137 -0
  136. package/dist/checks/consolidated/script-performance.js.map +1 -0
  137. package/dist/checks/consolidated/security.d.ts +78 -0
  138. package/dist/checks/consolidated/security.d.ts.map +1 -0
  139. package/dist/checks/consolidated/security.js +404 -0
  140. package/dist/checks/consolidated/security.js.map +1 -0
  141. package/dist/checks/consolidated/seo.d.ts +31 -0
  142. package/dist/checks/consolidated/seo.d.ts.map +1 -0
  143. package/dist/checks/consolidated/seo.js +1438 -0
  144. package/dist/checks/consolidated/seo.js.map +1 -0
  145. package/dist/checks/consolidated/sx-prop-deprecation.d.ts +22 -0
  146. package/dist/checks/consolidated/sx-prop-deprecation.d.ts.map +1 -0
  147. package/dist/checks/consolidated/sx-prop-deprecation.js +280 -0
  148. package/dist/checks/consolidated/sx-prop-deprecation.js.map +1 -0
  149. package/dist/checks/consolidated/tailwind-class-validation.d.ts +25 -0
  150. package/dist/checks/consolidated/tailwind-class-validation.d.ts.map +1 -0
  151. package/dist/checks/consolidated/tailwind-class-validation.js +533 -0
  152. package/dist/checks/consolidated/tailwind-class-validation.js.map +1 -0
  153. package/dist/checks/consolidated/testing.d.ts +54 -0
  154. package/dist/checks/consolidated/testing.d.ts.map +1 -0
  155. package/dist/checks/consolidated/testing.js +163 -0
  156. package/dist/checks/consolidated/testing.js.map +1 -0
  157. package/dist/checks/consolidated/typescript.d.ts +3 -0
  158. package/dist/checks/consolidated/typescript.d.ts.map +1 -0
  159. package/dist/checks/consolidated/typescript.js +31 -0
  160. package/dist/checks/consolidated/typescript.js.map +1 -0
  161. package/dist/checks/consolidated/ui-accessibility-advanced.d.ts +104 -0
  162. package/dist/checks/consolidated/ui-accessibility-advanced.d.ts.map +1 -0
  163. package/dist/checks/consolidated/ui-accessibility-advanced.js +689 -0
  164. package/dist/checks/consolidated/ui-accessibility-advanced.js.map +1 -0
  165. package/dist/checks/consolidated/ui-accessibility.d.ts +121 -0
  166. package/dist/checks/consolidated/ui-accessibility.d.ts.map +1 -0
  167. package/dist/checks/consolidated/ui-accessibility.js +776 -0
  168. package/dist/checks/consolidated/ui-accessibility.js.map +1 -0
  169. package/dist/checks/consolidated/ui-advanced-spacing.d.ts +142 -0
  170. package/dist/checks/consolidated/ui-advanced-spacing.d.ts.map +1 -0
  171. package/dist/checks/consolidated/ui-advanced-spacing.js +1220 -0
  172. package/dist/checks/consolidated/ui-advanced-spacing.js.map +1 -0
  173. package/dist/checks/consolidated/ui-animation-duration.d.ts +108 -0
  174. package/dist/checks/consolidated/ui-animation-duration.d.ts.map +1 -0
  175. package/dist/checks/consolidated/ui-animation-duration.js +531 -0
  176. package/dist/checks/consolidated/ui-animation-duration.js.map +1 -0
  177. package/dist/checks/consolidated/ui-border-radius.d.ts +90 -0
  178. package/dist/checks/consolidated/ui-border-radius.d.ts.map +1 -0
  179. package/dist/checks/consolidated/ui-border-radius.js +519 -0
  180. package/dist/checks/consolidated/ui-border-radius.js.map +1 -0
  181. package/dist/checks/consolidated/ui-buttons.d.ts +32 -0
  182. package/dist/checks/consolidated/ui-buttons.d.ts.map +1 -0
  183. package/dist/checks/consolidated/ui-buttons.js +481 -0
  184. package/dist/checks/consolidated/ui-buttons.js.map +1 -0
  185. package/dist/checks/consolidated/ui-cards.d.ts +29 -0
  186. package/dist/checks/consolidated/ui-cards.d.ts.map +1 -0
  187. package/dist/checks/consolidated/ui-cards.js +504 -0
  188. package/dist/checks/consolidated/ui-cards.js.map +1 -0
  189. package/dist/checks/consolidated/ui-checks.d.ts +48 -0
  190. package/dist/checks/consolidated/ui-checks.d.ts.map +1 -0
  191. package/dist/checks/consolidated/ui-checks.js +264 -0
  192. package/dist/checks/consolidated/ui-checks.js.map +1 -0
  193. package/dist/checks/consolidated/ui-cleanup.d.ts +81 -0
  194. package/dist/checks/consolidated/ui-cleanup.d.ts.map +1 -0
  195. package/dist/checks/consolidated/ui-cleanup.js +650 -0
  196. package/dist/checks/consolidated/ui-cleanup.js.map +1 -0
  197. package/dist/checks/consolidated/ui-components.d.ts +255 -0
  198. package/dist/checks/consolidated/ui-components.d.ts.map +1 -0
  199. package/dist/checks/consolidated/ui-components.js +2008 -0
  200. package/dist/checks/consolidated/ui-components.js.map +1 -0
  201. package/dist/checks/consolidated/ui-consistency-advanced.d.ts +130 -0
  202. package/dist/checks/consolidated/ui-consistency-advanced.d.ts.map +1 -0
  203. package/dist/checks/consolidated/ui-consistency-advanced.js +982 -0
  204. package/dist/checks/consolidated/ui-consistency-advanced.js.map +1 -0
  205. package/dist/checks/consolidated/ui-consistency-comprehensive.d.ts +30 -0
  206. package/dist/checks/consolidated/ui-consistency-comprehensive.d.ts.map +1 -0
  207. package/dist/checks/consolidated/ui-consistency-comprehensive.js +1018 -0
  208. package/dist/checks/consolidated/ui-consistency-comprehensive.js.map +1 -0
  209. package/dist/checks/consolidated/ui-consistency-extended.d.ts +26 -0
  210. package/dist/checks/consolidated/ui-consistency-extended.d.ts.map +1 -0
  211. package/dist/checks/consolidated/ui-consistency-extended.js +606 -0
  212. package/dist/checks/consolidated/ui-consistency-extended.js.map +1 -0
  213. package/dist/checks/consolidated/ui-data-display.d.ts +103 -0
  214. package/dist/checks/consolidated/ui-data-display.d.ts.map +1 -0
  215. package/dist/checks/consolidated/ui-data-display.js +740 -0
  216. package/dist/checks/consolidated/ui-data-display.js.map +1 -0
  217. package/dist/checks/consolidated/ui-deprecated.d.ts +22 -0
  218. package/dist/checks/consolidated/ui-deprecated.d.ts.map +1 -0
  219. package/dist/checks/consolidated/ui-deprecated.js +336 -0
  220. package/dist/checks/consolidated/ui-deprecated.js.map +1 -0
  221. package/dist/checks/consolidated/ui-empty-null-states.d.ts +90 -0
  222. package/dist/checks/consolidated/ui-empty-null-states.d.ts.map +1 -0
  223. package/dist/checks/consolidated/ui-empty-null-states.js +511 -0
  224. package/dist/checks/consolidated/ui-empty-null-states.js.map +1 -0
  225. package/dist/checks/consolidated/ui-error-states.d.ts +99 -0
  226. package/dist/checks/consolidated/ui-error-states.d.ts.map +1 -0
  227. package/dist/checks/consolidated/ui-error-states.js +694 -0
  228. package/dist/checks/consolidated/ui-error-states.js.map +1 -0
  229. package/dist/checks/consolidated/ui-feedback-confirmations.d.ts +90 -0
  230. package/dist/checks/consolidated/ui-feedback-confirmations.d.ts.map +1 -0
  231. package/dist/checks/consolidated/ui-feedback-confirmations.js +596 -0
  232. package/dist/checks/consolidated/ui-feedback-confirmations.js.map +1 -0
  233. package/dist/checks/consolidated/ui-forms.d.ts +32 -0
  234. package/dist/checks/consolidated/ui-forms.d.ts.map +1 -0
  235. package/dist/checks/consolidated/ui-forms.js +568 -0
  236. package/dist/checks/consolidated/ui-forms.js.map +1 -0
  237. package/dist/checks/consolidated/ui-gradient-shadow.d.ts +90 -0
  238. package/dist/checks/consolidated/ui-gradient-shadow.d.ts.map +1 -0
  239. package/dist/checks/consolidated/ui-gradient-shadow.js +568 -0
  240. package/dist/checks/consolidated/ui-gradient-shadow.js.map +1 -0
  241. package/dist/checks/consolidated/ui-grid-responsive.d.ts +27 -0
  242. package/dist/checks/consolidated/ui-grid-responsive.d.ts.map +1 -0
  243. package/dist/checks/consolidated/ui-grid-responsive.js +441 -0
  244. package/dist/checks/consolidated/ui-grid-responsive.js.map +1 -0
  245. package/dist/checks/consolidated/ui-icon-size-tokens.d.ts +104 -0
  246. package/dist/checks/consolidated/ui-icon-size-tokens.d.ts.map +1 -0
  247. package/dist/checks/consolidated/ui-icon-size-tokens.js +514 -0
  248. package/dist/checks/consolidated/ui-icon-size-tokens.js.map +1 -0
  249. package/dist/checks/consolidated/ui-iconography.d.ts +90 -0
  250. package/dist/checks/consolidated/ui-iconography.d.ts.map +1 -0
  251. package/dist/checks/consolidated/ui-iconography.js +565 -0
  252. package/dist/checks/consolidated/ui-iconography.js.map +1 -0
  253. package/dist/checks/consolidated/ui-interactive-states.d.ts +240 -0
  254. package/dist/checks/consolidated/ui-interactive-states.d.ts.map +1 -0
  255. package/dist/checks/consolidated/ui-interactive-states.js +2474 -0
  256. package/dist/checks/consolidated/ui-interactive-states.js.map +1 -0
  257. package/dist/checks/consolidated/ui-layout.d.ts +256 -0
  258. package/dist/checks/consolidated/ui-layout.d.ts.map +1 -0
  259. package/dist/checks/consolidated/ui-layout.js +1371 -0
  260. package/dist/checks/consolidated/ui-layout.js.map +1 -0
  261. package/dist/checks/consolidated/ui-loading-skeletons.d.ts +11 -0
  262. package/dist/checks/consolidated/ui-loading-skeletons.d.ts.map +1 -0
  263. package/dist/checks/consolidated/ui-loading-skeletons.js +145 -0
  264. package/dist/checks/consolidated/ui-loading-skeletons.js.map +1 -0
  265. package/dist/checks/consolidated/ui-loading-state-skeletons.d.ts +9 -0
  266. package/dist/checks/consolidated/ui-loading-state-skeletons.d.ts.map +1 -0
  267. package/dist/checks/consolidated/ui-loading-state-skeletons.js +125 -0
  268. package/dist/checks/consolidated/ui-loading-state-skeletons.js.map +1 -0
  269. package/dist/checks/consolidated/ui-media.d.ts +74 -0
  270. package/dist/checks/consolidated/ui-media.d.ts.map +1 -0
  271. package/dist/checks/consolidated/ui-media.js +408 -0
  272. package/dist/checks/consolidated/ui-media.js.map +1 -0
  273. package/dist/checks/consolidated/ui-micro-interactions.d.ts +107 -0
  274. package/dist/checks/consolidated/ui-micro-interactions.d.ts.map +1 -0
  275. package/dist/checks/consolidated/ui-micro-interactions.js +825 -0
  276. package/dist/checks/consolidated/ui-micro-interactions.js.map +1 -0
  277. package/dist/checks/consolidated/ui-microcopy-consistency.d.ts +114 -0
  278. package/dist/checks/consolidated/ui-microcopy-consistency.d.ts.map +1 -0
  279. package/dist/checks/consolidated/ui-microcopy-consistency.js +566 -0
  280. package/dist/checks/consolidated/ui-microcopy-consistency.js.map +1 -0
  281. package/dist/checks/consolidated/ui-mobile-ux.d.ts +251 -0
  282. package/dist/checks/consolidated/ui-mobile-ux.d.ts.map +1 -0
  283. package/dist/checks/consolidated/ui-mobile-ux.js +2212 -0
  284. package/dist/checks/consolidated/ui-mobile-ux.js.map +1 -0
  285. package/dist/checks/consolidated/ui-motion-accessibility.d.ts +93 -0
  286. package/dist/checks/consolidated/ui-motion-accessibility.d.ts.map +1 -0
  287. package/dist/checks/consolidated/ui-motion-accessibility.js +450 -0
  288. package/dist/checks/consolidated/ui-motion-accessibility.js.map +1 -0
  289. package/dist/checks/consolidated/ui-navigation.d.ts +85 -0
  290. package/dist/checks/consolidated/ui-navigation.d.ts.map +1 -0
  291. package/dist/checks/consolidated/ui-navigation.js +673 -0
  292. package/dist/checks/consolidated/ui-navigation.js.map +1 -0
  293. package/dist/checks/consolidated/ui-patterns.d.ts +174 -0
  294. package/dist/checks/consolidated/ui-patterns.d.ts.map +1 -0
  295. package/dist/checks/consolidated/ui-patterns.js +1532 -0
  296. package/dist/checks/consolidated/ui-patterns.js.map +1 -0
  297. package/dist/checks/consolidated/ui-responsive.d.ts +89 -0
  298. package/dist/checks/consolidated/ui-responsive.d.ts.map +1 -0
  299. package/dist/checks/consolidated/ui-responsive.js +588 -0
  300. package/dist/checks/consolidated/ui-responsive.js.map +1 -0
  301. package/dist/checks/consolidated/ui-spacing-standards.d.ts +43 -0
  302. package/dist/checks/consolidated/ui-spacing-standards.d.ts.map +1 -0
  303. package/dist/checks/consolidated/ui-spacing-standards.js +874 -0
  304. package/dist/checks/consolidated/ui-spacing-standards.js.map +1 -0
  305. package/dist/checks/consolidated/ui-spacing.d.ts +751 -0
  306. package/dist/checks/consolidated/ui-spacing.d.ts.map +1 -0
  307. package/dist/checks/consolidated/ui-spacing.js +4996 -0
  308. package/dist/checks/consolidated/ui-spacing.js.map +1 -0
  309. package/dist/checks/consolidated/ui-standards-auto-fixer.d.ts +70 -0
  310. package/dist/checks/consolidated/ui-standards-auto-fixer.d.ts.map +1 -0
  311. package/dist/checks/consolidated/ui-standards-auto-fixer.js +429 -0
  312. package/dist/checks/consolidated/ui-standards-auto-fixer.js.map +1 -0
  313. package/dist/checks/consolidated/ui-standards-enforcement.d.ts +100 -0
  314. package/dist/checks/consolidated/ui-standards-enforcement.d.ts.map +1 -0
  315. package/dist/checks/consolidated/ui-standards-enforcement.js +935 -0
  316. package/dist/checks/consolidated/ui-standards-enforcement.js.map +1 -0
  317. package/dist/checks/consolidated/ui-state-consistency.d.ts +90 -0
  318. package/dist/checks/consolidated/ui-state-consistency.d.ts.map +1 -0
  319. package/dist/checks/consolidated/ui-state-consistency.js +659 -0
  320. package/dist/checks/consolidated/ui-state-consistency.js.map +1 -0
  321. package/dist/checks/consolidated/ui-style-validation.d.ts +74 -0
  322. package/dist/checks/consolidated/ui-style-validation.d.ts.map +1 -0
  323. package/dist/checks/consolidated/ui-style-validation.js +403 -0
  324. package/dist/checks/consolidated/ui-style-validation.js.map +1 -0
  325. package/dist/checks/consolidated/ui-tokens.d.ts +110 -0
  326. package/dist/checks/consolidated/ui-tokens.d.ts.map +1 -0
  327. package/dist/checks/consolidated/ui-tokens.js +990 -0
  328. package/dist/checks/consolidated/ui-tokens.js.map +1 -0
  329. package/dist/checks/consolidated/ui-typography.d.ts +77 -0
  330. package/dist/checks/consolidated/ui-typography.d.ts.map +1 -0
  331. package/dist/checks/consolidated/ui-typography.js +416 -0
  332. package/dist/checks/consolidated/ui-typography.js.map +1 -0
  333. package/dist/checks/consolidated/ui-visual-hierarchy.d.ts +90 -0
  334. package/dist/checks/consolidated/ui-visual-hierarchy.d.ts.map +1 -0
  335. package/dist/checks/consolidated/ui-visual-hierarchy.js +562 -0
  336. package/dist/checks/consolidated/ui-visual-hierarchy.js.map +1 -0
  337. package/dist/checks/consolidated/woocommerce.d.ts +50 -0
  338. package/dist/checks/consolidated/woocommerce.d.ts.map +1 -0
  339. package/dist/checks/consolidated/woocommerce.js +198 -0
  340. package/dist/checks/consolidated/woocommerce.js.map +1 -0
  341. package/dist/checks/core/api-route-protection.d.ts +2 -0
  342. package/dist/checks/core/api-route-protection.d.ts.map +1 -0
  343. package/dist/checks/core/api-route-protection.js +101 -0
  344. package/dist/checks/core/api-route-protection.js.map +1 -0
  345. package/dist/checks/core/critical.d.ts +8 -0
  346. package/dist/checks/core/critical.d.ts.map +1 -0
  347. package/dist/checks/core/critical.js +200 -0
  348. package/dist/checks/core/critical.js.map +1 -0
  349. package/dist/checks/core/database.d.ts +8 -0
  350. package/dist/checks/core/database.d.ts.map +1 -0
  351. package/dist/checks/core/database.js +699 -0
  352. package/dist/checks/core/database.js.map +1 -0
  353. package/dist/checks/core/development.d.ts +8 -0
  354. package/dist/checks/core/development.d.ts.map +1 -0
  355. package/dist/checks/core/development.js +417 -0
  356. package/dist/checks/core/development.js.map +1 -0
  357. package/dist/checks/core/hydration-mismatch-check.d.ts +38 -0
  358. package/dist/checks/core/hydration-mismatch-check.d.ts.map +1 -0
  359. package/dist/checks/core/hydration-mismatch-check.js +411 -0
  360. package/dist/checks/core/hydration-mismatch-check.js.map +1 -0
  361. package/dist/checks/core/performance.d.ts +8 -0
  362. package/dist/checks/core/performance.d.ts.map +1 -0
  363. package/dist/checks/core/performance.js +474 -0
  364. package/dist/checks/core/performance.js.map +1 -0
  365. package/dist/checks/core/security.d.ts +8 -0
  366. package/dist/checks/core/security.d.ts.map +1 -0
  367. package/dist/checks/core/security.js +275 -0
  368. package/dist/checks/core/security.js.map +1 -0
  369. package/dist/checks/core/standardized-error-handling.d.ts +43 -0
  370. package/dist/checks/core/standardized-error-handling.d.ts.map +1 -0
  371. package/dist/checks/core/standardized-error-handling.js +384 -0
  372. package/dist/checks/core/standardized-error-handling.js.map +1 -0
  373. package/dist/checks/core/supercatch.d.ts +8 -0
  374. package/dist/checks/core/supercatch.d.ts.map +1 -0
  375. package/dist/checks/core/supercatch.js +750 -0
  376. package/dist/checks/core/supercatch.js.map +1 -0
  377. package/dist/checks/core/suppression-check.d.ts +2 -0
  378. package/dist/checks/core/suppression-check.d.ts.map +1 -0
  379. package/dist/checks/core/suppression-check.js +129 -0
  380. package/dist/checks/core/suppression-check.js.map +1 -0
  381. package/dist/checks/core/ui-quality.d.ts +8 -0
  382. package/dist/checks/core/ui-quality.d.ts.map +1 -0
  383. package/dist/checks/core/ui-quality.js +1736 -0
  384. package/dist/checks/core/ui-quality.js.map +1 -0
  385. package/dist/checks/core/unused-assets-check.d.ts +2 -0
  386. package/dist/checks/core/unused-assets-check.d.ts.map +1 -0
  387. package/dist/checks/core/unused-assets-check.js +112 -0
  388. package/dist/checks/core/unused-assets-check.js.map +1 -0
  389. package/dist/checks/core/use-status-ssr-safety.d.ts +34 -0
  390. package/dist/checks/core/use-status-ssr-safety.d.ts.map +1 -0
  391. package/dist/checks/core/use-status-ssr-safety.js +283 -0
  392. package/dist/checks/core/use-status-ssr-safety.js.map +1 -0
  393. package/dist/checks/email/email-flow-validation.d.ts +23 -0
  394. package/dist/checks/email/email-flow-validation.d.ts.map +1 -0
  395. package/dist/checks/email/email-flow-validation.js +468 -0
  396. package/dist/checks/email/email-flow-validation.js.map +1 -0
  397. package/dist/checks/email/email-template-db-verification.d.ts +20 -0
  398. package/dist/checks/email/email-template-db-verification.d.ts.map +1 -0
  399. package/dist/checks/email/email-template-db-verification.js +46 -0
  400. package/dist/checks/email/email-template-db-verification.js.map +1 -0
  401. package/dist/checks/email/email-template-validation.d.ts +24 -0
  402. package/dist/checks/email/email-template-validation.d.ts.map +1 -0
  403. package/dist/checks/email/email-template-validation.js +688 -0
  404. package/dist/checks/email/email-template-validation.js.map +1 -0
  405. package/dist/checks/jsx/comment-placement.d.ts +45 -0
  406. package/dist/checks/jsx/comment-placement.d.ts.map +1 -0
  407. package/dist/checks/jsx/comment-placement.js +316 -0
  408. package/dist/checks/jsx/comment-placement.js.map +1 -0
  409. package/dist/checks/specialized/admin-layout-check.d.ts +19 -0
  410. package/dist/checks/specialized/admin-layout-check.d.ts.map +1 -0
  411. package/dist/checks/specialized/admin-layout-check.js +166 -0
  412. package/dist/checks/specialized/admin-layout-check.js.map +1 -0
  413. package/dist/checks/specialized/client-server-separation.d.ts +14 -0
  414. package/dist/checks/specialized/client-server-separation.d.ts.map +1 -0
  415. package/dist/checks/specialized/client-server-separation.js +197 -0
  416. package/dist/checks/specialized/client-server-separation.js.map +1 -0
  417. package/dist/checks/specialized/cost-optimization.d.ts +18 -0
  418. package/dist/checks/specialized/cost-optimization.d.ts.map +1 -0
  419. package/dist/checks/specialized/cost-optimization.js +78 -0
  420. package/dist/checks/specialized/cost-optimization.js.map +1 -0
  421. package/dist/checks/specialized/database-migration-sync.d.ts +21 -0
  422. package/dist/checks/specialized/database-migration-sync.d.ts.map +1 -0
  423. package/dist/checks/specialized/database-migration-sync.js +150 -0
  424. package/dist/checks/specialized/database-migration-sync.js.map +1 -0
  425. package/dist/checks/specialized/database-model-validation.d.ts +15 -0
  426. package/dist/checks/specialized/database-model-validation.d.ts.map +1 -0
  427. package/dist/checks/specialized/database-model-validation.js +35 -0
  428. package/dist/checks/specialized/database-model-validation.js.map +1 -0
  429. package/dist/checks/specialized/database-schema-migrations-diff.d.ts +27 -0
  430. package/dist/checks/specialized/database-schema-migrations-diff.d.ts.map +1 -0
  431. package/dist/checks/specialized/database-schema-migrations-diff.js +177 -0
  432. package/dist/checks/specialized/database-schema-migrations-diff.js.map +1 -0
  433. package/dist/checks/specialized/database-schema-sync.d.ts +23 -0
  434. package/dist/checks/specialized/database-schema-sync.d.ts.map +1 -0
  435. package/dist/checks/specialized/database-schema-sync.js +77 -0
  436. package/dist/checks/specialized/database-schema-sync.js.map +1 -0
  437. package/dist/checks/specialized/decimal-serialization.d.ts +24 -0
  438. package/dist/checks/specialized/decimal-serialization.d.ts.map +1 -0
  439. package/dist/checks/specialized/decimal-serialization.js +400 -0
  440. package/dist/checks/specialized/decimal-serialization.js.map +1 -0
  441. package/dist/checks/specialized/detect-router-issues.d.ts +14 -0
  442. package/dist/checks/specialized/detect-router-issues.d.ts.map +1 -0
  443. package/dist/checks/specialized/detect-router-issues.js +96 -0
  444. package/dist/checks/specialized/detect-router-issues.js.map +1 -0
  445. package/dist/checks/specialized/enum-validation.d.ts +15 -0
  446. package/dist/checks/specialized/enum-validation.d.ts.map +1 -0
  447. package/dist/checks/specialized/enum-validation.js +35 -0
  448. package/dist/checks/specialized/enum-validation.js.map +1 -0
  449. package/dist/checks/specialized/hash-collision.d.ts +18 -0
  450. package/dist/checks/specialized/hash-collision.d.ts.map +1 -0
  451. package/dist/checks/specialized/hash-collision.js +78 -0
  452. package/dist/checks/specialized/hash-collision.js.map +1 -0
  453. package/dist/checks/specialized/id-generation-enforcement.d.ts +16 -0
  454. package/dist/checks/specialized/id-generation-enforcement.d.ts.map +1 -0
  455. package/dist/checks/specialized/id-generation-enforcement.js +307 -0
  456. package/dist/checks/specialized/id-generation-enforcement.js.map +1 -0
  457. package/dist/checks/specialized/image-data-integrity.d.ts +15 -0
  458. package/dist/checks/specialized/image-data-integrity.d.ts.map +1 -0
  459. package/dist/checks/specialized/image-data-integrity.js +79 -0
  460. package/dist/checks/specialized/image-data-integrity.js.map +1 -0
  461. package/dist/checks/specialized/image-health.d.ts +14 -0
  462. package/dist/checks/specialized/image-health.d.ts.map +1 -0
  463. package/dist/checks/specialized/image-health.js +122 -0
  464. package/dist/checks/specialized/image-health.js.map +1 -0
  465. package/dist/checks/specialized/image-metadata-validation.d.ts +14 -0
  466. package/dist/checks/specialized/image-metadata-validation.d.ts.map +1 -0
  467. package/dist/checks/specialized/image-metadata-validation.js +95 -0
  468. package/dist/checks/specialized/image-metadata-validation.js.map +1 -0
  469. package/dist/checks/specialized/image-optimization.d.ts +16 -0
  470. package/dist/checks/specialized/image-optimization.d.ts.map +1 -0
  471. package/dist/checks/specialized/image-optimization.js +86 -0
  472. package/dist/checks/specialized/image-optimization.js.map +1 -0
  473. package/dist/checks/specialized/invalid-module-imports.d.ts +24 -0
  474. package/dist/checks/specialized/invalid-module-imports.d.ts.map +1 -0
  475. package/dist/checks/specialized/invalid-module-imports.js +209 -0
  476. package/dist/checks/specialized/invalid-module-imports.js.map +1 -0
  477. package/dist/checks/specialized/lint-validation.d.ts +26 -0
  478. package/dist/checks/specialized/lint-validation.d.ts.map +1 -0
  479. package/dist/checks/specialized/lint-validation.js +193 -0
  480. package/dist/checks/specialized/lint-validation.js.map +1 -0
  481. package/dist/checks/specialized/listing-workflow.d.ts +19 -0
  482. package/dist/checks/specialized/listing-workflow.d.ts.map +1 -0
  483. package/dist/checks/specialized/listing-workflow.js +89 -0
  484. package/dist/checks/specialized/listing-workflow.js.map +1 -0
  485. package/dist/checks/specialized/mui-imports-validation.d.ts +18 -0
  486. package/dist/checks/specialized/mui-imports-validation.d.ts.map +1 -0
  487. package/dist/checks/specialized/mui-imports-validation.js +134 -0
  488. package/dist/checks/specialized/mui-imports-validation.js.map +1 -0
  489. package/dist/checks/specialized/nextauth-v5-compliance.d.ts +16 -0
  490. package/dist/checks/specialized/nextauth-v5-compliance.d.ts.map +1 -0
  491. package/dist/checks/specialized/nextauth-v5-compliance.js +164 -0
  492. package/dist/checks/specialized/nextauth-v5-compliance.js.map +1 -0
  493. package/dist/checks/specialized/nextjs-params-check.d.ts +14 -0
  494. package/dist/checks/specialized/nextjs-params-check.d.ts.map +1 -0
  495. package/dist/checks/specialized/nextjs-params-check.js +140 -0
  496. package/dist/checks/specialized/nextjs-params-check.js.map +1 -0
  497. package/dist/checks/specialized/no-legacy-catalog-aliases-validation.d.ts +16 -0
  498. package/dist/checks/specialized/no-legacy-catalog-aliases-validation.d.ts.map +1 -0
  499. package/dist/checks/specialized/no-legacy-catalog-aliases-validation.js +36 -0
  500. package/dist/checks/specialized/no-legacy-catalog-aliases-validation.js.map +1 -0
  501. package/dist/checks/specialized/no-wata-cardgraded-validation.d.ts +22 -0
  502. package/dist/checks/specialized/no-wata-cardgraded-validation.d.ts.map +1 -0
  503. package/dist/checks/specialized/no-wata-cardgraded-validation.js +97 -0
  504. package/dist/checks/specialized/no-wata-cardgraded-validation.js.map +1 -0
  505. package/dist/checks/specialized/parameter-consistency-check.d.ts +20 -0
  506. package/dist/checks/specialized/parameter-consistency-check.d.ts.map +1 -0
  507. package/dist/checks/specialized/parameter-consistency-check.js +115 -0
  508. package/dist/checks/specialized/parameter-consistency-check.js.map +1 -0
  509. package/dist/checks/specialized/prisma-field-names-validation.d.ts +15 -0
  510. package/dist/checks/specialized/prisma-field-names-validation.d.ts.map +1 -0
  511. package/dist/checks/specialized/prisma-field-names-validation.js +35 -0
  512. package/dist/checks/specialized/prisma-field-names-validation.js.map +1 -0
  513. package/dist/checks/specialized/prisma-null-syntax.d.ts +34 -0
  514. package/dist/checks/specialized/prisma-null-syntax.d.ts.map +1 -0
  515. package/dist/checks/specialized/prisma-null-syntax.js +330 -0
  516. package/dist/checks/specialized/prisma-null-syntax.js.map +1 -0
  517. package/dist/checks/specialized/prisma-query-validation.d.ts +15 -0
  518. package/dist/checks/specialized/prisma-query-validation.d.ts.map +1 -0
  519. package/dist/checks/specialized/prisma-query-validation.js +35 -0
  520. package/dist/checks/specialized/prisma-query-validation.js.map +1 -0
  521. package/dist/checks/specialized/product-type-validation.d.ts +17 -0
  522. package/dist/checks/specialized/product-type-validation.d.ts.map +1 -0
  523. package/dist/checks/specialized/product-type-validation.js +129 -0
  524. package/dist/checks/specialized/product-type-validation.js.map +1 -0
  525. package/dist/checks/specialized/responsive-image-validation.d.ts +14 -0
  526. package/dist/checks/specialized/responsive-image-validation.d.ts.map +1 -0
  527. package/dist/checks/specialized/responsive-image-validation.js +101 -0
  528. package/dist/checks/specialized/responsive-image-validation.js.map +1 -0
  529. package/dist/checks/specialized/root-cleanliness.d.ts +21 -0
  530. package/dist/checks/specialized/root-cleanliness.d.ts.map +1 -0
  531. package/dist/checks/specialized/root-cleanliness.js +251 -0
  532. package/dist/checks/specialized/root-cleanliness.js.map +1 -0
  533. package/dist/checks/specialized/rotation-detection-validation.d.ts +16 -0
  534. package/dist/checks/specialized/rotation-detection-validation.d.ts.map +1 -0
  535. package/dist/checks/specialized/rotation-detection-validation.js +113 -0
  536. package/dist/checks/specialized/rotation-detection-validation.js.map +1 -0
  537. package/dist/checks/specialized/script-organization.d.ts +17 -0
  538. package/dist/checks/specialized/script-organization.d.ts.map +1 -0
  539. package/dist/checks/specialized/script-organization.js +487 -0
  540. package/dist/checks/specialized/script-organization.js.map +1 -0
  541. package/dist/checks/specialized/shared-components-migration.d.ts +137 -0
  542. package/dist/checks/specialized/shared-components-migration.d.ts.map +1 -0
  543. package/dist/checks/specialized/shared-components-migration.js +1288 -0
  544. package/dist/checks/specialized/shared-components-migration.js.map +1 -0
  545. package/dist/checks/specialized/store-specialties-normalization.d.ts +10 -0
  546. package/dist/checks/specialized/store-specialties-normalization.d.ts.map +1 -0
  547. package/dist/checks/specialized/store-specialties-normalization.js +126 -0
  548. package/dist/checks/specialized/store-specialties-normalization.js.map +1 -0
  549. package/dist/checks/specialized/two-stage-trim-validation.d.ts +16 -0
  550. package/dist/checks/specialized/two-stage-trim-validation.d.ts.map +1 -0
  551. package/dist/checks/specialized/two-stage-trim-validation.js +115 -0
  552. package/dist/checks/specialized/two-stage-trim-validation.js.map +1 -0
  553. package/dist/checks/specialized/underscore-variable-audit.d.ts +26 -0
  554. package/dist/checks/specialized/underscore-variable-audit.d.ts.map +1 -0
  555. package/dist/checks/specialized/underscore-variable-audit.js +219 -0
  556. package/dist/checks/specialized/underscore-variable-audit.js.map +1 -0
  557. package/dist/checks/specialized/unified-badge-consistency.d.ts +16 -0
  558. package/dist/checks/specialized/unified-badge-consistency.d.ts.map +1 -0
  559. package/dist/checks/specialized/unified-badge-consistency.js +284 -0
  560. package/dist/checks/specialized/unified-badge-consistency.js.map +1 -0
  561. package/dist/checks/specialized/validate-integration-enums.d.ts +15 -0
  562. package/dist/checks/specialized/validate-integration-enums.d.ts.map +1 -0
  563. package/dist/checks/specialized/validate-integration-enums.js +131 -0
  564. package/dist/checks/specialized/validate-integration-enums.js.map +1 -0
  565. package/dist/checks/testing/action-regression.d.ts +23 -0
  566. package/dist/checks/testing/action-regression.d.ts.map +1 -0
  567. package/dist/checks/testing/action-regression.js +192 -0
  568. package/dist/checks/testing/action-regression.js.map +1 -0
  569. package/dist/checks/testing/critical-api-coverage.d.ts +21 -0
  570. package/dist/checks/testing/critical-api-coverage.d.ts.map +1 -0
  571. package/dist/checks/testing/critical-api-coverage.js +158 -0
  572. package/dist/checks/testing/critical-api-coverage.js.map +1 -0
  573. package/dist/checks/testing/data-entry-regression-required.d.ts +24 -0
  574. package/dist/checks/testing/data-entry-regression-required.d.ts.map +1 -0
  575. package/dist/checks/testing/data-entry-regression-required.js +378 -0
  576. package/dist/checks/testing/data-entry-regression-required.js.map +1 -0
  577. package/dist/checks/testing/e2e-best-practices.d.ts +24 -0
  578. package/dist/checks/testing/e2e-best-practices.d.ts.map +1 -0
  579. package/dist/checks/testing/e2e-best-practices.js +791 -0
  580. package/dist/checks/testing/e2e-best-practices.js.map +1 -0
  581. package/dist/checks/testing/e2e-flake-patterns.d.ts +26 -0
  582. package/dist/checks/testing/e2e-flake-patterns.d.ts.map +1 -0
  583. package/dist/checks/testing/e2e-flake-patterns.js +305 -0
  584. package/dist/checks/testing/e2e-flake-patterns.js.map +1 -0
  585. package/dist/checks/testing/e2e-redundant-visibility-checks.d.ts +25 -0
  586. package/dist/checks/testing/e2e-redundant-visibility-checks.d.ts.map +1 -0
  587. package/dist/checks/testing/e2e-redundant-visibility-checks.js +613 -0
  588. package/dist/checks/testing/e2e-redundant-visibility-checks.js.map +1 -0
  589. package/dist/checks/testing/e2e-slow-tests.d.ts +9 -0
  590. package/dist/checks/testing/e2e-slow-tests.d.ts.map +1 -0
  591. package/dist/checks/testing/e2e-slow-tests.js +142 -0
  592. package/dist/checks/testing/e2e-slow-tests.js.map +1 -0
  593. package/dist/checks/testing/e2e-timeouts.d.ts +9 -0
  594. package/dist/checks/testing/e2e-timeouts.d.ts.map +1 -0
  595. package/dist/checks/testing/e2e-timeouts.js +82 -0
  596. package/dist/checks/testing/e2e-timeouts.js.map +1 -0
  597. package/dist/checks/testing/integration-e2e-depth.d.ts +20 -0
  598. package/dist/checks/testing/integration-e2e-depth.d.ts.map +1 -0
  599. package/dist/checks/testing/integration-e2e-depth.js +575 -0
  600. package/dist/checks/testing/integration-e2e-depth.js.map +1 -0
  601. package/dist/checks/testing/playwright-feature-coverage-gaps.d.ts +31 -0
  602. package/dist/checks/testing/playwright-feature-coverage-gaps.d.ts.map +1 -0
  603. package/dist/checks/testing/playwright-feature-coverage-gaps.js +1582 -0
  604. package/dist/checks/testing/playwright-feature-coverage-gaps.js.map +1 -0
  605. package/dist/checks/testing/playwright-mock-inventory.d.ts +24 -0
  606. package/dist/checks/testing/playwright-mock-inventory.d.ts.map +1 -0
  607. package/dist/checks/testing/playwright-mock-inventory.js +380 -0
  608. package/dist/checks/testing/playwright-mock-inventory.js.map +1 -0
  609. package/dist/checks/testing/test-coverage-threshold.d.ts +25 -0
  610. package/dist/checks/testing/test-coverage-threshold.d.ts.map +1 -0
  611. package/dist/checks/testing/test-coverage-threshold.js +166 -0
  612. package/dist/checks/testing/test-coverage-threshold.js.map +1 -0
  613. package/dist/checks/testing/test-flakiness-score.d.ts +27 -0
  614. package/dist/checks/testing/test-flakiness-score.d.ts.map +1 -0
  615. package/dist/checks/testing/test-flakiness-score.js +358 -0
  616. package/dist/checks/testing/test-flakiness-score.js.map +1 -0
  617. package/dist/checks/testing/test-patterns.d.ts +16 -0
  618. package/dist/checks/testing/test-patterns.d.ts.map +1 -0
  619. package/dist/checks/testing/test-patterns.js +156 -0
  620. package/dist/checks/testing/test-patterns.js.map +1 -0
  621. package/dist/checks/workflows/a-plus-rating-validation.d.ts +42 -0
  622. package/dist/checks/workflows/a-plus-rating-validation.d.ts.map +1 -0
  623. package/dist/checks/workflows/a-plus-rating-validation.js +527 -0
  624. package/dist/checks/workflows/a-plus-rating-validation.js.map +1 -0
  625. package/dist/checks/workflows/affected.d.ts +14 -0
  626. package/dist/checks/workflows/affected.d.ts.map +1 -0
  627. package/dist/checks/workflows/affected.js +126 -0
  628. package/dist/checks/workflows/affected.js.map +1 -0
  629. package/dist/checks/workflows/ai.d.ts +6 -0
  630. package/dist/checks/workflows/ai.d.ts.map +1 -0
  631. package/dist/checks/workflows/ai.js +42 -0
  632. package/dist/checks/workflows/ai.js.map +1 -0
  633. package/dist/checks/workflows/all.d.ts +31 -0
  634. package/dist/checks/workflows/all.d.ts.map +1 -0
  635. package/dist/checks/workflows/all.js +2688 -0
  636. package/dist/checks/workflows/all.js.map +1 -0
  637. package/dist/checks/workflows/commit.d.ts +19 -0
  638. package/dist/checks/workflows/commit.d.ts.map +1 -0
  639. package/dist/checks/workflows/commit.js +207 -0
  640. package/dist/checks/workflows/commit.js.map +1 -0
  641. package/dist/checks/workflows/critical.d.ts +9 -0
  642. package/dist/checks/workflows/critical.d.ts.map +1 -0
  643. package/dist/checks/workflows/critical.js +213 -0
  644. package/dist/checks/workflows/critical.js.map +1 -0
  645. package/dist/checks/workflows/database-id-validation.d.ts +9 -0
  646. package/dist/checks/workflows/database-id-validation.d.ts.map +1 -0
  647. package/dist/checks/workflows/database-id-validation.js +13 -0
  648. package/dist/checks/workflows/database-id-validation.js.map +1 -0
  649. package/dist/checks/workflows/deploy.d.ts +20 -0
  650. package/dist/checks/workflows/deploy.d.ts.map +1 -0
  651. package/dist/checks/workflows/deploy.js +107 -0
  652. package/dist/checks/workflows/deploy.js.map +1 -0
  653. package/dist/checks/workflows/deployment-readiness.d.ts +12 -0
  654. package/dist/checks/workflows/deployment-readiness.d.ts.map +1 -0
  655. package/dist/checks/workflows/deployment-readiness.js +403 -0
  656. package/dist/checks/workflows/deployment-readiness.js.map +1 -0
  657. package/dist/checks/workflows/dev.d.ts +19 -0
  658. package/dist/checks/workflows/dev.d.ts.map +1 -0
  659. package/dist/checks/workflows/dev.js +88 -0
  660. package/dist/checks/workflows/dev.js.map +1 -0
  661. package/dist/checks/workflows/development.d.ts +9 -0
  662. package/dist/checks/workflows/development.d.ts.map +1 -0
  663. package/dist/checks/workflows/development.js +65 -0
  664. package/dist/checks/workflows/development.js.map +1 -0
  665. package/dist/checks/workflows/enterprise.d.ts +10 -0
  666. package/dist/checks/workflows/enterprise.d.ts.map +1 -0
  667. package/dist/checks/workflows/enterprise.js +359 -0
  668. package/dist/checks/workflows/enterprise.js.map +1 -0
  669. package/dist/checks/workflows/images.d.ts +6 -0
  670. package/dist/checks/workflows/images.d.ts.map +1 -0
  671. package/dist/checks/workflows/images.js +58 -0
  672. package/dist/checks/workflows/images.js.map +1 -0
  673. package/dist/checks/workflows/naming.d.ts +19 -0
  674. package/dist/checks/workflows/naming.d.ts.map +1 -0
  675. package/dist/checks/workflows/naming.js +42 -0
  676. package/dist/checks/workflows/naming.js.map +1 -0
  677. package/dist/checks/workflows/performance.d.ts +8 -0
  678. package/dist/checks/workflows/performance.d.ts.map +1 -0
  679. package/dist/checks/workflows/performance.js +77 -0
  680. package/dist/checks/workflows/performance.js.map +1 -0
  681. package/dist/checks/workflows/pre-deploy.d.ts +6 -0
  682. package/dist/checks/workflows/pre-deploy.d.ts.map +1 -0
  683. package/dist/checks/workflows/pre-deploy.js +41 -0
  684. package/dist/checks/workflows/pre-deploy.js.map +1 -0
  685. package/dist/checks/workflows/security.d.ts +8 -0
  686. package/dist/checks/workflows/security.d.ts.map +1 -0
  687. package/dist/checks/workflows/security.js +71 -0
  688. package/dist/checks/workflows/security.js.map +1 -0
  689. package/dist/checks/workflows/supercatch.d.ts +8 -0
  690. package/dist/checks/workflows/supercatch.d.ts.map +1 -0
  691. package/dist/checks/workflows/supercatch.js +127 -0
  692. package/dist/checks/workflows/supercatch.js.map +1 -0
  693. package/dist/checks/workflows/ui-quality.d.ts +9 -0
  694. package/dist/checks/workflows/ui-quality.d.ts.map +1 -0
  695. package/dist/checks/workflows/ui-quality.js +264 -0
  696. package/dist/checks/workflows/ui-quality.js.map +1 -0
  697. package/dist/checks/workflows/ui-uniformity.d.ts +18 -0
  698. package/dist/checks/workflows/ui-uniformity.d.ts.map +1 -0
  699. package/dist/checks/workflows/ui-uniformity.js +265 -0
  700. package/dist/checks/workflows/ui-uniformity.js.map +1 -0
  701. package/dist/checks/workflows/vercel.d.ts +16 -0
  702. package/dist/checks/workflows/vercel.d.ts.map +1 -0
  703. package/dist/checks/workflows/vercel.js +173 -0
  704. package/dist/checks/workflows/vercel.js.map +1 -0
  705. package/dist/utils/validation-helpers.d.ts +43 -0
  706. package/dist/utils/validation-helpers.d.ts.map +1 -0
  707. package/dist/utils/validation-helpers.js +370 -0
  708. package/dist/utils/validation-helpers.js.map +1 -0
  709. package/package.json +1 -1
@@ -0,0 +1,1546 @@
1
+ #!/usr/bin/env tsx
2
+ "use strict";
3
+ /**
4
+ * Consolidated Performance Preflight
5
+ *
6
+ * Combines 10 performance checks into one module:
7
+ * - bundle (bundle size & large dependencies)
8
+ * - images (image optimization & lazy loading & LCP priority)
9
+ * - lazy (heavy component lazy loading)
10
+ * - skeleton (skeleton loader usage)
11
+ * - virtual (virtual scroll candidates)
12
+ * - zindex (z-index design token usage)
13
+ * - recharts (recharts lazy loading)
14
+ * - dialogs (dialog lazy loading)
15
+ * - queries (N+1 patterns & force-dynamic without caching)
16
+ *
17
+ * Usage:
18
+ * pnpm preflight:perf # All checks
19
+ * pnpm preflight:perf bundle # Bundle size only
20
+ * pnpm preflight:perf images # Image optimization only
21
+ * pnpm preflight:perf lazy # Lazy loading only
22
+ * pnpm preflight:perf skeleton # Skeleton loaders only
23
+ * pnpm preflight:perf virtual # Virtual scroll only
24
+ * pnpm preflight:perf zindex # Z-index tokens only
25
+ * pnpm preflight:perf recharts # Recharts lazy loading only
26
+ * pnpm preflight:perf dialogs # Dialog lazy loading only
27
+ * pnpm preflight:perf queries # Database query efficiency only
28
+ */
29
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
30
+ if (k2 === undefined) k2 = k;
31
+ var desc = Object.getOwnPropertyDescriptor(m, k);
32
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
33
+ desc = { enumerable: true, get: function() { return m[k]; } };
34
+ }
35
+ Object.defineProperty(o, k2, desc);
36
+ }) : (function(o, m, k, k2) {
37
+ if (k2 === undefined) k2 = k;
38
+ o[k2] = m[k];
39
+ }));
40
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
41
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
42
+ }) : function(o, v) {
43
+ o["default"] = v;
44
+ });
45
+ var __importStar = (this && this.__importStar) || (function () {
46
+ var ownKeys = function(o) {
47
+ ownKeys = Object.getOwnPropertyNames || function (o) {
48
+ var ar = [];
49
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
50
+ return ar;
51
+ };
52
+ return ownKeys(o);
53
+ };
54
+ return function (mod) {
55
+ if (mod && mod.__esModule) return mod;
56
+ var result = {};
57
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
58
+ __setModuleDefault(result, mod);
59
+ return result;
60
+ };
61
+ })();
62
+ Object.defineProperty(exports, "__esModule", { value: true });
63
+ exports.PerformancePreflightModule = void 0;
64
+ const child_process_1 = require("child_process");
65
+ const fs = __importStar(require("fs"));
66
+ const net = __importStar(require("net"));
67
+ const path = __importStar(require("path"));
68
+ const playwright_1 = require("playwright");
69
+ const promises_1 = require("timers/promises");
70
+ const console_chars_1 = require("../../utils/console-chars");
71
+ const file_cache_1 = require("../../shared/file-cache");
72
+ const glob_patterns_1 = require("../../shared/glob-patterns");
73
+ const universal_progress_reporter_1 = require("../system/universal-progress-reporter");
74
+ const concurrency_config_1 = require("../../shared/concurrency-config");
75
+ const EXCLUDED = [...glob_patterns_1.STANDARD_EXCLUDES];
76
+ const PREFLIGHT_PORT = Number(process.env.PREFLIGHT_PORT || process.env.PORT || 3000);
77
+ const HOMEPAGE_URL = process.env.PREFLIGHT_BASE_URL || `http://localhost:${PREFLIGHT_PORT}`;
78
+ const DEV_SERVER_START_TIMEOUT = 30_000;
79
+ const PROD_SERVER_START_TIMEOUT = 90_000;
80
+ const PAGELOAD_SERVER_MODE = (process.env.PREFLIGHT_PAGELOAD_SERVER_MODE || "dev");
81
+ const PAGELOAD_NAVIGATION_BUDGET_MS = Number(process.env.PREFLIGHT_PAGELOAD_NAVIGATION_BUDGET_MS || 4_000);
82
+ const PAGELOAD_REQUEST_BUDGET = Number(process.env.PREFLIGHT_PAGELOAD_REQUEST_BUDGET || 14);
83
+ const PAGELOAD_API_DUPLICATE_LIMIT = Number(process.env.PREFLIGHT_PAGELOAD_API_DUPLICATE_LIMIT || 1); // Allow one hit per endpoint by default
84
+ const PAGELOAD_SESSION_DUPLICATE_LIMIT = Number(process.env.PREFLIGHT_PAGELOAD_SESSION_DUPLICATE_LIMIT || 1);
85
+ const PAGELOAD_NOTIFICATION_DUPLICATE_LIMIT = Number(process.env.PREFLIGHT_PAGELOAD_NOTIFICATION_DUPLICATE_LIMIT || 1);
86
+ const PAGELOAD_PRISMA_QUERY_BUDGET = Number(process.env.PREFLIGHT_PAGELOAD_PRISMA_QUERY_BUDGET || 40);
87
+ const PAGELOAD_PRISMA_DUPLICATE_THRESHOLD = Number(process.env.PREFLIGHT_PAGELOAD_PRISMA_DUPLICATE_THRESHOLD || 3);
88
+ const WAIT_FOR_STABLE_NETWORK_MS = Number(process.env.PREFLIGHT_PAGELOAD_STABLE_NETWORK_MS || 1_000);
89
+ const PAGELOAD_TRANSFER_BUDGET_BYTES = Number(process.env.PREFLIGHT_PAGELOAD_TRANSFER_BUDGET_BYTES || 1_000_000); // ~1MB
90
+ const PAGELOAD_ROUTE_TIMEOUT_MS = Number(process.env.PREFLIGHT_PAGELOAD_ROUTE_TIMEOUT_MS || 8_000);
91
+ const PAGELOAD_LOAD_TIMEOUT_MS = Number(process.env.PREFLIGHT_PAGELOAD_LOAD_TIMEOUT_MS || 6_000);
92
+ const PAGELOAD_NETWORKIDLE_TIMEOUT_MS = Number(process.env.PREFLIGHT_PAGELOAD_NETWORKIDLE_TIMEOUT_MS || 2_000);
93
+ const PAGELOAD_PROGRESS_EVERY = Number(process.env.PREFLIGHT_PAGELOAD_PROGRESS_EVERY || 10);
94
+ const PAGELOAD_CONCURRENCY = Math.max(1, Number(process.env.PREFLIGHT_PAGELOAD_CONCURRENCY || 1));
95
+ const PAGELOAD_STRICT = process.env.PREFLIGHT_PAGELOAD_STRICT === "1";
96
+ const PAGELOAD_INCLUDE_SITEMAP = process.env.PREFLIGHT_PAGELOAD_INCLUDE_SITEMAP === "1";
97
+ const PAGELOAD_SITEMAP_MAX_URLS = Math.max(0, Number(process.env.PREFLIGHT_PAGELOAD_SITEMAP_MAX_URLS || 2000));
98
+ const PAGELOAD_ROUTES_CONFIG = process.env.PREFLIGHT_PAGELOAD_ROUTES_CONFIG ||
99
+ path.join(process.cwd(), "scripts/active/preflights/config/page-load-routes.json");
100
+ const DEFAULT_PAGE_ROUTES = ["/"];
101
+ const PNPM_CMD = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
102
+ function normalizeRoute(route) {
103
+ if (!route)
104
+ return "/";
105
+ let normalized = route.trim();
106
+ if (!normalized.startsWith("http")) {
107
+ normalized = normalized.startsWith("/") ? normalized : `/${normalized}`;
108
+ }
109
+ if (normalized.endsWith("/") && normalized !== "/") {
110
+ normalized = normalized.slice(0, -1);
111
+ }
112
+ return normalized;
113
+ }
114
+ function normalizeExampleRoutes(examples) {
115
+ const normalized = {};
116
+ if (!examples)
117
+ return normalized;
118
+ for (const [pattern, value] of Object.entries(examples)) {
119
+ const values = Array.isArray(value) ? value : [value];
120
+ const routes = values.map((v) => normalizeRoute(v)).filter(Boolean);
121
+ if (routes.length > 0)
122
+ normalized[normalizeRoute(pattern)] = routes;
123
+ }
124
+ return normalized;
125
+ }
126
+ function substituteDynamicRoute(template, example) {
127
+ // Replace each [param] segment with example segments in order.
128
+ const templateParts = template.split("/").filter(Boolean);
129
+ const exampleParts = example.split("/").filter(Boolean);
130
+ const out = [];
131
+ let exampleIndex = 0;
132
+ for (const part of templateParts) {
133
+ if (part.startsWith("[") && part.endsWith("]")) {
134
+ if (exampleIndex >= exampleParts.length)
135
+ return null;
136
+ out.push(exampleParts[exampleIndex++]);
137
+ continue;
138
+ }
139
+ out.push(part);
140
+ if (exampleParts[exampleIndex] === part)
141
+ exampleIndex++;
142
+ }
143
+ return `/${out.join("/")}`.replace(/\/+$/, "") || "/";
144
+ }
145
+ function matchRoutePattern(pattern, route) {
146
+ const normalizedPattern = (pattern || "").trim();
147
+ if (!normalizedPattern)
148
+ return false;
149
+ if (normalizedPattern.startsWith("re:")) {
150
+ try {
151
+ return new RegExp(normalizedPattern.slice(3)).test(route);
152
+ }
153
+ catch {
154
+ return false;
155
+ }
156
+ }
157
+ // Simple glob-ish support: '*' means any chars.
158
+ if (normalizedPattern.includes("*")) {
159
+ const escaped = normalizedPattern.replace(/[.+^${}()|[\]\\]/g, "\\$&");
160
+ const regex = new RegExp(`^${escaped.replace(/\*/g, ".*")}$`);
161
+ return regex.test(route);
162
+ }
163
+ // Prefix match support for directory-like patterns.
164
+ if (normalizedPattern.endsWith("/")) {
165
+ return route.startsWith(normalizedPattern);
166
+ }
167
+ return route === normalizedPattern;
168
+ }
169
+ function dynamicTemplateMatchesRoute(template, route) {
170
+ if (!template.includes("["))
171
+ return template === route;
172
+ const escaped = template.replace(/[.+^${}()|[\]\\]/g, "\\$&");
173
+ const regexStr = `^${escaped.replace(/\\\[[^\]]+\\\]/g, "[^/]+")}$`;
174
+ try {
175
+ return new RegExp(regexStr).test(route);
176
+ }
177
+ catch {
178
+ return false;
179
+ }
180
+ }
181
+ function extractSitemapLocs(xml) {
182
+ const locs = [];
183
+ const re = /<loc>([^<]+)<\/loc>/gim;
184
+ let match;
185
+ while ((match = re.exec(xml))) {
186
+ const loc = (match[1] || "").trim();
187
+ if (loc)
188
+ locs.push(loc);
189
+ }
190
+ return locs;
191
+ }
192
+ async function fetchText(url) {
193
+ try {
194
+ const res = await fetch(url, { redirect: "follow" });
195
+ if (!res.ok)
196
+ return null;
197
+ return await res.text();
198
+ }
199
+ catch {
200
+ return null;
201
+ }
202
+ }
203
+ async function discoverRoutesFromSitemaps() {
204
+ if (!PAGELOAD_INCLUDE_SITEMAP)
205
+ return [];
206
+ const base = HOMEPAGE_URL.replace(/\/$/, "");
207
+ // On some Windows setups `localhost` resolves to IPv6 first; use IPv4 loopback for fetch to avoid connection issues.
208
+ const fetchBase = base.replace("://localhost", "://127.0.0.1");
209
+ const primaryCandidates = [`${fetchBase}/sitemap.xml`, `${fetchBase}/sitemap/0.xml`];
210
+ let xml = null;
211
+ for (const candidate of primaryCandidates) {
212
+ xml = await fetchText(candidate);
213
+ if (xml)
214
+ break;
215
+ }
216
+ if (!xml)
217
+ return [];
218
+ const locs = extractSitemapLocs(xml);
219
+ const sitemapXmlUrls = locs.filter((l) => l.toLowerCase().endsWith(".xml"));
220
+ const urlLocs = [];
221
+ if (sitemapXmlUrls.length > 0) {
222
+ for (const sitemapUrl of sitemapXmlUrls.slice(0, 25)) {
223
+ const childXml = await fetchText(sitemapUrl);
224
+ if (!childXml)
225
+ continue;
226
+ urlLocs.push(...extractSitemapLocs(childXml));
227
+ if (PAGELOAD_SITEMAP_MAX_URLS > 0 && urlLocs.length >= PAGELOAD_SITEMAP_MAX_URLS)
228
+ break;
229
+ }
230
+ }
231
+ else {
232
+ urlLocs.push(...locs);
233
+ }
234
+ const paths = [];
235
+ for (const loc of urlLocs) {
236
+ try {
237
+ const u = new URL(loc);
238
+ const pathOnly = normalizeRoute(u.pathname);
239
+ if (pathOnly.startsWith("/_next"))
240
+ continue;
241
+ paths.push(pathOnly);
242
+ if (PAGELOAD_SITEMAP_MAX_URLS > 0 && paths.length >= PAGELOAD_SITEMAP_MAX_URLS)
243
+ break;
244
+ }
245
+ catch {
246
+ // ignore invalid loc
247
+ }
248
+ }
249
+ return Array.from(new Set(paths)).sort();
250
+ }
251
+ async function discoverRoutesFromApp() {
252
+ const files = await file_cache_1.fileCache.getFiles("app/**/page.{ts,tsx,js,jsx}", { ignore: EXCLUDED });
253
+ const routes = [];
254
+ const skippedDynamic = [];
255
+ for (const file of files) {
256
+ const rel = file.replace(/\\/g, "/");
257
+ const withoutApp = rel.replace(/^app\//, "");
258
+ const withoutPage = withoutApp.replace(/(^|[\\/])page\.(ts|tsx|js|jsx)$/i, "");
259
+ // Empty => root
260
+ const segments = withoutPage ? withoutPage.split("/") : [];
261
+ // Skip route groups, parallel routes, and intercepting routes in path computation.
262
+ const cleaned = [];
263
+ let isDynamic = false;
264
+ for (const seg of segments) {
265
+ if (!seg)
266
+ continue;
267
+ if (seg.startsWith("(") && seg.endsWith(")"))
268
+ continue; // route group
269
+ if (seg.startsWith("@"))
270
+ continue; // parallel route
271
+ if (seg.startsWith("(..") || seg.startsWith("(.)"))
272
+ continue; // intercepting
273
+ if (seg.startsWith("[") && seg.endsWith("]")) {
274
+ isDynamic = true;
275
+ cleaned.push(seg);
276
+ continue;
277
+ }
278
+ cleaned.push(seg);
279
+ }
280
+ const route = `/${cleaned.filter(Boolean).join("/")}`.replace(/\/+$/, "") || "/";
281
+ const normalized = normalizeRoute(route);
282
+ if (isDynamic) {
283
+ skippedDynamic.push(normalized);
284
+ continue;
285
+ }
286
+ routes.push(normalized);
287
+ }
288
+ return {
289
+ routes: Array.from(new Set(routes)).sort(),
290
+ skippedDynamic: Array.from(new Set(skippedDynamic)).sort(),
291
+ };
292
+ }
293
+ async function loadPageRoutes() {
294
+ const envRoutes = process.env.PREFLIGHT_PAGE_ROUTES;
295
+ const envMaxRoutes = Number(process.env.PREFLIGHT_PAGELOAD_MAX_ROUTES || 0);
296
+ const envAllowPartial = process.env.PREFLIGHT_PAGELOAD_ALLOW_PARTIAL === "1";
297
+ if (envRoutes) {
298
+ const parts = envRoutes.split(",").map((r) => normalizeRoute(r));
299
+ const dedupedParts = Array.from(new Set(parts)).filter(Boolean);
300
+ return {
301
+ routes: dedupedParts.length > 0 ? dedupedParts : DEFAULT_PAGE_ROUTES,
302
+ skippedDynamic: [],
303
+ maxRoutes: envMaxRoutes > 0 ? envMaxRoutes : 250,
304
+ allowPartial: envAllowPartial,
305
+ exclude: [],
306
+ };
307
+ }
308
+ let cfg;
309
+ if (fs.existsSync(PAGELOAD_ROUTES_CONFIG)) {
310
+ try {
311
+ cfg = JSON.parse(fs.readFileSync(PAGELOAD_ROUTES_CONFIG, "utf8"));
312
+ }
313
+ catch (err) {
314
+ console.warn("Unable to parse page-load-routes config, falling back to discovery:", err);
315
+ }
316
+ }
317
+ // Back-compat: array = explicit list.
318
+ if (Array.isArray(cfg)) {
319
+ const normalized = Array.from(new Set((cfg || []).map((r) => normalizeRoute(r)))).filter(Boolean);
320
+ return {
321
+ routes: normalized.length > 0 ? normalized : DEFAULT_PAGE_ROUTES,
322
+ skippedDynamic: [],
323
+ maxRoutes: envMaxRoutes > 0 ? envMaxRoutes : 250,
324
+ allowPartial: envAllowPartial,
325
+ exclude: [],
326
+ };
327
+ }
328
+ const mode = cfg?.mode || "discover";
329
+ const exclude = (cfg?.exclude || []).map((r) => normalizeRoute(r));
330
+ const allowPartial = process.env.PREFLIGHT_PAGELOAD_ALLOW_PARTIAL === "1"
331
+ ? true
332
+ : (cfg?.allowPartial ?? envAllowPartial);
333
+ const maxRoutes = envMaxRoutes > 0 ? envMaxRoutes : cfg?.maxRoutes || 250;
334
+ const requireDynamicExamples = process.env.PREFLIGHT_PAGELOAD_REQUIRE_DYNAMIC_EXAMPLES === "1";
335
+ const dynamicExamples = normalizeExampleRoutes(cfg?.dynamicExamples);
336
+ const storageStatePath = process.env.PREFLIGHT_PLAYWRIGHT_STORAGE_STATE;
337
+ const includeProtected = process.env.PREFLIGHT_PAGELOAD_INCLUDE_PROTECTED === "1";
338
+ const defaultProtectedPrefixes = ["/account/", "/admin/", "/seller/", "/store/"];
339
+ const effectiveExclude = [...exclude];
340
+ if (!storageStatePath && !includeProtected) {
341
+ // Skip protected areas by default when we don't have auth state.
342
+ defaultProtectedPrefixes.forEach((p) => effectiveExclude.push(`${p}*`));
343
+ }
344
+ if (mode === "list") {
345
+ const configured = (cfg?.routes || []).map((r) => normalizeRoute(r));
346
+ const include = (cfg?.include || []).map((r) => normalizeRoute(r));
347
+ const routes = Array.from(new Set([...configured, ...include])).filter(Boolean);
348
+ const filtered = effectiveExclude.length > 0
349
+ ? routes.filter((r) => !effectiveExclude.some((p) => matchRoutePattern(p, r)))
350
+ : routes;
351
+ return {
352
+ routes: filtered.length > 0 ? filtered : DEFAULT_PAGE_ROUTES,
353
+ skippedDynamic: [],
354
+ maxRoutes,
355
+ allowPartial,
356
+ exclude: effectiveExclude,
357
+ };
358
+ }
359
+ const discovered = await discoverRoutesFromApp();
360
+ const include = (cfg?.include || []).map((r) => normalizeRoute(r));
361
+ let merged = Array.from(new Set([...discovered.routes, ...include])).filter(Boolean);
362
+ // Expand dynamic routes with user-provided examples.
363
+ const expandedDynamic = [];
364
+ const stillSkipped = [];
365
+ for (const dyn of discovered.skippedDynamic) {
366
+ const matches = Object.entries(dynamicExamples).find(([pattern]) => matchRoutePattern(pattern, dyn) || pattern === dyn);
367
+ const exampleList = matches ? matches[1] : undefined;
368
+ if (exampleList && exampleList.length > 0) {
369
+ for (const ex of exampleList) {
370
+ // If user provides a full example route, accept it. If they provide only segments, best-effort substitute.
371
+ const resolved = ex.includes("[")
372
+ ? null
373
+ : ex.startsWith("/")
374
+ ? ex
375
+ : substituteDynamicRoute(dyn, ex);
376
+ const route = resolved ? normalizeRoute(resolved) : normalizeRoute(ex);
377
+ if (route && !route.includes("["))
378
+ expandedDynamic.push(route);
379
+ }
380
+ }
381
+ else {
382
+ stillSkipped.push(dyn);
383
+ }
384
+ }
385
+ if (expandedDynamic.length > 0) {
386
+ merged = Array.from(new Set([...merged, ...expandedDynamic]));
387
+ }
388
+ if (effectiveExclude.length > 0) {
389
+ merged = merged.filter((route) => !effectiveExclude.some((pattern) => matchRoutePattern(pattern, route)));
390
+ }
391
+ const finalSkippedDynamic = stillSkipped;
392
+ if (requireDynamicExamples && finalSkippedDynamic.length > 0) {
393
+ // Keep them in the skipped list; the checker will convert this into a blocking error.
394
+ }
395
+ return {
396
+ routes: merged.length > 0 ? merged : DEFAULT_PAGE_ROUTES,
397
+ skippedDynamic: finalSkippedDynamic,
398
+ maxRoutes,
399
+ allowPartial,
400
+ exclude: effectiveExclude,
401
+ };
402
+ }
403
+ function buildUrl(route) {
404
+ try {
405
+ return new URL(route, HOMEPAGE_URL).toString();
406
+ }
407
+ catch (_err) {
408
+ return `${HOMEPAGE_URL.replace(/\/$/, "")}${route.startsWith("/") ? route : `/${route}`}`;
409
+ }
410
+ }
411
+ async function isPortOpen(port) {
412
+ return new Promise((resolve) => {
413
+ const socket = net.createConnection({ port, host: "127.0.0.1" });
414
+ socket.once("connect", () => {
415
+ socket.destroy();
416
+ resolve(true);
417
+ });
418
+ socket.once("error", () => resolve(false));
419
+ });
420
+ }
421
+ async function waitForPort(port, timeoutMs) {
422
+ const start = Date.now();
423
+ while (Date.now() - start < timeoutMs) {
424
+ if (await isPortOpen(port))
425
+ return true;
426
+ await (0, promises_1.setTimeout)(300);
427
+ }
428
+ return false;
429
+ }
430
+ function startServer(logs) {
431
+ const args = PAGELOAD_SERVER_MODE === "prod" ? ["start"] : ["dev"];
432
+ const env = {
433
+ ...process.env,
434
+ PORT: String(PREFLIGHT_PORT),
435
+ NEXT_TELEMETRY_DISABLED: "1",
436
+ TURBO_NO_PERSISTENCE: "1",
437
+ ...(process.env.NODE_NO_WARNINGS ? {} : { NODE_NO_WARNINGS: "1" }),
438
+ ...(PAGELOAD_SERVER_MODE === "prod" ? { NODE_ENV: "production" } : {}),
439
+ };
440
+ if (PAGELOAD_SERVER_MODE === "prod") {
441
+ // next start requires a build output
442
+ const nextDir = path.join(process.cwd(), ".next");
443
+ if (!fs.existsSync(nextDir)) {
444
+ throw new Error("Production page-load budgets require a built .next directory. Run `pnpm build` first or use PREFLIGHT_PAGELOAD_SERVER_MODE=dev.");
445
+ }
446
+ const buildIdPath = path.join(nextDir, "BUILD_ID");
447
+ if (!fs.existsSync(buildIdPath)) {
448
+ throw new Error("Production page-load budgets require a complete Next.js production build (.next/BUILD_ID missing). Run `pnpm build` (or at least `pnpm next build`) before running PREFLIGHT_PAGELOAD_SERVER_MODE=prod.");
449
+ }
450
+ }
451
+ // Windows quirks:
452
+ // - npm_execpath may be pnpm.exe (native) or a JS entrypoint. Don't try to run pnpm.exe as JS.
453
+ // - Spawning .cmd can be flaky in some environments; prefer pnpm.exe when available.
454
+ const pnpmExecPath = process.platform === "win32" ? process.env.npm_execpath : undefined;
455
+ const pnpmExecLooksLikeExe = !!pnpmExecPath && /\.exe$/i.test(pnpmExecPath);
456
+ const pnpmExecLooksLikeNodeScript = !!pnpmExecPath && /\.(c?js|mjs)$/i.test(pnpmExecPath);
457
+ const spawnCommand = process.platform === "win32" && pnpmExecLooksLikeNodeScript
458
+ ? process.execPath
459
+ : process.platform === "win32" && pnpmExecLooksLikeExe
460
+ ? pnpmExecPath
461
+ : PNPM_CMD;
462
+ const spawnArgs = process.platform === "win32" && pnpmExecLooksLikeNodeScript ? [pnpmExecPath, ...args] : args;
463
+ const server = (0, child_process_1.spawn)(spawnCommand, spawnArgs, {
464
+ cwd: process.cwd(),
465
+ env,
466
+ stdio: ["pipe", "pipe", "pipe"],
467
+ });
468
+ server.stdout.on("data", (chunk) => logs.push(chunk.toString()));
469
+ server.stderr.on("data", (chunk) => logs.push(chunk.toString()));
470
+ return server;
471
+ }
472
+ function stopServer(server) {
473
+ if (!server)
474
+ return;
475
+ try {
476
+ if (process.platform === "win32" && typeof server.pid === "number") {
477
+ (0, child_process_1.spawnSync)("taskkill", ["/PID", String(server.pid), "/T", "/F"], {
478
+ stdio: "ignore",
479
+ });
480
+ return;
481
+ }
482
+ server.kill();
483
+ }
484
+ catch (err) {
485
+ console.warn("Failed to stop server:", err);
486
+ }
487
+ }
488
+ // CACHED FILE LISTS - Scan once, use everywhere
489
+ let _cachedAppTsxFiles = null;
490
+ async function getAppTsxFiles() {
491
+ if (!_cachedAppTsxFiles) {
492
+ _cachedAppTsxFiles = await file_cache_1.fileCache.getAppTSX();
493
+ }
494
+ return _cachedAppTsxFiles;
495
+ }
496
+ let _cachedAppComponentsTsxFiles = null;
497
+ async function getAppComponentsTsxFiles() {
498
+ if (!_cachedAppComponentsTsxFiles) {
499
+ _cachedAppComponentsTsxFiles = await file_cache_1.fileCache.getAppAndComponentsTSX();
500
+ }
501
+ return _cachedAppComponentsTsxFiles;
502
+ }
503
+ async function getAppLibFiles() {
504
+ return file_cache_1.fileCache.getAppLibFiles();
505
+ }
506
+ // Get concurrency from shared config (respects PREFLIGHT_CONCURRENCY env var)
507
+ const concurrencyConfig = (0, concurrency_config_1.getConcurrencyConfig)();
508
+ class PerformancePreflightModule {
509
+ verbose;
510
+ parallel = false;
511
+ constructor(options = {}) {
512
+ this.verbose = options.verbose || false;
513
+ this.parallel = options.parallel || concurrencyConfig.parallel;
514
+ }
515
+ async ensureServer(serverLogs) {
516
+ const alreadyRunning = await isPortOpen(PREFLIGHT_PORT);
517
+ if (alreadyRunning) {
518
+ return { usedExisting: true };
519
+ }
520
+ const server = startServer(serverLogs);
521
+ const timeoutMs = PAGELOAD_SERVER_MODE === "prod" ? PROD_SERVER_START_TIMEOUT : DEV_SERVER_START_TIMEOUT;
522
+ const readyResult = await Promise.race([
523
+ waitForPort(PREFLIGHT_PORT, timeoutMs).then((ok) => ({
524
+ ok,
525
+ exited: false,
526
+ })),
527
+ new Promise((resolve) => {
528
+ server.once("exit", (code, signal) => resolve({ ok: false, exited: true, code, signal }));
529
+ }),
530
+ ]);
531
+ if (!readyResult.ok) {
532
+ stopServer(server);
533
+ const lastLogs = serverLogs.slice(-20).join("").trim();
534
+ const exitInfo = readyResult.exited
535
+ ? `Process exited early (code: ${readyResult.code ?? "unknown"}, signal: ${readyResult.signal ?? "none"}). `
536
+ : "";
537
+ throw new Error(`${exitInfo}Server did not start on port ${PREFLIGHT_PORT} within ${timeoutMs}ms.` +
538
+ (lastLogs ? `\n\nLast server logs:\n${lastLogs}` : ""));
539
+ }
540
+ // Let the server settle before navigation to avoid capturing cold-start noise only.
541
+ await (0, promises_1.setTimeout)(500);
542
+ return { usedExisting: false, server };
543
+ }
544
+ async capturePageTrace(context, route) {
545
+ const page = await context.newPage();
546
+ const requests = [];
547
+ const startTimes = new Map();
548
+ page.on("request", (req) => {
549
+ startTimes.set(req.url(), Date.now());
550
+ });
551
+ page.on("requestfinished", async (req) => {
552
+ const started = startTimes.get(req.url());
553
+ const res = await req.response();
554
+ requests.push({
555
+ url: req.url(),
556
+ method: req.method(),
557
+ status: res?.status(),
558
+ durationMs: started ? Date.now() - started : undefined,
559
+ resourceType: req.resourceType(),
560
+ });
561
+ });
562
+ page.on("requestfailed", (req) => {
563
+ const started = startTimes.get(req.url());
564
+ requests.push({
565
+ url: req.url(),
566
+ method: req.method(),
567
+ status: undefined,
568
+ durationMs: started ? Date.now() - started : undefined,
569
+ resourceType: req.resourceType(),
570
+ });
571
+ });
572
+ try {
573
+ await page.goto(buildUrl(route), {
574
+ waitUntil: "domcontentloaded",
575
+ timeout: PAGELOAD_ROUTE_TIMEOUT_MS,
576
+ });
577
+ await page
578
+ .waitForLoadState("load", { timeout: PAGELOAD_LOAD_TIMEOUT_MS })
579
+ .catch(() => undefined);
580
+ await page
581
+ .waitForLoadState("networkidle", {
582
+ timeout: PAGELOAD_NETWORKIDLE_TIMEOUT_MS,
583
+ })
584
+ .catch(() => undefined);
585
+ await (0, promises_1.setTimeout)(WAIT_FOR_STABLE_NETWORK_MS);
586
+ const metrics = await page.evaluate(() => {
587
+ const nav = performance.getEntriesByType("navigation")[0];
588
+ const resources = performance.getEntriesByType("resource");
589
+ const totalTransferBytes = resources.reduce((sum, r) => sum + (r.transferSize || 0), 0);
590
+ const apiTransferBytes = resources
591
+ .filter((r) => typeof r.name === "string" && r.name.includes("/api/"))
592
+ .reduce((sum, r) => sum + (r.transferSize || 0), 0);
593
+ return {
594
+ navDuration: nav?.duration || 0,
595
+ totalTransferBytes,
596
+ apiTransferBytes,
597
+ };
598
+ });
599
+ return {
600
+ requests,
601
+ navDuration: metrics.navDuration,
602
+ totalTransferBytes: metrics.totalTransferBytes,
603
+ apiTransferBytes: metrics.apiTransferBytes,
604
+ finalUrl: page.url(),
605
+ };
606
+ }
607
+ finally {
608
+ await page.close().catch(() => undefined);
609
+ }
610
+ }
611
+ async checkPageLoadBudgets() {
612
+ const startTime = Date.now();
613
+ const issues = [];
614
+ const serverLogs = [];
615
+ let server;
616
+ let routes = [];
617
+ let skippedDynamic = [];
618
+ let maxRoutes = 250;
619
+ let allowPartial = false;
620
+ let exclude = [];
621
+ const pathKey = (url) => {
622
+ try {
623
+ return new URL(url).pathname;
624
+ }
625
+ catch (_err) {
626
+ return url.split("?")[0];
627
+ }
628
+ };
629
+ const evaluateRoute = (route, requests, navDuration, totalTransferBytes, apiTransferBytes, prismaLogSlice) => {
630
+ const routeIssues = [];
631
+ const apiRequests = requests.filter((r) => {
632
+ const path = pathKey(r.url);
633
+ const isApi = path.startsWith("/api");
634
+ const isFetchLike = r.resourceType === "fetch" ||
635
+ r.resourceType === "xhr" ||
636
+ r.resourceType === "document" ||
637
+ !r.resourceType;
638
+ return isApi && isFetchLike;
639
+ });
640
+ const documentRequests = requests.filter((r) => r.resourceType === "document");
641
+ const meaningfulRequestCount = apiRequests.length + documentRequests.length;
642
+ const apiCountByPath = new Map();
643
+ apiRequests.forEach((req) => {
644
+ const key = pathKey(req.url);
645
+ apiCountByPath.set(key, (apiCountByPath.get(key) || 0) + 1);
646
+ });
647
+ const duplicateApis = Array.from(apiCountByPath.entries()).filter(([, count]) => count > PAGELOAD_API_DUPLICATE_LIMIT);
648
+ const sessionHits = apiCountByPath.get("/api/auth/session") || 0;
649
+ const notificationHits = apiCountByPath.get("/api/notifications") || 0;
650
+ if (navDuration > PAGELOAD_NAVIGATION_BUDGET_MS) {
651
+ routeIssues.push({
652
+ file: route,
653
+ type: "page-load-duration",
654
+ severity: "warning",
655
+ message: `Navigation duration ${navDuration.toFixed(0)}ms exceeds budget ${PAGELOAD_NAVIGATION_BUDGET_MS}ms`,
656
+ suggestion: "Reduce above-the-fold data fetching and defer non-critical API calls",
657
+ });
658
+ }
659
+ if (meaningfulRequestCount > PAGELOAD_REQUEST_BUDGET) {
660
+ routeIssues.push({
661
+ file: route,
662
+ type: "page-load-requests",
663
+ severity: "warning",
664
+ message: `Document + API requests ${meaningfulRequestCount} exceed budget ${PAGELOAD_REQUEST_BUDGET}`,
665
+ suggestion: "Consolidate API calls, enable caching, and defer non-critical widgets",
666
+ });
667
+ }
668
+ if (duplicateApis.length > 0) {
669
+ duplicateApis.forEach(([path, count]) => {
670
+ routeIssues.push({
671
+ file: route,
672
+ type: "duplicate-api-calls",
673
+ severity: "warning",
674
+ message: `${path} called ${count} times on first render`,
675
+ suggestion: "Use server-side injection or SWR dedupe for repeated endpoints",
676
+ });
677
+ });
678
+ }
679
+ if (sessionHits > PAGELOAD_SESSION_DUPLICATE_LIMIT) {
680
+ routeIssues.push({
681
+ file: route,
682
+ type: "session-duplication",
683
+ severity: "info",
684
+ message: `/api/auth/session called ${sessionHits} times`,
685
+ suggestion: "Inject session server-side or memoize client fetch",
686
+ });
687
+ }
688
+ if (notificationHits > PAGELOAD_NOTIFICATION_DUPLICATE_LIMIT) {
689
+ routeIssues.push({
690
+ file: route,
691
+ type: "notification-duplication",
692
+ severity: "info",
693
+ message: `/api/notifications called ${notificationHits} times`,
694
+ suggestion: "Combine counts + list into one query or cache the list server-side",
695
+ });
696
+ }
697
+ if (apiTransferBytes > PAGELOAD_TRANSFER_BUDGET_BYTES) {
698
+ routeIssues.push({
699
+ file: route,
700
+ type: "transfer-size",
701
+ severity: "info",
702
+ message: `API transfer ${(apiTransferBytes / 1024 / 1024).toFixed(2)}MB exceeds ${(PAGELOAD_TRANSFER_BUDGET_BYTES / 1024 / 1024).toFixed(2)}MB budget`,
703
+ suggestion: "Reduce initial API payloads and avoid overfetching",
704
+ });
705
+ }
706
+ if (totalTransferBytes > PAGELOAD_TRANSFER_BUDGET_BYTES * 4) {
707
+ routeIssues.push({
708
+ file: route,
709
+ type: "total-transfer-size",
710
+ severity: "info",
711
+ message: `Total transfer ${(totalTransferBytes / 1024 / 1024).toFixed(2)}MB (assets + API)`,
712
+ suggestion: "If this stays high in production, review bundle splitting and image optimization",
713
+ });
714
+ }
715
+ if (prismaLogSlice.length > 0) {
716
+ if (prismaLogSlice.length > PAGELOAD_PRISMA_QUERY_BUDGET) {
717
+ routeIssues.push({
718
+ file: route,
719
+ type: "prisma-query-volume",
720
+ severity: "warning",
721
+ message: `Prisma queries during first paint: ${prismaLogSlice.length} (budget ${PAGELOAD_PRISMA_QUERY_BUDGET})`,
722
+ suggestion: "Batch page queries and cache counts",
723
+ });
724
+ }
725
+ const prismaStatements = prismaLogSlice.map((line) => line.replace(/^.*prisma:query\s+/i, "").trim());
726
+ const prismaCounts = prismaStatements.reduce((acc, stmt) => {
727
+ acc[stmt] = (acc[stmt] || 0) + 1;
728
+ return acc;
729
+ }, {});
730
+ Object.entries(prismaCounts)
731
+ .filter(([, count]) => count >= PAGELOAD_PRISMA_DUPLICATE_THRESHOLD)
732
+ .slice(0, 5)
733
+ .forEach(([stmt, count]) => {
734
+ routeIssues.push({
735
+ file: route,
736
+ type: "prisma-duplicate-query",
737
+ severity: "warning",
738
+ message: `Repeated Prisma query (${count}x): ${stmt.slice(0, 160)}...`,
739
+ suggestion: "Cache notification counts and reuse results across components",
740
+ });
741
+ });
742
+ const nullInPatterns = prismaLogSlice.filter((line) => /IN\s*\(NULL\)/i.test(line));
743
+ if (nullInPatterns.length > 0) {
744
+ routeIssues.push({
745
+ file: route,
746
+ type: "prisma-null-in",
747
+ severity: "info",
748
+ message: `Prisma executed ${nullInPatterns.length} queries with IN (NULL)`,
749
+ suggestion: "Guard empty ID lists before querying to avoid wasted queries",
750
+ });
751
+ }
752
+ }
753
+ return routeIssues;
754
+ };
755
+ let browser;
756
+ let context;
757
+ try {
758
+ const { usedExisting, server: started } = await this.ensureServer(serverLogs);
759
+ server = started;
760
+ const loaded = await loadPageRoutes();
761
+ routes = loaded.routes;
762
+ skippedDynamic = loaded.skippedDynamic;
763
+ maxRoutes = loaded.maxRoutes;
764
+ allowPartial = loaded.allowPartial;
765
+ exclude = loaded.exclude;
766
+ browser = await playwright_1.chromium.launch({ headless: true });
767
+ const storageStatePath = process.env.PREFLIGHT_PLAYWRIGHT_STORAGE_STATE;
768
+ context = storageStatePath
769
+ ? await browser.newContext({ storageState: storageStatePath })
770
+ : await browser.newContext();
771
+ if (!context) {
772
+ throw new Error("Failed to create Playwright browser context");
773
+ }
774
+ // Augment with sitemap URLs (helps cover dynamic routes without manual examples).
775
+ if (PAGELOAD_INCLUDE_SITEMAP) {
776
+ const sitemapRoutes = await discoverRoutesFromSitemaps();
777
+ if (sitemapRoutes.length > 0) {
778
+ routes = Array.from(new Set([...routes, ...sitemapRoutes]));
779
+ issues.push({
780
+ file: "sitemap",
781
+ type: "sitemap-discovery",
782
+ severity: "info",
783
+ message: `Discovered ${sitemapRoutes.length} routes from sitemap`,
784
+ suggestion: "Disable PREFLIGHT_PAGELOAD_INCLUDE_SITEMAP if you only want filesystem-discovered routes",
785
+ });
786
+ }
787
+ else {
788
+ issues.push({
789
+ file: "sitemap",
790
+ type: "sitemap-discovery",
791
+ severity: "info",
792
+ message: "Sitemap discovery enabled but no sitemap URLs were found",
793
+ suggestion: "Ensure your app serves /sitemap.xml or /sitemap/0.xml in production mode",
794
+ });
795
+ }
796
+ }
797
+ // Enforce true dynamic coverage when requested.
798
+ if (process.env.PREFLIGHT_PAGELOAD_REQUIRE_DYNAMIC_EXAMPLES === "1" &&
799
+ skippedDynamic.length > 0) {
800
+ const missing = skippedDynamic.filter((tpl) => !routes.some((r) => dynamicTemplateMatchesRoute(tpl, r)));
801
+ if (missing.length > 0) {
802
+ issues.push({
803
+ file: PAGELOAD_ROUTES_CONFIG,
804
+ type: "dynamic-routes-missing-examples",
805
+ severity: "error",
806
+ message: `Dynamic routes require examples but ${missing.length} are still missing coverage: ${missing.slice(0, 10).join(", ")}${missing.length > 10 ? "${chars.ellipsis}" : ""}`,
807
+ suggestion: "Add dynamicExamples entries to the configured routes JSON, or enable PREFLIGHT_PAGELOAD_INCLUDE_SITEMAP to pick up real URLs.",
808
+ });
809
+ return {
810
+ name: "Page Load Budgets",
811
+ passed: false,
812
+ blocking: true,
813
+ issues,
814
+ duration: Date.now() - startTime,
815
+ };
816
+ }
817
+ }
818
+ // Warm up a freshly started server to avoid penalizing cold-start compilation/caching.
819
+ if (!usedExisting) {
820
+ try {
821
+ await this.capturePageTrace(context, "/");
822
+ }
823
+ catch {
824
+ // ignore warmup failures
825
+ }
826
+ }
827
+ if (skippedDynamic.length > 0) {
828
+ issues.push({
829
+ file: "app",
830
+ type: "dynamic-routes-skipped",
831
+ severity: "info",
832
+ message: `Skipped ${skippedDynamic.length} dynamic routes (require params): ${skippedDynamic.slice(0, 10).join(", ")}${skippedDynamic.length > 10 ? "${chars.ellipsis}" : ""}`,
833
+ suggestion: "Add explicit examples via list-mode config if you want dynamic route coverage",
834
+ });
835
+ }
836
+ if (exclude.length > 0) {
837
+ issues.push({
838
+ file: PAGELOAD_ROUTES_CONFIG,
839
+ type: "route-excludes",
840
+ severity: "info",
841
+ message: `Excluded ${exclude.length} patterns from page-load budgets`,
842
+ suggestion: "Remove excludes if you want stricter coverage",
843
+ });
844
+ }
845
+ if (routes.length > maxRoutes) {
846
+ const msg = `Discovered ${routes.length} routes but maxRoutes is ${maxRoutes}`;
847
+ if (!allowPartial) {
848
+ issues.push({
849
+ file: PAGELOAD_ROUTES_CONFIG,
850
+ type: "too-many-routes",
851
+ severity: "error",
852
+ message: msg,
853
+ suggestion: "Increase maxRoutes or set PREFLIGHT_PAGELOAD_ALLOW_PARTIAL=1 to sample",
854
+ });
855
+ return {
856
+ name: "Page Load Budgets",
857
+ passed: false,
858
+ blocking: true,
859
+ issues,
860
+ duration: Date.now() - startTime,
861
+ };
862
+ }
863
+ issues.push({
864
+ file: PAGELOAD_ROUTES_CONFIG,
865
+ type: "route-sampling",
866
+ severity: "warning",
867
+ message: `${msg}; sampling first ${maxRoutes}`,
868
+ suggestion: "Increase maxRoutes to cover more pages",
869
+ });
870
+ routes = routes.slice(0, maxRoutes);
871
+ }
872
+ if (PAGELOAD_CONCURRENCY > 1) {
873
+ issues.push({
874
+ file: "page-load",
875
+ type: "concurrency-enabled",
876
+ severity: "info",
877
+ message: `Running page-load budgets with concurrency=${PAGELOAD_CONCURRENCY}`,
878
+ suggestion: "Set PREFLIGHT_PAGELOAD_CONCURRENCY=1 for deterministic per-route Prisma attribution",
879
+ });
880
+ }
881
+ let completed = 0;
882
+ let nextIndex = 0;
883
+ const runOne = async () => {
884
+ while (nextIndex < routes.length) {
885
+ const index = nextIndex++;
886
+ if (index >= routes.length) {
887
+ return;
888
+ }
889
+ const route = routes[index];
890
+ if (this.verbose) {
891
+ console.log(` ā†ŖļøŽ pageload ${route}`);
892
+ }
893
+ const { requests, navDuration, totalTransferBytes, apiTransferBytes, finalUrl } = await this.capturePageTrace(context, route);
894
+ // When running concurrently we can't reliably slice logs per-route.
895
+ const prismaLogSlice = PAGELOAD_CONCURRENCY > 1
896
+ ? []
897
+ : serverLogs.filter((line) => line.includes("prisma:query"));
898
+ let intendedPath;
899
+ let finalPath;
900
+ try {
901
+ intendedPath = new URL(buildUrl(route)).pathname;
902
+ finalPath = new URL(finalUrl).pathname;
903
+ }
904
+ catch {
905
+ // ignore url parse issues
906
+ }
907
+ if (intendedPath && finalPath && intendedPath !== finalPath) {
908
+ issues.push({
909
+ file: route,
910
+ type: "redirect-detected",
911
+ severity: "info",
912
+ message: `Route redirected: ${intendedPath} ${console_chars_1.chars.arrow} ${finalPath}`,
913
+ suggestion: "Provide PREFLIGHT_PLAYWRIGHT_STORAGE_STATE to test authenticated pages (or list-mode config to exclude protected routes)",
914
+ });
915
+ const authRedirect = finalPath === "/login" ||
916
+ finalPath.startsWith("/login/") ||
917
+ finalPath.startsWith("/auth/signin") ||
918
+ finalPath.startsWith("/auth/error") ||
919
+ finalPath === "/forbidden" ||
920
+ finalPath.startsWith("/forbidden/");
921
+ if (authRedirect) {
922
+ continue; // Don't apply budgets to protected routes when unauthenticated.
923
+ }
924
+ }
925
+ issues.push(...evaluateRoute(route, requests, navDuration, totalTransferBytes, apiTransferBytes, prismaLogSlice));
926
+ if (usedExisting && prismaLogSlice.length === 0) {
927
+ issues.push({
928
+ file: route,
929
+ type: "log-capture",
930
+ severity: "info",
931
+ message: "Prisma logs not captured (dev server already running)",
932
+ suggestion: "Run preflight on a fresh dev server to capture query counts",
933
+ });
934
+ }
935
+ completed++;
936
+ if (!this.verbose &&
937
+ PAGELOAD_PROGRESS_EVERY > 0 &&
938
+ completed % PAGELOAD_PROGRESS_EVERY === 0) {
939
+ console.log(` pageload progress ${completed}/${routes.length}`);
940
+ }
941
+ }
942
+ };
943
+ const workerCount = Math.min(PAGELOAD_CONCURRENCY, routes.length);
944
+ await Promise.all(Array.from({ length: workerCount }, () => runOne()));
945
+ }
946
+ catch (err) {
947
+ issues.push({
948
+ file: "page-load",
949
+ type: "page-load-check",
950
+ severity: "error",
951
+ message: `Failed to run page load budget: ${err?.message || err}`,
952
+ suggestion: "Ensure pnpm dev can start and Playwright is installed",
953
+ });
954
+ }
955
+ finally {
956
+ await context?.close().catch(() => undefined);
957
+ await browser?.close().catch(() => undefined);
958
+ stopServer(server);
959
+ }
960
+ const failedIssues = issues.filter((i) => i.severity === "error" || (PAGELOAD_STRICT && i.severity === "warning"));
961
+ return {
962
+ name: "Page Load Budgets",
963
+ passed: failedIssues.length === 0,
964
+ blocking: true,
965
+ issues,
966
+ duration: Date.now() - startTime,
967
+ };
968
+ }
969
+ /**
970
+ * Bundle Size Check
971
+ */
972
+ async checkBundleSize() {
973
+ const startTime = Date.now();
974
+ const issues = [];
975
+ // Check for large dependencies
976
+ const largeDeps = [
977
+ { name: "moment", suggestion: "Use date-fns (90% smaller)" },
978
+ { name: "lodash", suggestion: "Use lodash-es or individual imports" },
979
+ { name: "@mui/material", suggestion: "Use @supercatch/ui (98% smaller)" },
980
+ ];
981
+ if (fs.existsSync("package.json")) {
982
+ const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
983
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
984
+ for (const { name, suggestion } of largeDeps) {
985
+ if (deps[name]) {
986
+ issues.push({
987
+ file: "package.json",
988
+ type: "large-dep",
989
+ severity: "warning",
990
+ message: `Large dependency: ${name}`,
991
+ suggestion,
992
+ });
993
+ }
994
+ }
995
+ }
996
+ return {
997
+ name: "Bundle Size",
998
+ passed: true,
999
+ blocking: false,
1000
+ issues,
1001
+ duration: Date.now() - startTime,
1002
+ };
1003
+ }
1004
+ /**
1005
+ * Image Optimization Check
1006
+ * Detects:
1007
+ * - Images without width/height (causes CLS)
1008
+ * - Missing loading="lazy" on below-fold images
1009
+ * - Missing priority prop on above-fold/hero/featured images
1010
+ * - ListingShowcaseCard without priority prop in homepage/featured contexts
1011
+ */
1012
+ async checkImageOptimization() {
1013
+ const startTime = Date.now();
1014
+ const issues = [];
1015
+ const files = await getAppComponentsTsxFiles();
1016
+ for (const file of files) {
1017
+ const content = fs.readFileSync(file, "utf8");
1018
+ const lines = content.split("\n");
1019
+ lines.forEach((line, index) => {
1020
+ // Check for img without width/height
1021
+ if (/<img[^>]*src=/i.test(line) && !/<img[^>]*(?:width|height)=/i.test(line)) {
1022
+ issues.push({
1023
+ file,
1024
+ line: index + 1,
1025
+ type: "img-no-dimensions",
1026
+ severity: "warning",
1027
+ message: "img without width/height (causes CLS)",
1028
+ suggestion: "Add width and height attributes",
1029
+ });
1030
+ }
1031
+ // Check for img without loading="lazy"
1032
+ if (/<img[^>]*src=/i.test(line) && !line.includes("loading=")) {
1033
+ const context = lines.slice(Math.max(0, index - 5), index).join("\n");
1034
+ if (!context.includes("priority") && !context.includes("above-fold")) {
1035
+ issues.push({
1036
+ file,
1037
+ line: index + 1,
1038
+ type: "img-no-lazy",
1039
+ severity: "info",
1040
+ message: 'img without loading="lazy"',
1041
+ suggestion: 'Add loading="lazy" for below-fold images',
1042
+ });
1043
+ }
1044
+ }
1045
+ // Check for Next.js Image in hero/featured/banner contexts without priority
1046
+ if (/<Image[^>]*src=/i.test(line)) {
1047
+ const contextBefore = lines
1048
+ .slice(Math.max(0, index - 10), index + 1)
1049
+ .join("\n")
1050
+ .toLowerCase();
1051
+ const contextAfter = lines
1052
+ .slice(index, Math.min(lines.length, index + 5))
1053
+ .join("\n")
1054
+ .toLowerCase();
1055
+ const fullContext = contextBefore + contextAfter;
1056
+ const isAboveFold = /hero|banner|featured|showcase|primary|main.*image|first.*card/i.test(fullContext);
1057
+ const hasPriority = /priority/i.test(line) || /priority/i.test(contextAfter);
1058
+ if (isAboveFold && !hasPriority) {
1059
+ issues.push({
1060
+ file,
1061
+ line: index + 1,
1062
+ type: "lcp-no-priority",
1063
+ severity: "warning",
1064
+ message: "Above-fold Image missing priority prop (hurts LCP)",
1065
+ suggestion: "Add priority prop to above-fold images for better LCP",
1066
+ });
1067
+ }
1068
+ }
1069
+ // Check for ListingShowcaseCard in homepage/featured without priority
1070
+ if (/ListingShowcaseCard/i.test(line) && !line.includes("priority")) {
1071
+ const contextBefore = lines
1072
+ .slice(Math.max(0, index - 15), index)
1073
+ .join("\n")
1074
+ .toLowerCase();
1075
+ const isHomepageOrFeatured = /featured|homepage|hero|showcase|first/i.test(contextBefore) ||
1076
+ file.includes("page.tsx") ||
1077
+ file.includes("HomePageClient");
1078
+ if (isHomepageOrFeatured) {
1079
+ issues.push({
1080
+ file,
1081
+ line: index + 1,
1082
+ type: "showcase-no-priority",
1083
+ severity: "info",
1084
+ message: "ListingShowcaseCard in featured context without priority prop",
1085
+ suggestion: "Add priority={true} for first few visible cards to improve LCP",
1086
+ });
1087
+ }
1088
+ }
1089
+ });
1090
+ }
1091
+ return {
1092
+ name: "Image Optimization",
1093
+ passed: true,
1094
+ blocking: false,
1095
+ issues,
1096
+ duration: Date.now() - startTime,
1097
+ };
1098
+ }
1099
+ /**
1100
+ * Lazy Loading Check
1101
+ */
1102
+ async checkLazyLoading() {
1103
+ const startTime = Date.now();
1104
+ const issues = [];
1105
+ const files = await getAppComponentsTsxFiles();
1106
+ const heavyComponents = ["Chart", "Editor", "Map", "Calendar", "DataGrid", "RichText"];
1107
+ for (const file of files) {
1108
+ const content = fs.readFileSync(file, "utf8");
1109
+ for (const component of heavyComponents) {
1110
+ const staticImport = new RegExp(`import\\s+.*${component}.*from`);
1111
+ if (staticImport.test(content) && !content.includes("dynamic(")) {
1112
+ const lineNumber = content.split("\n").findIndex((l) => staticImport.test(l)) + 1;
1113
+ issues.push({
1114
+ file,
1115
+ line: lineNumber,
1116
+ type: "static-heavy-import",
1117
+ severity: "info",
1118
+ message: `Heavy component ${component} imported statically`,
1119
+ suggestion: `Use dynamic(() => import('...'))`,
1120
+ });
1121
+ }
1122
+ }
1123
+ }
1124
+ return {
1125
+ name: "Lazy Loading",
1126
+ passed: true,
1127
+ blocking: false,
1128
+ issues,
1129
+ duration: Date.now() - startTime,
1130
+ };
1131
+ }
1132
+ /**
1133
+ * Skeleton Loader Usage Check
1134
+ */
1135
+ async checkSkeletonLoaders() {
1136
+ const startTime = Date.now();
1137
+ const issues = [];
1138
+ const files = await getAppComponentsTsxFiles();
1139
+ for (const file of files) {
1140
+ const content = fs.readFileSync(file, "utf8");
1141
+ // Check for loading states without skeleton
1142
+ if (content.includes("isLoading") || content.includes("loading")) {
1143
+ if (content.includes("Loading...") || content.includes('"Loading"')) {
1144
+ const lineNumber = content.split("\n").findIndex((l) => /Loading\.\.\./.test(l) || /"Loading"/.test(l)) +
1145
+ 1;
1146
+ issues.push({
1147
+ file,
1148
+ line: lineNumber,
1149
+ type: "text-loading",
1150
+ severity: "info",
1151
+ message: "Text-based loading indicator",
1152
+ suggestion: "Use SkeletonLoader for better UX",
1153
+ });
1154
+ }
1155
+ }
1156
+ }
1157
+ return {
1158
+ name: "Skeleton Loaders",
1159
+ passed: true,
1160
+ blocking: false,
1161
+ issues,
1162
+ duration: Date.now() - startTime,
1163
+ };
1164
+ }
1165
+ /**
1166
+ * Virtual Scroll Candidates Check
1167
+ */
1168
+ async checkVirtualScroll() {
1169
+ const startTime = Date.now();
1170
+ const issues = [];
1171
+ const files = await getAppComponentsTsxFiles();
1172
+ for (const file of files) {
1173
+ const content = fs.readFileSync(file, "utf8");
1174
+ const lines = content.split("\n");
1175
+ lines.forEach((line, index) => {
1176
+ // Check for .map() on potentially large arrays
1177
+ if (/\.(map|forEach)\s*\(\s*\([^)]*\)\s*=>/i.test(line)) {
1178
+ const context = lines.slice(Math.max(0, index - 10), index + 1).join("\n");
1179
+ if (/items|products|listings|results|data/i.test(context) &&
1180
+ !context.includes("slice(") &&
1181
+ !context.includes("VirtualList")) {
1182
+ // Only flag if it looks like a large list render
1183
+ if (context.includes("return") &&
1184
+ (context.includes("<li") || context.includes("<div") || context.includes("<Card"))) {
1185
+ issues.push({
1186
+ file,
1187
+ line: index + 1,
1188
+ type: "large-list",
1189
+ severity: "info",
1190
+ message: "Potentially large list without virtualization",
1191
+ suggestion: "Consider VirtualTable or VirtualList from @/components/shared",
1192
+ });
1193
+ }
1194
+ }
1195
+ }
1196
+ });
1197
+ }
1198
+ return {
1199
+ name: "Virtual Scroll Candidates",
1200
+ passed: true,
1201
+ blocking: false,
1202
+ issues,
1203
+ duration: Date.now() - startTime,
1204
+ };
1205
+ }
1206
+ /**
1207
+ * Z-Index Token Usage Check
1208
+ */
1209
+ async checkZIndexTokens() {
1210
+ const startTime = Date.now();
1211
+ const issues = [];
1212
+ const files = await getAppComponentsTsxFiles();
1213
+ for (const file of files) {
1214
+ const content = fs.readFileSync(file, "utf8");
1215
+ const lines = content.split("\n");
1216
+ lines.forEach((line, index) => {
1217
+ // Skip comments
1218
+ if (line.trim().startsWith("//") || line.trim().startsWith("*"))
1219
+ return;
1220
+ // Check for hardcoded z-index values >= 100
1221
+ const zIndexMatch = line.match(/zIndex:\s*(\d+)/);
1222
+ if (zIndexMatch) {
1223
+ const value = parseInt(zIndexMatch[1], 10);
1224
+ if (value >= 100) {
1225
+ issues.push({
1226
+ file,
1227
+ line: index + 1,
1228
+ type: "hardcoded-zindex",
1229
+ severity: "warning",
1230
+ message: `Hardcoded z-index: ${value}`,
1231
+ suggestion: "Use design tokens: var(--z-modal), var(--z-dropdown), var(--z-sticky), etc.",
1232
+ });
1233
+ }
1234
+ }
1235
+ });
1236
+ }
1237
+ return {
1238
+ name: "Z-Index Tokens",
1239
+ passed: issues.length === 0,
1240
+ blocking: false,
1241
+ issues,
1242
+ duration: Date.now() - startTime,
1243
+ };
1244
+ }
1245
+ /**
1246
+ * Recharts Lazy Loading Check
1247
+ */
1248
+ async checkRechartsLazyLoading() {
1249
+ const startTime = Date.now();
1250
+ const issues = [];
1251
+ const files = await getAppComponentsTsxFiles();
1252
+ for (const file of files) {
1253
+ const content = fs.readFileSync(file, "utf8");
1254
+ // Check for static recharts imports
1255
+ const rechartsImport = /import\s+\{[^}]+\}\s+from\s+["']recharts["']/;
1256
+ if (rechartsImport.test(content)) {
1257
+ // Check if it's using dynamic import
1258
+ if (!content.includes("dynamic(") || !content.includes("recharts")) {
1259
+ const lineNumber = content.split("\n").findIndex((l) => rechartsImport.test(l)) + 1;
1260
+ issues.push({
1261
+ file,
1262
+ line: lineNumber,
1263
+ type: "static-recharts",
1264
+ severity: "warning",
1265
+ message: "Static recharts import (~200KB)",
1266
+ suggestion: 'Use dynamic(() => import("recharts").then(mod => mod.Component), { ssr: false })',
1267
+ });
1268
+ }
1269
+ }
1270
+ }
1271
+ return {
1272
+ name: "Recharts Lazy Loading",
1273
+ passed: issues.length === 0,
1274
+ blocking: false,
1275
+ issues,
1276
+ duration: Date.now() - startTime,
1277
+ };
1278
+ }
1279
+ /**
1280
+ * Dialog Lazy Loading Check
1281
+ */
1282
+ async checkDialogLazyLoading() {
1283
+ const startTime = Date.now();
1284
+ const issues = [];
1285
+ const files = await getAppTsxFiles();
1286
+ for (const file of files) {
1287
+ const content = fs.readFileSync(file, "utf8");
1288
+ // Check for static dialog imports from local components
1289
+ const dialogImport = /import\s+\{[^}]*Dialog[^}]*\}\s+from\s+["']\.\/components/;
1290
+ if (dialogImport.test(content)) {
1291
+ const lineNumber = content.split("\n").findIndex((l) => dialogImport.test(l)) + 1;
1292
+ issues.push({
1293
+ file,
1294
+ line: lineNumber,
1295
+ type: "static-dialog",
1296
+ severity: "info",
1297
+ message: "Static dialog import - consider lazy loading",
1298
+ suggestion: "Use DynamicXxxDialog from @/lib/dynamic-imports for dialogs that are not immediately visible",
1299
+ });
1300
+ }
1301
+ }
1302
+ return {
1303
+ name: "Dialog Lazy Loading",
1304
+ passed: true,
1305
+ blocking: false,
1306
+ issues,
1307
+ duration: Date.now() - startTime,
1308
+ };
1309
+ }
1310
+ /**
1311
+ * Database Query Efficiency Check
1312
+ * Detects N+1 query patterns and suggests Prisma include
1313
+ */
1314
+ async checkDatabaseQueryEfficiency() {
1315
+ const startTime = Date.now();
1316
+ const issues = [];
1317
+ const files = await getAppLibFiles();
1318
+ for (const file of files) {
1319
+ const content = fs.readFileSync(file, "utf8");
1320
+ const lines = content.split("\n");
1321
+ // Check for N+1 pattern: findMany followed by separate queries for related data
1322
+ const hasFindMany = /prisma\.\w+\.findMany/.test(content);
1323
+ const hasManualStitching = /\.map\s*\(\s*\([^)]*\)\s*=>\s*[^)]*\.get\s*\(/.test(content);
1324
+ const hasParallelQueries = /Promise\.all\s*\(\s*\[[\s\S]*?prisma\.\w+\.findMany[\s\S]*?\]\s*\)/.test(content);
1325
+ if (hasFindMany && hasManualStitching && hasParallelQueries) {
1326
+ // Find the line with findMany
1327
+ const lineNumber = lines.findIndex((l) => /prisma\.\w+\.findMany/.test(l)) + 1;
1328
+ issues.push({
1329
+ file,
1330
+ line: lineNumber,
1331
+ type: "n-plus-1-pattern",
1332
+ severity: "warning",
1333
+ message: "Potential N+1 query pattern detected (findMany + separate relation queries)",
1334
+ suggestion: "Use Prisma include: { relatedModel: true } for single optimized query",
1335
+ });
1336
+ }
1337
+ // Check for force-dynamic without caching
1338
+ if (content.includes("dynamic = 'force-dynamic'") ||
1339
+ content.includes('dynamic = "force-dynamic"')) {
1340
+ const hasUnstableCache = content.includes("unstable_cache");
1341
+ const lineNumber = lines.findIndex((l) => /dynamic\s*=\s*['"]force-dynamic['"]/.test(l)) + 1;
1342
+ // Skip layout.tsx which has a documented reason
1343
+ if (!file.includes("layout.tsx") && !hasUnstableCache) {
1344
+ issues.push({
1345
+ file,
1346
+ line: lineNumber,
1347
+ type: "force-dynamic-no-cache",
1348
+ severity: "warning",
1349
+ message: "force-dynamic without unstable_cache disables all caching",
1350
+ suggestion: "Remove force-dynamic and use unstable_cache for data fetching, or add caching if dynamic is required",
1351
+ });
1352
+ }
1353
+ }
1354
+ }
1355
+ return {
1356
+ name: "Database Query Efficiency",
1357
+ passed: issues.length === 0,
1358
+ blocking: false,
1359
+ issues,
1360
+ duration: Date.now() - startTime,
1361
+ };
1362
+ }
1363
+ async runAll() {
1364
+ const startTime = Date.now();
1365
+ console.log(`\n${console_chars_1.emoji.lightning} CONSOLIDATED PERFORMANCE PREFLIGHT`);
1366
+ console.log((0, console_chars_1.createDivider)(80, "heavy"));
1367
+ const checkPromises = [
1368
+ this.checkBundleSize(),
1369
+ this.checkImageOptimization(),
1370
+ this.checkLazyLoading(),
1371
+ this.checkSkeletonLoaders(),
1372
+ this.checkVirtualScroll(),
1373
+ this.checkZIndexTokens(),
1374
+ this.checkRechartsLazyLoading(),
1375
+ this.checkDialogLazyLoading(),
1376
+ this.checkDatabaseQueryEfficiency(),
1377
+ ];
1378
+ if (process.env.PREFLIGHT_ENABLE_PAGELOAD_BUDGETS === "1") {
1379
+ checkPromises.push(this.checkPageLoadBudgets());
1380
+ }
1381
+ const checks = await Promise.all(checkPromises);
1382
+ const totalDuration = Date.now() - startTime;
1383
+ const allIssues = checks.flatMap((c) => c.issues);
1384
+ const hasBlockingFailure = checks.some((c) => !c.passed && c.blocking);
1385
+ const summary = {
1386
+ total: checks.length,
1387
+ passed: checks.filter((c) => c.passed).length,
1388
+ failed: checks.filter((c) => !c.passed).length,
1389
+ errors: allIssues.filter((i) => i.severity === "error").length,
1390
+ warnings: allIssues.filter((i) => i.severity === "warning").length,
1391
+ };
1392
+ this.printResults(checks, totalDuration, summary, hasBlockingFailure);
1393
+ return {
1394
+ module: "performance",
1395
+ passed: !hasBlockingFailure,
1396
+ totalDuration,
1397
+ checks,
1398
+ summary,
1399
+ };
1400
+ }
1401
+ printResults(checks, totalDuration, summary, hasBlockingFailure) {
1402
+ console.log("\n" + (0, console_chars_1.createDivider)(80, "heavy"));
1403
+ console.log(`${console_chars_1.emoji.chart} PERFORMANCE RESULTS`);
1404
+ console.log((0, console_chars_1.createDivider)(80, "heavy"));
1405
+ const allIssues = checks.flatMap((c) => c.issues);
1406
+ checks.forEach((check) => {
1407
+ const icon = check.passed
1408
+ ? `${console_chars_1.emoji.success}`
1409
+ : check.blocking
1410
+ ? `${console_chars_1.emoji.error}`
1411
+ : `${console_chars_1.emoji.warning}`;
1412
+ const count = check.issues.length > 0 ? ` (${check.issues.length} issues)` : "";
1413
+ console.log(`${icon} ${check.name.padEnd(30)} ${(check.duration / 1000).toFixed(1)}s${count}`);
1414
+ });
1415
+ console.log((0, console_chars_1.createDivider)(80, "heavy"));
1416
+ console.log(`Warnings: ${summary.warnings} | Info: ${allIssues.filter((i) => i.severity === "info").length} | Time: ${(totalDuration / 1000).toFixed(1)}s`);
1417
+ const shouldPrintDetails = hasBlockingFailure || this.verbose || process.env.PREFLIGHT_VERBOSE === "1";
1418
+ if (shouldPrintDetails) {
1419
+ console.log("\nšŸ“Œ Details (top findings)");
1420
+ console.log((0, console_chars_1.createDivider)(80, "heavy"));
1421
+ for (const check of checks) {
1422
+ if (check.issues.length === 0)
1423
+ continue;
1424
+ console.log(`\n${console_chars_1.chars.bullet} ${check.name} (${check.issues.length})`);
1425
+ // Special formatting for page routes
1426
+ if (check.name === "Page Load Budgets") {
1427
+ const byRoute = new Map();
1428
+ for (const issue of check.issues) {
1429
+ const key = issue.file || "unknown";
1430
+ if (!byRoute.has(key))
1431
+ byRoute.set(key, []);
1432
+ byRoute.get(key).push(issue);
1433
+ }
1434
+ const sorted = Array.from(byRoute.entries()).sort((a, b) => b[1].filter((i) => i.severity !== "info").length -
1435
+ a[1].filter((i) => i.severity !== "info").length);
1436
+ for (const [route, routeIssues] of sorted.slice(0, 15)) {
1437
+ const failing = routeIssues.filter((i) => i.severity !== "info");
1438
+ const info = routeIssues.filter((i) => i.severity === "info");
1439
+ const label = failing.length > 0 ? `${console_chars_1.emoji.error}` : `${console_chars_1.emoji.info}`;
1440
+ console.log(` ${label} ${route} (${failing.length} blocking/warn, ${info.length} info)`);
1441
+ routeIssues.slice(0, 6).forEach((i) => {
1442
+ const sev = i.severity === "error" ? "ERROR" : i.severity === "warning" ? "WARN" : "INFO";
1443
+ console.log(` - [${sev}] ${i.message}`);
1444
+ });
1445
+ if (routeIssues.length > 6)
1446
+ console.log(` - ... +${routeIssues.length - 6} more`);
1447
+ }
1448
+ }
1449
+ else {
1450
+ check.issues.slice(0, 15).forEach((i) => {
1451
+ const sev = i.severity === "error" ? "ERROR" : i.severity === "warning" ? "WARN" : "INFO";
1452
+ console.log(` - [${sev}] ${i.file}${i.line ? `:${i.line}` : ""} ${i.message}`);
1453
+ });
1454
+ if (check.issues.length > 15)
1455
+ console.log(` - ... +${check.issues.length - 15} more`);
1456
+ }
1457
+ }
1458
+ }
1459
+ if (hasBlockingFailure) {
1460
+ console.log(`\n${console_chars_1.emoji.error} PERFORMANCE FAILED (blocking)`);
1461
+ }
1462
+ else if (summary.warnings > 0) {
1463
+ console.log(`\n${console_chars_1.emoji.warning} PERFORMANCE PASSED WITH WARNINGS`);
1464
+ }
1465
+ else {
1466
+ console.log(`\n${console_chars_1.emoji.success} PERFORMANCE PASSED`);
1467
+ }
1468
+ }
1469
+ }
1470
+ exports.PerformancePreflightModule = PerformancePreflightModule;
1471
+ async function main() {
1472
+ const reporter = (0, universal_progress_reporter_1.createUniversalProgressReporter)(path.basename(__filename, ".ts"));
1473
+ const args = process.argv.slice(2);
1474
+ const mode = args[0] || "all";
1475
+ const verbose = args.includes("--verbose") || args.includes("-v");
1476
+ const parallel = args.includes("--parallel") || args.includes("-p");
1477
+ const module = new PerformancePreflightModule({ verbose, parallel });
1478
+ const runSingle = async (name, fn) => {
1479
+ const check = await fn();
1480
+ console.log(`\n${check.passed ? "${emoji.success}" : "${emoji.warning}"} ${check.name}: ${check.issues.length} issues`);
1481
+ if (check.issues.length > 0) {
1482
+ const shouldPrintMore = !check.passed || check.blocking || verbose || process.env.PREFLIGHT_VERBOSE === "1";
1483
+ const limit = shouldPrintMore ? 30 : 5;
1484
+ check.issues
1485
+ .slice(0, limit)
1486
+ .forEach((i) => console.log(` ${i.file}${i.line ? `:${i.line}` : ""} - ${i.message}`));
1487
+ if (check.issues.length > limit)
1488
+ console.log(` ... and ${check.issues.length - limit} more`);
1489
+ }
1490
+ const hasBlockingFailure = !check.passed && check.blocking;
1491
+ return {
1492
+ module: `performance:${name}`,
1493
+ passed: !hasBlockingFailure,
1494
+ totalDuration: check.duration,
1495
+ checks: [check],
1496
+ summary: {
1497
+ total: 1,
1498
+ passed: check.passed ? 1 : 0,
1499
+ failed: check.passed ? 0 : 1,
1500
+ errors: check.issues.filter((i) => i.severity === "error").length,
1501
+ warnings: check.issues.filter((i) => i.severity === "warning").length,
1502
+ },
1503
+ };
1504
+ };
1505
+ let result;
1506
+ switch (mode) {
1507
+ case "bundle":
1508
+ result = await runSingle("bundle", () => module.checkBundleSize());
1509
+ break;
1510
+ case "images":
1511
+ result = await runSingle("images", () => module.checkImageOptimization());
1512
+ break;
1513
+ case "lazy":
1514
+ result = await runSingle("lazy", () => module.checkLazyLoading());
1515
+ break;
1516
+ case "skeleton":
1517
+ result = await runSingle("skeleton", () => module.checkSkeletonLoaders());
1518
+ break;
1519
+ case "virtual":
1520
+ result = await runSingle("virtual", () => module.checkVirtualScroll());
1521
+ break;
1522
+ case "zindex":
1523
+ result = await runSingle("zindex", () => module.checkZIndexTokens());
1524
+ break;
1525
+ case "recharts":
1526
+ result = await runSingle("recharts", () => module.checkRechartsLazyLoading());
1527
+ break;
1528
+ case "dialogs":
1529
+ result = await runSingle("dialogs", () => module.checkDialogLazyLoading());
1530
+ break;
1531
+ case "queries":
1532
+ result = await runSingle("queries", () => module.checkDatabaseQueryEfficiency());
1533
+ break;
1534
+ case "pageload":
1535
+ result = await runSingle("pageload", () => module.checkPageLoadBudgets());
1536
+ break;
1537
+ default:
1538
+ result = await module.runAll();
1539
+ break;
1540
+ }
1541
+ process.exit(result.passed ? 0 : 1);
1542
+ }
1543
+ if (require.main === module) {
1544
+ main();
1545
+ }
1546
+ //# sourceMappingURL=performance.js.map