catalyst-core 0.3.0-beta.5 → 0.3.0-canary.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. package/changelog.md +185 -71
  2. package/dist/errors/generateDocs.js +100 -0
  3. package/dist/errors/index.js +243 -0
  4. package/dist/errors/registry.js +483 -0
  5. package/dist/errors-index.json +506 -0
  6. package/dist/globals.d.ts +62 -0
  7. package/dist/index.d.ts +5 -0
  8. package/dist/index.jsx +5 -8
  9. package/dist/logger.js +1 -1
  10. package/dist/native/androidProject/app/build.gradle.kts +142 -7
  11. package/dist/native/androidProject/app/src/main/AndroidManifest.xml +4 -0
  12. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeBridge.kt +2 -2
  13. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/BarcodeDetector.kt +3 -0
  14. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/CameraSessionManager.kt +3 -0
  15. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/FrameworkServerUtils.kt +43 -8
  16. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/BridgeUtilsTest.kt +181 -1
  17. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/CameraUtilsTest.kt +156 -236
  18. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/FileSizeRouterUtilsTest.kt +471 -0
  19. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/FileUtilsTest.kt +222 -226
  20. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/FrameworkServerUtilsTest.kt +300 -0
  21. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/IntentUtilsTest.kt +244 -0
  22. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/MetricsMonitorTest.kt +359 -0
  23. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/NativeBridgeTest.kt +108 -63
  24. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/NotificationUtilsTest.kt +329 -385
  25. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/OfflineCacheServiceTest.kt +302 -0
  26. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/PerfEventBufferTest.kt +133 -0
  27. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/UtilsKtTest.kt +152 -0
  28. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/WebCacheManagerTest.kt +145 -324
  29. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/BarcodeDetectorTest.kt +132 -0
  30. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/HoldControllerTest.kt +155 -0
  31. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/TorchControllerTest.kt +150 -0
  32. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/VideoStreamStateMachineTest.kt +120 -0
  33. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/VideoStreamStateTest.kt +62 -0
  34. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/ViewfinderMapperTest.kt +143 -0
  35. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/camera/ZoomControllerTest.kt +421 -0
  36. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/design/DesignTokensTest.kt +207 -0
  37. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/plugins/PluginBridgeTest.kt +368 -0
  38. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/security/FridaDetectorTest.kt +193 -0
  39. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/security/SecurityCheckManagerTest.kt +260 -0
  40. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/security/SecurityCheckSchedulerTest.kt +166 -0
  41. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/DeviceInfoUtilsTest.kt +167 -0
  42. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/DownloadUtilsTest.kt +197 -0
  43. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/NetworkMonitorTest.kt +271 -0
  44. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/PushNotificationUtilsTest.kt +119 -0
  45. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/utils/SafeAreaUtilsTest.kt +108 -0
  46. package/dist/native/androidProject/build.gradle.kts +1 -0
  47. package/dist/native/androidProject/gradle/libs.versions.toml +26 -0
  48. package/dist/native/androidProject/settings.gradle.kts +11 -8
  49. package/dist/native/androidSetup.js +2 -2
  50. package/dist/native/bridge/WebBridge.d.ts +98 -0
  51. package/dist/native/bridge/WebBridge.js +40 -6
  52. package/dist/native/bridge/constants/NativeInterfaces.d.ts +391 -0
  53. package/dist/native/bridge/errors.d.ts +67 -0
  54. package/dist/native/bridge/errors.js +66 -151
  55. package/dist/native/bridge/hooks/index.d.ts +13 -0
  56. package/dist/native/bridge/hooks/index.js +0 -6
  57. package/dist/native/bridge/hooks/useAI.d.ts +1 -0
  58. package/dist/native/bridge/hooks/useAI.js +3 -1
  59. package/dist/native/bridge/hooks/useCamera.d.ts +86 -0
  60. package/dist/native/bridge/hooks/useCamera.js +35 -6
  61. package/dist/native/bridge/hooks/useDataProtection.d.ts +17 -0
  62. package/dist/native/bridge/hooks/useDeviceInfo.d.ts +34 -0
  63. package/dist/native/bridge/hooks/useDeviceInfo.js +5 -0
  64. package/dist/native/bridge/hooks/useFilePicker.d.ts +53 -0
  65. package/dist/native/bridge/hooks/useFilePicker.js +13 -0
  66. package/dist/native/bridge/hooks/useGoogleSignIn.d.ts +12 -0
  67. package/dist/native/bridge/hooks/useHapticFeedback.d.ts +76 -0
  68. package/dist/native/bridge/hooks/useHapticFeedback.js +6 -1
  69. package/dist/native/bridge/hooks/useIntent.d.ts +33 -0
  70. package/dist/native/bridge/hooks/useIntent.js +2 -0
  71. package/dist/native/bridge/hooks/useNativeTransition.d.ts +53 -0
  72. package/dist/native/bridge/hooks/useNativeTransition.js +12 -5
  73. package/dist/native/bridge/hooks/useNetworkStatus.d.ts +22 -0
  74. package/dist/native/bridge/hooks/useNetworkStatus.js +7 -0
  75. package/dist/native/bridge/hooks/useNotification.d.ts +83 -0
  76. package/dist/native/bridge/hooks/useNotification.js +81 -34
  77. package/dist/native/bridge/hooks/useSafeArea.d.ts +12 -0
  78. package/dist/native/bridge/hooks/useSafeArea.js +8 -0
  79. package/dist/native/bridge/hooks/useVideoStream.d.ts +67 -0
  80. package/dist/native/bridge/hooks/useVideoStream.js +38 -52
  81. package/dist/native/bridge/hooks/utils.d.ts +4 -0
  82. package/dist/native/bridge/hooks.d.ts +1 -0
  83. package/dist/native/bridge/perf/collectors/ApiCollector.d.ts +30 -0
  84. package/dist/native/bridge/perf/collectors/ApiCollector.js +4 -0
  85. package/dist/native/bridge/perf/collectors/CacheCollector.d.ts +43 -0
  86. package/dist/native/bridge/perf/collectors/CacheCollector.js +4 -0
  87. package/dist/native/bridge/perf/collectors/HookCollector.d.ts +37 -0
  88. package/dist/native/bridge/perf/collectors/HookCollector.js +4 -0
  89. package/dist/native/bridge/perf/collectors/InsightsCollector.d.ts +103 -0
  90. package/dist/native/bridge/perf/collectors/InsightsCollector.js +4 -0
  91. package/dist/native/bridge/perf/collectors/InteractionCollector.d.ts +53 -0
  92. package/dist/native/bridge/perf/collectors/InteractionCollector.js +4 -0
  93. package/dist/native/bridge/perf/collectors/KeyboardCollector.d.ts +30 -0
  94. package/dist/native/bridge/perf/collectors/KeyboardCollector.js +4 -0
  95. package/dist/native/bridge/perf/collectors/NavigationCollector.d.ts +37 -0
  96. package/dist/native/bridge/perf/collectors/NavigationCollector.js +4 -0
  97. package/dist/native/bridge/perf/collectors/NetworkTimingCollector.d.ts +30 -0
  98. package/dist/native/bridge/perf/collectors/NetworkTimingCollector.js +4 -0
  99. package/dist/native/bridge/perf/collectors/RenderCollector.d.ts +47 -0
  100. package/dist/native/bridge/perf/collectors/RenderCollector.js +8 -0
  101. package/dist/native/bridge/perf/collectors/ScrollCollector.d.ts +29 -0
  102. package/dist/native/bridge/perf/collectors/ScrollCollector.js +4 -0
  103. package/dist/native/bridge/perf/collectors/ThreadCollector.d.ts +31 -0
  104. package/dist/native/bridge/perf/collectors/ThreadCollector.js +4 -0
  105. package/dist/native/bridge/perf/core/constants.d.ts +76 -0
  106. package/dist/native/bridge/perf/core/measure.d.ts +39 -0
  107. package/dist/native/bridge/perf/core/measure.js +4 -0
  108. package/dist/native/bridge/perf/core/session.d.ts +49 -0
  109. package/dist/native/bridge/perf/core/session.js +4 -0
  110. package/dist/native/bridge/perf/core/store.d.ts +37 -0
  111. package/dist/native/bridge/perf/core/store.js +4 -0
  112. package/dist/native/bridge/perf/core/summary.d.ts +60 -0
  113. package/dist/native/bridge/perf/core/traceExport.d.ts +10 -0
  114. package/dist/native/bridge/perf/core/waterfalls.d.ts +2 -0
  115. package/dist/native/bridge/perf/index.d.ts +63 -0
  116. package/dist/native/bridge/perf/index.js +4 -0
  117. package/dist/native/bridge/safeArea.d.ts +11 -0
  118. package/dist/native/bridge/safeArea.js +2 -0
  119. package/dist/native/bridge/useBaseHook.d.ts +137 -0
  120. package/dist/native/bridge/useBaseHook.js +34 -4
  121. package/dist/native/bridge/utils/CameraUtils.d.ts +94 -0
  122. package/dist/native/bridge/utils/CameraUtils.js +4 -0
  123. package/dist/native/bridge/utils/FileObjectConverter.d.ts +36 -0
  124. package/dist/native/bridge/utils/NativeBridge.d.ts +270 -0
  125. package/dist/native/bridge/utils/NativeBridge.js +10 -0
  126. package/dist/native/buildAndroid/index.js +1 -1
  127. package/dist/native/buildAppAndroid.js +9 -0
  128. package/dist/native/buildAppIos.js +16 -1
  129. package/dist/native/buildErrorFormat.js +57 -0
  130. package/dist/native/buildIos/config.js +15 -1
  131. package/dist/native/buildIos/index.js +1 -1
  132. package/dist/native/buildIos/plugins.js +10 -1
  133. package/dist/native/iosnativeWebView/CoreLogic/Package.swift +36 -0
  134. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Camera/VideoStreamState.swift +1 -1
  135. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Camera/VideoStreamStateMachine.swift +6 -4
  136. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/BootTimingUtility.swift +3 -3
  137. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/FrameworkServerUtils.swift +14 -9
  138. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/NetworkMonitor.swift +11 -9
  139. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/NotificationHandlerProvider.swift +1 -1
  140. package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/URLWhitelistManager.swift +7 -7
  141. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/AnyCodableTests.swift +154 -0
  142. package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/BootTimingUtilityTests.swift +23 -5
  143. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/CatalystConstantsTests.swift +192 -0
  144. package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/ConfigMappingTests.swift +1 -1
  145. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/FrameworkServerUtilsErrorPathTests.swift +106 -0
  146. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/FrameworkServerUtilsLoopbackTests.swift +243 -0
  147. package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/FrameworkServerUtilsTests.swift +1 -1
  148. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/NetworkMonitorTests.swift +119 -0
  149. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/NotificationHandlerProviderTests.swift +59 -0
  150. package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/NotificationHandlerTests.swift +1 -1
  151. package/dist/native/iosnativeWebView/{iosnativeWebViewTests → CoreLogic/Tests/CatalystCoreLogicTests}/URLWhitelistManagerTests.swift +1 -1
  152. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/VideoStreamStateMachineTests.swift +171 -0
  153. package/dist/native/iosnativeWebView/CoreLogic/Tests/CatalystCoreLogicTests/VideoStreamStateTests.swift +91 -0
  154. package/dist/native/iosnativeWebView/Package.swift +10 -9
  155. package/dist/native/iosnativeWebView/Sources/CatalystNotifications/LocalNotificationHandler.swift +7 -2
  156. package/dist/native/iosnativeWebView/Sources/CatalystNotifications/NotificationManager.swift +1 -2
  157. package/dist/native/iosnativeWebView/Sources/CatalystNotifications/PushNotificationHandler.swift +5 -4
  158. package/dist/native/iosnativeWebView/Sources/Core/Camera/CameraSessionManager.swift +1 -0
  159. package/dist/native/iosnativeWebView/Sources/Core/Camera/HoldController.swift +1 -0
  160. package/dist/native/iosnativeWebView/Sources/Core/Camera/NativeCameraManager.swift +6 -5
  161. package/dist/native/iosnativeWebView/Sources/Core/Camera/ZoomController.swift +1 -0
  162. package/dist/native/iosnativeWebView/Sources/Core/Plugins/PluginBridge.swift +1 -0
  163. package/dist/native/iosnativeWebView/Sources/Core/Utils/CacheManager.swift +31 -30
  164. package/dist/native/iosnativeWebView/Sources/Core/Utils/CameraTransportUtils.swift +2 -1
  165. package/dist/native/iosnativeWebView/Sources/Core/Utils/DeviceInfoUtils.swift +1 -1
  166. package/dist/native/iosnativeWebView/Sources/Core/Utils/FilePickerHandler.swift +22 -19
  167. package/dist/native/iosnativeWebView/Sources/Core/Utils/ImageHandler.swift +40 -39
  168. package/dist/native/iosnativeWebView/Sources/Core/Utils/PerfEventBuffer.swift +1 -0
  169. package/dist/native/iosnativeWebView/Sources/Core/Utils/ResourceURLProtocol.swift +15 -15
  170. package/dist/native/iosnativeWebView/Sources/Core/Utils/WebKitConfig.swift +4 -3
  171. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeCommandHandler.swift +6 -1
  172. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeDelegateHandler.swift +1 -0
  173. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeFileHandler.swift +2 -1
  174. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeJavaScriptInterface.swift +2 -1
  175. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeMessageValidator.swift +3 -5
  176. package/dist/native/iosnativeWebView/Sources/Core/WebView/NativeBridge.swift +20 -13
  177. package/dist/native/iosnativeWebView/Sources/Core/WebView/SplashView.swift +6 -5
  178. package/dist/native/iosnativeWebView/Sources/Core/WebView/SplashViewModel.swift +14 -13
  179. package/dist/native/iosnativeWebView/Sources/Core/WebView/TransitionManager.swift +3 -3
  180. package/dist/native/iosnativeWebView/Sources/Core/WebView/WebView.swift +9 -8
  181. package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewModel.swift +7 -6
  182. package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewNavigationDelegate.swift +24 -25
  183. package/dist/native/iosnativeWebView/iosnativeWebView/AppDelegate.swift +6 -1
  184. package/dist/native/iosnativeWebView/iosnativeWebView/ContentView.swift +1 -0
  185. package/dist/native/iosnativeWebView/iosnativeWebView/iosnativeWebViewApp.swift +4 -0
  186. package/dist/native/iosnativeWebView/iosnativeWebView.xcodeproj/project.pbxproj +2 -22
  187. package/dist/native/iosnativeWebView/iosnativeWebViewTests/BridgeMessageValidatorTests.swift +1 -0
  188. package/dist/native/iosnativeWebView/iosnativeWebViewTests/CacheManagerTests.swift +1 -0
  189. package/dist/native/iosnativeWebView/iosnativeWebViewTests/FilePickerHandlerTests.swift +2 -1
  190. package/dist/native/iosnativeWebView/iosnativeWebViewTests/NativeBridgeTests.swift +15 -9
  191. package/dist/native/iosnativeWebView/iosnativeWebViewTests/WebViewTests.swift +1 -0
  192. package/dist/native/setupEmulatorIos.js +2 -2
  193. package/dist/native/terminalProgress.js +17 -17
  194. package/dist/router/ClientRouter.d.ts +8 -0
  195. package/dist/router/ClientRouter.js +13 -11
  196. package/dist/router/ServerRouter.d.ts +13 -0
  197. package/dist/router/ServerRouter.js +19 -7
  198. package/dist/scripts/build.js +14 -2
  199. package/dist/scripts/loadEnvironmentVariables.js +3 -2
  200. package/dist/scripts/plugins.js +1 -1
  201. package/dist/scripts/preServerInit.js +49 -3
  202. package/dist/scripts/preflight.js +111 -0
  203. package/dist/scripts/scriptUtils.js +46 -1
  204. package/dist/scripts/serve.js +7 -3
  205. package/dist/scripts/start.js +8 -3
  206. package/dist/server/expressServer.d.ts +1 -0
  207. package/dist/server/expressServer.js +247 -271
  208. package/dist/server/manifestCache.d.ts +2 -0
  209. package/dist/server/manifestCache.js +25 -33
  210. package/dist/server/renderer/ChunkExtractor.d.ts +44 -0
  211. package/dist/server/renderer/ChunkExtractor.js +113 -125
  212. package/dist/server/renderer/document/Body.d.ts +21 -0
  213. package/dist/server/renderer/document/Body.jsx +45 -45
  214. package/dist/server/renderer/document/FastRefresh.d.ts +3 -0
  215. package/dist/server/renderer/document/FastRefresh.jsx +7 -13
  216. package/dist/server/renderer/document/Head.d.ts +20 -0
  217. package/dist/server/renderer/document/Head.jsx +32 -32
  218. package/dist/server/renderer/document/index.d.ts +2 -0
  219. package/dist/server/renderer/document/index.jsx +2 -2
  220. package/dist/server/renderer/extract.d.ts +67 -0
  221. package/dist/server/renderer/extract.js +92 -89
  222. package/dist/server/renderer/handler.d.ts +2 -0
  223. package/dist/server/renderer/handler.jsx +401 -404
  224. package/dist/server/renderer/index.d.ts +2 -0
  225. package/dist/server/renderer/index.js +5 -8
  226. package/dist/server/renderer/render.d.ts +35 -0
  227. package/dist/server/renderer/render.js +25 -32
  228. package/dist/server/utils/botDetectionMiddleware.d.ts +1 -0
  229. package/dist/server/utils/botDetectionMiddleware.js +33 -23
  230. package/dist/server/utils/cjsRequire.d.ts +8 -0
  231. package/dist/server/utils/cjsRequire.js +2 -2
  232. package/dist/server/utils/userAgentUtil.d.ts +7 -0
  233. package/dist/server/utils/userAgentUtil.js +68 -71
  234. package/dist/server/utils/validator.d.ts +31 -0
  235. package/dist/server/utils/validator.js +133 -158
  236. package/dist/vite/inject-cache-key-plugin.js +3 -27
  237. package/dist/vite/moduleAliases.js +36 -0
  238. package/dist/vite/node-loader.mjs +2 -29
  239. package/dist/vite/resolveDevServerConfig.js +4 -1
  240. package/dist/vite/vite.config.js +2 -29
  241. package/dist/web-router/components/MetaTag.d.ts +4 -0
  242. package/dist/web-router/components/MetaTag.jsx +26 -28
  243. package/dist/web-router/components/MetaTag.test.jsx +100 -0
  244. package/dist/web-router/components/RouterDataProvider.d.ts +96 -0
  245. package/dist/web-router/components/RouterDataProvider.jsx +260 -259
  246. package/dist/web-router/components/RouterDataProvider.server.test.jsx +98 -0
  247. package/dist/web-router/components/RouterDataProvider.test.jsx +310 -0
  248. package/dist/web-router/components/Split.d.ts +74 -0
  249. package/dist/web-router/components/Split.jsx +147 -156
  250. package/dist/web-router/components/Split.server.test.jsx +52 -0
  251. package/dist/web-router/components/Split.test.jsx +167 -0
  252. package/dist/web-router/components/SplitInview.d.ts +22 -0
  253. package/dist/web-router/components/SplitInview.jsx +78 -89
  254. package/dist/web-router/components/SplitInview.test.jsx +112 -0
  255. package/dist/web-router/components/SsrRequestContext.d.ts +20 -0
  256. package/dist/web-router/components/SsrRequestContext.jsx +17 -7
  257. package/dist/web-router/components/SsrRequestContext.test.jsx +53 -0
  258. package/dist/web-router/context.d.ts +15 -0
  259. package/dist/web-router/context.jsx +5 -5
  260. package/dist/web-router/context.test.jsx +10 -0
  261. package/dist/web-router/utils/metaDataUtils.d.ts +24 -0
  262. package/dist/web-router/utils/metaDataUtils.jsx +86 -86
  263. package/dist/web-router/utils/metaDataUtils.test.jsx +188 -0
  264. package/dist/web-router/vitest.setup.js +12 -0
  265. package/mcp_v2/knowledge-base.json +115 -17
  266. package/mcp_v2/mcp.js +141 -3
  267. package/mcp_v2/package-lock.json +2031 -0
  268. package/mcp_v2/package.json +13 -2
  269. package/mcp_v2/scripts/copyErrorsIndex.cjs +34 -0
  270. package/mcp_v2/test/errors.test.ts +123 -0
  271. package/mcp_v2/test/github.test.ts +177 -0
  272. package/mcp_v2/tools/errors.d.ts +20 -0
  273. package/mcp_v2/tools/errors.js +63 -0
  274. package/mcp_v2/tools/github.d.ts +41 -0
  275. package/mcp_v2/tools/github.js +231 -0
  276. package/mcp_v2/vitest.config.mjs +22 -0
  277. package/package.json +60 -11
  278. package/test/errors/docsDrift.test.ts +113 -0
  279. package/test/errors/index.test.ts +200 -0
  280. package/test/errors/registry.test.ts +108 -0
  281. package/test/scripts/preflight.test.ts +118 -0
  282. package/test/server/ChunkExtractor.test.ts +97 -0
  283. package/test/server/extract.test.ts +128 -0
  284. package/test/server/fixtures/template/server/document.jsx +19 -0
  285. package/test/server/fixtures/template/server/index.js +10 -0
  286. package/test/server/fixtures/template/src/js/containers/App/index.jsx +33 -0
  287. package/test/server/fixtures/template/src/js/routes/index.jsx +72 -0
  288. package/test/server/fixtures/template/src/js/routes/utils.jsx +39 -0
  289. package/test/server/fixtures/template/src/js/store/index.js +19 -0
  290. package/test/server/handler.assets.test.ts +330 -0
  291. package/test/server/handler.test.ts +208 -0
  292. package/test/server/manifestCache.test.ts +71 -0
  293. package/test/server/render.test.ts +71 -0
  294. package/test/server/scriptUtils.test.ts +103 -0
  295. package/test/server/userAgentUtil.test.ts +48 -0
  296. package/test/server/validator.test.ts +225 -0
  297. package/test/vite/resolveDevServerConfig.test.js +4 -1
  298. package/tsconfig.test.json +23 -0
  299. package/vitest.config.ts +93 -0
  300. package/dist/caching.js +0 -1
  301. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/DeviceInfoUtilsTest.kt +0 -187
  302. package/dist/native/bridge/standardizedHooks.js +0 -611
  303. package/dist/router.js +0 -1
  304. package/dist/scripts/validator.js +0 -149
  305. package/dist/web-router/hooks.jsx +0 -72
  306. package/dist/web-router/types/components/MetaTag.d.ts +0 -2
  307. package/dist/web-router/types/components/RouterDataProvider.d.ts +0 -95
  308. package/dist/web-router/types/context.d.ts +0 -14
  309. package/dist/web-router/types/hooks.d.ts +0 -1
  310. package/dist/web-router/types/index.d.ts +0 -3
  311. package/dist/web-router/types/utils/metaDataUtils.d.ts +0 -40
  312. /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Constants/CatalystConstants.swift +0 -0
  313. /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Constants/ConfigConstants.swift +0 -0
  314. /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Notifications/NotificationModels.swift +0 -0
  315. /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Protocols/NotificationHandlerProtocol.swift +0 -0
  316. /package/dist/native/iosnativeWebView/{Sources/Core → CoreLogic/Sources/CatalystCoreLogic}/Utils/NullNotificationHandler.swift +0 -0
@@ -120,6 +120,41 @@ const ISSUE_TEMPLATES = {
120
120
  },
121
121
  }
122
122
 
123
+ // Pull-request templates, one per change type. Section lists mirror the
124
+ // `##` headings in .github/PULL_REQUEST_TEMPLATE/<change_type>.md exactly —
125
+ // the drift test in test/github.test.ts asserts that, the same way it
126
+ // checks ISSUE_TEMPLATES against .github/ISSUE_TEMPLATE/*.yml.
127
+ const PR_TEMPLATES = {
128
+ fix: {
129
+ change_type: "fix",
130
+ name: "Bug fix",
131
+ use_when: "The PR corrects broken, ignored, regressed, or misdocumented behavior.",
132
+ sections: ["Root cause", "Repro", "Fix", "Regression test", "Affected error codes"],
133
+ },
134
+ feature: {
135
+ change_type: "feature",
136
+ name: "Feature",
137
+ use_when: "The PR adds a new capability, hook, CLI behavior, or framework ergonomics change.",
138
+ sections: ["What", "Why", "New error codes", "Test coverage"],
139
+ },
140
+ chore: {
141
+ change_type: "chore",
142
+ name: "Chore (no behaviour change)",
143
+ use_when:
144
+ "The PR changes deps, CI, tooling, docs, or internal structure with no runtime behavior change.",
145
+ sections: ["What triggered this", "Change", "No behaviour change"],
146
+ },
147
+ }
148
+
149
+ // Appended verbatim to every rendered PR body. Kept in sync with the shared
150
+ // footer in .github/PULL_REQUEST_TEMPLATE*.md (also asserted by the drift test).
151
+ const PR_FOOTER_CHECKLIST = [
152
+ "- [ ] `npm run test:unit` passes locally",
153
+ "- [ ] `npm run lint` passes locally",
154
+ "- [ ] No new raw `throw new Error(...)` in changed files",
155
+ "- [ ] Coverage gate (`coverage-summary`, #415/#437) not regressed",
156
+ ].join("\n")
157
+
123
158
  function init(projectInfo) {
124
159
  _projectInfo = projectInfo
125
160
  }
@@ -1122,7 +1157,203 @@ async function handle_create_github_issue(args = {}) {
1122
1157
  }
1123
1158
  }
1124
1159
 
1160
+ // ── Pull request workflow ────────────────────────────────────────────────────
1161
+
1162
+ function resolvePrChangeType(args) {
1163
+ const requested = typeof args.change_type === "string" ? args.change_type.trim().toLowerCase() : ""
1164
+ if (PR_TEMPLATES[requested]) return requested
1165
+
1166
+ const text = `${args.title || ""}\n${args.summary || args.body || ""}`.toLowerCase()
1167
+ if (/\b(fix|bug|regress|broken|crash|incorrect)\b/.test(text)) return "fix"
1168
+ if (/\b(feat|feature|add\s+support|new\s+(hook|api|capability))\b/.test(text)) return "feature"
1169
+ return "chore"
1170
+ }
1171
+
1172
+ // Compose a PR body in the shape of the matching .github/PULL_REQUEST_TEMPLATE
1173
+ // file. Pre-structured markdown (already has `##` headings) is passed through
1174
+ // untouched; otherwise the structured per-type fields are laid out in the
1175
+ // template's section order. The shared footer checklist is always appended.
1176
+ function buildPrBody(args) {
1177
+ const changeType = resolvePrChangeType(args)
1178
+ const rawBody = stripExistingFooter(args.body)
1179
+ const closesLine =
1180
+ args.closes_issue != null && `${args.closes_issue}`.trim()
1181
+ ? `Closes #${`${args.closes_issue}`.replace(/^#/, "").trim()}`
1182
+ : ""
1183
+
1184
+ let content
1185
+ if (rawBody && hasMarkdownHeadings(rawBody)) {
1186
+ content = rawBody
1187
+ } else {
1188
+ const sections = []
1189
+ if (changeType === "fix") {
1190
+ appendSection(sections, "Root cause", firstNonEmpty(args.root_cause, args.summary, rawBody))
1191
+ appendSection(sections, "Repro", args.repro || args.steps_to_reproduce)
1192
+ appendSection(sections, "Fix", firstNonEmpty(args.fix, args.proposed_fix))
1193
+ appendSection(sections, "Regression test", args.regression_test)
1194
+ appendSection(sections, "Affected error codes", firstNonEmpty(args.affected_error_codes, "none"))
1195
+ } else if (changeType === "feature") {
1196
+ appendSection(sections, "What", firstNonEmpty(args.what, args.summary, rawBody))
1197
+ appendSection(sections, "Why", firstNonEmpty(args.why, args.motivation))
1198
+ appendSection(
1199
+ sections,
1200
+ "New error codes",
1201
+ firstNonEmpty(args.new_error_codes, "No new error codes")
1202
+ )
1203
+ appendSection(sections, "Test coverage", args.coverage_delta || args.test_coverage)
1204
+ } else {
1205
+ appendSection(
1206
+ sections,
1207
+ "What triggered this",
1208
+ firstNonEmpty(args.change_trigger, args.summary, rawBody)
1209
+ )
1210
+ appendSection(sections, "Change", firstNonEmpty(args.change, args.summary, rawBody))
1211
+ appendSection(
1212
+ sections,
1213
+ "No behaviour change",
1214
+ args.no_behaviour_change === true || args.no_behaviour_change === "true"
1215
+ ? "- [x] Confirmed: no runtime behaviour change — output, public API, and error codes are unchanged"
1216
+ : "- [ ] Confirmed: no runtime behaviour change — output, public API, and error codes are unchanged"
1217
+ )
1218
+ }
1219
+ content = sections.join("\n\n").trim()
1220
+ }
1221
+
1222
+ const body = [closesLine, content, "---", PR_FOOTER_CHECKLIST].filter(Boolean).join("\n\n").trim()
1223
+
1224
+ return { change_type: changeType, body }
1225
+ }
1226
+
1227
+ async function handle_create_github_pr(args = {}) {
1228
+ const { title } = args
1229
+ if (!title || typeof title !== "string" || title.trim() === "") {
1230
+ return { ok: false, error: "title is required and must be a non-empty string." }
1231
+ }
1232
+ if (
1233
+ !firstNonEmpty(args.body, args.summary, args.root_cause, args.what, args.change, args.change_trigger)
1234
+ ) {
1235
+ return {
1236
+ ok: false,
1237
+ error: "body or a structured field (summary / root_cause / what / change / change_trigger) is required.",
1238
+ }
1239
+ }
1240
+
1241
+ const root = getProjectRoot(args)
1242
+ const head = firstNonEmpty(args.head, runGit(root, "git rev-parse --abbrev-ref HEAD")) || ""
1243
+ if (!head || head === "HEAD") {
1244
+ return {
1245
+ ok: false,
1246
+ error: "Could not resolve the head branch. Pass head explicitly (you may be in a detached HEAD).",
1247
+ }
1248
+ }
1249
+ const base = firstNonEmpty(args.base) || "main"
1250
+ if (head === base) {
1251
+ return { ok: false, error: `head and base are the same branch (${head}).` }
1252
+ }
1253
+
1254
+ const { change_type: changeType, body } = buildPrBody(args)
1255
+ const draft = args.draft !== false
1256
+ const dryRun = args.dry_run !== false
1257
+
1258
+ const remoteHead = runGit(root, `git rev-parse --verify --quiet origin/${head}`)
1259
+ const commits = runGit(root, `git log --oneline origin/${base}..${head} 2>/dev/null`) || ""
1260
+ const tokenResult = getToken()
1261
+
1262
+ const preview = {
1263
+ type: "pull_request",
1264
+ repo: `${GITHUB_OWNER}/${GITHUB_REPO}`,
1265
+ title: title.trim(),
1266
+ head,
1267
+ base,
1268
+ draft,
1269
+ change_type: changeType,
1270
+ suggested_template: PR_TEMPLATES[changeType],
1271
+ body,
1272
+ head_pushed: Boolean(remoteHead),
1273
+ commits_ahead_of_base: commits ? commits.split("\n") : [],
1274
+ }
1275
+
1276
+ if (dryRun) {
1277
+ return {
1278
+ ok: true,
1279
+ dry_run: true,
1280
+ preview,
1281
+ token_source: tokenResult.ok ? tokenResult.source : "none",
1282
+ auth_warning: tokenResult.ok ? null : tokenResult.error,
1283
+ push_warning: remoteHead
1284
+ ? null
1285
+ : `origin/${head} not found — push the branch before publishing: git push -u origin ${head}`,
1286
+ instructions:
1287
+ "Show the rendered PR preview (title, head → base, change type, body) to the developer. Ask whether to edit, cancel, or publish. Publish only after explicit approval with dry_run:false.",
1288
+ next_action:
1289
+ "Wait for explicit developer approval before calling create_github_pr with dry_run:false.",
1290
+ }
1291
+ }
1292
+
1293
+ if (!remoteHead) {
1294
+ return {
1295
+ ok: false,
1296
+ blocked: true,
1297
+ error: `origin/${head} does not exist. Push the branch first: git push -u origin ${head}`,
1298
+ preview,
1299
+ }
1300
+ }
1301
+
1302
+ if (!tokenResult.ok) {
1303
+ return { ok: false, error: tokenResult.error, preview }
1304
+ }
1305
+
1306
+ try {
1307
+ const res = await githubRequest(
1308
+ "POST",
1309
+ `/repos/${GITHUB_OWNER}/${GITHUB_REPO}/pulls`,
1310
+ tokenResult.token,
1311
+ { title: title.trim(), head, base, body, draft }
1312
+ )
1313
+
1314
+ if (res.status === 201) {
1315
+ return {
1316
+ ok: true,
1317
+ message: `PR #${res.body.number} created successfully.`,
1318
+ number: res.body.number,
1319
+ url: res.body.html_url,
1320
+ head,
1321
+ base,
1322
+ draft: res.body.draft,
1323
+ change_type: changeType,
1324
+ token_source: tokenResult.source,
1325
+ }
1326
+ }
1327
+
1328
+ const apiMessage = res.body && res.body.message ? res.body.message : JSON.stringify(res.body)
1329
+ const fallbackDir = ensureFallbackDir(root)
1330
+ const fallbackPath = path.join(
1331
+ fallbackDir,
1332
+ `${new Date().toISOString().replace(/[:.]/g, "-")}-pr-${slugify(title)}.md`
1333
+ )
1334
+ fs.writeFileSync(
1335
+ fallbackPath,
1336
+ [`# ${title.trim()}`, "", `Base: ${base} · Head: ${head}`, "", "## Body", "", body, ""].join(
1337
+ "\n"
1338
+ ),
1339
+ "utf8"
1340
+ )
1341
+ return {
1342
+ ok: false,
1343
+ error: `GitHub API returned HTTP ${res.status}: ${apiMessage}`,
1344
+ fallback: { markdown_path: fallbackPath },
1345
+ }
1346
+ } catch (err) {
1347
+ return { ok: false, error: `Network error while calling GitHub API: ${err.message}` }
1348
+ }
1349
+ }
1350
+
1125
1351
  module.exports = {
1126
1352
  init,
1127
1353
  handle_create_github_issue,
1354
+ handle_create_github_pr,
1355
+ ISSUE_TEMPLATES,
1356
+ PR_TEMPLATES,
1357
+ PR_FOOTER_CHECKLIST,
1358
+ DEFAULT_LABELS,
1128
1359
  }
@@ -0,0 +1,22 @@
1
+ import { defineConfig } from "vitest/config"
2
+
3
+ // Framework-level (Tier 1) unit tests for catalyst-mcp's own internals.
4
+ // mcp_v2 lives inside packages/catalyst-core/mcp_v2/ (it ships bundled
5
+ // inside the catalyst-core package, see ../mcp_v2/scripts/copyErrorsIndex.cjs
6
+ // and errors.js's own packaged-path handling) and is NOT matched by the
7
+ // packages/* workspace glob, so it's invisible to `npm run test:unit` unless
8
+ // explicitly wired in — see the root package.json's test:unit script.
9
+ export default defineConfig({
10
+ test: {
11
+ environment: "node",
12
+ include: ["test/**/*.test.ts"],
13
+ // tools/errors.js itself is CommonJS, loaded via require() from the
14
+ // .ts test file below. .ts, not .cts: this Vite/Rollup version's SSR
15
+ // transform doesn't strip TS syntax from .cts files at all (fails to
16
+ // parse even a single type annotation — a real tooling gap,
17
+ // confirmed empirically, not a config mistake). vitest's own
18
+ // describe/it/expect exports can't be require()'d, only import'd —
19
+ // globals injects them instead.
20
+ globals: true,
21
+ },
22
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "catalyst-core",
3
- "version": "0.3.0-beta.5",
3
+ "version": "0.3.0-canary.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.jsx",
6
6
  "description": "Web framework that provides great performance out of the box",
@@ -16,41 +16,71 @@
16
16
  "@catalyst/template": "."
17
17
  },
18
18
  "exports": {
19
- ".": "./dist/index.jsx",
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.jsx"
22
+ },
20
23
  "./package.json": "./package.json",
21
24
  "./logger": "./dist/logger.js",
22
- "./caching": "./dist/caching.js",
23
- "./router/ClientRouter": "./dist/router/ClientRouter.js",
24
- "./document": "./dist/server/renderer/document/index.jsx",
25
- "./WebBridge": "./dist/native/bridge/WebBridge.js",
26
- "./hooks": "./dist/native/bridge/hooks.js",
25
+ "./router/ClientRouter": {
26
+ "types": "./dist/router/ClientRouter.d.ts",
27
+ "default": "./dist/router/ClientRouter.js"
28
+ },
29
+ "./WebBridge": {
30
+ "types": "./dist/native/bridge/WebBridge.d.ts",
31
+ "default": "./dist/native/bridge/WebBridge.js"
32
+ },
33
+ "./hooks": {
34
+ "types": "./dist/native/bridge/hooks.d.ts",
35
+ "default": "./dist/native/bridge/hooks.js"
36
+ },
37
+ "./errors": "./dist/errors/index.js",
27
38
  "./sentry": "./dist/sentry.cjs",
28
39
  "./otel": "./dist/otel.js"
29
40
  },
41
+ "typesVersions": {
42
+ "*": {
43
+ "hooks": [
44
+ "./dist/native/bridge/hooks.d.ts"
45
+ ],
46
+ "WebBridge": [
47
+ "./dist/native/bridge/WebBridge.d.ts"
48
+ ],
49
+ "router/ClientRouter": [
50
+ "./dist/router/ClientRouter.d.ts"
51
+ ]
52
+ }
53
+ },
30
54
  "scripts": {
31
55
  "lint": "eslint .",
32
56
  "lint-staged": "lint-staged",
33
57
  "test:unit": "node --test \"test/**/*.test.js\"",
58
+ "typecheck": "tsc --noEmit",
34
59
  "prettify": "prettier . --write",
35
- "prepare": "node ../../scripts/safe-rimraf.js ./dist && cp -r ./src ./dist && babel src/native --out-dir dist/native --config-file ./babel.native.config.cjs --ignore '**/.build/**' && babel src/sentry.js --out-file dist/sentry.cjs --config-file ./babel.native.config.cjs",
60
+ "prepare": "node ../../scripts/safe-rimraf.js ./dist && node scripts/build-dist.mjs && cp -r ./src/native ./dist/native && babel src/native --out-dir dist/native --config-file ./babel.native.config.cjs --extensions '.js,.jsx,.ts,.tsx' --ignore '**/.build/**' && node scripts/strip-ts-sources.mjs ./dist/native && babel src/sentry.js --out-file dist/sentry.cjs --config-file ./babel.native.config.cjs && tsc -p tsconfig.declarations.json && node ./mcp_v2/scripts/copyErrorsIndex.cjs",
36
61
  "prepublishOnly": "npm run prepare",
62
+ "test": "npm run test:types && vitest run",
63
+ "test:watch": "vitest",
64
+ "test:types": "tsc -p tsconfig.test.json --noEmit",
37
65
  "test:fixture": "sh ../../scripts/test-catalyst-core.sh"
38
66
  },
39
67
  "license": "MIT",
68
+ "engines": {
69
+ "node": ">=22.12"
70
+ },
40
71
  "dependencies": {
41
72
  "@vitejs/plugin-react": "^4.4.1",
73
+ "ansis": "^4.3.1",
42
74
  "body-parser": "^1.20.2",
43
75
  "compression": "^1.7.4",
44
76
  "cookie-parser": "^1.4.6",
45
77
  "express": "^4.18.2",
46
78
  "express-static-gzip": "^2.1.7",
47
- "picocolors": "^1.0.0",
48
79
  "react": "19.0.0",
49
80
  "react-dom": "19.0.0",
50
81
  "react-helmet-async": "^1.3.0",
51
82
  "react-redux": "^9.2.0",
52
83
  "react-refresh": "^0.14.0",
53
- "react-router": "^7.18.2",
54
84
  "redux": "^4.2.1",
55
85
  "sanitize-html": "^2.17.6",
56
86
  "sass": "^1.89.2",
@@ -60,6 +90,15 @@
60
90
  "winston": "^3.11.0",
61
91
  "winston-daily-rotate-file": "^5.0.0"
62
92
  },
93
+ "peerDependencies": {
94
+ "@types/react": "^19.0.0",
95
+ "react-router": "^7.18.2"
96
+ },
97
+ "peerDependenciesMeta": {
98
+ "@types/react": {
99
+ "optional": true
100
+ }
101
+ },
63
102
  "devDependencies": {
64
103
  "@babel/cli": "^7.23.0",
65
104
  "@babel/core": "^7.23.2",
@@ -69,6 +108,13 @@
69
108
  "@babel/preset-typescript": "^7.24.7",
70
109
  "@commitlint/cli": "^19.3.0",
71
110
  "@commitlint/config-conventional": "^19.2.2",
111
+ "@testing-library/dom": "10.4.1",
112
+ "@testing-library/jest-dom": "7.0.1",
113
+ "@testing-library/react": "16.3.2",
114
+ "@types/node": "^22.20.1",
115
+ "@types/react": "^19.2.18",
116
+ "@types/react-dom": "^19.2.5",
117
+ "@vitest/coverage-v8": "4.1.9",
72
118
  "eslint": "^8.26.0",
73
119
  "eslint-plugin-babel": "^5.3.1",
74
120
  "eslint-plugin-react": "^7.34.1",
@@ -77,8 +123,11 @@
77
123
  "eslint-plugin-risxss": "^2.1.0",
78
124
  "eslint-plugin-security": "^3.0.0",
79
125
  "husky": "^9.0.11",
126
+ "jsdom": "30.0.1",
80
127
  "lint-staged": "^15.2.2",
81
- "prettier": "^3.2.5"
128
+ "prettier": "^3.2.5",
129
+ "typescript": "^7.0.2",
130
+ "vitest": "4.1.9"
82
131
  },
83
132
  "lint-staged": {
84
133
  "*.{js,jsx}": [
@@ -0,0 +1,113 @@
1
+ import { describe, it, expect, afterEach } from "vitest"
2
+ import { mkdtempSync, rmSync, readFileSync, readdirSync, existsSync } from "fs"
3
+ import { tmpdir } from "os"
4
+ import path from "path"
5
+ import { fileURLToPath } from "url"
6
+ import { generateDocs } from "../../src/errors/generateDocs.js"
7
+ import { ERROR_DEFINITIONS } from "../../src/errors/registry.js"
8
+
9
+ // Framework-level (Tier 1) contract test: catches the "edited registry.js
10
+ // without regenerating docs" or "hand-edited a generated .md directly"
11
+ // mistake. Regenerates into a scratch dir (never touches the committed
12
+ // errors/ tree) and diffs the core-owned slice against what's checked in.
13
+
14
+ const __filename = fileURLToPath(import.meta.url)
15
+ const __dirname = path.dirname(__filename)
16
+
17
+ // test/errors -> repo root /errors (the committed output)
18
+ const COMMITTED_ERRORS_DIR = path.resolve(__dirname, "../../../../errors")
19
+
20
+ // Shape of one errors/index.json entry, as written by generateDocs.js.
21
+ // registry.js/generateDocs.js stay plain JS until #420's source conversion —
22
+ // this type exists only to give the test file real safety in the meantime.
23
+ interface IndexEntry {
24
+ category: string
25
+ message: string
26
+ details: string
27
+ suggestedAction: string
28
+ docUrl: string
29
+ }
30
+
31
+ let scratchDir: string | undefined
32
+
33
+ afterEach(() => {
34
+ if (scratchDir) rmSync(scratchDir, { recursive: true, force: true })
35
+ scratchDir = undefined
36
+ })
37
+
38
+ describe("generated error docs match committed output (docs-drift check)", () => {
39
+ it("regenerating into a scratch dir produces byte-identical .md files for every core-owned code", () => {
40
+ scratchDir = mkdtempSync(path.join(tmpdir(), "catalyst-core-docs-drift-"))
41
+ generateDocs(scratchDir)
42
+
43
+ const mismatches: string[] = []
44
+ for (const [code, def] of Object.entries(ERROR_DEFINITIONS)) {
45
+ const relPath = path.join(def.category, `${code}.md`)
46
+ const committedPath = path.join(COMMITTED_ERRORS_DIR, relPath)
47
+ const scratchPath = path.join(scratchDir, relPath)
48
+
49
+ if (!existsSync(committedPath)) {
50
+ mismatches.push(`${relPath}: missing from committed errors/ — run generateDocs.js and commit the output`)
51
+ continue
52
+ }
53
+ const committed = readFileSync(committedPath, "utf8")
54
+ const fresh = readFileSync(scratchPath, "utf8")
55
+ if (committed !== fresh) {
56
+ mismatches.push(`${relPath}: committed content differs from what generateDocs() produces today`)
57
+ }
58
+ }
59
+ expect(mismatches).toEqual([])
60
+ })
61
+
62
+ it("committed index.json has an up-to-date entry for every core-owned code", () => {
63
+ const indexPath = path.join(COMMITTED_ERRORS_DIR, "index.json")
64
+ const committedIndex: Record<string, IndexEntry> = JSON.parse(readFileSync(indexPath, "utf8"))
65
+
66
+ const mismatches: string[] = []
67
+ for (const [code, def] of Object.entries(ERROR_DEFINITIONS)) {
68
+ const entry = committedIndex[code]
69
+ if (!entry) {
70
+ mismatches.push(`${code}: missing from committed errors/index.json`)
71
+ continue
72
+ }
73
+ if (entry.category !== def.category) mismatches.push(`${code}: index.json category "${entry.category}" !== registry "${def.category}"`)
74
+ if (entry.message !== def.defaultMessage) mismatches.push(`${code}: index.json message drifted from registry defaultMessage`)
75
+ if (entry.details !== def.defaultDetails) mismatches.push(`${code}: index.json details drifted from registry defaultDetails`)
76
+ if (entry.suggestedAction !== def.suggestedAction) mismatches.push(`${code}: index.json suggestedAction drifted from registry`)
77
+ }
78
+ expect(mismatches).toEqual([])
79
+ })
80
+
81
+ it("committed index.json has no stale core-category entry for a code removed from the registry", () => {
82
+ const indexPath = path.join(COMMITTED_ERRORS_DIR, "index.json")
83
+ const committedIndex: Record<string, IndexEntry> = JSON.parse(readFileSync(indexPath, "utf8"))
84
+ const ownedCategories = new Set(Object.values(ERROR_DEFINITIONS).map((d) => d.category))
85
+
86
+ const stale: string[] = []
87
+ for (const [code, entry] of Object.entries(committedIndex)) {
88
+ if (ownedCategories.has(entry.category) && !(code in ERROR_DEFINITIONS)) {
89
+ stale.push(`${code}: stale entry in errors/index.json — its category ("${entry.category}") is core-owned but this code no longer exists in the registry`)
90
+ }
91
+ }
92
+ expect(stale).toEqual([])
93
+ })
94
+
95
+ it("committed errors/ tree has no stray core-category .md files not backed by a current registry entry", () => {
96
+ const ownedCategories = new Set(Object.values(ERROR_DEFINITIONS).map((d) => d.category))
97
+ const knownFiles = new Set(
98
+ Object.entries(ERROR_DEFINITIONS).map(([code, def]) => path.join(def.category, `${code}.md`))
99
+ )
100
+
101
+ const stray: string[] = []
102
+ for (const category of ownedCategories) {
103
+ const dir = path.join(COMMITTED_ERRORS_DIR, category)
104
+ if (!existsSync(dir)) continue
105
+ for (const file of readdirSync(dir)) {
106
+ if (!file.endsWith(".md")) continue
107
+ const rel = path.join(category, file)
108
+ if (!knownFiles.has(rel)) stray.push(rel)
109
+ }
110
+ }
111
+ expect(stray).toEqual([])
112
+ })
113
+ })