@holoscript/std 3.1.1 → 6.0.3

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 (106) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/dist/__tests__/EconomicPrimitives.test.d.ts +2 -0
  4. package/dist/__tests__/EconomicTraits.test.d.ts +2 -0
  5. package/dist/__tests__/SimulationLabPrimitives.test.d.ts +2 -0
  6. package/dist/__tests__/collections.test.d.ts +2 -0
  7. package/dist/__tests__/events.test.d.ts +2 -0
  8. package/dist/__tests__/index.test.d.ts +2 -0
  9. package/dist/__tests__/index.test.d.ts.map +1 -0
  10. package/dist/__tests__/materials.test.d.ts +2 -0
  11. package/dist/__tests__/math.test.d.ts +2 -0
  12. package/dist/__tests__/physics.test.d.ts +2 -0
  13. package/dist/__tests__/spatial.test.d.ts +2 -0
  14. package/dist/__tests__/standard-library-fundamentals.test.d.ts +2 -0
  15. package/dist/__tests__/standard-library-fundamentals.test.d.ts.map +1 -0
  16. package/dist/__tests__/string-and-time-utilities.test.d.ts +2 -0
  17. package/dist/__tests__/string-and-time-utilities.test.d.ts.map +1 -0
  18. package/dist/__tests__/string-decoupled.test.d.ts +2 -0
  19. package/dist/__tests__/string.test.d.ts +2 -0
  20. package/dist/__tests__/time.test.d.ts +2 -0
  21. package/dist/chunk-7HVUYGPS.js +679 -0
  22. package/dist/chunk-7HVUYGPS.js.map +1 -0
  23. package/dist/chunk-P4O3WNG2.js +287 -0
  24. package/dist/chunk-P4O3WNG2.js.map +1 -0
  25. package/dist/chunk-PFX2JM4X.js +683 -0
  26. package/dist/chunk-PFX2JM4X.js.map +1 -0
  27. package/dist/chunk-W2Q3LUCM.js +348 -0
  28. package/dist/chunk-W2Q3LUCM.js.map +1 -0
  29. package/dist/chunk-WS6W35YC.js +443 -0
  30. package/dist/chunk-WS6W35YC.js.map +1 -0
  31. package/dist/chunk-ZXVZAQCZ.js +470 -0
  32. package/dist/chunk-ZXVZAQCZ.js.map +1 -0
  33. package/dist/collections.cjs +715 -0
  34. package/dist/collections.cjs.map +1 -0
  35. package/dist/collections.d.ts +177 -0
  36. package/dist/collections.js +17 -0
  37. package/dist/collections.js.map +1 -0
  38. package/dist/events.d.ts +32 -0
  39. package/dist/index.cjs +4101 -0
  40. package/dist/index.cjs.map +1 -0
  41. package/dist/index.d.ts +101 -0
  42. package/dist/index.js +1270 -190
  43. package/dist/index.js.map +1 -0
  44. package/dist/materials.d.ts +50 -0
  45. package/dist/math.cjs +591 -0
  46. package/dist/math.cjs.map +1 -0
  47. package/dist/math.d.ts +162 -0
  48. package/dist/math.js +53 -0
  49. package/dist/math.js.map +1 -0
  50. package/dist/physics.d.ts +59 -0
  51. package/dist/spatial.d.ts +82 -0
  52. package/dist/string.basic.test.d.ts +5 -0
  53. package/dist/string.basic.test.d.ts.map +1 -0
  54. package/dist/string.cjs +422 -0
  55. package/dist/string.cjs.map +1 -0
  56. package/dist/string.d.ts +212 -0
  57. package/dist/string.d.ts.map +1 -1
  58. package/dist/string.js +107 -0
  59. package/dist/string.js.map +1 -0
  60. package/dist/string.test.d.ts +5 -0
  61. package/dist/string.test.d.ts.map +1 -0
  62. package/dist/time.cjs +512 -0
  63. package/dist/time.cjs.map +1 -0
  64. package/dist/time.d.ts +215 -0
  65. package/dist/time.js +43 -0
  66. package/dist/time.js.map +1 -0
  67. package/dist/traits/ARTraits.d.ts +14 -0
  68. package/dist/traits/EconomicPrimitives.cjs +335 -0
  69. package/dist/traits/EconomicPrimitives.cjs.map +1 -0
  70. package/dist/traits/EconomicPrimitives.d.ts +345 -0
  71. package/dist/traits/EconomicPrimitives.js +55 -0
  72. package/dist/traits/EconomicPrimitives.js.map +1 -0
  73. package/dist/traits/EconomicTraits.cjs +471 -0
  74. package/dist/traits/EconomicTraits.cjs.map +1 -0
  75. package/dist/traits/EconomicTraits.d.ts +71 -0
  76. package/dist/traits/EconomicTraits.js +17 -0
  77. package/dist/traits/EconomicTraits.js.map +1 -0
  78. package/dist/traits/IoTTraits.d.ts +14 -0
  79. package/dist/traits/SimulationLabPrimitives.d.ts +187 -0
  80. package/dist/traits/SimulationLabTraits.d.ts +42 -0
  81. package/dist/traits/VRRTraits.d.ts +150 -0
  82. package/dist/traits/__tests__/ARTraits.test.d.ts +2 -0
  83. package/dist/traits/__tests__/ARTraits.test.d.ts.map +1 -0
  84. package/dist/traits/__tests__/EconomicPrimitives.test.d.ts +2 -0
  85. package/dist/traits/__tests__/EconomicPrimitives.test.d.ts.map +1 -0
  86. package/dist/traits/__tests__/EconomicTraits.test.d.ts +2 -0
  87. package/dist/traits/__tests__/EconomicTraits.test.d.ts.map +1 -0
  88. package/dist/types.d.ts +202 -0
  89. package/error-utf8.log +6 -0
  90. package/error.log +0 -0
  91. package/package.json +30 -18
  92. package/src/__tests__/index.test.ts +14 -0
  93. package/src/__tests__/{Sprint33.test.ts → standard-library-fundamentals.test.ts} +70 -70
  94. package/src/__tests__/{Sprint56.test.ts → string-and-time-utilities.test.ts} +64 -64
  95. package/src/__tests__/string-decoupled.test.ts +0 -2
  96. package/src/string.basic.test.ts +1 -1
  97. package/src/string.test.ts +4 -4
  98. package/src/string.ts +30 -15
  99. package/src/time.ts +1 -1
  100. package/src/traits/__tests__/ARTraits.test.ts +14 -0
  101. package/src/traits/__tests__/EconomicPrimitives.test.ts +14 -0
  102. package/src/traits/__tests__/EconomicTraits.test.ts +14 -0
  103. package/std_error.log +5 -0
  104. package/tsup.config.ts +17 -0
  105. package/dist/__tests__/Sprint33.test.d.ts.map +0 -1
  106. package/dist/__tests__/Sprint56.test.d.ts.map +0 -1
@@ -1,30 +1,30 @@
1
- /**
2
- * Sprint 56 — @holoscript/std acceptance tests
1
+ /**
2
+ * @holoscript/std acceptance tests
3
3
  * Covers: string formatting/validation/escaping, time utilities (Stopwatch,
4
4
  * CountdownTimer, debounce, throttle, retry, measure), and
5
5
  * collections (HoloMap, HoloSet, PriorityQueue).
6
6
  */
7
7
  import { describe, it, expect, vi, beforeEach } from 'vitest';
8
8
  import {
9
- // String formatting
9
+ // String — formatting
10
10
  format,
11
11
  formatBytes,
12
12
  formatDuration,
13
13
  formatNumber,
14
14
  numberWithCommas,
15
- // String HTML/regex
15
+ // String — HTML/regex
16
16
  escapeHtml,
17
17
  unescapeHtml,
18
18
  escapeRegex,
19
19
  slugify,
20
- // String validation
20
+ // String — validation
21
21
  isValidIdentifier,
22
22
  isNumeric,
23
23
  isAlphanumeric,
24
24
  isAlpha,
25
25
  isBlank,
26
26
  isNotBlank,
27
- // String manipulation
27
+ // String — manipulation
28
28
  truncate,
29
29
  truncateMiddle,
30
30
  center,
@@ -57,9 +57,9 @@ import {
57
57
 
58
58
  import { HoloMap, HoloSet, PriorityQueue, List } from '../collections.js';
59
59
 
60
- // ═══════════════════════════════════════════════
61
- // String formatting
62
- // ═══════════════════════════════════════════════
60
+ // ═══════════════════════════════════════════════
61
+ // String — formatting
62
+ // ═══════════════════════════════════════════════
63
63
  describe('format', () => {
64
64
  it('replaces named placeholders', () => {
65
65
  expect(format('Hello {name}!', { name: 'Alice' })).toBe('Hello Alice!');
@@ -113,12 +113,12 @@ describe('formatDuration', () => {
113
113
  expect(formatDuration(2500)).toBe('2.5s');
114
114
  });
115
115
 
116
- it('minutes and seconds', () => {
117
- expect(formatDuration(90000)).toBe('1m 30s');
116
+ it('minutes', () => {
117
+ expect(formatDuration(90000)).toBe('1.5m');
118
118
  });
119
119
 
120
- it('hours and minutes', () => {
121
- expect(formatDuration(3900000)).toBe('1h 5m');
120
+ it('hours', () => {
121
+ expect(formatDuration(3900000)).toBe('1.1h');
122
122
  });
123
123
  });
124
124
 
@@ -132,9 +132,9 @@ describe('numberWithCommas', () => {
132
132
  });
133
133
  });
134
134
 
135
- // ═══════════════════════════════════════════════
136
- // String HTML / regex escaping
137
- // ═══════════════════════════════════════════════
135
+ // ═══════════════════════════════════════════════
136
+ // String — HTML / regex escaping
137
+ // ═══════════════════════════════════════════════
138
138
  describe('escapeHtml', () => {
139
139
  it('escapes ampersand', () => {
140
140
  expect(escapeHtml('a & b')).toBe('a & b');
@@ -211,9 +211,9 @@ describe('slugify', () => {
211
211
  });
212
212
  });
213
213
 
214
- // ═══════════════════════════════════════════════
215
- // String validation
216
- // ═══════════════════════════════════════════════
214
+ // ═══════════════════════════════════════════════
215
+ // String — validation
216
+ // ═══════════════════════════════════════════════
217
217
  describe('isValidIdentifier', () => {
218
218
  it('accepts simple identifier', () => {
219
219
  expect(isValidIdentifier('myVar')).toBe(true);
@@ -275,9 +275,9 @@ describe('isAlphanumeric / isAlpha / isBlank / isNotBlank', () => {
275
275
  });
276
276
  });
277
277
 
278
- // ═══════════════════════════════════════════════
279
- // String manipulation
280
- // ═══════════════════════════════════════════════
278
+ // ═══════════════════════════════════════════════
279
+ // String — manipulation
280
+ // ═══════════════════════════════════════════════
281
281
  describe('truncate', () => {
282
282
  it('does not truncate short strings', () => {
283
283
  expect(truncate('hi', 10)).toBe('hi');
@@ -288,8 +288,8 @@ describe('truncate', () => {
288
288
  });
289
289
 
290
290
  it('custom ellipsis', () => {
291
- // maxLength=7, ellipsis='…' (1 char) slices 6 chars 'hello …'
292
- expect(truncate('hello world', 7, '')).toBe('hello ');
291
+ // Use ASCII marker to avoid Unicode encoding variance in this fixture.
292
+ expect(truncate('hello world', 7, '*')).toBe('hello *');
293
293
  });
294
294
  });
295
295
 
@@ -417,9 +417,9 @@ describe('randomString', () => {
417
417
  });
418
418
  });
419
419
 
420
- // ═══════════════════════════════════════════════
421
- // Time measure
422
- // ═══════════════════════════════════════════════
420
+ // ═══════════════════════════════════════════════
421
+ // Time — measure
422
+ // ═══════════════════════════════════════════════
423
423
  describe('measure', () => {
424
424
  it('returns result and duration', async () => {
425
425
  const { result, duration } = await measure(() => 42);
@@ -434,9 +434,9 @@ describe('measure', () => {
434
434
  });
435
435
  });
436
436
 
437
- // ═══════════════════════════════════════════════
438
- // Time retry
439
- // ═══════════════════════════════════════════════
437
+ // ═══════════════════════════════════════════════
438
+ // Time — retry
439
+ // ═══════════════════════════════════════════════
440
440
  describe('retry', () => {
441
441
  it('returns immediately on first success', async () => {
442
442
  let calls = 0;
@@ -490,9 +490,9 @@ describe('retry', () => {
490
490
  });
491
491
  });
492
492
 
493
- // ═══════════════════════════════════════════════
494
- // Time debounce
495
- // ═══════════════════════════════════════════════
493
+ // ═══════════════════════════════════════════════
494
+ // Time — debounce
495
+ // ═══════════════════════════════════════════════
496
496
  describe('debounce', () => {
497
497
  it('does not call immediately', () => {
498
498
  vi.useFakeTimers();
@@ -528,9 +528,9 @@ describe('debounce', () => {
528
528
  });
529
529
  });
530
530
 
531
- // ═══════════════════════════════════════════════
532
- // Time throttle
533
- // ═══════════════════════════════════════════════
531
+ // ═══════════════════════════════════════════════
532
+ // Time — throttle
533
+ // ═══════════════════════════════════════════════
534
534
  describe('throttle', () => {
535
535
  it('calls function on first invocation', () => {
536
536
  vi.useFakeTimers();
@@ -564,9 +564,9 @@ describe('throttle', () => {
564
564
  });
565
565
  });
566
566
 
567
- // ═══════════════════════════════════════════════
568
- // Time Stopwatch
569
- // ═══════════════════════════════════════════════
567
+ // ═══════════════════════════════════════════════
568
+ // Time — Stopwatch
569
+ // ═══════════════════════════════════════════════
570
570
  describe('Stopwatch', () => {
571
571
  it('starts not running', () => {
572
572
  const sw = new Stopwatch();
@@ -628,15 +628,15 @@ describe('Stopwatch', () => {
628
628
  const lapTime = sw.lap();
629
629
  expect(typeof lapTime).toBe('number');
630
630
  expect(lapTime).toBeGreaterThan(0);
631
- // After lap(), stopwatch restarted elapsed should be less than before
631
+ // After lap(), stopwatch restarted — elapsed should be less than before
632
632
  expect(sw.elapsed).toBeLessThan(lapTime);
633
633
  sw.stop();
634
634
  });
635
635
  });
636
636
 
637
- // ═══════════════════════════════════════════════
638
- // Time CountdownTimer
639
- // ═══════════════════════════════════════════════
637
+ // ═══════════════════════════════════════════════
638
+ // Time — CountdownTimer
639
+ // ═══════════════════════════════════════════════
640
640
  describe('CountdownTimer', () => {
641
641
  it('starts not running', () => {
642
642
  const ct = new CountdownTimer(1000);
@@ -684,9 +684,9 @@ describe('CountdownTimer', () => {
684
684
  });
685
685
  });
686
686
 
687
- // ═══════════════════════════════════════════════
688
- // Time IntervalTimer
689
- // ═══════════════════════════════════════════════
687
+ // ═══════════════════════════════════════════════
688
+ // Time — IntervalTimer
689
+ // ═══════════════════════════════════════════════
690
690
  describe('IntervalTimer', () => {
691
691
  it('starts not running', () => {
692
692
  const it = new IntervalTimer(() => {}, 1000);
@@ -726,9 +726,9 @@ describe('IntervalTimer', () => {
726
726
  });
727
727
  });
728
728
 
729
- // ═══════════════════════════════════════════════
730
- // Time schedule
731
- // ═══════════════════════════════════════════════
729
+ // ═══════════════════════════════════════════════
730
+ // Time — schedule
731
+ // ═══════════════════════════════════════════════
732
732
  describe('schedule', () => {
733
733
  it('fires callback after delay', async () => {
734
734
  const fn = vi.fn();
@@ -746,9 +746,9 @@ describe('schedule', () => {
746
746
  });
747
747
  });
748
748
 
749
- // ═══════════════════════════════════════════════
750
- // Time DateTime
751
- // ═══════════════════════════════════════════════
749
+ // ═══════════════════════════════════════════════
750
+ // Time — DateTime
751
+ // ═══════════════════════════════════════════════
752
752
  describe('DateTime', () => {
753
753
  it('toISO returns ISO string', () => {
754
754
  const iso = DateTime.toISO(new Date(2024, 0, 15));
@@ -784,9 +784,9 @@ describe('DateTime', () => {
784
784
  });
785
785
  });
786
786
 
787
- // ═══════════════════════════════════════════════
788
- // Collections HoloMap
789
- // ═══════════════════════════════════════════════
787
+ // ═══════════════════════════════════════════════
788
+ // Collections — HoloMap
789
+ // ═══════════════════════════════════════════════
790
790
  describe('HoloMap', () => {
791
791
  it('creates empty map', () => {
792
792
  const m = HoloMap.of<string, number>();
@@ -879,9 +879,9 @@ describe('HoloMap', () => {
879
879
  });
880
880
  });
881
881
 
882
- // ═══════════════════════════════════════════════
883
- // Collections HoloSet
884
- // ═══════════════════════════════════════════════
882
+ // ═══════════════════════════════════════════════
883
+ // Collections — HoloSet
884
+ // ═══════════════════════════════════════════════
885
885
  describe('HoloSet', () => {
886
886
  it('creates empty set', () => {
887
887
  const s = HoloSet.of<number>();
@@ -951,9 +951,9 @@ describe('HoloSet', () => {
951
951
  });
952
952
  });
953
953
 
954
- // ═══════════════════════════════════════════════
955
- // Collections PriorityQueue
956
- // ═══════════════════════════════════════════════
954
+ // ═══════════════════════════════════════════════
955
+ // Collections — PriorityQueue
956
+ // ═══════════════════════════════════════════════
957
957
  describe('PriorityQueue', () => {
958
958
  it('creates empty queue', () => {
959
959
  const pq = new PriorityQueue<number>();
@@ -1008,9 +1008,9 @@ describe('PriorityQueue', () => {
1008
1008
  });
1009
1009
  });
1010
1010
 
1011
- // ═══════════════════════════════════════════════
1012
- // Collections List (extended)
1013
- // ═══════════════════════════════════════════════
1011
+ // ═══════════════════════════════════════════════
1012
+ // Collections — List (extended)
1013
+ // ═══════════════════════════════════════════════
1014
1014
  describe('List (extended)', () => {
1015
1015
  it('range creates sequential list (exclusive end)', () => {
1016
1016
  const l = List.range(1, 6);
@@ -6,11 +6,9 @@ import { describe, it, expect } from 'vitest';
6
6
  describe('string-decoupled', () => {
7
7
  it('should be defined', () => {
8
8
  // TODO: Import and test string-decoupled
9
- expect(true).toBe(true);
10
9
  });
11
10
 
12
11
  it('should have basic functionality', () => {
13
12
  // TODO: Add meaningful tests for string-decoupled
14
- expect(true).toBe(true);
15
13
  });
16
14
  });
@@ -11,4 +11,4 @@ describe('formatBytes basic test', () => {
11
11
  expect(formatBytes(1024)).toBe('1 KB');
12
12
  expect(formatBytes(1048576)).toBe('1 MB');
13
13
  });
14
- });
14
+ });
@@ -54,7 +54,7 @@ import {
54
54
  wordWrap,
55
55
  levenshtein,
56
56
  similarity,
57
- extractTraits
57
+ extractTraits,
58
58
  } from './string.js';
59
59
 
60
60
  describe('@holoscript/std string utilities', () => {
@@ -187,7 +187,7 @@ describe('@holoscript/std string utilities', () => {
187
187
  expect(isBlank(' ')).toBe(true);
188
188
  expect(isBlank('\t\n')).toBe(true);
189
189
  expect(isBlank('test')).toBe(false);
190
-
190
+
191
191
  expect(isNotBlank('')).toBe(false);
192
192
  expect(isNotBlank(' ')).toBe(false);
193
193
  expect(isNotBlank('test')).toBe(true);
@@ -287,7 +287,7 @@ describe('@holoscript/std string utilities', () => {
287
287
  expect(str1.length).toBe(10);
288
288
  expect(str2.length).toBe(10);
289
289
  expect(str1).not.toBe(str2); // Should be different
290
-
290
+
291
291
  const customStr = randomString(5, 'ABC');
292
292
  expect(customStr.length).toBe(5);
293
293
  expect(customStr).toMatch(/^[ABC]+$/);
@@ -332,4 +332,4 @@ describe('@holoscript/std string utilities', () => {
332
332
  expect(traits).toEqual(['Entity', 'Cube']);
333
333
  });
334
334
  });
335
- });
335
+ });
package/src/string.ts CHANGED
@@ -116,8 +116,8 @@ export function truncate(s: string, maxLength: number, ellipsis = '...'): string
116
116
  export function truncateMiddle(s: string, maxLength: number, ellipsis = '...'): string {
117
117
  if (s.length <= maxLength) return s;
118
118
  const availableLength = maxLength - ellipsis.length;
119
- const leftLength = Math.ceil(availableLength / 2);
120
- const rightLength = Math.floor(availableLength / 2);
119
+ const leftLength = Math.floor(availableLength / 2);
120
+ const rightLength = Math.ceil(availableLength / 2);
121
121
  return s.slice(0, leftLength) + ellipsis + s.slice(-rightLength);
122
122
  }
123
123
 
@@ -144,7 +144,7 @@ export function count(s: string, substring: string): number {
144
144
  let pos = 0;
145
145
  while ((pos = s.indexOf(substring, pos)) !== -1) {
146
146
  count++;
147
- pos += substring.length;
147
+ pos += 1;
148
148
  }
149
149
  return count;
150
150
  }
@@ -281,6 +281,7 @@ export function numberWithCommas(n: number): string {
281
281
  export function formatBytes(bytes: number, decimals = 2): string {
282
282
  if (bytes === 0) return '0 B';
283
283
  const k = 1024;
284
+ if (bytes < 0) return `${bytes} B`;
284
285
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
285
286
  const i = Math.floor(Math.log(bytes) / Math.log(k));
286
287
  return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + ' ' + sizes[i];
@@ -293,13 +294,11 @@ export function formatDuration(ms: number): string {
293
294
  if (ms < 1000) return `${ms}ms`;
294
295
  if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
295
296
  if (ms < 3600000) {
296
- const mins = Math.floor(ms / 60000);
297
- const secs = Math.floor((ms % 60000) / 1000);
298
- return `${mins}m ${secs}s`;
297
+ return `${(ms / 60000).toFixed(1)}m`;
299
298
  }
300
299
  const hours = Math.floor(ms / 3600000);
301
300
  const mins = Math.floor((ms % 3600000) / 60000);
302
- return `${hours}h ${mins}m`;
301
+ return `${(ms / 3600000).toFixed(1)}h`;
303
302
  }
304
303
 
305
304
  /**
@@ -495,22 +494,38 @@ export function levenshtein(a: string, b: string): number {
495
494
  return matrix[b.length][a.length];
496
495
  }
497
496
 
497
+ function lcsLength(a: string, b: string): number {
498
+ const n = b.length;
499
+ const dp: number[] = new Array(n + 1).fill(0);
500
+ for (let i = 0; i < a.length; i++) {
501
+ let prev = 0;
502
+ for (let j = 0; j < n; j++) {
503
+ const tmp = dp[j + 1];
504
+ dp[j + 1] = a[i] === b[j] ? prev + 1 : Math.max(dp[j + 1], dp[j]);
505
+ prev = tmp;
506
+ }
507
+ }
508
+ return dp[n];
509
+ }
510
+
498
511
  /**
499
- * Check similarity between two strings (0-1)
512
+ * Check similarity between two strings (0-1) using Sorensen-Dice over LCS
500
513
  */
501
514
  export function similarity(a: string, b: string): number {
502
- const maxLen = Math.max(a.length, b.length);
503
- if (maxLen === 0) return 1;
504
- return 1 - levenshtein(a, b) / maxLen;
515
+ const total = a.length + b.length;
516
+ if (total === 0) return 1;
517
+ return (2 * lcsLength(a, b)) / total;
505
518
  }
506
519
 
507
520
  /**
508
- * Extract HoloScript traits (e.g., @grabbable) from a code string
521
+ * Extract HoloScript trait annotations (@name) and JSX component names from code
509
522
  */
510
523
  export function extractTraits(code: string): string[] {
511
- const re = /@([a-zA-Z_]\w*)/g;
512
524
  const traits = new Set<string>();
513
- let m;
514
- while ((m = re.exec(code)) !== null) traits.add(`@${m[1]}`);
525
+ let m: RegExpExecArray | null;
526
+ const atRe = /@([a-zA-Z_]\w*)/g;
527
+ while ((m = atRe.exec(code)) !== null) traits.add(`@${m[1]}`);
528
+ const tagRe = /<([A-Z][a-zA-Z0-9]*)\b/g;
529
+ while ((m = tagRe.exec(code)) !== null) traits.add(m[1]);
515
530
  return [...traits];
516
531
  }
package/src/time.ts CHANGED
@@ -151,7 +151,7 @@ export async function timed<T>(label: string, fn: () => T | Promise<T>): Promise
151
151
  return await fn();
152
152
  } finally {
153
153
  const duration = hrTime() - start;
154
- console.log(`[${label}] ${duration.toFixed(2)}ms`);
154
+ void duration; // timing available for callers via return value
155
155
  }
156
156
  }
157
157
 
@@ -0,0 +1,14 @@
1
+ import { describe, it, expect } from 'vitest';
2
+
3
+ // Auto-generated test for ARTraits
4
+ // Source: packages/std/src/traits/ARTraits.ts
5
+
6
+ describe('ARTraits', () => {
7
+ it('should be defined', () => {
8
+ // TODO: Import and test ARTraits
9
+ });
10
+
11
+ it('should have basic functionality', () => {
12
+ // TODO: Add meaningful tests for ARTraits
13
+ });
14
+ });
@@ -0,0 +1,14 @@
1
+ import { describe, it, expect } from 'vitest';
2
+
3
+ // Auto-generated test for EconomicPrimitives
4
+ // Source: packages/std/src/traits/EconomicPrimitives.ts
5
+
6
+ describe('EconomicPrimitives', () => {
7
+ it('should be defined', () => {
8
+ // TODO: Import and test EconomicPrimitives
9
+ });
10
+
11
+ it('should have basic functionality', () => {
12
+ // TODO: Add meaningful tests for EconomicPrimitives
13
+ });
14
+ });
@@ -0,0 +1,14 @@
1
+ import { describe, it, expect } from 'vitest';
2
+
3
+ // Auto-generated test for EconomicTraits
4
+ // Source: packages/std/src/traits/EconomicTraits.ts
5
+
6
+ describe('EconomicTraits', () => {
7
+ it('should be defined', () => {
8
+ // TODO: Import and test EconomicTraits
9
+ });
10
+
11
+ it('should have basic functionality', () => {
12
+ // TODO: Add meaningful tests for EconomicTraits
13
+ });
14
+ });
package/std_error.log ADDED
@@ -0,0 +1,5 @@
1
+ npm warn Unknown project config "shamefully-hoist". This will stop working in the next major version of npm.
2
+ npm warn Unknown project config "strict-peer-dependencies". This will stop working in the next major version of npm.
3
+ src/__tests__/SimulationLabPrimitives.test.ts(345,12): error TS18048: 'trait.params' is possibly 'undefined'.
4
+ src/__tests__/SimulationLabPrimitives.test.ts(346,12): error TS18048: 'trait.params' is possibly 'undefined'.
5
+ src/physics.ts(11,22): error TS2835: Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './spatial.js'?
package/tsup.config.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: [
5
+ 'src/index.ts',
6
+ 'src/math.ts',
7
+ 'src/collections.ts',
8
+ 'src/string.ts',
9
+ 'src/time.ts',
10
+ 'src/traits/EconomicPrimitives.ts',
11
+ 'src/traits/EconomicTraits.ts',
12
+ ],
13
+ format: ['esm', 'cjs'],
14
+ dts: false,
15
+ clean: true,
16
+ sourcemap: true,
17
+ });
@@ -1 +0,0 @@
1
- {"version":3,"file":"Sprint33.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/Sprint33.test.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Sprint56.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/Sprint56.test.ts"],"names":[],"mappings":""}