lecodes-cli 0.19.2 → 0.20.0
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/README.md +1 -0
- package/dist/index.js +458 -280
- package/package.json +5 -5
- package/runtime/scene-harness.json +1 -1
- package/runtime/sdk-types.json +1 -1
- package/runtime/web/assets/Roboto-Variable-DHm9jpd-.woff2 +0 -0
- package/runtime/web/assets/__vite-browser-external-BIHI7g3E.js +1 -0
- package/runtime/web/assets/basis-C64VHDVD.js +1 -0
- package/runtime/web/assets/basis_transcoder-VXdx5NbI.wasm +0 -0
- package/runtime/web/assets/createViewerLite-BvHobVhp.js +852 -0
- package/runtime/web/assets/draco-BiISTFcR.js +118 -0
- package/runtime/web/assets/draco_decoder-DsQ12WqX.wasm +0 -0
- package/runtime/web/assets/index-CfNCCBjN.js +2 -0
- package/runtime/web/assets/mapViewImpl-B2JcES8l.js +810 -0
- package/runtime/web/assets/maplibre-gl-worker-CJfwIrte.js +8 -0
- package/runtime/web/assets/neutral_ibl128-D-lzdkLN.ktx +0 -0
- package/runtime/web/assets/worker-Caf-yYEI.js +2 -0
- package/runtime/web/embed.html +32 -0
- package/runtime/web/embed.js +171 -0
- package/src/commands/app.ts +6 -1
- package/src/commands/appDesktop.ts +15 -2
- package/src/commands/appShared.ts +97 -3
- package/src/commands/appTemplates.ts +28 -4
- package/src/commands/desktop.ts +6 -1
- package/src/commands/dev.ts +22 -0
- package/src/commands/projectTemplates.ts +4 -3
- package/src/commands/render.ts +5 -3
- package/src/commands/test.ts +2 -1
- package/src/desktopRenderer.ts +15 -2
- package/src/dev/devServer.ts +47 -6
- package/src/dev/webRunner.ts +22 -0
- package/src/index.ts +3 -0
package/dist/index.js
CHANGED
|
@@ -3177,7 +3177,7 @@ var require_source_map_support = __commonJS((exports, module) => {
|
|
|
3177
3177
|
|
|
3178
3178
|
// ../../node_modules/.bun/typescript@5.8.3/node_modules/typescript/lib/typescript.js
|
|
3179
3179
|
var require_typescript = __commonJS((exports, module) => {
|
|
3180
|
-
var __dirname = "
|
|
3180
|
+
var __dirname = "/Users/den/Desktop/Ingenuity/le-codes/node_modules/.bun/typescript@5.8.3/node_modules/typescript/lib", __filename = "/Users/den/Desktop/Ingenuity/le-codes/node_modules/.bun/typescript@5.8.3/node_modules/typescript/lib/typescript.js";
|
|
3181
3181
|
/*! *****************************************************************************
|
|
3182
3182
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3183
3183
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
|
@@ -172193,6 +172193,8 @@ var compileProject = async (opts) => {
|
|
|
172193
172193
|
}
|
|
172194
172194
|
} else if (e.path.toLowerCase().endsWith(".svg")) {
|
|
172195
172195
|
files[e.path] = `export default SvgSource(\`${e.text ?? ""}\`)`;
|
|
172196
|
+
} else if (e.path.toLowerCase().endsWith(".json")) {
|
|
172197
|
+
files[e.path] = `export default ${e.text?.trim() || "null"}`;
|
|
172196
172198
|
} else {
|
|
172197
172199
|
files[e.path] = e.text ?? "";
|
|
172198
172200
|
}
|
|
@@ -214125,26 +214127,26 @@ var init_esm30 = __esm(() => {
|
|
|
214125
214127
|
|
|
214126
214128
|
// src/types.ts
|
|
214127
214129
|
import { dirname as dirname13, join as join22, relative as relative3, sep } from "node:path";
|
|
214128
|
-
import { existsSync as existsSync21, mkdirSync as mkdirSync15, readdirSync as
|
|
214130
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync15, readdirSync as readdirSync11, readFileSync as readFileSync18, rmSync as rmSync8, statSync as statSync9, writeFileSync as writeFileSync17 } from "node:fs";
|
|
214129
214131
|
import { createRequire as createRequire4 } from "node:module";
|
|
214130
214132
|
var TSCONFIG, listBundleFiles = (dir, base = dir) => {
|
|
214131
214133
|
if (!existsSync21(dir))
|
|
214132
214134
|
return [];
|
|
214133
214135
|
const out = [];
|
|
214134
|
-
for (const name of
|
|
214136
|
+
for (const name of readdirSync11(dir)) {
|
|
214135
214137
|
const path2 = join22(dir, name);
|
|
214136
|
-
if (
|
|
214138
|
+
if (statSync9(path2).isDirectory())
|
|
214137
214139
|
out.push(...listBundleFiles(path2, base));
|
|
214138
214140
|
else
|
|
214139
214141
|
out.push(relative3(base, path2).split(sep).join("/"));
|
|
214140
214142
|
}
|
|
214141
214143
|
return out;
|
|
214142
214144
|
}, pruneEmptyDirs = (dir, root) => {
|
|
214143
|
-
if (!existsSync21(dir) || !
|
|
214145
|
+
if (!existsSync21(dir) || !statSync9(dir).isDirectory())
|
|
214144
214146
|
return;
|
|
214145
|
-
for (const name of
|
|
214147
|
+
for (const name of readdirSync11(dir))
|
|
214146
214148
|
pruneEmptyDirs(join22(dir, name), root);
|
|
214147
|
-
if (dir !== root &&
|
|
214149
|
+
if (dir !== root && readdirSync11(dir).length === 0)
|
|
214148
214150
|
rmSync8(dir, { recursive: true });
|
|
214149
214151
|
}, writeTypeBundle = (root, bundle) => {
|
|
214150
214152
|
const typesDir = join22(root, LECODES_DIR, "types");
|
|
@@ -214230,13 +214232,13 @@ var init_types4 = __esm(() => {
|
|
|
214230
214232
|
|
|
214231
214233
|
// src/compile/designCompile.ts
|
|
214232
214234
|
import { readFileSync as readFileSync19 } from "node:fs";
|
|
214233
|
-
import { basename as
|
|
214235
|
+
import { basename as basename10 } from "node:path";
|
|
214234
214236
|
var LOCAL_ASSET_SCHEME = "lecodesfile://", compileDesignScreen = async (opts) => {
|
|
214235
214237
|
const { root, manifest, designDir, designKey, screenId, state } = opts;
|
|
214236
214238
|
const entries = [];
|
|
214237
214239
|
const scan2 = scanLocal(root, { ignore: loadIgnore(root), tracked: new Set(Object.keys(manifest?.files ?? {})) });
|
|
214238
214240
|
for (const file of scan2.files) {
|
|
214239
|
-
const type = manifest?.files[file.path]?.type ?? classifyKind(
|
|
214241
|
+
const type = manifest?.files[file.path]?.type ?? classifyKind(basename10(file.path));
|
|
214240
214242
|
if (type === "resource") {
|
|
214241
214243
|
entries.push({
|
|
214242
214244
|
path: file.path,
|
|
@@ -214872,8 +214874,8 @@ __export(exports_design, {
|
|
|
214872
214874
|
flushDesignComments: () => flushDesignComments,
|
|
214873
214875
|
design: () => design
|
|
214874
214876
|
});
|
|
214875
|
-
import { existsSync as existsSync24, mkdirSync as mkdirSync18, readFileSync as readFileSync21, readdirSync as
|
|
214876
|
-
import { basename as
|
|
214877
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync18, readFileSync as readFileSync21, readdirSync as readdirSync14, writeFileSync as writeFileSync19, appendFileSync } from "node:fs";
|
|
214878
|
+
import { basename as basename11, join as join25 } from "node:path";
|
|
214877
214879
|
var DEFAULT_DIR = "design", DEFAULT_PORT = 4477, getContext = (args) => {
|
|
214878
214880
|
let root;
|
|
214879
214881
|
let manifest;
|
|
@@ -214888,7 +214890,7 @@ var DEFAULT_DIR = "design", DEFAULT_PORT = 4477, getContext = (args) => {
|
|
|
214888
214890
|
return {
|
|
214889
214891
|
root,
|
|
214890
214892
|
manifest,
|
|
214891
|
-
name: manifest?.name ??
|
|
214893
|
+
name: manifest?.name ?? basename11(root),
|
|
214892
214894
|
dirName,
|
|
214893
214895
|
designDir: join25(root, dirName),
|
|
214894
214896
|
designKey: "/" + dirName.replace(/\\/g, "/")
|
|
@@ -214929,7 +214931,7 @@ var DEFAULT_DIR = "design", DEFAULT_PORT = 4477, getContext = (args) => {
|
|
|
214929
214931
|
const dir = join25(designDir, "screens");
|
|
214930
214932
|
if (!existsSync24(dir))
|
|
214931
214933
|
return [];
|
|
214932
|
-
return
|
|
214934
|
+
return readdirSync14(dir).filter((f3) => f3.endsWith(".ts") && !f3.startsWith(".")).map((f3) => f3.slice(0, -3)).sort();
|
|
214933
214935
|
}, writeMcpConfig = (ctx, port) => {
|
|
214934
214936
|
const path2 = join25(ctx.root, ".mcp.json");
|
|
214935
214937
|
const entry = { type: "http", url: `http://localhost:${port}/mcp` };
|
|
@@ -216539,7 +216541,7 @@ var require_main = __commonJS((exports, module) => {
|
|
|
216539
216541
|
// package.json
|
|
216540
216542
|
var package_default = {
|
|
216541
216543
|
name: "lecodes-cli",
|
|
216542
|
-
version: "0.
|
|
216544
|
+
version: "0.20.0",
|
|
216543
216545
|
dependencies: {
|
|
216544
216546
|
"@letary/chisel": "^0.10.0",
|
|
216545
216547
|
jimp: "^1.6.1",
|
|
@@ -216556,7 +216558,7 @@ var package_default = {
|
|
|
216556
216558
|
},
|
|
216557
216559
|
peerDependencies: {
|
|
216558
216560
|
"lecodes-design": "^0.9.0",
|
|
216559
|
-
"lecodes-renderer": "^0.
|
|
216561
|
+
"lecodes-renderer": "^0.20.0",
|
|
216560
216562
|
"lecodes-3d-editor": "^0.7.0",
|
|
216561
216563
|
"lecodes-assets": "^0.2.1"
|
|
216562
216564
|
},
|
|
@@ -216609,7 +216611,7 @@ var package_default = {
|
|
|
216609
216611
|
init_manifest();
|
|
216610
216612
|
init_config();
|
|
216611
216613
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
216612
|
-
import { cpSync as cpSync4, existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as readFileSync17, readdirSync as
|
|
216614
|
+
import { cpSync as cpSync4, existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as readFileSync17, readdirSync as readdirSync10, rmSync as rmSync7, statSync as statSync8, writeFileSync as writeFileSync16 } from "node:fs";
|
|
216613
216615
|
import { homedir as homedir7 } from "node:os";
|
|
216614
216616
|
import { basename as basename8, dirname as dirname12, join as join21, resolve as resolve8 } from "node:path";
|
|
216615
216617
|
|
|
@@ -217036,12 +217038,13 @@ init_manifest();
|
|
|
217036
217038
|
init_ignore();
|
|
217037
217039
|
init_util();
|
|
217038
217040
|
import { execFileSync } from "node:child_process";
|
|
217039
|
-
import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync13, writeFileSync as writeFileSync9 } from "node:fs";
|
|
217041
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync8, readdirSync as readdirSync5, readFileSync as readFileSync13, statSync as statSync3, writeFileSync as writeFileSync9 } from "node:fs";
|
|
217040
217042
|
import { homedir as homedir4 } from "node:os";
|
|
217041
217043
|
import { dirname as dirname8, join as join15, resolve as resolve2 } from "node:path";
|
|
217042
217044
|
var FIRST_PARTY_PLUGINS = {
|
|
217043
217045
|
camera: "letary/lecodes-plugins",
|
|
217044
217046
|
"qr-scanner": "letary/lecodes-plugins",
|
|
217047
|
+
map: "letary/lecodes-plugins",
|
|
217045
217048
|
geolocation: "letary/lecodes-plugins",
|
|
217046
217049
|
push: "letary/lecodes-plugins"
|
|
217047
217050
|
};
|
|
@@ -217072,6 +217075,7 @@ var desktopDefaultViewport = (root) => {
|
|
|
217072
217075
|
height: cfg.desktop.window?.height ?? DESKTOP_DEFAULT_WINDOW.height
|
|
217073
217076
|
};
|
|
217074
217077
|
};
|
|
217078
|
+
var swiftPackageName = (url) => (url.replace(/\/+$/, "").split("/").pop() ?? url).replace(/\.git$/, "");
|
|
217075
217079
|
var readJson = (path) => {
|
|
217076
217080
|
if (!existsSync13(path))
|
|
217077
217081
|
return null;
|
|
@@ -217225,7 +217229,8 @@ var ensureRepo = (repo, wantTag, lock) => {
|
|
|
217225
217229
|
git(cache, "checkout", "--quiet", "--detach", commit);
|
|
217226
217230
|
return { dir: cache, tag: tag ?? "unknown", commit };
|
|
217227
217231
|
};
|
|
217228
|
-
var
|
|
217232
|
+
var PLUGIN_PLATFORM_LABEL = { ios: "iOS", android: "Android", desktop: "desktop" };
|
|
217233
|
+
function resolvePlugin(id, spec, lock, platform, opts) {
|
|
217229
217234
|
let repo;
|
|
217230
217235
|
let subdir;
|
|
217231
217236
|
let wantTag = null;
|
|
@@ -217249,7 +217254,9 @@ var resolvePlugin = (id, spec, lock, platform) => {
|
|
|
217249
217254
|
if (manifest.id !== id)
|
|
217250
217255
|
throw new CliError(`Plugin "${id}": manifest declares id "${manifest.id}"`);
|
|
217251
217256
|
if (!manifest[platform]) {
|
|
217252
|
-
|
|
217257
|
+
if (opts?.optional)
|
|
217258
|
+
return null;
|
|
217259
|
+
throw new CliError(`Plugin "${id}" does not support ${PLUGIN_PLATFORM_LABEL[platform]} (manifest "${platform}" is null)`);
|
|
217253
217260
|
}
|
|
217254
217261
|
if (spec.startsWith("github:")) {
|
|
217255
217262
|
const names = [...manifest.provides?.views ?? [], ...manifest.provides?.services ?? []];
|
|
@@ -217264,7 +217271,7 @@ var resolvePlugin = (id, spec, lock, platform) => {
|
|
|
217264
217271
|
manifest,
|
|
217265
217272
|
lock: { repo, tag: checkout.tag, commit: checkout.commit, version: manifest.version ?? "unknown" }
|
|
217266
217273
|
};
|
|
217267
|
-
}
|
|
217274
|
+
}
|
|
217268
217275
|
var latestPluginTag = (repo) => {
|
|
217269
217276
|
try {
|
|
217270
217277
|
return ensureRepo(repo, null, undefined).tag;
|
|
@@ -217272,6 +217279,55 @@ var latestPluginTag = (repo) => {
|
|
|
217272
217279
|
return null;
|
|
217273
217280
|
}
|
|
217274
217281
|
};
|
|
217282
|
+
var desktopPluginTarget = () => `${process.platform}-${process.arch}`;
|
|
217283
|
+
var isDesktopPluginLibrary = (name) => {
|
|
217284
|
+
const n = name.toLowerCase();
|
|
217285
|
+
return process.platform === "win32" ? n.endsWith(".dll") : n.endsWith(".so");
|
|
217286
|
+
};
|
|
217287
|
+
var desktopPluginLibraries = (root, opts = {}) => {
|
|
217288
|
+
const dirs = [];
|
|
217289
|
+
const files = [];
|
|
217290
|
+
const local = join15(root, "plugins");
|
|
217291
|
+
if (existsSync13(local) && statSync3(local).isDirectory()) {
|
|
217292
|
+
dirs.push(local);
|
|
217293
|
+
for (const f2 of readdirSync5(local))
|
|
217294
|
+
if (isDesktopPluginLibrary(f2))
|
|
217295
|
+
files.push(join15(local, f2));
|
|
217296
|
+
}
|
|
217297
|
+
const config = readJson(join15(root, "app.json"));
|
|
217298
|
+
const specs = Object.entries(config?.plugins ?? {});
|
|
217299
|
+
if (specs.length === 0)
|
|
217300
|
+
return { dirs, files };
|
|
217301
|
+
const lock = readJson(join15(root, "plugins.lock.json"))?.plugins ?? {};
|
|
217302
|
+
const target = desktopPluginTarget();
|
|
217303
|
+
for (const [id, spec] of specs) {
|
|
217304
|
+
let plugin;
|
|
217305
|
+
try {
|
|
217306
|
+
plugin = resolvePlugin(id, spec, lock[id], "desktop", { optional: true });
|
|
217307
|
+
} catch (e) {
|
|
217308
|
+
if (opts.strict)
|
|
217309
|
+
throw e;
|
|
217310
|
+
warn(`Plugin "${id}": ${e.message} — skipped for this desktop run`);
|
|
217311
|
+
continue;
|
|
217312
|
+
}
|
|
217313
|
+
const rel = plugin?.manifest.desktop?.library?.[target];
|
|
217314
|
+
if (!plugin || !rel)
|
|
217315
|
+
continue;
|
|
217316
|
+
const abs = resolve2(plugin.dir, rel);
|
|
217317
|
+
if (!existsSync13(abs)) {
|
|
217318
|
+
const msg = `Plugin "${id}": desktop library ${abs} is missing (manifest desktop.library["${target}"])`;
|
|
217319
|
+
if (opts.strict)
|
|
217320
|
+
throw new CliError(msg);
|
|
217321
|
+
warn(`${msg} — skipped for this desktop run`);
|
|
217322
|
+
continue;
|
|
217323
|
+
}
|
|
217324
|
+
files.push(abs);
|
|
217325
|
+
const dir = dirname8(abs);
|
|
217326
|
+
if (!dirs.includes(dir))
|
|
217327
|
+
dirs.push(dir);
|
|
217328
|
+
}
|
|
217329
|
+
return { dirs, files };
|
|
217330
|
+
};
|
|
217275
217331
|
|
|
217276
217332
|
// src/commands/compile.ts
|
|
217277
217333
|
init_util();
|
|
@@ -218076,13 +218132,31 @@ var APP_ICON_JSON = `{
|
|
|
218076
218132
|
`;
|
|
218077
218133
|
var runtimePackageTemplate = (sdkVersion, variant, plugins) => {
|
|
218078
218134
|
const product = `LeCodesSDK-${variant}`;
|
|
218079
|
-
const
|
|
218135
|
+
const packages = new Map;
|
|
218136
|
+
for (const p of plugins) {
|
|
218137
|
+
for (const pkg of p.packages ?? []) {
|
|
218138
|
+
const prior = packages.get(pkg.url);
|
|
218139
|
+
if (prior && (prior.exact !== pkg.exact || prior.from !== pkg.from)) {
|
|
218140
|
+
throw new Error(`Plugin "${p.id}" pins ${pkg.url} at ${pkg.exact ?? `from ${pkg.from}`} but another plugin pins ${prior.exact ?? `from ${prior.from}`} — the shell can link one version.`);
|
|
218141
|
+
}
|
|
218142
|
+
packages.set(pkg.url, pkg);
|
|
218143
|
+
}
|
|
218144
|
+
}
|
|
218145
|
+
const packageDecls = [...packages.values()].map((pkg) => `
|
|
218146
|
+
.package(url: "${pkg.url}", ${pkg.exact ? `exact: "${pkg.exact}"` : `from: "${pkg.from}"`}),`).join("");
|
|
218147
|
+
const pluginTargets = plugins.map((p) => {
|
|
218148
|
+
const deps = [
|
|
218149
|
+
`.product(name: "${product}", package: "lecodes-ios-sdk")`,
|
|
218150
|
+
...(p.packages ?? []).flatMap((pkg) => pkg.products.map((name) => `.product(name: "${name}", package: "${swiftPackageName(pkg.url)}")`))
|
|
218151
|
+
];
|
|
218152
|
+
return `
|
|
218080
218153
|
// plugin: ${p.id} (vendored — see plugins.lock.json)
|
|
218081
218154
|
.target(
|
|
218082
218155
|
name: "${p.module}",
|
|
218083
|
-
dependencies: [.
|
|
218156
|
+
dependencies: [${deps.join(", ")}],
|
|
218084
218157
|
path: "Sources/${p.module}"
|
|
218085
|
-
)
|
|
218158
|
+
),`;
|
|
218159
|
+
}).join("");
|
|
218086
218160
|
const runtimeDeps = [`.product(name: "${product}", package: "lecodes-ios-sdk")`, ...plugins.map((p) => `"${p.module}"`)];
|
|
218087
218161
|
return `// swift-tools-version:5.9
|
|
218088
218162
|
//
|
|
@@ -218101,7 +218175,7 @@ let package = Package(
|
|
|
218101
218175
|
.library(name: "LeCodesRuntime", targets: ["LeCodesRuntime"]),
|
|
218102
218176
|
],
|
|
218103
218177
|
dependencies: [
|
|
218104
|
-
.package(url: "https://github.com/letary/lecodes-ios-sdk.git", exact: "${sdkVersion}")
|
|
218178
|
+
.package(url: "https://github.com/letary/lecodes-ios-sdk.git", exact: "${sdkVersion}"),${packageDecls}
|
|
218105
218179
|
],
|
|
218106
218180
|
targets: [
|
|
218107
218181
|
.target(
|
|
@@ -218247,7 +218321,7 @@ buildNumber) — edit it there, then re-run \`lecodes app sync\`. Plugins are ma
|
|
|
218247
218321
|
init_manifest();
|
|
218248
218322
|
import { execFileSync as execFileSync2, spawn, spawnSync as spawnSync3 } from "node:child_process";
|
|
218249
218323
|
import { createHash as createHash6 } from "node:crypto";
|
|
218250
|
-
import { chmodSync, cpSync, existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync15, readdirSync as
|
|
218324
|
+
import { chmodSync, cpSync, existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync15, readdirSync as readdirSync6, renameSync as renameSync2, rmSync as rmSync3, statSync as statSync4, writeFileSync as writeFileSync12 } from "node:fs";
|
|
218251
218325
|
import { homedir as homedir5 } from "node:os";
|
|
218252
218326
|
import { basename as basename5, dirname as dirname10, join as join17 } from "node:path";
|
|
218253
218327
|
init_util();
|
|
@@ -219494,7 +219568,7 @@ var syncAndroid = async (root, config, prior) => {
|
|
|
219494
219568
|
}
|
|
219495
219569
|
const namespace = register.split(".").slice(0, -1).join(".");
|
|
219496
219570
|
const libsDir = join17(dest, "libs");
|
|
219497
|
-
const aarNames = existsSync16(libsDir) ?
|
|
219571
|
+
const aarNames = existsSync16(libsDir) ? readdirSync6(libsDir).filter((f3) => f3.endsWith(".aar")) : [];
|
|
219498
219572
|
for (const aar of aarNames) {
|
|
219499
219573
|
const base = aar.replace(/\.aar$/, "");
|
|
219500
219574
|
const wrapDir = join17(libsDir, base);
|
|
@@ -219510,8 +219584,8 @@ var syncAndroid = async (root, config, prior) => {
|
|
|
219510
219584
|
log(`${c.green("plugin")} ${id}@${plugin.lock.version} (${plugin.lock.tag} → plugins/${module})`);
|
|
219511
219585
|
}
|
|
219512
219586
|
const keep = new Set(runtimePlugins.map((p2) => p2.module));
|
|
219513
|
-
for (const entry of existsSync16(pluginsDir) ?
|
|
219514
|
-
if (!keep.has(entry) &&
|
|
219587
|
+
for (const entry of existsSync16(pluginsDir) ? readdirSync6(pluginsDir) : []) {
|
|
219588
|
+
if (!keep.has(entry) && statSync4(join17(pluginsDir, entry)).isDirectory()) {
|
|
219515
219589
|
rmrf(join17(pluginsDir, entry));
|
|
219516
219590
|
log(`${c.yellow("removed")} android/plugins/${entry} (plugin uninstalled)`);
|
|
219517
219591
|
}
|
|
@@ -219676,7 +219750,7 @@ var buildAndroid = async (args) => {
|
|
|
219676
219750
|
for (const dir of [apkDir, aabDir]) {
|
|
219677
219751
|
if (!existsSync16(dir))
|
|
219678
219752
|
continue;
|
|
219679
|
-
for (const f3 of
|
|
219753
|
+
for (const f3 of readdirSync6(dir)) {
|
|
219680
219754
|
if (f3.endsWith(".apk") || f3.endsWith(".aab"))
|
|
219681
219755
|
outputs.push(join17(dir, f3));
|
|
219682
219756
|
}
|
|
@@ -219733,7 +219807,7 @@ var doctorAndroidChecks = async (root, config, check) => {
|
|
|
219733
219807
|
const validVariant = requestedVariant === "auto" || SDK_VARIANTS.includes(requestedVariant);
|
|
219734
219808
|
check(validVariant, `android.variant "${requestedVariant}"`, `use "auto" or one of ${SDK_VARIANTS.join(", ")}`);
|
|
219735
219809
|
const wrapperJar = join17(androidDir, "gradle", "wrapper", "gradle-wrapper.jar");
|
|
219736
|
-
check(existsSync16(wrapperJar) &&
|
|
219810
|
+
check(existsSync16(wrapperJar) && statSync4(wrapperJar).size > 0, "Gradle wrapper jar", `run \`gradle wrapper --gradle-version ${GRADLE_VERSION}\` in android/ (or let Android Studio repair it)`);
|
|
219737
219811
|
check(existsSync16(join17(androidDir, "app", "src", "main", "assets", "app.js")), "Bundled app.js", "run `lecodes app sync`");
|
|
219738
219812
|
const linked = shellSdkVersionAndroid(androidDir);
|
|
219739
219813
|
const pin = config.android?.sdk ?? "latest";
|
|
@@ -219756,14 +219830,14 @@ var doctorAndroidChecks = async (root, config, check) => {
|
|
|
219756
219830
|
|
|
219757
219831
|
// src/commands/appDesktop.ts
|
|
219758
219832
|
import { execFileSync as execFileSync5, spawn as spawn4 } from "node:child_process";
|
|
219759
|
-
import { cpSync as cpSync3, existsSync as existsSync19, mkdirSync as mkdirSync13, readdirSync as
|
|
219833
|
+
import { cpSync as cpSync3, existsSync as existsSync19, mkdirSync as mkdirSync13, readdirSync as readdirSync9, rmSync as rmSync6, statSync as statSync7, writeFileSync as writeFileSync15 } from "node:fs";
|
|
219760
219834
|
import { basename as basename7, dirname as dirname11, join as join20, resolve as resolve7 } from "node:path";
|
|
219761
219835
|
|
|
219762
219836
|
// src/desktopRenderer.ts
|
|
219763
219837
|
import { execFileSync as execFileSync3, spawn as spawn2, spawnSync as spawnSync4 } from "node:child_process";
|
|
219764
|
-
import { copyFileSync, existsSync as existsSync17, mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync2, readdirSync as
|
|
219838
|
+
import { copyFileSync, existsSync as existsSync17, mkdirSync as mkdirSync11, mkdtempSync as mkdtempSync2, readdirSync as readdirSync7, readFileSync as readFileSync16, rmSync as rmSync4, statSync as statSync5, writeFileSync as writeFileSync13 } from "node:fs";
|
|
219765
219839
|
import { homedir as homedir6, tmpdir as tmpdir2 } from "node:os";
|
|
219766
|
-
import { join as join18, resolve as resolve5 } from "node:path";
|
|
219840
|
+
import { delimiter, join as join18, resolve as resolve5 } from "node:path";
|
|
219767
219841
|
init_util();
|
|
219768
219842
|
|
|
219769
219843
|
// ../viewer-lite/src/sourcemapError.ts
|
|
@@ -219883,7 +219957,7 @@ var isMac = () => process.platform === "darwin";
|
|
|
219883
219957
|
var exeName = () => process.platform === "win32" ? "lecodes-desktop.exe" : isMac() ? "lecodes-app" : "lecodes-desktop";
|
|
219884
219958
|
var findExe = (dir) => {
|
|
219885
219959
|
const name = exeName();
|
|
219886
|
-
for (const entry of
|
|
219960
|
+
for (const entry of readdirSync7(dir, { withFileTypes: true })) {
|
|
219887
219961
|
const p2 = join18(dir, entry.name);
|
|
219888
219962
|
if (entry.isFile() && entry.name === name)
|
|
219889
219963
|
return p2;
|
|
@@ -219899,7 +219973,7 @@ var cacheRoot2 = () => join18(homedir6(), ".lecodes", "renderer");
|
|
|
219899
219973
|
var currentFile = () => join18(cacheRoot2(), "current.json");
|
|
219900
219974
|
var installedDesktopVersions = () => {
|
|
219901
219975
|
try {
|
|
219902
|
-
return
|
|
219976
|
+
return readdirSync7(cacheRoot2(), { withFileTypes: true }).filter((e2) => e2.isDirectory() && e2.name.startsWith("desktop-")).map((e2) => e2.name.slice("desktop-".length)).filter((v) => findExe(join18(cacheRoot2(), `desktop-${v}`)) !== null).sort(semverNewer);
|
|
219903
219977
|
} catch {
|
|
219904
219978
|
return [];
|
|
219905
219979
|
}
|
|
@@ -219924,7 +219998,7 @@ var extractDmg = (archive, stage) => {
|
|
|
219924
219998
|
mkdirSync11(mount, { recursive: true });
|
|
219925
219999
|
execFileSync3("hdiutil", ["attach", "-nobrowse", "-readonly", "-quiet", "-mountpoint", mount, archive]);
|
|
219926
220000
|
try {
|
|
219927
|
-
const app =
|
|
220001
|
+
const app = readdirSync7(mount).find((n2) => n2.endsWith(".app"));
|
|
219928
220002
|
if (!app)
|
|
219929
220003
|
throw new CliError("The downloaded DMG holds no .app bundle.");
|
|
219930
220004
|
execFileSync3("cp", ["-R", join18(mount, app), join18(stage, app)]);
|
|
@@ -220045,8 +220119,12 @@ var updateDesktop = async () => {
|
|
|
220045
220119
|
else
|
|
220046
220120
|
note(`Desktop renderer set to ${latest} (was ${before}).`);
|
|
220047
220121
|
};
|
|
220122
|
+
var pluginEnv = (dirs) => {
|
|
220123
|
+
const all = [...dirs ?? [], ...process.env.CREATOR_PLUGIN_DIRS ? [process.env.CREATOR_PLUGIN_DIRS] : []];
|
|
220124
|
+
return all.length > 0 ? { CREATOR_PLUGIN_DIRS: all.join(delimiter) } : {};
|
|
220125
|
+
};
|
|
220048
220126
|
var windowEnv = (opts) => {
|
|
220049
|
-
const env = {};
|
|
220127
|
+
const env = { ...pluginEnv(opts.pluginDirs) };
|
|
220050
220128
|
const width = opts.width ?? (opts.height !== undefined ? 1280 : undefined);
|
|
220051
220129
|
const height = opts.height ?? (opts.width !== undefined ? 720 : undefined);
|
|
220052
220130
|
if (width && height)
|
|
@@ -220090,7 +220168,7 @@ var stageBundle = (js, resources) => {
|
|
|
220090
220168
|
const runDir = mkdtempSync2(join18(tmpdir2(), "lecodes-render-"));
|
|
220091
220169
|
writeFileSync13(join18(runDir, "app.js"), js);
|
|
220092
220170
|
for (const r2 of resources) {
|
|
220093
|
-
if (r2.absPath && existsSync17(r2.absPath) &&
|
|
220171
|
+
if (r2.absPath && existsSync17(r2.absPath) && statSync5(r2.absPath).isFile()) {
|
|
220094
220172
|
copyFileSync(r2.absPath, join18(runDir, r2.name));
|
|
220095
220173
|
}
|
|
220096
220174
|
}
|
|
@@ -220182,6 +220260,7 @@ var runDesktopRender = async (js, resources, opts) => {
|
|
|
220182
220260
|
env.CREATOR_CAMERA = opts.camera;
|
|
220183
220261
|
if (opts.view)
|
|
220184
220262
|
env.CREATOR_VIEW = opts.view;
|
|
220263
|
+
Object.assign(env, pluginEnv(opts.pluginDirs));
|
|
220185
220264
|
const demangle = makeStackDemangler(js) ?? ((text) => text);
|
|
220186
220265
|
return await new Promise((done, fail) => {
|
|
220187
220266
|
const child = spawn2(exe, [appJs], { cwd: runDir, env, stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -220240,13 +220319,13 @@ init_util();
|
|
|
220240
220319
|
// src/commands/appDesktopMac.ts
|
|
220241
220320
|
init_util();
|
|
220242
220321
|
import { execFileSync as execFileSync4, spawn as spawn3, spawnSync as spawnSync5 } from "node:child_process";
|
|
220243
|
-
import { cpSync as cpSync2, existsSync as existsSync18, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readdirSync as
|
|
220322
|
+
import { cpSync as cpSync2, existsSync as existsSync18, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readdirSync as readdirSync8, rmSync as rmSync5, statSync as statSync6, symlinkSync, writeFileSync as writeFileSync14 } from "node:fs";
|
|
220244
220323
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
220245
220324
|
import { basename as basename6, join as join19, resolve as resolve6 } from "node:path";
|
|
220246
220325
|
var mb = (bytes) => `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
220247
|
-
var dirSize = (dir) =>
|
|
220326
|
+
var dirSize = (dir) => readdirSync8(dir, { withFileTypes: true }).reduce((sum, e2) => {
|
|
220248
220327
|
const p2 = join19(dir, e2.name);
|
|
220249
|
-
return sum + (e2.isDirectory() ? dirSize(p2) : e2.isSymbolicLink() ? 0 :
|
|
220328
|
+
return sum + (e2.isDirectory() ? dirSize(p2) : e2.isSymbolicLink() ? 0 : statSync6(p2).size);
|
|
220250
220329
|
}, 0);
|
|
220251
220330
|
var cleanBundleName = (name) => name.replace(/[/:]/g, "").trim() || "App";
|
|
220252
220331
|
var macHostAppOf = (exe) => {
|
|
@@ -220259,7 +220338,7 @@ var macHostAppOf = (exe) => {
|
|
|
220259
220338
|
var macHostProvidedNames = (exe) => {
|
|
220260
220339
|
const names3 = new Set;
|
|
220261
220340
|
const walk = (dir) => {
|
|
220262
|
-
for (const e2 of
|
|
220341
|
+
for (const e2 of readdirSync8(dir, { withFileTypes: true })) {
|
|
220263
220342
|
if (e2.isDirectory())
|
|
220264
220343
|
walk(join19(dir, e2.name));
|
|
220265
220344
|
else
|
|
@@ -220413,7 +220492,7 @@ ${(r2.stdout + r2.stderr).trim()}`);
|
|
|
220413
220492
|
if (signing.notaryProfile)
|
|
220414
220493
|
notarize(dmg, signing.notaryProfile, tmp, "disk image");
|
|
220415
220494
|
}
|
|
220416
|
-
success(`DMG: ${dmg} (${mb(
|
|
220495
|
+
success(`DMG: ${dmg} (${mb(statSync6(dmg).size)})`);
|
|
220417
220496
|
};
|
|
220418
220497
|
var gatekeeperVerdict = (app) => {
|
|
220419
220498
|
const r2 = spawnSync5("spctl", ["-a", "-t", "exec", "-vv", app], { encoding: "utf8" });
|
|
@@ -220514,12 +220593,12 @@ var buildMacApp = async (input) => {
|
|
|
220514
220593
|
writeFileSync14(join19(proj, "app.js"), js);
|
|
220515
220594
|
let assetBytes = 0, assetCount = 0;
|
|
220516
220595
|
for (const r2 of shipped) {
|
|
220517
|
-
if (!r2.absPath || !existsSync18(r2.absPath) || !
|
|
220596
|
+
if (!r2.absPath || !existsSync18(r2.absPath) || !statSync6(r2.absPath).isFile()) {
|
|
220518
220597
|
warn(`asset "${r2.name}" (${r2.path}) has no local file — skipped`);
|
|
220519
220598
|
continue;
|
|
220520
220599
|
}
|
|
220521
220600
|
cpSync2(r2.absPath, join19(proj, "assets", r2.name));
|
|
220522
|
-
assetBytes +=
|
|
220601
|
+
assetBytes += statSync6(r2.absPath).size;
|
|
220523
220602
|
assetCount++;
|
|
220524
220603
|
}
|
|
220525
220604
|
note(` assets: ${assetCount} files, ${mb(assetBytes)} → Contents/Resources/project/assets/`);
|
|
@@ -220567,7 +220646,7 @@ var buildMacApp = async (input) => {
|
|
|
220567
220646
|
const zip = join19(out, `${appName}.zip`);
|
|
220568
220647
|
rmSync5(zip, { force: true });
|
|
220569
220648
|
execFileSync4("ditto", ["-c", "-k", "--keepParent", app, zip]);
|
|
220570
|
-
success(`Zip: ${zip} (${mb(
|
|
220649
|
+
success(`Zip: ${zip} (${mb(statSync6(zip).size)})`);
|
|
220571
220650
|
} else if (!flagBool(args, "dmg")) {
|
|
220572
220651
|
note("Tip: --zip packs the .app for sending; --dmg wraps it in a drag-to-Applications image.");
|
|
220573
220652
|
}
|
|
@@ -220591,9 +220670,9 @@ or remove the quarantine flag in Terminal: xattr -dr com.apple.quarantine "` +
|
|
|
220591
220670
|
|
|
220592
220671
|
// src/commands/appDesktop.ts
|
|
220593
220672
|
var mb2 = (bytes) => `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
220594
|
-
var dirSize2 = (dir) =>
|
|
220673
|
+
var dirSize2 = (dir) => readdirSync9(dir, { withFileTypes: true }).reduce((sum, e2) => {
|
|
220595
220674
|
const p2 = join20(dir, e2.name);
|
|
220596
|
-
return sum + (e2.isDirectory() ? dirSize2(p2) :
|
|
220675
|
+
return sum + (e2.isDirectory() ? dirSize2(p2) : statSync7(p2).size);
|
|
220597
220676
|
}, 0);
|
|
220598
220677
|
var initDesktop = async (args) => {
|
|
220599
220678
|
const root = projectRoot();
|
|
@@ -220622,7 +220701,7 @@ var buildDesktop = async (args) => {
|
|
|
220622
220701
|
const slug = flagStr(args, "slug") ?? cleanFileName(name);
|
|
220623
220702
|
const out = resolve7(root, flagStr(args, "o", "out") ?? join20(root, "dist", slug));
|
|
220624
220703
|
if (existsSync19(out)) {
|
|
220625
|
-
const entries =
|
|
220704
|
+
const entries = readdirSync9(out);
|
|
220626
220705
|
const looksLikeBuild = entries.length === 0 || entries.includes("app.js") || entries.some((e2) => e2.endsWith(".app"));
|
|
220627
220706
|
if (!looksLikeBuild) {
|
|
220628
220707
|
throw new CliError(`${out} exists and doesn't look like a previous desktop build — pick another -o or clear it yourself.`);
|
|
@@ -220659,7 +220738,7 @@ var buildDesktop = async (args) => {
|
|
|
220659
220738
|
const hostProvided = mac ? macHostProvidedNames(exe) : new Set;
|
|
220660
220739
|
if (!mac) {
|
|
220661
220740
|
try {
|
|
220662
|
-
for (const f3 of
|
|
220741
|
+
for (const f3 of readdirSync9(join20(hostDir, "assets")))
|
|
220663
220742
|
hostProvided.add(f3);
|
|
220664
220743
|
} catch {}
|
|
220665
220744
|
}
|
|
@@ -220675,7 +220754,7 @@ var buildDesktop = async (args) => {
|
|
|
220675
220754
|
const version = process.env.LECODES_DESKTOP_EXE ? "local build" : selectedDesktopVersion();
|
|
220676
220755
|
rmSync6(out, { recursive: true, force: true });
|
|
220677
220756
|
mkdirSync13(out, { recursive: true });
|
|
220678
|
-
for (const entry of
|
|
220757
|
+
for (const entry of readdirSync9(hostDir, { withFileTypes: true })) {
|
|
220679
220758
|
if (entry.isFile() && entry.name.toLowerCase().endsWith(".dll")) {
|
|
220680
220759
|
cpSync3(join20(hostDir, entry.name), join20(out, entry.name));
|
|
220681
220760
|
} else if (entry.isDirectory() && entry.name === "assets") {
|
|
@@ -220695,12 +220774,12 @@ var buildDesktop = async (args) => {
|
|
|
220695
220774
|
if (shipped.length > 0)
|
|
220696
220775
|
mkdirSync13(join20(out, ASSETS_DIR), { recursive: true });
|
|
220697
220776
|
for (const r2 of shipped) {
|
|
220698
|
-
if (!r2.absPath || !existsSync19(r2.absPath) || !
|
|
220777
|
+
if (!r2.absPath || !existsSync19(r2.absPath) || !statSync7(r2.absPath).isFile()) {
|
|
220699
220778
|
warn(`asset "${r2.name}" (${r2.path}) has no local file — skipped`);
|
|
220700
220779
|
continue;
|
|
220701
220780
|
}
|
|
220702
220781
|
cpSync3(r2.absPath, join20(out, ASSETS_DIR, r2.name));
|
|
220703
|
-
assetBytes +=
|
|
220782
|
+
assetBytes += statSync7(r2.absPath).size;
|
|
220704
220783
|
assetCount++;
|
|
220705
220784
|
}
|
|
220706
220785
|
note(` assets: ${assetCount} files, ${mb2(assetBytes)} → ${ASSETS_DIR}/`);
|
|
@@ -220709,6 +220788,15 @@ var buildDesktop = async (args) => {
|
|
|
220709
220788
|
await writeIco(root, config, join20(out, "app.ico"));
|
|
220710
220789
|
note(" app.ico rendered from " + config.icon);
|
|
220711
220790
|
}
|
|
220791
|
+
{
|
|
220792
|
+
const { files } = desktopPluginLibraries(root, { strict: true });
|
|
220793
|
+
if (files.length > 0) {
|
|
220794
|
+
mkdirSync13(join20(out, "plugins"), { recursive: true });
|
|
220795
|
+
for (const f3 of files)
|
|
220796
|
+
cpSync3(f3, join20(out, "plugins", basename7(f3)));
|
|
220797
|
+
note(` plugins: ${files.map((f3) => basename7(f3)).join(", ")} → plugins/`);
|
|
220798
|
+
}
|
|
220799
|
+
}
|
|
220712
220800
|
writeFileSync15(join20(out, "README.txt"), "\uFEFF" + readmeText2(name, exeName2, version));
|
|
220713
220801
|
success(`Portable build: ${out} (${mb2(dirSize2(out))})`);
|
|
220714
220802
|
if (flagBool(args, "probe"))
|
|
@@ -220808,7 +220896,7 @@ var zipBuild = (out) => {
|
|
|
220808
220896
|
} else {
|
|
220809
220897
|
execFileSync5("zip", ["-rq", zip, basename7(out)], { cwd: dirname11(out) });
|
|
220810
220898
|
}
|
|
220811
|
-
success(`Zip: ${zip} (${mb2(
|
|
220899
|
+
success(`Zip: ${zip} (${mb2(statSync7(zip).size)})`);
|
|
220812
220900
|
};
|
|
220813
220901
|
var readmeText2 = (name, exeName2, version) => `${name}
|
|
220814
220902
|
${"=".repeat(Math.max(name.length, 4))}
|
|
@@ -221015,13 +221103,18 @@ var syncIos = async (root, config) => {
|
|
|
221015
221103
|
for (const [key, value] of Object.entries(ios.entitlements ?? {})) {
|
|
221016
221104
|
(entitlementValues[key] ??= []).push(value);
|
|
221017
221105
|
}
|
|
221018
|
-
|
|
221106
|
+
for (const pkg of ios.packages ?? []) {
|
|
221107
|
+
if (!pkg.url || !Array.isArray(pkg.products) || pkg.products.length === 0 || !pkg.exact && !pkg.from || pkg.exact && pkg.from) {
|
|
221108
|
+
throw new CliError(`Plugin "${id}": manifest ios.packages entries need { url, exact | from, products: [...] } — got ${JSON.stringify(pkg)}`);
|
|
221109
|
+
}
|
|
221110
|
+
}
|
|
221111
|
+
runtimePlugins.push({ id, module, register, packages: ios.packages });
|
|
221019
221112
|
newLock[id] = plugin.lock;
|
|
221020
221113
|
log(`${c.green("plugin")} ${id}@${plugin.lock.version} (${plugin.lock.tag} → Sources/${module})`);
|
|
221021
221114
|
}
|
|
221022
221115
|
const keep = new Set(["LeCodesRuntime", ...runtimePlugins.map((p2) => p2.module)]);
|
|
221023
|
-
for (const entry of existsSync20(sourcesDir) ?
|
|
221024
|
-
if (!keep.has(entry) &&
|
|
221116
|
+
for (const entry of existsSync20(sourcesDir) ? readdirSync10(sourcesDir) : []) {
|
|
221117
|
+
if (!keep.has(entry) && statSync8(join21(sourcesDir, entry)).isDirectory()) {
|
|
221025
221118
|
rmSync7(join21(sourcesDir, entry), { recursive: true });
|
|
221026
221119
|
log(`${c.yellow("removed")} ios/LeCodesRuntime/Sources/${entry} (plugin uninstalled)`);
|
|
221027
221120
|
}
|
|
@@ -221049,7 +221142,7 @@ var syncIos = async (root, config) => {
|
|
|
221049
221142
|
if (variant === "3d" || variant === "full") {
|
|
221050
221143
|
const sdkResources = await ensureSdkResourcesBundle(sdkVersion);
|
|
221051
221144
|
cpSync4(sdkResources, join21(resourcesDir, "LeCodesSDKResources.bundle"), { recursive: true });
|
|
221052
|
-
for (const f3 of
|
|
221145
|
+
for (const f3 of readdirSync10(sdkResources))
|
|
221053
221146
|
if (f3 !== "Info.plist")
|
|
221054
221147
|
sdkProvided.add(f3);
|
|
221055
221148
|
log(`${c.green("resources")} LeCodesSDKResources.bundle (filament) → ios/App/Resources/`);
|
|
@@ -221387,7 +221480,7 @@ var doctorIosChecks = async (root, config, check) => {
|
|
|
221387
221480
|
check(xcodeVersion !== "", `Xcode CLI (${xcodeVersion || "not found"})`, "install Xcode + command line tools");
|
|
221388
221481
|
check(!!config.ios.teamId, "Development team set", "lecodes app init wrote app.json — fill ios.teamId", false);
|
|
221389
221482
|
const iconDir = join21(root, "ios", "App", "Assets.xcassets", "AppIcon.appiconset");
|
|
221390
|
-
const hasIcon = existsSync20(iconDir) &&
|
|
221483
|
+
const hasIcon = existsSync20(iconDir) && readdirSync10(iconDir).some((f3) => f3.endsWith(".png"));
|
|
221391
221484
|
check(hasIcon, "App icon present", "drop a 1024×1024 PNG into ios/App/Assets.xcassets/AppIcon.appiconset/ (App Store requires it)", false);
|
|
221392
221485
|
const bundle = join21(root, "ios", "App", "Resources", "app.js");
|
|
221393
221486
|
check(existsSync20(bundle), "Bundled app.js", "run `lecodes app sync`");
|
|
@@ -221430,7 +221523,7 @@ var doctorIosChecks = async (root, config, check) => {
|
|
|
221430
221523
|
const plist = readFileSync17(join21(root, "ios", "App", "Info.plist"), "utf8");
|
|
221431
221524
|
check(plist.includes("<key>LeCodesUpdateURL</key>"), "OTA update URL in Info.plist", "run `lecodes app sync`", false);
|
|
221432
221525
|
const appDir = join21(root, "ios", "App");
|
|
221433
|
-
const callsUpdater =
|
|
221526
|
+
const callsUpdater = readdirSync10(appDir).some((f3) => f3.endsWith(".swift") && readFileSync17(join21(appDir, f3), "utf8").includes("LeCodesUpdater.activeBundle"));
|
|
221434
221527
|
check(callsUpdater, "App code launches via LeCodesUpdater", `no App/*.swift calls LeCodesUpdater.activeBundle() — downloaded updates would never run; see "Over-the-air updates" in ios/README.md for the ViewController snippet`, false);
|
|
221435
221528
|
}
|
|
221436
221529
|
const asc = readJson(join21(homedir7(), ".lecodes", "asc.json"));
|
|
@@ -221583,7 +221676,7 @@ var app = async (args) => {
|
|
|
221583
221676
|
init_api();
|
|
221584
221677
|
init_config();
|
|
221585
221678
|
init_manifest();
|
|
221586
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync16, readdirSync as
|
|
221679
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync16, readdirSync as readdirSync12 } from "node:fs";
|
|
221587
221680
|
import { resolve as resolve9 } from "node:path";
|
|
221588
221681
|
init_types4();
|
|
221589
221682
|
init_ignore();
|
|
@@ -221606,7 +221699,7 @@ var clone3 = async (args) => {
|
|
|
221606
221699
|
const project = await getProject(apiUrl, token, uuid);
|
|
221607
221700
|
const dir = args._[1] ?? slug(project.name);
|
|
221608
221701
|
const root = resolve9(dir);
|
|
221609
|
-
if (existsSync22(root) &&
|
|
221702
|
+
if (existsSync22(root) && readdirSync12(root).length > 0) {
|
|
221610
221703
|
throw new CliError(`Directory "${dir}" already exists and is not empty.`);
|
|
221611
221704
|
}
|
|
221612
221705
|
mkdirSync16(root, { recursive: true });
|
|
@@ -221632,7 +221725,7 @@ init_config();
|
|
|
221632
221725
|
init_manifest();
|
|
221633
221726
|
init_types4();
|
|
221634
221727
|
init_ignore();
|
|
221635
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync17, readdirSync as
|
|
221728
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync17, readdirSync as readdirSync13, writeFileSync as writeFileSync18 } from "node:fs";
|
|
221636
221729
|
import { join as join23, resolve as resolve10 } from "node:path";
|
|
221637
221730
|
|
|
221638
221731
|
// src/commands/projectTemplates.ts
|
|
@@ -221655,7 +221748,7 @@ lecodes render src/screens/cart.ts # ONE screen module, without booting the ap
|
|
|
221655
221748
|
# --state <name> picks the branch). Same flags as above.
|
|
221656
221749
|
lecodes render --desktop --png shot.png # NATIVE render: real Filament 3D + UI + 2D composited —
|
|
221657
221750
|
# use this to SEE 3D scenes / procedural geometry (headless
|
|
221658
|
-
# renders record 3D as JSON
|
|
221751
|
+
# renders record 3D as JSON — simulated, not drawn). Windows/Linux; downloads
|
|
221659
221752
|
# the renderer on first use. --frames <n> for slow loads.
|
|
221660
221753
|
lecodes render --script <file> # drive the app through a scenario (format below)
|
|
221661
221754
|
lecodes render --desktop --view iso --png iso.png # 3D: inspection camera fitted to the WHOLE
|
|
@@ -221704,8 +221797,9 @@ advance in fixed 1/60 steps driven by \`wait\`/\`frames\`/\`drag\`/\`key\` — n
|
|
|
221704
221797
|
so a flow that passes once passes every time. \`Input.key(code)\` reads the keys a flow holds and
|
|
221705
221798
|
\`Input.on('keydown' | 'keyup', e => e.code)\` fires for each \`key\`/\`keyDown\`/\`keyUp\` step
|
|
221706
221799
|
(events land before the next loop tick); \`stick\` values are what \`Input.gamepad(0).axis()\` reads.
|
|
221707
|
-
Headless draws UI + the 2D scene (sprites, tilemaps, Box2D); 3D is captured as JSON
|
|
221708
|
-
|
|
221800
|
+
Headless draws UI + the 2D scene (sprites, tilemaps, Box2D); 3D is captured as JSON with REAL Jolt
|
|
221801
|
+
physics (bodies fall, characters collide, triggers fire, ragdolls drop — a character with no ground
|
|
221802
|
+
under it falls, like on device) — use \`--desktop\` for 3D pixels. \`console.log\` + \`expect.log\` is the assertion
|
|
221709
221803
|
channel for game state that has no UI.
|
|
221710
221804
|
|
|
221711
221805
|
## Make the app testable
|
|
@@ -221774,7 +221868,7 @@ var create = async (args) => {
|
|
|
221774
221868
|
throw new CliError("Usage: lecodes create <name> [directory]");
|
|
221775
221869
|
const dir = args._[1] ?? slug2(name);
|
|
221776
221870
|
const root = resolve10(dir);
|
|
221777
|
-
if (existsSync23(root) &&
|
|
221871
|
+
if (existsSync23(root) && readdirSync13(root).length > 0) {
|
|
221778
221872
|
throw new CliError(`Directory "${dir}" already exists and is not empty.`);
|
|
221779
221873
|
}
|
|
221780
221874
|
mkdirSync17(root, { recursive: true });
|
|
@@ -221797,6 +221891,7 @@ var create = async (args) => {
|
|
|
221797
221891
|
// src/commands/desktop.ts
|
|
221798
221892
|
init_util();
|
|
221799
221893
|
init_manifest();
|
|
221894
|
+
import { basename as basename9 } from "node:path";
|
|
221800
221895
|
var resolveScale = (flag, cfg) => {
|
|
221801
221896
|
const raw = flag ?? cfg;
|
|
221802
221897
|
if (raw === undefined || raw === "system")
|
|
@@ -221830,9 +221925,13 @@ var run = async (args) => {
|
|
|
221830
221925
|
const renderer = resolveDesktopRenderer(root, args);
|
|
221831
221926
|
const { js, resources } = await buildBundle(args, undefined, { localAssets: true, desktopRenderer: renderer });
|
|
221832
221927
|
assertRendererSupportsBundle(renderer, js);
|
|
221928
|
+
const { dirs: pluginDirs, files: pluginFiles } = desktopPluginLibraries(root);
|
|
221929
|
+
if (pluginFiles.length > 0)
|
|
221930
|
+
note(`Native plugins: ${pluginFiles.map((f3) => basename9(f3)).join(", ")}`);
|
|
221833
221931
|
note(`Launching LeCodes Desktop${renderer === "vulkan" ? " (Vulkan)" : ""}… (close the window to return)`);
|
|
221834
221932
|
await runDesktopApp(js, resources, {
|
|
221835
221933
|
renderer,
|
|
221934
|
+
pluginDirs,
|
|
221836
221935
|
width: Number(flagStr(args, "width")) || win?.width,
|
|
221837
221936
|
height: Number(flagStr(args, "height")) || win?.height,
|
|
221838
221937
|
minWidth: win?.minWidth,
|
|
@@ -221886,15 +221985,15 @@ init_design();
|
|
|
221886
221985
|
// src/commands/dev.ts
|
|
221887
221986
|
init_manifest();
|
|
221888
221987
|
init_ignore();
|
|
221889
|
-
import { existsSync as
|
|
221988
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync19, readFileSync as readFileSync22, watch, writeFileSync as writeFileSync20 } from "node:fs";
|
|
221890
221989
|
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
221891
221990
|
import { networkInterfaces } from "node:os";
|
|
221892
|
-
import { basename as
|
|
221991
|
+
import { basename as basename12, join as join28 } from "node:path";
|
|
221893
221992
|
|
|
221894
221993
|
// src/dev/devServer.ts
|
|
221895
221994
|
init_localFiles();
|
|
221896
221995
|
import { createServer as createServer2 } from "node:http";
|
|
221897
|
-
import { createReadStream, statSync as
|
|
221996
|
+
import { createReadStream, statSync as statSync10 } from "node:fs";
|
|
221898
221997
|
import { join as join26 } from "node:path";
|
|
221899
221998
|
init_projectCompile();
|
|
221900
221999
|
init_fonts();
|
|
@@ -222158,7 +222257,12 @@ var MIME = {
|
|
|
222158
222257
|
woff2: "font/woff2",
|
|
222159
222258
|
json: "application/json",
|
|
222160
222259
|
txt: "text/plain",
|
|
222161
|
-
js: "text/javascript"
|
|
222260
|
+
js: "text/javascript",
|
|
222261
|
+
mjs: "text/javascript",
|
|
222262
|
+
css: "text/css",
|
|
222263
|
+
html: "text/html",
|
|
222264
|
+
wasm: "application/wasm",
|
|
222265
|
+
map: "application/json"
|
|
222162
222266
|
};
|
|
222163
222267
|
var contentType = (path2) => {
|
|
222164
222268
|
const i2 = path2.lastIndexOf(".");
|
|
@@ -222253,22 +222357,58 @@ var startDevServer = async (options) => {
|
|
|
222253
222357
|
else if (m.type === "error")
|
|
222254
222358
|
log2(`[device:error] ${demangle(m.text ?? "")}`);
|
|
222255
222359
|
};
|
|
222256
|
-
const transportOf = (url) =>
|
|
222360
|
+
const transportOf = (url) => {
|
|
222361
|
+
const t2 = url.searchParams.get("t");
|
|
222362
|
+
return t2 === "poll" ? "poll" : t2 === "web" ? "web" : "ws";
|
|
222363
|
+
};
|
|
222364
|
+
const withPrelude = (js, url, v2) => {
|
|
222365
|
+
const transport = transportOf(url);
|
|
222366
|
+
return transport === "web" ? js : js + `
|
|
222367
|
+
` + renderPrelude({ origin, base, transport, v: v2 });
|
|
222368
|
+
};
|
|
222369
|
+
const webDir = options.webDir ?? null;
|
|
222257
222370
|
const handle = async (req, res) => {
|
|
222258
222371
|
const url = new URL(req.url ?? "/", origin);
|
|
222259
222372
|
const path2 = url.pathname;
|
|
222373
|
+
if (path2 === "/favicon.ico") {
|
|
222374
|
+
res.writeHead(204);
|
|
222375
|
+
res.end();
|
|
222376
|
+
return;
|
|
222377
|
+
}
|
|
222260
222378
|
if (!path2.startsWith(base + "/"))
|
|
222261
222379
|
return sendText(res, 404, "text/plain", "Not found");
|
|
222262
222380
|
const route = path2.slice(base.length);
|
|
222263
222381
|
if (route === "/dev.js") {
|
|
222264
|
-
return sendText(res, 200, "text/javascript", devJs
|
|
222265
|
-
` + renderPrelude({ origin, base, transport: transportOf(url), v: -1 }));
|
|
222382
|
+
return sendText(res, 200, "text/javascript", withPrelude(devJs, url, -1));
|
|
222266
222383
|
}
|
|
222267
222384
|
if (route === "/bundle.js") {
|
|
222268
222385
|
if (bundleJs === null)
|
|
222269
222386
|
return sendText(res, 503, "text/plain", "No successful compile yet — check the terminal.");
|
|
222270
|
-
|
|
222271
|
-
|
|
222387
|
+
res.setHeader("x-lecodes-v", String(v));
|
|
222388
|
+
return sendText(res, 200, "text/javascript", withPrelude(bundleJs, url, v));
|
|
222389
|
+
}
|
|
222390
|
+
if (route === "/web") {
|
|
222391
|
+
res.writeHead(302, { location: `${base}/web/${url.search}` });
|
|
222392
|
+
res.end();
|
|
222393
|
+
return;
|
|
222394
|
+
}
|
|
222395
|
+
if (route.startsWith("/web/")) {
|
|
222396
|
+
if (!webDir)
|
|
222397
|
+
return sendText(res, 404, "text/plain", "No Web Lite runner vendored with this CLI (lecodes-viewer-lite dist-embed).");
|
|
222398
|
+
const rel = route === "/web/" ? "embed.html" : route.slice("/web/".length);
|
|
222399
|
+
if (rel.split("/").some((seg) => seg === ".." || seg === "" || seg === "."))
|
|
222400
|
+
return sendText(res, 400, "text/plain", "Bad path");
|
|
222401
|
+
const abs = join26(webDir, ...rel.split("/"));
|
|
222402
|
+
try {
|
|
222403
|
+
if (!statSync10(abs).isFile())
|
|
222404
|
+
throw new Error("not a file");
|
|
222405
|
+
} catch {
|
|
222406
|
+
return sendText(res, 404, "text/plain", "Not found");
|
|
222407
|
+
}
|
|
222408
|
+
const hashed = rel.startsWith("assets/");
|
|
222409
|
+
res.writeHead(200, { "content-type": contentType(rel), "cache-control": hashed ? "max-age=31536000, immutable" : "no-store" });
|
|
222410
|
+
createReadStream(abs).pipe(res);
|
|
222411
|
+
return;
|
|
222272
222412
|
}
|
|
222273
222413
|
if (route === "/version") {
|
|
222274
222414
|
return sendJson(res, 200, { v });
|
|
@@ -222283,7 +222423,7 @@ var startDevServer = async (options) => {
|
|
|
222283
222423
|
return sendText(res, 400, "text/plain", "Bad path");
|
|
222284
222424
|
const abs = join26(shadersCacheDir(root), name2);
|
|
222285
222425
|
try {
|
|
222286
|
-
if (!
|
|
222426
|
+
if (!statSync10(abs).isFile())
|
|
222287
222427
|
throw new Error("not a file");
|
|
222288
222428
|
} catch {
|
|
222289
222429
|
return sendText(res, 404, "text/plain", "Not found");
|
|
@@ -222300,7 +222440,7 @@ var startDevServer = async (options) => {
|
|
|
222300
222440
|
return sendText(res, 400, "text/plain", "Bad path");
|
|
222301
222441
|
}
|
|
222302
222442
|
const abs = resolveLocalPath(root, key);
|
|
222303
|
-
if (!abs || !
|
|
222443
|
+
if (!abs || !statSync10(abs).isFile())
|
|
222304
222444
|
return sendText(res, 404, "text/plain", "Not found");
|
|
222305
222445
|
res.writeHead(200, { "content-type": contentType(key), "cache-control": "no-store" });
|
|
222306
222446
|
createReadStream(abs).pipe(res);
|
|
@@ -222354,6 +222494,7 @@ var startDevServer = async (options) => {
|
|
|
222354
222494
|
const boundPort = typeof address === "object" && address !== null ? address.port : options.port;
|
|
222355
222495
|
return {
|
|
222356
222496
|
url: `${origin}${base}/dev.js`,
|
|
222497
|
+
webUrl: webDir ? `${origin}${base}/web/` : null,
|
|
222357
222498
|
base,
|
|
222358
222499
|
port: boundPort,
|
|
222359
222500
|
v: () => v,
|
|
@@ -222367,7 +222508,25 @@ var startDevServer = async (options) => {
|
|
|
222367
222508
|
};
|
|
222368
222509
|
};
|
|
222369
222510
|
|
|
222511
|
+
// src/dev/webRunner.ts
|
|
222512
|
+
init_distRoot();
|
|
222513
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
222514
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
222515
|
+
import { dirname as dirname14, join as join27 } from "node:path";
|
|
222516
|
+
var resolveWebRunnerDir = () => {
|
|
222517
|
+
const candidates = [join27(distRoot, "runtime", "web")];
|
|
222518
|
+
try {
|
|
222519
|
+
const pkg = createRequire5(import.meta.url).resolve("lecodes-viewer-lite/package.json");
|
|
222520
|
+
candidates.push(join27(dirname14(pkg), "dist-embed"));
|
|
222521
|
+
} catch {}
|
|
222522
|
+
for (const dir of candidates)
|
|
222523
|
+
if (existsSync25(join27(dir, "embed.html")) && existsSync25(join27(dir, "embed.js")))
|
|
222524
|
+
return dir;
|
|
222525
|
+
return null;
|
|
222526
|
+
};
|
|
222527
|
+
|
|
222370
222528
|
// src/commands/dev.ts
|
|
222529
|
+
init_browserAuth();
|
|
222371
222530
|
init_util();
|
|
222372
222531
|
var DEFAULT_PORT2 = 4499;
|
|
222373
222532
|
var DEBOUNCE_MS = 120;
|
|
@@ -222395,14 +222554,14 @@ var lanCandidates = () => {
|
|
|
222395
222554
|
return out.sort((x2, y2) => x2.rank - y2.rank).map(({ address, iface }) => ({ address, iface }));
|
|
222396
222555
|
};
|
|
222397
222556
|
var loadDevToken = (root) => {
|
|
222398
|
-
const path2 =
|
|
222557
|
+
const path2 = join28(root, LECODES_DIR, "dev.json");
|
|
222399
222558
|
try {
|
|
222400
222559
|
const token2 = JSON.parse(readFileSync22(path2, "utf8")).token;
|
|
222401
222560
|
if (token2 && /^[a-z0-9]{8,}$/.test(token2))
|
|
222402
222561
|
return token2;
|
|
222403
222562
|
} catch {}
|
|
222404
222563
|
const token = randomBytes3(6).toString("hex");
|
|
222405
|
-
mkdirSync19(
|
|
222564
|
+
mkdirSync19(join28(root, LECODES_DIR), { recursive: true });
|
|
222406
222565
|
writeFileSync20(path2, JSON.stringify({ token }, null, 2) + `
|
|
222407
222566
|
`);
|
|
222408
222567
|
return token;
|
|
@@ -222428,7 +222587,7 @@ var dev = async (args) => {
|
|
|
222428
222587
|
root = process.cwd();
|
|
222429
222588
|
manifest = null;
|
|
222430
222589
|
}
|
|
222431
|
-
const name = manifest?.name ??
|
|
222590
|
+
const name = manifest?.name ?? basename12(root);
|
|
222432
222591
|
if (typeof globalThis.Bun !== "undefined") {
|
|
222433
222592
|
warnErr("Running under Bun: the websocket reload channel doesn't work here — run `lecodes dev` with Node (or use ?t=poll on the device URL).");
|
|
222434
222593
|
}
|
|
@@ -222440,6 +222599,10 @@ var dev = async (args) => {
|
|
|
222440
222599
|
const alternatives = candidates.filter((c4) => c4.address !== host);
|
|
222441
222600
|
const origin = `http://${host}:${port}`;
|
|
222442
222601
|
const token = loadDevToken(root);
|
|
222602
|
+
const webDir = resolveWebRunnerDir();
|
|
222603
|
+
if (flagBool(args, "web") && !webDir) {
|
|
222604
|
+
throw new CliError("No Web Lite runner found for --web: this CLI has no runtime/web (a monorepo checkout needs `bun run build:embed` in packages/viewer-lite).");
|
|
222605
|
+
}
|
|
222443
222606
|
const server2 = await startDevServer({
|
|
222444
222607
|
root,
|
|
222445
222608
|
manifest,
|
|
@@ -222448,6 +222611,7 @@ var dev = async (args) => {
|
|
|
222448
222611
|
port,
|
|
222449
222612
|
token,
|
|
222450
222613
|
entryOverride: flagStr(args, "entry"),
|
|
222614
|
+
webDir,
|
|
222451
222615
|
log: note
|
|
222452
222616
|
}).catch((e2) => {
|
|
222453
222617
|
const msg = e2 instanceof Error ? e2.message : String(e2);
|
|
@@ -222516,14 +222680,21 @@ ${result.error}`);
|
|
|
222516
222680
|
if (!flagBool(args, "no-qr"))
|
|
222517
222681
|
await printQr(server2.url);
|
|
222518
222682
|
log(`Scan the QR with the LeCodes app, or open: ${c.bold(server2.url)}`);
|
|
222683
|
+
const webLocal = server2.webUrl ? server2.webUrl.replace(`http://${host}:`, "http://localhost:") : null;
|
|
222684
|
+
if (server2.webUrl && webLocal)
|
|
222685
|
+
log(`In the browser (Web Lite): ${c.bold(webLocal)} (LAN: ${server2.webUrl})`);
|
|
222519
222686
|
note(`Older desktop builds (no websocket bridge): ${server2.url}?t=poll`);
|
|
222520
222687
|
if (alternatives.length > 0) {
|
|
222521
222688
|
note(`Device can't reach it? This machine also has ${alternatives.map((a2) => `${a2.address} (${a2.iface})`).join(", ")} — retry with --host <ip>.`);
|
|
222522
222689
|
}
|
|
222523
|
-
if (
|
|
222690
|
+
if (existsSync26(join28(root, LECODES_DIR, "manifest.json")))
|
|
222524
222691
|
note(`Token stored in ${LECODES_DIR}/dev.json (delete it to rotate the URL).`);
|
|
222525
222692
|
log("");
|
|
222526
222693
|
log(`Watching ${root} — save a file to hot-reload. Ctrl+C to stop.`);
|
|
222694
|
+
if (flagBool(args, "web") && webLocal) {
|
|
222695
|
+
note("Opening the browser…");
|
|
222696
|
+
openBrowser(webLocal);
|
|
222697
|
+
}
|
|
222527
222698
|
if (flagBool(args, "desktop")) {
|
|
222528
222699
|
const appCfg = readAppConfigAt(root);
|
|
222529
222700
|
const win = appCfg?.desktop?.window;
|
|
@@ -222550,7 +222721,7 @@ init_localFiles();
|
|
|
222550
222721
|
// src/serverDiff.ts
|
|
222551
222722
|
init_localFiles();
|
|
222552
222723
|
import { readFileSync as readFileSync23 } from "node:fs";
|
|
222553
|
-
import { basename as
|
|
222724
|
+
import { basename as basename13 } from "node:path";
|
|
222554
222725
|
var isTextAsset = (t2) => t2 === "text" || t2 === "shader" || t2 === "scene";
|
|
222555
222726
|
var computeServerDiff = (project, scan2) => {
|
|
222556
222727
|
const pathById = buildPaths(project.assets);
|
|
@@ -222567,7 +222738,7 @@ var computeServerDiff = (project, scan2) => {
|
|
|
222567
222738
|
const server2 = serverByPath.get(path2);
|
|
222568
222739
|
const local = localByPath.get(path2);
|
|
222569
222740
|
if (local && !server2) {
|
|
222570
|
-
const text = isTextKind(classifyKind(
|
|
222741
|
+
const text = isTextKind(classifyKind(basename13(path2)));
|
|
222571
222742
|
entries.push({ path: path2, status: "added", binary: !text, serverText: "", localText: text ? readFileSync23(local.absPath, "utf8") : undefined });
|
|
222572
222743
|
continue;
|
|
222573
222744
|
}
|
|
@@ -222742,8 +222913,8 @@ var statusLabel = (e2) => e2.status === "added" ? c.green(" added ") : e2.st
|
|
|
222742
222913
|
init_manifest();
|
|
222743
222914
|
init_types4();
|
|
222744
222915
|
init_ignore();
|
|
222745
|
-
import { existsSync as
|
|
222746
|
-
import { basename as
|
|
222916
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync20, writeFileSync as writeFileSync21 } from "node:fs";
|
|
222917
|
+
import { basename as basename14, dirname as dirname15, join as join29, resolve as resolve11 } from "node:path";
|
|
222747
222918
|
init_util();
|
|
222748
222919
|
var STARTER2 = `// Welcome to LeCodes — the whole SDK is available as globals, no imports needed.
|
|
222749
222920
|
// Run it live on a device with \`lecodes dev\`, or bundle it with \`lecodes compile -o app.js\`.
|
|
@@ -222852,16 +223023,16 @@ Full command list: \`lecodes --help\`.
|
|
|
222852
223023
|
var init2 = async (args) => {
|
|
222853
223024
|
const dirArg = (args._[0] ?? ".").replace(/[/\\]+$/, "") || ".";
|
|
222854
223025
|
const root = resolve11(dirArg);
|
|
222855
|
-
const name =
|
|
223026
|
+
const name = basename14(root);
|
|
222856
223027
|
mkdirSync20(root, { recursive: true });
|
|
222857
223028
|
let created = 0;
|
|
222858
223029
|
const write = (rel, content) => {
|
|
222859
|
-
const abs =
|
|
222860
|
-
if (
|
|
223030
|
+
const abs = join29(root, rel);
|
|
223031
|
+
if (existsSync27(abs)) {
|
|
222861
223032
|
note(`kept ${rel}`);
|
|
222862
223033
|
return;
|
|
222863
223034
|
}
|
|
222864
|
-
mkdirSync20(
|
|
223035
|
+
mkdirSync20(dirname15(abs), { recursive: true });
|
|
222865
223036
|
writeFileSync21(abs, content);
|
|
222866
223037
|
log(`${c.green("created")} ${rel}`);
|
|
222867
223038
|
created++;
|
|
@@ -222909,8 +223080,8 @@ init_config();
|
|
|
222909
223080
|
init_ignore();
|
|
222910
223081
|
init_localFiles();
|
|
222911
223082
|
init_manifest();
|
|
222912
|
-
import { existsSync as
|
|
222913
|
-
import { basename as
|
|
223083
|
+
import { existsSync as existsSync28 } from "node:fs";
|
|
223084
|
+
import { basename as basename16, join as join30, resolve as resolve12 } from "node:path";
|
|
222914
223085
|
init_types4();
|
|
222915
223086
|
init_util();
|
|
222916
223087
|
|
|
@@ -222919,7 +223090,7 @@ init_api();
|
|
|
222919
223090
|
init_config();
|
|
222920
223091
|
init_manifest();
|
|
222921
223092
|
init_localFiles();
|
|
222922
|
-
import { basename as
|
|
223093
|
+
import { basename as basename15 } from "node:path";
|
|
222923
223094
|
import { readFileSync as readFileSync24 } from "node:fs";
|
|
222924
223095
|
init_util();
|
|
222925
223096
|
var push = async (args) => {
|
|
@@ -222976,14 +223147,14 @@ var push = async (args) => {
|
|
|
222976
223147
|
let uploaded = 0;
|
|
222977
223148
|
for (const file of scan2.files) {
|
|
222978
223149
|
const source = sourceFor(file.path);
|
|
222979
|
-
const kind = source?.type ?? classifyKind(
|
|
223150
|
+
const kind = source?.type ?? classifyKind(basename15(file.path));
|
|
222980
223151
|
const entry = { path: file.path, type: kind };
|
|
222981
223152
|
if (source)
|
|
222982
223153
|
entry.assetId = source.id;
|
|
222983
223154
|
if (isTextKind(kind)) {
|
|
222984
223155
|
entry.text = readFileSync24(file.absPath, "utf8");
|
|
222985
223156
|
} else if (!source || source.sha !== file.sha) {
|
|
222986
|
-
const blob = await uploadBlob(apiUrl, token, manifest.uuid,
|
|
223157
|
+
const blob = await uploadBlob(apiUrl, token, manifest.uuid, basename15(file.path), readFileSync24(file.absPath));
|
|
222987
223158
|
entry.blobFileId = blob.id;
|
|
222988
223159
|
uploaded++;
|
|
222989
223160
|
}
|
|
@@ -223091,9 +223262,9 @@ var link = async (args) => {
|
|
|
223091
223262
|
const token = requireToken(config);
|
|
223092
223263
|
const dirArg = args._[0];
|
|
223093
223264
|
const root = dirArg ? resolve12(dirArg) : process.cwd();
|
|
223094
|
-
if (!
|
|
223265
|
+
if (!existsSync28(root))
|
|
223095
223266
|
throw new CliError(`No such directory: ${root}`);
|
|
223096
|
-
if (
|
|
223267
|
+
if (existsSync28(join30(root, LECODES_DIR, "manifest.json")) && !flagBool(args, "force")) {
|
|
223097
223268
|
throw new CliError("This folder is already linked (.lecodes/manifest.json exists) — use `lecodes push`, or `lecodes link --force` to re-link it to another project.");
|
|
223098
223269
|
}
|
|
223099
223270
|
let enclosing = null;
|
|
@@ -223120,7 +223291,7 @@ var link = async (args) => {
|
|
|
223120
223291
|
}
|
|
223121
223292
|
name = project.name;
|
|
223122
223293
|
} else {
|
|
223123
|
-
name = flagStr(args, "name") ??
|
|
223294
|
+
name = flagStr(args, "name") ?? basename16(root);
|
|
223124
223295
|
info(c.dim(`Creating project ${c.bold(name)}…`));
|
|
223125
223296
|
uuid = (await createProject(apiUrl, token, name, flagStr(args, "team"))).uuid;
|
|
223126
223297
|
files = {};
|
|
@@ -223157,10 +223328,10 @@ var link = async (args) => {
|
|
|
223157
223328
|
|
|
223158
223329
|
// src/commands/lightmap.ts
|
|
223159
223330
|
init_manifest();
|
|
223160
|
-
import { existsSync as
|
|
223331
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync21, mkdtempSync as mkdtempSync4, readFileSync as readFileSync25, renameSync as renameSync3, rmSync as rmSync9, statSync as statSync11, unlinkSync, writeFileSync as writeFileSync22 } from "node:fs";
|
|
223161
223332
|
import { spawn as spawn6, spawnSync as spawnSync6 } from "node:child_process";
|
|
223162
223333
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
223163
|
-
import { join as
|
|
223334
|
+
import { join as join31, relative as relative4, resolve as resolve13 } from "node:path";
|
|
223164
223335
|
init_util();
|
|
223165
223336
|
var num = (args, key, fallback, min, max) => {
|
|
223166
223337
|
const raw = flagStr(args, key);
|
|
@@ -223173,13 +223344,13 @@ var num = (args, key, fallback, min, max) => {
|
|
|
223173
223344
|
};
|
|
223174
223345
|
var findToktx = () => {
|
|
223175
223346
|
const env = process.env.KTX_TOKTX;
|
|
223176
|
-
if (env &&
|
|
223347
|
+
if (env && existsSync29(env))
|
|
223177
223348
|
return env;
|
|
223178
|
-
for (const base of [process.env.LOCALAPPDATA &&
|
|
223349
|
+
for (const base of [process.env.LOCALAPPDATA && join31(process.env.LOCALAPPDATA, "Programs"), process.env.ProgramFiles]) {
|
|
223179
223350
|
if (!base)
|
|
223180
223351
|
continue;
|
|
223181
|
-
const guess =
|
|
223182
|
-
if (
|
|
223352
|
+
const guess = join31(base, "KTX-Software", "bin", "toktx.exe");
|
|
223353
|
+
if (existsSync29(guess))
|
|
223183
223354
|
return guess;
|
|
223184
223355
|
}
|
|
223185
223356
|
return "toktx";
|
|
@@ -223234,7 +223405,7 @@ var bake = async (args) => {
|
|
|
223234
223405
|
throw new CliError(`--name wants a plain file stem (letters, digits, - and _), got "${stem}".`);
|
|
223235
223406
|
const entryFlag = flagStr(args, "entry");
|
|
223236
223407
|
const entryFile = entryFlag ?? "main.ts";
|
|
223237
|
-
if (!
|
|
223408
|
+
if (!existsSync29(resolve13(root, entryFile))) {
|
|
223238
223409
|
throw new CliError(`No ${entryFile} in ${root} — pass --entry <file> (the file that builds the scene and calls Lightmap.load).`);
|
|
223239
223410
|
}
|
|
223240
223411
|
const cfg = {
|
|
@@ -223275,8 +223446,8 @@ import ${JSON.stringify(importPath)}
|
|
|
223275
223446
|
extraEntries: [{ path: entryPath, type: "text", text: entryText }],
|
|
223276
223447
|
entryOverride: entryPath
|
|
223277
223448
|
});
|
|
223278
|
-
const scratch = mkdtempSync4(
|
|
223279
|
-
const outPng =
|
|
223449
|
+
const scratch = mkdtempSync4(join31(tmpdir4(), "lecodes-lightmap-"));
|
|
223450
|
+
const outPng = join31(scratch, "frame.png");
|
|
223280
223451
|
note(`Baking up to ${cfg.pages} × ${cfg.size}² at ${(cfg.texel * 100).toFixed(1)} cm texels (${cfg.sunRays} sun + ${cfg.aoRays} AO + ${cfg.lightRays} light rays)${cfg.volumeCell ? ` + a ${cfg.volumeCell} m light volume` : ""} → ${relative4(root, outDir) || "."}/${stem}.*…`);
|
|
223281
223452
|
let output = "";
|
|
223282
223453
|
try {
|
|
@@ -223310,8 +223481,8 @@ import ${JSON.stringify(importPath)}
|
|
|
223310
223481
|
logErr(text.startsWith("error") ? c.red(`✗ ${text}`) : text.startsWith("warning") ? c.yellow(` ${text}`) : c.dim(` ${text}`));
|
|
223311
223482
|
}
|
|
223312
223483
|
if (/\[lightmap\] done/.test(output)) {
|
|
223313
|
-
const bakePath =
|
|
223314
|
-
if (!
|
|
223484
|
+
const bakePath = join31(outDir, "lightmap.bake");
|
|
223485
|
+
if (!existsSync29(bakePath))
|
|
223315
223486
|
throw new CliError(`The host reported a bake but ${bakePath} is missing.`);
|
|
223316
223487
|
const data = JSON.parse(readFileSync25(bakePath, "utf8"));
|
|
223317
223488
|
const pages = Math.max(1, data.pages ?? 1);
|
|
@@ -223319,13 +223490,13 @@ import ${JSON.stringify(importPath)}
|
|
|
223319
223490
|
const t0 = Date.now();
|
|
223320
223491
|
let pngKb = 0, ktxKb = 0;
|
|
223321
223492
|
const encodePage = async (page, light) => {
|
|
223322
|
-
const png2 =
|
|
223323
|
-
const ktx2 =
|
|
223324
|
-
if (!
|
|
223493
|
+
const png2 = join31(outDir, pageFile("lightmap", page, light, ".png"));
|
|
223494
|
+
const ktx2 = join31(outDir, pageFile(stem, page, light));
|
|
223495
|
+
if (!existsSync29(png2))
|
|
223325
223496
|
throw new CliError(`The host reported a bake but ${png2} is missing.`);
|
|
223326
223497
|
await encodeKtx2(toktx, png2, ktx2);
|
|
223327
|
-
pngKb +=
|
|
223328
|
-
ktxKb +=
|
|
223498
|
+
pngKb += statSync11(png2).size / 1024;
|
|
223499
|
+
ktxKb += statSync11(ktx2).size / 1024;
|
|
223329
223500
|
unlinkSync(png2);
|
|
223330
223501
|
};
|
|
223331
223502
|
const encodes = [];
|
|
@@ -223337,14 +223508,14 @@ import ${JSON.stringify(importPath)}
|
|
|
223337
223508
|
await Promise.all(encodes);
|
|
223338
223509
|
for (let p2 = pages;p2 < 16; p2++) {
|
|
223339
223510
|
for (const light of [false, true]) {
|
|
223340
|
-
const stale =
|
|
223341
|
-
if (
|
|
223511
|
+
const stale = join31(outDir, pageFile(stem, p2, light));
|
|
223512
|
+
if (existsSync29(stale) && statSync11(stale).size !== PLACEHOLDER_KTX2.length)
|
|
223342
223513
|
writeFileSync22(stale, PLACEHOLDER_KTX2);
|
|
223343
223514
|
}
|
|
223344
223515
|
}
|
|
223345
223516
|
if (!hasLight) {
|
|
223346
|
-
const light =
|
|
223347
|
-
if (
|
|
223517
|
+
const light = join31(outDir, pageFile(stem, 0, true));
|
|
223518
|
+
if (existsSync29(light) && statSync11(light).size !== PLACEHOLDER_KTX2.length)
|
|
223348
223519
|
writeFileSync22(light, PLACEHOLDER_KTX2);
|
|
223349
223520
|
}
|
|
223350
223521
|
data.texture = pageFile(stem, 0, false);
|
|
@@ -223353,19 +223524,19 @@ import ${JSON.stringify(importPath)}
|
|
|
223353
223524
|
data.lightTextures = Array.from({ length: pages }, (_, p2) => pageFile(stem, p2, true));
|
|
223354
223525
|
if (data.volume)
|
|
223355
223526
|
data.volume.file = `${stem}.volume`;
|
|
223356
|
-
writeFileSync22(
|
|
223527
|
+
writeFileSync22(join31(outDir, `${stem}.bake`), JSON.stringify(data, null, 1) + `
|
|
223357
223528
|
`);
|
|
223358
223529
|
if (stem !== "lightmap")
|
|
223359
223530
|
unlinkSync(bakePath);
|
|
223360
|
-
const volumeSrc =
|
|
223361
|
-
const hasVolume = cfg.volumeCell > 0 &&
|
|
223531
|
+
const volumeSrc = join31(outDir, "lightmap.volume");
|
|
223532
|
+
const hasVolume = cfg.volumeCell > 0 && existsSync29(volumeSrc);
|
|
223362
223533
|
if (hasVolume && stem !== "lightmap") {
|
|
223363
|
-
rmSync9(
|
|
223364
|
-
renameSync3(volumeSrc,
|
|
223534
|
+
rmSync9(join31(outDir, `${stem}.volume`), { force: true });
|
|
223535
|
+
renameSync3(volumeSrc, join31(outDir, `${stem}.volume`));
|
|
223365
223536
|
}
|
|
223366
223537
|
logErr(c.dim(` encoded ${pages} page(s)${hasLight ? " + the light atlas" : ""} (UASTC + mips, ${Math.round(ktxKb)} KB from ${Math.round(pngKb)} KB of rasters) in ${((Date.now() - t0) / 1000).toFixed(1)} s`));
|
|
223367
223538
|
logErr(c.green(`✓ baked → ${relative4(root, outDir) || "."}/${stem}.bake + ${data.textures.join(", ")}${hasLight ? ` + ${data.lightTextures.join(", ")}` : ""}${hasVolume ? ` + ${stem}.volume` : ""}`));
|
|
223368
|
-
const rel = (f3) => relative4(root,
|
|
223539
|
+
const rel = (f3) => relative4(root, join31(outDir, f3)).replace(/\\/g, "/");
|
|
223369
223540
|
const assets = (files) => files.length === 1 ? `asset('<rel>/${rel(files[0])}')` : `[${files.map((f3) => `asset('<rel>/${rel(f3)}')`).join(", ")}]`;
|
|
223370
223541
|
logErr(c.dim(` scene file: env.lightmap: { data: asset('<rel>/${rel(`${stem}.bake`)}'), texture: ${assets(data.textures)}${hasLight ? `, light: ${assets(data.lightTextures)}` : ""}${hasVolume ? `, volume: asset('<rel>/${rel(`${stem}.volume`)}')` : ""} } — asset() paths are relative to the scene file`));
|
|
223371
223542
|
return;
|
|
@@ -223395,11 +223566,11 @@ var placeholderVolume = () => {
|
|
|
223395
223566
|
return b;
|
|
223396
223567
|
};
|
|
223397
223568
|
var ensurePlaceholders = (outDir, stem) => {
|
|
223398
|
-
const missing = (f3) => !
|
|
223399
|
-
const bake2 =
|
|
223400
|
-
const ktx2 =
|
|
223401
|
-
const light =
|
|
223402
|
-
const volume =
|
|
223569
|
+
const missing = (f3) => !existsSync29(f3) || statSync11(f3).size === 0;
|
|
223570
|
+
const bake2 = join31(outDir, `${stem}.bake`);
|
|
223571
|
+
const ktx2 = join31(outDir, pageFile(stem, 0, false));
|
|
223572
|
+
const light = join31(outDir, pageFile(stem, 0, true));
|
|
223573
|
+
const volume = join31(outDir, `${stem}.volume`);
|
|
223403
223574
|
if (missing(bake2))
|
|
223404
223575
|
writeFileSync22(bake2, JSON.stringify({ version: 2, placeholder: true, size: 1, texel: 0, pages: 1, instances: [] }) + `
|
|
223405
223576
|
`);
|
|
@@ -223419,9 +223590,9 @@ var lightmap = async (args) => {
|
|
|
223419
223590
|
|
|
223420
223591
|
// src/commands/navmesh.ts
|
|
223421
223592
|
init_manifest();
|
|
223422
|
-
import { existsSync as
|
|
223593
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync5, readdirSync as readdirSync15, readFileSync as readFileSync26, rmSync as rmSync10, statSync as statSync12, unlinkSync as unlinkSync2, writeFileSync as writeFileSync23 } from "node:fs";
|
|
223423
223594
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
223424
|
-
import { basename as
|
|
223595
|
+
import { basename as basename17, join as join32, relative as relative5, resolve as resolve14 } from "node:path";
|
|
223425
223596
|
init_util();
|
|
223426
223597
|
|
|
223427
223598
|
// ../creator-nav/dist/creatorNav.js
|
|
@@ -223438,8 +223609,8 @@ var createCreatorNav = (() => {
|
|
|
223438
223609
|
var ENVIRONMENT_IS_WORKER = typeof WorkerGlobalScope != "undefined";
|
|
223439
223610
|
var ENVIRONMENT_IS_NODE = typeof process == "object" && process.versions?.node && process.type != "renderer";
|
|
223440
223611
|
if (ENVIRONMENT_IS_NODE) {
|
|
223441
|
-
const { createRequire:
|
|
223442
|
-
var require2 =
|
|
223612
|
+
const { createRequire: createRequire6 } = await import("module");
|
|
223613
|
+
var require2 = createRequire6(import.meta.url);
|
|
223443
223614
|
}
|
|
223444
223615
|
var arguments_ = [];
|
|
223445
223616
|
var thisProgram = "./this.program";
|
|
@@ -224218,13 +224389,13 @@ var num2 = (args, key, fallback, min, max) => {
|
|
|
224218
224389
|
return n2;
|
|
224219
224390
|
};
|
|
224220
224391
|
var guessName = (root) => {
|
|
224221
|
-
const dirs = [
|
|
224392
|
+
const dirs = [join32(root, "src"), root];
|
|
224222
224393
|
for (const dir of dirs) {
|
|
224223
|
-
if (!
|
|
224394
|
+
if (!existsSync30(dir))
|
|
224224
224395
|
continue;
|
|
224225
224396
|
let entries;
|
|
224226
224397
|
try {
|
|
224227
|
-
entries =
|
|
224398
|
+
entries = readdirSync15(dir);
|
|
224228
224399
|
} catch {
|
|
224229
224400
|
continue;
|
|
224230
224401
|
}
|
|
@@ -224232,7 +224403,7 @@ var guessName = (root) => {
|
|
|
224232
224403
|
if (!f3.endsWith(".scene.ts"))
|
|
224233
224404
|
continue;
|
|
224234
224405
|
try {
|
|
224235
|
-
if (/\bnavmesh\s*:/.test(readFileSync26(
|
|
224406
|
+
if (/\bnavmesh\s*:/.test(readFileSync26(join32(dir, f3), "utf8")))
|
|
224236
224407
|
return f3.slice(0, -".scene.ts".length);
|
|
224237
224408
|
} catch {}
|
|
224238
224409
|
}
|
|
@@ -224275,7 +224446,7 @@ var bake2 = async (args) => {
|
|
|
224275
224446
|
const outDir = resolve14(root, flagStr(args, "out") ?? "assets/nav");
|
|
224276
224447
|
const entryFlag = flagStr(args, "entry");
|
|
224277
224448
|
const entryFile = entryFlag ?? "main.ts";
|
|
224278
|
-
if (!
|
|
224449
|
+
if (!existsSync30(resolve14(root, entryFile))) {
|
|
224279
224450
|
throw new CliError(`No ${entryFile} in ${root} — pass --entry <file> (the file that builds the level: a scene file with env.navmesh, or code calling NavMesh.load).`);
|
|
224280
224451
|
}
|
|
224281
224452
|
const name = flagStr(args, "name") ?? guessName(root) ?? "scene";
|
|
@@ -224287,8 +224458,8 @@ var bake2 = async (args) => {
|
|
|
224287
224458
|
const keepGeometry = flagBool(args, "keep-geometry");
|
|
224288
224459
|
const obj = flagBool(args, "obj");
|
|
224289
224460
|
mkdirSync22(outDir, { recursive: true });
|
|
224290
|
-
const navmeshPath =
|
|
224291
|
-
if (!
|
|
224461
|
+
const navmeshPath = join32(outDir, `${name}.navmesh`);
|
|
224462
|
+
if (!existsSync30(navmeshPath))
|
|
224292
224463
|
writeFileSync23(navmeshPath, placeholderLnav());
|
|
224293
224464
|
const importPath = "./" + entryFile.replace(/\\/g, "/").replace(/\.tsx?$/, "");
|
|
224294
224465
|
const entryPath = "/.navmesh-entry.ts";
|
|
@@ -224303,8 +224474,8 @@ import ${JSON.stringify(importPath)}
|
|
|
224303
224474
|
extraEntries: [{ path: entryPath, type: "text", text: entryText }],
|
|
224304
224475
|
entryOverride: entryPath
|
|
224305
224476
|
});
|
|
224306
|
-
const scratch = mkdtempSync5(
|
|
224307
|
-
const outPng =
|
|
224477
|
+
const scratch = mkdtempSync5(join32(tmpdir5(), "lecodes-navmesh-"));
|
|
224478
|
+
const outPng = join32(scratch, "frame.png");
|
|
224308
224479
|
note(`Dumping the level's static collision geometry through the desktop host → ${relative5(root, outDir) || "."}/${name}.navgeo…`);
|
|
224309
224480
|
let output = "";
|
|
224310
224481
|
try {
|
|
@@ -224357,8 +224528,8 @@ import ${JSON.stringify(importPath)}
|
|
|
224357
224528
|
}
|
|
224358
224529
|
if (!config)
|
|
224359
224530
|
throw new CliError("The host reported a dump but no `[navmesh] config` line — SDK/host mismatch?");
|
|
224360
|
-
const geoPath =
|
|
224361
|
-
if (!
|
|
224531
|
+
const geoPath = join32(outDir, `${name}.navgeo`);
|
|
224532
|
+
if (!existsSync30(geoPath))
|
|
224362
224533
|
throw new CliError(`The host reported a dump but ${geoPath} is missing.`);
|
|
224363
224534
|
const geo = readNgeo(new Uint8Array(readFileSync26(geoPath)));
|
|
224364
224535
|
const params = {
|
|
@@ -224408,18 +224579,18 @@ import ${JSON.stringify(importPath)}
|
|
|
224408
224579
|
}
|
|
224409
224580
|
writeFileSync23(navmeshPath, result.data);
|
|
224410
224581
|
if (obj) {
|
|
224411
|
-
const objPath =
|
|
224582
|
+
const objPath = join32(outDir, `${name}.navmesh.obj`);
|
|
224412
224583
|
writeObj(objPath, navMeshTriangles(mod, result.data));
|
|
224413
224584
|
logErr(c.dim(` wrote ${relative5(root, objPath)} (the polygon mesh, for inspection)`));
|
|
224414
224585
|
}
|
|
224415
224586
|
if (!keepGeometry)
|
|
224416
224587
|
unlinkSync2(geoPath);
|
|
224417
|
-
const kb = Math.round(
|
|
224588
|
+
const kb = Math.round(statSync12(navmeshPath).size / 1024);
|
|
224418
224589
|
const b = result.bounds;
|
|
224419
224590
|
logErr(c.dim(` ${result.tiles} tiles, ${result.polys} polygons, ${(b.max[0] - b.min[0]).toFixed(0)} × ${(b.max[2] - b.min[2]).toFixed(0)} m, ${result.time.toFixed(1)} s`));
|
|
224420
224591
|
logErr(c.green(`✓ baked → ${relative5(root, navmeshPath).replace(/\\/g, "/")} (${kb} KB)`));
|
|
224421
224592
|
if (!config.data) {
|
|
224422
|
-
logErr(c.dim(` load it with env.navmesh: { data: asset('<rel>/${
|
|
224593
|
+
logErr(c.dim(` load it with env.navmesh: { data: asset('<rel>/${basename17(navmeshPath)}') } in the scene file, or NavMesh.load(scene, { data: asset(...) })`));
|
|
224423
224594
|
}
|
|
224424
224595
|
};
|
|
224425
224596
|
var navmesh = async (args) => {
|
|
@@ -224565,7 +224736,7 @@ var shaders = async (args) => {
|
|
|
224565
224736
|
|
|
224566
224737
|
// src/commands/render.ts
|
|
224567
224738
|
import { mkdirSync as mkdirSync23, readFileSync as readFileSync29, writeFileSync as writeFileSync24 } from "node:fs";
|
|
224568
|
-
import { dirname as
|
|
224739
|
+
import { dirname as dirname16, resolve as resolve17 } from "node:path";
|
|
224569
224740
|
|
|
224570
224741
|
// src/compile/headlessBundle.ts
|
|
224571
224742
|
init_api();
|
|
@@ -224649,8 +224820,8 @@ var compileHeadlessBundle = async (args, opts = {}) => {
|
|
|
224649
224820
|
// src/compile/screenEntry.ts
|
|
224650
224821
|
init_designMeta();
|
|
224651
224822
|
init_util();
|
|
224652
|
-
import { existsSync as
|
|
224653
|
-
import { isAbsolute, join as
|
|
224823
|
+
import { existsSync as existsSync31, readFileSync as readFileSync28, statSync as statSync13 } from "node:fs";
|
|
224824
|
+
import { isAbsolute, join as join33, relative as relative6, resolve as resolve15 } from "node:path";
|
|
224654
224825
|
var SCREEN_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs"];
|
|
224655
224826
|
var SCREEN_ENTRY_PATH = "/.screen-entry.ts";
|
|
224656
224827
|
var DEFAULT_DESIGN_DIR = "design";
|
|
@@ -224659,13 +224830,13 @@ var hasSeparator = (file) => file.includes("/") || file.includes("\\");
|
|
|
224659
224830
|
var findScreenFile = (root, file, dirFlag) => {
|
|
224660
224831
|
const candidates = [resolve15(process.cwd(), file)];
|
|
224661
224832
|
if (!hasSeparator(file)) {
|
|
224662
|
-
candidates.push(
|
|
224833
|
+
candidates.push(join33(root, (dirFlag ?? DEFAULT_DESIGN_DIR).replace(/[/\\]+$/, ""), "screens", file));
|
|
224663
224834
|
}
|
|
224664
224835
|
for (const base of candidates) {
|
|
224665
|
-
if (
|
|
224836
|
+
if (existsSync31(base) && statSync13(base).isFile())
|
|
224666
224837
|
return base;
|
|
224667
224838
|
for (const ext2 of SCREEN_EXTS)
|
|
224668
|
-
if (
|
|
224839
|
+
if (existsSync31(base + ext2))
|
|
224669
224840
|
return base + ext2;
|
|
224670
224841
|
}
|
|
224671
224842
|
throw new CliError(`No screen file at "${file}".` + (hasSeparator(file) ? "" : ` Pass a path, or a screen id that exists in ${dirFlag ?? DEFAULT_DESIGN_DIR}/screens/.`));
|
|
@@ -224674,8 +224845,8 @@ var designDirOf = (root, key) => {
|
|
|
224674
224845
|
const m = /^\/(.*)screens\/([^/]+)\.[^./]+$/.exec(key);
|
|
224675
224846
|
if (!m)
|
|
224676
224847
|
return null;
|
|
224677
|
-
const dir =
|
|
224678
|
-
return
|
|
224848
|
+
const dir = join33(root, m[1]);
|
|
224849
|
+
return existsSync31(join33(dir, "meta.json")) ? { dir, id: m[2] } : null;
|
|
224679
224850
|
};
|
|
224680
224851
|
var resolveScreenTarget = (root, file, opts = {}) => {
|
|
224681
224852
|
const abs = findScreenFile(root, file, opts.dir);
|
|
@@ -225034,7 +225205,7 @@ var requireRenderer = async () => {
|
|
|
225034
225205
|
var fileScenarioIO = (dir) => ({
|
|
225035
225206
|
write: (relPath, data) => {
|
|
225036
225207
|
const abs = resolve17(dir, relPath);
|
|
225037
|
-
mkdirSync23(
|
|
225208
|
+
mkdirSync23(dirname16(abs), { recursive: true });
|
|
225038
225209
|
writeFileSync24(abs, data);
|
|
225039
225210
|
}
|
|
225040
225211
|
});
|
|
@@ -225109,23 +225280,25 @@ var renderDesktop = async (args) => {
|
|
|
225109
225280
|
if ((camera || view) && scenario)
|
|
225110
225281
|
throw new CliError('--camera/--view apply to a plain render; in a --script run use a { "view": "iso" } or { "camera": { "at", "lookAt" } } step before the screenshot.');
|
|
225111
225282
|
const desktopRenderer = resolveDesktopRenderer(root, args);
|
|
225283
|
+
const { dirs: pluginDirs } = desktopPluginLibraries(root);
|
|
225112
225284
|
const { js, resources } = await buildBundle(args, undefined, {
|
|
225113
225285
|
localAssets: true,
|
|
225114
225286
|
desktopRenderer,
|
|
225115
225287
|
extraEntries: screen2 ? [screen2.entry] : undefined,
|
|
225116
225288
|
entryOverride: screen2?.entryPath
|
|
225117
225289
|
});
|
|
225118
|
-
mkdirSync23(
|
|
225290
|
+
mkdirSync23(dirname16(resolve17(pngFlag)), { recursive: true });
|
|
225119
225291
|
if (scenario) {
|
|
225120
225292
|
const outDir = flagStr(args, "out-dir") ?? ".";
|
|
225121
225293
|
const plan = translateScenario(scenario.steps, { outDir, headroomFrames: frames });
|
|
225122
225294
|
for (const st of plan.steps)
|
|
225123
225295
|
if (st.screenshot)
|
|
225124
|
-
mkdirSync23(
|
|
225296
|
+
mkdirSync23(dirname16(st.screenshot), { recursive: true });
|
|
225125
225297
|
const timeoutMs2 = Number(flagStr(args, "timeout")) || 60000 + plan.steps.length * 5000;
|
|
225126
225298
|
note(`Running ${plan.steps.length} step${plan.steps.length === 1 ? "" : "s"} (native)…`);
|
|
225127
225299
|
const { output } = await runDesktopRender(js, resources, {
|
|
225128
225300
|
renderer: desktopRenderer,
|
|
225301
|
+
pluginDirs,
|
|
225129
225302
|
width,
|
|
225130
225303
|
height,
|
|
225131
225304
|
frames: plan.frameCap,
|
|
@@ -225158,6 +225331,7 @@ var renderDesktop = async (args) => {
|
|
|
225158
225331
|
note(screen2 ? `Rendering ${screen2.label} (native)…` : "Rendering (native)…");
|
|
225159
225332
|
await runDesktopRender(js, resources, {
|
|
225160
225333
|
renderer: desktopRenderer,
|
|
225334
|
+
pluginDirs,
|
|
225161
225335
|
width,
|
|
225162
225336
|
height,
|
|
225163
225337
|
frames,
|
|
@@ -225225,7 +225399,7 @@ var render = async (args) => {
|
|
|
225225
225399
|
const settleStr = flagStr(args, "settle") ?? (scenario?.settle !== undefined ? String(scenario.settle) : undefined);
|
|
225226
225400
|
const timeStr = flagStr(args, "time");
|
|
225227
225401
|
const onConsole = flagBool(args, "logs") ? (level, text2) => logErr(`${c.dim(`[${level}]`)} ${text2}`) : undefined;
|
|
225228
|
-
const envelopeFixtures = resolveFixtures(scenario?.fixtures, scriptFlag !== undefined ?
|
|
225402
|
+
const envelopeFixtures = resolveFixtures(scenario?.fixtures, scriptFlag !== undefined ? dirname16(resolve17(scriptFlag)) : ".");
|
|
225229
225403
|
const flagFixtures = resolveFixtures(flagStr(args, "fixtures"), ".");
|
|
225230
225404
|
const fixtures = envelopeFixtures || flagFixtures ? { ...envelopeFixtures, ...flagFixtures } : undefined;
|
|
225231
225405
|
if (fixtures) {
|
|
@@ -225285,7 +225459,7 @@ var render = async (args) => {
|
|
|
225285
225459
|
for (const w of [...warnings, ...mapWarnings])
|
|
225286
225460
|
warnErr(w);
|
|
225287
225461
|
const pngPath = mapFlag.endsWith(".png") ? mapFlag : mapFlag + ".png";
|
|
225288
|
-
mkdirSync23(
|
|
225462
|
+
mkdirSync23(dirname16(resolve17(pngPath)), { recursive: true });
|
|
225289
225463
|
writeFileSync24(resolve17(pngPath), png2);
|
|
225290
225464
|
const jsonPath = pngPath.slice(0, -4) + ".json";
|
|
225291
225465
|
writeFileSync24(resolve17(jsonPath), JSON.stringify(data, null, 2));
|
|
@@ -225308,7 +225482,7 @@ var render = async (args) => {
|
|
|
225308
225482
|
if (isNullSink(pngFlag)) {
|
|
225309
225483
|
note(`Discarded PNG (${pngFlag})`);
|
|
225310
225484
|
} else {
|
|
225311
|
-
mkdirSync23(
|
|
225485
|
+
mkdirSync23(dirname16(resolve17(pngFlag)), { recursive: true });
|
|
225312
225486
|
writeFileSync24(resolve17(pngFlag), png2);
|
|
225313
225487
|
note(`Wrote ${pngFlag} (${png2.length} bytes, ${outW}x${outH}${clip !== undefined ? ", clipped" : ""})`);
|
|
225314
225488
|
}
|
|
@@ -225339,8 +225513,8 @@ init_api();
|
|
|
225339
225513
|
init_config();
|
|
225340
225514
|
init_manifest();
|
|
225341
225515
|
init_util();
|
|
225342
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
225343
|
-
import { join as
|
|
225516
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync32, readFileSync as readFileSync30, writeFileSync as writeFileSync25 } from "node:fs";
|
|
225517
|
+
import { join as join34 } from "node:path";
|
|
225344
225518
|
var ENV_VAR = "LECODES_PUSH_KEY";
|
|
225345
225519
|
var context = () => {
|
|
225346
225520
|
const root = findProjectRoot(process.cwd());
|
|
@@ -225484,9 +225658,9 @@ var pnKeysList = async (ctx) => {
|
|
|
225484
225658
|
};
|
|
225485
225659
|
var writeEnv = (root, key) => {
|
|
225486
225660
|
const touched = [];
|
|
225487
|
-
const envPath =
|
|
225661
|
+
const envPath = join34(root, ".env");
|
|
225488
225662
|
const line = `${ENV_VAR}=${key}`;
|
|
225489
|
-
const existing =
|
|
225663
|
+
const existing = existsSync32(envPath) ? readFileSync30(envPath, "utf8") : "";
|
|
225490
225664
|
if (new RegExp(`^${ENV_VAR}=`, "m").test(existing)) {
|
|
225491
225665
|
writeFileSync25(envPath, existing.replace(new RegExp(`^${ENV_VAR}=.*$`, "m"), line));
|
|
225492
225666
|
} else {
|
|
@@ -225497,8 +225671,8 @@ var writeEnv = (root, key) => {
|
|
|
225497
225671
|
`);
|
|
225498
225672
|
}
|
|
225499
225673
|
touched.push(".env");
|
|
225500
|
-
const ignorePath =
|
|
225501
|
-
const ignore =
|
|
225674
|
+
const ignorePath = join34(root, ".gitignore");
|
|
225675
|
+
const ignore = existsSync32(ignorePath) ? readFileSync30(ignorePath, "utf8") : "";
|
|
225502
225676
|
if (!ignore.split(`
|
|
225503
225677
|
`).some((l2) => l2.trim() === ".env")) {
|
|
225504
225678
|
const separator = !ignore || ignore.endsWith(`
|
|
@@ -225597,8 +225771,8 @@ var pn = async (args) => {
|
|
|
225597
225771
|
init_api();
|
|
225598
225772
|
init_config();
|
|
225599
225773
|
init_manifest();
|
|
225600
|
-
import { existsSync as
|
|
225601
|
-
import { dirname as
|
|
225774
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync24, rmSync as rmSync11, writeFileSync as writeFileSync26 } from "node:fs";
|
|
225775
|
+
import { dirname as dirname17, join as join35 } from "node:path";
|
|
225602
225776
|
init_types4();
|
|
225603
225777
|
init_localFiles();
|
|
225604
225778
|
init_util();
|
|
@@ -225621,8 +225795,8 @@ var pull = async (args) => {
|
|
|
225621
225795
|
const remotePaths = new Set([...buildPaths(project.assets).entries()].filter(([id]) => project.assets.find((a2) => a2.id === id)?.type !== "folder").map(([, path2]) => path2));
|
|
225622
225796
|
for (const path2 of Object.keys(manifest.files)) {
|
|
225623
225797
|
if (!remotePaths.has(path2)) {
|
|
225624
|
-
const abs =
|
|
225625
|
-
if (
|
|
225798
|
+
const abs = join35(root, ...path2.replace(/^\//, "").split("/"));
|
|
225799
|
+
if (existsSync33(abs))
|
|
225626
225800
|
rmSync11(abs);
|
|
225627
225801
|
}
|
|
225628
225802
|
}
|
|
@@ -225660,8 +225834,8 @@ var pullPaths = async (root, manifest, project, paths, apiUrl, token) => {
|
|
|
225660
225834
|
const files = { ...manifest.files };
|
|
225661
225835
|
for (const asset of targets) {
|
|
225662
225836
|
const key = pathById.get(asset.id);
|
|
225663
|
-
const abs =
|
|
225664
|
-
mkdirSync24(
|
|
225837
|
+
const abs = join35(root, ...key.replace(/^\//, "").split("/"));
|
|
225838
|
+
mkdirSync24(dirname17(abs), { recursive: true });
|
|
225665
225839
|
let sha;
|
|
225666
225840
|
if (asset.type === "file") {
|
|
225667
225841
|
if (!asset.file?.src)
|
|
@@ -225684,8 +225858,8 @@ var pullPaths = async (root, manifest, project, paths, apiUrl, token) => {
|
|
|
225684
225858
|
|
|
225685
225859
|
// src/commands/scene.ts
|
|
225686
225860
|
init_manifest();
|
|
225687
|
-
import { existsSync as
|
|
225688
|
-
import { basename as
|
|
225861
|
+
import { existsSync as existsSync35, readFileSync as readFileSync32, readdirSync as readdirSync16, statSync as statSync14, writeFileSync as writeFileSync28 } from "node:fs";
|
|
225862
|
+
import { basename as basename18, dirname as dirname18, join as join37, resolve as resolve18 } from "node:path";
|
|
225689
225863
|
|
|
225690
225864
|
// src/compile/sceneCompile.ts
|
|
225691
225865
|
init_localFiles();
|
|
@@ -225694,17 +225868,17 @@ init_distRoot();
|
|
|
225694
225868
|
init_util();
|
|
225695
225869
|
init_projectCompile();
|
|
225696
225870
|
import { createHash as createHash8 } from "node:crypto";
|
|
225697
|
-
import { existsSync as
|
|
225698
|
-
import { join as
|
|
225871
|
+
import { existsSync as existsSync34, mkdirSync as mkdirSync25, readFileSync as readFileSync31, writeFileSync as writeFileSync27 } from "node:fs";
|
|
225872
|
+
import { join as join36 } from "node:path";
|
|
225699
225873
|
var TEXT_EXT = /\.(ts|js|json|svg|txt|md)$/i;
|
|
225700
225874
|
var rel = (key) => key.replace(/^\//, "");
|
|
225701
225875
|
var resolveHarness = (loadSceneHarness2) => {
|
|
225702
|
-
const inRepo =
|
|
225876
|
+
const inRepo = join36(distRoot, "..", "projects", "src", "scene-editor");
|
|
225703
225877
|
try {
|
|
225704
|
-
return loadSceneHarness2(
|
|
225878
|
+
return loadSceneHarness2(existsSync34(inRepo) ? inRepo : undefined);
|
|
225705
225879
|
} catch {
|
|
225706
|
-
const vendored =
|
|
225707
|
-
if (
|
|
225880
|
+
const vendored = join36(distRoot, "runtime", "scene-harness.json");
|
|
225881
|
+
if (existsSync34(vendored))
|
|
225708
225882
|
return JSON.parse(readFileSync31(vendored, "utf8"));
|
|
225709
225883
|
throw new CliError("scene-editor harness sources not found — reinstall the CLI or set LECODES_SCENE_HARNESS_DIR.");
|
|
225710
225884
|
}
|
|
@@ -225737,8 +225911,8 @@ var compileSceneEditor = async (opts) => {
|
|
|
225737
225911
|
const dir = shadersCacheDir(root);
|
|
225738
225912
|
mkdirSync25(dir, { recursive: true });
|
|
225739
225913
|
const liteName = `${hash}_webgl-lite.filamat`;
|
|
225740
|
-
if (!
|
|
225741
|
-
writeFileSync27(
|
|
225914
|
+
if (!existsSync34(join36(dir, liteName)))
|
|
225915
|
+
writeFileSync27(join36(dir, liteName), JSON.stringify(buildLiteMaterialArtifact2(e2.text ?? "")));
|
|
225742
225916
|
const src = `/project/.lecodes/shaders/${hash}_opengl.filamat`;
|
|
225743
225917
|
e2.shaders = ["opengl", "webgl-lite"].map((platform) => ({ platform, src }));
|
|
225744
225918
|
}
|
|
@@ -225772,9 +225946,9 @@ var DEFAULT_PORT3 = 4488;
|
|
|
225772
225946
|
var findAppRoot = (start) => {
|
|
225773
225947
|
let dir = start;
|
|
225774
225948
|
while (true) {
|
|
225775
|
-
if (
|
|
225949
|
+
if (existsSync35(join37(dir, "app.json")))
|
|
225776
225950
|
return dir;
|
|
225777
|
-
const parent =
|
|
225951
|
+
const parent = dirname18(dir);
|
|
225778
225952
|
if (parent === dir)
|
|
225779
225953
|
return null;
|
|
225780
225954
|
dir = parent;
|
|
@@ -225799,23 +225973,23 @@ var getContext2 = (args) => {
|
|
|
225799
225973
|
const pathArg = args._[0];
|
|
225800
225974
|
if (pathArg) {
|
|
225801
225975
|
const abs = resolve18(process.cwd(), pathArg);
|
|
225802
|
-
if (
|
|
225976
|
+
if (existsSync35(abs) && statSync14(abs).isDirectory())
|
|
225803
225977
|
root = abs;
|
|
225804
|
-
else if (abs.endsWith(".scene.ts") &&
|
|
225805
|
-
root = findAppRoot(
|
|
225978
|
+
else if (abs.endsWith(".scene.ts") && existsSync35(abs))
|
|
225979
|
+
root = findAppRoot(dirname18(abs)) ?? dirname18(abs);
|
|
225806
225980
|
else
|
|
225807
225981
|
throw new CliError(`No such folder or .scene.ts: ${pathArg}`);
|
|
225808
225982
|
} else {
|
|
225809
225983
|
root = findAppRoot(root) ?? root;
|
|
225810
225984
|
}
|
|
225811
225985
|
}
|
|
225812
|
-
return { root, manifest, name: manifest?.name ??
|
|
225986
|
+
return { root, manifest, name: manifest?.name ?? basename18(root) };
|
|
225813
225987
|
};
|
|
225814
225988
|
var writeMcpConfig2 = (root, port) => {
|
|
225815
|
-
const path2 =
|
|
225989
|
+
const path2 = join37(root, ".mcp.json");
|
|
225816
225990
|
const entry = { type: "http", url: `http://localhost:${port}/mcp` };
|
|
225817
225991
|
let config = {};
|
|
225818
|
-
if (
|
|
225992
|
+
if (existsSync35(path2)) {
|
|
225819
225993
|
try {
|
|
225820
225994
|
config = JSON.parse(readFileSync32(path2, "utf8"));
|
|
225821
225995
|
} catch {
|
|
@@ -225836,11 +226010,11 @@ var writeMcpConfig2 = (root, port) => {
|
|
|
225836
226010
|
};
|
|
225837
226011
|
var countScenes = (dir) => {
|
|
225838
226012
|
let n2 = 0;
|
|
225839
|
-
for (const name of
|
|
226013
|
+
for (const name of readdirSync16(dir)) {
|
|
225840
226014
|
if (name === "node_modules" || name.startsWith("."))
|
|
225841
226015
|
continue;
|
|
225842
|
-
const full =
|
|
225843
|
-
if (
|
|
226016
|
+
const full = join37(dir, name);
|
|
226017
|
+
if (statSync14(full).isDirectory())
|
|
225844
226018
|
n2 += countScenes(full);
|
|
225845
226019
|
else if (name.endsWith(".scene.ts"))
|
|
225846
226020
|
n2++;
|
|
@@ -225882,11 +226056,11 @@ var scene = async (args) => {
|
|
|
225882
226056
|
};
|
|
225883
226057
|
|
|
225884
226058
|
// src/commands/thumbs.ts
|
|
225885
|
-
import { createRequire as
|
|
226059
|
+
import { createRequire as createRequire6 } from "node:module";
|
|
225886
226060
|
import { execFileSync as execFileSync7 } from "node:child_process";
|
|
225887
|
-
import { existsSync as
|
|
226061
|
+
import { existsSync as existsSync36, mkdtempSync as mkdtempSync6, readdirSync as readdirSync17, rmSync as rmSync12, statSync as statSync15 } from "node:fs";
|
|
225888
226062
|
import { tmpdir as tmpdir6 } from "node:os";
|
|
225889
|
-
import { extname, join as
|
|
226063
|
+
import { extname, join as join38, relative as relative7, resolve as resolve19 } from "node:path";
|
|
225890
226064
|
init_util();
|
|
225891
226065
|
var DEFAULT_SIZE = 256;
|
|
225892
226066
|
var IMAGE_EXT = /\.(png|jpe?g|webp|bmp|gif|tiff?|ktx2)$/i;
|
|
@@ -225897,13 +226071,13 @@ var findKtx = () => {
|
|
|
225897
226071
|
process.env.LECODES_KTX,
|
|
225898
226072
|
process.env.KTX_CLI,
|
|
225899
226073
|
process.env.KTX_TOKTX?.replace(/toktx(\.exe)?$/i, exe),
|
|
225900
|
-
process.platform === "win32" ?
|
|
225901
|
-
process.platform === "win32" ?
|
|
226074
|
+
process.platform === "win32" ? join38(process.env.LOCALAPPDATA ?? "", "Programs", "KTX-Software", "bin", exe) : null,
|
|
226075
|
+
process.platform === "win32" ? join38(process.env.ProgramFiles ?? "", "KTX-Software", "bin", exe) : null,
|
|
225902
226076
|
"/usr/local/bin/ktx",
|
|
225903
226077
|
"/opt/homebrew/bin/ktx"
|
|
225904
226078
|
].filter((p2) => !!p2);
|
|
225905
226079
|
for (const path2 of candidates) {
|
|
225906
|
-
if (
|
|
226080
|
+
if (existsSync36(path2))
|
|
225907
226081
|
return path2;
|
|
225908
226082
|
}
|
|
225909
226083
|
try {
|
|
@@ -225915,8 +226089,8 @@ var findKtx = () => {
|
|
|
225915
226089
|
};
|
|
225916
226090
|
var sharpResizer = () => {
|
|
225917
226091
|
try {
|
|
225918
|
-
const req =
|
|
225919
|
-
const sharp =
|
|
226092
|
+
const req = createRequire6(import.meta.url);
|
|
226093
|
+
const sharp = createRequire6(req.resolve("lecodes-assets/cli"))("sharp");
|
|
225920
226094
|
return async (file, size) => sharp(file).resize({ width: size, height: size, fit: "inside", withoutEnlargement: true }).png().toBuffer();
|
|
225921
226095
|
} catch {
|
|
225922
226096
|
return null;
|
|
@@ -225935,17 +226109,17 @@ var ktxToPng = (ktx, file, out) => {
|
|
|
225935
226109
|
run2(["extract", "--transcode", "rgba8", "--level", "0", file, out]);
|
|
225936
226110
|
} catch (e2) {
|
|
225937
226111
|
run2(["extract", "--level", "0", file, out]);
|
|
225938
|
-
if (!
|
|
226112
|
+
if (!existsSync36(out))
|
|
225939
226113
|
throw e2;
|
|
225940
226114
|
}
|
|
225941
226115
|
};
|
|
225942
226116
|
var collect = (dir) => {
|
|
225943
226117
|
const out = [];
|
|
225944
|
-
for (const name of
|
|
226118
|
+
for (const name of readdirSync17(dir)) {
|
|
225945
226119
|
if (name === "node_modules" || name.startsWith("."))
|
|
225946
226120
|
continue;
|
|
225947
|
-
const full =
|
|
225948
|
-
if (
|
|
226121
|
+
const full = join38(dir, name);
|
|
226122
|
+
if (statSync15(full).isDirectory())
|
|
225949
226123
|
out.push(...collect(full));
|
|
225950
226124
|
else if (IMAGE_EXT.test(name))
|
|
225951
226125
|
out.push(full);
|
|
@@ -225967,9 +226141,9 @@ var thumbs = async (args) => {
|
|
|
225967
226141
|
if (args._.length > 0) {
|
|
225968
226142
|
for (const arg of args._) {
|
|
225969
226143
|
const abs = resolve19(process.cwd(), arg);
|
|
225970
|
-
if (!
|
|
226144
|
+
if (!existsSync36(abs))
|
|
225971
226145
|
throw new CliError(`No such file or folder: ${arg}`);
|
|
225972
|
-
if (
|
|
226146
|
+
if (statSync15(abs).isDirectory())
|
|
225973
226147
|
files.push(...collect(abs));
|
|
225974
226148
|
else if (IMAGE_EXT.test(abs))
|
|
225975
226149
|
files.push(abs);
|
|
@@ -225989,7 +226163,7 @@ var thumbs = async (args) => {
|
|
|
225989
226163
|
const ktx = files.some((f3) => f3.toLowerCase().endsWith(".ktx2")) ? findKtx() : null;
|
|
225990
226164
|
const sharp = sharpResizer();
|
|
225991
226165
|
const resize = sharp ?? jimpResizer();
|
|
225992
|
-
const tmp = mkdtempSync6(
|
|
226166
|
+
const tmp = mkdtempSync6(join38(tmpdir6(), "lecodes-thumbs-"));
|
|
225993
226167
|
let made = 0, fresh = 0;
|
|
225994
226168
|
const skipped = [];
|
|
225995
226169
|
try {
|
|
@@ -226015,7 +226189,7 @@ var thumbs = async (args) => {
|
|
|
226015
226189
|
skipped.push(`${asset} (KTX2 needs KTX-Software's \`ktx\` — set LECODES_KTX or put it on PATH)`);
|
|
226016
226190
|
continue;
|
|
226017
226191
|
}
|
|
226018
|
-
source =
|
|
226192
|
+
source = join38(tmp, `${i2}.png`);
|
|
226019
226193
|
ktxToPng(ktx, file, source);
|
|
226020
226194
|
}
|
|
226021
226195
|
sceneServer.writePreviewFile(root, asset, await resize(source, size));
|
|
@@ -226035,16 +226209,16 @@ var thumbs = async (args) => {
|
|
|
226035
226209
|
if (rendered.length > 0) {
|
|
226036
226210
|
warnErr(`Models, materials and prefabs are RENDERED, not decoded — the scene editor does those: ${rendered.join(", ")}`);
|
|
226037
226211
|
}
|
|
226038
|
-
note(`Cache: ${
|
|
226212
|
+
note(`Cache: ${join38(root, ".lecodes", "preview")} (re-runs skip everything unchanged)`);
|
|
226039
226213
|
};
|
|
226040
226214
|
|
|
226041
226215
|
// src/commands/assets.ts
|
|
226042
226216
|
init_util();
|
|
226043
226217
|
|
|
226044
226218
|
// src/cmgenTool.ts
|
|
226045
|
-
import { existsSync as
|
|
226219
|
+
import { existsSync as existsSync37, readdirSync as readdirSync18 } from "node:fs";
|
|
226046
226220
|
import { homedir as homedir8 } from "node:os";
|
|
226047
|
-
import { join as
|
|
226221
|
+
import { join as join39, resolve as resolve20 } from "node:path";
|
|
226048
226222
|
init_util();
|
|
226049
226223
|
var exeName2 = () => process.platform === "win32" ? "cmgen.exe" : "cmgen";
|
|
226050
226224
|
var platformKey3 = () => {
|
|
@@ -226054,10 +226228,10 @@ var platformKey3 = () => {
|
|
|
226054
226228
|
return "linux-x64";
|
|
226055
226229
|
throw new CliError(process.platform === "darwin" ? "cmgen isn't published for macOS yet — build filament's host tools locally and set LECODES_CMGEN." : `cmgen isn't published for ${process.platform}.`);
|
|
226056
226230
|
};
|
|
226057
|
-
var cacheRoot3 = () =>
|
|
226231
|
+
var cacheRoot3 = () => join39(homedir8(), ".lecodes", "cmgen");
|
|
226058
226232
|
var findCmgenIn = (dir) => {
|
|
226059
|
-
for (const entry of
|
|
226060
|
-
const p2 =
|
|
226233
|
+
for (const entry of readdirSync18(dir, { withFileTypes: true })) {
|
|
226234
|
+
const p2 = join39(dir, entry.name);
|
|
226061
226235
|
if (entry.isFile() && entry.name === exeName2())
|
|
226062
226236
|
return p2;
|
|
226063
226237
|
if (entry.isDirectory()) {
|
|
@@ -226070,7 +226244,7 @@ var findCmgenIn = (dir) => {
|
|
|
226070
226244
|
};
|
|
226071
226245
|
var installedCmgenVersions = () => {
|
|
226072
226246
|
try {
|
|
226073
|
-
return
|
|
226247
|
+
return readdirSync18(cacheRoot3(), { withFileTypes: true }).filter((e2) => e2.isDirectory() && e2.name.startsWith("cmgen-")).map((e2) => e2.name.slice("cmgen-".length)).filter((v) => findCmgenIn(join39(cacheRoot3(), `cmgen-${v}`)) !== null).sort(semverNewer);
|
|
226074
226248
|
} catch {
|
|
226075
226249
|
return [];
|
|
226076
226250
|
}
|
|
@@ -226092,19 +226266,19 @@ var downloadCmgen = async (version, versions, dest) => {
|
|
|
226092
226266
|
var resolveCmgenExeCached = () => {
|
|
226093
226267
|
const override = process.env.LECODES_CMGEN;
|
|
226094
226268
|
if (override) {
|
|
226095
|
-
if (!
|
|
226269
|
+
if (!existsSync37(override))
|
|
226096
226270
|
throw new CliError(`LECODES_CMGEN points at "${override}" which doesn't exist.`);
|
|
226097
226271
|
return resolve20(override);
|
|
226098
226272
|
}
|
|
226099
226273
|
const cached = installedCmgenVersions()[0];
|
|
226100
|
-
return cached ? findCmgenIn(
|
|
226274
|
+
return cached ? findCmgenIn(join39(cacheRoot3(), `cmgen-${cached}`)) : null;
|
|
226101
226275
|
};
|
|
226102
226276
|
var resolveCmgenExe = async () => {
|
|
226103
226277
|
const cached = resolveCmgenExeCached();
|
|
226104
226278
|
if (cached)
|
|
226105
226279
|
return cached;
|
|
226106
226280
|
const { latest, versions } = await fetchCmgenManifest();
|
|
226107
|
-
const dir =
|
|
226281
|
+
const dir = join39(cacheRoot3(), `cmgen-${latest}`);
|
|
226108
226282
|
await downloadCmgen(latest, versions, dir);
|
|
226109
226283
|
const exe = findCmgenIn(dir);
|
|
226110
226284
|
if (!exe)
|
|
@@ -226162,8 +226336,8 @@ var status3 = async (_args) => {
|
|
|
226162
226336
|
};
|
|
226163
226337
|
|
|
226164
226338
|
// src/commands/test.ts
|
|
226165
|
-
import { existsSync as
|
|
226166
|
-
import { dirname as
|
|
226339
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync26, readFileSync as readFileSync33, readdirSync as readdirSync19 } from "node:fs";
|
|
226340
|
+
import { dirname as dirname19, resolve as resolve21 } from "node:path";
|
|
226167
226341
|
init_manifest();
|
|
226168
226342
|
init_util();
|
|
226169
226343
|
var deriveDesignFlows = (meta, entryScreen) => {
|
|
@@ -226240,7 +226414,7 @@ var readFlowFile = (abs, displayName) => {
|
|
|
226240
226414
|
name: file.name ?? displayName,
|
|
226241
226415
|
kind: "file",
|
|
226242
226416
|
steps: file.steps,
|
|
226243
|
-
fixtures: resolveFixtures(file.fixtures,
|
|
226417
|
+
fixtures: resolveFixtures(file.fixtures, dirname19(abs)),
|
|
226244
226418
|
width: file.width,
|
|
226245
226419
|
height: file.height,
|
|
226246
226420
|
settle: file.settle,
|
|
@@ -226289,29 +226463,29 @@ var test = async (args) => {
|
|
|
226289
226463
|
if (args._.length > 0) {
|
|
226290
226464
|
for (const given of args._) {
|
|
226291
226465
|
const candidates = [resolve21(given), resolve21(testsDir, given), resolve21(testsDir, `${given}.flow.json`)];
|
|
226292
|
-
const abs = candidates.find((p2) =>
|
|
226466
|
+
const abs = candidates.find((p2) => existsSync38(p2));
|
|
226293
226467
|
if (!abs)
|
|
226294
226468
|
throw new CliError(`No such test: "${given}" (looked in ${testsDir}).`);
|
|
226295
226469
|
cases.push(readFlowFile(abs, given));
|
|
226296
226470
|
}
|
|
226297
|
-
} else if (
|
|
226298
|
-
for (const f3 of
|
|
226471
|
+
} else if (existsSync38(testsDir)) {
|
|
226472
|
+
for (const f3 of readdirSync19(testsDir).filter((f4) => f4.endsWith(".flow.json")).sort()) {
|
|
226299
226473
|
cases.push(readFlowFile(resolve21(testsDir, f3), f3));
|
|
226300
226474
|
}
|
|
226301
226475
|
}
|
|
226302
226476
|
const fixturesFlag = flagStr(args, "fixtures");
|
|
226303
226477
|
const defaultPack = resolve21(testsDir, "fixtures.json");
|
|
226304
|
-
const flowFixtures = fixturesFlag !== undefined ? resolveFixtures(fixturesFlag, ".") :
|
|
226478
|
+
const flowFixtures = fixturesFlag !== undefined ? resolveFixtures(fixturesFlag, ".") : existsSync38(defaultPack) ? resolveFixtures("fixtures.json", testsDir) : undefined;
|
|
226305
226479
|
const flowsOnly = flagBool(args, "flows");
|
|
226306
226480
|
const wantFlows = !flagBool(args, "no-flows") && args._.length === 0;
|
|
226307
226481
|
if (flowsOnly)
|
|
226308
226482
|
cases.length = 0;
|
|
226309
226483
|
let skipped = [];
|
|
226310
226484
|
let entryScreen = null;
|
|
226311
|
-
if (desktop2 && wantFlows &&
|
|
226485
|
+
if (desktop2 && wantFlows && existsSync38(designMetaPath)) {
|
|
226312
226486
|
note("Design-derived flows skipped with --desktop (they tap by name; run `lecodes test` headless for them).");
|
|
226313
226487
|
}
|
|
226314
|
-
if (!desktop2 && (wantFlows || flowsOnly) &&
|
|
226488
|
+
if (!desktop2 && (wantFlows || flowsOnly) && existsSync38(designMetaPath)) {
|
|
226315
226489
|
let meta;
|
|
226316
226490
|
try {
|
|
226317
226491
|
meta = JSON.parse(readFileSync33(designMetaPath, "utf8"));
|
|
@@ -226353,11 +226527,12 @@ var test = async (args) => {
|
|
|
226353
226527
|
const plan = translateScenario(kase.steps, { outDir: caseDir, headroomFrames: nativeFrames });
|
|
226354
226528
|
for (const st of plan.steps)
|
|
226355
226529
|
if (st.screenshot)
|
|
226356
|
-
mkdirSync26(
|
|
226530
|
+
mkdirSync26(dirname19(st.screenshot), { recursive: true });
|
|
226357
226531
|
mkdirSync26(caseDir, { recursive: true });
|
|
226358
226532
|
const finalPng = resolve21(caseDir, "final.png");
|
|
226359
226533
|
const { output } = await runDesktopRender(native.js, native.resources, {
|
|
226360
226534
|
renderer: desktopRenderer,
|
|
226535
|
+
pluginDirs: desktopPluginLibraries(root).dirs,
|
|
226361
226536
|
width: Number(flagStr(args, "width")) || kase.width || projectViewport?.width || 390,
|
|
226362
226537
|
height: Number(flagStr(args, "height")) || kase.height || projectViewport?.height || 844,
|
|
226363
226538
|
frames: plan.frameCap,
|
|
@@ -226478,15 +226653,15 @@ var test = async (args) => {
|
|
|
226478
226653
|
|
|
226479
226654
|
// src/commands/update.ts
|
|
226480
226655
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
226481
|
-
import { existsSync as
|
|
226656
|
+
import { existsSync as existsSync40, readdirSync as readdirSync20 } from "node:fs";
|
|
226482
226657
|
import { homedir as homedir9 } from "node:os";
|
|
226483
|
-
import { dirname as
|
|
226658
|
+
import { dirname as dirname21, join as join41, resolve as resolve23 } from "node:path";
|
|
226484
226659
|
init_util();
|
|
226485
226660
|
|
|
226486
226661
|
// src/peers.ts
|
|
226487
|
-
import { existsSync as
|
|
226488
|
-
import { createRequire as
|
|
226489
|
-
import { dirname as
|
|
226662
|
+
import { existsSync as existsSync39, readFileSync as readFileSync34 } from "node:fs";
|
|
226663
|
+
import { createRequire as createRequire7 } from "node:module";
|
|
226664
|
+
import { dirname as dirname20, join as join40 } from "node:path";
|
|
226490
226665
|
var OPTIONAL_PEERS = [
|
|
226491
226666
|
["lecodes-renderer", "lecodes-renderer/headless"],
|
|
226492
226667
|
["lecodes-design", "lecodes-design/server"],
|
|
@@ -226495,16 +226670,16 @@ var OPTIONAL_PEERS = [
|
|
|
226495
226670
|
];
|
|
226496
226671
|
var peerVersion = (name, probe) => {
|
|
226497
226672
|
try {
|
|
226498
|
-
const require2 =
|
|
226499
|
-
let dir =
|
|
226673
|
+
const require2 = createRequire7(import.meta.url);
|
|
226674
|
+
let dir = dirname20(require2.resolve(probe));
|
|
226500
226675
|
for (let depth = 0;depth < 16; depth++) {
|
|
226501
|
-
const manifest =
|
|
226502
|
-
if (
|
|
226676
|
+
const manifest = join40(dir, "package.json");
|
|
226677
|
+
if (existsSync39(manifest)) {
|
|
226503
226678
|
const parsed = JSON.parse(readFileSync34(manifest, "utf8"));
|
|
226504
226679
|
if (parsed.name === name)
|
|
226505
226680
|
return parsed.version ?? "unknown";
|
|
226506
226681
|
}
|
|
226507
|
-
const parent =
|
|
226682
|
+
const parent = dirname20(dir);
|
|
226508
226683
|
if (parent === dir)
|
|
226509
226684
|
break;
|
|
226510
226685
|
dir = parent;
|
|
@@ -226586,9 +226761,9 @@ var findProjectDir = (start) => {
|
|
|
226586
226761
|
const home = resolve23(homedir9());
|
|
226587
226762
|
let dir = resolve23(start);
|
|
226588
226763
|
while (true) {
|
|
226589
|
-
if (dir !== home && (
|
|
226764
|
+
if (dir !== home && (existsSync40(join41(dir, "app.json")) || existsSync40(join41(dir, ".lecodes", "manifest.json")) || existsSync40(join41(dir, ".lecodes", "types"))))
|
|
226590
226765
|
return dir;
|
|
226591
|
-
const parent =
|
|
226766
|
+
const parent = dirname21(dir);
|
|
226592
226767
|
if (parent === dir)
|
|
226593
226768
|
return null;
|
|
226594
226769
|
dir = parent;
|
|
@@ -226616,7 +226791,7 @@ var semverNewer2 = (a2, b) => {
|
|
|
226616
226791
|
return 0;
|
|
226617
226792
|
};
|
|
226618
226793
|
var FROM_SOURCE = /[\\/]src[\\/]commands[\\/]/.test(import.meta.url);
|
|
226619
|
-
var STANDALONE =
|
|
226794
|
+
var STANDALONE = existsSync40(join41(dirname21(process.execPath), "runtime")) && existsSync40(join41(dirname21(process.execPath), process.platform === "win32" ? "chisel.exe" : "chisel"));
|
|
226620
226795
|
var update = async (args) => {
|
|
226621
226796
|
const steps = [];
|
|
226622
226797
|
const heading = (name, what) => log(`
|
|
@@ -226665,7 +226840,7 @@ ${c.bold(name)} ${c.dim(what)}`);
|
|
|
226665
226840
|
return ["skipped", "not inside a project"];
|
|
226666
226841
|
if (flagBool(args, "no-shells"))
|
|
226667
226842
|
return ["skipped", "--no-shells"];
|
|
226668
|
-
const present = ["ios", "android"].filter((d) =>
|
|
226843
|
+
const present = ["ios", "android"].filter((d) => existsSync40(join41(root, d)) && readdirSync20(join41(root, d)).length > 0);
|
|
226669
226844
|
if (present.length === 0)
|
|
226670
226845
|
return ["skipped", "no ios/ or android/ shell in this project (`lecodes app init ios|android`)"];
|
|
226671
226846
|
await app({ _: ["update"], flags: {} });
|
|
@@ -226720,15 +226895,15 @@ ${c.bold("Summary")}`);
|
|
|
226720
226895
|
};
|
|
226721
226896
|
|
|
226722
226897
|
// src/index.ts
|
|
226723
|
-
import { existsSync as
|
|
226724
|
-
import { delimiter as
|
|
226898
|
+
import { existsSync as existsSync43, realpathSync as realpathSync2 } from "node:fs";
|
|
226899
|
+
import { delimiter as delimiter3, dirname as dirname24, join as join44 } from "node:path";
|
|
226725
226900
|
|
|
226726
226901
|
// src/commands/install.ts
|
|
226727
226902
|
init_util();
|
|
226728
226903
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
226729
|
-
import { appendFileSync as appendFileSync3, chmodSync as chmodSync2, cpSync as cpSync5, existsSync as
|
|
226904
|
+
import { appendFileSync as appendFileSync3, chmodSync as chmodSync2, cpSync as cpSync5, existsSync as existsSync41, mkdirSync as mkdirSync27, readFileSync as readFileSync35, realpathSync, rmSync as rmSync13, symlinkSync as symlinkSync2 } from "node:fs";
|
|
226730
226905
|
import { homedir as homedir10 } from "node:os";
|
|
226731
|
-
import { basename as
|
|
226906
|
+
import { basename as basename19, delimiter as delimiter2, dirname as dirname22, join as join42, resolve as resolve24, sep as sep2 } from "node:path";
|
|
226732
226907
|
var isWin = process.platform === "win32";
|
|
226733
226908
|
var HOME = homedir10();
|
|
226734
226909
|
var safeRealpath = (p2) => {
|
|
@@ -226740,7 +226915,7 @@ var safeRealpath = (p2) => {
|
|
|
226740
226915
|
};
|
|
226741
226916
|
var onPath = (dir) => {
|
|
226742
226917
|
const want = safeRealpath(dir);
|
|
226743
|
-
return (process.env.PATH ?? "").split(
|
|
226918
|
+
return (process.env.PATH ?? "").split(delimiter2).some((p2) => {
|
|
226744
226919
|
if (!p2)
|
|
226745
226920
|
return false;
|
|
226746
226921
|
try {
|
|
@@ -226751,13 +226926,13 @@ var onPath = (dir) => {
|
|
|
226751
226926
|
});
|
|
226752
226927
|
};
|
|
226753
226928
|
var install = async (args) => {
|
|
226754
|
-
const bundle =
|
|
226755
|
-
const exeName3 =
|
|
226929
|
+
const bundle = dirname22(process.execPath);
|
|
226930
|
+
const exeName3 = basename19(process.execPath);
|
|
226756
226931
|
const chiselName = isWin ? "chisel.exe" : "chisel";
|
|
226757
|
-
if (!
|
|
226932
|
+
if (!existsSync41(join42(bundle, "runtime")) || !existsSync41(join42(bundle, chiselName))) {
|
|
226758
226933
|
throw new CliError("`lecodes install` only works from the packaged release build (the archive containing lecodes + " + "chisel + runtime/). You appear to be running from source or an npm install — install globally " + "with your package manager there instead.");
|
|
226759
226934
|
}
|
|
226760
|
-
const companions = [exeName3, chiselName, "runtime", "README.txt"].filter((f3) =>
|
|
226935
|
+
const companions = [exeName3, chiselName, "runtime", "README.txt"].filter((f3) => existsSync41(join42(bundle, f3)));
|
|
226761
226936
|
if (isWin)
|
|
226762
226937
|
return installWindows(args, bundle, companions);
|
|
226763
226938
|
return installUnix(args, bundle, companions);
|
|
@@ -226767,9 +226942,9 @@ var copyBundle = (bundle, target, companions) => {
|
|
|
226767
226942
|
if (safeRealpath(target) === safeRealpath(bundle))
|
|
226768
226943
|
return;
|
|
226769
226944
|
for (const f3 of companions) {
|
|
226770
|
-
const dest =
|
|
226945
|
+
const dest = join42(target, f3);
|
|
226771
226946
|
rmSync13(dest, { recursive: true, force: true });
|
|
226772
|
-
cpSync5(
|
|
226947
|
+
cpSync5(join42(bundle, f3), dest, { recursive: true });
|
|
226773
226948
|
}
|
|
226774
226949
|
};
|
|
226775
226950
|
var permError = (e2, dir, system) => {
|
|
@@ -226781,41 +226956,41 @@ var permError = (e2, dir, system) => {
|
|
|
226781
226956
|
};
|
|
226782
226957
|
var installUnix = (args, bundle, companions) => {
|
|
226783
226958
|
const system = flagBool(args, "system");
|
|
226784
|
-
const libDir = resolve24(flagStr(args, "dir") ?? (system ? "/usr/local/lib/lecodes-cli" :
|
|
226785
|
-
const binDir = resolve24(flagStr(args, "bin") ?? (system ? "/usr/local/bin" :
|
|
226786
|
-
const link2 =
|
|
226959
|
+
const libDir = resolve24(flagStr(args, "dir") ?? (system ? "/usr/local/lib/lecodes-cli" : join42(HOME, ".local", "lib", "lecodes-cli")));
|
|
226960
|
+
const binDir = resolve24(flagStr(args, "bin") ?? (system ? "/usr/local/bin" : join42(HOME, ".local", "bin")));
|
|
226961
|
+
const link2 = join42(binDir, "lecodes");
|
|
226787
226962
|
try {
|
|
226788
226963
|
copyBundle(bundle, libDir, companions);
|
|
226789
|
-
chmodSync2(
|
|
226790
|
-
chmodSync2(
|
|
226964
|
+
chmodSync2(join42(libDir, "lecodes"), 493);
|
|
226965
|
+
chmodSync2(join42(libDir, "chisel"), 493);
|
|
226791
226966
|
} catch (e2) {
|
|
226792
226967
|
throw permError(e2, libDir, system);
|
|
226793
226968
|
}
|
|
226794
226969
|
try {
|
|
226795
226970
|
mkdirSync27(binDir, { recursive: true });
|
|
226796
226971
|
rmSync13(link2, { force: true });
|
|
226797
|
-
symlinkSync2(
|
|
226972
|
+
symlinkSync2(join42(libDir, "lecodes"), link2);
|
|
226798
226973
|
} catch (e2) {
|
|
226799
226974
|
throw permError(e2, binDir, system);
|
|
226800
226975
|
}
|
|
226801
226976
|
success(`Installed to ${c.bold(libDir)}`);
|
|
226802
|
-
log(` ${c.dim(link2 + " → " +
|
|
226977
|
+
log(` ${c.dim(link2 + " → " + join42(libDir, "lecodes"))}`);
|
|
226803
226978
|
finishPathUnix(args, binDir);
|
|
226804
226979
|
};
|
|
226805
226980
|
var shellRc = () => {
|
|
226806
|
-
const shell =
|
|
226981
|
+
const shell = basename19(process.env.SHELL ?? "");
|
|
226807
226982
|
if (shell === "zsh")
|
|
226808
|
-
return { file:
|
|
226983
|
+
return { file: join42(HOME, ".zshrc"), name: "~/.zshrc" };
|
|
226809
226984
|
if (shell === "bash")
|
|
226810
|
-
return { file:
|
|
226811
|
-
return { file:
|
|
226985
|
+
return { file: join42(HOME, ".bashrc"), name: "~/.bashrc" };
|
|
226986
|
+
return { file: join42(HOME, ".profile"), name: "~/.profile" };
|
|
226812
226987
|
};
|
|
226813
226988
|
var PATH_MARKER = "# Added by `lecodes install`";
|
|
226814
226989
|
var appendPathToShellRc = (binDir) => {
|
|
226815
226990
|
const { file, name } = shellRc();
|
|
226816
226991
|
const line = `export PATH="${binDir}:$PATH"`;
|
|
226817
226992
|
try {
|
|
226818
|
-
const existing =
|
|
226993
|
+
const existing = existsSync41(file) ? readFileSync35(file, "utf8") : "";
|
|
226819
226994
|
if (existing.includes(line))
|
|
226820
226995
|
return name;
|
|
226821
226996
|
appendFileSync3(file, `${existing && !existing.endsWith(`
|
|
@@ -226853,7 +227028,7 @@ var finishPathUnix = (args, binDir) => {
|
|
|
226853
227028
|
log(` • or install system-wide (no PATH edit): ${c.bold("sudo lecodes install --system")}`);
|
|
226854
227029
|
};
|
|
226855
227030
|
var installWindows = (args, bundle, companions) => {
|
|
226856
|
-
const target = resolve24(flagStr(args, "dir") ??
|
|
227031
|
+
const target = resolve24(flagStr(args, "dir") ?? join42(process.env.LOCALAPPDATA ?? join42(HOME, "AppData", "Local"), "Programs", "lecodes-cli"));
|
|
226857
227032
|
try {
|
|
226858
227033
|
copyBundle(bundle, target, companions);
|
|
226859
227034
|
} catch (e2) {
|
|
@@ -226892,9 +227067,9 @@ var addToUserPathWindows = (dir) => {
|
|
|
226892
227067
|
init_util();
|
|
226893
227068
|
|
|
226894
227069
|
// src/projectEnv.ts
|
|
226895
|
-
import { existsSync as
|
|
227070
|
+
import { existsSync as existsSync42, readFileSync as readFileSync36 } from "node:fs";
|
|
226896
227071
|
import { homedir as homedir11 } from "node:os";
|
|
226897
|
-
import { dirname as
|
|
227072
|
+
import { dirname as dirname23, join as join43, resolve as resolve25 } from "node:path";
|
|
226898
227073
|
var KEY_RE = /^(LECODES|CREATOR)_[A-Z0-9_]+$/;
|
|
226899
227074
|
var parseDotEnv = (text) => {
|
|
226900
227075
|
const out = {};
|
|
@@ -226931,7 +227106,7 @@ var applyDotEnv = (parsed, dir, env) => {
|
|
|
226931
227106
|
if (value.startsWith("./") || value.startsWith("../"))
|
|
226932
227107
|
value = resolve25(dir, value);
|
|
226933
227108
|
else if (value === "~" || value.startsWith("~/"))
|
|
226934
|
-
value =
|
|
227109
|
+
value = join43(homedir11(), value.slice(1));
|
|
226935
227110
|
out[key] = value;
|
|
226936
227111
|
}
|
|
226937
227112
|
return out;
|
|
@@ -226939,9 +227114,9 @@ var applyDotEnv = (parsed, dir, env) => {
|
|
|
226939
227114
|
var findEnvRoot = (start) => {
|
|
226940
227115
|
let dir = resolve25(start);
|
|
226941
227116
|
while (true) {
|
|
226942
|
-
if (
|
|
227117
|
+
if (existsSync42(join43(dir, "app.json")) || existsSync42(join43(dir, ".lecodes")))
|
|
226943
227118
|
return dir;
|
|
226944
|
-
const parent =
|
|
227119
|
+
const parent = dirname23(dir);
|
|
226945
227120
|
if (parent === dir)
|
|
226946
227121
|
return null;
|
|
226947
227122
|
dir = parent;
|
|
@@ -226952,8 +227127,8 @@ var loadProjectEnv = (cwd = process.cwd()) => {
|
|
|
226952
227127
|
const root = findEnvRoot(cwd);
|
|
226953
227128
|
if (!root)
|
|
226954
227129
|
return [];
|
|
226955
|
-
const file =
|
|
226956
|
-
if (!
|
|
227130
|
+
const file = join43(root, ".env");
|
|
227131
|
+
if (!existsSync42(file))
|
|
226957
227132
|
return [];
|
|
226958
227133
|
const added = applyDotEnv(parseDotEnv(readFileSync36(file, "utf8")), root, process.env);
|
|
226959
227134
|
for (const [k, v] of Object.entries(added))
|
|
@@ -226966,9 +227141,9 @@ var loadProjectEnv = (cwd = process.cwd()) => {
|
|
|
226966
227141
|
|
|
226967
227142
|
// src/index.ts
|
|
226968
227143
|
var STANDALONE2 = (() => {
|
|
226969
|
-
const dir =
|
|
227144
|
+
const dir = dirname24(process.execPath);
|
|
226970
227145
|
const chisel = process.platform === "win32" ? "chisel.exe" : "chisel";
|
|
226971
|
-
return
|
|
227146
|
+
return existsSync43(join44(dir, "runtime")) && existsSync43(join44(dir, chisel));
|
|
226972
227147
|
})();
|
|
226973
227148
|
var INSTALLED = STANDALONE2 && (() => {
|
|
226974
227149
|
const exe = process.platform === "win32" ? "lecodes.exe" : "lecodes";
|
|
@@ -226979,12 +227154,12 @@ var INSTALLED = STANDALONE2 && (() => {
|
|
|
226979
227154
|
return process.execPath;
|
|
226980
227155
|
}
|
|
226981
227156
|
})();
|
|
226982
|
-
return (process.env.PATH ?? "").split(
|
|
227157
|
+
return (process.env.PATH ?? "").split(delimiter3).some((d) => {
|
|
226983
227158
|
if (!d)
|
|
226984
227159
|
return false;
|
|
226985
227160
|
try {
|
|
226986
|
-
const cand =
|
|
226987
|
-
return
|
|
227161
|
+
const cand = join44(d, exe);
|
|
227162
|
+
return existsSync43(cand) && realpathSync2(cand) === self2;
|
|
226988
227163
|
} catch {
|
|
226989
227164
|
return false;
|
|
226990
227165
|
}
|
|
@@ -227052,6 +227227,9 @@ ${c.bold("Commands:")}
|
|
|
227052
227227
|
--host <ip> LAN address to advertise (default: auto-detect)
|
|
227053
227228
|
--entry <path> override the entrypoint
|
|
227054
227229
|
--no-qr don't render the QR code
|
|
227230
|
+
--web also open the app in the browser (Web Lite host:
|
|
227231
|
+
same bundle + hot reload, camera/map plugins
|
|
227232
|
+
have web twins; the /web/ URL is served always)
|
|
227055
227233
|
--desktop also open the app in the native desktop host
|
|
227056
227234
|
(same hot reload; window from app.json's
|
|
227057
227235
|
desktop block; closing it keeps the server)
|