@needle-tools/engine 4.14.0 → 4.15.0-next.f391a30

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 (198) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/components.needle.json +1 -1
  3. package/dist/{gltf-progressive-BttGBXw6.umd.cjs → gltf-progressive-CMwJPwEt.umd.cjs} +1 -1
  4. package/dist/{gltf-progressive-Bm_6aEi4.js → gltf-progressive-CTlvpS3A.js} +1 -1
  5. package/dist/{gltf-progressive-T5WKTux5.min.js → gltf-progressive-DYL3SLVb.min.js} +1 -1
  6. package/dist/materialx-4jJLLe9Q.js +4174 -0
  7. package/dist/materialx-Bt9FHwco.min.js +158 -0
  8. package/dist/materialx-NDD0y4JY.umd.cjs +158 -0
  9. package/dist/{needle-engine.bundle-COL2Bar3.umd.cjs → needle-engine.bundle-C1BFRZDF.umd.cjs} +150 -140
  10. package/dist/{needle-engine.bundle-Z_gAD7Kg.js → needle-engine.bundle-DB4kLWO_.js} +6651 -6400
  11. package/dist/{needle-engine.bundle-NolzHLqO.min.js → needle-engine.bundle-DsTdfmeb.min.js} +151 -141
  12. package/dist/needle-engine.d.ts +345 -88
  13. package/dist/needle-engine.js +322 -322
  14. package/dist/needle-engine.min.js +1 -1
  15. package/dist/needle-engine.umd.cjs +1 -1
  16. package/dist/{postprocessing-06AXuvdv.min.js → postprocessing-BN-f4viE.min.js} +1 -1
  17. package/dist/{postprocessing-CPDcA21P.umd.cjs → postprocessing-DYmYOVm4.umd.cjs} +1 -1
  18. package/dist/{postprocessing-CI2x8Cln.js → postprocessing-De9ZpJrk.js} +1 -1
  19. package/dist/{three-examples-BMmNgNCN.umd.cjs → three-examples-BHqRVpO_.umd.cjs} +12 -12
  20. package/dist/{three-examples-CMYCd5nH.js → three-examples-C0ZCCA_K.js} +182 -192
  21. package/dist/{three-examples-CQl1fFZp.min.js → three-examples-DmTY8tGr.min.js} +14 -14
  22. package/lib/engine/api.d.ts +0 -2
  23. package/lib/engine/api.js +0 -2
  24. package/lib/engine/api.js.map +1 -1
  25. package/lib/engine/debug/debug.js +1 -1
  26. package/lib/engine/debug/debug.js.map +1 -1
  27. package/lib/engine/debug/debug_spatial_console.js +1 -1
  28. package/lib/engine/debug/debug_spatial_console.js.map +1 -1
  29. package/lib/engine/engine_accessibility.d.ts +77 -0
  30. package/lib/engine/engine_accessibility.js +162 -0
  31. package/lib/engine/engine_accessibility.js.map +1 -0
  32. package/lib/engine/engine_context.d.ts +2 -0
  33. package/lib/engine/engine_context.js +8 -1
  34. package/lib/engine/engine_context.js.map +1 -1
  35. package/lib/engine/engine_create_objects.js +1 -1
  36. package/lib/engine/engine_create_objects.js.map +1 -1
  37. package/lib/engine/engine_gizmos.js +1 -1
  38. package/lib/engine/engine_gizmos.js.map +1 -1
  39. package/lib/engine/engine_license.js +7 -2
  40. package/lib/engine/engine_license.js.map +1 -1
  41. package/lib/engine/engine_materialpropertyblock.d.ts +90 -4
  42. package/lib/engine/engine_materialpropertyblock.js +97 -7
  43. package/lib/engine/engine_materialpropertyblock.js.map +1 -1
  44. package/lib/engine/engine_math.d.ts +34 -1
  45. package/lib/engine/engine_math.js +34 -1
  46. package/lib/engine/engine_math.js.map +1 -1
  47. package/lib/engine/engine_networking.js +1 -1
  48. package/lib/engine/engine_networking.js.map +1 -1
  49. package/lib/engine/engine_types.d.ts +2 -0
  50. package/lib/engine/engine_types.js +2 -0
  51. package/lib/engine/engine_types.js.map +1 -1
  52. package/lib/engine/engine_utils.js +2 -2
  53. package/lib/engine/engine_utils.js.map +1 -1
  54. package/lib/engine/export/gltf/EXT_mesh_gpu_instancing_exporter.js.map +1 -0
  55. package/lib/engine/export/gltf/index.js +1 -1
  56. package/lib/engine/export/gltf/index.js.map +1 -1
  57. package/lib/engine/webcomponents/icons.js +3 -0
  58. package/lib/engine/webcomponents/icons.js.map +1 -1
  59. package/lib/engine/webcomponents/logo-element.d.ts +7 -3
  60. package/lib/engine/webcomponents/logo-element.js +21 -1
  61. package/lib/engine/webcomponents/logo-element.js.map +1 -1
  62. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
  63. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  64. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +10 -7
  65. package/lib/engine/webcomponents/needle menu/needle-menu.js +14 -4
  66. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  67. package/lib/engine/webcomponents/needle-button.d.ts +37 -11
  68. package/lib/engine/webcomponents/needle-button.js +42 -11
  69. package/lib/engine/webcomponents/needle-button.js.map +1 -1
  70. package/lib/engine/webcomponents/needle-engine.ar-overlay.js +10 -1
  71. package/lib/engine/webcomponents/needle-engine.ar-overlay.js.map +1 -1
  72. package/lib/engine/webcomponents/needle-engine.d.ts +13 -2
  73. package/lib/engine/webcomponents/needle-engine.js +23 -3
  74. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  75. package/lib/engine-components/Component.d.ts +1 -2
  76. package/lib/engine-components/Component.js +1 -3
  77. package/lib/engine-components/Component.js.map +1 -1
  78. package/lib/engine-components/DragControls.d.ts +1 -0
  79. package/lib/engine-components/DragControls.js +21 -0
  80. package/lib/engine-components/DragControls.js.map +1 -1
  81. package/lib/engine-components/NeedleMenu.d.ts +2 -0
  82. package/lib/engine-components/NeedleMenu.js +2 -0
  83. package/lib/engine-components/NeedleMenu.js.map +1 -1
  84. package/lib/engine-components/Networking.d.ts +28 -3
  85. package/lib/engine-components/Networking.js +28 -3
  86. package/lib/engine-components/Networking.js.map +1 -1
  87. package/lib/engine-components/ReflectionProbe.d.ts +25 -2
  88. package/lib/engine-components/ReflectionProbe.js +46 -2
  89. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  90. package/lib/engine-components/Skybox.js +4 -2
  91. package/lib/engine-components/Skybox.js.map +1 -1
  92. package/lib/engine-components/export/gltf/GltfExport.js +1 -1
  93. package/lib/engine-components/export/gltf/GltfExport.js.map +1 -1
  94. package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +2 -2
  95. package/lib/engine-components/export/usdz/USDZExporter.js +1 -1
  96. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  97. package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.d.ts +15 -0
  98. package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js +77 -0
  99. package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js.map +1 -1
  100. package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js +2 -2
  101. package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js.map +1 -1
  102. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
  103. package/lib/engine-components/ui/Button.d.ts +1 -0
  104. package/lib/engine-components/ui/Button.js +11 -0
  105. package/lib/engine-components/ui/Button.js.map +1 -1
  106. package/lib/engine-components/ui/Text.d.ts +1 -0
  107. package/lib/engine-components/ui/Text.js +11 -0
  108. package/lib/engine-components/ui/Text.js.map +1 -1
  109. package/package.json +18 -14
  110. package/plugins/common/buildinfo.js +46 -10
  111. package/plugins/common/files.js +2 -1
  112. package/plugins/common/license.js +144 -69
  113. package/plugins/common/logger.js +172 -11
  114. package/plugins/common/needle-engine-skill.md +175 -0
  115. package/plugins/common/worker.js +5 -4
  116. package/plugins/types/userconfig.d.ts +40 -2
  117. package/plugins/vite/ai.js +71 -0
  118. package/plugins/vite/alias.js +6 -5
  119. package/plugins/vite/asap.js +6 -5
  120. package/plugins/vite/build-pipeline.js +224 -41
  121. package/plugins/vite/buildinfo.js +66 -6
  122. package/plugins/vite/copyfiles.js +41 -12
  123. package/plugins/vite/custom-element-data.js +26 -16
  124. package/plugins/vite/defines.js +8 -5
  125. package/plugins/vite/dependencies.js +16 -10
  126. package/plugins/vite/dependency-watcher.js +35 -7
  127. package/plugins/vite/drop-client.js +7 -5
  128. package/plugins/vite/drop.js +16 -14
  129. package/plugins/vite/editor-connection.js +18 -16
  130. package/plugins/vite/imports-logger.js +12 -2
  131. package/plugins/vite/index.js +8 -3
  132. package/plugins/vite/local-files-analysis.js +789 -0
  133. package/plugins/vite/local-files-core.js +992 -0
  134. package/plugins/vite/local-files-internals.js +28 -0
  135. package/plugins/vite/local-files-types.d.ts +111 -0
  136. package/plugins/vite/local-files-utils.js +359 -0
  137. package/plugins/vite/local-files.js +2 -441
  138. package/plugins/vite/logger.client.js +45 -35
  139. package/plugins/vite/logger.js +6 -3
  140. package/plugins/vite/logging.js +129 -0
  141. package/plugins/vite/meta.js +18 -4
  142. package/plugins/vite/needle-app.js +4 -3
  143. package/plugins/vite/peer.js +2 -1
  144. package/plugins/vite/pwa.js +33 -17
  145. package/plugins/vite/reload.js +24 -2
  146. package/src/engine/api.ts +0 -3
  147. package/src/engine/debug/debug.ts +1 -1
  148. package/src/engine/debug/debug_spatial_console.ts +5 -1
  149. package/src/engine/engine_accessibility.ts +198 -0
  150. package/src/engine/engine_context.ts +10 -1
  151. package/src/engine/engine_create_objects.ts +1 -1
  152. package/src/engine/engine_gizmos.ts +9 -5
  153. package/src/engine/engine_license.ts +7 -2
  154. package/src/engine/engine_materialpropertyblock.ts +102 -11
  155. package/src/engine/engine_math.ts +34 -1
  156. package/src/engine/engine_networking.ts +1 -1
  157. package/src/engine/engine_types.ts +5 -0
  158. package/src/engine/engine_utils.ts +2 -2
  159. package/src/engine/export/gltf/index.ts +1 -1
  160. package/src/engine/webcomponents/icons.ts +3 -0
  161. package/src/engine/webcomponents/logo-element.ts +24 -4
  162. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +6 -2
  163. package/src/engine/webcomponents/needle menu/needle-menu.ts +23 -11
  164. package/src/engine/webcomponents/needle-button.ts +44 -13
  165. package/src/engine/webcomponents/needle-engine.ar-overlay.ts +13 -2
  166. package/src/engine/webcomponents/needle-engine.ts +31 -8
  167. package/src/engine-components/Component.ts +2 -5
  168. package/src/engine-components/DragControls.ts +29 -4
  169. package/src/engine-components/NeedleMenu.ts +5 -3
  170. package/src/engine-components/Networking.ts +29 -4
  171. package/src/engine-components/ReflectionProbe.ts +52 -9
  172. package/src/engine-components/Skybox.ts +4 -2
  173. package/src/engine-components/export/gltf/GltfExport.ts +1 -1
  174. package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +2 -2
  175. package/src/engine-components/export/usdz/USDZExporter.ts +1 -1
  176. package/src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +108 -32
  177. package/src/engine-components/export/usdz/extensions/behavior/PhysicsExtension.ts +2 -2
  178. package/src/engine-components/ui/Button.ts +12 -0
  179. package/src/engine-components/ui/Text.ts +13 -0
  180. package/dist/materialx-CJyQZtjt.min.js +0 -90
  181. package/dist/materialx-DMs1E08Z.js +0 -4636
  182. package/dist/materialx-DaKKOoVk.umd.cjs +0 -90
  183. package/lib/engine/engine_test_utils.d.ts +0 -39
  184. package/lib/engine/engine_test_utils.js +0 -84
  185. package/lib/engine/engine_test_utils.js.map +0 -1
  186. package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js.map +0 -1
  187. package/src/engine/engine_test_utils.ts +0 -109
  188. package/src/include/draco/draco_decoder.js +0 -34
  189. package/src/include/draco/draco_decoder.wasm +0 -0
  190. package/src/include/draco/draco_wasm_wrapper.js +0 -117
  191. package/src/include/ktx2/basis_transcoder.js +0 -19
  192. package/src/include/ktx2/basis_transcoder.wasm +0 -0
  193. package/src/include/needle/arial-msdf.json +0 -1472
  194. package/src/include/needle/arial.png +0 -0
  195. package/src/include/needle/poweredbyneedle.webp +0 -0
  196. /package/lib/{include/three → engine/export/gltf}/EXT_mesh_gpu_instancing_exporter.d.ts +0 -0
  197. /package/lib/{include/three → engine/export/gltf}/EXT_mesh_gpu_instancing_exporter.js +0 -0
  198. /package/src/{include/three → engine/export/gltf}/EXT_mesh_gpu_instancing_exporter.js +0 -0
@@ -1,15 +1,18 @@
1
+ // @ts-check
1
2
  import fs from 'fs';
2
3
  import path from 'path';
3
4
 
5
+ /** @typedef {{ version?: number, tags?: {name: string, [key: string]: unknown}[], valueSets?: {name: string, [key: string]: unknown}[], globalAttributes?: unknown[] }} CustomElementData */
6
+
4
7
  /** Known needle-engine tag names that should be updated from the source */
5
8
  const NEEDLE_TAG_NAMES = ['needle-engine', 'needle-menu', 'needle-button'];
6
9
 
7
10
  /**
8
11
  * Merges needle-engine custom element data into an existing custom-elements.json file.
9
12
  * Preserves user-defined tags while updating needle-engine specific tags.
10
- * @param {object} sourceData - The needle-engine custom-elements.json data
11
- * @param {object} targetData - The existing project custom-elements.json data
12
- * @returns {object} Merged data
13
+ * @param {CustomElementData} sourceData - The needle-engine custom-elements.json data
14
+ * @param {CustomElementData} targetData - The existing project custom-elements.json data
15
+ * @returns {CustomElementData} Merged data
13
16
  */
14
17
  function mergeCustomElementData(sourceData, targetData) {
15
18
  const merged = { ...targetData };
@@ -74,23 +77,30 @@ export const needleCustomElementData = (command, config, userSettings = {}) => {
74
77
 
75
78
  // Path to source custom-elements.json in node_modules
76
79
  const sourceFile = path.join(cwd, 'node_modules', '@needle-tools', 'engine', 'custom-elements.json');
77
- // Path to target custom-elements.json in project root
78
- const targetFile = path.join(cwd, 'custom-elements.json');
80
+ // Path to target custom-elements.json in project vs code directory
81
+ const targetFile = path.join(cwd, '.vscode', 'custom-elements.json');
79
82
 
80
83
  // Copy/merge custom-elements.json to project
81
84
  if (fs.existsSync(sourceFile)) {
82
85
  try {
83
- const sourceData = JSON.parse(fs.readFileSync(sourceFile, 'utf8'));
86
+ const sourceData = /** @type {CustomElementData} */ (JSON.parse(fs.readFileSync(sourceFile, 'utf8')));
84
87
 
85
- let targetData = {};
88
+ let targetData = /** @type {CustomElementData} */ ({});
86
89
  if (fs.existsSync(targetFile)) {
87
90
  // Merge with existing file to preserve user content
88
91
  try {
89
- targetData = JSON.parse(fs.readFileSync(targetFile, 'utf8'));
92
+ targetData = /** @type {CustomElementData} */ (JSON.parse(fs.readFileSync(targetFile, 'utf8')));
90
93
  } catch {
91
94
  targetData = {};
92
95
  }
93
96
  }
97
+ else {
98
+ // Ensure .vscode directory exists
99
+ const vscodeDir = path.dirname(targetFile);
100
+ if (!fs.existsSync(vscodeDir)) {
101
+ fs.mkdirSync(vscodeDir);
102
+ }
103
+ }
94
104
 
95
105
  const mergedData = mergeCustomElementData(sourceData, targetData);
96
106
  const newContent = JSON.stringify(mergedData, null, 2);
@@ -125,7 +135,7 @@ export const needleCustomElementData = (command, config, userSettings = {}) => {
125
135
  const full = path.join(cwd, f);
126
136
  try {
127
137
  const raw = fs.readFileSync(full, 'utf8');
128
- const data = JSON.parse(raw);
138
+ const data = /** @type {{settings?: {'html.customData'?: string[], [key: string]: unknown}}} */ (JSON.parse(raw));
129
139
 
130
140
  // Ensure settings.html.customData contains the local path
131
141
  data.settings = data.settings || {};
@@ -156,20 +166,20 @@ export const needleCustomElementData = (command, config, userSettings = {}) => {
156
166
  if (fs.existsSync(settingsFile)) {
157
167
  try {
158
168
  const rawSettings = fs.readFileSync(settingsFile, 'utf8');
159
- /** @type {Record<string, any>} */
169
+ /** @type {Record<string, unknown>} */
160
170
  const settings = JSON.parse(rawSettings) || {};
161
-
162
- settings['html.customData'] = settings['html.customData'] || [];
171
+ const htmlData = /** @type {string[]} */ (settings['html.customData'] || []);
172
+ settings['html.customData'] = htmlData;
163
173
 
164
174
  // Remove old node_modules path if present
165
- const oldIndex = settings['html.customData'].indexOf(oldNodeModulesPath);
175
+ const oldIndex = htmlData.indexOf(oldNodeModulesPath);
166
176
  if (oldIndex >= 0) {
167
- settings['html.customData'].splice(oldIndex, 1);
177
+ htmlData.splice(oldIndex, 1);
168
178
  }
169
179
 
170
180
  // Add local path if not present
171
- if (!settings['html.customData'].includes(localCustomDataPath)) {
172
- settings['html.customData'].push(localCustomDataPath);
181
+ if (!htmlData.includes(localCustomDataPath)) {
182
+ htmlData.push(localCustomDataPath);
173
183
 
174
184
  // Write back settings.json if changed
175
185
  const newRawSettings = JSON.stringify(settings, null, 2);
@@ -1,6 +1,7 @@
1
1
  import { loadConfig } from "./config.js";
2
2
  import { tryGetNeedleEngineVersion } from "../common/version.js";
3
3
  import { getPublicIdentifier as getPublicIdentifier } from "../common/license.js";
4
+ import { needleLog } from "./logging.js";
4
5
 
5
6
  // NOTE: ALL DEFINES MUST BE SET HERE! NEVER ADD OR RELY ON DEFINES IN ANY OTHER PLUGIN
6
7
 
@@ -11,6 +12,8 @@ import { getPublicIdentifier as getPublicIdentifier } from "../common/license.js
11
12
  // https://vitejs.dev/config/#using-environment-variables-in-config
12
13
 
13
14
  /**
15
+ * @param {string} command
16
+ * @param {{ generator?: string, useRapier?: boolean } | null | undefined} needleEngineConfig
14
17
  * @param {import('../types').userSettings} userSettings
15
18
  */
16
19
  export const needleDefines = (command, needleEngineConfig, userSettings) => {
@@ -28,11 +31,11 @@ export const needleDefines = (command, needleEngineConfig, userSettings) => {
28
31
  return {
29
32
  name: 'needle:defines',
30
33
  enforce: 'pre',
31
- async config(viteConfig) {
34
+ async config(/** @type {{ define?: Record<string, unknown> }} */ viteConfig) {
32
35
  // console.log("Update vite defines -------------------------------------------");
33
36
  if (!viteConfig.define) viteConfig.define = {};
34
37
  const version = tryGetNeedleEngineVersion();
35
- console.log("Needle Engine Version: " + version, needleEngineConfig?.generator ?? "(unknown generator)");
38
+ needleLog("needle-defines", "Needle Engine Version: " + version + " " + (needleEngineConfig?.generator ?? "(unknown generator)"));
36
39
  if (version)
37
40
  viteConfig.define.NEEDLE_ENGINE_VERSION = "\"" + version + "\"";
38
41
  if (needleEngineConfig)
@@ -57,11 +60,11 @@ export const needleDefines = (command, needleEngineConfig, userSettings) => {
57
60
  // this gives a timestamp containing the timezone
58
61
  viteConfig.define.NEEDLE_PROJECT_BUILD_TIME = "\"" + new Date().toString() + "\"";
59
62
 
60
- const projectId = undefined; // TODO: this needs to be exported by the integration (if any)
63
+ const projectId = /** @type {string | undefined} */ (undefined); // TODO: this needs to be exported by the integration (if any)
61
64
  const publicIdentifier = await getPublicIdentifier(projectId, {
62
65
  loglevel: userSettings?.debugLicense === true ? "verbose" : undefined,
63
- }).catch(err => {
64
- console.warn("Failed to get public identifier:", err.message);
66
+ }).catch((/** @type {{ message?: string }} */ err) => {
67
+ needleLog("needle-defines", "Failed to get public identifier: " + err.message, "warn");
65
68
  });
66
69
  if (publicIdentifier) {
67
70
  viteConfig.define.NEEDLE_PUBLIC_KEY = "\"" + publicIdentifier + "\"";
@@ -1,4 +1,5 @@
1
1
  import { tryGetNeedleEngineVersion, tryGetPackageVersion } from '../common/version.js';
2
+ import { needleLog } from './logging.js';
2
3
 
3
4
  /**
4
5
  * @type {string[]}
@@ -39,9 +40,10 @@ const excludeDependencies = [
39
40
  * @param {import('vite').UserConfig} config
40
41
  */
41
42
  function handleOptimizeDeps(config) {
43
+ const logLines = [];
42
44
  excludeDependencies.forEach(dep => {
43
45
  if (config.optimizeDeps?.include?.includes(dep)) {
44
- console.log(`[needle-dependencies] ${dep} is included in the optimizeDeps.include array. This may cause issues with the worker import.`);
46
+ logLines.push(`${dep} is included in the optimizeDeps.include array. This may cause issues with the worker import.`);
45
47
  }
46
48
  else {
47
49
  if (!config.optimizeDeps) {
@@ -54,7 +56,7 @@ function handleOptimizeDeps(config) {
54
56
  // This needs to be excluded from optimization because otherwise the worker import fails
55
57
  // three-mesh-bvh/src/workers/generateMeshBVH.worker.js?worker
56
58
  // same for gltf-progressive
57
- console.log(`[needle-dependencies] Adding ${dep} to the optimizeDeps.exclude array to support workers.`);
59
+ logLines.push(`Adding ${dep} to the optimizeDeps.exclude array to support workers.`);
58
60
  config.optimizeDeps.exclude.push(dep);
59
61
 
60
62
  if (!config.server) config.server = {};
@@ -65,12 +67,14 @@ function handleOptimizeDeps(config) {
65
67
  }
66
68
  }
67
69
  });
70
+ if (logLines.length) needleLog("needle-dependencies", logLines.join("\n"));
68
71
  }
69
72
 
70
73
  /**
71
74
  * @param {import('vite').UserConfig} config
72
75
  */
73
76
  function handleManualChunks(config) {
77
+ const logLines = [];
74
78
  if (!config.build) {
75
79
  config.build = {};
76
80
  }
@@ -85,7 +89,7 @@ function handleManualChunks(config) {
85
89
 
86
90
  if (Array.isArray(rollupOutput)) {
87
91
  // append the manualChunks function to the array
88
- console.log("[needle-dependencies] registering manualChunks");
92
+ logLines.push("registering manualChunks");
89
93
  rollupOutput.push({
90
94
  manualChunks: needleManualChunks
91
95
  })
@@ -96,37 +100,39 @@ function handleManualChunks(config) {
96
100
  if ("manualChunks" in rollupOutput) {
97
101
  allowManualChunks = false;
98
102
  // if the user has already defined manualChunks (even when set to undefined), we don't want to overwrite it
99
- console.log("[needle-dependencies] manualChunks already found in vite config - will not overwrite it");
103
+ logLines.push("manualChunks already found in vite config - will not overwrite it");
100
104
  }
101
105
  else if (rollupOutput.preserveModules === true) {
102
106
  allowManualChunks = false;
103
- console.log("[needle-dependencies] manualChunks can not be registered because preserveModules is true");
107
+ logLines.push("manualChunks can not be registered because preserveModules is true");
104
108
  }
105
109
  if (rollupOutput.inlineDynamicImports === true) {
106
110
  allowManualChunks = false;
107
- console.log("[needle-dependencies] manualChunks can not be registered because inlineDynamicImports is true");
111
+ logLines.push("manualChunks can not be registered because inlineDynamicImports is true");
108
112
  }
109
113
 
110
114
  if (allowManualChunks) {
111
- console.log("[needle-dependencies] registering manualChunks");
115
+ logLines.push("registering manualChunks");
112
116
  rollupOutput.manualChunks = needleManualChunks;
113
117
  }
114
118
 
115
119
  if (rollupOutput.chunkFileNames) {
116
- console.log("[needle-dependencies] chunkFileNames already defined");
120
+ logLines.push("chunkFileNames already defined");
117
121
  }
118
122
  else {
119
123
  rollupOutput.chunkFileNames = handleChunkFileNames;
120
124
  }
121
125
 
122
126
  if (rollupOutput.assetFileNames) {
123
- console.log("[needle-dependencies] assetFileNames already defined");
127
+ logLines.push("assetFileNames already defined");
124
128
  }
125
129
  else {
126
130
  rollupOutput.assetFileNames = assetFileNames;
127
131
  }
128
132
  }
129
133
 
134
+ if (logLines.length) needleLog("needle-dependencies", logLines.join("\n"));
135
+
130
136
  // TODO: this was a test if it allows us to remove the sync import of postprocessing due to n8ao's import
131
137
  // config.build.rollupOptions.external = (source, importer, isResolved) => {
132
138
  // if (importer?.includes("node_modules/n8ao/") || importer?.includes("node_modules/postprocessing/")) {
@@ -159,7 +165,7 @@ function handleManualChunks(config) {
159
165
  }
160
166
  }
161
167
  catch (e) {
162
- console.warn("[needle-dependencies] Error reading version", e);
168
+ needleLog("needle-dependencies", "Error reading version " + e, "warn");
163
169
  }
164
170
  }
165
171
  else if (chunk.name === 'three') {
@@ -1,13 +1,19 @@
1
+ // @ts-check
1
2
  import { exec, execSync } from 'child_process';
2
3
  import { existsSync, readFileSync, rmSync, statSync, writeFileSync } from 'fs';
3
4
  import path from 'path';
5
+ import { needleLog } from './logging.js';
4
6
 
5
- const prefix = "[needle-dependency-watcher] ";
7
+ /** @typedef {{dependencies?: Record<string, string>, devDependencies?: Record<string, string>}} PackageJson */
8
+
9
+ /** @param {...string} msg */
6
10
  function log(...msg) {
7
- console.log(prefix, ...msg)
11
+ needleLog("needle-dependency-watcher", msg.join(" "));
8
12
  }
9
13
 
10
14
  /**
15
+ * @param {string} command
16
+ * @param {unknown} config
11
17
  * @param {import('../types').userSettings} userSettings
12
18
  */
13
19
  export const needleDependencyWatcher = (command, config, userSettings) => {
@@ -19,17 +25,26 @@ export const needleDependencyWatcher = (command, config, userSettings) => {
19
25
  const packageJsonPath = path.join(dir, "package.json");
20
26
  const viteCacheDir = path.join(dir, "node_modules", ".vite");
21
27
 
22
- return {
28
+ return /** @type {import('vite').Plugin} */ ({
23
29
  name: 'needle-dependency-watcher',
30
+ /** @param {import('vite').ViteDevServer} server */
24
31
  configureServer(server) {
25
- watchPackageJson(server, dir, packageJsonPath, viteCacheDir);
26
32
  manageClients(server);
33
+ const startWatching = () => watchPackageJson(server, dir, packageJsonPath, viteCacheDir);
34
+ if (server.httpServer?.listening) {
35
+ startWatching();
36
+ }
37
+ else {
38
+ server.httpServer?.once("listening", startWatching);
39
+ }
27
40
  }
28
- }
41
+ });
29
42
  }
30
43
 
44
+ /** @type {Set<{send: (data: string) => void, on: (event: string, cb: () => void) => void}>} */
31
45
  const currentClients = new Set();
32
46
 
47
+ /** @param {import('vite').ViteDevServer} server */
33
48
  function manageClients(server) {
34
49
  server.ws.on("connection", (socket) => {
35
50
  currentClients.add(socket);
@@ -50,12 +65,22 @@ async function triggerReloadOnClients() {
50
65
  }
51
66
 
52
67
 
68
+ /** @type {import('fs').Stats | undefined} */
53
69
  let packageJsonStat;
70
+ /** @type {Date | undefined} */
54
71
  let lastEditTime;
72
+ /** @type {number | undefined} */
55
73
  let packageJsonSize;
74
+ /** @type {PackageJson | undefined} */
56
75
  let packageJson;
57
76
  let requireInstall = false;
58
77
 
78
+ /**
79
+ * @param {import('vite').ViteDevServer} server
80
+ * @param {string} projectDir
81
+ * @param {string} packageJsonPath
82
+ * @param {string} cachePath
83
+ */
59
84
  function watchPackageJson(server, projectDir, packageJsonPath, cachePath) {
60
85
 
61
86
  if (!existsSync(packageJsonPath)) {
@@ -68,6 +93,7 @@ function watchPackageJson(server, projectDir, packageJsonPath, cachePath) {
68
93
  packageJsonStat = statSync(packageJsonPath);
69
94
  lastEditTime = packageJsonStat.mtime;
70
95
  packageJsonSize = packageJsonStat.size;
96
+ /** @type {PackageJson} */
71
97
  packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
72
98
 
73
99
  setTimeout(() => {
@@ -91,7 +117,7 @@ function watchPackageJson(server, projectDir, packageJsonPath, cachePath) {
91
117
  }
92
118
 
93
119
  // test if dependencies changed
94
- let newPackageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
120
+ let newPackageJson = /** @type {PackageJson} */ (JSON.parse(readFileSync(packageJsonPath, "utf8")));
95
121
  if (newPackageJson.dependencies) {
96
122
  for (const key in newPackageJson.dependencies) {
97
123
  if (packageJson.dependencies[key] !== newPackageJson.dependencies[key] && newPackageJson.dependencies[key] !== undefined) {
@@ -125,6 +151,7 @@ function watchPackageJson(server, projectDir, packageJsonPath, cachePath) {
125
151
  }, 2000);
126
152
  }
127
153
 
154
+ /** @param {string} projectDir @param {PackageJson | undefined} packageJson @returns {boolean} */
128
155
  function testIfInstallIsRequired(projectDir, packageJson) {
129
156
  if (packageJson.dependencies) {
130
157
  for (const key in packageJson.dependencies) {
@@ -195,6 +222,7 @@ let isRunningRestart = false;
195
222
  let restartId = 0;
196
223
  let lastRestartTime = 0;
197
224
 
225
+ /** @param {import('vite').ViteDevServer} server @param {string} projectDir @param {string} cachePath */
198
226
  async function restart(server, projectDir, cachePath) {
199
227
 
200
228
  if (isRunningRestart) return;
@@ -233,7 +261,7 @@ async function restart(server, projectDir, cachePath) {
233
261
  server.restart();
234
262
  }
235
263
  isRunningRestart = false;
236
- console.log("-----------------------------------------------")
264
+ needleLog("needle-dependency-watcher", "-----------------------------------------------");
237
265
  }
238
266
  catch (err) {
239
267
  log("Error restarting server", err);
@@ -6,8 +6,8 @@ import { Context, destroy, loadSync } from "@needle-tools/engine"
6
6
 
7
7
  if (import.meta?.hot) {
8
8
 
9
- const previouslyLoaded = [];
10
- import.meta.hot.on("needle-editor:exported-file", async msg => {
9
+ const previouslyLoaded = /** @type {unknown[]} */ ([]);
10
+ import.meta.hot.on("needle-editor:exported-file", async (/** @type {{ path: string }} */ msg) => {
11
11
  try {
12
12
  console.log(msg);
13
13
  const ctx = Context.Current;
@@ -21,11 +21,12 @@ if (import.meta?.hot) {
21
21
  console.log(glb);
22
22
  ctx.scene.add(glb.scene);
23
23
  }
24
- catch (err) {
24
+ catch (/** @type {unknown} */ err) {
25
25
  console.error(err);
26
26
  }
27
27
  })
28
28
 
29
+ /** @param {unknown} target */
29
30
  function isNeedleCanvas(target) {
30
31
  if (target instanceof HTMLCanvasElement) {
31
32
  return true
@@ -45,8 +46,9 @@ if (import.meta?.hot) {
45
46
 
46
47
  window.addEventListener('drop', (e) => {
47
48
  if (!isNeedleCanvas(e.target)) return;
49
+ if (!e.dataTransfer) return;
48
50
 
49
- for (const file of e.dataTransfer.files) {
51
+ for (const file of /** @type {Iterable<File>} */ (e.dataTransfer.files)) {
50
52
  if (file.name.endsWith(".prefab") ||
51
53
  file.name.endsWith(".fbx") ||
52
54
  file.name.endsWith(".gltf") ||
@@ -60,7 +62,7 @@ if (import.meta?.hot) {
60
62
  name: file.name,
61
63
  size: file.size,
62
64
  lastModified: file.lastModified,
63
- location: undefined
65
+ location: /** @type {{ x: number, y: number, z: number } | undefined} */ (undefined)
64
66
  };
65
67
 
66
68
  const hits = Context.Current?.physics.raycast();
@@ -8,6 +8,8 @@ const __dirname = path.dirname(__filename);
8
8
 
9
9
  /** experimental, allow dropping files from Unity into the running scene */
10
10
  /**
11
+ * @param {string} command
12
+ * @param {import('../types/needleConfig').needleMeta | null | undefined} config
11
13
  * @param {import('../types/userconfig.js').userSettings} userSettings
12
14
  */
13
15
  export const needleDrop = (command, config, userSettings) => {
@@ -17,16 +19,16 @@ export const needleDrop = (command, config, userSettings) => {
17
19
 
18
20
  return {
19
21
  name: "needle:drop",
20
- config(config) {
22
+ config(/** @type {{ server?: { hmr?: { port?: number } } }} */ viteConfig) {
21
23
  if(userSettings)
22
- if (!config.server) config.server = {};
23
- if (!config.server.hmr) config.server.hmr = {};
24
- config.server.hmr.port = 8080;
25
- setTimeout(() => console.log("Update HMR port to " + config.server.hmr.port));
24
+ if (!viteConfig.server) viteConfig.server = {};
25
+ if (!viteConfig.server.hmr) viteConfig.server.hmr = {};
26
+ viteConfig.server.hmr.port = 8080;
27
+ setTimeout(() => console.log("Update HMR port to " + viteConfig.server?.hmr?.port));
26
28
  },
27
29
  transformIndexHtml: {
28
30
  order: 'pre',
29
- handler(html, _) {
31
+ handler(/** @type {string} */ html, /** @type {unknown} */ _) {
30
32
  const file = path.join(__dirname, 'drop-client.js');
31
33
  return [
32
34
  {
@@ -40,28 +42,28 @@ export const needleDrop = (command, config, userSettings) => {
40
42
  ];
41
43
  },
42
44
  },
43
- configureServer(server) {
45
+ configureServer(/** @type {{ ws: { on(event: string, cb: (...args: unknown[]) => void): void, send(type: string, data?: unknown): void } }} */ server) {
44
46
 
45
- server.ws.on('needle:drop-file', async (data, client) => {
46
- server.ws.send({ type: 'needle-editor:drop-file', data: data });
47
+ server.ws.on('needle:drop-file', async (/** @type {unknown} */ data, /** @type {unknown} */ client) => {
48
+ server.ws.send('needle-editor:drop-file', data);
47
49
  });
48
50
  // TODO: not sure how we can receive it with the normal vite server
49
51
  // server.ws.on("custom", (data, client) => {
50
52
  // console.log(data);
51
53
  // })
52
54
 
53
- server.ws.on('connection', (socket, request) => {
54
- socket.on('message', async (bytes) => {
55
+ server.ws.on('connection', (/** @type {{ on(event: string, cb: (...args: unknown[]) => void): void }} */ socket, /** @type {unknown} */ request) => {
56
+ socket.on('message', async (/** @type {Buffer | string} */ bytes) => {
55
57
  try {
56
- const message = Buffer.from(bytes).toString();
58
+ const message = Buffer.from(/** @type {ArrayBuffer} */ (bytes)).toString();
57
59
  if (message && message.startsWith("{")) {
58
- const obj = JSON.parse(message);
60
+ const obj = /** @type {{ type: string, data: unknown }} */ (JSON.parse(message));
59
61
  if (obj.type === "needle-editor:exported-file") {
60
62
  server.ws.send(obj.type, obj.data);
61
63
  }
62
64
  }
63
65
  }
64
- catch (e) {
66
+ catch (/** @type {{ message?: string }} */ e) {
65
67
  console.error(e.message);
66
68
  }
67
69
  });
@@ -1,4 +1,5 @@
1
1
  import { existsSync } from "fs";
2
+ import { needleLog } from "./logging.js";
2
3
 
3
4
  const root = process.cwd();
4
5
 
@@ -13,7 +14,7 @@ const editorSyncPackageName = "@needle-tools/editor-sync"
13
14
  let editorSyncEnabled = false;
14
15
 
15
16
  /**
16
- * @param {import('../types').userSettings} userSettings
17
+ * @type {(command: string, config: { generator?: string | null, needleEditor?: { enabled?: boolean } | string | null, dontInstallEditor?: boolean }, userSettings: { dontInstallEditor?: boolean }, pluginsArray: unknown[]) => Promise<import('vite').Plugin | undefined>}
17
18
  */
18
19
  export const editorConnection = async (command, config, userSettings, pluginsArray) => {
19
20
  if (command === "build") return;
@@ -22,7 +23,7 @@ export const editorConnection = async (command, config, userSettings, pluginsArr
22
23
  if (typeof config.generator === "string" && !config.generator.includes("Unity")) return;
23
24
 
24
25
  if (!config) {
25
- setTimeout(() => console.log("Needle Editor Sync can not be installed automatically to vite: missing config"), 1000);
26
+ setTimeout(() => needleLog("needle-editor-sync", "Needle Editor Sync can not be installed automatically to vite: missing config", "warn"), 1000);
26
27
  return createPlugin(false);
27
28
  }
28
29
 
@@ -37,29 +38,31 @@ export const editorConnection = async (command, config, userSettings, pluginsArr
37
38
  // }
38
39
  // }
39
40
  if (needleEditorSettings && needleEditorSettings.enabled === false) {
40
- setTimeout(() => console.log("Needle Editor Sync is not enabled. Add a 'Needle Editor Sync' component to your scene to enable"), 1000);
41
+ setTimeout(() => needleLog("needle-editor-sync", "Needle Editor Sync is not enabled. Add a 'Needle Editor Sync' component to your scene to enable", "warn"), 1000);
41
42
  return createPlugin(false);
42
43
  }
43
44
 
44
45
  // Check if the editor package is installed
45
46
  let path = root + `/node_modules/${editorSyncPackageName}/plugins/index.js`;
46
47
  if (existsSync(path) === false) {
47
- setTimeout(() => console.log(`> ${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`), 1000);
48
+ 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);
48
49
  return createPlugin(false);
49
50
  }
50
51
 
51
52
 
52
53
  // Load vite plugin
53
54
  if (!path.startsWith("file:")) path = "file:" + path;
54
- const { needleEditor } = await import(path);
55
- setTimeout(() => console.log("Automatically installed Needle Editor Sync"), 500)
55
+ const { needleEditor } = /** @type {{ needleEditor: () => Record<string, unknown> }} */ (await import(path));
56
+ setTimeout(() => needleLog("needle-editor-sync", "Automatically installed Needle Editor Sync"), 500)
56
57
  const method = needleEditor();
57
- pluginsArray.push(method);
58
+ const typedPluginsArray = /** @type {Array<Record<string, unknown>>} */ (pluginsArray);
59
+ typedPluginsArray.push(method);
58
60
  return createPlugin(true);
59
61
  }
60
62
 
63
+ /** @param {boolean} isInstalled */
61
64
  function createPlugin(isInstalled) {
62
- return {
65
+ return /** @type {import('vite').Plugin} */ ({
63
66
  name: "needle-editor-connection",
64
67
  // Setup HMR port for connecting to the editor
65
68
  config(config) {
@@ -67,12 +70,12 @@ function createPlugin(isInstalled) {
67
70
  if (!config.server) config.server = {};
68
71
  if (!config.server.hmr) config.server.hmr = {};
69
72
  if (config.server.hmr === false) {
70
- setTimeout(() => console.log("[needle-editor-sync] HMR is disabled, not initializing Needle Editor"));
73
+ setTimeout(() => needleLog("needle-editor-sync", "HMR is disabled, not initializing Needle Editor", "warn"));
71
74
  return;
72
75
  }
73
76
  if (config.server.hmr.port === undefined) {
74
77
  config.server.hmr.port = 1107;
75
- setTimeout(() => console.log("[needle-editor-sync] Update HMR port to " + config.server.hmr.port));
78
+ setTimeout(() => needleLog("needle-editor-sync", "Update HMR port to " + config.server.hmr.port));
76
79
  }
77
80
  }
78
81
 
@@ -94,7 +97,7 @@ function createPlugin(isInstalled) {
94
97
  if (bytes?.length < 50) {
95
98
  const message = Buffer.from(bytes).toString();
96
99
  if (message === "needle:editor:restart") {
97
- console.log("Received request for a soft restart of the vite server... ")
100
+ needleLog("needle-editor-sync", "Received request for a soft restart of the vite server...")
98
101
  // This just restarts the vite server
99
102
  server.restart();
100
103
  }
@@ -105,7 +108,7 @@ function createPlugin(isInstalled) {
105
108
  socket.send(JSON.stringify({ type: "pong" }));
106
109
  }
107
110
  else if (message === "needle:editor:editor-sync-enabled") {
108
- console.log("Editor sync enabled")
111
+ needleLog("needle-editor-sync", "Editor sync enabled")
109
112
  editorSyncEnabled = true;
110
113
  }
111
114
  else if (message === "needle:editor:editor-sync-disabled") {
@@ -115,11 +118,10 @@ function createPlugin(isInstalled) {
115
118
  })
116
119
  });
117
120
  }
118
- catch(err){
119
- console.error("Error in needle-editor-connection")
121
+ catch(/** @type {unknown} */ err){
122
+ needleLog("needle-editor-sync", "Error in needle-editor-connection", "error")
120
123
  console.error(err)
121
124
  }
122
125
  }
123
-
124
- }
126
+ })
125
127
  }
@@ -1,14 +1,20 @@
1
+ // @ts-check
1
2
  import path from 'path';
2
3
  import fs from 'fs';
3
4
 
5
+ /** @typedef {{ id: string, imports: GraphNode[], importedBy: GraphNode[] }} GraphNode */
6
+
4
7
  /**
8
+ * @param {string} command
9
+ * @param {unknown} config
5
10
  * @param {import('../types').userSettings} userSettings
6
11
  */
7
12
  export const needleImportsLogger = (command, config, userSettings) => {
8
13
 
9
14
  if (!userSettings.debugImportChains) return;
10
15
 
11
- const graph = {
16
+ /** @type {{allNodes: Map<string, GraphNode>, graph: Record<string, unknown>}} */
17
+ const graph = {
12
18
  allNodes: new Map(),
13
19
  graph: {},
14
20
  };
@@ -21,6 +27,7 @@ export const needleImportsLogger = (command, config, userSettings) => {
21
27
  return {
22
28
  name: 'needle:imports-logger',
23
29
  enforce: 'pre',
30
+ /** @param {string} id @param {string | undefined} importer */
24
31
  resolveId(id, importer) {
25
32
 
26
33
  // we want to make a graph of all the imports
@@ -57,6 +64,7 @@ export const needleImportsLogger = (command, config, userSettings) => {
57
64
 
58
65
  return;
59
66
  },
67
+ /** @param {Error | undefined} [error] */
60
68
  buildEnd(error) {
61
69
  try {
62
70
  // create log file and append lines to it
@@ -64,6 +72,7 @@ export const needleImportsLogger = (command, config, userSettings) => {
64
72
  // append a single line efficiently; replace if necessary
65
73
  const fd = fs.openSync(logFile, "w");
66
74
 
75
+ /** @param {string} str */
67
76
  const write = (str) => {
68
77
  if (logToConsole)
69
78
  console.log(str);
@@ -76,7 +85,8 @@ export const needleImportsLogger = (command, config, userSettings) => {
76
85
  }
77
86
 
78
87
  // log graph
79
- const loggedNodes = new Set();
88
+ const loggedNodes = /** @type {Set<string>} */ (new Set());
89
+ /** @param {GraphNode} node @param {number} depth @param {0|1|2} type */
80
90
  const logNode = (node, depth, type) => {
81
91
  if (!showOneLevelOfImportsThatWereAlreadyLogged && loggedNodes.has(node.id))
82
92
  return;