vxrn 1.26.1 → 2.0.0-beta.33.1

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.
@@ -1,6 +1,6 @@
1
1
  import { createHash } from "crypto";
2
2
  import { basename, dirname, extname, join, relative, resolve } from "path";
3
- import { copyFileSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync } from "fs";
3
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, watch, writeFileSync } from "fs";
4
4
  import { pathToFileURL } from "url";
5
5
  import micromatch from "micromatch";
6
6
  import { loadEnv, normalizePath } from "vite";
@@ -273,6 +273,7 @@ function nativeBundlePostProcessPlugin() {
273
273
  };
274
274
  }
275
275
  async function createNativeDevEngine(options) {
276
+ var _statSync;
276
277
  var {
277
278
  root,
278
279
  port,
@@ -300,7 +301,9 @@ async function createNativeDevEngine(options) {
300
301
  var bundlePromise = null;
301
302
  var resolvedHost = host === "0.0.0.0" ? "localhost" : host;
302
303
  var virtualEntry = nativeVirtualEntryPlugin(root, {
303
- dev: true
304
+ dev: true,
305
+ platform,
306
+ dynamicRoutes: true
304
307
  });
305
308
  var engineWork = Promise.resolve();
306
309
  var queueEngineWork = function (work) {
@@ -346,30 +349,21 @@ try {
346
349
  };
347
350
  var outputProcessed = Promise.resolve();
348
351
  var engine;
349
- var rebuildIfNewRoute = async function (files) {
350
- var {
351
- routeRoot,
352
- files: knownRoutes,
353
- isRouteFile
354
- } = virtualEntry.routes;
355
- var routeRootPrefix = `${normalizePath(routeRoot)}/`;
356
- if (!files.some(function (file) {
357
- var _statSync;
358
- var normalized = normalizePath(file);
359
- if (isRouteFile(normalized)) return !knownRoutes.has(normalized);
360
- return normalized.startsWith(routeRootPrefix) && ((_statSync = statSync(file, {
361
- throwIfNoEntry: false
362
- })) === null || _statSync === void 0 ? void 0 : _statSync.isDirectory()) === true;
363
- })) return false;
364
- await queueEngineWork(async function () {
365
- engine.triggerFullBuild();
366
- await engine.ensureLatestBuildOutput();
367
- await outputProcessed;
368
- });
369
- onHmrUpdate === null || onHmrUpdate === void 0 || onHmrUpdate({
370
- type: "hmr:reload"
352
+ var routeWatcher;
353
+ var rebuildIfRouteGraphChanged = function () {
354
+ return queueEngineWork(async function () {
355
+ var {
356
+ files: knownRoutes,
357
+ scanFiles,
358
+ updateFiles
359
+ } = virtualEntry.routes;
360
+ var currentRoutes = scanFiles();
361
+ if (!(currentRoutes.size !== knownRoutes.size || [...currentRoutes].some(function (route) {
362
+ return !knownRoutes.has(route);
363
+ }))) return false;
364
+ updateFiles(currentRoutes);
365
+ return true;
371
366
  });
372
- return true;
373
367
  };
374
368
  engine = await dev(inputOptions, outputOptions, {
375
369
  onOutput: async function (result) {
@@ -391,7 +385,7 @@ try {
391
385
  });
392
386
  return;
393
387
  }
394
- if (await rebuildIfNewRoute(result.changedFiles)) return;
388
+ if (await rebuildIfRouteGraphChanged()) return;
395
389
  var _iteratorNormalCompletion = true,
396
390
  _didIteratorError = false,
397
391
  _iteratorError = void 0;
@@ -466,6 +460,29 @@ try {
466
460
  }
467
461
  }
468
462
  await engine.run();
463
+ var routeWatchTarget = virtualEntry.routes.routeRoot;
464
+ while (!((_statSync = statSync(routeWatchTarget, {
465
+ throwIfNoEntry: false
466
+ })) === null || _statSync === void 0 ? void 0 : _statSync.isDirectory())) {
467
+ var parent = dirname(routeWatchTarget);
468
+ if (parent === routeWatchTarget) break;
469
+ routeWatchTarget = parent;
470
+ }
471
+ var normalizedRouteRoot = normalizePath(virtualEntry.routes.routeRoot);
472
+ routeWatcher = watch(routeWatchTarget, {
473
+ recursive: true
474
+ }, function (_eventType, file) {
475
+ if (file === null) return;
476
+ var changed = normalizePath(resolve(routeWatchTarget, file.toString()));
477
+ if (changed !== normalizedRouteRoot && !changed.startsWith(`${normalizedRouteRoot}/`)) return;
478
+ rebuildIfRouteGraphChanged().catch(function (error) {
479
+ console.error(`[vxrn] rebuilding the native route map failed`, error);
480
+ });
481
+ });
482
+ routeWatcher.on("error", function (error) {
483
+ console.error(`[vxrn] watching the native route map failed`, error);
484
+ });
485
+ await rebuildIfRouteGraphChanged();
469
486
  return {
470
487
  engine,
471
488
  async getBundle() {
@@ -500,10 +517,8 @@ try {
500
517
  return assetRegistry.resolve(pathname, hash);
501
518
  },
502
519
  async close() {
520
+ routeWatcher === null || routeWatcher === void 0 || routeWatcher.close();
503
521
  await engine.close();
504
- },
505
- async handleAddedFile(file) {
506
- await rebuildIfNewRoute([file]);
507
522
  }
508
523
  };
509
524
  }
@@ -546,7 +561,8 @@ async function buildNativeBundle(options) {
546
561
  ".js": "jsx"
547
562
  },
548
563
  plugins: [...(entryFile ? [] : [nativeVirtualEntryPlugin(root, {
549
- dev
564
+ dev,
565
+ platform
550
566
  }).plugin]), ...getNativePlugins(root, platform, viteImportGlobPlugin, dev, assetsDest, void 0, sourcemap, userPlugins), nativeBundlePostProcessPlugin()],
551
567
  output: getNativeOutputOptions(prelude, sourcemap, minify)
552
568
  })).output.find(function (o) {
@@ -562,6 +578,7 @@ async function buildNativeBundle(options) {
562
578
  var VIRTUAL_NATIVE_ENTRY = "virtual:native-entry";
563
579
  function nativeVirtualEntryPlugin(root, opts) {
564
580
  var isDev = (opts === null || opts === void 0 ? void 0 : opts.dev) !== false;
581
+ var useDynamicRouteRegistry = opts.dynamicRoutes === true;
565
582
  var resolvedId = normalizePath(resolve(root, "__virtual-native-entry.tsx"));
566
583
  var entryConfig = globalThis.__vxrnNativeEntryConfig || {};
567
584
  var routerRoot = entryConfig.routerRoot || "app";
@@ -578,8 +595,7 @@ function nativeVirtualEntryPlugin(root, opts) {
578
595
  var routeGlobs = [`./${routerRoot}/**/*.tsx`, `./${routerRoot}/**/*.ts`, `!./${routerRoot}/**/*+api.*`, `!./${routerRoot}/**/*.test.*`, `!./${routerRoot}/**/*.d.ts`, `!./${routerRoot}/**/*.server.*`, `!./${routerRoot}/**/_middleware.*`, `!./${routerRoot}/**/*.web.*`, ...(entryConfig.ignoredRouteFiles || []).map(function (pattern) {
579
596
  return `!./${routerRoot}/${pattern}`;
580
597
  })];
581
- var entryCode = `
582
- ${isDev ? `
598
+ var refreshSetup = isDev ? `
583
599
  // react-refresh/runtime MUST initialize before React loads
584
600
  import RefreshRuntime from 'react-refresh/runtime';
585
601
  RefreshRuntime.injectIntoGlobalHook(globalThis);
@@ -588,22 +604,26 @@ globalThis.$RefreshReg$ = function(type, id) {
588
604
  RefreshRuntime.register(type, id);
589
605
  };
590
606
  globalThis.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
591
- ` : ""}
607
+ ` : "";
608
+ var entryCode = function () {
609
+ return `
610
+ ${refreshSetup}
592
611
  import * as ReactNativeInitializeCore from 'react-native/Libraries/Core/InitializeCore';
593
612
  import NativeWebSocket from 'react-native/Libraries/WebSocket/WebSocket';
613
+ import DevSettings from 'react-native/Libraries/Utilities/DevSettings';
594
614
  ${setupFileImport}
615
+ ${routeImports}
595
616
  import { createApp } from 'one';
596
617
 
597
618
  void ReactNativeInitializeCore;
598
619
  globalThis.WebSocket = NativeWebSocket;
620
+ globalThis.__VXRN_RELOAD_NATIVE_DEV_BUNDLE__ = function(reason) {
621
+ DevSettings.reload(reason);
622
+ };
599
623
 
600
- var _routes = import.meta.glob(${JSON.stringify(routeGlobs)}, { exhaustive: true });
601
- // fix route keys: One expects '/${routerRoot}/...' prefix but import.meta.glob returns './${routerRoot}/...'
602
- var routes = {};
603
- Object.keys(_routes).forEach(function(key) {
604
- var normalizedKey = key.replace(/^\\.\\//, '');
605
- routes['/' + normalizedKey] = _routes[key];
606
- });
624
+ // React Native reloads a dev bundle in the existing JS runtime. Advance One's
625
+ // route-cache version so a full reload cannot reuse the previous context.
626
+ globalThis.__vxrnVersion = (globalThis.__vxrnVersion || 0) + 1;
607
627
 
608
628
  createApp({
609
629
  routes: routes,
@@ -611,7 +631,10 @@ createApp({
611
631
  flags: ${JSON.stringify(flags)},
612
632
  linking: ${JSON.stringify(linking)},
613
633
  });
634
+
635
+ ${routeHmr}
614
636
  `;
637
+ };
615
638
  var routeRoot = resolve(root, routerRoot);
616
639
  var stripDot = function (pattern) {
617
640
  return pattern.replace(/^\.\//, "");
@@ -628,11 +651,77 @@ createApp({
628
651
  var relativeToRoot = normalizePath(relative(root, file));
629
652
  return micromatch.isMatch(relativeToRoot, includeGlobs) && !micromatch.isMatch(relativeToRoot, excludeGlobs);
630
653
  };
654
+ var scanFiles = function () {
655
+ var _statSync;
656
+ var files = /* @__PURE__ */new Set();
657
+ var walkRouteRoot = function (dir) {
658
+ var _iteratorNormalCompletion = true,
659
+ _didIteratorError = false,
660
+ _iteratorError = void 0;
661
+ try {
662
+ for (var _iterator = readdirSync(dir, {
663
+ withFileTypes: true
664
+ })[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
665
+ var entry = _step.value;
666
+ var child = resolve(dir, entry.name);
667
+ if (entry.isDirectory()) walkRouteRoot(child);else if (isRouteFile(child)) files.add(normalizePath(child));
668
+ }
669
+ } catch (err) {
670
+ _didIteratorError = true;
671
+ _iteratorError = err;
672
+ } finally {
673
+ try {
674
+ if (!_iteratorNormalCompletion && _iterator.return != null) _iterator.return();
675
+ } finally {
676
+ if (_didIteratorError) throw _iteratorError;
677
+ }
678
+ }
679
+ };
680
+ if ((_statSync = statSync(routeRoot, {
681
+ throwIfNoEntry: false
682
+ })) === null || _statSync === void 0 ? void 0 : _statSync.isDirectory()) walkRouteRoot(routeRoot);
683
+ return files;
684
+ };
685
+ var registrySpecifier = `./node_modules/.vxrn/native-routes-${opts.platform}.mjs`;
686
+ var registryPath = resolve(root, registrySpecifier);
631
687
  var routes = {
632
688
  routeRoot,
633
689
  files: /* @__PURE__ */new Set(),
634
- isRouteFile
690
+ isRouteFile,
691
+ scanFiles,
692
+ updateFiles(files) {
693
+ routes.files = files;
694
+ if (!useDynamicRouteRegistry) return;
695
+ var source = `export const routes = {
696
+ ${[...files].sort().map(function (file) {
697
+ var routeKey = `/${normalizePath(relative(root, file))}`;
698
+ var importPath = normalizePath(relative(dirname(registryPath), file));
699
+ if (!importPath.startsWith(".")) importPath = `./${importPath}`;
700
+ return ` ${JSON.stringify(routeKey)}: () => import(${JSON.stringify(importPath)})`;
701
+ }).join(",\n")}
702
+ }
703
+ `;
704
+ mkdirSync(dirname(registryPath), {
705
+ recursive: true
706
+ });
707
+ if (!existsSync(registryPath) || readFileSync(registryPath, "utf8") !== source) writeFileSync(registryPath, source);
708
+ }
635
709
  };
710
+ routes.updateFiles(routes.scanFiles());
711
+ var routeImports = useDynamicRouteRegistry ? `import { routes } from ${JSON.stringify(registrySpecifier)};` : `var _routes = import.meta.glob(${JSON.stringify(routeGlobs)}, { exhaustive: true });
712
+ // fix route keys: One expects '/${routerRoot}/...' prefix but import.meta.glob returns './${routerRoot}/...'
713
+ var routes = {};
714
+ Object.keys(_routes).forEach(function(key) {
715
+ var normalizedKey = key.replace(/^\\.\\//, '');
716
+ routes['/' + normalizedKey] = _routes[key];
717
+ });`;
718
+ var routeHmr = useDynamicRouteRegistry ? `if (import.meta.hot) {
719
+ import.meta.hot.accept(${JSON.stringify(registrySpecifier)}, function(next) {
720
+ if (globalThis.__VXRN_UPDATE_NATIVE_ROUTES__) {
721
+ globalThis.__VXRN_UPDATE_NATIVE_ROUTES__(next.routes);
722
+ }
723
+ });
724
+ }` : "";
636
725
  return {
637
726
  routes,
638
727
  plugin: {
@@ -641,38 +730,8 @@ createApp({
641
730
  if (id === VIRTUAL_NATIVE_ENTRY) return resolvedId;
642
731
  },
643
732
  load(id) {
644
- var _this = this;
645
- var _statSync;
646
733
  if (id !== resolvedId) return;
647
- routes.files.clear();
648
- var walkRouteRoot = function (dir) {
649
- _this.addWatchFile(dir);
650
- var _iteratorNormalCompletion = true,
651
- _didIteratorError = false,
652
- _iteratorError = void 0;
653
- try {
654
- for (var _iterator = readdirSync(dir, {
655
- withFileTypes: true
656
- })[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
657
- var entry = _step.value;
658
- var child = resolve(dir, entry.name);
659
- if (entry.isDirectory()) walkRouteRoot(child);else if (isRouteFile(child)) routes.files.add(normalizePath(child));
660
- }
661
- } catch (err) {
662
- _didIteratorError = true;
663
- _iteratorError = err;
664
- } finally {
665
- try {
666
- if (!_iteratorNormalCompletion && _iterator.return != null) _iterator.return();
667
- } finally {
668
- if (_didIteratorError) throw _iteratorError;
669
- }
670
- }
671
- };
672
- if ((_statSync = statSync(routeRoot, {
673
- throwIfNoEntry: false
674
- })) === null || _statSync === void 0 ? void 0 : _statSync.isDirectory()) walkRouteRoot(routeRoot);else this.addWatchFile(dirname(routeRoot));
675
- return entryCode;
734
+ return entryCode();
676
735
  }
677
736
  }
678
737
  };
@@ -1466,11 +1525,13 @@ class ReactNativeDevRuntime extends BaseDevRuntime {
1466
1525
  }
1467
1526
  }
1468
1527
 
1469
- reload() {
1470
- var proxy = globalThis.__turboModuleProxy
1471
- ? globalThis.__turboModuleProxy('DevSettings')
1472
- : globalThis.nativeModuleProxy && globalThis.nativeModuleProxy.DevSettings;
1473
- if (proxy && proxy.reload) proxy.reload();
1528
+ reload(reason) {
1529
+ var reloadNativeBundle = globalThis.__VXRN_RELOAD_NATIVE_DEV_BUNDLE__;
1530
+ if (typeof reloadNativeBundle === 'function') {
1531
+ reloadNativeBundle(reason);
1532
+ return;
1533
+ }
1534
+ console.error('[vxrn HMR]: DevSettings.reload is unavailable');
1474
1535
  }
1475
1536
 
1476
1537
  setup(socket) {
@@ -1492,10 +1553,10 @@ class ReactNativeDevRuntime extends BaseDevRuntime {
1492
1553
  if (message.type === 'hmr:update') {
1493
1554
  // a patch that cannot be applied in place is the reload signal
1494
1555
  if (!runtime.applyHmrUpdate(message.code, message.changedIds, message.seq)) {
1495
- runtime.reload();
1556
+ runtime.reload('native HMR update could not be applied');
1496
1557
  }
1497
1558
  } else if (message.type === 'hmr:reload') {
1498
- runtime.reload();
1559
+ runtime.reload('native route map changed');
1499
1560
  }
1500
1561
  } catch (error) {
1501
1562
  console.error('[vxrn HMR]: failed to apply update', error);