bleam 0.0.3 → 0.0.5

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/cli.cjs CHANGED
@@ -36,7 +36,7 @@ function invocationRoot() {
36
36
  function parseDevOptions(argv) {
37
37
  const root = invocationRoot();
38
38
  let projectRoot = root;
39
- let port = 8082;
39
+ let port = 8081;
40
40
  let hasProjectRootArg = false;
41
41
  for (let index = 0; index < argv.length; index += 1) {
42
42
  const arg = argv[index];
@@ -85,8 +85,37 @@ function parseNewOptions(argv) {
85
85
  run
86
86
  };
87
87
  }
88
+ function parseInternalMetroOptions(argv) {
89
+ let workspaceRoot;
90
+ let port = 8081;
91
+ for (let index = 0; index < argv.length; index += 1) {
92
+ const arg = argv[index];
93
+ if (arg === "--workspace-root") {
94
+ workspaceRoot = node_path.default.resolve(invocationRoot(), argv[++index] ?? "");
95
+ continue;
96
+ }
97
+ if (arg === "--port") {
98
+ port = Number(argv[++index]);
99
+ continue;
100
+ }
101
+ if (arg.startsWith("--port=")) {
102
+ port = Number(arg.slice(7));
103
+ continue;
104
+ }
105
+ throw new Error(`Unknown internal option: ${arg}`);
106
+ }
107
+ if (!workspaceRoot) throw new Error("Missing --workspace-root");
108
+ if (!Number.isInteger(port) || port <= 0) throw new Error(`Invalid port: ${port}`);
109
+ return {
110
+ workspaceRoot,
111
+ port
112
+ };
113
+ }
88
114
  function isBleamProjectRoot(projectRoot) {
89
- return (0, node_fs.existsSync)(node_path.default.join(projectRoot, "app.config.ts")) && (0, node_fs.existsSync)(node_path.default.join(projectRoot, "app.tsx"));
115
+ return (0, node_fs.existsSync)(node_path.default.join(projectRoot, "app.config.ts")) && (0, node_fs.existsSync)(node_path.default.join(projectRoot, "app", "index.tsx"));
116
+ }
117
+ function resolvedDependencyRoot() {
118
+ return node_path.default.dirname(node_path.default.dirname(require$1.resolve("react-native/package.json")));
90
119
  }
91
120
  function discoverBleamProjectRoot(searchRoot) {
92
121
  const ignoredNames = new Set([
@@ -138,7 +167,7 @@ function loadAppConfig(projectRoot) {
138
167
  ...process.env,
139
168
  NODE_PATH: [
140
169
  node_path.default.join(projectRoot, "node_modules"),
141
- node_path.default.join(packageRoot, "node_modules"),
170
+ resolvedDependencyRoot(),
142
171
  process.env.NODE_PATH
143
172
  ].filter(Boolean).join(node_path.default.delimiter)
144
173
  }
@@ -155,7 +184,12 @@ function loadAppConfig(projectRoot) {
155
184
  function assertBleamConfigFiles(projectRoot) {
156
185
  if ((0, node_fs.existsSync)(node_path.default.join(projectRoot, "app.json"))) throw new Error("Bleam projects use app.config.ts; app.json is not supported.");
157
186
  if (!(0, node_fs.existsSync)(node_path.default.join(projectRoot, "app.config.ts"))) throw new Error("Missing app.config.ts. Bleam projects must define app.config.ts.");
158
- if (!(0, node_fs.existsSync)(node_path.default.join(projectRoot, "app.tsx"))) throw new Error("Missing app.tsx. Bleam projects must define app.tsx.");
187
+ if (!(0, node_fs.existsSync)(node_path.default.join(projectRoot, "app", "index.tsx"))) throw new Error("Missing app/index.tsx. Bleam projects must define app/index.tsx.");
188
+ }
189
+ function ensureProjectTsconfig(projectRoot) {
190
+ const tsconfigPath = node_path.default.join(projectRoot, "tsconfig.json");
191
+ if ((0, node_fs.existsSync)(tsconfigPath)) return;
192
+ (0, node_fs.writeFileSync)(tsconfigPath, `${JSON.stringify({ extends: "./.bleam/dev/tsconfig.json" }, null, 2)}\n`);
159
193
  }
160
194
  function readProjectConfig(options) {
161
195
  assertBleamConfigFiles(options.projectRoot);
@@ -183,14 +217,27 @@ function createNewProject(options) {
183
217
  if ((0, node_fs.existsSync)(options.projectRoot) && (0, node_fs.readdirSync)(options.projectRoot).length > 0) throw new Error(`Directory is not empty: ${options.projectRoot}`);
184
218
  (0, node_fs.mkdirSync)(options.projectRoot, { recursive: true });
185
219
  (0, node_fs.cpSync)(templateRoot, options.projectRoot, { recursive: true });
186
- (0, node_fs.writeFileSync)(node_path.default.join(options.projectRoot, "app.config.ts"), `export default {\n name: ${JSON.stringify(nameFromDirectory(options.projectRoot))},\n}\n`);
220
+ const name = nameFromDirectory(options.projectRoot);
221
+ (0, node_fs.writeFileSync)(node_path.default.join(options.projectRoot, "app.config.ts"), `export default {\n name: ${JSON.stringify(name)},\n}\n`);
222
+ (0, node_fs.writeFileSync)(node_path.default.join(options.projectRoot, ".gitignore"), `.bleam\n`);
223
+ createDevWorkspace(options.projectRoot, {
224
+ name,
225
+ runtimeVersion,
226
+ sdkVersion: runtimeVersion
227
+ });
187
228
  console.log(`Created Bleam project at ${options.projectRoot}`);
188
229
  }
189
230
  function createDevWorkspace(projectRoot, config) {
190
231
  const workspaceRoot = node_path.default.join(projectRoot, ".bleam", "dev");
191
232
  (0, node_fs.mkdirSync)(workspaceRoot, { recursive: true });
192
233
  const workspaceNodeModules = node_path.default.join(workspaceRoot, "node_modules");
193
- if (!(0, node_fs.existsSync)(workspaceNodeModules)) (0, node_fs.symlinkSync)(node_path.default.join(packageRoot, "node_modules"), workspaceNodeModules);
234
+ const dependencyRoot = resolvedDependencyRoot();
235
+ (0, node_fs.rmSync)(workspaceNodeModules, {
236
+ recursive: true,
237
+ force: true
238
+ });
239
+ (0, node_fs.symlinkSync)(dependencyRoot, workspaceNodeModules);
240
+ ensureProjectTsconfig(projectRoot);
194
241
  (0, node_fs.writeFileSync)(node_path.default.join(workspaceRoot, "app.config.js"), `module.exports = ${JSON.stringify({ expo: {
195
242
  name: config.name,
196
243
  slug: slugFromName(config.name),
@@ -210,12 +257,25 @@ function createDevWorkspace(projectRoot, config) {
210
257
  "@types/react": packageJson.dependencies?.["@types/react"],
211
258
  expo: packageJson.dependencies?.expo,
212
259
  react: packageJson.dependencies?.react,
213
- "react-native": packageJson.dependencies?.["react-native"]
214
- }
260
+ "react-native": packageJson.dependencies?.["react-native"],
261
+ typescript: packageJson.dependencies?.typescript
262
+ },
263
+ expo: { install: { exclude: ["typescript"] } }
215
264
  }, null, 2)}\n`);
216
265
  (0, node_fs.writeFileSync)(node_path.default.join(workspaceRoot, "tsconfig.json"), `${JSON.stringify({
217
266
  extends: "bleam/tsconfig",
218
- include: [node_path.default.relative(workspaceRoot, node_path.default.join(projectRoot, "app.tsx")), node_path.default.relative(workspaceRoot, node_path.default.join(projectRoot, "app.config.ts"))]
267
+ compilerOptions: { paths: {
268
+ bleam: ["./node_modules/bleam"],
269
+ "bleam/*": ["./node_modules/bleam/*"],
270
+ expo: ["./node_modules/expo"],
271
+ "expo/*": ["./node_modules/expo/*"],
272
+ react: ["./node_modules/@types/react"],
273
+ "react/jsx-runtime": ["./node_modules/@types/react/jsx-runtime"],
274
+ "react/jsx-dev-runtime": ["./node_modules/@types/react/jsx-dev-runtime"],
275
+ "react-native": ["./node_modules/react-native"],
276
+ "react-native/*": ["./node_modules/react-native/*"]
277
+ } },
278
+ include: [node_path.default.relative(workspaceRoot, node_path.default.join(projectRoot, "app")), node_path.default.relative(workspaceRoot, node_path.default.join(projectRoot, "app.config.ts"))]
219
279
  }, null, 2)}\n`);
220
280
  return workspaceRoot;
221
281
  }
@@ -338,39 +398,6 @@ function copyRuntimeClient(projectRoot, runtime) {
338
398
  (0, node_fs.cpSync)(runtime.appPath, clientAppPath, { recursive: true });
339
399
  return clientAppPath;
340
400
  }
341
- function waitForDevServer(port, timeoutMs = 12e4) {
342
- return new Promise((resolve, reject) => {
343
- const startedAt = Date.now();
344
- const poll = () => {
345
- const req = node_http.default.get(`http://localhost:${port}/status`, (res) => {
346
- let data = "";
347
- res.on("data", (chunk) => {
348
- data += chunk.toString();
349
- });
350
- res.on("end", () => {
351
- if (data.includes("packager-status:running")) {
352
- resolve();
353
- return;
354
- }
355
- retry();
356
- });
357
- });
358
- req.on("error", retry);
359
- req.setTimeout(2e3, () => {
360
- req.destroy();
361
- retry();
362
- });
363
- };
364
- const retry = () => {
365
- if (Date.now() - startedAt > timeoutMs) {
366
- reject(/* @__PURE__ */ new Error(`Bleam dev server did not start within ${timeoutMs / 1e3}s`));
367
- return;
368
- }
369
- setTimeout(poll, 500);
370
- };
371
- poll();
372
- });
373
- }
374
401
  function isBleamManifest(value) {
375
402
  const manifest = value && typeof value === "object" ? value : {};
376
403
  return typeof manifest.name === "string" && typeof manifest.bundleUrl === "string" && manifest.platform === "macos" && manifest.dev === true;
@@ -378,6 +405,7 @@ function isBleamManifest(value) {
378
405
  async function readDevManifest(origin, timeoutMs = 3e4) {
379
406
  const manifestUrl = `${origin}/bleam/manifest.json`;
380
407
  const startedAt = Date.now();
408
+ console.log("Waiting for Bleam dev server...");
381
409
  while (Date.now() - startedAt <= timeoutMs) {
382
410
  try {
383
411
  const response = await fetch(manifestUrl, { cache: "no-store" });
@@ -388,8 +416,37 @@ async function readDevManifest(origin, timeoutMs = 3e4) {
388
416
  }
389
417
  throw new Error(`Bleam manifest did not become available: ${manifestUrl}`);
390
418
  }
419
+ function formatDuration(ms) {
420
+ return `${(ms / 1e3).toFixed(1)}s`;
421
+ }
422
+ async function waitForDevBundle(bundleUrl, timeoutMs = 6e4) {
423
+ const startedAt = Date.now();
424
+ const requestTimeoutMs = 3e4;
425
+ console.log("Bundling app...");
426
+ while (Date.now() - startedAt <= timeoutMs) {
427
+ const requestStartedAt = Date.now();
428
+ try {
429
+ const response = await fetch(bundleUrl, {
430
+ cache: "no-store",
431
+ signal: AbortSignal.timeout(requestTimeoutMs)
432
+ });
433
+ await response.body?.cancel();
434
+ if (response.ok) {
435
+ console.log(`Bundled app in ${formatDuration(Date.now() - startedAt)}`);
436
+ return;
437
+ }
438
+ console.log(`Bundle request returned ${response.status}, retrying...`);
439
+ } catch (error) {
440
+ if (error instanceof Error && error.name === "TimeoutError") console.log(`Bundle request timed out after ${formatDuration(Date.now() - requestStartedAt)}, retrying...`);
441
+ else console.log(`Bundle request failed: ${error instanceof Error ? error.message : String(error)}`);
442
+ }
443
+ await new Promise((resolve) => setTimeout(resolve, 500));
444
+ }
445
+ throw new Error(`Bleam bundle did not complete within ${formatDuration(timeoutMs)}: ${bundleUrl}`);
446
+ }
391
447
  function openRuntimeClient(appPath, projectConfigPath, manifest) {
392
- (0, node_child_process.spawn)("open", [
448
+ const child = (0, node_child_process.spawn)("open", [
449
+ "-n",
393
450
  appPath,
394
451
  "--args",
395
452
  "--bleam-project-config",
@@ -398,10 +455,56 @@ function openRuntimeClient(appPath, projectConfigPath, manifest) {
398
455
  manifest.bundleUrl,
399
456
  "--bleam-title",
400
457
  manifest.name
401
- ], {
402
- detached: true,
403
- stdio: "ignore"
404
- }).unref();
458
+ ], { stdio: "ignore" });
459
+ child.on("error", (error) => {
460
+ console.error(`Failed to open Bleam runtime at ${appPath}: ${error.message}`);
461
+ });
462
+ child.on("exit", (code) => {
463
+ if (code && code !== 0) console.error(`Failed to open Bleam runtime at ${appPath}`);
464
+ });
465
+ }
466
+ async function startInternalMetroServer(options) {
467
+ const metro = require$1("@expo/metro/metro");
468
+ const { loadConfig } = require$1("@expo/metro/metro-config");
469
+ const config = await loadConfig({
470
+ config: node_path.default.join(options.workspaceRoot, "metro.config.js"),
471
+ cwd: options.workspaceRoot,
472
+ port: options.port
473
+ });
474
+ const { middleware, end, attachHmrServer } = await metro.createConnectMiddleware(config, {
475
+ watch: true,
476
+ waitForBundler: true
477
+ });
478
+ const server = node_http.default.createServer((req, res) => {
479
+ if (req.url?.split("?")[0] === "/status") {
480
+ res.writeHead(200, {
481
+ "Cache-Control": "no-store",
482
+ "Content-Type": "text/plain; charset=utf-8",
483
+ "X-React-Native-Project-Root": encodeURI(config.projectRoot)
484
+ });
485
+ res.end("packager-status:running");
486
+ return;
487
+ }
488
+ middleware(req, res);
489
+ });
490
+ server.timeout = 0;
491
+ attachHmrServer(server);
492
+ await new Promise((resolve, reject) => {
493
+ server.on("error", reject);
494
+ server.listen(options.port, "localhost", () => resolve());
495
+ });
496
+ server.on("error", (error) => {
497
+ console.error(error instanceof Error ? error.message : String(error));
498
+ });
499
+ console.log(`Bleam dev server running at http://localhost:${options.port}`);
500
+ const close = () => {
501
+ server.close(() => {
502
+ end();
503
+ process.exit(0);
504
+ });
505
+ };
506
+ process.on("SIGINT", close);
507
+ process.on("SIGTERM", close);
405
508
  }
406
509
  async function startDevServer(options) {
407
510
  const config = readProjectConfig(options);
@@ -411,10 +514,10 @@ async function startDevServer(options) {
411
514
  const origin = `http://localhost:${options.port}`;
412
515
  const projectConfigPath = writeProjectRuntimeConfig(options.projectRoot, config, origin);
413
516
  const child = (0, node_child_process.spawn)(process.execPath, [
414
- require$1.resolve("expo/bin/cli"),
415
- "start",
517
+ (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href),
518
+ "internal:metro",
519
+ "--workspace-root",
416
520
  workspaceRoot,
417
- "--localhost",
418
521
  "--port",
419
522
  String(options.port)
420
523
  ], {
@@ -430,7 +533,7 @@ async function startDevServer(options) {
430
533
  BLEAM_DEV_SDK_VERSION: config.sdkVersion,
431
534
  NODE_PATH: [
432
535
  node_path.default.join(options.projectRoot, "node_modules"),
433
- node_path.default.join(packageRoot, "node_modules"),
536
+ resolvedDependencyRoot(),
434
537
  node_path.default.dirname(node_path.default.dirname(require$1.resolve("expo/package.json"))),
435
538
  node_path.default.dirname(node_path.default.dirname(require$1.resolve("react/package.json"))),
436
539
  node_path.default.dirname(node_path.default.dirname(require$1.resolve("react-native/package.json"))),
@@ -444,9 +547,17 @@ async function startDevServer(options) {
444
547
  process.on("SIGINT", () => stop("SIGINT"));
445
548
  process.on("SIGTERM", () => stop("SIGTERM"));
446
549
  child.on("exit", (code) => process.exit(code ?? 0));
447
- await waitForDevServer(options.port);
448
- const manifest = await readDevManifest(origin);
449
- if (process.env.BLEAM_NO_OPEN !== "1") openRuntimeClient(clientAppPath, projectConfigPath, manifest);
550
+ try {
551
+ const manifest = await readDevManifest(origin);
552
+ if (process.env.BLEAM_NO_OPEN !== "1") {
553
+ await waitForDevBundle(manifest.bundleUrl);
554
+ console.log("Opening Bleam app...");
555
+ openRuntimeClient(clientAppPath, projectConfigPath, manifest);
556
+ }
557
+ } catch (error) {
558
+ child.kill("SIGTERM");
559
+ throw error;
560
+ }
450
561
  }
451
562
  async function main(argv = process.argv.slice(2)) {
452
563
  const [command, ...args] = argv;
@@ -459,7 +570,7 @@ async function main(argv = process.argv.slice(2)) {
459
570
  createNewProject(options);
460
571
  if (options.run) await startDevServer({
461
572
  projectRoot: options.projectRoot,
462
- port: 8082
573
+ port: 8081
463
574
  });
464
575
  return;
465
576
  }
@@ -467,6 +578,10 @@ async function main(argv = process.argv.slice(2)) {
467
578
  await startDevServer(parseDevOptions(args));
468
579
  return;
469
580
  }
581
+ if (command === "internal:metro") {
582
+ await startInternalMetroServer(parseInternalMetroOptions(args));
583
+ return;
584
+ }
470
585
  throw new Error(`Unknown command: ${command}`);
471
586
  }
472
587
  main().catch((error) => {
package/dist/cli.js CHANGED
@@ -27,7 +27,7 @@ function invocationRoot() {
27
27
  function parseDevOptions(argv) {
28
28
  const root = invocationRoot();
29
29
  let projectRoot = root;
30
- let port = 8082;
30
+ let port = 8081;
31
31
  let hasProjectRootArg = false;
32
32
  for (let index = 0; index < argv.length; index += 1) {
33
33
  const arg = argv[index];
@@ -76,8 +76,37 @@ function parseNewOptions(argv) {
76
76
  run
77
77
  };
78
78
  }
79
+ function parseInternalMetroOptions(argv) {
80
+ let workspaceRoot;
81
+ let port = 8081;
82
+ for (let index = 0; index < argv.length; index += 1) {
83
+ const arg = argv[index];
84
+ if (arg === "--workspace-root") {
85
+ workspaceRoot = path.resolve(invocationRoot(), argv[++index] ?? "");
86
+ continue;
87
+ }
88
+ if (arg === "--port") {
89
+ port = Number(argv[++index]);
90
+ continue;
91
+ }
92
+ if (arg.startsWith("--port=")) {
93
+ port = Number(arg.slice(7));
94
+ continue;
95
+ }
96
+ throw new Error(`Unknown internal option: ${arg}`);
97
+ }
98
+ if (!workspaceRoot) throw new Error("Missing --workspace-root");
99
+ if (!Number.isInteger(port) || port <= 0) throw new Error(`Invalid port: ${port}`);
100
+ return {
101
+ workspaceRoot,
102
+ port
103
+ };
104
+ }
79
105
  function isBleamProjectRoot(projectRoot) {
80
- return existsSync(path.join(projectRoot, "app.config.ts")) && existsSync(path.join(projectRoot, "app.tsx"));
106
+ return existsSync(path.join(projectRoot, "app.config.ts")) && existsSync(path.join(projectRoot, "app", "index.tsx"));
107
+ }
108
+ function resolvedDependencyRoot() {
109
+ return path.dirname(path.dirname(require.resolve("react-native/package.json")));
81
110
  }
82
111
  function discoverBleamProjectRoot(searchRoot) {
83
112
  const ignoredNames = new Set([
@@ -129,7 +158,7 @@ function loadAppConfig(projectRoot) {
129
158
  ...process.env,
130
159
  NODE_PATH: [
131
160
  path.join(projectRoot, "node_modules"),
132
- path.join(packageRoot, "node_modules"),
161
+ resolvedDependencyRoot(),
133
162
  process.env.NODE_PATH
134
163
  ].filter(Boolean).join(path.delimiter)
135
164
  }
@@ -146,7 +175,12 @@ function loadAppConfig(projectRoot) {
146
175
  function assertBleamConfigFiles(projectRoot) {
147
176
  if (existsSync(path.join(projectRoot, "app.json"))) throw new Error("Bleam projects use app.config.ts; app.json is not supported.");
148
177
  if (!existsSync(path.join(projectRoot, "app.config.ts"))) throw new Error("Missing app.config.ts. Bleam projects must define app.config.ts.");
149
- if (!existsSync(path.join(projectRoot, "app.tsx"))) throw new Error("Missing app.tsx. Bleam projects must define app.tsx.");
178
+ if (!existsSync(path.join(projectRoot, "app", "index.tsx"))) throw new Error("Missing app/index.tsx. Bleam projects must define app/index.tsx.");
179
+ }
180
+ function ensureProjectTsconfig(projectRoot) {
181
+ const tsconfigPath = path.join(projectRoot, "tsconfig.json");
182
+ if (existsSync(tsconfigPath)) return;
183
+ writeFileSync(tsconfigPath, `${JSON.stringify({ extends: "./.bleam/dev/tsconfig.json" }, null, 2)}\n`);
150
184
  }
151
185
  function readProjectConfig(options) {
152
186
  assertBleamConfigFiles(options.projectRoot);
@@ -174,14 +208,27 @@ function createNewProject(options) {
174
208
  if (existsSync(options.projectRoot) && readdirSync(options.projectRoot).length > 0) throw new Error(`Directory is not empty: ${options.projectRoot}`);
175
209
  mkdirSync(options.projectRoot, { recursive: true });
176
210
  cpSync(templateRoot, options.projectRoot, { recursive: true });
177
- writeFileSync(path.join(options.projectRoot, "app.config.ts"), `export default {\n name: ${JSON.stringify(nameFromDirectory(options.projectRoot))},\n}\n`);
211
+ const name = nameFromDirectory(options.projectRoot);
212
+ writeFileSync(path.join(options.projectRoot, "app.config.ts"), `export default {\n name: ${JSON.stringify(name)},\n}\n`);
213
+ writeFileSync(path.join(options.projectRoot, ".gitignore"), `.bleam\n`);
214
+ createDevWorkspace(options.projectRoot, {
215
+ name,
216
+ runtimeVersion,
217
+ sdkVersion: runtimeVersion
218
+ });
178
219
  console.log(`Created Bleam project at ${options.projectRoot}`);
179
220
  }
180
221
  function createDevWorkspace(projectRoot, config) {
181
222
  const workspaceRoot = path.join(projectRoot, ".bleam", "dev");
182
223
  mkdirSync(workspaceRoot, { recursive: true });
183
224
  const workspaceNodeModules = path.join(workspaceRoot, "node_modules");
184
- if (!existsSync(workspaceNodeModules)) symlinkSync(path.join(packageRoot, "node_modules"), workspaceNodeModules);
225
+ const dependencyRoot = resolvedDependencyRoot();
226
+ rmSync(workspaceNodeModules, {
227
+ recursive: true,
228
+ force: true
229
+ });
230
+ symlinkSync(dependencyRoot, workspaceNodeModules);
231
+ ensureProjectTsconfig(projectRoot);
185
232
  writeFileSync(path.join(workspaceRoot, "app.config.js"), `module.exports = ${JSON.stringify({ expo: {
186
233
  name: config.name,
187
234
  slug: slugFromName(config.name),
@@ -201,12 +248,25 @@ function createDevWorkspace(projectRoot, config) {
201
248
  "@types/react": packageJson.dependencies?.["@types/react"],
202
249
  expo: packageJson.dependencies?.expo,
203
250
  react: packageJson.dependencies?.react,
204
- "react-native": packageJson.dependencies?.["react-native"]
205
- }
251
+ "react-native": packageJson.dependencies?.["react-native"],
252
+ typescript: packageJson.dependencies?.typescript
253
+ },
254
+ expo: { install: { exclude: ["typescript"] } }
206
255
  }, null, 2)}\n`);
207
256
  writeFileSync(path.join(workspaceRoot, "tsconfig.json"), `${JSON.stringify({
208
257
  extends: "bleam/tsconfig",
209
- include: [path.relative(workspaceRoot, path.join(projectRoot, "app.tsx")), path.relative(workspaceRoot, path.join(projectRoot, "app.config.ts"))]
258
+ compilerOptions: { paths: {
259
+ bleam: ["./node_modules/bleam"],
260
+ "bleam/*": ["./node_modules/bleam/*"],
261
+ expo: ["./node_modules/expo"],
262
+ "expo/*": ["./node_modules/expo/*"],
263
+ react: ["./node_modules/@types/react"],
264
+ "react/jsx-runtime": ["./node_modules/@types/react/jsx-runtime"],
265
+ "react/jsx-dev-runtime": ["./node_modules/@types/react/jsx-dev-runtime"],
266
+ "react-native": ["./node_modules/react-native"],
267
+ "react-native/*": ["./node_modules/react-native/*"]
268
+ } },
269
+ include: [path.relative(workspaceRoot, path.join(projectRoot, "app")), path.relative(workspaceRoot, path.join(projectRoot, "app.config.ts"))]
210
270
  }, null, 2)}\n`);
211
271
  return workspaceRoot;
212
272
  }
@@ -329,39 +389,6 @@ function copyRuntimeClient(projectRoot, runtime) {
329
389
  cpSync(runtime.appPath, clientAppPath, { recursive: true });
330
390
  return clientAppPath;
331
391
  }
332
- function waitForDevServer(port, timeoutMs = 12e4) {
333
- return new Promise((resolve, reject) => {
334
- const startedAt = Date.now();
335
- const poll = () => {
336
- const req = http.get(`http://localhost:${port}/status`, (res) => {
337
- let data = "";
338
- res.on("data", (chunk) => {
339
- data += chunk.toString();
340
- });
341
- res.on("end", () => {
342
- if (data.includes("packager-status:running")) {
343
- resolve();
344
- return;
345
- }
346
- retry();
347
- });
348
- });
349
- req.on("error", retry);
350
- req.setTimeout(2e3, () => {
351
- req.destroy();
352
- retry();
353
- });
354
- };
355
- const retry = () => {
356
- if (Date.now() - startedAt > timeoutMs) {
357
- reject(/* @__PURE__ */ new Error(`Bleam dev server did not start within ${timeoutMs / 1e3}s`));
358
- return;
359
- }
360
- setTimeout(poll, 500);
361
- };
362
- poll();
363
- });
364
- }
365
392
  function isBleamManifest(value) {
366
393
  const manifest = value && typeof value === "object" ? value : {};
367
394
  return typeof manifest.name === "string" && typeof manifest.bundleUrl === "string" && manifest.platform === "macos" && manifest.dev === true;
@@ -369,6 +396,7 @@ function isBleamManifest(value) {
369
396
  async function readDevManifest(origin, timeoutMs = 3e4) {
370
397
  const manifestUrl = `${origin}/bleam/manifest.json`;
371
398
  const startedAt = Date.now();
399
+ console.log("Waiting for Bleam dev server...");
372
400
  while (Date.now() - startedAt <= timeoutMs) {
373
401
  try {
374
402
  const response = await fetch(manifestUrl, { cache: "no-store" });
@@ -379,8 +407,37 @@ async function readDevManifest(origin, timeoutMs = 3e4) {
379
407
  }
380
408
  throw new Error(`Bleam manifest did not become available: ${manifestUrl}`);
381
409
  }
410
+ function formatDuration(ms) {
411
+ return `${(ms / 1e3).toFixed(1)}s`;
412
+ }
413
+ async function waitForDevBundle(bundleUrl, timeoutMs = 6e4) {
414
+ const startedAt = Date.now();
415
+ const requestTimeoutMs = 3e4;
416
+ console.log("Bundling app...");
417
+ while (Date.now() - startedAt <= timeoutMs) {
418
+ const requestStartedAt = Date.now();
419
+ try {
420
+ const response = await fetch(bundleUrl, {
421
+ cache: "no-store",
422
+ signal: AbortSignal.timeout(requestTimeoutMs)
423
+ });
424
+ await response.body?.cancel();
425
+ if (response.ok) {
426
+ console.log(`Bundled app in ${formatDuration(Date.now() - startedAt)}`);
427
+ return;
428
+ }
429
+ console.log(`Bundle request returned ${response.status}, retrying...`);
430
+ } catch (error) {
431
+ if (error instanceof Error && error.name === "TimeoutError") console.log(`Bundle request timed out after ${formatDuration(Date.now() - requestStartedAt)}, retrying...`);
432
+ else console.log(`Bundle request failed: ${error instanceof Error ? error.message : String(error)}`);
433
+ }
434
+ await new Promise((resolve) => setTimeout(resolve, 500));
435
+ }
436
+ throw new Error(`Bleam bundle did not complete within ${formatDuration(timeoutMs)}: ${bundleUrl}`);
437
+ }
382
438
  function openRuntimeClient(appPath, projectConfigPath, manifest) {
383
- spawn("open", [
439
+ const child = spawn("open", [
440
+ "-n",
384
441
  appPath,
385
442
  "--args",
386
443
  "--bleam-project-config",
@@ -389,10 +446,56 @@ function openRuntimeClient(appPath, projectConfigPath, manifest) {
389
446
  manifest.bundleUrl,
390
447
  "--bleam-title",
391
448
  manifest.name
392
- ], {
393
- detached: true,
394
- stdio: "ignore"
395
- }).unref();
449
+ ], { stdio: "ignore" });
450
+ child.on("error", (error) => {
451
+ console.error(`Failed to open Bleam runtime at ${appPath}: ${error.message}`);
452
+ });
453
+ child.on("exit", (code) => {
454
+ if (code && code !== 0) console.error(`Failed to open Bleam runtime at ${appPath}`);
455
+ });
456
+ }
457
+ async function startInternalMetroServer(options) {
458
+ const metro = require("@expo/metro/metro");
459
+ const { loadConfig } = require("@expo/metro/metro-config");
460
+ const config = await loadConfig({
461
+ config: path.join(options.workspaceRoot, "metro.config.js"),
462
+ cwd: options.workspaceRoot,
463
+ port: options.port
464
+ });
465
+ const { middleware, end, attachHmrServer } = await metro.createConnectMiddleware(config, {
466
+ watch: true,
467
+ waitForBundler: true
468
+ });
469
+ const server = http.createServer((req, res) => {
470
+ if (req.url?.split("?")[0] === "/status") {
471
+ res.writeHead(200, {
472
+ "Cache-Control": "no-store",
473
+ "Content-Type": "text/plain; charset=utf-8",
474
+ "X-React-Native-Project-Root": encodeURI(config.projectRoot)
475
+ });
476
+ res.end("packager-status:running");
477
+ return;
478
+ }
479
+ middleware(req, res);
480
+ });
481
+ server.timeout = 0;
482
+ attachHmrServer(server);
483
+ await new Promise((resolve, reject) => {
484
+ server.on("error", reject);
485
+ server.listen(options.port, "localhost", () => resolve());
486
+ });
487
+ server.on("error", (error) => {
488
+ console.error(error instanceof Error ? error.message : String(error));
489
+ });
490
+ console.log(`Bleam dev server running at http://localhost:${options.port}`);
491
+ const close = () => {
492
+ server.close(() => {
493
+ end();
494
+ process.exit(0);
495
+ });
496
+ };
497
+ process.on("SIGINT", close);
498
+ process.on("SIGTERM", close);
396
499
  }
397
500
  async function startDevServer(options) {
398
501
  const config = readProjectConfig(options);
@@ -402,10 +505,10 @@ async function startDevServer(options) {
402
505
  const origin = `http://localhost:${options.port}`;
403
506
  const projectConfigPath = writeProjectRuntimeConfig(options.projectRoot, config, origin);
404
507
  const child = spawn(process.execPath, [
405
- require.resolve("expo/bin/cli"),
406
- "start",
508
+ fileURLToPath(import.meta.url),
509
+ "internal:metro",
510
+ "--workspace-root",
407
511
  workspaceRoot,
408
- "--localhost",
409
512
  "--port",
410
513
  String(options.port)
411
514
  ], {
@@ -421,7 +524,7 @@ async function startDevServer(options) {
421
524
  BLEAM_DEV_SDK_VERSION: config.sdkVersion,
422
525
  NODE_PATH: [
423
526
  path.join(options.projectRoot, "node_modules"),
424
- path.join(packageRoot, "node_modules"),
527
+ resolvedDependencyRoot(),
425
528
  path.dirname(path.dirname(require.resolve("expo/package.json"))),
426
529
  path.dirname(path.dirname(require.resolve("react/package.json"))),
427
530
  path.dirname(path.dirname(require.resolve("react-native/package.json"))),
@@ -435,9 +538,17 @@ async function startDevServer(options) {
435
538
  process.on("SIGINT", () => stop("SIGINT"));
436
539
  process.on("SIGTERM", () => stop("SIGTERM"));
437
540
  child.on("exit", (code) => process.exit(code ?? 0));
438
- await waitForDevServer(options.port);
439
- const manifest = await readDevManifest(origin);
440
- if (process.env.BLEAM_NO_OPEN !== "1") openRuntimeClient(clientAppPath, projectConfigPath, manifest);
541
+ try {
542
+ const manifest = await readDevManifest(origin);
543
+ if (process.env.BLEAM_NO_OPEN !== "1") {
544
+ await waitForDevBundle(manifest.bundleUrl);
545
+ console.log("Opening Bleam app...");
546
+ openRuntimeClient(clientAppPath, projectConfigPath, manifest);
547
+ }
548
+ } catch (error) {
549
+ child.kill("SIGTERM");
550
+ throw error;
551
+ }
441
552
  }
442
553
  async function main(argv = process.argv.slice(2)) {
443
554
  const [command, ...args] = argv;
@@ -450,7 +561,7 @@ async function main(argv = process.argv.slice(2)) {
450
561
  createNewProject(options);
451
562
  if (options.run) await startDevServer({
452
563
  projectRoot: options.projectRoot,
453
- port: 8082
564
+ port: 8081
454
565
  });
455
566
  return;
456
567
  }
@@ -458,6 +569,10 @@ async function main(argv = process.argv.slice(2)) {
458
569
  await startDevServer(parseDevOptions(args));
459
570
  return;
460
571
  }
572
+ if (command === "internal:metro") {
573
+ await startInternalMetroServer(parseInternalMetroOptions(args));
574
+ return;
575
+ }
461
576
  throw new Error(`Unknown command: ${command}`);
462
577
  }
463
578
  main().catch((error) => {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","names":["matches: string[]","value: unknown"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { execFileSync, spawn, spawnSync } from 'node:child_process'\nimport { createHash } from 'node:crypto'\nimport {\n cpSync,\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n rmSync,\n symlinkSync,\n writeFileSync,\n} from 'node:fs'\nimport http from 'node:http'\nimport { createRequire } from 'node:module'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\n\nimport type { BleamConfig } from './config'\n\ninterface DevOptions {\n projectRoot: string\n port: number\n}\n\ninterface NewOptions {\n projectRoot: string\n run: boolean\n}\n\ninterface ProjectConfig {\n name: string\n version?: string\n bundleIdentifier?: string\n teamId?: string\n runtimeVersion: string\n sdkVersion: string\n}\n\ninterface RuntimeArtifact {\n appPath: string\n version: string\n platform: string\n}\n\ninterface BleamManifest {\n name: string\n bundleUrl: string\n platform: 'macos'\n dev: boolean\n}\n\nconst require = createRequire(import.meta.url)\nconst packageRoot = path.dirname(\n fileURLToPath(new URL('../package.json', import.meta.url)),\n)\nconst packageJson = require('../package.json') as {\n version: string\n dependencies?: Record<string, string>\n}\nconst runtimeVersion = packageJson.version\nconst runtimePlatform = `macos-${process.arch}`\n\nfunction printUsage() {\n console.log(`Usage: bleam <command>\n\nCommands:\n new [dir] [--run] Create a new Bleam project\n dev [dir] [--port <port>] Start a Bleam dev server`)\n}\n\nfunction invocationRoot() {\n return path.isAbsolute(process.env.PWD ?? '')\n ? process.env.PWD!\n : process.cwd()\n}\n\nfunction parseDevOptions(argv: string[]): DevOptions {\n const root = invocationRoot()\n let projectRoot = root\n let port = 8082\n let hasProjectRootArg = false\n\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index]\n\n if (arg === '--port' || arg === '-p') {\n const value = argv[++index]\n port = Number(value)\n continue\n }\n\n if (arg.startsWith('--port=')) {\n port = Number(arg.slice('--port='.length))\n continue\n }\n\n if (arg === '--help' || arg === '-h') {\n printUsage()\n process.exit(0)\n }\n\n if (arg.startsWith('-')) {\n throw new Error(`Unknown option: ${arg}`)\n }\n\n projectRoot = path.resolve(root, arg)\n hasProjectRootArg = true\n }\n\n if (!Number.isInteger(port) || port <= 0) {\n throw new Error(`Invalid port: ${port}`)\n }\n\n if (!hasProjectRootArg && !isBleamProjectRoot(projectRoot)) {\n projectRoot = discoverBleamProjectRoot(projectRoot) ?? projectRoot\n }\n\n return { projectRoot: path.resolve(projectRoot), port }\n}\n\nfunction parseNewOptions(argv: string[]): NewOptions {\n const root = invocationRoot()\n let projectRoot = root\n let run = false\n\n for (const arg of argv) {\n if (arg === '--run') {\n run = true\n continue\n }\n\n if (arg === '--help' || arg === '-h') {\n printUsage()\n process.exit(0)\n }\n\n if (arg.startsWith('-')) {\n throw new Error(`Unknown option: ${arg}`)\n }\n\n projectRoot = path.resolve(root, arg)\n }\n\n return { projectRoot, run }\n}\n\nfunction isBleamProjectRoot(projectRoot: string) {\n return (\n existsSync(path.join(projectRoot, 'app.config.ts')) &&\n existsSync(path.join(projectRoot, 'app.tsx'))\n )\n}\n\nfunction discoverBleamProjectRoot(searchRoot: string) {\n const ignoredNames = new Set([\n '.bleam',\n '.expo',\n '.git',\n '.yarn',\n 'build',\n 'dist',\n 'node_modules',\n 'templates',\n ])\n const matches: string[] = []\n\n function visit(directory: string) {\n if (matches.length > 1) {\n return\n }\n\n if (isBleamProjectRoot(directory)) {\n matches.push(directory)\n return\n }\n\n for (const entry of readdirSync(directory, { withFileTypes: true })) {\n if (!entry.isDirectory() || ignoredNames.has(entry.name)) {\n continue\n }\n\n visit(path.join(directory, entry.name))\n }\n }\n\n visit(searchRoot)\n\n if (matches.length > 1) {\n throw new Error('Multiple Bleam projects found. Run bleam dev <dir>.')\n }\n\n return matches[0]\n}\n\nfunction assertStringField(value: unknown, field: keyof BleamConfig): string {\n if (typeof value !== 'string' || value.trim() === '') {\n throw new Error(`app.config.ts must define ${field}`)\n }\n return value\n}\n\nfunction loadAppConfig(projectRoot: string): BleamConfig {\n const configPath = path.join(projectRoot, 'app.config.ts')\n const loader = `\n const mod = await import(${JSON.stringify(pathToFileURL(configPath).href)});\n const config = mod.default?.default ?? mod.default ?? mod;\n process.stdout.write(JSON.stringify(config));\n `\n\n const result = spawnSync(\n process.execPath,\n ['--import', require.resolve('tsx'), '--eval', loader],\n {\n cwd: projectRoot,\n encoding: 'utf8',\n env: {\n ...process.env,\n NODE_PATH: [\n path.join(projectRoot, 'node_modules'),\n path.join(packageRoot, 'node_modules'),\n process.env.NODE_PATH,\n ]\n .filter(Boolean)\n .join(path.delimiter),\n },\n },\n )\n\n if (result.status !== 0) {\n throw new Error(result.stderr.trim() || 'Failed to load app.config.ts')\n }\n\n const value = JSON.parse(result.stdout) as Partial<BleamConfig>\n return {\n name: assertStringField(value.name, 'name'),\n version: typeof value.version === 'string' ? value.version : undefined,\n bundleIdentifier:\n typeof value.bundleIdentifier === 'string'\n ? value.bundleIdentifier\n : undefined,\n teamId: typeof value.teamId === 'string' ? value.teamId : undefined,\n }\n}\n\nfunction assertBleamConfigFiles(projectRoot: string) {\n if (existsSync(path.join(projectRoot, 'app.json'))) {\n throw new Error(\n 'Bleam projects use app.config.ts; app.json is not supported.',\n )\n }\n\n if (!existsSync(path.join(projectRoot, 'app.config.ts'))) {\n throw new Error(\n 'Missing app.config.ts. Bleam projects must define app.config.ts.',\n )\n }\n\n if (!existsSync(path.join(projectRoot, 'app.tsx'))) {\n throw new Error('Missing app.tsx. Bleam projects must define app.tsx.')\n }\n}\n\nfunction readProjectConfig(options: DevOptions): ProjectConfig {\n assertBleamConfigFiles(options.projectRoot)\n const config = loadAppConfig(options.projectRoot)\n\n return {\n name: config.name,\n version: config.version,\n bundleIdentifier: config.bundleIdentifier,\n teamId: config.teamId,\n runtimeVersion,\n sdkVersion: runtimeVersion,\n }\n}\n\nfunction slugFromName(name: string) {\n return (\n name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '') || 'bleam-app'\n )\n}\n\nfunction nameFromDirectory(projectRoot: string) {\n const name = path.basename(projectRoot).replace(/[-_]+/g, ' ').trim()\n if (!name) {\n return 'Bleam App'\n }\n\n return name.replace(/\\b\\w/g, (letter) => letter.toUpperCase())\n}\n\nfunction createNewProject(options: NewOptions) {\n const templateRoot = path.join(packageRoot, 'templates', 'basic')\n\n if (!existsSync(templateRoot)) {\n throw new Error(`Missing basic template: ${templateRoot}`)\n }\n\n if (\n existsSync(options.projectRoot) &&\n readdirSync(options.projectRoot).length > 0\n ) {\n throw new Error(`Directory is not empty: ${options.projectRoot}`)\n }\n\n mkdirSync(options.projectRoot, { recursive: true })\n cpSync(templateRoot, options.projectRoot, { recursive: true })\n writeFileSync(\n path.join(options.projectRoot, 'app.config.ts'),\n `export default {\\n name: ${JSON.stringify(nameFromDirectory(options.projectRoot))},\\n}\\n`,\n )\n\n console.log(`Created Bleam project at ${options.projectRoot}`)\n}\n\nfunction createDevWorkspace(projectRoot: string, config: ProjectConfig) {\n const workspaceRoot = path.join(projectRoot, '.bleam', 'dev')\n mkdirSync(workspaceRoot, { recursive: true })\n const workspaceNodeModules = path.join(workspaceRoot, 'node_modules')\n if (!existsSync(workspaceNodeModules)) {\n symlinkSync(path.join(packageRoot, 'node_modules'), workspaceNodeModules)\n }\n\n writeFileSync(\n path.join(workspaceRoot, 'app.config.js'),\n `module.exports = ${JSON.stringify(\n {\n expo: {\n name: config.name,\n slug: slugFromName(config.name),\n version: config.version ?? '0.0.0',\n orientation: 'default',\n platforms: ['ios'],\n newArchEnabled: true,\n },\n },\n null,\n 2,\n )}\\n`,\n )\n\n writeFileSync(\n path.join(workspaceRoot, 'index.js'),\n `import { registerApp } from 'bleam/app'\\nimport App from ${JSON.stringify(path.join(projectRoot, 'app'))}\\n\\nregisterApp(App)\\n`,\n )\n\n writeFileSync(\n path.join(workspaceRoot, 'metro.config.js'),\n `const { getDefaultConfig } = require(${JSON.stringify(path.join(packageRoot, 'metro-config.cjs'))})\\n\\nmodule.exports = getDefaultConfig(__dirname)\\n`,\n )\n\n writeFileSync(\n path.join(workspaceRoot, 'package.json'),\n `${JSON.stringify(\n {\n name: `${slugFromName(config.name)}-bleam-dev`,\n version: config.version ?? '0.0.0',\n private: true,\n main: 'index.js',\n dependencies: {\n '@types/react': packageJson.dependencies?.['@types/react'],\n expo: packageJson.dependencies?.expo,\n react: packageJson.dependencies?.react,\n 'react-native': packageJson.dependencies?.['react-native'],\n },\n },\n null,\n 2,\n )}\\n`,\n )\n\n writeFileSync(\n path.join(workspaceRoot, 'tsconfig.json'),\n `${JSON.stringify(\n {\n extends: 'bleam/tsconfig',\n include: [\n path.relative(workspaceRoot, path.join(projectRoot, 'app.tsx')),\n path.relative(workspaceRoot, path.join(projectRoot, 'app.config.ts')),\n ],\n },\n null,\n 2,\n )}\\n`,\n )\n\n return workspaceRoot\n}\n\nfunction writeProjectRuntimeConfig(\n projectRoot: string,\n config: ProjectConfig,\n origin: string,\n) {\n const projectConfigPath = path.join(projectRoot, '.bleam', 'project.json')\n mkdirSync(path.dirname(projectConfigPath), { recursive: true })\n writeFileSync(\n projectConfigPath,\n `${JSON.stringify(\n {\n name: config.name,\n version: config.version,\n bundleIdentifier: config.bundleIdentifier,\n teamId: config.teamId,\n devServer: origin,\n runtimeVersion: config.runtimeVersion,\n sdkVersion: config.sdkVersion,\n },\n null,\n 2,\n )}\\n`,\n )\n return projectConfigPath\n}\n\nfunction runtimeCacheRoot() {\n return path.join(\n os.homedir(),\n 'Library',\n 'Caches',\n 'bleam',\n 'runtimes',\n runtimeVersion,\n runtimePlatform,\n )\n}\n\nfunction localDevelopmentRuntimeAppPath() {\n return path.resolve(\n packageRoot,\n '..',\n '..',\n 'app',\n 'bleam',\n 'build',\n 'Build',\n 'Products',\n 'Debug-maccatalyst',\n 'Bleam.app',\n )\n}\n\nfunction runtimeReleaseBaseUrl() {\n return (\n process.env.BLEAM_RUNTIME_RELEASE_BASE_URL ??\n 'https://github.com/bajedev/bleam-app/releases/download'\n )\n}\n\nfunction runtimeArchiveName() {\n return `bleam-runtime-v${runtimeVersion}-${runtimePlatform}.zip`\n}\n\nfunction runtimeArchiveUrl() {\n const tag = encodeURIComponent(`bleam@${runtimeVersion}`)\n return `${runtimeReleaseBaseUrl()}/${tag}/${runtimeArchiveName()}`\n}\n\nfunction sha256(filePath: string) {\n return createHash('sha256').update(readFileSync(filePath)).digest('hex')\n}\n\nasync function downloadFile(url: string, destination: string) {\n const response = await fetch(url)\n if (!response.ok) {\n throw new Error(\n `Failed to download ${url}: ${response.status} ${response.statusText}`,\n )\n }\n\n const bytes = new Uint8Array(await response.arrayBuffer())\n writeFileSync(destination, bytes)\n}\n\nasync function downloadExpectedSha256(url: string) {\n const response = await fetch(`${url}.sha256`)\n if (!response.ok) {\n return undefined\n }\n\n const text = await response.text()\n return text.trim().split(/\\s+/)[0]\n}\n\nasync function downloadRuntimeArtifact(): Promise<RuntimeArtifact> {\n if (process.platform !== 'darwin') {\n throw new Error(\n 'Bleam runtime artifacts are currently only available on macOS.',\n )\n }\n\n const cacheRoot = runtimeCacheRoot()\n const cachedAppPath = path.join(cacheRoot, 'Bleam.app')\n if (existsSync(cachedAppPath)) {\n return {\n appPath: cachedAppPath,\n version: runtimeVersion,\n platform: runtimePlatform,\n }\n }\n\n mkdirSync(cacheRoot, { recursive: true })\n const archiveUrl = runtimeArchiveUrl()\n const archivePath = path.join(cacheRoot, runtimeArchiveName())\n const extractRoot = path.join(cacheRoot, 'extract')\n\n await downloadFile(archiveUrl, archivePath)\n const expectedSha256 = await downloadExpectedSha256(archiveUrl)\n if (expectedSha256 && sha256(archivePath) !== expectedSha256) {\n rmSync(archivePath, { force: true })\n throw new Error(`Runtime artifact checksum mismatch: ${archiveUrl}`)\n }\n\n rmSync(extractRoot, { recursive: true, force: true })\n mkdirSync(extractRoot, { recursive: true })\n execFileSync('ditto', ['-x', '-k', archivePath, extractRoot], {\n stdio: 'ignore',\n })\n\n const extractedAppPath = path.join(extractRoot, 'Bleam.app')\n if (!existsSync(extractedAppPath)) {\n throw new Error(`Runtime archive did not contain Bleam.app: ${archiveUrl}`)\n }\n\n rmSync(cachedAppPath, { recursive: true, force: true })\n cpSync(extractedAppPath, cachedAppPath, { recursive: true })\n rmSync(extractRoot, { recursive: true, force: true })\n\n return {\n appPath: cachedAppPath,\n version: runtimeVersion,\n platform: runtimePlatform,\n }\n}\n\nasync function resolveRuntimeArtifact(): Promise<RuntimeArtifact> {\n const overrideAppPath = process.env.BLEAM_RUNTIME_APP\n if (overrideAppPath) {\n const appPath = path.resolve(overrideAppPath)\n if (!existsSync(appPath)) {\n throw new Error(`BLEAM_RUNTIME_APP does not exist: ${appPath}`)\n }\n\n return { appPath, version: runtimeVersion, platform: runtimePlatform }\n }\n\n const localAppPath = localDevelopmentRuntimeAppPath()\n if (existsSync(localAppPath)) {\n return {\n appPath: localAppPath,\n version: runtimeVersion,\n platform: runtimePlatform,\n }\n }\n\n return downloadRuntimeArtifact()\n}\n\nfunction copyRuntimeClient(projectRoot: string, runtime: RuntimeArtifact) {\n const clientAppPath = path.join(projectRoot, '.bleam', 'client', 'Bleam.app')\n rmSync(clientAppPath, { recursive: true, force: true })\n mkdirSync(path.dirname(clientAppPath), { recursive: true })\n cpSync(runtime.appPath, clientAppPath, { recursive: true })\n return clientAppPath\n}\n\nfunction waitForDevServer(port: number, timeoutMs = 120_000) {\n return new Promise<void>((resolve, reject) => {\n const startedAt = Date.now()\n\n const poll = () => {\n const req = http.get(`http://localhost:${port}/status`, (res) => {\n let data = ''\n res.on('data', (chunk) => {\n data += chunk.toString()\n })\n res.on('end', () => {\n if (data.includes('packager-status:running')) {\n resolve()\n return\n }\n\n retry()\n })\n })\n\n req.on('error', retry)\n req.setTimeout(2_000, () => {\n req.destroy()\n retry()\n })\n }\n\n const retry = () => {\n if (Date.now() - startedAt > timeoutMs) {\n reject(\n new Error(\n `Bleam dev server did not start within ${timeoutMs / 1000}s`,\n ),\n )\n return\n }\n\n setTimeout(poll, 500)\n }\n\n poll()\n })\n}\n\nfunction isBleamManifest(value: unknown): value is BleamManifest {\n const manifest =\n value && typeof value === 'object' ? (value as Partial<BleamManifest>) : {}\n\n return (\n typeof manifest.name === 'string' &&\n typeof manifest.bundleUrl === 'string' &&\n manifest.platform === 'macos' &&\n manifest.dev === true\n )\n}\n\nasync function readDevManifest(origin: string, timeoutMs = 30_000) {\n const manifestUrl = `${origin}/bleam/manifest.json`\n const startedAt = Date.now()\n\n while (Date.now() - startedAt <= timeoutMs) {\n try {\n const response = await fetch(manifestUrl, { cache: 'no-store' })\n const value: unknown = await response.json()\n if (response.ok && isBleamManifest(value)) {\n return value\n }\n } catch {\n // Metro can answer /status before custom middleware is ready.\n }\n\n await new Promise((resolve) => setTimeout(resolve, 500))\n }\n\n throw new Error(`Bleam manifest did not become available: ${manifestUrl}`)\n}\n\nfunction openRuntimeClient(\n appPath: string,\n projectConfigPath: string,\n manifest: BleamManifest,\n) {\n const child = spawn(\n 'open',\n [\n appPath,\n '--args',\n '--bleam-project-config',\n projectConfigPath,\n '--bleam-bundle-url',\n manifest.bundleUrl,\n '--bleam-title',\n manifest.name,\n ],\n {\n detached: true,\n stdio: 'ignore',\n },\n )\n child.unref()\n}\n\nasync function startDevServer(options: DevOptions) {\n const config = readProjectConfig(options)\n const runtime = await resolveRuntimeArtifact()\n const clientAppPath = copyRuntimeClient(options.projectRoot, runtime)\n const workspaceRoot = createDevWorkspace(options.projectRoot, config)\n const origin = `http://localhost:${options.port}`\n const projectConfigPath = writeProjectRuntimeConfig(\n options.projectRoot,\n config,\n origin,\n )\n const child = spawn(\n process.execPath,\n [\n require.resolve('expo/bin/cli'),\n 'start',\n workspaceRoot,\n '--localhost',\n '--port',\n String(options.port),\n ],\n {\n stdio: 'inherit',\n env: {\n ...process.env,\n BLEAM_DEV: '1',\n BLEAM_PROJECT_ROOT: options.projectRoot,\n BLEAM_DEV_NAME: config.name,\n BLEAM_DEV_ORIGIN: origin,\n BLEAM_DEV_PORT: String(options.port),\n BLEAM_DEV_RUNTIME_VERSION: config.runtimeVersion,\n BLEAM_DEV_SDK_VERSION: config.sdkVersion,\n NODE_PATH: [\n path.join(options.projectRoot, 'node_modules'),\n path.join(packageRoot, 'node_modules'),\n path.dirname(path.dirname(require.resolve('expo/package.json'))),\n path.dirname(path.dirname(require.resolve('react/package.json'))),\n path.dirname(\n path.dirname(require.resolve('react-native/package.json')),\n ),\n process.env.NODE_PATH,\n ]\n .filter(Boolean)\n .join(path.delimiter),\n },\n },\n )\n\n const stop = (signal: NodeJS.Signals) => {\n child.kill(signal)\n }\n\n process.on('SIGINT', () => stop('SIGINT'))\n process.on('SIGTERM', () => stop('SIGTERM'))\n child.on('exit', (code) => process.exit(code ?? 0))\n\n await waitForDevServer(options.port)\n const manifest = await readDevManifest(origin)\n if (process.env.BLEAM_NO_OPEN !== '1') {\n openRuntimeClient(clientAppPath, projectConfigPath, manifest)\n }\n}\n\nasync function main(argv = process.argv.slice(2)) {\n const [command, ...args] = argv\n\n if (!command || command === '--help' || command === '-h') {\n printUsage()\n return\n }\n\n if (command === 'new') {\n const options = parseNewOptions(args)\n createNewProject(options)\n if (options.run) {\n await startDevServer({ projectRoot: options.projectRoot, port: 8082 })\n }\n return\n }\n\n if (command === 'dev') {\n await startDevServer(parseDevOptions(args))\n return\n }\n\n throw new Error(`Unknown command: ${command}`)\n}\n\nmain().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error))\n process.exit(1)\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","names":["workspaceRoot: string | undefined","matches: string[]","value: unknown"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { execFileSync, spawn, spawnSync } from 'node:child_process'\nimport { createHash } from 'node:crypto'\nimport {\n cpSync,\n existsSync,\n mkdirSync,\n readFileSync,\n readdirSync,\n rmSync,\n symlinkSync,\n writeFileSync,\n} from 'node:fs'\nimport http from 'node:http'\nimport { createRequire } from 'node:module'\nimport os from 'node:os'\nimport path from 'node:path'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\n\nimport type { BleamConfig } from './config'\n\ninterface DevOptions {\n projectRoot: string\n port: number\n}\n\ninterface NewOptions {\n projectRoot: string\n run: boolean\n}\n\ninterface ProjectConfig {\n name: string\n version?: string\n bundleIdentifier?: string\n teamId?: string\n runtimeVersion: string\n sdkVersion: string\n}\n\ninterface RuntimeArtifact {\n appPath: string\n version: string\n platform: string\n}\n\ninterface BleamManifest {\n name: string\n bundleUrl: string\n platform: 'macos'\n dev: boolean\n}\n\ninterface InternalMetroOptions {\n workspaceRoot: string\n port: number\n}\n\nconst require = createRequire(import.meta.url)\nconst packageRoot = path.dirname(\n fileURLToPath(new URL('../package.json', import.meta.url)),\n)\nconst packageJson = require('../package.json') as {\n version: string\n dependencies?: Record<string, string>\n}\nconst runtimeVersion = packageJson.version\nconst runtimePlatform = `macos-${process.arch}`\n\nfunction printUsage() {\n console.log(`Usage: bleam <command>\n\nCommands:\n new [dir] [--run] Create a new Bleam project\n dev [dir] [--port <port>] Start a Bleam dev server`)\n}\n\nfunction invocationRoot() {\n return path.isAbsolute(process.env.PWD ?? '')\n ? process.env.PWD!\n : process.cwd()\n}\n\nfunction parseDevOptions(argv: string[]): DevOptions {\n const root = invocationRoot()\n let projectRoot = root\n let port = 8081\n let hasProjectRootArg = false\n\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index]\n\n if (arg === '--port' || arg === '-p') {\n const value = argv[++index]\n port = Number(value)\n continue\n }\n\n if (arg.startsWith('--port=')) {\n port = Number(arg.slice('--port='.length))\n continue\n }\n\n if (arg === '--help' || arg === '-h') {\n printUsage()\n process.exit(0)\n }\n\n if (arg.startsWith('-')) {\n throw new Error(`Unknown option: ${arg}`)\n }\n\n projectRoot = path.resolve(root, arg)\n hasProjectRootArg = true\n }\n\n if (!Number.isInteger(port) || port <= 0) {\n throw new Error(`Invalid port: ${port}`)\n }\n\n if (!hasProjectRootArg && !isBleamProjectRoot(projectRoot)) {\n projectRoot = discoverBleamProjectRoot(projectRoot) ?? projectRoot\n }\n\n return { projectRoot: path.resolve(projectRoot), port }\n}\n\nfunction parseNewOptions(argv: string[]): NewOptions {\n const root = invocationRoot()\n let projectRoot = root\n let run = false\n\n for (const arg of argv) {\n if (arg === '--run') {\n run = true\n continue\n }\n\n if (arg === '--help' || arg === '-h') {\n printUsage()\n process.exit(0)\n }\n\n if (arg.startsWith('-')) {\n throw new Error(`Unknown option: ${arg}`)\n }\n\n projectRoot = path.resolve(root, arg)\n }\n\n return { projectRoot, run }\n}\n\nfunction parseInternalMetroOptions(argv: string[]): InternalMetroOptions {\n let workspaceRoot: string | undefined\n let port = 8081\n\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index]\n\n if (arg === '--workspace-root') {\n workspaceRoot = path.resolve(invocationRoot(), argv[++index] ?? '')\n continue\n }\n\n if (arg === '--port') {\n port = Number(argv[++index])\n continue\n }\n\n if (arg.startsWith('--port=')) {\n port = Number(arg.slice('--port='.length))\n continue\n }\n\n throw new Error(`Unknown internal option: ${arg}`)\n }\n\n if (!workspaceRoot) {\n throw new Error('Missing --workspace-root')\n }\n\n if (!Number.isInteger(port) || port <= 0) {\n throw new Error(`Invalid port: ${port}`)\n }\n\n return { workspaceRoot, port }\n}\n\nfunction isBleamProjectRoot(projectRoot: string) {\n return (\n existsSync(path.join(projectRoot, 'app.config.ts')) &&\n existsSync(path.join(projectRoot, 'app', 'index.tsx'))\n )\n}\n\nfunction resolvedDependencyRoot() {\n return path.dirname(\n path.dirname(require.resolve('react-native/package.json')),\n )\n}\n\nfunction discoverBleamProjectRoot(searchRoot: string) {\n const ignoredNames = new Set([\n '.bleam',\n '.expo',\n '.git',\n '.yarn',\n 'build',\n 'dist',\n 'node_modules',\n 'templates',\n ])\n const matches: string[] = []\n\n function visit(directory: string) {\n if (matches.length > 1) {\n return\n }\n\n if (isBleamProjectRoot(directory)) {\n matches.push(directory)\n return\n }\n\n for (const entry of readdirSync(directory, { withFileTypes: true })) {\n if (!entry.isDirectory() || ignoredNames.has(entry.name)) {\n continue\n }\n\n visit(path.join(directory, entry.name))\n }\n }\n\n visit(searchRoot)\n\n if (matches.length > 1) {\n throw new Error('Multiple Bleam projects found. Run bleam dev <dir>.')\n }\n\n return matches[0]\n}\n\nfunction assertStringField(value: unknown, field: keyof BleamConfig): string {\n if (typeof value !== 'string' || value.trim() === '') {\n throw new Error(`app.config.ts must define ${field}`)\n }\n return value\n}\n\nfunction loadAppConfig(projectRoot: string): BleamConfig {\n const configPath = path.join(projectRoot, 'app.config.ts')\n const loader = `\n const mod = await import(${JSON.stringify(pathToFileURL(configPath).href)});\n const config = mod.default?.default ?? mod.default ?? mod;\n process.stdout.write(JSON.stringify(config));\n `\n\n const result = spawnSync(\n process.execPath,\n ['--import', require.resolve('tsx'), '--eval', loader],\n {\n cwd: projectRoot,\n encoding: 'utf8',\n env: {\n ...process.env,\n NODE_PATH: [\n path.join(projectRoot, 'node_modules'),\n resolvedDependencyRoot(),\n process.env.NODE_PATH,\n ]\n .filter(Boolean)\n .join(path.delimiter),\n },\n },\n )\n\n if (result.status !== 0) {\n throw new Error(result.stderr.trim() || 'Failed to load app.config.ts')\n }\n\n const value = JSON.parse(result.stdout) as Partial<BleamConfig>\n return {\n name: assertStringField(value.name, 'name'),\n version: typeof value.version === 'string' ? value.version : undefined,\n bundleIdentifier:\n typeof value.bundleIdentifier === 'string'\n ? value.bundleIdentifier\n : undefined,\n teamId: typeof value.teamId === 'string' ? value.teamId : undefined,\n }\n}\n\nfunction assertBleamConfigFiles(projectRoot: string) {\n if (existsSync(path.join(projectRoot, 'app.json'))) {\n throw new Error(\n 'Bleam projects use app.config.ts; app.json is not supported.',\n )\n }\n\n if (!existsSync(path.join(projectRoot, 'app.config.ts'))) {\n throw new Error(\n 'Missing app.config.ts. Bleam projects must define app.config.ts.',\n )\n }\n\n if (!existsSync(path.join(projectRoot, 'app', 'index.tsx'))) {\n throw new Error(\n 'Missing app/index.tsx. Bleam projects must define app/index.tsx.',\n )\n }\n}\n\nfunction ensureProjectTsconfig(projectRoot: string) {\n const tsconfigPath = path.join(projectRoot, 'tsconfig.json')\n if (existsSync(tsconfigPath)) {\n return\n }\n\n writeFileSync(\n tsconfigPath,\n `${JSON.stringify(\n {\n extends: './.bleam/dev/tsconfig.json',\n },\n null,\n 2,\n )}\\n`,\n )\n}\n\nfunction readProjectConfig(options: DevOptions): ProjectConfig {\n assertBleamConfigFiles(options.projectRoot)\n const config = loadAppConfig(options.projectRoot)\n\n return {\n name: config.name,\n version: config.version,\n bundleIdentifier: config.bundleIdentifier,\n teamId: config.teamId,\n runtimeVersion,\n sdkVersion: runtimeVersion,\n }\n}\n\nfunction slugFromName(name: string) {\n return (\n name\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '') || 'bleam-app'\n )\n}\n\nfunction nameFromDirectory(projectRoot: string) {\n const name = path.basename(projectRoot).replace(/[-_]+/g, ' ').trim()\n if (!name) {\n return 'Bleam App'\n }\n\n return name.replace(/\\b\\w/g, (letter) => letter.toUpperCase())\n}\n\nfunction createNewProject(options: NewOptions) {\n const templateRoot = path.join(packageRoot, 'templates', 'basic')\n\n if (!existsSync(templateRoot)) {\n throw new Error(`Missing basic template: ${templateRoot}`)\n }\n\n if (\n existsSync(options.projectRoot) &&\n readdirSync(options.projectRoot).length > 0\n ) {\n throw new Error(`Directory is not empty: ${options.projectRoot}`)\n }\n\n mkdirSync(options.projectRoot, { recursive: true })\n cpSync(templateRoot, options.projectRoot, { recursive: true })\n const name = nameFromDirectory(options.projectRoot)\n writeFileSync(\n path.join(options.projectRoot, 'app.config.ts'),\n `export default {\\n name: ${JSON.stringify(name)},\\n}\\n`,\n )\n writeFileSync(path.join(options.projectRoot, '.gitignore'), `.bleam\\n`)\n createDevWorkspace(options.projectRoot, {\n name,\n runtimeVersion,\n sdkVersion: runtimeVersion,\n })\n\n console.log(`Created Bleam project at ${options.projectRoot}`)\n}\n\nfunction createDevWorkspace(projectRoot: string, config: ProjectConfig) {\n const workspaceRoot = path.join(projectRoot, '.bleam', 'dev')\n mkdirSync(workspaceRoot, { recursive: true })\n const workspaceNodeModules = path.join(workspaceRoot, 'node_modules')\n const dependencyRoot = resolvedDependencyRoot()\n rmSync(workspaceNodeModules, { recursive: true, force: true })\n symlinkSync(dependencyRoot, workspaceNodeModules)\n ensureProjectTsconfig(projectRoot)\n\n writeFileSync(\n path.join(workspaceRoot, 'app.config.js'),\n `module.exports = ${JSON.stringify(\n {\n expo: {\n name: config.name,\n slug: slugFromName(config.name),\n version: config.version ?? '0.0.0',\n orientation: 'default',\n platforms: ['ios'],\n newArchEnabled: true,\n },\n },\n null,\n 2,\n )}\\n`,\n )\n\n writeFileSync(\n path.join(workspaceRoot, 'index.js'),\n `import { registerApp } from 'bleam/app'\\nimport App from ${JSON.stringify(path.join(projectRoot, 'app'))}\\n\\nregisterApp(App)\\n`,\n )\n\n writeFileSync(\n path.join(workspaceRoot, 'metro.config.js'),\n `const { getDefaultConfig } = require(${JSON.stringify(path.join(packageRoot, 'metro-config.cjs'))})\\n\\nmodule.exports = getDefaultConfig(__dirname)\\n`,\n )\n\n writeFileSync(\n path.join(workspaceRoot, 'package.json'),\n `${JSON.stringify(\n {\n name: `${slugFromName(config.name)}-bleam-dev`,\n version: config.version ?? '0.0.0',\n private: true,\n main: 'index.js',\n dependencies: {\n '@types/react': packageJson.dependencies?.['@types/react'],\n expo: packageJson.dependencies?.expo,\n react: packageJson.dependencies?.react,\n 'react-native': packageJson.dependencies?.['react-native'],\n typescript: packageJson.dependencies?.typescript,\n },\n expo: {\n install: {\n exclude: ['typescript'],\n },\n },\n },\n null,\n 2,\n )}\\n`,\n )\n\n writeFileSync(\n path.join(workspaceRoot, 'tsconfig.json'),\n `${JSON.stringify(\n {\n extends: 'bleam/tsconfig',\n compilerOptions: {\n paths: {\n bleam: ['./node_modules/bleam'],\n 'bleam/*': ['./node_modules/bleam/*'],\n expo: ['./node_modules/expo'],\n 'expo/*': ['./node_modules/expo/*'],\n react: ['./node_modules/@types/react'],\n 'react/jsx-runtime': ['./node_modules/@types/react/jsx-runtime'],\n 'react/jsx-dev-runtime': [\n './node_modules/@types/react/jsx-dev-runtime',\n ],\n 'react-native': ['./node_modules/react-native'],\n 'react-native/*': ['./node_modules/react-native/*'],\n },\n },\n include: [\n path.relative(workspaceRoot, path.join(projectRoot, 'app')),\n path.relative(workspaceRoot, path.join(projectRoot, 'app.config.ts')),\n ],\n },\n null,\n 2,\n )}\\n`,\n )\n\n return workspaceRoot\n}\n\nfunction writeProjectRuntimeConfig(\n projectRoot: string,\n config: ProjectConfig,\n origin: string,\n) {\n const projectConfigPath = path.join(projectRoot, '.bleam', 'project.json')\n mkdirSync(path.dirname(projectConfigPath), { recursive: true })\n writeFileSync(\n projectConfigPath,\n `${JSON.stringify(\n {\n name: config.name,\n version: config.version,\n bundleIdentifier: config.bundleIdentifier,\n teamId: config.teamId,\n devServer: origin,\n runtimeVersion: config.runtimeVersion,\n sdkVersion: config.sdkVersion,\n },\n null,\n 2,\n )}\\n`,\n )\n return projectConfigPath\n}\n\nfunction runtimeCacheRoot() {\n return path.join(\n os.homedir(),\n 'Library',\n 'Caches',\n 'bleam',\n 'runtimes',\n runtimeVersion,\n runtimePlatform,\n )\n}\n\nfunction localDevelopmentRuntimeAppPath() {\n return path.resolve(\n packageRoot,\n '..',\n '..',\n 'app',\n 'bleam',\n 'build',\n 'Build',\n 'Products',\n 'Debug-maccatalyst',\n 'Bleam.app',\n )\n}\n\nfunction runtimeReleaseBaseUrl() {\n return (\n process.env.BLEAM_RUNTIME_RELEASE_BASE_URL ??\n 'https://github.com/bajedev/bleam-app/releases/download'\n )\n}\n\nfunction runtimeArchiveName() {\n return `bleam-runtime-v${runtimeVersion}-${runtimePlatform}.zip`\n}\n\nfunction runtimeArchiveUrl() {\n const tag = encodeURIComponent(`bleam@${runtimeVersion}`)\n return `${runtimeReleaseBaseUrl()}/${tag}/${runtimeArchiveName()}`\n}\n\nfunction sha256(filePath: string) {\n return createHash('sha256').update(readFileSync(filePath)).digest('hex')\n}\n\nasync function downloadFile(url: string, destination: string) {\n const response = await fetch(url)\n if (!response.ok) {\n throw new Error(\n `Failed to download ${url}: ${response.status} ${response.statusText}`,\n )\n }\n\n const bytes = new Uint8Array(await response.arrayBuffer())\n writeFileSync(destination, bytes)\n}\n\nasync function downloadExpectedSha256(url: string) {\n const response = await fetch(`${url}.sha256`)\n if (!response.ok) {\n return undefined\n }\n\n const text = await response.text()\n return text.trim().split(/\\s+/)[0]\n}\n\nasync function downloadRuntimeArtifact(): Promise<RuntimeArtifact> {\n if (process.platform !== 'darwin') {\n throw new Error(\n 'Bleam runtime artifacts are currently only available on macOS.',\n )\n }\n\n const cacheRoot = runtimeCacheRoot()\n const cachedAppPath = path.join(cacheRoot, 'Bleam.app')\n if (existsSync(cachedAppPath)) {\n return {\n appPath: cachedAppPath,\n version: runtimeVersion,\n platform: runtimePlatform,\n }\n }\n\n mkdirSync(cacheRoot, { recursive: true })\n const archiveUrl = runtimeArchiveUrl()\n const archivePath = path.join(cacheRoot, runtimeArchiveName())\n const extractRoot = path.join(cacheRoot, 'extract')\n\n await downloadFile(archiveUrl, archivePath)\n const expectedSha256 = await downloadExpectedSha256(archiveUrl)\n if (expectedSha256 && sha256(archivePath) !== expectedSha256) {\n rmSync(archivePath, { force: true })\n throw new Error(`Runtime artifact checksum mismatch: ${archiveUrl}`)\n }\n\n rmSync(extractRoot, { recursive: true, force: true })\n mkdirSync(extractRoot, { recursive: true })\n execFileSync('ditto', ['-x', '-k', archivePath, extractRoot], {\n stdio: 'ignore',\n })\n\n const extractedAppPath = path.join(extractRoot, 'Bleam.app')\n if (!existsSync(extractedAppPath)) {\n throw new Error(`Runtime archive did not contain Bleam.app: ${archiveUrl}`)\n }\n\n rmSync(cachedAppPath, { recursive: true, force: true })\n cpSync(extractedAppPath, cachedAppPath, { recursive: true })\n rmSync(extractRoot, { recursive: true, force: true })\n\n return {\n appPath: cachedAppPath,\n version: runtimeVersion,\n platform: runtimePlatform,\n }\n}\n\nasync function resolveRuntimeArtifact(): Promise<RuntimeArtifact> {\n const overrideAppPath = process.env.BLEAM_RUNTIME_APP\n if (overrideAppPath) {\n const appPath = path.resolve(overrideAppPath)\n if (!existsSync(appPath)) {\n throw new Error(`BLEAM_RUNTIME_APP does not exist: ${appPath}`)\n }\n\n return { appPath, version: runtimeVersion, platform: runtimePlatform }\n }\n\n const localAppPath = localDevelopmentRuntimeAppPath()\n if (existsSync(localAppPath)) {\n return {\n appPath: localAppPath,\n version: runtimeVersion,\n platform: runtimePlatform,\n }\n }\n\n return downloadRuntimeArtifact()\n}\n\nfunction copyRuntimeClient(projectRoot: string, runtime: RuntimeArtifact) {\n const clientAppPath = path.join(projectRoot, '.bleam', 'client', 'Bleam.app')\n rmSync(clientAppPath, { recursive: true, force: true })\n mkdirSync(path.dirname(clientAppPath), { recursive: true })\n cpSync(runtime.appPath, clientAppPath, { recursive: true })\n return clientAppPath\n}\n\nfunction isBleamManifest(value: unknown): value is BleamManifest {\n const manifest =\n value && typeof value === 'object' ? (value as Partial<BleamManifest>) : {}\n\n return (\n typeof manifest.name === 'string' &&\n typeof manifest.bundleUrl === 'string' &&\n manifest.platform === 'macos' &&\n manifest.dev === true\n )\n}\n\nasync function readDevManifest(origin: string, timeoutMs = 30_000) {\n const manifestUrl = `${origin}/bleam/manifest.json`\n const startedAt = Date.now()\n\n console.log('Waiting for Bleam dev server...')\n\n while (Date.now() - startedAt <= timeoutMs) {\n try {\n const response = await fetch(manifestUrl, { cache: 'no-store' })\n const value: unknown = await response.json()\n if (response.ok && isBleamManifest(value)) {\n return value\n }\n } catch {\n // Metro can answer /status before custom middleware is ready.\n }\n\n await new Promise((resolve) => setTimeout(resolve, 500))\n }\n\n throw new Error(`Bleam manifest did not become available: ${manifestUrl}`)\n}\n\nfunction formatDuration(ms: number) {\n return `${(ms / 1000).toFixed(1)}s`\n}\n\nasync function waitForDevBundle(bundleUrl: string, timeoutMs = 60_000) {\n const startedAt = Date.now()\n const requestTimeoutMs = 30_000\n\n console.log('Bundling app...')\n\n while (Date.now() - startedAt <= timeoutMs) {\n const requestStartedAt = Date.now()\n try {\n const response = await fetch(bundleUrl, {\n cache: 'no-store',\n signal: AbortSignal.timeout(requestTimeoutMs),\n })\n await response.body?.cancel()\n if (response.ok) {\n console.log(`Bundled app in ${formatDuration(Date.now() - startedAt)}`)\n return\n }\n\n console.log(`Bundle request returned ${response.status}, retrying...`)\n } catch (error) {\n if (error instanceof Error && error.name === 'TimeoutError') {\n console.log(\n `Bundle request timed out after ${formatDuration(\n Date.now() - requestStartedAt,\n )}, retrying...`,\n )\n } else {\n console.log(\n `Bundle request failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n }\n\n await new Promise((resolve) => setTimeout(resolve, 500))\n }\n\n throw new Error(\n `Bleam bundle did not complete within ${formatDuration(\n timeoutMs,\n )}: ${bundleUrl}`,\n )\n}\n\nfunction openRuntimeClient(\n appPath: string,\n projectConfigPath: string,\n manifest: BleamManifest,\n) {\n const child = spawn(\n 'open',\n [\n '-n',\n appPath,\n '--args',\n '--bleam-project-config',\n projectConfigPath,\n '--bleam-bundle-url',\n manifest.bundleUrl,\n '--bleam-title',\n manifest.name,\n ],\n {\n stdio: 'ignore',\n },\n )\n\n child.on('error', (error) => {\n console.error(\n `Failed to open Bleam runtime at ${appPath}: ${error.message}`,\n )\n })\n\n child.on('exit', (code) => {\n if (code && code !== 0) {\n console.error(`Failed to open Bleam runtime at ${appPath}`)\n }\n })\n}\n\nasync function startInternalMetroServer(options: InternalMetroOptions) {\n const metro = require('@expo/metro/metro') as typeof import('metro')\n const { loadConfig } =\n require('@expo/metro/metro-config') as typeof import('metro-config')\n const config = await loadConfig({\n config: path.join(options.workspaceRoot, 'metro.config.js'),\n cwd: options.workspaceRoot,\n port: options.port,\n })\n const { middleware, end, attachHmrServer } =\n await metro.createConnectMiddleware(config, {\n watch: true,\n waitForBundler: true,\n })\n const server = http.createServer((req, res) => {\n if (req.url?.split('?')[0] === '/status') {\n res.writeHead(200, {\n 'Cache-Control': 'no-store',\n 'Content-Type': 'text/plain; charset=utf-8',\n 'X-React-Native-Project-Root': encodeURI(config.projectRoot),\n })\n res.end('packager-status:running')\n return\n }\n\n middleware(req, res)\n })\n\n server.timeout = 0\n attachHmrServer(server)\n\n await new Promise<void>((resolve, reject) => {\n server.on('error', reject)\n server.listen(options.port, 'localhost', () => resolve())\n })\n\n server.on('error', (error) => {\n console.error(error instanceof Error ? error.message : String(error))\n })\n\n console.log(`Bleam dev server running at http://localhost:${options.port}`)\n\n const close = () => {\n server.close(() => {\n end()\n process.exit(0)\n })\n }\n process.on('SIGINT', close)\n process.on('SIGTERM', close)\n}\n\nasync function startDevServer(options: DevOptions) {\n const config = readProjectConfig(options)\n const runtime = await resolveRuntimeArtifact()\n const clientAppPath = copyRuntimeClient(options.projectRoot, runtime)\n const workspaceRoot = createDevWorkspace(options.projectRoot, config)\n const origin = `http://localhost:${options.port}`\n const projectConfigPath = writeProjectRuntimeConfig(\n options.projectRoot,\n config,\n origin,\n )\n const child = spawn(\n process.execPath,\n [\n fileURLToPath(import.meta.url),\n 'internal:metro',\n '--workspace-root',\n workspaceRoot,\n '--port',\n String(options.port),\n ],\n {\n stdio: 'inherit',\n env: {\n ...process.env,\n BLEAM_DEV: '1',\n BLEAM_PROJECT_ROOT: options.projectRoot,\n BLEAM_DEV_NAME: config.name,\n BLEAM_DEV_ORIGIN: origin,\n BLEAM_DEV_PORT: String(options.port),\n BLEAM_DEV_RUNTIME_VERSION: config.runtimeVersion,\n BLEAM_DEV_SDK_VERSION: config.sdkVersion,\n NODE_PATH: [\n path.join(options.projectRoot, 'node_modules'),\n resolvedDependencyRoot(),\n path.dirname(path.dirname(require.resolve('expo/package.json'))),\n path.dirname(path.dirname(require.resolve('react/package.json'))),\n path.dirname(\n path.dirname(require.resolve('react-native/package.json')),\n ),\n process.env.NODE_PATH,\n ]\n .filter(Boolean)\n .join(path.delimiter),\n },\n },\n )\n\n const stop = (signal: NodeJS.Signals) => {\n child.kill(signal)\n }\n\n process.on('SIGINT', () => stop('SIGINT'))\n process.on('SIGTERM', () => stop('SIGTERM'))\n child.on('exit', (code) => process.exit(code ?? 0))\n\n try {\n const manifest = await readDevManifest(origin)\n if (process.env.BLEAM_NO_OPEN !== '1') {\n await waitForDevBundle(manifest.bundleUrl)\n console.log('Opening Bleam app...')\n openRuntimeClient(clientAppPath, projectConfigPath, manifest)\n }\n } catch (error) {\n child.kill('SIGTERM')\n throw error\n }\n}\n\nasync function main(argv = process.argv.slice(2)) {\n const [command, ...args] = argv\n\n if (!command || command === '--help' || command === '-h') {\n printUsage()\n return\n }\n\n if (command === 'new') {\n const options = parseNewOptions(args)\n createNewProject(options)\n if (options.run) {\n await startDevServer({ projectRoot: options.projectRoot, port: 8081 })\n }\n return\n }\n\n if (command === 'dev') {\n await startDevServer(parseDevOptions(args))\n return\n }\n\n if (command === 'internal:metro') {\n await startInternalMetroServer(parseInternalMetroOptions(args))\n return\n }\n\n throw new Error(`Unknown command: ${command}`)\n}\n\nmain().catch((error) => {\n console.error(error instanceof Error ? error.message : String(error))\n process.exit(1)\n})\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"fs-CEhcjuN6.d.ts","names":[],"sources":["../src/fs.ts"],"sourcesContent":[],"mappings":";UAAiB,eAAA;EAAA,QAAA,CAAA,IAAA,EAAA,MAAe,CAAA,EACN,OAAA,CAAA,MACmB,CAAA;EAGhC,SAOZ,CAAA,IAAA,EAPgB,MAAA,EAAA,QAOhB,EAAA,MAAA,CAAA,EAV4C,OAU5C,CAAA,IAAA,CAAA;;cAPY,IAAI"}
1
+ {"version":3,"file":"fs-CEhcjuN6.d.ts","names":[],"sources":["../src/fs.ts"],"sourcesContent":[],"mappings":";UAAiB,eAAA;EAAA,QAAA,CAAA,IAAA,EAAA,MAAe,CAAA,EACN,OAAA,CAAA,MAAA,CACmB;EAGhC,SAOZ,CAAA,IAAA,EAAA,MAPgB,EAAA,QAAA,EAOhB,MAAA,CAAA,EAV4C,OAU5C,CAAA,IAAA,CAAA;;cAPY,IAAI"}
@@ -1 +1 @@
1
- {"version":3,"file":"fs-CfE8CHf_.d.cts","names":[],"sources":["../src/fs.ts"],"sourcesContent":[],"mappings":";UAAiB,eAAA;EAAA,QAAA,CAAA,IAAA,EAAA,MAAe,CAAA,EACN,OAAA,CAAA,MAAA,CACmB;EAGhC,SAOZ,CAAA,IAAA,EAAA,MAPgB,EAAA,QAAA,EAOhB,MAAA,CAAA,EAV4C,OAU5C,CAAA,IAAA,CAAA;;cAPY,IAAI"}
1
+ {"version":3,"file":"fs-CfE8CHf_.d.cts","names":[],"sources":["../src/fs.ts"],"sourcesContent":[],"mappings":";UAAiB,eAAA;EAAA,QAAA,CAAA,IAAA,EAAA,MAAe,CAAA,EACN,OAAA,CAAA,MACmB,CAAA;EAGhC,SAOZ,CAAA,IAAA,EAPgB,MAAA,EAAA,QAOhB,EAAA,MAAA,CAAA,EAV4C,OAU5C,CAAA,IAAA,CAAA;;cAPY,IAAI"}
package/metro-config.cjs CHANGED
@@ -12,7 +12,7 @@ function packageRoot(name) {
12
12
 
13
13
  function getDefaultConfig(projectRoot) {
14
14
  const appRoot = process.env.BLEAM_PROJECT_ROOT ?? projectRoot
15
- const port = Number(process.env.BLEAM_DEV_PORT ?? 8082)
15
+ const port = Number(process.env.BLEAM_DEV_PORT ?? 8081)
16
16
  const origin = process.env.BLEAM_DEV_ORIGIN ?? `http://localhost:${port}`
17
17
  const config = getExpoDefaultConfig(projectRoot)
18
18
  const upstreamEnhanceMiddleware = config.server.enhanceMiddleware
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bleam",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "packageManager": "yarn@1.22.22",
5
5
  "type": "module",
6
6
  "files": [
@@ -11,7 +11,7 @@
11
11
  "tsconfig.base.json"
12
12
  ],
13
13
  "bin": {
14
- "bleam": "./dist/cli.js"
14
+ "bleam": "dist/cli.js"
15
15
  },
16
16
  "scripts": {
17
17
  "build": "tsdown",
@@ -27,16 +27,24 @@
27
27
  "devDependencies": {
28
28
  "@types/node": "^25.5.0",
29
29
  "prettier": "^3.8.2",
30
- "tsdown": "^0.15.6",
31
- "typescript": "^5.9.2"
30
+ "tsdown": "^0.15.6"
32
31
  },
33
32
  "dependencies": {
33
+ "@expo/metro": "56.0.0",
34
34
  "@nativescript/react-native": "9.0.0-preview.4",
35
35
  "@types/react": "~19.2.14",
36
36
  "expo": "56",
37
37
  "react": "19.2.3",
38
38
  "react-native": "0.85.3",
39
- "tsx": "^4.21.0"
39
+ "tsx": "^4.21.0",
40
+ "typescript": "~6.0.3"
41
+ },
42
+ "expo": {
43
+ "install": {
44
+ "exclude": [
45
+ "typescript"
46
+ ]
47
+ }
40
48
  },
41
49
  "main": "./dist/index.cjs",
42
50
  "module": "./dist/index.js",
@@ -3,7 +3,7 @@ import { StyleSheet, Text, View } from 'react-native'
3
3
  export default function App() {
4
4
  return (
5
5
  <View style={styles.container}>
6
- <Text>Open up app.tsx to start working on your app!</Text>
6
+ <Text>Open up app/index.tsx to start working on your app!</Text>
7
7
  </View>
8
8
  )
9
9
  }