@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,441 +1,2 @@
1
- import https from 'https';
2
- import { createHash } from 'crypto';
3
- import { existsSync, mkdirSync, writeFileSync } from 'fs';
4
- import { resolve } from 'path';
5
- import { start } from 'repl';
6
-
7
- /**
8
- * @typedef {{pluginContext:import('rollup').TransformPluginContext, cache:Cache, command:string, viteConfig:import("vite").ResolvedConfig | null}} Context
9
- */
10
-
11
- const debug = false;
12
-
13
- /**
14
- * Checks if the local files plugin is enabled in user settings.
15
- * @param {import('../types/userconfig.js').userSettings} userSettings - The user settings object
16
- */
17
- export const makeFilesLocalIsEnabled = (userSettings) => {
18
- if (typeof userSettings?.makeFilesLocal === "object") return userSettings?.makeFilesLocal?.enabled === true;
19
- return userSettings?.makeFilesLocal === true;
20
- }
21
-
22
- /**
23
- * Download files and rewrite code
24
- * @param {string} command - The command that is being run
25
- * @param {object} config - The config object
26
- * @param {import('../types/userconfig.js').userSettings} userSettings
27
- * @returns {import('vite').Plugin | null}
28
- */
29
- export const needleMakeFilesLocal = (command, config, userSettings) => {
30
-
31
- if (!makeFilesLocalIsEnabled(userSettings)) {
32
- return null;
33
- }
34
-
35
- console.log(`[needle:local-files] Local files plugin is enabled`);
36
-
37
- const cache = new Cache();
38
-
39
- /** @type {import("vite").ResolvedConfig | null} */
40
- let viteConfig = null;
41
-
42
- /** @type {import("vite").Plugin} */
43
- const plugin = {
44
- name: "needle:local-files",
45
- // enforce: 'pre', // explictly DON'T define enforce:pre because of svelte postcss compat
46
- apply: "build",
47
- configResolved(config) {
48
- viteConfig = config;
49
- },
50
- // transform bundle
51
- async transform(src, _id) {
52
- src = await makeLocal(src, "ext/", "", {
53
- pluginContext: this,
54
- cache: cache,
55
- command: command,
56
- viteConfig: viteConfig,
57
- });
58
- return {
59
- code: src,
60
- map: null,
61
- };
62
- },
63
- buildEnd() {
64
- const map = cache.map;
65
- console.log(""); // Make a new line for better readability
66
- console.log(`[needle:local-files] Made ${map.size} files local:`);
67
- for (const [key, value] of map.entries()) {
68
- console.log(`- ${key} → ${value}`);
69
- }
70
- }
71
- }
72
- return plugin;
73
- }
74
-
75
- /**
76
- * Rewrites the source code to make local files
77
- * @param {string} src - The source code to rewrite
78
- * @param {string} basePath - The base path where the files will be saved
79
- * @param {string} currentDir - The current directory of the file being processed
80
- * @param {Context} context - The Vite plugin context and command
81
- */
82
- async function makeLocal(src, basePath, currentDir, context) {
83
-
84
- const command = context.command;
85
-
86
- if (debug) {
87
- // Find all urls in the source code.
88
- // Exclude URLs inside comments, like:
89
- // - // https://example.com
90
- // - /* ... https://example.com ... */
91
- // - @link https://example.com
92
- // - * ... https://example.com
93
- const urlRegexExcludingComments = /(?<!\/\/.*)(?<!\/\*.*)(?<!@link\s+)(["'])(https?:\/\/[^\s'"]+?)\1/g;
94
- let match0;
95
- while ((match0 = urlRegexExcludingComments.exec(src)) !== null) {
96
- const url = match0[2];
97
- if (debug) console.log(`\nFound URL: ${url} in ${currentDir}`);
98
- }
99
- }
100
-
101
- // Google Fonts URLs
102
- while (true) {
103
- const match = /["'](https:\/\/fonts\.googleapis\.com\/.+?)["']/g.exec(src);
104
- if (match === null) {
105
- break;
106
- }
107
- const url = match[1];
108
- if (debug) console.log(`\nFound google font URL: ${url}`);
109
- // Check if the font URL is already in the cache
110
- const cachedPath = context.cache.getFromCache(url);
111
- if (cachedPath) {
112
- if (debug) console.log(`Using cached font URL: ${cachedPath}`);
113
- src = src.replace(url, cachedPath);
114
- continue; // Skip downloading if already cached
115
- }
116
- let font = await downloadText(url);
117
- const familyNameMatch = /family=([^&]+)/.exec(url);
118
- const familyName = familyNameMatch ? getValidFilename(familyNameMatch[1], font) : (new URL(url).pathname.split('/').pop());
119
- font = await makeLocal(font, basePath, basePath, context);
120
- const fontFileName = `font-${familyName}.css`;
121
- const outputPath = basePath + fontFileName;
122
- let newPath;
123
- if (command === 'build') {
124
- const referenceId = context.pluginContext.emitFile({
125
- type: 'asset',
126
- fileName: outputPath,
127
- source: font,
128
- });
129
- const localPath = `${context.pluginContext.getFileName(referenceId)}`;
130
- newPath = getRelativeToBasePath(localPath, currentDir);
131
- // ensureFileExists(localPath, font);
132
- }
133
- else {
134
- // Create base64 URL for dev mode
135
- const base64Font = Buffer.from(font).toString('base64');
136
- newPath = `data:text/css;base64,${base64Font}`;
137
- }
138
- if (newPath) {
139
- context.cache.addToCache(url, newPath);
140
- src = src.replace(url, newPath);
141
- }
142
- }
143
-
144
- // Google Fonts gstatic URLs
145
- while (true) {
146
- const match = /["'(](https:\/\/fonts\.gstatic\.com\/)(.+?)["')]/g.exec(src);
147
- if (match === null) {
148
- break;
149
- }
150
- const fontPath = match[2];
151
- const url = match[1] + fontPath;
152
- if (debug) console.log(`\nFound gstatic URL: ${url}`);
153
- // Check if the font URL is already in the cache
154
- const cachedPath = context.cache.getFromCache(url);
155
- if (cachedPath) {
156
- if (debug) console.log(`Using cached gstatic font URL: ${cachedPath}`);
157
- src = src.replace(url, cachedPath);
158
- continue; // Skip downloading if already cached
159
- }
160
- const font = await downloadBinary(url);
161
- const filename = getValidFilename(fontPath, font);
162
- if (debug) console.log(`Saving font to: ${basePath + filename}`);
163
- let newPath;
164
- if (command === 'build') {
165
- const referenceId = context.pluginContext.emitFile({
166
- type: 'asset',
167
- fileName: basePath + filename,
168
- source: font,
169
- });
170
- const localPath = `${context.pluginContext.getFileName(referenceId)}`;
171
- newPath = getRelativeToBasePath(localPath, currentDir);
172
- // ensureFileExists(localPath, font);
173
- } else {
174
- // Create base64 URL for dev mode
175
- const base64Font = Buffer.from(font).toString('base64');
176
- newPath = `data:text/css;base64,${base64Font}`;
177
- }
178
- context.cache.addToCache(url, newPath);
179
- src = src.replace(url, newPath);
180
- }
181
-
182
- // Load QRCode.js
183
- while (true) {
184
- // https://cdn.jsdelivr.net/gh/davidshimjs/qrcodejs@gh-pages/qrcode.min.js
185
- const match = /["'](https:\/\/cdn\.jsdelivr\.net\/gh\/davidshimjs\/qrcodejs@[^'"]+?\/qrcode\.min\.js)["']/g.exec(src);
186
- if (match === null) {
187
- break;
188
- }
189
- const url = match[1];
190
- if (debug) console.log(`\nFound QR code URL: ${url}`);
191
- // Check if the QR code URL is already in the cache
192
- const cachedPath = context.cache.getFromCache(url);
193
- if (cachedPath) {
194
- if (debug) console.log(`Using cached QR code URL: ${cachedPath}`);
195
- src = src.replace(url, cachedPath);
196
- continue; // Skip downloading if already cached
197
- }
198
- const qrCode = await downloadBinary(url);
199
- const filename = getValidFilename(url, qrCode);
200
- if (debug) console.log(`Saving QR code to: ${basePath + filename}`);
201
- let newPath;
202
- if (command === 'build') {
203
- const referenceId = context.pluginContext.emitFile({
204
- type: 'asset',
205
- fileName: basePath + filename,
206
- source: qrCode,
207
- });
208
- const localPath = `${context.pluginContext.getFileName(referenceId)}`;
209
- newPath = getRelativeToBasePath(localPath, currentDir);
210
- // ensureFileExists(localPath, qrCode);
211
- } else {
212
- // create base64 URL for dev mode
213
- const base64QrCode = Buffer.from(qrCode).toString('base64');
214
- newPath = `data:application/javascript;base64,${base64QrCode}`;
215
- }
216
- context.cache.addToCache(url, newPath);
217
- src = src.replace(url, newPath);
218
- }
219
-
220
- // Polyhaven.org URLs
221
- let startIndex = 0;
222
- while (true) {
223
- const match = /["'](https:\/\/dl\.polyhaven\.org\/file\/.+?)["']/g.exec(src.slice(startIndex));
224
- if (match === null) {
225
- break;
226
- }
227
- startIndex += match.index + match[0].length; // Update startIndex to continue searching
228
- const url = match[1];
229
- if (url.endsWith("/")) {
230
- if (debug) console.warn(`Skipping Polyhaven URL that ends with a slash: ${url}`);
231
- continue; // Skip URLs that end with a slash
232
- }
233
- if (url.includes("\"") || url.includes("'")) {
234
- if (debug) console.warn(`Skipping Polyhaven URL with quotes: ${url}`);
235
- continue; // Skip URLs with quotes
236
- }
237
- if (debug) console.log(`\nFound Polyhaven URL: ${url}`);
238
- // Check if the Polyhaven URL is already in the cache
239
- const cachedPath = context.cache.getFromCache(url);
240
- if (cachedPath) {
241
- if (debug) console.log(`Using cached Polyhaven URL: ${cachedPath}`);
242
- src = src.replace(url, cachedPath);
243
- continue; // Skip downloading if already cached
244
- }
245
- const polyhavenFile = await downloadBinary(url);
246
- const filename = getValidFilename(url, polyhavenFile);
247
- if (debug) console.log(`Saving Polyhaven file to: ${basePath + filename}`);
248
- let newPath;
249
- if (command === 'build') {
250
- const referenceId = context.pluginContext.emitFile({
251
- type: 'asset',
252
- fileName: basePath + filename,
253
- source: polyhavenFile,
254
- });
255
- const localPath = `${context.pluginContext.getFileName(referenceId)}`;
256
- newPath = getRelativeToBasePath(localPath, currentDir);
257
- // ensureFileExists(localPath, polyhavenFile);
258
- } else {
259
- // Create base64 URL for dev mode
260
- const base64PolyhavenFile = Buffer.from(polyhavenFile).toString('base64');
261
- newPath = `data:application/octet-stream;base64,${base64PolyhavenFile}`;
262
- }
263
- if (newPath) {
264
- context.cache.addToCache(url, newPath);
265
- src = src.replace(url, newPath);
266
- }
267
- }
268
-
269
- return src;
270
-
271
- // /**
272
- // * Ensures that a file exists at the specified relative path with the given content.
273
- // * If the file does not exist, it will be created with the provided content.
274
- // * @param {string} relPath - The relative path to the file
275
- // * @param {string|Uint8Array} content - The content to write to the file
276
- // * @returns {void}
277
- // */
278
- // function ensureFileExists(relPath, content) {
279
- // const outputPath = context.viteConfig?.build?.outDir || "dist";
280
- // const fullPath = resolve(outputPath, relPath);
281
- // if (!existsSync(fullPath)) {
282
- // if (debug) console.log(`Creating file: ${fullPath}`);
283
- // const dir = resolve(fullPath, '..');
284
- // mkdirSync(dir, { recursive: true });
285
- // writeFileSync(fullPath, content);
286
- // }
287
- // }
288
- }
289
-
290
-
291
- class Cache {
292
- __cache = new Map();
293
- /**
294
- * Adds a key-value pair to the cache.
295
- * @param {string} key - The key to store the value under
296
- * @param {string|Uint8Array} value - The value to store in the cache
297
- * @returns {void}
298
- */
299
- addToCache(key, value) {
300
- if (this.__cache.has(key)) {
301
- if (debug) console.warn(`Key ${key} already exists in cache, overwriting.`);
302
- }
303
- this.__cache.set(key, value);
304
- }
305
- /**
306
- * Retrieves a value from the cache by its key.
307
- * @param {string} key - The key to look up in the cache
308
- */
309
- getFromCache(key) {
310
- if (this.__cache.has(key)) {
311
- return this.__cache.get(key);
312
- } else {
313
- return null;
314
- }
315
- }
316
- get map() {
317
- return this.__cache;
318
- }
319
- }
320
-
321
-
322
- /**
323
- * Returns a relative path based on the base path.
324
- * @param {string} path - The path to check
325
- * @param {string | undefined | null} basePath - The base path to compare against
326
- * @return {string} - The relative path if it starts with the base path, otherwise the original path
327
- */
328
- function getRelativeToBasePath(path, basePath) {
329
- if (basePath?.length && path.startsWith(basePath)) {
330
- return "./" + path.substring(basePath.length);
331
- }
332
- return path;
333
- }
334
-
335
-
336
- /**
337
- * Generates a valid filename from a given path.
338
- * @param {string} path - The path to generate a filename from
339
- * @param {string|Uint8Array} content - The content to hash for uniqueness (not used in this example)
340
- */
341
- function getValidFilename(path, content) {
342
- if (path.startsWith("http:") || path.startsWith("https:")) {
343
- const url = new URL(path);
344
- const pathParts = url.pathname.split('/');
345
- const filename = pathParts.pop() || 'file';
346
- const nameParts = filename.split('.');
347
- const nameWithoutExt = nameParts.slice(0, -1).join('.');
348
- path = `${nameWithoutExt}-${createContentMd5(url.host + pathParts.join('/'))}.${nameParts.pop() || 'unknown'}`;
349
- }
350
-
351
- // Remove any characters that are not valid in filenames
352
- let name = path.replace(/[^a-z0-9_\-\.\+]/gi, '-');
353
-
354
- const maxLength = 200;
355
- if (path.length > maxLength) {
356
- // If the name is too long, hash it to create a unique identifier
357
- const hash = createContentMd5(content);
358
- let ext = "";
359
- const extIndex = name.lastIndexOf('.');
360
- if (extIndex !== -1) {
361
- ext = name.substring(extIndex + 1);
362
- name = name.substring(0, extIndex);
363
- }
364
- name = `${name.substring(0, maxLength)}-${hash}${ext ? `.${ext}` : ''}`;
365
- }
366
- return name;
367
-
368
- }
369
-
370
- /**
371
- * Creates a hash of the content using MD5.
372
- * @param {string|Uint8Array} str - The content to hash
373
- */
374
- function createContentMd5(str) {
375
- return createHash('md5')
376
- .update(str)
377
- .digest('hex');
378
- }
379
-
380
-
381
- /**
382
- * @param {string} url - The URL of the font to download
383
- */
384
- function downloadText(url) {
385
- return new Promise(((res, rej) => {
386
- https.get(url, (response) => {
387
- if (response.statusCode !== 200) {
388
- console.log();
389
- console.error(`Failed to download (${response.statusCode}): ${url}`);
390
- rej(new Error(`Failed to download (${response.statusCode}): ${url}`));
391
- return;
392
- }
393
-
394
- console.log(""); // Make a new line for better readability
395
- console.log(`[needle:local-files] Make local: ${url}`);
396
-
397
- let data = '';
398
- response.on('data', (chunk) => {
399
- data += chunk;
400
- });
401
- response.on('end', () => {
402
- // Here you can save the data to a file or process it as needed
403
- if (debug) console.log(`Downloaded from ${url}`);
404
- res(data);
405
- });
406
- });
407
- }))
408
- }
409
-
410
- function downloadBinary(url) {
411
- return new Promise((res, rej) => {
412
- https.get(url, (response) => {
413
-
414
- // Handle redirects
415
- if (response.statusCode && response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
416
- if (debug) console.log(`Redirecting to ${response.headers.location}`);
417
- return downloadBinary(response.headers.location).then(res).catch(rej);
418
- }
419
-
420
- if (response.statusCode !== 200) {
421
- console.log();
422
- console.error(`Failed to download (${response.statusCode}): ${url}`);
423
- rej(new Error(`Failed to download (${response.statusCode}): ${url}`));
424
- return;
425
- }
426
-
427
- console.log(""); // Make a new line for better readability
428
- console.log(`[needle:local-files] Make local: ${url}`);
429
-
430
- const chunks = [];
431
- response.on('data', (chunk) => {
432
- chunks.push(chunk);
433
- });
434
- response.on('end', () => {
435
- // Here you can save the data to a file or process it as needed
436
- if (debug) console.log(`Downloaded from ${url}`);
437
- res(Buffer.concat(chunks));
438
- });
439
- });
440
- });
441
- }
1
+ export { needleMakeFilesLocal, makeFilesLocalIsEnabled } from './local-files-core.js';
2
+ export { needleLocalFilesSceneAnalysis } from './local-files-analysis.js';
@@ -1,3 +1,4 @@
1
+ // @ts-check
1
2
  import path from "path";
2
3
 
3
4
  let isStringifying = false;
@@ -6,7 +7,7 @@ let isStringifying = false;
6
7
  * Patches console methods to capture log messages and send them to the server.
7
8
  * This is useful for debugging and logging in the client.
8
9
  * @param {"log" | "warn" | "info" | "debug" | "error" | "internal"} level
9
- * @param {any} message - The log message to capture.
10
+ * @param {...unknown} message - The log message to capture.
10
11
  */
11
12
  function sendLogToServer(level, ...message) {
12
13
  if (isStringifying) return;
@@ -14,20 +15,20 @@ function sendLogToServer(level, ...message) {
14
15
  try {
15
16
  isStringifying = true;
16
17
  // console.time("sendLogToServer");
17
- message = stringifyLog(message);
18
+ let msg = /** @type {string} */ (stringifyLog(message));
18
19
  // console.timeEnd("sendLogToServer");
19
20
  // keep messages below payload limit
20
- if (message.length > 100_000) {
21
- message = message.slice(0, 100_000) + "... <truncated>";
21
+ if (msg.length > 100_000) {
22
+ msg = msg.slice(0, 100_000) + "... <truncated>";
22
23
  }
23
24
  // @ts-ignore
24
- import.meta.hot.send("needle:client-log", { level, message: message });
25
- } catch (e) {
25
+ import.meta.hot.send("needle:client-log", { level, message: msg });
26
+ } catch (/** @type {{ message?: string }} */ e) {
26
27
  // silently fail but send a message
27
28
  try {
28
29
  import.meta.hot.send("needle:client-log", { level: "error", message: `Error during logging: ${e.message}` });
29
30
  }
30
- catch (e2) {
31
+ catch (/** @type {unknown} */ e2) {
31
32
  // fallback failed as well
32
33
  }
33
34
  }
@@ -37,6 +38,7 @@ function sendLogToServer(level, ...message) {
37
38
  }
38
39
  }
39
40
 
41
+ /** @param {(...args: unknown[]) => void} fn @param {unknown[]} args */
40
42
  function logHelper(fn, args) {
41
43
  const error = new Error();
42
44
  const stack = error.stack;
@@ -52,32 +54,32 @@ function logHelper(fn, args) {
52
54
  if (import.meta && "hot" in import.meta) {
53
55
 
54
56
  function patchLogs() {
55
- const originalLog = console.log.bind(console);
56
- const originalWarn = console.warn.bind(console);
57
- const originalInfo = console.info.bind(console);
58
- const originalDebug = console.debug.bind(console);
59
- const originalError = console.error.bind(console);
57
+ const originalLog = /** @type {(...args: unknown[]) => void} */ (console.log.bind(console));
58
+ const originalWarn = /** @type {(...args: unknown[]) => void} */ (console.warn.bind(console));
59
+ const originalInfo = /** @type {(...args: unknown[]) => void} */ (console.info.bind(console));
60
+ const originalDebug = /** @type {(...args: unknown[]) => void} */ (console.debug.bind(console));
61
+ const originalError = /** @type {(...args: unknown[]) => void} */ (console.error.bind(console));
60
62
 
61
- console.log = function (...args) {
63
+ console.log = /** @type {(...args: unknown[]) => void} */ (function (...args) {
62
64
  logHelper(originalLog, args);
63
65
  sendLogToServer("log", ...args);
64
- }
65
- console.warn = (...args) => {
66
+ })
67
+ console.warn = /** @type {(...args: unknown[]) => void} */ ((...args) => {
66
68
  logHelper(originalWarn, args);
67
69
  sendLogToServer("warn", ...args);
68
- }
69
- console.info = (...args) => {
70
+ })
71
+ console.info = /** @type {(...args: unknown[]) => void} */ ((...args) => {
70
72
  logHelper(originalInfo, args);
71
73
  sendLogToServer("info", ...args);
72
- }
73
- console.debug = (...args) => {
74
+ })
75
+ console.debug = /** @type {(...args: unknown[]) => void} */ ((...args) => {
74
76
  logHelper(originalDebug, args);
75
77
  sendLogToServer("debug", ...args);
76
- }
77
- console.error = (...args) => {
78
+ })
79
+ console.error = /** @type {(...args: unknown[]) => void} */ ((...args) => {
78
80
  logHelper(originalError, args);
79
81
  sendLogToServer("error", ...args);
80
- }
82
+ })
81
83
  return () => {
82
84
  console.log = originalLog;
83
85
  console.warn = originalWarn;
@@ -125,11 +127,12 @@ Connection: ${"connection" in navigator ? JSON.stringify(navigator.connection) :
125
127
  User Activation: ${"userActivation" in navigator ? JSON.stringify(navigator.userActivation) : "Not available"}
126
128
  `);
127
129
 
130
+ /** @typedef {{ vendor?: string, architecture?: string, device?: string, description?: string, features?: unknown, limits?: unknown }} GPUAdapterInfoLike */
128
131
  if ("gpu" in navigator) {
129
132
  // @ts-ignore
130
133
  navigator.gpu.requestAdapter()
131
- .then(adapter => adapter ? adapter.requestDevice() : null)
132
- .then(device => {
134
+ .then(/** @type {(adapter: {requestDevice(): Promise<{adapterInfo: GPUAdapterInfoLike}>}|null) => Promise<{adapterInfo: GPUAdapterInfoLike}>|null} */ (adapter) => adapter ? adapter.requestDevice() : null)
135
+ .then(/** @type {(device: {adapterInfo: GPUAdapterInfoLike}|null) => void} */ (device) => {
133
136
  if (device) {
134
137
  const adapterInfo = device.adapterInfo;
135
138
  if (adapterInfo) {
@@ -146,17 +149,21 @@ User Activation: ${"userActivation" in navigator ? JSON.stringify(navigator.user
146
149
  });
147
150
  }
148
151
  }
149
- catch (e) {
152
+ catch (/** @type {{ message?: string }} */ e) {
150
153
  // silently fail
151
154
  sendLogToServer("error", `Error during initial log: ${e.message}`);
152
155
  }
153
156
 
154
157
  window.addEventListener('error', (event) => {
155
- const errorMessage = event.error ? event.error.stack || event.error.message : event.message;
158
+ const typedErrorEvent = /** @type {{ error: unknown, message: string }} */ (/** @type {unknown} */ (event));
159
+ const error = /** @type {{ stack?: string, message?: string } | null | undefined} */ (typedErrorEvent.error);
160
+ const errorMessage = error ? error.stack || error.message : typedErrorEvent.message;
156
161
  sendLogToServer("error", errorMessage);
157
162
  });
158
163
  window.addEventListener('unhandledrejection', (event) => {
159
- const reason = event.reason ? event.reason.stack || event.reason.message : "Unhandled rejection without reason";
164
+ const typedRejEvent = /** @type {{ reason: unknown }} */ (/** @type {unknown} */ (event));
165
+ const rejectionReason = /** @type {{ stack?: string, message?: string } | null | undefined} */ (typedRejEvent.reason);
166
+ const reason = rejectionReason ? rejectionReason.stack || rejectionReason.message : "Unhandled rejection without reason";
160
167
  sendLogToServer("error", `Unhandled promise rejection: ${reason}`);
161
168
  });
162
169
  window.addEventListener('beforeunload', () => {
@@ -211,7 +218,7 @@ User Activation: ${"userActivation" in navigator ? JSON.stringify(navigator.user
211
218
  sendLogToServer("internal", `URL hash changed to ${location.hash}`);
212
219
  });
213
220
  window.addEventListener('popstate', () => {
214
- sendLogToServer("internal", `History state changed: ${JSON.stringify(history.state)}`);
221
+ sendLogToServer("internal", `History state changed: ${JSON.stringify(/** @type {{ state: unknown }} */ (history).state)}`);
215
222
  });
216
223
 
217
224
 
@@ -227,10 +234,10 @@ User Activation: ${"userActivation" in navigator ? JSON.stringify(navigator.user
227
234
 
228
235
  /**
229
236
  * Stringifies a log message, handling circular references and formatting.
230
- * @param {any} log
231
- * @param {Set<any>} [seen]
237
+ * @param {unknown} log
238
+ * @param {Set<unknown>} [seen]
232
239
  */
233
- function stringifyLog(log, seen = new Set(), depth = 0) {
240
+ function stringifyLog(log, seen = /** @type {Set<unknown>} */ (new Set()), depth = 0) {
234
241
  const isServer = typeof window === "undefined";
235
242
  const stringify_limits = {
236
243
  string: isServer ? 100_000 : 1_000,
@@ -272,8 +279,9 @@ function stringifyLog(log, seen = new Set(), depth = 0) {
272
279
  || log instanceof BigUint64Array
273
280
  || log instanceof Float64Array
274
281
  ) {
275
- seen.add(log);
276
- return stringifyArray(log);
282
+ const logArr = /** @type {ArrayLike<unknown>} */ (/** @type {unknown} */ (log));
283
+ seen.add(logArr);
284
+ return stringifyArray(logArr);
277
285
  }
278
286
  if (typeof log === "object") {
279
287
 
@@ -287,11 +295,12 @@ function stringifyLog(log, seen = new Set(), depth = 0) {
287
295
  return `<Error: ${log.message}\nStack: ${log.stack}>`;
288
296
  }
289
297
 
290
- const keys = Object.keys(log);
298
+ const logObj = /** @type {Record<string, unknown>} */ (log);
299
+ const keys = Object.keys(logObj);
291
300
  let res = "{";
292
301
  for (let i = 0; i < keys.length; i++) {
293
302
  const key = keys[i];
294
- let value = log[key];
303
+ let value = logObj[key];
295
304
  if (i >= stringify_limits.object_keys) {
296
305
  res += `, ... <truncated ${keys.length - i} keys>`;
297
306
  break;
@@ -326,6 +335,7 @@ function stringifyLog(log, seen = new Set(), depth = 0) {
326
335
 
327
336
  return String(log);
328
337
 
338
+ /** @param {ArrayLike<unknown>} arr @returns {string} */
329
339
  function stringifyArray(arr) {
330
340
  let res = "";
331
341
  for (let i = 0; i < arr.length; i++) {
@@ -1,3 +1,4 @@
1
+ // @ts-check
1
2
  import { existsSync, readFileSync } from 'fs';
2
3
  import path from 'path';
3
4
  import { fileURLToPath } from 'url';
@@ -9,6 +10,8 @@ const __dirname = path.dirname(__filename);
9
10
 
10
11
  /**
11
12
  * write logs to local file
13
+ * @param {string} command
14
+ * @param {unknown} config
12
15
  * @param {import('../types/userconfig.js').userSettings} userSettings
13
16
  * @returns {import('vite').Plugin | null}
14
17
  */
@@ -18,7 +21,7 @@ export const needleLogger = (command, config, userSettings) => {
18
21
  return null;
19
22
  }
20
23
 
21
- patchConsoleLogs();
24
+ patchConsoleLogs({ command });
22
25
  captureLogMessage("server", "info", "Vite started with command \"" + command + "\" in " + __dirname, null);
23
26
 
24
27
  return {
@@ -51,7 +54,7 @@ export const needleLogger = (command, config, userSettings) => {
51
54
  }
52
55
  }
53
56
  },
54
- },
57
+ }
55
58
  }
56
59
  }
57
60
 
@@ -81,7 +84,7 @@ function logRequests(server, log_http_requests = false) {
81
84
  });
82
85
  });
83
86
  // Client log messages via websocket
84
- server.ws.on('needle:client-log', async (data, client) => {
87
+ server.ws.on('needle:client-log', async (/** @type {{level: string, message: unknown}} */ data, /** @type {{socket: import('net').Socket}} */ client) => {
85
88
  if (!data || !data.level || !data.message) {
86
89
  console.warn("Received empty log data, ignoring");
87
90
  return;