@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
@@ -12,14 +12,14 @@ function log(...msg) {
12
12
  }
13
13
 
14
14
  /**
15
- * @param {string} command
16
- * @param {unknown} config
15
+ * @param {"build" | "serve"} command
16
+ * @param {unknown} _config
17
17
  * @param {import('../types').userSettings} userSettings
18
18
  */
19
- export const needleDependencyWatcher = (command, config, userSettings) => {
20
- if (command === "build") return;
19
+ export const needleDependencyWatcher = (command, _config, userSettings) => {
20
+ if (command === "build") return null;
21
21
 
22
- if (userSettings?.noDependencyWatcher === true) return;
22
+ if (userSettings?.noDependencyWatcher === true) return null;
23
23
 
24
24
  const dir = process.cwd();
25
25
  const packageJsonPath = path.join(dir, "package.json");
@@ -101,6 +101,7 @@ function watchPackageJson(server, projectDir, packageJsonPath, cachePath) {
101
101
  }, 1000);
102
102
 
103
103
  setInterval(() => {
104
+ if (!packageJson || lastEditTime === undefined) return;
104
105
  packageJsonStat = statSync(packageJsonPath);
105
106
  let modified = false;
106
107
  if (packageJsonStat.mtime > lastEditTime) {
@@ -120,14 +121,14 @@ function watchPackageJson(server, projectDir, packageJsonPath, cachePath) {
120
121
  let newPackageJson = /** @type {PackageJson} */ (JSON.parse(readFileSync(packageJsonPath, "utf8")));
121
122
  if (newPackageJson.dependencies) {
122
123
  for (const key in newPackageJson.dependencies) {
123
- if (packageJson.dependencies[key] !== newPackageJson.dependencies[key] && newPackageJson.dependencies[key] !== undefined) {
124
+ if (packageJson.dependencies?.[key] !== newPackageJson.dependencies[key] && newPackageJson.dependencies[key] !== undefined) {
124
125
  log("Detected new dependency: " + key)
125
126
  requireReload = true;
126
127
  requireInstall = true;
127
128
  }
128
129
  }
129
130
  }
130
- if (packageJson.devDependencies) {
131
+ if (packageJson.devDependencies && newPackageJson.devDependencies) {
131
132
  for (const key in packageJson.devDependencies) {
132
133
  if (packageJson.devDependencies[key] !== newPackageJson.devDependencies[key] && newPackageJson.devDependencies[key] !== undefined) {
133
134
  log("Detected new devDependency: " + key)
@@ -153,6 +154,7 @@ function watchPackageJson(server, projectDir, packageJsonPath, cachePath) {
153
154
 
154
155
  /** @param {string} projectDir @param {PackageJson | undefined} packageJson @returns {boolean} */
155
156
  function testIfInstallIsRequired(projectDir, packageJson) {
157
+ if (!packageJson) return false;
156
158
  if (packageJson.dependencies) {
157
159
  for (const key in packageJson.dependencies) {
158
160
  // make sure the dependency is installed
@@ -264,7 +266,7 @@ async function restart(server, projectDir, cachePath) {
264
266
  needleLog("needle-dependency-watcher", "-----------------------------------------------");
265
267
  }
266
268
  catch (err) {
267
- log("Error restarting server", err);
269
+ log("Error restarting server", String(err));
268
270
  isRunningRestart = false;
269
271
  }
270
272
 
@@ -5,13 +5,13 @@ import fs from 'fs';
5
5
  /** @typedef {{ id: string, imports: GraphNode[], importedBy: GraphNode[] }} GraphNode */
6
6
 
7
7
  /**
8
- * @param {string} command
9
- * @param {unknown} config
8
+ * @param {"build" | "serve"} _command
9
+ * @param {unknown} _config
10
10
  * @param {import('../types').userSettings} userSettings
11
11
  */
12
- export const needleImportsLogger = (command, config, userSettings) => {
12
+ export const needleImportsLogger = (_command, _config, userSettings) => {
13
13
 
14
- if (!userSettings.debugImportChains) return;
14
+ if (!userSettings.debugImportChains) return null;
15
15
 
16
16
  /** @type {{allNodes: Map<string, GraphNode>, graph: Record<string, unknown>}} */
17
17
  const graph = {
@@ -47,7 +47,7 @@ export const needleImportsLogger = (command, config, userSettings) => {
47
47
  });
48
48
  }
49
49
 
50
- if (!graph.allNodes.has(importer)) {
50
+ if (importer && !graph.allNodes.has(importer)) {
51
51
  graph.allNodes.set(importer, {
52
52
  id: importer,
53
53
  imports: [],
@@ -56,16 +56,18 @@ export const needleImportsLogger = (command, config, userSettings) => {
56
56
  }
57
57
 
58
58
  const node = graph.allNodes.get(id);
59
- const importerNode = graph.allNodes.get(importer);
60
- if (!node.importedBy.includes(importerNode))
61
- node.importedBy.push(importerNode);
62
- if (!importerNode.imports.includes(node))
63
- importerNode.imports.push(node);
59
+ const importerNode = importer ? graph.allNodes.get(importer) : undefined;
60
+ if (node && importerNode) {
61
+ if (!node.importedBy.includes(importerNode))
62
+ node.importedBy.push(importerNode);
63
+ if (!importerNode.imports.includes(node))
64
+ importerNode.imports.push(node);
65
+ }
64
66
 
65
67
  return;
66
68
  },
67
- /** @param {Error | undefined} [error] */
68
- buildEnd(error) {
69
+ /** @param {Error | undefined} [_error] */
70
+ buildEnd(_error) {
69
71
  try {
70
72
  // create log file and append lines to it
71
73
  const logFile = path.resolve(process.cwd(), "imports.log");
@@ -81,7 +81,7 @@ export function getLocalFilesAutoPolicy(projectDir) {
81
81
  * @returns {boolean}
82
82
  */
83
83
  export function makeFilesLocalIsEnabled(userSettings) {
84
- if (typeof userSettings?.makeFilesLocal === "object") return userSettings?.makeFilesLocal?.enabled !== false;
84
+ if (typeof userSettings?.makeFilesLocal === "object") return userSettings?.makeFilesLocal?.enabled === true;
85
85
  if (userSettings?.makeFilesLocal === "auto") return true;
86
86
  return userSettings?.makeFilesLocal === true;
87
87
  }
@@ -93,7 +93,7 @@ export function makeFilesLocalIsEnabled(userSettings) {
93
93
  export function resolveOptions(userSettings) {
94
94
  if (typeof userSettings?.makeFilesLocal === "object") {
95
95
  const raw = userSettings.makeFilesLocal;
96
- const opts = { ...raw };
96
+ const opts = /** @type {LocalizationOptions} */ ({ ...raw });
97
97
  if (!opts.exclude?.length && opts.excludeUrls?.length) {
98
98
  opts.exclude = opts.excludeUrls;
99
99
  }
@@ -288,7 +288,7 @@ export function analyzeProjectGlbs(projectDir) {
288
288
  const extensions = /** @type {Set<string>} */ (new Set());
289
289
  const componentTypes = /** @type {Set<string>} */ (new Set());
290
290
  const componentCounts = /** @type {Map<string, number>} */ (new Map());
291
- const needleExtensionBlobs = /** @type {unknown[]} */ ([]);
291
+ const needleExtensionBlobs = /** @type {string[]} */ ([]);
292
292
 
293
293
  let hasWebXRComponent = false;
294
294
  let hasVideoPlayerComponent = false;
@@ -303,9 +303,9 @@ export function analyzeProjectGlbs(projectDir) {
303
303
 
304
304
  for (const file of sceneFiles) {
305
305
  try {
306
- const json = file.type === "glb"
306
+ const json = /** @type {Record<string,any>|null} */ (file.type === "glb"
307
307
  ? readGlbJsonChunk(file.path)
308
- : readGltfJsonFile(file.path);
308
+ : readGltfJsonFile(file.path));
309
309
  if (!json || typeof json !== "object") continue;
310
310
 
311
311
  const used = Array.isArray(json.extensionsUsed) ? json.extensionsUsed : [];
@@ -408,7 +408,7 @@ export function analyzeProjectGlbs(projectDir) {
408
408
  }
409
409
 
410
410
  /**
411
- * @param {Record<string, unknown> | null | undefined} primitive
411
+ * @param {Record<string, any> | null | undefined} primitive
412
412
  * @returns {number}
413
413
  */
414
414
  function getPrimitivePositionAccessorIndex(primitive) {
@@ -472,9 +472,7 @@ function collectNeedleComponentNames(json) {
472
472
  * @param {Set<string>} names
473
473
  */
474
474
  function collectComponentNamesFromNeedleExtension(value, names) {
475
- const builtinComponents = Array.isArray(value?.builtin_components)
476
- ? value.builtin_components
477
- : [];
475
+ const builtinComponents = value?.builtin_components ?? [];
478
476
 
479
477
  for (const entry of builtinComponents) {
480
478
  const candidateName = getBuiltinComponentName(entry);
@@ -496,10 +494,10 @@ function getBuiltinComponentName(node) {
496
494
  * @param {SceneAnalysisReport} report
497
495
  * @param {AutoPolicy | null} autoPolicy
498
496
  * @param {string} projectDir
499
- * @param {string} mode
497
+ * @param {string} _mode
500
498
  * @returns {string}
501
499
  */
502
- function formatSceneAnalysisReport(report, autoPolicy, projectDir, mode) {
500
+ function formatSceneAnalysisReport(report, autoPolicy, projectDir, _mode) {
503
501
  const supportsColor = needleSupportsColor();
504
502
  const projectName = relative(process.cwd(), projectDir) || ".";
505
503
  const componentList = report.componentCounts?.size > 0
@@ -765,7 +763,7 @@ function collectSourceFiles(dir, depth = 0) {
765
763
  /**
766
764
  * @param {string} url
767
765
  * @param {UrlHandler} handler
768
- * @param {{ options: LocalizationOptions, autoPolicy: AutoPolicy | null }} context
766
+ * @param {LocalizationContext} context
769
767
  * @returns {boolean}
770
768
  */
771
769
  export function shouldHandleUrlInAutoMode(url, handler, context) {
@@ -208,7 +208,7 @@ function recordLocalizedAsset(stats, url, sizeBytes, mimeType) {
208
208
  }
209
209
 
210
210
  /**
211
- * @param {string} command
211
+ * @param {"build" | "serve"} command
212
212
  * @param {unknown} _config
213
213
  * @param {import('../types').userSettings} userSettings
214
214
  * @returns {import('vite').Plugin | null}
@@ -259,7 +259,7 @@ export const needleMakeFilesLocal = (command, _config, userSettings) => {
259
259
  },
260
260
  async buildStart() {
261
261
  await prefetchConfiguredAssets({
262
- pluginContext: this,
262
+ pluginContext: /** @type {import('rollup').PluginContext} */ (this),
263
263
  cache,
264
264
  command,
265
265
  viteConfig,
@@ -282,7 +282,7 @@ export const needleMakeFilesLocal = (command, _config, userSettings) => {
282
282
  const isCssTransform = /\.css($|\?)/i.test(_id || "");
283
283
  const currentDir = isCssTransform ? assetsDir : "";
284
284
  src = await makeLocal(src, "ext/", currentDir, {
285
- pluginContext: this,
285
+ pluginContext: /** @type {import('rollup').PluginContext} */ (this),
286
286
  cache,
287
287
  command,
288
288
  viteConfig,
@@ -557,7 +557,7 @@ async function expandTemplateUrls(src, stripped, basePath, currentDir, context)
557
557
  }
558
558
 
559
559
  const replaceRegex = new RegExp('`' + escapedPrefix + '([^`]*\\$\\{[^`]*)`', 'g');
560
- src = src.replace(replaceRegex, (/** @type {string} */ fullMatch, /** @type {string} */ rest) => {
560
+ src = src.replace(replaceRegex, (/** @type {string} */ _fullMatch, /** @type {string} */ rest) => {
561
561
  const newPrefix = getRelativeToBasePath(localBasePath, currentDir);
562
562
  return '`' + newPrefix + rest + '`';
563
563
  });
@@ -770,7 +770,7 @@ function mapFeatureToOutputDir(feature) {
770
770
  */
771
771
  async function handleCssUrl(url, basePath, currentDir, context, handlers) {
772
772
  const cached = context.cache.getFromCache(url);
773
- if (cached) return cached;
773
+ if (typeof cached === 'string') return cached;
774
774
 
775
775
  let cssContent = await downloadText(url);
776
776
  cssContent = await makeLocal(cssContent, basePath, basePath, context, handlers);
@@ -809,7 +809,7 @@ async function handleCssUrl(url, basePath, currentDir, context, handlers) {
809
809
  */
810
810
  async function handleBinaryUrl(url, basePath, currentDir, context) {
811
811
  const cached = context.cache.getFromCache(url);
812
- if (cached) return cached;
812
+ if (typeof cached === 'string') return cached;
813
813
 
814
814
  const data = await downloadBinary(url);
815
815
  recordLocalizedAsset(context.localizationStats, url, data.length, inferMimeType(url));
@@ -844,7 +844,7 @@ async function handleBinaryUrl(url, basePath, currentDir, context) {
844
844
  */
845
845
  async function handleDecoderDir(baseUrl, basePath, currentDir, handler, context) {
846
846
  const cached = context.cache.getFromCache(baseUrl);
847
- if (cached) return cached;
847
+ if (typeof cached === 'string') return cached;
848
848
 
849
849
  const normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
850
850
  const localDir = ensureTrailingSlash(basePath);
@@ -888,7 +888,7 @@ async function handleDecoderDir(baseUrl, basePath, currentDir, handler, context)
888
888
  */
889
889
  export async function handleWebXRProfiles(baseUrl, basePath, currentDir, context) {
890
890
  const cached = context.cache.getFromCache(baseUrl);
891
- if (cached) return cached;
891
+ if (typeof cached === 'string') return cached;
892
892
 
893
893
  const normalizedBaseUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
894
894
  const localDir = basePath + "webxr-profiles/";
@@ -19,8 +19,39 @@ export interface LocalizationStats {
19
19
  mimeCounts: Map<string, number>;
20
20
  }
21
21
 
22
+ /**
23
+ * Configuration for the `makeFilesLocal` build plugin.
24
+ * Controls which external CDN assets are downloaded at build time and bundled locally,
25
+ * producing fully self-contained deployments that work without internet access.
26
+ * Useful for playable ads, app stores requiring single-origin bundles, offline PWAs,
27
+ * and restricted hosting environments.
28
+ */
22
29
  export interface LocalizationOptions {
30
+ /**
31
+ * Which feature categories to include when downloading assets.
32
+ * - `"auto"` — scan project scene files and source code to detect which features are actually used, then only download those.
33
+ * - `string[]` — explicit list of feature names. When set, **only** these features are processed.
34
+ * - When omitted, **all** features are included.
35
+ *
36
+ * Available features:
37
+ * `"draco"`, `"ktx2"`, `"materialx"`, `"xr"`, `"skybox"`, `"fonts"`,
38
+ * `"needle-fonts"`, `"needle-models"`, `"needle-avatars"`, `"needle-branding"`,
39
+ * `"polyhaven"`, `"cdn-scripts"`, `"github-content"`, `"threejs-models"`, `"needle-uploads"`
40
+ *
41
+ * @example
42
+ * features: "auto"
43
+ * @example
44
+ * features: ["draco", "ktx2", "fonts"]
45
+ */
23
46
  features?: string | string[];
47
+ /**
48
+ * Feature categories to exclude. Applied **after** `features` (including after auto-detection).
49
+ * Use this to opt out of specific categories you don't need without having to list every other one.
50
+ *
51
+ * @example
52
+ * // Auto-detect everything except XR controller profiles
53
+ * { features: "auto", excludeFeatures: ["xr"] }
54
+ */
24
55
  excludeFeatures?: string[];
25
56
  /** URL substrings or RegExps to skip. */
26
57
  exclude?: (string | RegExp)[];
@@ -34,9 +65,25 @@ export interface LocalizationOptions {
34
65
  skybox?: string | string[];
35
66
  /** WebXR controller profile mode: "minimal" | "quest" | "pico" | "all" */
36
67
  webxr?: string;
68
+ /**
69
+ * Template-based URL expansion rules. Used for CDN URLs that contain template-literal
70
+ * variables (e.g. `${version}`, `${platform}`). The plugin expands every combination
71
+ * of the provided variable values, downloads each concrete URL, and rewrites the
72
+ * template literal to point at the local copy.
73
+ *
74
+ * @example
75
+ * templateExpansions: [{
76
+ * cdnPrefix: "https://cdn.example.com/decoders/",
77
+ * variables: { version: ["v1", "v2"], arch: ["wasm", "js"] },
78
+ * localPrefix: "decoders" // optional — derived from cdnPrefix when omitted
79
+ * }]
80
+ */
37
81
  templateExpansions?: Array<{
82
+ /** The CDN base URL that the template literals start with. */
38
83
  cdnPrefix: string;
84
+ /** Map of variable names to all possible values. Every combination is expanded and downloaded. */
39
85
  variables: Record<string, string[]>;
86
+ /** Local output subdirectory. Derived from `cdnPrefix` hostname when omitted. */
40
87
  localPrefix?: string;
41
88
  }>;
42
89
  /** Used when makeFilesLocal is an object — set to false to disable. */
@@ -51,18 +98,9 @@ export interface AutoPolicy {
51
98
  selectedWebXRProfiles: string[];
52
99
  }
53
100
 
54
- export interface VitePluginContext {
55
- emitFile(asset: {
56
- type: "asset" | "chunk";
57
- fileName?: string;
58
- name?: string;
59
- source?: string | Uint8Array;
60
- }): string;
61
- getFileName(referenceId: string): string;
62
- }
63
-
64
101
  export interface LocalizationContext {
65
- pluginContext: VitePluginContext | null;
102
+ /** The Rollup plugin context, available during build hooks (null in dev/serve). */
103
+ pluginContext: import('rollup').PluginContext | null;
66
104
  cache: {
67
105
  addToCache(key: string, value: Buffer | string): void;
68
106
  getFromCache(key: string): Buffer | string | null;
@@ -118,7 +118,7 @@ export function ensureTrailingSlash(path) {
118
118
  export function fixRelativeNewURL(src) {
119
119
  src = src.replace(
120
120
  /(?<==\s*)(["'])((?:(?:\.{1,2}\/)|\/)?ext\/[^"']*\/)\1/g,
121
- (/** @type {string} */ match, /** @type {string} */ quote, /** @type {string} */ path) => {
121
+ (/** @type {string} */ _match, /** @type {string} */ quote, /** @type {string} */ path) => {
122
122
  const runtimePath = path.startsWith("/ext/") ? path.substring(1) : path;
123
123
  return `new URL(${quote}${runtimePath}${quote}, self.location?.href || ${quote}${quote}).href`;
124
124
  }
@@ -126,7 +126,7 @@ export function fixRelativeNewURL(src) {
126
126
 
127
127
  src = src.replace(
128
128
  /new\s+URL\s*\(\s*(["'`])((?:(?:\.{1,2}\/)|\/)?ext\/[^"'`]+)\1\s*\)/g,
129
- (/** @type {string} */ match, /** @type {string} */ quote, /** @type {string} */ path) => {
129
+ (/** @type {string} */ _match, /** @type {string} */ quote, /** @type {string} */ path) => {
130
130
  const runtimePath = path.startsWith("/ext/") ? path.substring(1) : path;
131
131
  return `new URL(${quote}${runtimePath}${quote}, self.location?.href)`;
132
132
  }
@@ -175,7 +175,7 @@ export function getValidFilename(path, content) {
175
175
  }
176
176
 
177
177
  /**
178
- * @param {string} str
178
+ * @param {string | Buffer} str
179
179
  * @returns {string}
180
180
  */
181
181
  function createContentMd5(str) {
@@ -197,7 +197,8 @@ export function downloadText(url) {
197
197
  const req = (url.startsWith("http://") ? http.get(url, (response) => {
198
198
  if (response.statusCode && response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
199
199
  clearTimeout(timer);
200
- return downloadText(response.headers.location).then(res).catch(rej);
200
+ downloadText(response.headers.location).then(res).catch(rej);
201
+ return;
201
202
  }
202
203
 
203
204
  if (response.statusCode !== 200) {
@@ -224,7 +225,8 @@ export function downloadText(url) {
224
225
  }) : https.get(url, (response) => {
225
226
  if (response.statusCode && response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
226
227
  clearTimeout(timer);
227
- return downloadText(response.headers.location).then(res).catch(rej);
228
+ downloadText(response.headers.location).then(res).catch(rej);
229
+ return;
228
230
  }
229
231
 
230
232
  if (response.statusCode !== 200) {
@@ -270,7 +272,8 @@ export function downloadBinary(url) {
270
272
  const req = (url.startsWith("http://") ? http.get(url, (response) => {
271
273
  if (response.statusCode && response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
272
274
  clearTimeout(timer);
273
- return downloadBinary(response.headers.location).then(res).catch(rej);
275
+ downloadBinary(response.headers.location).then(res).catch(rej);
276
+ return;
274
277
  }
275
278
 
276
279
  if (response.statusCode !== 200) {
@@ -283,7 +286,7 @@ export function downloadBinary(url) {
283
286
  updateMakeLocalProgress(url);
284
287
 
285
288
  const chunks = /** @type {Buffer[]} */ ([]);
286
- response.on('data', (/** @type {Buffer|string} */ chunk) => {
289
+ response.on('data', (/** @type {Buffer} */ chunk) => {
287
290
  chunks.push(chunk);
288
291
  });
289
292
  response.on('end', () => {
@@ -297,7 +300,8 @@ export function downloadBinary(url) {
297
300
  }) : https.get(url, (response) => {
298
301
  if (response.statusCode && response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
299
302
  clearTimeout(timer);
300
- return downloadBinary(response.headers.location).then(res).catch(rej);
303
+ downloadBinary(response.headers.location).then(res).catch(rej);
304
+ return;
301
305
  }
302
306
 
303
307
  if (response.statusCode !== 200) {
@@ -310,7 +314,7 @@ export function downloadBinary(url) {
310
314
  updateMakeLocalProgress(url);
311
315
 
312
316
  const chunks = /** @type {Buffer[]} */ ([]);
313
- response.on('data', (/** @type {Buffer|string} */ chunk) => {
317
+ response.on('data', (/** @type {Buffer} */ chunk) => {
314
318
  chunks.push(chunk);
315
319
  });
316
320
  response.on('end', () => {
@@ -337,7 +341,7 @@ export function downloadBinary(url) {
337
341
  */
338
342
  export function recordFailedDownload(context, url, err) {
339
343
  if (!url || !context?.failedDownloads) return;
340
- const message = err?.message ? String(err.message) : "";
344
+ const message = err instanceof Error ? err.message : "";
341
345
  if (!context.failedDownloads.has(url)) {
342
346
  context.failedDownloads.set(url, message);
343
347
  }
@@ -23,10 +23,10 @@ function sendLogToServer(level, ...message) {
23
23
  }
24
24
  // @ts-ignore
25
25
  import.meta.hot.send("needle:client-log", { level, message: msg });
26
- } catch (/** @type {{ message?: string }} */ e) {
26
+ } catch (/** @type {any} */ e) {
27
27
  // silently fail but send a message
28
28
  try {
29
- import.meta.hot.send("needle:client-log", { level: "error", message: `Error during logging: ${e.message}` });
29
+ import.meta.hot?.send("needle:client-log", { level: "error", message: `Error during logging: ${e?.message ?? String(e)}` });
30
30
  }
31
31
  catch (/** @type {unknown} */ e2) {
32
32
  // fallback failed as well
@@ -149,9 +149,9 @@ User Activation: ${"userActivation" in navigator ? JSON.stringify(navigator.user
149
149
  });
150
150
  }
151
151
  }
152
- catch (/** @type {{ message?: string }} */ e) {
152
+ catch (/** @type {any} */ e) {
153
153
  // silently fail
154
- sendLogToServer("error", `Error during initial log: ${e.message}`);
154
+ sendLogToServer("error", `Error during initial log: ${e?.message ?? String(e)}`);
155
155
  }
156
156
 
157
157
  window.addEventListener('error', (event) => {
@@ -11,11 +11,11 @@ const __dirname = path.dirname(__filename);
11
11
  /**
12
12
  * write logs to local file
13
13
  * @param {string} command
14
- * @param {unknown} config
14
+ * @param {unknown} _config
15
15
  * @param {import('../types/userconfig.js').userSettings} userSettings
16
16
  * @returns {import('vite').Plugin | null}
17
17
  */
18
- export const needleLogger = (command, config, userSettings) => {
18
+ export const needleLogger = (command, _config, userSettings) => {
19
19
 
20
20
  if (userSettings?.disableLogging === true) {
21
21
  return null;
@@ -35,7 +35,7 @@ export const needleLogger = (command, config, userSettings) => {
35
35
  },
36
36
  transformIndexHtml: {
37
37
  order: 'pre',
38
- handler(html, ctx) {
38
+ handler(_html, _ctx) {
39
39
  // inject client logger script during development
40
40
  if (command === 'serve') {
41
41
  const file = path.join(__dirname, 'logger.client.js');
@@ -53,6 +53,7 @@ export const needleLogger = (command, config, userSettings) => {
53
53
  ];
54
54
  }
55
55
  }
56
+ return [];
56
57
  },
57
58
  }
58
59
  }
@@ -84,18 +85,17 @@ function logRequests(server, log_http_requests = false) {
84
85
  });
85
86
  });
86
87
  // Client log messages via websocket
87
- server.ws.on('needle:client-log', async (/** @type {{level: string, message: unknown}} */ data, /** @type {{socket: import('net').Socket}} */ client) => {
88
+ server.ws.on('needle:client-log', async (/** @type {{level: string, message: unknown}} */ data, /** @type {import('vite').WebSocketClient} */ client) => {
88
89
  if (!data || !data.level || !data.message) {
89
90
  console.warn("Received empty log data, ignoring");
90
91
  return;
91
92
  }
92
- const socket = client.socket;
93
- const info = connectedClients.get(socket);
93
+ const info = connectedClients.get(client.socket);
94
94
  captureLogMessage("client", data.level, data.message, info ? info.id : null);
95
95
  });
96
96
  }
97
97
  // Log HTTP requests
98
- server.middlewares.use((req, res, next) => {
98
+ server.middlewares.use((req, _res, next) => {
99
99
  if (log_http_requests) {
100
100
  captureLogMessage("client-http", "info", [req.method, req.url], null);
101
101
  }
@@ -6,6 +6,22 @@ const colors = createColors(isColorSupported);
6
6
  /** @type {null | (() => void)} */
7
7
  let transientLogLineCleaner = null;
8
8
 
9
+ /**
10
+ * Tracks the last plugin name that called needleLog.
11
+ * Used to suppress repeated header lines for consecutive logs from the same plugin.
12
+ * @type {string | null}
13
+ */
14
+ let lastLoggedPlugin = null;
15
+
16
+ /**
17
+ * Resets the sticky-header state so the next needleLog call always emits its
18
+ * [plugin-name] header. Call this at the start of a new build or any logical
19
+ * output section where you want a guaranteed fresh header.
20
+ */
21
+ export function resetLastLoggedPlugin() {
22
+ lastLoggedPlugin = null;
23
+ }
24
+
9
25
  function getConsoleMethod(level) {
10
26
  if (level === 'error') return console.error;
11
27
  if (level === 'warn') return console.warn;
@@ -67,13 +83,20 @@ export function needleLog(pluginName, message, level = 'log', options = undefine
67
83
  const leadingNewline = options?.leadingNewline === true;
68
84
  const showHeader = options?.showHeader !== false;
69
85
 
86
+ // Sticky header: only re-emit [plugin-name] when the plugin changes.
87
+ // Always re-emit for warn/error (for clarity), header-only calls (no body),
88
+ // or section breaks (leadingNewline).
89
+ const pluginChanged = pluginName !== lastLoggedPlugin;
90
+ const emitHeader = showHeader && (pluginChanged || level !== 'log' || bodyText.length === 0 || leadingNewline);
91
+ lastLoggedPlugin = pluginName;
92
+
70
93
  if (isColorSupported) {
71
94
  const header = `\x1b[0m${headerText}`;
72
95
  const leveledBody = colorBodyByLevel(level, bodyText);
73
96
  const body = bodyText.length > 0
74
97
  ? (dimBody ? leveledBody.split('\n').map(l => colors.dim(l)).join('\n') : leveledBody)
75
98
  : "";
76
- const payloadCore = showHeader
99
+ const payloadCore = emitHeader
77
100
  ? (body.length > 0 ? `${header}\n${body}\n` : `${header}\n`)
78
101
  : (body.length > 0 ? `${body}\n` : "");
79
102
  const payload = leadingNewline ? `\n${payloadCore}` : payloadCore;
@@ -82,11 +105,11 @@ export function needleLog(pluginName, message, level = 'log', options = undefine
82
105
  }
83
106
 
84
107
  if (bodyText.length > 0) {
85
- const out = showHeader ? `${headerText} ${bodyText}` : bodyText;
108
+ const out = emitHeader ? `${headerText} ${bodyText}` : bodyText;
86
109
  log(leadingNewline ? `\n${out}` : out);
87
110
  }
88
111
  else {
89
- const out = showHeader ? headerText : "";
112
+ const out = emitHeader ? headerText : "";
90
113
  if (out.length > 0) {
91
114
  log(leadingNewline ? `\n${out}` : out);
92
115
  }
@@ -3,6 +3,7 @@ import { copyFileSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync,
3
3
 
4
4
  import { getOutputDirectory } from './config.js';
5
5
  import { getPosterPath } from './poster.js';
6
+ import { needleLog } from './logging.js';
6
7
 
7
8
  const pwaErrorWithInstructions = "It seems that you're trying to build a PWA using 'vite-plugin-pwa'!\nNeedle can manage PWA settings for you – just pass the same 'pwaOptions' to the needlePlugins and VitePWA plugins:\n\n1. Install the vite PWA plugin: npm install vite-plugin-pwa --save-dev\n\n2. Then update your vite.config.js:\n\n import { VitePWA } from 'vite-plugin-pwa';\n ...\n needlePlugins(command, needleConfig, { pwa: pwaOptions }),\n VitePWA(pwaOptions),\n\nIf you want to manage PWA building yourself and skip this check, please pass '{ pwa: false }' to needlePlugins.";
8
9
 
@@ -267,7 +268,7 @@ updateSW = registerSW({
267
268
  }
268
269
 
269
270
  /** Checks if the vite-plugin-pwa is present in the vite config
270
- * @param {{ plugins?: readonly unknown[] }} config
271
+ * @param {import('vite').ResolvedConfig} config
271
272
  * @returns {import('vite-plugin-pwa').VitePWAOptions | null}
272
273
  */
273
274
  function findVitePWAPlugin(config) {
@@ -291,7 +292,7 @@ function findVitePWAPlugin(config) {
291
292
  /** @param {import('../types/index.d.ts').NeedlePWAProcessContext} context */
292
293
  function cleanup(context) {
293
294
  for (const file of context.generatedFiles) {
294
- log("Cleanup generated file", file);
295
+ if (process.env.DEBUG) log("Cleanup generated file", file);
295
296
  rmSync(file);
296
297
  }
297
298
  context.generatedFiles.length = 0;
@@ -299,7 +300,7 @@ function cleanup(context) {
299
300
 
300
301
  /** @param {...unknown} args */
301
302
  function log(...args) {
302
- console.log("[needle-pwa]", ...args);
303
+ needleLog("needle-pwa", args.map(a => a != null && typeof a === 'object' ? JSON.stringify(a) : String(a ?? "")).join(" "), "log", { dimBody: false });
303
304
  }
304
305
 
305
306
  /** Throws an error with defined stacktrace.
@@ -451,7 +452,7 @@ function processIcons(manifest, outDir, context) {
451
452
  */
452
453
  function generateIcons(manifest, context) {
453
454
  if (!manifest.icons) manifest.icons = [];
454
- log("Generating PWA icons");
455
+ if (process.env.DEBUG) log("Generating PWA icons");
455
456
  const sizes = [48, 128, 144, 192, 512];
456
457
  // Needle icon
457
458
  const defaultIconSVG = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 160 187.74"><defs><linearGradient id="a" x1="89.64" y1="184.81" x2="90.48" y2="21.85" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#62d399"/><stop offset=".51" stop-color="#acd842"/><stop offset=".9" stop-color="#d7db0a"/></linearGradient><linearGradient id="b" x1="69.68" y1="178.9" x2="68.08" y2="16.77" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#0ba398"/><stop offset=".5" stop-color="#4ca352"/><stop offset="1" stop-color="#76a30a"/></linearGradient><linearGradient id="c" x1="36.6" y1="152.17" x2="34.7" y2="84.19" gradientUnits="userSpaceOnUse"><stop offset=".19" stop-color="#36a382"/><stop offset=".54" stop-color="#49a459"/><stop offset="1" stop-color="#76a30b"/></linearGradient><linearGradient id="d" x1="15.82" y1="153.24" x2="18" y2="90.86" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#267880"/><stop offset=".51" stop-color="#457a5c"/><stop offset="1" stop-color="#717516"/></linearGradient><linearGradient id="e" x1="135.08" y1="135.43" x2="148.93" y2="63.47" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#b0d939"/><stop offset="1" stop-color="#eadb04"/></linearGradient><linearGradient id="f" x1="-4163.25" y1="2285.12" x2="-4160.81" y2="2215.34" gradientTransform="rotate(20 4088.49 13316.712)" gradientUnits="userSpaceOnUse"><stop offset=".17" stop-color="#74af52"/><stop offset=".48" stop-color="#99be32"/><stop offset="1" stop-color="#c0c40a"/></linearGradient><symbol id="g" viewBox="0 0 160 187.74"><path style="fill:url(#a)" d="M79.32 36.98v150.76L95 174.54l6.59-156.31-22.27 18.75z"/><path style="fill:url(#b)" d="M79.32 36.98 57.05 18.23l6.59 156.31 15.68 13.2V36.98z"/><path style="fill:url(#c)" d="m25.19 104.83 8.63 49.04 12.5-14.95-2.46-56.42-18.67 22.33z"/><path style="fill:url(#d)" d="M25.19 104.83 0 90.24l16.97 53.86 16.85 9.77-8.63-49.04z"/><path style="fill:#9c3" d="M43.86 82.5 18.69 67.98 0 90.24l25.18 14.59L43.86 82.5z"/><path style="fill:url(#e)" d="m134.82 78.69-9.97 56.5 15.58-9.04L160 64.1l-25.18 14.59z"/><path style="fill:url(#f)" d="m134.82 78.69-18.68-22.33-2.86 65 11.57 13.83 9.97-56.5z"/><path style="fill:#ffe113" d="m160 64.1-18.69-22.26-25.17 14.52 18.67 22.33L160 64.1z"/><path style="fill:#f3e600" d="M101.59 18.23 79.32 0 57.05 18.23l22.27 18.75 22.27-18.75z"/></symbol></defs><use width="160" height="187.74" xlink:href="#g"/></svg>`;
@@ -504,7 +505,7 @@ function copyIcons(manifest, outDir) {
504
505
  if (!existsSync(outputDirectory)) {
505
506
  mkdirSync(outputDirectory, { recursive: true });
506
507
  }
507
- log("Copy PWA icon " + src + " to output");
508
+ if (process.env.DEBUG) log("Copy PWA icon " + src + " to output");
508
509
  copyFileSync(srcPath, targetPath);
509
510
  }
510
511
  }