lecodes-cli 0.19.2 → 0.20.1

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 (59) hide show
  1. package/README.md +1 -0
  2. package/dist/index.js +1324 -658
  3. package/package.json +9 -9
  4. package/runtime/materials/decal-relief.mat +178 -0
  5. package/runtime/materials/decal.mat +172 -0
  6. package/runtime/materials/lightmap-baked-lite.mat +175 -0
  7. package/runtime/materials/lightmap-baked.mat +176 -0
  8. package/runtime/materials/lightmap.mat +181 -0
  9. package/runtime/materials/lit.mat +43 -0
  10. package/runtime/materials/particles-quad.mat +171 -0
  11. package/runtime/materials/particles.mat +121 -0
  12. package/runtime/materials/shadow.mat +21 -0
  13. package/runtime/materials/terrain.mat +134 -0
  14. package/runtime/materials/unlit-transparent.mat +42 -0
  15. package/runtime/materials/unlit.mat +44 -0
  16. package/runtime/materials/video.mat +31 -0
  17. package/runtime/sdk-types.json +1 -1
  18. package/runtime/web/assets/Roboto-Variable-DHm9jpd-.woff2 +0 -0
  19. package/runtime/web/assets/__vite-browser-external-BIHI7g3E.js +1 -0
  20. package/runtime/web/assets/basis-C64VHDVD.js +1 -0
  21. package/runtime/web/assets/basis_transcoder-VXdx5NbI.wasm +0 -0
  22. package/runtime/web/assets/createViewerLite-C_bkKXLg.js +852 -0
  23. package/runtime/web/assets/draco-BiISTFcR.js +118 -0
  24. package/runtime/web/assets/draco_decoder-DsQ12WqX.wasm +0 -0
  25. package/runtime/web/assets/index-BTB5KV9x.js +2 -0
  26. package/runtime/web/assets/mapViewImpl-B2JcES8l.js +810 -0
  27. package/runtime/web/assets/maplibre-gl-worker-CJfwIrte.js +8 -0
  28. package/runtime/web/assets/neutral_ibl128-D-lzdkLN.ktx +0 -0
  29. package/runtime/web/assets/worker-Caf-yYEI.js +2 -0
  30. package/runtime/web/embed.html +32 -0
  31. package/runtime/web/embed.js +171 -0
  32. package/src/cmgenTool.ts +17 -9
  33. package/src/commands/app.ts +6 -1
  34. package/src/commands/appDesktop.ts +27 -4
  35. package/src/commands/appShared.ts +145 -3
  36. package/src/commands/appTemplates.ts +28 -4
  37. package/src/commands/assets.ts +3 -7
  38. package/src/commands/design.ts +9 -26
  39. package/src/commands/desktop.ts +9 -1
  40. package/src/commands/dev.ts +64 -0
  41. package/src/commands/projectTemplates.ts +17 -4
  42. package/src/commands/render.ts +9 -11
  43. package/src/commands/scene.ts +2 -6
  44. package/src/commands/shaders.ts +17 -1
  45. package/src/commands/shadersNew.ts +133 -0
  46. package/src/commands/test.ts +2 -1
  47. package/src/commands/thumbs.ts +3 -6
  48. package/src/commands/update.ts +42 -21
  49. package/src/desktopRenderer.ts +32 -2
  50. package/src/desktopScript.ts +1 -1
  51. package/src/dev/androidDev.ts +154 -0
  52. package/src/dev/devServer.ts +53 -6
  53. package/src/dev/webRunner.ts +22 -0
  54. package/src/index.ts +24 -4
  55. package/src/matcTool.ts +31 -19
  56. package/src/peerInstall.ts +160 -0
  57. package/src/peers.ts +48 -14
  58. package/src/projectEnv.ts +4 -0
  59. package/src/releases.ts +16 -0
package/src/peers.ts CHANGED
@@ -1,26 +1,49 @@
1
1
  import { existsSync, readFileSync } from "node:fs"
2
2
  import { createRequire } from "node:module"
3
- import { dirname, join } from "node:path"
4
-
5
- /* Optional peer packages a user installs separately — `npm install -g …`, matching how the CLI
6
- * itself is installed. A bare specifier resolves upward from the importing FILE, so a global CLI
7
- * only ever sees globally installed peers: a project-local `-D` install is invisible to it, and
8
- * under `npx` neither works (pass every peer as its own `-p`). `--version` reports each one's
9
- * installed version so a stale/mismatched copy — the usual cause of "needs X" errors or silent
10
- * render failures like a design screen coming back empty — is visible at a glance. The probe is an
11
- * export subpath that resolves to a real file in BOTH the published package and the workspace
12
- * source, so version reporting works whether the CLI runs from npm or straight from the monorepo. */
3
+ import { homedir } from "node:os"
4
+ import { dirname, join, resolve } from "node:path"
5
+
6
+ /* Optional peer packages the CLI loads lazily. Two places they can live:
7
+ *
8
+ * global `npm install -g …`, next to a globally installed CLI — the original way. A bare specifier
9
+ * resolves upward from the importing FILE, so a global CLI only ever sees globally installed
10
+ * peers (a project-local `-D` install is invisible to it).
11
+ * prefix ~/.lecodes/peers (LECODES_PEERS_DIR) — the CLI's own install dir, filled ON FIRST USE by
12
+ * peerInstall.ts when a command needs a peer that isn't there: no admin rights, and the
13
+ * runtime-set peer (lecodes-renderer) is pinned to THIS CLI's version, so the compiler and
14
+ * the headless host can't drift apart. `@napi-rs/canvas` (PNG output) rides along with it.
15
+ *
16
+ * Global wins when both exist (it is what the user chose by hand). `--version` reports each peer's
17
+ * installed version + where it came from, so a stale/mismatched copy — the usual cause of "needs X"
18
+ * errors or a design screen rendering empty — is visible at a glance. The probe is an export subpath
19
+ * that resolves to a real file in BOTH the published package and the workspace source. */
13
20
  export const OPTIONAL_PEERS: [name: string, probe: string][] = [
14
21
  ["lecodes-renderer", "lecodes-renderer/headless"],
15
22
  ["lecodes-design", "lecodes-design/server"],
16
23
  ["lecodes-3d-editor", "lecodes-3d-editor/server"],
17
24
  ["lecodes-assets", "lecodes-assets/cli"],
25
+ ["@napi-rs/canvas", "@napi-rs/canvas"],
18
26
  ]
19
27
 
20
- /** Installed version of an optional peer, or null when it isn't installed. Resolves the probe
21
- * subpath, then walks up to the nearest package.json that actually names the package (skipping any
22
- * nested ones). Never throws — a standalone binary with no node_modules reports every peer absent. */
23
- export const peerVersion = (name: string, probe: string): string | null => {
28
+ /** The CLI's own peer install dir. */
29
+ export const peersDir = (): string =>
30
+ process.env.LECODES_PEERS_DIR ? resolve(process.env.LECODES_PEERS_DIR) : join(homedir(), ".lecodes", "peers")
31
+
32
+ /** Where a peer sits inside the prefix (scoped names span two directories). */
33
+ export const peerDirInPrefix = (name: string): string => join(peersDir(), "node_modules", ...name.split("/"))
34
+
35
+ const readVersion = (dir: string): string | null => {
36
+ try {
37
+ return (JSON.parse(readFileSync(join(dir, "package.json"), "utf8")) as { version?: string }).version ?? "unknown"
38
+ } catch {
39
+ return null
40
+ }
41
+ }
42
+
43
+ /** Installed version of a peer as a bare specifier resolves it (global / workspace), or null. Resolves
44
+ * the probe subpath, then walks up to the nearest package.json that actually names the package
45
+ * (skipping any nested ones). Never throws — a standalone binary with no node_modules reports absent. */
46
+ export const peerVersionGlobal = (name: string, probe: string): string | null => {
24
47
  try {
25
48
  const require = createRequire(import.meta.url)
26
49
  let dir = dirname(require.resolve(probe))
@@ -38,3 +61,14 @@ export const peerVersion = (name: string, probe: string): string | null => {
38
61
  return null
39
62
  }
40
63
 
64
+ /** Installed version of a peer in the CLI's own prefix, or null. */
65
+ export const peerVersionPrefix = (name: string): string | null => readVersion(peerDirInPrefix(name))
66
+
67
+ /** Installed version of a peer wherever it lives (global first), or null when it isn't installed. */
68
+ export const peerVersion = (name: string, probe: string): string | null =>
69
+ peerVersionGlobal(name, probe) ?? peerVersionPrefix(name)
70
+
71
+ /** Which install a bare load of the peer would hit: "global" (npm -g / the workspace), "prefix"
72
+ * (~/.lecodes/peers), or null when it is nowhere. */
73
+ export const peerSource = (name: string, probe: string): "global" | "prefix" | null =>
74
+ peerVersionGlobal(name, probe) !== null ? "global" : peerVersionPrefix(name) !== null ? "prefix" : null
package/src/projectEnv.ts CHANGED
@@ -69,7 +69,11 @@ export const applyDotEnv = (
69
69
  /** The nearest project root at or above `start`: the first dir with app.json or .lecodes/. */
70
70
  export const findEnvRoot = (start: string): string | null => {
71
71
  let dir = resolve(start)
72
+ // The home dir holds the CLI's own ~/.lecodes (matc, desktop host, peers) — never a project, and a
73
+ // `~/.env` must not be loaded as one (update.ts's findProjectDir draws the same line).
74
+ const home = resolve(homedir())
72
75
  while (true) {
76
+ if (dir === home) return null
73
77
  if (existsSync(join(dir, "app.json")) || existsSync(join(dir, ".lecodes"))) return dir
74
78
  const parent = dirname(dir)
75
79
  if (parent === dir) return null
package/src/releases.ts CHANGED
@@ -43,6 +43,22 @@ export const semverNewer = (a: string, b: string): number => {
43
43
  return 0
44
44
  }
45
45
 
46
+ /**
47
+ * The newest published version that actually carries a build for this platform — NOT the product's
48
+ * `latest`. A release ships the platforms whose machine ran it: matc 1.4.0 is windows-x64 alone, and
49
+ * its macOS build lives on 1.3.2. Keying off `latest` therefore reports "isn't published" to everyone
50
+ * whose platform missed the last release, even though a perfectly good older build is right there.
51
+ * Null when the platform has never been published at all. (These tools are deliberately version-loose:
52
+ * a filamat is tied to the vendored Filament, which changes rarely — see matcTool's header.)
53
+ */
54
+ export const newestForPlatform = (
55
+ versions: ManifestVersion[], key: string,
56
+ ): { version: string, file: ManifestFile } | null => {
57
+ const carrying = versions.filter((v) => v.files[key]).sort((a, b) => semverNewer(a.version, b.version))
58
+ const newest = carrying[0]
59
+ return newest ? { version: newest.version, file: newest.files[key]! } : null
60
+ }
61
+
46
62
  /** One product from the release manifest (always fetched fresh — see MANIFEST_URL). */
47
63
  export const fetchReleaseProduct = async (
48
64
  product: string, label: string,