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.
- package/README.md +56 -57
- package/dist/index.js +11052 -7592
- package/package.json +14 -8
- package/runtime/materials/decal-relief.mat +12 -1
- package/runtime/materials/decal.mat +17 -3
- package/runtime/materials/lightmap.mat +117 -138
- package/runtime/materials/particles-quad.mat +6 -2
- package/runtime/materials/terrain-lightmap.mat +123 -0
- package/runtime/materials/terrain.mat +36 -55
- package/runtime/sdk-types.json +1 -1
- package/runtime/web/VERSION.json +5 -0
- package/runtime/web/assets/camera-5XOM8eHl.js +1 -0
- package/runtime/web/assets/creator-2d-D9WKYM6h.js +1 -0
- package/runtime/web/assets/creator-2d-ukvEmNEp.wasm +0 -0
- package/runtime/web/assets/creator-full-BBXzQlhq.js +1 -0
- package/runtime/web/assets/creator-full-D2dSDdDj.wasm +0 -0
- package/runtime/web/assets/creator-full.js-BYswGsqR.symbols +8124 -0
- package/runtime/web/assets/creator-ui-DIc92ion.wasm +0 -0
- package/runtime/web/assets/creator-ui-_1Z_AX2M.js +1 -0
- package/runtime/web/assets/geolocation-BjTKN9_P.js +1 -0
- package/runtime/web/assets/inspect-C7x78PNs.js +2 -0
- package/runtime/web/assets/map-CyBxOSV0.js +1 -0
- package/runtime/web/assets/map-XzoOFt0E.js +2 -0
- package/runtime/web/assets/mapImpl-bxvQ2h1Z.js +823 -0
- package/runtime/web/assets/maplibre-gl-worker-B7LXXUkR.js +8 -0
- package/runtime/web/assets/materials-uri4FvPE.bin +0 -0
- package/runtime/web/assets/materials-world-CQWt8TAm.bin +0 -0
- package/runtime/web/assets/qr-scanner-CK_cYoJR.js +1 -0
- package/runtime/web/assets/uberarchive-DLH-kBhM.bin +0 -0
- package/runtime/web/index.html +36 -0
- package/runtime/web/player.js +21 -0
- package/runtime/web-page/index.html +41 -0
- package/runtime/web-page/page.css +1 -0
- package/runtime/web-page/page.js +31 -0
- 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 +158 -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} +454 -43
- package/src/commands/{appDesktop.ts → app/desktop.ts} +64 -33
- package/src/commands/{appDesktopMac.ts → app/desktopMac.ts} +34 -27
- package/src/commands/{appIcon.ts → app/icon.ts} +11 -8
- package/src/commands/{app.ts → app/index.ts} +400 -290
- package/src/commands/{appShared.ts → app/shared.ts} +43 -44
- package/src/commands/{appTemplatesAndroid.ts → app/templates/android.ts} +72 -39
- package/src/commands/{appTemplatesGradlew.ts → app/templates/gradlew.ts} +1 -1
- package/src/commands/{appTemplates.ts → app/templates/ios.ts} +2 -2
- package/src/commands/assets.ts +23 -21
- package/src/commands/clone.ts +48 -51
- package/src/commands/compile.ts +76 -89
- 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 +94 -82
- package/src/commands/dev.ts +260 -182
- package/src/commands/diff.ts +39 -51
- package/src/commands/index.ts +64 -0
- package/src/commands/{init.ts → init/index.ts} +195 -191
- package/src/commands/{projectTemplates.ts → init/templates.ts} +64 -21
- package/src/commands/install.ts +80 -67
- package/src/commands/lightmap.ts +543 -252
- package/src/commands/link.ts +87 -94
- package/src/commands/login.ts +25 -23
- package/src/commands/navmesh.ts +169 -139
- package/src/commands/plugin.ts +46 -0
- 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 +176 -111
- package/src/commands/scene.ts +63 -55
- package/src/commands/serve.ts +58 -0
- package/src/commands/{shaders.ts → shaders/index.ts} +61 -42
- package/src/commands/{shadersNew.ts → shaders/new.ts} +3 -3
- package/src/commands/shared.ts +79 -0
- package/src/commands/status.ts +22 -26
- package/src/commands/test.ts +94 -63
- 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 +4 -4
- package/src/compile/headlessBundle.ts +16 -12
- package/src/compile/nativeStack.ts +1 -1
- package/src/compile/projectCompile.ts +12 -4
- package/src/compile/sceneCompile.ts +14 -26
- package/src/compile/screenEntry.ts +123 -127
- package/src/compile/shaders.ts +3 -3
- package/src/{lecodes-3d-editor.d.ts → declarations/lecodes-3d-editor.d.ts} +4 -0
- package/src/{lecodes-assets.d.ts → declarations/lecodes-assets.d.ts} +1 -1
- package/src/{lecodes-renderer.d.ts → declarations/lecodes-headless.d.ts} +3 -3
- package/src/dev/androidDev.ts +1 -1
- package/src/dev/clientTemplates.ts +18 -14
- package/src/dev/devServer.ts +78 -41
- package/src/dev/iosDev.ts +180 -0
- package/src/dev/webRunner.ts +83 -15
- package/src/{cmgenTool.ts → hosts/cmgenTool.ts} +2 -2
- package/src/{desktopRenderer.ts → hosts/desktopRenderer.ts} +104 -32
- package/src/{desktopScript.ts → hosts/desktopScript.ts} +151 -36
- package/src/{distRoot.ts → hosts/distRoot.ts} +9 -5
- package/src/{matcTool.ts → hosts/matcTool.ts} +2 -2
- package/src/{peerInstall.ts → hosts/peerInstall.ts} +7 -7
- package/src/{peers.ts → hosts/peers.ts} +2 -2
- package/src/{releases.ts → hosts/releases.ts} +1 -1
- package/src/index.ts +35 -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/plugin/contract.ts +438 -0
- package/src/plugin/emitKotlin.ts +357 -0
- package/src/plugin/emitSdk.ts +259 -0
- package/src/plugin/emitSwift.ts +336 -0
- package/src/plugin/emitWeb.ts +383 -0
- package/src/plugin/generate.ts +157 -0
- package/src/plugin/lines.ts +28 -0
- package/src/plugin/lower.ts +231 -0
- package/src/plugin/manifest.ts +192 -0
- package/src/{projectEnv.ts → project/env.ts} +33 -2
- package/src/{ignore.ts → project/ignore.ts} +164 -163
- 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/materials/lightmap-baked-lite.mat +0 -175
- package/runtime/materials/lightmap-baked.mat +0 -176
- package/runtime/scene-harness.json +0 -1
- package/runtime/web/assets/__vite-browser-external-BIHI7g3E.js +0 -1
- package/runtime/web/assets/basis-C64VHDVD.js +0 -1
- package/runtime/web/assets/basis_transcoder-VXdx5NbI.wasm +0 -0
- package/runtime/web/assets/createViewerLite-Ct_PZdof.js +0 -852
- package/runtime/web/assets/draco-BiISTFcR.js +0 -118
- package/runtime/web/assets/draco_decoder-DsQ12WqX.wasm +0 -0
- package/runtime/web/assets/index-BMt7AnC5.js +0 -2
- package/runtime/web/assets/mapViewImpl-B2JcES8l.js +0 -810
- package/runtime/web/assets/maplibre-gl-worker-CJfwIrte.js +0 -8
- package/runtime/web/assets/worker-Caf-yYEI.js +0 -2
- package/runtime/web/embed.html +0 -32
- package/runtime/web/embed.js +0 -171
- package/src/commands/design.ts +0 -846
- package/src/commands/update.ts +0 -211
- package/src/util.ts +0 -146
- /package/src/{lecodes-design.d.ts → declarations/lecodes-design.d.ts} +0 -0
- /package/src/{qrcode-terminal.d.ts → declarations/qrcode-terminal.d.ts} +0 -0
- /package/src/{designMeta.ts → project/designMeta.ts} +0 -0
package/src/commands/compile.ts
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
import { writeFileSync } from "node:fs"
|
|
2
2
|
import { basename, resolve } from "node:path"
|
|
3
|
-
import { getProject } from "../api"
|
|
4
|
-
import {
|
|
5
|
-
import { findProjectRoot, readManifest, type Manifest } from "../manifest"
|
|
3
|
+
import { getProject } from "../platform/api"
|
|
4
|
+
import { findProjectRoot, readManifest, type Manifest } from "../project/manifest"
|
|
6
5
|
import { collectEntries } from "../compile/collect"
|
|
7
6
|
import { collectLocalEntries } from "../compile/collectLocal"
|
|
8
|
-
import { ambiguousEntryWarning, compileProject, type CompileEntry } from "../compile/projectCompile"
|
|
7
|
+
import { ambiguousEntryWarning, compileProject, localAssetNames, type CompileEntry } from "../compile/projectCompile"
|
|
9
8
|
import { applyProjectFonts } from "../compile/fonts"
|
|
10
9
|
import { applyLocalShaders, desktopShaderPlatform, type StagedShader } from "../compile/shaders"
|
|
11
|
-
import type { DesktopRenderer } from "../desktopRenderer"
|
|
10
|
+
import type { DesktopRenderer } from "../hosts/desktopRenderer"
|
|
12
11
|
import { applyAppAssetIcons } from "../compile/assetIcons"
|
|
13
|
-
import { buildGlobMatcher } from "../ignore"
|
|
14
|
-
import { readAppConfigAt } from "./
|
|
15
|
-
import {
|
|
12
|
+
import { buildGlobMatcher } from "../project/ignore"
|
|
13
|
+
import { readAppConfigAt } from "./app/shared"
|
|
14
|
+
import { defineCommand, isNullSink, note, warnErr } from "../cli"
|
|
15
|
+
import { bundleFlags, bundleOptions, outFlag, session, type BundleOptions } from "./shared"
|
|
16
16
|
|
|
17
17
|
/*
|
|
18
|
-
* `lecodes compile` —
|
|
19
|
-
*
|
|
20
|
-
* `lecodes preview` is the legacy alias for this command (see `previewLegacy` below).
|
|
18
|
+
* `lecodes compile` — the local project as one JS bundle (the server's pipeline), printed to stdout
|
|
19
|
+
* or written with -o. Diagnostics go to stderr, so `lecodes compile > app.js` stays clean.
|
|
21
20
|
*
|
|
22
21
|
* Two modes, picked automatically:
|
|
23
22
|
* - Server-backed project (a cloned/created one with .lecodes/manifest.json): code/.svg/scene
|
|
@@ -34,14 +33,14 @@ import { flagBool, flagStr, isNullSink, note, warnErr, type Args } from "../util
|
|
|
34
33
|
* `lecodes render` has. `--remote-assets` (or an explicit `--public-url`) opts back into server
|
|
35
34
|
* URLs; app.json `resources.remote` matches stay URLs either way (they stream in the built app too).
|
|
36
35
|
*
|
|
37
|
-
* A third mode exists for `lecodes app sync` only (
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
36
|
+
* A third mode exists for `lecodes app sync` only (`compileShell`): compile for a native shell that
|
|
37
|
+
* ships its assets inside the app. Resources resolve locally (`id:` + fetchLocal) in BOTH project
|
|
38
|
+
* modes, fonts vendor into assets/fonts/ (never CDN — text must render offline, before any
|
|
39
|
+
* network), and resources matching `shell.remotePatterns` keep their server URL for streaming.
|
|
40
|
+
* Returns every resource entry so the caller can copy the bundled ones into the shell.
|
|
42
41
|
*/
|
|
43
42
|
|
|
44
|
-
/** One project resource as the
|
|
43
|
+
/** One project resource as the compile resolved it (returned to `lecodes app sync`). */
|
|
45
44
|
export type BundleResource = {
|
|
46
45
|
/** Root-relative project path. */
|
|
47
46
|
path: string
|
|
@@ -60,14 +59,6 @@ export type BundleResource = {
|
|
|
60
59
|
/** Shell-compile options (see the mode note above) — only `lecodes app sync` passes this. */
|
|
61
60
|
export type ShellCompile = { remotePatterns: string[] }
|
|
62
61
|
|
|
63
|
-
/** The `lecodes compile` command. */
|
|
64
|
-
export const compile = async (args: Args): Promise<void> => { await compileImpl(args) }
|
|
65
|
-
|
|
66
|
-
/** `lecodes app sync`'s entry: shell mode (see above), returning the resource inventory. */
|
|
67
|
-
export const compileShell = (args: Args, shell: ShellCompile): Promise<BundleResource[]> => compileImpl(args, shell)
|
|
68
|
-
|
|
69
|
-
/** The compiled project without any output handling — `lecodes render --desktop` runs this bundle in
|
|
70
|
-
* the native desktop host, copying the local-asset resources next to it (fetchLocal by basename). */
|
|
71
62
|
export type BuiltBundle = { js: string, resources: BundleResource[] }
|
|
72
63
|
|
|
73
64
|
/** Extra knobs for the desktop-host callers (see the mode note above). */
|
|
@@ -81,32 +72,46 @@ export type BuildBundleOptions = {
|
|
|
81
72
|
/** The desktop renderer this bundle is being built FOR, when the caller knows (it stages or spawns
|
|
82
73
|
* the very exe that will run it). Narrows the shader compile + staging to the one artifact that
|
|
83
74
|
* host asks for, instead of shipping every native variant. Leave unset when the target is unknown
|
|
84
|
-
* — a generic
|
|
75
|
+
* — a generic bundle can be carried anywhere. */
|
|
85
76
|
desktopRenderer?: DesktopRenderer
|
|
86
77
|
/** Synthetic in-memory entries added to the project's own (a virtual entry module, say — see
|
|
87
78
|
* `lecodes lightmap bake`). Paths use the entry convention ("/.name.ts" at the root). */
|
|
88
79
|
extraEntries?: CompileEntry[]
|
|
89
|
-
/** Compile from this entry instead of the detected one /
|
|
80
|
+
/** Compile from this entry instead of the detected one / `entry` (pairs with `extraEntries`). */
|
|
90
81
|
entryOverride?: string
|
|
82
|
+
/** Shell mode (`lecodes app sync`) — see above. */
|
|
83
|
+
shell?: ShellCompile
|
|
91
84
|
}
|
|
92
85
|
|
|
93
|
-
|
|
94
|
-
|
|
86
|
+
export default defineCommand({
|
|
87
|
+
name: "compile",
|
|
88
|
+
summary: "Compile the local project to one JS bundle (stdout, or -o <file>)",
|
|
89
|
+
description: "Works on a cloned / created project (binary asset URLs resolved from the server) or a local `init` project (no login — asset() resources resolve on the host via fetchLocal, so the bundle is self-contained for LeCodes Desktop). Diagnostics go to stderr; the bundle is the only thing on stdout.",
|
|
90
|
+
aliases: ["preview"],
|
|
91
|
+
flags: { ...outFlag, ...bundleFlags },
|
|
92
|
+
examples: ["lecodes compile -o app.js", "lecodes compile --no-minify > app.js"],
|
|
93
|
+
run: async ({ flags }) => {
|
|
94
|
+
const { js } = await buildBundle(bundleOptions(flags))
|
|
95
|
+
writeBundle(js, flags.out)
|
|
96
|
+
},
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
/** Print or write a bundle (`-o /dev/null` discards it). */
|
|
100
|
+
export const writeBundle = (js: string, out: string | undefined): void => {
|
|
101
|
+
if (out && isNullSink(out)) note(`Discarded output (${out})`)
|
|
102
|
+
else if (out) { writeFileSync(resolve(out), js); note(`Wrote ${out} (${js.length} bytes)`) }
|
|
103
|
+
else { process.stdout.write(js); if (!js.endsWith("\n")) process.stdout.write("\n") }
|
|
104
|
+
}
|
|
95
105
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
writeFileSync(resolve(out), js)
|
|
101
|
-
note(`Wrote ${out} (${js.length} bytes)`)
|
|
102
|
-
} else {
|
|
103
|
-
process.stdout.write(js)
|
|
104
|
-
if (!js.endsWith("\n")) process.stdout.write("\n")
|
|
105
|
-
}
|
|
106
|
+
/** `lecodes app sync`'s entry: shell mode (see above), the bundle written to `out`, the resource inventory returned. */
|
|
107
|
+
export const compileShell = async (out: string, shell: ShellCompile): Promise<BundleResource[]> => {
|
|
108
|
+
const { js, resources } = await buildBundle({}, { shell })
|
|
109
|
+
writeBundle(js, out)
|
|
106
110
|
return resources
|
|
107
111
|
}
|
|
108
112
|
|
|
109
|
-
export const buildBundle = async (
|
|
113
|
+
export const buildBundle = async (bundle: BundleOptions, opts: BuildBundleOptions = {}): Promise<BuiltBundle> => {
|
|
114
|
+
const shell = opts.shell
|
|
110
115
|
let root: string
|
|
111
116
|
let manifest: Manifest | null
|
|
112
117
|
try {
|
|
@@ -124,21 +129,19 @@ export const buildBundle = async (args: Args, shell?: ShellCompile, opts: BuildB
|
|
|
124
129
|
let localAssets = false
|
|
125
130
|
|
|
126
131
|
if (manifest) {
|
|
127
|
-
const
|
|
128
|
-
const apiUrl = requireApiUrl(config)
|
|
129
|
-
const token = requireToken(config)
|
|
130
|
-
|
|
131
|
-
const publicUrlFlag = flagStr(args, "public-url")
|
|
132
|
+
const { apiUrl, token } = session()
|
|
132
133
|
// Shell compiles always bundle; a desktop-host run reads the tree unless told to use the server.
|
|
133
|
-
localAssets = !!shell || (!!opts.localAssets &&
|
|
134
|
+
localAssets = !!shell || (!!opts.localAssets && bundle.publicUrl === undefined && !bundle.remoteAssets)
|
|
134
135
|
|
|
135
136
|
note("Resolving project assets…")
|
|
137
|
+
const tResolve = performance.now()
|
|
136
138
|
const project = await getProject(apiUrl, token, manifest.uuid)
|
|
137
139
|
// Local-asset compiles use URL-less resources as-is instead of degrading, so skip that warning
|
|
138
140
|
// there (an unpushed resources.remote match still warns below).
|
|
139
141
|
;({ entries, warnings } = collectEntries(root, manifest, project, { warnMissingUrl: !localAssets }))
|
|
140
142
|
name = manifest.name
|
|
141
|
-
publicUrl =
|
|
143
|
+
publicUrl = bundle.publicUrl ?? apiUrl
|
|
144
|
+
note(`Resolved ${entries.length} entries in ${((performance.now() - tResolve) / 1000).toFixed(1)} s`)
|
|
142
145
|
|
|
143
146
|
// Local-asset compile: everything resolves from the tree except the resources.remote matches,
|
|
144
147
|
// which keep their server URL — and can't without one, so an unpushed match falls back to local.
|
|
@@ -155,20 +158,17 @@ export const buildBundle = async (args: Args, shell?: ShellCompile, opts: BuildB
|
|
|
155
158
|
// Local project (no server): compile from the tree. Without an explicit --public-url the assets
|
|
156
159
|
// resolve locally (host fetchLocal) so the bundle is self-contained for LeCodes Desktop.
|
|
157
160
|
// fileSrc stays a path (assetBase "") — compileProject prefixes publicUrl exactly once, same as
|
|
158
|
-
// the server/dev conventions.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (opts.localAssets && flagBool(args, "remote-assets")) {
|
|
163
|
-
warnErr("This is a local project (no server) — assets always load from the working tree.")
|
|
164
|
-
}
|
|
161
|
+
// the server/dev conventions.
|
|
162
|
+
localAssets = shell ? true : bundle.publicUrl === undefined
|
|
163
|
+
publicUrl = bundle.publicUrl ?? ""
|
|
164
|
+
if (opts.localAssets && bundle.remoteAssets) warnErr("This is a local project (no server) — assets always load from the working tree.")
|
|
165
165
|
// localShaders: a local-asset compile compiles the .mat files itself below, so the
|
|
166
166
|
// "push the project once" degradation notice would be wrong.
|
|
167
|
+
const tEntries = performance.now()
|
|
167
168
|
;({ entries, warnings } = collectLocalEntries(root, null, "", { localShaders: localAssets && (opts.localShaders ?? !shell) }))
|
|
169
|
+
note(`Collected ${entries.length} entries in ${((performance.now() - tEntries) / 1000).toFixed(1)} s`)
|
|
168
170
|
name = basename(root)
|
|
169
|
-
if (shell && shell.remotePatterns.length > 0)
|
|
170
|
-
warnErr("resources.remote needs a server-backed project (a streamed asset needs a server URL) — bundling everything.")
|
|
171
|
-
}
|
|
171
|
+
if (shell && shell.remotePatterns.length > 0) warnErr("resources.remote needs a server-backed project (a streamed asset needs a server URL) — bundling everything.")
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
// Custom shaders (.mat) for a host with no asset server: compile them locally (matc) and stage
|
|
@@ -181,9 +181,7 @@ export const buildBundle = async (args: Args, shell?: ShellCompile, opts: BuildB
|
|
|
181
181
|
// A caller that knows its target host (every desktop path) narrows this to the single artifact
|
|
182
182
|
// that host will fetch; otherwise every native variant is compiled and staged, since the
|
|
183
183
|
// runtime picks by `_creator.backend` and the bundle could be carried anywhere.
|
|
184
|
-
const platforms = opts.desktopRenderer
|
|
185
|
-
? [desktopShaderPlatform(process.platform, opts.desktopRenderer)]
|
|
186
|
-
: undefined
|
|
184
|
+
const platforms = opts.desktopRenderer ? [desktopShaderPlatform(process.platform, opts.desktopRenderer)] : undefined
|
|
187
185
|
const local = await applyLocalShaders(entries, { root, local: true, platforms })
|
|
188
186
|
warnings.push(...local.warnings)
|
|
189
187
|
stagedShaders = local.artifacts
|
|
@@ -193,6 +191,7 @@ export const buildBundle = async (args: Args, shell?: ShellCompile, opts: BuildB
|
|
|
193
191
|
// vendors faces into assets/fonts/ so the bundle stays self-contained (fetchLocal / --public-url).
|
|
194
192
|
// Shell compiles pass publicUrl "" here so the `// fonts:` header carries no face URLs — the
|
|
195
193
|
// host must register faces from the bundle, never wait on the network before first paint.
|
|
194
|
+
const tPrep = performance.now()
|
|
196
195
|
const fontsHeader = await applyProjectFonts(entries, (manifest && !localAssets)
|
|
197
196
|
? { mode: "cdn", root, publicUrl }
|
|
198
197
|
: {
|
|
@@ -205,49 +204,37 @@ export const buildBundle = async (args: Args, shell?: ShellCompile, opts: BuildB
|
|
|
205
204
|
// project. The returned pack list becomes the `// icons:` attribution header.
|
|
206
205
|
if (opts.extraEntries) entries.push(...opts.extraEntries)
|
|
207
206
|
const iconsHeader = await applyAppAssetIcons(entries)
|
|
207
|
+
note(`Prepared shaders, fonts and icons in ${((performance.now() - tPrep) / 1000).toFixed(1)} s`)
|
|
208
208
|
|
|
209
209
|
note("Compiling…")
|
|
210
|
-
const
|
|
211
|
-
|
|
210
|
+
const tCompile = performance.now()
|
|
211
|
+
const entryOverride = opts.entryOverride ?? bundle.entry
|
|
212
|
+
if (!entryOverride) {
|
|
212
213
|
const ambiguous = ambiguousEntryWarning(entries)
|
|
213
214
|
if (ambiguous) warnErr(ambiguous)
|
|
214
215
|
}
|
|
215
216
|
const js = await compileProject({
|
|
216
|
-
entries,
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
fontsHeader,
|
|
223
|
-
iconsHeader,
|
|
224
|
-
// Both default on; `false` only when the flag is present, so the SDK's own defaults stand.
|
|
225
|
-
minify: flagBool(args, "no-minify") ? false : undefined,
|
|
226
|
-
sourcemap: flagBool(args, "no-sourcemap", "no-source-map") ? false : undefined,
|
|
217
|
+
entries, name, publicUrl, entryOverride,
|
|
218
|
+
header: bundle.header ?? true,
|
|
219
|
+
localAssets, fontsHeader, iconsHeader,
|
|
220
|
+
minify: bundle.minify,
|
|
221
|
+
sourcemap: bundle.sourcemap,
|
|
222
|
+
onWarning: (w) => warnings.push(w),
|
|
227
223
|
})
|
|
224
|
+
note(`Compiled in ${((performance.now() - tCompile) / 1000).toFixed(1)} s (${(js.length / 1024).toFixed(0)} KB)`)
|
|
228
225
|
|
|
229
226
|
for (const w of warnings) warnErr(w)
|
|
230
227
|
|
|
231
228
|
// Resource inventory for shell/render callers (includes faces the font pass vendored into entries).
|
|
229
|
+
// The NAME is what the bundle passes to fetchLocal, so it has to come from where the bundle got
|
|
230
|
+
// it: a basename two project files share is disambiguated there, and a caller that re-derived the
|
|
231
|
+
// basename here would stage both packs' SM_Sign_01.glb onto one file again.
|
|
232
|
+
const localNames = localAssetNames(entries)
|
|
232
233
|
const resources: BundleResource[] = entries
|
|
233
234
|
.filter((e) => e.type === "resource")
|
|
234
|
-
.map((e) => ({
|
|
235
|
-
path: e.path.replace(/^\//, ""),
|
|
236
|
-
name: e.path.split(/[\\/]/).pop() ?? e.path,
|
|
237
|
-
absPath: e.absPath,
|
|
238
|
-
remote: !!e.remote,
|
|
239
|
-
}))
|
|
235
|
+
.map((e) => ({ path: e.path.replace(/^\//, ""), name: localNames.get(e.path) ?? e.path.split(/[\\/]/).pop() ?? e.path, absPath: e.absPath, remote: !!e.remote }))
|
|
240
236
|
// Compiled shader artifacts ship the same way (copied next to app.js, loaded by name), flagged
|
|
241
237
|
// so the desktop packager keeps them — they have no asset() reference for its scan to match.
|
|
242
|
-
for (const artifact of stagedShaders) {
|
|
243
|
-
resources.push({ path: artifact.name, name: artifact.name, absPath: artifact.absPath, remote: false, shader: true })
|
|
244
|
-
}
|
|
238
|
+
for (const artifact of stagedShaders) resources.push({ path: artifact.name, name: artifact.name, absPath: artifact.absPath, remote: false, shader: true })
|
|
245
239
|
return { js, resources }
|
|
246
240
|
}
|
|
247
|
-
|
|
248
|
-
/** `lecodes preview` — the command's former name, kept working for existing scripts. The deprecation
|
|
249
|
-
* goes to stderr, so a piped `lecodes preview > app.js` still yields a clean bundle. */
|
|
250
|
-
export const previewLegacy = async (args: Args) => {
|
|
251
|
-
warnErr("'lecodes preview' is now 'lecodes compile' — the old name still works.")
|
|
252
|
-
await compile(args)
|
|
253
|
-
}
|
package/src/commands/create.ts
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs"
|
|
2
2
|
import { join, resolve } from "node:path"
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { appClaudeMd, CLAUDE_SETTINGS } from "./
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
/* `lecodes create <name> [dir]` —
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
|
|
15
|
-
const slug = (name: string) => name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "project"
|
|
3
|
+
import { CliError, UsageError, c, defineCommand, info, str, success } from "../cli"
|
|
4
|
+
import { createProject, getCommits } from "../platform/api"
|
|
5
|
+
import { writeDefaultIgnore } from "../project/ignore"
|
|
6
|
+
import { writeManifest } from "../project/manifest"
|
|
7
|
+
import { materializeTypes, writeTsconfig } from "../project/types"
|
|
8
|
+
import { appClaudeMd, CLAUDE_SETTINGS } from "./init/templates"
|
|
9
|
+
import { session, slugOf } from "./shared"
|
|
10
|
+
|
|
11
|
+
/* `lecodes create <name> [dir]` — a brand-new project on the server plus a local folder for it:
|
|
12
|
+
* the server's type definitions (IntelliSense matches the deployed runtime), a tsconfig, an ignore
|
|
13
|
+
* file and an import-free starter. Edit, then `lecodes push`. */
|
|
16
14
|
|
|
17
15
|
const STARTER = `// Welcome to le.codes — no imports needed, the whole SDK is available as globals.
|
|
18
16
|
const scene = new Scene2D({ background: '#10131a' })
|
|
@@ -23,37 +21,38 @@ setLoop((dt) => {
|
|
|
23
21
|
})
|
|
24
22
|
`
|
|
25
23
|
|
|
26
|
-
export
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
24
|
+
export default defineCommand({
|
|
25
|
+
name: "create",
|
|
26
|
+
summary: "Create a new project on the server and scaffold it locally",
|
|
27
|
+
usage: "<name> [dir]",
|
|
28
|
+
flags: { team: str("create it inside a team", { value: "<uuid>" }) },
|
|
29
|
+
run: async ({ args, flags }) => {
|
|
30
|
+
const { apiUrl, token } = session()
|
|
31
|
+
const name = args[0]
|
|
32
|
+
if (!name) throw new UsageError("a project name is required")
|
|
33
|
+
|
|
34
|
+
const dir = args[1] ?? slugOf(name)
|
|
35
|
+
const root = resolve(dir)
|
|
36
|
+
if (existsSync(root) && readdirSync(root).length > 0) throw new CliError(`Directory "${dir}" already exists and is not empty.`)
|
|
37
|
+
mkdirSync(root, { recursive: true })
|
|
38
|
+
|
|
39
|
+
info(c.dim(`Creating project ${c.bold(name)}…`))
|
|
40
|
+
const { uuid } = await createProject(apiUrl, token, name, flags.team)
|
|
41
|
+
|
|
42
|
+
info(c.dim("Fetching type definitions…"))
|
|
43
|
+
await materializeTypes(root, apiUrl)
|
|
44
|
+
writeTsconfig(root)
|
|
45
|
+
writeDefaultIgnore(root)
|
|
46
|
+
writeFileSync(join(root, "main.ts"), STARTER)
|
|
47
|
+
writeFileSync(join(root, "CLAUDE.md"), appClaudeMd(name))
|
|
48
|
+
mkdirSync(join(root, ".claude"), { recursive: true })
|
|
49
|
+
writeFileSync(join(root, ".claude", "settings.json"), CLAUDE_SETTINGS)
|
|
50
|
+
|
|
51
|
+
// A fresh project's tree is empty on the server; the local main.ts is a pending add for the first push.
|
|
52
|
+
const commits = await getCommits(apiUrl, token, uuid)
|
|
53
|
+
writeManifest(root, { uuid, apiUrl, name, baseHeadId: commits.headId, files: {} })
|
|
54
|
+
|
|
55
|
+
success(`Created ${c.bold(name)} in ${c.bold(dir)}/`)
|
|
56
|
+
info(c.dim(` cd ${dir} — edit main.ts, then \`lecodes push -m "first commit"\` to save it`))
|
|
57
|
+
},
|
|
58
|
+
})
|