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.
- package/babel.native.config.cjs +8 -0
- package/bin/catalyst.js +49 -105
- package/changelog.md +8 -0
- package/dist/caching.js +1 -1
- package/dist/index.jsx +8 -0
- package/dist/logger.js +74 -3
- package/dist/native/androidProject/app/build.gradle.kts +1 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/CustomWebview.kt +143 -4
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MainActivity.kt +26 -6
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MetricsMonitor.kt +143 -17
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeBridge.kt +6 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/WebCacheManager.kt +26 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/BridgeUtils.kt +56 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/KeyboardUtil.kt +48 -8
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/PerfDeliveryState.kt +36 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/PerfEventBuffer.kt +289 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/ProfilerNavigationState.kt +13 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/ProfilerLifecycleTest.kt +51 -0
- package/dist/native/androidSetup.js +300 -8
- package/dist/native/bridge/WebBridge.js +481 -59
- package/dist/native/bridge/constants/NativeInterfaces.js +290 -44
- package/dist/native/bridge/errors.js +250 -26
- package/dist/native/bridge/hooks/index.js +125 -1
- package/dist/native/bridge/hooks/useCamera.js +347 -9
- package/dist/native/bridge/hooks/useDataProtection.js +200 -2
- package/dist/native/bridge/hooks/useDeviceInfo.js +71 -2
- package/dist/native/bridge/hooks/useFilePicker.js +429 -2
- package/dist/native/bridge/hooks/useGoogleSignIn.js +81 -1
- package/dist/native/bridge/hooks/useHapticFeedback.js +196 -1
- package/dist/native/bridge/hooks/useIntent.js +95 -1
- package/dist/native/bridge/hooks/useNativeTransition.js +202 -27
- package/dist/native/bridge/hooks/useNetworkStatus.js +84 -3
- package/dist/native/bridge/hooks/useNotification.js +318 -2
- package/dist/native/bridge/hooks/useSafeArea.js +84 -2
- package/dist/native/bridge/hooks/useVideoStream.js +434 -6
- package/dist/native/bridge/hooks/utils.js +27 -1
- package/dist/native/bridge/hooks.js +16 -1
- package/dist/native/bridge/perf/collectors/ApiCollector.js +85 -0
- package/dist/native/bridge/perf/collectors/CacheCollector.js +215 -0
- package/dist/native/bridge/perf/collectors/HookCollector.js +165 -0
- package/dist/native/bridge/perf/collectors/InsightsCollector.js +505 -0
- package/dist/native/bridge/perf/collectors/InteractionCollector.js +273 -0
- package/dist/native/bridge/perf/collectors/KeyboardCollector.js +124 -0
- package/dist/native/bridge/perf/collectors/NavigationCollector.js +294 -0
- package/dist/native/bridge/perf/collectors/NetworkTimingCollector.js +183 -0
- package/dist/native/bridge/perf/collectors/RenderCollector.js +284 -0
- package/dist/native/bridge/perf/collectors/ScrollCollector.js +111 -0
- package/dist/native/bridge/perf/collectors/ThreadCollector.js +111 -0
- package/dist/native/bridge/perf/core/constants.js +126 -0
- package/dist/native/bridge/perf/core/measure.js +189 -0
- package/dist/native/bridge/perf/core/session.js +100 -0
- package/dist/native/bridge/perf/core/store.js +554 -0
- package/dist/native/bridge/perf/core/summary.js +174 -0
- package/dist/native/bridge/perf/core/traceExport.js +240 -0
- package/dist/native/bridge/perf/core/waterfalls.js +146 -0
- package/dist/native/bridge/perf/index.js +402 -0
- package/dist/native/bridge/safeArea.js +53 -5
- package/dist/native/bridge/standardizedHooks.js +595 -82
- package/dist/native/bridge/useBaseHook.js +274 -38
- package/dist/native/bridge/utils/CameraUtils.js +201 -56
- package/dist/native/bridge/utils/FileObjectConverter.js +129 -18
- package/dist/native/bridge/utils/NativeBridge.js +425 -141
- package/dist/native/buildAndroid/assets.js +510 -13
- package/dist/native/buildAndroid/build.js +296 -19
- package/dist/native/buildAndroid/config.js +87 -1
- package/dist/native/buildAndroid/index.js +374 -1
- package/dist/native/buildAppAndroid.js +34 -2
- package/dist/native/buildAppIos.js +62 -2
- package/dist/native/buildIos/assets.js +609 -8
- package/dist/native/buildIos/build.js +639 -20
- package/dist/native/buildIos/config.js +294 -12
- package/dist/native/buildIos/index.js +343 -6
- package/dist/native/buildIos/plugins.js +343 -16
- package/dist/native/internal-plugins/device-info-plugin/android/DeviceInfoPlugin.kt +43 -0
- package/dist/native/internal-plugins/device-info-plugin/ios/DeviceInfoPlugin.swift +28 -0
- package/dist/native/internal-plugins/device-info-plugin/manifest.json +19 -0
- package/dist/native/internalPluginUtils.js +232 -7
- package/dist/native/iosnativeWebView/Sources/Core/Constants/CatalystConstants.swift +19 -0
- package/dist/native/iosnativeWebView/Sources/Core/Constants/ConfigConstants.swift +4 -0
- package/dist/native/iosnativeWebView/Sources/Core/Utils/BootTimingUtility.swift +5 -1
- package/dist/native/iosnativeWebView/Sources/Core/Utils/CacheManager.swift +10 -0
- package/dist/native/iosnativeWebView/Sources/Core/Utils/DisplayLinkPerfMonitor.swift +89 -0
- package/dist/native/iosnativeWebView/Sources/Core/Utils/PerfEventBuffer.swift +373 -0
- package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeFileHandler.swift +35 -1
- package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeMessageValidator.swift +24 -11
- package/dist/native/iosnativeWebView/Sources/Core/WebView/NativeBridge.swift +9 -0
- package/dist/native/iosnativeWebView/Sources/Core/WebView/WebView.swift +126 -0
- package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewNavigationDelegate.swift +75 -1
- package/dist/native/iosnativeWebView/iosnativeWebViewTests/BridgeMessageValidatorTests.swift +13 -0
- package/dist/native/package.json +3 -0
- package/dist/native/plugin-bridge/PluginBridge.js +227 -1
- package/dist/native/pluginComposerAndroid.js +407 -23
- package/dist/native/pluginComposerIos.js +435 -11
- package/dist/native/renameAndroidProject.js +1094 -88
- package/dist/native/setupEmulatorIos.js +289 -22
- package/dist/native/setupServer.js +160 -19
- package/dist/native/terminalProgress.js +199 -11
- package/dist/native/utils.js +193 -15
- package/dist/offline/catalyst-sw.js +145 -1
- package/dist/offline/registerServiceWorker.js +33 -1
- package/dist/otel.js +375 -46
- package/dist/router/ClientRouter.js +14 -2
- package/dist/router/ServerRouter.js +9 -1
- package/dist/router.js +1 -1
- package/dist/scripts/build.js +112 -3
- package/dist/scripts/checkVersion.js +3 -1
- package/dist/scripts/cleanCache.js +30 -1
- package/dist/scripts/generateOfflineManifest.js +116 -1
- package/dist/scripts/loadEnvironmentVariables.js +32 -6
- package/dist/scripts/plugins.js +309 -1
- package/dist/scripts/preServerInit.js +13 -0
- package/dist/scripts/scriptUtils.js +54 -3
- package/dist/scripts/serve.js +51 -4
- package/dist/scripts/start.js +47 -10
- package/dist/scripts/validator.js +149 -1
- package/dist/sentry.cjs +127 -0
- package/dist/sentry.js +125 -5
- package/dist/server/expressServer.js +250 -5
- package/dist/server/manifestCache.js +36 -0
- package/dist/server/renderer/ChunkExtractor.js +144 -0
- package/dist/server/renderer/document/Body.jsx +59 -0
- package/dist/server/renderer/document/FastRefresh.jsx +20 -0
- package/dist/server/renderer/document/Head.jsx +60 -0
- package/dist/server/renderer/document/index.jsx +2 -0
- package/dist/server/renderer/extract.js +149 -31
- package/dist/server/renderer/handler.jsx +433 -0
- package/dist/server/renderer/index.js +8 -1
- package/dist/server/renderer/render.js +47 -0
- package/dist/server/utils/botDetectionMiddleware.js +29 -0
- package/dist/server/utils/cjsRequire.js +10 -0
- package/dist/server/utils/userAgentUtil.js +87 -9
- package/dist/server/utils/validator.js +164 -1
- package/dist/vite/FastRefresh.jsx +20 -0
- package/dist/vite/inject-cache-key-plugin.js +276 -0
- package/dist/vite/loadCustomViteConfig.js +22 -0
- package/dist/vite/manifest-categorization-plugin.js +455 -0
- package/dist/vite/node-loader.mjs +458 -0
- package/dist/vite/scssParams.js +21 -0
- package/dist/vite/vite.config.client.js +130 -0
- package/dist/vite/vite.config.js +422 -0
- package/dist/vite/vite.config.server.js +84 -0
- package/dist/web-router/components/MetaTag.jsx +34 -0
- package/dist/web-router/components/RouterDataProvider.jsx +332 -0
- package/dist/web-router/components/Split.jsx +200 -0
- package/dist/web-router/components/SplitInview.jsx +106 -0
- package/dist/web-router/components/SsrRequestContext.jsx +14 -0
- package/dist/web-router/context.jsx +12 -0
- package/dist/web-router/hooks.jsx +72 -0
- package/dist/web-router/types/components/MetaTag.d.ts +2 -0
- package/dist/web-router/types/components/RouterDataProvider.d.ts +95 -0
- package/dist/web-router/types/context.d.ts +14 -0
- package/dist/web-router/types/hooks.d.ts +1 -0
- package/dist/web-router/types/index.d.ts +3 -0
- package/dist/web-router/types/utils/metaDataUtils.d.ts +24 -0
- package/dist/web-router/utils/metaDataUtils.jsx +119 -0
- package/mcp_v2/conversion-tasks.json +35 -17
- package/mcp_v2/knowledge-base.json +124 -13
- package/mcp_v2/lib/helpers.js +10 -0
- package/mcp_v2/mcp.js +4 -4
- package/mcp_v2/package.json +1 -0
- package/mcp_v2/tools/build.js +116 -20
- package/mcp_v2/tools/conversion.js +106 -5
- package/mcp_v2/tools/tasks.js +18 -14
- package/package.json +35 -68
- package/babel.config.js +0 -32
- package/dist/index.js +0 -1
- package/dist/scripts/devBuild.js +0 -3
- package/dist/scripts/devServe.js +0 -3
- package/dist/scripts/loadScriptsBeforeServerStarts.js +0 -4
- package/dist/scripts/registerAliases.js +0 -6
- package/dist/server/renderer/document/Body.js +0 -11
- package/dist/server/renderer/document/Head.js +0 -9
- package/dist/server/renderer/document/index.js +0 -1
- package/dist/server/renderer/handler.js +0 -47
- package/dist/server/startServer.js +0 -57
- package/dist/webpack/babel-plugins/remove-client.plugin.js +0 -5
- package/dist/webpack/babel-plugins/remove-ssr.plugin.js +0 -5
- package/dist/webpack/babel.config.client.js +0 -1
- package/dist/webpack/babel.config.ssr.js +0 -1
- package/dist/webpack/base.babel.js +0 -7
- package/dist/webpack/development.client.babel.js +0 -10
- package/dist/webpack/production.client.babel.js +0 -4
- package/dist/webpack/production.ssr.babel.js +0 -8
- 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
|
+
}
|