@holoscript/std 6.0.3 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/README.md +8 -0
  2. package/dist/chunk-DGUM43GV.js +11 -0
  3. package/dist/chunk-DGUM43GV.js.map +1 -0
  4. package/dist/{chunk-PFX2JM4X.js → chunk-FAMOLKH3.js} +2 -1
  5. package/dist/{chunk-PFX2JM4X.js.map → chunk-FAMOLKH3.js.map} +1 -1
  6. package/dist/{chunk-7HVUYGPS.js → chunk-SOKH6FJ7.js} +37 -5
  7. package/dist/chunk-SOKH6FJ7.js.map +1 -0
  8. package/dist/{chunk-W2Q3LUCM.js → chunk-XJIFG7G3.js} +3 -3
  9. package/dist/chunk-XJIFG7G3.js.map +1 -0
  10. package/dist/collections.cjs +1 -0
  11. package/dist/collections.cjs.map +1 -1
  12. package/dist/collections.js +2 -1
  13. package/dist/fs/fs.d.ts +288 -0
  14. package/dist/fs/fs.d.ts.map +1 -0
  15. package/dist/fs/index.cjs +1049 -0
  16. package/dist/fs/index.cjs.map +1 -0
  17. package/dist/fs/index.d.ts +51 -0
  18. package/dist/fs/index.d.ts.map +1 -0
  19. package/dist/fs/index.js +918 -0
  20. package/dist/fs/index.js.map +1 -0
  21. package/dist/fs/path.d.ts +135 -0
  22. package/dist/fs/path.d.ts.map +1 -0
  23. package/dist/fs/sandbox.d.ts +49 -0
  24. package/dist/fs/sandbox.d.ts.map +1 -0
  25. package/dist/fs/watch.d.ts +133 -0
  26. package/dist/fs/watch.d.ts.map +1 -0
  27. package/dist/index.cjs +54 -7
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.js +19 -4
  30. package/dist/index.js.map +1 -1
  31. package/dist/math.cjs +21 -2
  32. package/dist/math.cjs.map +1 -1
  33. package/dist/math.js +2 -1
  34. package/dist/string.cjs +2 -2
  35. package/dist/string.cjs.map +1 -1
  36. package/dist/string.js +2 -1
  37. package/dist/time.js +1 -0
  38. package/dist/traits/EconomicPrimitives.js +1 -0
  39. package/dist/traits/EconomicTraits.js +1 -0
  40. package/dist/traits/VRRTraits.d.ts +2 -2
  41. package/dist/types.d.ts.map +1 -1
  42. package/package.json +24 -9
  43. package/CHANGELOG.md +0 -7
  44. package/dist/__tests__/EconomicPrimitives.test.d.ts +0 -2
  45. package/dist/__tests__/EconomicPrimitives.test.d.ts.map +0 -1
  46. package/dist/__tests__/EconomicTraits.test.d.ts +0 -2
  47. package/dist/__tests__/EconomicTraits.test.d.ts.map +0 -1
  48. package/dist/__tests__/SimulationLabPrimitives.test.d.ts +0 -2
  49. package/dist/__tests__/SimulationLabPrimitives.test.d.ts.map +0 -1
  50. package/dist/__tests__/collections.test.d.ts +0 -2
  51. package/dist/__tests__/collections.test.d.ts.map +0 -1
  52. package/dist/__tests__/events.test.d.ts +0 -2
  53. package/dist/__tests__/events.test.d.ts.map +0 -1
  54. package/dist/__tests__/index.test.d.ts +0 -2
  55. package/dist/__tests__/index.test.d.ts.map +0 -1
  56. package/dist/__tests__/materials.test.d.ts +0 -2
  57. package/dist/__tests__/materials.test.d.ts.map +0 -1
  58. package/dist/__tests__/math.test.d.ts +0 -2
  59. package/dist/__tests__/math.test.d.ts.map +0 -1
  60. package/dist/__tests__/physics.test.d.ts +0 -2
  61. package/dist/__tests__/physics.test.d.ts.map +0 -1
  62. package/dist/__tests__/spatial.test.d.ts +0 -2
  63. package/dist/__tests__/spatial.test.d.ts.map +0 -1
  64. package/dist/__tests__/standard-library-fundamentals.test.d.ts +0 -2
  65. package/dist/__tests__/standard-library-fundamentals.test.d.ts.map +0 -1
  66. package/dist/__tests__/string-and-time-utilities.test.d.ts +0 -2
  67. package/dist/__tests__/string-and-time-utilities.test.d.ts.map +0 -1
  68. package/dist/__tests__/string-decoupled.test.d.ts +0 -2
  69. package/dist/__tests__/string-decoupled.test.d.ts.map +0 -1
  70. package/dist/__tests__/string.test.d.ts +0 -2
  71. package/dist/__tests__/string.test.d.ts.map +0 -1
  72. package/dist/__tests__/time.test.d.ts +0 -2
  73. package/dist/__tests__/time.test.d.ts.map +0 -1
  74. package/dist/chunk-7HVUYGPS.js.map +0 -1
  75. package/dist/chunk-W2Q3LUCM.js.map +0 -1
  76. package/dist/string.basic.test.d.ts +0 -5
  77. package/dist/string.basic.test.d.ts.map +0 -1
  78. package/dist/string.test.d.ts +0 -5
  79. package/dist/string.test.d.ts.map +0 -1
  80. package/dist/traits/__tests__/ARTraits.test.d.ts +0 -2
  81. package/dist/traits/__tests__/ARTraits.test.d.ts.map +0 -1
  82. package/dist/traits/__tests__/EconomicPrimitives.test.d.ts +0 -2
  83. package/dist/traits/__tests__/EconomicPrimitives.test.d.ts.map +0 -1
  84. package/dist/traits/__tests__/EconomicTraits.test.d.ts +0 -2
  85. package/dist/traits/__tests__/EconomicTraits.test.d.ts.map +0 -1
  86. package/error-utf8.log +0 -6
  87. package/error.log +0 -0
  88. package/src/__tests__/EconomicPrimitives.test.ts +0 -690
  89. package/src/__tests__/EconomicTraits.test.ts +0 -425
  90. package/src/__tests__/SimulationLabPrimitives.test.ts +0 -415
  91. package/src/__tests__/collections.test.ts +0 -182
  92. package/src/__tests__/events.test.ts +0 -135
  93. package/src/__tests__/index.test.ts +0 -14
  94. package/src/__tests__/materials.test.ts +0 -84
  95. package/src/__tests__/math.test.ts +0 -246
  96. package/src/__tests__/physics.test.ts +0 -83
  97. package/src/__tests__/spatial.test.ts +0 -333
  98. package/src/__tests__/standard-library-fundamentals.test.ts +0 -1301
  99. package/src/__tests__/string-and-time-utilities.test.ts +0 -1070
  100. package/src/__tests__/string-decoupled.test.ts +0 -14
  101. package/src/__tests__/string.test.ts +0 -164
  102. package/src/__tests__/time.test.ts +0 -110
  103. package/src/collections.ts +0 -850
  104. package/src/events.ts +0 -88
  105. package/src/index.ts +0 -474
  106. package/src/materials.ts +0 -109
  107. package/src/math.ts +0 -674
  108. package/src/physics.ts +0 -141
  109. package/src/spatial.ts +0 -320
  110. package/src/string.basic.test.ts +0 -14
  111. package/src/string.test.ts +0 -335
  112. package/src/string.ts +0 -531
  113. package/src/time.ts +0 -621
  114. package/src/traits/ARTraits.ts +0 -103
  115. package/src/traits/EconomicPrimitives.ts +0 -755
  116. package/src/traits/EconomicTraits.ts +0 -552
  117. package/src/traits/IoTTraits.ts +0 -102
  118. package/src/traits/SimulationLabPrimitives.ts +0 -650
  119. package/src/traits/SimulationLabTraits.ts +0 -191
  120. package/src/traits/VRRTraits.ts +0 -326
  121. package/src/traits/__tests__/ARTraits.test.ts +0 -14
  122. package/src/traits/__tests__/EconomicPrimitives.test.ts +0 -14
  123. package/src/traits/__tests__/EconomicTraits.test.ts +0 -14
  124. package/src/types.ts +0 -411
  125. package/std_error.log +0 -5
  126. package/tsconfig.json +0 -18
  127. package/tsup.config.ts +0 -17
  128. package/vitest.config.ts +0 -10
package/src/time.ts DELETED
@@ -1,621 +0,0 @@
1
- /**
2
- * @holoscript/std - Time Module
3
- *
4
- * Time, timer, and scheduling utilities for HoloScript Plus programs.
5
- */
6
-
7
- /**
8
- * Get current timestamp in milliseconds
9
- */
10
- export function now(): number {
11
- return Date.now();
12
- }
13
-
14
- /**
15
- * Get high-resolution timestamp (for performance measurement)
16
- */
17
- export function hrTime(): number {
18
- if (typeof performance !== 'undefined') {
19
- return performance.now();
20
- }
21
- return Date.now();
22
- }
23
-
24
- /**
25
- * Sleep for a specified number of milliseconds
26
- */
27
- export function sleep(ms: number): Promise<void> {
28
- return new Promise((resolve) => setTimeout(resolve, ms));
29
- }
30
-
31
- /**
32
- * Wait until a condition is true
33
- */
34
- export async function waitUntil(
35
- condition: () => boolean | Promise<boolean>,
36
- options: { timeout?: number; interval?: number } = {}
37
- ): Promise<void> {
38
- const { timeout = 30000, interval = 100 } = options;
39
- const startTime = now();
40
-
41
- while (true) {
42
- if (await condition()) return;
43
- if (now() - startTime > timeout) {
44
- throw new Error('waitUntil timeout');
45
- }
46
- await sleep(interval);
47
- }
48
- }
49
-
50
- /**
51
- * Execute a function with timeout
52
- */
53
- export async function withTimeout<T>(fn: () => Promise<T>, ms: number): Promise<T> {
54
- return Promise.race([
55
- fn(),
56
- new Promise<T>((_, reject) => setTimeout(() => reject(new Error('Timeout')), ms)),
57
- ]);
58
- }
59
-
60
- /**
61
- * Retry a function with exponential backoff
62
- */
63
- export async function retry<T>(
64
- fn: () => Promise<T>,
65
- options: {
66
- maxAttempts?: number;
67
- initialDelay?: number;
68
- maxDelay?: number;
69
- factor?: number;
70
- onRetry?: (error: Error, attempt: number) => void;
71
- } = {}
72
- ): Promise<T> {
73
- const { maxAttempts = 3, initialDelay = 1000, maxDelay = 30000, factor = 2, onRetry } = options;
74
-
75
- let lastError: Error;
76
- let delay = initialDelay;
77
-
78
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
79
- try {
80
- return await fn();
81
- } catch (error) {
82
- lastError = error instanceof Error ? error : new Error(String(error));
83
-
84
- if (attempt === maxAttempts) break;
85
-
86
- onRetry?.(lastError, attempt);
87
- await sleep(delay);
88
- delay = Math.min(delay * factor, maxDelay);
89
- }
90
- }
91
-
92
- throw lastError!;
93
- }
94
-
95
- /**
96
- * Debounce a function
97
- */
98
- export function debounce<T extends (...args: unknown[]) => unknown>(fn: T, ms: number): T {
99
- let timeoutId: ReturnType<typeof setTimeout> | null = null;
100
-
101
- return ((...args: unknown[]) => {
102
- if (timeoutId) clearTimeout(timeoutId);
103
- timeoutId = setTimeout(() => {
104
- timeoutId = null;
105
- fn(...args);
106
- }, ms);
107
- }) as T;
108
- }
109
-
110
- /**
111
- * Throttle a function
112
- */
113
- export function throttle<T extends (...args: unknown[]) => unknown>(fn: T, ms: number): T {
114
- let lastCall = 0;
115
- let timeoutId: ReturnType<typeof setTimeout> | null = null;
116
-
117
- return ((...args: unknown[]) => {
118
- const elapsed = now() - lastCall;
119
-
120
- if (elapsed >= ms) {
121
- lastCall = now();
122
- fn(...args);
123
- } else if (!timeoutId) {
124
- timeoutId = setTimeout(() => {
125
- lastCall = now();
126
- timeoutId = null;
127
- fn(...args);
128
- }, ms - elapsed);
129
- }
130
- }) as T;
131
- }
132
-
133
- /**
134
- * Measure execution time of a function
135
- */
136
- export async function measure<T>(
137
- fn: () => T | Promise<T>
138
- ): Promise<{ result: T; duration: number }> {
139
- const start = hrTime();
140
- const result = await fn();
141
- const duration = hrTime() - start;
142
- return { result, duration };
143
- }
144
-
145
- /**
146
- * Measure execution time and log it
147
- */
148
- export async function timed<T>(label: string, fn: () => T | Promise<T>): Promise<T> {
149
- const start = hrTime();
150
- try {
151
- return await fn();
152
- } finally {
153
- const duration = hrTime() - start;
154
- void duration; // timing available for callers via return value
155
- }
156
- }
157
-
158
- /**
159
- * Simple stopwatch for measuring elapsed time
160
- */
161
- export class Stopwatch {
162
- private startTime: number = 0;
163
- private pausedTime: number = 0;
164
- private running: boolean = false;
165
-
166
- start(): this {
167
- if (!this.running) {
168
- this.startTime = hrTime() - this.pausedTime;
169
- this.running = true;
170
- }
171
- return this;
172
- }
173
-
174
- stop(): number {
175
- if (this.running) {
176
- this.pausedTime = hrTime() - this.startTime;
177
- this.running = false;
178
- }
179
- return this.pausedTime;
180
- }
181
-
182
- reset(): this {
183
- this.startTime = 0;
184
- this.pausedTime = 0;
185
- this.running = false;
186
- return this;
187
- }
188
-
189
- restart(): this {
190
- return this.reset().start();
191
- }
192
-
193
- get elapsed(): number {
194
- if (this.running) {
195
- return hrTime() - this.startTime;
196
- }
197
- return this.pausedTime;
198
- }
199
-
200
- get isRunning(): boolean {
201
- return this.running;
202
- }
203
-
204
- lap(): number {
205
- const elapsed = this.elapsed;
206
- this.restart();
207
- return elapsed;
208
- }
209
- }
210
-
211
- /**
212
- * Interval timer with pause/resume support
213
- */
214
- export class IntervalTimer {
215
- private intervalId: ReturnType<typeof setInterval> | null = null;
216
- private callback: () => void;
217
- private intervalMs: number;
218
- private isPaused: boolean = false;
219
-
220
- constructor(callback: () => void, intervalMs: number) {
221
- this.callback = callback;
222
- this.intervalMs = intervalMs;
223
- }
224
-
225
- start(): this {
226
- if (!this.intervalId && !this.isPaused) {
227
- this.intervalId = setInterval(this.callback, this.intervalMs);
228
- }
229
- return this;
230
- }
231
-
232
- stop(): this {
233
- if (this.intervalId) {
234
- clearInterval(this.intervalId);
235
- this.intervalId = null;
236
- }
237
- this.isPaused = false;
238
- return this;
239
- }
240
-
241
- pause(): this {
242
- if (this.intervalId) {
243
- clearInterval(this.intervalId);
244
- this.intervalId = null;
245
- this.isPaused = true;
246
- }
247
- return this;
248
- }
249
-
250
- resume(): this {
251
- if (this.isPaused) {
252
- this.isPaused = false;
253
- this.intervalId = setInterval(this.callback, this.intervalMs);
254
- }
255
- return this;
256
- }
257
-
258
- get running(): boolean {
259
- return this.intervalId !== null;
260
- }
261
-
262
- get paused(): boolean {
263
- return this.isPaused;
264
- }
265
- }
266
-
267
- /**
268
- * Countdown timer
269
- */
270
- export class CountdownTimer {
271
- private remainingMs: number;
272
- private startTime: number = 0;
273
- private running: boolean = false;
274
- private onTick?: (remaining: number) => void;
275
- private onComplete?: () => void;
276
- private tickIntervalId: ReturnType<typeof setInterval> | null = null;
277
-
278
- constructor(
279
- durationMs: number,
280
- options: {
281
- onTick?: (remaining: number) => void;
282
- onComplete?: () => void;
283
- tickInterval?: number;
284
- } = {}
285
- ) {
286
- this.remainingMs = durationMs;
287
- this.onTick = options.onTick;
288
- this.onComplete = options.onComplete;
289
-
290
- if (options.onTick && options.tickInterval) {
291
- this.tickIntervalId = setInterval(() => {
292
- if (this.running) {
293
- this.onTick?.(this.remaining);
294
- }
295
- }, options.tickInterval);
296
- }
297
- }
298
-
299
- start(): this {
300
- if (!this.running && this.remainingMs > 0) {
301
- this.startTime = hrTime();
302
- this.running = true;
303
- this.scheduleCompletion();
304
- }
305
- return this;
306
- }
307
-
308
- pause(): this {
309
- if (this.running) {
310
- this.remainingMs = Math.max(0, this.remainingMs - (hrTime() - this.startTime));
311
- this.running = false;
312
- }
313
- return this;
314
- }
315
-
316
- resume(): this {
317
- return this.start();
318
- }
319
-
320
- reset(durationMs?: number): this {
321
- this.running = false;
322
- this.remainingMs = durationMs ?? this.remainingMs;
323
- return this;
324
- }
325
-
326
- stop(): this {
327
- this.running = false;
328
- if (this.tickIntervalId) {
329
- clearInterval(this.tickIntervalId);
330
- this.tickIntervalId = null;
331
- }
332
- return this;
333
- }
334
-
335
- get remaining(): number {
336
- if (this.running) {
337
- return Math.max(0, this.remainingMs - (hrTime() - this.startTime));
338
- }
339
- return this.remainingMs;
340
- }
341
-
342
- get isRunning(): boolean {
343
- return this.running;
344
- }
345
-
346
- get isComplete(): boolean {
347
- return this.remaining <= 0;
348
- }
349
-
350
- private scheduleCompletion(): void {
351
- setTimeout(() => {
352
- if (this.running && this.remaining <= 0) {
353
- this.running = false;
354
- this.onComplete?.();
355
- }
356
- }, this.remainingMs);
357
- }
358
- }
359
-
360
- /**
361
- * Frame-based timer for game loops
362
- */
363
- export class FrameTimer {
364
- private lastFrameTime: number = 0;
365
- private deltaTime: number = 0;
366
- private frameCount: number = 0;
367
- private fps: number = 0;
368
- private fpsUpdateInterval: number = 1000;
369
- private lastFpsUpdate: number = 0;
370
- private framesSinceLastFpsUpdate: number = 0;
371
-
372
- /**
373
- * Call at the start of each frame
374
- */
375
- update(): void {
376
- const currentTime = hrTime();
377
-
378
- if (this.lastFrameTime > 0) {
379
- this.deltaTime = (currentTime - this.lastFrameTime) / 1000; // Convert to seconds
380
- }
381
-
382
- this.lastFrameTime = currentTime;
383
- this.frameCount++;
384
- this.framesSinceLastFpsUpdate++;
385
-
386
- // Update FPS calculation
387
- if (currentTime - this.lastFpsUpdate >= this.fpsUpdateInterval) {
388
- this.fps = (this.framesSinceLastFpsUpdate * 1000) / (currentTime - this.lastFpsUpdate);
389
- this.lastFpsUpdate = currentTime;
390
- this.framesSinceLastFpsUpdate = 0;
391
- }
392
- }
393
-
394
- /**
395
- * Get delta time in seconds since last frame
396
- */
397
- get delta(): number {
398
- return this.deltaTime;
399
- }
400
-
401
- /**
402
- * Get delta time in milliseconds since last frame
403
- */
404
- get deltaMs(): number {
405
- return this.deltaTime * 1000;
406
- }
407
-
408
- /**
409
- * Get total frame count
410
- */
411
- get frames(): number {
412
- return this.frameCount;
413
- }
414
-
415
- /**
416
- * Get current FPS (frames per second)
417
- */
418
- get currentFps(): number {
419
- return this.fps;
420
- }
421
-
422
- /**
423
- * Get total elapsed time in seconds
424
- */
425
- get totalTime(): number {
426
- return this.lastFrameTime / 1000;
427
- }
428
-
429
- /**
430
- * Reset the timer
431
- */
432
- reset(): void {
433
- this.lastFrameTime = 0;
434
- this.deltaTime = 0;
435
- this.frameCount = 0;
436
- this.fps = 0;
437
- this.lastFpsUpdate = 0;
438
- this.framesSinceLastFpsUpdate = 0;
439
- }
440
- }
441
-
442
- /**
443
- * Schedule a callback to run after a delay
444
- */
445
- export function schedule(callback: () => void, delayMs: number): () => void {
446
- const timeoutId = setTimeout(callback, delayMs);
447
- return () => clearTimeout(timeoutId);
448
- }
449
-
450
- /**
451
- * Schedule a callback to run at regular intervals
452
- */
453
- export function scheduleInterval(callback: () => void, intervalMs: number): () => void {
454
- const intervalId = setInterval(callback, intervalMs);
455
- return () => clearInterval(intervalId);
456
- }
457
-
458
- /**
459
- * Schedule a callback to run on the next animation frame (browser only)
460
- */
461
- export function scheduleFrame(callback: (timestamp: number) => void): () => void {
462
- if (typeof requestAnimationFrame !== 'undefined') {
463
- const id = requestAnimationFrame(callback);
464
- return () => cancelAnimationFrame(id);
465
- }
466
- // Fallback for non-browser environments
467
- const id = setTimeout(() => callback(hrTime()), 16);
468
- return () => clearTimeout(id);
469
- }
470
-
471
- /**
472
- * Create a ticker that calls a callback at a target frame rate
473
- */
474
- export function createTicker(
475
- callback: (delta: number) => void,
476
- targetFps: number = 60
477
- ): { start: () => void; stop: () => void } {
478
- const frameTime = 1000 / targetFps;
479
- let lastTime = 0;
480
- let running = false;
481
- let animationId: number | ReturnType<typeof setTimeout>;
482
-
483
- const tick = (currentTime: number) => {
484
- if (!running) return;
485
-
486
- if (lastTime > 0) {
487
- const delta = (currentTime - lastTime) / 1000;
488
- callback(delta);
489
- }
490
- lastTime = currentTime;
491
-
492
- if (typeof requestAnimationFrame !== 'undefined') {
493
- animationId = requestAnimationFrame(tick);
494
- } else {
495
- animationId = setTimeout(() => tick(hrTime()), frameTime);
496
- }
497
- };
498
-
499
- return {
500
- start: () => {
501
- if (!running) {
502
- running = true;
503
- lastTime = 0;
504
- if (typeof requestAnimationFrame !== 'undefined') {
505
- animationId = requestAnimationFrame(tick);
506
- } else {
507
- tick(hrTime());
508
- }
509
- }
510
- },
511
- stop: () => {
512
- running = false;
513
- if (typeof cancelAnimationFrame !== 'undefined') {
514
- cancelAnimationFrame(animationId as number);
515
- } else {
516
- clearTimeout(animationId as ReturnType<typeof setTimeout>);
517
- }
518
- },
519
- };
520
- }
521
-
522
- /**
523
- * Date/time formatting utilities
524
- */
525
- export const DateTime = {
526
- /**
527
- * Format a date as ISO string
528
- */
529
- toISO(date: Date = new Date()): string {
530
- return date.toISOString();
531
- },
532
-
533
- /**
534
- * Format a date as local string
535
- */
536
- toLocal(date: Date = new Date()): string {
537
- return date.toLocaleString();
538
- },
539
-
540
- /**
541
- * Format a date using a pattern
542
- * Supports: YYYY, MM, DD, HH, mm, ss, SSS
543
- */
544
- format(date: Date, pattern: string): string {
545
- const pad = (n: number, width: number) => String(n).padStart(width, '0');
546
-
547
- return pattern
548
- .replace('YYYY', String(date.getFullYear()))
549
- .replace('MM', pad(date.getMonth() + 1, 2))
550
- .replace('DD', pad(date.getDate(), 2))
551
- .replace('HH', pad(date.getHours(), 2))
552
- .replace('mm', pad(date.getMinutes(), 2))
553
- .replace('ss', pad(date.getSeconds(), 2))
554
- .replace('SSS', pad(date.getMilliseconds(), 3));
555
- },
556
-
557
- /**
558
- * Parse a date string
559
- */
560
- parse(dateString: string): Date {
561
- return new Date(dateString);
562
- },
563
-
564
- /**
565
- * Get difference between two dates in various units
566
- */
567
- diff(date1: Date, date2: Date, unit: 'ms' | 's' | 'm' | 'h' | 'd' = 'ms'): number {
568
- const diffMs = date1.getTime() - date2.getTime();
569
- switch (unit) {
570
- case 'ms':
571
- return diffMs;
572
- case 's':
573
- return diffMs / 1000;
574
- case 'm':
575
- return diffMs / 60000;
576
- case 'h':
577
- return diffMs / 3600000;
578
- case 'd':
579
- return diffMs / 86400000;
580
- }
581
- },
582
-
583
- /**
584
- * Add time to a date
585
- */
586
- add(date: Date, amount: number, unit: 'ms' | 's' | 'm' | 'h' | 'd'): Date {
587
- const _ms = DateTime.diff(new Date(amount), new Date(0), 'ms');
588
- const multipliers = { ms: 1, s: 1000, m: 60000, h: 3600000, d: 86400000 };
589
- return new Date(date.getTime() + amount * multipliers[unit]);
590
- },
591
-
592
- /**
593
- * Check if a date is today
594
- */
595
- isToday(date: Date): boolean {
596
- const today = new Date();
597
- return (
598
- date.getDate() === today.getDate() &&
599
- date.getMonth() === today.getMonth() &&
600
- date.getFullYear() === today.getFullYear()
601
- );
602
- },
603
-
604
- /**
605
- * Get start of day
606
- */
607
- startOfDay(date: Date = new Date()): Date {
608
- const result = new Date(date);
609
- result.setHours(0, 0, 0, 0);
610
- return result;
611
- },
612
-
613
- /**
614
- * Get end of day
615
- */
616
- endOfDay(date: Date = new Date()): Date {
617
- const result = new Date(date);
618
- result.setHours(23, 59, 59, 999);
619
- return result;
620
- },
621
- };
@@ -1,103 +0,0 @@
1
- /**
2
- * @fileoverview AR Traits (Augmented Reality)
3
- * @module @holoscript/std/traits
4
- *
5
- * Defines the AST traits required for augmented reality overlays
6
- * and real-world physical anchoring.
7
- */
8
-
9
- import type { TraitDefinition } from '../types.js';
10
-
11
- /**
12
- * Standard AR traits included in HoloScript's base functionality
13
- */
14
- export const ARTraits: TraitDefinition[] = [
15
- {
16
- name: '@ar_beacon',
17
- type: 'marker',
18
- description:
19
- 'Binds a UI or 3D overlay to a physical reality marker (QR code, NFC, BLE beacon, or visual image).',
20
- parameters: [
21
- {
22
- name: 'type',
23
- type: 'string',
24
- required: true,
25
- validation: (val: any) => ['qr', 'image', 'nfc', 'ble', 'gps'].includes(val),
26
- description: 'The type of physical beacon (qr, image, nfc, ble, gps)',
27
- },
28
- {
29
- name: 'id',
30
- type: 'string',
31
- required: true,
32
- description: 'The unique identifier data the beacon broadcasts or visually represents',
33
- },
34
- {
35
- name: 'physical_size',
36
- type: 'number',
37
- required: false,
38
- description:
39
- 'The expected physical size of the image/marker in meters (for image/qr types)',
40
- },
41
- ],
42
- validation: (node: any) => {
43
- return { valid: true }; // Allowed on any Node (Zones, Objects, UI)
44
- },
45
- },
46
- {
47
- name: '@overlay',
48
- type: 'behavior',
49
- description:
50
- 'Marks a HoloUI panel or 3D object to act as a pass-through overlay locked to the viewport or surface.',
51
- parameters: [
52
- {
53
- name: 'anchor',
54
- type: 'string',
55
- required: false,
56
- defaultValue: 'viewport',
57
- validation: (val: any) => ['viewport', 'surface', 'plane', 'face', 'hand'].includes(val),
58
- description: 'How the overlay anchors to the AR pass-through feed.',
59
- },
60
- {
61
- name: 'occlusion',
62
- type: 'boolean',
63
- required: false,
64
- defaultValue: true,
65
- description: 'Whether physical real-world objects occlude this virtual overlay.',
66
- },
67
- ],
68
- validation: (node: any) => {
69
- // Typically used on UI or SpatialGroups
70
- if (node.type !== 'HoloUI' && node.type !== 'SpatialGroup') {
71
- return { valid: false, message: '@overlay must be attached to HoloUI or SpatialGroup.' };
72
- }
73
- return { valid: true };
74
- },
75
- },
76
- {
77
- name: '@layer_shift',
78
- type: 'behavior',
79
- description:
80
- 'Controls the automatic transition between physical reality (AR) and digital twin reality (VR/VRR) boundaries.',
81
- parameters: [
82
- {
83
- name: 'trigger',
84
- type: 'string',
85
- required: true,
86
- validation: (val: any) => ['proximity', 'scan', 'payment', 'quest_step'].includes(val),
87
- description: 'What triggers the reality shift.',
88
- },
89
- {
90
- name: 'to_layer',
91
- type: 'string',
92
- required: true,
93
- validation: (val: any) => ['vr', 'vrr', 'ar'].includes(val),
94
- description: 'Which layer the user shifts into.',
95
- },
96
- ],
97
- validation: (node: any) => {
98
- return { valid: true };
99
- },
100
- },
101
- ];
102
-
103
- export default ARTraits;