@flare-desktop/cli 0.1.1 → 0.1.3
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 +25 -0
- package/package.json +5 -2
- package/src/assets/flare-mark.png +0 -0
- package/src/cli.js +4 -0
- package/src/commands/build.js +2 -0
- package/src/commands/bundle.js +2 -0
- package/src/commands/codegen.js +53 -0
- package/src/commands/dev.js +9 -1
- package/src/commands/init.js +52 -11
- package/src/help.js +7 -1
- package/src/lib/args.js +5 -0
- package/src/lib/build.js +27 -2
- package/src/lib/cmake.js +25 -7
- package/src/lib/commands.js +1 -0
- package/src/lib/embed-config-cli.js +14 -0
- package/src/lib/embedded-config.js +181 -0
- package/src/lib/icons.js +7 -17
- package/src/lib/project.js +4 -3
- package/src/lib/sdk.js +54 -0
- package/src/release-versions.js +2 -0
- package/src/templates/clang-format.txt +32 -0
- package/src/templates/core.d.ts +135 -0
- package/src/templates/core.js +278 -0
- package/src/templates/project.js +87 -28
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
|
|
4
|
+
import { loadProject, mergeConfig, parseConfig } from "./project.js";
|
|
5
|
+
|
|
6
|
+
function cppString(value) {
|
|
7
|
+
const bytes = Buffer.from(value, "utf8");
|
|
8
|
+
let output = '"';
|
|
9
|
+
for (const byte of bytes) {
|
|
10
|
+
if (byte === 34) output += '\\"';
|
|
11
|
+
else if (byte === 92) output += "\\\\";
|
|
12
|
+
else if (byte >= 32 && byte <= 126) output += String.fromCharCode(byte);
|
|
13
|
+
else output += `\\${byte.toString(8).padStart(3, "0")}`;
|
|
14
|
+
}
|
|
15
|
+
return `${output}"`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function cppJson(value) {
|
|
19
|
+
if (value === null) return "Flare::JSON(nullptr)";
|
|
20
|
+
if (Array.isArray(value)) return `Flare::JSON::array({${value.map(cppJson).join(", ")}})`;
|
|
21
|
+
if (typeof value === "object") {
|
|
22
|
+
const entries = Object.entries(value).map(([key, item]) => `{${cppString(key)}, ${cppJson(item)}}`);
|
|
23
|
+
return `Flare::JSON::object({${entries.join(", ")}})`;
|
|
24
|
+
}
|
|
25
|
+
if (typeof value === "string") return `Flare::JSON(${cppString(value)})`;
|
|
26
|
+
if (typeof value === "boolean") return `Flare::JSON(${value})`;
|
|
27
|
+
if (typeof value === "number" && Number.isFinite(value)) return `Flare::JSON(${value})`;
|
|
28
|
+
throw new TypeError("unsupported JSON value in configuration");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function scalar(value, kind) {
|
|
32
|
+
if (kind === "string" && typeof value === "string") return cppString(value);
|
|
33
|
+
if (kind === "bool" && typeof value === "boolean") return `${value}`;
|
|
34
|
+
if (kind === "number" && typeof value === "number" && Number.isFinite(value)) return `${value}`;
|
|
35
|
+
if (kind === "int" && Number.isSafeInteger(value)) return `${value}`;
|
|
36
|
+
if (kind === "strings" && Array.isArray(value)) {
|
|
37
|
+
return `{${value.filter((item) => typeof item === "string").map(cppString).join(", ")}}`;
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const FIELDS = {
|
|
43
|
+
package: { productName: "string", version: "string" },
|
|
44
|
+
app: { productName: "string", mainBinaryName: "string", version: "string", identifier: "string" },
|
|
45
|
+
build: {
|
|
46
|
+
beforeDevCommand: "string", afterDevCommand: "string", beforeBuildCommand: "string",
|
|
47
|
+
afterBuildCommand: "string", frontendDist: "string", devUrl: "string", removeUnusedCommands: "strings"
|
|
48
|
+
},
|
|
49
|
+
"build.features": { customProtocol: "bool", devtools: "bool", isolation: "bool", systemTray: "bool" },
|
|
50
|
+
bundle: {
|
|
51
|
+
active: "bool", identifier: "string", icon: "string", version: "string", publisher: "string",
|
|
52
|
+
homepage: "string", longDescription: "string", copyright: "string", category: "string",
|
|
53
|
+
shortDescription: "string", licenseFile: "string", targets: "strings", resources: "strings",
|
|
54
|
+
externalBin: "strings"
|
|
55
|
+
},
|
|
56
|
+
"bundle.linuxBundle": { depends: "string", desktopTemplate: "string", section: "string", priority: "string", files: "strings" },
|
|
57
|
+
"bundle.windows": { language: "string", installerIcon: "string", installMode: "int", webviewInstallModeOffline: "bool" },
|
|
58
|
+
"bundle.macos": { minimumSystemVersion: "string", frameworks: "bool", signingIdentity: "string" },
|
|
59
|
+
security: {
|
|
60
|
+
freezePrototype: "bool", dangerousDisableAssetCspModification: "bool", dangerousUseHttpScheme: "bool",
|
|
61
|
+
dangerousAcceptInvalidCertificates: "bool", capabilities: "strings", dangerousRemoteDomainIpcAccess: "strings"
|
|
62
|
+
},
|
|
63
|
+
window: {
|
|
64
|
+
label: "string", title: "string", resizable: "bool", maximized: "bool", fullscreen: "bool",
|
|
65
|
+
alwaysOnTop: "bool", decorations: "bool", transparent: "bool", visible: "bool", center: "bool",
|
|
66
|
+
devtools: "bool", url: "string"
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
function emitFields(lines, target, input, fields) {
|
|
71
|
+
if (input === null || typeof input !== "object" || Array.isArray(input)) return;
|
|
72
|
+
for (const [key, kind] of Object.entries(fields)) {
|
|
73
|
+
const result = scalar(input[key], kind);
|
|
74
|
+
if (result !== null) lines.push(`${target}.${key} = ${result};`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function emitSize(lines, target, input) {
|
|
79
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return;
|
|
80
|
+
for (const key of ["width", "height"]) {
|
|
81
|
+
const result = scalar(input[key], "number");
|
|
82
|
+
if (result !== null) lines.push(`${target}.${key} = ${result};`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function emitCsp(lines, input) {
|
|
87
|
+
if (typeof input === "string") {
|
|
88
|
+
const directives = input.split(";").map((statement) => statement.trim()).filter(Boolean);
|
|
89
|
+
lines.push(`config.security.csp.enabled = ${input.trim() ? "true" : "false"};`);
|
|
90
|
+
for (const statement of directives) {
|
|
91
|
+
const [name, ...sources] = statement.split(/\s+/);
|
|
92
|
+
lines.push(`config.security.csp.directives.push_back(Flare::CspDirective{${cppString(name)}, ${scalar(sources, "strings")}});`);
|
|
93
|
+
}
|
|
94
|
+
} else if (input && typeof input === "object" && !Array.isArray(input)) {
|
|
95
|
+
lines.push("config.security.csp.enabled = true;");
|
|
96
|
+
for (const [name, sources] of Object.entries(input).sort(([a], [b]) => a.localeCompare(b))) {
|
|
97
|
+
const values = typeof sources === "string" ? sources.trim().split(/\s+/).filter(Boolean) : sources;
|
|
98
|
+
lines.push(`config.security.csp.directives.push_back(Flare::CspDirective{${cppString(name)}, ${scalar(values, "strings") ?? "{}"}});`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function generateEmbeddedConfig(config, raw = config, namespace = "FlareGenerated") {
|
|
104
|
+
if (!/^[A-Za-z_][A-Za-z_0-9]*$/.test(namespace)) throw new Error("invalid C++ namespace");
|
|
105
|
+
config = structuredClone(config);
|
|
106
|
+
const lines = [
|
|
107
|
+
"#pragma once", "", "#include <flare/config/config.h>", "", `namespace ${namespace} {`,
|
|
108
|
+
"inline Flare::Config EmbeddedConfig() {", "Flare::Config config;"
|
|
109
|
+
];
|
|
110
|
+
if (raw.package && typeof raw.package === "object" && !Array.isArray(raw.package)) {
|
|
111
|
+
config.package.version ??= "0.1.0";
|
|
112
|
+
}
|
|
113
|
+
if (raw.build && typeof raw.build === "object" && !Array.isArray(raw.build)) {
|
|
114
|
+
config.build.frontendDist ??= "../dist";
|
|
115
|
+
}
|
|
116
|
+
if (raw.bundle && typeof raw.bundle === "object" && !Array.isArray(raw.bundle)) {
|
|
117
|
+
config.bundle.active ??= true;
|
|
118
|
+
config.bundle.icon ??= "icons/icon.png";
|
|
119
|
+
config.bundle.category ??= "DeveloperTool";
|
|
120
|
+
}
|
|
121
|
+
if (raw.bundle?.linux && typeof raw.bundle.linux === "object") {
|
|
122
|
+
config.bundle.linux.section ??= "utils";
|
|
123
|
+
config.bundle.linux.priority ??= "optional";
|
|
124
|
+
}
|
|
125
|
+
if (raw.bundle?.windows && typeof raw.bundle.windows === "object") {
|
|
126
|
+
config.bundle.windows.language ??= "en-US";
|
|
127
|
+
}
|
|
128
|
+
emitFields(lines, "config.package", config.package, FIELDS.package);
|
|
129
|
+
emitFields(lines, "config.app", config.app, FIELDS.app);
|
|
130
|
+
emitFields(lines, "config.build", config.build, FIELDS.build);
|
|
131
|
+
emitFields(lines, "config.build.features", config.build?.features, FIELDS["build.features"]);
|
|
132
|
+
emitFields(lines, "config.bundle", config.bundle, FIELDS.bundle);
|
|
133
|
+
emitFields(lines, "config.bundle.linuxBundle", config.bundle?.linux, FIELDS["bundle.linuxBundle"]);
|
|
134
|
+
emitFields(lines, "config.bundle.windows", config.bundle?.windows, FIELDS["bundle.windows"]);
|
|
135
|
+
emitFields(lines, "config.bundle.macos", config.bundle?.macos, FIELDS["bundle.macos"]);
|
|
136
|
+
emitFields(lines, "config.security", config.security, FIELDS.security);
|
|
137
|
+
emitCsp(lines, config.security?.csp);
|
|
138
|
+
if (typeof config.$schema === "string") lines.push(`config.schema = ${cppString(config.$schema)};`);
|
|
139
|
+
const windows = Array.isArray(config.windows) && config.windows.length ? config.windows : [{}];
|
|
140
|
+
for (const value of windows) {
|
|
141
|
+
lines.push("{ Flare::WindowConfig window;");
|
|
142
|
+
emitFields(lines, "window", value, FIELDS.window);
|
|
143
|
+
emitSize(lines, "window.size", value);
|
|
144
|
+
emitSize(lines, "window.size", value.size);
|
|
145
|
+
lines.push("window.minimumSize = Flare::WindowSize{0.0, 0.0};");
|
|
146
|
+
lines.push("window.maximumSize = Flare::WindowSize{0.0, 0.0};");
|
|
147
|
+
emitSize(lines, "window.minimumSize", value.minimumSize);
|
|
148
|
+
emitSize(lines, "window.maximumSize", value.maximumSize);
|
|
149
|
+
if (value.position && typeof value.position === "object" && !Array.isArray(value.position)) {
|
|
150
|
+
const x = scalar(value.position.x, "number") ?? "0.0";
|
|
151
|
+
const y = scalar(value.position.y, "number") ?? "0.0";
|
|
152
|
+
lines.push(`window.position = Flare::WindowPosition{${x}, ${y}};`);
|
|
153
|
+
}
|
|
154
|
+
if (typeof value.theme === "string") {
|
|
155
|
+
const theme = { light: "Light", dark: "Dark", automatic: "Automatic", system: "Automatic", auto: "Automatic" }[value.theme.toLowerCase()];
|
|
156
|
+
if (theme) lines.push(`window.theme = Flare::WindowTheme::${theme};`);
|
|
157
|
+
}
|
|
158
|
+
lines.push("config.windows.push_back(window); }");
|
|
159
|
+
}
|
|
160
|
+
if (config.plugins && typeof config.plugins === "object" && !Array.isArray(config.plugins)) {
|
|
161
|
+
for (const [name, value] of Object.entries(config.plugins).sort(([a], [b]) => a.localeCompare(b))) {
|
|
162
|
+
lines.push(`config.plugins.push_back(Flare::PluginConfig{${cppString(name)}, ${cppJson(value)}});`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
lines.push(`config.raw = ${cppJson(raw)};`);
|
|
166
|
+
lines.push("return config;", "}", "}", "");
|
|
167
|
+
return lines.join("\n");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function writeEmbeddedConfig({ projectDirectory, configFile = "flare.config.json", environment = "production", output }) {
|
|
171
|
+
const { config, files } = loadProject({ projectDirectory, configFile, environment });
|
|
172
|
+
let raw = {};
|
|
173
|
+
for (const file of files) raw = mergeConfig(raw, parseConfig(readFileSync(file, "utf8"), file));
|
|
174
|
+
writeFileSync(output, generateEmbeddedConfig(config, raw), "utf8");
|
|
175
|
+
const result = spawnSync("clang-format", ["-style=file", "-i", output], { cwd: projectDirectory });
|
|
176
|
+
if (result.error && result.error.code !== "ENOENT") throw result.error;
|
|
177
|
+
if (!result.error && result.status !== 0) {
|
|
178
|
+
throw new Error(`clang-format failed: ${result.stderr.toString("utf8")}`);
|
|
179
|
+
}
|
|
180
|
+
return files;
|
|
181
|
+
}
|
package/src/lib/icons.js
CHANGED
|
@@ -1,23 +1,13 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
|
|
1
3
|
import { FlareError } from "./errors.js";
|
|
2
|
-
import { resizePng, writePng } from "./png.js";
|
|
4
|
+
import { readPng, resizePng, writePng } from "./png.js";
|
|
5
|
+
|
|
6
|
+
let defaultMark;
|
|
3
7
|
|
|
4
8
|
export function placeholderIcon(size = 512) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const radius = size * 0.46;
|
|
8
|
-
for (let y = 0; y < size; y += 1) {
|
|
9
|
-
for (let x = 0; x < size; x += 1) {
|
|
10
|
-
const target = (y * size + x) * 4;
|
|
11
|
-
const distance = Math.hypot(x - center, y - center) / radius;
|
|
12
|
-
const glow = Math.max(0, Math.min(1, 1 - Math.abs(distance - 0.55) * 1.6));
|
|
13
|
-
const edge = distance <= 1 ? 1 : 0;
|
|
14
|
-
data[target] = edge ? Math.round(44 + 172 * glow) : 0;
|
|
15
|
-
data[target + 1] = edge ? Math.round(35 + 132 * glow) : 0;
|
|
16
|
-
data[target + 2] = edge ? Math.round(40 + 137 * glow) : 0;
|
|
17
|
-
data[target + 3] = edge ? 255 : 0;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return { width: size, height: size, data };
|
|
9
|
+
defaultMark ??= readPng(readFileSync(new URL("../assets/flare-mark.png", import.meta.url)));
|
|
10
|
+
return resizePng(defaultMark, size, size);
|
|
21
11
|
}
|
|
22
12
|
|
|
23
13
|
const ICO_SIZES = [16, 24, 32, 48, 64, 128, 256];
|
package/src/lib/project.js
CHANGED
|
@@ -175,8 +175,8 @@ export function mergeConfig(base, overlay) {
|
|
|
175
175
|
function normalizeWindow(window, fallbackTitle) {
|
|
176
176
|
const value = isObject(window) ? { ...window } : {};
|
|
177
177
|
const title = value.title ?? fallbackTitle;
|
|
178
|
-
const width = value.width ?? value.
|
|
179
|
-
const height = value.height ?? value.
|
|
178
|
+
const width = value.size?.width ?? value.width ?? 800;
|
|
179
|
+
const height = value.size?.height ?? value.height ?? 600;
|
|
180
180
|
return {
|
|
181
181
|
...value,
|
|
182
182
|
label: value.label ?? "main",
|
|
@@ -212,7 +212,8 @@ export function normalizeConfig(raw) {
|
|
|
212
212
|
if (!config.app.mainBinaryName) config.app.mainBinaryName = config.app.productName;
|
|
213
213
|
|
|
214
214
|
const fallbackTitle = config.app.productName || "flare-app";
|
|
215
|
-
const
|
|
215
|
+
const sourceWindows = Array.isArray(config.windows) ? config.windows : config.app.windows;
|
|
216
|
+
const windows = Array.isArray(sourceWindows) && sourceWindows.length > 0 ? sourceWindows : [{}];
|
|
216
217
|
config.windows = windows.map((window) => normalizeWindow(window, fallbackTitle));
|
|
217
218
|
|
|
218
219
|
return config;
|
package/src/lib/sdk.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { mkdtempSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { extract } from "tar";
|
|
5
|
+
|
|
6
|
+
import { FlareError } from "./errors.js";
|
|
7
|
+
|
|
8
|
+
export function sdkTarget(platform = process.platform, arch = process.arch) {
|
|
9
|
+
if (!(["x64", "arm64"].includes(arch))) throw new FlareError(`prebuilt SDK is not available for ${arch}; choose source mode`);
|
|
10
|
+
if (platform === "win32") {
|
|
11
|
+
if (arch !== "x64") throw new FlareError("prebuilt Windows SDK supports x64 MSVC only; choose source mode");
|
|
12
|
+
return { platform: "windows-x64", runtimes: ["md", "mt"] };
|
|
13
|
+
}
|
|
14
|
+
if (platform === "darwin") return { platform: `macos-${arch}`, runtimes: ["default"] };
|
|
15
|
+
if (platform === "linux" && arch === "x64") return { platform: "linux-x64", runtimes: ["default"] };
|
|
16
|
+
throw new FlareError(`prebuilt SDK is not available for ${platform}-${arch}; choose source mode`);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function installSdk({ destination, version, platform = process.platform, arch = process.arch, fetchImpl = fetch }) {
|
|
20
|
+
const target = sdkTarget(platform, arch);
|
|
21
|
+
mkdirSync(path.dirname(destination), { recursive: true });
|
|
22
|
+
const temporary = mkdtempSync(path.join(path.dirname(destination), ".flare-sdk-"));
|
|
23
|
+
const sdk = path.join(temporary, "flare");
|
|
24
|
+
mkdirSync(sdk);
|
|
25
|
+
try {
|
|
26
|
+
const checksumsUrl = `https://github.com/flare-desktop/flare/releases/download/v${version}/SHA256SUMS.txt`;
|
|
27
|
+
const checksumsResponse = await fetchImpl(checksumsUrl);
|
|
28
|
+
if (!checksumsResponse.ok) throw new FlareError(`SDK checksums are unavailable (HTTP ${checksumsResponse.status}); publish core v${version} first`);
|
|
29
|
+
const sums = new Map((await checksumsResponse.text()).split("\n").map((line) => /^(\w{64})\s+\*?(\S+)$/.exec(line)).filter(Boolean).map((match) => [match[2], match[1].toLowerCase()]));
|
|
30
|
+
for (const runtime of target.runtimes) {
|
|
31
|
+
const file = `flare-sdk-v${version}-${target.platform}-${runtime}.tar.gz`;
|
|
32
|
+
const url = `https://github.com/flare-desktop/flare/releases/download/v${version}/${file}`;
|
|
33
|
+
let response;
|
|
34
|
+
try { response = await fetchImpl(url); } catch (error) { throw new FlareError(`failed to download ${file}: ${error.message}`); }
|
|
35
|
+
if (!response.ok) throw new FlareError(`SDK archive ${file} is unavailable (HTTP ${response.status}); publish core v${version} SDK release first, or choose source mode`);
|
|
36
|
+
const archive = path.join(temporary, file);
|
|
37
|
+
const data = Buffer.from(await response.arrayBuffer());
|
|
38
|
+
const digest = createHash("sha256").update(data).digest("hex");
|
|
39
|
+
if (!sums.has(file) || sums.get(file) !== digest) throw new FlareError(`SDK checksum mismatch for ${file}`);
|
|
40
|
+
writeFileSync(archive, data);
|
|
41
|
+
await extract({ file: archive, cwd: temporary, strict: true, filter: (entry) => entry === "flare" || entry.startsWith("flare/") });
|
|
42
|
+
const manifest = JSON.parse(readFileSync(path.join(sdk, "sdk-manifest.json"), "utf8"));
|
|
43
|
+
if (manifest.version !== version || manifest.target !== target.platform || manifest.crt !== runtime) {
|
|
44
|
+
throw new FlareError(`SDK archive ${file} has incorrect platform or version metadata`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
rmSync(destination, { recursive: true, force: true });
|
|
48
|
+
mkdirSync(path.dirname(destination), { recursive: true });
|
|
49
|
+
renameSync(sdk, destination);
|
|
50
|
+
} finally {
|
|
51
|
+
rmSync(temporary, { recursive: true, force: true });
|
|
52
|
+
}
|
|
53
|
+
return target;
|
|
54
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
BasedOnStyle: Google
|
|
2
|
+
Standard: c++20
|
|
3
|
+
ColumnLimit: 120
|
|
4
|
+
IndentWidth: 4
|
|
5
|
+
TabWidth: 4
|
|
6
|
+
ContinuationIndentWidth: 4
|
|
7
|
+
ConstructorInitializerIndentWidth: 4
|
|
8
|
+
AccessModifierOffset: -4
|
|
9
|
+
NamespaceIndentation: All
|
|
10
|
+
UseTab: Never
|
|
11
|
+
PointerAlignment: Left
|
|
12
|
+
DerivePointerAlignment: false
|
|
13
|
+
AllowShortFunctionsOnASingleLine: Inline
|
|
14
|
+
AllowShortIfStatementsOnASingleLine: WithoutElse
|
|
15
|
+
AllowShortLoopsOnASingleLine: false
|
|
16
|
+
RemoveBracesLLVM: true
|
|
17
|
+
SortIncludes: Never
|
|
18
|
+
FixNamespaceComments: false
|
|
19
|
+
AlignAfterOpenBracket: BlockIndent
|
|
20
|
+
AlignOperands: DontAlign
|
|
21
|
+
AlignTrailingComments: false
|
|
22
|
+
AllowAllArgumentsOnNextLine: false
|
|
23
|
+
AllowAllParametersOfDeclarationOnNextLine: false
|
|
24
|
+
BinPackArguments: false
|
|
25
|
+
BinPackParameters: false
|
|
26
|
+
BreakBeforeBinaryOperators: NonAssignment
|
|
27
|
+
BreakConstructorInitializers: BeforeColon
|
|
28
|
+
PackConstructorInitializers: Never
|
|
29
|
+
LambdaBodyIndentation: OuterScope
|
|
30
|
+
PenaltyBreakBeforeFirstCallParameter: 10
|
|
31
|
+
AlwaysBreakAfterReturnType: None
|
|
32
|
+
PenaltyReturnTypeOnItsOwnLine: 1000
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
export type Payload = Record<string, unknown> | unknown[] | string | number | boolean | null;
|
|
2
|
+
|
|
3
|
+
export interface InvokeOptions {
|
|
4
|
+
id?: string;
|
|
5
|
+
window?: string;
|
|
6
|
+
webview?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface ListenOptions {
|
|
10
|
+
window?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface IpcErrorShape {
|
|
14
|
+
code: string;
|
|
15
|
+
message: string;
|
|
16
|
+
details?: Payload;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface IpcFailure extends Error {
|
|
20
|
+
code: string;
|
|
21
|
+
details?: Payload;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ChannelMessage {
|
|
25
|
+
sequence: number;
|
|
26
|
+
payload: Payload;
|
|
27
|
+
state: 'open' | 'closed';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface Channel {
|
|
31
|
+
identifier: number;
|
|
32
|
+
name: string;
|
|
33
|
+
send(payload?: Payload): Promise<void>;
|
|
34
|
+
deliver(message: ChannelMessage): void;
|
|
35
|
+
close(): void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface Metadata {
|
|
39
|
+
readonly protocol: string;
|
|
40
|
+
readonly host: string;
|
|
41
|
+
readonly version: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function isFlare(): boolean;
|
|
45
|
+
export function metadata(): Metadata;
|
|
46
|
+
export function invoke<T = unknown>(command: string, payload?: Payload, options?: InvokeOptions): Promise<T>;
|
|
47
|
+
export function listen(event: string, handler: (payload: Payload) => void, options?: ListenOptions): Promise<() => Promise<void>>;
|
|
48
|
+
export function once(event: string, handler: (payload: Payload) => void, options?: ListenOptions): Promise<() => Promise<void>>;
|
|
49
|
+
export function unlisten(event: string, id: number): Promise<void>;
|
|
50
|
+
export function emit(event: string, payload?: Payload): Promise<void>;
|
|
51
|
+
export function dispatch(event: string, payload?: Payload): number;
|
|
52
|
+
export function createChannel(onMessage: (message: ChannelMessage) => void): Channel;
|
|
53
|
+
export function currentWindow(): {
|
|
54
|
+
label: string;
|
|
55
|
+
close(): Promise<unknown>;
|
|
56
|
+
setTitle(title: string): Promise<unknown>;
|
|
57
|
+
show(): Promise<unknown>;
|
|
58
|
+
hide(): Promise<unknown>;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const app: {
|
|
62
|
+
version(): Promise<string>;
|
|
63
|
+
describe(): Promise<Payload>;
|
|
64
|
+
config(): Promise<Payload>;
|
|
65
|
+
platform(): Promise<Payload>;
|
|
66
|
+
exit(): Promise<unknown>;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const window: {
|
|
70
|
+
list(): Promise<string[]>;
|
|
71
|
+
emit(event: string, payload?: Payload): Promise<unknown>;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const plugins: { list(): Promise<Payload> };
|
|
75
|
+
export interface MenuItem {
|
|
76
|
+
id?: string;
|
|
77
|
+
kind?: 'text' | 'check' | 'radio' | 'separator' | 'submenu' | 'predefined';
|
|
78
|
+
text?: string;
|
|
79
|
+
accelerator?: string;
|
|
80
|
+
enabled?: boolean;
|
|
81
|
+
checked?: boolean;
|
|
82
|
+
icon?: string;
|
|
83
|
+
items?: MenuItem[];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const menu: {
|
|
87
|
+
describe(): Promise<{ id: string; items: MenuItem[] }>;
|
|
88
|
+
set(items: MenuItem[]): Promise<boolean>;
|
|
89
|
+
dispatch(id: string): Promise<boolean>;
|
|
90
|
+
onCommand(handler: (id: string, payload: { id: string }) => void): () => Promise<boolean>;
|
|
91
|
+
};
|
|
92
|
+
export const commands: {
|
|
93
|
+
register(name: string, handler: (payload: Payload) => Payload): void;
|
|
94
|
+
unregister(name: string): boolean;
|
|
95
|
+
has(name: string): boolean;
|
|
96
|
+
names(): string[];
|
|
97
|
+
};
|
|
98
|
+
export const log: {
|
|
99
|
+
trace(message: string): Promise<void>;
|
|
100
|
+
debug(message: string): Promise<void>;
|
|
101
|
+
info(message: string): Promise<void>;
|
|
102
|
+
warn(message: string): Promise<void>;
|
|
103
|
+
error(message: string): Promise<void>;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export type DirectoryName =
|
|
107
|
+
| 'appData'
|
|
108
|
+
| 'appLocalData'
|
|
109
|
+
| 'appConfig'
|
|
110
|
+
| 'appCache'
|
|
111
|
+
| 'appLog'
|
|
112
|
+
| 'home'
|
|
113
|
+
| 'documents'
|
|
114
|
+
| 'downloads'
|
|
115
|
+
| 'desktop'
|
|
116
|
+
| 'pictures'
|
|
117
|
+
| 'temp'
|
|
118
|
+
| 'executable'
|
|
119
|
+
| 'resource'
|
|
120
|
+
| 'current';
|
|
121
|
+
|
|
122
|
+
export const path: {
|
|
123
|
+
resolve(name: DirectoryName | string): Promise<{ name: string; path: string }>;
|
|
124
|
+
all(): Promise<Record<DirectoryName, string>>;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const tray: {
|
|
128
|
+
describe(): Promise<Payload & { menu: { id: string; items: MenuItem[] } }>;
|
|
129
|
+
setIcon(icon: string): Promise<Payload>;
|
|
130
|
+
setTooltip(tooltip: string): Promise<Payload>;
|
|
131
|
+
setTitle(title: string): Promise<Payload>;
|
|
132
|
+
setVisible(visible: boolean): Promise<Payload>;
|
|
133
|
+
setMenu(items: MenuItem[]): Promise<Payload>;
|
|
134
|
+
dispatch(id: string): Promise<boolean>;
|
|
135
|
+
};
|