@needle-tools/engine 5.1.0-canary.e9062c0 → 5.1.0-canary.f57972c

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 (322) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/SKILL.md +4 -1
  3. package/components.needle.json +1 -1
  4. package/dist/{needle-engine.bundle-CDKcuALa.js → needle-engine.bundle-CAIG39cL.js} +13605 -12680
  5. package/dist/needle-engine.bundle-CFh_isu6.umd.cjs +1734 -0
  6. package/dist/needle-engine.bundle-CtadUKoi.min.js +1734 -0
  7. package/dist/needle-engine.d.ts +1579 -394
  8. package/dist/needle-engine.js +542 -538
  9. package/dist/needle-engine.min.js +1 -1
  10. package/dist/needle-engine.umd.cjs +1 -1
  11. package/dist/three.js +1 -0
  12. package/dist/three.min.js +21 -21
  13. package/dist/three.umd.cjs +16 -16
  14. package/lib/engine/api.d.ts +8 -1
  15. package/lib/engine/api.js +7 -1
  16. package/lib/engine/api.js.map +1 -1
  17. package/lib/engine/codegen/register_types.js +10 -18
  18. package/lib/engine/codegen/register_types.js.map +1 -1
  19. package/lib/engine/debug/debug_spatial_console.d.ts +2 -0
  20. package/lib/engine/debug/debug_spatial_console.js +10 -7
  21. package/lib/engine/debug/debug_spatial_console.js.map +1 -1
  22. package/lib/engine/engine_addressables.d.ts +2 -0
  23. package/lib/engine/engine_addressables.js +6 -3
  24. package/lib/engine/engine_addressables.js.map +1 -1
  25. package/lib/engine/engine_audio.d.ts +68 -0
  26. package/lib/engine/engine_audio.js +172 -0
  27. package/lib/engine/engine_audio.js.map +1 -1
  28. package/lib/engine/engine_camera.fit.js +16 -4
  29. package/lib/engine/engine_camera.fit.js.map +1 -1
  30. package/lib/engine/engine_components.js +1 -1
  31. package/lib/engine/engine_components.js.map +1 -1
  32. package/lib/engine/engine_context.d.ts +37 -27
  33. package/lib/engine/engine_context.js +51 -31
  34. package/lib/engine/engine_context.js.map +1 -1
  35. package/lib/engine/engine_context_eventbus.d.ts +47 -0
  36. package/lib/engine/engine_context_eventbus.js +47 -0
  37. package/lib/engine/engine_context_eventbus.js.map +1 -0
  38. package/lib/engine/engine_disposable.d.ts +172 -0
  39. package/lib/engine/engine_disposable.js +136 -0
  40. package/lib/engine/engine_disposable.js.map +1 -0
  41. package/lib/engine/engine_gameobject.d.ts +1 -10
  42. package/lib/engine/engine_gameobject.js +22 -120
  43. package/lib/engine/engine_gameobject.js.map +1 -1
  44. package/lib/engine/engine_gltf_builtin_components.js +7 -69
  45. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  46. package/lib/engine/engine_init.js +14 -4
  47. package/lib/engine/engine_init.js.map +1 -1
  48. package/lib/engine/engine_input.d.ts +24 -5
  49. package/lib/engine/engine_input.js +3 -2
  50. package/lib/engine/engine_input.js.map +1 -1
  51. package/lib/engine/engine_instantiate_resolve.d.ts +42 -0
  52. package/lib/engine/engine_instantiate_resolve.js +372 -0
  53. package/lib/engine/engine_instantiate_resolve.js.map +1 -0
  54. package/lib/engine/engine_license.d.ts +7 -7
  55. package/lib/engine/engine_license.js +186 -58
  56. package/lib/engine/engine_license.js.map +1 -1
  57. package/lib/engine/engine_mainloop_utils.js +7 -4
  58. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  59. package/lib/engine/engine_networking.d.ts +51 -37
  60. package/lib/engine/engine_networking.js +132 -82
  61. package/lib/engine/engine_networking.js.map +1 -1
  62. package/lib/engine/engine_networking.transport.websocket.d.ts +15 -0
  63. package/lib/engine/engine_networking.transport.websocket.js +38 -0
  64. package/lib/engine/engine_networking.transport.websocket.js.map +1 -0
  65. package/lib/engine/engine_networking_blob.js +4 -4
  66. package/lib/engine/engine_networking_blob.js.map +1 -1
  67. package/lib/engine/engine_networking_instantiate.js +2 -2
  68. package/lib/engine/engine_networking_instantiate.js.map +1 -1
  69. package/lib/engine/engine_networking_types.d.ts +39 -1
  70. package/lib/engine/engine_networking_types.js +7 -0
  71. package/lib/engine/engine_networking_types.js.map +1 -1
  72. package/lib/engine/engine_physics_rapier.d.ts +21 -3
  73. package/lib/engine/engine_physics_rapier.js +94 -25
  74. package/lib/engine/engine_physics_rapier.js.map +1 -1
  75. package/lib/engine/engine_scenedata.d.ts +5 -7
  76. package/lib/engine/engine_scenedata.js +16 -13
  77. package/lib/engine/engine_scenedata.js.map +1 -1
  78. package/lib/engine/engine_serialization_builtin_serializer.d.ts +10 -16
  79. package/lib/engine/engine_serialization_builtin_serializer.js +56 -46
  80. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  81. package/lib/engine/engine_serialization_core.d.ts +1 -0
  82. package/lib/engine/engine_serialization_core.js +7 -0
  83. package/lib/engine/engine_serialization_core.js.map +1 -1
  84. package/lib/engine/engine_types.d.ts +29 -11
  85. package/lib/engine/engine_types.js +1 -1
  86. package/lib/engine/engine_types.js.map +1 -1
  87. package/lib/engine/engine_util_decorator.js +7 -2
  88. package/lib/engine/engine_util_decorator.js.map +1 -1
  89. package/lib/engine/engine_utils.d.ts +1 -1
  90. package/lib/engine/engine_utils.js +19 -5
  91. package/lib/engine/engine_utils.js.map +1 -1
  92. package/lib/engine/engine_utils_qrcode.js +2 -2
  93. package/lib/engine/engine_utils_qrcode.js.map +1 -1
  94. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  95. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
  96. package/lib/engine/webcomponents/jsx.d.ts +9 -2
  97. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
  98. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  99. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +1 -1
  100. package/lib/engine/webcomponents/needle menu/needle-menu.js +6 -6
  101. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  102. package/lib/engine/webcomponents/needle-engine.d.ts +10 -4
  103. package/lib/engine/webcomponents/needle-engine.js +3 -3
  104. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  105. package/lib/engine/webcomponents/needle-engine.loading.js +2 -2
  106. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  107. package/lib/engine/xr/NeedleXRSession.d.ts +3 -2
  108. package/lib/engine/xr/NeedleXRSession.js +50 -14
  109. package/lib/engine/xr/NeedleXRSession.js.map +1 -1
  110. package/lib/engine/xr/TempXRContext.js +2 -2
  111. package/lib/engine/xr/TempXRContext.js.map +1 -1
  112. package/lib/engine/xr/events.d.ts +1 -1
  113. package/lib/engine/xr/events.js.map +1 -1
  114. package/lib/engine-components/Animation.js +17 -16
  115. package/lib/engine-components/Animation.js.map +1 -1
  116. package/lib/engine-components/AnimationBuilder.d.ts +158 -0
  117. package/lib/engine-components/AnimationBuilder.js +305 -0
  118. package/lib/engine-components/AnimationBuilder.js.map +1 -0
  119. package/lib/engine-components/Animator.d.ts +6 -0
  120. package/lib/engine-components/Animator.js +23 -13
  121. package/lib/engine-components/Animator.js.map +1 -1
  122. package/lib/engine-components/AnimatorController.builder.d.ts +191 -0
  123. package/lib/engine-components/AnimatorController.builder.js +263 -0
  124. package/lib/engine-components/AnimatorController.builder.js.map +1 -0
  125. package/lib/engine-components/AnimatorController.d.ts +4 -119
  126. package/lib/engine-components/AnimatorController.js +37 -233
  127. package/lib/engine-components/AnimatorController.js.map +1 -1
  128. package/lib/engine-components/AudioSource.d.ts +19 -3
  129. package/lib/engine-components/AudioSource.js +121 -68
  130. package/lib/engine-components/AudioSource.js.map +1 -1
  131. package/lib/engine-components/Collider.d.ts +18 -9
  132. package/lib/engine-components/Collider.js +61 -14
  133. package/lib/engine-components/Collider.js.map +1 -1
  134. package/lib/engine-components/Component.d.ts +72 -9
  135. package/lib/engine-components/Component.js +114 -10
  136. package/lib/engine-components/Component.js.map +1 -1
  137. package/lib/engine-components/ContactShadows.d.ts +1 -0
  138. package/lib/engine-components/ContactShadows.js +14 -1
  139. package/lib/engine-components/ContactShadows.js.map +1 -1
  140. package/lib/engine-components/DragControls.d.ts +7 -0
  141. package/lib/engine-components/DragControls.js +19 -7
  142. package/lib/engine-components/DragControls.js.map +1 -1
  143. package/lib/engine-components/DropListener.js +3 -0
  144. package/lib/engine-components/DropListener.js.map +1 -1
  145. package/lib/engine-components/EventList.d.ts +31 -9
  146. package/lib/engine-components/EventList.js +37 -76
  147. package/lib/engine-components/EventList.js.map +1 -1
  148. package/lib/engine-components/Joints.d.ts +4 -2
  149. package/lib/engine-components/Joints.js +19 -3
  150. package/lib/engine-components/Joints.js.map +1 -1
  151. package/lib/engine-components/Light.js +13 -3
  152. package/lib/engine-components/Light.js.map +1 -1
  153. package/lib/engine-components/Networking.d.ts +1 -1
  154. package/lib/engine-components/Networking.js +1 -1
  155. package/lib/engine-components/OrbitControls.d.ts +0 -2
  156. package/lib/engine-components/OrbitControls.js +30 -12
  157. package/lib/engine-components/OrbitControls.js.map +1 -1
  158. package/lib/engine-components/ReflectionProbe.js +2 -0
  159. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  160. package/lib/engine-components/RigidBody.d.ts +12 -4
  161. package/lib/engine-components/RigidBody.js +18 -4
  162. package/lib/engine-components/RigidBody.js.map +1 -1
  163. package/lib/engine-components/SceneSwitcher.js +3 -0
  164. package/lib/engine-components/SceneSwitcher.js.map +1 -1
  165. package/lib/engine-components/SeeThrough.js +2 -2
  166. package/lib/engine-components/SeeThrough.js.map +1 -1
  167. package/lib/engine-components/api.d.ts +2 -1
  168. package/lib/engine-components/api.js +2 -1
  169. package/lib/engine-components/api.js.map +1 -1
  170. package/lib/engine-components/codegen/components.d.ts +7 -13
  171. package/lib/engine-components/codegen/components.js +7 -13
  172. package/lib/engine-components/codegen/components.js.map +1 -1
  173. package/lib/engine-components/export/usdz/USDZExporter.js +4 -4
  174. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  175. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
  176. package/lib/engine-components/postprocessing/VolumeParameter.d.ts +2 -0
  177. package/lib/engine-components/postprocessing/VolumeParameter.js +4 -1
  178. package/lib/engine-components/postprocessing/VolumeParameter.js.map +1 -1
  179. package/lib/engine-components/timeline/PlayableDirector.d.ts +21 -11
  180. package/lib/engine-components/timeline/PlayableDirector.js +75 -67
  181. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  182. package/lib/engine-components/timeline/SignalAsset.d.ts +3 -1
  183. package/lib/engine-components/timeline/SignalAsset.js +1 -0
  184. package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
  185. package/lib/engine-components/timeline/TimelineBuilder.d.ts +413 -0
  186. package/lib/engine-components/timeline/TimelineBuilder.js +506 -0
  187. package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -0
  188. package/lib/engine-components/timeline/TimelineModels.d.ts +2 -1
  189. package/lib/engine-components/timeline/TimelineModels.js +3 -0
  190. package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
  191. package/lib/engine-components/timeline/TimelineTracks.d.ts +37 -6
  192. package/lib/engine-components/timeline/TimelineTracks.js +92 -26
  193. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  194. package/lib/engine-components/timeline/index.d.ts +2 -1
  195. package/lib/engine-components/timeline/index.js +2 -0
  196. package/lib/engine-components/timeline/index.js.map +1 -1
  197. package/lib/engine-components/ui/Canvas.d.ts +1 -1
  198. package/lib/engine-components/ui/Canvas.js +2 -8
  199. package/lib/engine-components/ui/Canvas.js.map +1 -1
  200. package/lib/engine-components/ui/Text.d.ts +1 -0
  201. package/lib/engine-components/ui/Text.js +10 -7
  202. package/lib/engine-components/ui/Text.js.map +1 -1
  203. package/lib/engine-components/web/CursorFollow.d.ts +0 -1
  204. package/lib/engine-components/web/CursorFollow.js +21 -13
  205. package/lib/engine-components/web/CursorFollow.js.map +1 -1
  206. package/lib/engine-components/webxr/WebXRImageTracking.d.ts +62 -1
  207. package/lib/engine-components/webxr/WebXRImageTracking.js +59 -2
  208. package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
  209. package/package.json +2 -83
  210. package/plugins/common/cloud.js +6 -1
  211. package/plugins/common/license.js +31 -10
  212. package/plugins/common/worker.js +9 -4
  213. package/plugins/vite/asap.js +17 -8
  214. package/plugins/vite/dependencies.js +29 -10
  215. package/plugins/vite/dependency-watcher.js +2 -2
  216. package/plugins/vite/editor-connection.js +3 -3
  217. package/plugins/vite/license.js +42 -7
  218. package/plugins/vite/local-files-core.js +3 -3
  219. package/plugins/vite/local-files-utils.d.ts +3 -1
  220. package/plugins/vite/local-files-utils.js +29 -5
  221. package/plugins/vite/reload.js +19 -18
  222. package/plugins/vite/server.js +2 -1
  223. package/src/engine/api.ts +11 -1
  224. package/src/engine/codegen/register_types.ts +10 -18
  225. package/src/engine/debug/debug_spatial_console.ts +10 -7
  226. package/src/engine/engine_addressables.ts +6 -3
  227. package/src/engine/engine_audio.ts +184 -0
  228. package/src/engine/engine_camera.fit.ts +15 -4
  229. package/src/engine/engine_components.ts +1 -1
  230. package/src/engine/engine_context.ts +63 -39
  231. package/src/engine/engine_context_eventbus.ts +73 -0
  232. package/src/engine/engine_disposable.ts +214 -0
  233. package/src/engine/engine_gameobject.ts +54 -159
  234. package/src/engine/engine_gltf_builtin_components.ts +7 -76
  235. package/src/engine/engine_init.ts +14 -4
  236. package/src/engine/engine_input.ts +28 -7
  237. package/src/engine/engine_instantiate_resolve.ts +407 -0
  238. package/src/engine/engine_license.ts +202 -56
  239. package/src/engine/engine_mainloop_utils.ts +7 -4
  240. package/src/engine/engine_networking.transport.websocket.ts +45 -0
  241. package/src/engine/engine_networking.ts +161 -137
  242. package/src/engine/engine_networking_blob.ts +4 -4
  243. package/src/engine/engine_networking_instantiate.ts +2 -2
  244. package/src/engine/engine_networking_types.ts +41 -1
  245. package/src/engine/engine_physics_rapier.ts +102 -33
  246. package/src/engine/engine_scenedata.ts +16 -13
  247. package/src/engine/engine_serialization_builtin_serializer.ts +64 -52
  248. package/src/engine/engine_serialization_core.ts +9 -0
  249. package/src/engine/engine_types.ts +46 -27
  250. package/src/engine/engine_util_decorator.ts +7 -2
  251. package/src/engine/engine_utils.ts +16 -5
  252. package/src/engine/engine_utils_qrcode.ts +2 -2
  253. package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  254. package/src/engine/webcomponents/jsx.d.ts +9 -2
  255. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
  256. package/src/engine/webcomponents/needle menu/needle-menu.ts +6 -6
  257. package/src/engine/webcomponents/needle-engine.loading.ts +6 -6
  258. package/src/engine/webcomponents/needle-engine.ts +12 -6
  259. package/src/engine/xr/NeedleXRSession.ts +48 -13
  260. package/src/engine/xr/TempXRContext.ts +2 -2
  261. package/src/engine/xr/events.ts +1 -1
  262. package/src/engine-components/Animation.ts +19 -16
  263. package/src/engine-components/AnimationBuilder.ts +472 -0
  264. package/src/engine-components/Animator.ts +24 -12
  265. package/src/engine-components/AnimatorController.builder.ts +387 -0
  266. package/src/engine-components/AnimatorController.ts +24 -292
  267. package/src/engine-components/AudioSource.ts +130 -79
  268. package/src/engine-components/Collider.ts +66 -18
  269. package/src/engine-components/Component.ts +118 -20
  270. package/src/engine-components/ContactShadows.ts +15 -1
  271. package/src/engine-components/DragControls.ts +18 -11
  272. package/src/engine-components/DropListener.ts +3 -0
  273. package/src/engine-components/EventList.ts +45 -83
  274. package/src/engine-components/Joints.ts +20 -4
  275. package/src/engine-components/Light.ts +13 -4
  276. package/src/engine-components/Networking.ts +1 -1
  277. package/src/engine-components/OrbitControls.ts +34 -14
  278. package/src/engine-components/ReflectionProbe.ts +2 -0
  279. package/src/engine-components/RigidBody.ts +18 -4
  280. package/src/engine-components/SceneSwitcher.ts +3 -0
  281. package/src/engine-components/SeeThrough.ts +2 -2
  282. package/src/engine-components/api.ts +2 -1
  283. package/src/engine-components/codegen/components.ts +7 -13
  284. package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
  285. package/src/engine-components/postprocessing/VolumeParameter.ts +4 -1
  286. package/src/engine-components/timeline/PlayableDirector.ts +83 -81
  287. package/src/engine-components/timeline/SignalAsset.ts +4 -1
  288. package/src/engine-components/timeline/TimelineBuilder.ts +824 -0
  289. package/src/engine-components/timeline/TimelineModels.ts +5 -1
  290. package/src/engine-components/timeline/TimelineTracks.ts +96 -27
  291. package/src/engine-components/timeline/index.ts +2 -1
  292. package/src/engine-components/ui/Canvas.ts +2 -8
  293. package/src/engine-components/ui/Text.ts +12 -8
  294. package/src/engine-components/web/CursorFollow.ts +21 -14
  295. package/src/engine-components/webxr/WebXRImageTracking.ts +79 -7
  296. package/dist/needle-engine.bundle--q_w7iXI.umd.cjs +0 -1732
  297. package/dist/needle-engine.bundle-w22UkaT_.min.js +0 -1732
  298. package/lib/engine-components/AvatarLoader.d.ts +0 -80
  299. package/lib/engine-components/AvatarLoader.js +0 -232
  300. package/lib/engine-components/AvatarLoader.js.map +0 -1
  301. package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +0 -11
  302. package/lib/engine-components/avatar/AvatarBlink_Simple.js +0 -77
  303. package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +0 -1
  304. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +0 -14
  305. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +0 -69
  306. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +0 -1
  307. package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +0 -29
  308. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +0 -122
  309. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +0 -1
  310. package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +0 -15
  311. package/lib/engine-components/avatar/Avatar_MouthShapes.js +0 -80
  312. package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +0 -1
  313. package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +0 -9
  314. package/lib/engine-components/avatar/Avatar_MustacheShake.js +0 -30
  315. package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +0 -1
  316. package/src/engine-components/AvatarLoader.ts +0 -264
  317. package/src/engine-components/avatar/AvatarBlink_Simple.ts +0 -70
  318. package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +0 -64
  319. package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +0 -140
  320. package/src/engine-components/avatar/Avatar_MouthShapes.ts +0 -84
  321. package/src/engine-components/avatar/Avatar_MustacheShake.ts +0 -32
  322. package/src/vite-env.d.ts +0 -16
@@ -86,24 +86,38 @@ async function requestNeedleCloud(path, options) {
86
86
 
87
87
  /** @typedef {{ ok: boolean, status: number, statusText: string, text: string }} NeedleCloudHttpResponse */
88
88
 
89
+ /** @typedef {{ type: string, jwt: string | null }} LicenseResult */
90
+
89
91
  /**
90
92
  * Replace license string - used for webpack
91
93
  * @param {string} code
92
94
  * @param {DefaultOptions & {accessToken?:string, team:string|undefined}} opts
93
95
  */
94
96
  export async function replaceLicense(code, opts) {
95
- const index = code?.indexOf("NEEDLE_ENGINE_LICENSE_TYPE");
97
+ const index = code?.indexOf("_EubmJj");
96
98
  if (index >= 0) {
97
- const licenseType = await resolveLicense(opts);
98
- if (!licenseType) {
99
+ const licenseResult = await resolveLicense(opts);
100
+ if (!licenseResult) {
99
101
  return code;
100
102
  }
101
103
  const end = code.indexOf(";", index);
102
104
  if (end >= 0) {
103
105
  const line = code.substring(index, end);
104
- const replaced = "NEEDLE_ENGINE_LICENSE_TYPE = \"" + licenseType + "\"";
106
+ const replaced = "_EubmJj = \"" + licenseResult.type + "\"";
105
107
  code = code.replace(line, replaced);
106
- return code;
108
+ }
109
+
110
+ // Also inject JWT if available
111
+ if (licenseResult.jwt) {
112
+ const jwtIndex = code.indexOf("__OXddGMYg");
113
+ if (jwtIndex >= 0) {
114
+ const jwtEnd = code.indexOf(";", jwtIndex);
115
+ if (jwtEnd >= 0) {
116
+ const jwtLine = code.substring(jwtIndex, jwtEnd);
117
+ const jwtReplaced = "__OXddGMYg = \"" + licenseResult.jwt + "\"";
118
+ code = code.replace(jwtLine, jwtReplaced);
119
+ }
120
+ }
107
121
  }
108
122
  }
109
123
  return code;
@@ -112,7 +126,7 @@ export async function replaceLicense(code, opts) {
112
126
  /**
113
127
  * Resolve the license using the needle engine licensing server
114
128
  * @param {DefaultOptions & {accessToken?:string, team?:string} | null} args
115
- * @returns {Promise<string | null>}
129
+ * @returns {Promise<LicenseResult | null>}
116
130
  */
117
131
  export async function resolveLicense(args = null) {
118
132
  let accessToken = args?.accessToken;
@@ -210,7 +224,7 @@ export async function resolveLicense(args = null) {
210
224
  return null;
211
225
  }
212
226
  else if (!licenseResponse.ok) {
213
- if (licenseResponse.status === 500)
227
+ if (licenseResponse.status >= 500)
214
228
  logLicense(`ERROR: Failed to fetch license (${licenseResponse.status})`, "error");
215
229
  else
216
230
  logLicense(`No license found (${licenseResponse.status})`);
@@ -226,10 +240,11 @@ export async function resolveLicense(args = null) {
226
240
  /**
227
241
  * @param {string} str License string
228
242
  * @param {{includeFetchLine?: boolean}} [options]
243
+ * @returns {LicenseResult | null}
229
244
  */
230
245
  function tryParseLicense(str, options = undefined) {
231
246
  try {
232
- /** @type {{needle_engine_license:string}} */
247
+ /** @type {{needle_engine_license:string, needle_license_jwt?:string}} */
233
248
  const licenseJson = JSON.parse(str);
234
249
  if (licenseJson.needle_engine_license) {
235
250
  const success = `INFO: Successfully received \"${licenseJson.needle_engine_license?.toUpperCase()}\" license`;
@@ -239,7 +254,10 @@ function tryParseLicense(str, options = undefined) {
239
254
  else {
240
255
  logLicense(success);
241
256
  }
242
- return licenseJson.needle_engine_license;
257
+ return {
258
+ type: licenseJson.needle_engine_license,
259
+ jwt: licenseJson.needle_license_jwt || null,
260
+ };
243
261
  }
244
262
  if ("error" in licenseJson) {
245
263
  logLicense(`ERROR in license check: \"${licenseJson.error}\"`, "error");
@@ -361,7 +379,10 @@ export async function getPublicIdentifier(project_id, opts = undefined) {
361
379
  return null;
362
380
  }
363
381
  else if (!res.ok) {
364
- logIdentifier("ERROR: Failed to fetch project identifier", "error");
382
+ if (res.status >= 500)
383
+ logIdentifier(`Failed to fetch project identifier (${res.status})`, "error");
384
+ else
385
+ logIdentifier(`No project identifier found (${res.status})`);
365
386
  await releaseResponse(res);
366
387
  return null;
367
388
  }
@@ -1,3 +1,4 @@
1
+ import path from 'path';
1
2
  import { needleLog } from '../vite/logging.js';
2
3
 
3
4
 
@@ -53,13 +54,17 @@ export function rollupFixWorkerImport(opts = { logFail: true }) {
53
54
  // console.log("WORKER?", url)
54
55
  if (url?.startsWith("/")) {
55
56
  needleLog("rollup", `Rewrite worker import in ${chunk.fileName}`, "log", { leadingNewline: true, dimBody: false });
56
- // Make url file-relative
57
- const newUrl = url.replace(/^\//, "");
57
+ // Compute the relative path from the chunk's directory to the worker file.
58
+ // url is absolute from build root (e.g. "/assets/worker.js") and the chunk
59
+ // may itself be inside assets/ — using path.posix.relative avoids producing
60
+ // a double "assets/assets/" path.
61
+ const workerPath = url.replace(/^\//, "");
62
+ const chunkDir = path.posix.dirname(chunk.fileName);
63
+ const relativeUrl = path.posix.relative(chunkDir, workerPath) || workerPath;
58
64
  // For CORS issues we need to use importScripts: https://linear.app/needle/issue/NE-6572#comment-ea5dc65e
59
- const output = `/* new-worker */ new Worker(URL.createObjectURL(new Blob(["import '" + \`\${new URL('./${newUrl}', import.meta.url).toString()}\` + "';"], { type: 'text/javascript' }))`;
65
+ const output = `/* new-worker */ new Worker(URL.createObjectURL(new Blob(["import '" + \`\${new URL('./${relativeUrl}', import.meta.url).toString()}\` + "';"], { type: 'text/javascript' }))`;
60
66
  needleLog("rollup", "Did rewrite worker output to: " + output, "log", { leadingNewline: true });
61
67
  return output;
62
- // return `new Worker(new URL("./${newUrl}", import.meta.url)`;
63
68
  }
64
69
  return match;
65
70
  });
@@ -50,7 +50,7 @@ export async function needleAsap(command, config, userSettings) {
50
50
  const tags = [];
51
51
 
52
52
  try {
53
- generateGltfPreloadLinks(config, html, tags);
53
+ generateGltfPreloadLinks(config, html, tags, viteConfig?.base);
54
54
  }
55
55
  catch (err) {
56
56
  console.error("Error generating gltf preload links", err);
@@ -173,18 +173,21 @@ function fixMainTs() {
173
173
  * @param {import('vite').ResolvedConfig} _config
174
174
  * @param {import('vite').HtmlTagDescriptor[]} tags
175
175
  */
176
- function generateScriptPreloadLinks(_config, tags) {
176
+ function generateScriptPreloadLinks(config, tags) {
177
177
  try {
178
+ const base = config.base || '/';
178
179
  const chunks = preloadScriptPaths;
179
180
  // console.log("ASAP", chunks)
180
181
  if (chunks.length > 0) {
181
182
  for (const chunk of chunks) {
183
+ // Apply base path so preload hrefs resolve correctly under SPA routing
184
+ const href = chunk.startsWith('./') ? base + chunk.slice(2) : chunk;
182
185
  tags.push({
183
186
  tag: 'link',
184
187
  attrs: {
185
188
  rel: "modulepreload",
186
189
  as: "script",
187
- href: chunk,
190
+ href: href,
188
191
  }
189
192
  });
190
193
  }
@@ -203,15 +206,16 @@ const codegenRegex = /\"(?<gltf>.+(.glb|.gltf)(\?.*)?)\"/gm;
203
206
  /**
204
207
  * @param {import('../types').needleConfig} config
205
208
  * @param {string} html
206
- * @param {import('vite').HtmlTagDescriptor[]} tags
209
+ * @param {import('vite').HtmlTagDescriptor[]} tags
210
+ * @param {string} [base]
207
211
  **/
208
- function generateGltfPreloadLinks(config, html, tags) {
212
+ function generateGltfPreloadLinks(config, html, tags, base) {
209
213
 
210
214
  // TODO: try to get the <needle-engine src> element src attribute and preload that
211
215
  const needleEngineMatches = tryParseNeedleEngineSrcAttributeFromHtml(html);
212
216
  if (needleEngineMatches?.length) {
213
217
  for (const item of needleEngineMatches) {
214
- insertPreloadLink(tags, item, "model/gltf+json");
218
+ insertPreloadLink(tags, item, "model/gltf+json", base);
215
219
  }
216
220
  }
217
221
 
@@ -246,7 +250,7 @@ function generateGltfPreloadLinks(config, html, tags) {
246
250
  }
247
251
  }
248
252
  needleLog("needle:asap", `Insert glTF preload link: ${value}`);
249
- insertPreloadLink(tags, value, "model/gltf+json");
253
+ insertPreloadLink(tags, value, "model/gltf+json", base);
250
254
  }
251
255
  }
252
256
  }
@@ -258,9 +262,14 @@ function generateGltfPreloadLinks(config, html, tags) {
258
262
  * @param {import('vite').HtmlTagDescriptor[]} tags
259
263
  * @param {string} href
260
264
  * @param {string} type
265
+ * @param {string} [base]
261
266
  */
262
- function insertPreloadLink(tags, href, type) {
267
+ function insertPreloadLink(tags, href, type, base) {
263
268
  if (!href) return;
269
+ // Apply base path so preload hrefs resolve correctly under SPA routing
270
+ if (base && !href.startsWith('http') && !href.startsWith('/')) {
271
+ href = base + (href.startsWith('./') ? href.slice(2) : href);
272
+ }
264
273
  tags.push({
265
274
  tag: 'link',
266
275
  attrs: {
@@ -61,6 +61,35 @@ export function needleDependencies(command, config, userSettings) {
61
61
  }
62
62
  },
63
63
  },
64
+ // Vite 8's optimizer rebases `new URL(specifier, import.meta.url)` paths
65
+ // inside pre-bundled dependencies (PR #21434), but only handles truly relative
66
+ // paths (./ ../). Bare-specifier paths like `three-mesh-bvh/src/workers/...`
67
+ // are treated as relative to the *source file* that contained the `new URL()`
68
+ // call, producing a wrong URL such as:
69
+ // /node_modules/@needle-tools/engine/.../three-mesh-bvh/src/workers/generateMeshBVH.worker.js
70
+ // This middleware rewrites those broken URLs so the dev server finds the file at
71
+ // its real location in node_modules.
72
+ {
73
+ name: 'needle:worker-url-rewrite',
74
+ configureServer(server) {
75
+ const rewritePackages = ['three-mesh-bvh'];
76
+ server.middlewares.use((req, _res, next) => {
77
+ if (req.url) {
78
+ for (const pkg of rewritePackages) {
79
+ const marker = `/${pkg}/`;
80
+ if (req.url.includes(marker) && !req.url.startsWith(`/node_modules/${pkg}/`) && !req.url.startsWith('/@fs/')) {
81
+ const idx = req.url.indexOf(marker);
82
+ const rewritten = '/node_modules' + req.url.slice(idx);
83
+ needleLog('needle-dependencies', `Rewriting worker URL → ${rewritten}`);
84
+ req.url = rewritten;
85
+ break;
86
+ }
87
+ }
88
+ }
89
+ next();
90
+ });
91
+ },
92
+ },
64
93
  ]
65
94
  }
66
95
 
@@ -158,16 +187,6 @@ function handleOptimizeDeps(config) {
158
187
  config.optimizeDeps.exclude.push('@needle-tools/engine');
159
188
  needleLog("needle-dependencies", 'Detected local @needle-tools/engine package → will exclude it from optimization');
160
189
  }
161
- // When engine is excluded from optimizeDeps, three-mesh-bvh must also be excluded.
162
- // The BVH worker (generateMeshBVH.worker.js) uses bare imports like `import 'three'`
163
- // which only resolve correctly when served through Vite's dev server module system.
164
- // If three-mesh-bvh is pre-bundled, the worker URL points into the cache and bare
165
- // imports fail at runtime → "Unknown error. Please check the server console."
166
- if (!config.optimizeDeps.include?.includes('three-mesh-bvh') &&
167
- !config.optimizeDeps.exclude.includes('three-mesh-bvh')) {
168
- config.optimizeDeps.exclude.push('three-mesh-bvh');
169
- needleLog("needle-dependencies", 'Detected local @needle-tools/engine package → will also exclude three-mesh-bvh from optimization');
170
- }
171
190
  }
172
191
  }
173
192
 
@@ -98,7 +98,7 @@ function watchPackageJson(server, projectDir, packageJsonPath, cachePath) {
98
98
 
99
99
  setTimeout(() => {
100
100
  requireInstall = testIfInstallIsRequired(projectDir, packageJson);
101
- }, 1000);
101
+ }, 1000).unref();
102
102
 
103
103
  setInterval(() => {
104
104
  if (!packageJson || lastEditTime === undefined) return;
@@ -149,7 +149,7 @@ function watchPackageJson(server, projectDir, packageJsonPath, cachePath) {
149
149
  restart(server, projectDir, cachePath);
150
150
  }
151
151
  }
152
- }, 2000);
152
+ }, 2000).unref();
153
153
  }
154
154
 
155
155
  /** @param {string} projectDir @param {PackageJson | undefined} packageJson @returns {boolean} */
@@ -27,7 +27,7 @@ export async function editorConnection(command, config, userSettings, pluginsArr
27
27
  if (typeof config.generator === "string" && !config.generator.includes("Unity")) return;
28
28
 
29
29
  if (!config) {
30
- setTimeout(() => needleLog("needle-editor-sync", "Needle Editor Sync can not be installed automatically to vite: missing config", "warn"), 1000);
30
+ setTimeout(() => needleLog("needle-editor-sync", "Needle Editor Sync can not be installed automatically to vite: missing config", "warn"), 1000).unref();
31
31
  return createPlugin(false);
32
32
  }
33
33
 
@@ -42,14 +42,14 @@ export async function editorConnection(command, config, userSettings, pluginsArr
42
42
  // }
43
43
  // }
44
44
  if (needleEditorSettings && needleEditorSettings.enabled === false) {
45
- setTimeout(() => needleLog("needle-editor-sync", "Needle Editor Sync is not enabled. Add a 'Needle Editor Sync' component to your scene to enable", "warn"), 1000);
45
+ setTimeout(() => needleLog("needle-editor-sync", "Needle Editor Sync is not enabled. Add a 'Needle Editor Sync' component to your scene to enable", "warn"), 1000).unref();
46
46
  return createPlugin(false);
47
47
  }
48
48
 
49
49
  // Check if the editor package is installed
50
50
  let path = root + `/node_modules/${editorSyncPackageName}/plugins/index.js`;
51
51
  if (existsSync(path) === false) {
52
- setTimeout(() => needleLog("needle-editor-sync", `${editorSyncPackageName} is not installed: Add the "Needle Editor Sync" component to your scene if you want to send changes directly from the Unity Editor to web app`, "warn"), 1000);
52
+ setTimeout(() => needleLog("needle-editor-sync", `${editorSyncPackageName} is not installed: Add the "Needle Editor Sync" component to your scene if you want to send changes directly from the Unity Editor to web app`, "warn"), 1000).unref();
53
53
  return createPlugin(false);
54
54
  }
55
55
 
@@ -8,7 +8,9 @@ import { loadConfig } from './config.js';
8
8
  * @returns {import('vite').Plugin}
9
9
  */
10
10
  export function needleLicense(command, config, userSettings) {
11
- let license = undefined;
11
+ /** @type {import('../common/license.js').LicenseResult | null | undefined} */
12
+ let licenseResult = undefined;
13
+ let appliedLicense = false;
12
14
 
13
15
  return {
14
16
  name: "needle:license",
@@ -23,7 +25,7 @@ export function needleLicense(command, config, userSettings) {
23
25
  }
24
26
  }
25
27
 
26
- license = await resolveLicense({
28
+ licenseResult = await resolveLicense({
27
29
  team: team,
28
30
  accessToken: userSettings?.license?.accessToken,
29
31
  loglevel: userSettings?.debugLicense === true ? "verbose" : undefined
@@ -31,25 +33,58 @@ export function needleLicense(command, config, userSettings) {
31
33
 
32
34
  },
33
35
  async transform(src, id) {
34
- const isNeedleEngineFile = id.includes("engine/engine_license") || id.includes("needle-tools_engine");
36
+ // Vite 4 and 8 handling:
37
+ const isNeedleEngineFile = id.includes("engine/engine_license")
38
+ || id.includes("needle-tools_engine")
39
+ || id.includes("@needle-tools")
40
+ || id.includes("needle-engine");
35
41
  // sometimes the actual license parameter is in a unnamed chunk file
36
42
  const isViteChunkFile = id.includes("chunk") && id.includes(".vite");
37
43
  if (isNeedleEngineFile || isViteChunkFile) {
38
44
 
39
- if (!license) {
45
+ if (!licenseResult) {
40
46
  return;
41
47
  }
42
48
 
43
- const index = src.indexOf("NEEDLE_ENGINE_LICENSE_TYPE");
49
+ let modified = false;
50
+
51
+ // Replace license type
52
+ const index = src.indexOf("_EubmJj");
44
53
  if (index >= 0) {
45
54
  const end = src.indexOf(";", index);
46
55
  if (end >= 0) {
47
56
  const line = src.substring(index, end);
48
- const replaced = "NEEDLE_ENGINE_LICENSE_TYPE = \"" + license + "\"";
57
+ const replaced = "_EubmJj = \"" + licenseResult.type + "\"";
49
58
  src = src.replace(line, replaced);
50
- return { code: src, map: null }
59
+ modified = true;
51
60
  }
52
61
  }
62
+
63
+ // Replace license JWT (same pattern)
64
+ if (licenseResult.jwt) {
65
+ const jwtIndex = src.indexOf("__OXddGMYg");
66
+ if (jwtIndex >= 0) {
67
+ const jwtEnd = src.indexOf(";", jwtIndex);
68
+ if (jwtEnd >= 0) {
69
+ const jwtLine = src.substring(jwtIndex, jwtEnd);
70
+ const jwtReplaced = "__OXddGMYg = \"" + licenseResult.jwt + "\"";
71
+ src = src.replace(jwtLine, jwtReplaced);
72
+ modified = true;
73
+ }
74
+ }
75
+ }
76
+
77
+ if (modified) {
78
+ appliedLicense = true;
79
+ return { code: src, map: null }
80
+ }
81
+ }
82
+ },
83
+ buildEnd() {
84
+ if (!appliedLicense) {
85
+ if (process.env.NEEDLE_TEST_ENV) {
86
+ console.error("ERR: License was not applied!");
87
+ }
53
88
  }
54
89
  }
55
90
  }
@@ -291,7 +291,7 @@ export function needleMakeFilesLocal(command, _config, userSettings) {
291
291
  failedDownloads,
292
292
  localizationStats,
293
293
  }, activeHandlers);
294
- src = fixRelativeNewURL(src);
294
+ src = fixRelativeNewURL(src, viteConfig?.base);
295
295
  }
296
296
  catch (err) {
297
297
  needleLog("needle:local-files", "Error in transform: " + getErrMessage(err), "error");
@@ -303,7 +303,7 @@ export function needleMakeFilesLocal(command, _config, userSettings) {
303
303
  },
304
304
  renderChunk(code, chunk) {
305
305
  if (!chunk.fileName?.endsWith(".js")) return null;
306
- const fixed = fixRelativeNewURL(code);
306
+ const fixed = fixRelativeNewURL(code, viteConfig?.base);
307
307
  if (fixed === code) return null;
308
308
  return {
309
309
  code: fixed,
@@ -314,7 +314,7 @@ export function needleMakeFilesLocal(command, _config, userSettings) {
314
314
  for (const output of Object.values(bundle)) {
315
315
  if (output.type !== "chunk") continue;
316
316
  if (!output.fileName?.endsWith(".js")) continue;
317
- const fixed = fixRelativeNewURL(output.code);
317
+ const fixed = fixRelativeNewURL(output.code, viteConfig?.base);
318
318
  if (fixed !== output.code) output.code = fixed;
319
319
  }
320
320
  },
@@ -24,9 +24,11 @@ export function normalizeWebPath(path: string): string;
24
24
  export function ensureTrailingSlash(path: string): string;
25
25
  /**
26
26
  * @param {string} src
27
+ * @param {string} [base] - Vite base path (e.g. "/" or "/app/"). When provided,
28
+ * ext/ paths are made absolute so they resolve correctly under SPA routing.
27
29
  * @returns {string}
28
30
  */
29
- export function fixRelativeNewURL(src: string): string;
31
+ export function fixRelativeNewURL(src: string, base?: string): string;
30
32
  /**
31
33
  * @param {string} src
32
34
  * @returns {string}
@@ -113,25 +113,49 @@ export function ensureTrailingSlash(path) {
113
113
 
114
114
  /**
115
115
  * @param {string} src
116
+ * @param {string} [base] - Vite base path (e.g. "/" or "/app/"). When provided,
117
+ * ext/ paths are made absolute so they resolve correctly under SPA routing.
116
118
  * @returns {string}
117
119
  */
118
- export function fixRelativeNewURL(src) {
120
+ export function fixRelativeNewURL(src, base) {
121
+ /** @param {string} path */
122
+ function makeAbsolute(path) {
123
+ // Strip any leading ./ ../ or / prefix to get the clean ext/... path
124
+ const clean = path.replace(/^(?:\.\.?\/)+/, '').replace(/^\//, '');
125
+ if (base) return base.replace(/\/+$/, '') + '/' + clean;
126
+ return clean;
127
+ }
128
+
119
129
  src = src.replace(
120
130
  /(?<==\s*)(["'])((?:(?:\.{1,2}\/)|\/)?ext\/[^"']*\/)\1/g,
121
131
  (/** @type {string} */ _match, /** @type {string} */ quote, /** @type {string} */ path) => {
122
- const runtimePath = path.startsWith("/ext/") ? path.substring(1) : path;
123
- return `new URL(${quote}${runtimePath}${quote}, self.location?.href || ${quote}${quote}).href`;
132
+ const resolved = makeAbsolute(path);
133
+ return `new URL(${quote}${resolved}${quote}, self.location?.href || ${quote}${quote}).href`;
124
134
  }
125
135
  );
126
136
 
127
137
  src = src.replace(
128
138
  /new\s+URL\s*\(\s*(["'`])((?:(?:\.{1,2}\/)|\/)?ext\/[^"'`]+)\1\s*\)/g,
129
139
  (/** @type {string} */ _match, /** @type {string} */ quote, /** @type {string} */ path) => {
130
- const runtimePath = path.startsWith("/ext/") ? path.substring(1) : path;
131
- return `new URL(${quote}${runtimePath}${quote}, self.location?.href)`;
140
+ const resolved = makeAbsolute(path);
141
+ return `new URL(${quote}${resolved}${quote}, self.location?.href)`;
132
142
  }
133
143
  );
134
144
 
145
+ // Make remaining ext/ string literals absolute (e.g. font paths passed as
146
+ // function arguments like addVariant("normal","normal","ext/fonts/...")).
147
+ // The regexes above already consumed paths inside new URL() calls and
148
+ // assignment-based patterns, so this only catches leftover bare strings.
149
+ if (base) {
150
+ src = src.replace(
151
+ /(["'`])((?:\.{1,2}\/)?ext\/[^"'`]+)\1/g,
152
+ (/** @type {string} */ _match, /** @type {string} */ quote, /** @type {string} */ path) => {
153
+ const resolved = makeAbsolute(path);
154
+ return `${quote}${resolved}${quote}`;
155
+ }
156
+ );
157
+ }
158
+
135
159
  return src;
136
160
  }
137
161
 
@@ -7,6 +7,7 @@ import { existsSync, readFileSync, statSync } from 'fs';
7
7
  import { fileURLToPath } from 'url';
8
8
  import { needleLog } from './logging.js';
9
9
 
10
+ const pluginName = "needle-reload";
10
11
  const __filename = fileURLToPath(import.meta.url);
11
12
  const __dirname = path.dirname(__filename);
12
13
 
@@ -39,7 +40,7 @@ export function needleReload(_command, config, userSettings) {
39
40
  const buildDirectory = projectConfig?.buildDirectory?.length ? process.cwd().replaceAll("\\", "/") + "/" + projectConfig?.buildDirectory : "";
40
41
  if (buildDirectory?.length) {
41
42
  const relativeBuildDirectory = path.relative(process.cwd(), buildDirectory).replaceAll("\\", "/") || ".";
42
- setTimeout(() => needleLog("needle-reload", "Build directory: " + relativeBuildDirectory), 100);
43
+ setTimeout(() => needleLog(pluginName, "Build directory: " + relativeBuildDirectory), 100);
43
44
  }
44
45
 
45
46
  // These ignore patterns will be injected into user config to better control vite reloading
@@ -59,7 +60,7 @@ export function needleReload(_command, config, userSettings) {
59
60
  // @ts-ignore - watch.ignored is guaranteed to be string[] by the guards above
60
61
  config.server.watch.ignored.push(pattern);
61
62
  if (userSettings?.debug === true)
62
- setTimeout(() => needleLog("needle-reload", "Updated server ignore patterns: " + JSON.stringify(config.server?.watch?.ignored)), 100);
63
+ setTimeout(() => needleLog(pluginName, "Updated server ignore patterns: " + JSON.stringify(config.server?.watch?.ignored)), 100);
63
64
  },
64
65
  /** @param {import('vite').HmrContext & {buildDirectory?: string}} args */
65
66
  handleHotUpdate(args) {
@@ -118,7 +119,7 @@ function getHot(server) {
118
119
 
119
120
  /** @param {import('vite').ViteDevServer} server @param {string} [file] */
120
121
  function notifyClientWillReload(server, file) {
121
- console.log("Send reload notification");
122
+ needleLog(pluginName, "Send reload notification");
122
123
  getHot(server).send('needle:reload', { type: 'will-reload', file: file });
123
124
  }
124
125
 
@@ -134,7 +135,7 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
134
135
 
135
136
  // Dont reload the whole server when a file that is using hot reload changes
136
137
  if (filesUsingHotReload.has(file)) {
137
- console.log("File is using hot reload: " + file);
138
+ needleLog(pluginName, "File is using hot reload: " + file);
138
139
  return null;
139
140
  }
140
141
 
@@ -153,7 +154,7 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
153
154
  // instead of relying on the vite server watch ignore array
154
155
  // we could here also match paths that we know we dont want to track
155
156
  if (ignorePatterns.length > 0 && ignoreRegex.test(file)) {
156
- console.log("Ignore change in file: " + getFileNameLog(file));
157
+ needleLog(pluginName, "Ignore change in file: " + getFileNameLog(file));
157
158
  return [];
158
159
  }
159
160
 
@@ -163,7 +164,7 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
163
164
  if (buildDirectory?.length) {
164
165
  const dir = path.dirname(file).replaceAll("\\", "/");
165
166
  if (dir.startsWith(buildDirectory)) {
166
- console.log("Ignore change in build directory: " + getFileNameLog(file));
167
+ needleLog(pluginName, "Ignore change in build directory: " + getFileNameLog(file));
167
168
  return [];
168
169
  }
169
170
  }
@@ -178,13 +179,13 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
178
179
  return [];
179
180
  }
180
181
  if (await testIfFileContentChanged(file, read) === false) {
181
- console.log("File content didnt change: " + getFileNameLog(file));
182
+ needleLog(pluginName, "File content didnt change: " + getFileNameLog(file));
182
183
  return [];
183
184
  }
184
185
  }
185
186
 
186
187
  // these are known file types we export from integrations
187
- const knownExportFileTypes = [ ".glb", ".gltf", ".bin", "exr", ".ktx2", ".mp3", ".ogg", ".mp4", ".webm" ];
188
+ const knownExportFileTypes = [".glb", ".gltf", ".bin", "exr", ".ktx2", ".mp3", ".ogg", ".mp4", ".webm"];
188
189
  if (!knownExportFileTypes.some((type) => file.endsWith(type)))
189
190
  return null;
190
191
 
@@ -208,7 +209,7 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
208
209
  }
209
210
  }
210
211
 
211
- console.log("> Detected file change: ", getFileNameLog(file) + " (" + ((fileSize / (1024 * 1024)).toFixed(1)) + " MB)");
212
+ needleLog(pluginName, "> Detected file change: " + getFileNameLog(file) + " (" + ((fileSize / (1024 * 1024)).toFixed(1)) + " MB)");
212
213
  notifyClientWillReload(server);
213
214
  scheduleReload(server);
214
215
  return [];
@@ -223,8 +224,8 @@ async function scheduleReload(server, level = 0) {
223
224
  const lockFile = path.join(process.cwd(), lockFileName);
224
225
  if (existsSync(lockFile)) {
225
226
  if (level === 0)
226
- console.log("Lock file exists, waiting for export to finish...");
227
- setTimeout(() => scheduleReload(server, level += 1), 300);
227
+ needleLog(pluginName, "Lock file exists, waiting for export to finish...");
228
+ setTimeout(() => scheduleReload(server, level += 1), 300).unref();
228
229
  return;
229
230
  }
230
231
 
@@ -234,13 +235,13 @@ async function scheduleReload(server, level = 0) {
234
235
  if (timeDiff < 1000) {
235
236
  // Sometimes file changes happen immediately after triggering a reload
236
237
  // we dont want to reload again in that case
237
- console.log("Ignoring reload, last reload was too recent", timeDiff);
238
+ needleLog(pluginName, "Ignoring reload, last reload was too recent" + timeDiff + "ms ago");
238
239
  return;
239
240
  }
240
241
 
241
242
  lastReloadTime = Date.now();
242
243
  const readableTime = new Date(lastReloadTime).toLocaleTimeString();
243
- console.log("< Reloading... " + readableTime)
244
+ needleLog(pluginName, "< Reloading... " + readableTime);
244
245
  getHot(server).send({
245
246
  type: 'full-reload',
246
247
  path: '*'
@@ -299,10 +300,10 @@ function removeVersionQueryArgument(content) {
299
300
  function insertScriptRegisterHotReloadCode(src, filePath) {
300
301
 
301
302
  // We only want to inject the hot reload code in the needle-engine root file
302
- if(!filePath.includes("/src/needle-engine.ts")) {
303
+ if (!filePath.includes("/src/needle-engine.ts")) {
303
304
  return src;
304
305
  }
305
- console.log("[Needle HMR] Hot reload is enabled");
306
+ needleLog(pluginName, "[Needle HMR] Hot reload is enabled");
306
307
  // this code let's the engine know that we are in hot reload mode
307
308
  const code = `
308
309
  globalThis.NEEDLE_HOT_RELOAD_ENABLED = true;
@@ -338,12 +339,12 @@ function insertScriptHotReloadCode(src, filePath) {
338
339
  return undefined;
339
340
  // make import path from engine package
340
341
  const fullPathToHotReload = process.cwd() + "/node_modules/@needle-tools/engine/src/engine/engine_hot_reload.ts";
341
- // console.log(fullPathToHotReload);
342
+ // needleLog(pluginName, fullPathToHotReload);
342
343
  const fileDirectory = path.dirname(filePath);
343
- // console.log("DIR", fileDirectory)
344
+ // needleLog(pluginName, "DIR", fileDirectory)
344
345
  const relativePath = path.relative(fileDirectory, fullPathToHotReload);
345
346
  importPath = relativePath.replace(/\\/g, "/");
346
- // console.log("importPath: ", importPath);
347
+ // needleLog(pluginName, "importPath: ", importPath);
347
348
  }
348
349
 
349
350
  // console.log(importPath, ">", filePath);
@@ -60,7 +60,8 @@ export function needleServer(command, config, userSettings) {
60
60
  })
61
61
  .catch((err) => console.error("ERR: [needle:server] 'open' package not found - please make sure to install 'open' in your package.json\n", err));
62
62
  }
63
- }, 100)
63
+ }, 100);
64
+ i.unref();
64
65
  }
65
66
  },
66
67
  }