catalyst-core 0.2.0-beta.3 → 0.3.0-beta.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 (167) hide show
  1. package/babel.native.config.cjs +8 -0
  2. package/bin/catalyst.js +49 -105
  3. package/changelog.md +8 -0
  4. package/dist/caching.js +1 -1
  5. package/dist/globals.d.ts +7 -0
  6. package/dist/index.jsx +8 -0
  7. package/dist/logger.js +74 -3
  8. package/dist/native/androidProject/app/build.gradle.kts +45 -4
  9. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeBridge.kt +86 -0
  10. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/BridgeUtils.kt +8 -0
  11. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/FrameworkServerUtils.kt +173 -13
  12. package/dist/native/androidProject/settings.gradle.kts +10 -0
  13. package/dist/native/androidSetup.js +300 -8
  14. package/dist/native/bridge/WebBridge.js +481 -59
  15. package/dist/native/bridge/constants/NativeInterfaces.js +304 -45
  16. package/dist/native/bridge/errors.js +250 -26
  17. package/dist/native/bridge/hooks/index.js +132 -1
  18. package/dist/native/bridge/hooks/useAI.js +94 -0
  19. package/dist/native/bridge/hooks/useCamera.js +347 -9
  20. package/dist/native/bridge/hooks/useDataProtection.js +200 -2
  21. package/dist/native/bridge/hooks/useDeviceInfo.js +71 -2
  22. package/dist/native/bridge/hooks/useFilePicker.js +429 -2
  23. package/dist/native/bridge/hooks/useGoogleSignIn.js +81 -1
  24. package/dist/native/bridge/hooks/useHapticFeedback.js +196 -1
  25. package/dist/native/bridge/hooks/useIntent.js +95 -1
  26. package/dist/native/bridge/hooks/useNativeTransition.js +202 -27
  27. package/dist/native/bridge/hooks/useNetworkStatus.js +84 -3
  28. package/dist/native/bridge/hooks/useNotification.js +318 -2
  29. package/dist/native/bridge/hooks/useSafeArea.js +84 -2
  30. package/dist/native/bridge/hooks/useVideoStream.js +434 -6
  31. package/dist/native/bridge/hooks/utils.js +27 -1
  32. package/dist/native/bridge/hooks.js +16 -1
  33. package/dist/native/bridge/perf/collectors/ApiCollector.js +66 -3
  34. package/dist/native/bridge/perf/collectors/CacheCollector.js +186 -11
  35. package/dist/native/bridge/perf/collectors/HookCollector.js +141 -19
  36. package/dist/native/bridge/perf/collectors/InsightsCollector.js +481 -23
  37. package/dist/native/bridge/perf/collectors/InteractionCollector.js +245 -10
  38. package/dist/native/bridge/perf/collectors/KeyboardCollector.js +107 -8
  39. package/dist/native/bridge/perf/collectors/NavigationCollector.js +273 -32
  40. package/dist/native/bridge/perf/collectors/NetworkTimingCollector.js +178 -2
  41. package/dist/native/bridge/perf/collectors/RenderCollector.js +258 -14
  42. package/dist/native/bridge/perf/collectors/ScrollCollector.js +95 -9
  43. package/dist/native/bridge/perf/collectors/ThreadCollector.js +90 -6
  44. package/dist/native/bridge/perf/core/constants.js +103 -20
  45. package/dist/native/bridge/perf/core/measure.js +179 -30
  46. package/dist/native/bridge/perf/core/session.js +89 -23
  47. package/dist/native/bridge/perf/core/store.js +554 -1
  48. package/dist/native/bridge/perf/core/summary.js +174 -1
  49. package/dist/native/bridge/perf/core/traceExport.js +240 -1
  50. package/dist/native/bridge/perf/core/waterfalls.js +146 -1
  51. package/dist/native/bridge/perf/index.js +359 -38
  52. package/dist/native/bridge/safeArea.js +53 -5
  53. package/dist/native/bridge/standardizedHooks.js +595 -82
  54. package/dist/native/bridge/useBaseHook.js +274 -38
  55. package/dist/native/bridge/utils/CameraUtils.js +201 -56
  56. package/dist/native/bridge/utils/FileObjectConverter.js +129 -18
  57. package/dist/native/bridge/utils/NativeBridge.js +425 -141
  58. package/dist/native/buildAndroid/assets.js +510 -13
  59. package/dist/native/buildAndroid/build.js +296 -19
  60. package/dist/native/buildAndroid/config.js +87 -1
  61. package/dist/native/buildAndroid/index.js +406 -1
  62. package/dist/native/buildAppAndroid.js +34 -2
  63. package/dist/native/buildAppIos.js +62 -2
  64. package/dist/native/buildIos/assets.js +609 -8
  65. package/dist/native/buildIos/build.js +639 -20
  66. package/dist/native/buildIos/config.js +294 -12
  67. package/dist/native/buildIos/index.js +343 -6
  68. package/dist/native/buildIos/plugins.js +343 -16
  69. package/dist/native/internal-plugins/device-info-plugin/android/DeviceInfoPlugin.kt +43 -0
  70. package/dist/native/internal-plugins/device-info-plugin/ios/DeviceInfoPlugin.swift +28 -0
  71. package/dist/native/internal-plugins/device-info-plugin/manifest.json +19 -0
  72. package/dist/native/internalPluginUtils.js +232 -7
  73. package/dist/native/package.json +3 -0
  74. package/dist/native/plugin-bridge/PluginBridge.js +227 -1
  75. package/dist/native/pluginComposerAndroid.js +407 -23
  76. package/dist/native/pluginComposerIos.js +435 -11
  77. package/dist/native/renameAndroidProject.js +1094 -88
  78. package/dist/native/setupEmulatorIos.js +289 -22
  79. package/dist/native/setupServer.js +160 -19
  80. package/dist/native/terminalProgress.js +199 -11
  81. package/dist/native/utils.js +193 -15
  82. package/dist/offline/catalyst-sw.js +145 -1
  83. package/dist/offline/registerServiceWorker.js +33 -1
  84. package/dist/otel.js +375 -46
  85. package/dist/router/ClientRouter.js +14 -2
  86. package/dist/router/ServerRouter.js +9 -1
  87. package/dist/router.js +1 -1
  88. package/dist/scripts/build.js +112 -3
  89. package/dist/scripts/checkVersion.js +3 -1
  90. package/dist/scripts/cleanCache.js +30 -1
  91. package/dist/scripts/generateOfflineManifest.js +116 -1
  92. package/dist/scripts/loadEnvironmentVariables.js +32 -6
  93. package/dist/scripts/plugins.js +309 -1
  94. package/dist/scripts/preServerInit.js +13 -0
  95. package/dist/scripts/scriptUtils.js +54 -3
  96. package/dist/scripts/serve.js +51 -4
  97. package/dist/scripts/start.js +47 -10
  98. package/dist/scripts/validator.js +149 -1
  99. package/dist/sentry.cjs +127 -0
  100. package/dist/sentry.js +125 -5
  101. package/dist/server/expressServer.js +296 -5
  102. package/dist/server/manifestCache.js +36 -0
  103. package/dist/server/renderer/ChunkExtractor.js +144 -0
  104. package/dist/server/renderer/document/Body.jsx +59 -0
  105. package/dist/server/renderer/document/FastRefresh.jsx +20 -0
  106. package/dist/server/renderer/document/Head.jsx +60 -0
  107. package/dist/server/renderer/document/index.jsx +2 -0
  108. package/dist/server/renderer/extract.js +149 -31
  109. package/dist/server/renderer/handler.jsx +450 -0
  110. package/dist/server/renderer/index.js +8 -1
  111. package/dist/server/renderer/render.js +47 -0
  112. package/dist/server/utils/botDetectionMiddleware.js +29 -0
  113. package/dist/server/utils/cjsRequire.js +10 -0
  114. package/dist/server/utils/userAgentUtil.js +87 -9
  115. package/dist/server/utils/validator.js +164 -1
  116. package/dist/vite/FastRefresh.jsx +20 -0
  117. package/dist/vite/inject-cache-key-plugin.js +276 -0
  118. package/dist/vite/loadCustomViteConfig.js +22 -0
  119. package/dist/vite/manifest-categorization-plugin.js +455 -0
  120. package/dist/vite/node-loader.mjs +458 -0
  121. package/dist/vite/scssParams.js +21 -0
  122. package/dist/vite/vite.config.client.js +130 -0
  123. package/dist/vite/vite.config.js +498 -0
  124. package/dist/vite/vite.config.server.js +84 -0
  125. package/dist/web-router/components/MetaTag.jsx +34 -0
  126. package/dist/web-router/components/RouterDataProvider.jsx +332 -0
  127. package/dist/web-router/components/Split.jsx +200 -0
  128. package/dist/web-router/components/SplitInview.jsx +106 -0
  129. package/dist/web-router/components/SsrRequestContext.jsx +14 -0
  130. package/dist/web-router/context.jsx +12 -0
  131. package/dist/web-router/hooks.jsx +72 -0
  132. package/dist/web-router/types/components/MetaTag.d.ts +2 -0
  133. package/dist/web-router/types/components/RouterDataProvider.d.ts +95 -0
  134. package/dist/web-router/types/context.d.ts +14 -0
  135. package/dist/web-router/types/hooks.d.ts +1 -0
  136. package/dist/web-router/types/index.d.ts +3 -0
  137. package/dist/web-router/types/utils/metaDataUtils.d.ts +24 -0
  138. package/dist/web-router/utils/metaDataUtils.jsx +119 -0
  139. package/mcp_v2/conversion-tasks.json +35 -17
  140. package/mcp_v2/knowledge-base.json +176 -17
  141. package/mcp_v2/lib/helpers.js +10 -0
  142. package/mcp_v2/mcp.js +40 -8
  143. package/mcp_v2/package.json +1 -0
  144. package/mcp_v2/tools/build.js +161 -37
  145. package/mcp_v2/tools/conversion.js +106 -5
  146. package/mcp_v2/tools/tasks.js +18 -14
  147. package/package.json +35 -68
  148. package/babel.config.js +0 -32
  149. package/dist/index.js +0 -1
  150. package/dist/scripts/devBuild.js +0 -3
  151. package/dist/scripts/devServe.js +0 -3
  152. package/dist/scripts/loadScriptsBeforeServerStarts.js +0 -4
  153. package/dist/scripts/registerAliases.js +0 -6
  154. package/dist/server/renderer/document/Body.js +0 -11
  155. package/dist/server/renderer/document/Head.js +0 -9
  156. package/dist/server/renderer/document/index.js +0 -1
  157. package/dist/server/renderer/handler.js +0 -47
  158. package/dist/server/startServer.js +0 -57
  159. package/dist/webpack/babel-plugins/remove-client.plugin.js +0 -5
  160. package/dist/webpack/babel-plugins/remove-ssr.plugin.js +0 -5
  161. package/dist/webpack/babel.config.client.js +0 -1
  162. package/dist/webpack/babel.config.ssr.js +0 -1
  163. package/dist/webpack/base.babel.js +0 -7
  164. package/dist/webpack/development.client.babel.js +0 -10
  165. package/dist/webpack/production.client.babel.js +0 -4
  166. package/dist/webpack/production.ssr.babel.js +0 -8
  167. package/dist/webpack/scssParams.js +0 -9
@@ -1,6 +1,11 @@
1
1
  "use strict"
2
2
 
3
- const { makeProjectHelpers, findCatalystRoot } = require("../lib/helpers")
3
+ const {
4
+ makeProjectHelpers,
5
+ findCatalystRoot,
6
+ catalystGeneration,
7
+ VITE_RUNTIME_VERSION,
8
+ } = require("../lib/helpers")
4
9
 
5
10
  let _db
6
11
 
@@ -18,7 +23,7 @@ const MASTER_FLOWS = {
18
23
  step: 1,
19
24
  cmd: "catalyst start",
20
25
  label: "Start dev server",
21
- detail: "Starts webpack-dev-server + SSR Node server on NODE_SERVER_PORT. Hot reload enabled.",
26
+ detail: "Starts the Vite middleware-mode development server and Catalyst SSR server on NODE_SERVER_PORT. Hot reload and React Fast Refresh are enabled.",
22
27
  },
23
28
  {
24
29
  step: 2,
@@ -33,7 +38,7 @@ const MASTER_FLOWS = {
33
38
  step: 1,
34
39
  cmd: "catalyst build",
35
40
  label: "Production build",
36
- detail: "Runs webpack in production mode. Outputs to build/ (or OUTPUT_PATH from config). Includes SSR bundle + client chunks.",
41
+ detail: "Runs parallel Vite client and SSR builds. Outputs client assets to build/client, the renderer to build/server, Vite manifests under build/.vite, and offline runtime files at the build root.",
37
42
  },
38
43
  {
39
44
  step: 2,
@@ -48,7 +53,7 @@ const MASTER_FLOWS = {
48
53
  step: 1,
49
54
  cmd: "catalyst build",
50
55
  label: "Build",
51
- detail: "Production webpack build. Set BUILD_ENV=production in env or config.",
56
+ detail: "Production Vite client and SSR build. Set BUILD_ENV=production in env or config.",
52
57
  },
53
58
  {
54
59
  step: 2,
@@ -69,7 +74,7 @@ const MASTER_FLOWS = {
69
74
  step: 1,
70
75
  cmd: "catalyst build",
71
76
  label: "Build",
72
- detail: "Same webpack build — staging is config-only, not a different build target.",
77
+ detail: "Same Vite build — staging is config-only, not a different build target.",
73
78
  },
74
79
  {
75
80
  step: 2,
@@ -94,7 +99,7 @@ const MASTER_FLOWS = {
94
99
  },
95
100
  {
96
101
  step: 3,
97
- cmd: "npm run build:android",
102
+ cmd: "npm run buildApp:android",
98
103
  label: "Android debug build",
99
104
  detail: "Runs buildAppAndroid.js: validates ADB + emulator path from sdkPath, launches emulator (emulatorName), copies web assets to androidProject/, runs Gradle debug build, installs APK.",
100
105
  },
@@ -123,11 +128,11 @@ const MASTER_FLOWS = {
123
128
  step: 3,
124
129
  cmd: "catalyst build",
125
130
  label: "Build web assets",
126
- detail: "Production webpack build. Assets bundled into AAB.",
131
+ detail: "Production web build. Assets are consumed by the Android release build.",
127
132
  },
128
133
  {
129
134
  step: 4,
130
- cmd: "npm run build:android:release",
135
+ cmd: "npm run buildApp:android",
131
136
  label: "Android release build",
132
137
  detail: "Skips emulator validation. Runs Gradle release build. Calls buildAndroidAAB() — renames project, creates/verifies keystore, signs AAB. Output goes to ./deployment/.",
133
138
  },
@@ -144,19 +149,19 @@ const MASTER_FLOWS = {
144
149
  step: 1,
145
150
  cmd: null,
146
151
  label: "Pre-check: config",
147
- detail: 'Reads WEBVIEW_CONFIG.ios. Requires: appBundleId, simulatorName, buildType (default "debug").',
152
+ detail: "Reads WEBVIEW_CONFIG and WEBVIEW_CONFIG.ios. Confirm the development URL, appBundleId, simulatorName, plugins, and selected public/ios assets.",
148
153
  },
149
154
  {
150
155
  step: 2,
151
- cmd: "catalyst build",
152
- label: "Build web assets",
153
- detail: "Compiles web app. iOS build embeds these.",
156
+ cmd: "npm run buildApp:ios",
157
+ label: "iOS simulator build",
158
+ detail: "Generates native configuration and plugin code in the package-owned Xcode project, syncs selected assets, compiles with Xcode's Debug configuration, installs the .app, and launches it.",
154
159
  },
155
160
  {
156
161
  step: 3,
157
- cmd: "npm run build:ios",
158
- label: "iOS simulator build",
159
- detail: "Runs buildAppIos.js: generates ConfigConstants.swift from config (bundleId, URL, port, protocol), launches simulator (simulatorName), cleans Xcode artifacts, compiles with xcodebuild, installs .app, launches.",
162
+ cmd: null,
163
+ label: "Remote web application",
164
+ detail: "The iOS shell loads the configured remote URL. buildApp:ios does not bundle the full Catalyst web client, so the target web application must be reachable.",
160
165
  },
161
166
  {
162
167
  step: 4,
@@ -170,31 +175,89 @@ const MASTER_FLOWS = {
170
175
  {
171
176
  step: 1,
172
177
  cmd: null,
178
+ label: "Deploy the production web application",
179
+ detail: "Deploy the web application first and confirm its production URL is reachable over HTTPS. The iOS shell loads this remote URL; it does not embed the full web client bundle.",
180
+ },
181
+ {
182
+ step: 2,
183
+ cmd: null,
173
184
  label: "Pre-check: config",
174
- detail: 'buildType must be "Release" (capital R — case-sensitive). appBundleId required. If googleSignIn enabled, GoogleService-Info.plist must be present.',
185
+ detail: "Finalize WEBVIEW_CONFIG, appBundleId, app name, version, incremented build number, access-control rules, plugins, permissions, capabilities, icons, splash assets, and privacy declarations.",
175
186
  },
176
- { step: 2, cmd: "catalyst build", label: "Build web assets", detail: "Production build." },
177
187
  {
178
188
  step: 3,
179
- cmd: "npm run build:ios",
180
- label: "iOS release build",
181
- detail: "Same script — build type is driven by WEBVIEW_CONFIG.ios.buildType. Generates ConfigConstants.swift with production URL and bundleId. Xcode compiles Release scheme.",
189
+ cmd: "npm run buildApp:ios",
190
+ label: "Prepare the native project",
191
+ detail: "Run from the consuming Catalyst app root. This generates native configuration and plugin code, syncs selected assets, and performs a Debug native build. It does not create an App Store archive.",
182
192
  },
183
193
  {
184
194
  step: 4,
185
195
  cmd: null,
186
- label: "Archive + export IPA",
187
- detail: "Post-build: archive via Xcode Organizer or xcodebuild -exportArchive. Requires Apple distribution certificate + provisioning profile configured in Xcode.",
196
+ label: "Open the generated Xcode project",
197
+ detail: "Open node_modules/catalyst-core/dist/native/iosnativeWebView/iosnativeWebView.xcodeproj (or the resolved package equivalent). Confirm the iosnativeWebView scheme's Archive action uses Release.",
188
198
  },
189
199
  {
190
200
  step: 5,
191
201
  cmd: null,
192
- label: "App Store submission",
193
- detail: "Upload IPA via Transporter or Xcode Organizer. TestFlight for beta before release.",
202
+ label: "Configure signing and archive",
203
+ detail: "Select the correct Apple Developer team, distribution signing, capabilities, entitlements, bundle ID, version, and build. Choose a generic iOS device destination, then Product → Archive.",
204
+ },
205
+ {
206
+ step: 6,
207
+ cmd: null,
208
+ label: "Validate and upload",
209
+ detail: "In Xcode Organizer, run Validate App, then Distribute App → TestFlight & App Store and upload the build.",
210
+ },
211
+ {
212
+ step: 7,
213
+ cmd: null,
214
+ label: "Complete the release",
215
+ detail: "Wait for App Store Connect processing, test through TestFlight, complete store metadata and privacy disclosures, select the processed build, and submit it for App Review.",
194
216
  },
195
217
  ],
196
218
  }
197
219
 
220
+ const LEGACY_WEB_FLOWS = {
221
+ web_dev: [
222
+ {
223
+ step: 1,
224
+ cmd: "catalyst start",
225
+ label: "Start legacy dev server",
226
+ detail: "Starts the Catalyst 0.2.x webpack development and SSR servers with hot reload.",
227
+ },
228
+ {
229
+ step: 2,
230
+ cmd: null,
231
+ label: "Browser / WebView loads",
232
+ detail: "The browser or native WebView loads the configured development origin.",
233
+ },
234
+ ],
235
+ web_build: [
236
+ {
237
+ step: 1,
238
+ cmd: "catalyst build",
239
+ label: "Legacy production build",
240
+ detail: "Runs the Catalyst 0.2.x webpack build, including loadable metadata and SSR output.",
241
+ },
242
+ {
243
+ step: 2,
244
+ cmd: "catalyst serve",
245
+ label: "Serve legacy build",
246
+ detail: "Serves the webpack-era production output for smoke testing.",
247
+ },
248
+ ],
249
+ web_prod: null,
250
+ web_staging: null,
251
+ }
252
+ LEGACY_WEB_FLOWS.web_prod = MASTER_FLOWS.web_prod.map((step) => ({
253
+ ...step,
254
+ detail: step.detail.replace("Vite client and SSR", "legacy webpack"),
255
+ }))
256
+ LEGACY_WEB_FLOWS.web_staging = MASTER_FLOWS.web_staging.map((step) => ({
257
+ ...step,
258
+ detail: step.detail.replace("Vite", "legacy webpack"),
259
+ }))
260
+
198
261
  // ─── Architecture diagrams ───────────────────────────────────────────────────
199
262
 
200
263
  const MASTER_DIAGRAMS = {
@@ -293,18 +356,18 @@ const MASTER_DIAGRAMS = {
293
356
  layers: [
294
357
  {
295
358
  layer: "web",
296
- label: "Webpack (catalyst build)",
297
- detail: "Produces: build/public/ (client chunks), build/server.js (SSR bundle). Loadable-stats.json for code-splitting.",
359
+ label: "Vite (catalyst build)",
360
+ detail: "Runs client and SSR builds in parallel. Produces build/client, build/server, Vite manifests, categorized assets, and root offline runtime files.",
298
361
  },
299
362
  {
300
363
  layer: "prepare",
301
364
  label: "catalyst-core prepare",
302
- detail: "Compiles catalyst-core/src/ → dist/ via Babel. Copies src/native/ → dist/native/ (androidProject, iosnativeWebView, assets). This is the framework build, not the app build.",
365
+ detail: "Copies the ESM web runtime into dist and Babel-compiles native/CommonJS compatibility outputs. Package metadata, bin, and dist form one package contract.",
303
366
  },
304
367
  {
305
368
  layer: "copy",
306
369
  label: "Dev copy workflow",
307
- detail: "After prepare: copy catalyst-core/dist/ → test-app/node_modules/catalyst-core/. Also copy package.json (required for Node 20 exports map — ERR_PACKAGE_PATH_NOT_EXPORTED fix).",
370
+ detail: "After prepare, copy dist, bin, and package.json together. Copying only dist creates a mixed package with incompatible exports and CLI code.",
308
371
  },
309
372
  {
310
373
  layer: "native",
@@ -316,12 +379,11 @@ const MASTER_DIAGRAMS = {
316
379
  "[Framework dev] Edit catalyst-core/src/",
317
380
  "→ npm run prepare (in catalyst-core)",
318
381
  "→ dist/ updated",
319
- "→ Copy dist/ → test-app/node_modules/catalyst-core/",
320
- "→ Copy package.json → test-app/node_modules/catalyst-core/package.json",
382
+ "→ Replace test-app node_modules/catalyst-core dist + bin + package.json together",
321
383
  "",
322
384
  "[App build] In app project root:",
323
- "→ catalyst build (webpack, outputs build/)",
324
- "→ npm run build:android / build:ios",
385
+ "→ catalyst build (Vite client + SSR output)",
386
+ "→ npm run buildApp:android / buildApp:ios",
325
387
  "→ native build script reads WEBVIEW_CONFIG from config/config.json",
326
388
  "→ copies build/ assets into native project",
327
389
  "→ compiles native project (Gradle / xcodebuild)",
@@ -405,6 +467,33 @@ const MASTER_DIAGRAMS = {
405
467
  },
406
468
  }
407
469
 
470
+ const LEGACY_BUILD_PIPELINE = {
471
+ title: "Legacy Build Pipeline (Catalyst 0.2.x)",
472
+ description: "The webpack-era Catalyst build and native consumption flow.",
473
+ layers: [
474
+ {
475
+ layer: "web",
476
+ label: "Webpack",
477
+ detail: "Produces webpack client chunks, SSR output, and @loadable/component metadata.",
478
+ },
479
+ {
480
+ layer: "prepare",
481
+ label: "Babel prepare",
482
+ detail: "Compiles catalyst-core source into the legacy dist package.",
483
+ },
484
+ {
485
+ layer: "native",
486
+ label: "Native build",
487
+ detail: "buildApp:android and buildApp:ios consume the prepared web and native assets.",
488
+ },
489
+ ],
490
+ flow: [
491
+ "catalyst build (webpack)",
492
+ "→ catalyst serve for production-style validation",
493
+ "→ npm run buildApp:android or npm run buildApp:ios",
494
+ ],
495
+ }
496
+
408
497
  // ─── Helpers ─────────────────────────────────────────────────────────────────
409
498
 
410
499
  function getProjectContext(root) {
@@ -423,6 +512,7 @@ function getProjectContext(root) {
423
512
  iosBuildType: (wv.ios?.buildType || "debug").toLowerCase(),
424
513
  hasKeystore: !!wv.android?.keystoreConfig,
425
514
  hasGoogleSignIn: !!wv.googleSignIn?.enabled,
515
+ hasNotifications: !!wv.notifications?.enabled,
426
516
  hasEcosystem: fileExists("ecosystem.config.js"),
427
517
  port: wv.port,
428
518
  useHttps: !!wv.useHttps,
@@ -464,6 +554,14 @@ function handle_get_build_flow({ platform, mode, symptom } = {}) {
464
554
  }
465
555
 
466
556
  const ctx = getProjectContext(catalystRoot.dir)
557
+ const installedVersion = catalystRoot.installedVersion || catalystRoot.catalystVersion
558
+ const generation = catalystGeneration(installedVersion)
559
+ if (generation === "unknown") {
560
+ return {
561
+ error: "catalyst_version_required",
562
+ message: `Unable to determine whether this project targets legacy 0.2.x or current ${VITE_RUNTIME_VERSION}+. Confirm the target version before applying build guidance.`,
563
+ }
564
+ }
467
565
  const p = (platform || "web").toLowerCase()
468
566
  const m = (mode || "dev").toLowerCase() // dev | build | production | staging | release
469
567
 
@@ -538,7 +636,7 @@ function handle_get_build_flow({ platform, mode, symptom } = {}) {
538
636
  )
539
637
  }
540
638
 
541
- const isRelease = m === "release" || ctx.iosBuildType === "release"
639
+ const isRelease = m === "release"
542
640
  flow_key = isRelease ? "ios_release" : "ios_debug"
543
641
 
544
642
  if (!ctx.wv.ios?.appBundleId) {
@@ -554,13 +652,23 @@ function handle_get_build_flow({ platform, mode, symptom } = {}) {
554
652
  "googleSignIn.enabled=true but iosClientId may be missing — check WEBVIEW_CONFIG.googleSignIn.iosClientId."
555
653
  )
556
654
  }
557
- if (isRelease && ctx.iosBuildType !== "release") {
655
+ if (isRelease && !ctx.useHttps) {
656
+ warnings.push(
657
+ "WEBVIEW_CONFIG.useHttps is not enabled — the App Store flow requires a reachable HTTPS production web application."
658
+ )
659
+ }
660
+ if (isRelease && ctx.hasNotifications) {
558
661
  warnings.push(
559
- 'ios.buildType is not "Release" (case-sensitive). Release builds require exactly "Release" — not "release".'
662
+ "Push notifications are enabled — review the generated aps-environment entitlement and Release provisioning before archiving."
560
663
  )
561
664
  }
562
665
 
563
666
  notes.push(`buildType detected: ${ctx.wv.ios?.buildType || "not set (defaults to debug)"}`)
667
+ if (isRelease) {
668
+ notes.push(
669
+ "ios.buildType does not select the App Store build configuration; buildApp:ios still performs a Debug build. Archive the generated project with the scheme's Release action."
670
+ )
671
+ }
564
672
  if (ctx.wv.ios?.appBundleId) notes.push(`appBundleId: ${ctx.wv.ios.appBundleId}`)
565
673
  if (ctx.wv.ios?.simulatorName) notes.push(`simulatorName: ${ctx.wv.ios.simulatorName}`)
566
674
  if (ctx.hasGoogleSignIn) notes.push("googleSignIn: enabled")
@@ -578,7 +686,11 @@ function handle_get_build_flow({ platform, mode, symptom } = {}) {
578
686
  mode: flow_key,
579
687
  project_root: catalystRoot.dir,
580
688
  catalyst_version: catalystRoot.catalystVersion,
581
- steps: MASTER_FLOWS[flow_key],
689
+ catalyst_generation: generation,
690
+ steps:
691
+ generation === "legacy" && LEGACY_WEB_FLOWS[flow_key]
692
+ ? LEGACY_WEB_FLOWS[flow_key]
693
+ : MASTER_FLOWS[flow_key],
582
694
  project_config: notes,
583
695
  warnings: warnings.length ? warnings : undefined,
584
696
  related_errors: related_errors.length ? related_errors : undefined,
@@ -594,6 +706,7 @@ function handle_get_architecture_diagram({ feature, symptom } = {}) {
594
706
  }
595
707
 
596
708
  const ctx = getProjectContext(catalystRoot.dir)
709
+ const generation = catalystGeneration(catalystRoot.installedVersion || catalystRoot.catalystVersion)
597
710
 
598
711
  // Match feature to a diagram key
599
712
  const f = (feature || "").toLowerCase()
@@ -625,7 +738,17 @@ function handle_get_architecture_diagram({ feature, symptom } = {}) {
625
738
  }
626
739
  }
627
740
 
628
- const diagram = MASTER_DIAGRAMS[diagram_key]
741
+ if (diagram_key === "build_pipeline" && generation === "unknown") {
742
+ return {
743
+ error: "catalyst_version_required",
744
+ message: `Build architecture differs between legacy 0.2.x and current ${VITE_RUNTIME_VERSION}+. Confirm the target Catalyst version.`,
745
+ }
746
+ }
747
+
748
+ const diagram =
749
+ diagram_key === "build_pipeline" && generation === "legacy"
750
+ ? LEGACY_BUILD_PIPELINE
751
+ : MASTER_DIAGRAMS[diagram_key]
629
752
 
630
753
  // ── Annotate with project-specific context ────────────────────────────────
631
754
  const project_context = []
@@ -671,6 +794,7 @@ function handle_get_architecture_diagram({ feature, symptom } = {}) {
671
794
 
672
795
  return {
673
796
  feature,
797
+ catalyst_generation: generation,
674
798
  matched_diagram: diagram_key,
675
799
  title: diagram.title,
676
800
  description: diagram.description,
@@ -1,7 +1,12 @@
1
1
  "use strict"
2
2
  const fs = require("fs")
3
3
  const path = require("path")
4
- const { makeProjectHelpers, versionOlderThan } = require("../lib/helpers")
4
+ const {
5
+ makeProjectHelpers,
6
+ versionOlderThan,
7
+ catalystGeneration,
8
+ VITE_RUNTIME_VERSION,
9
+ } = require("../lib/helpers")
5
10
 
6
11
  // Tasks that require a minimum catalyst-core version.
7
12
  // Key = task ID, value = { minVersion, reason, upgradeNote }
@@ -35,6 +40,7 @@ function handle_get_conversion_status({ project_path, include_not_applicable = f
35
40
 
36
41
  // ── Version gate: read installed catalyst-core version ────────────────────
37
42
  const installedVersion = _projectInfo.installedVersion || null
43
+ const generation = catalystGeneration(installedVersion)
38
44
 
39
45
  // ── Load project state once ────────────────────────────────────────────────
40
46
  const config = readJson("config/config.json")
@@ -78,14 +84,36 @@ function handle_get_conversion_status({ project_path, include_not_applicable = f
78
84
  },
79
85
 
80
86
  T2_ROUTER_DEP: () => {
81
- if (!allDeps["@tata1mg/router"])
87
+ if (generation === "unknown")
88
+ return {
89
+ status: "needs_review",
90
+ native_risk: "Router ownership differs between Catalyst 0.2.x and 0.3.x.",
91
+ reason: `Unable to determine the installed catalyst-core version. Confirm whether the target is legacy 0.2.x or current ${VITE_RUNTIME_VERSION}+ before changing router dependencies.`,
92
+ review_context: {
93
+ question: "Which catalyst-core version is this project targeting?",
94
+ what_correct_looks_like:
95
+ "0.2.x uses @tata1mg/router; 0.3.x+ removes it and imports Catalyst router APIs from catalyst-core.",
96
+ what_gap_looks_like:
97
+ "Router dependencies and imports are mixed across runtime generations.",
98
+ },
99
+ }
100
+ if (generation === "legacy") {
101
+ if (!allDeps["@tata1mg/router"])
102
+ return {
103
+ status: "gap",
104
+ native_risk: "Catalyst 0.2.x requires its external router package for SSR routing.",
105
+ reason: "Legacy Catalyst detected but @tata1mg/router is missing",
106
+ }
107
+ return { status: "completed", note: "Legacy 0.2.x external router dependency detected." }
108
+ }
109
+ if (allDeps["@tata1mg/router"])
82
110
  return {
83
111
  status: "gap",
84
112
  native_risk:
85
- "react-router-dom does not support SSR + hydration required by catalyst-core. App routing will break on native.",
86
- reason: "@tata1mg/router not in package.json dependencies",
113
+ "Catalyst 0.3.x owns the router implementation. Keeping @tata1mg/router can install a second routing runtime and produce incompatible React elements.",
114
+ reason: "Remove @tata1mg/router and import router APIs from catalyst-core",
87
115
  }
88
- return { status: "completed" }
116
+ return { status: "completed", note: "Current 0.3.x integrated router contract detected." }
89
117
  },
90
118
 
91
119
  T3_ROUTES_FILE: () => {
@@ -111,6 +139,38 @@ function handle_get_conversion_status({ project_path, include_not_applicable = f
111
139
  return { status: "completed" }
112
140
  },
113
141
 
142
+ T2b_RUNTIME_DEPS: () => {
143
+ if (generation !== "current")
144
+ return {
145
+ status: generation === "legacy" ? "completed" : "needs_review",
146
+ reason:
147
+ generation === "legacy"
148
+ ? "Legacy 0.2.x dependency contract retained."
149
+ : "Catalyst version is unknown; do not change React versions until the target is confirmed.",
150
+ native_risk:
151
+ generation === "unknown"
152
+ ? "Applying React 19 requirements to an unknown Catalyst runtime can break SSR."
153
+ : undefined,
154
+ review_context:
155
+ generation === "unknown"
156
+ ? { question: "Is this project staying on 0.2.x or targeting 0.3.x?" }
157
+ : undefined,
158
+ }
159
+ const invalid = []
160
+ if (allDeps.react !== "19.0.0") invalid.push(`react=${allDeps.react || "missing"}`)
161
+ if (allDeps["react-dom"] !== "19.0.0")
162
+ invalid.push(`react-dom=${allDeps["react-dom"] || "missing"}`)
163
+ if (allDeps["@loadable/component"]) invalid.push("@loadable/component is installed")
164
+ if (invalid.length)
165
+ return {
166
+ status: "gap",
167
+ native_risk:
168
+ "Mixed React or legacy loadable runtimes can cause invalid React child, hook, or hydration failures.",
169
+ reason: invalid.join(", "),
170
+ }
171
+ return { status: "completed" }
172
+ },
173
+
114
174
  T4_DATA_FETCHING: () => {
115
175
  const useEffectFiles = grepSrc(
116
176
  /useEffect.*fetch|useEffect.*axios|useEffect.*\.get\(|useEffect.*\.post\(/
@@ -198,6 +258,40 @@ function handle_get_conversion_status({ project_path, include_not_applicable = f
198
258
  "Client entry files are required for hydration. Without them the native WebView loads server HTML but JS never hydrates — app is non-interactive.",
199
259
  reason: `Missing: ${missing.join(", ")}`,
200
260
  }
261
+ const clientEntry = readText("client/index.js") || ""
262
+ if (generation === "current" && /@loadable\/component|loadableReady/.test(clientEntry))
263
+ return {
264
+ status: "gap",
265
+ native_risk:
266
+ "Catalyst 0.3.x uses its Vite split hydration contract; loadableReady belongs to the legacy webpack runtime.",
267
+ reason: "Replace loadableReady with hydrationReady from catalyst-core",
268
+ }
269
+ return { status: "completed" }
270
+ },
271
+
272
+ T7b_NATIVE_SCRIPTS: () => {
273
+ const scripts = pkg.scripts || {}
274
+ const required = [
275
+ "buildApp",
276
+ "buildApp:ios",
277
+ "buildApp:android",
278
+ "setupEmulator",
279
+ "setupEmulator:ios",
280
+ "setupEmulator:android",
281
+ ]
282
+ const missing = required.filter((name) => !scripts[name])
283
+ if (missing.length)
284
+ return {
285
+ status: "gap",
286
+ native_risk: `Native Catalyst commands are unavailable: ${missing.join(", ")}.`,
287
+ reason: `Missing package scripts: ${missing.join(", ")}`,
288
+ }
289
+ if (generation === "current" && (scripts.devBuild || scripts.devServe))
290
+ return {
291
+ status: "gap",
292
+ native_risk: "devBuild and devServe were removed from the Catalyst 0.3.x CLI.",
293
+ reason: "Remove devBuild/devServe and use start for development or build + serve for production",
294
+ }
201
295
  return { status: "completed" }
202
296
  },
203
297
 
@@ -657,6 +751,13 @@ function handle_get_conversion_status({ project_path, include_not_applicable = f
657
751
  project: pkg.name || root,
658
752
  scanned_at: new Date().toISOString(),
659
753
  catalyst_core_version: installedVersion || "unknown",
754
+ catalyst_generation: generation,
755
+ guidance:
756
+ generation === "unknown"
757
+ ? `Specify a target Catalyst version before applying router, build, or hydration changes. Current Vite guidance starts at ${VITE_RUNTIME_VERSION}.`
758
+ : generation === "legacy"
759
+ ? "Using legacy Catalyst 0.2.x webpack/router guidance. Request an upgrade plan explicitly to target 0.3.x."
760
+ : "Using current Catalyst 0.3.x Vite/integrated-router guidance.",
660
761
  project_context,
661
762
  ...(versionBanner ? { version_warning: versionBanner } : {}),
662
763
  summary: {
@@ -2,7 +2,7 @@
2
2
 
3
3
  const fs = require("fs")
4
4
  const path = require("path")
5
- const { findCatalystRoot } = require("../lib/helpers")
5
+ const { findCatalystRoot, catalystGeneration } = require("../lib/helpers")
6
6
  const conversion = require("./conversion")
7
7
 
8
8
  let _db
@@ -597,33 +597,34 @@ function appendToMdFindings(projectRoot, slug, finding) {
597
597
 
598
598
  // Commands that are verified to exist in catalyst-core projects
599
599
  const VALID_COMMANDS = new Set([
600
- "npm run build:android",
601
- "npm run build:android:release",
602
- "npm run build:ios",
600
+ "npm run start",
601
+ "npm run build",
602
+ "npm run serve",
603
603
  "npm run buildApp:android",
604
604
  "npm run buildApp:ios",
605
- "npm run buildApp:android:release",
606
- "npm run buildApp:ios:release",
607
605
  "npm run setupEmulator:android",
608
606
  "npm run setupEmulator:ios",
609
- "npm run devBuild",
610
- "npm run devServe",
611
607
  "npm run prepare",
612
608
  "node .catalyst/mcp/setup.js",
613
609
  ])
614
610
 
615
- function validateStepCommands(steps) {
611
+ function validateStepCommands(steps, generation) {
612
+ const validCommands = new Set(VALID_COMMANDS)
613
+ if (generation === "legacy") {
614
+ validCommands.add("npm run devBuild")
615
+ validCommands.add("npm run devServe")
616
+ }
616
617
  const invalid = []
617
618
  for (const s of steps) {
618
619
  const text = `${typeof s === "string" ? s : (s.title || "") + " " + (s.detail || "")}`
619
620
  const cmds = text.match(/npm [\w:]+(?:\s[\w:]+)?|npx [\w@/-]+|node [\w./]+/g) || []
620
621
  for (const cmd of cmds) {
621
- if (!VALID_COMMANDS.has(cmd)) {
622
+ if (!validCommands.has(cmd)) {
622
623
  invalid.push(cmd)
623
624
  }
624
625
  }
625
626
  }
626
- return invalid
627
+ return { invalid, validCommands }
627
628
  }
628
629
 
629
630
  function handle_create_task_plan({ goal, steps: customSteps } = {}) {
@@ -650,13 +651,16 @@ function handle_create_task_plan({ goal, steps: customSteps } = {}) {
650
651
 
651
652
  if (customSteps && Array.isArray(customSteps) && customSteps.length) {
652
653
  // Validate any commands in custom steps against known catalyst commands
653
- const invalidCmds = validateStepCommands(customSteps)
654
+ const { invalid: invalidCmds, validCommands } = validateStepCommands(
655
+ customSteps,
656
+ catalystGeneration(catalystRoot.installedVersion || catalystRoot.catalystVersion)
657
+ )
654
658
  if (invalidCmds.length > 0) {
655
659
  return {
656
660
  error: "invalid_commands_in_steps",
657
- message: `Steps contain commands that do not exist in catalyst-core projects: ${invalidCmds.join(", ")}. Do not invent commands. Valid catalyst commands are: ${[...VALID_COMMANDS].join(", ")}. For conversion/migration goals, omit steps entirely — auto-generation runs live file detection and builds accurate steps.`,
661
+ message: `Steps contain commands that do not exist for this catalyst-core generation: ${invalidCmds.join(", ")}. Do not invent commands. Valid commands are: ${[...validCommands].join(", ")}. For conversion/migration goals, omit steps entirely so live detection can generate version-aware steps.`,
658
662
  invalid_commands: invalidCmds,
659
- valid_commands: [...VALID_COMMANDS],
663
+ valid_commands: [...validCommands],
660
664
  }
661
665
  }
662
666
  steps = customSteps.map((s, i) => ({