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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/babel.native.config.cjs +8 -0
  2. package/bin/catalyst.js +49 -105
  3. package/changelog.md +8 -0
  4. package/dist/caching.js +1 -1
  5. package/dist/globals.d.ts +7 -0
  6. package/dist/index.jsx +8 -0
  7. package/dist/logger.js +74 -3
  8. package/dist/native/androidProject/app/build.gradle.kts +45 -4
  9. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeBridge.kt +86 -0
  10. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/BridgeUtils.kt +8 -0
  11. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/FrameworkServerUtils.kt +173 -13
  12. package/dist/native/androidProject/settings.gradle.kts +10 -0
  13. package/dist/native/androidSetup.js +300 -8
  14. package/dist/native/bridge/WebBridge.js +481 -59
  15. package/dist/native/bridge/constants/NativeInterfaces.js +304 -45
  16. package/dist/native/bridge/errors.js +250 -26
  17. package/dist/native/bridge/hooks/index.js +132 -1
  18. package/dist/native/bridge/hooks/useAI.js +94 -0
  19. package/dist/native/bridge/hooks/useCamera.js +347 -9
  20. package/dist/native/bridge/hooks/useDataProtection.js +200 -2
  21. package/dist/native/bridge/hooks/useDeviceInfo.js +71 -2
  22. package/dist/native/bridge/hooks/useFilePicker.js +429 -2
  23. package/dist/native/bridge/hooks/useGoogleSignIn.js +81 -1
  24. package/dist/native/bridge/hooks/useHapticFeedback.js +196 -1
  25. package/dist/native/bridge/hooks/useIntent.js +95 -1
  26. package/dist/native/bridge/hooks/useNativeTransition.js +202 -27
  27. package/dist/native/bridge/hooks/useNetworkStatus.js +84 -3
  28. package/dist/native/bridge/hooks/useNotification.js +318 -2
  29. package/dist/native/bridge/hooks/useSafeArea.js +84 -2
  30. package/dist/native/bridge/hooks/useVideoStream.js +434 -6
  31. package/dist/native/bridge/hooks/utils.js +27 -1
  32. package/dist/native/bridge/hooks.js +16 -1
  33. package/dist/native/bridge/perf/collectors/ApiCollector.js +66 -3
  34. package/dist/native/bridge/perf/collectors/CacheCollector.js +186 -11
  35. package/dist/native/bridge/perf/collectors/HookCollector.js +141 -19
  36. package/dist/native/bridge/perf/collectors/InsightsCollector.js +481 -23
  37. package/dist/native/bridge/perf/collectors/InteractionCollector.js +245 -10
  38. package/dist/native/bridge/perf/collectors/KeyboardCollector.js +107 -8
  39. package/dist/native/bridge/perf/collectors/NavigationCollector.js +273 -32
  40. package/dist/native/bridge/perf/collectors/NetworkTimingCollector.js +178 -2
  41. package/dist/native/bridge/perf/collectors/RenderCollector.js +258 -14
  42. package/dist/native/bridge/perf/collectors/ScrollCollector.js +95 -9
  43. package/dist/native/bridge/perf/collectors/ThreadCollector.js +90 -6
  44. package/dist/native/bridge/perf/core/constants.js +103 -20
  45. package/dist/native/bridge/perf/core/measure.js +179 -30
  46. package/dist/native/bridge/perf/core/session.js +89 -23
  47. package/dist/native/bridge/perf/core/store.js +554 -1
  48. package/dist/native/bridge/perf/core/summary.js +174 -1
  49. package/dist/native/bridge/perf/core/traceExport.js +240 -1
  50. package/dist/native/bridge/perf/core/waterfalls.js +146 -1
  51. package/dist/native/bridge/perf/index.js +359 -38
  52. package/dist/native/bridge/safeArea.js +53 -5
  53. package/dist/native/bridge/standardizedHooks.js +595 -82
  54. package/dist/native/bridge/useBaseHook.js +274 -38
  55. package/dist/native/bridge/utils/CameraUtils.js +201 -56
  56. package/dist/native/bridge/utils/FileObjectConverter.js +129 -18
  57. package/dist/native/bridge/utils/NativeBridge.js +425 -141
  58. package/dist/native/buildAndroid/assets.js +510 -13
  59. package/dist/native/buildAndroid/build.js +296 -19
  60. package/dist/native/buildAndroid/config.js +87 -1
  61. package/dist/native/buildAndroid/index.js +406 -1
  62. package/dist/native/buildAppAndroid.js +34 -2
  63. package/dist/native/buildAppIos.js +62 -2
  64. package/dist/native/buildIos/assets.js +609 -8
  65. package/dist/native/buildIos/build.js +639 -20
  66. package/dist/native/buildIos/config.js +294 -12
  67. package/dist/native/buildIos/index.js +343 -6
  68. package/dist/native/buildIos/plugins.js +343 -16
  69. package/dist/native/internal-plugins/device-info-plugin/android/DeviceInfoPlugin.kt +43 -0
  70. package/dist/native/internal-plugins/device-info-plugin/ios/DeviceInfoPlugin.swift +28 -0
  71. package/dist/native/internal-plugins/device-info-plugin/manifest.json +19 -0
  72. package/dist/native/internalPluginUtils.js +232 -7
  73. package/dist/native/package.json +3 -0
  74. package/dist/native/plugin-bridge/PluginBridge.js +227 -1
  75. package/dist/native/pluginComposerAndroid.js +407 -23
  76. package/dist/native/pluginComposerIos.js +435 -11
  77. package/dist/native/renameAndroidProject.js +1094 -88
  78. package/dist/native/setupEmulatorIos.js +289 -22
  79. package/dist/native/setupServer.js +160 -19
  80. package/dist/native/terminalProgress.js +199 -11
  81. package/dist/native/utils.js +193 -15
  82. package/dist/offline/catalyst-sw.js +145 -1
  83. package/dist/offline/registerServiceWorker.js +33 -1
  84. package/dist/otel.js +375 -46
  85. package/dist/router/ClientRouter.js +14 -2
  86. package/dist/router/ServerRouter.js +9 -1
  87. package/dist/router.js +1 -1
  88. package/dist/scripts/build.js +112 -3
  89. package/dist/scripts/checkVersion.js +3 -1
  90. package/dist/scripts/cleanCache.js +30 -1
  91. package/dist/scripts/generateOfflineManifest.js +116 -1
  92. package/dist/scripts/loadEnvironmentVariables.js +32 -6
  93. package/dist/scripts/plugins.js +309 -1
  94. package/dist/scripts/preServerInit.js +13 -0
  95. package/dist/scripts/scriptUtils.js +54 -3
  96. package/dist/scripts/serve.js +51 -4
  97. package/dist/scripts/start.js +47 -10
  98. package/dist/scripts/validator.js +149 -1
  99. package/dist/sentry.cjs +127 -0
  100. package/dist/sentry.js +125 -5
  101. package/dist/server/expressServer.js +296 -5
  102. package/dist/server/manifestCache.js +36 -0
  103. package/dist/server/renderer/ChunkExtractor.js +144 -0
  104. package/dist/server/renderer/document/Body.jsx +59 -0
  105. package/dist/server/renderer/document/FastRefresh.jsx +20 -0
  106. package/dist/server/renderer/document/Head.jsx +60 -0
  107. package/dist/server/renderer/document/index.jsx +2 -0
  108. package/dist/server/renderer/extract.js +149 -31
  109. package/dist/server/renderer/handler.jsx +450 -0
  110. package/dist/server/renderer/index.js +8 -1
  111. package/dist/server/renderer/render.js +47 -0
  112. package/dist/server/utils/botDetectionMiddleware.js +29 -0
  113. package/dist/server/utils/cjsRequire.js +10 -0
  114. package/dist/server/utils/userAgentUtil.js +87 -9
  115. package/dist/server/utils/validator.js +164 -1
  116. package/dist/vite/FastRefresh.jsx +20 -0
  117. package/dist/vite/inject-cache-key-plugin.js +276 -0
  118. package/dist/vite/loadCustomViteConfig.js +22 -0
  119. package/dist/vite/manifest-categorization-plugin.js +455 -0
  120. package/dist/vite/node-loader.mjs +458 -0
  121. package/dist/vite/scssParams.js +21 -0
  122. package/dist/vite/vite.config.client.js +130 -0
  123. package/dist/vite/vite.config.js +498 -0
  124. package/dist/vite/vite.config.server.js +84 -0
  125. package/dist/web-router/components/MetaTag.jsx +34 -0
  126. package/dist/web-router/components/RouterDataProvider.jsx +332 -0
  127. package/dist/web-router/components/Split.jsx +200 -0
  128. package/dist/web-router/components/SplitInview.jsx +106 -0
  129. package/dist/web-router/components/SsrRequestContext.jsx +14 -0
  130. package/dist/web-router/context.jsx +12 -0
  131. package/dist/web-router/hooks.jsx +72 -0
  132. package/dist/web-router/types/components/MetaTag.d.ts +2 -0
  133. package/dist/web-router/types/components/RouterDataProvider.d.ts +95 -0
  134. package/dist/web-router/types/context.d.ts +14 -0
  135. package/dist/web-router/types/hooks.d.ts +1 -0
  136. package/dist/web-router/types/index.d.ts +3 -0
  137. package/dist/web-router/types/utils/metaDataUtils.d.ts +24 -0
  138. package/dist/web-router/utils/metaDataUtils.jsx +119 -0
  139. package/mcp_v2/conversion-tasks.json +35 -17
  140. package/mcp_v2/knowledge-base.json +176 -17
  141. package/mcp_v2/lib/helpers.js +10 -0
  142. package/mcp_v2/mcp.js +40 -8
  143. package/mcp_v2/package.json +1 -0
  144. package/mcp_v2/tools/build.js +161 -37
  145. package/mcp_v2/tools/conversion.js +106 -5
  146. package/mcp_v2/tools/tasks.js +18 -14
  147. package/package.json +35 -68
  148. package/babel.config.js +0 -32
  149. package/dist/index.js +0 -1
  150. package/dist/scripts/devBuild.js +0 -3
  151. package/dist/scripts/devServe.js +0 -3
  152. package/dist/scripts/loadScriptsBeforeServerStarts.js +0 -4
  153. package/dist/scripts/registerAliases.js +0 -6
  154. package/dist/server/renderer/document/Body.js +0 -11
  155. package/dist/server/renderer/document/Head.js +0 -9
  156. package/dist/server/renderer/document/index.js +0 -1
  157. package/dist/server/renderer/handler.js +0 -47
  158. package/dist/server/startServer.js +0 -57
  159. package/dist/webpack/babel-plugins/remove-client.plugin.js +0 -5
  160. package/dist/webpack/babel-plugins/remove-ssr.plugin.js +0 -5
  161. package/dist/webpack/babel.config.client.js +0 -1
  162. package/dist/webpack/babel.config.ssr.js +0 -1
  163. package/dist/webpack/base.babel.js +0 -7
  164. package/dist/webpack/development.client.babel.js +0 -10
  165. package/dist/webpack/production.client.babel.js +0 -4
  166. package/dist/webpack/production.ssr.babel.js +0 -8
  167. package/dist/webpack/scssParams.js +0 -9
@@ -1,4 +1,11 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.Measure=void 0;var _constants=require("./constants.js");/**
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Measure = void 0;
7
+ var _constants = require("./constants.js");
8
+ /**
2
9
  * measure.js
3
10
  *
4
11
  * Shared _measure() and _colorFor() logic used by every collector.
@@ -9,32 +16,174 @@
9
16
  * - custom data goes in properties[] as [key, value] pairs
10
17
  * - start AND end must both be numeric ms timestamps — passing a mark name
11
18
  * string as start causes silent fallback to Timings row (confirmed Chrome 145)
12
- */const INTERNAL_PROPERTIES=new Set(["simulatorValid"]);const PROPERTY_LABELS={interactionId:"Related tap",parentOperation:"Parent operation",callId:"Call ID",requestId:"Request ID",memoryId:"Memory sample"};const PROPERTY_PRIORITY={interactionId:0,parentOperation:1,outcome:2,ok:3,status:4,durationMs:5,roundTripMs:5,responseMs:5};class Measure{constructor(){// Rolling window of recent LoAF entries — shared across all collectors
13
- // so any collector can check loafOverlap without knowing about others.
14
- this._recentLoafs=[];}/**
15
- * Record a LoAF entry so overlap detection stays current.
16
- * Called by RenderCollector whenever a long-animation-frame fires.
17
- */recordLoaf(start,end){this._recentLoafs.push({start,end});if(this._recentLoafs.length>_constants.THRESHOLD.LOAF_WINDOW){this._recentLoafs.shift();}}overlapsLoaf(startMs,endMs){return this._recentLoafs.some(loaf=>startMs<loaf.end&&endMs>loaf.start);}/**
18
- * Emit a performance.measure() with Chrome DevTools Extensibility API metadata.
19
- *
20
- * @param {string} name - measure name (catalyst:...)
21
- * @param {string} startMark - name of the opening performance.mark()
22
- * @param {number} endTime - end time in ms (performance.now()-space)
23
- * @param {object} detail - arbitrary detail fields added as properties[]
24
- * @param {string} track - Chrome DevTools track name (from TRACK constant)
25
- * @param {string} [color] - override color; if omitted, derived from name+detail
26
- * @param {string} [trackGroup] - Chrome DevTools track group
27
- */emit(name,startMark,endTime,detail={},track,color=null,trackGroup=_constants.TRACK_GROUP){try{const startTime=performance.getEntriesByName(startMark,"mark")[0]?.startTime;if(startTime==null){console.warn("[CatalystPerf] measure skipped — mark not found:",startMark);return;}const resolvedColor=color??this._colorFor(name,detail,startTime,endTime);const properties=this._properties(detail);performance.measure(name,{start:startTime,end:endTime,detail:{devtools:{dataType:"track-entry",trackGroup,track,color:resolvedColor,tooltipText:name,properties}}});}catch(e){console.warn("[CatalystPerf] measure failed:",name,e.message);}}marker(name,startTime,detail={},color=_constants.COLOR.SECONDARY){try{performance.mark(name,{startTime,detail:{devtools:{dataType:"marker",color,tooltipText:name,properties:this._properties(detail)}}});}catch(e){console.warn("[CatalystPerf] marker failed:",name,e.message);}}_properties(detail){return Object.entries(detail).filter(([key,value])=>!INTERNAL_PROPERTIES.has(key)&&value!=null).sort(([left],[right])=>(PROPERTY_PRIORITY[left]??100)-(PROPERTY_PRIORITY[right]??100)).map(([key,value])=>[this._propertyName(key),this._propertyValue(value)]);}_propertyName(key){if(PROPERTY_LABELS[key])return PROPERTY_LABELS[key];return key.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/[._-]+/g," ").replace(/^./,char=>char.toUpperCase());}_propertyValue(value){if(typeof value==="object"){try{return JSON.stringify(value);}catch{return String(value);}}return String(value);}// ─── Color derivation ─────────────────────────────────────────────────────
28
- _colorFor(name,detail,startTime,endTime){const duration=endTime-startTime;// LoAF — always error (it's a bad frame by definition)
29
- if(name.startsWith(_constants.PREFIX.LOAF))return _constants.COLOR.ERROR;// LCP — error if slow
30
- if(name.startsWith(_constants.PREFIX.LCP))return detail.renderTime>_constants.THRESHOLD.LCP_BAD_MS?_constants.COLOR.ERROR:_constants.COLOR.PRIMARY;if(name.startsWith(_constants.PREFIX.FCP))return _constants.COLOR.PRIMARY;// Navigation session
31
- if(name.startsWith(_constants.PREFIX.SESSION_NAV))return duration>_constants.THRESHOLD.NAV_SESSION_BAD_MS?_constants.COLOR.ERROR:_constants.COLOR.PRIMARY;// Route transition
32
- if(name.startsWith(_constants.PREFIX.ROUTE_TRANSITION))return _constants.COLOR.SECONDARY;// Scroll session — error if janky
33
- if(name.startsWith(_constants.PREFIX.SESSION_SCROLL))return detail.loafCount>0?_constants.COLOR.ERROR:_constants.COLOR.PRIMARY;// Keyboard / viewport — informational
34
- if(name.startsWith(_constants.PREFIX.SESSION_KEYBOARD))return _constants.COLOR.SECONDARY;if(name.startsWith(_constants.PREFIX.VIEWPORT_RESIZE))return _constants.COLOR.SECONDARY;// Layout shift
35
- if(name.startsWith(_constants.PREFIX.LAYOUT_SHIFT))return detail.value>_constants.THRESHOLD.CLS_BAD?_constants.COLOR.ERROR:_constants.COLOR.TERTIARY;// Cache spans — color passed explicitly by CacheCollector, this is fallback only
36
- if(name.startsWith(_constants.PREFIX.CACHE+"/")){if(name.includes("/hit|memory|"))return _constants.COLOR.PRIMARY;if(name.includes("/hit|disk|"))return _constants.COLOR.PRIMARY_LIGHT;if(name.includes("/miss|"))return _constants.COLOR.ERROR;return _constants.COLOR.TERTIARY;}// Browser network calls
37
- if(name.startsWith(_constants.PREFIX.NETWORK_TIMING)){if(detail.ok===false||duration>_constants.THRESHOLD.FETCH_SLOW_MS)return _constants.COLOR.ERROR;return _constants.COLOR.SECONDARY;}// Hook spans — error if LoAF burst detected during mount
38
- if(name.startsWith(_constants.PREFIX.HOOK_MOUNT)||name.startsWith(_constants.PREFIX.HOOK_LAZY))return detail.loafCount>0?_constants.COLOR.ERROR:_constants.COLOR.SECONDARY;// Interaction
39
- if(name.startsWith(_constants.PREFIX.INTERACTION)||Number.isFinite(detail.responseMs))return(detail.responseMs??duration)>_constants.THRESHOLD.INTERACTION_SLOW_MS?_constants.COLOR.ERROR:_constants.COLOR.PRIMARY;// Long press — just informational
40
- if(name.startsWith(_constants.PREFIX.LONG_PRESS))return _constants.COLOR.TERTIARY;return _constants.COLOR.SECONDARY;}}exports.Measure=Measure;
19
+ */
20
+
21
+ const INTERNAL_PROPERTIES = new Set(["simulatorValid"]);
22
+ const PROPERTY_LABELS = {
23
+ interactionId: "Related tap",
24
+ parentOperation: "Parent operation",
25
+ callId: "Call ID",
26
+ requestId: "Request ID",
27
+ memoryId: "Memory sample"
28
+ };
29
+ const PROPERTY_PRIORITY = {
30
+ interactionId: 0,
31
+ parentOperation: 1,
32
+ outcome: 2,
33
+ ok: 3,
34
+ status: 4,
35
+ durationMs: 5,
36
+ roundTripMs: 5,
37
+ responseMs: 5
38
+ };
39
+ class Measure {
40
+ constructor() {
41
+ // Rolling window of recent LoAF entries — shared across all collectors
42
+ // so any collector can check loafOverlap without knowing about others.
43
+ this._recentLoafs = [];
44
+ }
45
+
46
+ /**
47
+ * Record a LoAF entry so overlap detection stays current.
48
+ * Called by RenderCollector whenever a long-animation-frame fires.
49
+ */
50
+ recordLoaf(start, end) {
51
+ this._recentLoafs.push({
52
+ start,
53
+ end
54
+ });
55
+ if (this._recentLoafs.length > _constants.THRESHOLD.LOAF_WINDOW) {
56
+ this._recentLoafs.shift();
57
+ }
58
+ }
59
+ overlapsLoaf(startMs, endMs) {
60
+ return this._recentLoafs.some(loaf => startMs < loaf.end && endMs > loaf.start);
61
+ }
62
+
63
+ /**
64
+ * Emit a performance.measure() with Chrome DevTools Extensibility API metadata.
65
+ *
66
+ * @param {string} name - measure name (catalyst:...)
67
+ * @param {string} startMark - name of the opening performance.mark()
68
+ * @param {number} endTime - end time in ms (performance.now()-space)
69
+ * @param {object} detail - arbitrary detail fields added as properties[]
70
+ * @param {string} track - Chrome DevTools track name (from TRACK constant)
71
+ * @param {string} [color] - override color; if omitted, derived from name+detail
72
+ * @param {string} [trackGroup] - Chrome DevTools track group
73
+ */
74
+ emit(name, startMark, endTime, detail = {}, track, color = null, trackGroup = _constants.TRACK_GROUP) {
75
+ try {
76
+ const startTime = performance.getEntriesByName(startMark, "mark")[0]?.startTime;
77
+ if (startTime == null) {
78
+ console.warn("[CatalystPerf] measure skipped — mark not found:", startMark);
79
+ return;
80
+ }
81
+ const resolvedColor = color ?? this._colorFor(name, detail, startTime, endTime);
82
+ const properties = this._properties(detail);
83
+ performance.measure(name, {
84
+ start: startTime,
85
+ end: endTime,
86
+ detail: {
87
+ devtools: {
88
+ dataType: "track-entry",
89
+ trackGroup,
90
+ track,
91
+ color: resolvedColor,
92
+ tooltipText: name,
93
+ properties
94
+ }
95
+ }
96
+ });
97
+ } catch (e) {
98
+ console.warn("[CatalystPerf] measure failed:", name, e.message);
99
+ }
100
+ }
101
+ marker(name, startTime, detail = {}, color = _constants.COLOR.SECONDARY) {
102
+ try {
103
+ performance.mark(name, {
104
+ startTime,
105
+ detail: {
106
+ devtools: {
107
+ dataType: "marker",
108
+ color,
109
+ tooltipText: name,
110
+ properties: this._properties(detail)
111
+ }
112
+ }
113
+ });
114
+ } catch (e) {
115
+ console.warn("[CatalystPerf] marker failed:", name, e.message);
116
+ }
117
+ }
118
+ _properties(detail) {
119
+ return Object.entries(detail).filter(([key, value]) => !INTERNAL_PROPERTIES.has(key) && value != null).sort(([left], [right]) => (PROPERTY_PRIORITY[left] ?? 100) - (PROPERTY_PRIORITY[right] ?? 100)).map(([key, value]) => [this._propertyName(key), this._propertyValue(value)]);
120
+ }
121
+ _propertyName(key) {
122
+ if (PROPERTY_LABELS[key]) return PROPERTY_LABELS[key];
123
+ return key.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[._-]+/g, " ").replace(/^./, char => char.toUpperCase());
124
+ }
125
+ _propertyValue(value) {
126
+ if (typeof value === "object") {
127
+ try {
128
+ return JSON.stringify(value);
129
+ } catch {
130
+ return String(value);
131
+ }
132
+ }
133
+ return String(value);
134
+ }
135
+
136
+ // ─── Color derivation ─────────────────────────────────────────────────────
137
+
138
+ _colorFor(name, detail, startTime, endTime) {
139
+ const duration = endTime - startTime;
140
+
141
+ // LoAF — always error (it's a bad frame by definition)
142
+ if (name.startsWith(_constants.PREFIX.LOAF)) return _constants.COLOR.ERROR;
143
+
144
+ // LCP — error if slow
145
+ if (name.startsWith(_constants.PREFIX.LCP)) return detail.renderTime > _constants.THRESHOLD.LCP_BAD_MS ? _constants.COLOR.ERROR : _constants.COLOR.PRIMARY;
146
+ if (name.startsWith(_constants.PREFIX.FCP)) return _constants.COLOR.PRIMARY;
147
+
148
+ // Navigation session
149
+ if (name.startsWith(_constants.PREFIX.SESSION_NAV)) return duration > _constants.THRESHOLD.NAV_SESSION_BAD_MS ? _constants.COLOR.ERROR : _constants.COLOR.PRIMARY;
150
+
151
+ // Route transition
152
+ if (name.startsWith(_constants.PREFIX.ROUTE_TRANSITION)) return _constants.COLOR.SECONDARY;
153
+
154
+ // Scroll session — error if janky
155
+ if (name.startsWith(_constants.PREFIX.SESSION_SCROLL)) return detail.loafCount > 0 ? _constants.COLOR.ERROR : _constants.COLOR.PRIMARY;
156
+
157
+ // Keyboard / viewport — informational
158
+ if (name.startsWith(_constants.PREFIX.SESSION_KEYBOARD)) return _constants.COLOR.SECONDARY;
159
+ if (name.startsWith(_constants.PREFIX.VIEWPORT_RESIZE)) return _constants.COLOR.SECONDARY;
160
+
161
+ // Layout shift
162
+ if (name.startsWith(_constants.PREFIX.LAYOUT_SHIFT)) return detail.value > _constants.THRESHOLD.CLS_BAD ? _constants.COLOR.ERROR : _constants.COLOR.TERTIARY;
163
+
164
+ // Cache spans — color passed explicitly by CacheCollector, this is fallback only
165
+ if (name.startsWith(_constants.PREFIX.CACHE + "/")) {
166
+ if (name.includes("/hit|memory|")) return _constants.COLOR.PRIMARY;
167
+ if (name.includes("/hit|disk|")) return _constants.COLOR.PRIMARY_LIGHT;
168
+ if (name.includes("/miss|")) return _constants.COLOR.ERROR;
169
+ return _constants.COLOR.TERTIARY;
170
+ }
171
+
172
+ // Browser network calls
173
+ if (name.startsWith(_constants.PREFIX.NETWORK_TIMING)) {
174
+ if (detail.ok === false || duration > _constants.THRESHOLD.FETCH_SLOW_MS) return _constants.COLOR.ERROR;
175
+ return _constants.COLOR.SECONDARY;
176
+ }
177
+
178
+ // Hook spans — error if LoAF burst detected during mount
179
+ if (name.startsWith(_constants.PREFIX.HOOK_MOUNT) || name.startsWith(_constants.PREFIX.HOOK_LAZY)) return detail.loafCount > 0 ? _constants.COLOR.ERROR : _constants.COLOR.SECONDARY;
180
+
181
+ // Interaction
182
+ if (name.startsWith(_constants.PREFIX.INTERACTION) || Number.isFinite(detail.responseMs)) return (detail.responseMs ?? duration) > _constants.THRESHOLD.INTERACTION_SLOW_MS ? _constants.COLOR.ERROR : _constants.COLOR.PRIMARY;
183
+
184
+ // Long press — just informational
185
+ if (name.startsWith(_constants.PREFIX.LONG_PRESS)) return _constants.COLOR.TERTIARY;
186
+ return _constants.COLOR.SECONDARY;
187
+ }
188
+ }
189
+ exports.Measure = Measure;
@@ -1,4 +1,10 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.Session=void 0;/**
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Session = void 0;
7
+ /**
2
8
  * session.js
3
9
  *
4
10
  * Reusable open/close session pattern.
@@ -10,25 +16,85 @@
10
16
  * session.close({ loafCount: 3, janky: true })
11
17
  *
12
18
  * The session owns its own start mark so callers don't track mark names.
13
- */class Session{/**
14
- * @param {string} name - base measure name (catalyst:session/...)
15
- * @param {Measure} measure - shared Measure instance
16
- * @param {string} track - Chrome DevTools track name
17
- */constructor(name,measure,track){this._name=name;this._measure=measure;this._track=track;this._state=null;// { startMark, startTime, ...extra } | null
18
- }get isOpen(){return this._state!==null;}get startTime(){return this._state?.startTime??null;}/**
19
- * Open the session.
20
- * @param {object} extra - any fields to carry in state (e.g. loafCount)
21
- * @param {number} [atTime] - override start time (default: performance.now())
22
- */open(extra={},atTime=null){if(this._state)return;// already open — ignore double-open
23
- const startTime=atTime??performance.now();const startMark=`${this._name}:start:${Math.round(startTime)}`;performance.mark(startMark,{startTime});this._state={startMark,startTime,...extra};}/**
24
- * Close the session and emit the measure.
25
- * @param {object} detail - fields added to properties[] in DevTools
26
- * @param {number} [atTime] - override end time (default: performance.now())
27
- * @param {string} [color] - override color
28
- */close(detail={},atTime=null,color=null){if(!this._state)return;const{startMark,startTime}=this._state;const endTime=atTime??performance.now();this._state=null;this._measure.emit(this._name,startMark,endTime,{duration:Math.round(endTime-startTime),...detail},this._track,color);}/**
29
- * Read a value stored in session state (e.g. loafCount).
30
- */get(key){return this._state?.[key];}/**
31
- * Update a value in session state without closing.
32
- */set(key,value){if(this._state)this._state[key]=value;}/**
33
- * Increment a numeric counter in session state.
34
- */increment(key){if(this._state)this._state[key]=(this._state[key]??0)+1;}}exports.Session=Session;
19
+ */
20
+
21
+ class Session {
22
+ /**
23
+ * @param {string} name - base measure name (catalyst:session/...)
24
+ * @param {Measure} measure - shared Measure instance
25
+ * @param {string} track - Chrome DevTools track name
26
+ */
27
+ constructor(name, measure, track) {
28
+ this._name = name;
29
+ this._measure = measure;
30
+ this._track = track;
31
+ this._state = null; // { startMark, startTime, ...extra } | null
32
+ }
33
+ get isOpen() {
34
+ return this._state !== null;
35
+ }
36
+ get startTime() {
37
+ return this._state?.startTime ?? null;
38
+ }
39
+
40
+ /**
41
+ * Open the session.
42
+ * @param {object} extra - any fields to carry in state (e.g. loafCount)
43
+ * @param {number} [atTime] - override start time (default: performance.now())
44
+ */
45
+ open(extra = {}, atTime = null) {
46
+ if (this._state) return; // already open — ignore double-open
47
+ const startTime = atTime ?? performance.now();
48
+ const startMark = `${this._name}:start:${Math.round(startTime)}`;
49
+ performance.mark(startMark, {
50
+ startTime
51
+ });
52
+ this._state = {
53
+ startMark,
54
+ startTime,
55
+ ...extra
56
+ };
57
+ }
58
+
59
+ /**
60
+ * Close the session and emit the measure.
61
+ * @param {object} detail - fields added to properties[] in DevTools
62
+ * @param {number} [atTime] - override end time (default: performance.now())
63
+ * @param {string} [color] - override color
64
+ */
65
+ close(detail = {}, atTime = null, color = null) {
66
+ if (!this._state) return;
67
+ const {
68
+ startMark,
69
+ startTime
70
+ } = this._state;
71
+ const endTime = atTime ?? performance.now();
72
+ this._state = null;
73
+ this._measure.emit(this._name, startMark, endTime, {
74
+ duration: Math.round(endTime - startTime),
75
+ ...detail
76
+ }, this._track, color);
77
+ }
78
+
79
+ /**
80
+ * Read a value stored in session state (e.g. loafCount).
81
+ */
82
+ get(key) {
83
+ return this._state?.[key];
84
+ }
85
+
86
+ /**
87
+ * Update a value in session state without closing.
88
+ */
89
+ set(key, value) {
90
+ if (this._state) this._state[key] = value;
91
+ }
92
+
93
+ /**
94
+ * Increment a numeric counter in session state.
95
+ */
96
+ increment(key) {
97
+ if (this._state) this._state[key] = (this._state[key] ?? 0) + 1;
98
+ }
99
+ }
100
+ exports.Session = Session;