@holoscript/core 1.0.0-alpha.2 → 2.0.0

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 (74) hide show
  1. package/package.json +2 -2
  2. package/src/HoloScript2DParser.js +227 -0
  3. package/src/HoloScript2DParser.ts +5 -0
  4. package/src/HoloScriptCodeParser.js +1102 -0
  5. package/src/HoloScriptCodeParser.ts +145 -20
  6. package/src/HoloScriptDebugger.js +458 -0
  7. package/src/HoloScriptParser.js +338 -0
  8. package/src/HoloScriptPlusParser.js +371 -0
  9. package/src/HoloScriptPlusParser.ts +543 -0
  10. package/src/HoloScriptRuntime.js +1399 -0
  11. package/src/HoloScriptRuntime.test.js +351 -0
  12. package/src/HoloScriptRuntime.ts +17 -3
  13. package/src/HoloScriptTypeChecker.js +356 -0
  14. package/src/__tests__/GraphicsServices.test.js +357 -0
  15. package/src/__tests__/GraphicsServices.test.ts +427 -0
  16. package/src/__tests__/HoloScriptPlusParser.test.js +317 -0
  17. package/src/__tests__/HoloScriptPlusParser.test.ts +392 -0
  18. package/src/__tests__/integration.test.js +336 -0
  19. package/src/__tests__/performance.bench.js +218 -0
  20. package/src/__tests__/type-checker.test.js +60 -0
  21. package/src/__tests__/type-checker.test.ts +73 -0
  22. package/src/index.js +217 -0
  23. package/src/index.ts +158 -18
  24. package/src/interop/Interoperability.js +413 -0
  25. package/src/interop/Interoperability.ts +494 -0
  26. package/src/logger.js +42 -0
  27. package/src/parser/EnhancedParser.js +205 -0
  28. package/src/parser/EnhancedParser.ts +251 -0
  29. package/src/parser/HoloScriptPlusParser.js +928 -0
  30. package/src/parser/HoloScriptPlusParser.ts +1089 -0
  31. package/src/runtime/HoloScriptPlusRuntime.js +674 -0
  32. package/src/runtime/HoloScriptPlusRuntime.ts +861 -0
  33. package/src/runtime/PerformanceTelemetry.js +323 -0
  34. package/src/runtime/PerformanceTelemetry.ts +467 -0
  35. package/src/runtime/RuntimeOptimization.js +361 -0
  36. package/src/runtime/RuntimeOptimization.ts +416 -0
  37. package/src/services/HololandGraphicsPipelineService.js +506 -0
  38. package/src/services/HololandGraphicsPipelineService.ts +662 -0
  39. package/src/services/PlatformPerformanceOptimizer.js +356 -0
  40. package/src/services/PlatformPerformanceOptimizer.ts +503 -0
  41. package/src/state/ReactiveState.js +427 -0
  42. package/src/state/ReactiveState.ts +572 -0
  43. package/src/tools/DeveloperExperience.js +376 -0
  44. package/src/tools/DeveloperExperience.ts +438 -0
  45. package/src/traits/AIDriverTrait.js +322 -0
  46. package/src/traits/AIDriverTrait.test.js +329 -0
  47. package/src/traits/AIDriverTrait.test.ts +357 -0
  48. package/src/traits/AIDriverTrait.ts +474 -0
  49. package/src/traits/LightingTrait.js +313 -0
  50. package/src/traits/LightingTrait.test.js +410 -0
  51. package/src/traits/LightingTrait.test.ts +462 -0
  52. package/src/traits/LightingTrait.ts +505 -0
  53. package/src/traits/MaterialTrait.js +194 -0
  54. package/src/traits/MaterialTrait.test.js +286 -0
  55. package/src/traits/MaterialTrait.test.ts +329 -0
  56. package/src/traits/MaterialTrait.ts +324 -0
  57. package/src/traits/RenderingTrait.js +356 -0
  58. package/src/traits/RenderingTrait.test.js +363 -0
  59. package/src/traits/RenderingTrait.test.ts +427 -0
  60. package/src/traits/RenderingTrait.ts +555 -0
  61. package/src/traits/VRTraitSystem.js +740 -0
  62. package/src/traits/VRTraitSystem.ts +1040 -0
  63. package/src/traits/VoiceInputTrait.js +284 -0
  64. package/src/traits/VoiceInputTrait.test.js +226 -0
  65. package/src/traits/VoiceInputTrait.test.ts +252 -0
  66. package/src/traits/VoiceInputTrait.ts +401 -0
  67. package/src/types/AdvancedTypeSystem.js +226 -0
  68. package/src/types/AdvancedTypeSystem.ts +494 -0
  69. package/src/types/HoloScriptPlus.d.ts +853 -0
  70. package/src/types.js +6 -0
  71. package/src/types.ts +96 -1
  72. package/tsconfig.json +1 -1
  73. package/tsup.config.d.ts +2 -0
  74. package/tsup.config.js +18 -0
@@ -0,0 +1,467 @@
1
+ /**
2
+ * @holoscript/core Performance Telemetry
3
+ *
4
+ * Real-time performance monitoring, profiling, and metrics collection
5
+ * Exports metrics to analytics platforms and provides performance budgets
6
+ */
7
+
8
+ export type MetricType = 'gauge' | 'counter' | 'histogram' | 'timer';
9
+ export type SeverityLevel = 'info' | 'warning' | 'critical';
10
+
11
+ /**
12
+ * Performance metric
13
+ */
14
+ export interface Metric {
15
+ name: string;
16
+ type: MetricType;
17
+ value: number;
18
+ timestamp: number;
19
+ tags?: Record<string, string>;
20
+ unit?: string;
21
+ }
22
+
23
+ /**
24
+ * Performance budget threshold
25
+ */
26
+ export interface PerformanceBudget {
27
+ metricName: string;
28
+ maxValue: number;
29
+ severity: SeverityLevel;
30
+ enabled: boolean;
31
+ }
32
+
33
+ /**
34
+ * Frame timing information
35
+ */
36
+ export interface FrameTiming {
37
+ frameNumber: number;
38
+ fps: number;
39
+ frameDuration: number; // ms
40
+ cpuTime: number; // ms
41
+ gpuTime: number; // ms
42
+ renderTime: number; // ms
43
+ logicTime: number; // ms
44
+ timestamp: number;
45
+ }
46
+
47
+ /**
48
+ * Memory snapshot
49
+ */
50
+ export interface MemorySnapshot {
51
+ usedJSHeapSize: number;
52
+ totalJSHeapSize: number;
53
+ jsHeapSizeLimit: number;
54
+ objectCount: number;
55
+ gcEventsSinceLastSnapshot: number;
56
+ timestamp: number;
57
+ }
58
+
59
+ /**
60
+ * Performance analytics exporter
61
+ */
62
+ export interface AnalyticsExporter {
63
+ export(metrics: Metric[]): Promise<void>;
64
+ flush(): Promise<void>;
65
+ }
66
+
67
+ /**
68
+ * PerformanceTelemetry - Monitor and analyze runtime performance
69
+ */
70
+ export class PerformanceTelemetry {
71
+ private metrics: Metric[] = [];
72
+ private budgets: Map<string, PerformanceBudget> = new Map();
73
+ private frameTimings: FrameTiming[] = [];
74
+ private memorySnapshots: MemorySnapshot[] = [];
75
+ private exporters: AnalyticsExporter[] = [];
76
+
77
+ private frameCounter: number = 0;
78
+ private lastFrameTime: number = Date.now();
79
+ private frameTimes: number[] = [];
80
+ private maxFrameHistory: number = 300; // ~5s at 60fps
81
+
82
+ private monitoringEnabled: boolean = false;
83
+ private exportInterval: ReturnType<typeof setInterval> | null = null;
84
+ private exportIntervalMs: number = 10000; // Export every 10s
85
+
86
+ constructor() {
87
+ this.initializeDefaultBudgets();
88
+ }
89
+
90
+ /**
91
+ * Initialize default performance budgets
92
+ */
93
+ private initializeDefaultBudgets(): void {
94
+ // Frame budget: 16.67ms target (60fps)
95
+ this.setBudget({
96
+ metricName: 'frame_duration',
97
+ maxValue: 16.67,
98
+ severity: 'warning',
99
+ enabled: true,
100
+ });
101
+
102
+ // Memory budget: 100MB
103
+ this.setBudget({
104
+ metricName: 'heap_used',
105
+ maxValue: 100 * 1024 * 1024,
106
+ severity: 'warning',
107
+ enabled: true,
108
+ });
109
+
110
+ // Render time budget: 10ms
111
+ this.setBudget({
112
+ metricName: 'render_time',
113
+ maxValue: 10,
114
+ severity: 'warning',
115
+ enabled: true,
116
+ });
117
+ }
118
+
119
+ /**
120
+ * Start performance monitoring
121
+ */
122
+ public startMonitoring(): void {
123
+ if (this.monitoringEnabled) return;
124
+
125
+ this.monitoringEnabled = true;
126
+ this.lastFrameTime = performance.now();
127
+
128
+ // Setup auto-export
129
+ if (this.exporters.length > 0) {
130
+ this.exportInterval = setInterval(() => {
131
+ this.exportMetrics();
132
+ }, this.exportIntervalMs);
133
+ }
134
+
135
+ console.log('Performance monitoring started');
136
+ }
137
+
138
+ /**
139
+ * Stop performance monitoring
140
+ */
141
+ public stopMonitoring(): void {
142
+ if (!this.monitoringEnabled) return;
143
+
144
+ this.monitoringEnabled = false;
145
+
146
+ if (this.exportInterval) {
147
+ clearInterval(this.exportInterval);
148
+ this.exportInterval = null;
149
+ }
150
+
151
+ console.log('Performance monitoring stopped');
152
+ }
153
+
154
+ /**
155
+ * Record frame timing
156
+ */
157
+ public recordFrame(
158
+ cpuTime: number,
159
+ gpuTime: number,
160
+ renderTime: number,
161
+ logicTime: number
162
+ ): void {
163
+ if (!this.monitoringEnabled) return;
164
+
165
+ const now = performance.now();
166
+ const frameDuration = now - this.lastFrameTime;
167
+ const fps = Math.round(1000 / frameDuration);
168
+
169
+ this.frameTimes.push(frameDuration);
170
+ if (this.frameTimes.length > this.maxFrameHistory) {
171
+ this.frameTimes.shift();
172
+ }
173
+
174
+ const timing: FrameTiming = {
175
+ frameNumber: this.frameCounter++,
176
+ fps,
177
+ frameDuration,
178
+ cpuTime,
179
+ gpuTime,
180
+ renderTime,
181
+ logicTime,
182
+ timestamp: now,
183
+ };
184
+
185
+ this.frameTimings.push(timing);
186
+
187
+ // Record metrics
188
+ this.recordMetric({
189
+ name: 'frame_duration',
190
+ type: 'gauge',
191
+ value: frameDuration,
192
+ unit: 'ms',
193
+ timestamp: now,
194
+ });
195
+
196
+ this.recordMetric({
197
+ name: 'fps',
198
+ type: 'gauge',
199
+ value: fps,
200
+ timestamp: now,
201
+ });
202
+
203
+ this.recordMetric({
204
+ name: 'render_time',
205
+ type: 'gauge',
206
+ value: renderTime,
207
+ unit: 'ms',
208
+ timestamp: now,
209
+ });
210
+
211
+ this.checkBudgets(timing);
212
+ this.lastFrameTime = now;
213
+ }
214
+
215
+ /**
216
+ * Record custom metric
217
+ */
218
+ public recordMetric(metric: Omit<Metric, 'timestamp'> & { timestamp?: number }): void {
219
+ this.metrics.push({
220
+ ...metric,
221
+ timestamp: metric.timestamp ?? Date.now(),
222
+ });
223
+ }
224
+
225
+ /**
226
+ * Record memory snapshot
227
+ */
228
+ public recordMemorySnapshot(): void {
229
+ if (!this.monitoringEnabled) return;
230
+
231
+ const perf = (performance as any).memory;
232
+
233
+ if (!perf) {
234
+ console.warn('Memory profiling not available');
235
+ return;
236
+ }
237
+
238
+ const snapshot: MemorySnapshot = {
239
+ usedJSHeapSize: perf.usedJSHeapSize,
240
+ totalJSHeapSize: perf.totalJSHeapSize,
241
+ jsHeapSizeLimit: perf.jsHeapSizeLimit,
242
+ objectCount: 0, // Would require additional instrumentation
243
+ gcEventsSinceLastSnapshot: 0,
244
+ timestamp: Date.now(),
245
+ };
246
+
247
+ this.memorySnapshots.push(snapshot);
248
+
249
+ // Record as metrics
250
+ this.recordMetric({
251
+ name: 'heap_used',
252
+ type: 'gauge',
253
+ value: snapshot.usedJSHeapSize,
254
+ unit: 'bytes',
255
+ timestamp: snapshot.timestamp,
256
+ });
257
+
258
+ this.recordMetric({
259
+ name: 'heap_total',
260
+ type: 'gauge',
261
+ value: snapshot.totalJSHeapSize,
262
+ unit: 'bytes',
263
+ timestamp: snapshot.timestamp,
264
+ });
265
+
266
+ // Check memory budget
267
+ const budget = this.budgets.get('heap_used');
268
+ if (budget && budget.enabled && snapshot.usedJSHeapSize > budget.maxValue) {
269
+ this.emitBudgetViolation(
270
+ 'heap_used',
271
+ snapshot.usedJSHeapSize,
272
+ budget.maxValue,
273
+ budget.severity
274
+ );
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Check frame metrics against budgets
280
+ */
281
+ private checkBudgets(timing: FrameTiming): void {
282
+ // Check frame duration budget
283
+ const frameBudget = this.budgets.get('frame_duration');
284
+ if (
285
+ frameBudget &&
286
+ frameBudget.enabled &&
287
+ timing.frameDuration > frameBudget.maxValue
288
+ ) {
289
+ this.emitBudgetViolation(
290
+ 'frame_duration',
291
+ timing.frameDuration,
292
+ frameBudget.maxValue,
293
+ frameBudget.severity
294
+ );
295
+ }
296
+
297
+ // Check render time budget
298
+ const renderBudget = this.budgets.get('render_time');
299
+ if (
300
+ renderBudget &&
301
+ renderBudget.enabled &&
302
+ timing.renderTime > renderBudget.maxValue
303
+ ) {
304
+ this.emitBudgetViolation(
305
+ 'render_time',
306
+ timing.renderTime,
307
+ renderBudget.maxValue,
308
+ renderBudget.severity
309
+ );
310
+ }
311
+ }
312
+
313
+ /**
314
+ * Emit budget violation warning
315
+ */
316
+ private emitBudgetViolation(
317
+ metric: string,
318
+ actual: number,
319
+ budget: number,
320
+ severity: SeverityLevel
321
+ ): void {
322
+ const message = `Budget violation: ${metric} = ${actual.toFixed(2)} (budget: ${budget.toFixed(2)})`;
323
+
324
+ if (severity === 'critical') {
325
+ console.error(`❌ ${message}`);
326
+ } else if (severity === 'warning') {
327
+ console.warn(`⚠️ ${message}`);
328
+ } else {
329
+ console.log(`ℹ️ ${message}`);
330
+ }
331
+ }
332
+
333
+ /**
334
+ * Set or update performance budget
335
+ */
336
+ public setBudget(budget: PerformanceBudget): void {
337
+ this.budgets.set(budget.metricName, budget);
338
+ }
339
+
340
+ /**
341
+ * Get average FPS over recent frames
342
+ */
343
+ public getAverageFPS(): number {
344
+ if (this.frameTimes.length === 0) return 0;
345
+
346
+ const avgFrameTime =
347
+ this.frameTimes.reduce((a, b) => a + b, 0) / this.frameTimes.length;
348
+ return Math.round(1000 / avgFrameTime);
349
+ }
350
+
351
+ /**
352
+ * Get memory usage stats
353
+ */
354
+ public getMemoryStats(): {
355
+ used: number;
356
+ total: number;
357
+ limit: number;
358
+ percentage: number;
359
+ } {
360
+ if (this.memorySnapshots.length === 0) {
361
+ return { used: 0, total: 0, limit: 0, percentage: 0 };
362
+ }
363
+
364
+ const latest = this.memorySnapshots[this.memorySnapshots.length - 1];
365
+ return {
366
+ used: latest.usedJSHeapSize,
367
+ total: latest.totalJSHeapSize,
368
+ limit: latest.jsHeapSizeLimit,
369
+ percentage: (latest.usedJSHeapSize / latest.jsHeapSizeLimit) * 100,
370
+ };
371
+ }
372
+
373
+ /**
374
+ * Get recent frame timings
375
+ */
376
+ public getRecentFrameTimings(count: number = 60): FrameTiming[] {
377
+ return this.frameTimings.slice(-count);
378
+ }
379
+
380
+ /**
381
+ * Add analytics exporter
382
+ */
383
+ public addExporter(exporter: AnalyticsExporter): void {
384
+ this.exporters.push(exporter);
385
+ }
386
+
387
+ /**
388
+ * Export all metrics to registered exporters
389
+ */
390
+ public async exportMetrics(): Promise<void> {
391
+ if (this.metrics.length === 0) return;
392
+
393
+ const metricsToExport = [...this.metrics];
394
+ this.metrics = []; // Clear after export
395
+
396
+ for (const exporter of this.exporters) {
397
+ try {
398
+ await exporter.export(metricsToExport);
399
+ } catch (error) {
400
+ console.error('Failed to export metrics:', error);
401
+ }
402
+ }
403
+ }
404
+
405
+ /**
406
+ * Generate performance report
407
+ */
408
+ public generateReport(): string {
409
+ const avgFps = this.getAverageFPS();
410
+ const memStats = this.getMemoryStats();
411
+ const recentFrames = this.getRecentFrameTimings(60);
412
+
413
+ let report = '=== Performance Report ===\n\n';
414
+
415
+ report += `Average FPS: ${avgFps}\n`;
416
+ report += `Recent Frame Count: ${recentFrames.length}\n`;
417
+
418
+ if (recentFrames.length > 0) {
419
+ const avgFrameTime =
420
+ recentFrames.reduce((sum, f) => sum + f.frameDuration, 0) /
421
+ recentFrames.length;
422
+ const maxFrameTime = Math.max(...recentFrames.map((f) => f.frameDuration));
423
+ const minFrameTime = Math.min(...recentFrames.map((f) => f.frameDuration));
424
+
425
+ report += `Frame Time: min=${minFrameTime.toFixed(2)}ms, avg=${avgFrameTime.toFixed(2)}ms, max=${maxFrameTime.toFixed(2)}ms\n`;
426
+ }
427
+
428
+ report += `\nMemory Usage:\n`;
429
+ report += ` Used: ${(memStats.used / 1024 / 1024).toFixed(2)} MB\n`;
430
+ report += ` Total: ${(memStats.total / 1024 / 1024).toFixed(2)} MB\n`;
431
+ report += ` Limit: ${(memStats.limit / 1024 / 1024).toFixed(2)} MB\n`;
432
+ report += ` Percentage: ${memStats.percentage.toFixed(1)}%\n`;
433
+
434
+ report += `\nMetrics Recorded: ${this.metrics.length}\n`;
435
+ report += `Memory Snapshots: ${this.memorySnapshots.length}\n`;
436
+
437
+ return report;
438
+ }
439
+
440
+ /**
441
+ * Dispose and cleanup
442
+ */
443
+ public dispose(): void {
444
+ this.stopMonitoring();
445
+ this.metrics = [];
446
+ this.frameTimings = [];
447
+ this.memorySnapshots = [];
448
+ this.frameTimes = [];
449
+ this.budgets.clear();
450
+ this.exporters = [];
451
+ }
452
+ }
453
+
454
+ /**
455
+ * Singleton instance
456
+ */
457
+ let telemetryInstance: PerformanceTelemetry | null = null;
458
+
459
+ /**
460
+ * Get or create telemetry instance
461
+ */
462
+ export function getPerformanceTelemetry(): PerformanceTelemetry {
463
+ if (!telemetryInstance) {
464
+ telemetryInstance = new PerformanceTelemetry();
465
+ }
466
+ return telemetryInstance;
467
+ }