@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,1438 @@
1
+ #!/usr/bin/env tsx
2
+ "use strict";
3
+ /**
4
+ * SEO Preflight (Authoritative)
5
+ *
6
+ * This module is used in two ways:
7
+ * 1) Imported by the main preflight system (via the consolidated module runner)
8
+ * - Should be non-blocking by default (returns passed=true with warnings)
9
+ * 2) Executed directly via `pnpm preflight:seo` (package.json)
10
+ * - Supports `--strict` to fail on blocking issues
11
+ *
12
+ * Goals:
13
+ * - Single source of truth for SEO validation.
14
+ * - Keep legacy node-based SEO checks (already battle-tested).
15
+ * - Add missing coverage: metadata presence/quality, OG/Twitter correctness,
16
+ * robots/sitemap safety rails, and crawlable internal linking.
17
+ */
18
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ var desc = Object.getOwnPropertyDescriptor(m, k);
21
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
22
+ desc = { enumerable: true, get: function() { return m[k]; } };
23
+ }
24
+ Object.defineProperty(o, k2, desc);
25
+ }) : (function(o, m, k, k2) {
26
+ if (k2 === undefined) k2 = k;
27
+ o[k2] = m[k];
28
+ }));
29
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
30
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
31
+ }) : function(o, v) {
32
+ o["default"] = v;
33
+ });
34
+ var __importStar = (this && this.__importStar) || (function () {
35
+ var ownKeys = function(o) {
36
+ ownKeys = Object.getOwnPropertyNames || function (o) {
37
+ var ar = [];
38
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
39
+ return ar;
40
+ };
41
+ return ownKeys(o);
42
+ };
43
+ return function (mod) {
44
+ if (mod && mod.__esModule) return mod;
45
+ var result = {};
46
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
47
+ __setModuleDefault(result, mod);
48
+ return result;
49
+ };
50
+ })();
51
+ Object.defineProperty(exports, "__esModule", { value: true });
52
+ exports.default = run;
53
+ const child_process_1 = require("child_process");
54
+ const fs = __importStar(require("fs"));
55
+ const path = __importStar(require("path"));
56
+ const ts = __importStar(require("typescript"));
57
+ const console_chars_1 = require("../../utils/console-chars");
58
+ const file_cache_1 = require("../../shared/file-cache");
59
+ const glob_1 = require("glob");
60
+ const EXCLUDED_GLOBS = [
61
+ "**/node_modules/**",
62
+ "**/.next/**",
63
+ "**/dist/**",
64
+ "**/coverage/**",
65
+ "**/test-results/**",
66
+ "**/__tests__/**",
67
+ "**/*.test.*",
68
+ "**/*.spec.*",
69
+ ];
70
+ function readText(filePath) {
71
+ return fs.readFileSync(filePath, "utf8");
72
+ }
73
+ function addIssue(issues, issue) {
74
+ issues.push(issue);
75
+ }
76
+ function formatIssue(issue) {
77
+ const where = issue.file ? ` (${issue.file})` : "";
78
+ return `${issue.message}${where}`;
79
+ }
80
+ function runScriptAsChildProcess(params) {
81
+ const { command, args, label, strict, verbose, alwaysWarn } = params;
82
+ return new Promise((resolve) => {
83
+ const child = (0, child_process_1.spawn)(command, args, {
84
+ cwd: process.cwd(),
85
+ stdio: ["ignore", "pipe", "pipe"],
86
+ });
87
+ let stdout = "";
88
+ let stderr = "";
89
+ child.stdout.on("data", (data) => {
90
+ stdout += data.toString();
91
+ });
92
+ child.stderr.on("data", (data) => {
93
+ stderr += data.toString();
94
+ });
95
+ child.on("close", (code) => {
96
+ stdout = stdout.trim();
97
+ stderr = stderr.trim();
98
+ if (verbose) {
99
+ if (stdout)
100
+ console.log(stdout);
101
+ if (stderr)
102
+ console.error(stderr);
103
+ }
104
+ // Heuristic: non-zero exit code is blocking in strict mode, warning otherwise.
105
+ if (code && code !== 0) {
106
+ const severity = alwaysWarn ? "warning" : strict ? "blocking" : "warning";
107
+ const message = `${label} failed (exit ${code})`;
108
+ const details = [stdout, stderr].filter(Boolean).join("\n");
109
+ resolve([
110
+ {
111
+ severity,
112
+ message: details ? `${message}: ${details.split("\n")[0]}` : message,
113
+ },
114
+ ]);
115
+ return;
116
+ }
117
+ // Some scripts return 0 but contain warnings; surface a summary line (optional).
118
+ if (!strict && stdout.includes(`${console_chars_1.emoji.warning}`) && !stdout.includes(`${console_chars_1.emoji.error}`)) {
119
+ resolve([
120
+ {
121
+ severity: "warning",
122
+ message: `${label} reported warnings`,
123
+ },
124
+ ]);
125
+ return;
126
+ }
127
+ resolve([]);
128
+ });
129
+ child.on("error", (err) => {
130
+ resolve([
131
+ {
132
+ severity: "blocking",
133
+ message: `${label} failed to spawn: ${err.message}`,
134
+ },
135
+ ]);
136
+ });
137
+ });
138
+ }
139
+ function parseMetadataLiteralForStrings(content) {
140
+ // Deprecated: kept for backward compatibility in case other callers rely on it.
141
+ // New checks use AST parsing (see analyzeNextMetadata()).
142
+ const titleMatch = content.match(/\btitle\s*:\s*(?:"([^"\n]+)"|'([^'\n]+)'|`([^`\n]+)`)/);
143
+ const descriptionMatch = content.match(/\bdescription\s*:\s*(?:"([^"\n]+)"|'([^'\n]+)'|`([^`\n]+)`)/);
144
+ const title = (titleMatch?.[1] || titleMatch?.[2] || titleMatch?.[3])?.trim();
145
+ const description = (descriptionMatch?.[1] ||
146
+ descriptionMatch?.[2] ||
147
+ descriptionMatch?.[3])?.trim();
148
+ return { title, description };
149
+ }
150
+ function tryGetLiteralString(node) {
151
+ if (!node)
152
+ return undefined;
153
+ if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
154
+ return { value: node.text, kind: "string" };
155
+ }
156
+ if (ts.isTemplateExpression(node)) {
157
+ const head = node.head.text;
158
+ const hasExpressions = node.templateSpans.length > 0;
159
+ if (!hasExpressions)
160
+ return { value: head, kind: "template" };
161
+ return undefined;
162
+ }
163
+ return undefined;
164
+ }
165
+ function isFalseLiteral(expr) {
166
+ return expr?.kind === ts.SyntaxKind.FalseKeyword;
167
+ }
168
+ function getPropertyNameText(name) {
169
+ if (ts.isIdentifier(name))
170
+ return name.text;
171
+ if (ts.isStringLiteral(name))
172
+ return name.text;
173
+ if (ts.isNumericLiteral(name))
174
+ return name.text;
175
+ return undefined;
176
+ }
177
+ function collectObjectLiteralProps(expr, out) {
178
+ if (!expr)
179
+ return;
180
+ if (!ts.isObjectLiteralExpression(expr))
181
+ return;
182
+ for (const prop of expr.properties) {
183
+ if (ts.isPropertyAssignment(prop)) {
184
+ const key = getPropertyNameText(prop.name);
185
+ if (key)
186
+ out.set(key, prop.initializer);
187
+ }
188
+ else if (ts.isShorthandPropertyAssignment(prop)) {
189
+ out.set(prop.name.text, prop.name);
190
+ }
191
+ else if (ts.isSpreadAssignment(prop)) {
192
+ const spreadExpr = prop.expression;
193
+ // Common pattern: ...buildMetadata({ title, description, path })
194
+ if (ts.isCallExpression(spreadExpr) && spreadExpr.arguments.length > 0) {
195
+ const arg0 = spreadExpr.arguments[0];
196
+ if (ts.isObjectLiteralExpression(arg0))
197
+ collectObjectLiteralProps(arg0, out);
198
+ }
199
+ }
200
+ }
201
+ }
202
+ function tryGetNestedLiteralString(root, pathSegments) {
203
+ let current = root;
204
+ for (const seg of pathSegments) {
205
+ if (!current || !ts.isObjectLiteralExpression(current))
206
+ return undefined;
207
+ const props = new Map();
208
+ collectObjectLiteralProps(current, props);
209
+ current = props.get(seg);
210
+ }
211
+ return tryGetLiteralString(current);
212
+ }
213
+ function isLikelyInternalOrAuthRoute(routePath) {
214
+ return (routePath.startsWith("/admin") ||
215
+ routePath.startsWith("/api") ||
216
+ routePath.startsWith("/account") ||
217
+ routePath.startsWith("/auth") ||
218
+ routePath.startsWith("/dashboard") ||
219
+ routePath.startsWith("/seller") ||
220
+ routePath.startsWith("/store/") ||
221
+ routePath.startsWith("/login") ||
222
+ routePath.startsWith("/register") ||
223
+ routePath.startsWith("/reset-password") ||
224
+ routePath.startsWith("/forgot-password"));
225
+ }
226
+ function classifyAppFileKind(appFile) {
227
+ if (!appFile.startsWith("app\\") && !appFile.startsWith("app/"))
228
+ return "public";
229
+ const normalized = appFile.replace(/\\/g, "/");
230
+ const routePath = "/" +
231
+ normalized
232
+ .replace(/^app\//, "")
233
+ .replace(/\/(page|layout|template|loading|error|not-found|head)\.(ts|tsx)$/, "");
234
+ return isLikelyInternalOrAuthRoute(routePath) ? "internal" : "public";
235
+ }
236
+ function findExportedConstInitializer(sf, name) {
237
+ for (const statement of sf.statements) {
238
+ if (!ts.isVariableStatement(statement))
239
+ continue;
240
+ const hasExport = statement.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
241
+ if (!hasExport)
242
+ continue;
243
+ for (const decl of statement.declarationList.declarations) {
244
+ if (!ts.isIdentifier(decl.name))
245
+ continue;
246
+ if (decl.name.text !== name)
247
+ continue;
248
+ return decl.initializer;
249
+ }
250
+ }
251
+ return undefined;
252
+ }
253
+ function findExportedFunctionDeclaration(sf, name) {
254
+ for (const statement of sf.statements) {
255
+ if (!ts.isFunctionDeclaration(statement))
256
+ continue;
257
+ if (!statement.name || statement.name.text !== name)
258
+ continue;
259
+ const hasExport = statement.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
260
+ if (!hasExport)
261
+ continue;
262
+ return statement;
263
+ }
264
+ return undefined;
265
+ }
266
+ function hasReexportedNamedExport(sf, exportName) {
267
+ for (const statement of sf.statements) {
268
+ if (!ts.isExportDeclaration(statement))
269
+ continue;
270
+ if (!statement.exportClause)
271
+ continue;
272
+ if (!ts.isNamedExports(statement.exportClause))
273
+ continue;
274
+ for (const el of statement.exportClause.elements) {
275
+ if (el.name.text === exportName)
276
+ return true;
277
+ if (el.propertyName && el.propertyName.text === exportName)
278
+ return true;
279
+ }
280
+ }
281
+ return false;
282
+ }
283
+ function collectReturnedObjectLiterals(fn) {
284
+ const objects = [];
285
+ if (!fn.body)
286
+ return objects;
287
+ const visit = (node) => {
288
+ if (ts.isReturnStatement(node) &&
289
+ node.expression &&
290
+ ts.isObjectLiteralExpression(node.expression)) {
291
+ objects.push(node.expression);
292
+ }
293
+ ts.forEachChild(node, visit);
294
+ };
295
+ visit(fn.body);
296
+ return objects;
297
+ }
298
+ function analyzeNextMetadata(sourceText, fileNameForDiagnostics) {
299
+ const sf = ts.createSourceFile(fileNameForDiagnostics, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
300
+ const metadataInit = findExportedConstInitializer(sf, "metadata");
301
+ const generateMetadataFn = findExportedFunctionDeclaration(sf, "generateMetadata");
302
+ const hasReexportedMetadata = hasReexportedNamedExport(sf, "metadata");
303
+ const hasReexportedGenerateMetadata = hasReexportedNamedExport(sf, "generateMetadata");
304
+ const metadataProps = new Map();
305
+ if (metadataInit)
306
+ collectObjectLiteralProps(metadataInit, metadataProps);
307
+ const returnedMetadataProps = [];
308
+ if (generateMetadataFn) {
309
+ const returnedObjects = collectReturnedObjectLiterals(generateMetadataFn);
310
+ for (const obj of returnedObjects) {
311
+ const props = new Map();
312
+ collectObjectLiteralProps(obj, props);
313
+ returnedMetadataProps.push(props);
314
+ }
315
+ }
316
+ const hasMetadataExport = Boolean(metadataInit) || hasReexportedMetadata;
317
+ const hasGenerateMetadata = Boolean(generateMetadataFn) || hasReexportedGenerateMetadata;
318
+ const hasTitle = (hasMetadataExport && metadataProps.has("title")) ||
319
+ (hasGenerateMetadata && returnedMetadataProps.some((p) => p.has("title")));
320
+ const hasDescription = (hasMetadataExport && metadataProps.has("description")) ||
321
+ (hasGenerateMetadata && returnedMetadataProps.some((p) => p.has("description")));
322
+ const titleLiteral = (hasMetadataExport
323
+ ? tryGetLiteralString(metadataProps.get("title"))
324
+ : undefined) ||
325
+ (hasGenerateMetadata
326
+ ? (() => {
327
+ for (const p of returnedMetadataProps) {
328
+ const lit = tryGetLiteralString(p.get("title"));
329
+ if (lit)
330
+ return lit;
331
+ }
332
+ return undefined;
333
+ })()
334
+ : undefined);
335
+ const descriptionLiteral = (hasMetadataExport
336
+ ? tryGetLiteralString(metadataProps.get("description"))
337
+ : undefined) ||
338
+ (hasGenerateMetadata
339
+ ? (() => {
340
+ for (const p of returnedMetadataProps) {
341
+ const lit = tryGetLiteralString(p.get("description"));
342
+ if (lit)
343
+ return lit;
344
+ }
345
+ return undefined;
346
+ })()
347
+ : undefined);
348
+ const robotsIndexFalse = (hasMetadataExport &&
349
+ (() => {
350
+ const robotsExpr = metadataProps.get("robots");
351
+ if (!robotsExpr)
352
+ return false;
353
+ const robotsProps = new Map();
354
+ collectObjectLiteralProps(robotsExpr, robotsProps);
355
+ const indexExpr = robotsProps.get("index");
356
+ return isFalseLiteral(indexExpr);
357
+ })()) ||
358
+ (hasGenerateMetadata &&
359
+ returnedMetadataProps.some((props) => {
360
+ const robotsExpr = props.get("robots");
361
+ if (!robotsExpr)
362
+ return false;
363
+ const robotsProps = new Map();
364
+ collectObjectLiteralProps(robotsExpr, robotsProps);
365
+ const indexExpr = robotsProps.get("index");
366
+ return isFalseLiteral(indexExpr);
367
+ }));
368
+ return {
369
+ hasMetadataExport,
370
+ hasGenerateMetadata,
371
+ hasTitle,
372
+ hasDescription,
373
+ titleLiteral,
374
+ descriptionLiteral,
375
+ canonicalLiteral: (hasMetadataExport
376
+ ? tryGetNestedLiteralString(metadataInit, ["alternates", "canonical"])
377
+ : undefined) ||
378
+ (hasGenerateMetadata
379
+ ? (() => {
380
+ for (const props of returnedMetadataProps) {
381
+ const canonical = tryGetNestedLiteralString(props.get("alternates"), ["canonical"]);
382
+ if (canonical)
383
+ return canonical;
384
+ }
385
+ return undefined;
386
+ })()
387
+ : undefined),
388
+ openGraphUrlLiteral: (hasMetadataExport
389
+ ? tryGetNestedLiteralString(metadataInit, ["openGraph", "url"])
390
+ : undefined) ||
391
+ (hasGenerateMetadata
392
+ ? (() => {
393
+ for (const props of returnedMetadataProps) {
394
+ const url = tryGetNestedLiteralString(props.get("openGraph"), ["url"]);
395
+ if (url)
396
+ return url;
397
+ }
398
+ return undefined;
399
+ })()
400
+ : undefined),
401
+ robotsIndexFalse,
402
+ hasReexportedMetadata,
403
+ hasReexportedGenerateMetadata,
404
+ };
405
+ }
406
+ function classifyPageKind(file) {
407
+ if (file.includes("/api/") || file.includes("\\api\\"))
408
+ return "internal";
409
+ const routePath = "/" +
410
+ file
411
+ .replace(/^app[\\/]/, "")
412
+ .replace(/[\\/]page\.(ts|tsx)$/, "")
413
+ .replace(/\\/g, "/");
414
+ if (isLikelyInternalOrAuthRoute(routePath))
415
+ return "internal";
416
+ return "public";
417
+ }
418
+ function isAbsoluteHttpUrl(value) {
419
+ return /^https?:\/\//i.test(value);
420
+ }
421
+ function stripJsComments(input) {
422
+ // Best-effort removal of /* */ and // comments to reduce false positives.
423
+ return input.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:\\])\/\/.*$/gm, "$1");
424
+ }
425
+ function isRelativeRootPath(value) {
426
+ return value.startsWith("/");
427
+ }
428
+ function checkMetadataUrlCorrectness(params) {
429
+ const { file, analysis, strict, ci, hasRootMetadataBase } = params;
430
+ const issues = [];
431
+ const pageKind = classifyPageKind(file);
432
+ if (pageKind !== "public")
433
+ return issues;
434
+ const canonical = analysis.canonicalLiteral?.value?.trim();
435
+ if (canonical) {
436
+ if (isAbsoluteHttpUrl(canonical)) {
437
+ // OK
438
+ }
439
+ else if (isRelativeRootPath(canonical)) {
440
+ // Relative canonicals are acceptable if metadataBase is configured.
441
+ if (!hasRootMetadataBase) {
442
+ addIssue(issues, {
443
+ severity: ci ? "blocking" : "warning",
444
+ file,
445
+ message: "Page uses a relative canonical but root metadataBase is missing (canonical may become incorrect)",
446
+ });
447
+ }
448
+ else {
449
+ addIssue(issues, {
450
+ severity: "info",
451
+ file,
452
+ message: "Canonical is relative; ensure metadataBase is correct for absolute output",
453
+ });
454
+ }
455
+ }
456
+ else {
457
+ addIssue(issues, {
458
+ severity: ci ? "blocking" : "warning",
459
+ file,
460
+ message: "Canonical URL does not look like an absolute URL or root-relative path",
461
+ });
462
+ }
463
+ }
464
+ const ogUrl = analysis.openGraphUrlLiteral?.value?.trim();
465
+ if (ogUrl) {
466
+ // Best practice: OpenGraph url should be absolute for scrapers.
467
+ if (!isAbsoluteHttpUrl(ogUrl)) {
468
+ addIssue(issues, {
469
+ severity: ci ? "blocking" : "warning",
470
+ file,
471
+ message: "openGraph.url should be an absolute URL (e.g., derived from SITE_URL)",
472
+ });
473
+ }
474
+ }
475
+ return issues;
476
+ }
477
+ // CACHED FILE LISTS - Scan once, use everywhere
478
+ let _cachedPageTsFiles = null;
479
+ async function getPageTsFiles() {
480
+ if (!_cachedPageTsFiles) {
481
+ _cachedPageTsFiles = await file_cache_1.fileCache.getPageTsFiles();
482
+ }
483
+ return _cachedPageTsFiles;
484
+ }
485
+ async function checkForceDynamicCaching(options) {
486
+ const issues = [];
487
+ const strict = options.strict;
488
+ const ci = options.ci;
489
+ const pageFiles = await getPageTsFiles();
490
+ for (const file of pageFiles) {
491
+ const pageKind = classifyPageKind(file);
492
+ if (pageKind !== "public")
493
+ continue;
494
+ const content = readText(path.join(process.cwd(), file));
495
+ const isForceDynamic = /export\s+const\s+dynamic\s*=\s*['"]force-dynamic['"]/.test(content);
496
+ if (!isForceDynamic)
497
+ continue;
498
+ const usesUnstableCache = /unstable_cache\b/.test(content);
499
+ const hasRevalidateConst = /export\s+const\s+revalidate\s*=\s*\d+/.test(content);
500
+ const usesFetchRevalidate = /next\s*:\s*\{\s*revalidate\s*:\s*\d+/.test(content);
501
+ if (!usesUnstableCache && !hasRevalidateConst && !usesFetchRevalidate) {
502
+ addIssue(issues, {
503
+ severity: ci ? "blocking" : "warning",
504
+ file,
505
+ message: "Page sets dynamic=force-dynamic but shows no unstable_cache/ISR revalidate; consider caching to avoid per-request database work",
506
+ });
507
+ }
508
+ }
509
+ return issues;
510
+ }
511
+ async function checkPaginationMetadataHeuristics(options) {
512
+ const issues = [];
513
+ const strict = options.strict;
514
+ const ci = options.ci;
515
+ const pageFiles = await getPageTsFiles();
516
+ for (const file of pageFiles) {
517
+ const pageKind = classifyPageKind(file);
518
+ if (pageKind !== "public")
519
+ continue;
520
+ const raw = readText(path.join(process.cwd(), file));
521
+ const content = stripJsComments(raw);
522
+ // Heuristics for pagination:
523
+ // - Explicit query usage: get('page') OR URLSearchParams({ page: ... })
524
+ // - Pagination component usage: <Pagination ...>
525
+ // Keep this conservative to avoid false positives from unrelated mentions.
526
+ const readsPageQuery = /get\(\s*['"]page['"]\s*\)/.test(content) || /\?page=/.test(content);
527
+ const hasClientPaginationState = /\bcurrentPage\b/.test(content) && /\btotalPages\b/.test(content);
528
+ const hasPageParamUsage = readsPageQuery || hasClientPaginationState;
529
+ const hasPaginationUi = /<Pagination\b/.test(content);
530
+ const looksPaginated = hasPageParamUsage || hasPaginationUi;
531
+ if (!looksPaginated)
532
+ continue;
533
+ const hasPrevNextAlternates = /rel\s*=\s*['"]prev['"]|rel\s*=\s*['"]next['"]/.test(content);
534
+ const usesPaginationHelper = /generatePaginationMetadata\s*\(/.test(content);
535
+ if (!hasPrevNextAlternates && !usesPaginationHelper) {
536
+ addIssue(issues, {
537
+ severity: ci ? "blocking" : strict ? "warning" : "info",
538
+ file,
539
+ message: "Paginated page heuristics detected; consider adding prev/next links via generatePaginationMetadata() for better crawl discovery",
540
+ });
541
+ }
542
+ }
543
+ return issues;
544
+ }
545
+ async function checkTypographyHeadingSemantics(options) {
546
+ const issues = [];
547
+ const strict = options.strict;
548
+ const ci = options.ci;
549
+ const pageFiles = await getPageTsFiles();
550
+ for (const file of pageFiles) {
551
+ const pageKind = classifyPageKind(file);
552
+ if (pageKind !== "public")
553
+ continue;
554
+ const content = readText(path.join(process.cwd(), file));
555
+ // Best-effort scan of Typography tags for semantic heading components.
556
+ // We only gate h1/h2/h3 variants since those matter most for SEO.
557
+ const tagMatches = content.match(/<Typography\b[^>]*>/g) || [];
558
+ for (const tag of tagMatches) {
559
+ const variantMatch = tag.match(/\bvariant\s*=\s*['"](h1|h2|h3)['"]/);
560
+ if (!variantMatch)
561
+ continue;
562
+ const variant = variantMatch[1];
563
+ const hasComponentProp = /\bcomponent\s*=\s*['"]/i.test(tag);
564
+ const componentMatch = tag.match(/\bcomponent\s*=\s*['"](h1|h2|h3|h4|h5|h6)['"]/i);
565
+ if (!hasComponentProp) {
566
+ addIssue(issues, {
567
+ severity: ci ? "blocking" : strict ? "warning" : "info",
568
+ file,
569
+ message: `Typography variant="${variant}" is missing component="${variant}" (semantic headings improve SEO + accessibility)`,
570
+ });
571
+ continue;
572
+ }
573
+ // If component is present but differs, that's usually intentional (ex: visual h2 but semantic h1).
574
+ // We keep this informational even in CI.
575
+ if (componentMatch && componentMatch[1] !== variant) {
576
+ addIssue(issues, {
577
+ severity: "info",
578
+ file,
579
+ message: `Typography variant="${variant}" uses component="${componentMatch[1]}"`,
580
+ });
581
+ }
582
+ }
583
+ }
584
+ return issues;
585
+ }
586
+ async function checkNativeImgAndAltText(options) {
587
+ const issues = [];
588
+ const strict = options.strict;
589
+ const ci = options.ci;
590
+ // Focus on app + product components (high-SEO surface area) to avoid exploding noise.
591
+ const files = await file_cache_1.fileCache.getFiles("{app,components/product}/**/*.{ts,tsx}", { ignore: EXCLUDED_GLOBS });
592
+ for (const file of files) {
593
+ const isUnderApp = file.startsWith("app/") || file.startsWith("app\\");
594
+ if (isUnderApp && classifyAppFileKind(file) !== "public")
595
+ continue;
596
+ const content = readText(path.join(process.cwd(), file));
597
+ const hasImg = /<img\b/i.test(content);
598
+ if (hasImg) {
599
+ addIssue(issues, {
600
+ severity: ci ? "blocking" : strict ? "warning" : "info",
601
+ file,
602
+ message: "Native <img> tag detected; prefer next/image for optimization (or ensure width/height + lazy loading + good alt)",
603
+ });
604
+ }
605
+ const genericAlt = /\balt\s*=\s*['"](card image|image|photo|picture)['"]/i.test(content);
606
+ if (genericAlt) {
607
+ addIssue(issues, {
608
+ severity: ci ? "blocking" : strict ? "warning" : "info",
609
+ file,
610
+ message: "Generic alt text detected; use descriptive alt for SEO/Google Images",
611
+ });
612
+ }
613
+ }
614
+ return issues;
615
+ }
616
+ async function checkSchemaGeneratorSerializability() {
617
+ const issues = [];
618
+ try {
619
+ // These imports should be safe (pure helpers, no DB access).
620
+ const productSchemaModule = await Promise.resolve(`${pathToFileUrl("lib/product-schema.ts")}`).then(s => __importStar(require(s)));
621
+ const seoModule = await Promise.resolve(`${pathToFileUrl("lib/seo.ts")}`).then(s => __importStar(require(s)));
622
+ const { generateProductSchema, generateBreadcrumbSchema, generateImageSchema } = productSchemaModule;
623
+ const { generateFAQPageSchema, generateBreadcrumbSchema: generateSeoBreadcrumbSchema } = seoModule;
624
+ const dummyCard = {
625
+ id: "test",
626
+ featured: "Test Player",
627
+ year: "2024",
628
+ brand: "TOPPS",
629
+ series: "Test Series",
630
+ cardNumber: "1",
631
+ sport: "BASEBALL",
632
+ team: "Test Team",
633
+ productType: "SPORTS_CARD",
634
+ description: "Test description",
635
+ };
636
+ const dummyListing = {
637
+ price: 12.34,
638
+ imageUrls: ["https://example.com/image.jpg"],
639
+ condition: "NEAR_MINT",
640
+ sellerName: "Test Seller",
641
+ quantityAvailable: 1,
642
+ freeShipping: true,
643
+ shippingCost: 0,
644
+ returnPolicy: 30,
645
+ };
646
+ const samples = [];
647
+ if (typeof generateProductSchema === "function") {
648
+ samples.push({
649
+ label: "generateProductSchema",
650
+ value: generateProductSchema(dummyCard, [dummyListing], dummyListing, [dummyListing], "test-slug"),
651
+ });
652
+ }
653
+ if (typeof generateBreadcrumbSchema === "function") {
654
+ samples.push({
655
+ label: "generateBreadcrumbSchema(product)",
656
+ value: generateBreadcrumbSchema(dummyCard, "test-slug"),
657
+ });
658
+ }
659
+ if (typeof generateImageSchema === "function") {
660
+ samples.push({
661
+ label: "generateImageSchema",
662
+ value: generateImageSchema(dummyCard, "https://example.com/image.jpg"),
663
+ });
664
+ }
665
+ if (typeof generateFAQPageSchema === "function") {
666
+ samples.push({
667
+ label: "generateFAQPageSchema",
668
+ value: generateFAQPageSchema([
669
+ { question: "What is SuperCatch?", answer: "A marketplace." },
670
+ ]),
671
+ });
672
+ }
673
+ if (typeof generateSeoBreadcrumbSchema === "function") {
674
+ samples.push({
675
+ label: "generateBreadcrumbSchema(seo)",
676
+ value: generateSeoBreadcrumbSchema([
677
+ { name: "Home", url: "https://example.com" },
678
+ { name: "Test", url: "https://example.com/test" },
679
+ ]),
680
+ });
681
+ }
682
+ for (const sample of samples) {
683
+ try {
684
+ const json = JSON.stringify(sample.value);
685
+ if (!json) {
686
+ addIssue(issues, {
687
+ severity: "warning",
688
+ file: "lib/product-schema.ts",
689
+ message: `${sample.label} produced empty JSON output`,
690
+ });
691
+ continue;
692
+ }
693
+ JSON.parse(json);
694
+ }
695
+ catch (error) {
696
+ addIssue(issues, {
697
+ severity: "blocking",
698
+ file: "lib/product-schema.ts",
699
+ message: `${sample.label} output is not JSON-serializable: ${error?.message || String(error)}`,
700
+ });
701
+ }
702
+ }
703
+ }
704
+ catch (error) {
705
+ addIssue(issues, {
706
+ severity: "warning",
707
+ file: "scripts/active/preflights/seo.ts",
708
+ message: `Could not import schema generators for serializability checks: ${error?.message || String(error)}`,
709
+ });
710
+ }
711
+ return issues;
712
+ }
713
+ function pathToFileUrl(relativePath) {
714
+ // Ensure a stable file:// URL for dynamic imports.
715
+ const absolute = path.join(process.cwd(), relativePath);
716
+ const normalized = absolute.replace(/\\/g, "/");
717
+ return `file:///${normalized.replace(/^\/+/, "")}`;
718
+ }
719
+ async function checkMetadataPresenceAndQuality(options) {
720
+ const issues = [];
721
+ const strict = options.strict;
722
+ const pageFiles = await getPageTsFiles();
723
+ const titlesByFile = [];
724
+ const descriptionsByFile = [];
725
+ const robotsText = (() => {
726
+ const robotsPath = path.join(process.cwd(), "app/robots.ts");
727
+ if (!fs.existsSync(robotsPath))
728
+ return "";
729
+ return readText(robotsPath);
730
+ })();
731
+ const disallowedPrefixes = (() => {
732
+ const prefixes = new Set();
733
+ // Best-effort extraction of string literal disallow entries.
734
+ const matches = robotsText.matchAll(/disallow\s*:\s*\[([\s\S]*?)\]/g);
735
+ for (const m of matches) {
736
+ const list = m[1] || "";
737
+ const itemMatches = list.matchAll(/['"](\/[^'"]+)['"]/g);
738
+ for (const im of itemMatches)
739
+ prefixes.add(im[1]);
740
+ }
741
+ return Array.from(prefixes);
742
+ })();
743
+ const isBlockedByRobots = (routePath) => {
744
+ const normalized = routePath.replace(/\\/g, "/");
745
+ const normalizedWithSlash = normalized.endsWith("/") ? normalized : `${normalized}/`;
746
+ return disallowedPrefixes.some((p) => {
747
+ const prefix = p.endsWith("/") ? p : `${p}/`;
748
+ return normalizedWithSlash.startsWith(prefix);
749
+ });
750
+ };
751
+ const isAuthOrInternal = (file) => {
752
+ const normalized = file.replace(/\\/g, "/");
753
+ const internalPrefixes = [
754
+ "app/admin/",
755
+ "app/account/",
756
+ "app/store/",
757
+ "app/seller/",
758
+ "app/dashboard/",
759
+ "app/checkout/",
760
+ "app/api/",
761
+ "app/dev/", // Dev-only pages
762
+ "app/invite/", // Private invitation pages
763
+ ];
764
+ const authPrefixes = [
765
+ "app/login/",
766
+ "app/register/",
767
+ "app/reset-password/",
768
+ "app/forgot-password/",
769
+ "app/auth/",
770
+ ];
771
+ if (internalPrefixes.some((p) => normalized.startsWith(p)))
772
+ return true;
773
+ if (authPrefixes.some((p) => normalized.startsWith(p)))
774
+ return true;
775
+ return false;
776
+ };
777
+ const findClosestLayoutWithMetadata = (pageFile) => {
778
+ const normalized = pageFile.replace(/\\/g, "/");
779
+ const parts = normalized.split("/");
780
+ // parts[0] === "app"
781
+ for (let i = parts.length - 1; i >= 1; i--) {
782
+ const dir = parts.slice(0, i).join("/");
783
+ const layoutCandidates = [`${dir}/layout.tsx`, `${dir}/layout.ts`];
784
+ for (const candidate of layoutCandidates) {
785
+ const full = path.join(process.cwd(), candidate);
786
+ if (!fs.existsSync(full))
787
+ continue;
788
+ const layoutContent = readText(full);
789
+ const layoutAnalysis = analyzeNextMetadata(layoutContent, candidate);
790
+ if (layoutAnalysis.hasMetadataExport || layoutAnalysis.hasGenerateMetadata) {
791
+ return { file: candidate, analysis: layoutAnalysis };
792
+ }
793
+ }
794
+ }
795
+ return undefined;
796
+ };
797
+ for (const file of pageFiles) {
798
+ const fullPath = path.join(process.cwd(), file);
799
+ const content = readText(fullPath);
800
+ const analysis = analyzeNextMetadata(content, file);
801
+ const closestLayout = findClosestLayoutWithMetadata(file);
802
+ const pageHasOwnMetadata = analysis.hasMetadataExport || analysis.hasGenerateMetadata;
803
+ const effectiveHasMetadata = pageHasOwnMetadata ||
804
+ Boolean(closestLayout?.analysis.hasMetadataExport || closestLayout?.analysis.hasGenerateMetadata);
805
+ const effectiveHasTitle = analysis.hasTitle || Boolean(closestLayout?.analysis.hasTitle);
806
+ const effectiveHasDescription = analysis.hasDescription || Boolean(closestLayout?.analysis.hasDescription);
807
+ const effectiveRobotsNoIndex = analysis.robotsIndexFalse || Boolean(closestLayout?.analysis.robotsIndexFalse);
808
+ const routePath = file
809
+ .replace(/\\/g, "/")
810
+ .replace(/^app\//, "/")
811
+ .replace(/\/page\.(ts|tsx)$/, "");
812
+ // Ignore utility-only pages with special Next.js conventions (rare, but avoid noise)
813
+ const isNotFound = file.endsWith("/not-found.tsx");
814
+ if (isNotFound)
815
+ continue;
816
+ // The homepage often relies on root layout metadata.
817
+ const isRootPage = file.replace(/\\/g, "/") === "app/page.tsx";
818
+ // Requested safety rail: public pages should define their own metadata at the page level
819
+ // (do not rely solely on layouts). In non-strict mode this is a warning; in strict mode it blocks.
820
+ if (!isAuthOrInternal(file) && !isRootPage && !pageHasOwnMetadata) {
821
+ addIssue(issues, {
822
+ severity: strict ? "blocking" : "warning",
823
+ file,
824
+ message: "Public page should export metadata or generateMetadata (page-level), not only via layout",
825
+ });
826
+ }
827
+ // Re-exported metadata is valid, but we can't reliably verify title/description literals.
828
+ if ((analysis.hasReexportedMetadata || analysis.hasReexportedGenerateMetadata) &&
829
+ !isAuthOrInternal(file)) {
830
+ addIssue(issues, {
831
+ severity: "info",
832
+ file,
833
+ message: "Page re-exports metadata/generateMetadata; title/description quality checks may be incomplete",
834
+ });
835
+ }
836
+ if (!effectiveHasMetadata && !isRootPage) {
837
+ addIssue(issues, {
838
+ severity: isAuthOrInternal(file) ? "warning" : strict ? "blocking" : "warning",
839
+ file,
840
+ message: "Route has no metadata/generateMetadata on page or layout chain",
841
+ });
842
+ continue;
843
+ }
844
+ // Indexability rails: internal/auth routes should be noindex OR blocked by robots.ts.
845
+ if (isAuthOrInternal(file)) {
846
+ if (!effectiveRobotsNoIndex && !isBlockedByRobots(routePath)) {
847
+ addIssue(issues, {
848
+ severity: strict ? "blocking" : "warning",
849
+ file,
850
+ message: "Internal/auth route should be noindex (metadata robots.index=false) or blocked via robots.ts",
851
+ });
852
+ }
853
+ // Do not enforce title/description quality on internal/auth routes.
854
+ continue;
855
+ }
856
+ if (!effectiveHasTitle) {
857
+ addIssue(issues, {
858
+ severity: strict ? "blocking" : "warning",
859
+ file,
860
+ message: "Metadata missing title (title is required for SEO)",
861
+ });
862
+ }
863
+ else if (!analysis.hasTitle && Boolean(closestLayout?.analysis.hasTitle)) {
864
+ addIssue(issues, {
865
+ severity: "info",
866
+ file,
867
+ message: "Title appears to be provided by a layout; prefer page-level title for uniqueness",
868
+ });
869
+ }
870
+ if (!effectiveHasDescription) {
871
+ addIssue(issues, {
872
+ severity: strict ? "blocking" : "warning",
873
+ file,
874
+ message: "Metadata missing description (description is required for SEO)",
875
+ });
876
+ }
877
+ else if (!analysis.hasDescription && Boolean(closestLayout?.analysis.hasDescription)) {
878
+ addIssue(issues, {
879
+ severity: "info",
880
+ file,
881
+ message: "Description appears to be provided by a layout; prefer page-level description for uniqueness",
882
+ });
883
+ }
884
+ if (analysis.titleLiteral?.value) {
885
+ const title = analysis.titleLiteral.value.trim();
886
+ if (title) {
887
+ titlesByFile.push({ file, title });
888
+ if (title.length < 30 || title.length > 60) {
889
+ addIssue(issues, {
890
+ severity: "warning",
891
+ file,
892
+ message: `Title length out of bounds (${title.length} chars). Expected ~30–60.`,
893
+ });
894
+ }
895
+ }
896
+ }
897
+ if (analysis.descriptionLiteral?.value) {
898
+ const description = analysis.descriptionLiteral.value.trim();
899
+ if (description) {
900
+ descriptionsByFile.push({ file, description });
901
+ if (description.length < 50 || description.length > 160) {
902
+ addIssue(issues, {
903
+ severity: "warning",
904
+ file,
905
+ message: `Description length out of bounds (${description.length} chars). Expected ~50–160.`,
906
+ });
907
+ }
908
+ }
909
+ }
910
+ }
911
+ // Duplicate-title heuristic (only for literal strings we captured)
912
+ const titleCounts = new Map();
913
+ for (const item of titlesByFile) {
914
+ const key = item.title.toLowerCase();
915
+ titleCounts.set(key, [...(titleCounts.get(key) || []), item.file]);
916
+ }
917
+ for (const [titleKey, files] of titleCounts.entries()) {
918
+ if (files.length >= 2) {
919
+ addIssue(issues, {
920
+ severity: "warning",
921
+ message: `Duplicate page titles detected (${files.length} pages share the same title): "${titleKey}"`,
922
+ file: files.slice(0, 3).join(", ") + (files.length > 3 ? "${chars.ellipsis}" : ""),
923
+ });
924
+ }
925
+ }
926
+ const descriptionCounts = new Map();
927
+ for (const item of descriptionsByFile) {
928
+ const key = item.description.toLowerCase();
929
+ descriptionCounts.set(key, [...(descriptionCounts.get(key) || []), item.file]);
930
+ }
931
+ for (const [descKey, files] of descriptionCounts.entries()) {
932
+ if (files.length >= 2) {
933
+ addIssue(issues, {
934
+ severity: "warning",
935
+ message: `Duplicate page descriptions detected (${files.length} pages share the same description): "${descKey.slice(0, 80)}${descKey.length > 80 ? "${chars.ellipsis}" : ""}"`,
936
+ file: files.slice(0, 3).join(", ") + (files.length > 3 ? "${chars.ellipsis}" : ""),
937
+ });
938
+ }
939
+ }
940
+ return issues;
941
+ }
942
+ function checkRootLayoutMetadata() {
943
+ const issues = [];
944
+ const layoutPath = path.join(process.cwd(), "app/layout.tsx");
945
+ if (!fs.existsSync(layoutPath)) {
946
+ addIssue(issues, {
947
+ severity: "blocking",
948
+ file: "app/layout.tsx",
949
+ message: "Missing root layout (Next.js requires app/layout.tsx)",
950
+ });
951
+ return issues;
952
+ }
953
+ const content = readText(layoutPath);
954
+ if (!/metadataBase\s*:/.test(content)) {
955
+ addIssue(issues, {
956
+ severity: "blocking",
957
+ file: "app/layout.tsx",
958
+ message: "Root layout metadata missing metadataBase (helps canonical + absolute OG URLs)",
959
+ });
960
+ }
961
+ // Hardcoded absolute metadataBase is a common source of canonical/OG drift.
962
+ if (/metadataBase\s*:\s*new\s+URL\(\s*['"]https?:\/\//.test(content)) {
963
+ addIssue(issues, {
964
+ severity: "blocking",
965
+ file: "app/layout.tsx",
966
+ message: "Root layout metadataBase appears hardcoded; derive it from SITE_URL/env",
967
+ });
968
+ }
969
+ const usesBuildMetadataHelper = /buildMetadata\s*\(/.test(content) || /generateMetadata\s+as\s+buildMetadata/.test(content);
970
+ if (!usesBuildMetadataHelper && !/openGraph\s*:/.test(content)) {
971
+ addIssue(issues, {
972
+ severity: "warning",
973
+ file: "app/layout.tsx",
974
+ message: "Root layout missing default openGraph metadata",
975
+ });
976
+ }
977
+ if (!usesBuildMetadataHelper && !/twitter\s*:/.test(content)) {
978
+ addIssue(issues, {
979
+ severity: "warning",
980
+ file: "app/layout.tsx",
981
+ message: "Root layout missing default twitter metadata",
982
+ });
983
+ }
984
+ // Ensure themeColor is not a CSS variable (known rendering timing issue)
985
+ if (/themeColor\s*:\s*["']var\(--[^)]+\)["']/.test(content)) {
986
+ addIssue(issues, {
987
+ severity: "blocking",
988
+ file: "app/layout.tsx",
989
+ message: "themeColor uses a CSS var; browsers/crawlers may not resolve it early",
990
+ });
991
+ }
992
+ return issues;
993
+ }
994
+ function checkProductOGType() {
995
+ const issues = [];
996
+ const productPage = path.join(process.cwd(), "app/product/[slug]/page.tsx");
997
+ if (!fs.existsSync(productPage))
998
+ return issues;
999
+ const file = "app/product/[slug]/page.tsx";
1000
+ const content = readText(productPage);
1001
+ const analysis = analyzeNextMetadata(content, file);
1002
+ if (!analysis.hasGenerateMetadata && !analysis.hasMetadataExport) {
1003
+ addIssue(issues, {
1004
+ severity: "blocking",
1005
+ file,
1006
+ message: "Product page must export generateMetadata or metadata",
1007
+ });
1008
+ return issues;
1009
+ }
1010
+ // Next.js 16 only supports standard OpenGraph types: website, article, book, profile, music.*, video.*
1011
+ // "product" is NOT a valid OpenGraph type - use "website" and rely on JSON-LD Schema.org for product data
1012
+ const hasWebsiteType = /openGraph\s*:\s*\{[\s\S]*?type\s*:\s*["']website["']/.test(content);
1013
+ const hasInvalidProductType = /openGraph\s*:\s*\{[\s\S]*?type\s*:\s*["']product["']/.test(content);
1014
+ if (hasInvalidProductType) {
1015
+ addIssue(issues, {
1016
+ severity: "blocking",
1017
+ file,
1018
+ message: "Product page openGraph.type is 'product' which is invalid in Next.js 16 - use 'website' instead",
1019
+ });
1020
+ }
1021
+ else if (!hasWebsiteType) {
1022
+ addIssue(issues, {
1023
+ severity: "warning",
1024
+ file,
1025
+ message: "Product page openGraph.type should be 'website' (product data via JSON-LD Schema.org)",
1026
+ });
1027
+ }
1028
+ // Ensure twitter card config exists and matches product sharing expectations.
1029
+ if (!/twitter\s*:\s*\{[\s\S]*?card\s*:\s*["']summary_large_image["']/.test(content)) {
1030
+ addIssue(issues, {
1031
+ severity: "blocking",
1032
+ file,
1033
+ message: "Product page twitter.card must be 'summary_large_image'",
1034
+ });
1035
+ }
1036
+ // Images: prefer object form with url+alt, and urls should be absolute.
1037
+ const hasOgImages = /openGraph\s*:\s*\{[\s\S]*?images\s*:\s*/.test(content);
1038
+ if (!hasOgImages) {
1039
+ addIssue(issues, {
1040
+ severity: "blocking",
1041
+ file,
1042
+ message: "Product page openGraph.images missing",
1043
+ });
1044
+ }
1045
+ const usesStringImages = /openGraph\s*:\s*\{[\s\S]*?images\s*:\s*\[[^\]]*['"][^\]]*['"]/s.test(content);
1046
+ if (usesStringImages) {
1047
+ addIssue(issues, {
1048
+ severity: "blocking",
1049
+ file,
1050
+ message: "Product page openGraph.images should use object entries with url+alt (not plain strings)",
1051
+ });
1052
+ }
1053
+ const hasAlt = /openGraph\s*:\s*\{[\s\S]*?images\s*:\s*[\s\S]*?alt\s*:\s*/.test(content);
1054
+ if (!hasAlt) {
1055
+ addIssue(issues, {
1056
+ severity: "blocking",
1057
+ file,
1058
+ message: "Product page openGraph.images entries should include alt text",
1059
+ });
1060
+ }
1061
+ // width/height is ideal for scrapers/crawlers, but not always feasible with dynamic product images.
1062
+ const hasWidth = /openGraph\s*:\s*\{[\s\S]*?images\s*:\s*[\s\S]*?width\s*:\s*/.test(content);
1063
+ const hasHeight = /openGraph\s*:\s*\{[\s\S]*?images\s*:\s*[\s\S]*?height\s*:\s*/.test(content);
1064
+ if (hasOgImages && !usesStringImages && (!hasWidth || !hasHeight)) {
1065
+ addIssue(issues, {
1066
+ severity: "info",
1067
+ file,
1068
+ message: "Product page openGraph.images objects should ideally include width/height",
1069
+ });
1070
+ }
1071
+ const derivesAbsoluteUrl = /new\s+URL\(\s*[^,]+,\s*SITE_URL\s*\)/.test(content);
1072
+ if (!derivesAbsoluteUrl && !/https?:\/\//.test(content)) {
1073
+ addIssue(issues, {
1074
+ severity: "warning",
1075
+ file,
1076
+ message: "Could not confirm OG image URLs are absolute (prefer new URL(image, SITE_URL))",
1077
+ });
1078
+ }
1079
+ return issues;
1080
+ }
1081
+ function checkRobotsAndSitemapSafety() {
1082
+ const issues = [];
1083
+ const robotsPath = path.join(process.cwd(), "app/robots.ts");
1084
+ if (!fs.existsSync(robotsPath)) {
1085
+ addIssue(issues, {
1086
+ severity: "warning",
1087
+ file: "app/robots.ts",
1088
+ message: "Missing app/robots.ts",
1089
+ });
1090
+ }
1091
+ else {
1092
+ const content = readText(robotsPath);
1093
+ // Environment-aware behavior: non-prod should default to disallow all crawling.
1094
+ // We expect an explicit staging/dev guard (ex: IS_STAGING) that returns disallow: '/'.
1095
+ const hasEnvGuard = /IS_STAGING|VERCEL_ENV|NODE_ENV/.test(content);
1096
+ if (!hasEnvGuard) {
1097
+ addIssue(issues, {
1098
+ severity: "warning",
1099
+ file: "app/robots.ts",
1100
+ message: "robots.ts should be environment-aware (non-prod should default to disallow crawling)",
1101
+ });
1102
+ }
1103
+ const hasStagingDisallowAll = /if\s*\(\s*IS_STAGING\s*\)[\s\S]*?disallow\s*:\s*['"]\/["']/.test(content);
1104
+ if (hasEnvGuard && !hasStagingDisallowAll) {
1105
+ addIssue(issues, {
1106
+ severity: "warning",
1107
+ file: "app/robots.ts",
1108
+ message: "robots.ts should disallow '/' in staging/dev guard to prevent indexing",
1109
+ });
1110
+ }
1111
+ if (content.includes("'/_next/'") || content.includes('"/_next/"')) {
1112
+ addIssue(issues, {
1113
+ severity: "blocking",
1114
+ file: "app/robots.ts",
1115
+ message: "robots.ts disallows /_next/ (Googlebot cannot render CSS/JS)",
1116
+ });
1117
+ }
1118
+ if (content.includes("'/static/'") || content.includes('"/static/"')) {
1119
+ addIssue(issues, {
1120
+ severity: "blocking",
1121
+ file: "app/robots.ts",
1122
+ message: "robots.ts disallows /static/ (Googlebot cannot fetch static assets)",
1123
+ });
1124
+ }
1125
+ if (/disallow.*['"]\/stores\//i.test(content)) {
1126
+ addIssue(issues, {
1127
+ severity: "blocking",
1128
+ file: "app/robots.ts",
1129
+ message: "robots.ts blocks /stores/ (public seller profiles)",
1130
+ });
1131
+ }
1132
+ }
1133
+ const sitemapPath = path.join(process.cwd(), "app/sitemap.ts");
1134
+ if (!fs.existsSync(sitemapPath)) {
1135
+ addIssue(issues, {
1136
+ severity: "warning",
1137
+ file: "app/sitemap.ts",
1138
+ message: "Missing app/sitemap.ts",
1139
+ });
1140
+ }
1141
+ else {
1142
+ const content = readText(sitemapPath);
1143
+ // Fake freshness / poor caching signal
1144
+ if (/lastModified\s*:\s*new\s+Date\(\)/.test(content)) {
1145
+ addIssue(issues, {
1146
+ severity: "warning",
1147
+ file: "app/sitemap.ts",
1148
+ message: "Sitemap uses lastModified: new Date() (can create fake freshness + churn)",
1149
+ });
1150
+ }
1151
+ // Quick sanity check that product sitemap pagination exists if expected.
1152
+ const hasSitemapProductsRoute = fs.existsSync(path.join(process.cwd(), "app/sitemap-products-[page]/route.ts"));
1153
+ if (!hasSitemapProductsRoute) {
1154
+ addIssue(issues, {
1155
+ severity: "info",
1156
+ file: "app/sitemap-products-[page]/route.ts",
1157
+ message: "No sitemap-products-[page] route found (consider sitemap index/pagination for large catalogs)",
1158
+ });
1159
+ }
1160
+ }
1161
+ return issues;
1162
+ }
1163
+ function checkStructuredDataGenerators() {
1164
+ const issues = [];
1165
+ const schemaFile = "lib/product-schema.ts";
1166
+ const schemaPath = path.join(process.cwd(), schemaFile);
1167
+ if (!fs.existsSync(schemaPath)) {
1168
+ addIssue(issues, {
1169
+ severity: "warning",
1170
+ file: schemaFile,
1171
+ message: "Missing lib/product-schema.ts (cannot validate Product/Breadcrumb schema shapes)",
1172
+ });
1173
+ return issues;
1174
+ }
1175
+ const content = readText(schemaPath);
1176
+ const mustContain = (needle, message) => {
1177
+ if (!content.includes(needle)) {
1178
+ addIssue(issues, {
1179
+ severity: "blocking",
1180
+ file: schemaFile,
1181
+ message,
1182
+ });
1183
+ }
1184
+ };
1185
+ // Product schema must contain key fields for Merchant / rich results.
1186
+ mustContain('"@type": "Product"', "generateProductSchema should emit @type=Product");
1187
+ mustContain('"@context": "https://schema.org"', "generateProductSchema should emit @context=https://schema.org");
1188
+ mustContain("offers:", "generateProductSchema should emit offers");
1189
+ mustContain('"@type": "Offer"', "generateProductSchema should emit individual Offer entries");
1190
+ mustContain("priceCurrency", "Offer/AggregateOffer should include priceCurrency");
1191
+ mustContain("availability", "Offer should include availability");
1192
+ mustContain("url:", "Offer should include url");
1193
+ // BreadcrumbList schema must use ListItem wrappers.
1194
+ mustContain('"@type": "BreadcrumbList"', "generateBreadcrumbSchema should emit @type=BreadcrumbList");
1195
+ mustContain("itemListElement", "BreadcrumbList should include itemListElement");
1196
+ mustContain('"@type": "ListItem"', "Breadcrumb itemListElement entries should be ListItem");
1197
+ mustContain("position", "Breadcrumb ListItem should include position");
1198
+ mustContain("name", "Breadcrumb ListItem should include name");
1199
+ mustContain("item", "Breadcrumb ListItem should include item URL");
1200
+ return issues;
1201
+ }
1202
+ async function checkCrawlableInternalLinking() {
1203
+ const issues = [];
1204
+ // Product pages should expose crawlable internal links to related items.
1205
+ const productPagePath = path.join(process.cwd(), "app/product/[slug]/page.tsx");
1206
+ if (fs.existsSync(productPagePath)) {
1207
+ const content = readText(productPagePath);
1208
+ const usesRelatedProductsComponent = /<RelatedProducts\b/.test(content);
1209
+ const mentionsRelated = usesRelatedProductsComponent ||
1210
+ /Related\s+Products|You\s+may\s+also\s+like|Similar\s+items/i.test(content);
1211
+ // Note: The product page uses a server component (`components/product/RelatedProducts.tsx`)
1212
+ // that renders crawlable <Link href="/product/..."> anchors. This check is best-effort
1213
+ // and should not false-positive when the component is present.
1214
+ const hasProductLinks = usesRelatedProductsComponent ||
1215
+ /<Link[^>]+href=\{?['"]\/product\//.test(content) ||
1216
+ /href=\{?`\$\{.*\}\/product\//.test(content);
1217
+ if (!mentionsRelated) {
1218
+ addIssue(issues, {
1219
+ severity: "info",
1220
+ file: "app/product/[slug]/page.tsx",
1221
+ message: "Product page does not appear to render a related-products section (helps internal linking + discovery)",
1222
+ });
1223
+ }
1224
+ if (mentionsRelated && !hasProductLinks) {
1225
+ addIssue(issues, {
1226
+ severity: "warning",
1227
+ file: "app/product/[slug]/page.tsx",
1228
+ message: "Related-products section detected but no obvious crawlable /product/ links found",
1229
+ });
1230
+ }
1231
+ }
1232
+ // Category pages should avoid JS-only navigation for key lists (best-effort scan).
1233
+ const categoryPages = await (0, glob_1.glob)("app/{sports-cards,trading-card-games,video-games,autographs,tickets,non-sports-cards}/**/page.tsx", {
1234
+ ignore: EXCLUDED_GLOBS,
1235
+ });
1236
+ for (const file of categoryPages) {
1237
+ const content = readText(path.join(process.cwd(), file));
1238
+ const hasRouterPush = /router\.push\(/.test(content);
1239
+ const hasLink = /<Link\b/.test(content);
1240
+ if (hasRouterPush && !hasLink) {
1241
+ addIssue(issues, {
1242
+ severity: "info",
1243
+ file,
1244
+ message: "Category page uses router.push without obvious <Link> usage (ensure crawlable anchors for SEO)",
1245
+ });
1246
+ }
1247
+ }
1248
+ return issues;
1249
+ }
1250
+ function normalizeResult(issues, strict) {
1251
+ const errors = [];
1252
+ const warnings = [];
1253
+ const info = [];
1254
+ for (const issue of issues) {
1255
+ const msg = formatIssue(issue);
1256
+ if (issue.severity === "blocking") {
1257
+ if (strict)
1258
+ errors.push(msg);
1259
+ else
1260
+ warnings.push(`[BLOCKING] ${msg}`);
1261
+ }
1262
+ else if (issue.severity === "warning") {
1263
+ warnings.push(msg);
1264
+ }
1265
+ else {
1266
+ info.push(msg);
1267
+ }
1268
+ }
1269
+ return {
1270
+ passed: errors.length === 0,
1271
+ errors,
1272
+ warnings,
1273
+ info: info.length > 0 ? info : undefined,
1274
+ };
1275
+ }
1276
+ async function run(options = {}) {
1277
+ const strict = options.strict ?? false;
1278
+ const verbose = options.verbose ?? false;
1279
+ const ci = options.ci ?? false;
1280
+ const issues = [];
1281
+ const rootLayoutPath = path.join(process.cwd(), "app/layout.tsx");
1282
+ const hasRootMetadataBase = fs.existsSync(rootLayoutPath)
1283
+ ? /metadataBase\s*:/.test(readText(rootLayoutPath))
1284
+ : false;
1285
+ // 1) Root layout SEO defaults
1286
+ issues.push(...checkRootLayoutMetadata());
1287
+ // 1b) Structured data shape validation (static, generator-level)
1288
+ issues.push(...checkStructuredDataGenerators());
1289
+ // 1c) Structured data runtime serializability (sample outputs must JSON.stringify + JSON.parse)
1290
+ issues.push(...(await checkSchemaGeneratorSerializability()));
1291
+ // 2) Metadata presence & basic quality
1292
+ {
1293
+ const metadataIssues = await checkMetadataPresenceAndQuality({ strict });
1294
+ issues.push(...metadataIssues);
1295
+ // Additional metadata URL correctness checks are derived from the same AST analysis.
1296
+ // (We keep them separate to avoid bloating the main metadata quality loop.)
1297
+ const pageFiles = await getPageTsFiles();
1298
+ for (const file of pageFiles) {
1299
+ const content = readText(path.join(process.cwd(), file));
1300
+ const analysis = analyzeNextMetadata(content, file);
1301
+ issues.push(...checkMetadataUrlCorrectness({
1302
+ file,
1303
+ analysis,
1304
+ strict,
1305
+ ci,
1306
+ hasRootMetadataBase,
1307
+ }));
1308
+ }
1309
+ }
1310
+ // 3) OG correctness on product page
1311
+ issues.push(...checkProductOGType());
1312
+ // 4) Robots + sitemap safety rails
1313
+ issues.push(...checkRobotsAndSitemapSafety());
1314
+ // 5) Crawlable internal linking depth heuristics
1315
+ issues.push(...(await checkCrawlableInternalLinking()));
1316
+ // 5b) Caching guardrails for public pages (force-dynamic without caching)
1317
+ issues.push(...(await checkForceDynamicCaching({ strict, ci })));
1318
+ // 5c) Pagination metadata heuristics for public pages
1319
+ issues.push(...(await checkPaginationMetadataHeuristics({ strict, ci })));
1320
+ // 5d) Semantic heading enforcement for top-level headings
1321
+ issues.push(...(await checkTypographyHeadingSemantics({ strict, ci })));
1322
+ // 5e) Image + alt-text guardrails on public surfaces
1323
+ issues.push(...(await checkNativeImgAndAltText({ strict, ci })));
1324
+ // 6) Run legacy, battle-tested SEO checks as child processes
1325
+ // NOTE: In non-strict mode, failures are downgraded to warnings so the main
1326
+ // preflight system can treat SEO as "warnOn".
1327
+ const childChecks = [
1328
+ {
1329
+ label: "SEO Best Practices",
1330
+ command: process.execPath,
1331
+ args: ["scripts/active/preflights/seo/seo-best-practices.js"],
1332
+ alwaysWarn: true,
1333
+ },
1334
+ {
1335
+ label: "Heading Hierarchy",
1336
+ command: process.execPath,
1337
+ args: ["scripts/active/preflights/seo/heading-hierarchy-validation.js"],
1338
+ alwaysWarn: true,
1339
+ },
1340
+ {
1341
+ label: "Schema Usage",
1342
+ command: process.execPath,
1343
+ args: ["scripts/active/preflights/seo/schema-usage-validation.js"],
1344
+ alwaysWarn: true,
1345
+ },
1346
+ {
1347
+ label: "Hardcoded URLs",
1348
+ command: process.execPath,
1349
+ args: ["scripts/active/preflights/seo/hardcoded-urls.js"],
1350
+ alwaysWarn: false,
1351
+ },
1352
+ {
1353
+ label: "SEO Gaps",
1354
+ command: process.execPath,
1355
+ args: ["scripts/active/preflights/seo/seo-gaps-validation.js"],
1356
+ alwaysWarn: true,
1357
+ },
1358
+ {
1359
+ label: "Category FAQ Schema",
1360
+ command: process.execPath,
1361
+ args: ["scripts/active/preflights/seo/category-faq-schema-validation.js"],
1362
+ alwaysWarn: true,
1363
+ },
1364
+ {
1365
+ label: "Store Local SEO",
1366
+ command: process.execPath,
1367
+ args: ["scripts/active/preflights/seo/store-local-seo-validation.js"],
1368
+ alwaysWarn: true,
1369
+ },
1370
+ {
1371
+ label: "JSON-LD Validation",
1372
+ command: process.execPath,
1373
+ args: ["scripts/active/preflights/seo/json-ld-validation.js"],
1374
+ alwaysWarn: true,
1375
+ },
1376
+ {
1377
+ label: "Social Meta Tags",
1378
+ command: process.execPath,
1379
+ args: ["scripts/active/preflights/seo/social-meta-validation.js"],
1380
+ alwaysWarn: true,
1381
+ },
1382
+ ];
1383
+ const childPromises = childChecks.map((check) => runScriptAsChildProcess({
1384
+ command: check.command,
1385
+ args: check.args,
1386
+ label: check.label,
1387
+ strict,
1388
+ verbose,
1389
+ alwaysWarn: check.alwaysWarn,
1390
+ }));
1391
+ const childResults = await Promise.all(childPromises);
1392
+ for (const childIssues of childResults) {
1393
+ issues.push(...childIssues);
1394
+ }
1395
+ return normalizeResult(issues, strict);
1396
+ }
1397
+ function isDirectCliInvocation() {
1398
+ return require.main === module;
1399
+ }
1400
+ async function runAsCli() {
1401
+ const strict = process.argv.includes("--strict");
1402
+ const verbose = process.argv.includes("--verbose");
1403
+ const ci = process.argv.includes("--ci") || process.argv.includes("--enforce-best-practices");
1404
+ console.log(`\n${console_chars_1.emoji.search} Running SEO Preflight (authoritative)...\n`);
1405
+ const result = await run({ strict, verbose, ci });
1406
+ if (result.errors.length > 0) {
1407
+ console.log(`${console_chars_1.emoji.error} Errors:\n`);
1408
+ result.errors.forEach((e) => console.log(` - ${e}`));
1409
+ console.log("");
1410
+ }
1411
+ if (result.warnings.length > 0) {
1412
+ console.log(`${console_chars_1.emoji.warning} Warnings:\n`);
1413
+ const maxLines = verbose ? result.warnings.length : 30;
1414
+ result.warnings.slice(0, maxLines).forEach((w) => console.log(` - ${w}`));
1415
+ if (!verbose && result.warnings.length > maxLines) {
1416
+ console.log(` - ${console_chars_1.chars.ellipsis}and ${result.warnings.length - maxLines} more (re-run with --verbose)`);
1417
+ }
1418
+ console.log("");
1419
+ }
1420
+ if (result.info && result.info.length > 0 && verbose) {
1421
+ console.log(`${console_chars_1.emoji.info} Info:\n`);
1422
+ result.info.forEach((i) => console.log(` - ${i}`));
1423
+ console.log("");
1424
+ }
1425
+ if (result.passed) {
1426
+ console.log(`${console_chars_1.emoji.success} SEO preflight passed\n`);
1427
+ process.exit(0);
1428
+ }
1429
+ console.log(`${console_chars_1.emoji.error} SEO preflight failed\n`);
1430
+ process.exit(1);
1431
+ }
1432
+ if (isDirectCliInvocation()) {
1433
+ runAsCli().catch((error) => {
1434
+ console.error(`${console_chars_1.emoji.error} SEO preflight crashed:`, error);
1435
+ process.exit(1);
1436
+ });
1437
+ }
1438
+ //# sourceMappingURL=seo.js.map