lecodes-cli 0.19.0 → 0.19.2
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/dist/index.js +730 -235
- package/package.json +14 -13
- package/runtime/scene-harness.json +1 -1
- package/runtime/sdk-types.json +1 -1
- package/src/api.ts +302 -0
- package/src/browserAuth.ts +87 -0
- package/src/cmgenTool.ts +104 -0
- package/src/commands/app.ts +891 -0
- package/src/commands/appAndroid.ts +603 -0
- package/src/commands/appDesktop.ts +326 -0
- package/src/commands/appDesktopMac.ts +470 -0
- package/src/commands/appIcon.ts +187 -0
- package/src/commands/appShared.ts +448 -0
- package/src/commands/appTemplates.ts +883 -0
- package/src/commands/appTemplatesAndroid.ts +599 -0
- package/src/commands/appTemplatesGradlew.ts +9 -0
- package/src/commands/assets.ts +28 -0
- package/src/commands/clone.ts +60 -0
- package/src/commands/compile.ts +253 -0
- package/src/commands/create.ts +59 -0
- package/src/commands/design.ts +863 -0
- package/src/commands/designTemplates.ts +11 -0
- package/src/commands/desktop.ts +122 -0
- package/src/commands/dev.ts +214 -0
- package/src/commands/diff.ts +59 -0
- package/src/commands/init.ts +191 -0
- package/src/commands/install.ts +198 -0
- package/src/commands/lightmap.ts +290 -0
- package/src/commands/link.ts +147 -0
- package/src/commands/login.ts +24 -0
- package/src/commands/navmesh.ts +225 -0
- package/src/commands/pn.ts +305 -0
- package/src/commands/projectTemplates.ts +129 -0
- package/src/commands/pull.ts +109 -0
- package/src/commands/push.ts +173 -0
- package/src/commands/render.ts +414 -0
- package/src/commands/scene.ts +148 -0
- package/src/commands/shaders.ts +157 -0
- package/src/commands/status.ts +29 -0
- package/src/commands/test.ts +370 -0
- package/src/commands/thumbs.ts +178 -0
- package/src/commands/types.ts +87 -0
- package/src/commands/update.ts +190 -0
- package/src/compile/assetIcons.ts +214 -0
- package/src/compile/collect.ts +46 -0
- package/src/compile/collectLocal.ts +37 -0
- package/src/compile/designCompile.ts +104 -0
- package/src/compile/fonts.ts +156 -0
- package/src/compile/headlessBundle.ts +129 -0
- package/src/compile/nativeStack.ts +21 -0
- package/src/compile/projectCompile.ts +109 -0
- package/src/compile/sceneCompile.ts +113 -0
- package/src/compile/screenEntry.ts +127 -0
- package/src/compile/shaders.ts +245 -0
- package/src/config.ts +42 -0
- package/src/designMeta.ts +35 -0
- package/src/desktopRenderer.ts +532 -0
- package/src/desktopScript.ts +276 -0
- package/src/dev/clientTemplates.ts +160 -0
- package/src/dev/devServer.ts +292 -0
- package/src/dev/wsServer.ts +144 -0
- package/src/distRoot.ts +20 -0
- package/src/ignore.ts +163 -0
- package/src/index.ts +491 -0
- package/src/lecodes-3d-editor.d.ts +41 -0
- package/src/lecodes-assets.d.ts +7 -0
- package/src/lecodes-design.d.ts +191 -0
- package/src/lecodes-renderer.d.ts +131 -0
- package/src/localFiles.ts +144 -0
- package/src/manifest.ts +46 -0
- package/src/matcTool.ts +137 -0
- package/src/peers.ts +40 -0
- package/src/project.ts +61 -0
- package/src/projectEnv.ts +94 -0
- package/src/qrcode-terminal.d.ts +9 -0
- package/src/releases.ts +125 -0
- package/src/serverDiff.ts +78 -0
- package/src/textDiff.ts +103 -0
- package/src/types.ts +0 -0
- package/src/util.ts +146 -0
- package/runtime/sdk/animate/animate.ts +0 -238
- package/runtime/sdk/animate/bezier.ts +0 -138
- package/runtime/sdk/animate/easings.ts +0 -126
- package/runtime/sdk/canvas/Canvas.ts +0 -305
- package/runtime/sdk/compile/aspectMacro.ts +0 -86
- package/runtime/sdk/compile/assetIconMacro.ts +0 -384
- package/runtime/sdk/compile/assetMacro.ts +0 -146
- package/runtime/sdk/compile/assetName.ts +0 -50
- package/runtime/sdk/compile/bundler.ts +0 -287
- package/runtime/sdk/compile/compileProject.ts +0 -129
- package/runtime/sdk/compile/detectEntry.ts +0 -128
- package/runtime/sdk/compile/fontMacro.ts +0 -459
- package/runtime/sdk/compile/fontRegistry.ts +0 -78
- package/runtime/sdk/compile/header.ts +0 -67
- package/runtime/sdk/compile/index.ts +0 -100
- package/runtime/sdk/compile/libraryImports.ts +0 -52
- package/runtime/sdk/compile/liteMaterial.ts +0 -247
- package/runtime/sdk/compile/sceneEditor.ts +0 -88
- package/runtime/sdk/compile/serverSplit.ts +0 -233
- package/runtime/sdk/compile/serverTypes.ts +0 -227
- package/runtime/sdk/compile/sfnt.ts +0 -98
- package/runtime/sdk/compile/shaderSchema.ts +0 -202
- package/runtime/sdk/compile/shaderTargets.ts +0 -81
- package/runtime/sdk/compile/sourcemap.ts +0 -25
- package/runtime/sdk/core/Aspect.ts +0 -568
- package/runtime/sdk/core/InspectorUI.ts +0 -212
- package/runtime/sdk/core/StateMachine.ts +0 -308
- package/runtime/sdk/core/color.ts +0 -66
- package/runtime/sdk/core/compWrite.ts +0 -42
- package/runtime/sdk/core/events.ts +0 -38
- package/runtime/sdk/core/fields.ts +0 -120
- package/runtime/sdk/core/registry.ts +0 -23
- package/runtime/sdk/core/signals.ts +0 -277
- package/runtime/sdk/core/time.ts +0 -84
- package/runtime/sdk/g2/Camera2D.ts +0 -40
- package/runtime/sdk/g2/CharacterController2D.ts +0 -276
- package/runtime/sdk/g2/Node2D.ts +0 -267
- package/runtime/sdk/g2/OneWay2D.ts +0 -66
- package/runtime/sdk/g2/Physics2D.ts +0 -346
- package/runtime/sdk/g2/Scene2D.ts +0 -209
- package/runtime/sdk/g2/Shape2D.ts +0 -259
- package/runtime/sdk/g2/Sprite.ts +0 -89
- package/runtime/sdk/g2/SpriteAnimation.ts +0 -171
- package/runtime/sdk/g2/SpriteSheet.ts +0 -166
- package/runtime/sdk/g2/Texture2D.ts +0 -47
- package/runtime/sdk/g2/Tilemap.ts +0 -41
- package/runtime/sdk/g2/Tileset.ts +0 -71
- package/runtime/sdk/g2/Trigger2D.ts +0 -77
- package/runtime/sdk/g2/autotile.ts +0 -433
- package/runtime/sdk/g2/cells.ts +0 -91
- package/runtime/sdk/g2/defineScene2d.ts +0 -381
- package/runtime/sdk/g2/groups2d.ts +0 -106
- package/runtime/sdk/g2/loop.ts +0 -50
- package/runtime/sdk/g2/scenarios2d.ts +0 -69
- package/runtime/sdk/g2/touch.ts +0 -83
- package/runtime/sdk/gl/Camera.ts +0 -160
- package/runtime/sdk/gl/CameraPlace.ts +0 -52
- package/runtime/sdk/gl/CharacterController.ts +0 -238
- package/runtime/sdk/gl/Gearbox.ts +0 -212
- package/runtime/sdk/gl/Geometry.ts +0 -279
- package/runtime/sdk/gl/IK.ts +0 -193
- package/runtime/sdk/gl/InstancedMesh.ts +0 -132
- package/runtime/sdk/gl/Light.ts +0 -107
- package/runtime/sdk/gl/Lightmap.ts +0 -256
- package/runtime/sdk/gl/Material.ts +0 -260
- package/runtime/sdk/gl/Mesh.ts +0 -83
- package/runtime/sdk/gl/Model.ts +0 -124
- package/runtime/sdk/gl/NavAgent.ts +0 -337
- package/runtime/sdk/gl/NavMesh.ts +0 -397
- package/runtime/sdk/gl/Node.ts +0 -350
- package/runtime/sdk/gl/Noise.ts +0 -30
- package/runtime/sdk/gl/Particles.ts +0 -676
- package/runtime/sdk/gl/Physics.ts +0 -222
- package/runtime/sdk/gl/Plane.ts +0 -53
- package/runtime/sdk/gl/Ragdoll.ts +0 -270
- package/runtime/sdk/gl/Ray.ts +0 -16
- package/runtime/sdk/gl/Scene.ts +0 -486
- package/runtime/sdk/gl/Shape.ts +0 -409
- package/runtime/sdk/gl/Terrain.ts +0 -1092
- package/runtime/sdk/gl/Texture.ts +0 -63
- package/runtime/sdk/gl/Trigger.ts +0 -45
- package/runtime/sdk/gl/Vehicle.ts +0 -473
- package/runtime/sdk/gl/Wheel.ts +0 -240
- package/runtime/sdk/gl/animation/AnimationClip.ts +0 -204
- package/runtime/sdk/gl/animation/Animator.ts +0 -120
- package/runtime/sdk/gl/animation/Layer.ts +0 -31
- package/runtime/sdk/gl/animation/Loop.ts +0 -30
- package/runtime/sdk/gl/animation/Playback.ts +0 -44
- package/runtime/sdk/gl/animation/core.ts +0 -336
- package/runtime/sdk/gl/controls.ts +0 -95
- package/runtime/sdk/gl/physicsEvents.ts +0 -20
- package/runtime/sdk/gl/scenarios.ts +0 -291
- package/runtime/sdk/gl/state.ts +0 -6
- package/runtime/sdk/gl/terrainMesh.ts +0 -219
- package/runtime/sdk/gl/touch.ts +0 -68
- package/runtime/sdk/inject.ts +0 -197
- package/runtime/sdk/math/Mathf.ts +0 -118
- package/runtime/sdk/math/mat4.ts +0 -278
- package/runtime/sdk/math/quat.ts +0 -232
- package/runtime/sdk/math/vec.ts +0 -255
- package/runtime/sdk/net/codec.ts +0 -119
- package/runtime/sdk/net/core.ts +0 -384
- package/runtime/sdk/net/index.ts +0 -181
- package/runtime/sdk/net/replication.ts +0 -622
- package/runtime/sdk/plugins/camera.ts +0 -81
- package/runtime/sdk/plugins/geolocation.ts +0 -123
- package/runtime/sdk/plugins/oauth.ts +0 -61
- package/runtime/sdk/plugins/permission.ts +0 -7
- package/runtime/sdk/plugins/push.ts +0 -132
- package/runtime/sdk/plugins/qr.ts +0 -73
- package/runtime/sdk/plugins/service.ts +0 -47
- package/runtime/sdk/runtime/app.ts +0 -101
- package/runtime/sdk/runtime/appEvents.ts +0 -54
- package/runtime/sdk/runtime/channel.ts +0 -61
- package/runtime/sdk/runtime/clipboard.ts +0 -20
- package/runtime/sdk/runtime/datetime.ts +0 -329
- package/runtime/sdk/runtime/device.ts +0 -293
- package/runtime/sdk/runtime/fetch.ts +0 -77
- package/runtime/sdk/runtime/files.ts +0 -23
- package/runtime/sdk/runtime/input.ts +0 -175
- package/runtime/sdk/runtime/media.ts +0 -111
- package/runtime/sdk/runtime/misc.ts +0 -16
- package/runtime/sdk/runtime/net.ts +0 -36
- package/runtime/sdk/runtime/rpc.ts +0 -218
- package/runtime/sdk/runtime/service.ts +0 -83
- package/runtime/sdk/runtime/share.ts +0 -9
- package/runtime/sdk/runtime/storage.ts +0 -13
- package/runtime/sdk/runtime/touch.ts +0 -76
- package/runtime/sdk/scene/defineScene.ts +0 -1353
- package/runtime/sdk/scene/editorPlugins.ts +0 -110
- package/runtime/sdk/scene/gizmos.ts +0 -148
- package/runtime/sdk/scene/grammar.ts +0 -120
- package/runtime/sdk/scene/material.ts +0 -188
- package/runtime/sdk/server/auth/appConfig.ts +0 -12
- package/runtime/sdk/server/auth/global.ts +0 -80
- package/runtime/sdk/server/auth/host.ts +0 -318
- package/runtime/sdk/server/auth/models.ts +0 -83
- package/runtime/sdk/server/auth/types.ts +0 -50
- package/runtime/sdk/server/channel.ts +0 -56
- package/runtime/sdk/server/context.ts +0 -36
- package/runtime/sdk/server/db/defineDb.ts +0 -237
- package/runtime/sdk/server/db/fields.ts +0 -132
- package/runtime/sdk/server/db/httpTransport.ts +0 -93
- package/runtime/sdk/server/db/index.ts +0 -7
- package/runtime/sdk/server/db/marci/query.ts +0 -412
- package/runtime/sdk/server/db/types.ts +0 -202
- package/runtime/sdk/server/errors.ts +0 -12
- package/runtime/sdk/server/host.ts +0 -74
- package/runtime/sdk/server/inject.ts +0 -13
- package/runtime/sdk/server/runtime.ts +0 -133
- package/runtime/sdk/server/validate.ts +0 -87
- package/runtime/sdk/ui/NativeView.ts +0 -142
- package/runtime/sdk/ui/UI.ts +0 -39
- package/runtime/sdk/ui/UIBottomSheet.ts +0 -139
- package/runtime/sdk/ui/UIButton.ts +0 -101
- package/runtime/sdk/ui/UIContainer.ts +0 -60
- package/runtime/sdk/ui/UIImage.ts +0 -83
- package/runtime/sdk/ui/UIInput.ts +0 -185
- package/runtime/sdk/ui/UIModal.ts +0 -139
- package/runtime/sdk/ui/UINode.ts +0 -830
- package/runtime/sdk/ui/UIPager.ts +0 -362
- package/runtime/sdk/ui/UIPopover.ts +0 -100
- package/runtime/sdk/ui/UIScreen.ts +0 -123
- package/runtime/sdk/ui/UIScrollable.ts +0 -87
- package/runtime/sdk/ui/UISpacer.ts +0 -14
- package/runtime/sdk/ui/UITabs.ts +0 -236
- package/runtime/sdk/ui/UIText.ts +0 -51
- package/runtime/sdk/ui/UIVideo.ts +0 -88
- package/runtime/sdk/ui/UIVirtualizedList.ts +0 -241
- package/runtime/sdk/ui/UIWidget.ts +0 -127
- package/runtime/sdk/ui/fonts.ts +0 -13
- package/runtime/sdk/ui/presentable.ts +0 -117
- package/runtime/sdk/ui/router.ts +0 -132
- package/runtime/sdk/ui/theme.ts +0 -84
package/src/index.ts
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
import pkg from "../package.json"
|
|
2
|
+
import { app } from "./commands/app"
|
|
3
|
+
import { clone } from "./commands/clone"
|
|
4
|
+
import { compile, previewLegacy } from "./commands/compile"
|
|
5
|
+
import { create } from "./commands/create"
|
|
6
|
+
import { desktop } from "./commands/desktop"
|
|
7
|
+
import { design } from "./commands/design"
|
|
8
|
+
import { dev } from "./commands/dev"
|
|
9
|
+
import { diff } from "./commands/diff"
|
|
10
|
+
import { init } from "./commands/init"
|
|
11
|
+
import { link } from "./commands/link"
|
|
12
|
+
import { lightmap } from "./commands/lightmap"
|
|
13
|
+
import { navmesh } from "./commands/navmesh"
|
|
14
|
+
import { login } from "./commands/login"
|
|
15
|
+
import { shaders } from "./commands/shaders"
|
|
16
|
+
import { render } from "./commands/render"
|
|
17
|
+
import { pn } from "./commands/pn"
|
|
18
|
+
import { pull } from "./commands/pull"
|
|
19
|
+
import { push } from "./commands/push"
|
|
20
|
+
import { scene } from "./commands/scene"
|
|
21
|
+
import { thumbs } from "./commands/thumbs"
|
|
22
|
+
import { assets } from "./commands/assets"
|
|
23
|
+
import { status } from "./commands/status"
|
|
24
|
+
import { test } from "./commands/test"
|
|
25
|
+
import { update } from "./commands/update"
|
|
26
|
+
import { existsSync, readFileSync, realpathSync } from "node:fs"
|
|
27
|
+
import { createRequire } from "node:module"
|
|
28
|
+
import { delimiter, dirname, join } from "node:path"
|
|
29
|
+
import { install } from "./commands/install"
|
|
30
|
+
import { CliError, c, log, parseArgs, type Args } from "./util"
|
|
31
|
+
import { installedDesktopVersions, selectedDesktopVersion } from "./desktopRenderer"
|
|
32
|
+
import { installedMatcVersions } from "./matcTool"
|
|
33
|
+
import { loadProjectEnv } from "./projectEnv"
|
|
34
|
+
import { OPTIONAL_PEERS, peerVersion } from "./peers"
|
|
35
|
+
|
|
36
|
+
/* `install` is a standalone-binary-only command: it installs the shipped bundle onto PATH, so it's only
|
|
37
|
+
* meaningful when that bundle actually sits next to the executable — the `chisel` bundler + `runtime/`
|
|
38
|
+
* that scripts/build-bin.ts lays down beside the compiled binary. For an npm install process.execPath
|
|
39
|
+
* is `node`, and for `bun run` it's `bun`; neither has those companions, so `install` is unavailable
|
|
40
|
+
* there (omitted from help and unregistered → `lecodes install` reports an unknown command). */
|
|
41
|
+
const STANDALONE = (() => {
|
|
42
|
+
const dir = dirname(process.execPath)
|
|
43
|
+
const chisel = process.platform === "win32" ? "chisel.exe" : "chisel"
|
|
44
|
+
return existsSync(join(dir, "runtime")) && existsSync(join(dir, chisel))
|
|
45
|
+
})()
|
|
46
|
+
|
|
47
|
+
/* Are we ALREADY the installed copy — i.e. is a `lecodes` on PATH resolving to this very executable?
|
|
48
|
+
* If so, re-installing is pointless, so we drop `install` from help (but keep it runnable for repair /
|
|
49
|
+
* install-over-the-top). Running the freshly-unpacked archive instead: no PATH entry points back to it
|
|
50
|
+
* → this is false → `install` is offered. */
|
|
51
|
+
const INSTALLED = STANDALONE && (() => {
|
|
52
|
+
const exe = process.platform === "win32" ? "lecodes.exe" : "lecodes"
|
|
53
|
+
const self = (() => { try { return realpathSync(process.execPath) } catch { return process.execPath } })()
|
|
54
|
+
return (process.env.PATH ?? "").split(delimiter).some(d => {
|
|
55
|
+
if (!d) return false
|
|
56
|
+
try { const cand = join(d, exe); return existsSync(cand) && realpathSync(cand) === self } catch { return false }
|
|
57
|
+
})
|
|
58
|
+
})()
|
|
59
|
+
|
|
60
|
+
const INSTALL_HELP = STANDALONE && !INSTALLED ? `
|
|
61
|
+
install Install this standalone build so 'lecodes' is on your PATH
|
|
62
|
+
(copies the bundle to a library folder + a symlink/PATH entry).
|
|
63
|
+
--modify-path also add it to PATH (edits your shell rc / user PATH)
|
|
64
|
+
--system install for all users (Linux/macOS; needs sudo)
|
|
65
|
+
--dir <path> override the install/library folder
|
|
66
|
+
--bin <path> override the symlink folder (Linux/macOS)` : ""
|
|
67
|
+
|
|
68
|
+
const HELP = `${c.bold("lecodes")} — clone, edit and push LeCodes projects from your machine.
|
|
69
|
+
|
|
70
|
+
${c.bold("Usage:")} lecodes <command> [options]
|
|
71
|
+
|
|
72
|
+
${c.bold("Commands:")}
|
|
73
|
+
init [dir] Scaffold a new LOCAL project (no login/server): a starter
|
|
74
|
+
main.ts, a CLAUDE.md + passing flow test (the headless
|
|
75
|
+
render/test loop), IDE types + tsconfig, a .lecodesignore.
|
|
76
|
+
Run it with 'lecodes dev' or 'lecodes compile'.
|
|
77
|
+
--desktop also write an app.json declaring the desktop
|
|
78
|
+
target (window size; 'dev --desktop',
|
|
79
|
+
'desktop run' and headless render/test
|
|
80
|
+
pick it up)${INSTALL_HELP}
|
|
81
|
+
login Authorize in the browser and store an access token
|
|
82
|
+
--token <pat> store a token from the web UI instead
|
|
83
|
+
--api <url> API origin (default https://le.codes)
|
|
84
|
+
--web <url> app origin for the browser flow
|
|
85
|
+
create <name> [dir] Create a new project on the server and scaffold it locally
|
|
86
|
+
(types from the server + tsconfig + a starter main.ts)
|
|
87
|
+
--team <uuid> create it inside a team
|
|
88
|
+
clone <uuid|url> [dir] Download a project's files + types into a new folder
|
|
89
|
+
--no-types skip the .d.ts / tsconfig generation
|
|
90
|
+
link [dir] Connect an existing local folder (e.g. one made by 'lecodes
|
|
91
|
+
init') to the platform — the reverse of clone. Creates a
|
|
92
|
+
project on the server, writes .lecodes/manifest.json and
|
|
93
|
+
refreshes the types; nothing is uploaded until you push
|
|
94
|
+
--name <s> project name (default: folder name)
|
|
95
|
+
--team <uuid> create it inside a team
|
|
96
|
+
--project <uuid|url> adopt an EXISTING project instead —
|
|
97
|
+
prints what your next push would change
|
|
98
|
+
on its server tree, and confirms first
|
|
99
|
+
--push [-m <msg>] push right after linking (--publish to
|
|
100
|
+
deploy it live in the same step)
|
|
101
|
+
--force re-link a folder that's already linked
|
|
102
|
+
--no-types skip the .d.ts / tsconfig refresh
|
|
103
|
+
status Show local changes vs the last sync
|
|
104
|
+
diff [path…] Show a unified diff of local vs the current server state
|
|
105
|
+
--name-only list changed paths + status only
|
|
106
|
+
pull [path…] Overwrite local files with the project's current state
|
|
107
|
+
(with path… : pull only those files/folders, keep other edits)
|
|
108
|
+
--force discard uncommitted local changes
|
|
109
|
+
push Push local changes as one new checkpoint
|
|
110
|
+
-m, --message checkpoint message
|
|
111
|
+
--publish also deploy the project live (compile) with the push
|
|
112
|
+
--force push even if the server moved on (shows + confirms
|
|
113
|
+
which server files get overwritten)
|
|
114
|
+
-y, --yes skip the --force overwrite confirmation
|
|
115
|
+
dev Run the project on a device from this machine, with hot reload:
|
|
116
|
+
starts a LAN dev server + prints a QR code; scan it with the
|
|
117
|
+
LeCodes app. Saves recompile + hot-swap the running app; device
|
|
118
|
+
logs/errors stream back here. No login needed.
|
|
119
|
+
--port <n> server port (default 4499)
|
|
120
|
+
--host <ip> LAN address to advertise (default: auto-detect)
|
|
121
|
+
--entry <path> override the entrypoint
|
|
122
|
+
--no-qr don't render the QR code
|
|
123
|
+
--desktop also open the app in the native desktop host
|
|
124
|
+
(same hot reload; window from app.json's
|
|
125
|
+
desktop block; closing it keeps the server)
|
|
126
|
+
--fps (--desktop) draw the host's frame counter
|
|
127
|
+
compile Compile the local project to JS (prints to stdout)
|
|
128
|
+
(was 'lecodes preview' — the old name still works)
|
|
129
|
+
-o, --out <file> write to a file instead of stdout
|
|
130
|
+
--entry <path> override the entrypoint
|
|
131
|
+
--no-header omit the metadata header
|
|
132
|
+
--no-minify keep the bundle readable (no compress/mangle)
|
|
133
|
+
--no-sourcemap don't generate/inline the source map
|
|
134
|
+
--public-url <url> asset URL prefix (default: the API origin)
|
|
135
|
+
render [file] Render the local UI project to a semantic JSON description
|
|
136
|
+
(needs the optional 'lecodes-renderer' package; UI projects only)
|
|
137
|
+
[file] render ONE screen module instead of the app:
|
|
138
|
+
a file that default-exports a UIScreen (or a
|
|
139
|
+
(state) => UIScreen) — every 'lecodes design'
|
|
140
|
+
screen is written that way. A bare id
|
|
141
|
+
("login") resolves in design/screens/, and a
|
|
142
|
+
design screen renders at its meta.json frame
|
|
143
|
+
--state <name> ([file]) the state to pass a
|
|
144
|
+
(state) => UIScreen screen
|
|
145
|
+
-o, --out <file> write JSON to a file instead of stdout
|
|
146
|
+
--png [file] rasterize a PNG (default screenshot.png;
|
|
147
|
+
needs @napi-rs/canvas)
|
|
148
|
+
--map [file] draw the 3D scene's annotated top-down map
|
|
149
|
+
(grid + XZ footprints + named markers) as
|
|
150
|
+
<file>.png + <file>.json world-space data
|
|
151
|
+
(default map.png; --label-all, --max-px N;
|
|
152
|
+
also a { "map": "f.png" } script step)
|
|
153
|
+
--script <file> drive the app through a step list (tap/type/
|
|
154
|
+
scroll/wait/expect/screenshot/json steps;
|
|
155
|
+
games: frames/drag/hold/key/keyDown/keyUp,
|
|
156
|
+
expect.log, screenshot clip)
|
|
157
|
+
--out-dir <dir> where --script step outputs land (default .)
|
|
158
|
+
--clip <name|x,y,w,h> (--png) crop to one node's rect or a
|
|
159
|
+
logical-px rect — a component/region render
|
|
160
|
+
--fixtures <file> canned fetch responses (URL pattern →
|
|
161
|
+
{ status?, json?, text? }) — make
|
|
162
|
+
backend-gated screens reachable headless
|
|
163
|
+
--scale <n> PNG device-pixel scale (default 2)
|
|
164
|
+
--width/--height viewport size (default 390x844)
|
|
165
|
+
--entry <path> override the entrypoint
|
|
166
|
+
--settle <ms> wait for promises/timers/fetch before snapshot
|
|
167
|
+
--wait-network let data fetches hit the real network
|
|
168
|
+
--logs forward the app's console output (to stderr)
|
|
169
|
+
--desktop render through the NATIVE desktop host instead:
|
|
170
|
+
real Filament 3D + tgfx UI + 2D, composited.
|
|
171
|
+
PNG only (--png). Downloads the LeCodes
|
|
172
|
+
Desktop renderer on first use into
|
|
173
|
+
~/.lecodes/renderer (Windows/Linux;
|
|
174
|
+
LECODES_DESKTOP_EXE overrides)
|
|
175
|
+
--frames <n> (--desktop) frames to run before the shot —
|
|
176
|
+
headroom for async loads (default 60)
|
|
177
|
+
--desktop --script <file> drive the scenario through the native
|
|
178
|
+
host: tap/drag/hold take { x, y } coordinates
|
|
179
|
+
(no names — the host has no UI tree; type/
|
|
180
|
+
scroll/clip unavailable), expect.log is
|
|
181
|
+
checked, text/node/screen/value are skipped;
|
|
182
|
+
per-step screenshots + final --png
|
|
183
|
+
--view <name> (--desktop) inspection camera auto-fitted to the
|
|
184
|
+
whole 3D scene: iso | top | front | side | back
|
|
185
|
+
[--fov N]; the app's camera is untouched
|
|
186
|
+
--camera x,y,z --look-at x,y,z [--fov N]
|
|
187
|
+
(--desktop) inspection camera at a fixed eye /
|
|
188
|
+
look-at point (world units, Y up). In a
|
|
189
|
+
--script run use { "view" } / { "camera" } steps
|
|
190
|
+
--fixed-dt <ms> (--desktop) virtual app clock, ms per frame —
|
|
191
|
+
deterministic game time (scripted runs
|
|
192
|
+
default to 16; plain renders to wall clock)
|
|
193
|
+
test [name…] Run headless flow tests: tests/*.flow.json scenarios, plus flows
|
|
194
|
+
derived from the design graph (design/meta.json activator edges
|
|
195
|
+
— checks the built app against the designed navigation; needs
|
|
196
|
+
named elements + screen roots). Failing steps dump the frame
|
|
197
|
+
(JSON + PNG) under tests/.artifacts/<flow>/.
|
|
198
|
+
Design flows read tests/fixtures.json automatically (canned
|
|
199
|
+
fetch responses) so backend-gated transitions run headless;
|
|
200
|
+
file scenarios declare their own via the "fixtures" envelope.
|
|
201
|
+
--flows run ONLY the design-derived flows
|
|
202
|
+
--no-flows run ONLY the tests/*.flow.json files
|
|
203
|
+
--fixtures <file> fixture pack for the design flows (overrides
|
|
204
|
+
the tests/fixtures.json default)
|
|
205
|
+
--json machine-readable report on stdout
|
|
206
|
+
--dir <folder> tests folder (default tests/)
|
|
207
|
+
--design-dir <dir> design folder (default design/)
|
|
208
|
+
--artifacts <dir> failure-artifact folder override
|
|
209
|
+
--desktop run the file scenarios through the NATIVE host
|
|
210
|
+
(coordinates only; expect.log checked,
|
|
211
|
+
text/node/screen/value skipped; design flows
|
|
212
|
+
stay headless). --frames / --fixed-dt as in
|
|
213
|
+
render --desktop
|
|
214
|
+
(+ the render timing flags: --width/--height, --settle,
|
|
215
|
+
--device, --safe-area, --wait-network, --logs, --entry)
|
|
216
|
+
update Move everything a project depends on to its newest published
|
|
217
|
+
state, in dependency order: the desktop host ('desktop
|
|
218
|
+
update'), matc ('shaders update'), the project's shader
|
|
219
|
+
compiles, the IDE types (.lecodes/types/ + tsconfig.json,
|
|
220
|
+
from the server — the former 'lecodes types'), the
|
|
221
|
+
ios/android shell pins ('app update'), then the GLOBAL npm
|
|
222
|
+
installs: every installed optional peer (lecodes-renderer,
|
|
223
|
+
lecodes-design, lecodes-3d-editor, lecodes-assets) and this
|
|
224
|
+
CLI that is behind npm's latest gets 'npm install -g'.
|
|
225
|
+
Pinned tools are skipped, not overridden: LECODES_DESKTOP_EXE
|
|
226
|
+
/ LECODES_MATC mean a local build. Keeps going when a step
|
|
227
|
+
fails; the summary says which.
|
|
228
|
+
--local types from the SDK bundled in this CLI
|
|
229
|
+
--no-shells leave ios/android pins alone (no re-sync)
|
|
230
|
+
--check npm step: report what's behind, install nothing
|
|
231
|
+
--no-cli skip the npm step (offline)
|
|
232
|
+
design [serve] LeCodes Design — a live canvas of screens for AI-driven prototyping
|
|
233
|
+
(needs the optional 'lecodes-design' package; works inside a
|
|
234
|
+
cloned project or standalone in any folder)
|
|
235
|
+
--port <n> dev-server port (default 4477)
|
|
236
|
+
--dir <folder> design folder (default design/)
|
|
237
|
+
--no-open don't open the browser
|
|
238
|
+
design init Scaffold the design folder (screens/, shared/, meta.json, CLAUDE.md)
|
|
239
|
+
--desktop desktop-frame board (meta.json defaultSize
|
|
240
|
+
[1280, 800] instead of the phone frame)
|
|
241
|
+
design snapshot [screen…] Render design screens headless (needs 'lecodes-renderer')
|
|
242
|
+
one screen → JSON to stdout; else files in design/.snapshots/
|
|
243
|
+
--png also rasterize PNGs (needs @napi-rs/canvas)
|
|
244
|
+
--out-dir <dir> output folder override
|
|
245
|
+
--logs forward the screens' console output (to stderr)
|
|
246
|
+
design comments Review comments pinned to the board, grouped by screen (open first)
|
|
247
|
+
--all include resolved threads
|
|
248
|
+
add "<text>" [--screen <id>] [--state <s>] [--element <name>]
|
|
249
|
+
reply <number> "<text>" · resolve <number> [--reply "<text>"] [--reopen]
|
|
250
|
+
(--ai signs a write as Claude; sends with the next "lecodes push")
|
|
251
|
+
desktop [run|build|update] The desktop target — the host 'lecodes render --desktop' uses too:
|
|
252
|
+
no args shows the version status (selected / downloaded /
|
|
253
|
+
newest published)
|
|
254
|
+
run compile the current project and open it in a real
|
|
255
|
+
desktop window (size/min-size/title default from
|
|
256
|
+
app.json's desktop block; --width/--height/--title
|
|
257
|
+
override; --fullscreen/--windowed override the
|
|
258
|
+
app.json fullscreen; --scale <0.5..4|fit> overrides
|
|
259
|
+
the display scale — "fit" sizes a 1080p-designed app
|
|
260
|
+
to the monitor with the density raised to match;
|
|
261
|
+
--entry overrides the entrypoint; --fps draws the
|
|
262
|
+
host's frame counter in the corner — composited fps,
|
|
263
|
+
plus the 3D fps when they diverge; asset() resources
|
|
264
|
+
load from the working tree — --remote-assets or
|
|
265
|
+
--public-url <url> uses the server's copies instead);
|
|
266
|
+
--server [--port N] [--max-clients N] launches the
|
|
267
|
+
host as a multiplayer server, --connect ip:port as a
|
|
268
|
+
client — both only set Net.launch (the app decides)
|
|
269
|
+
build stage a portable app folder (default dist/<name>/):
|
|
270
|
+
the cached host renamed to <Name>.exe + app.js +
|
|
271
|
+
assets/ (the project's files) + runtime/ (the engine's)
|
|
272
|
+
+ app.json (the host reads title/size/fullscreen from
|
|
273
|
+
it) + app.ico from app.json "icon". Duplicate asset
|
|
274
|
+
basenames are a build error (they silently alias in
|
|
275
|
+
the bundle). Also spelled 'lecodes app build desktop'.
|
|
276
|
+
On macOS: a signed .app instead (the downloaded LeCodes
|
|
277
|
+
Desktop.app + the project inside it); app.json
|
|
278
|
+
desktop.macos = bundleId / buildNumber / category /
|
|
279
|
+
signing.identity / notarize.profile (a notarytool
|
|
280
|
+
keychain profile — notarized + stapled, so it opens
|
|
281
|
+
on any Mac without "Open Anyway").
|
|
282
|
+
-o <dir> output folder (default dist/<name>)
|
|
283
|
+
--slug <name> folder/zip name override (Latin-only)
|
|
284
|
+
--renderer <gl|vulkan> host + shader variant
|
|
285
|
+
--probe headless-render the staged folder to PNG
|
|
286
|
+
(macOS: a brief windowed run + snapshot)
|
|
287
|
+
--zip also pack the result for sending
|
|
288
|
+
--dmg macOS: also build a drag-to-Applications
|
|
289
|
+
disk image (signed + notarized too)
|
|
290
|
+
--sign <identity|adhoc> macOS codesign identity
|
|
291
|
+
--notarize <profile> / --no-notarize macOS
|
|
292
|
+
--zip <out>.zip, UTF-8/forward-slash entries
|
|
293
|
+
update move to the newest published release
|
|
294
|
+
(cached in ~/.lecodes/renderer)
|
|
295
|
+
lightmap bake Bake static shadows + ambient occlusion into a lightmap atlas
|
|
296
|
+
(assets/lightmap/lightmap.{png,bake}) by running the app in
|
|
297
|
+
the desktop host: the statics are what the app registers
|
|
298
|
+
with Lightmap.add, the bake fires at its Lightmap.load call.
|
|
299
|
+
Props need UVs first: lecodes assets doctor … --lightmap-uv
|
|
300
|
+
--out <dir> where the atlas lands (assets/lightmap)
|
|
301
|
+
--size <px> atlas edge (4096) --texel <m> density (0.02)
|
|
302
|
+
--sun-rays/--ao-rays <n> quality (32 / 64)
|
|
303
|
+
--ao-distance <m> AO reach (2) --sun-angle <deg> (0.5)
|
|
304
|
+
--frames <n> load headroom (900) --logs host output
|
|
305
|
+
navmesh bake Build the level's navigation mesh (assets/nav/<scene>.navmesh)
|
|
306
|
+
for NavAgent / NavMesh: the desktop host dumps every STATIC
|
|
307
|
+
body's collision triangles at the scene's env.navmesh (or
|
|
308
|
+
NavMesh.load) point, Recast builds the mesh here.
|
|
309
|
+
--out <dir> where it lands (assets/nav)
|
|
310
|
+
--name <n> file name (the scene file with env.navmesh)
|
|
311
|
+
--radius/--height/--climb/--slope agent size (scene's)
|
|
312
|
+
--cell <m> (0.25) --cell-height <m> (0.1) --tile <cells> (48)
|
|
313
|
+
--obj also write <n>.navmesh.obj to inspect
|
|
314
|
+
--frames <n> load headroom (900) --logs host output
|
|
315
|
+
shaders [compile|update] The project's custom shaders (.mat) and their local compile:
|
|
316
|
+
no args lists the shaders + their compile state; compile
|
|
317
|
+
compiles them all into .lecodes/shaders (the same pass
|
|
318
|
+
'lecodes dev' runs on the fly — via Filament's matc,
|
|
319
|
+
downloaded on first use to ~/.lecodes/matc); update
|
|
320
|
+
downloads the newest matc (run after an engine upgrade)
|
|
321
|
+
scene [path] LeCodes Scene Editor — visually edit a .scene.ts (tree, inspector,
|
|
322
|
+
gizmo) on local files (needs the optional 'lecodes-3d-editor' package;
|
|
323
|
+
works inside a cloned project or standalone in any folder)
|
|
324
|
+
--port <n> editor-server port (default 4488)
|
|
325
|
+
--no-open don't open the browser
|
|
326
|
+
--no-mcp don't register the MCP server in .mcp.json
|
|
327
|
+
thumbs [path…] Asset thumbnails for the scene editor, WITHOUT a browser: decodes
|
|
328
|
+
the project's images (KTX2 too, via KTX-Software's ktx tool) into the
|
|
329
|
+
editor's preview cache. Incremental — the cached name carries the
|
|
330
|
+
asset's content hash, so unchanged files are skipped. Models,
|
|
331
|
+
materials and prefabs are rendered by the editor, not here
|
|
332
|
+
--force redo even the up-to-date ones
|
|
333
|
+
--size <px> longest edge (default 256)
|
|
334
|
+
assets convert <model.fbx|.glb> [--clips a.fbx b.fbx …] [-o out.glb] [--drop-model-clips]
|
|
335
|
+
[--fix] [--ktx2|--ktx2-hq]
|
|
336
|
+
FBX → LeCodes-ready GLB: meters/Y-up, textures embedded, clips from
|
|
337
|
+
other FBX files merged by bone name (Mixamo: one FBX per animation);
|
|
338
|
+
--fix/--ktx2 run the doctor passes (needs 'lecodes-assets')
|
|
339
|
+
Unity .mat files next to the FBX are read for the real textures
|
|
340
|
+
(metallic/roughness/ORM/emission packed the glTF way); --no-unity
|
|
341
|
+
keeps the FBX references; --unity-index <unity-index.txt> resolves GUIDs
|
|
342
|
+
--list-nodes / --keep <node> … / --split [dir]: carve one variant out of a
|
|
343
|
+
multi-variant prop file, re-origined on the ground (or one GLB per node)
|
|
344
|
+
--merge-skins b.fbx …: modular character pieces onto ONE skeleton
|
|
345
|
+
assets unpack <pkg.unitypackage> [-o dir] [--only re …] [--list]
|
|
346
|
+
Stream a .unitypackage to a folder: writes unity-index.txt (GUID → path,
|
|
347
|
+
what convert resolves textures with) and the matching assets + .meta
|
|
348
|
+
assets scene <map.unity> [-o level.json] [--filter re] [--group g] [--region x0,z0,x1,z1]
|
|
349
|
+
Unity scene → placed prefabs / mesh objects with world TRS in LeCodes'
|
|
350
|
+
frame + a prefab table (FBX + --keep node per prefab)
|
|
351
|
+
assets probe <file.fbx|.glb> [--filmstrip [out.png]]
|
|
352
|
+
Skeleton, clips (+ root motion / first-frame-vs-rest per clip), meshes,
|
|
353
|
+
materials, textures, bind sanity, duplicate names; --filmstrip renders
|
|
354
|
+
a CPU-skinned PNG strip per clip (no GPU)
|
|
355
|
+
assets sky <env.exr|.hdr> [-o dir] [--size N] [--ibl-size N] [--ibl-only]
|
|
356
|
+
Equirectangular HDR → the two cubemaps a scene needs: sky.ktx (sharp,
|
|
357
|
+
for 'skybox: { texture }') and ibl.ktx (prefiltered + SH, lights the
|
|
358
|
+
scene) — they are NOT interchangeable. Reports where the sun is in
|
|
359
|
+
the environment so the scene's light can be aimed to match
|
|
360
|
+
assets terrain-pack <layer> … [-o dir] [--normals n0 n1 …] [--names a b …] [--size N] [--png]
|
|
361
|
+
A terrain's splat layers (≤ 4) → <name>.ktx2 per layer + the packed
|
|
362
|
+
normal maps normals01/normals23.ktx2 (what Terrain.create's
|
|
363
|
+
layers/normals read). A layer = an albedo file or a FOLDER holding
|
|
364
|
+
*Albedo* + *Normal* (Unity packs). Prints the Terrain.create fragment
|
|
365
|
+
assets doctor <in.glb|dir> [--fix] [--ktx2] [--dump]
|
|
366
|
+
Analyze / fix a GLB against engine limits (bone cap 256, texture
|
|
367
|
+
formats/size, KTX2 via toktx)
|
|
368
|
+
app init <ios|android|desktop> Generate a native shell in <project>/ios/ or <project>/android/
|
|
369
|
+
(offline-first: runs the bundled app.js; never pushed to LeCodes).
|
|
370
|
+
desktop: no shell needed — writes app.json's desktop block
|
|
371
|
+
(window size; --fullscreen for kiosks)
|
|
372
|
+
--name <s> display name (default: app.json / folder name)
|
|
373
|
+
--bundle-id <id> iOS bundle identifier
|
|
374
|
+
--app-id <id> Android applicationId (default com.example.<slug>)
|
|
375
|
+
--team <id> Apple development team id
|
|
376
|
+
--variant <v> iOS SDK variant: auto (default — sync picks the
|
|
377
|
+
smallest of core/2d/3d/full covering what
|
|
378
|
+
the bundle uses), or one of those to pin
|
|
379
|
+
--sdk <v> native SDK release (default: the newest one,
|
|
380
|
+
pinned in app.json ios.sdk / android.sdk);
|
|
381
|
+
'latest' floats it — every sync re-resolves
|
|
382
|
+
app sync [ios|android] Make every existing shell match the project: compile the bundle
|
|
383
|
+
+ embed its assets (ios/App/Resources/ resp. the android
|
|
384
|
+
assets/; offline by default, also for server projects;
|
|
385
|
+
app.json "resources": {"remote": [globs]} keeps heavy assets
|
|
386
|
+
streaming), pick the iOS SDK variant from the bundle's engine
|
|
387
|
+
use, vendor app.json plugins (pinned in plugins.lock.json),
|
|
388
|
+
regenerate the CLI-owned shell files. app.json "update": true
|
|
389
|
+
(or {"url": …}) enables native OTA JS updates at launch (iOS).
|
|
390
|
+
app.json "icon" (square ≥1024px image) renders the app icons
|
|
391
|
+
every sync ("iconBackground": adaptive/flatten backdrop)
|
|
392
|
+
app update [ios|android] Move the shell's pins forward — app.json ios.sdk / android.sdk
|
|
393
|
+
to the newest published SDK release, plugins.lock.json to each
|
|
394
|
+
plugin's newest tag — then re-sync
|
|
395
|
+
--sdk <v|latest> pin that release instead of the newest
|
|
396
|
+
--check report available updates, write nothing
|
|
397
|
+
--no-plugins only move the SDK pin
|
|
398
|
+
--no-sync update the pins without re-syncing
|
|
399
|
+
app plugin <list|add|remove> Manage native plugins in app.json (then run 'lecodes app sync')
|
|
400
|
+
add takes a known id (camera, qr-scanner) or github:owner/repo[@tag]
|
|
401
|
+
app open [ios|android] Open the native shell in its IDE (Xcode / Android Studio)
|
|
402
|
+
app doctor Preflight checks for building/uploading the shells
|
|
403
|
+
app build ios Sync, archive and export the .ipa (automatic signing)
|
|
404
|
+
--configuration <c> build configuration (default Release)
|
|
405
|
+
--method <m> export method (default app-store-connect)
|
|
406
|
+
--no-export stop after the archive
|
|
407
|
+
--no-sync skip the lecodes app sync step
|
|
408
|
+
app build android Sync, then gradlew assembleRelease + bundleRelease (signing via
|
|
409
|
+
android/keystore.properties or LECODES_ANDROID_* env vars)
|
|
410
|
+
--configuration <c> Release (default) or Debug
|
|
411
|
+
--no-aab skip the .aab (APK only)
|
|
412
|
+
--no-sync skip the lecodes app sync step
|
|
413
|
+
app build desktop Same as 'lecodes desktop build' (kept for symmetry with the
|
|
414
|
+
ios/android shells) — see the desktop group above.
|
|
415
|
+
app upload ios Upload the archive to App Store Connect (then bumps buildNumber)
|
|
416
|
+
--key-path <p8> --key-id <id> --issuer-id <id>
|
|
417
|
+
ASC API key; stored in ~/.lecodes/asc.json
|
|
418
|
+
pn send --title <s> Push notifications for this project ('lecodes pn' for the group).
|
|
419
|
+
Sends with your login — no push key needed to test.
|
|
420
|
+
--user <ids> target Push.register({ user }) ids (comma-sep)
|
|
421
|
+
--to <pa_…> target addresses (comma-separated)
|
|
422
|
+
--body/--url/--badge/--data payload fields
|
|
423
|
+
pn devices Which devices registered (the 'why didn't it arrive?' command)
|
|
424
|
+
--user <id> only that user's devices
|
|
425
|
+
pn keys [new|revoke] Push keys for YOUR server: list, mint (owner only, shown once
|
|
426
|
+
— 'new --env' banks it in .env), revoke <id>
|
|
427
|
+
|
|
428
|
+
Config lives in ~/.lecodes/config.json (override with LECODES_API / LECODES_TOKEN).
|
|
429
|
+
A .env next to app.json is read at startup for LECODES_* / CREATOR_* keys (the shell's own
|
|
430
|
+
environment wins; ./ paths resolve against the project; the file is never pushed) — e.g.
|
|
431
|
+
LECODES_DESKTOP_EXE, LECODES_MATC, LECODES_NOTARY_PROFILE, LECODES_MACOS_SIGN_ID, LECODES_TOKEN.`
|
|
432
|
+
|
|
433
|
+
// `preview` is the legacy name of `compile` — kept registered (and out of the help) for old scripts.
|
|
434
|
+
const commands: Record<string, (args: Args) => Promise<void>> = { init, login, create, clone, link, status, diff, pull, push, compile, preview: previewLegacy, render, test, design, scene, thumbs, dev, app, pn, desktop, shaders, assets, lightmap, navmesh, update }
|
|
435
|
+
if (STANDALONE) commands.install = install
|
|
436
|
+
|
|
437
|
+
/** Package version, inlined at build time (the standalone binary has no package.json on disk). */
|
|
438
|
+
const readVersion = (): string => pkg.version ?? "unknown"
|
|
439
|
+
|
|
440
|
+
/** `--version`: the CLI version, every separately-installed optional peer (or "not installed"),
|
|
441
|
+
* and the desktop render host `render --desktop` would use (no network — cache state only). */
|
|
442
|
+
const printVersion = () => {
|
|
443
|
+
const rows: [label: string, value: string][] = [["lecodes-cli", readVersion()]]
|
|
444
|
+
for (const [name, probe] of OPTIONAL_PEERS) {
|
|
445
|
+
const version = peerVersion(name, probe)
|
|
446
|
+
rows.push([name, version ?? c.dim("not installed")])
|
|
447
|
+
}
|
|
448
|
+
const desktopVersion = selectedDesktopVersion()
|
|
449
|
+
rows.push(["lecodes-desktop", installedDesktopVersions().includes(desktopVersion)
|
|
450
|
+
? desktopVersion
|
|
451
|
+
: `${desktopVersion} ${c.dim("(not downloaded — fetched on first `render --desktop`)")}`])
|
|
452
|
+
const matcVersion = installedMatcVersions()[0]
|
|
453
|
+
rows.push(["matc", matcVersion ?? c.dim("not downloaded — fetched on the first local shader compile")])
|
|
454
|
+
const width = Math.max(...rows.map(([label]) => label.length))
|
|
455
|
+
for (const [label, value] of rows) log(`${label.padEnd(width)} ${value}`)
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const main = async () => {
|
|
459
|
+
const argv = process.argv.slice(2)
|
|
460
|
+
const command = argv[0]
|
|
461
|
+
// The project's .env (LECODES_* / CREATOR_* next to app.json) — before any command reads the
|
|
462
|
+
// environment; the real environment keeps precedence. See projectEnv.ts.
|
|
463
|
+
loadProjectEnv()
|
|
464
|
+
|
|
465
|
+
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
466
|
+
log(HELP)
|
|
467
|
+
return
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (command === "--version" || command === "-v" || command === "version") {
|
|
471
|
+
printVersion()
|
|
472
|
+
return
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
const run = commands[command]
|
|
476
|
+
if (!run) {
|
|
477
|
+
log(c.red(`Unknown command: ${command}`))
|
|
478
|
+
log(HELP)
|
|
479
|
+
process.exitCode = 1
|
|
480
|
+
return
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// `assets` owns its own flag grammar (multi-value --clips …) — hand it the raw argv too.
|
|
484
|
+
await run(Object.assign(parseArgs(argv.slice(1)), { _raw: argv.slice(1) }))
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
main().catch((e: unknown) => {
|
|
488
|
+
if (e instanceof CliError) log(c.red("✗ ") + e.message)
|
|
489
|
+
else log(c.red("✗ Unexpected error: ") + (e instanceof Error ? e.message : String(e)))
|
|
490
|
+
process.exitCode = 1
|
|
491
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Types for the optional `lecodes-3d-editor` package's server entry (lazy-loaded by the `scene`
|
|
2
|
+
// command). The real package is installed separately; this lets the dynamic import typecheck
|
|
3
|
+
// without it present. Keep in sync with lecodes-tools/packages/lecodes-3d-editor/src/server/index.ts (the CLI↔tool
|
|
4
|
+
// dist coupling: after a server-surface change, rebuild the editor's dist and update this file).
|
|
5
|
+
declare module "lecodes-3d-editor/server" {
|
|
6
|
+
export type CompiledScene = { js: string | null, error?: string }
|
|
7
|
+
|
|
8
|
+
export type SceneServerOptions = {
|
|
9
|
+
root: string
|
|
10
|
+
compile: (scenePath: string) => Promise<CompiledScene>
|
|
11
|
+
/** A shader's compiled artifact file for a platform ("webgl-lite" / "webgl") from the host's
|
|
12
|
+
* cache, null when absent (the server builds the lite JSON itself then). */
|
|
13
|
+
shaderArtifact?: (shaderText: string, platform: string) => string | null
|
|
14
|
+
port?: number
|
|
15
|
+
appDir?: string
|
|
16
|
+
log?: (message: string) => void
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type SceneServer = {
|
|
20
|
+
port: number
|
|
21
|
+
url: string
|
|
22
|
+
close: () => void
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function startSceneServer(options: SceneServerOptions): Promise<SceneServer>
|
|
26
|
+
|
|
27
|
+
/* The asset-preview cache (server/previewCache.ts) — `lecodes thumbs` writes into the same
|
|
28
|
+
* `.lecodes/preview/<asset>.<hash>.png` layout the editor reads. */
|
|
29
|
+
|
|
30
|
+
/** sha256 tag (10 hex) of an asset's current bytes; null when the file is gone. */
|
|
31
|
+
export function hashAsset(projectDir: string, assetPath: string): string | null
|
|
32
|
+
/** Whether the cached preview for THAT hash is already on disk (the incremental skip). */
|
|
33
|
+
export function previewIsCurrent(projectDir: string, assetPath: string, hash: string): boolean
|
|
34
|
+
/** Cache file name for an asset at a known hash. */
|
|
35
|
+
export function previewName(assetPath: string, hash: string): string
|
|
36
|
+
/** Store a preview PNG under the asset's current hash (older ones are dropped); returns the file
|
|
37
|
+
* name written, or null when the asset itself is missing. */
|
|
38
|
+
export function writePreviewFile(projectDir: string, assetPath: string, png: Uint8Array): string | null
|
|
39
|
+
/** Asset path → cache file name, for every preview on disk. */
|
|
40
|
+
export function listPreviews(projectDir: string): Record<string, string>
|
|
41
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Types for the optional `lecodes-assets` package's CLI entry (lazy-loaded by the `assets` command).
|
|
2
|
+
// The real package is installed separately; this lets the dynamic import typecheck without it
|
|
3
|
+
// present. Keep in sync with packages/lecodes-assets/src/cli.ts.
|
|
4
|
+
declare module "lecodes-assets/cli" {
|
|
5
|
+
/** Runs `convert | probe | doctor` with the given argv (sub-command first). Resolves to the exit code. */
|
|
6
|
+
export function runAssetsCli(argv: string[]): Promise<number>
|
|
7
|
+
}
|