@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.
- package/CHANGELOG.md +8 -0
- package/components.needle.json +1 -1
- package/dist/{gltf-progressive-BttGBXw6.umd.cjs → gltf-progressive-CMwJPwEt.umd.cjs} +1 -1
- package/dist/{gltf-progressive-Bm_6aEi4.js → gltf-progressive-CTlvpS3A.js} +1 -1
- package/dist/{gltf-progressive-T5WKTux5.min.js → gltf-progressive-DYL3SLVb.min.js} +1 -1
- package/dist/materialx-4jJLLe9Q.js +4174 -0
- package/dist/materialx-Bt9FHwco.min.js +158 -0
- package/dist/materialx-NDD0y4JY.umd.cjs +158 -0
- package/dist/{needle-engine.bundle-COL2Bar3.umd.cjs → needle-engine.bundle-C1BFRZDF.umd.cjs} +150 -140
- package/dist/{needle-engine.bundle-Z_gAD7Kg.js → needle-engine.bundle-DB4kLWO_.js} +6651 -6400
- package/dist/{needle-engine.bundle-NolzHLqO.min.js → needle-engine.bundle-DsTdfmeb.min.js} +151 -141
- package/dist/needle-engine.d.ts +345 -88
- package/dist/needle-engine.js +322 -322
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{postprocessing-06AXuvdv.min.js → postprocessing-BN-f4viE.min.js} +1 -1
- package/dist/{postprocessing-CPDcA21P.umd.cjs → postprocessing-DYmYOVm4.umd.cjs} +1 -1
- package/dist/{postprocessing-CI2x8Cln.js → postprocessing-De9ZpJrk.js} +1 -1
- package/dist/{three-examples-BMmNgNCN.umd.cjs → three-examples-BHqRVpO_.umd.cjs} +12 -12
- package/dist/{three-examples-CMYCd5nH.js → three-examples-C0ZCCA_K.js} +182 -192
- package/dist/{three-examples-CQl1fFZp.min.js → three-examples-DmTY8tGr.min.js} +14 -14
- package/lib/engine/api.d.ts +0 -2
- package/lib/engine/api.js +0 -2
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/debug/debug.js +1 -1
- package/lib/engine/debug/debug.js.map +1 -1
- package/lib/engine/debug/debug_spatial_console.js +1 -1
- package/lib/engine/debug/debug_spatial_console.js.map +1 -1
- package/lib/engine/engine_accessibility.d.ts +77 -0
- package/lib/engine/engine_accessibility.js +162 -0
- package/lib/engine/engine_accessibility.js.map +1 -0
- package/lib/engine/engine_context.d.ts +2 -0
- package/lib/engine/engine_context.js +8 -1
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_create_objects.js +1 -1
- package/lib/engine/engine_create_objects.js.map +1 -1
- package/lib/engine/engine_gizmos.js +1 -1
- package/lib/engine/engine_gizmos.js.map +1 -1
- package/lib/engine/engine_license.js +7 -2
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_materialpropertyblock.d.ts +90 -4
- package/lib/engine/engine_materialpropertyblock.js +97 -7
- package/lib/engine/engine_materialpropertyblock.js.map +1 -1
- package/lib/engine/engine_math.d.ts +34 -1
- package/lib/engine/engine_math.js +34 -1
- package/lib/engine/engine_math.js.map +1 -1
- package/lib/engine/engine_networking.js +1 -1
- package/lib/engine/engine_networking.js.map +1 -1
- package/lib/engine/engine_types.d.ts +2 -0
- package/lib/engine/engine_types.js +2 -0
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_utils.js +2 -2
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/export/gltf/EXT_mesh_gpu_instancing_exporter.js.map +1 -0
- package/lib/engine/export/gltf/index.js +1 -1
- package/lib/engine/export/gltf/index.js.map +1 -1
- package/lib/engine/webcomponents/icons.js +3 -0
- package/lib/engine/webcomponents/icons.js.map +1 -1
- package/lib/engine/webcomponents/logo-element.d.ts +7 -3
- package/lib/engine/webcomponents/logo-element.js +21 -1
- package/lib/engine/webcomponents/logo-element.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +10 -7
- package/lib/engine/webcomponents/needle menu/needle-menu.js +14 -4
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-button.d.ts +37 -11
- package/lib/engine/webcomponents/needle-button.js +42 -11
- package/lib/engine/webcomponents/needle-button.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.ar-overlay.js +10 -1
- package/lib/engine/webcomponents/needle-engine.ar-overlay.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.d.ts +13 -2
- package/lib/engine/webcomponents/needle-engine.js +23 -3
- package/lib/engine/webcomponents/needle-engine.js.map +1 -1
- package/lib/engine-components/Component.d.ts +1 -2
- package/lib/engine-components/Component.js +1 -3
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/DragControls.d.ts +1 -0
- package/lib/engine-components/DragControls.js +21 -0
- package/lib/engine-components/DragControls.js.map +1 -1
- package/lib/engine-components/NeedleMenu.d.ts +2 -0
- package/lib/engine-components/NeedleMenu.js +2 -0
- package/lib/engine-components/NeedleMenu.js.map +1 -1
- package/lib/engine-components/Networking.d.ts +28 -3
- package/lib/engine-components/Networking.js +28 -3
- package/lib/engine-components/Networking.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.d.ts +25 -2
- package/lib/engine-components/ReflectionProbe.js +46 -2
- package/lib/engine-components/ReflectionProbe.js.map +1 -1
- package/lib/engine-components/Skybox.js +4 -2
- package/lib/engine-components/Skybox.js.map +1 -1
- package/lib/engine-components/export/gltf/GltfExport.js +1 -1
- package/lib/engine-components/export/gltf/GltfExport.js.map +1 -1
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +2 -2
- package/lib/engine-components/export/usdz/USDZExporter.js +1 -1
- package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.d.ts +15 -0
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js +77 -0
- package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js.map +1 -1
- package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js +2 -2
- package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
- package/lib/engine-components/ui/Button.d.ts +1 -0
- package/lib/engine-components/ui/Button.js +11 -0
- package/lib/engine-components/ui/Button.js.map +1 -1
- package/lib/engine-components/ui/Text.d.ts +1 -0
- package/lib/engine-components/ui/Text.js +11 -0
- package/lib/engine-components/ui/Text.js.map +1 -1
- package/package.json +18 -14
- package/plugins/common/buildinfo.js +46 -10
- package/plugins/common/files.js +2 -1
- package/plugins/common/license.js +144 -69
- package/plugins/common/logger.js +172 -11
- package/plugins/common/needle-engine-skill.md +175 -0
- package/plugins/common/worker.js +5 -4
- package/plugins/types/userconfig.d.ts +40 -2
- package/plugins/vite/ai.js +71 -0
- package/plugins/vite/alias.js +6 -5
- package/plugins/vite/asap.js +6 -5
- package/plugins/vite/build-pipeline.js +224 -41
- package/plugins/vite/buildinfo.js +66 -6
- package/plugins/vite/copyfiles.js +41 -12
- package/plugins/vite/custom-element-data.js +26 -16
- package/plugins/vite/defines.js +8 -5
- package/plugins/vite/dependencies.js +16 -10
- package/plugins/vite/dependency-watcher.js +35 -7
- package/plugins/vite/drop-client.js +7 -5
- package/plugins/vite/drop.js +16 -14
- package/plugins/vite/editor-connection.js +18 -16
- package/plugins/vite/imports-logger.js +12 -2
- package/plugins/vite/index.js +8 -3
- package/plugins/vite/local-files-analysis.js +789 -0
- package/plugins/vite/local-files-core.js +992 -0
- package/plugins/vite/local-files-internals.js +28 -0
- package/plugins/vite/local-files-types.d.ts +111 -0
- package/plugins/vite/local-files-utils.js +359 -0
- package/plugins/vite/local-files.js +2 -441
- package/plugins/vite/logger.client.js +45 -35
- package/plugins/vite/logger.js +6 -3
- package/plugins/vite/logging.js +129 -0
- package/plugins/vite/meta.js +18 -4
- package/plugins/vite/needle-app.js +4 -3
- package/plugins/vite/peer.js +2 -1
- package/plugins/vite/pwa.js +33 -17
- package/plugins/vite/reload.js +24 -2
- package/src/engine/api.ts +0 -3
- package/src/engine/debug/debug.ts +1 -1
- package/src/engine/debug/debug_spatial_console.ts +5 -1
- package/src/engine/engine_accessibility.ts +198 -0
- package/src/engine/engine_context.ts +10 -1
- package/src/engine/engine_create_objects.ts +1 -1
- package/src/engine/engine_gizmos.ts +9 -5
- package/src/engine/engine_license.ts +7 -2
- package/src/engine/engine_materialpropertyblock.ts +102 -11
- package/src/engine/engine_math.ts +34 -1
- package/src/engine/engine_networking.ts +1 -1
- package/src/engine/engine_types.ts +5 -0
- package/src/engine/engine_utils.ts +2 -2
- package/src/engine/export/gltf/index.ts +1 -1
- package/src/engine/webcomponents/icons.ts +3 -0
- package/src/engine/webcomponents/logo-element.ts +24 -4
- package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +6 -2
- package/src/engine/webcomponents/needle menu/needle-menu.ts +23 -11
- package/src/engine/webcomponents/needle-button.ts +44 -13
- package/src/engine/webcomponents/needle-engine.ar-overlay.ts +13 -2
- package/src/engine/webcomponents/needle-engine.ts +31 -8
- package/src/engine-components/Component.ts +2 -5
- package/src/engine-components/DragControls.ts +29 -4
- package/src/engine-components/NeedleMenu.ts +5 -3
- package/src/engine-components/Networking.ts +29 -4
- package/src/engine-components/ReflectionProbe.ts +52 -9
- package/src/engine-components/Skybox.ts +4 -2
- package/src/engine-components/export/gltf/GltfExport.ts +1 -1
- package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +2 -2
- package/src/engine-components/export/usdz/USDZExporter.ts +1 -1
- package/src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +108 -32
- package/src/engine-components/export/usdz/extensions/behavior/PhysicsExtension.ts +2 -2
- package/src/engine-components/ui/Button.ts +12 -0
- package/src/engine-components/ui/Text.ts +13 -0
- package/dist/materialx-CJyQZtjt.min.js +0 -90
- package/dist/materialx-DMs1E08Z.js +0 -4636
- package/dist/materialx-DaKKOoVk.umd.cjs +0 -90
- package/lib/engine/engine_test_utils.d.ts +0 -39
- package/lib/engine/engine_test_utils.js +0 -84
- package/lib/engine/engine_test_utils.js.map +0 -1
- package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js.map +0 -1
- package/src/engine/engine_test_utils.ts +0 -109
- package/src/include/draco/draco_decoder.js +0 -34
- package/src/include/draco/draco_decoder.wasm +0 -0
- package/src/include/draco/draco_wasm_wrapper.js +0 -117
- package/src/include/ktx2/basis_transcoder.js +0 -19
- package/src/include/ktx2/basis_transcoder.wasm +0 -0
- package/src/include/needle/arial-msdf.json +0 -1472
- package/src/include/needle/arial.png +0 -0
- package/src/include/needle/poweredbyneedle.webp +0 -0
- /package/lib/{include/three → engine/export/gltf}/EXT_mesh_gpu_instancing_exporter.d.ts +0 -0
- /package/lib/{include/three → engine/export/gltf}/EXT_mesh_gpu_instancing_exporter.js +0 -0
- /package/src/{include/three → engine/export/gltf}/EXT_mesh_gpu_instancing_exporter.js +0 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import picocolors from 'picocolors';
|
|
2
|
+
|
|
3
|
+
const { createColors, isColorSupported } = picocolors;
|
|
4
|
+
|
|
5
|
+
const colors = createColors(isColorSupported);
|
|
6
|
+
/** @type {null | (() => void)} */
|
|
7
|
+
let transientLogLineCleaner = null;
|
|
8
|
+
|
|
9
|
+
function getConsoleMethod(level) {
|
|
10
|
+
if (level === 'error') return console.error;
|
|
11
|
+
if (level === 'warn') return console.warn;
|
|
12
|
+
return console.log;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function colorBodyByLevel(level, text) {
|
|
16
|
+
if (!isColorSupported) return text;
|
|
17
|
+
if (level === 'error') return colors.red(text);
|
|
18
|
+
if (level === 'warn') return colors.yellow(text);
|
|
19
|
+
return text;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function normalizeMessage(message) {
|
|
23
|
+
if (Array.isArray(message)) return message.join("\n");
|
|
24
|
+
if (message === undefined || message === null) return "";
|
|
25
|
+
return String(message);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function formatHeader(pluginName) {
|
|
29
|
+
if (!isColorSupported) return `[${pluginName}]`;
|
|
30
|
+
|
|
31
|
+
const name = String(pluginName ?? "");
|
|
32
|
+
let prefix = "";
|
|
33
|
+
let suffix = name;
|
|
34
|
+
if (name.startsWith("needle-")) {
|
|
35
|
+
prefix = "needle-";
|
|
36
|
+
suffix = name.substring("needle-".length);
|
|
37
|
+
}
|
|
38
|
+
else if (name.startsWith("needle:")) {
|
|
39
|
+
prefix = "needle:";
|
|
40
|
+
suffix = name.substring("needle:".length);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const open = colors.green("[");
|
|
44
|
+
const close = colors.green("]");
|
|
45
|
+
if (!prefix.length) {
|
|
46
|
+
return `${open}${colors.bold(colors.green(name))}${close}`;
|
|
47
|
+
}
|
|
48
|
+
const prefixStyled = colors.green(prefix);
|
|
49
|
+
const suffixStyled = colors.bold(colors.green(suffix));
|
|
50
|
+
return `${open}${prefixStyled}${suffixStyled}${close}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {string} pluginName
|
|
55
|
+
* @param {string | string[]} message
|
|
56
|
+
* @param {'log' | 'warn' | 'error'} [level='log']
|
|
57
|
+
* @param {{ dimBody?: boolean, leadingNewline?: boolean, showHeader?: boolean }} [options]
|
|
58
|
+
*/
|
|
59
|
+
export function needleLog(pluginName, message, level = 'log', options = undefined) {
|
|
60
|
+
if (typeof transientLogLineCleaner === "function") {
|
|
61
|
+
transientLogLineCleaner();
|
|
62
|
+
}
|
|
63
|
+
const log = getConsoleMethod(level);
|
|
64
|
+
const headerText = formatHeader(pluginName);
|
|
65
|
+
const bodyText = normalizeMessage(message);
|
|
66
|
+
const dimBody = options?.dimBody ?? (level === 'log');
|
|
67
|
+
const leadingNewline = options?.leadingNewline === true;
|
|
68
|
+
const showHeader = options?.showHeader !== false;
|
|
69
|
+
|
|
70
|
+
if (isColorSupported) {
|
|
71
|
+
const header = `\x1b[0m${headerText}`;
|
|
72
|
+
const leveledBody = colorBodyByLevel(level, bodyText);
|
|
73
|
+
const body = bodyText.length > 0
|
|
74
|
+
? (dimBody ? leveledBody.split('\n').map(l => colors.dim(l)).join('\n') : leveledBody)
|
|
75
|
+
: "";
|
|
76
|
+
const payloadCore = showHeader
|
|
77
|
+
? (body.length > 0 ? `${header}\n${body}\n` : `${header}\n`)
|
|
78
|
+
: (body.length > 0 ? `${body}\n` : "");
|
|
79
|
+
const payload = leadingNewline ? `\n${payloadCore}` : payloadCore;
|
|
80
|
+
log(payload);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (bodyText.length > 0) {
|
|
85
|
+
const out = showHeader ? `${headerText} ${bodyText}` : bodyText;
|
|
86
|
+
log(leadingNewline ? `\n${out}` : out);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const out = showHeader ? headerText : "";
|
|
90
|
+
if (out.length > 0) {
|
|
91
|
+
log(leadingNewline ? `\n${out}` : out);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {string} pluginName
|
|
98
|
+
* @param {string[]} lines
|
|
99
|
+
* @param {'log' | 'warn' | 'error'} [level='log']
|
|
100
|
+
*/
|
|
101
|
+
export function needleLogLines(pluginName, lines, level = 'log') {
|
|
102
|
+
needleLog(pluginName, lines.join("\n"), level);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function needleSupportsColor() {
|
|
106
|
+
return isColorSupported;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function needleBlue(text) {
|
|
110
|
+
const value = String(text ?? "");
|
|
111
|
+
return isColorSupported ? colors.blue(value) : value;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function needleDim(text) {
|
|
115
|
+
const value = String(text ?? "");
|
|
116
|
+
return isColorSupported ? colors.dim(value) : value;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function needleGreenBold(text) {
|
|
120
|
+
const value = String(text ?? "");
|
|
121
|
+
return isColorSupported ? colors.bold(colors.green(value)) : value;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @param {(() => void) | null} cleaner
|
|
126
|
+
*/
|
|
127
|
+
export function setTransientLogLineCleaner(cleaner) {
|
|
128
|
+
transientLogLineCleaner = typeof cleaner === "function" ? cleaner : null;
|
|
129
|
+
}
|
package/plugins/vite/meta.js
CHANGED
|
@@ -3,6 +3,7 @@ import fs from 'fs';
|
|
|
3
3
|
import { tryGetNeedleEngineVersion } from '../common/version.js';
|
|
4
4
|
import { loadConfig } from './config.js';
|
|
5
5
|
import { getPosterPath } from './poster.js';
|
|
6
|
+
import { needleGreenBold, needleLog } from './logging.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* @param {string} command
|
|
@@ -25,7 +26,7 @@ export const needleMeta = (command, config, userSettings) => {
|
|
|
25
26
|
name: 'needle:meta',
|
|
26
27
|
transformIndexHtml: {
|
|
27
28
|
order: 'pre',
|
|
28
|
-
handler(html, _ctx) {
|
|
29
|
+
handler(/** @type {string} */ html, /** @type {unknown} */ _ctx) {
|
|
29
30
|
|
|
30
31
|
if (userSettings.allowMetaPlugin === false) return [];
|
|
31
32
|
|
|
@@ -74,7 +75,7 @@ export const needleMeta = (command, config, userSettings) => {
|
|
|
74
75
|
tags.push({ tag: 'meta', attrs: { name: 'og:image:height', content: 1080 } });
|
|
75
76
|
}
|
|
76
77
|
else if (isBuild) {
|
|
77
|
-
|
|
78
|
+
needleLog("needle-meta", `meta.image is set but absolutePath is ${config.absolutePath} in userSettings. Skipping meta.image.`, "warn", { dimBody: false });
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
|
|
@@ -114,10 +115,10 @@ export const needleMeta = (command, config, userSettings) => {
|
|
|
114
115
|
const needleEngineVersion = tryGetNeedleEngineVersion();
|
|
115
116
|
if (needleEngineVersion) {
|
|
116
117
|
if (command === "build")
|
|
117
|
-
|
|
118
|
+
needleLog("needle-meta", needleGreenBold(`✨ Needle Engine version: ${needleEngineVersion} 🌵`), "log", { dimBody: false });
|
|
118
119
|
tags.push({ tag: 'meta', attrs: { name: 'needle-engine', content: needleEngineVersion } });
|
|
119
120
|
}
|
|
120
|
-
else
|
|
121
|
+
else needleLog("needle-meta", "Could not find needle engine package.json", "warn", { dimBody: false })
|
|
121
122
|
|
|
122
123
|
tags.push({ tag: 'meta', attrs: { name: 'needle:buildtime', content: new Date().toISOString() } });
|
|
123
124
|
|
|
@@ -128,6 +129,11 @@ export const needleMeta = (command, config, userSettings) => {
|
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
|
|
132
|
+
/**
|
|
133
|
+
* @param {string} html
|
|
134
|
+
* @param {string} url
|
|
135
|
+
* @returns {string}
|
|
136
|
+
*/
|
|
131
137
|
function updateUrlMetaTag(html, url) {
|
|
132
138
|
const result = `<meta name="url" content="${url}">`;
|
|
133
139
|
html = html.replace(`<meta name="url" content="https://needle.tools">`, result);
|
|
@@ -135,14 +141,21 @@ function updateUrlMetaTag(html, url) {
|
|
|
135
141
|
return html;
|
|
136
142
|
}
|
|
137
143
|
|
|
144
|
+
/** @param {string} str @returns {string} */
|
|
138
145
|
function appendVersion(str) {
|
|
139
146
|
return str + "?v=" + Date.now();
|
|
140
147
|
}
|
|
141
148
|
|
|
149
|
+
/** @param {string} url @returns {string} */
|
|
142
150
|
function removeDuplicateSlashesInUrl(url) {
|
|
143
151
|
return url.replace(/([^:]\/)\/+/g, "$1");
|
|
144
152
|
}
|
|
145
153
|
|
|
154
|
+
/**
|
|
155
|
+
* @param {string} html
|
|
156
|
+
* @param {string} name
|
|
157
|
+
* @returns {string}
|
|
158
|
+
*/
|
|
146
159
|
function removeMetaTag(html, name) {
|
|
147
160
|
// TODO: maybe we could also just replace the content
|
|
148
161
|
const regex = new RegExp(`<meta (name|property)="${name}".+?\/?>`, 'gs');
|
|
@@ -154,6 +167,7 @@ function removeMetaTag(html, name) {
|
|
|
154
167
|
return newHtml;
|
|
155
168
|
}
|
|
156
169
|
|
|
170
|
+
/** @param {string} html @returns {string} */
|
|
157
171
|
function insertNeedleCredits(html) {
|
|
158
172
|
const needleCredits = `<!-- 🌵 Made with Needle — https://needle.tools -->`;
|
|
159
173
|
html = html.replace(
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { writeFile } from 'fs';
|
|
2
2
|
import { tryParseNeedleEngineSrcAttributeFromHtml } from '../common/needle-engine.js';
|
|
3
|
+
import { needleLog } from './logging.js';
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
|
|
@@ -54,15 +55,15 @@ export const needleApp = (command, config, userSettings) => {
|
|
|
54
55
|
const webComponent = generateNeedleEmbedWebComponent(path, main_asset);
|
|
55
56
|
await writeFile(`${outputDir}/needle-app.js`, webComponent, (err) => {
|
|
56
57
|
if (err) {
|
|
57
|
-
|
|
58
|
+
needleLog("needle-app", "Could not create needle-app.js: " + err.message, "error", { dimBody: false });
|
|
58
59
|
}
|
|
59
60
|
else {
|
|
60
|
-
|
|
61
|
+
needleLog("needle-app", "Created needle-app.js", "log", { dimBody: false });
|
|
61
62
|
}
|
|
62
63
|
});
|
|
63
64
|
}
|
|
64
65
|
catch (e) {
|
|
65
|
-
|
|
66
|
+
needleLog("needle-app", "Could not create needle-app.js: " + e.message, "warn", { dimBody: false });
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
}
|
package/plugins/vite/peer.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const peerjsString = `/* needle: fix for peerjs */ window.global = window; var parcelRequire;`
|
|
2
|
+
import { needleLog } from './logging.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* @param {import('../types').userSettings} userSettings
|
|
@@ -80,7 +81,7 @@ function patchWebRTCAdapterForGemini(code, id) {
|
|
|
80
81
|
if(!didTransform) return undefined;
|
|
81
82
|
|
|
82
83
|
if(!didLog) {
|
|
83
|
-
|
|
84
|
+
needleLog("needle:peerjs", "Fixed WebRTC assignment", "log", { dimBody: false });
|
|
84
85
|
didLog = true;
|
|
85
86
|
}
|
|
86
87
|
|
package/plugins/vite/pwa.js
CHANGED
|
@@ -7,6 +7,7 @@ import { getPosterPath } from './poster.js';
|
|
|
7
7
|
const pwaErrorWithInstructions = "It seems that you're trying to build a PWA using 'vite-plugin-pwa'!\nNeedle can manage PWA settings for you – just pass the same 'pwaOptions' to the needlePlugins and VitePWA plugins:\n\n1. Install the vite PWA plugin: npm install vite-plugin-pwa --save-dev\n\n2. Then update your vite.config.js:\n\n import { VitePWA } from 'vite-plugin-pwa';\n ...\n needlePlugins(command, needleConfig, { pwa: pwaOptions }),\n VitePWA(pwaOptions),\n\nIf you want to manage PWA building yourself and skip this check, please pass '{ pwa: false }' to needlePlugins.";
|
|
8
8
|
|
|
9
9
|
/** Provides reasonable defaults for a PWA manifest and workbox settings.
|
|
10
|
+
* @param {string} command
|
|
10
11
|
* @param {import('../types').userSettings} userSettings
|
|
11
12
|
* @param {import("../types/needleConfig").needleMeta | null} config
|
|
12
13
|
* @returns {import('vite').Plugin | void}
|
|
@@ -71,7 +72,7 @@ export const needlePWA = (command, config, userSettings) => {
|
|
|
71
72
|
const customManifest = manifests.length > 0 ? manifests[0] : {};
|
|
72
73
|
|
|
73
74
|
// ensure we have proper icons/name/description to match user settings
|
|
74
|
-
processPWA(customManifest, context, pwaOptions, config, userSettings).catch(e => log("Error post processing PWA", customManifest, e));
|
|
75
|
+
processPWA(customManifest, context, pwaOptions, config, userSettings).catch((/** @type {unknown} */ e) => log("Error post processing PWA", customManifest, e));
|
|
75
76
|
// ensures we have a valid workbox config
|
|
76
77
|
processWorkboxConfig(pwaOptions);
|
|
77
78
|
|
|
@@ -81,14 +82,15 @@ export const needlePWA = (command, config, userSettings) => {
|
|
|
81
82
|
// for debugging
|
|
82
83
|
// log("PWA options", pwaOptions);
|
|
83
84
|
|
|
84
|
-
return {
|
|
85
|
+
return /** @type {import('vite').Plugin} */ ({
|
|
85
86
|
name: 'needle:pwa',
|
|
86
87
|
apply: 'build',
|
|
87
88
|
enforce: "post",
|
|
88
|
-
config(viteConfig) {
|
|
89
|
+
config(/** @type {{ plugins?: Array<Record<string,unknown>> }} */ viteConfig) {
|
|
89
90
|
// Move the gzip plugin after PWA bundling
|
|
90
91
|
let gzipPluginIndex = -1;
|
|
91
92
|
let pwaPluginIndex = -1;
|
|
93
|
+
/** @type {Record<string, unknown> | null} */
|
|
92
94
|
let gzipPlugin = null;
|
|
93
95
|
if (viteConfig.plugins) {
|
|
94
96
|
for (let i = viteConfig.plugins.length - 1; i >= 0; i--) {
|
|
@@ -168,7 +170,7 @@ export const needlePWA = (command, config, userSettings) => {
|
|
|
168
170
|
}
|
|
169
171
|
}
|
|
170
172
|
}
|
|
171
|
-
catch (err) {
|
|
173
|
+
catch (/** @type {unknown} */ err) {
|
|
172
174
|
cleanup(context);
|
|
173
175
|
throw err;
|
|
174
176
|
}
|
|
@@ -251,7 +253,7 @@ updateSW = registerSW({
|
|
|
251
253
|
try {
|
|
252
254
|
copyIcons(pwaOptions.manifest, outputDir);
|
|
253
255
|
}
|
|
254
|
-
catch (e) {
|
|
256
|
+
catch (/** @type {unknown} */ e) {
|
|
255
257
|
log("Error post processing PWA", e);
|
|
256
258
|
}
|
|
257
259
|
|
|
@@ -261,20 +263,23 @@ updateSW = registerSW({
|
|
|
261
263
|
console.log(msg);
|
|
262
264
|
}
|
|
263
265
|
}
|
|
264
|
-
}
|
|
266
|
+
})
|
|
265
267
|
}
|
|
266
268
|
|
|
267
269
|
/** Checks if the vite-plugin-pwa is present in the vite config
|
|
268
|
-
* @param {
|
|
270
|
+
* @param {{ plugins?: readonly unknown[] }} config
|
|
269
271
|
* @returns {import('vite-plugin-pwa').VitePWAOptions | null}
|
|
270
272
|
*/
|
|
271
273
|
function findVitePWAPlugin(config) {
|
|
272
|
-
const plugins = config.plugins || [];
|
|
274
|
+
const plugins = /** @type {Array<Record<string,unknown>>} */ (config.plugins || []);
|
|
275
|
+
/** @param {unknown} p
|
|
276
|
+
* @returns {Record<string, unknown> | undefined}
|
|
277
|
+
*/
|
|
273
278
|
function _findVitePWAPlugin(p) {
|
|
274
279
|
if (Array.isArray(p))
|
|
275
|
-
return p.find(_findVitePWAPlugin);
|
|
276
|
-
if (p?.name === "vite-plugin-pwa")
|
|
277
|
-
return p;
|
|
280
|
+
return /** @type {Array<unknown>} */ (p).find(_findVitePWAPlugin);
|
|
281
|
+
if (/** @type {Record<string,unknown>} */(p)?.name === "vite-plugin-pwa")
|
|
282
|
+
return /** @type {Record<string, unknown>} */ (p);
|
|
278
283
|
}
|
|
279
284
|
for (const plugin of plugins) {
|
|
280
285
|
const foundVitePWAPlugin = _findVitePWAPlugin(plugin);
|
|
@@ -283,6 +288,7 @@ function findVitePWAPlugin(config) {
|
|
|
283
288
|
return null;
|
|
284
289
|
}
|
|
285
290
|
|
|
291
|
+
/** @param {import('../types/index.d.ts').NeedlePWAProcessContext} context */
|
|
286
292
|
function cleanup(context) {
|
|
287
293
|
for (const file of context.generatedFiles) {
|
|
288
294
|
log("Cleanup generated file", file);
|
|
@@ -291,6 +297,7 @@ function cleanup(context) {
|
|
|
291
297
|
context.generatedFiles.length = 0;
|
|
292
298
|
}
|
|
293
299
|
|
|
300
|
+
/** @param {...unknown} args */
|
|
294
301
|
function log(...args) {
|
|
295
302
|
console.log("[needle-pwa]", ...args);
|
|
296
303
|
}
|
|
@@ -337,10 +344,16 @@ async function processPWA(webmanifestPath, context, pwaOptions, config, userSett
|
|
|
337
344
|
// pwaOptions.includeAssets = [...pwaOptions.includeAssets, ...manifest.icons?.map(i => i.src)];
|
|
338
345
|
|
|
339
346
|
const packageJsonPath = process.cwd() + "/package.json";
|
|
340
|
-
const packageJson = existsSync(packageJsonPath) ? JSON.parse(readFileSync(packageJsonPath, 'utf8')) : {};
|
|
347
|
+
const packageJson = /** @type {{ name?: string, description?: string }} */ (existsSync(packageJsonPath) ? JSON.parse(readFileSync(packageJsonPath, 'utf8')) : {});
|
|
341
348
|
|
|
342
|
-
const name = packageJson.name;
|
|
343
349
|
const appName = config?.sceneName || packageJson.name || "Needle App";
|
|
350
|
+
const packageName = typeof packageJson.name === "string" && packageJson.name.length > 0
|
|
351
|
+
? packageJson.name
|
|
352
|
+
: appName;
|
|
353
|
+
const packageNameSanitized = packageName
|
|
354
|
+
.toLowerCase()
|
|
355
|
+
.replace(/[^a-z0-9\/\-]/g, '')
|
|
356
|
+
.replace("\/", ".");
|
|
344
357
|
const description = typeof config?.meta === "string"
|
|
345
358
|
? config.meta : config?.meta?.description
|
|
346
359
|
|| packageJson.description
|
|
@@ -351,9 +364,11 @@ async function processPWA(webmanifestPath, context, pwaOptions, config, userSett
|
|
|
351
364
|
// Use the same title as in NeedleMeta
|
|
352
365
|
name: appName,
|
|
353
366
|
short_name: appName,
|
|
354
|
-
id: "app.made-with-needle." +
|
|
367
|
+
id: "app.made-with-needle." + packageNameSanitized,
|
|
355
368
|
description,
|
|
356
369
|
start_url: "./index.html",
|
|
370
|
+
theme_color: "#000000",
|
|
371
|
+
background_color: "#000000",
|
|
357
372
|
display: "standalone",
|
|
358
373
|
display_override: [
|
|
359
374
|
"window-controls-overlay",
|
|
@@ -423,7 +438,7 @@ function processIcons(manifest, outDir, context) {
|
|
|
423
438
|
modified = true;
|
|
424
439
|
}
|
|
425
440
|
}
|
|
426
|
-
catch (e) {
|
|
441
|
+
catch (/** @type {unknown} */ e) {
|
|
427
442
|
log("Error processing PWA icon[" + i + "]", e);
|
|
428
443
|
}
|
|
429
444
|
}
|
|
@@ -460,6 +475,7 @@ function generateIcons(manifest, context) {
|
|
|
460
475
|
/** Tries to copy the icons to the output directory
|
|
461
476
|
* TODO this should not be needed if we use pwaOptions.includeAssets
|
|
462
477
|
* @param {Partial<import("vite-plugin-pwa").ManifestOptions>} manifest
|
|
478
|
+
* @param {string} outDir
|
|
463
479
|
*/
|
|
464
480
|
function copyIcons(manifest, outDir) {
|
|
465
481
|
for (let i = 0; i < manifest.icons?.length; i++) {
|
|
@@ -492,7 +508,7 @@ function copyIcons(manifest, outDir) {
|
|
|
492
508
|
copyFileSync(srcPath, targetPath);
|
|
493
509
|
}
|
|
494
510
|
}
|
|
495
|
-
catch (e) {
|
|
511
|
+
catch (/** @type {unknown} */ e) {
|
|
496
512
|
log("Error processing PWA icon[" + i + "]", e);
|
|
497
513
|
}
|
|
498
514
|
}
|
|
@@ -582,7 +598,7 @@ function processWorkboxConfig(manifest) {
|
|
|
582
598
|
},
|
|
583
599
|
// allow caching local resources
|
|
584
600
|
{
|
|
585
|
-
urlPattern: ({ url }) => url,
|
|
601
|
+
urlPattern: (/** @type {{ url: URL }} */ { url }) => url,
|
|
586
602
|
// Apply a network-first strategy.
|
|
587
603
|
handler: 'NetworkFirst',
|
|
588
604
|
options: {
|
package/plugins/vite/reload.js
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import path from 'path';
|
|
2
3
|
import { loadConfig, tryLoadProjectConfig } from './config.js';
|
|
3
4
|
import { getPosterPath } from './poster.js';
|
|
4
5
|
import * as crypto from 'crypto';
|
|
5
6
|
import { existsSync, readFileSync, statSync } from 'fs';
|
|
6
7
|
import { fileURLToPath } from 'url';
|
|
8
|
+
import { needleLog } from './logging.js';
|
|
7
9
|
|
|
8
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
11
|
const __dirname = path.dirname(__filename);
|
|
10
12
|
|
|
13
|
+
/** @type {Set<string>} */
|
|
11
14
|
const filesUsingHotReload = new Set();
|
|
12
15
|
let assetsDirectory = "";
|
|
13
16
|
|
|
14
17
|
/**
|
|
18
|
+
* @param {string} command
|
|
19
|
+
* @param {import('../types').userSettings | null} config
|
|
15
20
|
* @param {import('../types').userSettings} userSettings
|
|
16
21
|
*/
|
|
17
22
|
export const needleReload = (command, config, userSettings) => {
|
|
@@ -34,7 +39,8 @@ export const needleReload = (command, config, userSettings) => {
|
|
|
34
39
|
|
|
35
40
|
const buildDirectory = projectConfig?.buildDirectory?.length ? process.cwd().replaceAll("\\", "/") + "/" + projectConfig?.buildDirectory : "";
|
|
36
41
|
if (buildDirectory?.length) {
|
|
37
|
-
|
|
42
|
+
const relativeBuildDirectory = path.relative(process.cwd(), buildDirectory).replaceAll("\\", "/") || ".";
|
|
43
|
+
setTimeout(() => needleLog("needle-reload", "Build directory: " + relativeBuildDirectory), 100);
|
|
38
44
|
}
|
|
39
45
|
|
|
40
46
|
// These ignore patterns will be injected into user config to better control vite reloading
|
|
@@ -44,6 +50,7 @@ export const needleReload = (command, config, userSettings) => {
|
|
|
44
50
|
|
|
45
51
|
return {
|
|
46
52
|
name: 'needle:reload',
|
|
53
|
+
/** @param {import('vite').UserConfig} config */
|
|
47
54
|
config(config) {
|
|
48
55
|
if (!config.server) config.server = { watch: { ignored: [] } };
|
|
49
56
|
else if (!config.server.watch) config.server.watch = { ignored: [] };
|
|
@@ -51,12 +58,14 @@ export const needleReload = (command, config, userSettings) => {
|
|
|
51
58
|
for (const pattern of ignorePatterns)
|
|
52
59
|
config.server.watch.ignored.push(pattern);
|
|
53
60
|
if (config?.debug === true || userSettings?.debug === true)
|
|
54
|
-
setTimeout(() =>
|
|
61
|
+
setTimeout(() => needleLog("needle-reload", "Updated server ignore patterns: " + JSON.stringify(config.server.watch.ignored)), 100);
|
|
55
62
|
},
|
|
63
|
+
/** @param {{file: string, server: import('vite').ViteDevServer, modules: unknown[], read: (file?: string) => Promise<string>, buildDirectory?: string}} args */
|
|
56
64
|
handleHotUpdate(args) {
|
|
57
65
|
args.buildDirectory = buildDirectory;
|
|
58
66
|
return handleReload(args);
|
|
59
67
|
},
|
|
68
|
+
/** @param {string} src @param {string} id */
|
|
60
69
|
transform(src, id) {
|
|
61
70
|
if (!id.includes(".ts")) return;
|
|
62
71
|
updateConfig();
|
|
@@ -67,6 +76,7 @@ export const needleReload = (command, config, userSettings) => {
|
|
|
67
76
|
},
|
|
68
77
|
transformIndexHtml: {
|
|
69
78
|
order: 'pre',
|
|
79
|
+
/** @param {string} html @param {unknown} _ */
|
|
70
80
|
handler(html, _) {
|
|
71
81
|
if (config?.allowHotReload === false) return html;
|
|
72
82
|
if (userSettings?.allowHotReload === false) return html;
|
|
@@ -91,6 +101,7 @@ export const needleReload = (command, config, userSettings) => {
|
|
|
91
101
|
}
|
|
92
102
|
|
|
93
103
|
|
|
104
|
+
/** @type {string[]} */
|
|
94
105
|
const ignorePatterns = [];
|
|
95
106
|
const ignoreRegex = new RegExp(ignorePatterns.join("|"));
|
|
96
107
|
|
|
@@ -99,11 +110,15 @@ const posterPath = getPosterPath();
|
|
|
99
110
|
let reloadIsScheduled = false;
|
|
100
111
|
const lockFileName = "needle.lock";
|
|
101
112
|
|
|
113
|
+
/** @param {import('vite').ViteDevServer} server @param {string} [file] */
|
|
102
114
|
function notifyClientWillReload(server, file) {
|
|
103
115
|
console.log("Send reload notification");
|
|
104
116
|
server.ws.send('needle:reload', { type: 'will-reload', file: file });
|
|
105
117
|
}
|
|
106
118
|
|
|
119
|
+
/**
|
|
120
|
+
* @param {{file: string, server: import('vite').ViteDevServer, modules: unknown[], read: (file?: string) => Promise<string>, buildDirectory?: string}} param0
|
|
121
|
+
*/
|
|
107
122
|
async function handleReload({ file, server, modules, read, buildDirectory }) {
|
|
108
123
|
|
|
109
124
|
// dont reload the full page on css changes
|
|
@@ -191,6 +206,7 @@ async function handleReload({ file, server, modules, read, buildDirectory }) {
|
|
|
191
206
|
}
|
|
192
207
|
|
|
193
208
|
|
|
209
|
+
/** @param {import('vite').ViteDevServer} server @param {number} [level] */
|
|
194
210
|
async function scheduleReload(server, level = 0) {
|
|
195
211
|
if (reloadIsScheduled && level === 0) return;
|
|
196
212
|
reloadIsScheduled = true;
|
|
@@ -224,6 +240,7 @@ async function scheduleReload(server, level = 0) {
|
|
|
224
240
|
|
|
225
241
|
const projectDirectory = process.cwd().replaceAll("\\", "/");
|
|
226
242
|
|
|
243
|
+
/** @param {string} file @returns {string} */
|
|
227
244
|
function getFileNameLog(file) {
|
|
228
245
|
if (file.startsWith(projectDirectory)) {
|
|
229
246
|
return file.substring(projectDirectory.length);
|
|
@@ -231,9 +248,11 @@ function getFileNameLog(file) {
|
|
|
231
248
|
return file;
|
|
232
249
|
}
|
|
233
250
|
|
|
251
|
+
/** @type {Map<string, string>} */
|
|
234
252
|
const hashes = new Map();
|
|
235
253
|
const hash256 = crypto.createHash('sha256');
|
|
236
254
|
|
|
255
|
+
/** @param {string} file @param {(file?: string) => Promise<string>} read @returns {Promise<boolean>} */
|
|
237
256
|
async function testIfFileContentChanged(file, read) {
|
|
238
257
|
let content = await read(file);
|
|
239
258
|
content = removeVersionQueryArgument(content);
|
|
@@ -252,6 +271,7 @@ async function testIfFileContentChanged(file, read) {
|
|
|
252
271
|
}
|
|
253
272
|
return false;
|
|
254
273
|
}
|
|
274
|
+
/** @param {string} content @returns {string} */
|
|
255
275
|
function removeVersionQueryArgument(content) {
|
|
256
276
|
if (typeof content === "string") {
|
|
257
277
|
// Some codegen files include hashes for loading glb files (e.g. ?v=213213124)
|
|
@@ -266,6 +286,7 @@ function removeVersionQueryArgument(content) {
|
|
|
266
286
|
|
|
267
287
|
|
|
268
288
|
|
|
289
|
+
/** @param {string} src @param {string} filePath @returns {string} */
|
|
269
290
|
function insertScriptRegisterHotReloadCode(src, filePath) {
|
|
270
291
|
|
|
271
292
|
// We only want to inject the hot reload code in the needle-engine root file
|
|
@@ -284,6 +305,7 @@ globalThis.NEEDLE_HOT_RELOAD_ENABLED = true;
|
|
|
284
305
|
const HOT_RELOAD_START_MARKER = "NEEDLE_HOT_RELOAD_BEGIN";
|
|
285
306
|
const HOT_RELOAD_END_MARKER = "NEEDLE_HOT_RELOAD_END";
|
|
286
307
|
|
|
308
|
+
/** @param {string} src @param {string} filePath @returns {{code: string, map: null} | undefined} */
|
|
287
309
|
function insertScriptHotReloadCode(src, filePath) {
|
|
288
310
|
if (filePath.includes("engine_hot_reload")) return;
|
|
289
311
|
if (filePath.includes(".vite")) return;
|
package/src/engine/api.ts
CHANGED
|
@@ -354,9 +354,6 @@ export { type ISerializable } from "./engine_serialization_core.js";
|
|
|
354
354
|
// General-purpose utility functions and helpers.
|
|
355
355
|
// ============================================================================
|
|
356
356
|
|
|
357
|
-
/** Testing utilities for automated tests */
|
|
358
|
-
export * from "./engine_test_utils.js";
|
|
359
|
-
|
|
360
357
|
/** Texture utilities and processing */
|
|
361
358
|
export * from "./engine_texture.js";
|
|
362
359
|
|
|
@@ -8,7 +8,7 @@ export {
|
|
|
8
8
|
clearMessages as clearOverlayMessages,
|
|
9
9
|
LogType,
|
|
10
10
|
setAllowBalloonMessages,
|
|
11
|
-
// eslint-disable-next-line
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
12
12
|
setAllowOverlayMessages,
|
|
13
13
|
};
|
|
14
14
|
export { enableSpatialConsole } from "./debug_spatial_console.js";
|
|
@@ -169,7 +169,11 @@ class SpatialMessagesHandler {
|
|
|
169
169
|
|
|
170
170
|
if (!fontFamily) {
|
|
171
171
|
fontFamily = ThreeMeshUI.FontLibrary.addFontFamily(this.familyName);
|
|
172
|
-
const variant = fontFamily.addVariant(
|
|
172
|
+
const variant = fontFamily.addVariant(
|
|
173
|
+
"normal",
|
|
174
|
+
"normal",
|
|
175
|
+
"https://cdn.needle.tools/static/fonts/msdf/arial/arial-msdf.json",
|
|
176
|
+
"https://cdn.needle.tools/static/fonts/msdf/arial/arial.png") as any as ThreeMeshUI.FontVariant;
|
|
173
177
|
/** @ts-ignore */
|
|
174
178
|
variant?.addEventListener('ready', () => {
|
|
175
179
|
ThreeMeshUI.update();
|