@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
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
// @ts-check
|
|
1
2
|
import { spawn } from "child_process";
|
|
2
3
|
import { NEEDLE_CLOUD_CLI_NAME } from "./cloud.js";
|
|
3
4
|
import { existsSync } from "fs";
|
|
4
5
|
import http from "http";
|
|
5
6
|
import https from "https";
|
|
7
|
+
import { needleLog } from "../vite/logging.js";
|
|
6
8
|
|
|
7
9
|
const port = 8424;
|
|
8
10
|
const localServerUrl = `http://localhost:${port}`;
|
|
@@ -10,10 +12,80 @@ const licenseServerUrl = `http://localhost:${port}/api/license`;
|
|
|
10
12
|
const projectIdentifierUrl = `http://localhost:${port}/api/public_key`;
|
|
11
13
|
const needleCloudApiEndpoint = "https://cloud.needle.tools/api";
|
|
12
14
|
|
|
15
|
+
/** @param {string} message @param {string} [level] */
|
|
16
|
+
function logLicense(message, level = "log") {
|
|
17
|
+
needleLog("needle-license", message, level);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** @param {string} message @param {string} [level] */
|
|
21
|
+
function logIdentifier(message, level = "log") {
|
|
22
|
+
needleLog("needle-identifier", message, level);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Ensure response streams are fully released to avoid lingering sockets.
|
|
27
|
+
* @param {Response | null | undefined} response
|
|
28
|
+
*/
|
|
29
|
+
async function releaseResponse(response) {
|
|
30
|
+
if (!response?.body) return;
|
|
31
|
+
try {
|
|
32
|
+
await response.arrayBuffer();
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
try {
|
|
36
|
+
await response.body.cancel();
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// ignore
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {string} path
|
|
46
|
+
* @param {{ method:"GET"|"POST", accessToken:string, body?: Record<string, any>, timeoutMs:number }} options
|
|
47
|
+
* @returns {Promise<NeedleCloudHttpResponse>}
|
|
48
|
+
*/
|
|
49
|
+
async function requestNeedleCloud(path, options) {
|
|
50
|
+
const url = new URL(`${needleCloudApiEndpoint}${path}`);
|
|
51
|
+
const requestBody = options.body ? JSON.stringify(options.body) : undefined;
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
const req = https.request(url, {
|
|
54
|
+
method: options.method,
|
|
55
|
+
agent: false,
|
|
56
|
+
timeout: options.timeoutMs,
|
|
57
|
+
headers: {
|
|
58
|
+
Authorization: `Bearer ${options.accessToken}`,
|
|
59
|
+
"x-needle": "cli",
|
|
60
|
+
"Connection": "close",
|
|
61
|
+
...(requestBody ? { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(requestBody) } : {}),
|
|
62
|
+
}
|
|
63
|
+
}, (res) => {
|
|
64
|
+
let text = "";
|
|
65
|
+
res.setEncoding("utf8");
|
|
66
|
+
res.on("data", (/** @type {Buffer|string} */ chunk) => text += chunk);
|
|
67
|
+
res.on("end", () => {
|
|
68
|
+
resolve({
|
|
69
|
+
ok: (res.statusCode || 500) >= 200 && (res.statusCode || 500) < 300,
|
|
70
|
+
status: res.statusCode || 500,
|
|
71
|
+
statusText: res.statusMessage || "",
|
|
72
|
+
text,
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
req.on("timeout", () => req.destroy(new Error("Request timed out")));
|
|
77
|
+
req.on("error", reject);
|
|
78
|
+
if (requestBody) req.write(requestBody);
|
|
79
|
+
req.end();
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
13
83
|
/**
|
|
14
84
|
* @typedef {{loglevel?:"verbose"}} DefaultOptions
|
|
15
85
|
*/
|
|
16
86
|
|
|
87
|
+
/** @typedef {{ ok: boolean, status: number, statusText: string, text: string }} NeedleCloudHttpResponse */
|
|
88
|
+
|
|
17
89
|
/**
|
|
18
90
|
* Replace license string - used for webpack
|
|
19
91
|
* @param {string} code
|
|
@@ -48,37 +120,31 @@ export async function resolveLicense(args = null) {
|
|
|
48
120
|
// If a process.env.NEEDLE_CLOUD_TOKEN is set we want to use this (e.g. via nextjs)
|
|
49
121
|
if (!accessToken) {
|
|
50
122
|
if (process.env.NEEDLE_CLOUD_TOKEN) {
|
|
51
|
-
|
|
123
|
+
logLicense("INFO: Using Needle Cloud access token from NEEDLE_CLOUD_TOKEN environment variable");
|
|
52
124
|
accessToken = process.env.NEEDLE_CLOUD_TOKEN;
|
|
53
125
|
}
|
|
54
126
|
else if (process.env.CI) {
|
|
55
|
-
|
|
127
|
+
logLicense("WARN: Missing NEEDLE_CLOUD_TOKEN for CI environment", "warn");
|
|
56
128
|
}
|
|
57
129
|
}
|
|
58
130
|
|
|
59
131
|
if (accessToken) {
|
|
60
|
-
const
|
|
61
|
-
const url = new URL(`${needleCloudApiEndpoint}/v1/account/get/licenses`);
|
|
62
|
-
const res = await fetch(url, {
|
|
132
|
+
const res = await requestNeedleCloud("/v1/account/get/licenses", {
|
|
63
133
|
method: "GET",
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"x-needle": "cli"
|
|
68
|
-
}
|
|
69
|
-
}).catch(err => {
|
|
134
|
+
accessToken,
|
|
135
|
+
timeoutMs: 10_000,
|
|
136
|
+
}).catch((/** @type {{ message?: string }} */ err) => {
|
|
70
137
|
return { ok: false, error: err.message };
|
|
71
138
|
});
|
|
72
139
|
if ("error" in res) {
|
|
73
|
-
|
|
140
|
+
logLicense(`Could not fetch license from Needle Cloud API (${res.error})`, "error");
|
|
74
141
|
return null;
|
|
75
142
|
}
|
|
76
143
|
if (res.ok) {
|
|
77
|
-
|
|
78
|
-
return tryParseLicense(text);
|
|
144
|
+
return tryParseLicense(res.text);
|
|
79
145
|
}
|
|
80
146
|
else {
|
|
81
|
-
|
|
147
|
+
logLicense(`Could not fetch license from Needle Cloud API (${res.status})`, "error");
|
|
82
148
|
if (process.env.CI) {
|
|
83
149
|
return null;
|
|
84
150
|
}
|
|
@@ -86,26 +152,26 @@ export async function resolveLicense(args = null) {
|
|
|
86
152
|
}
|
|
87
153
|
else if (process.env.CI) {
|
|
88
154
|
const isGithubCI = process.env.GITHUB_ACTIONS;
|
|
89
|
-
let message = "
|
|
155
|
+
let message = "WARN: Missing NEEDLE_CLOUD_TOKEN for CI environment run.";
|
|
90
156
|
if (isGithubCI) {
|
|
91
157
|
const repositoryUrl = process.env.GITHUB_REPOSITORY;
|
|
92
158
|
const url = `${repositoryUrl}/settings/secrets/actions`;
|
|
93
159
|
message += `\nPlease add the token to your GitHub repository secrets: ${url}`;
|
|
94
160
|
}
|
|
95
|
-
|
|
161
|
+
logLicense(message, "warn");
|
|
96
162
|
return null;
|
|
97
163
|
}
|
|
98
164
|
|
|
99
165
|
|
|
100
166
|
if (!canRunCLI(args)) {
|
|
101
|
-
|
|
167
|
+
logLicense("License server CLI is not available. Please use an access token for authorization.", "error");
|
|
102
168
|
return null;
|
|
103
169
|
}
|
|
104
170
|
|
|
105
171
|
// Fallback to use CLI
|
|
106
172
|
// Wait for the server to start
|
|
107
173
|
if (!await waitForLicenseServer(args || undefined)) {
|
|
108
|
-
|
|
174
|
+
logLicense("ERR: Failed to start license server...", "error");
|
|
109
175
|
return null;
|
|
110
176
|
}
|
|
111
177
|
|
|
@@ -116,12 +182,15 @@ export async function resolveLicense(args = null) {
|
|
|
116
182
|
url.searchParams.append("token", accessToken);
|
|
117
183
|
}
|
|
118
184
|
|
|
119
|
-
|
|
185
|
+
const includeFetchLineInSuccessLog = true;
|
|
120
186
|
const timeout = AbortSignal.timeout(10_000);
|
|
121
187
|
const licenseResponse = await fetch(url.toString(), {
|
|
122
188
|
method: "GET",
|
|
123
|
-
signal: timeout
|
|
124
|
-
|
|
189
|
+
signal: timeout,
|
|
190
|
+
headers: {
|
|
191
|
+
"Connection": "close"
|
|
192
|
+
}
|
|
193
|
+
}).catch((/** @type {{ message?: string, cause?: { code?: string } }} */ err) => {
|
|
125
194
|
if (args?.loglevel === "verbose") console.error("Error fetching license", err.message);
|
|
126
195
|
|
|
127
196
|
if (err.cause?.code === "ECONNREFUSED") {
|
|
@@ -133,7 +202,7 @@ export async function resolveLicense(args = null) {
|
|
|
133
202
|
});
|
|
134
203
|
|
|
135
204
|
if (!licenseResponse) {
|
|
136
|
-
|
|
205
|
+
logLicense("WARN: Failed to fetch license", "warn");
|
|
137
206
|
return null;
|
|
138
207
|
}
|
|
139
208
|
else if ("error" in licenseResponse) {
|
|
@@ -142,41 +211,49 @@ export async function resolveLicense(args = null) {
|
|
|
142
211
|
}
|
|
143
212
|
else if (!licenseResponse.ok) {
|
|
144
213
|
if (licenseResponse.status === 500)
|
|
145
|
-
|
|
214
|
+
logLicense(`ERROR: Failed to fetch license (${licenseResponse.status})`, "error");
|
|
146
215
|
else
|
|
147
|
-
|
|
216
|
+
logLicense(`No license found (${licenseResponse.status})`);
|
|
217
|
+
await releaseResponse(licenseResponse);
|
|
148
218
|
return null;
|
|
149
219
|
}
|
|
150
220
|
|
|
151
221
|
const text = await licenseResponse.text();
|
|
152
|
-
return tryParseLicense(text);
|
|
222
|
+
return tryParseLicense(text, { includeFetchLine: includeFetchLineInSuccessLog });
|
|
153
223
|
}
|
|
154
224
|
|
|
155
225
|
|
|
156
226
|
/**
|
|
157
227
|
* @param {string} str License string
|
|
228
|
+
* @param {{includeFetchLine?: boolean}} [options]
|
|
158
229
|
*/
|
|
159
|
-
function tryParseLicense(str) {
|
|
230
|
+
function tryParseLicense(str, options = undefined) {
|
|
160
231
|
try {
|
|
161
232
|
/** @type {{needle_engine_license:string}} */
|
|
162
233
|
const licenseJson = JSON.parse(str);
|
|
163
234
|
if (licenseJson.needle_engine_license) {
|
|
164
|
-
|
|
235
|
+
const success = `INFO: Successfully received \"${licenseJson.needle_engine_license?.toUpperCase()}\" license`;
|
|
236
|
+
if (options?.includeFetchLine) {
|
|
237
|
+
logLicense(`INFO: Fetching license...\n${success}`);
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
logLicense(success);
|
|
241
|
+
}
|
|
165
242
|
return licenseJson.needle_engine_license;
|
|
166
243
|
}
|
|
167
244
|
if ("error" in licenseJson) {
|
|
168
|
-
|
|
245
|
+
logLicense(`ERROR in license check: \"${licenseJson.error}\"`, "error");
|
|
169
246
|
}
|
|
170
247
|
else if (licenseJson.needle_engine_license == null) {
|
|
171
248
|
return null;
|
|
172
249
|
}
|
|
173
250
|
else {
|
|
174
|
-
|
|
251
|
+
logLicense("WARN: Received invalid license. " + JSON.stringify(licenseJson), "warn");
|
|
175
252
|
}
|
|
176
253
|
return null;
|
|
177
254
|
}
|
|
178
|
-
catch (err) {
|
|
179
|
-
|
|
255
|
+
catch (/** @type {unknown} */ err) {
|
|
256
|
+
logLicense("ERROR: Failed to parse license response", "error");
|
|
180
257
|
return null;
|
|
181
258
|
}
|
|
182
259
|
}
|
|
@@ -188,58 +265,50 @@ function tryParseLicense(str) {
|
|
|
188
265
|
*/
|
|
189
266
|
export async function getPublicIdentifier(project_id, opts = undefined) {
|
|
190
267
|
|
|
191
|
-
let accessToken = undefined;
|
|
268
|
+
let accessToken = /** @type {string | undefined} */ (undefined);
|
|
192
269
|
if (!accessToken) {
|
|
193
270
|
|
|
194
|
-
if (opts?.loglevel === "verbose" && process.env.CI)
|
|
271
|
+
if (opts?.loglevel === "verbose" && process.env.CI) logIdentifier("INFO: Running in CI environment");
|
|
195
272
|
|
|
196
273
|
if (process.env.NEEDLE_CLOUD_TOKEN) {
|
|
197
|
-
|
|
274
|
+
logIdentifier("INFO: Using Needle Cloud access token from environment variable");
|
|
198
275
|
accessToken = process.env.NEEDLE_CLOUD_TOKEN;
|
|
199
276
|
}
|
|
200
277
|
|
|
201
278
|
if (accessToken) {
|
|
202
|
-
const url = new URL(`${needleCloudApiEndpoint}/v1/account/public_key`);
|
|
203
279
|
const body = {
|
|
204
280
|
project_id: project_id || process.env.GITHUB_REPOSITORY || undefined,
|
|
205
281
|
machine_id: process.env.GITHUB_REPOSITORY_ID || "unknown",
|
|
206
282
|
}
|
|
207
|
-
const
|
|
208
|
-
const res = await fetch(url, {
|
|
283
|
+
const res = await requestNeedleCloud("/v1/account/public_key", {
|
|
209
284
|
method: "POST",
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
"x-needle": "cli"
|
|
215
|
-
},
|
|
216
|
-
body: JSON.stringify(body),
|
|
217
|
-
}).catch(err => {
|
|
285
|
+
accessToken,
|
|
286
|
+
timeoutMs: 10_000,
|
|
287
|
+
body,
|
|
288
|
+
}).catch((/** @type {{ message?: string }} */ err) => {
|
|
218
289
|
if (opts?.loglevel === "verbose") {
|
|
219
290
|
console.error(err);
|
|
220
291
|
}
|
|
221
292
|
return { ok: false, error: err.message };
|
|
222
293
|
});
|
|
223
294
|
if ("error" in res) {
|
|
224
|
-
|
|
295
|
+
logIdentifier(`Could not fetch project identifier from Needle Cloud API (${res.error})`, "error");
|
|
225
296
|
return null;
|
|
226
297
|
}
|
|
227
298
|
if (res.ok) {
|
|
228
|
-
const text = await res.text();
|
|
229
299
|
try {
|
|
230
300
|
/** @type {{public_key:string}} */
|
|
231
|
-
const json = JSON.parse(text);
|
|
232
|
-
|
|
301
|
+
const json = JSON.parse(res.text);
|
|
302
|
+
logIdentifier(`INFO: Successfully received public project identifier`);
|
|
233
303
|
return json.public_key;
|
|
234
304
|
}
|
|
235
|
-
catch (err) {
|
|
236
|
-
|
|
305
|
+
catch (/** @type {unknown} */ err) {
|
|
306
|
+
logIdentifier("ERROR: Failed to parse project identifier response", "error");
|
|
237
307
|
return null;
|
|
238
308
|
}
|
|
239
309
|
}
|
|
240
310
|
else {
|
|
241
|
-
|
|
242
|
-
console.error(`[needle-identifier] Could not fetch project identifier from Needle Cloud API (${res.status}, ${res.statusText}, ${message})`);
|
|
311
|
+
logIdentifier(`Could not fetch project identifier from Needle Cloud API (${res.status}, ${res.statusText}, ${res.text})`, "error");
|
|
243
312
|
return null;
|
|
244
313
|
}
|
|
245
314
|
}
|
|
@@ -247,7 +316,7 @@ export async function getPublicIdentifier(project_id, opts = undefined) {
|
|
|
247
316
|
|
|
248
317
|
|
|
249
318
|
if (!canRunCLI(opts)) {
|
|
250
|
-
|
|
319
|
+
logLicense("License server CLI is not available. Please use an access token for authorization.", "error");
|
|
251
320
|
return null;
|
|
252
321
|
}
|
|
253
322
|
|
|
@@ -255,18 +324,21 @@ export async function getPublicIdentifier(project_id, opts = undefined) {
|
|
|
255
324
|
|
|
256
325
|
// Wait for the server to start
|
|
257
326
|
if (!await waitForLicenseServer(opts)) {
|
|
258
|
-
|
|
327
|
+
logIdentifier("ERR: Failed to start license server...", "error");
|
|
259
328
|
return null;
|
|
260
329
|
}
|
|
261
330
|
|
|
262
|
-
|
|
331
|
+
logIdentifier(`INFO: Fetching project identifier...`);
|
|
263
332
|
const url = new URL(projectIdentifierUrl);
|
|
264
333
|
if (project_id) url.searchParams.append("project_id", project_id);
|
|
265
334
|
const timeout = AbortSignal.timeout(5_000);
|
|
266
335
|
const res = await fetch(projectIdentifierUrl, {
|
|
267
336
|
method: "GET",
|
|
268
|
-
signal: timeout
|
|
269
|
-
|
|
337
|
+
signal: timeout,
|
|
338
|
+
headers: {
|
|
339
|
+
"Connection": "close"
|
|
340
|
+
}
|
|
341
|
+
}).catch((/** @type {{ message?: string, cause?: { code?: string } }} */ err) => {
|
|
270
342
|
|
|
271
343
|
if (opts?.loglevel === "verbose") {
|
|
272
344
|
console.error(err);
|
|
@@ -281,7 +353,7 @@ export async function getPublicIdentifier(project_id, opts = undefined) {
|
|
|
281
353
|
})
|
|
282
354
|
|
|
283
355
|
if (!res) {
|
|
284
|
-
|
|
356
|
+
logIdentifier("WARN: Failed to fetch project identifier", "warn");
|
|
285
357
|
return null;
|
|
286
358
|
}
|
|
287
359
|
else if ("error" in res) {
|
|
@@ -289,7 +361,8 @@ export async function getPublicIdentifier(project_id, opts = undefined) {
|
|
|
289
361
|
return null;
|
|
290
362
|
}
|
|
291
363
|
else if (!res.ok) {
|
|
292
|
-
|
|
364
|
+
logIdentifier("ERROR: Failed to fetch project identifier", "error");
|
|
365
|
+
await releaseResponse(res);
|
|
293
366
|
return null;
|
|
294
367
|
}
|
|
295
368
|
const text = await res.text();
|
|
@@ -299,7 +372,7 @@ export async function getPublicIdentifier(project_id, opts = undefined) {
|
|
|
299
372
|
const json = JSON.parse(text);
|
|
300
373
|
return json.public_key;
|
|
301
374
|
}
|
|
302
|
-
catch (err) {
|
|
375
|
+
catch (/** @type {unknown} */ err) {
|
|
303
376
|
// TODO: report error to backend
|
|
304
377
|
if (opts?.loglevel === "verbose") console.error(err);
|
|
305
378
|
return null;
|
|
@@ -307,6 +380,7 @@ export async function getPublicIdentifier(project_id, opts = undefined) {
|
|
|
307
380
|
};
|
|
308
381
|
|
|
309
382
|
|
|
383
|
+
/** @type {boolean | undefined} */
|
|
310
384
|
let licenseServerStarted = undefined;
|
|
311
385
|
|
|
312
386
|
/**
|
|
@@ -333,7 +407,7 @@ async function waitForLicenseServer(opts) {
|
|
|
333
407
|
const response = await fetch_WaitForServer(localServerUrl, {
|
|
334
408
|
method: "GET",
|
|
335
409
|
signal: timeout
|
|
336
|
-
}).catch(err => {
|
|
410
|
+
}).catch((/** @type {{ message?: string, stack?: string }} */ err) => {
|
|
337
411
|
if (opts?.loglevel === "verbose") {
|
|
338
412
|
console.error("ERROR connecting to local license server url at " + localServerUrl, err.message);
|
|
339
413
|
}
|
|
@@ -383,12 +457,12 @@ async function waitForLicenseServer(opts) {
|
|
|
383
457
|
*/
|
|
384
458
|
function canRunCLI(opts) {
|
|
385
459
|
if (process.env.CI) {
|
|
386
|
-
if (opts?.loglevel === "verbose")
|
|
460
|
+
if (opts?.loglevel === "verbose") logLicense("INFO: Running in CI environment");
|
|
387
461
|
return false; // We cannot run the CLI in CI environments
|
|
388
462
|
}
|
|
389
463
|
// Note: the .stackblitz directory doesnt always exist it seems
|
|
390
464
|
if (existsSync("/home/.stackblitz")) {
|
|
391
|
-
if (opts?.loglevel === "verbose")
|
|
465
|
+
if (opts?.loglevel === "verbose") logLicense("INFO: Running in Stackblitz environment");
|
|
392
466
|
return false;
|
|
393
467
|
}
|
|
394
468
|
// Default to true:
|
|
@@ -399,9 +473,10 @@ function canRunCLI(opts) {
|
|
|
399
473
|
* @param {string} processName
|
|
400
474
|
* @param {string[]} args
|
|
401
475
|
* @param {DefaultOptions | undefined} opts
|
|
476
|
+
* @returns {Promise<boolean>}
|
|
402
477
|
*/
|
|
403
478
|
async function runCommand(processName, args, opts) {
|
|
404
|
-
if (opts?.loglevel === "verbose")
|
|
479
|
+
if (opts?.loglevel === "verbose") logLicense(`INFO: Running command: ${processName} ${args.join(" ")}`);
|
|
405
480
|
const process = spawn(processName, [...args], {
|
|
406
481
|
shell: true,
|
|
407
482
|
timeout: 30_000,
|
|
@@ -411,11 +486,11 @@ async function runCommand(processName, args, opts) {
|
|
|
411
486
|
return new Promise((resolve, _reject) => {
|
|
412
487
|
process.on('close', (code) => {
|
|
413
488
|
if (opts?.loglevel === "verbose")
|
|
414
|
-
|
|
489
|
+
logLicense(`INFO: \"${processName}\" process exited with code ${code}`);
|
|
415
490
|
if (code === 0 || code === null || code === undefined) {
|
|
416
491
|
resolve(true);
|
|
417
492
|
} else {
|
|
418
|
-
|
|
493
|
+
logLicense(`WARN: \"${processName}\" process exited with code ${code}\nProcess Arguments: ${args.join(" ")}`, "warn");
|
|
419
494
|
resolve(false);
|
|
420
495
|
}
|
|
421
496
|
});
|
|
@@ -440,7 +515,7 @@ function fetch_WaitForServer(url, options) {
|
|
|
440
515
|
if (!options) { options = {}; }
|
|
441
516
|
module.get(url, options, (res) => {
|
|
442
517
|
let data = '';
|
|
443
|
-
res.on('data', (chunk) => {
|
|
518
|
+
res.on('data', (/** @type {Buffer|string} */ chunk) => {
|
|
444
519
|
data += chunk;
|
|
445
520
|
});
|
|
446
521
|
res.on('end', () => {
|