@nativedesktop/cli 0.4.0 → 0.4.2
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/package.json +2 -2
- package/src/config.test.ts +30 -4
- package/src/config.ts +31 -0
- package/src/index.ts +5 -3
- package/src/package/doctor.ts +5 -1
- package/src/package/identity.test.ts +3 -1
- package/src/package/linux.ts +4 -1
- package/src/package/mac.ts +2 -1
- package/src/package/payload.ts +4 -1
- package/src/package/templates.ts +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nativedesktop/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "The nd CLI: dev-runs, builds, and packages NativeDesktop apps",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,6 +25,6 @@
|
|
|
25
25
|
"./config": "./src/config.ts"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@nativedesktop/host": "0.4.
|
|
28
|
+
"@nativedesktop/host": "0.4.2"
|
|
29
29
|
}
|
|
30
30
|
}
|
package/src/config.test.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
// Webview engine and
|
|
2
|
-
// and `nd doctor` all make from the same config, and the values
|
|
3
|
-
// the host as ND_WEBVIEW_ENGINE and
|
|
1
|
+
// Webview engine, scheme and style resolution: the decisions `nd dev`,
|
|
2
|
+
// `nd package` and `nd doctor` all make from the same config, and the values
|
|
3
|
+
// `nd dev` hands the host as ND_WEBVIEW_ENGINE, ND_CEF_SCHEMES and ND_CEF_STYLE.
|
|
4
4
|
import { describe, expect, test } from "bun:test";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
engineTargetFor,
|
|
7
|
+
type NativeDesktopConfig,
|
|
8
|
+
resolveCefSchemes,
|
|
9
|
+
resolveCefStyle,
|
|
10
|
+
resolveWebViewEngine,
|
|
11
|
+
} from "./config.ts";
|
|
6
12
|
|
|
7
13
|
const chromiumOnMac: NativeDesktopConfig = { webview: { engine: { mac: "chromium" } } };
|
|
8
14
|
|
|
@@ -52,3 +58,23 @@ describe("resolveCefSchemes", () => {
|
|
|
52
58
|
expect(() => resolveCefSchemes(bad, {})).toThrow("webview.cef.schemes");
|
|
53
59
|
});
|
|
54
60
|
});
|
|
61
|
+
|
|
62
|
+
describe("resolveCefStyle", () => {
|
|
63
|
+
const chrome: NativeDesktopConfig = { webview: { cef: { style: "chrome" } } };
|
|
64
|
+
|
|
65
|
+
test("defaults to alloy", () => {
|
|
66
|
+
expect(resolveCefStyle({}, {})).toBe("alloy");
|
|
67
|
+
expect(resolveCefStyle(chrome, {})).toBe("chrome");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("ND_CEF_STYLE overrides the config in both directions", () => {
|
|
71
|
+
expect(resolveCefStyle({}, { ND_CEF_STYLE: "chrome" })).toBe("chrome");
|
|
72
|
+
expect(resolveCefStyle(chrome, { ND_CEF_STYLE: "alloy" })).toBe("alloy");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("an unknown style names where it came from", () => {
|
|
76
|
+
expect(() => resolveCefStyle({}, { ND_CEF_STYLE: "views" })).toThrow("ND_CEF_STYLE");
|
|
77
|
+
const bad = { webview: { cef: { style: "blink" } } } as unknown as NativeDesktopConfig;
|
|
78
|
+
expect(() => resolveCefStyle(bad, {})).toThrow("webview.cef.style");
|
|
79
|
+
});
|
|
80
|
+
});
|
package/src/config.ts
CHANGED
|
@@ -145,6 +145,9 @@ export interface PackageConfig {
|
|
|
145
145
|
/** `<webview>` engine: the platform's own WebKit, or Chromium via CEF. */
|
|
146
146
|
export type WebViewEngine = "system" | "chromium";
|
|
147
147
|
|
|
148
|
+
/** CEF browser style, per `cef_runtime_style_t`. */
|
|
149
|
+
export type CefStyle = "alloy" | "chrome";
|
|
150
|
+
|
|
148
151
|
export interface CefConfig {
|
|
149
152
|
/** Pinned CEF release, matched against cef-builds.spotifycdn.com/index.json.
|
|
150
153
|
* Default: DEFAULT_CEF_VERSION from @nativedesktop/host/cef. */
|
|
@@ -156,6 +159,11 @@ export interface CefConfig {
|
|
|
156
159
|
* cef_initialize, which is long before app code runs, so the list has to come
|
|
157
160
|
* from config rather than a runtime call. */
|
|
158
161
|
schemes?: string[];
|
|
162
|
+
/** Browser style. Default "alloy". "chrome" gives the embedded browser
|
|
163
|
+
* Chromium's own browser runtime, which is the only way to run Chrome
|
|
164
|
+
* extensions; it costs Chromium's own handling of some UI that Alloy leaves
|
|
165
|
+
* to the embedder. See docs/webview.md. */
|
|
166
|
+
style?: CefStyle;
|
|
159
167
|
}
|
|
160
168
|
|
|
161
169
|
export interface WebViewConfig {
|
|
@@ -235,6 +243,29 @@ export function resolveCefSchemes(
|
|
|
235
243
|
return [...new Set(declared)];
|
|
236
244
|
}
|
|
237
245
|
|
|
246
|
+
const CEF_STYLES: readonly CefStyle[] = ["alloy", "chrome"];
|
|
247
|
+
|
|
248
|
+
function expectStyle(value: string, source: string): CefStyle {
|
|
249
|
+
if (!CEF_STYLES.includes(value as CefStyle)) {
|
|
250
|
+
throw new Error(`nd: ${source} must be "alloy" or "chrome" (got "${value}")`);
|
|
251
|
+
}
|
|
252
|
+
return value as CefStyle;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* The browser style a launch declares. ND_CEF_STYLE wins outright, the same way
|
|
257
|
+
* ND_WEBVIEW_ENGINE and ND_CEF_SCHEMES do, and takes the name the host reads.
|
|
258
|
+
*/
|
|
259
|
+
export function resolveCefStyle(
|
|
260
|
+
config: NativeDesktopConfig,
|
|
261
|
+
env: Record<string, string | undefined> = process.env,
|
|
262
|
+
): CefStyle {
|
|
263
|
+
const override = env.ND_CEF_STYLE;
|
|
264
|
+
if (override) return expectStyle(override, "ND_CEF_STYLE");
|
|
265
|
+
const declared = config.webview?.cef?.style;
|
|
266
|
+
return declared ? expectStyle(declared, "webview.cef.style") : "alloy";
|
|
267
|
+
}
|
|
268
|
+
|
|
238
269
|
export function defineConfig(config: NativeDesktopConfig): NativeDesktopConfig { return config; }
|
|
239
270
|
|
|
240
271
|
export async function loadConfig(cwd = process.cwd()): Promise<NativeDesktopConfig> {
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
loadConfig,
|
|
14
14
|
type NativeDesktopConfig,
|
|
15
15
|
resolveCefSchemes,
|
|
16
|
+
resolveCefStyle,
|
|
16
17
|
resolveWebViewEngine,
|
|
17
18
|
} from "./config.ts";
|
|
18
19
|
import { packageApp, type PackageOptions } from "./package/index.ts";
|
|
@@ -24,15 +25,16 @@ async function nativeEnv(config: NativeDesktopConfig): Promise<Record<string, st
|
|
|
24
25
|
return paths.length ? { ND_PLUGINS: "1", ND_PLUGIN_PATHS: paths.join(":") } : {};
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
/** The host reads the engine
|
|
28
|
-
* environment, so
|
|
29
|
-
* Windows has no engine target yet. */
|
|
28
|
+
/** The host reads the engine, its launch-declared schemes and the browser style
|
|
29
|
+
* off its environment, so those config decisions have to be made here and
|
|
30
|
+
* handed down. Windows has no engine target yet. */
|
|
30
31
|
function engineEnv(config: NativeDesktopConfig): Record<string, string> {
|
|
31
32
|
const target = engineTargetFor();
|
|
32
33
|
if (!target) return {};
|
|
33
34
|
const schemes = resolveCefSchemes(config);
|
|
34
35
|
return {
|
|
35
36
|
ND_WEBVIEW_ENGINE: resolveWebViewEngine(config, target),
|
|
37
|
+
ND_CEF_STYLE: resolveCefStyle(config),
|
|
36
38
|
...(schemes.length ? { ND_CEF_SCHEMES: schemes.join(",") } : {}),
|
|
37
39
|
};
|
|
38
40
|
}
|
package/src/package/doctor.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
loadConfig,
|
|
11
11
|
type NativeDesktopConfig,
|
|
12
12
|
resolveCefSchemes,
|
|
13
|
+
resolveCefStyle,
|
|
13
14
|
resolveWebViewEngine,
|
|
14
15
|
type WebViewEngine,
|
|
15
16
|
} from "../config.ts";
|
|
@@ -78,9 +79,11 @@ export function webviewChecks(config: NativeDesktopConfig, cwd: string): Check[]
|
|
|
78
79
|
if (!target) return [];
|
|
79
80
|
let engine: WebViewEngine;
|
|
80
81
|
let schemes: string[];
|
|
82
|
+
let style: string;
|
|
81
83
|
try {
|
|
82
84
|
engine = resolveWebViewEngine(config, target);
|
|
83
85
|
schemes = resolveCefSchemes(config);
|
|
86
|
+
style = resolveCefStyle(config);
|
|
84
87
|
} catch (err) {
|
|
85
88
|
return [{ name: "webview", status: "error", detail: String(err) }];
|
|
86
89
|
}
|
|
@@ -88,7 +91,8 @@ export function webviewChecks(config: NativeDesktopConfig, cwd: string): Check[]
|
|
|
88
91
|
name: "webview",
|
|
89
92
|
status: "ok",
|
|
90
93
|
detail: `engine=${engine} (${target})${process.env.ND_WEBVIEW_ENGINE ? " from ND_WEBVIEW_ENGINE" : ""}` +
|
|
91
|
-
(schemes.length ? ` schemes=${schemes.join(",")}` : "")
|
|
94
|
+
(schemes.length ? ` schemes=${schemes.join(",")}` : "") +
|
|
95
|
+
(engine === "chromium" ? ` style=${style}` : ""),
|
|
92
96
|
}];
|
|
93
97
|
|
|
94
98
|
const version = cefVersionFor(config.webview?.cef);
|
|
@@ -208,7 +208,7 @@ describe("buildDesktopEntry / appRunTemplate", () => {
|
|
|
208
208
|
expect(script).not.toContain("ND_WEBVIEW_ENGINE");
|
|
209
209
|
});
|
|
210
210
|
|
|
211
|
-
test("AppRun exports the engine and
|
|
211
|
+
test("AppRun exports the engine, its schemes and the style, behind an override", () => {
|
|
212
212
|
const script = appRunTemplate({
|
|
213
213
|
entry: "src/main.tsx",
|
|
214
214
|
cwd: ".",
|
|
@@ -216,8 +216,10 @@ describe("buildDesktopEntry / appRunTemplate", () => {
|
|
|
216
216
|
pluginPaths: [],
|
|
217
217
|
engine: "chromium",
|
|
218
218
|
schemes: ["nbext", "nbint"],
|
|
219
|
+
style: "chrome",
|
|
219
220
|
});
|
|
220
221
|
expect(script).toContain('export ND_WEBVIEW_ENGINE="${ND_WEBVIEW_ENGINE:-chromium}"');
|
|
221
222
|
expect(script).toContain('export ND_CEF_SCHEMES="${ND_CEF_SCHEMES:-nbext,nbint}"');
|
|
223
|
+
expect(script).toContain('export ND_CEF_STYLE="${ND_CEF_STYLE:-chrome}"');
|
|
222
224
|
});
|
|
223
225
|
});
|
package/src/package/linux.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { chmodSync, cpSync, mkdirSync, writeFileSync } from "node:fs";
|
|
|
7
7
|
import { join, resolve } from "node:path";
|
|
8
8
|
import { resolveHostBinary } from "@nativedesktop/host";
|
|
9
9
|
import { cefPlatformKey } from "@nativedesktop/host/cef";
|
|
10
|
-
import { type NativeDesktopConfig, resolveCefSchemes, resolveWebViewEngine } from "../config.ts";
|
|
10
|
+
import { type NativeDesktopConfig, resolveCefSchemes, resolveCefStyle, resolveWebViewEngine } from "../config.ts";
|
|
11
11
|
import { applyCefLinuxPlan, cefVersionFor, ensureCefDist, planCefLinux } from "./cef.ts";
|
|
12
12
|
import { installLinuxIcon } from "./icons.ts";
|
|
13
13
|
import { buildAppRun, buildDesktopEntry, buildMimeInfoXml, type ResolvedIdentity } from "./identity.ts";
|
|
@@ -32,6 +32,7 @@ export async function packageLinuxApp(
|
|
|
32
32
|
|
|
33
33
|
const engine = resolveWebViewEngine(config, "linux");
|
|
34
34
|
const schemes = resolveCefSchemes(config);
|
|
35
|
+
const style = resolveCefStyle(config);
|
|
35
36
|
const payload = await assemblePayload({
|
|
36
37
|
appDir,
|
|
37
38
|
config,
|
|
@@ -39,6 +40,7 @@ export async function packageLinuxApp(
|
|
|
39
40
|
appRoot: join(appdir, "app"),
|
|
40
41
|
engine,
|
|
41
42
|
schemes,
|
|
43
|
+
style,
|
|
42
44
|
entry: options.entry,
|
|
43
45
|
compile: options.compile,
|
|
44
46
|
});
|
|
@@ -51,6 +53,7 @@ export async function packageLinuxApp(
|
|
|
51
53
|
pluginPaths: payload.pluginPaths,
|
|
52
54
|
engine,
|
|
53
55
|
schemes,
|
|
56
|
+
style,
|
|
54
57
|
}));
|
|
55
58
|
chmodSync(join(appdir, "AppRun"), 0o755);
|
|
56
59
|
writeFileSync(join(appdir, `${identity.slug}.desktop`), buildDesktopEntry(identity, linux));
|
package/src/package/mac.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { chmodSync, cpSync, existsSync, mkdirSync, readFileSync, writeFileSync }
|
|
|
7
7
|
import { join, resolve } from "node:path";
|
|
8
8
|
import { resolveHostBinary } from "@nativedesktop/host";
|
|
9
9
|
import { cefPlatformKey } from "@nativedesktop/host/cef";
|
|
10
|
-
import { type NativeDesktopConfig, resolveCefSchemes, resolveWebViewEngine } from "../config.ts";
|
|
10
|
+
import { type NativeDesktopConfig, resolveCefSchemes, resolveCefStyle, resolveWebViewEngine } from "../config.ts";
|
|
11
11
|
import {
|
|
12
12
|
applyCefMacPlan,
|
|
13
13
|
type CefMacPlan,
|
|
@@ -80,6 +80,7 @@ export async function packageMacApp(
|
|
|
80
80
|
appRoot: join(c, "Resources", "app"),
|
|
81
81
|
engine,
|
|
82
82
|
schemes: resolveCefSchemes(config),
|
|
83
|
+
style: resolveCefStyle(config),
|
|
83
84
|
entry: options.entry,
|
|
84
85
|
compile: options.compile,
|
|
85
86
|
});
|
package/src/package/payload.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// workspace-relative path and relative imports keep resolving packaged.
|
|
5
5
|
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { basename, join, relative, resolve, sep } from "node:path";
|
|
7
|
-
import { buildNativePlugins, type NativeDesktopConfig, type PackageConfig, type WebViewEngine } from "../config.ts";
|
|
7
|
+
import { buildNativePlugins, type CefStyle, type NativeDesktopConfig, type PackageConfig, type WebViewEngine } from "../config.ts";
|
|
8
8
|
import type { ResolvedIdentity } from "./identity.ts";
|
|
9
9
|
import { assertResolvableEntries, flattenRuntimeModules } from "./modules.ts";
|
|
10
10
|
|
|
@@ -46,6 +46,8 @@ export interface PayloadOptions {
|
|
|
46
46
|
engine: WebViewEngine;
|
|
47
47
|
/** Launch-declared CEF schemes, recorded for the same reason. */
|
|
48
48
|
schemes: string[];
|
|
49
|
+
/** CEF browser style, recorded for the same reason. */
|
|
50
|
+
style: CefStyle;
|
|
49
51
|
/** CLI --entry override (app-relative source entry). */
|
|
50
52
|
entry?: string;
|
|
51
53
|
/** false forces raw source (--no-compile). */
|
|
@@ -170,6 +172,7 @@ export async function assemblePayload(o: PayloadOptions): Promise<PayloadResult>
|
|
|
170
172
|
pluginPaths,
|
|
171
173
|
engine: o.engine,
|
|
172
174
|
schemes: o.schemes,
|
|
175
|
+
style: o.style,
|
|
173
176
|
}, null, 2)}\n`);
|
|
174
177
|
|
|
175
178
|
return { entry: appEntry, cwd, pluginPaths };
|
package/src/package/templates.ts
CHANGED
|
@@ -99,6 +99,8 @@ export interface AppRunSpec {
|
|
|
99
99
|
engine?: string;
|
|
100
100
|
/** Launch-declared CEF schemes. */
|
|
101
101
|
schemes?: string[];
|
|
102
|
+
/** CEF browser style the AppDir was staged for. */
|
|
103
|
+
style?: string;
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
export function appRunTemplate(s: AppRunSpec): string {
|
|
@@ -108,11 +110,12 @@ export function appRunTemplate(s: AppRunSpec): string {
|
|
|
108
110
|
`export ND_SCRIPT="$HERE/app/${s.entry}"\n` +
|
|
109
111
|
'export PATH="$HERE/usr/bin:$PATH"\n';
|
|
110
112
|
if (s.appId) script += `export ND_APP_ID="${s.appId}"\n`;
|
|
111
|
-
// Every CEF process reads
|
|
113
|
+
// Every CEF process reads these, and each has to be settled before
|
|
112
114
|
// cef_initialize. The :- form keeps an explicit override ahead of the bundle,
|
|
113
115
|
// matching how the mac bootstrap defers to an already-set variable.
|
|
114
116
|
if (s.engine) script += `export ND_WEBVIEW_ENGINE="\${ND_WEBVIEW_ENGINE:-${s.engine}}"\n`;
|
|
115
117
|
if (s.schemes?.length) script += `export ND_CEF_SCHEMES="\${ND_CEF_SCHEMES:-${s.schemes.join(",")}}"\n`;
|
|
118
|
+
if (s.style) script += `export ND_CEF_STYLE="\${ND_CEF_STYLE:-${s.style}}"\n`;
|
|
116
119
|
if (s.pluginPaths.length) {
|
|
117
120
|
script += 'export ND_PLUGINS="1"\n';
|
|
118
121
|
script += `export ND_PLUGIN_PATHS="${s.pluginPaths.map((p) => `$HERE/app/${p}`).join(":")}"\n`;
|