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
package/dist/otel.js CHANGED
@@ -1,72 +1,401 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;exports.withObservability=withObservability;exports.withSyncObservability=withSyncObservability;function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var r=new WeakMap(),n=new WeakMap();return(_interopRequireWildcard=function(e,t){if(!t&&e&&e.__esModule)return e;var o,i,f={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return f;if(o=t?n:r){if(o.has(e))return o.get(e);o.set(e,f);}for(const t in e)"default"!==t&&{}.hasOwnProperty.call(e,t)&&((i=(o=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,t))&&(i.get||i.set)?o(f,t,i):f[t]=e[t]);return f;})(e,t);}// OpenTelemetry is an OPT-IN feature. Nothing from "@opentelemetry/*" is
2
- // imported at module-eval time on purpose: the packages are declared as
3
- // (optional) peerDependencies and may not be installed in the consuming app.
4
- //
5
- // All OTel packages are loaded lazily via dynamic import() inside init(), and
6
- // only when OTEL_ENABLE === "true". Consequences:
7
- // - Apps that keep OTEL disabled don't need the packages installed.
8
- // - Bundlers don't pull the packages into the static import graph, so
9
- // `import "catalyst-core/otel"` no longer forces them to resolve
10
- // "@opentelemetry/exporter-trace-otlp-http" & friends at build time.
11
- // (Pair this with marking "@opentelemetry/*" external in the bundler so the
12
- // dynamic import() chunk isn't resolved at build time either โ€” see the SSR
13
- // webpack configs under src/webpack.)
14
- // Set once by init() (when enabled) to the loaded "@opentelemetry/api" module.
15
- // The wrappers below read it lazily so they never need a static OTel import.
16
- let _otelApi=null;const isOtelEnabled=()=>process.env.OTEL_ENABLE==="true";async function init(config={}){if(!isOtelEnabled()){return{sdk:null,meter:null};}const{serviceName="catalyst-server",serviceVersion="1.0.0",environment="development",traceUrl="http://localhost:4317",metricUrl="http://localhost:4317",traceProtocol="grpc",// "grpc" or "http"
17
- metricProtocol,// "grpc" or "http" - if not provided, metrics will be disabled
18
- traceHeaders={},metricHeaders={},batchProcessorConfig={},exportIntervalMillis=10000,instrumentations,samplingRate=1.0,grpcCredentials}=config;try{// Lazy-load every OpenTelemetry package. These dynamic imports run only
19
- // when OTEL_ENABLE=true, so the packages are required at runtime solely
20
- // for opted-in deployments.
21
- const[otelApi,{NodeSDK},{resourceFromAttributes},{BatchSpanProcessor,TraceIdRatioBasedSampler,ParentBasedSampler},{PeriodicExportingMetricReader},{OTLPTraceExporter},{OTLPMetricExporter},{getNodeAutoInstrumentations},{OTLPTraceExporter:OTLPTraceExporterHTTP},{OTLPMetricExporter:OTLPMetricExporterHTTP},{ATTR_SERVICE_NAME,ATTR_SERVICE_VERSION,ATTR_DEPLOYMENT_ENVIRONMENT}]=await Promise.all([Promise.resolve().then(()=>_interopRequireWildcard(require("@opentelemetry/api"))),Promise.resolve().then(()=>_interopRequireWildcard(require("@opentelemetry/sdk-node"))),Promise.resolve().then(()=>_interopRequireWildcard(require("@opentelemetry/resources"))),Promise.resolve().then(()=>_interopRequireWildcard(require("@opentelemetry/sdk-trace-node"))),Promise.resolve().then(()=>_interopRequireWildcard(require("@opentelemetry/sdk-metrics"))),Promise.resolve().then(()=>_interopRequireWildcard(require("@opentelemetry/exporter-trace-otlp-grpc"))),Promise.resolve().then(()=>_interopRequireWildcard(require("@opentelemetry/exporter-metrics-otlp-grpc"))),Promise.resolve().then(()=>_interopRequireWildcard(require("@opentelemetry/auto-instrumentations-node"))),Promise.resolve().then(()=>_interopRequireWildcard(require("@opentelemetry/exporter-trace-otlp-http"))),Promise.resolve().then(()=>_interopRequireWildcard(require("@opentelemetry/exporter-metrics-otlp-http"))),Promise.resolve().then(()=>_interopRequireWildcard(require("@opentelemetry/semantic-conventions")))]);// Enables the withObservability / withSyncObservability wrappers.
22
- _otelApi=otelApi;const traceExporters={OTLPTraceExporter,OTLPTraceExporterHTTP};const metricExporters={OTLPMetricExporter,OTLPMetricExporterHTTP};const otlpTraceExporter=createTraceExporter(traceExporters,traceProtocol,traceUrl,traceHeaders,grpcCredentials);// Create metric exporter only if metricProtocol is specified
23
- let metricReader=null;if(metricProtocol){const otlpMetricExporter=createMetricExporter(metricExporters,metricProtocol,metricUrl,metricHeaders,grpcCredentials);metricReader=new PeriodicExportingMetricReader({exporter:otlpMetricExporter,exportIntervalMillis});}const sampler=new ParentBasedSampler({root:new TraceIdRatioBasedSampler(samplingRate)});const sdkConfig={resource:resourceFromAttributes({[ATTR_SERVICE_NAME]:serviceName,[ATTR_SERVICE_VERSION]:serviceVersion,[ATTR_DEPLOYMENT_ENVIRONMENT]:environment}),spanProcessor:new BatchSpanProcessor(otlpTraceExporter,batchProcessorConfig),instrumentations:instrumentations??[getNodeAutoInstrumentations()],sampler};// Add metric reader only if metrics are enabled
24
- if(metricReader){sdkConfig.metricReader=metricReader;}const sdk=new NodeSDK(sdkConfig);sdk.start();logger.info("โœ… OpenTelemetry started successfully");// Initialize custom metrics only if metrics are enabled
25
- let meter=null;if(metricProtocol){meter=initializeCustomMetrics(otelApi,serviceName,serviceVersion);}const gracefulShutdown=signal=>{logger.info(`๐Ÿ“ก Received ${signal}, shutting down OpenTelemetry gracefully...`);sdk.shutdown().then(()=>logger.info("โœ… OpenTelemetry shutdown completed")).catch(error=>{logger.error("โŒ Error terminating OpenTelemetry:",error);}).finally(()=>process.exit());};process.on("SIGTERM",()=>gracefulShutdown("SIGTERM"));process.on("SIGINT",()=>gracefulShutdown("SIGINT"));return{sdk,meter};}catch(error){logger.error("โŒ Failed to initialize OpenTelemetry:",error);throw error;}}/**
1
+ import { metrics } from "@opentelemetry/api"
2
+ import { NodeSDK } from "@opentelemetry/sdk-node"
3
+ import { resourceFromAttributes } from "@opentelemetry/resources"
4
+ import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-node"
5
+ import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics"
6
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc"
7
+ import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc"
8
+ import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node"
9
+ import { TraceIdRatioBasedSampler, ParentBasedSampler } from "@opentelemetry/sdk-trace-node"
10
+ import { OTLPTraceExporter as OTLPTraceExporterHTTP } from "@opentelemetry/exporter-trace-otlp-http"
11
+ import { OTLPMetricExporter as OTLPMetricExporterHTTP } from "@opentelemetry/exporter-metrics-otlp-http"
12
+ import { trace, context, createContextKey } from "@opentelemetry/api"
13
+
14
+ export const IS_BOT_KEY = createContextKey("catalyst.is_bot")
15
+
16
+ import semanticConventions from "@opentelemetry/semantic-conventions"
17
+ const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION, ATTR_DEPLOYMENT_ENVIRONMENT } = semanticConventions
18
+
19
+ function init(config = {}) {
20
+ // OpenTelemetry is opt-in โ€” bail out unless explicitly enabled. Mirrors the
21
+ // OTEL_ENABLE guard in server/expressServer.js and server/renderer/handler.jsx
22
+ // so the SDK, exporters, instrumentations and signal handlers are never set
23
+ // up when tracing is off. Returns the same shape so callers can destructure.
24
+ if (process.env.OTEL_ENABLE !== true) {
25
+ return { sdk: null, meter: null }
26
+ }
27
+
28
+ const {
29
+ serviceName = "catalyst-server",
30
+ serviceVersion = "1.0.0",
31
+ environment = "development",
32
+ traceUrl = "http://localhost:4317",
33
+ metricUrl = "http://localhost:4317",
34
+ traceProtocol = "grpc", // "grpc" or "http"
35
+ metricProtocol, // "grpc" or "http" - if not provided, metrics will be disabled
36
+ traceHeaders = {},
37
+ metricHeaders = {},
38
+ batchProcessorConfig = {},
39
+ exportIntervalMillis = 10000,
40
+ instrumentations,
41
+ samplingRate = 1.0,
42
+ grpcCredentials,
43
+ } = config
44
+
45
+ try {
46
+ const otlpTraceExporter = createTraceExporter(traceProtocol, traceUrl, traceHeaders, grpcCredentials)
47
+
48
+ // Create metric exporter only if metricProtocol is specified
49
+ let otlpMetricExporter = null
50
+ let metricReader = null
51
+ if (metricProtocol) {
52
+ otlpMetricExporter = createMetricExporter(
53
+ metricProtocol,
54
+ metricUrl,
55
+ metricHeaders,
56
+ grpcCredentials
57
+ )
58
+ metricReader = new PeriodicExportingMetricReader({
59
+ exporter: otlpMetricExporter,
60
+ exportIntervalMillis,
61
+ })
62
+ }
63
+
64
+ const sampler = new ParentBasedSampler({
65
+ root: new TraceIdRatioBasedSampler(samplingRate),
66
+ })
67
+
68
+ const sdkConfig = {
69
+ resource: resourceFromAttributes({
70
+ [ATTR_SERVICE_NAME]: serviceName,
71
+ [ATTR_SERVICE_VERSION]: serviceVersion,
72
+ [ATTR_DEPLOYMENT_ENVIRONMENT]: environment,
73
+ }),
74
+ spanProcessor: new BatchSpanProcessor(otlpTraceExporter, batchProcessorConfig),
75
+ instrumentations: instrumentations ?? [getNodeAutoInstrumentations()],
76
+ sampler,
77
+ }
78
+
79
+ // Add metric reader only if metrics are enabled
80
+ if (metricReader) {
81
+ sdkConfig.metricReader = metricReader
82
+ }
83
+
84
+ const sdk = new NodeSDK(sdkConfig)
85
+
86
+ sdk.start()
87
+ logger.info("โœ… OpenTelemetry started successfully")
88
+
89
+ // Initialize custom metrics only if metrics are enabled
90
+ let meter = null
91
+ if (metricProtocol) {
92
+ meter = initializeCustomMetrics(serviceName, serviceVersion)
93
+ }
94
+
95
+ const gracefulShutdown = (signal) => {
96
+ logger.info(`๐Ÿ“ก Received ${signal}, shutting down OpenTelemetry gracefully...`)
97
+ sdk.shutdown()
98
+ .then(() => logger.info("โœ… OpenTelemetry shutdown completed"))
99
+ .catch((error) => {
100
+ logger.error("โŒ Error terminating OpenTelemetry:", error)
101
+ })
102
+ .finally(() => process.exit())
103
+ }
104
+
105
+ process.on("SIGTERM", () => gracefulShutdown("SIGTERM"))
106
+ process.on("SIGINT", () => gracefulShutdown("SIGINT"))
107
+
108
+ return { sdk, meter }
109
+ } catch (error) {
110
+ logger.error("โŒ Failed to initialize OpenTelemetry:", error)
111
+ throw error
112
+ }
113
+ }
114
+
115
+ /**
26
116
  * Creates a trace exporter based on the specified protocol
27
- * @param {object} exporters - Lazily-loaded exporter constructors { OTLPTraceExporter, OTLPTraceExporterHTTP }
28
117
  * @param {string} protocol - "grpc" or "http"
29
118
  * @param {string} url - Exporter endpoint URL
30
119
  * @param {object} headers - Headers to include in requests
31
120
  * @param {Function} [grpcCredentials] - gRPC Credentials (optional)
32
- * @returns {object} Configured trace exporter
33
- */function createTraceExporter(exporters,protocol,url,headers={},grpcCredentials){const{OTLPTraceExporter,OTLPTraceExporterHTTP}=exporters;if(protocol.toLowerCase()==="http"){logger.info(`๐Ÿ“ก Creating HTTP trace exporter for URL: ${url}`);return new OTLPTraceExporterHTTP({url:url,headers:headers});}else if(protocol.toLowerCase()==="grpc"){logger.info(`๐Ÿ“ก Creating gRPC trace exporter for URL: ${url}`);return new OTLPTraceExporter({url:url,headers:headers,credentials:grpcCredentials});}else{throw new Error(`โŒ Unsupported trace protocol: ${protocol}. Supported protocols are "grpc" and "http"`);}}/**
121
+ * @returns {OTLPTraceExporter|OTLPTraceExporterHTTP} Configured trace exporter
122
+ */
123
+ function createTraceExporter(protocol, url, headers = {}, grpcCredentials) {
124
+ if (protocol.toLowerCase() === "http") {
125
+ logger.info(`๐Ÿ“ก Creating HTTP trace exporter for URL: ${url}`)
126
+ return new OTLPTraceExporterHTTP({
127
+ url: url,
128
+ headers: headers,
129
+ })
130
+ } else if (protocol.toLowerCase() === "grpc") {
131
+ logger.info(`๐Ÿ“ก Creating gRPC trace exporter for URL: ${url}`)
132
+ return new OTLPTraceExporter({
133
+ url: url,
134
+ headers: headers,
135
+ credentials: grpcCredentials,
136
+ })
137
+ } else {
138
+ throw new Error(
139
+ `โŒ Unsupported trace protocol: ${protocol}. Supported protocols are "grpc" and "http"`
140
+ )
141
+ }
142
+ }
143
+
144
+ /**
34
145
  * Creates a metric exporter based on the specified protocol
35
- * @param {object} exporters - Lazily-loaded exporter constructors { OTLPMetricExporter, OTLPMetricExporterHTTP }
36
146
  * @param {string} protocol - "grpc" or "http"
37
147
  * @param {string} url - Exporter endpoint URL
38
148
  * @param {object} headers - Headers to include in requests
39
149
  * @param {Function} [grpcCredentials] - gRPC Credentials (optional)
40
- * @returns {object} Configured metric exporter
41
- */function createMetricExporter(exporters,protocol,url,headers={},grpcCredentials){const{OTLPMetricExporter,OTLPMetricExporterHTTP}=exporters;if(protocol.toLowerCase()==="http"){logger.info(`๐Ÿ“Š Creating HTTP metric exporter for URL: ${url}`);return new OTLPMetricExporterHTTP({url:url,headers:headers});}else if(protocol.toLowerCase()==="grpc"){logger.info(`๐Ÿ“Š Creating gRPC metric exporter for URL: ${url}`);return new OTLPMetricExporter({url:url,headers:headers,credentials:grpcCredentials});}else{throw new Error(`โŒ Unsupported metric protocol: ${protocol}. Supported protocols are "grpc" and "http"`);}}/**
42
- * @param {object} otelApi - The loaded "@opentelemetry/api" module
43
- */function initializeCustomMetrics(otelApi,serviceName,serviceVersion){let customMetrics={};const meter=otelApi.metrics.getMeter(serviceName,serviceVersion);// CPU usage gauge
44
- customMetrics.cpuUsage=meter.createObservableGauge("process_cpu_usage_percent",{description:"Current CPU usage percentage"});// Memory usage gauges
45
- customMetrics.memoryUsage=meter.createObservableGauge("process_memory_usage_bytes",{description:"Current memory usage in bytes",unit:"bytes"});customMetrics.memoryHeapUsed=meter.createObservableGauge("process_memory_heap_used_bytes",{description:"Current heap memory used in bytes",unit:"bytes"});customMetrics.memoryHeapTotal=meter.createObservableGauge("process_memory_heap_total_bytes",{description:"Current heap memory total in bytes",unit:"bytes"});let lastCpuUsage=process.cpuUsage();let lastMeasureTime=process.hrtime.bigint();customMetrics.cpuUsage.addCallback(result=>{const currentCpuUsage=process.cpuUsage(lastCpuUsage);const currentTime=process.hrtime.bigint();const timeDiff=Number(currentTime-lastMeasureTime)/1000000;// Convert to milliseconds
46
- const cpuPercent=(currentCpuUsage.user+currentCpuUsage.system)/1000/timeDiff*100;result.observe(cpuPercent);lastCpuUsage=process.cpuUsage();lastMeasureTime=currentTime;});customMetrics.memoryUsage.addCallback(result=>{const memUsage=process.memoryUsage();result.observe(memUsage.rss,{type:"rss"});result.observe(memUsage.external,{type:"external"});result.observe(memUsage.arrayBuffers,{type:"arrayBuffers"});});customMetrics.memoryHeapUsed.addCallback(result=>{const memUsage=process.memoryUsage();result.observe(memUsage.heapUsed);});customMetrics.memoryHeapTotal.addCallback(result=>{const memUsage=process.memoryUsage();result.observe(memUsage.heapTotal);});return meter;}/**
150
+ * @returns {OTLPMetricExporter|OTLPMetricExporterHTTP} Configured metric exporter
151
+ */
152
+ function createMetricExporter(protocol, url, headers = {}, grpcCredentials) {
153
+ if (protocol.toLowerCase() === "http") {
154
+ logger.info(`๐Ÿ“Š Creating HTTP metric exporter for URL: ${url}`)
155
+ return new OTLPMetricExporterHTTP({
156
+ url: url,
157
+ headers: headers,
158
+ })
159
+ } else if (protocol.toLowerCase() === "grpc") {
160
+ logger.info(`๐Ÿ“Š Creating gRPC metric exporter for URL: ${url}`)
161
+ return new OTLPMetricExporter({
162
+ url: url,
163
+ headers: headers,
164
+ credentials: grpcCredentials,
165
+ })
166
+ } else {
167
+ throw new Error(
168
+ `โŒ Unsupported metric protocol: ${protocol}. Supported protocols are "grpc" and "http"`
169
+ )
170
+ }
171
+ }
172
+
173
+ function initializeCustomMetrics(serviceName, serviceVersion) {
174
+ let customMetrics = {}
175
+ const meter = metrics.getMeter(serviceName, serviceVersion)
176
+
177
+ // CPU usage gauge
178
+ customMetrics.cpuUsage = meter.createObservableGauge("process_cpu_usage_percent", {
179
+ description: "Current CPU usage percentage",
180
+ })
181
+
182
+ // Memory usage gauges
183
+ customMetrics.memoryUsage = meter.createObservableGauge("process_memory_usage_bytes", {
184
+ description: "Current memory usage in bytes",
185
+ unit: "bytes",
186
+ })
187
+
188
+ customMetrics.memoryHeapUsed = meter.createObservableGauge("process_memory_heap_used_bytes", {
189
+ description: "Current heap memory used in bytes",
190
+ unit: "bytes",
191
+ })
192
+
193
+ customMetrics.memoryHeapTotal = meter.createObservableGauge("process_memory_heap_total_bytes", {
194
+ description: "Current heap memory total in bytes",
195
+ unit: "bytes",
196
+ })
197
+
198
+ let lastCpuUsage = process.cpuUsage()
199
+ let lastMeasureTime = process.hrtime.bigint()
200
+
201
+ customMetrics.cpuUsage.addCallback((result) => {
202
+ const currentCpuUsage = process.cpuUsage(lastCpuUsage)
203
+ const currentTime = process.hrtime.bigint()
204
+ const timeDiff = Number(currentTime - lastMeasureTime) / 1000000 // Convert to milliseconds
205
+
206
+ const cpuPercent = ((currentCpuUsage.user + currentCpuUsage.system) / 1000 / timeDiff) * 100
207
+
208
+ result.observe(cpuPercent)
209
+
210
+ lastCpuUsage = process.cpuUsage()
211
+ lastMeasureTime = currentTime
212
+ })
213
+
214
+ customMetrics.memoryUsage.addCallback((result) => {
215
+ const memUsage = process.memoryUsage()
216
+ result.observe(memUsage.rss, { type: "rss" })
217
+ result.observe(memUsage.external, { type: "external" })
218
+ result.observe(memUsage.arrayBuffers, { type: "arrayBuffers" })
219
+ })
220
+
221
+ customMetrics.memoryHeapUsed.addCallback((result) => {
222
+ const memUsage = process.memoryUsage()
223
+ result.observe(memUsage.heapUsed)
224
+ })
225
+
226
+ customMetrics.memoryHeapTotal.addCallback((result) => {
227
+ const memUsage = process.memoryUsage()
228
+ result.observe(memUsage.heapTotal)
229
+ })
230
+
231
+ return meter
232
+ }
233
+
234
+ /**
47
235
  * Wraps a synchronous function and measures total execution time.
48
236
  * Creates a single OpenTelemetry span per function call.
49
237
  * Use this instead of withObservability when the wrapped function is synchronous,
50
238
  * so the return type and call sites remain unchanged.
51
239
  *
52
- * When OTEL is disabled the original function is returned unchanged, so there is
53
- * zero overhead and no dependency on any @opentelemetry/* package.
54
- *
55
240
  * @param {string} serviceName - The name of the service
56
241
  * @param {Function} fn - The synchronous function to wrap
57
242
  * @param {string} name - Span name (optional)
58
243
  * @returns {Function} Wrapped function (still synchronous)
59
- */function withSyncObservability(serviceName,fn,name){if(!isOtelEnabled())return fn;const spanName=name||fn.name||"anonymousFunction";return function(...args){// init() may not have populated the API yet โ€” run untraced rather than throw.
60
- const api=_otelApi;if(!api)return fn(...args);const tracer=api.trace.getTracer(serviceName);return tracer.startActiveSpan(spanName,span=>{try{return fn(...args);}catch(err){span.recordException(err);span.setStatus({code:2,message:err.message});throw err;}finally{span.end();}});};}/**
244
+ */
245
+ export function withSyncObservability(serviceName, fn, name) {
246
+ const tracer = trace.getTracer(serviceName)
247
+ const spanName = name || fn.name || "anonymousFunction"
248
+
249
+ return function (...args) {
250
+ const isBot = context.active().getValue(IS_BOT_KEY)
251
+ return tracer.startActiveSpan(spanName, (span) => {
252
+ if (isBot !== undefined) span.setAttribute("http.response.is_bot", isBot)
253
+ try {
254
+ return fn(...args)
255
+ } catch (err) {
256
+ span.recordException(err)
257
+ span.setStatus({ code: 2, message: err.message })
258
+ throw err
259
+ } finally {
260
+ span.end()
261
+ }
262
+ })
263
+ }
264
+ }
265
+
266
+ /**
61
267
  * Wraps a function (sync or async) and measures total execution time.
62
268
  * Creates a single OpenTelemetry span per function call.
63
269
  *
64
- * When OTEL is disabled the original function is returned unchanged, so there is
65
- * zero overhead and no dependency on any @opentelemetry/* package.
66
- *
67
270
  * @param {string} serviceName - The name of the service
68
271
  * @param {Function} fn - The function to wrap
69
272
  * @param {string} name - Span name (optional)
70
273
  * @returns {Function} Wrapped function
71
- */function withObservability(serviceName,fn,name){if(!isOtelEnabled())return fn;const spanName=name||fn.name||"anonymousFunction";return async function(...args){// init() may not have populated the API yet โ€” run untraced rather than throw.
72
- const api=_otelApi;if(!api)return fn(...args);const tracer=api.trace.getTracer(serviceName);return tracer.startActiveSpan(spanName,async span=>{try{const result=await fn(...args);return result;}catch(err){span.recordException(err);span.setStatus({code:2,message:err.message});throw err;}finally{span.end();}});};}var _default=exports.default={init,withObservability,withSyncObservability};
274
+ */
275
+ export function withObservability(serviceName, fn, name) {
276
+ const tracer = trace.getTracer(serviceName)
277
+ const spanName = name || fn.name || "anonymousFunction"
278
+
279
+ return async function (...args) {
280
+ const isBot = context.active().getValue(IS_BOT_KEY)
281
+ return tracer.startActiveSpan(spanName, async (span) => {
282
+ if (isBot !== undefined) span.setAttribute("http.response.is_bot", isBot)
283
+ try {
284
+ const result = await fn(...args)
285
+ return result
286
+ } catch (err) {
287
+ span.recordException(err)
288
+ span.setStatus({ code: 2, message: err.message })
289
+ throw err
290
+ } finally {
291
+ span.end()
292
+ }
293
+ })
294
+ }
295
+ }
296
+
297
+ /**
298
+ * Express middleware that emits two spans describing what happens to the
299
+ * response body AFTER the app calls res.end() โ€” the work that lives past the
300
+ * `handler` span and makes the HTTP server span run longer:
301
+ *
302
+ * โ€ข response.compress โ€” gzip/brotli of the body. Starts when the app calls
303
+ * res.end() (which returns immediately, since compression is async) and
304
+ * ends when the compressed bytes are handed to the real socket end.
305
+ * โ€ข response.flush โ€” network egress. Starts when those bytes hit the socket
306
+ * and ends on 'finish' (all bytes handed to the OS) or 'close' (connection
307
+ * torn down first).
308
+ *
309
+ * Implementation: the gap is bounded by the *app's* res.end() call (outer) and
310
+ * the *real* socket end after compression (inner), so the middleware wraps
311
+ * res.end on BOTH sides of the compression middleware. It installs an inner
312
+ * hook before next() (which compression then wraps) to time the END of
313
+ * compression, and after next() โ€” once compression has synchronously patched
314
+ * res.end โ€” installs an outer hook on top to time the START.
315
+ *
316
+ * MOUNT THIS IMMEDIATELY BEFORE compression() so the post-next() outer hook
317
+ * reliably wraps compression's patch (no async middleware in between). If
318
+ * compression isn't present (or skips the response) only response.flush is
319
+ * emitted. Uses startSpan (not startActiveSpan), so the spans are siblings of
320
+ * `handler` under the same request span. No span is emitted if the app never
321
+ * writes (e.g. the client aborts first).
322
+ *
323
+ * @param {string} serviceName
324
+ * @param {string} [flushName] - egress span name
325
+ * @param {string} [compressName] - compression span name
326
+ * @returns {Function} Express middleware
327
+ */
328
+ export function responseFlushMiddleware(
329
+ serviceName,
330
+ flushName = "response.flush",
331
+ compressName = "response.compress"
332
+ ) {
333
+ const tracer = trace.getTracer(serviceName)
334
+
335
+ return function (req, res, next) {
336
+ // Captured while the request span is active; both spans parent to it.
337
+ const parentContext = context.active()
338
+
339
+ let compressSpan = null
340
+ let flushSpan = null
341
+ let finished = false
342
+
343
+ const finalize = (endEvent) => {
344
+ if (finished) return
345
+ finished = true
346
+ // Whichever span is still open when the response ends gets tagged.
347
+ const open = flushSpan || compressSpan
348
+ if (open) {
349
+ open.setAttribute("http.response.end_event", endEvent) // "finish" | "close"
350
+ open.end()
351
+ }
352
+ compressSpan = null
353
+ flushSpan = null
354
+ }
355
+
356
+ // Inner hook: wraps the real res.end (installed before compression), so
357
+ // it fires once compression has produced the final bytes โ†’ close the
358
+ // compression span and open the egress span.
359
+ const realEnd = res.end
360
+ const innerEnd = function (...args) {
361
+ if (!finished && !flushSpan) {
362
+ if (compressSpan) {
363
+ compressSpan.end()
364
+ compressSpan = null
365
+ }
366
+ flushSpan = tracer.startSpan(
367
+ flushName,
368
+ { attributes: { "http.response.is_bot": res.locals.is_bot } },
369
+ parentContext
370
+ )
371
+ }
372
+ return realEnd.apply(this, args)
373
+ }
374
+ res.end = innerEnd
375
+
376
+ res.once("finish", () => finalize("finish"))
377
+ res.once("close", () => finalize("close"))
378
+
379
+ next()
380
+
381
+ // After next(): compression has synchronously wrapped innerEnd. Install
382
+ // an outer hook on top to catch the app's res.end() call โ†’ open the
383
+ // compression span. Skipped if nothing wrapped innerEnd (no compression),
384
+ // in which case innerEnd alone times the flush from the app's res.end().
385
+ if (res.end !== innerEnd) {
386
+ const chainEnd = res.end
387
+ res.end = function (...args) {
388
+ if (!finished && !compressSpan && !flushSpan) {
389
+ compressSpan = tracer.startSpan(
390
+ compressName,
391
+ { attributes: { "http.response.is_bot": res.locals.is_bot } },
392
+ parentContext
393
+ )
394
+ }
395
+ return chainEnd.apply(this, args)
396
+ }
397
+ }
398
+ }
399
+ }
400
+
401
+ export default { init, withObservability, withSyncObservability, responseFlushMiddleware }
@@ -1,3 +1,15 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _router=require("@tata1mg/router");var _registerServiceWorker=require("../offline/registerServiceWorker.js");const{preparedRoutes}=require(`${process.env.src_path}/src/js/routes/utils.js`);(0,_registerServiceWorker.registerCatalystServiceWorker)();/**
1
+ import { createBrowserRouter } from "../index.jsx"
2
+ import { preparedRoutes } from "@catalyst/template/src/js/routes/utils"
3
+ import { registerCatalystServiceWorker } from "../offline/registerServiceWorker.js"
4
+
5
+ registerCatalystServiceWorker()
6
+
7
+ /**
2
8
  * @returns returns browsers routers (client routes)
3
- */const clientRouter=({store,routerInitialState})=>(0,_router.createBrowserRouter)(preparedRoutes({store,routerInitialState}));var _default=exports.default=clientRouter;
9
+ */
10
+ const clientRouter = ({ routerInitialState }) => {
11
+ const browserRouter = createBrowserRouter(preparedRoutes({ routerInitialState }))
12
+ return browserRouter
13
+ }
14
+
15
+ export default clientRouter
@@ -1 +1,9 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _router=require("@tata1mg/router");const{preparedRoutes}=require(`${process.env.src_path}/src/js/routes/utils.js`);const ServerRouter=reduxData=>{const{store,intialData}=reduxData;return(0,_router.useRoutes)(preparedRoutes({store,routerInitialState:intialData}));};var _default=exports.default=ServerRouter;
1
+ import { useRoutes } from "../index.jsx"
2
+ import { preparedRoutes } from "@catalyst/template/src/js/routes/utils"
3
+
4
+ const ServerRouter = (reduxData) => {
5
+ const { store, intialData } = reduxData
6
+ return useRoutes(preparedRoutes({ store, routerInitialState: intialData }))
7
+ }
8
+
9
+ export default ServerRouter
package/dist/router.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});var _router=require("@tata1mg/router");Object.keys(_router).forEach(function(key){if(key==="default"||key==="__esModule")return;if(key in exports&&exports[key]===_router[key])return;Object.defineProperty(exports,key,{enumerable:true,get:function(){return _router[key];}});});
1
+ export * from "@tata1mg/router"
@@ -1,3 +1,112 @@
1
- "use strict";const path=require("path");const{green,cyan,yellow}=require("picocolors");const{name}=require(`${process.cwd()}/package.json`);const{BUILD_OUTPUT_PATH}=require(`${process.cwd()}/config/config.json`);const{arrayToObject,printBundleInformation,runBuildCommands}=require("./scriptUtils.js");/**
2
- * @description - creates a production build of the application.
3
- */function build(){const isWindows=process.platform==="win32";const commandLineArguments=process.argv.slice(2);const argumentsObject=arrayToObject(commandLineArguments);const dirname=path.resolve(__dirname,"../../");const commands=["node ./dist/scripts/checkVersion",`${isWindows?"rd -r -fo":"rm -rf"} ${process.cwd()}/${BUILD_OUTPUT_PATH} & node ./dist/scripts/loadScriptsBeforeServerStarts.js`,`cross-env APPLICATION=${name||"catalyst_app"} webpack --config ./dist/webpack/production.client.babel.js --progress`,`cross-env APPLICATION=${name||"catalyst_app"} SSR=true webpack --config ./dist/webpack/production.ssr.babel.js`,`cross-env APPLICATION=${name||"catalyst_app"} node ./dist/scripts/generateOfflineManifest.js`,`cross-env APPLICATION=${name||"catalyst_app"} npx babel ./dist/server --out-dir ${process.cwd()}/${BUILD_OUTPUT_PATH} --extensions .js,.ts,.jsx,.tsx --ignore '**/*.test.js,./dist/server/renderer/handler.js' --quiet`,`cross-env APPLICATION=${name||"catalyst_app"} npx babel ${process.cwd()}/server --out-dir ${process.cwd()}/${BUILD_OUTPUT_PATH} --extensions .js,.ts,.jsx,.tsx --quiet`];console.log("Creating an optimized production build...");runBuildCommands({commands,cwd:dirname,env:{...process.env,src_path:process.cwd(),BUILD_OUTPUT_PATH:BUILD_OUTPUT_PATH,NODE_ENV:"production",IS_DEV_COMMAND:false,...argumentsObject}});console.log(green("Compiled successfully."));console.log("\nFile sizes after gzip:\n");printBundleInformation();console.log(`\nThe ${cyan(BUILD_OUTPUT_PATH)} folder is ready to be deployed.`);console.log("You may serve it with a serve command:");console.log(cyan("\n npm run serve"));console.log("\nFind out more about deployment here:");console.log(yellow("\n https://catalyst.1mg.com/public_docs/content/Deployment%20and%20Production/deployment\n"));}build();
1
+ import path from "path"
2
+ import { spawn } from "child_process"
3
+ import { arrayToObject } from "./scriptUtils.js"
4
+ import { fileURLToPath } from "url"
5
+ import { dirname } from "path"
6
+ import { readFileSync, existsSync, rmSync } from "fs"
7
+
8
+ const __filename = fileURLToPath(import.meta.url)
9
+ const __dirname = dirname(__filename)
10
+ const loaderPath = path.resolve(__dirname, "../../dist/vite/node-loader.mjs")
11
+ const configPath = path.join(process.env.PWD, "config/config.json")
12
+ const configJSON = JSON.parse(readFileSync(configPath), "utf-8")
13
+
14
+ /**
15
+ * @param {string} command
16
+ * @param {import('child_process').SpawnOptions} options
17
+ */
18
+ function runBuildStep(command, options) {
19
+ return new Promise((resolve, reject) => {
20
+ const child = spawn(command, [], {
21
+ ...options,
22
+ shell: true,
23
+ })
24
+ child.on("close", (code) => {
25
+ if (code === 0) {
26
+ resolve()
27
+ } else {
28
+ reject(Object.assign(new Error(`Build step failed with exit code ${code}`), { code }))
29
+ }
30
+ })
31
+ child.on("error", reject)
32
+ })
33
+ }
34
+
35
+ /**
36
+ * @description - builds the application for production
37
+ */
38
+ async function build() {
39
+ const commandLineArguments = process.argv.slice(2)
40
+ const argumentsObject = arrayToObject(commandLineArguments)
41
+ const dirname = path.resolve(__dirname, "../../")
42
+
43
+ // Read package.json
44
+ const packageJson = JSON.parse(readFileSync(path.join(process.env.PWD, "package.json"), "utf-8"))
45
+ const { name } = packageJson
46
+
47
+ const buildOutputPath = path.join(process.env.PWD, configJSON.BUILD_OUTPUT_PATH || "build")
48
+ if (existsSync(buildOutputPath)) {
49
+ console.log("๐Ÿงน Clearing previous build output...")
50
+ rmSync(buildOutputPath, { recursive: true, force: true })
51
+ }
52
+
53
+ console.log("๐Ÿ—๏ธ Building application for production...")
54
+
55
+ const baseEnv = {
56
+ ...process.env,
57
+ src_path: process.env.PWD,
58
+ NODE_ENV: "production",
59
+ VITE_BUILD_MODE: "true",
60
+ APPLICATION: name || "catalyst_app",
61
+ NODE_OPTIONS: `--loader ${loaderPath}`,
62
+ ...argumentsObject,
63
+ filterKeys: JSON.stringify([
64
+ "src_path",
65
+ "NODE_ENV",
66
+ "VITE_BUILD_MODE",
67
+ "APPLICATION",
68
+ ...Object.keys(argumentsObject),
69
+ ]),
70
+ }
71
+
72
+ const serverBuildCommand = `vite build --config ./dist/vite/vite.config.server.js --ssr`
73
+ const clientBuildCommand = `vite build --config ./dist/vite/vite.config.client.js`
74
+ const spawnBase = {
75
+ cwd: dirname,
76
+ stdio: "inherit",
77
+ }
78
+
79
+ console.log("๐Ÿ”ง๐Ÿ“ฆ Building server and client bundles in parallel...")
80
+
81
+ try {
82
+ await Promise.all([
83
+ runBuildStep(serverBuildCommand, {
84
+ ...spawnBase,
85
+ env: { ...baseEnv, CATALYST_VITE_CACHE_ID: "ssr" },
86
+ }),
87
+ runBuildStep(clientBuildCommand, {
88
+ ...spawnBase,
89
+ env: { ...baseEnv, CATALYST_VITE_CACHE_ID: "client" },
90
+ }),
91
+ ])
92
+ } catch {
93
+ console.error("โŒ Build failed!")
94
+ process.exit(1)
95
+ }
96
+
97
+ console.log("โœ… Server and client builds completed!")
98
+
99
+ await runBuildStep("node ./dist/scripts/generateOfflineManifest.js", {
100
+ ...spawnBase,
101
+ env: baseEnv,
102
+ })
103
+
104
+ console.log("๐ŸŽ‰ Build completed successfully!")
105
+ console.log("๐Ÿ“ Built files are located in the 'build' directory")
106
+ console.log("๐Ÿš€ Run 'npm run serve' to start the production server")
107
+ }
108
+
109
+ build().catch((err) => {
110
+ console.error(err)
111
+ process.exit(1)
112
+ })
@@ -1 +1,3 @@
1
- "use strict";if(process.versions.node.split(".")[0]<20){console.error("\x1b[31m%s\x1b[0m","use node version >=20");}
1
+ if (process.versions.node.split(".")[0] < 20) {
2
+ console.error("\x1b[31m%s\x1b[0m", "use node version >=20")
3
+ }
@@ -1 +1,30 @@
1
- "use strict";const fs=require("fs");const path=require("path");function cleanCache(){const catalystCacheDir=path.join(process.cwd(),"node_modules/catalyst-core");const webpackCacheDir=path.join(catalystCacheDir,".cache/webpack");const loadableStats=path.join(catalystCacheDir,"loadable-stats.json");let cleaned=false;if(fs.existsSync(webpackCacheDir)){fs.rmSync(webpackCacheDir,{recursive:true,force:true});console.log("[Catalyst] Removed webpack filesystem cache.");cleaned=true;}if(fs.existsSync(loadableStats)){fs.rmSync(loadableStats);console.log("[Catalyst] Removed loadable-stats.json.");cleaned=true;}if(!cleaned){console.log("[Catalyst] Nothing to clean โ€” cache is already empty.");}else{console.log("[Catalyst] Clean complete. Next dev start will be a full rebuild.");}}cleanCache();
1
+ const fs = require("fs")
2
+ const path = require("path")
3
+
4
+ function cleanCache() {
5
+ const catalystCacheDir = path.join(process.cwd(), "node_modules/catalyst-core")
6
+ const webpackCacheDir = path.join(catalystCacheDir, ".cache/webpack")
7
+ const loadableStats = path.join(catalystCacheDir, "loadable-stats.json")
8
+
9
+ let cleaned = false
10
+
11
+ if (fs.existsSync(webpackCacheDir)) {
12
+ fs.rmSync(webpackCacheDir, { recursive: true, force: true })
13
+ console.log("[Catalyst] Removed webpack filesystem cache.")
14
+ cleaned = true
15
+ }
16
+
17
+ if (fs.existsSync(loadableStats)) {
18
+ fs.rmSync(loadableStats)
19
+ console.log("[Catalyst] Removed loadable-stats.json.")
20
+ cleaned = true
21
+ }
22
+
23
+ if (!cleaned) {
24
+ console.log("[Catalyst] Nothing to clean โ€” cache is already empty.")
25
+ } else {
26
+ console.log("[Catalyst] Clean complete. Next dev start will be a full rebuild.")
27
+ }
28
+ }
29
+
30
+ cleanCache()