brep-io-kernel 1.0.26 → 1.0.28

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.
@@ -1,6 +1,7 @@
1
1
  // Registers the default toolbar buttons using the viewer's addToolbarButton API.
2
2
  // Each button's logic is implemented in its own module.
3
3
 
4
+ import { createNewButton } from './newButton.js';
4
5
  import { createSaveButton } from './saveButton.js';
5
6
  import { createUndoButton, createRedoButton } from './undoRedoButtons.js';
6
7
  import { createZoomToFitButton } from './zoomToFitButton.js';
@@ -17,6 +18,7 @@ export function registerDefaultToolbarButtons(viewer) {
17
18
  if (!viewer || typeof viewer.addToolbarButton !== 'function') return;
18
19
 
19
20
  const creators = [
21
+ createNewButton,
20
22
  createSaveButton,
21
23
  createZoomToFitButton,
22
24
  createWireframeToggleButton,
@@ -87,7 +87,7 @@ export function createSaveButton(viewer) {
87
87
  const b64 = _uint8ToBase64(bytes);
88
88
  // Do not persist a separate thumbnail; it's embedded in the 3MF
89
89
  const payload = { savedAt: new Date().toISOString(), data3mf: b64 };
90
- LS.setItem('__BREP_MODEL__:autosave', JSON.stringify(payload));
90
+ LS.setItem('__BREP_DATA__:autosave', JSON.stringify(payload));
91
91
  LS.setItem('__BREP_MODELS_LASTNAME__', 'autosave');
92
92
  alert('Saved as "autosave"');
93
93
  } catch {
package/src/UI/viewer.js CHANGED
@@ -37,6 +37,7 @@ import { PMIMode } from './pmi/PMIMode.js';
37
37
  import { annotationRegistry } from './pmi/AnnotationRegistry.js';
38
38
  import { SchemaForm } from './featureDialogs.js';
39
39
  import './dialogs.js';
40
+ import { maybeStartStartupTour } from './startupTour.js';
40
41
  import { BREP } from '../BREP/BREP.js';
41
42
  import { createAxisHelperGroup, DEFAULT_AXIS_HELPER_PX } from '../utils/axisHelpers.js';
42
43
 
@@ -1220,6 +1221,9 @@ export class Viewer {
1220
1221
 
1221
1222
  // Ensure toolbar sits above the canvas and doesn't block controls when not hovered
1222
1223
  try { this.renderer.domElement.style.marginTop = '0px'; } catch { }
1224
+
1225
+ // Start the startup tour once the core UI is mounted, if not already completed.
1226
+ try { await maybeStartStartupTour(this); } catch { }
1223
1227
  }
1224
1228
 
1225
1229
  // Public: allow plugins to add toolbar buttons even before MainToolbar is constructed
package/src/fs.proxy.js CHANGED
@@ -78,12 +78,48 @@ async function idbGet(db, key) {
78
78
  return promisifyRequest(store.get(key));
79
79
  }
80
80
 
81
- async function idbPut(db, key, value) {
81
+ async function idbDelete(db, key) {
82
82
  const tx = db.transaction([VFS_STORE_NAME], 'readwrite');
83
- tx.objectStore(VFS_STORE_NAME).put(value, key);
83
+ tx.objectStore(VFS_STORE_NAME).delete(key);
84
84
  return new Promise((resolve, reject) => {
85
85
  tx.oncomplete = () => resolve();
86
- tx.onerror = () => reject(tx.error || new Error('IDB put failed'));
86
+ tx.onerror = () => reject(tx.error || new Error('IDB delete failed'));
87
+ });
88
+ }
89
+
90
+ async function idbGetAllEntries(db) {
91
+ const tx = db.transaction([VFS_STORE_NAME], 'readonly');
92
+ const store = tx.objectStore(VFS_STORE_NAME);
93
+ if (store.getAll && store.getAllKeys) {
94
+ const [items, keys] = await Promise.all([promisifyRequest(store.getAll()), promisifyRequest(store.getAllKeys())]);
95
+ const out = new Map();
96
+ for (let i = 0; i < keys.length; i++) out.set(String(keys[i]), items[i]);
97
+ return out;
98
+ }
99
+ return new Promise((resolve, reject) => {
100
+ const out = new Map();
101
+ const req = store.openCursor();
102
+ req.onsuccess = (e) => {
103
+ const cursor = e.target.result;
104
+ if (cursor) {
105
+ out.set(String(cursor.key), cursor.value);
106
+ cursor.continue();
107
+ } else {
108
+ resolve(out);
109
+ }
110
+ };
111
+ req.onerror = () => reject(req.error || new Error('Cursor failed'));
112
+ });
113
+ }
114
+
115
+ async function idbPutDeleteEntries(db, puts, deletes) {
116
+ const tx = db.transaction([VFS_STORE_NAME], 'readwrite');
117
+ const store = tx.objectStore(VFS_STORE_NAME);
118
+ for (const key of deletes || []) store.delete(key);
119
+ for (const [key, value] of puts || []) store.put(value, key);
120
+ return new Promise((resolve, reject) => {
121
+ tx.oncomplete = () => resolve();
122
+ tx.onerror = () => reject(tx.error || new Error('IDB batch failed'));
87
123
  });
88
124
  }
89
125
 
@@ -198,9 +234,27 @@ class IndexedDbFS {
198
234
  this._dbPromise = openVfsDB();
199
235
  try {
200
236
  const db = await this._dbPromise;
201
- const stored = coerceIndex(await idbGet(db, VFS_KEY));
202
- if (stored) {
203
- this.index = stored;
237
+ const legacyRaw = await idbGet(db, VFS_KEY);
238
+ const legacyIndex = coerceIndex(legacyRaw);
239
+ if (legacyIndex) {
240
+ this.index = legacyIndex;
241
+ const puts = Object.entries(this.index.entries);
242
+ await idbPutDeleteEntries(db, puts, [VFS_KEY]);
243
+ } else {
244
+ if (legacyRaw !== undefined && legacyRaw !== null) {
245
+ await idbDelete(db, VFS_KEY);
246
+ }
247
+ const map = await idbGetAllEntries(db);
248
+ if (map.size) {
249
+ const entries = {};
250
+ for (const [key, value] of map.entries()) {
251
+ if (key === VFS_KEY) continue;
252
+ if (value && typeof value === 'object' && typeof value.type === 'string') {
253
+ entries[key] = value;
254
+ }
255
+ }
256
+ if (Object.keys(entries).length) this.index = { entries };
257
+ }
204
258
  }
205
259
  } catch (err) {
206
260
  console.warn('[vfs] IndexedDB unavailable; using in-memory storage only.', err);
@@ -225,17 +279,25 @@ class IndexedDbFS {
225
279
  }
226
280
  if (!this.index.entries['/']) {
227
281
  this.index.entries['/'] = { type: 'dir', children: [], mtimeMs: nowMs(), mode: 0o777 };
228
- this._save();
282
+ this._save(['/']);
229
283
  }
230
284
  }
231
285
 
232
- _save() {
286
+ _save(puts = [], deletes = []) {
233
287
  if (!this._idbEnabled) return;
234
288
  if (!this._dbPromise) this._dbPromise = openVfsDB();
235
- const snapshot = this.index;
289
+ const entries = this.index.entries;
290
+ const putList = Array.isArray(puts) ? puts : [];
291
+ const deleteList = Array.isArray(deletes) ? deletes : [];
292
+ if (!putList.length && !deleteList.length) return;
293
+ const putPairs = [];
294
+ for (const key of putList) {
295
+ const entry = entries[key];
296
+ if (entry) putPairs.push([key, entry]);
297
+ }
236
298
  this._persistChain = this._persistChain
237
299
  .then(() => this._dbPromise)
238
- .then((db) => idbPut(db, VFS_KEY, snapshot))
300
+ .then((db) => idbPutDeleteEntries(db, putPairs, deleteList))
239
301
  .catch((err) => {
240
302
  console.warn('[vfs] Persist failed:', err);
241
303
  });
@@ -250,8 +312,10 @@ class IndexedDbFS {
250
312
  if (!eParent.children.includes(name)) {
251
313
  eParent.children.push(name);
252
314
  eParent.mtimeMs = nowMs();
315
+ return parent;
253
316
  }
254
317
  }
318
+ return null;
255
319
  }
256
320
  _unlinkFromParent(p) {
257
321
  const parent = dirname(p);
@@ -262,8 +326,10 @@ class IndexedDbFS {
262
326
  if (i >= 0) {
263
327
  eParent.children.splice(i, 1);
264
328
  eParent.mtimeMs = nowMs();
329
+ return parent;
265
330
  }
266
331
  }
332
+ return null;
267
333
  }
268
334
  _resolveEncoding(options) {
269
335
  if (!options) return null;
@@ -303,8 +369,12 @@ class IndexedDbFS {
303
369
  mtimeMs: nowMs(),
304
370
  mode: (options.mode ?? 0o666)
305
371
  };
306
- if (!exists) this._linkIntoParent(path);
307
- this._save();
372
+ const touched = new Set([path]);
373
+ if (!exists) {
374
+ const p = this._linkIntoParent(path);
375
+ if (p) touched.add(p);
376
+ }
377
+ this._save([...touched]);
308
378
  }
309
379
 
310
380
  appendFileSync(path, data, options = {}) {
@@ -337,7 +407,7 @@ class IndexedDbFS {
337
407
  existing.data = uint8ToBase64(merged);
338
408
  existing.size = merged.length;
339
409
  existing.mtimeMs = nowMs();
340
- this._save();
410
+ this._save([path]);
341
411
  }
342
412
 
343
413
  readFileSync(path, options = {}) {
@@ -368,21 +438,28 @@ class IndexedDbFS {
368
438
  const eParent = this.index.entries[parent];
369
439
  if (!eParent || eParent.type !== 'dir') throw this._enoent('ENOENT', parent);
370
440
  this.index.entries[path] = { type: 'dir', children: [], mtimeMs: nowMs(), mode: options.mode ?? 0o777 };
371
- this._linkIntoParent(path); this._save(); return;
441
+ const touched = new Set([path]);
442
+ const p = this._linkIntoParent(path);
443
+ if (p) touched.add(p);
444
+ this._save([...touched]);
445
+ return;
372
446
  }
373
447
  const parts = normalizePath(path).split('/').filter(Boolean);
374
448
  let cur = '/';
449
+ const touched = new Set();
375
450
  for (const part of parts) {
376
451
  const next = normalizePath(cur + '/' + part);
377
452
  if (!this.index.entries[next]) {
378
453
  this.index.entries[next] = { type: 'dir', children: [], mtimeMs: nowMs(), mode: 0o777 };
379
- this._linkIntoParent(next);
454
+ touched.add(next);
455
+ const p = this._linkIntoParent(next);
456
+ if (p) touched.add(p);
380
457
  } else if (this.index.entries[next].type !== 'dir') {
381
458
  throw this._eexist('EEXIST', next);
382
459
  }
383
460
  cur = next;
384
461
  }
385
- this._save();
462
+ if (touched.size) this._save([...touched]);
386
463
  }
387
464
 
388
465
  readdirSync(path, options = {}) {
@@ -411,8 +488,9 @@ class IndexedDbFS {
411
488
  if (!entry) throw this._enoent('ENOENT', path);
412
489
  if (entry.type !== 'file') throw this._enoent('EISDIR', path);
413
490
  delete this.index.entries[path];
414
- this._unlinkFromParent(path);
415
- this._save();
491
+ const p = this._unlinkFromParent(path);
492
+ const puts = p ? [p] : [];
493
+ this._save(puts, [path]);
416
494
  }
417
495
 
418
496
  rmdirSync(path, options = {}) {
@@ -425,6 +503,7 @@ class IndexedDbFS {
425
503
  if (entry.children.length && !recursive) {
426
504
  const err = new Error(`ENOTEMPTY: directory not empty, ${path}`); err.code = 'ENOTEMPTY'; throw err;
427
505
  }
506
+ const toDelete = [];
428
507
  if (recursive) {
429
508
  const stack = [path];
430
509
  while (stack.length) {
@@ -434,12 +513,16 @@ class IndexedDbFS {
434
513
  if (e.type === 'dir') {
435
514
  for (const name of e.children) stack.push(normalizePath(cur + '/' + name));
436
515
  }
437
- if (cur !== path) delete this.index.entries[cur];
516
+ delete this.index.entries[cur];
517
+ toDelete.push(cur);
438
518
  }
519
+ } else {
520
+ delete this.index.entries[path];
521
+ toDelete.push(path);
439
522
  }
440
- delete this.index.entries[path];
441
- this._unlinkFromParent(path);
442
- this._save();
523
+ const p = this._unlinkFromParent(path);
524
+ const puts = p ? [p] : [];
525
+ this._save(puts, toDelete);
443
526
  }
444
527
 
445
528
  renameSync(oldPath, newPath) {
@@ -453,18 +536,26 @@ class IndexedDbFS {
453
536
  const pEntry = this.index.entries[newParent];
454
537
  if (!pEntry || pEntry.type !== 'dir') throw this._enoent('ENOENT', newParent);
455
538
 
539
+ const toPut = new Set();
540
+ const toDelete = new Set();
456
541
  if (this.index.entries[newPath]) {
457
542
  if (this.index.entries[newPath].type === 'dir') {
458
543
  const err = new Error(`EISDIR: illegal operation on a directory, ${newPath}`); err.code = 'EISDIR'; throw err;
459
544
  }
545
+ toDelete.add(newPath);
460
546
  delete this.index.entries[newPath];
461
547
  }
462
548
 
463
549
  this.index.entries[newPath] = entry;
464
550
  delete this.index.entries[oldPath];
465
551
 
466
- this._unlinkFromParent(oldPath);
467
- this._linkIntoParent(newPath);
552
+ toDelete.add(oldPath);
553
+ toPut.add(newPath);
554
+
555
+ const oldParent = this._unlinkFromParent(oldPath);
556
+ const newParent2 = this._linkIntoParent(newPath);
557
+ if (oldParent) toPut.add(oldParent);
558
+ if (newParent2) toPut.add(newParent2);
468
559
 
469
560
  if (entry.type === 'dir') {
470
561
  const toFix = [];
@@ -476,11 +567,14 @@ class IndexedDbFS {
476
567
  const target = normalizePath(newPath + rel);
477
568
  this.index.entries[target] = this.index.entries[oldChild];
478
569
  delete this.index.entries[oldChild];
570
+ toDelete.add(oldChild);
571
+ toPut.add(target);
479
572
  }
480
573
  }
481
574
 
482
575
  entry.mtimeMs = nowMs();
483
- this._save();
576
+ toPut.add(newPath);
577
+ this._save([...toPut], [...toDelete]);
484
578
  }
485
579
 
486
580
  statSync(path) {
@@ -0,0 +1,2 @@
1
+ // Auto-generated by scripts/generateLicenseBundle.js
2
+ export const LICENSE_BUNDLE_TEXT = "brep-io-kernel License\nLicense: SEE LICENSE IN LICENSE.md\n\nCopyright 2025 Autodrop3d LLC\nhttps://autodrop3d.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and \nassociated documentation files (the \"Software\"), to deal in the Software without restriction, \nincluding without limitation the rights to use, copy, modify, merge, publish, distribute, \nsublicense, and/or sell copies of the Software, and to permit persons to whom the Software is \nfurnished to do so, subject to the following conditions:\n\n1. Any modifications made to the Software must be submitted to Autodrop3d LLC with an irrevocable \n assignment of the copyright via git pull request. This is intended to allow Autodrop3d LLC to \n sell commercial licenses of the Software for use in proprietary products under a \n dual-licensing strategy. Failure to contribute back modifications without a commercial \n license purchased from Autodrop3d LLC voids all permissions granted by this license.\n\n2. If Autodrop3d LLC is sold, merged, transferred, or otherwise succeeded by any entity or \n individual, all rights and obligations described in this license shall transfer automatically \n to that successor entity or individual.\n\n3. If Autodrop3d LLC ceases operations or dissolves, and no successor entity or individual \n continues to publicly host the Software in a manner that allows the public to obtain the source \n code and submit contributions for a period of at least eighteen (18) consecutive months, then \n Clauses 1 and 2 of this license shall be automatically and irrevocably canceled.\n\nThe above copyright notice and these permission notices shall be included in all copies or \nsubstantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING \nBUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, \nDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nThird-party licenses (production dependencies)\n55 packages • 9 license types\nGenerated from: pnpm licenses list --prod --long --json\n\n(MIT AND Zlib) (1 package)\n- pako@1.0.11 — zlib port to javascript - fast, modularized, with browser support — https://github.com/nodeca/pako\n\n(MIT OR GPL-3.0-or-later) (1 package)\n- jszip@3.10.1 — Create, read and edit .zip files with JavaScript http://stuartk.com/jszip — Author: Stuart Knightley — https://github.com/Stuk/jszip#readme\n\n(MPL-2.0 OR Apache-2.0) (1 package)\n- dompurify@3.2.7 — DOMPurify is a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG. It's written in JavaScript and works in all modern browsers (Safari, Opera (15+), Internet Explorer (10+), Firefox and Chrome - as well as almost anything else using Blink or WebKit). DOMPurify is written by security people who have vast background in web attacks and XSS. Fear not. — Author: Dr.-Ing. Mario Heiderich, Cure53 — https://github.com/cure53/DOMPurify\n\nApache-2.0 (5 packages)\n- @img/sharp-linux-x64@0.34.5 — Prebuilt sharp for use with Linux (glibc) x64 — Author: Lovell Fuller — https://sharp.pixelplumbing.com\n- @img/sharp-linuxmusl-x64@0.34.5 — Prebuilt sharp for use with Linux (musl) x64 — Author: Lovell Fuller — https://sharp.pixelplumbing.com\n- detect-libc@2.1.2 — Node.js module to detect the C standard library (libc) implementation family and version — Author: Lovell Fuller — https://github.com/lovell/detect-libc#readme\n- manifold-3d@3.3.2 — Geometry library for topological robustness — https://github.com/elalish/manifold#readme\n- sharp@0.34.5 — High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images — Author: Lovell Fuller — https://sharp.pixelplumbing.com\n\nbsd-2-clause (1 package)\n- esbuild-plugin-text-replace@1.3.0 — Replace Text with Regex in files before bundling. — Author: Andreas Heissenberger — https://github.com/aheissenberger/esbuild-plugin-text-replace\n\nISC (2 packages)\n- inherits@2.0.4 — Browser-friendly inheritance fully compatible with standard node.js inherits() — https://github.com/isaacs/inherits#readme\n- semver@7.7.3 — The semantic version parser used by npm. — Author: GitHub Inc. — https://github.com/npm/node-semver#readme\n\nLGPL-3.0-or-later (2 packages)\n- @img/sharp-libvips-linux-x64@1.2.4 — Prebuilt libvips and dependencies for use with sharp on Linux (glibc) x64 — Author: Lovell Fuller — https://sharp.pixelplumbing.com\n- @img/sharp-libvips-linuxmusl-x64@1.2.4 — Prebuilt libvips and dependencies for use with sharp on Linux (musl) x64 — Author: Lovell Fuller — https://sharp.pixelplumbing.com\n\nMIT (41 packages)\n- @gltf-transform/core@4.3.0 — glTF 2.0 SDK for JavaScript and TypeScript, on Web and Node.js. — Author: Don McCurdy — https://gltf-transform.dev/\n- @gltf-transform/extensions@4.3.0 — Adds extension support to @gltf-transform/core — Author: Don McCurdy — https://gltf-transform.dev/extensions.html\n- @gltf-transform/functions@4.3.0 — Functions for common glTF modifications, written using the core API — Author: Don McCurdy — https://gltf-transform.dev/functions.html\n- @img/colour@1.0.0 — The ESM-only 'color' package made compatible for use with CommonJS runtimes — https://github.com/lovell/colour#readme\n- @jridgewell/resolve-uri@3.1.2 — Resolve a URI relative to an optional base URI — Author: Justin Ridgewell — https://github.com/jridgewell/resolve-uri#readme\n- @jridgewell/sourcemap-codec@1.5.5 — Encode/decode sourcemap mappings — Author: Justin Ridgewell — https://github.com/jridgewell/sourcemaps/tree/main/packages/sourcemap-codec\n- @jridgewell/trace-mapping@0.3.31 — Trace the original position through a source map — Author: Justin Ridgewell — https://github.com/jridgewell/sourcemaps/tree/main/packages/trace-mapping\n- @jscadui/3mf-export@0.5.0 — 3mf export\n- @tarikjabiri/dxf@2.8.9 — A JavaScript interface to Dxf written in TypeScript. — Author: Tarik EL JABIRI — https://dxf.vercel.app\n- @types/ndarray@1.0.14 — TypeScript definitions for ndarray — https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/ndarray\n- @types/trusted-types@2.0.7 — TypeScript definitions for trusted-types — https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/trusted-types\n- commander@13.1.0 — the complete solution for node.js command-line programs — Author: TJ Holowaychuk — https://github.com/tj/commander.js#readme\n- convert-source-map@2.0.0 — Converts a source-map from/to different formats and allows adding/changing properties. — Author: Thorsten Lorenz — https://github.com/thlorenz/convert-source-map\n- core-js@3.48.0 — Standard library — Author: Denis Pushkarev — https://core-js.io\n- core-util-is@1.0.3 — The `util.is*` functions introduced in Node v0.12. — Author: Isaac Z. Schlueter — https://github.com/isaacs/core-util-is#readme\n- cwise-compiler@1.1.3 — cwise's internal compiler — Author: Mikola Lysenko — https://github.com/scijs/cwise-compiler#readme\n- esbuild-wasm@0.25.12 — The cross-platform WebAssembly binary for esbuild, a JavaScript bundler. — https://github.com/evanw/esbuild#readme\n- fflate@0.8.2 — High performance (de)compression in an 8kB package — Author: Arjun Barrett — https://101arrowz.github.io/fflate\n- immediate@3.0.6 — A cross browser microtask library — https://github.com/calvinmetcalf/immediate#readme\n- iota-array@1.0.0 — Generates an array of consecutive integers starting at 0 — Author: Mikola Lysenko — https://github.com/mikolalysenko/iota-array#readme\n- is-buffer@1.1.6 — Determine if an object is a Buffer — Author: Feross Aboukhadijeh — https://github.com/feross/is-buffer#readme\n- isarray@1.0.0 — Array#isArray for older browsers — Author: Julian Gruber — https://github.com/juliangruber/isarray\n- ktx-parse@1.1.0 — KTX 2.0 (.ktx2) parser and serializer. — Author: Don McCurdy — https://github.com/donmccurdy/ktx-parse#readme\n- lie@3.3.0 — A basic but performant promise implementation — https://github.com/calvinmetcalf/lie#readme\n- marked@14.0.0 — A markdown parser built for speed — Author: Christopher Jeffrey — https://marked.js.org\n- monaco-editor@0.55.1 — A browser based code editor — Author: Microsoft Corporation — https://github.com/microsoft/monaco-editor\n- ndarray@1.0.19 — Multidimensional Arrays — Author: Mikola Lysenko — https://github.com/mikolalysenko/ndarray#readme\n- ndarray-lanczos@0.3.0 — Resize an ndarray with Lanczos resampling — Author: Don McCurdy — https://github.com/donmccurdy/ndarray-lanczos#readme\n- ndarray-ops@1.2.2 — Common operations for ndarray arrays — Author: Mikola Lysenko — https://github.com/mikolalysenko/ndarray-ops#readme\n- ndarray-pixels@5.0.1 — ndarray-pixels — Author: Don McCurdy — https://github.com/donmccurdy/ndarray-pixels#readme\n- process-nextick-args@2.0.1 — process.nextTick but always with args — https://github.com/calvinmetcalf/process-nextick-args\n- property-graph@4.0.0 — Base for creating objects that behave like a Property Graph. — Author: Don McCurdy — https://github.com/donmccurdy/property-graph#readme\n- readable-stream@2.3.8 — Streams3, a user-land copy of the stream library from Node.js — https://github.com/nodejs/readable-stream#readme\n- safe-buffer@5.1.2 — Safer Node.js Buffer API — Author: Feross Aboukhadijeh — https://github.com/feross/safe-buffer\n- setimmediate@1.0.5 — A shim for the setImmediate efficient script yielding API — Author: YuzuJS — https://github.com/YuzuJS/setImmediate#readme\n- string_decoder@1.1.1 — The string_decoder module from Node core — https://github.com/nodejs/string_decoder\n- three@0.182.0 — JavaScript 3D library — Author: mrdoob — https://threejs.org/\n- three-mesh-bvh@0.9.8 — A BVH implementation to speed up raycasting against three.js meshes. — Author: Garrett Johnson — https://github.com/gkjohnson/three-mesh-bvh#readme\n- ts-replace-all@1.0.0 — https://github.com/LinusU/ts-replace-all#readme\n- uniq@1.0.1 — Removes duplicates from a sorted array in place — Author: Mikola Lysenko — https://github.com/mikolalysenko/uniq#readme\n- util-deprecate@1.0.2 — The Node.js `util.deprecate()` function with browser support — Author: Nathan Rajlich — https://github.com/TooTallNate/util-deprecate\n\nSGI-B-2.0 (1 package)\n- tess2@1.0.0 — GLU tesselator ported to Javascript, performs polygon boolean operations and triangulation — Author: Matt DesLauriers — https://github.com/memononen/tess2.js";