lecodes-cli 0.20.2 → 2.0.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.
Files changed (154) hide show
  1. package/README.md +56 -57
  2. package/dist/index.js +11052 -7592
  3. package/package.json +14 -8
  4. package/runtime/materials/decal-relief.mat +12 -1
  5. package/runtime/materials/decal.mat +17 -3
  6. package/runtime/materials/lightmap.mat +117 -138
  7. package/runtime/materials/particles-quad.mat +6 -2
  8. package/runtime/materials/terrain-lightmap.mat +123 -0
  9. package/runtime/materials/terrain.mat +36 -55
  10. package/runtime/sdk-types.json +1 -1
  11. package/runtime/web/VERSION.json +5 -0
  12. package/runtime/web/assets/camera-5XOM8eHl.js +1 -0
  13. package/runtime/web/assets/creator-2d-D9WKYM6h.js +1 -0
  14. package/runtime/web/assets/creator-2d-ukvEmNEp.wasm +0 -0
  15. package/runtime/web/assets/creator-full-BBXzQlhq.js +1 -0
  16. package/runtime/web/assets/creator-full-D2dSDdDj.wasm +0 -0
  17. package/runtime/web/assets/creator-full.js-BYswGsqR.symbols +8124 -0
  18. package/runtime/web/assets/creator-ui-DIc92ion.wasm +0 -0
  19. package/runtime/web/assets/creator-ui-_1Z_AX2M.js +1 -0
  20. package/runtime/web/assets/geolocation-BjTKN9_P.js +1 -0
  21. package/runtime/web/assets/inspect-C7x78PNs.js +2 -0
  22. package/runtime/web/assets/map-CyBxOSV0.js +1 -0
  23. package/runtime/web/assets/map-XzoOFt0E.js +2 -0
  24. package/runtime/web/assets/mapImpl-bxvQ2h1Z.js +823 -0
  25. package/runtime/web/assets/maplibre-gl-worker-B7LXXUkR.js +8 -0
  26. package/runtime/web/assets/materials-uri4FvPE.bin +0 -0
  27. package/runtime/web/assets/materials-world-CQWt8TAm.bin +0 -0
  28. package/runtime/web/assets/qr-scanner-CK_cYoJR.js +1 -0
  29. package/runtime/web/assets/uberarchive-DLH-kBhM.bin +0 -0
  30. package/runtime/web/index.html +36 -0
  31. package/runtime/web/player.js +21 -0
  32. package/runtime/web-page/index.html +41 -0
  33. package/runtime/web-page/page.css +1 -0
  34. package/runtime/web-page/page.js +31 -0
  35. package/src/api.ts +1 -302
  36. package/src/cli/args.ts +37 -0
  37. package/src/cli/command.ts +113 -0
  38. package/src/cli/errors.ts +13 -0
  39. package/src/cli/help.ts +158 -0
  40. package/src/cli/index.ts +7 -0
  41. package/src/cli/output.ts +102 -0
  42. package/src/cli/run.ts +106 -0
  43. package/src/commands/{appAndroid.ts → app/android.ts} +454 -43
  44. package/src/commands/{appDesktop.ts → app/desktop.ts} +64 -33
  45. package/src/commands/{appDesktopMac.ts → app/desktopMac.ts} +34 -27
  46. package/src/commands/{appIcon.ts → app/icon.ts} +11 -8
  47. package/src/commands/{app.ts → app/index.ts} +400 -290
  48. package/src/commands/{appShared.ts → app/shared.ts} +43 -44
  49. package/src/commands/{appTemplatesAndroid.ts → app/templates/android.ts} +72 -39
  50. package/src/commands/{appTemplatesGradlew.ts → app/templates/gradlew.ts} +1 -1
  51. package/src/commands/{appTemplates.ts → app/templates/ios.ts} +2 -2
  52. package/src/commands/assets.ts +23 -21
  53. package/src/commands/clone.ts +48 -51
  54. package/src/commands/compile.ts +76 -89
  55. package/src/commands/create.ts +46 -47
  56. package/src/commands/design/comments.ts +361 -0
  57. package/src/commands/design/context.ts +101 -0
  58. package/src/commands/design/index.ts +391 -0
  59. package/src/commands/design/snapshot.ts +134 -0
  60. package/src/commands/{designTemplates.ts → design/templates.ts} +4 -3
  61. package/src/commands/desktop.ts +94 -82
  62. package/src/commands/dev.ts +260 -182
  63. package/src/commands/diff.ts +39 -51
  64. package/src/commands/index.ts +64 -0
  65. package/src/commands/{init.ts → init/index.ts} +195 -191
  66. package/src/commands/{projectTemplates.ts → init/templates.ts} +64 -21
  67. package/src/commands/install.ts +80 -67
  68. package/src/commands/lightmap.ts +543 -252
  69. package/src/commands/link.ts +87 -94
  70. package/src/commands/login.ts +25 -23
  71. package/src/commands/navmesh.ts +169 -139
  72. package/src/commands/plugin.ts +46 -0
  73. package/src/commands/pn.ts +201 -244
  74. package/src/commands/pull.ts +49 -56
  75. package/src/commands/push.ts +48 -54
  76. package/src/commands/render.ts +176 -111
  77. package/src/commands/scene.ts +63 -55
  78. package/src/commands/serve.ts +58 -0
  79. package/src/commands/{shaders.ts → shaders/index.ts} +61 -42
  80. package/src/commands/{shadersNew.ts → shaders/new.ts} +3 -3
  81. package/src/commands/shared.ts +79 -0
  82. package/src/commands/status.ts +22 -26
  83. package/src/commands/test.ts +94 -63
  84. package/src/commands/thumbs.ts +185 -175
  85. package/src/commands/update/index.ts +226 -0
  86. package/src/commands/{types.ts → update/types.ts} +31 -22
  87. package/src/compile/collect.ts +5 -5
  88. package/src/compile/collectLocal.ts +3 -3
  89. package/src/compile/designCompile.ts +4 -4
  90. package/src/compile/headlessBundle.ts +16 -12
  91. package/src/compile/nativeStack.ts +1 -1
  92. package/src/compile/projectCompile.ts +12 -4
  93. package/src/compile/sceneCompile.ts +14 -26
  94. package/src/compile/screenEntry.ts +123 -127
  95. package/src/compile/shaders.ts +3 -3
  96. package/src/{lecodes-3d-editor.d.ts → declarations/lecodes-3d-editor.d.ts} +4 -0
  97. package/src/{lecodes-assets.d.ts → declarations/lecodes-assets.d.ts} +1 -1
  98. package/src/{lecodes-renderer.d.ts → declarations/lecodes-headless.d.ts} +3 -3
  99. package/src/dev/androidDev.ts +1 -1
  100. package/src/dev/clientTemplates.ts +18 -14
  101. package/src/dev/devServer.ts +78 -41
  102. package/src/dev/iosDev.ts +180 -0
  103. package/src/dev/webRunner.ts +83 -15
  104. package/src/{cmgenTool.ts → hosts/cmgenTool.ts} +2 -2
  105. package/src/{desktopRenderer.ts → hosts/desktopRenderer.ts} +104 -32
  106. package/src/{desktopScript.ts → hosts/desktopScript.ts} +151 -36
  107. package/src/{distRoot.ts → hosts/distRoot.ts} +9 -5
  108. package/src/{matcTool.ts → hosts/matcTool.ts} +2 -2
  109. package/src/{peerInstall.ts → hosts/peerInstall.ts} +7 -7
  110. package/src/{peers.ts → hosts/peers.ts} +2 -2
  111. package/src/{releases.ts → hosts/releases.ts} +1 -1
  112. package/src/index.ts +35 -480
  113. package/src/platform/api.ts +302 -0
  114. package/src/{browserAuth.ts → platform/browserAuth.ts} +1 -1
  115. package/src/{config.ts → platform/config.ts} +1 -1
  116. package/src/{serverDiff.ts → platform/serverDiff.ts} +3 -3
  117. package/src/plugin/contract.ts +438 -0
  118. package/src/plugin/emitKotlin.ts +357 -0
  119. package/src/plugin/emitSdk.ts +259 -0
  120. package/src/plugin/emitSwift.ts +336 -0
  121. package/src/plugin/emitWeb.ts +383 -0
  122. package/src/plugin/generate.ts +157 -0
  123. package/src/plugin/lines.ts +28 -0
  124. package/src/plugin/lower.ts +231 -0
  125. package/src/plugin/manifest.ts +192 -0
  126. package/src/{projectEnv.ts → project/env.ts} +33 -2
  127. package/src/{ignore.ts → project/ignore.ts} +164 -163
  128. package/src/{localFiles.ts → project/localFiles.ts} +1 -1
  129. package/src/{manifest.ts → project/manifest.ts} +1 -1
  130. package/src/{project.ts → project/materialize.ts} +2 -2
  131. package/src/project/paths.ts +20 -0
  132. package/src/{textDiff.ts → project/textDiff.ts} +1 -1
  133. package/src/{types.ts → project/types.ts} +0 -0
  134. package/runtime/materials/lightmap-baked-lite.mat +0 -175
  135. package/runtime/materials/lightmap-baked.mat +0 -176
  136. package/runtime/scene-harness.json +0 -1
  137. package/runtime/web/assets/__vite-browser-external-BIHI7g3E.js +0 -1
  138. package/runtime/web/assets/basis-C64VHDVD.js +0 -1
  139. package/runtime/web/assets/basis_transcoder-VXdx5NbI.wasm +0 -0
  140. package/runtime/web/assets/createViewerLite-Ct_PZdof.js +0 -852
  141. package/runtime/web/assets/draco-BiISTFcR.js +0 -118
  142. package/runtime/web/assets/draco_decoder-DsQ12WqX.wasm +0 -0
  143. package/runtime/web/assets/index-BMt7AnC5.js +0 -2
  144. package/runtime/web/assets/mapViewImpl-B2JcES8l.js +0 -810
  145. package/runtime/web/assets/maplibre-gl-worker-CJfwIrte.js +0 -8
  146. package/runtime/web/assets/worker-Caf-yYEI.js +0 -2
  147. package/runtime/web/embed.html +0 -32
  148. package/runtime/web/embed.js +0 -171
  149. package/src/commands/design.ts +0 -846
  150. package/src/commands/update.ts +0 -211
  151. package/src/util.ts +0 -146
  152. /package/src/{lecodes-design.d.ts → declarations/lecodes-design.d.ts} +0 -0
  153. /package/src/{qrcode-terminal.d.ts → declarations/qrcode-terminal.d.ts} +0 -0
  154. /package/src/{designMeta.ts → project/designMeta.ts} +0 -0
@@ -1,26 +1,19 @@
1
1
  import { basename } from "node:path"
2
- import { CliError, c, flagBool, flagStr, log, note, type Args } from "../util"
3
- import { findProjectRoot } from "../manifest"
4
- import { buildBundle } from "./compile"
5
- import { assertRendererSupportsBundle, desktopPluginLibraries, readAppConfigAt, resolveDesktopRenderer } from "./appShared"
6
- import { buildDesktop } from "./appDesktop"
2
+ import { CliError, bool, c, defineCommand, log, note, num, str } from "../cli"
7
3
  import {
8
- DESKTOP_RENDERER_VERSION,
9
- fetchDesktopManifest,
10
- findMacHostExe,
11
- installedDesktopVersions,
12
- runDesktopApp,
13
- selectedDesktopVersion,
14
- semverNewer,
15
- updateDesktop,
16
- } from "../desktopRenderer"
4
+ DESKTOP_RENDERER_VERSION, fetchDesktopManifest, findMacHostExe, installedDesktopVersions, runDesktopApp,
5
+ selectedDesktopVersion, semverNewer, updateDesktop,
6
+ } from "../hosts/desktopRenderer"
7
+ import { desktopBuild } from "./app/desktop"
8
+ import { desktopPluginLibraries, readAppConfigAt, resolveDesktopRenderer } from "./app/shared"
9
+ import { buildBundle } from "./compile"
10
+ import { bundleFlags, bundleOptions, localProject } from "./shared"
17
11
 
18
12
  /*
19
- * `lecodes desktop` — everything about the desktop target in one place.
13
+ * `lecodes desktop` — the desktop target, the host `lecodes render --desktop` uses too.
20
14
  * (no args) status: the version renders use, what's cached, what's published
21
15
  * run compile the current project and open it in a real desktop window
22
- * build stage a portable app folder (the same command as `lecodes app build desktop`,
23
- * which stays for symmetry with the ios/android shells)
16
+ * build stage a portable app folder (the same as `lecodes app build desktop`)
24
17
  * update move the host to the newest published release (downloads it if needed)
25
18
  * The binary cache lives in ~/.lecodes/renderer/; LECODES_DESKTOP_EXE overrides everything.
26
19
  */
@@ -32,9 +25,7 @@ export const resolveScale = (flag: string | undefined, cfg: number | "fit" | "sy
32
25
  if (raw === undefined || raw === "system") return undefined
33
26
  if (raw === "fit") return "fit"
34
27
  const n = Number(raw)
35
- if (!Number.isFinite(n) || n < 0.5 || n > 4) {
36
- throw new CliError(`scale must be a number 0.5..4, "fit" or "system" (got "${raw}")`)
37
- }
28
+ if (!Number.isFinite(n) || n < 0.5 || n > 4) throw new CliError(`scale must be a number 0.5..4, "fit" or "system" (got "${raw}")`)
38
29
  return n
39
30
  }
40
31
 
@@ -46,55 +37,75 @@ export const resolveRenderScale = (flag: string | undefined, cfg: number | undef
46
37
  return n
47
38
  }
48
39
 
49
- const run = async (args: Args) => {
50
- // Window defaults come from app.json's desktop block (flags win); standalone projects
51
- // without an app.json keep the host's built-in 1280×720.
52
- let root: string
53
- try { root = findProjectRoot(process.cwd()) } catch { root = process.cwd() }
54
- const appCfg = readAppConfigAt(root)
55
- const win = appCfg?.desktop?.window
56
- // ONE renderer decision per run: it picks the host binary AND which .filamat gets staged beside
57
- // the bundle. Reading the config twice is how a Vulkan exe ends up next to an OpenGL shader.
58
- const renderer = resolveDesktopRenderer(root, args)
59
- const { js, resources } = await buildBundle(args, undefined, { localAssets: true, desktopRenderer: renderer })
60
- assertRendererSupportsBundle(renderer, js)
61
- // Native plugins: the project's plugins/ dir + declared plugin libraries, scanned by the host.
62
- const { dirs: pluginDirs, files: pluginFiles } = desktopPluginLibraries(root)
63
- if (pluginFiles.length > 0) note(`Native plugins: ${pluginFiles.map((f) => basename(f)).join(", ")}`)
64
- note(`Launching LeCodes Desktop${renderer === "vulkan" ? " (Vulkan)" : ""}… (close the window to return)`)
65
- await runDesktopApp(js, resources, {
66
- renderer,
67
- pluginDirs,
68
- width: Number(flagStr(args, "width")) || win?.width,
69
- height: Number(flagStr(args, "height")) || win?.height,
70
- minWidth: win?.minWidth,
71
- minHeight: win?.minHeight,
72
- resizable: win?.resizable,
73
- title: flagStr(args, "title") ?? win?.title ?? appCfg?.name,
74
- storageScope: appCfg?.name,
75
- // --fullscreen forces it on; --windowed forces it off (over app.json); else the config decides.
76
- fullscreen: flagBool(args, "fullscreen") ? true : flagBool(args, "windowed") ? false : win?.fullscreen,
77
- scale: resolveScale(flagStr(args, "scale"), win?.scale),
78
- // 3D render resolution: --render-scale wins over app.json desktop.renderScale; the cap comes
79
- // from app.json only. Both are desktop-level (the machine/app), not window-level.
80
- renderScale: resolveRenderScale(flagStr(args, "render-scale"), appCfg?.desktop?.renderScale),
81
- maxRenderSize: appCfg?.desktop?.maxRenderSize,
82
- mouseEmulateTouch: appCfg?.desktop?.mouseEmulateTouch,
83
- virtualKeyboard: appCfg?.desktop?.virtualKeyboard,
84
- // --fps: the host's own corner counter. A flag and not app.json on purpose — it is something you
85
- // switch on while looking at a frame, not a property of the app.
86
- fps: flagBool(args, "fps"),
87
- // Multiplayer (docs/multiplayer-plan.md): --server [--port N] [--max-clients N] starts the host as a
88
- // dedicated server; --connect ip:port joins one. Both only set Net.launch — the app calls Net.listen/connect.
89
- net: flagBool(args, "server")
90
- ? { role: "server", port: Number(flagStr(args, "port")) || undefined, maxClients: Number(flagStr(args, "max-clients")) || undefined }
91
- : flagStr(args, "connect")
92
- ? { role: "client", address: flagStr(args, "connect") }
93
- : undefined,
94
- })
95
- }
40
+ const run = defineCommand({
41
+ name: "run",
42
+ summary: "Compile the current project and open it in a desktop window",
43
+ description: "Window size / min size / title default from app.json's desktop block; asset() resources load from the working tree. Multiplayer: --server starts the host as a dedicated server, --connect joins one — both only set Net.launch (the app decides).",
44
+ flags: {
45
+ width: num("window width (logical px)"),
46
+ height: num("window height (logical px)"),
47
+ title: str("window title", { value: "<s>" }),
48
+ fullscreen: bool("force fullscreen (over app.json)"),
49
+ windowed: bool("force windowed (over app.json)"),
50
+ scale: str('display scale: 0.5..4, "fit" (size a 1080p-designed app to the monitor), or "system"', { value: "<n|fit>" }),
51
+ "render-scale": str("3D render resolution 0.25..1 (over app.json desktop.renderScale)", { value: "<n>" }),
52
+ renderer: str("host + shader variant: gl | vulkan (default: app.json desktop.renderer, else gl)", { value: "<gl|vulkan>" }),
53
+ fps: bool("draw the host's frame counter in the corner (composited fps + the 3D fps when they diverge)"),
54
+ perf: bool("the host's profiler: a [perf] line a second (GPU frame time, CPU split, what the camera sees) + a second overlay row; implies --fps"),
55
+ server: bool("launch as a multiplayer server"),
56
+ port: num("(--server) listen port"),
57
+ "max-clients": num("(--server) client cap"),
58
+ connect: str("join a server as a client", { value: "<ip:port>" }),
59
+ ...bundleFlags,
60
+ },
61
+ examples: ["lecodes desktop run", "lecodes desktop run --scale fit --fps", "lecodes desktop run --perf", "lecodes desktop run --server --port 7777"],
62
+ run: async ({ flags, raw }) => {
63
+ // Window defaults come from app.json's desktop block (flags win); standalone projects
64
+ // without an app.json keep the host's built-in 1280×720.
65
+ const { root } = localProject()
66
+ const appCfg = readAppConfigAt(root)
67
+ const win = appCfg?.desktop?.window
68
+ // ONE renderer decision per run: it picks the host binary AND which .filamat gets staged beside
69
+ // the bundle. Reading the config twice is how a Vulkan exe ends up next to an OpenGL shader.
70
+ const renderer = resolveDesktopRenderer(root, flags.renderer)
71
+ const { js, resources } = await buildBundle(bundleOptions(flags), { localAssets: true, desktopRenderer: renderer })
72
+ // Native plugins: the project's plugins/ dir + declared plugin libraries, scanned by the host.
73
+ const { dirs: pluginDirs, files: pluginFiles } = desktopPluginLibraries(root)
74
+ if (pluginFiles.length > 0) note(`Native plugins: ${pluginFiles.map((f) => basename(f)).join(", ")}`)
75
+ note(`Launching LeCodes Desktop${renderer === "vulkan" ? " (Vulkan)" : ""}… (close the window to return)`)
76
+ await runDesktopApp(js, resources, {
77
+ renderer,
78
+ pluginDirs,
79
+ width: flags.width || win?.width,
80
+ height: flags.height || win?.height,
81
+ minWidth: win?.minWidth,
82
+ minHeight: win?.minHeight,
83
+ resizable: win?.resizable,
84
+ title: flags.title ?? win?.title ?? appCfg?.name,
85
+ storageScope: appCfg?.name,
86
+ // --fullscreen forces it on; --windowed forces it off (over app.json); else the config decides.
87
+ fullscreen: flags.fullscreen ? true : flags.windowed ? false : win?.fullscreen,
88
+ scale: resolveScale(flags.scale, win?.scale),
89
+ // 3D render resolution: --render-scale wins over app.json desktop.renderScale; the cap comes
90
+ // from app.json only. Both are desktop-level (the machine/app), not window-level.
91
+ renderScale: resolveRenderScale(flags["render-scale"], appCfg?.desktop?.renderScale),
92
+ maxRenderSize: appCfg?.desktop?.maxRenderSize,
93
+ // Frame-rate cap (app.json only — like renderScale it is a property of the app, not of a run).
94
+ frameRate: appCfg?.desktop?.frameRate,
95
+ mouseEmulateTouch: appCfg?.desktop?.mouseEmulateTouch,
96
+ virtualKeyboard: appCfg?.desktop?.virtualKeyboard,
97
+ // --fps: the host's own corner counter. A flag and not app.json on purpose — it is something you
98
+ // switch on while looking at a frame, not a property of the app.
99
+ fps: flags.fps,
100
+ perf: flags.perf,
101
+ net: flags.server
102
+ ? { role: "server", port: flags.port, maxClients: flags["max-clients"] }
103
+ : flags.connect ? { role: "client", address: flags.connect } : undefined,
104
+ })
105
+ },
106
+ })
96
107
 
97
- const status = async () => {
108
+ const status = async (): Promise<void> => {
98
109
  const selected = selectedDesktopVersion()
99
110
  const installed = installedDesktopVersions()
100
111
  log(`renders with ${selected}${installed.includes(selected) ? "" : c.dim(" (not downloaded yet — fetched on first render)")}`)
@@ -103,28 +114,29 @@ const status = async () => {
103
114
  if (process.env.LECODES_DESKTOP_EXE) log(`override LECODES_DESKTOP_EXE=${process.env.LECODES_DESKTOP_EXE}`)
104
115
  if (process.platform === "darwin") {
105
116
  // The cache is what runs/builds use; a hand-installed app only steps in when the manifest is unreachable.
106
- const installed = findMacHostExe()
107
- log(`installed ${installed ?? c.dim("none")} ${c.dim("(offline fallback only)")}`)
117
+ const mac = findMacHostExe()
118
+ log(`installed ${mac ?? c.dim("none")} ${c.dim("(offline fallback only)")}`)
108
119
  }
109
120
  try {
110
121
  const { latest } = await fetchDesktopManifest()
111
122
  const hint = semverNewer(selected, latest) > 0
112
123
  ? c.yellow("(newer — run `lecodes desktop update`)")
113
- : latest === selected
114
- ? c.dim("(up to date)")
115
- : c.dim("(older than the CLI's minimum — this desktop release isn't published yet)")
124
+ : latest === selected ? c.dim("(up to date)") : c.dim("(older than the CLI's minimum — this desktop release isn't published yet)")
116
125
  log(`published ${latest} ${hint}`)
117
126
  } catch {
118
127
  log(`published ${c.dim("unknown (couldn't reach the release manifest)")}`)
119
128
  }
120
129
  }
121
130
 
122
- export const desktop = async (args: Args) => {
123
- const sub = args._[0]
124
- if (sub === undefined) return status()
125
- if (sub === "run") return run(args)
126
- // `buildDesktop` reads only flags, never positionals, so it takes both spellings unchanged.
127
- if (sub === "build") return buildDesktop(args)
128
- if (sub === "update") return updateDesktop()
129
- throw new CliError(`Unknown subcommand "desktop ${sub}". Use \`lecodes desktop\` (status), \`lecodes desktop run\`, \`lecodes desktop build\` or \`lecodes desktop update\`.`)
130
- }
131
+ export default defineCommand({
132
+ name: "desktop",
133
+ summary: "The desktop host: status, run the project in a window, build a portable app, update",
134
+ description: "Bare `lecodes desktop` prints the version status: the host renders use, what is cached in ~/.lecodes/renderer, the newest published one. LECODES_DESKTOP_EXE points every desktop command at a local host build instead.",
135
+ commands: [
136
+ run,
137
+ // `buildDesktop` is shared with `lecodes app build desktop`; its flags live there.
138
+ desktopBuild,
139
+ defineCommand({ name: "update", summary: "Move the host to the newest published release", run: () => updateDesktop() }),
140
+ ],
141
+ run: () => status(),
142
+ })