bleam 0.0.5 → 0.0.6
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/dist/ai.cjs +187 -0
- package/dist/ai.d.cts +52 -0
- package/dist/ai.d.ts +52 -0
- package/dist/ai.js +182 -0
- package/dist/animated.cjs +286 -0
- package/dist/animated.d.cts +47 -0
- package/dist/animated.d.ts +47 -0
- package/dist/animated.js +281 -0
- package/dist/app.d.cts +1 -2
- package/dist/app.d.ts +1 -2
- package/dist/app.js +1 -2
- package/dist/bundler.d.cts +1 -2
- package/dist/bundler.d.ts +1 -2
- package/dist/chrome.cjs +265 -0
- package/dist/chrome.d.cts +19 -0
- package/dist/chrome.d.ts +19 -0
- package/dist/chrome.js +262 -0
- package/dist/cli.cjs +768 -31
- package/dist/cli.js +767 -34
- package/dist/config-Bb6SULnR.cjs +46 -0
- package/dist/config-CfWa3q-k.js +28 -0
- package/dist/config-ClDGHNb3.d.ts +39 -0
- package/dist/config-D3gPaVMb.d.cts +39 -0
- package/dist/config.cjs +4 -25
- package/dist/config.d.cts +2 -28
- package/dist/config.d.ts +2 -28
- package/dist/config.js +2 -24
- package/dist/crypto-BB92-Upx.js +7 -0
- package/dist/crypto-CT3VZ7lF.cjs +13 -0
- package/dist/crypto.cjs +2 -2
- package/dist/crypto.d.cts +8 -1
- package/dist/crypto.d.ts +8 -1
- package/dist/crypto.js +2 -2
- package/dist/dev-protocol.d.cts +3 -3
- package/dist/dev-protocol.d.ts +3 -3
- package/dist/dev-protocol.js +1 -2
- package/dist/fs.cjs +12 -2
- package/dist/fs.d.cts +7 -1
- package/dist/fs.d.ts +7 -1
- package/dist/fs.js +10 -1
- package/dist/index.cjs +4 -5
- package/dist/index.d.cts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.js +2 -4
- package/dist/native-macos-D6p2SmUj.js +20 -0
- package/dist/native-macos-DLwo_ii9.cjs +31 -0
- package/dist/native-runtime-C85Nuc4F.js +10 -0
- package/dist/native-runtime-CbPzrs8j.d.cts +33 -0
- package/dist/{native-runtime-CdeT0JyQ.cjs → native-runtime-CsXnXkQn.cjs} +1 -14
- package/dist/native-runtime-DxHSrsTX.d.ts +33 -0
- package/dist/native.cjs +35 -32
- package/dist/native.d.cts +4 -34
- package/dist/native.d.ts +3 -33
- package/dist/native.js +36 -34
- package/dist/runtime.d.cts +1 -2
- package/dist/runtime.d.ts +1 -2
- package/dist/schema-BOuUHcqo.d.cts +58 -0
- package/dist/schema-DVmoD9JL.js +90 -0
- package/dist/schema-bxeeCyLn.cjs +102 -0
- package/dist/schema-ipsECAso.d.ts +58 -0
- package/dist/schema.cjs +4 -0
- package/dist/schema.d.cts +2 -0
- package/dist/schema.d.ts +2 -0
- package/dist/schema.js +3 -0
- package/dist/state.cjs +765 -0
- package/dist/state.d.cts +129 -0
- package/dist/state.d.ts +129 -0
- package/dist/state.js +747 -0
- package/dist/styles.cjs +742 -0
- package/dist/styles.d.cts +701 -0
- package/dist/styles.d.ts +701 -0
- package/dist/styles.js +739 -0
- package/dist/ui.cjs +113 -0
- package/dist/ui.d.cts +30 -0
- package/dist/ui.d.ts +30 -0
- package/dist/ui.js +110 -0
- package/metro-config.cjs +18 -13
- package/package.json +47 -13
- package/templates/basic/app/index.tsx +130 -12
- package/templates/basic/app.config.ts +4 -2
- package/dist/app.d.cts.map +0 -1
- package/dist/app.d.ts.map +0 -1
- package/dist/app.js.map +0 -1
- package/dist/bundler.d.cts.map +0 -1
- package/dist/bundler.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/config.d.cts.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/crypto-BNhWeXMj.cjs +0 -15
- package/dist/crypto-Bg8cD8wX.d.cts +0 -8
- package/dist/crypto-Bg8cD8wX.d.cts.map +0 -1
- package/dist/crypto-CCA_hvao.js +0 -11
- package/dist/crypto-CCA_hvao.js.map +0 -1
- package/dist/crypto-IOzbNoJD.d.ts +0 -8
- package/dist/crypto-IOzbNoJD.d.ts.map +0 -1
- package/dist/dev-protocol.d.cts.map +0 -1
- package/dist/dev-protocol.d.ts.map +0 -1
- package/dist/dev-protocol.js.map +0 -1
- package/dist/fs-BK7joD1g.js +0 -13
- package/dist/fs-BK7joD1g.js.map +0 -1
- package/dist/fs-CEhcjuN6.d.ts +0 -9
- package/dist/fs-CEhcjuN6.d.ts.map +0 -1
- package/dist/fs-CfE8CHf_.d.cts +0 -9
- package/dist/fs-CfE8CHf_.d.cts.map +0 -1
- package/dist/fs-DKHYTPua.cjs +0 -18
- package/dist/native-runtime-BoqybBBf.js +0 -18
- package/dist/native-runtime-BoqybBBf.js.map +0 -1
- package/dist/native.d.cts.map +0 -1
- package/dist/native.d.ts.map +0 -1
- package/dist/native.js.map +0 -1
- package/dist/runtime.d.cts.map +0 -1
- package/dist/runtime.d.ts.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -2,32 +2,100 @@
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { execFileSync, spawn, spawnSync } from "node:child_process";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
|
-
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
6
6
|
import http from "node:http";
|
|
7
7
|
import os from "node:os";
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
10
|
+
import { WebSocket, WebSocketServer } from "ws";
|
|
11
|
+
import yoctoSpinner from "yocto-spinner";
|
|
12
|
+
import { bold, dim, green, red, yellow } from "yoctocolors";
|
|
10
13
|
|
|
11
14
|
//#region src/cli.ts
|
|
12
15
|
const require = createRequire(import.meta.url);
|
|
13
16
|
const packageRoot = path.dirname(fileURLToPath(new URL("../package.json", import.meta.url)));
|
|
14
17
|
const packageJson = require("../package.json");
|
|
15
18
|
const runtimeVersion = packageJson.version;
|
|
16
|
-
|
|
19
|
+
function artifactPlatform() {
|
|
20
|
+
return `macos-${process.arch}`;
|
|
21
|
+
}
|
|
22
|
+
function prettyPath(value) {
|
|
23
|
+
const home = os.homedir();
|
|
24
|
+
return value === home || value.startsWith(`${home}${path.sep}`) ? `~${value.slice(home.length)}` : value;
|
|
25
|
+
}
|
|
26
|
+
function commandSucceeds(command, args) {
|
|
27
|
+
const result = spawnSync(command, args, { stdio: "ignore" });
|
|
28
|
+
return !result.error && result.status === 0;
|
|
29
|
+
}
|
|
30
|
+
function commandText(command, args) {
|
|
31
|
+
return [command, ...args].join(" ");
|
|
32
|
+
}
|
|
33
|
+
function doctorHint(projectRoot) {
|
|
34
|
+
return projectRoot ? `Run ${bold(`bleam doctor ${projectRoot}`)} for diagnostics.` : `Run ${bold("bleam doctor")} for diagnostics.`;
|
|
35
|
+
}
|
|
36
|
+
function appConfigBuildExample() {
|
|
37
|
+
return [
|
|
38
|
+
"Example:",
|
|
39
|
+
"import { appConfig } from 'bleam'",
|
|
40
|
+
"",
|
|
41
|
+
"export default appConfig({",
|
|
42
|
+
" name: 'My App',",
|
|
43
|
+
" bundleIdentifier: 'com.example.myapp',",
|
|
44
|
+
" teamId: 'ABCDE12345',",
|
|
45
|
+
"})"
|
|
46
|
+
].join("\n");
|
|
47
|
+
}
|
|
48
|
+
function missingBuildFieldError(field) {
|
|
49
|
+
return /* @__PURE__ */ new Error(`app.config.ts must define ${field} for bleam build.\n\n${appConfigBuildExample()}`);
|
|
50
|
+
}
|
|
51
|
+
function heading(text) {
|
|
52
|
+
return bold(text);
|
|
53
|
+
}
|
|
54
|
+
function muted(text) {
|
|
55
|
+
return dim(text);
|
|
56
|
+
}
|
|
57
|
+
function statusLabel(status) {
|
|
58
|
+
if (status === "pass") return green("[ok]");
|
|
59
|
+
if (status === "warn") return yellow("[warn]");
|
|
60
|
+
return red("[fail]");
|
|
61
|
+
}
|
|
62
|
+
function startSpinner(text) {
|
|
63
|
+
if (!process.stderr.isTTY) {
|
|
64
|
+
console.log(text);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
return yoctoSpinner({
|
|
68
|
+
text,
|
|
69
|
+
handleSignals: false
|
|
70
|
+
}).start();
|
|
71
|
+
}
|
|
17
72
|
function printUsage() {
|
|
18
73
|
console.log(`Usage: bleam <command>
|
|
19
74
|
|
|
20
75
|
Commands:
|
|
21
76
|
new [dir] [--run] Create a new Bleam project
|
|
22
|
-
dev [dir] [--port <port>]
|
|
77
|
+
dev [dir] [--port <port>] [--run]
|
|
78
|
+
Start a Bleam dev server
|
|
79
|
+
build [dir] [--output <dir>]
|
|
80
|
+
Build App Store-ready native archives
|
|
81
|
+
doctor [dir] Check the local Bleam environment
|
|
82
|
+
check [dir] [--write] Format, lint, and organize imports
|
|
83
|
+
format [dir] [--check] Format project files
|
|
84
|
+
lint [dir] Lint project files`);
|
|
23
85
|
}
|
|
24
86
|
function invocationRoot() {
|
|
25
|
-
|
|
87
|
+
const pwd = process.env.PWD;
|
|
88
|
+
return pwd && path.isAbsolute(pwd) ? pwd : process.cwd();
|
|
89
|
+
}
|
|
90
|
+
function canonicalPath(value) {
|
|
91
|
+
const resolved = path.resolve(value);
|
|
92
|
+
return existsSync(resolved) ? realpathSync.native(resolved) : resolved;
|
|
26
93
|
}
|
|
27
94
|
function parseDevOptions(argv) {
|
|
28
95
|
const root = invocationRoot();
|
|
29
96
|
let projectRoot = root;
|
|
30
97
|
let port = 8081;
|
|
98
|
+
let run = false;
|
|
31
99
|
let hasProjectRootArg = false;
|
|
32
100
|
for (let index = 0; index < argv.length; index += 1) {
|
|
33
101
|
const arg = argv[index];
|
|
@@ -40,6 +108,10 @@ function parseDevOptions(argv) {
|
|
|
40
108
|
port = Number(arg.slice(7));
|
|
41
109
|
continue;
|
|
42
110
|
}
|
|
111
|
+
if (arg === "--run") {
|
|
112
|
+
run = true;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
43
115
|
if (arg === "--help" || arg === "-h") {
|
|
44
116
|
printUsage();
|
|
45
117
|
process.exit(0);
|
|
@@ -51,8 +123,9 @@ function parseDevOptions(argv) {
|
|
|
51
123
|
if (!Number.isInteger(port) || port <= 0) throw new Error(`Invalid port: ${port}`);
|
|
52
124
|
if (!hasProjectRootArg && !isBleamProjectRoot(projectRoot)) projectRoot = discoverBleamProjectRoot(projectRoot) ?? projectRoot;
|
|
53
125
|
return {
|
|
54
|
-
projectRoot:
|
|
55
|
-
port
|
|
126
|
+
projectRoot: canonicalPath(projectRoot),
|
|
127
|
+
port,
|
|
128
|
+
run
|
|
56
129
|
};
|
|
57
130
|
}
|
|
58
131
|
function parseNewOptions(argv) {
|
|
@@ -72,10 +145,108 @@ function parseNewOptions(argv) {
|
|
|
72
145
|
projectRoot = path.resolve(root, arg);
|
|
73
146
|
}
|
|
74
147
|
return {
|
|
75
|
-
projectRoot,
|
|
148
|
+
projectRoot: canonicalPath(projectRoot),
|
|
76
149
|
run
|
|
77
150
|
};
|
|
78
151
|
}
|
|
152
|
+
function parseBuildOptions(argv) {
|
|
153
|
+
const root = invocationRoot();
|
|
154
|
+
let projectRoot = root;
|
|
155
|
+
let hasProjectRootArg = false;
|
|
156
|
+
let output;
|
|
157
|
+
let configuration = "Release";
|
|
158
|
+
let exportOptionsPlist;
|
|
159
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
160
|
+
const arg = argv[index];
|
|
161
|
+
if (arg === "--output" || arg === "-o") {
|
|
162
|
+
output = argv[++index];
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (arg.startsWith("--output=")) {
|
|
166
|
+
output = arg.slice(9);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (arg === "--configuration") {
|
|
170
|
+
const value = argv[++index];
|
|
171
|
+
if (!value) throw new Error("Missing --configuration value");
|
|
172
|
+
configuration = value;
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
if (arg.startsWith("--configuration=")) {
|
|
176
|
+
configuration = arg.slice(16);
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (arg === "--export-options-plist") {
|
|
180
|
+
exportOptionsPlist = argv[++index];
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (arg.startsWith("--export-options-plist=")) {
|
|
184
|
+
exportOptionsPlist = arg.slice(23);
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
if (arg === "--help" || arg === "-h") {
|
|
188
|
+
printUsage();
|
|
189
|
+
process.exit(0);
|
|
190
|
+
}
|
|
191
|
+
if (arg.startsWith("-")) throw new Error(`Unknown option: ${arg}`);
|
|
192
|
+
projectRoot = path.resolve(root, arg);
|
|
193
|
+
hasProjectRootArg = true;
|
|
194
|
+
}
|
|
195
|
+
if (!hasProjectRootArg && !isBleamProjectRoot(projectRoot)) projectRoot = discoverBleamProjectRoot(projectRoot) ?? projectRoot;
|
|
196
|
+
const resolvedProjectRoot = canonicalPath(projectRoot);
|
|
197
|
+
return {
|
|
198
|
+
projectRoot: resolvedProjectRoot,
|
|
199
|
+
output: path.resolve(resolvedProjectRoot, output ?? "dist"),
|
|
200
|
+
configuration,
|
|
201
|
+
exportOptionsPlist: exportOptionsPlist ? path.resolve(root, exportOptionsPlist) : void 0
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function parseProjectToolOptions(argv) {
|
|
205
|
+
const root = invocationRoot();
|
|
206
|
+
let projectRoot = root;
|
|
207
|
+
let hasProjectRootArg = false;
|
|
208
|
+
let write = false;
|
|
209
|
+
let formatCheck = false;
|
|
210
|
+
for (const arg of argv) {
|
|
211
|
+
if (arg === "--write") {
|
|
212
|
+
write = true;
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
if (arg === "--check") {
|
|
216
|
+
formatCheck = true;
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (arg === "--help" || arg === "-h") {
|
|
220
|
+
printUsage();
|
|
221
|
+
process.exit(0);
|
|
222
|
+
}
|
|
223
|
+
if (arg.startsWith("-")) throw new Error(`Unknown option: ${arg}`);
|
|
224
|
+
projectRoot = path.resolve(root, arg);
|
|
225
|
+
hasProjectRootArg = true;
|
|
226
|
+
}
|
|
227
|
+
if (!hasProjectRootArg && !isBleamProjectRoot(projectRoot)) projectRoot = discoverBleamProjectRoot(projectRoot) ?? projectRoot;
|
|
228
|
+
return {
|
|
229
|
+
projectRoot: canonicalPath(projectRoot),
|
|
230
|
+
write,
|
|
231
|
+
formatCheck
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function parseDoctorOptions(argv) {
|
|
235
|
+
const root = invocationRoot();
|
|
236
|
+
let projectRoot = root;
|
|
237
|
+
let hasProjectRootArg = false;
|
|
238
|
+
for (const arg of argv) {
|
|
239
|
+
if (arg === "--help" || arg === "-h") {
|
|
240
|
+
printUsage();
|
|
241
|
+
process.exit(0);
|
|
242
|
+
}
|
|
243
|
+
if (arg.startsWith("-")) throw new Error(`Unknown option: ${arg}`);
|
|
244
|
+
projectRoot = path.resolve(root, arg);
|
|
245
|
+
hasProjectRootArg = true;
|
|
246
|
+
}
|
|
247
|
+
if (!hasProjectRootArg && !isBleamProjectRoot(projectRoot)) projectRoot = discoverBleamProjectRoot(projectRoot) ?? projectRoot;
|
|
248
|
+
return { projectRoot: canonicalPath(projectRoot) };
|
|
249
|
+
}
|
|
79
250
|
function parseInternalMetroOptions(argv) {
|
|
80
251
|
let workspaceRoot;
|
|
81
252
|
let port = 8081;
|
|
@@ -139,6 +310,23 @@ function assertStringField(value, field) {
|
|
|
139
310
|
if (typeof value !== "string" || value.trim() === "") throw new Error(`app.config.ts must define ${field}`);
|
|
140
311
|
return value;
|
|
141
312
|
}
|
|
313
|
+
function isHexColor(value) {
|
|
314
|
+
return typeof value === "string" && /^#[\da-f]{6}$/i.test(value);
|
|
315
|
+
}
|
|
316
|
+
function normalizeAppearance(value) {
|
|
317
|
+
const input = value && typeof value === "object" ? value : {};
|
|
318
|
+
const window = input.window && typeof input.window === "object" ? input.window : {};
|
|
319
|
+
const appearance = {};
|
|
320
|
+
if (window.backgroundColor !== void 0) {
|
|
321
|
+
if (!isHexColor(window.backgroundColor)) throw new Error("app.config.ts appearance.window.backgroundColor must be a #rrggbb color");
|
|
322
|
+
appearance.window = { backgroundColor: window.backgroundColor };
|
|
323
|
+
}
|
|
324
|
+
if (input.userInterfaceStyle !== void 0) {
|
|
325
|
+
if (input.userInterfaceStyle !== "automatic" && input.userInterfaceStyle !== "light" && input.userInterfaceStyle !== "dark") throw new Error("app.config.ts appearance.userInterfaceStyle must be automatic, light, or dark");
|
|
326
|
+
appearance.userInterfaceStyle = input.userInterfaceStyle;
|
|
327
|
+
}
|
|
328
|
+
return appearance;
|
|
329
|
+
}
|
|
142
330
|
function loadAppConfig(projectRoot) {
|
|
143
331
|
const configPath = path.join(projectRoot, "app.config.ts");
|
|
144
332
|
const loader = `
|
|
@@ -168,8 +356,10 @@ function loadAppConfig(projectRoot) {
|
|
|
168
356
|
return {
|
|
169
357
|
name: assertStringField(value.name, "name"),
|
|
170
358
|
version: typeof value.version === "string" ? value.version : void 0,
|
|
359
|
+
buildNumber: typeof value.buildNumber === "string" ? value.buildNumber : void 0,
|
|
171
360
|
bundleIdentifier: typeof value.bundleIdentifier === "string" ? value.bundleIdentifier : void 0,
|
|
172
|
-
teamId: typeof value.teamId === "string" ? value.teamId : void 0
|
|
361
|
+
teamId: typeof value.teamId === "string" ? value.teamId : void 0,
|
|
362
|
+
appearance: normalizeAppearance(value.appearance)
|
|
173
363
|
};
|
|
174
364
|
}
|
|
175
365
|
function assertBleamConfigFiles(projectRoot) {
|
|
@@ -188,8 +378,10 @@ function readProjectConfig(options) {
|
|
|
188
378
|
return {
|
|
189
379
|
name: config.name,
|
|
190
380
|
version: config.version,
|
|
381
|
+
buildNumber: config.buildNumber ?? "1",
|
|
191
382
|
bundleIdentifier: config.bundleIdentifier,
|
|
192
383
|
teamId: config.teamId,
|
|
384
|
+
appearance: config.appearance ?? normalizeAppearance(void 0),
|
|
193
385
|
runtimeVersion,
|
|
194
386
|
sdkVersion: runtimeVersion
|
|
195
387
|
};
|
|
@@ -202,6 +394,9 @@ function nameFromDirectory(projectRoot) {
|
|
|
202
394
|
if (!name) return "Bleam App";
|
|
203
395
|
return name.replace(/\b\w/g, (letter) => letter.toUpperCase());
|
|
204
396
|
}
|
|
397
|
+
function singleQuotedString(value) {
|
|
398
|
+
return `'${value.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/\r/g, "\\r").replace(/\n/g, "\\n")}'`;
|
|
399
|
+
}
|
|
205
400
|
function createNewProject(options) {
|
|
206
401
|
const templateRoot = path.join(packageRoot, "templates", "basic");
|
|
207
402
|
if (!existsSync(templateRoot)) throw new Error(`Missing basic template: ${templateRoot}`);
|
|
@@ -209,10 +404,12 @@ function createNewProject(options) {
|
|
|
209
404
|
mkdirSync(options.projectRoot, { recursive: true });
|
|
210
405
|
cpSync(templateRoot, options.projectRoot, { recursive: true });
|
|
211
406
|
const name = nameFromDirectory(options.projectRoot);
|
|
212
|
-
writeFileSync(path.join(options.projectRoot, "app.config.ts"), `
|
|
213
|
-
writeFileSync(path.join(options.projectRoot, ".gitignore"), `.bleam\n`);
|
|
407
|
+
writeFileSync(path.join(options.projectRoot, "app.config.ts"), `import { appConfig } from 'bleam'\n\nexport default appConfig({\n name: ${singleQuotedString(name)},\n})\n`);
|
|
408
|
+
writeFileSync(path.join(options.projectRoot, ".gitignore"), `.bleam\nbiome.json\n.DS_Store\n`);
|
|
214
409
|
createDevWorkspace(options.projectRoot, {
|
|
215
410
|
name,
|
|
411
|
+
buildNumber: "1",
|
|
412
|
+
appearance: normalizeAppearance(void 0),
|
|
216
413
|
runtimeVersion,
|
|
217
414
|
sdkVersion: runtimeVersion
|
|
218
415
|
});
|
|
@@ -235,7 +432,13 @@ function createDevWorkspace(projectRoot, config) {
|
|
|
235
432
|
version: config.version ?? "0.0.0",
|
|
236
433
|
orientation: "default",
|
|
237
434
|
platforms: ["ios"],
|
|
238
|
-
newArchEnabled: true
|
|
435
|
+
newArchEnabled: true,
|
|
436
|
+
extra: { bleam: {
|
|
437
|
+
appearance: config.appearance,
|
|
438
|
+
buildNumber: config.buildNumber,
|
|
439
|
+
runtimeVersion: config.runtimeVersion,
|
|
440
|
+
sdkVersion: config.sdkVersion
|
|
441
|
+
} }
|
|
239
442
|
} }, null, 2)}\n`);
|
|
240
443
|
writeFileSync(path.join(workspaceRoot, "index.js"), `import { registerApp } from 'bleam/app'\nimport App from ${JSON.stringify(path.join(projectRoot, "app"))}\n\nregisterApp(App)\n`);
|
|
241
444
|
writeFileSync(path.join(workspaceRoot, "metro.config.js"), `const { getDefaultConfig } = require(${JSON.stringify(path.join(packageRoot, "metro-config.cjs"))})\n\nmodule.exports = getDefaultConfig(__dirname)\n`);
|
|
@@ -246,6 +449,7 @@ function createDevWorkspace(projectRoot, config) {
|
|
|
246
449
|
main: "index.js",
|
|
247
450
|
dependencies: {
|
|
248
451
|
"@types/react": packageJson.dependencies?.["@types/react"],
|
|
452
|
+
"@biomejs/biome": packageJson.dependencies?.["@biomejs/biome"],
|
|
249
453
|
expo: packageJson.dependencies?.expo,
|
|
250
454
|
react: packageJson.dependencies?.react,
|
|
251
455
|
"react-native": packageJson.dependencies?.["react-native"],
|
|
@@ -256,8 +460,8 @@ function createDevWorkspace(projectRoot, config) {
|
|
|
256
460
|
writeFileSync(path.join(workspaceRoot, "tsconfig.json"), `${JSON.stringify({
|
|
257
461
|
extends: "bleam/tsconfig",
|
|
258
462
|
compilerOptions: { paths: {
|
|
259
|
-
bleam: ["./node_modules/bleam"],
|
|
260
|
-
"bleam/*": ["./node_modules/bleam/*"],
|
|
463
|
+
bleam: ["./node_modules/bleam/dist/index"],
|
|
464
|
+
"bleam/*": ["./node_modules/bleam/dist/*"],
|
|
261
465
|
expo: ["./node_modules/expo"],
|
|
262
466
|
"expo/*": ["./node_modules/expo/*"],
|
|
263
467
|
react: ["./node_modules/@types/react"],
|
|
@@ -270,6 +474,34 @@ function createDevWorkspace(projectRoot, config) {
|
|
|
270
474
|
}, null, 2)}\n`);
|
|
271
475
|
return workspaceRoot;
|
|
272
476
|
}
|
|
477
|
+
function writeBiomeConfig(configPath) {
|
|
478
|
+
writeFileSync(configPath, `${JSON.stringify({
|
|
479
|
+
$schema: "https://biomejs.dev/schemas/2.5.2/schema.json",
|
|
480
|
+
files: { includes: [
|
|
481
|
+
"app/**/*",
|
|
482
|
+
"app.config.ts",
|
|
483
|
+
"tsconfig.json"
|
|
484
|
+
] },
|
|
485
|
+
formatter: {
|
|
486
|
+
enabled: true,
|
|
487
|
+
indentStyle: "space",
|
|
488
|
+
indentWidth: 2,
|
|
489
|
+
lineWidth: 80
|
|
490
|
+
},
|
|
491
|
+
javascript: { formatter: {
|
|
492
|
+
quoteStyle: "single",
|
|
493
|
+
semicolons: "asNeeded",
|
|
494
|
+
trailingCommas: "all"
|
|
495
|
+
} },
|
|
496
|
+
linter: {
|
|
497
|
+
enabled: true,
|
|
498
|
+
rules: {
|
|
499
|
+
preset: "recommended",
|
|
500
|
+
suspicious: { noExplicitAny: "off" }
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}, null, 2)}\n`);
|
|
504
|
+
}
|
|
273
505
|
function writeProjectRuntimeConfig(projectRoot, config, origin) {
|
|
274
506
|
const projectConfigPath = path.join(projectRoot, ".bleam", "project.json");
|
|
275
507
|
mkdirSync(path.dirname(projectConfigPath), { recursive: true });
|
|
@@ -278,28 +510,220 @@ function writeProjectRuntimeConfig(projectRoot, config, origin) {
|
|
|
278
510
|
version: config.version,
|
|
279
511
|
bundleIdentifier: config.bundleIdentifier,
|
|
280
512
|
teamId: config.teamId,
|
|
513
|
+
appearance: config.appearance,
|
|
281
514
|
devServer: origin,
|
|
282
515
|
runtimeVersion: config.runtimeVersion,
|
|
283
516
|
sdkVersion: config.sdkVersion
|
|
284
517
|
}, null, 2)}\n`);
|
|
285
518
|
return projectConfigPath;
|
|
286
519
|
}
|
|
520
|
+
function nativeRuntimeTemplateRoot() {
|
|
521
|
+
return path.resolve(packageRoot, "..", "..", "app", "bleam");
|
|
522
|
+
}
|
|
523
|
+
function safeArtifactName(name) {
|
|
524
|
+
return name.trim().replace(/[/:\\]/g, "-").replace(/\s+/g, " ") || "App";
|
|
525
|
+
}
|
|
526
|
+
function xcodeSettingValue(value) {
|
|
527
|
+
if (/^[A-Za-z0-9_.$-]+$/.test(value)) return value;
|
|
528
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
|
|
529
|
+
}
|
|
530
|
+
function plistString(value) {
|
|
531
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
532
|
+
}
|
|
533
|
+
function replacePlistString(plist, key, value) {
|
|
534
|
+
const pattern = /* @__PURE__ */ new RegExp(`(<key>${key}</key>\\s*<string>)([^<]*)(</string>)`);
|
|
535
|
+
if (!pattern.test(plist)) return plist;
|
|
536
|
+
return plist.replace(pattern, `$1${plistString(value)}$3`);
|
|
537
|
+
}
|
|
538
|
+
function writeGeneratedAppJson(nativeRoot, config) {
|
|
539
|
+
writeFileSync(path.join(nativeRoot, "app.json"), `${JSON.stringify({ expo: {
|
|
540
|
+
name: config.name,
|
|
541
|
+
slug: slugFromName(config.name),
|
|
542
|
+
version: config.version ?? "1.0.0",
|
|
543
|
+
platforms: ["ios"],
|
|
544
|
+
ios: {
|
|
545
|
+
appleTeamId: config.teamId,
|
|
546
|
+
buildNumber: config.buildNumber,
|
|
547
|
+
bundleIdentifier: config.bundleIdentifier
|
|
548
|
+
}
|
|
549
|
+
} }, null, 2)}\n`);
|
|
550
|
+
}
|
|
551
|
+
function patchNativeProject(nativeRoot, config) {
|
|
552
|
+
const projectPath = path.join(nativeRoot, "ios", "Bleam.xcodeproj", "project.pbxproj");
|
|
553
|
+
const infoPlistPath = path.join(nativeRoot, "ios", "Bleam", "Info.plist");
|
|
554
|
+
const productName = xcodeSettingValue(config.name);
|
|
555
|
+
const bundleIdentifier = xcodeSettingValue(config.bundleIdentifier ?? "");
|
|
556
|
+
const teamId = xcodeSettingValue(config.teamId ?? "");
|
|
557
|
+
const version = xcodeSettingValue(config.version ?? "1.0.0");
|
|
558
|
+
const buildNumber = xcodeSettingValue(config.buildNumber);
|
|
559
|
+
let project = readFileSync(projectPath, "utf8");
|
|
560
|
+
project = project.replace(/PRODUCT_BUNDLE_IDENTIFIER = [^;]+;/g, () => {
|
|
561
|
+
return `PRODUCT_BUNDLE_IDENTIFIER = ${bundleIdentifier};`;
|
|
562
|
+
}).replace(/DEVELOPMENT_TEAM = [^;]+;/g, () => {
|
|
563
|
+
return `DEVELOPMENT_TEAM = ${teamId};`;
|
|
564
|
+
}).replace(/MARKETING_VERSION = [^;]+;/g, () => {
|
|
565
|
+
return `MARKETING_VERSION = ${version};`;
|
|
566
|
+
}).replace(/CURRENT_PROJECT_VERSION = [^;]+;/g, () => {
|
|
567
|
+
return `CURRENT_PROJECT_VERSION = ${buildNumber};`;
|
|
568
|
+
}).replace(/PRODUCT_NAME = [^;]+;/g, () => {
|
|
569
|
+
return `PRODUCT_NAME = ${productName};`;
|
|
570
|
+
});
|
|
571
|
+
writeFileSync(projectPath, project);
|
|
572
|
+
let infoPlist = readFileSync(infoPlistPath, "utf8");
|
|
573
|
+
infoPlist = replacePlistString(infoPlist, "CFBundleDisplayName", config.name);
|
|
574
|
+
infoPlist = replacePlistString(infoPlist, "CFBundleShortVersionString", config.version ?? "1.0.0");
|
|
575
|
+
infoPlist = replacePlistString(infoPlist, "CFBundleVersion", config.buildNumber);
|
|
576
|
+
writeFileSync(infoPlistPath, infoPlist);
|
|
577
|
+
}
|
|
578
|
+
function createBuildNativeWorkspace(options, config) {
|
|
579
|
+
const nativeRoot = path.join(options.projectRoot, ".bleam", "build", "native");
|
|
580
|
+
const templateRoot = nativeRuntimeTemplateRoot();
|
|
581
|
+
rmSync(nativeRoot, {
|
|
582
|
+
recursive: true,
|
|
583
|
+
force: true
|
|
584
|
+
});
|
|
585
|
+
mkdirSync(path.dirname(nativeRoot), { recursive: true });
|
|
586
|
+
cpSync(templateRoot, nativeRoot, {
|
|
587
|
+
recursive: true,
|
|
588
|
+
filter(source) {
|
|
589
|
+
return !path.relative(templateRoot, source).split(path.sep).some((part) => {
|
|
590
|
+
return part === "build" || part === "dist" || part === "node_modules" || part === ".expo" || part === "Pods" || part === ".xcode.env.local" || part === ".DS_Store" || part.endsWith(".xcworkspace");
|
|
591
|
+
});
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
const nodeModules = path.join(nativeRoot, "node_modules");
|
|
595
|
+
rmSync(nodeModules, {
|
|
596
|
+
recursive: true,
|
|
597
|
+
force: true
|
|
598
|
+
});
|
|
599
|
+
symlinkSync(resolvedDependencyRoot(), nodeModules);
|
|
600
|
+
writeGeneratedAppJson(nativeRoot, config);
|
|
601
|
+
writeFileSync(path.join(nativeRoot, "index.ts"), `import { registerApp } from 'bleam/app'\nimport App from ${JSON.stringify(path.join(options.projectRoot, "app"))}\n\nregisterApp(App)\n`);
|
|
602
|
+
writeFileSync(path.join(nativeRoot, "metro.config.js"), `const { getDefaultConfig } = require(${JSON.stringify(path.join(packageRoot, "metro-config.cjs"))})\n\nmodule.exports = getDefaultConfig(__dirname)\n`);
|
|
603
|
+
writeFileSync(path.join(nativeRoot, "ios", ".xcode.env"), `export NODE_BINARY=$(command -v node)\nexport BLEAM_PROJECT_ROOT=${singleQuotedString(options.projectRoot)}\nexport BLEAM_DEV_PLATFORM=macos\n`);
|
|
604
|
+
patchNativeProject(nativeRoot, config);
|
|
605
|
+
return nativeRoot;
|
|
606
|
+
}
|
|
607
|
+
function preflightBuild(options, config) {
|
|
608
|
+
if (process.platform !== "darwin") throw new Error(`bleam build requires macOS and Xcode. Current platform: ${process.platform}.\n${doctorHint(options.projectRoot)}`);
|
|
609
|
+
if (!config.bundleIdentifier) throw missingBuildFieldError("bundleIdentifier");
|
|
610
|
+
if (!config.teamId) throw missingBuildFieldError("teamId");
|
|
611
|
+
const templateRoot = nativeRuntimeTemplateRoot();
|
|
612
|
+
if (!existsSync(templateRoot)) throw new Error(`Missing native runtime template: ${templateRoot}\n${doctorHint(options.projectRoot)}`);
|
|
613
|
+
if (!commandSucceeds("pod", ["--version"])) throw new Error(`CocoaPods is required for bleam build, but ${bold("pod")} is unavailable.\nInstall CocoaPods, then run bleam build again.\n${doctorHint(options.projectRoot)}`);
|
|
614
|
+
if (!commandSucceeds("xcodebuild", ["-version"])) throw new Error(`Xcode command line tools are required for bleam build, but ${bold("xcodebuild")} is unavailable.\nInstall Xcode or run ${bold("xcode-select --install")}, then run bleam build again.\n${doctorHint(options.projectRoot)}`);
|
|
615
|
+
}
|
|
616
|
+
function runInheritedCommand(command, args, cwd) {
|
|
617
|
+
const text = commandText(command, args);
|
|
618
|
+
const result = spawnSync(command, args, {
|
|
619
|
+
cwd,
|
|
620
|
+
stdio: "inherit",
|
|
621
|
+
env: process.env
|
|
622
|
+
});
|
|
623
|
+
if (result.error) throw new Error(`${text} could not start in ${cwd}: ${result.error.message}\n${doctorHint()}`);
|
|
624
|
+
if (result.status !== 0) throw new Error(`${text} failed in ${cwd} with exit code ${result.status ?? "unknown"}.\nNative command output above may contain the underlying Xcode/CocoaPods error.\n${doctorHint()}`);
|
|
625
|
+
}
|
|
626
|
+
function installPods(nativeRoot) {
|
|
627
|
+
console.log("Installing native dependencies...");
|
|
628
|
+
runInheritedCommand("pod", ["install"], path.join(nativeRoot, "ios"));
|
|
629
|
+
}
|
|
630
|
+
function archiveNativeApp(options) {
|
|
631
|
+
const platformOutput = path.join(options.outputRoot, "macos");
|
|
632
|
+
const archivePath = path.join(platformOutput, `${safeArtifactName(options.config.name)}.xcarchive`);
|
|
633
|
+
mkdirSync(platformOutput, { recursive: true });
|
|
634
|
+
rmSync(archivePath, {
|
|
635
|
+
recursive: true,
|
|
636
|
+
force: true
|
|
637
|
+
});
|
|
638
|
+
console.log(`Archiving ${options.config.name} for macOS...`);
|
|
639
|
+
runInheritedCommand("xcodebuild", [
|
|
640
|
+
"-allowProvisioningUpdates",
|
|
641
|
+
"-workspace",
|
|
642
|
+
path.join(options.nativeRoot, "ios", "Bleam.xcworkspace"),
|
|
643
|
+
"-scheme",
|
|
644
|
+
"bleam",
|
|
645
|
+
"-configuration",
|
|
646
|
+
options.configuration,
|
|
647
|
+
"-destination",
|
|
648
|
+
"platform=macOS,arch=arm64,variant=Mac Catalyst",
|
|
649
|
+
"-archivePath",
|
|
650
|
+
archivePath,
|
|
651
|
+
"archive"
|
|
652
|
+
], options.nativeRoot);
|
|
653
|
+
return archivePath;
|
|
654
|
+
}
|
|
655
|
+
function exportNativeArchive(options) {
|
|
656
|
+
const exportPath = path.join(options.outputRoot, "macos", "export");
|
|
657
|
+
rmSync(exportPath, {
|
|
658
|
+
recursive: true,
|
|
659
|
+
force: true
|
|
660
|
+
});
|
|
661
|
+
mkdirSync(exportPath, { recursive: true });
|
|
662
|
+
console.log("Exporting macOS archive...");
|
|
663
|
+
runInheritedCommand("xcodebuild", [
|
|
664
|
+
"-allowProvisioningUpdates",
|
|
665
|
+
"-exportArchive",
|
|
666
|
+
"-archivePath",
|
|
667
|
+
options.archivePath,
|
|
668
|
+
"-exportPath",
|
|
669
|
+
exportPath,
|
|
670
|
+
"-exportOptionsPlist",
|
|
671
|
+
options.exportOptionsPlist
|
|
672
|
+
], path.dirname(options.archivePath));
|
|
673
|
+
return exportPath;
|
|
674
|
+
}
|
|
675
|
+
async function buildNativeArchives(options) {
|
|
676
|
+
const config = readProjectConfig(options);
|
|
677
|
+
preflightBuild(options, config);
|
|
678
|
+
const nativeRoot = createBuildNativeWorkspace(options, config);
|
|
679
|
+
installPods(nativeRoot);
|
|
680
|
+
const archivePath = archiveNativeApp({
|
|
681
|
+
nativeRoot,
|
|
682
|
+
outputRoot: options.output,
|
|
683
|
+
configuration: options.configuration,
|
|
684
|
+
config
|
|
685
|
+
});
|
|
686
|
+
console.log(`Created ${archivePath}`);
|
|
687
|
+
if (options.exportOptionsPlist) {
|
|
688
|
+
const exportPath = exportNativeArchive({
|
|
689
|
+
archivePath,
|
|
690
|
+
outputRoot: options.output,
|
|
691
|
+
exportOptionsPlist: options.exportOptionsPlist
|
|
692
|
+
});
|
|
693
|
+
console.log(`Exported ${exportPath}`);
|
|
694
|
+
}
|
|
695
|
+
}
|
|
287
696
|
function runtimeCacheRoot() {
|
|
288
|
-
return path.join(os.homedir(), "Library", "Caches", "bleam", "runtimes", runtimeVersion,
|
|
697
|
+
return path.join(os.homedir(), "Library", "Caches", "bleam", "runtimes", runtimeVersion, artifactPlatform());
|
|
289
698
|
}
|
|
290
699
|
function localDevelopmentRuntimeAppPath() {
|
|
291
|
-
|
|
700
|
+
const productsRoot = path.resolve(packageRoot, "..", "..", "app", "bleam", "build", "Build", "Products", "Debug-maccatalyst");
|
|
701
|
+
for (const appName of ["Bleam.app", "bleam.app"]) {
|
|
702
|
+
const appPath = path.join(productsRoot, appName);
|
|
703
|
+
if (existsSync(appPath)) return appPath;
|
|
704
|
+
}
|
|
705
|
+
return path.join(productsRoot, "Bleam.app");
|
|
292
706
|
}
|
|
293
707
|
function runtimeReleaseBaseUrl() {
|
|
294
708
|
return process.env.BLEAM_RUNTIME_RELEASE_BASE_URL ?? "https://github.com/bajedev/bleam-app/releases/download";
|
|
295
709
|
}
|
|
296
710
|
function runtimeArchiveName() {
|
|
297
|
-
return `bleam-runtime-v${runtimeVersion}-${
|
|
711
|
+
return `bleam-runtime-v${runtimeVersion}-${artifactPlatform()}.zip`;
|
|
298
712
|
}
|
|
299
713
|
function runtimeArchiveUrl() {
|
|
300
714
|
const tag = encodeURIComponent(`bleam@${runtimeVersion}`);
|
|
301
715
|
return `${runtimeReleaseBaseUrl()}/${tag}/${runtimeArchiveName()}`;
|
|
302
716
|
}
|
|
717
|
+
function runtimeResolutionDetails() {
|
|
718
|
+
return [
|
|
719
|
+
`Runtime version: ${runtimeVersion}`,
|
|
720
|
+
`Runtime platform: ${artifactPlatform()}`,
|
|
721
|
+
`Runtime cache: ${runtimeCacheRoot()}`,
|
|
722
|
+
`Release URL: ${runtimeArchiveUrl()}`,
|
|
723
|
+
`Override with BLEAM_RUNTIME_APP=/path/to/Bleam.app for local testing.`,
|
|
724
|
+
doctorHint()
|
|
725
|
+
].join("\n");
|
|
726
|
+
}
|
|
303
727
|
function sha256(filePath) {
|
|
304
728
|
return createHash("sha256").update(readFileSync(filePath)).digest("hex");
|
|
305
729
|
}
|
|
@@ -314,7 +738,8 @@ async function downloadExpectedSha256(url) {
|
|
|
314
738
|
return (await response.text()).trim().split(/\s+/)[0];
|
|
315
739
|
}
|
|
316
740
|
async function downloadRuntimeArtifact() {
|
|
317
|
-
if (process.platform !== "darwin") throw new Error("Bleam runtime artifacts are currently only available
|
|
741
|
+
if (process.platform !== "darwin") throw new Error("Bleam runtime artifacts are currently only available from macOS hosts.");
|
|
742
|
+
const runtimePlatform = artifactPlatform();
|
|
318
743
|
const cacheRoot = runtimeCacheRoot();
|
|
319
744
|
const cachedAppPath = path.join(cacheRoot, "Bleam.app");
|
|
320
745
|
if (existsSync(cachedAppPath)) return {
|
|
@@ -361,10 +786,11 @@ async function downloadRuntimeArtifact() {
|
|
|
361
786
|
};
|
|
362
787
|
}
|
|
363
788
|
async function resolveRuntimeArtifact() {
|
|
789
|
+
const runtimePlatform = artifactPlatform();
|
|
364
790
|
const overrideAppPath = process.env.BLEAM_RUNTIME_APP;
|
|
365
791
|
if (overrideAppPath) {
|
|
366
792
|
const appPath = path.resolve(overrideAppPath);
|
|
367
|
-
if (!existsSync(appPath)) throw new Error(`BLEAM_RUNTIME_APP
|
|
793
|
+
if (!existsSync(appPath)) throw new Error(`BLEAM_RUNTIME_APP points to a missing app bundle: ${appPath}\nUnset BLEAM_RUNTIME_APP or point it to a valid Bleam.app.\n${doctorHint()}`);
|
|
368
794
|
return {
|
|
369
795
|
appPath,
|
|
370
796
|
version: runtimeVersion,
|
|
@@ -377,7 +803,11 @@ async function resolveRuntimeArtifact() {
|
|
|
377
803
|
version: runtimeVersion,
|
|
378
804
|
platform: runtimePlatform
|
|
379
805
|
};
|
|
380
|
-
|
|
806
|
+
try {
|
|
807
|
+
return await downloadRuntimeArtifact();
|
|
808
|
+
} catch (error) {
|
|
809
|
+
throw new Error(`Failed to resolve the Bleam runtime.\n${runtimeResolutionDetails()}\n\nCause: ${error instanceof Error ? error.message : String(error)}`);
|
|
810
|
+
}
|
|
381
811
|
}
|
|
382
812
|
function copyRuntimeClient(projectRoot, runtime) {
|
|
383
813
|
const clientAppPath = path.join(projectRoot, ".bleam", "client", "Bleam.app");
|
|
@@ -396,24 +826,104 @@ function isBleamManifest(value) {
|
|
|
396
826
|
async function readDevManifest(origin, timeoutMs = 3e4) {
|
|
397
827
|
const manifestUrl = `${origin}/bleam/manifest.json`;
|
|
398
828
|
const startedAt = Date.now();
|
|
399
|
-
|
|
829
|
+
const spinner = startSpinner("Waiting for Bleam dev server...");
|
|
400
830
|
while (Date.now() - startedAt <= timeoutMs) {
|
|
401
831
|
try {
|
|
402
832
|
const response = await fetch(manifestUrl, { cache: "no-store" });
|
|
403
833
|
const value = await response.json();
|
|
404
|
-
if (response.ok && isBleamManifest(value))
|
|
834
|
+
if (response.ok && isBleamManifest(value)) {
|
|
835
|
+
spinner?.success("Bleam dev server is ready");
|
|
836
|
+
return value;
|
|
837
|
+
}
|
|
405
838
|
} catch {}
|
|
406
839
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
407
840
|
}
|
|
841
|
+
spinner?.error("Bleam dev server did not become available");
|
|
408
842
|
throw new Error(`Bleam manifest did not become available: ${manifestUrl}`);
|
|
409
843
|
}
|
|
844
|
+
function pushDoctorCheck(checks, status, label, detail) {
|
|
845
|
+
checks.push({
|
|
846
|
+
status,
|
|
847
|
+
label,
|
|
848
|
+
detail
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
function printDoctorSection(title, checks) {
|
|
852
|
+
if (checks.length === 0) return;
|
|
853
|
+
console.log(`\n${heading(title)}`);
|
|
854
|
+
for (const check of checks) {
|
|
855
|
+
const detail = check.detail ? muted(`: ${check.detail}`) : "";
|
|
856
|
+
console.log(` ${statusLabel(check.status)} ${check.label}${detail}`);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
function runDoctor(options) {
|
|
860
|
+
const projectChecks = [];
|
|
861
|
+
const runtimeChecks = [];
|
|
862
|
+
const environmentChecks = [];
|
|
863
|
+
const appConfigPath = path.join(options.projectRoot, "app.config.ts");
|
|
864
|
+
const appEntryPath = path.join(options.projectRoot, "app", "index.tsx");
|
|
865
|
+
if (existsSync(appConfigPath)) pushDoctorCheck(projectChecks, "pass", "app.config.ts found");
|
|
866
|
+
else pushDoctorCheck(projectChecks, "fail", "app.config.ts missing");
|
|
867
|
+
if (existsSync(appEntryPath)) pushDoctorCheck(projectChecks, "pass", "app/index.tsx found");
|
|
868
|
+
else pushDoctorCheck(projectChecks, "fail", "app/index.tsx missing");
|
|
869
|
+
try {
|
|
870
|
+
const config = readProjectConfig(options);
|
|
871
|
+
pushDoctorCheck(projectChecks, "pass", "config loaded");
|
|
872
|
+
pushDoctorCheck(projectChecks, "pass", "name", config.name);
|
|
873
|
+
if (config.bundleIdentifier) pushDoctorCheck(projectChecks, "pass", "bundleIdentifier", config.bundleIdentifier);
|
|
874
|
+
else pushDoctorCheck(projectChecks, "warn", "bundleIdentifier not configured", "required for bleam build");
|
|
875
|
+
if (config.teamId) pushDoctorCheck(projectChecks, "pass", "teamId", config.teamId);
|
|
876
|
+
else pushDoctorCheck(projectChecks, "warn", "teamId not configured", "required for bleam build");
|
|
877
|
+
} catch (error) {
|
|
878
|
+
pushDoctorCheck(projectChecks, "fail", "config failed to load", error instanceof Error ? error.message : String(error));
|
|
879
|
+
}
|
|
880
|
+
const cacheRoot = runtimeCacheRoot();
|
|
881
|
+
const cachedAppPath = path.join(cacheRoot, "Bleam.app");
|
|
882
|
+
const localAppPath = localDevelopmentRuntimeAppPath();
|
|
883
|
+
pushDoctorCheck(runtimeChecks, "pass", "version", runtimeVersion);
|
|
884
|
+
pushDoctorCheck(runtimeChecks, "pass", "platform", artifactPlatform());
|
|
885
|
+
pushDoctorCheck(runtimeChecks, "pass", "cache", prettyPath(cacheRoot));
|
|
886
|
+
if (existsSync(cachedAppPath)) pushDoctorCheck(runtimeChecks, "pass", "cached runtime found");
|
|
887
|
+
else pushDoctorCheck(runtimeChecks, "warn", "runtime not cached yet", "bleam dev can download it on demand");
|
|
888
|
+
if (existsSync(localAppPath)) pushDoctorCheck(runtimeChecks, "pass", "local development runtime found", prettyPath(localAppPath));
|
|
889
|
+
else pushDoctorCheck(runtimeChecks, "warn", "local development runtime not found", prettyPath(localAppPath));
|
|
890
|
+
const overrideAppPath = process.env.BLEAM_RUNTIME_APP;
|
|
891
|
+
if (overrideAppPath) {
|
|
892
|
+
const appPath = path.resolve(overrideAppPath);
|
|
893
|
+
pushDoctorCheck(runtimeChecks, existsSync(appPath) ? "pass" : "fail", "BLEAM_RUNTIME_APP", prettyPath(appPath));
|
|
894
|
+
}
|
|
895
|
+
pushDoctorCheck(runtimeChecks, "pass", "release artifact URL", runtimeArchiveUrl());
|
|
896
|
+
pushDoctorCheck(environmentChecks, process.platform === "darwin" ? "pass" : "fail", "macOS host", process.platform);
|
|
897
|
+
pushDoctorCheck(environmentChecks, "pass", "node", prettyPath(process.execPath));
|
|
898
|
+
const hasXcodebuild = commandSucceeds("xcodebuild", ["-version"]);
|
|
899
|
+
pushDoctorCheck(environmentChecks, hasXcodebuild ? "pass" : "warn", "xcodebuild", hasXcodebuild ? "available" : "unavailable");
|
|
900
|
+
const hasPod = commandSucceeds("pod", ["--version"]);
|
|
901
|
+
pushDoctorCheck(environmentChecks, hasPod ? "pass" : "warn", "pod", hasPod ? "available" : "unavailable");
|
|
902
|
+
const allChecks = [
|
|
903
|
+
...projectChecks,
|
|
904
|
+
...runtimeChecks,
|
|
905
|
+
...environmentChecks
|
|
906
|
+
];
|
|
907
|
+
const counts = {
|
|
908
|
+
pass: allChecks.filter((check) => check.status === "pass").length,
|
|
909
|
+
warn: allChecks.filter((check) => check.status === "warn").length,
|
|
910
|
+
fail: allChecks.filter((check) => check.status === "fail").length
|
|
911
|
+
};
|
|
912
|
+
console.log(heading("Bleam Doctor"));
|
|
913
|
+
printDoctorSection("Project", projectChecks);
|
|
914
|
+
printDoctorSection("Runtime", runtimeChecks);
|
|
915
|
+
printDoctorSection("Environment", environmentChecks);
|
|
916
|
+
console.log(`\n${heading("Summary")}`);
|
|
917
|
+
console.log(` ${green(`${counts.pass} passed`)}, ${yellow(`${counts.warn} warnings`)}, ${counts.fail > 0 ? red(`${counts.fail} failed`) : green("0 failed")}`);
|
|
918
|
+
if (counts.fail > 0) process.exit(1);
|
|
919
|
+
}
|
|
410
920
|
function formatDuration(ms) {
|
|
411
921
|
return `${(ms / 1e3).toFixed(1)}s`;
|
|
412
922
|
}
|
|
413
923
|
async function waitForDevBundle(bundleUrl, timeoutMs = 6e4) {
|
|
414
924
|
const startedAt = Date.now();
|
|
415
925
|
const requestTimeoutMs = 3e4;
|
|
416
|
-
|
|
926
|
+
const spinner = startSpinner("Bundling app...");
|
|
417
927
|
while (Date.now() - startedAt <= timeoutMs) {
|
|
418
928
|
const requestStartedAt = Date.now();
|
|
419
929
|
try {
|
|
@@ -423,17 +933,27 @@ async function waitForDevBundle(bundleUrl, timeoutMs = 6e4) {
|
|
|
423
933
|
});
|
|
424
934
|
await response.body?.cancel();
|
|
425
935
|
if (response.ok) {
|
|
426
|
-
|
|
936
|
+
spinner?.success(`Bundled app in ${formatDuration(Date.now() - startedAt)}`);
|
|
937
|
+
if (!spinner) console.log(`Bundled app in ${formatDuration(Date.now() - startedAt)}`);
|
|
427
938
|
return;
|
|
428
939
|
}
|
|
429
|
-
|
|
940
|
+
if (spinner) spinner.text = `Bundle request returned ${response.status}, retrying...`;
|
|
941
|
+
else console.log(`Bundle request returned ${response.status}, retrying...`);
|
|
430
942
|
} catch (error) {
|
|
431
|
-
if (error instanceof Error && error.name === "TimeoutError")
|
|
432
|
-
|
|
943
|
+
if (error instanceof Error && error.name === "TimeoutError") {
|
|
944
|
+
const message = `Bundle request timed out after ${formatDuration(Date.now() - requestStartedAt)}, retrying...`;
|
|
945
|
+
if (spinner) spinner.text = message;
|
|
946
|
+
else console.log(message);
|
|
947
|
+
} else {
|
|
948
|
+
const message = `Bundle request failed: ${error instanceof Error ? error.message : String(error)}`;
|
|
949
|
+
if (spinner) spinner.text = `${message}, retrying...`;
|
|
950
|
+
else console.log(message);
|
|
951
|
+
}
|
|
433
952
|
}
|
|
434
953
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
435
954
|
}
|
|
436
|
-
|
|
955
|
+
spinner?.error("Bundle did not complete");
|
|
956
|
+
throw new Error(`Bleam bundle did not complete within ${formatDuration(timeoutMs)}.\nBundle URL: ${bundleUrl}\n${doctorHint()}`);
|
|
437
957
|
}
|
|
438
958
|
function openRuntimeClient(appPath, projectConfigPath, manifest) {
|
|
439
959
|
const child = spawn("open", [
|
|
@@ -454,7 +974,110 @@ function openRuntimeClient(appPath, projectConfigPath, manifest) {
|
|
|
454
974
|
if (code && code !== 0) console.error(`Failed to open Bleam runtime at ${appPath}`);
|
|
455
975
|
});
|
|
456
976
|
}
|
|
977
|
+
async function launchRuntimeClient(appPath, projectConfigPath, manifest) {
|
|
978
|
+
openRuntimeClient(appPath, projectConfigPath, manifest);
|
|
979
|
+
}
|
|
980
|
+
function focusRuntimeClient() {
|
|
981
|
+
return spawnSync("osascript", ["-e", "tell application id \"dev.bleam.app\" to activate"], { stdio: "ignore" }).status === 0;
|
|
982
|
+
}
|
|
983
|
+
function sendJson(res, status, value) {
|
|
984
|
+
res.writeHead(status, {
|
|
985
|
+
"Cache-Control": "no-store",
|
|
986
|
+
"Content-Type": "application/json; charset=utf-8"
|
|
987
|
+
});
|
|
988
|
+
res.end(JSON.stringify(value));
|
|
989
|
+
}
|
|
990
|
+
async function requestRuntimeReload(origin) {
|
|
991
|
+
const response = await fetch(`${origin}/bleam/reload`, {
|
|
992
|
+
method: "POST",
|
|
993
|
+
cache: "no-store"
|
|
994
|
+
});
|
|
995
|
+
const value = await response.json();
|
|
996
|
+
if (!response.ok) throw new Error(`Reload request failed: ${response.status}`);
|
|
997
|
+
const reload = value;
|
|
998
|
+
return typeof reload.clients === "number" ? reload.clients : 0;
|
|
999
|
+
}
|
|
1000
|
+
function biomeBinPath() {
|
|
1001
|
+
const biomePackageJsonPath = require.resolve("@biomejs/biome/package.json");
|
|
1002
|
+
const biomePackageRoot = path.dirname(biomePackageJsonPath);
|
|
1003
|
+
const biomePackage = require("@biomejs/biome/package.json");
|
|
1004
|
+
const bin = typeof biomePackage.bin === "string" ? biomePackage.bin : biomePackage.bin?.biome;
|
|
1005
|
+
if (!bin) throw new Error("Could not resolve @biomejs/biome binary");
|
|
1006
|
+
return path.join(biomePackageRoot, bin);
|
|
1007
|
+
}
|
|
1008
|
+
function ensureProjectToolWorkspace(options) {
|
|
1009
|
+
const config = readProjectConfig({ projectRoot: options.projectRoot });
|
|
1010
|
+
return createDevWorkspace(options.projectRoot, config);
|
|
1011
|
+
}
|
|
1012
|
+
function runBiomeCommand(command, options) {
|
|
1013
|
+
assertBleamConfigFiles(options.projectRoot);
|
|
1014
|
+
ensureProjectToolWorkspace(options);
|
|
1015
|
+
const configPath = path.join(options.projectRoot, "biome.json");
|
|
1016
|
+
const existingConfig = existsSync(configPath) ? readFileSync(configPath, "utf8") : void 0;
|
|
1017
|
+
const args = [
|
|
1018
|
+
command,
|
|
1019
|
+
"--config-path",
|
|
1020
|
+
"biome.json"
|
|
1021
|
+
];
|
|
1022
|
+
if (command === "check" && options.write) args.push("--write");
|
|
1023
|
+
if (command === "format" && !options.formatCheck) args.push("--write");
|
|
1024
|
+
args.push("app", "app.config.ts", "tsconfig.json");
|
|
1025
|
+
writeBiomeConfig(configPath);
|
|
1026
|
+
const result = spawnSync(biomeBinPath(), args, {
|
|
1027
|
+
cwd: options.projectRoot,
|
|
1028
|
+
stdio: "inherit"
|
|
1029
|
+
});
|
|
1030
|
+
if (existingConfig === void 0) rmSync(configPath, { force: true });
|
|
1031
|
+
else writeFileSync(configPath, existingConfig);
|
|
1032
|
+
if (result.error) throw result.error;
|
|
1033
|
+
process.exit(result.status ?? 1);
|
|
1034
|
+
}
|
|
1035
|
+
function setupInteractiveControls(options) {
|
|
1036
|
+
if (!process.stdin.isTTY) return () => {};
|
|
1037
|
+
const wasRaw = process.stdin.isRaw;
|
|
1038
|
+
let closed = false;
|
|
1039
|
+
const cleanup = () => {
|
|
1040
|
+
if (closed) return;
|
|
1041
|
+
closed = true;
|
|
1042
|
+
process.stdin.off("data", onData);
|
|
1043
|
+
process.stdin.setRawMode(wasRaw);
|
|
1044
|
+
};
|
|
1045
|
+
const onData = (data) => {
|
|
1046
|
+
for (const byte of data) {
|
|
1047
|
+
if (byte === 3) {
|
|
1048
|
+
cleanup();
|
|
1049
|
+
options.stop();
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
const key = String.fromCharCode(byte).toLowerCase();
|
|
1053
|
+
if (key === "o") {
|
|
1054
|
+
(async () => {
|
|
1055
|
+
try {
|
|
1056
|
+
if (!focusRuntimeClient()) {
|
|
1057
|
+
console.log("Opening Bleam app...");
|
|
1058
|
+
await launchRuntimeClient(options.clientAppPath, options.projectConfigPath, options.manifest);
|
|
1059
|
+
}
|
|
1060
|
+
} catch (error) {
|
|
1061
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
1062
|
+
}
|
|
1063
|
+
})();
|
|
1064
|
+
continue;
|
|
1065
|
+
}
|
|
1066
|
+
if (key === "r") requestRuntimeReload(options.origin).then((clients) => {
|
|
1067
|
+
console.log(`Reloaded app (${clients} client${clients === 1 ? "" : "s"})`);
|
|
1068
|
+
}).catch((error) => {
|
|
1069
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
};
|
|
1073
|
+
process.stdin.setRawMode(true);
|
|
1074
|
+
process.stdin.resume();
|
|
1075
|
+
process.stdin.on("data", onData);
|
|
1076
|
+
console.log("Press o to open, r to reload, Ctrl+C to stop.");
|
|
1077
|
+
return cleanup;
|
|
1078
|
+
}
|
|
457
1079
|
async function startInternalMetroServer(options) {
|
|
1080
|
+
process.env.BLEAM_DEV_PLATFORM ??= "macos";
|
|
458
1081
|
const metro = require("@expo/metro/metro");
|
|
459
1082
|
const { loadConfig } = require("@expo/metro/metro-config");
|
|
460
1083
|
const config = await loadConfig({
|
|
@@ -466,6 +1089,25 @@ async function startInternalMetroServer(options) {
|
|
|
466
1089
|
watch: true,
|
|
467
1090
|
waitForBundler: true
|
|
468
1091
|
});
|
|
1092
|
+
const messageClients = /* @__PURE__ */ new Set();
|
|
1093
|
+
const messageServer = new WebSocketServer({ noServer: true });
|
|
1094
|
+
const broadcastReload = () => {
|
|
1095
|
+
const message = JSON.stringify({
|
|
1096
|
+
version: 2,
|
|
1097
|
+
method: "reload",
|
|
1098
|
+
params: {}
|
|
1099
|
+
});
|
|
1100
|
+
let clients = 0;
|
|
1101
|
+
for (const client of messageClients) if (client.readyState === WebSocket.OPEN) {
|
|
1102
|
+
client.send(message);
|
|
1103
|
+
clients += 1;
|
|
1104
|
+
}
|
|
1105
|
+
return clients;
|
|
1106
|
+
};
|
|
1107
|
+
messageServer.on("connection", (client) => {
|
|
1108
|
+
messageClients.add(client);
|
|
1109
|
+
client.on("close", () => messageClients.delete(client));
|
|
1110
|
+
});
|
|
469
1111
|
const server = http.createServer((req, res) => {
|
|
470
1112
|
if (req.url?.split("?")[0] === "/status") {
|
|
471
1113
|
res.writeHead(200, {
|
|
@@ -476,10 +1118,49 @@ async function startInternalMetroServer(options) {
|
|
|
476
1118
|
res.end("packager-status:running");
|
|
477
1119
|
return;
|
|
478
1120
|
}
|
|
479
|
-
|
|
1121
|
+
if (req.url?.split("?")[0] === "/bleam/reload") {
|
|
1122
|
+
if (req.method !== "POST") {
|
|
1123
|
+
res.writeHead(405, { Allow: "POST" });
|
|
1124
|
+
res.end();
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
sendJson(res, 200, {
|
|
1128
|
+
ok: true,
|
|
1129
|
+
clients: broadcastReload()
|
|
1130
|
+
});
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
middleware(req, res, (error) => {
|
|
1134
|
+
if (res.headersSent) return;
|
|
1135
|
+
if (error) {
|
|
1136
|
+
console.error(error.message);
|
|
1137
|
+
res.writeHead(500, {
|
|
1138
|
+
"Cache-Control": "no-store",
|
|
1139
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
1140
|
+
});
|
|
1141
|
+
res.end(error.message);
|
|
1142
|
+
return;
|
|
1143
|
+
}
|
|
1144
|
+
res.writeHead(404, {
|
|
1145
|
+
"Cache-Control": "no-store",
|
|
1146
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
1147
|
+
});
|
|
1148
|
+
res.end("Not found");
|
|
1149
|
+
});
|
|
480
1150
|
});
|
|
481
1151
|
server.timeout = 0;
|
|
482
1152
|
attachHmrServer(server);
|
|
1153
|
+
const metroUpgradeListeners = server.listeners("upgrade");
|
|
1154
|
+
server.removeAllListeners("upgrade");
|
|
1155
|
+
server.on("upgrade", (req, socket, head) => {
|
|
1156
|
+
if (req.url?.split("?")[0] === "/message") {
|
|
1157
|
+
messageServer.handleUpgrade(req, socket, head, (client) => {
|
|
1158
|
+
messageServer.emit("connection", client, req);
|
|
1159
|
+
});
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
for (const listener of metroUpgradeListeners) listener.call(server, req, socket, head);
|
|
1163
|
+
});
|
|
483
1164
|
await new Promise((resolve, reject) => {
|
|
484
1165
|
server.on("error", reject);
|
|
485
1166
|
server.listen(options.port, "localhost", () => resolve());
|
|
@@ -489,6 +1170,9 @@ async function startInternalMetroServer(options) {
|
|
|
489
1170
|
});
|
|
490
1171
|
console.log(`Bleam dev server running at http://localhost:${options.port}`);
|
|
491
1172
|
const close = () => {
|
|
1173
|
+
setTimeout(() => process.exit(0), 1e3).unref();
|
|
1174
|
+
messageServer.close();
|
|
1175
|
+
for (const client of messageClients) client.terminate();
|
|
492
1176
|
server.close(() => {
|
|
493
1177
|
end();
|
|
494
1178
|
process.exit(0);
|
|
@@ -520,6 +1204,7 @@ async function startDevServer(options) {
|
|
|
520
1204
|
BLEAM_DEV_NAME: config.name,
|
|
521
1205
|
BLEAM_DEV_ORIGIN: origin,
|
|
522
1206
|
BLEAM_DEV_PORT: String(options.port),
|
|
1207
|
+
BLEAM_DEV_PLATFORM: "macos",
|
|
523
1208
|
BLEAM_DEV_RUNTIME_VERSION: config.runtimeVersion,
|
|
524
1209
|
BLEAM_DEV_SDK_VERSION: config.sdkVersion,
|
|
525
1210
|
NODE_PATH: [
|
|
@@ -532,20 +1217,48 @@ async function startDevServer(options) {
|
|
|
532
1217
|
].filter(Boolean).join(path.delimiter)
|
|
533
1218
|
}
|
|
534
1219
|
});
|
|
1220
|
+
let cleanupInteractiveControls = () => {};
|
|
1221
|
+
let stopping = false;
|
|
535
1222
|
const stop = (signal) => {
|
|
1223
|
+
if (stopping) return;
|
|
1224
|
+
stopping = true;
|
|
1225
|
+
cleanupInteractiveControls();
|
|
536
1226
|
child.kill(signal);
|
|
1227
|
+
setTimeout(() => process.exit(0), 2e3).unref();
|
|
537
1228
|
};
|
|
538
1229
|
process.on("SIGINT", () => stop("SIGINT"));
|
|
539
1230
|
process.on("SIGTERM", () => stop("SIGTERM"));
|
|
540
|
-
child.on("
|
|
1231
|
+
child.on("error", (error) => {
|
|
1232
|
+
cleanupInteractiveControls();
|
|
1233
|
+
console.error(`Bleam dev server process failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1234
|
+
console.error(doctorHint(options.projectRoot));
|
|
1235
|
+
process.exit(1);
|
|
1236
|
+
});
|
|
1237
|
+
child.on("exit", (code) => {
|
|
1238
|
+
cleanupInteractiveControls();
|
|
1239
|
+
process.exit(code ?? 0);
|
|
1240
|
+
});
|
|
541
1241
|
try {
|
|
542
1242
|
const manifest = await readDevManifest(origin);
|
|
543
|
-
|
|
1243
|
+
cleanupInteractiveControls = setupInteractiveControls({
|
|
1244
|
+
origin,
|
|
1245
|
+
clientAppPath,
|
|
1246
|
+
projectConfigPath,
|
|
1247
|
+
manifest,
|
|
1248
|
+
stop: () => stop("SIGINT")
|
|
1249
|
+
});
|
|
1250
|
+
if (options.run && process.env.BLEAM_NO_OPEN !== "1") try {
|
|
544
1251
|
await waitForDevBundle(manifest.bundleUrl);
|
|
545
1252
|
console.log("Opening Bleam app...");
|
|
546
|
-
|
|
1253
|
+
await launchRuntimeClient(clientAppPath, projectConfigPath, manifest);
|
|
1254
|
+
} catch (error) {
|
|
1255
|
+
console.error(`Initial app launch failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
1256
|
+
console.error(doctorHint(options.projectRoot));
|
|
1257
|
+
console.error("Check BLEAM_RUNTIME_APP if you are using a runtime override.");
|
|
1258
|
+
console.error("Bleam dev server is still running.");
|
|
547
1259
|
}
|
|
548
1260
|
} catch (error) {
|
|
1261
|
+
cleanupInteractiveControls();
|
|
549
1262
|
child.kill("SIGTERM");
|
|
550
1263
|
throw error;
|
|
551
1264
|
}
|
|
@@ -561,7 +1274,8 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
561
1274
|
createNewProject(options);
|
|
562
1275
|
if (options.run) await startDevServer({
|
|
563
1276
|
projectRoot: options.projectRoot,
|
|
564
|
-
port: 8081
|
|
1277
|
+
port: 8081,
|
|
1278
|
+
run: true
|
|
565
1279
|
});
|
|
566
1280
|
return;
|
|
567
1281
|
}
|
|
@@ -569,6 +1283,26 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
569
1283
|
await startDevServer(parseDevOptions(args));
|
|
570
1284
|
return;
|
|
571
1285
|
}
|
|
1286
|
+
if (command === "build") {
|
|
1287
|
+
await buildNativeArchives(parseBuildOptions(args));
|
|
1288
|
+
return;
|
|
1289
|
+
}
|
|
1290
|
+
if (command === "doctor") {
|
|
1291
|
+
runDoctor(parseDoctorOptions(args));
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1294
|
+
if (command === "check") {
|
|
1295
|
+
runBiomeCommand("check", parseProjectToolOptions(args));
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1298
|
+
if (command === "format") {
|
|
1299
|
+
runBiomeCommand("format", parseProjectToolOptions(args));
|
|
1300
|
+
return;
|
|
1301
|
+
}
|
|
1302
|
+
if (command === "lint") {
|
|
1303
|
+
runBiomeCommand("lint", parseProjectToolOptions(args));
|
|
1304
|
+
return;
|
|
1305
|
+
}
|
|
572
1306
|
if (command === "internal:metro") {
|
|
573
1307
|
await startInternalMetroServer(parseInternalMetroOptions(args));
|
|
574
1308
|
return;
|
|
@@ -581,5 +1315,4 @@ main().catch((error) => {
|
|
|
581
1315
|
});
|
|
582
1316
|
|
|
583
1317
|
//#endregion
|
|
584
|
-
export { };
|
|
585
|
-
//# sourceMappingURL=cli.js.map
|
|
1318
|
+
export { };
|