@needle-tools/engine 4.15.0-next.f391a30 → 4.16.0-next.35df6b8

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 (392) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/SKILL.md +237 -0
  3. package/components.needle.json +1 -1
  4. package/dist/{gltf-progressive-DYL3SLVb.min.js → gltf-progressive-DQa78GTA.min.js} +1 -1
  5. package/dist/{gltf-progressive-CMwJPwEt.umd.cjs → gltf-progressive-LOFTyzy4.umd.cjs} +1 -1
  6. package/dist/{gltf-progressive-CTlvpS3A.js → gltf-progressive-_wvokUUu.js} +3 -3
  7. package/dist/{materialx-NDD0y4JY.umd.cjs → materialx-BrPdNmQT.umd.cjs} +1 -1
  8. package/dist/{materialx-4jJLLe9Q.js → materialx-CT8J50pg.js} +2 -2
  9. package/dist/{materialx-Bt9FHwco.min.js → materialx-D_ofN96q.min.js} +1 -1
  10. package/dist/{needle-engine.bundle-DB4kLWO_.js → needle-engine.bundle-Bnwvh-4P.js} +3209 -3206
  11. package/dist/{needle-engine.bundle-C1BFRZDF.umd.cjs → needle-engine.bundle-DN7uXrFB.umd.cjs} +114 -116
  12. package/dist/{needle-engine.bundle-DsTdfmeb.min.js → needle-engine.bundle-DY3LoYIi.min.js} +109 -111
  13. package/dist/needle-engine.d.ts +63 -55
  14. package/dist/needle-engine.js +4 -4
  15. package/dist/needle-engine.min.js +1 -1
  16. package/dist/needle-engine.umd.cjs +1 -1
  17. package/dist/{postprocessing-De9ZpJrk.js → postprocessing-C-WOZQC5.js} +2 -2
  18. package/dist/{postprocessing-DYmYOVm4.umd.cjs → postprocessing-CtXfLXvp.umd.cjs} +1 -1
  19. package/dist/{postprocessing-BN-f4viE.min.js → postprocessing-DXm8YKbQ.min.js} +1 -1
  20. package/dist/{three-examples-C0ZCCA_K.js → three-examples.js} +1 -1
  21. package/dist/{three-examples-DmTY8tGr.min.js → three-examples.min.js} +1 -1
  22. package/dist/{three-examples-BHqRVpO_.umd.cjs → three-examples.umd.cjs} +1 -1
  23. package/dist/{three-mesh-ui-BlakAItG.js → three-mesh-ui-B-lqrZWj.js} +1 -1
  24. package/dist/{three-mesh-ui-D828VbQp.umd.cjs → three-mesh-ui-Chib781Y.umd.cjs} +1 -1
  25. package/dist/{three-mesh-ui-5HVE2RV-.min.js → three-mesh-ui-n3JU4M2W.min.js} +1 -1
  26. package/dist/{three-BjYim-vL.umd.cjs → three.umd.cjs} +1 -1
  27. package/dist/{vendor-ixwD-vv2.js → vendor-BsRxp-FT.js} +1 -1
  28. package/dist/{vendor-CIDkyBaO.umd.cjs → vendor-BwxpsdCm.umd.cjs} +1 -1
  29. package/dist/{vendor-BxK0WKmT.min.js → vendor-DZ45lcA8.min.js} +1 -1
  30. package/lib/asap/needle-asap.js.map +1 -1
  31. package/lib/asap/sessiongranted.js.map +1 -1
  32. package/lib/engine/analytics/index.d.ts +1 -1
  33. package/lib/engine/analytics/lcp.js.map +1 -1
  34. package/lib/engine/assets/index.js.map +1 -1
  35. package/lib/engine/debug/debug.d.ts +4 -4
  36. package/lib/engine/debug/debug.js +6 -6
  37. package/lib/engine/debug/debug.js.map +1 -1
  38. package/lib/engine/debug/debug_console.js.map +1 -1
  39. package/lib/engine/debug/debug_overlay.d.ts +16 -1
  40. package/lib/engine/debug/debug_overlay.js +47 -10
  41. package/lib/engine/debug/debug_overlay.js.map +1 -1
  42. package/lib/engine/debug/debug_spatial_console.js.map +1 -1
  43. package/lib/engine/debug/debug_spector.js.map +1 -1
  44. package/lib/engine/engine_accessibility.js.map +1 -1
  45. package/lib/engine/engine_addressables.d.ts +6 -3
  46. package/lib/engine/engine_addressables.js +10 -3
  47. package/lib/engine/engine_addressables.js.map +1 -1
  48. package/lib/engine/engine_animation.js.map +1 -1
  49. package/lib/engine/engine_application.d.ts +0 -7
  50. package/lib/engine/engine_application.js.map +1 -1
  51. package/lib/engine/engine_assetdatabase.js.map +1 -1
  52. package/lib/engine/engine_audio.js.map +1 -1
  53. package/lib/engine/engine_camera.fit.js.map +1 -1
  54. package/lib/engine/engine_camera.js.map +1 -1
  55. package/lib/engine/engine_components.js.map +1 -1
  56. package/lib/engine/engine_components_internal.js.map +1 -1
  57. package/lib/engine/engine_constants.js.map +1 -1
  58. package/lib/engine/engine_context.d.ts +0 -1
  59. package/lib/engine/engine_context.js +1 -1
  60. package/lib/engine/engine_context.js.map +1 -1
  61. package/lib/engine/engine_context_registry.js.map +1 -1
  62. package/lib/engine/engine_coroutine.js.map +1 -1
  63. package/lib/engine/engine_create_objects.js.map +1 -1
  64. package/lib/engine/engine_editor-sync.d.ts +1 -1
  65. package/lib/engine/engine_gameobject.js.map +1 -1
  66. package/lib/engine/engine_generic_utils.js.map +1 -1
  67. package/lib/engine/engine_gizmos.js.map +1 -1
  68. package/lib/engine/engine_gltf.js.map +1 -1
  69. package/lib/engine/engine_gltf_builtin_components.js +2 -2
  70. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  71. package/lib/engine/engine_hot_reload.js.map +1 -1
  72. package/lib/engine/engine_input.d.ts +0 -1
  73. package/lib/engine/engine_input.js.map +1 -1
  74. package/lib/engine/engine_instancing.js.map +1 -1
  75. package/lib/engine/engine_license.js.map +1 -1
  76. package/lib/engine/engine_lifecycle_functions_internal.js.map +1 -1
  77. package/lib/engine/engine_lightdata.js.map +1 -1
  78. package/lib/engine/engine_loaders.callbacks.js.map +1 -1
  79. package/lib/engine/engine_loaders.d.ts +7 -4
  80. package/lib/engine/engine_loaders.gltf.js.map +1 -1
  81. package/lib/engine/engine_loaders.js +7 -4
  82. package/lib/engine/engine_loaders.js.map +1 -1
  83. package/lib/engine/engine_lods.js.map +1 -1
  84. package/lib/engine/engine_mainloop_utils.d.ts +0 -1
  85. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  86. package/lib/engine/engine_materialpropertyblock.js.map +1 -1
  87. package/lib/engine/engine_math.js.map +1 -1
  88. package/lib/engine/engine_networking.js.map +1 -1
  89. package/lib/engine/engine_networking_auto.js.map +1 -1
  90. package/lib/engine/engine_networking_blob.js.map +1 -1
  91. package/lib/engine/engine_networking_files.js.map +1 -1
  92. package/lib/engine/engine_networking_instantiate.js.map +1 -1
  93. package/lib/engine/engine_networking_peer.js.map +1 -1
  94. package/lib/engine/engine_networking_streams.js +2 -0
  95. package/lib/engine/engine_networking_streams.js.map +1 -1
  96. package/lib/engine/engine_patcher.js.map +1 -1
  97. package/lib/engine/engine_physics.d.ts +2 -2
  98. package/lib/engine/engine_physics.js.map +1 -1
  99. package/lib/engine/engine_physics_rapier.js.map +1 -1
  100. package/lib/engine/engine_playerview.js.map +1 -1
  101. package/lib/engine/engine_pmrem.js.map +1 -1
  102. package/lib/engine/engine_scenelighting.d.ts +1 -1
  103. package/lib/engine/engine_scenelighting.js.map +1 -1
  104. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  105. package/lib/engine/engine_serialization_core.js.map +1 -1
  106. package/lib/engine/engine_serialization_decorator.d.ts +2 -2
  107. package/lib/engine/engine_serialization_decorator.js.map +1 -1
  108. package/lib/engine/engine_shaders.js.map +1 -1
  109. package/lib/engine/engine_shims.js.map +1 -1
  110. package/lib/engine/engine_texture.js.map +1 -1
  111. package/lib/engine/engine_three_utils.js.map +1 -1
  112. package/lib/engine/engine_time_utils.js.map +1 -1
  113. package/lib/engine/engine_tonemapping.js.map +1 -1
  114. package/lib/engine/engine_types.d.ts +0 -1
  115. package/lib/engine/engine_types.js.map +1 -1
  116. package/lib/engine/engine_typestore.js.map +1 -1
  117. package/lib/engine/engine_util_decorator.js +1 -1
  118. package/lib/engine/engine_util_decorator.js.map +1 -1
  119. package/lib/engine/engine_utils.js.map +1 -1
  120. package/lib/engine/engine_utils_attributes.js.map +1 -1
  121. package/lib/engine/engine_utils_format.js.map +1 -1
  122. package/lib/engine/engine_utils_qrcode.js.map +1 -1
  123. package/lib/engine/engine_utils_screenshot.js.map +1 -1
  124. package/lib/engine/engine_utils_screenshot.xr.js.map +1 -1
  125. package/lib/engine/export/gltf/EXT_mesh_gpu_instancing_exporter.js.map +1 -1
  126. package/lib/engine/export/gltf/Writers.js.map +1 -1
  127. package/lib/engine/export/gltf/index.js.map +1 -1
  128. package/lib/engine/export/state.js.map +1 -1
  129. package/lib/engine/extensions/EXT_texture_exr.js.map +1 -1
  130. package/lib/engine/extensions/NEEDLE_components.js.map +1 -1
  131. package/lib/engine/extensions/NEEDLE_gameobject_data.js.map +1 -1
  132. package/lib/engine/extensions/NEEDLE_lighting_settings.js.map +1 -1
  133. package/lib/engine/extensions/NEEDLE_lightmaps.js.map +1 -1
  134. package/lib/engine/extensions/NEEDLE_materialx.js.map +1 -1
  135. package/lib/engine/extensions/NEEDLE_persistent_assets.js.map +1 -1
  136. package/lib/engine/extensions/NEEDLE_render_objects.js.map +1 -1
  137. package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
  138. package/lib/engine/extensions/extension_utils.js.map +1 -1
  139. package/lib/engine/extensions/extensions.js.map +1 -1
  140. package/lib/engine/extensions/usage_tracker.js.map +1 -1
  141. package/lib/engine/js-extensions/ExtensionUtils.js.map +1 -1
  142. package/lib/engine/js-extensions/Object3D.js.map +1 -1
  143. package/lib/engine/js-extensions/RGBAColor.js.map +1 -1
  144. package/lib/engine/js-extensions/Vector.js.map +1 -1
  145. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
  146. package/lib/engine/shaders/shaderData.d.ts +6 -6
  147. package/lib/engine/tests/test_utils.js.map +1 -1
  148. package/lib/engine/webcomponents/WebXRButtons.d.ts +0 -1
  149. package/lib/engine/webcomponents/WebXRButtons.js.map +1 -1
  150. package/lib/engine/webcomponents/buttons.js.map +1 -1
  151. package/lib/engine/webcomponents/fonts.js.map +1 -1
  152. package/lib/engine/webcomponents/icons.js.map +1 -1
  153. package/lib/engine/webcomponents/logo-element.d.ts +3 -6
  154. package/lib/engine/webcomponents/logo-element.js +0 -18
  155. package/lib/engine/webcomponents/logo-element.js.map +1 -1
  156. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  157. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +7 -10
  158. package/lib/engine/webcomponents/needle menu/needle-menu.js +4 -16
  159. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  160. package/lib/engine/webcomponents/needle-button.js.map +1 -1
  161. package/lib/engine/webcomponents/needle-engine.ar-overlay.d.ts +0 -1
  162. package/lib/engine/webcomponents/needle-engine.ar-overlay.js.map +1 -1
  163. package/lib/engine/webcomponents/needle-engine.d.ts +0 -4
  164. package/lib/engine/webcomponents/needle-engine.js +1 -11
  165. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  166. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  167. package/lib/engine/xr/NeedleXRController.d.ts +0 -1
  168. package/lib/engine/xr/NeedleXRController.js +1 -1
  169. package/lib/engine/xr/NeedleXRController.js.map +1 -1
  170. package/lib/engine/xr/NeedleXRSession.d.ts +0 -1
  171. package/lib/engine/xr/NeedleXRSession.js.map +1 -1
  172. package/lib/engine/xr/NeedleXRSync.d.ts +0 -1
  173. package/lib/engine/xr/NeedleXRSync.js.map +1 -1
  174. package/lib/engine/xr/SceneTransition.js.map +1 -1
  175. package/lib/engine/xr/TempXRContext.d.ts +0 -1
  176. package/lib/engine/xr/TempXRContext.js.map +1 -1
  177. package/lib/engine/xr/events.js.map +1 -1
  178. package/lib/engine/xr/internal.js.map +1 -1
  179. package/lib/engine/xr/usdz.js.map +1 -1
  180. package/lib/engine/xr/utils.js.map +1 -1
  181. package/lib/engine-components/AlignmentConstraint.js.map +1 -1
  182. package/lib/engine-components/Animation.js.map +1 -1
  183. package/lib/engine-components/AnimationCurve.js.map +1 -1
  184. package/lib/engine-components/AnimationUtils.js.map +1 -1
  185. package/lib/engine-components/AnimationUtilsAutoplay.js.map +1 -1
  186. package/lib/engine-components/Animator.js.map +1 -1
  187. package/lib/engine-components/AnimatorController.js +1 -1
  188. package/lib/engine-components/AnimatorController.js.map +1 -1
  189. package/lib/engine-components/AudioListener.js.map +1 -1
  190. package/lib/engine-components/AudioSource.js.map +1 -1
  191. package/lib/engine-components/AvatarLoader.js.map +1 -1
  192. package/lib/engine-components/AxesHelper.js.map +1 -1
  193. package/lib/engine-components/BoxHelperComponent.js.map +1 -1
  194. package/lib/engine-components/Camera.js.map +1 -1
  195. package/lib/engine-components/CameraUtils.js.map +1 -1
  196. package/lib/engine-components/CharacterController.js.map +1 -1
  197. package/lib/engine-components/Collider.js.map +1 -1
  198. package/lib/engine-components/Component.d.ts +0 -1
  199. package/lib/engine-components/Component.js.map +1 -1
  200. package/lib/engine-components/ContactShadows.d.ts +0 -1
  201. package/lib/engine-components/ContactShadows.js.map +1 -1
  202. package/lib/engine-components/DeleteBox.js.map +1 -1
  203. package/lib/engine-components/DeviceFlag.js.map +1 -1
  204. package/lib/engine-components/DragControls.js +10 -0
  205. package/lib/engine-components/DragControls.js.map +1 -1
  206. package/lib/engine-components/DropListener.js.map +1 -1
  207. package/lib/engine-components/Duplicatable.js +8 -1
  208. package/lib/engine-components/Duplicatable.js.map +1 -1
  209. package/lib/engine-components/EventList.js.map +1 -1
  210. package/lib/engine-components/EventTrigger.js.map +1 -1
  211. package/lib/engine-components/Gizmos.js.map +1 -1
  212. package/lib/engine-components/GridHelper.js.map +1 -1
  213. package/lib/engine-components/GroundProjection.js.map +1 -1
  214. package/lib/engine-components/Joints.js.map +1 -1
  215. package/lib/engine-components/LODGroup.js.map +1 -1
  216. package/lib/engine-components/Light.js.map +1 -1
  217. package/lib/engine-components/NeedleMenu.js.map +1 -1
  218. package/lib/engine-components/NestedGltf.js.map +1 -1
  219. package/lib/engine-components/Networking.js.map +1 -1
  220. package/lib/engine-components/OffsetConstraint.js.map +1 -1
  221. package/lib/engine-components/OrbitControls.js.map +1 -1
  222. package/lib/engine-components/PlayerColor.js.map +1 -1
  223. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  224. package/lib/engine-components/Renderer.js +2 -1
  225. package/lib/engine-components/Renderer.js.map +1 -1
  226. package/lib/engine-components/RendererInstancing.js.map +1 -1
  227. package/lib/engine-components/RendererLightmap.js.map +1 -1
  228. package/lib/engine-components/RigidBody.js.map +1 -1
  229. package/lib/engine-components/SceneSwitcher.js.map +1 -1
  230. package/lib/engine-components/ScreenCapture.js.map +1 -1
  231. package/lib/engine-components/SeeThrough.js.map +1 -1
  232. package/lib/engine-components/ShadowCatcher.js.map +1 -1
  233. package/lib/engine-components/Skybox.js.map +1 -1
  234. package/lib/engine-components/SmoothFollow.js.map +1 -1
  235. package/lib/engine-components/SpatialTrigger.js.map +1 -1
  236. package/lib/engine-components/SpectatorCamera.js.map +1 -1
  237. package/lib/engine-components/SpriteRenderer.js.map +1 -1
  238. package/lib/engine-components/SyncedCamera.js.map +1 -1
  239. package/lib/engine-components/SyncedRoom.js +1 -1
  240. package/lib/engine-components/SyncedRoom.js.map +1 -1
  241. package/lib/engine-components/SyncedTransform.js.map +1 -1
  242. package/lib/engine-components/TestRunner.js.map +1 -1
  243. package/lib/engine-components/TransformGizmo.js.map +1 -1
  244. package/lib/engine-components/VideoPlayer.js.map +1 -1
  245. package/lib/engine-components/Voip.js.map +1 -1
  246. package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +1 -1
  247. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +1 -1
  248. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +1 -1
  249. package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +1 -1
  250. package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +1 -1
  251. package/lib/engine-components/debug/LogStats.js.map +1 -1
  252. package/lib/engine-components/export/gltf/GltfExport.js +1 -1
  253. package/lib/engine-components/export/gltf/GltfExport.js.map +1 -1
  254. package/lib/engine-components/export/usdz/ThreeUSDZExporter.d.ts +1 -1
  255. package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +23 -23
  256. package/lib/engine-components/export/usdz/ThreeUSDZExporter.js.map +1 -1
  257. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  258. package/lib/engine-components/export/usdz/extensions/Animation.d.ts +2 -2
  259. package/lib/engine-components/export/usdz/extensions/Animation.js.map +1 -1
  260. package/lib/engine-components/export/usdz/extensions/NodeMaterialConverter.js.map +1 -1
  261. package/lib/engine-components/export/usdz/extensions/USDZText.js.map +1 -1
  262. package/lib/engine-components/export/usdz/extensions/USDZUI.js.map +1 -1
  263. package/lib/engine-components/export/usdz/extensions/behavior/Actions.js.map +1 -1
  264. package/lib/engine-components/export/usdz/extensions/behavior/AudioExtension.js.map +1 -1
  265. package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js.map +1 -1
  266. package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js.map +1 -1
  267. package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js.map +1 -1
  268. package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js.map +1 -1
  269. package/lib/engine-components/export/usdz/utils/animationutils.js.map +1 -1
  270. package/lib/engine-components/export/usdz/utils/quicklook.js.map +1 -1
  271. package/lib/engine-components/particlesystem/ParticleSystem.js.map +1 -1
  272. package/lib/engine-components/particlesystem/ParticleSystemModules.js.map +1 -1
  273. package/lib/engine-components/particlesystem/ParticleSystemSubEmitter.js.map +1 -1
  274. package/lib/engine-components/postprocessing/Effects/Antialiasing.js.map +1 -1
  275. package/lib/engine-components/postprocessing/Effects/BloomEffect.js +2 -2
  276. package/lib/engine-components/postprocessing/Effects/BloomEffect.js.map +1 -1
  277. package/lib/engine-components/postprocessing/Effects/ChromaticAberration.js.map +1 -1
  278. package/lib/engine-components/postprocessing/Effects/ColorAdjustments.js.map +1 -1
  279. package/lib/engine-components/postprocessing/Effects/DepthOfField.js.map +1 -1
  280. package/lib/engine-components/postprocessing/Effects/Pixelation.js.map +1 -1
  281. package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.js +2 -2
  282. package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.js.map +1 -1
  283. package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.js.map +1 -1
  284. package/lib/engine-components/postprocessing/Effects/Tonemapping.js.map +1 -1
  285. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +3 -3
  286. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.js.map +1 -1
  287. package/lib/engine-components/postprocessing/PostProcessingEffect.js.map +1 -1
  288. package/lib/engine-components/postprocessing/PostProcessingHandler.js.map +1 -1
  289. package/lib/engine-components/postprocessing/Volume.js.map +1 -1
  290. package/lib/engine-components/postprocessing/VolumeParameter.js.map +1 -1
  291. package/lib/engine-components/postprocessing/VolumeProfile.js.map +1 -1
  292. package/lib/engine-components/postprocessing/utils.js.map +1 -1
  293. package/lib/engine-components/splines/Spline.js.map +1 -1
  294. package/lib/engine-components/splines/SplineWalker.js.map +1 -1
  295. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  296. package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
  297. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  298. package/lib/engine-components/ui/BaseUIComponent.js.map +1 -1
  299. package/lib/engine-components/ui/Button.js.map +1 -1
  300. package/lib/engine-components/ui/Canvas.js.map +1 -1
  301. package/lib/engine-components/ui/CanvasGroup.js.map +1 -1
  302. package/lib/engine-components/ui/EventSystem.js.map +1 -1
  303. package/lib/engine-components/ui/Graphic.js.map +1 -1
  304. package/lib/engine-components/ui/Image.js.map +1 -1
  305. package/lib/engine-components/ui/InputField.js.map +1 -1
  306. package/lib/engine-components/ui/Layout.js.map +1 -1
  307. package/lib/engine-components/ui/PointerEvents.d.ts +0 -1
  308. package/lib/engine-components/ui/PointerEvents.js.map +1 -1
  309. package/lib/engine-components/ui/RaycastUtils.js.map +1 -1
  310. package/lib/engine-components/ui/Raycaster.js.map +1 -1
  311. package/lib/engine-components/ui/RectTransform.js +2 -2
  312. package/lib/engine-components/ui/RectTransform.js.map +1 -1
  313. package/lib/engine-components/ui/SpatialHtml.js.map +1 -1
  314. package/lib/engine-components/ui/Text.js.map +1 -1
  315. package/lib/engine-components/ui/Utils.js.map +1 -1
  316. package/lib/engine-components/utils/EnvironmentScene.js.map +1 -1
  317. package/lib/engine-components/utils/LookAt.js.map +1 -1
  318. package/lib/engine-components/utils/OpenURL.js.map +1 -1
  319. package/lib/engine-components/web/Clickthrough.js.map +1 -1
  320. package/lib/engine-components/web/CursorFollow.js.map +1 -1
  321. package/lib/engine-components/web/HoverAnimation.js.map +1 -1
  322. package/lib/engine-components/web/ScrollFollow.js.map +1 -1
  323. package/lib/engine-components/web/ViewBox.js +2 -1
  324. package/lib/engine-components/web/ViewBox.js.map +1 -1
  325. package/lib/engine-components/webxr/Avatar.js.map +1 -1
  326. package/lib/engine-components/webxr/WebARCameraBackground.d.ts +0 -1
  327. package/lib/engine-components/webxr/WebARCameraBackground.js.map +1 -1
  328. package/lib/engine-components/webxr/WebARSessionRoot.d.ts +0 -1
  329. package/lib/engine-components/webxr/WebARSessionRoot.js.map +1 -1
  330. package/lib/engine-components/webxr/WebXR.d.ts +0 -1
  331. package/lib/engine-components/webxr/WebXR.js.map +1 -1
  332. package/lib/engine-components/webxr/WebXRImageTracking.d.ts +0 -1
  333. package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
  334. package/lib/engine-components/webxr/WebXRPlaneTracking.d.ts +2 -3
  335. package/lib/engine-components/webxr/WebXRPlaneTracking.js.map +1 -1
  336. package/lib/engine-components/webxr/WebXRRig.d.ts +0 -1
  337. package/lib/engine-components/webxr/WebXRRig.js.map +1 -1
  338. package/lib/engine-components/webxr/XRFlag.js.map +1 -1
  339. package/lib/engine-components/webxr/controllers/XRControllerFollow.d.ts +0 -1
  340. package/lib/engine-components/webxr/controllers/XRControllerFollow.js.map +1 -1
  341. package/lib/engine-components/webxr/controllers/XRControllerModel.d.ts +0 -1
  342. package/lib/engine-components/webxr/controllers/XRControllerModel.js.map +1 -1
  343. package/lib/engine-components/webxr/controllers/XRControllerMovement.js.map +1 -1
  344. package/lib/engine-components-experimental/Presentation.js.map +1 -1
  345. package/lib/engine-components-experimental/networking/PlayerSync.js.map +1 -1
  346. package/lib/engine-schemes/schemes.js.map +1 -1
  347. package/lib/needle-engine.js.map +1 -1
  348. package/package.json +6 -3
  349. package/plugins/common/buildinfo.js +1 -1
  350. package/plugins/common/license.js +5 -6
  351. package/plugins/common/logger.js +104 -14
  352. package/plugins/types/userconfig.d.ts +2 -0
  353. package/plugins/vite/ai.js +4 -18
  354. package/plugins/vite/alias.js +0 -13
  355. package/plugins/vite/asap.js +1 -1
  356. package/plugins/vite/build-pipeline.js +2 -5
  357. package/plugins/vite/buildinfo.js +9 -9
  358. package/plugins/vite/copyfiles.js +19 -16
  359. package/plugins/vite/custom-element-data.js +4 -4
  360. package/plugins/vite/dependencies.js +45 -18
  361. package/plugins/vite/dependency-watcher.js +10 -8
  362. package/plugins/vite/imports-logger.js +14 -12
  363. package/plugins/vite/local-files-analysis.js +10 -12
  364. package/plugins/vite/local-files-core.js +8 -8
  365. package/plugins/vite/local-files-types.d.ts +49 -11
  366. package/plugins/vite/local-files-utils.js +14 -10
  367. package/plugins/vite/logger.client.js +4 -4
  368. package/plugins/vite/logger.js +7 -7
  369. package/plugins/vite/logging.js +26 -3
  370. package/plugins/vite/pwa.js +6 -5
  371. package/plugins/vite/reload.js +27 -24
  372. package/src/asap/needle-asap.ts +1 -1
  373. package/src/engine/debug/debug.ts +8 -7
  374. package/src/engine/debug/debug_overlay.ts +66 -12
  375. package/src/engine/debug/debug_spector.ts +1 -1
  376. package/src/engine/engine_addressables.ts +11 -3
  377. package/src/engine/engine_application.ts +0 -7
  378. package/src/engine/engine_context.ts +1 -1
  379. package/src/engine/engine_gltf_builtin_components.ts +1 -1
  380. package/src/engine/engine_loaders.ts +7 -4
  381. package/src/engine/engine_networking_streams.ts +1 -0
  382. package/src/engine/engine_util_decorator.ts +2 -2
  383. package/src/engine/webcomponents/logo-element.ts +3 -20
  384. package/src/engine/webcomponents/needle menu/needle-menu.ts +11 -25
  385. package/src/engine/webcomponents/needle-engine.ts +1 -13
  386. package/src/engine-components/DragControls.ts +14 -0
  387. package/src/engine-components/Duplicatable.ts +9 -1
  388. package/src/engine-components/Renderer.ts +2 -1
  389. package/src/engine-components/SyncedRoom.ts +1 -1
  390. package/src/engine-components/export/usdz/USDZExporter.ts +1 -1
  391. /package/dist/{three-Bvk2VKbF.js → three.js} +0 -0
  392. /package/dist/{three-IG2qPafA.min.js → three.min.js} +0 -0
@@ -31,19 +31,33 @@ const buildOutputState = {
31
31
  compressionCaptureActive: false,
32
32
  };
33
33
 
34
- /** @param {unknown} value @returns {number} */
34
+ /**
35
+ * Parses a numeric kB value from a potentially formatted string (e.g. "1.23 kB"),
36
+ * stripping all non-numeric characters except the decimal point.
37
+ * Returns 0 for any value that cannot be parsed as a finite number.
38
+ * @param {unknown} value @returns {number}
39
+ */
35
40
  function parseKb(value) {
36
41
  const numeric = Number.parseFloat(String(value ?? "0").replace(/[^0-9.]/g, ""));
37
42
  return Number.isFinite(numeric) ? numeric : 0;
38
43
  }
39
44
 
45
+ /**
46
+ * Clears the current in-place progress line from the terminal, if one is active.
47
+ * Has no effect in non-TTY environments (CI, piped output).
48
+ */
40
49
  function clearBuildProgressLine() {
41
50
  if (!process.stdout.isTTY || !buildOutputState.progressActive) return;
42
51
  process.stdout.write("\r\x1b[2K");
43
52
  buildOutputState.progressActive = false;
44
53
  }
45
54
 
46
- /** @param {string} text */
55
+ /**
56
+ * Overwrites the current terminal line with a transient build progress indicator.
57
+ * Subsequent calls overwrite the same line in place, keeping the output clean.
58
+ * Has no effect in non-TTY environments (CI, piped output).
59
+ * @param {string} text
60
+ */
47
61
  function writeBuildProgressLine(text) {
48
62
  if (!process.stdout.isTTY) return;
49
63
  const maxLength = Math.max(24, (process.stdout.columns || 120) - 1);
@@ -52,6 +66,10 @@ function writeBuildProgressLine(text) {
52
66
  buildOutputState.progressActive = true;
53
67
  }
54
68
 
69
+ /**
70
+ * Resets all per-build asset and compression counters back to zero.
71
+ * Called at the start of each build and after summaries are flushed.
72
+ */
55
73
  function resetBuildOutputState() {
56
74
  buildOutputState.progressActive = false;
57
75
  buildOutputState.assetFiles = 0;
@@ -63,6 +81,16 @@ function resetBuildOutputState() {
63
81
  buildOutputState.compressionCaptureActive = false;
64
82
  }
65
83
 
84
+ /**
85
+ * Emits aggregated bundle/compression summary lines to stdout, then resets counters.
86
+ *
87
+ * During a build, Vite normally prints one line per output file (e.g.
88
+ * "dist/foo.js 1.23 kB │ gzip: 0.45 kB"). Those lines are intercepted by
89
+ * tryHandleBuildConsoleOutput, which silently accumulates file counts and sizes
90
+ * instead of printing them. This function is called once bundling finishes (when
91
+ * Vite emits "✓ built in …") and replaces all the per-file lines with a single
92
+ * formatted summary like "[needle-buildinfo]\n✓ Bundled 27 files (1234.56 kB)".
93
+ */
66
94
  function flushBuildOutputSummaries() {
67
95
  if (buildOutputState.mode !== "build") return;
68
96
  clearBuildProgressLine();
@@ -82,11 +110,20 @@ function flushBuildOutputSummaries() {
82
110
  resetBuildOutputState();
83
111
  }
84
112
 
113
+ /**
114
+ * Returns true if stdout is a TTY and the NO_COLOR environment variable is not set.
115
+ * Used to guard ANSI escape sequences so output stays clean in CI and piped contexts.
116
+ */
85
117
  function supportsColorOutput() {
86
118
  return !!process.stdout?.isTTY && process.env.NO_COLOR !== "1";
87
119
  }
88
120
 
89
- /** @param {string} name @returns {string} */
121
+ /**
122
+ * Formats a plugin name as a styled [header] string.
123
+ * Names starting with "needle-" or "needle:" get ANSI green coloring with a bold suffix.
124
+ * Falls back to plain "[name]" when color output is not supported.
125
+ * @param {string} name @returns {string}
126
+ */
90
127
  function formatNeedleHeader(name) {
91
128
  if (!supportsColorOutput()) return `[${name}]`;
92
129
  if (name.startsWith("needle-")) {
@@ -100,17 +137,39 @@ function formatNeedleHeader(name) {
100
137
  return `\x1b[32m[\x1b[0m\x1b[1;32m${name}\x1b[0m\x1b[32m]\x1b[0m`;
101
138
  }
102
139
 
103
- /** @param {string} body @returns {string} */
140
+ /**
141
+ * Wraps a build summary string under the [needle-buildinfo] header.
142
+ * Used by flushBuildOutputSummaries to format the final "✓ Bundled N files"
143
+ * and "✓ Gzip compressed N files" lines.
144
+ * @param {string} body @returns {string}
145
+ */
104
146
  function formatBuildInfoSummaryMessage(body) {
105
147
  return `${formatNeedleHeader("needle-buildinfo")}\n${body}`;
106
148
  }
107
149
 
108
- /** @param {unknown[]} args @returns {string} */
150
+ /**
151
+ * Joins an array of console.log arguments into a single string,
152
+ * serializing non-string values with stringifyLog.
153
+ * @param {unknown[]} args @returns {string}
154
+ */
109
155
  function normalizeConsoleArgs(args) {
110
156
  return args.map(arg => typeof arg === "string" ? arg : stringifyLog(arg)).join(" ");
111
157
  }
112
158
 
113
- /** @param {unknown[]} args @returns {boolean} */
159
+ /**
160
+ * Intercepts console output during a build run and decides whether to suppress or forward it.
161
+ *
162
+ * - Per-file asset lines ("dist/foo.js 1.23 kB") are silently accumulated into
163
+ * buildOutputState counters and replaced by a summary via flushBuildOutputSummaries.
164
+ * - vite-plugin-compression per-file lines are similarly accumulated.
165
+ * - "transforming (N)" progress messages are rendered as an animated in-place indicator.
166
+ * - Any other message (including "✓ built in …") triggers flushBuildOutputSummaries
167
+ * before passing through.
168
+ *
169
+ * Returns true if the message was fully consumed (caller must not forward to original
170
+ * console), or false if it should pass through normally.
171
+ * @param {unknown[]} args @returns {boolean}
172
+ */
114
173
  function tryHandleBuildConsoleOutput(args) {
115
174
  if (buildOutputState.mode !== "build") return false;
116
175
 
@@ -158,8 +217,22 @@ function tryHandleBuildConsoleOutput(args) {
158
217
  }
159
218
 
160
219
  /**
220
+ * Patches the global console methods to intercept and process Vite build output.
221
+ *
222
+ * In build mode, per-file asset lines emitted by Vite (and vite-plugin-compression)
223
+ * are absorbed silently, counts and sizes are accumulated, and a concise summary is
224
+ * printed by flushBuildOutputSummaries once bundling completes. In serve mode all
225
+ * messages pass through unchanged.
226
+ *
227
+ * All console output (log/error/warn/info/debug) is also written to a rotating
228
+ * timestamped log file under node_modules/.needle/logs/ via captureLogMessage.
229
+ *
230
+ * Calling patchConsoleLogs a second time is a no-op and returns the same unpatch
231
+ * function. Call the returned function to restore the original console methods and
232
+ * flush any pending summaries.
233
+ *
161
234
  * @param {{command?: string} | undefined} [options]
162
- * @returns {(() => void) | undefined}
235
+ * @returns {(() => void) | null}
163
236
  */
164
237
  export function patchConsoleLogs(options = undefined) {
165
238
  if (didPatch) return unpatchFunction;
@@ -216,6 +289,13 @@ const isCapturingLogMessage = new Set();
216
289
  const queue = new Array();
217
290
 
218
291
  /**
292
+ * Serializes a log message and appends it to the rotating per-process log file
293
+ * (node_modules/.needle/logs/<timestamp>.server.needle.log).
294
+ *
295
+ * Re-entrant calls while a capture is already in progress are queued and
296
+ * processed afterwards to prevent recursive logging loops. Circular references
297
+ * in the log value are also guarded against via the isCapturingLogMessage set.
298
+ *
219
299
  * @param {ProcessType} process
220
300
  * @param {string} key
221
301
  * @param {unknown} log
@@ -236,7 +316,7 @@ export function captureLogMessage(process, key, log, connectionId, time = Date.n
236
316
  isCapturingLogMessage.add(log);
237
317
 
238
318
  try {
239
- let str = stringifyLog(log);
319
+ let str = /** @type {string} */(stringifyLog(log));
240
320
  if (str.trim().length > 0) {
241
321
  // if(process === "server") str = stripAnsiColors(str);
242
322
  const prefix = `${getTimestamp(time, true)}, ${process}${connectionId ? (`[${connectionId}]`) : ""}.${key}: `;
@@ -261,7 +341,10 @@ export function captureLogMessage(process, key, log, connectionId, time = Date.n
261
341
 
262
342
 
263
343
  /**
264
- * Stringifies a log message, handling circular references and formatting.
344
+ * Recursively serializes an arbitrary value to a human-readable string.
345
+ * Handles primitives, plain objects, arrays, typed arrays, Error instances,
346
+ * circular references, and truncates large values based on per-environment limits
347
+ * (server limits are more generous than browser limits).
265
348
  * @param {unknown} log
266
349
  * @param {Set<unknown>} [seen]
267
350
  */
@@ -389,8 +472,10 @@ function stringifyLog(log, seen = /** @type {Set<unknown>} */ (new Set()), depth
389
472
  // #region utility functions
390
473
 
391
474
  /**
392
- * Returns the current timestamp in ISO format.
393
- * @param {number} [date] - Optional date to format, defaults to current date.
475
+ * Returns the current time as a HH:MM:SS string (timeOnly=true) or a full ISO 8601
476
+ * timestamp string. Used as a prefix in log file entries.
477
+ * @param {number} [date] - Optional timestamp in ms, defaults to now.
478
+ * @param {boolean} [timeOnly]
394
479
  */
395
480
  function getTimestamp(date, timeOnly = false) {
396
481
  const now = date ? new Date(date) : new Date();
@@ -467,12 +552,14 @@ if (existsSync(fileLogDirectory)) {
467
552
  }
468
553
 
469
554
  /**
470
- * Writes a log message to the file.
555
+ * Appends a single log entry to the per-process rotating file log.
556
+ * The file is created lazily under node_modules/.needle/logs/ on first write,
557
+ * using a timestamped filename so each process start gets a fresh file.
471
558
  * @param {ProcessType} process
472
559
  * @param {string} log
473
- * @param {string | null} connectionId - Optional connection ID for client logs.
560
+ * @param {string | null} _connectionId - Reserved for future per-connection log files.
474
561
  */
475
- function writeToFile(process, log, connectionId) {
562
+ function writeToFile(process, log, _connectionId) {
476
563
  const filename = `${process}.needle.log`; //connectionId && process === "client" ? `${process}-${connectionId}.needle.log` : `${process}.needle.log`;
477
564
 
478
565
  if (!filestreams.has(filename)) {
@@ -492,11 +579,14 @@ function writeToFile(process, log, connectionId) {
492
579
 
493
580
 
494
581
  // #region process exit
582
+
583
+ /** Flushes and closes all open log write streams. Registered for all exit-related process events. */
495
584
  function onExit() {
496
585
  filestreams.forEach((stream) => stream.end());
497
586
  filestreams.clear();
498
587
  }
499
588
 
589
+ /** Explicitly close all log file streams. Call this before a clean process exit (e.g. end of a build run). */
500
590
  export function closeLogStreams() {
501
591
  onExit();
502
592
  }
@@ -14,6 +14,8 @@ export type userSettings = {
14
14
 
15
15
  /** disable vite.alias modification */
16
16
  noAlias?: boolean;
17
+ /** Enable verbose debug output for needle plugins. */
18
+ debug?: boolean;
17
19
  /**
18
20
  * When set to `true` a plugin will log all alias resolutions to a file in the project node_modules directory
19
21
  * @default false
@@ -36,27 +36,14 @@ export const needleAI = (command, config, userSettings) => {
36
36
  };
37
37
  };
38
38
 
39
- /** Read the engine version from our own package.json */
40
- function getEngineVersion() {
41
- try {
42
- const pkgPath = join(__dirname, "../../package.json");
43
- const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
44
- return pkg.version || "unknown";
45
- }
46
- catch {
47
- return "unknown";
48
- }
49
- }
50
-
51
- function writeSkill(claudeDir, version) {
39
+ function writeSkill(claudeDir) {
52
40
  const skillDir = join(claudeDir, "skills", "needle-engine");
53
41
  if (!existsSync(skillDir)) {
54
42
  mkdirSync(skillDir, { recursive: true });
55
43
  }
56
44
  const skillPath = join(skillDir, "SKILL.md");
57
- const templatePath = join(__dirname, "../common/needle-engine-skill.md");
58
- const template = readFileSync(templatePath, "utf8");
59
- const content = template.replace("{{VERSION}}", version);
45
+ const templatePath = join(__dirname, "../../SKILL.md");
46
+ const content = readFileSync(templatePath, "utf8");
60
47
  writeFileSync(skillPath, content, "utf8");
61
48
  return skillPath;
62
49
  }
@@ -65,7 +52,6 @@ function installClaudeSkill() {
65
52
  const claudeDir = join(process.cwd(), ".claude");
66
53
  if (!existsSync(claudeDir)) return; // only install if developer uses Claude Code
67
54
 
68
- const version = getEngineVersion();
69
- const path = writeSkill(claudeDir, version);
55
+ const path = writeSkill(claudeDir);
70
56
  console.log(`[${pluginName}] Installed Needle Engine Claude skill → ${path}`);
71
57
  }
@@ -112,19 +112,6 @@ export const needleViteAlias = (command, config, userSettings) => {
112
112
  }
113
113
 
114
114
 
115
- // is needle engine a local package?
116
- // This will cause local changes to not be reflected anymore...
117
- const localEnginePath = path.resolve(projectDir, 'node_modules/', '@needle-tools/engine', 'node_modules', '.package-lock.json');
118
- if (existsSync(localEnginePath)) {
119
- config.optimizeDeps ??= {};
120
- config.optimizeDeps.exclude ??= [];
121
- if (!config.optimizeDeps.include?.includes('@needle-tools/engine')) {
122
- config.optimizeDeps.exclude.push('@needle-tools/engine');
123
- log("Detected local @needle-tools/engine package → will exclude it from optimization");
124
- }
125
- }
126
-
127
-
128
115
  if (debug) {
129
116
  const testResults = [];
130
117
  for (const name in aliasDict) {
@@ -202,7 +202,7 @@ function generateGltfPreloadLinks(config, html, tags) {
202
202
  filepath = decodeURIComponent(filepath);
203
203
  const fullpath = path.join(process.cwd(), filepath);
204
204
  if (!existsSync(fullpath)) {
205
- needleLog("needle:asap", `Could not insert head preload link: file not found at \"${filepath}\"`, "warn", { dimBody: false });
205
+ if (process.env.DEBUG) needleLog("needle:asap", `Could not insert head preload link: file not found at "${filepath}"`, "log", { dimBody: true });
206
206
  continue;
207
207
  }
208
208
  }
@@ -196,11 +196,9 @@ export const needleBuildPipeline = async (command, config, userSettings) => {
196
196
  const key = (/** @type {string} */ text) => supportsColor ? needleBlue(text) : text;
197
197
  const outputPath = relative(process.cwd(), buildPipelineTaskResults.outputDirectory).replaceAll("\\", "/") || ".";
198
198
  const moved = getDirectoryStats(buildPipelineTaskResults.tempDirectory);
199
- lines.push(`${key("Copying files")}: \"${outputPath}\"`);
200
199
  const ctx = { count: 0, bytes: 0 }
201
200
  copyFilesSync(buildPipelineTaskResults.tempDirectory, buildPipelineTaskResults.outputDirectory, true, ctx);
202
- lines.push(`${key("Copied files")}: ${ctx.count}`);
203
- lines.push(`${key("Data moved")}: ${formatBytes(moved.totalBytes)} (${moved.fileCount} files)`);
201
+ lines.push(`${key("Copying")}: "${outputPath}" — ${moved.fileCount} file${moved.fileCount !== 1 ? 's' : ''}, ${formatBytes(moved.totalBytes)}`);
204
202
  }
205
203
  else {
206
204
  lines.push("No files to copy - build pipeline did not run or did not finish successfully");
@@ -306,8 +304,7 @@ async function invokeBuildPipeline(opts, options = {}) {
306
304
  }
307
305
  }, 0);
308
306
  needleLog("needle-buildpipeline", [
309
- `${key("Files to process")}: ${files.length} in ${rel(outputDirectory)}`,
310
- `${key("Input size")}: ${formatBytes(filesBytes)}`,
307
+ `${key("Files to process")}: ${files.length} in ${rel(outputDirectory)}, ${formatBytes(filesBytes)}`,
311
308
  existsSync(process.cwd() + "/node_modules/.needle/build-pipeline/output") ? needleDim("Removing temporary output directory") : undefined,
312
309
  ].filter(Boolean), "log", { dimBody: false });
313
310
 
@@ -23,14 +23,13 @@ export const needleBuildInfo = (command, config, userSettings) => {
23
23
  },
24
24
  closeBundle: async () => {
25
25
  if (--level > 0) {
26
- needleLog("needle-buildinfo", "Skipped because of nested build");
27
- return;
26
+ return; // nested build (e.g. worker entry) — skip
28
27
  }
29
28
  const buildDirectory = getOutputDirectory();
30
29
  const beforeStats = collectBuildDirectoryStats(buildDirectory);
31
30
  const task = waitForBuildPipelineToFinish();
32
31
  if (task instanceof Promise) {
33
- needleLog("needle-buildinfo", "Waiting for build pipeline to finish");
32
+ if (process.env.DEBUG) needleLog("needle-buildinfo", "Waiting for build pipeline to finish");
34
33
  await task.catch(() => { });
35
34
  }
36
35
  // wait for gzip
@@ -45,14 +44,15 @@ export const needleBuildInfo = (command, config, userSettings) => {
45
44
  const key = (text) => supportsColor ? needleBlue(text) : text;
46
45
  const sizeDelta = (result.totalSizeBytes || 0) - (beforeStats.totalSizeBytes || 0);
47
46
  const fileDelta = (result.fileCount || 0) - (beforeStats.fileCount || 0);
47
+ const sizePct = beforeStats.totalSizeBytes > 0 ? Math.round(sizeDelta / beforeStats.totalSizeBytes * 100) : 0;
48
48
  const lines = [
49
49
  "Build pipeline finished!",
50
- `${key("Before pipeline")}: ${beforeStats.fileCount} files (${formatBytes(beforeStats.totalSizeBytes)})`,
51
- `${key("After pipeline")}: ${result.fileCount} files (${formatBytes(result.totalSizeBytes)})`,
52
- `${key("Delta")}: ${(sizeDelta >= 0 ? "+" : "-") + formatBytes(Math.abs(sizeDelta))}, ${(fileDelta >= 0 ? "+" : "") + fileDelta} files`,
53
- needleDim(`Begin collecting files in \"${result.buildDirectory}\"`),
54
- needleDim(`Collected ${result.fileCount} files (${result.totalSizeInMB.toFixed(2)} MB). Writing build info to \"${result.buildInfoPath}\"`),
55
- needleDim(`Build info file successfully written to \"${result.buildInfoPath}\"`),
50
+ `${key("Build info")}: ${formatBytes(beforeStats.totalSizeBytes)} ${formatBytes(result.totalSizeBytes)} (${sizePct >= 0 ? "+" : ""}${sizePct}%), ${beforeStats.fileCount} → ${result.fileCount} files (${fileDelta >= 0 ? "+" : ""}${fileDelta})`,
51
+ ...(process.env.DEBUG ? [
52
+ needleDim(`Begin collecting files in \"${result.buildDirectory}\"`),
53
+ needleDim(`Collected ${result.fileCount} files (${result.totalSizeInMB.toFixed(2)} MB). Writing build info to \"${result.buildInfoPath}\"`),
54
+ needleDim(`Build info file successfully written to \"${result.buildInfoPath}\"`),
55
+ ] : []),
56
56
  ];
57
57
  if (closedHandles > 0) lines.push(`Closed ${closedHandles} dangling network handle(s)`);
58
58
  needleLog("needle-buildinfo", lines.join("\n"), "log", { dimBody: false });
@@ -36,7 +36,6 @@ export const needleCopyFiles = (command, config, userSettings) => {
36
36
  * @param {import('../types').userSettings} config
37
37
  */
38
38
  async function run(buildstep, config) {
39
- const logLines = [needleDim(`Copy files at ${buildstep}`)];
40
39
  const copyIncludesFromEngine = config?.copyIncludesFromEngine ?? true;
41
40
  const copied = { count: 0, bytes: 0 };
42
41
 
@@ -62,11 +61,22 @@ async function run(buildstep, config) {
62
61
  outdirName = needleConfig.buildDirectory;
63
62
  }
64
63
 
64
+ // For the "end" step, the first log line carries a leading newline to visually
65
+ // separate this section from the build-pipeline output above it.
66
+ let firstLog = true;
67
+ const logLine = (msg) => {
68
+ needleLog(pluginName, msg, "log", {
69
+ dimBody: false,
70
+ leadingNewline: firstLog && buildstep === "end",
71
+ });
72
+ firstLog = false;
73
+ };
74
+
65
75
  if (copyIncludesFromEngine !== false) {
66
76
  // copy include from engine
67
77
  const engineIncludeDir = resolve(baseDir, 'node_modules', '@needle-tools', 'engine', 'src', 'include');
68
78
  if (existsSync(engineIncludeDir)) {
69
- logLines.push(`Engine include: ${rel(engineIncludeDir)} -> ${rel(resolve(baseDir, 'include'))}`);
79
+ logLine(needleDim(`Engine include: ${rel(engineIncludeDir)} ${rel(resolve(baseDir, 'include'))}`));
70
80
  const projectIncludeDir = resolve(baseDir, 'include');
71
81
  copyFilesSync(engineIncludeDir, projectIncludeDir, true, copied);
72
82
  }
@@ -94,7 +104,7 @@ async function run(buildstep, config) {
94
104
  const src = resolve(baseDir, entry);
95
105
  const dest = resolvePath(outDir, entry);
96
106
  if (existsSync(src) && dest) {
97
- logLines.push(`Configured copy: ${rel(src)} -> ${rel(dest)}`);
107
+ logLine(`Configured copy: ${rel(src)} ${rel(dest)}`);
98
108
  copyFilesSync(src, dest, override, copied);
99
109
  }
100
110
  }
@@ -107,33 +117,26 @@ async function run(buildstep, config) {
107
117
  // ensure that the target directory exists and is cleared if it already exists
108
118
  // otherwise we might run into issues where the build pipeline is running for already compressed files
109
119
  if (override && existsSync(targetDir)) {
110
- logLines.push(needleDim(`Clearing target directory "${rel(targetDir)}"`));
120
+ logLine(needleDim(`Clearing target directory "${rel(targetDir)}"`));
111
121
  rmSync(targetDir, { recursive: true, force: true });
112
122
  }
113
- logLines.push(needleDim(`Assets: ${rel(assetsDir)} -> ${rel(targetDir)}`));
123
+ logLine(`${key("Copying assets")}: ${rel(assetsDir)} ${rel(targetDir)}`);
114
124
  copyFilesSync(assetsDir, targetDir, override, copied);
115
125
  }
116
- else logLines.push(`No assets directory found. Skipping copy of ${assetsDirName} resolved to ${rel(assetsDir)}`);
126
+ else logLine(`No assets directory found. Skipping copy of ${assetsDirName} resolved to ${rel(assetsDir)}`);
117
127
 
118
128
  // copy include dir
119
129
  const includeDir = resolve(baseDir, 'include');
120
130
  if (existsSync(includeDir)) {
121
131
  const targetDir = resolve(outDir, 'include');
122
- logLines.push(needleDim(`Include: ${rel(includeDir)} -> ${rel(targetDir)}`));
132
+ logLine(needleDim(`Include: ${rel(includeDir)} ${rel(targetDir)}`));
123
133
  copyFilesSync(includeDir, targetDir, override, copied);
124
134
  }
125
135
 
126
- logLines.push(`${key("Copied files")}: ${copied.count}`);
127
- logLines.push(`${key("Copied size")}: ${formatBytes(copied.bytes || 0)}`);
136
+ logLine(`${key("Copied files")}: ${copied.count}, ${formatBytes(copied.bytes || 0)}`);
128
137
  if (buildstep === "end") {
129
- logLines.push("");
130
- logLines.push("✨ Happy creating! 🌵");
138
+ logLine("✨ Happy creating! 🌵");
131
139
  }
132
-
133
- needleLog(pluginName, logLines.join("\n"), "log", {
134
- leadingNewline: buildstep === "end",
135
- dimBody: false,
136
- });
137
140
  }
138
141
 
139
142
  function formatBytes(bytes) {
@@ -61,13 +61,13 @@ function mergeCustomElementData(sourceData, targetData) {
61
61
  * - Copies/merges `custom-elements.json` to project root
62
62
  * - Adds `./custom-elements.json` to `.code-workspace settings.html.customData`
63
63
  * - Adds `./custom-elements.json` to `.vscode/settings.json html.customData`
64
- * @param {string} command
65
- * @param {import('../types').needleMeta | null} config
64
+ * @param {"build" | "serve"} _command
65
+ * @param {import('../types').needleMeta | null} _config
66
66
  * @param {import('../types').userSettings} userSettings
67
67
  */
68
- export const needleCustomElementData = (command, config, userSettings = {}) => {
68
+ export const needleCustomElementData = (_command, _config, userSettings = {}) => {
69
69
  // Allow disabling the workspace updater
70
- if (config?.noCustomElementData === true || userSettings?.noCustomElementData === true) return;
70
+ if (userSettings?.noCustomElementData === true) return null;
71
71
 
72
72
  return {
73
73
  name: 'needle:custom-element-data',
@@ -1,3 +1,5 @@
1
+ import path from 'path';
2
+ import { existsSync } from 'fs';
1
3
  import { tryGetNeedleEngineVersion, tryGetPackageVersion } from '../common/version.js';
2
4
  import { needleLog } from './logging.js';
3
5
 
@@ -7,6 +9,20 @@ import { needleLog } from './logging.js';
7
9
  export const preloadScriptPaths = [];
8
10
 
9
11
 
12
+ /**
13
+ * Returns true when \`@needle-tools/engine\` is installed as a local package
14
+ * (i.e. it has its own nested `node_modules`). Vite's optimiser must skip such
15
+ * packages, otherwise it tries to pre-bundle source that was never meant to be
16
+ * pre-bundled and fails at dev-server start.
17
+ *
18
+ * @param {string} [root] – project root; defaults to `process.cwd()`.
19
+ * @returns {boolean}
20
+ */
21
+ export function isLocalNeedleEngineInstalled(root = process.cwd()) {
22
+ const lockPath = path.resolve(root, 'node_modules', '@needle-tools/engine', 'node_modules', '.package-lock.json');
23
+ return existsSync(lockPath);
24
+ }
25
+
10
26
  /**
11
27
  * @param {import('../types').userSettings} userSettings
12
28
  * @returns {import('vite').Plugin[]}
@@ -40,10 +56,9 @@ const excludeDependencies = [
40
56
  * @param {import('vite').UserConfig} config
41
57
  */
42
58
  function handleOptimizeDeps(config) {
43
- const logLines = [];
44
59
  excludeDependencies.forEach(dep => {
45
60
  if (config.optimizeDeps?.include?.includes(dep)) {
46
- logLines.push(`${dep} is included in the optimizeDeps.include array. This may cause issues with the worker import.`);
61
+ needleLog("needle-dependencies", `${dep} is included in the optimizeDeps.include array. This may cause issues with the worker import.`, "warn", { dimBody: false });
47
62
  }
48
63
  else {
49
64
  if (!config.optimizeDeps) {
@@ -56,7 +71,7 @@ function handleOptimizeDeps(config) {
56
71
  // This needs to be excluded from optimization because otherwise the worker import fails
57
72
  // three-mesh-bvh/src/workers/generateMeshBVH.worker.js?worker
58
73
  // same for gltf-progressive
59
- logLines.push(`Adding ${dep} to the optimizeDeps.exclude array to support workers.`);
74
+ needleLog("needle-dependencies", `Adding ${dep} to the optimizeDeps.exclude array to support workers.`);
60
75
  config.optimizeDeps.exclude.push(dep);
61
76
 
62
77
  if (!config.server) config.server = {};
@@ -67,14 +82,22 @@ function handleOptimizeDeps(config) {
67
82
  }
68
83
  }
69
84
  });
70
- if (logLines.length) needleLog("needle-dependencies", logLines.join("\n"));
85
+ // is needle engine a local package? exclude it from vite's optimizeDeps
86
+ if (isLocalNeedleEngineInstalled()) {
87
+ config.optimizeDeps ??= {};
88
+ config.optimizeDeps.exclude ??= [];
89
+ if (!config.optimizeDeps.include?.includes('@needle-tools/engine') &&
90
+ !config.optimizeDeps.exclude.includes('@needle-tools/engine')) {
91
+ config.optimizeDeps.exclude.push('@needle-tools/engine');
92
+ needleLog("needle-dependencies", 'Detected local @needle-tools/engine package → will exclude it from optimization');
93
+ }
94
+ }
71
95
  }
72
96
 
73
97
  /**
74
98
  * @param {import('vite').UserConfig} config
75
99
  */
76
100
  function handleManualChunks(config) {
77
- const logLines = [];
78
101
  if (!config.build) {
79
102
  config.build = {};
80
103
  }
@@ -89,7 +112,7 @@ function handleManualChunks(config) {
89
112
 
90
113
  if (Array.isArray(rollupOutput)) {
91
114
  // append the manualChunks function to the array
92
- logLines.push("registering manualChunks");
115
+ if (process.env.DEBUG) needleLog("needle-dependencies", "registering manualChunks");
93
116
  rollupOutput.push({
94
117
  manualChunks: needleManualChunks
95
118
  })
@@ -100,38 +123,37 @@ function handleManualChunks(config) {
100
123
  if ("manualChunks" in rollupOutput) {
101
124
  allowManualChunks = false;
102
125
  // if the user has already defined manualChunks (even when set to undefined), we don't want to overwrite it
103
- logLines.push("manualChunks already found in vite config - will not overwrite it");
126
+ needleLog("needle-dependencies", "manualChunks already found in vite config - will not overwrite it");
104
127
  }
105
128
  else if (rollupOutput.preserveModules === true) {
106
129
  allowManualChunks = false;
107
- logLines.push("manualChunks can not be registered because preserveModules is true");
130
+ needleLog("needle-dependencies", "manualChunks can not be registered because preserveModules is true");
108
131
  }
109
132
  if (rollupOutput.inlineDynamicImports === true) {
110
133
  allowManualChunks = false;
111
- logLines.push("manualChunks can not be registered because inlineDynamicImports is true");
134
+ needleLog("needle-dependencies", "manualChunks can not be registered because inlineDynamicImports is true");
112
135
  }
113
136
 
114
137
  if (allowManualChunks) {
115
- logLines.push("registering manualChunks");
138
+ if (process.env.DEBUG) needleLog("needle-dependencies", "registering manualChunks");
116
139
  rollupOutput.manualChunks = needleManualChunks;
117
140
  }
118
141
 
119
142
  if (rollupOutput.chunkFileNames) {
120
- logLines.push("chunkFileNames already defined");
143
+ needleLog("needle-dependencies", "chunkFileNames already defined");
121
144
  }
122
145
  else {
123
146
  rollupOutput.chunkFileNames = handleChunkFileNames;
124
147
  }
125
148
 
126
149
  if (rollupOutput.assetFileNames) {
127
- logLines.push("assetFileNames already defined");
150
+ needleLog("needle-dependencies", "assetFileNames already defined");
128
151
  }
129
152
  else {
130
153
  rollupOutput.assetFileNames = assetFileNames;
131
154
  }
132
155
  }
133
156
 
134
- if (logLines.length) needleLog("needle-dependencies", logLines.join("\n"));
135
157
 
136
158
  // TODO: this was a test if it allows us to remove the sync import of postprocessing due to n8ao's import
137
159
  // config.build.rollupOptions.external = (source, importer, isResolved) => {
@@ -168,13 +190,18 @@ function handleManualChunks(config) {
168
190
  needleLog("needle-dependencies", "Error reading version " + e, "warn");
169
191
  }
170
192
  }
171
- else if (chunk.name === 'three') {
172
- const version = tryGetPackageVersion("three");
173
- if (version) {
174
- const name = `assets/three@${version}.js`;
193
+ else if (chunk.name === 'three' || chunk.name === 'three-examples') {
194
+ // 'three' may be aliased to @needle-tools/three — check both package locations
195
+ const version = tryGetPackageVersion("three") ?? tryGetPackageVersion("@needle-tools/three");
196
+ const name = version
197
+ ? `assets/${chunk.name}@${version}.js`
198
+ : `assets/${chunk.name}.js`;
199
+ // Only eagerly preload three (the core math/scene-graph lib).
200
+ // three-examples (OrbitControls, loaders, etc.) is loaded on-demand — don't preload it.
201
+ if (chunk.name === 'three') {
175
202
  preloadScriptPaths.push(`./${name}`);
176
- return name;
177
203
  }
204
+ return name;
178
205
  }
179
206
  // else if(chunk.name === 'index') {
180
207
  // console.log(chunk);