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,12 +1,13 @@
|
|
|
1
1
|
import { execFileSync, spawn } from "node:child_process"
|
|
2
2
|
import { cpSync, existsSync, mkdirSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs"
|
|
3
3
|
import { basename, dirname, join, resolve } from "node:path"
|
|
4
|
-
import { buildBundle } from "
|
|
5
|
-
import { resolveDesktopExe, selectedDesktopVersion } from "
|
|
6
|
-
import { CliError,
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
4
|
+
import { buildBundle } from "../compile"
|
|
5
|
+
import { resolveDesktopExe, selectedDesktopVersion } from "../../hosts/desktopRenderer"
|
|
6
|
+
import { CliError, bool, c, defineCommand, log, note, num, str, success, warn, type FlagValues } from "../../cli"
|
|
7
|
+
import { bundleFlags, bundleOptions } from "../shared"
|
|
8
|
+
import { desktopPluginLibraries, projectRoot, readJson, resolveDesktopRenderer, writeJson, type AppConfig } from "./shared"
|
|
9
|
+
import { loadIconMaster } from "./icon"
|
|
10
|
+
import { buildMacApp, macHostProvidedNames } from "./desktopMac"
|
|
10
11
|
|
|
11
12
|
/*
|
|
12
13
|
* `lecodes app init|build desktop` — the desktop arm of the native-app commands
|
|
@@ -14,7 +15,8 @@ import { buildMacApp, macHostProvidedNames } from "./appDesktopMac"
|
|
|
14
15
|
* `build` stages the verified cached host + the compiled bundle + its assets into one portable
|
|
15
16
|
* folder that runs on a double-click. On macOS the same command produces a signed (and, with a
|
|
16
17
|
* notarytool profile, notarized) .app instead — the staging half is shared, the bundle half lives
|
|
17
|
-
* in
|
|
18
|
+
* in desktopMac.ts. The `build` node is defined here and mounted twice: `lecodes desktop build`
|
|
19
|
+
* (desktop.ts) and `lecodes app build desktop` (index.ts) are the same command.
|
|
18
20
|
*
|
|
19
21
|
* The staged folder is SELF-DESCRIBING: a pruned app.json (name + desktop.window) ships next to
|
|
20
22
|
* app.js, and the host (≥1.3.0) reads it for title/size/min-size/resizable/fullscreen — no
|
|
@@ -32,16 +34,19 @@ const dirSize = (dir: string): number =>
|
|
|
32
34
|
|
|
33
35
|
/* --------------------------------------- init ---------------------------------------- */
|
|
34
36
|
|
|
37
|
+
/** The `app init desktop` flags (index.ts declares the shared init node). */
|
|
38
|
+
export interface DesktopInitOptions { name?: string, fullscreen?: boolean }
|
|
39
|
+
|
|
35
40
|
/** `lecodes app init desktop` — declare the desktop target in app.json (mirrors
|
|
36
41
|
* `lecodes init --desktop` for existing projects). Purely additive; re-running keeps edits. */
|
|
37
|
-
export const initDesktop = async (
|
|
42
|
+
export const initDesktop = async (opts: DesktopInitOptions): Promise<void> => {
|
|
38
43
|
const root = projectRoot()
|
|
39
44
|
const existing = readJson<AppConfig>(join(root, "app.json")) ?? {}
|
|
40
|
-
const name =
|
|
45
|
+
const name = opts.name ?? existing.name ?? basename(root)
|
|
41
46
|
const window = {
|
|
42
47
|
width: 1280, height: 800, minWidth: 640, minHeight: 480,
|
|
43
48
|
...existing.desktop?.window,
|
|
44
|
-
...(
|
|
49
|
+
...(opts.fullscreen ? { fullscreen: true } : {}),
|
|
45
50
|
}
|
|
46
51
|
const config: AppConfig = { ...existing, name, desktop: { ...existing.desktop, window } }
|
|
47
52
|
writeJson(join(root, "app.json"), config)
|
|
@@ -60,12 +65,27 @@ const cleanFileName = (name: string) =>
|
|
|
60
65
|
const ASSETS_DIR = "assets" // the project's own files
|
|
61
66
|
const RUNTIME_DIR = "runtime" // the host's engine files (initial.js, built-in materials, IBL)
|
|
62
67
|
|
|
63
|
-
|
|
68
|
+
const desktopBuildFlags = {
|
|
69
|
+
out: str("output folder (default dist/<name>)", { alias: "o", value: "<dir>" }),
|
|
70
|
+
slug: str("folder / zip name override (Latin-only)", { value: "<name>" }),
|
|
71
|
+
renderer: str("host + shader variant: gl | vulkan (default: app.json desktop.renderer, else gl)", { value: "<gl|vulkan>" }),
|
|
72
|
+
probe: bool("headless-render the staged folder to a PNG next to it (macOS: a brief windowed run + snapshot)"),
|
|
73
|
+
frames: num("(--probe) frames to render before the snapshot", { default: 90 }),
|
|
74
|
+
after: num("(--probe, macOS) seconds the app runs before the snapshot", { default: 8 }),
|
|
75
|
+
zip: bool("also pack the result for sending: <out>.zip with UTF-8 / forward-slash entries (macOS: a ditto archive of the .app)"),
|
|
76
|
+
dmg: bool("macOS: also build a drag-to-Applications disk image (signed + notarized too)"),
|
|
77
|
+
sign: str("macOS codesign identity — a \"Developer ID Application: …\" cert, or adhoc (local only)", { value: "<identity|adhoc>" }),
|
|
78
|
+
notarize: str("macOS: notarize + staple with this `xcrun notarytool store-credentials` keychain profile", { value: "<profile>" }),
|
|
79
|
+
"no-notarize": bool("macOS: skip notarization even when app.json / the environment names a profile"),
|
|
80
|
+
...bundleFlags,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const buildDesktop = async (flags: FlagValues<typeof desktopBuildFlags>): Promise<void> => {
|
|
64
84
|
const root = projectRoot()
|
|
65
85
|
const config = readJson<AppConfig>(join(root, "app.json")) ?? {}
|
|
66
86
|
const name = (config.name ?? basename(root)).trim() || "app"
|
|
67
|
-
const slug =
|
|
68
|
-
const out = resolve(root,
|
|
87
|
+
const slug = flags.slug ?? cleanFileName(name)
|
|
88
|
+
const out = resolve(root, flags.out ?? join(root, "dist", slug))
|
|
69
89
|
|
|
70
90
|
// Only a previous build output (or an empty/absent dir) may be replaced — never wipe a
|
|
71
91
|
// directory this command didn't produce.
|
|
@@ -78,24 +98,21 @@ export const buildDesktop = async (args: Args) => {
|
|
|
78
98
|
}
|
|
79
99
|
|
|
80
100
|
// Per-target entry (app.json desktop.entry); an explicit --entry wins.
|
|
81
|
-
|
|
101
|
+
const bundle = bundleOptions(flags)
|
|
102
|
+
if (config.desktop?.entry && bundle.entry === undefined) bundle.entry = config.desktop.entry
|
|
82
103
|
|
|
83
104
|
// ONE renderer decision: it selects the host binary staged into the folder AND the single
|
|
84
105
|
// .filamat variant compiled beside the bundle. Two independent reads of the config is how a
|
|
85
106
|
// build ships a Vulkan exe next to an OpenGL shader (a Filament abort at the first material).
|
|
86
|
-
const renderer = resolveDesktopRenderer(root,
|
|
107
|
+
const renderer = resolveDesktopRenderer(root, flags.renderer)
|
|
87
108
|
|
|
88
109
|
const mac = process.platform === "darwin"
|
|
89
110
|
note(`Building "${name}" for ${mac ? "macOS" : "desktop"}${renderer === "vulkan" ? " (Vulkan)" : ""}…`)
|
|
90
|
-
const { js, resources } = await buildBundle(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
// The Vulkan host has no 2D engine — refuse now rather than shipping a folder that opens a blank
|
|
97
|
-
// window (see assertRendererSupportsBundle).
|
|
98
|
-
assertRendererSupportsBundle(renderer, js)
|
|
111
|
+
const { js, resources } = await buildBundle(bundle, {
|
|
112
|
+
shell: { remotePatterns: config.resources?.remote ?? [] },
|
|
113
|
+
localShaders: true,
|
|
114
|
+
desktopRenderer: renderer,
|
|
115
|
+
})
|
|
99
116
|
|
|
100
117
|
// Only what the bundle actually references ships — the compile inventory lists EVERY project
|
|
101
118
|
// resource (design/ references included), which would multiply the build size. asset() compiles
|
|
@@ -145,9 +162,14 @@ export const buildDesktop = async (args: Args) => {
|
|
|
145
162
|
throw new CliError(`The bundle references assets with no local file: ${missing.join(", ")}`)
|
|
146
163
|
}
|
|
147
164
|
|
|
148
|
-
// macOS: one signed .app rather than a folder — see
|
|
149
|
-
if (mac)
|
|
150
|
-
|
|
165
|
+
// macOS: one signed .app rather than a folder — see desktopMac.ts.
|
|
166
|
+
if (mac) {
|
|
167
|
+
return buildMacApp({
|
|
168
|
+
root, config, name, slug, out, js, shipped, hostExe: exe,
|
|
169
|
+
opts: { sign: flags.sign, notarize: flags.notarize, noNotarize: flags["no-notarize"], dmg: flags.dmg, zip: flags.zip, probe: flags.probe, after: flags.after },
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
if (flags.dmg) warn("--dmg is a macOS format — ignored on this platform.")
|
|
151
173
|
|
|
152
174
|
const version = process.env.LECODES_DESKTOP_EXE ? "local build" : selectedDesktopVersion()
|
|
153
175
|
|
|
@@ -236,11 +258,21 @@ export const buildDesktop = async (args: Args) => {
|
|
|
236
258
|
|
|
237
259
|
success(`Portable build: ${out} (${mb(dirSize(out))})`)
|
|
238
260
|
|
|
239
|
-
if (
|
|
240
|
-
if (
|
|
241
|
-
if (!
|
|
261
|
+
if (flags.probe) await probeBuild(out, exeName, config, flags.frames)
|
|
262
|
+
if (flags.zip) zipBuild(out)
|
|
263
|
+
if (!flags.probe) note(`Tip: --probe renders the staged folder headless to verify exactly what ships.`)
|
|
242
264
|
}
|
|
243
265
|
|
|
266
|
+
/** `lecodes desktop build` and `lecodes app build desktop` — the one node, mounted in both trees. */
|
|
267
|
+
export const desktopBuild = defineCommand({
|
|
268
|
+
name: "build",
|
|
269
|
+
summary: "Stage a portable desktop app folder (dist/<name>/): host exe + app.js + assets + runtime",
|
|
270
|
+
description: "The cached host renamed to <Name>.exe + app.js + assets/ (the project's files) + runtime/ (the engine's) + app.json (the host reads title/size/fullscreen from it) + app.ico from app.json \"icon\". Duplicate asset basenames are a build error (they silently alias in the bundle). Also spelled `lecodes app build desktop`.\n\nOn macOS: a signed .app instead (the downloaded LeCodes Desktop.app + the project inside it); app.json desktop.macos = bundleId / buildNumber / category / signing.identity / notarize.profile (a notarytool keychain profile — notarized + stapled, so it opens on any Mac without \"Open Anyway\"). --sign / --notarize / --no-notarize override it per build; LECODES_MACOS_SIGN_ID / LECODES_NOTARY_PROFILE sit between the flags and app.json.",
|
|
271
|
+
flags: desktopBuildFlags,
|
|
272
|
+
examples: ["lecodes desktop build", "lecodes app build desktop --zip --probe", "lecodes desktop build -o out/kiosk --renderer vulkan", "lecodes app build desktop --dmg --notarize MyProfile"],
|
|
273
|
+
run: ({ flags }) => buildDesktop(flags),
|
|
274
|
+
})
|
|
275
|
+
|
|
244
276
|
/** app.ico from the app.json icon master: PNG-compressed frames (fine on the Win10+ the
|
|
245
277
|
* distribution requires) at the sizes Windows asks for — no image tooling needed. */
|
|
246
278
|
const writeIco = async (root: string, config: AppConfig, dest: string) => {
|
|
@@ -272,9 +304,8 @@ const writeIco = async (root: string, config: AppConfig, dest: string) => {
|
|
|
272
304
|
|
|
273
305
|
/** `--probe`: run the STAGED folder hidden and dump a PNG next to it — verifies exactly what
|
|
274
306
|
* ships (the staged host, its assets, the bundle), not the dev environment. */
|
|
275
|
-
const probeBuild = async (out: string, exeName: string, config: AppConfig,
|
|
307
|
+
const probeBuild = async (out: string, exeName: string, config: AppConfig, frames: number) => {
|
|
276
308
|
const win = config.desktop?.window
|
|
277
|
-
const frames = Number(flagStr(args, "frames")) || 90
|
|
278
309
|
const shot = join(dirname(out), `${basename(out)}-probe.png`)
|
|
279
310
|
note(`Probe: hidden render of the staged folder (${frames} frames)…`)
|
|
280
311
|
await new Promise<void>((done, fail) => {
|
|
@@ -2,12 +2,12 @@ import { execFileSync, spawn, spawnSync } from "node:child_process"
|
|
|
2
2
|
import { cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs"
|
|
3
3
|
import { tmpdir } from "node:os"
|
|
4
4
|
import { basename, join, resolve } from "node:path"
|
|
5
|
-
import { CliError, c,
|
|
6
|
-
import { writeJson, type AppConfig, type MacDesktopConfig } from "./
|
|
7
|
-
import { loadIconMaster } from "./
|
|
5
|
+
import { CliError, c, log, note, success, warn } from "../../cli"
|
|
6
|
+
import { writeJson, type AppConfig, type MacDesktopConfig } from "./shared"
|
|
7
|
+
import { loadIconMaster } from "./icon"
|
|
8
8
|
|
|
9
9
|
/*
|
|
10
|
-
* `lecodes app build desktop` on macOS — the .app arm of
|
|
10
|
+
* `lecodes app build desktop` on macOS — the .app arm of desktop.ts.
|
|
11
11
|
*
|
|
12
12
|
* Windows/Linux stage a portable FOLDER (exe + app.js + assets/ + runtime/). macOS has no such
|
|
13
13
|
* thing: Gatekeeper judges one signed bundle as a whole, and a Finder launch runs with cwd "/", so
|
|
@@ -320,8 +320,7 @@ const writeIcns = async (root: string, config: AppConfig, dest: string, tmp: str
|
|
|
320
320
|
|
|
321
321
|
/** `--probe`: launch the built app for a few seconds and grab the presented 3D frame through the
|
|
322
322
|
* host's LECODES_SNAPSHOT hook. The window shows briefly — the macOS host has no hidden mode. */
|
|
323
|
-
const probeMacApp = async (app: string, out: string,
|
|
324
|
-
const after = Number(flagStr(args, "after")) || 8
|
|
323
|
+
const probeMacApp = async (app: string, out: string, after: number) => {
|
|
325
324
|
const shot = join(out, `${basename(app, ".app")}-probe.png`)
|
|
326
325
|
rmSync(shot, { force: true })
|
|
327
326
|
note(`Probe: launching the built app for ${after + 2}s (the window will show)…`)
|
|
@@ -348,6 +347,18 @@ const probeMacApp = async (app: string, out: string, args: Args) => {
|
|
|
348
347
|
|
|
349
348
|
/* ---------------------------------------- build ---------------------------------------- */
|
|
350
349
|
|
|
350
|
+
/** The macOS-relevant `desktop build` flags (desktop.ts declares them; this is the typed subset). */
|
|
351
|
+
export interface MacBuildOptions {
|
|
352
|
+
sign?: string
|
|
353
|
+
notarize?: string
|
|
354
|
+
noNotarize: boolean
|
|
355
|
+
dmg: boolean
|
|
356
|
+
zip: boolean
|
|
357
|
+
probe: boolean
|
|
358
|
+
/** `--probe`: seconds the app runs before the snapshot. */
|
|
359
|
+
after: number
|
|
360
|
+
}
|
|
361
|
+
|
|
351
362
|
export interface MacBuildInput {
|
|
352
363
|
root: string
|
|
353
364
|
config: AppConfig
|
|
@@ -357,11 +368,11 @@ export interface MacBuildInput {
|
|
|
357
368
|
js: string
|
|
358
369
|
shipped: { name: string, path: string, absPath?: string }[]
|
|
359
370
|
hostExe: string
|
|
360
|
-
|
|
371
|
+
opts: MacBuildOptions
|
|
361
372
|
}
|
|
362
373
|
|
|
363
374
|
export const buildMacApp = async (input: MacBuildInput) => {
|
|
364
|
-
const { root, config, name, slug, out, js, shipped, hostExe,
|
|
375
|
+
const { root, config, name, slug, out, js, shipped, hostExe, opts } = input
|
|
365
376
|
const hostApp = macHostAppOf(hostExe)
|
|
366
377
|
assertMacHostCanBundle(hostExe)
|
|
367
378
|
const mac = config.desktop?.macos ?? {}
|
|
@@ -416,12 +427,7 @@ export const buildMacApp = async (input: MacBuildInput) => {
|
|
|
416
427
|
note(` bundle: ${bundleId} ${config.version ?? "1.0"} (${mac.buildNumber ?? 1})`)
|
|
417
428
|
|
|
418
429
|
// 4) Sign the whole bundle (the project files are now sealed too), then notarize + staple.
|
|
419
|
-
const signing = resolveMacSigning(mac, {
|
|
420
|
-
sign: flagStr(args, "sign"),
|
|
421
|
-
notarize: flagStr(args, "notarize"),
|
|
422
|
-
noNotarize: flagBool(args, "no-notarize"),
|
|
423
|
-
env: process.env,
|
|
424
|
-
}, developerIdInKeychain)
|
|
430
|
+
const signing = resolveMacSigning(mac, { sign: opts.sign, notarize: opts.notarize, noNotarize: opts.noNotarize, env: process.env }, developerIdInKeychain)
|
|
425
431
|
await signApp(app, signing, hostApp, tmp)
|
|
426
432
|
if (signing.notaryProfile) {
|
|
427
433
|
notarize(app, signing.notaryProfile, tmp, "app")
|
|
@@ -439,16 +445,16 @@ export const buildMacApp = async (input: MacBuildInput) => {
|
|
|
439
445
|
success(`App: ${app} (${mb(dirSize(app))})`)
|
|
440
446
|
|
|
441
447
|
// The DMG goes before --probe/--zip so a failure there costs nothing already earned.
|
|
442
|
-
if (
|
|
443
|
-
if (
|
|
444
|
-
if (
|
|
448
|
+
if (opts.dmg) await buildDmg(app, out, appName, signing, tmp)
|
|
449
|
+
if (opts.probe) await probeMacApp(app, out, opts.after)
|
|
450
|
+
if (opts.zip) {
|
|
445
451
|
// ditto, not zip(1): it keeps the bundle's structure/xattrs (the stapled ticket rides in
|
|
446
452
|
// Contents/CodeResources) exactly as Finder's "Compress" would.
|
|
447
453
|
const zip = join(out, `${appName}.zip`)
|
|
448
454
|
rmSync(zip, { force: true })
|
|
449
455
|
execFileSync("ditto", ["-c", "-k", "--keepParent", app, zip])
|
|
450
456
|
success(`Zip: ${zip} (${mb(statSync(zip).size)})`)
|
|
451
|
-
} else if (!
|
|
457
|
+
} else if (!opts.dmg) {
|
|
452
458
|
note("Tip: --zip packs the .app for sending; --dmg wraps it in a drag-to-Applications image.")
|
|
453
459
|
}
|
|
454
460
|
} finally {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
|
|
2
2
|
import { dirname, join, resolve } from "node:path"
|
|
3
3
|
import type { JimpInstance } from "jimp"
|
|
4
|
-
import { CliError, c, log, warn } from "
|
|
5
|
-
import type { AppConfig } from "./
|
|
4
|
+
import { CliError, c, log, warn } from "../../cli"
|
|
5
|
+
import type { AppConfig } from "./shared"
|
|
6
6
|
|
|
7
7
|
/* App icons rendered from the one master image app.json "icon" names (a square ≥1024px
|
|
8
8
|
* PNG/JPEG, project-root-relative). Strictly additive: without the key, sync never touches an
|