@needle-tools/engine 5.1.0-alpha.1 → 5.1.0-alpha.3
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.
- package/.needle/generated/needle-bindings.gen.d.ts +5 -0
- package/CHANGELOG.md +52 -0
- package/components.needle.json +1 -1
- package/dist/{gltf-progressive-DJBMx-zB.umd.cjs → gltf-progressive-BmblPzFj.umd.cjs} +4 -4
- package/dist/{gltf-progressive-BryRjllq.min.js → gltf-progressive-CN_mbb66.min.js} +2 -2
- package/dist/{gltf-progressive-Cl167Vjx.js → gltf-progressive-DUlhxdv4.js} +5 -2
- package/dist/needle-engine.bundle-C-ixARur.umd.cjs +1733 -0
- package/dist/needle-engine.bundle-CHmXdnE1.min.js +1733 -0
- package/dist/{needle-engine.bundle-BGyKqxBH.js → needle-engine.bundle-DF01sSGQ.js} +10841 -10434
- package/dist/needle-engine.d.ts +244 -54
- package/dist/needle-engine.js +541 -536
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{postprocessing-B_9sKVU7.min.js → postprocessing-B571qGWR.min.js} +34 -34
- package/dist/{postprocessing-WDc9WwI3.js → postprocessing-CfrLAbLX.js} +0 -1
- package/dist/{postprocessing-B2wb6pzI.umd.cjs → postprocessing-CiGkAeM9.umd.cjs} +17 -17
- package/dist/{vendor-CAcsI0eU.js → vendor-BFrMaK9q.js} +8983 -9136
- package/dist/vendor-CJmyOrCq.min.js +1116 -0
- package/dist/vendor-DkMW3WY4.umd.cjs +1116 -0
- package/lib/engine/api.d.ts +14 -0
- package/lib/engine/api.js +4 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/debug/debug_environment.js +1 -1
- package/lib/engine/debug/debug_environment.js.map +1 -1
- package/lib/engine/debug/debug_spatial_console.d.ts +2 -0
- package/lib/engine/debug/debug_spatial_console.js +10 -7
- package/lib/engine/debug/debug_spatial_console.js.map +1 -1
- package/lib/engine/engine_addressables.d.ts +2 -0
- package/lib/engine/engine_addressables.js +6 -3
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_application.js +8 -6
- package/lib/engine/engine_application.js.map +1 -1
- package/lib/engine/engine_audio.d.ts +68 -0
- package/lib/engine/engine_audio.js +172 -0
- package/lib/engine/engine_audio.js.map +1 -1
- package/lib/engine/engine_components.js +1 -1
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_constants.js +6 -0
- package/lib/engine/engine_constants.js.map +1 -1
- package/lib/engine/engine_context.d.ts +33 -7
- package/lib/engine/engine_context.js +40 -2
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_context_registry.js +1 -1
- package/lib/engine/engine_context_registry.js.map +1 -1
- package/lib/engine/engine_gameobject.js +2 -2
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_init.js +16 -1
- package/lib/engine/engine_init.js.map +1 -1
- package/lib/engine/engine_input.d.ts +3 -2
- package/lib/engine/engine_input.js +3 -2
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_license.d.ts +2 -0
- package/lib/engine/engine_license.js +25 -15
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_lifecycle_functions_internal.js +5 -0
- package/lib/engine/engine_lifecycle_functions_internal.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.js +5 -2
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_networking_blob.d.ts +1 -1
- package/lib/engine/engine_networking_blob.js +5 -11
- package/lib/engine/engine_networking_blob.js.map +1 -1
- package/lib/engine/engine_physics_rapier.js +0 -1
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_pmrem.js +2 -2
- package/lib/engine/engine_pmrem.js.map +1 -1
- package/lib/engine/engine_scenedata.d.ts +32 -0
- package/lib/engine/engine_scenedata.js +138 -0
- package/lib/engine/engine_scenedata.js.map +1 -0
- package/lib/engine/engine_serialization_builtin_serializer.d.ts +10 -16
- package/lib/engine/engine_serialization_builtin_serializer.js +55 -41
- package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
- package/lib/engine/engine_ssr.d.ts +18 -0
- package/lib/engine/engine_ssr.js +40 -0
- package/lib/engine/engine_ssr.js.map +1 -0
- package/lib/engine/engine_three_utils.d.ts +14 -7
- package/lib/engine/engine_three_utils.js +14 -7
- package/lib/engine/engine_three_utils.js.map +1 -1
- package/lib/engine/engine_types.d.ts +2 -0
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_utils.js +2 -0
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/engine_utils_hash.d.ts +9 -0
- package/lib/engine/engine_utils_hash.js +112 -0
- package/lib/engine/engine_utils_hash.js.map +1 -0
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
- package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
- package/lib/engine/webcomponents/jsx.d.ts +51 -0
- package/lib/engine/webcomponents/logo-element.d.ts +2 -1
- package/lib/engine/webcomponents/logo-element.js +2 -1
- package/lib/engine/webcomponents/logo-element.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +4 -4
- package/lib/engine/webcomponents/needle menu/needle-menu.js +2 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-button.d.ts +2 -1
- package/lib/engine/webcomponents/needle-button.js +2 -1
- package/lib/engine/webcomponents/needle-button.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.d.ts +11 -4
- package/lib/engine/webcomponents/needle-engine.js +2 -1
- package/lib/engine/webcomponents/needle-engine.js.map +1 -1
- package/lib/engine/xr/NeedleXRSession.d.ts +3 -2
- package/lib/engine/xr/NeedleXRSession.js +51 -15
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine/xr/events.d.ts +1 -1
- package/lib/engine/xr/events.js.map +1 -1
- package/lib/engine-components/Animation.js +17 -16
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/AnimatorController.d.ts +2 -0
- package/lib/engine-components/AnimatorController.js +4 -1
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/AudioSource.d.ts +19 -3
- package/lib/engine-components/AudioSource.js +121 -68
- package/lib/engine-components/AudioSource.js.map +1 -1
- package/lib/engine-components/DragControls.d.ts +7 -0
- package/lib/engine-components/DragControls.js +19 -0
- package/lib/engine-components/DragControls.js.map +1 -1
- package/lib/engine-components/Light.d.ts +6 -8
- package/lib/engine-components/Light.js +40 -27
- package/lib/engine-components/Light.js.map +1 -1
- package/lib/engine-components/Networking.d.ts +1 -1
- package/lib/engine-components/Networking.js +1 -1
- package/lib/engine-components/OrbitControls.js +16 -11
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.js +2 -0
- package/lib/engine-components/ReflectionProbe.js.map +1 -1
- package/lib/engine-components/RigidBody.js +3 -3
- package/lib/engine-components/RigidBody.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.js +2 -0
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/SeeThrough.js +2 -2
- package/lib/engine-components/SeeThrough.js.map +1 -1
- package/lib/engine-components/api.d.ts +1 -1
- package/lib/engine-components/api.js +1 -1
- package/lib/engine-components/api.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/BloomEffect.d.ts +1 -1
- package/lib/engine-components/postprocessing/Effects/Sharpening.js +1 -2
- package/lib/engine-components/postprocessing/Effects/Sharpening.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
- package/lib/engine-components/postprocessing/PostProcessingHandler.js +5 -6
- package/lib/engine-components/postprocessing/PostProcessingHandler.js.map +1 -1
- package/lib/engine-components/postprocessing/VolumeParameter.d.ts +2 -0
- package/lib/engine-components/postprocessing/VolumeParameter.js +4 -1
- package/lib/engine-components/postprocessing/VolumeParameter.js.map +1 -1
- package/lib/engine-components/ui/Canvas.d.ts +1 -1
- package/lib/engine-components/ui/Canvas.js +2 -8
- package/lib/engine-components/ui/Canvas.js.map +1 -1
- package/lib/engine-components/ui/Text.d.ts +1 -0
- package/lib/engine-components/ui/Text.js +10 -7
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/lib/engine-components/web/CursorFollow.js +21 -12
- package/lib/engine-components/web/CursorFollow.js.map +1 -1
- package/lib/engine-components/web/ScrollFollow.d.ts +0 -1
- package/lib/engine-components/web/ScrollFollow.js +3 -2
- package/lib/engine-components/web/ScrollFollow.js.map +1 -1
- package/lib/engine-components/webxr/WebXRImageTracking.js +4 -0
- package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
- package/lib/needle-engine.d.ts +2 -0
- package/lib/needle-engine.js +2 -0
- package/lib/needle-engine.js.map +1 -1
- package/package.json +6 -4
- package/plugins/dts-generator/dts.codegen.js +334 -0
- package/plugins/dts-generator/dts.scan.js +99 -0
- package/plugins/dts-generator/dts.writer.js +59 -0
- package/plugins/dts-generator/glb.discovery.js +279 -0
- package/plugins/dts-generator/glb.extractor.js +215 -0
- package/plugins/dts-generator/glb.reader.js +167 -0
- package/plugins/dts-generator/index.js +36 -0
- package/plugins/dts-generator/manifest.types.js +174 -0
- package/plugins/types/index.d.ts +2 -1
- package/plugins/types/needle-bindings.d.ts +30 -0
- package/plugins/types/userconfig.d.ts +21 -2
- package/plugins/vite/asap.js +18 -9
- package/plugins/vite/dependencies.js +29 -0
- package/plugins/vite/dependency-watcher.d.ts +2 -2
- package/plugins/vite/dependency-watcher.js +3 -4
- package/plugins/vite/drop.d.ts +2 -2
- package/plugins/vite/drop.js +3 -4
- package/plugins/vite/dts-generator.d.ts +7 -0
- package/plugins/vite/dts-generator.js +191 -0
- package/plugins/vite/index.d.ts +10 -3
- package/plugins/vite/index.js +27 -10
- package/plugins/vite/local-files-core.js +3 -3
- package/plugins/vite/local-files-utils.d.ts +3 -1
- package/plugins/vite/local-files-utils.js +29 -5
- package/plugins/vite/logging.js +2 -2
- package/plugins/vite/meta.js +4 -2
- package/plugins/vite/poster.d.ts +2 -2
- package/plugins/vite/poster.js +3 -5
- package/plugins/vite/reload.d.ts +2 -2
- package/plugins/vite/reload.js +23 -22
- package/src/engine/api.ts +18 -1
- package/src/engine/debug/debug_environment.ts +1 -1
- package/src/engine/debug/debug_spatial_console.ts +10 -7
- package/src/engine/engine_addressables.ts +6 -3
- package/src/engine/engine_application.ts +8 -6
- package/src/engine/engine_audio.ts +184 -0
- package/src/engine/engine_components.ts +1 -1
- package/src/engine/engine_constants.ts +11 -6
- package/src/engine/engine_context.ts +50 -7
- package/src/engine/engine_context_registry.ts +1 -1
- package/src/engine/engine_gameobject.ts +2 -2
- package/src/engine/engine_init.ts +15 -1
- package/src/engine/engine_input.ts +3 -2
- package/src/engine/engine_license.ts +23 -19
- package/src/engine/engine_lifecycle_functions_internal.ts +7 -0
- package/src/engine/engine_mainloop_utils.ts +5 -2
- package/src/engine/engine_networking_blob.ts +5 -11
- package/src/engine/engine_physics_rapier.ts +0 -3
- package/src/engine/engine_pmrem.ts +3 -3
- package/src/engine/engine_scenedata.ts +136 -0
- package/src/engine/engine_serialization_builtin_serializer.ts +63 -46
- package/src/engine/engine_ssr.ts +48 -0
- package/src/engine/engine_three_utils.ts +15 -7
- package/src/engine/engine_types.ts +2 -0
- package/src/engine/engine_utils.ts +1 -0
- package/src/engine/engine_utils_hash.ts +65 -0
- package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
- package/src/engine/webcomponents/jsx.d.ts +51 -0
- package/src/engine/webcomponents/logo-element.ts +3 -1
- package/src/engine/webcomponents/needle menu/needle-menu.ts +4 -2
- package/src/engine/webcomponents/needle-button.ts +3 -1
- package/src/engine/webcomponents/needle-engine.ts +12 -4
- package/src/engine/xr/NeedleXRSession.ts +49 -14
- package/src/engine/xr/events.ts +1 -1
- package/src/engine-components/Animation.ts +19 -16
- package/src/engine-components/AnimatorController.ts +4 -1
- package/src/engine-components/AudioSource.ts +130 -79
- package/src/engine-components/DragControls.ts +18 -2
- package/src/engine-components/Light.ts +40 -26
- package/src/engine-components/Networking.ts +1 -1
- package/src/engine-components/OrbitControls.ts +18 -9
- package/src/engine-components/ReflectionProbe.ts +2 -0
- package/src/engine-components/RigidBody.ts +3 -3
- package/src/engine-components/SceneSwitcher.ts +1 -0
- package/src/engine-components/SeeThrough.ts +2 -2
- package/src/engine-components/api.ts +1 -1
- package/src/engine-components/postprocessing/Effects/BloomEffect.ts +1 -1
- package/src/engine-components/postprocessing/Effects/Sharpening.ts +1 -2
- package/src/engine-components/postprocessing/PostProcessingHandler.ts +4 -8
- package/src/engine-components/postprocessing/VolumeParameter.ts +4 -1
- package/src/engine-components/ui/Canvas.ts +2 -8
- package/src/engine-components/ui/Text.ts +12 -8
- package/src/engine-components/web/CursorFollow.ts +21 -13
- package/src/engine-components/web/ScrollFollow.ts +2 -2
- package/src/engine-components/webxr/WebXRImageTracking.ts +2 -0
- package/src/needle-engine.ts +3 -0
- package/src/vite-env.d.ts +16 -0
- package/dist/needle-engine.bundle-CiYtOO2O.min.js +0 -1732
- package/dist/needle-engine.bundle-DzVx9Z8D.umd.cjs +0 -1732
- package/dist/vendor-CEM38hLE.umd.cjs +0 -1116
- package/dist/vendor-HRlxIBga.min.js +0 -1116
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* Vite plugin: needle:dts-generator
|
|
4
|
+
*
|
|
5
|
+
* Thin wrapper around plugins/dts-generator/index.js.
|
|
6
|
+
* Regenerates `needle-bindings.d.ts` on startup and whenever a .glb / .gltf
|
|
7
|
+
* file changes in the assets directory.
|
|
8
|
+
*
|
|
9
|
+
* The generated file is written to `{codegenDirectory}/needle-bindings.d.ts`
|
|
10
|
+
* (falls back to `src/generated/needle-bindings.d.ts`).
|
|
11
|
+
*
|
|
12
|
+
* Usage — the plugin is already wired into needlePlugins(). To use standalone:
|
|
13
|
+
*
|
|
14
|
+
* import { needleDtsGenerator } from "@needle-tools/engine/plugins/vite/dts-generator.js";
|
|
15
|
+
* // in vite.config.js plugins array:
|
|
16
|
+
* needleDtsGenerator(command, needleConfig, userSettings)
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { join, resolve, dirname } from 'path';
|
|
20
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, realpathSync } from 'fs';
|
|
21
|
+
import { tryLoadProjectConfig } from './config.js';
|
|
22
|
+
import { generateBindingsDts } from '../dts-generator/index.js';
|
|
23
|
+
import { needleLog } from './logging.js';
|
|
24
|
+
|
|
25
|
+
// Two dirs up from plugins/vite/ → package root.
|
|
26
|
+
// Use fileURLToPath so %7E and other URL-encoded characters in the path are decoded correctly.
|
|
27
|
+
// realpathSync follows symlinks so the path is stable even in npm link / monorepo setups.
|
|
28
|
+
import { fileURLToPath } from 'url';
|
|
29
|
+
let _packageRoot = /** @type {string | null} */ (null);
|
|
30
|
+
try {
|
|
31
|
+
_packageRoot = realpathSync(join(dirname(fileURLToPath(import.meta.url)), '..', '..'));
|
|
32
|
+
} catch (_e) {
|
|
33
|
+
// If we can't resolve the package root (e.g. unusual install layout), the plugin
|
|
34
|
+
// will silently skip generation rather than crashing the dev server.
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Ensure `.vscode/settings.json` references the generated `needle-html-data.json`
|
|
39
|
+
* so VS Code provides `data-bind-needle` completions in HTML files automatically.
|
|
40
|
+
* Only adds the entry if it isn't already present — never overwrites other settings.
|
|
41
|
+
*
|
|
42
|
+
* @param {string} projectRoot
|
|
43
|
+
* @param {string} htmlDataPath Absolute path to the generated needle-html-data.json
|
|
44
|
+
*/
|
|
45
|
+
function ensureVscodeHtmlCustomData(projectRoot, htmlDataPath) {
|
|
46
|
+
const vscodeDir = join(projectRoot, ".vscode");
|
|
47
|
+
const settingsPath = join(vscodeDir, "settings.json");
|
|
48
|
+
|
|
49
|
+
// Relative path from project root for portability
|
|
50
|
+
const relPath = htmlDataPath.replace(projectRoot + "/", "").replace(projectRoot + "\\", "");
|
|
51
|
+
|
|
52
|
+
/** @type {Record<string, unknown>} */
|
|
53
|
+
let settings = {};
|
|
54
|
+
if (existsSync(settingsPath)) {
|
|
55
|
+
try {
|
|
56
|
+
settings = JSON.parse(readFileSync(settingsPath, "utf8"));
|
|
57
|
+
} catch (_e) { /* malformed JSON — leave settings empty, will add key */ }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const key = "html.customData";
|
|
61
|
+
const existing = Array.isArray(settings[key]) ? /** @type {string[]} */ (settings[key]) : [];
|
|
62
|
+
if (existing.includes(relPath)) return; // already registered
|
|
63
|
+
|
|
64
|
+
settings[key] = [...existing, relPath];
|
|
65
|
+
|
|
66
|
+
mkdirSync(vscodeDir, { recursive: true });
|
|
67
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
68
|
+
needleLog("needle:dts-generator", `registered HTML completions in .vscode/settings.json`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {"build" | "serve"} _command Vite command (unused — runs in both modes)
|
|
73
|
+
* @param {import('../types/needleConfig').needleMeta | null | undefined} _config
|
|
74
|
+
* @param {import('../types').userSettings} [_userSettings]
|
|
75
|
+
* @returns {import('vite').Plugin | null}
|
|
76
|
+
*/
|
|
77
|
+
export function needleDtsGenerator(_command, _config, _userSettings) {
|
|
78
|
+
|
|
79
|
+
if(_userSettings?.dts?.enabled === false) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let projectRoot = process.cwd();
|
|
84
|
+
|
|
85
|
+
function resolveCodegenDir() {
|
|
86
|
+
const projectConfig = tryLoadProjectConfig();
|
|
87
|
+
return projectConfig?.codegenDirectory
|
|
88
|
+
? resolve(projectRoot, projectConfig.codegenDirectory)
|
|
89
|
+
: join(projectRoot, "src", "generated");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function resolveOutputPath() {
|
|
93
|
+
// Write to a .needle dotfolder at the package root.
|
|
94
|
+
// Not in the `files` allowlist → never npm-published.
|
|
95
|
+
// ../../.needle/ from plugins/types/ resolves correctly for both
|
|
96
|
+
// symlinked (js/package~/) and published (node_modules/@needle-tools/engine/) layouts.
|
|
97
|
+
return join(/** @type {string} */ (_packageRoot), ".needle", "generated", "needle-bindings.gen.d.ts");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function resolveAssetsDir() {
|
|
101
|
+
const projectConfig = tryLoadProjectConfig();
|
|
102
|
+
return projectConfig?.assetsDirectory
|
|
103
|
+
? resolve(projectRoot, projectConfig.assetsDirectory)
|
|
104
|
+
: join(projectRoot, "assets");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** @type {import('vite').ViteDevServer | undefined} */
|
|
108
|
+
let devServer;
|
|
109
|
+
|
|
110
|
+
/** @type {Promise<void> | null} */
|
|
111
|
+
let _runInFlight = null;
|
|
112
|
+
|
|
113
|
+
function run() {
|
|
114
|
+
if (_runInFlight) return _runInFlight;
|
|
115
|
+
_runInFlight = _doRun().finally(() => { _runInFlight = null; });
|
|
116
|
+
return _runInFlight;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function _doRun() {
|
|
120
|
+
try {
|
|
121
|
+
if (!_packageRoot) return;
|
|
122
|
+
const assetsDir = resolveAssetsDir();
|
|
123
|
+
const outputPath = resolveOutputPath();
|
|
124
|
+
const codegenDir = resolveCodegenDir();
|
|
125
|
+
const count = await generateBindingsDts({ assetsDir, outputPath, projectRoot, codegenDir });
|
|
126
|
+
// HTML custom data sits next to the generated dts in .needle/generated/
|
|
127
|
+
const htmlDataPath = join(/** @type {string} */ (_packageRoot), ".needle", "generated", "needle-html-data.json");
|
|
128
|
+
ensureVscodeHtmlCustomData(projectRoot, htmlDataPath);
|
|
129
|
+
if (count !== false) {
|
|
130
|
+
needleLog("needle:dts-generator", `${count} binding(s) → ${outputPath.replace(process.cwd(), ".")}`);
|
|
131
|
+
if (devServer) {
|
|
132
|
+
const hot = devServer.hot ?? devServer.ws;
|
|
133
|
+
hot.send({ type: "full-reload", path: "*" });
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
needleLog("needle:dts-generator", `up-to-date → ${outputPath.replace(process.cwd(), ".")}`);
|
|
137
|
+
}
|
|
138
|
+
} catch (err) {
|
|
139
|
+
needleLog("needle:dts-generator", "Failed: " + (/** @type {any} */ (err)?.message ?? err));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
name: "needle:dts-generator",
|
|
145
|
+
|
|
146
|
+
/** @param {import('vite').ResolvedConfig} config */
|
|
147
|
+
configResolved(config) {
|
|
148
|
+
projectRoot = config.root ?? process.cwd();
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
buildStart() {
|
|
152
|
+
// In serve mode, the configureServer post-hook runs instead.
|
|
153
|
+
// Only run here for actual builds (no devServer).
|
|
154
|
+
if (!devServer) return run();
|
|
155
|
+
return undefined;
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
/** @param {import('vite').ViteDevServer} server */
|
|
159
|
+
configureServer(server) {
|
|
160
|
+
devServer = server;
|
|
161
|
+
|
|
162
|
+
// Watch assets directory for GLB/glTF changes and regenerate
|
|
163
|
+
const assetsDir = resolveAssetsDir();
|
|
164
|
+
server.watcher.add(assetsDir);
|
|
165
|
+
|
|
166
|
+
// Also watch files that determine which GLBs are entrypoints
|
|
167
|
+
const indexHtmlPath = join(projectRoot, "index.html");
|
|
168
|
+
const genJsPath = join(resolveCodegenDir(), "gen.js");
|
|
169
|
+
server.watcher.add(indexHtmlPath);
|
|
170
|
+
server.watcher.add(genJsPath);
|
|
171
|
+
|
|
172
|
+
server.watcher.on("change", (file) => {
|
|
173
|
+
if (
|
|
174
|
+
(/\.(glb|gltf)$/i.test(file) && file.startsWith(assetsDir)) ||
|
|
175
|
+
file === indexHtmlPath ||
|
|
176
|
+
file === genJsPath
|
|
177
|
+
) {
|
|
178
|
+
run();
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
server.watcher.on("add", (file) => {
|
|
182
|
+
if (/\.(glb|gltf)$/i.test(file) && file.startsWith(assetsDir)) {
|
|
183
|
+
run();
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Return post-hook so Vite awaits the initial run before printing "ready"
|
|
188
|
+
return () => run();
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
}
|
package/plugins/vite/index.d.ts
CHANGED
|
@@ -19,13 +19,20 @@
|
|
|
19
19
|
* ],
|
|
20
20
|
* }
|
|
21
21
|
* ```
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* When used without arguments (e.g. in a SvelteKit `defineConfig({})` plain object),
|
|
23
|
+
* the command is resolved automatically from Vite's `configResolved` hook.
|
|
24
|
+
* ```js
|
|
25
|
+
* // SvelteKit — no command needed:
|
|
26
|
+
* export default defineConfig({ plugins: [sveltekit(), needlePlugins()] });
|
|
27
|
+
* ```
|
|
28
|
+
* @param {"build" | "serve" | undefined} [command]
|
|
29
|
+
* @param {import('../types/needleConfig').needleMeta | null | undefined} [config]
|
|
24
30
|
* @param {import('../types/index.js').userSettings} [userSettings]
|
|
25
31
|
* @returns {Promise<import('vite').Plugin[]>}
|
|
26
32
|
*/
|
|
27
|
-
export function needlePlugins(command
|
|
33
|
+
export function needlePlugins(command?: "build" | "serve" | undefined, config?: import("../types/needleConfig").needleMeta | null | undefined, userSettings?: import("../types/index.js").userSettings): Promise<import("vite").Plugin[]>;
|
|
28
34
|
export { needleAI } from "./ai.js";
|
|
35
|
+
export { needleDtsGenerator } from "./dts-generator.js";
|
|
29
36
|
export { needleAsap } from "./asap.js";
|
|
30
37
|
export { needleDefines } from "./defines.js";
|
|
31
38
|
export { needleBuildPipeline } from "./build-pipeline.js";
|
package/plugins/vite/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { needleAI } from "./ai.js";
|
|
2
2
|
export { needleAI } from "./ai.js";
|
|
3
3
|
|
|
4
|
+
import { needleDtsGenerator } from "./dts-generator.js";
|
|
5
|
+
export { needleDtsGenerator } from "./dts-generator.js";
|
|
6
|
+
|
|
4
7
|
import { needleAsap } from "./asap.js";
|
|
5
8
|
export { needleAsap } from "./asap.js";
|
|
6
9
|
|
|
@@ -113,12 +116,18 @@ const defaultUserSettings = {
|
|
|
113
116
|
* ],
|
|
114
117
|
* }
|
|
115
118
|
* ```
|
|
116
|
-
*
|
|
117
|
-
*
|
|
119
|
+
* When used without arguments (e.g. in a SvelteKit `defineConfig({})` plain object),
|
|
120
|
+
* the command is resolved automatically from Vite's `configResolved` hook.
|
|
121
|
+
* ```js
|
|
122
|
+
* // SvelteKit — no command needed:
|
|
123
|
+
* export default defineConfig({ plugins: [sveltekit(), needlePlugins()] });
|
|
124
|
+
* ```
|
|
125
|
+
* @param {"build" | "serve" | undefined} [command]
|
|
126
|
+
* @param {import('../types/needleConfig').needleMeta | null | undefined} [config]
|
|
118
127
|
* @param {import('../types/index.js').userSettings} [userSettings]
|
|
119
128
|
* @returns {Promise<import('vite').Plugin[]>}
|
|
120
129
|
*/
|
|
121
|
-
export async function needlePlugins(command, config = undefined, userSettings = {}) {
|
|
130
|
+
export async function needlePlugins(command = undefined, config = undefined, userSettings = {}) {
|
|
122
131
|
|
|
123
132
|
if (!config) config = {}
|
|
124
133
|
|
|
@@ -126,6 +135,7 @@ export async function needlePlugins(command, config = undefined, userSettings =
|
|
|
126
135
|
userSettings = { ...defaultUserSettings, ...userSettings };
|
|
127
136
|
|
|
128
137
|
const array = [
|
|
138
|
+
needleDtsGenerator(command, config, userSettings),
|
|
129
139
|
needleAI(command, config, userSettings),
|
|
130
140
|
needleLogger(command, config, userSettings),
|
|
131
141
|
needleDefines(command, config, userSettings),
|
|
@@ -164,14 +174,21 @@ export async function needlePlugins(command, config = undefined, userSettings =
|
|
|
164
174
|
array.push(await editorConnection(command, config, userSettings, array));
|
|
165
175
|
array.push(needleDependencyWatcher(command, config, userSettings));
|
|
166
176
|
|
|
167
|
-
// Ensure the process exits on SIGINT (Ctrl+C) since plugin timers/sockets can keep the event loop alive
|
|
168
|
-
|
|
177
|
+
// Ensure the process exits on SIGINT (Ctrl+C) since plugin timers/sockets can keep the event loop alive.
|
|
178
|
+
// If command is unknown at call time (e.g. SvelteKit plain defineConfig), defer to configResolved.
|
|
179
|
+
const registerSigint = () => {
|
|
169
180
|
process.on('SIGINT', () => {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
181
|
+
setTimeout(() => { console.debug('\nGoodbye!'); process.exit(); }, 1000);
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
if (command === "serve") {
|
|
185
|
+
registerSigint();
|
|
186
|
+
} else if (command === undefined) {
|
|
187
|
+
array.push({
|
|
188
|
+
name: "needle:sigint",
|
|
189
|
+
configResolved(config) {
|
|
190
|
+
if (config.command === "serve") registerSigint();
|
|
191
|
+
}
|
|
175
192
|
});
|
|
176
193
|
}
|
|
177
194
|
|
|
@@ -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
|
|
123
|
-
return `new URL(${quote}${
|
|
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
|
|
131
|
-
return `new URL(${quote}${
|
|
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
|
|
package/plugins/vite/logging.js
CHANGED
|
@@ -97,8 +97,8 @@ export function needleLog(pluginName, message, level = 'log', options = undefine
|
|
|
97
97
|
? (dimBody ? leveledBody.split('\n').map(l => colors.dim(l)).join('\n') : leveledBody)
|
|
98
98
|
: "";
|
|
99
99
|
const payloadCore = emitHeader
|
|
100
|
-
? (body.length > 0 ? `${header}\n${body}
|
|
101
|
-
: (body.length > 0 ? `${body}
|
|
100
|
+
? (body.length > 0 ? `${header}\n${body}` : `${header}`)
|
|
101
|
+
: (body.length > 0 ? `${body}` : "");
|
|
102
102
|
const payload = leadingNewline ? `\n${payloadCore}` : payloadCore;
|
|
103
103
|
log(payload);
|
|
104
104
|
return;
|
package/plugins/vite/meta.js
CHANGED
|
@@ -13,8 +13,7 @@ import { needleGreenBold, needleLog } from './logging.js';
|
|
|
13
13
|
*/
|
|
14
14
|
export function needleMeta(command, config, userSettings) {
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
const isBuild = command === 'build';
|
|
16
|
+
let isBuild = command === 'build';
|
|
18
17
|
|
|
19
18
|
async function updateConfig() {
|
|
20
19
|
config = await loadConfig();
|
|
@@ -25,6 +24,9 @@ export function needleMeta(command, config, userSettings) {
|
|
|
25
24
|
return {
|
|
26
25
|
// replace meta tags
|
|
27
26
|
name: 'needle:meta',
|
|
27
|
+
configResolved(resolvedConfig) {
|
|
28
|
+
isBuild = resolvedConfig.command === 'build';
|
|
29
|
+
},
|
|
28
30
|
transformIndexHtml: {
|
|
29
31
|
order: 'pre',
|
|
30
32
|
handler(/** @type {string} */ html, /** @type {unknown} */ _ctx) {
|
package/plugins/vite/poster.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export function getPosterPath(): string;
|
|
2
2
|
/**
|
|
3
|
-
* @param {"build" | "serve"}
|
|
3
|
+
* @param {"build" | "serve" | undefined} _command
|
|
4
4
|
* @param {import('../types/needleConfig').needleMeta | null | undefined} config
|
|
5
5
|
* @param {import('../types').userSettings} userSettings
|
|
6
6
|
* @returns {import('vite').Plugin | undefined}
|
|
7
7
|
*/
|
|
8
|
-
export function needlePoster(
|
|
8
|
+
export function needlePoster(_command: "build" | "serve" | undefined, config: import("../types/needleConfig").needleMeta | null | undefined, userSettings: import("../types").userSettings): import("vite").Plugin | undefined;
|
package/plugins/vite/poster.js
CHANGED
|
@@ -10,19 +10,17 @@ export function getPosterPath() {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* @param {"build" | "serve"}
|
|
13
|
+
* @param {"build" | "serve" | undefined} _command
|
|
14
14
|
* @param {import('../types/needleConfig').needleMeta | null | undefined} config
|
|
15
15
|
* @param {import('../types').userSettings} userSettings
|
|
16
16
|
* @returns {import('vite').Plugin | undefined}
|
|
17
17
|
*/
|
|
18
|
-
export function needlePoster(
|
|
19
|
-
// only relevant for local development
|
|
20
|
-
if (command === 'build') return [];
|
|
21
|
-
|
|
18
|
+
export function needlePoster(_command, config, userSettings) {
|
|
22
19
|
if (userSettings.noPoster) return;
|
|
23
20
|
|
|
24
21
|
return {
|
|
25
22
|
name: 'needle:poster',
|
|
23
|
+
apply: 'serve',
|
|
26
24
|
configureServer(server) {
|
|
27
25
|
const hot = server.hot ?? server.ws;
|
|
28
26
|
hot.on('needle:screenshot', async (data, client) => {
|
package/plugins/vite/reload.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @param {"build" | "serve"}
|
|
2
|
+
* @param {"build" | "serve" | undefined} _command
|
|
3
3
|
* @param {import('../types/needleConfig').needleMeta | null} config
|
|
4
4
|
* @param {import('../types').userSettings} userSettings
|
|
5
5
|
* @returns {import('vite').Plugin | undefined}
|
|
6
6
|
*/
|
|
7
|
-
export function needleReload(
|
|
7
|
+
export function needleReload(_command: "build" | "serve" | undefined, config: import("../types/needleConfig").needleMeta | null, userSettings: import("../types").userSettings): import("vite").Plugin | undefined;
|
package/plugins/vite/reload.js
CHANGED
|
@@ -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
|
|
|
@@ -15,14 +16,12 @@ const filesUsingHotReload = new Set();
|
|
|
15
16
|
let assetsDirectory = "";
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
|
-
* @param {"build" | "serve"}
|
|
19
|
+
* @param {"build" | "serve" | undefined} _command
|
|
19
20
|
* @param {import('../types/needleConfig').needleMeta | null} config
|
|
20
21
|
* @param {import('../types').userSettings} userSettings
|
|
21
22
|
* @returns {import('vite').Plugin | undefined}
|
|
22
23
|
*/
|
|
23
|
-
export function needleReload(
|
|
24
|
-
if (command === "build") return undefined;
|
|
25
|
-
|
|
24
|
+
export function needleReload(_command, config, userSettings) {
|
|
26
25
|
if (userSettings?.noReload === true) return undefined;
|
|
27
26
|
|
|
28
27
|
|
|
@@ -41,7 +40,7 @@ export function needleReload(command, config, userSettings) {
|
|
|
41
40
|
const buildDirectory = projectConfig?.buildDirectory?.length ? process.cwd().replaceAll("\\", "/") + "/" + projectConfig?.buildDirectory : "";
|
|
42
41
|
if (buildDirectory?.length) {
|
|
43
42
|
const relativeBuildDirectory = path.relative(process.cwd(), buildDirectory).replaceAll("\\", "/") || ".";
|
|
44
|
-
setTimeout(() => needleLog(
|
|
43
|
+
setTimeout(() => needleLog(pluginName, "Build directory: " + relativeBuildDirectory), 100);
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
// These ignore patterns will be injected into user config to better control vite reloading
|
|
@@ -51,6 +50,7 @@ export function needleReload(command, config, userSettings) {
|
|
|
51
50
|
|
|
52
51
|
return {
|
|
53
52
|
name: 'needle:reload',
|
|
53
|
+
apply: 'serve',
|
|
54
54
|
/** @param {import('vite').UserConfig} config */
|
|
55
55
|
config(config) {
|
|
56
56
|
if (!config.server) config.server = { watch: { ignored: [] } };
|
|
@@ -60,7 +60,7 @@ export function needleReload(command, config, userSettings) {
|
|
|
60
60
|
// @ts-ignore - watch.ignored is guaranteed to be string[] by the guards above
|
|
61
61
|
config.server.watch.ignored.push(pattern);
|
|
62
62
|
if (userSettings?.debug === true)
|
|
63
|
-
setTimeout(() => needleLog(
|
|
63
|
+
setTimeout(() => needleLog(pluginName, "Updated server ignore patterns: " + JSON.stringify(config.server?.watch?.ignored)), 100);
|
|
64
64
|
},
|
|
65
65
|
/** @param {import('vite').HmrContext & {buildDirectory?: string}} args */
|
|
66
66
|
handleHotUpdate(args) {
|
|
@@ -119,7 +119,7 @@ function getHot(server) {
|
|
|
119
119
|
|
|
120
120
|
/** @param {import('vite').ViteDevServer} server @param {string} [file] */
|
|
121
121
|
function notifyClientWillReload(server, file) {
|
|
122
|
-
|
|
122
|
+
needleLog(pluginName, "Send reload notification");
|
|
123
123
|
getHot(server).send('needle:reload', { type: 'will-reload', file: file });
|
|
124
124
|
}
|
|
125
125
|
|
|
@@ -135,7 +135,7 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
|
|
|
135
135
|
|
|
136
136
|
// Dont reload the whole server when a file that is using hot reload changes
|
|
137
137
|
if (filesUsingHotReload.has(file)) {
|
|
138
|
-
|
|
138
|
+
needleLog(pluginName, "File is using hot reload: " + file);
|
|
139
139
|
return null;
|
|
140
140
|
}
|
|
141
141
|
|
|
@@ -154,7 +154,7 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
|
|
|
154
154
|
// instead of relying on the vite server watch ignore array
|
|
155
155
|
// we could here also match paths that we know we dont want to track
|
|
156
156
|
if (ignorePatterns.length > 0 && ignoreRegex.test(file)) {
|
|
157
|
-
|
|
157
|
+
needleLog(pluginName, "Ignore change in file: " + getFileNameLog(file));
|
|
158
158
|
return [];
|
|
159
159
|
}
|
|
160
160
|
|
|
@@ -164,7 +164,7 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
|
|
|
164
164
|
if (buildDirectory?.length) {
|
|
165
165
|
const dir = path.dirname(file).replaceAll("\\", "/");
|
|
166
166
|
if (dir.startsWith(buildDirectory)) {
|
|
167
|
-
|
|
167
|
+
needleLog(pluginName, "Ignore change in build directory: " + getFileNameLog(file));
|
|
168
168
|
return [];
|
|
169
169
|
}
|
|
170
170
|
}
|
|
@@ -172,19 +172,20 @@ async function handleReload({ file, server, modules: _modules, read, buildDirect
|
|
|
172
172
|
// Check if codegen files actually changed their content
|
|
173
173
|
// this will return false if its the first update
|
|
174
174
|
// meaning if its the first export after the server starts those will not trigger a reload
|
|
175
|
+
// Ignore d.ts
|
|
175
176
|
const shouldCheckIfContentChanged = file.includes("/codegen/") || file.includes("/generated/") || file.endsWith("gen.js");// || file.endsWith(".glb") || file.endsWith(".gltf") || file.endsWith(".bin");
|
|
176
|
-
if (shouldCheckIfContentChanged) {
|
|
177
|
+
if (!file.includes("/.svelte-kit/") && !file.endsWith(".d.ts") && !file.endsWith("needle-html-data.json") && shouldCheckIfContentChanged) {
|
|
177
178
|
if (reloadIsScheduled) {
|
|
178
179
|
return [];
|
|
179
180
|
}
|
|
180
181
|
if (await testIfFileContentChanged(file, read) === false) {
|
|
181
|
-
|
|
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 = [
|
|
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
|
-
|
|
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,7 +224,7 @@ 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
|
-
|
|
227
|
+
needleLog(pluginName, "Lock file exists, waiting for export to finish...");
|
|
227
228
|
setTimeout(() => scheduleReload(server, level += 1), 300);
|
|
228
229
|
return;
|
|
229
230
|
}
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
342
|
+
// needleLog(pluginName, fullPathToHotReload);
|
|
342
343
|
const fileDirectory = path.dirname(filePath);
|
|
343
|
-
//
|
|
344
|
+
// needleLog(pluginName, "DIR", fileDirectory)
|
|
344
345
|
const relativePath = path.relative(fileDirectory, fullPathToHotReload);
|
|
345
346
|
importPath = relativePath.replace(/\\/g, "/");
|
|
346
|
-
//
|
|
347
|
+
// needleLog(pluginName, "importPath: ", importPath);
|
|
347
348
|
}
|
|
348
349
|
|
|
349
350
|
// console.log(importPath, ">", filePath);
|