lecodes-cli 0.20.1 → 1.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.
- package/README.md +56 -57
- package/dist/index.js +5920 -5022
- package/package.json +9 -7
- package/runtime/materials/decal-relief.mat +12 -1
- package/runtime/materials/decal.mat +17 -3
- package/runtime/materials/lightmap-baked-lite.mat +6 -1
- package/runtime/materials/lightmap-baked.mat +6 -1
- package/runtime/materials/lightmap.mat +3 -0
- package/runtime/materials/particles-quad.mat +17 -9
- package/runtime/materials/particles.mat +17 -9
- package/runtime/scene-harness.json +1 -1
- package/runtime/sdk-types.json +1 -1
- package/runtime/web/assets/createViewerLite-DHqTFhWB.js +866 -0
- package/runtime/web/assets/{index-BTB5KV9x.js → index-Q06c6oHx.js} +1 -1
- package/runtime/web/embed.js +2 -2
- package/src/api.ts +1 -302
- package/src/cli/args.ts +37 -0
- package/src/cli/command.ts +113 -0
- package/src/cli/errors.ts +13 -0
- package/src/cli/help.ts +133 -0
- package/src/cli/index.ts +7 -0
- package/src/cli/output.ts +102 -0
- package/src/cli/run.ts +106 -0
- package/src/commands/{appAndroid.ts → app/android.ts} +451 -42
- package/src/commands/{appDesktop.ts → app/desktop.ts} +63 -32
- package/src/commands/{appDesktopMac.ts → app/desktopMac.ts} +24 -18
- package/src/commands/{appIcon.ts → app/icon.ts} +2 -2
- package/src/commands/{app.ts → app/index.ts} +397 -289
- package/src/commands/{appShared.ts → app/shared.ts} +30 -39
- package/src/commands/{appTemplatesAndroid.ts → app/templates/android.ts} +62 -28
- package/src/commands/{appTemplatesGradlew.ts → app/templates/gradlew.ts} +1 -1
- package/src/commands/{appTemplates.ts → app/templates/ios.ts} +1 -1
- package/src/commands/assets.ts +23 -21
- package/src/commands/clone.ts +48 -51
- package/src/commands/compile.ts +62 -88
- package/src/commands/create.ts +46 -47
- package/src/commands/design/comments.ts +361 -0
- package/src/commands/design/context.ts +101 -0
- package/src/commands/design/index.ts +391 -0
- package/src/commands/design/snapshot.ts +134 -0
- package/src/commands/{designTemplates.ts → design/templates.ts} +4 -3
- package/src/commands/desktop.ts +90 -82
- package/src/commands/dev.ts +201 -176
- package/src/commands/diff.ts +39 -51
- package/src/commands/index.ts +60 -0
- package/src/commands/{init.ts → init/index.ts} +199 -191
- package/src/commands/install.ts +80 -67
- package/src/commands/lightmap.ts +203 -171
- package/src/commands/link.ts +87 -94
- package/src/commands/login.ts +25 -23
- package/src/commands/navmesh.ts +168 -138
- package/src/commands/pn.ts +201 -244
- package/src/commands/pull.ts +49 -56
- package/src/commands/push.ts +48 -54
- package/src/commands/render.ts +158 -99
- package/src/commands/scene.ts +58 -55
- package/src/commands/{shaders.ts → shaders/index.ts} +61 -42
- package/src/commands/{shadersNew.ts → shaders/new.ts} +2 -2
- package/src/commands/shared.ts +79 -0
- package/src/commands/status.ts +22 -26
- package/src/commands/test.ts +398 -371
- package/src/commands/thumbs.ts +185 -175
- package/src/commands/update/index.ts +226 -0
- package/src/commands/{types.ts → update/types.ts} +31 -22
- package/src/compile/collect.ts +5 -5
- package/src/compile/collectLocal.ts +3 -3
- package/src/compile/designCompile.ts +3 -3
- package/src/compile/headlessBundle.ts +133 -129
- package/src/compile/projectCompile.ts +2 -2
- package/src/compile/sceneCompile.ts +10 -8
- package/src/compile/screenEntry.ts +123 -127
- package/src/compile/shaders.ts +3 -3
- package/src/dev/androidDev.ts +1 -1
- package/src/dev/devServer.ts +3 -3
- package/src/dev/webRunner.ts +1 -1
- package/src/{cmgenTool.ts → hosts/cmgenTool.ts} +1 -1
- package/src/{desktopRenderer.ts → hosts/desktopRenderer.ts} +6 -5
- package/src/{desktopScript.ts → hosts/desktopScript.ts} +1 -1
- package/src/{distRoot.ts → hosts/distRoot.ts} +9 -5
- package/src/{matcTool.ts → hosts/matcTool.ts} +1 -1
- package/src/{peerInstall.ts → hosts/peerInstall.ts} +2 -2
- package/src/{releases.ts → hosts/releases.ts} +1 -1
- package/src/index.ts +32 -480
- package/src/platform/api.ts +302 -0
- package/src/{browserAuth.ts → platform/browserAuth.ts} +1 -1
- package/src/{config.ts → platform/config.ts} +1 -1
- package/src/{serverDiff.ts → platform/serverDiff.ts} +3 -3
- package/src/{projectEnv.ts → project/env.ts} +33 -2
- package/src/{localFiles.ts → project/localFiles.ts} +1 -1
- package/src/{manifest.ts → project/manifest.ts} +1 -1
- package/src/{project.ts → project/materialize.ts} +2 -2
- package/src/project/paths.ts +20 -0
- package/src/{textDiff.ts → project/textDiff.ts} +1 -1
- package/src/{types.ts → project/types.ts} +0 -0
- package/runtime/web/assets/createViewerLite-C_bkKXLg.js +0 -852
- package/src/commands/design.ts +0 -846
- package/src/commands/update.ts +0 -211
- package/src/util.ts +0 -146
- /package/src/commands/{projectTemplates.ts → init/templates.ts} +0 -0
- /package/src/{lecodes-3d-editor.d.ts → declarations/lecodes-3d-editor.d.ts} +0 -0
- /package/src/{lecodes-assets.d.ts → declarations/lecodes-assets.d.ts} +0 -0
- /package/src/{lecodes-design.d.ts → declarations/lecodes-design.d.ts} +0 -0
- /package/src/{lecodes-renderer.d.ts → declarations/lecodes-renderer.d.ts} +0 -0
- /package/src/{qrcode-terminal.d.ts → declarations/qrcode-terminal.d.ts} +0 -0
- /package/src/{peers.ts → hosts/peers.ts} +0 -0
- /package/src/{designMeta.ts → project/designMeta.ts} +0 -0
- /package/src/{ignore.ts → project/ignore.ts} +0 -0
|
@@ -1,127 +1,123 @@
|
|
|
1
|
-
import { existsSync, readFileSync, statSync } from "node:fs"
|
|
2
|
-
import { isAbsolute, join, relative, resolve } from "node:path"
|
|
3
|
-
import { screenFrame } from "../designMeta"
|
|
4
|
-
import { CliError
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
entry
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
frame
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
/** Whether the argument names a path at all (vs a bare screen id). */
|
|
43
|
-
const hasSeparator = (file: string) => file.includes("/") || file.includes("\\")
|
|
44
|
-
|
|
45
|
-
/** Find the screen file: a path (with or without extension), or a bare id resolved against the
|
|
46
|
-
* design folder's screens/ (`lecodes render login`, honoring --dir). */
|
|
47
|
-
const findScreenFile = (root: string, file: string, dirFlag: string | undefined): string => {
|
|
48
|
-
const candidates = [resolve(process.cwd(), file)]
|
|
49
|
-
if (!hasSeparator(file)) {
|
|
50
|
-
candidates.push(join(root, (dirFlag ?? DEFAULT_DESIGN_DIR).replace(/[/\\]+$/, ""), "screens", file))
|
|
51
|
-
}
|
|
52
|
-
for (const base of candidates) {
|
|
53
|
-
if (existsSync(base) && statSync(base).isFile()) return base
|
|
54
|
-
for (const ext of SCREEN_EXTS) if (existsSync(base + ext)) return base + ext
|
|
55
|
-
}
|
|
56
|
-
throw new CliError(
|
|
57
|
-
`No screen file at "${file}".` +
|
|
58
|
-
(hasSeparator(file) ? "" : ` Pass a path, or a screen id that exists in ${dirFlag ?? DEFAULT_DESIGN_DIR}/screens/.`))
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/** The design folder a screen file belongs to ("<root>/design" for "/design/screens/login.ts"),
|
|
62
|
-
* or null when it isn't laid out as a design screen. */
|
|
63
|
-
const designDirOf = (root: string, key: string): { dir: string, id: string } | null => {
|
|
64
|
-
const m = /^\/(.*)screens\/([^/]+)\.[^./]+$/.exec(key)
|
|
65
|
-
if (!m) return null
|
|
66
|
-
const dir = join(root, m[1])
|
|
67
|
-
return existsSync(join(dir, "meta.json")) ? { dir, id: m[2] } : null
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Resolve `<file>` into the virtual entry that opens its default export.
|
|
72
|
-
* `state` picks the branch of a `(state) => UIScreen` screen (ignored by a value export).
|
|
73
|
-
*/
|
|
74
|
-
const resolveScreenTarget = (
|
|
75
|
-
root: string, file: string, opts: { state?: string, dir?: string } = {},
|
|
76
|
-
): ScreenTarget => {
|
|
77
|
-
const abs = findScreenFile(root, file, opts.dir)
|
|
78
|
-
const rel = relative(root, abs)
|
|
79
|
-
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
80
|
-
throw new CliError(
|
|
81
|
-
`"${file}" is outside the project (${root}) — a screen renders as part of its project, so its ` +
|
|
82
|
-
`imports and asset() files resolve from the same tree.`)
|
|
83
|
-
}
|
|
84
|
-
const key = toKey(rel)
|
|
85
|
-
|
|
86
|
-
// A file with no default export compiles to an empty render; say so here instead.
|
|
87
|
-
if (!/^\s*export\s+default\b/m.test(readFileSync(abs, "utf8"))) {
|
|
88
|
-
throw new CliError(
|
|
89
|
-
`${key.slice(1)} has no default export. A screen file ends with ` +
|
|
90
|
-
`\`export default UIScreen([...])\` — or \`export default (state) => UIScreen([...])\` for screen states.`)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Same wrapper the design board compiles (designCompile.ts): a function export is invoked with the
|
|
94
|
-
// chosen state (a bare call uses the parameter's default = the canonical state), a value is used
|
|
95
|
-
// as-is, and either way the screen is opened so the runtime has something to render.
|
|
96
|
-
const invoke = opts.state !== undefined ? `screen(${JSON.stringify(opts.state)})` : "screen()"
|
|
97
|
-
const spec = "." + key.replace(/\.[^./]+$/, "")
|
|
98
|
-
const design = designDirOf(root, key)
|
|
99
|
-
return {
|
|
100
|
-
entryPath: SCREEN_ENTRY_PATH,
|
|
101
|
-
entry: {
|
|
102
|
-
path: SCREEN_ENTRY_PATH,
|
|
103
|
-
type: "text",
|
|
104
|
-
text: `import screen from ${JSON.stringify(spec)}\n`
|
|
105
|
-
+ `const __screen = typeof screen === "function" ? ${invoke} : screen\n`
|
|
106
|
-
+ `__screen.open()\n`,
|
|
107
|
-
},
|
|
108
|
-
frame: design ? screenFrame(design.dir, design.id) : undefined,
|
|
109
|
-
label: (design ? design.id : key.slice(1)) + (opts.state !== undefined ? `@${opts.state}` : ""),
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* flag combinations that would fight over the entrypoint. */
|
|
115
|
-
export
|
|
116
|
-
|
|
117
|
-
if (file === undefined) {
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
throw new CliError("Use either a screen file or --entry, not both — each names the module to compile from.")
|
|
125
|
-
}
|
|
126
|
-
return resolveScreenTarget(root, file, { state: flagStr(args, "state"), dir: flagStr(args, "dir") })
|
|
127
|
-
}
|
|
1
|
+
import { existsSync, readFileSync, statSync } from "node:fs"
|
|
2
|
+
import { isAbsolute, join, relative, resolve } from "node:path"
|
|
3
|
+
import { screenFrame } from "../project/designMeta"
|
|
4
|
+
import { CliError } from "../cli"
|
|
5
|
+
import { toKey } from "../project/paths"
|
|
6
|
+
import type { CompileEntry } from "./projectCompile"
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Rendering ONE screen module instead of the whole app — `lecodes render <file>` (and
|
|
10
|
+
* `--desktop`). A design screen (`design/screens/login.ts`) never boots itself: it default-exports
|
|
11
|
+
* a `UIScreen`, or a `(state) => UIScreen` function for its states, and the design board / snapshot
|
|
12
|
+
* supply the `.open()`. This builds the same virtual entry for the normal project pipeline, so any
|
|
13
|
+
* file written that way — inside design/ or not — renders with the full `lecodes render` flag set
|
|
14
|
+
* (--png/--clip/--script/--device/…) against the project's real imports and assets.
|
|
15
|
+
*
|
|
16
|
+
* Kept in step with compile/designCompile.ts, which does the same wrapping per screen for the board.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** Extensions a screen module may carry (so `render design/screens/login` works too). */
|
|
20
|
+
const SCREEN_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs"]
|
|
21
|
+
|
|
22
|
+
/** Where the generated entry lives — the project root, so its import specifier is the screen's
|
|
23
|
+
* own project key ("./design/screens/login"). Leading dot: never a real project file. */
|
|
24
|
+
const SCREEN_ENTRY_PATH = "/.screen-entry.ts"
|
|
25
|
+
|
|
26
|
+
/** The design folder a bare screen id (`lecodes render login`) is looked up in. */
|
|
27
|
+
const DEFAULT_DESIGN_DIR = "design"
|
|
28
|
+
|
|
29
|
+
export type ScreenTarget = {
|
|
30
|
+
/** The virtual entry module — hand it to the compiler alongside the project's own entries. */
|
|
31
|
+
entry: CompileEntry
|
|
32
|
+
/** Path of that entry, for `entryOverride`. */
|
|
33
|
+
entryPath: string
|
|
34
|
+
/** The board frame from the design folder's meta.json, when this IS a design screen. */
|
|
35
|
+
frame?: [number, number]
|
|
36
|
+
/** How the screen is named in progress notes ("design/screens/login.ts", "login@empty"). */
|
|
37
|
+
label: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** `lecodes render <file|screen-id>` — the positional a screen render is asked for by. */
|
|
41
|
+
|
|
42
|
+
/** Whether the argument names a path at all (vs a bare screen id). */
|
|
43
|
+
const hasSeparator = (file: string) => file.includes("/") || file.includes("\\")
|
|
44
|
+
|
|
45
|
+
/** Find the screen file: a path (with or without extension), or a bare id resolved against the
|
|
46
|
+
* design folder's screens/ (`lecodes render login`, honoring --dir). */
|
|
47
|
+
const findScreenFile = (root: string, file: string, dirFlag: string | undefined): string => {
|
|
48
|
+
const candidates = [resolve(process.cwd(), file)]
|
|
49
|
+
if (!hasSeparator(file)) {
|
|
50
|
+
candidates.push(join(root, (dirFlag ?? DEFAULT_DESIGN_DIR).replace(/[/\\]+$/, ""), "screens", file))
|
|
51
|
+
}
|
|
52
|
+
for (const base of candidates) {
|
|
53
|
+
if (existsSync(base) && statSync(base).isFile()) return base
|
|
54
|
+
for (const ext of SCREEN_EXTS) if (existsSync(base + ext)) return base + ext
|
|
55
|
+
}
|
|
56
|
+
throw new CliError(
|
|
57
|
+
`No screen file at "${file}".` +
|
|
58
|
+
(hasSeparator(file) ? "" : ` Pass a path, or a screen id that exists in ${dirFlag ?? DEFAULT_DESIGN_DIR}/screens/.`))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** The design folder a screen file belongs to ("<root>/design" for "/design/screens/login.ts"),
|
|
62
|
+
* or null when it isn't laid out as a design screen. */
|
|
63
|
+
const designDirOf = (root: string, key: string): { dir: string, id: string } | null => {
|
|
64
|
+
const m = /^\/(.*)screens\/([^/]+)\.[^./]+$/.exec(key)
|
|
65
|
+
if (!m) return null
|
|
66
|
+
const dir = join(root, m[1])
|
|
67
|
+
return existsSync(join(dir, "meta.json")) ? { dir, id: m[2] } : null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Resolve `<file>` into the virtual entry that opens its default export.
|
|
72
|
+
* `state` picks the branch of a `(state) => UIScreen` screen (ignored by a value export).
|
|
73
|
+
*/
|
|
74
|
+
const resolveScreenTarget = (
|
|
75
|
+
root: string, file: string, opts: { state?: string, dir?: string } = {},
|
|
76
|
+
): ScreenTarget => {
|
|
77
|
+
const abs = findScreenFile(root, file, opts.dir)
|
|
78
|
+
const rel = relative(root, abs)
|
|
79
|
+
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
80
|
+
throw new CliError(
|
|
81
|
+
`"${file}" is outside the project (${root}) — a screen renders as part of its project, so its ` +
|
|
82
|
+
`imports and asset() files resolve from the same tree.`)
|
|
83
|
+
}
|
|
84
|
+
const key = toKey(rel)
|
|
85
|
+
|
|
86
|
+
// A file with no default export compiles to an empty render; say so here instead.
|
|
87
|
+
if (!/^\s*export\s+default\b/m.test(readFileSync(abs, "utf8"))) {
|
|
88
|
+
throw new CliError(
|
|
89
|
+
`${key.slice(1)} has no default export. A screen file ends with ` +
|
|
90
|
+
`\`export default UIScreen([...])\` — or \`export default (state) => UIScreen([...])\` for screen states.`)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Same wrapper the design board compiles (designCompile.ts): a function export is invoked with the
|
|
94
|
+
// chosen state (a bare call uses the parameter's default = the canonical state), a value is used
|
|
95
|
+
// as-is, and either way the screen is opened so the runtime has something to render.
|
|
96
|
+
const invoke = opts.state !== undefined ? `screen(${JSON.stringify(opts.state)})` : "screen()"
|
|
97
|
+
const spec = "." + key.replace(/\.[^./]+$/, "")
|
|
98
|
+
const design = designDirOf(root, key)
|
|
99
|
+
return {
|
|
100
|
+
entryPath: SCREEN_ENTRY_PATH,
|
|
101
|
+
entry: {
|
|
102
|
+
path: SCREEN_ENTRY_PATH,
|
|
103
|
+
type: "text",
|
|
104
|
+
text: `import screen from ${JSON.stringify(spec)}\n`
|
|
105
|
+
+ `const __screen = typeof screen === "function" ? ${invoke} : screen\n`
|
|
106
|
+
+ `__screen.open()\n`,
|
|
107
|
+
},
|
|
108
|
+
frame: design ? screenFrame(design.dir, design.id) : undefined,
|
|
109
|
+
label: (design ? design.id : key.slice(1)) + (opts.state !== undefined ? `@${opts.state}` : ""),
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** The screen target named on the command line (`render <file>`), or undefined when no screen was
|
|
114
|
+
* named. Rejects the flag combinations that would fight over the entrypoint. */
|
|
115
|
+
export type ScreenArgs = { file?: string, state?: string, entry?: string, dir?: string }
|
|
116
|
+
export const screenTargetFrom = (root: string, a: ScreenArgs): ScreenTarget | undefined => {
|
|
117
|
+
if (a.file === undefined) {
|
|
118
|
+
if (a.state !== undefined) throw new CliError("--state picks a screen's state — name the screen file too: lecodes render <file> --state <name>")
|
|
119
|
+
return undefined
|
|
120
|
+
}
|
|
121
|
+
if (a.entry !== undefined) throw new CliError("Use either a screen file or --entry, not both — each names the module to compile from.")
|
|
122
|
+
return resolveScreenTarget(root, a.file, { state: a.state, dir: a.dir })
|
|
123
|
+
}
|
package/src/compile/shaders.ts
CHANGED
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
matcArgs, MATC_PLATFORMS, TARGET_MATRIX_GENERATION,
|
|
9
9
|
type AnyMatcPlatform, type AnyShaderPlatform,
|
|
10
10
|
} from "lecodes-sdk/compile"
|
|
11
|
-
import { resolveMatcExe, resolveMatcExeCached } from "../matcTool"
|
|
12
|
-
import { LECODES_DIR } from "../manifest"
|
|
13
|
-
import { CliError } from "../
|
|
11
|
+
import { resolveMatcExe, resolveMatcExeCached } from "../hosts/matcTool"
|
|
12
|
+
import { LECODES_DIR } from "../project/manifest"
|
|
13
|
+
import { CliError } from "../cli"
|
|
14
14
|
import type { CompileEntry } from "./projectCompile"
|
|
15
15
|
|
|
16
16
|
/*
|
package/src/dev/androidDev.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, writeFileSync } from "node:fs"
|
|
2
2
|
import { join } from "node:path"
|
|
3
3
|
import { spawnSync } from "node:child_process"
|
|
4
|
-
import { CliError, note, warnErr } from "../
|
|
4
|
+
import { CliError, note, warnErr } from "../cli"
|
|
5
5
|
|
|
6
6
|
/*
|
|
7
7
|
* `lecodes dev --android` — open the dev URL in the LeCodes app on the connected phone, through adb.
|
package/src/dev/devServer.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createServer, type IncomingMessage, type Server, type ServerResponse } from "node:http"
|
|
2
2
|
import { createReadStream, statSync } from "node:fs"
|
|
3
3
|
import { join } from "node:path"
|
|
4
|
-
import type { Manifest } from "../manifest"
|
|
5
|
-
import { resolveLocalPath } from "../localFiles"
|
|
4
|
+
import type { Manifest } from "../project/manifest"
|
|
5
|
+
import { resolveLocalPath } from "../project/localFiles"
|
|
6
6
|
import { collectLocalEntries } from "../compile/collectLocal"
|
|
7
7
|
import { applyLocalShaders, isShaderArtifactName, shadersCacheDir } from "../compile/shaders"
|
|
8
8
|
import { ambiguousEntryWarning, compileProject } from "../compile/projectCompile"
|
|
@@ -10,7 +10,7 @@ import { applyProjectFonts } from "../compile/fonts"
|
|
|
10
10
|
import { applyAppAssetIcons } from "../compile/assetIcons"
|
|
11
11
|
import { renderDevScreen, renderPrelude } from "./clientTemplates"
|
|
12
12
|
import { upgradeWebSocket, type WsConnection } from "./wsServer"
|
|
13
|
-
import { toKey } from "../
|
|
13
|
+
import { toKey } from "../project/paths"
|
|
14
14
|
import { makeStackDemangler } from "../compile/nativeStack"
|
|
15
15
|
|
|
16
16
|
/*
|
package/src/dev/webRunner.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs"
|
|
2
2
|
import { createRequire } from "node:module"
|
|
3
3
|
import { dirname, join } from "node:path"
|
|
4
|
-
import { distRoot } from "../distRoot"
|
|
4
|
+
import { distRoot } from "../hosts/distRoot"
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Where the browser runner for `lecodes dev --web` lives: viewer-lite's built `dist-embed`
|
|
@@ -2,7 +2,7 @@ import { existsSync, readdirSync } from "node:fs"
|
|
|
2
2
|
import { homedir } from "node:os"
|
|
3
3
|
import { join, resolve } from "node:path"
|
|
4
4
|
import { downloadReleaseArchive, fetchReleaseProduct, newestForPlatform, semverNewer, type ManifestFile, type ManifestVersion } from "./releases"
|
|
5
|
-
import { CliError, note } from "
|
|
5
|
+
import { CliError, note } from "../cli"
|
|
6
6
|
|
|
7
7
|
/*
|
|
8
8
|
* Filament's cmgen (environment tool) — the tool behind `lecodes assets sky`, which turns an
|
|
@@ -3,8 +3,8 @@ import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFile
|
|
|
3
3
|
import { homedir, tmpdir } from "node:os"
|
|
4
4
|
import { delimiter, join, resolve } from "node:path"
|
|
5
5
|
import { cachedArtifactSha, downloadReleaseArchive, fetchReleaseProduct, semverNewer, type ManifestVersion } from "./releases"
|
|
6
|
-
import { CliError, note, warnErr } from "
|
|
7
|
-
import { makeStackDemangler } from "
|
|
6
|
+
import { CliError, note, warnErr } from "../cli"
|
|
7
|
+
import { makeStackDemangler } from "../compile/nativeStack"
|
|
8
8
|
|
|
9
9
|
/*
|
|
10
10
|
* The NATIVE renderer behind `lecodes render --desktop`: the LeCodes Desktop host (tgfx UI + Filament
|
|
@@ -38,9 +38,10 @@ export const DESKTOP_RENDERER_VERSION = "1.1.0"
|
|
|
38
38
|
export { semverNewer }
|
|
39
39
|
|
|
40
40
|
/** Which desktop host to run. "gl" is the default everywhere; "vulkan" is a separate Windows binary
|
|
41
|
-
* (Filament + tgfx on one VkDevice), NOT a runtime switch — it has its own artifact, its
|
|
42
|
-
* shaders, and a smaller feature set (no
|
|
43
|
-
* app.json `desktop.renderer`, or per run via `--renderer` /
|
|
41
|
+
* (Filament + tgfx + creator-2d on one VkDevice), NOT a runtime switch — it has its own artifact, its
|
|
42
|
+
* own shaders, and a smaller feature set (no native-view plugins; the 2D engine joined it 2026-09-08,
|
|
43
|
+
* i.e. desktop releases after 1.4.1). Chosen per project via app.json `desktop.renderer`, or per run via `--renderer` /
|
|
44
|
+
* LECODES_DESKTOP_RENDERER. */
|
|
44
45
|
export type DesktopRenderer = "gl" | "vulkan"
|
|
45
46
|
|
|
46
47
|
export const DESKTOP_RENDERER_MIN_VERSION: Record<DesktopRenderer, string> = { gl: "0.0.0", vulkan: "1.4.0" }
|
|
@@ -5,16 +5,20 @@ import { fileURLToPath } from "node:url"
|
|
|
5
5
|
/* Root of the CLI's on-disk companion files (runtime/ with the vendored SDK source + type bundle).
|
|
6
6
|
*
|
|
7
7
|
* Two distribution shapes:
|
|
8
|
-
* - npm package
|
|
9
|
-
*
|
|
8
|
+
* - npm package: the bundle is dist/index.js, companions at ../runtime.
|
|
9
|
+
* - monorepo dev: this module runs from src/hosts/, so the package root is two levels up. The
|
|
10
|
+
* package.json marker matters here — runtime/ is gitignored and absent until vendor-runtime runs,
|
|
11
|
+
* and callers also resolve siblings from the root (../projects, ../creator-gl).
|
|
10
12
|
* - standalone binary (`bun build --compile`, see scripts/build-bin.ts): import.meta.url points into
|
|
11
13
|
* the virtual bunfs archive which does NOT exist on disk, so the companions ship in the release
|
|
12
14
|
* archive NEXT TO the executable and are resolved via process.execPath. */
|
|
13
15
|
export const distRoot = (() => {
|
|
16
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
14
17
|
const candidates = [
|
|
15
|
-
join(
|
|
16
|
-
|
|
18
|
+
join(here, ".."), // npm package: dist/..
|
|
19
|
+
join(here, "..", ".."), // monorepo dev: src/hosts/../..
|
|
20
|
+
dirname(process.execPath), // standalone binary: next to the exe
|
|
17
21
|
]
|
|
18
|
-
for (const c of candidates) if (existsSync(join(c, "runtime"))) return c
|
|
22
|
+
for (const c of candidates) if (existsSync(join(c, "runtime")) || existsSync(join(c, "package.json"))) return c
|
|
19
23
|
return candidates[0]
|
|
20
24
|
})()
|
|
@@ -2,7 +2,7 @@ import { existsSync, readdirSync } from "node:fs"
|
|
|
2
2
|
import { homedir } from "node:os"
|
|
3
3
|
import { join, resolve } from "node:path"
|
|
4
4
|
import { downloadReleaseArchive, fetchReleaseProduct, newestForPlatform, semverNewer, type ManifestFile, type ManifestVersion } from "./releases"
|
|
5
|
-
import { CliError, note } from "
|
|
5
|
+
import { CliError, note } from "../cli"
|
|
6
6
|
|
|
7
7
|
/*
|
|
8
8
|
* Filament's matc (material compiler) — the tool behind LOCAL shader compile: `lecodes dev`
|
|
@@ -2,9 +2,9 @@ import { spawnSync } from "node:child_process"
|
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
|
|
3
3
|
import { join } from "node:path"
|
|
4
4
|
import { pathToFileURL } from "node:url"
|
|
5
|
-
import pkg from "
|
|
5
|
+
import pkg from "../../package.json"
|
|
6
6
|
import { peerDirInPrefix, peersDir, peerVersionGlobal } from "./peers"
|
|
7
|
-
import { CliError, c, confirm, log, note } from "
|
|
7
|
+
import { CliError, c, confirm, log, note } from "../cli"
|
|
8
8
|
|
|
9
9
|
/*
|
|
10
10
|
* Peers install themselves on first use. `lecodes render` on a machine with only the CLI asks once,
|
|
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto"
|
|
|
2
2
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs"
|
|
3
3
|
import { join } from "node:path"
|
|
4
4
|
import { spawnSync } from "node:child_process"
|
|
5
|
-
import { CliError } from "
|
|
5
|
+
import { CliError } from "../cli"
|
|
6
6
|
|
|
7
7
|
/*
|
|
8
8
|
* The S3 release channel the CLI downloads native tools from: the manifest scripts/release/*
|