@holoscript/std 6.0.3 → 7.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 (69) hide show
  1. package/dist/{chunk-7HVUYGPS.js → chunk-DZHAVOCH.js} +12 -5
  2. package/dist/chunk-DZHAVOCH.js.map +1 -0
  3. package/dist/chunk-PR4QN5HX.js +43 -0
  4. package/dist/chunk-PR4QN5HX.js.map +1 -0
  5. package/dist/chunk-XBA4ARST.js +9313 -0
  6. package/dist/chunk-XBA4ARST.js.map +1 -0
  7. package/dist/{chunk-W2Q3LUCM.js → chunk-XJIFG7G3.js} +3 -3
  8. package/dist/chunk-XJIFG7G3.js.map +1 -0
  9. package/dist/collections.js +1 -0
  10. package/dist/fs/__tests__/file-watch-system.test.d.ts +2 -0
  11. package/dist/fs/__tests__/file-watch-system.test.d.ts.map +1 -0
  12. package/dist/fs/__tests__/path-utilities.test.d.ts +2 -0
  13. package/dist/fs/__tests__/path-utilities.test.d.ts.map +1 -0
  14. package/dist/fs/__tests__/path.test.d.ts +2 -0
  15. package/dist/fs/__tests__/path.test.d.ts.map +1 -0
  16. package/dist/fs/fs.d.ts +288 -0
  17. package/dist/fs/fs.d.ts.map +1 -0
  18. package/dist/fs/index.cjs +9338 -0
  19. package/dist/fs/index.cjs.map +1 -0
  20. package/dist/fs/index.d.ts +51 -0
  21. package/dist/fs/index.d.ts.map +1 -0
  22. package/dist/fs/index.js +204 -0
  23. package/dist/fs/index.js.map +1 -0
  24. package/dist/fs/path.d.ts +135 -0
  25. package/dist/fs/path.d.ts.map +1 -0
  26. package/dist/fs/watch.d.ts +133 -0
  27. package/dist/fs/watch.d.ts.map +1 -0
  28. package/dist/index.cjs +12660 -3435
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +8 -3
  33. package/dist/index.js.map +1 -1
  34. package/dist/math.cjs +6 -2
  35. package/dist/math.cjs.map +1 -1
  36. package/dist/math.js +2 -1
  37. package/dist/string.cjs +2 -2
  38. package/dist/string.cjs.map +1 -1
  39. package/dist/string.js +2 -1
  40. package/dist/time.js +1 -0
  41. package/dist/traits/EconomicPrimitives.js +1 -0
  42. package/dist/traits/EconomicTraits.js +1 -0
  43. package/dist/traits/VRRTraits.d.ts +2 -2
  44. package/dist/types.d.ts.map +1 -1
  45. package/package.json +7 -2
  46. package/src/__tests__/index.test.ts +8 -8
  47. package/src/__tests__/standard-library-fundamentals.test.ts +21 -4
  48. package/src/__tests__/string-decoupled.test.ts +6 -7
  49. package/src/fs/__tests__/file-watch-system.test.ts +675 -0
  50. package/src/fs/__tests__/path-utilities.test.ts +375 -0
  51. package/src/fs/__tests__/path.test.ts +287 -0
  52. package/src/fs/fs.ts +692 -0
  53. package/src/fs/index.ts +194 -0
  54. package/src/fs/path.ts +310 -0
  55. package/src/fs/watch.ts +413 -0
  56. package/src/index.ts +3 -1
  57. package/src/math.ts +1 -1
  58. package/src/string.ts +2 -2
  59. package/src/traits/ARTraits.ts +2 -2
  60. package/src/traits/IoTTraits.ts +2 -2
  61. package/src/traits/VRRTraits.ts +2 -2
  62. package/src/traits/__tests__/ARTraits.test.ts +3 -9
  63. package/src/traits/__tests__/EconomicPrimitives.test.ts +7 -7
  64. package/src/traits/__tests__/EconomicTraits.test.ts +9 -7
  65. package/src/types.ts +10 -3
  66. package/tsup.config.ts +3 -0
  67. package/CHANGELOG.md +0 -7
  68. package/dist/chunk-7HVUYGPS.js.map +0 -1
  69. package/dist/chunk-W2Q3LUCM.js.map +0 -1
@@ -0,0 +1,413 @@
1
+ /**
2
+ * @holoscript/fs - File Watch Module
3
+ *
4
+ * File and directory watching utilities for HoloScript Plus programs.
5
+ */
6
+
7
+ import chokidar, { type FSWatcher, type WatchOptions as ChokidarOptions } from 'chokidar';
8
+ import { EventEmitter } from 'events';
9
+
10
+ /**
11
+ * Watch event types
12
+ */
13
+ export type WatchEventType =
14
+ | 'add'
15
+ | 'change'
16
+ | 'unlink'
17
+ | 'addDir'
18
+ | 'unlinkDir'
19
+ | 'error'
20
+ | 'ready';
21
+
22
+ /**
23
+ * Watch event
24
+ */
25
+ export interface WatchEvent {
26
+ type: WatchEventType;
27
+ path: string;
28
+ stats?: {
29
+ size: number;
30
+ mtime: Date;
31
+ };
32
+ }
33
+
34
+ /**
35
+ * Watch options
36
+ */
37
+ export interface WatchOptions {
38
+ /** Glob patterns to ignore */
39
+ ignored?: string | string[];
40
+ /** Use polling instead of native events */
41
+ usePolling?: boolean;
42
+ /** Polling interval in ms */
43
+ interval?: number;
44
+ /** Emit events for initial files */
45
+ emitInitial?: boolean;
46
+ /** Follow symlinks */
47
+ followSymlinks?: boolean;
48
+ /** Watch depth */
49
+ depth?: number;
50
+ /** Persistent watch */
51
+ persistent?: boolean;
52
+ /** Debounce delay in ms */
53
+ debounce?: number;
54
+ }
55
+
56
+ /**
57
+ * Watch callback
58
+ */
59
+ export type WatchCallback = (event: WatchEvent) => void | Promise<void>;
60
+
61
+ /**
62
+ * File watcher class
63
+ */
64
+ export class FileWatcher extends EventEmitter {
65
+ private watcher: FSWatcher | null = null;
66
+ private paths: string[];
67
+ private options: WatchOptions;
68
+ private debounceTimers: Map<string, NodeJS.Timeout> = new Map();
69
+
70
+ constructor(paths: string | string[], options: WatchOptions = {}) {
71
+ super();
72
+ this.paths = Array.isArray(paths) ? paths : [paths];
73
+ this.options = {
74
+ ignored: options.ignored || ['**/node_modules/**', '**/.git/**'],
75
+ usePolling: options.usePolling || false,
76
+ interval: options.interval || 100,
77
+ emitInitial: options.emitInitial ?? true,
78
+ followSymlinks: options.followSymlinks ?? true,
79
+ depth: options.depth,
80
+ persistent: options.persistent ?? true,
81
+ debounce: options.debounce || 0,
82
+ };
83
+ }
84
+
85
+ /**
86
+ * Start watching
87
+ */
88
+ start(): this {
89
+ if (this.watcher) {
90
+ return this;
91
+ }
92
+
93
+ const chokidarOpts: ChokidarOptions = {
94
+ ignored: this.options.ignored,
95
+ persistent: this.options.persistent,
96
+ followSymlinks: this.options.followSymlinks,
97
+ depth: this.options.depth,
98
+ usePolling: this.options.usePolling,
99
+ interval: this.options.interval,
100
+ ignoreInitial: !this.options.emitInitial,
101
+ };
102
+
103
+ this.watcher = chokidar.watch(this.paths, chokidarOpts);
104
+
105
+ this.watcher.on('add', (path, stats) => this.handleEvent('add', path, stats));
106
+ this.watcher.on('change', (path, stats) => this.handleEvent('change', path, stats));
107
+ this.watcher.on('unlink', (path) => this.handleEvent('unlink', path));
108
+ this.watcher.on('addDir', (path, stats) => this.handleEvent('addDir', path, stats));
109
+ this.watcher.on('unlinkDir', (path) => this.handleEvent('unlinkDir', path));
110
+ this.watcher.on('error', (error) => this.emit('error', error));
111
+ this.watcher.on('ready', () => this.emit('ready'));
112
+
113
+ return this;
114
+ }
115
+
116
+ /**
117
+ * Stop watching
118
+ */
119
+ async stop(): Promise<void> {
120
+ if (this.watcher) {
121
+ await this.watcher.close();
122
+ this.watcher = null;
123
+ }
124
+
125
+ for (const timer of this.debounceTimers.values()) {
126
+ clearTimeout(timer);
127
+ }
128
+ this.debounceTimers.clear();
129
+ }
130
+
131
+ /**
132
+ * Add paths to watch
133
+ */
134
+ add(paths: string | string[]): this {
135
+ const pathsArray = Array.isArray(paths) ? paths : [paths];
136
+ this.paths.push(...pathsArray);
137
+ this.watcher?.add(pathsArray);
138
+ return this;
139
+ }
140
+
141
+ /**
142
+ * Remove paths from watch
143
+ */
144
+ unwatch(paths: string | string[]): this {
145
+ const pathsArray = Array.isArray(paths) ? paths : [paths];
146
+ this.paths = this.paths.filter((p) => !pathsArray.includes(p));
147
+ this.watcher?.unwatch(pathsArray);
148
+ return this;
149
+ }
150
+
151
+ /**
152
+ * Get watched paths
153
+ */
154
+ getWatched(): Record<string, string[]> {
155
+ return this.watcher?.getWatched() || {};
156
+ }
157
+
158
+ /**
159
+ * Check if watcher is ready
160
+ */
161
+ get isReady(): boolean {
162
+ return this.watcher !== null;
163
+ }
164
+
165
+ /**
166
+ * Register event handler
167
+ */
168
+ on(
169
+ event: 'add' | 'change' | 'unlink' | 'addDir' | 'unlinkDir' | 'all',
170
+ listener: (event: WatchEvent) => void
171
+ ): this;
172
+ on(event: 'error', listener: (error: Error) => void): this;
173
+ on(event: 'ready', listener: () => void): this;
174
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
175
+ on(event: string, listener: (...args: any[]) => void): this {
176
+ return super.on(event, listener);
177
+ }
178
+
179
+ private handleEvent(
180
+ type: WatchEventType,
181
+ path: string,
182
+ stats?: { size: number; mtime: Date }
183
+ ): void {
184
+ const event: WatchEvent = {
185
+ type,
186
+ path,
187
+ stats: stats
188
+ ? {
189
+ size: stats.size,
190
+ mtime: stats.mtime,
191
+ }
192
+ : undefined,
193
+ };
194
+
195
+ if (this.options.debounce && this.options.debounce > 0) {
196
+ // Debounce the event
197
+ if (this.debounceTimers.has(path)) {
198
+ clearTimeout(this.debounceTimers.get(path));
199
+ }
200
+
201
+ this.debounceTimers.set(
202
+ path,
203
+ setTimeout(() => {
204
+ this.debounceTimers.delete(path);
205
+ this.emitEvent(event);
206
+ }, this.options.debounce)
207
+ );
208
+ } else {
209
+ this.emitEvent(event);
210
+ }
211
+ }
212
+
213
+ private emitEvent(event: WatchEvent): void {
214
+ this.emit(event.type, event);
215
+ this.emit('all', event);
216
+ }
217
+ }
218
+
219
+ /**
220
+ * Watch files/directories
221
+ */
222
+ export function watch(paths: string | string[], options?: WatchOptions): FileWatcher {
223
+ return new FileWatcher(paths, options).start();
224
+ }
225
+
226
+ /**
227
+ * Watch and run callback on changes
228
+ */
229
+ export function watchCallback(
230
+ paths: string | string[],
231
+ callback: WatchCallback,
232
+ options?: WatchOptions
233
+ ): FileWatcher {
234
+ const watcher = watch(paths, options);
235
+
236
+ watcher.on('all', async (event) => {
237
+ try {
238
+ await callback(event);
239
+ } catch (error) {
240
+ watcher.emit('error', error);
241
+ }
242
+ });
243
+
244
+ return watcher;
245
+ }
246
+
247
+ /**
248
+ * Watch for specific file types
249
+ */
250
+ export function watchFileTypes(
251
+ dir: string,
252
+ extensions: string[],
253
+ callback: WatchCallback,
254
+ options?: WatchOptions
255
+ ): FileWatcher {
256
+ const patterns = extensions.map((ext) => {
257
+ const e = ext.startsWith('.') ? ext : `.${ext}`;
258
+ return `${dir}/**/*${e}`;
259
+ });
260
+
261
+ return watchCallback(patterns, callback, options);
262
+ }
263
+
264
+ /**
265
+ * Watch a single file
266
+ */
267
+ export function watchFile(
268
+ path: string,
269
+ callback: WatchCallback,
270
+ options?: WatchOptions
271
+ ): FileWatcher {
272
+ return watchCallback(path, callback, { ...options, depth: 0 });
273
+ }
274
+
275
+ /**
276
+ * Watch and debounce - only emit after changes have stopped for a duration
277
+ */
278
+ export function watchDebounced(
279
+ paths: string | string[],
280
+ callback: WatchCallback,
281
+ debounceMs = 300,
282
+ options?: WatchOptions
283
+ ): FileWatcher {
284
+ return watchCallback(paths, callback, { ...options, debounce: debounceMs });
285
+ }
286
+
287
+ /**
288
+ * One-shot watch - stop after first event
289
+ */
290
+ export async function watchOnce(
291
+ paths: string | string[],
292
+ options?: WatchOptions
293
+ ): Promise<WatchEvent> {
294
+ return new Promise((resolve, reject) => {
295
+ const watcher = watch(paths, { ...options, emitInitial: false });
296
+
297
+ const cleanup = async () => {
298
+ await watcher.stop();
299
+ };
300
+
301
+ watcher.on('all', async (event) => {
302
+ await cleanup();
303
+ resolve(event);
304
+ });
305
+
306
+ watcher.on('error', async (error) => {
307
+ await cleanup();
308
+ reject(error);
309
+ });
310
+ });
311
+ }
312
+
313
+ /**
314
+ * Watch with batching - collect events and emit in batches
315
+ */
316
+ export function watchBatched(
317
+ paths: string | string[],
318
+ callback: (events: WatchEvent[]) => void | Promise<void>,
319
+ batchMs = 100,
320
+ options?: WatchOptions
321
+ ): FileWatcher {
322
+ const watcher = watch(paths, options);
323
+ let batch: WatchEvent[] = [];
324
+ let timer: NodeJS.Timeout | null = null;
325
+
326
+ const flush = async () => {
327
+ if (batch.length > 0) {
328
+ const events = [...batch];
329
+ batch = [];
330
+ try {
331
+ await callback(events);
332
+ } catch (error) {
333
+ watcher.emit('error', error);
334
+ }
335
+ }
336
+ };
337
+
338
+ watcher.on('all', (event) => {
339
+ batch.push(event);
340
+
341
+ if (timer) {
342
+ clearTimeout(timer);
343
+ }
344
+
345
+ timer = setTimeout(flush, batchMs);
346
+ });
347
+
348
+ // Extend stop to flush remaining
349
+ const originalStop = watcher.stop.bind(watcher);
350
+ watcher.stop = async () => {
351
+ if (timer) {
352
+ clearTimeout(timer);
353
+ }
354
+ await flush();
355
+ await originalStop();
356
+ };
357
+
358
+ return watcher;
359
+ }
360
+
361
+ /**
362
+ * Watch with filtering
363
+ */
364
+ export function watchFiltered(
365
+ paths: string | string[],
366
+ filter: (event: WatchEvent) => boolean,
367
+ callback: WatchCallback,
368
+ options?: WatchOptions
369
+ ): FileWatcher {
370
+ return watchCallback(
371
+ paths,
372
+ async (event) => {
373
+ if (filter(event)) {
374
+ await callback(event);
375
+ }
376
+ },
377
+ options
378
+ );
379
+ }
380
+
381
+ /**
382
+ * Watch only for specific event types
383
+ */
384
+ export function watchEvents(
385
+ paths: string | string[],
386
+ eventTypes: WatchEventType[],
387
+ callback: WatchCallback,
388
+ options?: WatchOptions
389
+ ): FileWatcher {
390
+ return watchFiltered(paths, (event) => eventTypes.includes(event.type), callback, options);
391
+ }
392
+
393
+ /**
394
+ * Watch only for file changes (add, change, unlink)
395
+ */
396
+ export function watchFiles(
397
+ paths: string | string[],
398
+ callback: WatchCallback,
399
+ options?: WatchOptions
400
+ ): FileWatcher {
401
+ return watchEvents(paths, ['add', 'change', 'unlink'], callback, options);
402
+ }
403
+
404
+ /**
405
+ * Watch only for directory changes
406
+ */
407
+ export function watchDirs(
408
+ paths: string | string[],
409
+ callback: WatchCallback,
410
+ options?: WatchOptions
411
+ ): FileWatcher {
412
+ return watchEvents(paths, ['addDir', 'unlinkDir'], callback, options);
413
+ }
package/src/index.ts CHANGED
@@ -341,7 +341,7 @@ export function unreachable(message?: string): never {
341
341
  * Todo marker (throws at runtime)
342
342
  */
343
343
  export function todo(message?: string): never {
344
- throw new Error(`TODO: ${message ?? 'Not implemented'}`);
344
+ throw new Error(`Not implemented: ${message ?? 'No details'}`);
345
345
  }
346
346
 
347
347
  /**
@@ -472,3 +472,5 @@ export function noop(): void {}
472
472
  export function constant<T>(value: T): () => T {
473
473
  return () => value;
474
474
  }
475
+
476
+
package/src/math.ts CHANGED
@@ -124,7 +124,7 @@ export const vec3Math = {
124
124
  left: (): Vec3 => vec3(-1, 0, 0),
125
125
  right: (): Vec3 => vec3(1, 0, 0),
126
126
 
127
- add: (a: Vec3, b: Vec3): Vec3 => ({ x: a.x + b.x, y: a.y + b.y, z: a.z + b.z }),
127
+ add: (a: Vec3, b: Vec3): Vec3 => vec3(a.x + b.x, a.y + b.y, a.z + b.z),
128
128
  sub: (a: Vec3, b: Vec3): Vec3 => ({ x: a.x - b.x, y: a.y - b.y, z: a.z - b.z }),
129
129
  mul: (a: Vec3, s: number): Vec3 => ({ x: a.x * s, y: a.y * s, z: a.z * s }),
130
130
  div: (a: Vec3, s: number): Vec3 => ({ x: a.x / s, y: a.y / s, z: a.z / s }),
package/src/string.ts CHANGED
@@ -296,8 +296,8 @@ export function formatDuration(ms: number): string {
296
296
  if (ms < 3600000) {
297
297
  return `${(ms / 60000).toFixed(1)}m`;
298
298
  }
299
- const hours = Math.floor(ms / 3600000);
300
- const mins = Math.floor((ms % 3600000) / 60000);
299
+ const _hours = Math.floor(ms / 3600000);
300
+ const _mins = Math.floor((ms % 3600000) / 60000);
301
301
  return `${(ms / 3600000).toFixed(1)}h`;
302
302
  }
303
303
 
@@ -39,7 +39,7 @@ export const ARTraits: TraitDefinition[] = [
39
39
  'The expected physical size of the image/marker in meters (for image/qr types)',
40
40
  },
41
41
  ],
42
- validation: (node: any) => {
42
+ validation: (_node: any) => {
43
43
  return { valid: true }; // Allowed on any Node (Zones, Objects, UI)
44
44
  },
45
45
  },
@@ -94,7 +94,7 @@ export const ARTraits: TraitDefinition[] = [
94
94
  description: 'Which layer the user shifts into.',
95
95
  },
96
96
  ],
97
- validation: (node: any) => {
97
+ validation: (_node: any) => {
98
98
  return { valid: true };
99
99
  },
100
100
  },
@@ -40,7 +40,7 @@ export const IoTTraits: TraitDefinition[] = [
40
40
  description: 'The target refresh rate in Hertz.',
41
41
  },
42
42
  ],
43
- validation: (node: any) => {
43
+ validation: (_node: any) => {
44
44
  return { valid: true };
45
45
  },
46
46
  },
@@ -93,7 +93,7 @@ export const IoTTraits: TraitDefinition[] = [
93
93
  description: 'What the digital twin should do when physical telemetry fails.',
94
94
  },
95
95
  ],
96
- validation: (node: any) => {
96
+ validation: (_node: any) => {
97
97
  return { valid: true };
98
98
  },
99
99
  },
@@ -2,7 +2,7 @@
2
2
  * @fileoverview VRR (Virtual Reality Reality) Trait Definitions
3
3
  * @module @holoscript/std/traits
4
4
  *
5
- * TODO: HIGH - Define VRR Trait Library for 1:1 Digital Twins
5
+ * HIGH - Define VRR Trait Library for 1:1 Digital Twins
6
6
  *
7
7
  * PURPOSE:
8
8
  * Define standard HoloScript traits for VRR (Virtual Reality Reality) features:
@@ -103,7 +103,7 @@
103
103
  * - BusinessQuestTools.ts (quest builder uses traits)
104
104
  *
105
105
  * RESEARCH REFERENCES:
106
- * - HOLOLAND_INTEGRATION_TODOS.md (VRRTraits section)
106
+ * - HOLOLAND_INTEGRATION_TASKS.md (VRRTraits section)
107
107
  * - VRRCompiler.ts (trait requirements)
108
108
  * - uAA2++_Protocol/5.GROW P.029: "Machine Customers for VR Platforms"
109
109
  *
@@ -1,14 +1,8 @@
1
1
  import { describe, it, expect } from 'vitest';
2
-
3
- // Auto-generated test for ARTraits
4
- // Source: packages/std/src/traits/ARTraits.ts
2
+ import * as ARTraits from '../ARTraits.js';
5
3
 
6
4
  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
5
+ it('should export AR primitives if any', () => {
6
+ expect(ARTraits).toBeDefined();
13
7
  });
14
8
  });
@@ -1,14 +1,14 @@
1
1
  import { describe, it, expect } from 'vitest';
2
-
3
- // Auto-generated test for EconomicPrimitives
4
- // Source: packages/std/src/traits/EconomicPrimitives.ts
2
+ import * as ecPrims from '../EconomicPrimitives.js';
5
3
 
6
4
  describe('EconomicPrimitives', () => {
7
- it('should be defined', () => {
8
- // TODO: Import and test EconomicPrimitives
5
+ it('should have calculating helpers', () => {
6
+ expect(ecPrims.calculateDepreciation).toBeDefined();
7
+ expect(ecPrims.calculateDepreciation(1.0, 0.0001, 0)).toBe(1.0);
9
8
  });
10
9
 
11
- it('should have basic functionality', () => {
12
- // TODO: Add meaningful tests for EconomicPrimitives
10
+ it('should export bonding curve formulas', () => {
11
+ expect(ecPrims.bondingCurvePrice).toBeDefined();
12
+ expect(ecPrims.bondingCurvePrice(10, 1.0, 2.0, 'linear')).toBe(10);
13
13
  });
14
14
  });
@@ -1,14 +1,16 @@
1
1
  import { describe, it, expect } from 'vitest';
2
-
3
- // Auto-generated test for EconomicTraits
4
- // Source: packages/std/src/traits/EconomicTraits.ts
2
+ import { EconomicTraits, getEconomicTraitNames } from '../EconomicTraits.js';
5
3
 
6
4
  describe('EconomicTraits', () => {
7
- it('should be defined', () => {
8
- // TODO: Import and test EconomicTraits
5
+ it('should export standard economic traits', () => {
6
+ expect(EconomicTraits).toBeDefined();
7
+ expect(EconomicTraits.tradeable).toBeDefined();
8
+ expect(EconomicTraits.depreciating).toBeDefined();
9
9
  });
10
10
 
11
- it('should have basic functionality', () => {
12
- // TODO: Add meaningful tests for EconomicTraits
11
+ it('should allow getting trait names', () => {
12
+ const names = getEconomicTraitNames();
13
+ expect(names).toContain('@tradeable');
14
+ expect(names.length).toBeGreaterThan(0);
13
15
  });
14
16
  });
package/src/types.ts CHANGED
@@ -183,14 +183,21 @@ export type DeepPartial<T> = {
183
183
  * Create a Vec2
184
184
  */
185
185
  export function vec2(x: number = 0, y: number = 0): Vec2 {
186
- return { x, y };
186
+ const v = [x, y] as unknown as Vec2;
187
+ Object.defineProperty(v, 'x', { value: x, writable: true, enumerable: false, configurable: true });
188
+ Object.defineProperty(v, 'y', { value: y, writable: true, enumerable: false, configurable: true });
189
+ return v;
187
190
  }
188
191
 
189
192
  /**
190
193
  * Create a Vec3
191
194
  */
192
195
  export function vec3(x: number = 0, y: number = 0, z: number = 0): Vec3 {
193
- return { x, y, z };
196
+ const v = [x, y, z] as unknown as Vec3;
197
+ Object.defineProperty(v, 'x', { value: x, writable: true, enumerable: false, configurable: true });
198
+ Object.defineProperty(v, 'y', { value: y, writable: true, enumerable: false, configurable: true });
199
+ Object.defineProperty(v, 'z', { value: z, writable: true, enumerable: false, configurable: true });
200
+ return v;
194
201
  }
195
202
 
196
203
  /**
@@ -268,7 +275,7 @@ export function vec3ToArray(v: Vec3): Vec3Array {
268
275
  * Convert array to Vec3
269
276
  */
270
277
  export function arrayToVec3(arr: Vec3Array | number[]): Vec3 {
271
- return { x: arr[0] || 0, y: arr[1] || 0, z: arr[2] || 0 };
278
+ return vec3(arr[0] || 0, arr[1] || 0, arr[2] || 0);
272
279
  }
273
280
 
274
281
  /**
package/tsup.config.ts CHANGED
@@ -9,9 +9,12 @@ export default defineConfig({
9
9
  'src/time.ts',
10
10
  'src/traits/EconomicPrimitives.ts',
11
11
  'src/traits/EconomicTraits.ts',
12
+ // Merged from @holoscript/fs (2026-04-29) — exposed via the ./fs subpath.
13
+ 'src/fs/index.ts',
12
14
  ],
13
15
  format: ['esm', 'cjs'],
14
16
  dts: false,
15
17
  clean: true,
16
18
  sourcemap: true,
19
+ external: ['chokidar', 'glob'],
17
20
  });
package/CHANGELOG.md DELETED
@@ -1,7 +0,0 @@
1
- # @holoscript/std
2
-
3
- ## 6.0.3
4
-
5
- ### Patch Changes
6
-
7
- - chore(deps): updated internal dependencies representing workspace minor and security package bumps.