catalyst-core 0.2.0-beta.2 → 0.3.0-beta.1

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 (184) 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/index.jsx +8 -0
  6. package/dist/logger.js +74 -3
  7. package/dist/native/androidProject/app/build.gradle.kts +1 -0
  8. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/CustomWebview.kt +143 -4
  9. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MainActivity.kt +26 -6
  10. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MetricsMonitor.kt +143 -17
  11. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeBridge.kt +6 -0
  12. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/WebCacheManager.kt +26 -0
  13. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/BridgeUtils.kt +56 -1
  14. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/KeyboardUtil.kt +48 -8
  15. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/PerfDeliveryState.kt +36 -0
  16. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/PerfEventBuffer.kt +289 -0
  17. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/ProfilerNavigationState.kt +13 -0
  18. package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/ProfilerLifecycleTest.kt +51 -0
  19. package/dist/native/androidSetup.js +300 -8
  20. package/dist/native/bridge/WebBridge.js +481 -59
  21. package/dist/native/bridge/constants/NativeInterfaces.js +290 -44
  22. package/dist/native/bridge/errors.js +250 -26
  23. package/dist/native/bridge/hooks/index.js +125 -1
  24. package/dist/native/bridge/hooks/useCamera.js +347 -9
  25. package/dist/native/bridge/hooks/useDataProtection.js +200 -2
  26. package/dist/native/bridge/hooks/useDeviceInfo.js +71 -2
  27. package/dist/native/bridge/hooks/useFilePicker.js +429 -2
  28. package/dist/native/bridge/hooks/useGoogleSignIn.js +81 -1
  29. package/dist/native/bridge/hooks/useHapticFeedback.js +196 -1
  30. package/dist/native/bridge/hooks/useIntent.js +95 -1
  31. package/dist/native/bridge/hooks/useNativeTransition.js +202 -27
  32. package/dist/native/bridge/hooks/useNetworkStatus.js +84 -3
  33. package/dist/native/bridge/hooks/useNotification.js +318 -2
  34. package/dist/native/bridge/hooks/useSafeArea.js +84 -2
  35. package/dist/native/bridge/hooks/useVideoStream.js +434 -6
  36. package/dist/native/bridge/hooks/utils.js +27 -1
  37. package/dist/native/bridge/hooks.js +16 -1
  38. package/dist/native/bridge/perf/collectors/ApiCollector.js +85 -0
  39. package/dist/native/bridge/perf/collectors/CacheCollector.js +215 -0
  40. package/dist/native/bridge/perf/collectors/HookCollector.js +165 -0
  41. package/dist/native/bridge/perf/collectors/InsightsCollector.js +505 -0
  42. package/dist/native/bridge/perf/collectors/InteractionCollector.js +273 -0
  43. package/dist/native/bridge/perf/collectors/KeyboardCollector.js +124 -0
  44. package/dist/native/bridge/perf/collectors/NavigationCollector.js +294 -0
  45. package/dist/native/bridge/perf/collectors/NetworkTimingCollector.js +183 -0
  46. package/dist/native/bridge/perf/collectors/RenderCollector.js +284 -0
  47. package/dist/native/bridge/perf/collectors/ScrollCollector.js +111 -0
  48. package/dist/native/bridge/perf/collectors/ThreadCollector.js +111 -0
  49. package/dist/native/bridge/perf/core/constants.js +126 -0
  50. package/dist/native/bridge/perf/core/measure.js +189 -0
  51. package/dist/native/bridge/perf/core/session.js +100 -0
  52. package/dist/native/bridge/perf/core/store.js +554 -0
  53. package/dist/native/bridge/perf/core/summary.js +174 -0
  54. package/dist/native/bridge/perf/core/traceExport.js +240 -0
  55. package/dist/native/bridge/perf/core/waterfalls.js +146 -0
  56. package/dist/native/bridge/perf/index.js +402 -0
  57. package/dist/native/bridge/safeArea.js +53 -5
  58. package/dist/native/bridge/standardizedHooks.js +595 -82
  59. package/dist/native/bridge/useBaseHook.js +274 -38
  60. package/dist/native/bridge/utils/CameraUtils.js +201 -56
  61. package/dist/native/bridge/utils/FileObjectConverter.js +129 -18
  62. package/dist/native/bridge/utils/NativeBridge.js +425 -141
  63. package/dist/native/buildAndroid/assets.js +510 -13
  64. package/dist/native/buildAndroid/build.js +296 -19
  65. package/dist/native/buildAndroid/config.js +87 -1
  66. package/dist/native/buildAndroid/index.js +374 -1
  67. package/dist/native/buildAppAndroid.js +34 -2
  68. package/dist/native/buildAppIos.js +62 -2
  69. package/dist/native/buildIos/assets.js +609 -8
  70. package/dist/native/buildIos/build.js +639 -20
  71. package/dist/native/buildIos/config.js +294 -12
  72. package/dist/native/buildIos/index.js +343 -6
  73. package/dist/native/buildIos/plugins.js +343 -16
  74. package/dist/native/internal-plugins/device-info-plugin/android/DeviceInfoPlugin.kt +43 -0
  75. package/dist/native/internal-plugins/device-info-plugin/ios/DeviceInfoPlugin.swift +28 -0
  76. package/dist/native/internal-plugins/device-info-plugin/manifest.json +19 -0
  77. package/dist/native/internalPluginUtils.js +232 -7
  78. package/dist/native/iosnativeWebView/Sources/Core/Constants/CatalystConstants.swift +19 -0
  79. package/dist/native/iosnativeWebView/Sources/Core/Constants/ConfigConstants.swift +4 -0
  80. package/dist/native/iosnativeWebView/Sources/Core/Utils/BootTimingUtility.swift +5 -1
  81. package/dist/native/iosnativeWebView/Sources/Core/Utils/CacheManager.swift +10 -0
  82. package/dist/native/iosnativeWebView/Sources/Core/Utils/DisplayLinkPerfMonitor.swift +89 -0
  83. package/dist/native/iosnativeWebView/Sources/Core/Utils/PerfEventBuffer.swift +373 -0
  84. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeFileHandler.swift +35 -1
  85. package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeMessageValidator.swift +24 -11
  86. package/dist/native/iosnativeWebView/Sources/Core/WebView/NativeBridge.swift +9 -0
  87. package/dist/native/iosnativeWebView/Sources/Core/WebView/WebView.swift +126 -0
  88. package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewNavigationDelegate.swift +75 -1
  89. package/dist/native/iosnativeWebView/iosnativeWebViewTests/BridgeMessageValidatorTests.swift +13 -0
  90. package/dist/native/package.json +3 -0
  91. package/dist/native/plugin-bridge/PluginBridge.js +227 -1
  92. package/dist/native/pluginComposerAndroid.js +407 -23
  93. package/dist/native/pluginComposerIos.js +435 -11
  94. package/dist/native/renameAndroidProject.js +1094 -88
  95. package/dist/native/setupEmulatorIos.js +289 -22
  96. package/dist/native/setupServer.js +160 -19
  97. package/dist/native/terminalProgress.js +199 -11
  98. package/dist/native/utils.js +193 -15
  99. package/dist/offline/catalyst-sw.js +145 -1
  100. package/dist/offline/registerServiceWorker.js +33 -1
  101. package/dist/otel.js +375 -46
  102. package/dist/router/ClientRouter.js +14 -2
  103. package/dist/router/ServerRouter.js +9 -1
  104. package/dist/router.js +1 -1
  105. package/dist/scripts/build.js +112 -3
  106. package/dist/scripts/checkVersion.js +3 -1
  107. package/dist/scripts/cleanCache.js +30 -1
  108. package/dist/scripts/generateOfflineManifest.js +116 -1
  109. package/dist/scripts/loadEnvironmentVariables.js +32 -6
  110. package/dist/scripts/plugins.js +309 -1
  111. package/dist/scripts/preServerInit.js +13 -0
  112. package/dist/scripts/scriptUtils.js +54 -3
  113. package/dist/scripts/serve.js +51 -4
  114. package/dist/scripts/start.js +47 -10
  115. package/dist/scripts/validator.js +149 -1
  116. package/dist/sentry.cjs +127 -0
  117. package/dist/sentry.js +125 -5
  118. package/dist/server/expressServer.js +250 -5
  119. package/dist/server/manifestCache.js +36 -0
  120. package/dist/server/renderer/ChunkExtractor.js +144 -0
  121. package/dist/server/renderer/document/Body.jsx +59 -0
  122. package/dist/server/renderer/document/FastRefresh.jsx +20 -0
  123. package/dist/server/renderer/document/Head.jsx +60 -0
  124. package/dist/server/renderer/document/index.jsx +2 -0
  125. package/dist/server/renderer/extract.js +149 -31
  126. package/dist/server/renderer/handler.jsx +433 -0
  127. package/dist/server/renderer/index.js +8 -1
  128. package/dist/server/renderer/render.js +47 -0
  129. package/dist/server/utils/botDetectionMiddleware.js +29 -0
  130. package/dist/server/utils/cjsRequire.js +10 -0
  131. package/dist/server/utils/userAgentUtil.js +87 -9
  132. package/dist/server/utils/validator.js +164 -1
  133. package/dist/vite/FastRefresh.jsx +20 -0
  134. package/dist/vite/inject-cache-key-plugin.js +276 -0
  135. package/dist/vite/loadCustomViteConfig.js +22 -0
  136. package/dist/vite/manifest-categorization-plugin.js +455 -0
  137. package/dist/vite/node-loader.mjs +458 -0
  138. package/dist/vite/scssParams.js +21 -0
  139. package/dist/vite/vite.config.client.js +130 -0
  140. package/dist/vite/vite.config.js +422 -0
  141. package/dist/vite/vite.config.server.js +84 -0
  142. package/dist/web-router/components/MetaTag.jsx +34 -0
  143. package/dist/web-router/components/RouterDataProvider.jsx +332 -0
  144. package/dist/web-router/components/Split.jsx +200 -0
  145. package/dist/web-router/components/SplitInview.jsx +106 -0
  146. package/dist/web-router/components/SsrRequestContext.jsx +14 -0
  147. package/dist/web-router/context.jsx +12 -0
  148. package/dist/web-router/hooks.jsx +72 -0
  149. package/dist/web-router/types/components/MetaTag.d.ts +2 -0
  150. package/dist/web-router/types/components/RouterDataProvider.d.ts +95 -0
  151. package/dist/web-router/types/context.d.ts +14 -0
  152. package/dist/web-router/types/hooks.d.ts +1 -0
  153. package/dist/web-router/types/index.d.ts +3 -0
  154. package/dist/web-router/types/utils/metaDataUtils.d.ts +24 -0
  155. package/dist/web-router/utils/metaDataUtils.jsx +119 -0
  156. package/mcp_v2/conversion-tasks.json +35 -17
  157. package/mcp_v2/knowledge-base.json +124 -13
  158. package/mcp_v2/lib/helpers.js +10 -0
  159. package/mcp_v2/mcp.js +4 -4
  160. package/mcp_v2/package.json +1 -0
  161. package/mcp_v2/tools/build.js +116 -20
  162. package/mcp_v2/tools/conversion.js +106 -5
  163. package/mcp_v2/tools/tasks.js +18 -14
  164. package/package.json +35 -68
  165. package/babel.config.js +0 -32
  166. package/dist/index.js +0 -1
  167. package/dist/scripts/devBuild.js +0 -3
  168. package/dist/scripts/devServe.js +0 -3
  169. package/dist/scripts/loadScriptsBeforeServerStarts.js +0 -4
  170. package/dist/scripts/registerAliases.js +0 -6
  171. package/dist/server/renderer/document/Body.js +0 -11
  172. package/dist/server/renderer/document/Head.js +0 -9
  173. package/dist/server/renderer/document/index.js +0 -1
  174. package/dist/server/renderer/handler.js +0 -47
  175. package/dist/server/startServer.js +0 -57
  176. package/dist/webpack/babel-plugins/remove-client.plugin.js +0 -5
  177. package/dist/webpack/babel-plugins/remove-ssr.plugin.js +0 -5
  178. package/dist/webpack/babel.config.client.js +0 -1
  179. package/dist/webpack/babel.config.ssr.js +0 -1
  180. package/dist/webpack/base.babel.js +0 -7
  181. package/dist/webpack/development.client.babel.js +0 -10
  182. package/dist/webpack/production.client.babel.js +0 -4
  183. package/dist/webpack/production.ssr.babel.js +0 -8
  184. package/dist/webpack/scssParams.js +0 -9
@@ -0,0 +1,422 @@
1
+ import { defineConfig, transformWithEsbuild } from "vite"
2
+ import react from "@vitejs/plugin-react"
3
+ import svgr from "vite-plugin-svgr"
4
+ import { builtinModules } from "node:module"
5
+
6
+ /**
7
+ * Treat all .scss imports as CSS modules (webpack compat).
8
+ * Webpack's css-loader with modules:true scopes every .scss file.
9
+ * Vite only does this for files named .module.scss.
10
+ * This plugin renames the resolved ID so Vite's CSS pipeline treats them as modules.
11
+ */
12
+ function scssModulesPlugin() {
13
+ return {
14
+ name: "vite-plugin-scss-as-modules",
15
+ enforce: "pre",
16
+ async resolveId(source, importer, options) {
17
+ if (!importer) return null
18
+
19
+ if (!source.endsWith(".scss") || source.includes(".module.")) return null
20
+
21
+ const resolved = await this.resolve(source, importer, { ...options, skipSelf: true })
22
+ if (!resolved || resolved.id.includes("node_modules") || resolved.id.includes("src/static/css"))
23
+ return null
24
+
25
+ return resolved.id.replace(/\.scss$/, ".module.scss")
26
+ },
27
+ load(id) {
28
+ const cleanId = id.split("?")[0]
29
+ if (cleanId.endsWith(".module.scss") && !fs.existsSync(cleanId)) {
30
+ const originalPath = cleanId.replace(/\.module\.scss$/, ".scss")
31
+ if (fs.existsSync(originalPath)) {
32
+ this.addWatchFile(originalPath)
33
+ return fs.readFileSync(originalPath, "utf-8")
34
+ }
35
+ }
36
+ return null
37
+ },
38
+ handleHotUpdate({ file, server }) {
39
+ if (file.endsWith(".scss") && !file.endsWith(".module.scss")) {
40
+ const virtualId = file.replace(/\.scss$/, ".module.scss")
41
+ const virtualMod = server.moduleGraph.getModuleById(virtualId)
42
+ if (virtualMod) {
43
+ server.moduleGraph.invalidateModule(virtualMod)
44
+ return [virtualMod]
45
+ }
46
+ }
47
+ },
48
+ }
49
+ }
50
+
51
+ function jsxInJsPlugin() {
52
+ return {
53
+ name: "vite-plugin-jsx-in-js",
54
+ enforce: "pre",
55
+ async transform(code, id) {
56
+ if (!id.endsWith(".js")) return null
57
+ if (id.includes("node_modules")) return null
58
+ if (!/</.test(code)) return null
59
+ return transformWithEsbuild(code, id, { loader: "jsx" })
60
+ },
61
+ }
62
+ }
63
+
64
+ const emptyStoreModuleId = "\0catalyst-empty-store"
65
+ const templateStoreImport = "@catalyst/template/src/js/store/index.js"
66
+
67
+ function optionalTemplateStorePlugin() {
68
+ return {
69
+ name: "vite-plugin-optional-template-store",
70
+ enforce: "pre",
71
+ resolveId(source) {
72
+ const storePath = path.join(process.env.src_path, "src/js/store/index.js")
73
+ const isTemplateStoreImport = source === templateStoreImport || path.resolve(source) === storePath
74
+ if (!isTemplateStoreImport) return null
75
+ if (fs.existsSync(storePath)) return null
76
+
77
+ return emptyStoreModuleId
78
+ },
79
+ load(id) {
80
+ if (id !== emptyStoreModuleId) return null
81
+
82
+ return `
83
+ export default function configureStore(initialState = {}) {
84
+ return {
85
+ getState: () => initialState,
86
+ dispatch: (action) => action,
87
+ subscribe: () => () => {},
88
+ replaceReducer: () => {},
89
+ }
90
+ }
91
+ `
92
+ },
93
+ }
94
+ }
95
+
96
+ import { fileURLToPath } from "url"
97
+ import { dirname } from "path"
98
+ const __filename = fileURLToPath(import.meta.url)
99
+ const __dirname = dirname(__filename)
100
+
101
+ import path from "path"
102
+ import fs from "fs"
103
+
104
+ const packageJsonConfig = path.resolve(process.env.src_path, "package.json")
105
+ const catalystPackageJsonConfig = path.resolve(__dirname, "../../package.json")
106
+
107
+ let packageJsonContent, catalystPackageJsonContent
108
+ let _moduleAliases = {},
109
+ catalyst_moduleAliases = {}
110
+
111
+ try {
112
+ packageJsonContent = fs.readFileSync(packageJsonConfig, "utf8")
113
+ const packageJson = JSON.parse(packageJsonContent)
114
+ _moduleAliases = packageJson._moduleAliases || {}
115
+ } catch (error) {
116
+ console.warn(`Failed to read or parse package.json from ${packageJsonConfig}:`, error.message)
117
+ }
118
+
119
+ try {
120
+ catalystPackageJsonContent = fs.readFileSync(catalystPackageJsonConfig, "utf8")
121
+ const catalystPackageJson = JSON.parse(catalystPackageJsonContent)
122
+ catalyst_moduleAliases = catalystPackageJson._moduleAliases || {}
123
+ } catch (error) {
124
+ console.warn(
125
+ `Failed to read or parse catalyst package.json from ${catalystPackageJsonConfig}:`,
126
+ error.message
127
+ )
128
+ }
129
+
130
+ const allAliases = { ..._moduleAliases, ...catalyst_moduleAliases }
131
+
132
+ import { imageUrl, fontUrl } from "./scssParams.js"
133
+
134
+ const alias = () => {
135
+ if (!allAliases || typeof allAliases !== "object") {
136
+ return {}
137
+ }
138
+
139
+ return Object.keys(allAliases).reduce((moduleEnvMap, alias) => {
140
+ if (allAliases[alias] && typeof allAliases[alias] === "string") {
141
+ try {
142
+ const aliasPath = path.join(process.env.src_path, ...allAliases[alias].split("/"))
143
+ moduleEnvMap[alias] = aliasPath
144
+ } catch (error) {
145
+ console.warn(`Failed to configure alias ${alias}:`, error.message)
146
+ }
147
+ }
148
+ return moduleEnvMap
149
+ }, {})
150
+ }
151
+
152
+ export const getClientEnvVariables = () => {
153
+ const clientEnvVars = process.env.CLIENT_ENV_VARIABLES
154
+
155
+ if (!clientEnvVars) {
156
+ return {}
157
+ }
158
+
159
+ // Parse CLIENT_ENV_VARIABLES if it's a JSON string
160
+ const allowedVars = typeof clientEnvVars === "string" ? JSON.parse(clientEnvVars) : clientEnvVars
161
+
162
+ // Create define object with only allowed environment variables
163
+ const envVarDefinitions = {}
164
+
165
+ allowedVars.forEach((varName) => {
166
+ if (process.env[varName] !== undefined) {
167
+ // Define as process.env.VARIABLE_NAME for client-side usage
168
+ envVarDefinitions[`process.env.${varName}`] = JSON.stringify(process.env[varName])
169
+ }
170
+ })
171
+ envVarDefinitions[`process.env.src_path`] = JSON.stringify(process.env["src_path"])
172
+ envVarDefinitions[`process.env.BUILD_OUTPUT_PATH`] = JSON.stringify(process.env["BUILD_OUTPUT_PATH"])
173
+ envVarDefinitions[`process.env.PUBLIC_STATIC_ASSET_PATH`] = JSON.stringify(
174
+ process.env["PUBLIC_STATIC_ASSET_PATH"]
175
+ )
176
+ envVarDefinitions[`process.env.PUBLIC_STATIC_ASSET_URL`] = JSON.stringify(
177
+ process.env["PUBLIC_STATIC_ASSET_URL"]
178
+ )
179
+
180
+ return envVarDefinitions
181
+ }
182
+
183
+ const isProduction = process.env.NODE_ENV === "production"
184
+
185
+ const getScssResourcesImport = () => {
186
+ const resourcesDir = path.join(process.env.src_path, "src/static/css/resources")
187
+ const indexPath = path.join(resourcesDir, "index.scss")
188
+ const variablesPath = path.join(resourcesDir, "_variables.scss")
189
+
190
+ if (fs.existsSync(indexPath)) {
191
+ return '@import "@css/resources/index.scss"; '
192
+ }
193
+
194
+ if (fs.existsSync(variablesPath)) {
195
+ return '@import "@css/resources/_variables.scss"; '
196
+ }
197
+
198
+ return ""
199
+ }
200
+
201
+ // Pre-bundling upfront avoids Vite discovering deps at runtime which causes
202
+ // cascading full-page reloads and "stuck in loading" on dev server.
203
+ const browserOptimizeDeps = [
204
+ "react",
205
+ "react-dom",
206
+ "react-dom/client",
207
+ "react-redux",
208
+ "react-router-dom",
209
+ "redux",
210
+ "redux-thunk",
211
+ "axios",
212
+ "react-helmet-async",
213
+ "react-google-recaptcha",
214
+ "react-fast-compare",
215
+ "history",
216
+ "lottie-web",
217
+ // Pre-bundle alongside React so esbuild marks react/react-router as external
218
+ // and avoids a duplicate React instance (which causes useContext null errors)
219
+ "@tata1mg/slowboi-react",
220
+ "invariant",
221
+ "shallowequal",
222
+ "prop-types",
223
+ "redux-logger",
224
+ "framer-motion",
225
+ "recharts",
226
+ "react-modal",
227
+ "react-datepicker",
228
+ "react-intersection-observer",
229
+ "react-markdown",
230
+ "react-lottie",
231
+ "isomorphic-dompurify",
232
+ "ua-parser-js",
233
+ "qrcode.react",
234
+ "fast-average-color",
235
+ "react-dfp",
236
+ "web-vitals",
237
+ // Referenced by manualChunks in vite.config.client.js — pre-bundle so the
238
+ // first navigation that pulls them in doesn't trigger a full-page reload.
239
+ "react-loadable-visibility",
240
+ "react-detect-offline",
241
+ "react-side-effect",
242
+ "react-async-script",
243
+ "normalize.css",
244
+ ]
245
+
246
+ // Node-only / instrumentation dependencies that must never be bundled into the
247
+ // SSR output. OpenTelemetry is opt-in (enabled at runtime via OTEL_ENABLE), so
248
+ // these packages may not be installed in the consuming app. They are imported
249
+ // only by dist/otel.js, which is itself dynamically imported at runtime and only
250
+ // when OTEL_ENABLE=true (see server/renderer/handler.jsx). Marking them external
251
+ // lets the bundler skip resolving them; Node resolves them at runtime, but only
252
+ // if/when the otel chunk is actually loaded.
253
+ export const nodeOnlyExternalDeps = [
254
+ "elastic-apm-node",
255
+ "@grpc/grpc-js",
256
+ "@opentelemetry/api",
257
+ "@opentelemetry/core",
258
+ "@opentelemetry/resources",
259
+ "@opentelemetry/semantic-conventions",
260
+ "@opentelemetry/sdk-node",
261
+ "@opentelemetry/sdk-metrics",
262
+ "@opentelemetry/sdk-trace-base",
263
+ "@opentelemetry/sdk-trace-node",
264
+ "@opentelemetry/exporter-trace-otlp-grpc",
265
+ "@opentelemetry/exporter-trace-otlp-http",
266
+ "@opentelemetry/exporter-metrics-otlp-grpc",
267
+ "@opentelemetry/exporter-metrics-otlp-http",
268
+ "@opentelemetry/auto-instrumentations-node",
269
+ "@opentelemetry/instrumentation-http",
270
+ "@opentelemetry/instrumentation-express",
271
+ ]
272
+
273
+ // Predicate form for Rollup's `external`. Also matches the many transitive
274
+ // @opentelemetry/instrumentation-* packages that auto-instrumentations-node pulls
275
+ // in, without having to enumerate each one.
276
+ const nodeBuiltins = new Set([...builtinModules, ...builtinModules.map((name) => `node:${name}`)])
277
+
278
+ export const isNodeOnlyExternal = (id) =>
279
+ nodeBuiltins.has(id) ||
280
+ id === "elastic-apm-node" ||
281
+ id === "@grpc/grpc-js" ||
282
+ id.startsWith("@opentelemetry/")
283
+
284
+ export default defineConfig({
285
+ // Parallel `vite build` (SSR + client) must use separate dirs or Vite will block on shared `node_modules/.vite`.
286
+ cacheDir: path.join(
287
+ process.env.src_path,
288
+ "node_modules",
289
+ process.env.CATALYST_VITE_CACHE_ID ? `.vite-${process.env.CATALYST_VITE_CACHE_ID}` : ".vite"
290
+ ),
291
+ ssr: {
292
+ // Keep selected React-side packages bundled for SSR (transformed by Vite, NOT pre-bundled)
293
+ // noExternal: ["@tata1mg/slowboi-react"],
294
+ // Ensure Node-only instrumentation and low-level Node deps stay external so
295
+ // the bundler never tries to resolve the optional (opt-in) OTEL packages.
296
+ external: nodeOnlyExternalDeps,
297
+ optimizeDeps: {
298
+ include: [
299
+ "invariant",
300
+ "react-fast-compare",
301
+ "shallowequal",
302
+ "prop-types",
303
+ "redux-thunk",
304
+ "redux-logger",
305
+ ],
306
+ // Prevent pre-bundling React ecosystem packages for SSR to avoid duplicate
307
+ // React instances. Pre-bundled copies in .vite/deps_ssr/ create a separate
308
+ // React instance from node_modules/react used by react-dom/server, causing
309
+ // "Invalid hook call" errors when hooks try to read a null dispatcher.
310
+ exclude: [
311
+ "react",
312
+ "react-dom",
313
+ "react-router-dom",
314
+ "@tata1mg/router",
315
+ // "@tata1mg/slowoi-react",
316
+ "catalyst-core/router/ClientRouter",
317
+ ],
318
+ esbuildOptions: {
319
+ format: "esm",
320
+ target: "node2022",
321
+ loader: {
322
+ ".js": "jsx",
323
+ },
324
+ },
325
+ },
326
+ },
327
+ plugins: [
328
+ optionalTemplateStorePlugin(),
329
+ scssModulesPlugin(),
330
+ jsxInJsPlugin(),
331
+ // `include` extends the default regex so Fast Refresh also wraps .js
332
+ // files (their JSX has already been transformed by jsxInJsPlugin above).
333
+ react({ include: /\.(mdx|js|jsx|ts|tsx)$/ }),
334
+ // Default: SVG → React component. Use `*.svg?url` (or `?raw`) for asset URL / raw source.
335
+ // Keep `*.svg?react` so explicit imports still work. Exclude node_modules so deps keep normal asset handling.
336
+ svgr({
337
+ include: ["**/*.svg", "**/*.svg?react"],
338
+ exclude: "**/node_modules/**",
339
+ }),
340
+ ],
341
+ resolve: {
342
+ alias: alias(),
343
+ // Ensure only one copy of React-related packages is used (prevents
344
+ // duplicate instances from hoisted/linked packages in monorepos)
345
+ dedupe: ["react", "react-dom", "react-router-dom", "@tata1mg/slowboi-react"],
346
+ },
347
+ define: {
348
+ ...getClientEnvVariables(),
349
+ },
350
+
351
+ build: {
352
+ outDir: path.join(process.env.src_path, process.env.BUILD_OUTPUT_PATH || "build"),
353
+ },
354
+
355
+ optimizeDeps: {
356
+ // Explicit entries so the dep scanner crawls the app's real import
357
+ // graph. Without this (SSR middleware mode has no index.html), Vite
358
+ // can't see dynamic `import()` chunks produced by split(), so every
359
+ // first-navigation discovers new deps and triggers a full reload.
360
+ entries: [
361
+ path.join(process.env.src_path, "client/index.js"),
362
+ path.join(process.env.src_path, "src/**/*.{js,jsx,ts,tsx}"),
363
+ ],
364
+ include: browserOptimizeDeps,
365
+ exclude: ["catalyst-core/router/ClientRouter"],
366
+ esbuildOptions: {
367
+ format: "esm",
368
+ target: "node2022",
369
+ loader: {
370
+ ".js": "jsx",
371
+ },
372
+ },
373
+ },
374
+
375
+ css: {
376
+ modules: {
377
+ localsConvention: "camelCase",
378
+ generateScopedName: "[name]__[local]___[hash:base64:5]",
379
+ },
380
+ preprocessorOptions: {
381
+ scss: {
382
+ additionalData: (content) =>
383
+ `${getScssResourcesImport()}$font_url: "${fontUrl()}"; $url_for: "${imageUrl()}";\n${content}`,
384
+ silenceDeprecations: [
385
+ "import",
386
+ "global-builtin",
387
+ "color-functions",
388
+ "if-function",
389
+ "slash-div",
390
+ ],
391
+ },
392
+ },
393
+ },
394
+ json: {
395
+ stringify: true,
396
+ },
397
+ assetsInclude: [
398
+ "**/*.png",
399
+ "**/*.jpg",
400
+ "**/*.gif",
401
+ "**/*.jpeg",
402
+ "**/*.ico",
403
+ "**/*.svg",
404
+ "**/*.ttf",
405
+ "**/*.eot",
406
+ "**/*.woff2",
407
+ ],
408
+
409
+ // Server configuration
410
+ server: {
411
+ hmr: !isProduction,
412
+ fs: {
413
+ allow: [process.env.src_path, __dirname],
414
+ },
415
+ },
416
+
417
+ // Preview configuration for production preview
418
+ preview: {
419
+ port: process.env.NODE_SERVER_PORT ? parseInt(process.env.NODE_SERVER_PORT) : 3005,
420
+ host: process.env.NODE_SERVER_HOSTNAME || "localhost",
421
+ },
422
+ })
@@ -0,0 +1,84 @@
1
+ import loadEnvironmentVariables from "../scripts/loadEnvironmentVariables.js"
2
+ loadEnvironmentVariables()
3
+ import { defineConfig } from "vite"
4
+ import baseConfig, { getClientEnvVariables, isNodeOnlyExternal } from "./vite.config.js"
5
+ import path from "path"
6
+ import { fileURLToPath } from "url"
7
+ import { dirname } from "path"
8
+ const __filename = fileURLToPath(import.meta.url)
9
+ const __dirname = dirname(__filename)
10
+ import { injectCacheKeyPlugin } from "./inject-cache-key-plugin.js"
11
+ import { loadCustomViteConfig } from "./loadCustomViteConfig.js"
12
+
13
+ export default defineConfig(async () => {
14
+ const customViteConfig = await loadCustomViteConfig()
15
+
16
+ return {
17
+ ...baseConfig,
18
+ mode: "production",
19
+
20
+ // Add cache key injection plugin first to transform split calls
21
+ plugins: [
22
+ injectCacheKeyPlugin(),
23
+ ...(baseConfig.plugins || []),
24
+ ...(customViteConfig?.ssrPlugins || []),
25
+ ],
26
+
27
+ build: {
28
+ ...baseConfig.build,
29
+ outDir: path.join(process.env.src_path, process.env.BUILD_OUTPUT_PATH || "build"),
30
+ target: "es2022",
31
+ minify: "esbuild",
32
+ sourcemap: false,
33
+ manifest: false,
34
+ ssrManifest: false,
35
+
36
+ rollupOptions: {
37
+ // Belt-and-suspenders with ssr.external: ensures the opt-in OTEL /
38
+ // node-only packages (and their transitive @opentelemetry/* deps) are
39
+ // never resolved/bundled, even though they may not be installed.
40
+ external: isNodeOnlyExternal,
41
+ input: {
42
+ // Server entry point for SSR
43
+ server: path.join(__dirname, "../server/renderer/index.js"),
44
+ },
45
+ output: {
46
+ format: "es",
47
+ entryFileNames: (chunkInfo) => {
48
+ return chunkInfo.name === "server"
49
+ ? "server/index.js"
50
+ : "server/assets/[name]-[hash].js"
51
+ },
52
+ chunkFileNames: "server/assets/[name]-[hash].js",
53
+ assetFileNames: (assetInfo) => {
54
+ const extType = assetInfo.name.split(".").pop()
55
+ if (/png|jpe?g|svg|gif|tiff|bmp|ico/i.test(extType)) {
56
+ return "server/assets/images/[name]-[hash][extname]"
57
+ }
58
+ if (/woff2?|eot|ttf|otf/i.test(extType)) {
59
+ return "server/assets/fonts/[name]-[hash][extname]"
60
+ }
61
+ if (/css/i.test(extType)) {
62
+ return "server/assets/css/[name]-[hash][extname]"
63
+ }
64
+ return "server/assets/[name]-[hash][extname]"
65
+ },
66
+ },
67
+ },
68
+
69
+ chunkSizeWarningLimit: 2000,
70
+ },
71
+
72
+ // Optimization for production
73
+ esbuild: {
74
+ legalComments: "none",
75
+ },
76
+
77
+ // Production-specific define
78
+ define: {
79
+ ...getClientEnvVariables(),
80
+ __DEV__: false,
81
+ "process.env.NODE_ENV": JSON.stringify("production"),
82
+ },
83
+ }
84
+ })
@@ -0,0 +1,34 @@
1
+ import React, { useContext, useState, useEffect } from "react"
2
+ import { HelmetProvider, Helmet } from "react-helmet-async"
3
+ import { OneMgRouterContext } from "../context.jsx"
4
+ import { useRouterData } from "./RouterDataProvider.jsx"
5
+ import { deleteHeadTagsByDataAttribute, getMetaData } from "../utils/metaDataUtils.jsx"
6
+ import { useLocation } from "react-router-dom"
7
+
8
+ /**
9
+ * @description renders meta tags component assigned to setMetaData
10
+ */
11
+ export const MetaTag = () => {
12
+ const { matchedRoutes } = useContext(OneMgRouterContext)
13
+ const routeData = useRouterData()
14
+ const location = useLocation()
15
+ const [metaTags, setMetaTags] = useState([<meta key={0}></meta>])
16
+
17
+ useEffect(() => {
18
+ const mergedMetaTags = getMetaData(matchedRoutes, routeData)
19
+ if (Array.isArray(mergedMetaTags) && mergedMetaTags.length > 0) {
20
+ setMetaTags(mergedMetaTags)
21
+ }
22
+ return () => deleteHeadTagsByDataAttribute("catalyst")
23
+ // eslint-disable-next-line react-hooks/exhaustive-deps
24
+ }, [location])
25
+
26
+ if (Array.isArray(metaTags) && metaTags.length >= 0) {
27
+ return (
28
+ <HelmetProvider>
29
+ <Helmet>{metaTags}</Helmet>
30
+ </HelmetProvider>
31
+ )
32
+ }
33
+ return <></>
34
+ }