vxrn 2.13.8 → 2.13.10

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.
Files changed (118) hide show
  1. package/dist/cli.mjs +3 -2
  2. package/dist/cli.mjs.map +1 -1
  3. package/dist/cli.native.js +5 -2
  4. package/dist/cli.native.js.map +1 -1
  5. package/dist/config/getBaseViteConfigOnly.mjs +3 -3
  6. package/dist/config/getBaseViteConfigOnly.mjs.map +1 -1
  7. package/dist/config/getBaseViteConfigOnly.native.js +3 -3
  8. package/dist/config/getBaseViteConfigOnly.native.js.map +1 -1
  9. package/dist/config/getOptionsFilled.mjs +24 -2
  10. package/dist/config/getOptionsFilled.mjs.map +1 -1
  11. package/dist/config/getOptionsFilled.native.js +25 -2
  12. package/dist/config/getOptionsFilled.native.js.map +1 -1
  13. package/dist/config/getServerOptionsFilled.mjs +119 -1
  14. package/dist/config/getServerOptionsFilled.mjs.map +1 -1
  15. package/dist/config/getServerOptionsFilled.native.js +137 -1
  16. package/dist/config/getServerOptionsFilled.native.js.map +1 -1
  17. package/dist/exports/build.mjs +5 -5
  18. package/dist/exports/build.mjs.map +1 -1
  19. package/dist/exports/build.native.js +5 -5
  20. package/dist/exports/build.native.js.map +1 -1
  21. package/dist/exports/dev.mjs +4 -6
  22. package/dist/exports/dev.mjs.map +1 -1
  23. package/dist/exports/dev.native.js +6 -6
  24. package/dist/exports/dev.native.js.map +1 -1
  25. package/dist/exports/prebuild.mjs +4 -4
  26. package/dist/exports/prebuild.mjs.map +1 -1
  27. package/dist/exports/prebuild.native.js +4 -4
  28. package/dist/exports/prebuild.native.js.map +1 -1
  29. package/dist/exports/prebuildWithoutExpo.mjs +95 -88
  30. package/dist/exports/prebuildWithoutExpo.mjs.map +1 -1
  31. package/dist/exports/prebuildWithoutExpo.native.js +95 -88
  32. package/dist/exports/prebuildWithoutExpo.native.js.map +1 -1
  33. package/dist/plugins/autoDepOptimizePlugin.mjs +3 -3
  34. package/dist/plugins/autoDepOptimizePlugin.mjs.map +1 -1
  35. package/dist/plugins/autoDepOptimizePlugin.native.js +3 -3
  36. package/dist/plugins/autoDepOptimizePlugin.native.js.map +1 -1
  37. package/dist/plugins/reactNativeDevAssetPlugin.mjs +4 -4
  38. package/dist/plugins/reactNativeDevAssetPlugin.mjs.map +1 -1
  39. package/dist/plugins/reactNativeDevAssetPlugin.native.js +4 -4
  40. package/dist/plugins/reactNativeDevAssetPlugin.native.js.map +1 -1
  41. package/dist/rn-commands/bundle/buildBundle.mjs +18 -5
  42. package/dist/rn-commands/bundle/buildBundle.mjs.map +1 -1
  43. package/dist/rn-commands/bundle/buildBundle.native.js +18 -5
  44. package/dist/rn-commands/bundle/buildBundle.native.js.map +1 -1
  45. package/dist/user-interface/index.mjs +1 -1
  46. package/dist/user-interface/index.mjs.map +1 -1
  47. package/dist/user-interface/index.native.js +1 -1
  48. package/dist/user-interface/index.native.js.map +1 -1
  49. package/dist/utils/env-editor.mjs +198 -0
  50. package/dist/utils/env-editor.mjs.map +1 -0
  51. package/dist/utils/env-editor.native.js +266 -0
  52. package/dist/utils/env-editor.native.js.map +1 -0
  53. package/dist/utils/fs.mjs +48 -0
  54. package/dist/utils/fs.mjs.map +1 -0
  55. package/dist/utils/fs.native.js +48 -0
  56. package/dist/utils/fs.native.js.map +1 -0
  57. package/dist/utils/getVitePath.mjs +2 -2
  58. package/dist/utils/getVitePath.mjs.map +1 -1
  59. package/dist/utils/getVitePath.native.js +2 -2
  60. package/dist/utils/getVitePath.native.js.map +1 -1
  61. package/dist/utils/patches.mjs +38 -29
  62. package/dist/utils/patches.mjs.map +1 -1
  63. package/dist/utils/patches.native.js +38 -29
  64. package/dist/utils/patches.native.js.map +1 -1
  65. package/dist/utils/scanDepsToOptimize.mjs +12 -11
  66. package/dist/utils/scanDepsToOptimize.mjs.map +1 -1
  67. package/dist/utils/scanDepsToOptimize.native.js +12 -11
  68. package/dist/utils/scanDepsToOptimize.native.js.map +1 -1
  69. package/dist/utils/state.mjs +5 -5
  70. package/dist/utils/state.mjs.map +1 -1
  71. package/dist/utils/state.native.js +5 -5
  72. package/dist/utils/state.native.js.map +1 -1
  73. package/dist/utils/utils.mjs +4 -3
  74. package/dist/utils/utils.mjs.map +1 -1
  75. package/dist/utils/utils.native.js +4 -3
  76. package/dist/utils/utils.native.js.map +1 -1
  77. package/package.json +12 -18
  78. package/src/cli.ts +5 -4
  79. package/src/config/getBaseViteConfigOnly.ts +3 -3
  80. package/src/config/getOptionsFilled.ts +35 -2
  81. package/src/config/getServerOptionsFilled.test.ts +37 -0
  82. package/src/config/getServerOptionsFilled.ts +57 -1
  83. package/src/exports/build.ts +5 -5
  84. package/src/exports/clean.test.ts +1 -1
  85. package/src/exports/dev.ts +5 -6
  86. package/src/exports/prebuild.ts +4 -4
  87. package/src/exports/prebuildWithoutExpo.ts +102 -89
  88. package/src/plugins/autoDepOptimizePlugin.ts +3 -3
  89. package/src/plugins/reactNativeDevAssetPlugin.ts +4 -4
  90. package/src/rn-commands/bundle/buildBundle.ts +15 -5
  91. package/src/user-interface/index.ts +1 -1
  92. package/src/utils/env-editor.LICENSE +9 -0
  93. package/src/utils/env-editor.ts +214 -0
  94. package/src/utils/fs.ts +59 -0
  95. package/src/utils/getVitePath.ts +2 -2
  96. package/src/utils/patches.test.ts +36 -36
  97. package/src/utils/patches.ts +39 -27
  98. package/src/utils/scanDepsToOptimize.test.ts +2 -2
  99. package/src/utils/scanDepsToOptimize.ts +6 -5
  100. package/src/utils/state.ts +5 -7
  101. package/src/utils/utils.ts +5 -5
  102. package/types/config/getOptionsFilled.d.ts +9 -2
  103. package/types/config/getOptionsFilled.d.ts.map +1 -1
  104. package/types/config/getServerOptionsFilled.d.ts.map +1 -1
  105. package/types/exports/build.d.ts +1 -1
  106. package/types/exports/dev.d.ts.map +1 -1
  107. package/types/exports/prebuildWithoutExpo.d.ts.map +1 -1
  108. package/types/rn-commands/bundle/buildBundle.d.ts.map +1 -1
  109. package/types/user-interface/index.d.ts.map +1 -1
  110. package/types/utils/env-editor.d.ts +9 -0
  111. package/types/utils/env-editor.d.ts.map +1 -0
  112. package/types/utils/fs.d.ts +9 -0
  113. package/types/utils/fs.d.ts.map +1 -0
  114. package/types/utils/patches.d.ts.map +1 -1
  115. package/types/utils/scanDepsToOptimize.d.ts.map +1 -1
  116. package/types/utils/state.d.ts.map +1 -1
  117. package/types/utils/utils.d.ts +2 -2
  118. package/types/utils/utils.d.ts.map +1 -1
@@ -1,11 +1,12 @@
1
1
  import { execFileSync } from "node:child_process";
2
2
  import { createHash } from "node:crypto";
3
+ import { copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
3
4
  import module from "node:module";
4
5
  import path from "node:path";
5
6
  import { pathToFileURL } from "node:url";
6
7
  import { androidAppPermissions, androidIconSuffix, appIconPreviewResources, iosUsageDescriptions, validateNativeApp } from "@vxrn/utils/nativeAppManifest";
7
- import FSExtra from "fs-extra";
8
8
  import sharp from "sharp";
9
+ import { readJSONSync } from "../utils/fs.mjs";
9
10
  import { swiftPackageDirectories } from "../utils/swiftPackageId.mjs";
10
11
 
11
12
  const requireVxrn = module.createRequire(import.meta.url);
@@ -186,7 +187,7 @@ ${imports.join("\n")}
186
187
  `;
187
188
  }
188
189
  function generateOneBridgingHeader(dest, app) {
189
- FSExtra.writeFileSync(path.join(dest, app.name, ONE_BRIDGING_HEADER_NAME), renderOneBridgingHeader(app));
190
+ writeFileSync(path.join(dest, app.name, ONE_BRIDGING_HEADER_NAME), renderOneBridgingHeader(app));
190
191
  }
191
192
  function patchIosPbxprojOneBridgingHeader(project, appName) {
192
193
  const anchor = `INFOPLIST_FILE = ${appName}/Info.plist;`;
@@ -312,11 +313,11 @@ function copyAppResources({ root, dest, platform, app }) {
312
313
  }
313
314
  for (const [file, target] of copies) {
314
315
  const source = path.resolve(root, file);
315
- if (!FSExtra.existsSync(source)) {
316
+ if (!existsSync(source)) {
316
317
  throw new Error(`[vxrn] native.app names ${file}, which does not exist`);
317
318
  }
318
- FSExtra.mkdirSync(path.dirname(target), { recursive: true });
319
- FSExtra.copyFileSync(source, target);
319
+ mkdirSync(path.dirname(target), { recursive: true });
320
+ copyFileSync(source, target);
320
321
  }
321
322
  }
322
323
  function patchIosPbxprojAppEntitlements(rendered, appName) {
@@ -522,29 +523,29 @@ ${value}`);
522
523
  function generateSceneDelegate(args) {
523
524
  const { dest, platform, app } = args;
524
525
  if (platform !== "ios") return;
525
- FSExtra.writeFileSync(path.join(dest, app.name, "SceneDelegate.swift"), renderSceneDelegateSwift(app.name));
526
+ writeFileSync(path.join(dest, app.name, "SceneDelegate.swift"), renderSceneDelegateSwift(app.name));
526
527
  const entitlements = appEntitlements(app);
527
528
  if (Object.keys(entitlements).length && !app.ios?.widgets) {
528
- FSExtra.writeFileSync(path.join(dest, app.name, `${app.name}.entitlements`), renderEntitlements(entitlements));
529
+ writeFileSync(path.join(dest, app.name, `${app.name}.entitlements`), renderEntitlements(entitlements));
529
530
  }
530
531
  }
531
532
  function generateIosAppIntents(dest, platform, app) {
532
533
  if (platform !== "ios" || !app.ios?.appIntents) return;
533
- FSExtra.writeFileSync(path.join(dest, app.name, "OneAppIntents.swift"), renderIosAppIntentsSwift(app.ios.appIntents.actions));
534
+ writeFileSync(path.join(dest, app.name, "OneAppIntents.swift"), renderIosAppIntentsSwift(app.ios.appIntents.actions));
534
535
  }
535
536
  function generateIosWidgets(dest, app) {
536
537
  const widgets = app.ios?.widgets;
537
538
  if (!widgets) return;
538
539
  const appDir = path.join(dest, app.name);
539
540
  const extensionDir = path.join(dest, "OneWidgets");
540
- FSExtra.mkdirSync(extensionDir, { recursive: true });
541
+ mkdirSync(extensionDir, { recursive: true });
541
542
  const entitlements = `<?xml version="1.0" encoding="UTF-8"?>
542
543
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
543
544
  <plist version="1.0"><dict><key>com.apple.security.application-groups</key><array><string>${escapeXml(widgets.appGroup)}</string></array></dict></plist>
544
545
  `;
545
- FSExtra.writeFileSync(path.join(appDir, "OneAppWidgets.entitlements"), renderEntitlements(appEntitlements(app)));
546
- FSExtra.writeFileSync(path.join(extensionDir, "OneWidgets.entitlements"), entitlements);
547
- FSExtra.writeFileSync(path.join(extensionDir, "WidgetInfo.plist"), `<?xml version="1.0" encoding="UTF-8"?>
546
+ writeFileSync(path.join(appDir, "OneAppWidgets.entitlements"), renderEntitlements(appEntitlements(app)));
547
+ writeFileSync(path.join(extensionDir, "OneWidgets.entitlements"), entitlements);
548
+ writeFileSync(path.join(extensionDir, "WidgetInfo.plist"), `<?xml version="1.0" encoding="UTF-8"?>
548
549
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
549
550
  <plist version="1.0"><dict>
550
551
  <key>CFBundleDevelopmentRegion</key><string>$(DEVELOPMENT_LANGUAGE)</string>
@@ -559,7 +560,7 @@ function generateIosWidgets(dest, app) {
559
560
  <key>NSExtension</key><dict><key>NSExtensionPointIdentifier</key><string>com.apple.widgetkit-extension</string></dict>
560
561
  </dict></plist>
561
562
  `);
562
- FSExtra.writeFileSync(path.join(appDir, "OneWidgetContract.swift"), `import Foundation
563
+ writeFileSync(path.join(appDir, "OneWidgetContract.swift"), `import Foundation
563
564
  import ActivityKit
564
565
 
565
566
  enum OneWidgetContract {
@@ -584,7 +585,7 @@ enum OneWidgetContract {
584
585
  }
585
586
  }
586
587
  `);
587
- FSExtra.writeFileSync(path.join(extensionDir, "OneWidget.swift"), `import SwiftUI
588
+ writeFileSync(path.join(extensionDir, "OneWidget.swift"), `import SwiftUI
588
589
  import WidgetKit
589
590
  import ActivityKit
590
591
 
@@ -872,7 +873,7 @@ struct OneWidgetsBundle: WidgetBundle {
872
873
  }
873
874
  }
874
875
  `);
875
- FSExtra.writeFileSync(path.join(appDir, "OneWidgetsBridge.m"), `#import <React/RCTBridgeModule.h>
876
+ writeFileSync(path.join(appDir, "OneWidgetsBridge.m"), `#import <React/RCTBridgeModule.h>
876
877
  #import <React/RCTEventEmitter.h>
877
878
 
878
879
  @interface RCT_EXTERN_MODULE(OneWidgetsBridge, RCTEventEmitter)
@@ -886,7 +887,7 @@ RCT_EXTERN_METHOD(end:(NSString *)identifier resolver:(RCTPromiseResolveBlock)re
886
887
  RCT_EXTERN_METHOD(pushToken:(NSString *)identifier resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
887
888
  @end
888
889
  `);
889
- FSExtra.writeFileSync(path.join(appDir, "OneWidgetsBridge.swift"), `import Foundation
890
+ writeFileSync(path.join(appDir, "OneWidgetsBridge.swift"), `import Foundation
890
891
  import React
891
892
  import WidgetKit
892
893
  import ActivityKit
@@ -1062,7 +1063,7 @@ async function writeAppearanceIcon(args) {
1062
1063
  const variantSource = (variant) => {
1063
1064
  if (!variant?.source) return source;
1064
1065
  const resolved = path.resolve(root, variant.source);
1065
- if (!FSExtra.existsSync(resolved)) {
1066
+ if (!existsSync(resolved)) {
1066
1067
  throw new Error(`[vxrn] native.app icon appearance source does not exist: ${resolved}`);
1067
1068
  }
1068
1069
  return resolved;
@@ -1094,7 +1095,7 @@ async function writeAppearanceIcon(args) {
1094
1095
  await render("icon-1024-tinted.png", variantSource(icon.tinted), icon.tinted.backgroundColor ?? "#000000", true);
1095
1096
  images.push(entry("icon-1024-tinted.png", "tinted"));
1096
1097
  }
1097
- FSExtra.writeFileSync(path.join(iconDir, "Contents.json"), `${JSON.stringify({
1098
+ writeFileSync(path.join(iconDir, "Contents.json"), `${JSON.stringify({
1098
1099
  images,
1099
1100
  info: {
1100
1101
  author: "xcode",
@@ -1108,11 +1109,11 @@ async function generateAppIcons(args) {
1108
1109
  if (!app.icon) return;
1109
1110
  if (platform === "ios") {
1110
1111
  const assetsDir = path.join(dest, app.name, "Images.xcassets");
1111
- const template = JSON.parse(FSExtra.readFileSync(path.join(assetsDir, "AppIcon.appiconset", "Contents.json"), "utf8"));
1112
+ const template = JSON.parse(readFileSync(path.join(assetsDir, "AppIcon.appiconset", "Contents.json"), "utf8"));
1112
1113
  const icons = [["AppIcon", app.icon], ...Object.entries(app.alternateIcons ?? {})];
1113
1114
  for (const [name, icon] of icons) {
1114
1115
  const source2 = path.resolve(root, icon.source);
1115
- if (!FSExtra.existsSync(source2)) {
1116
+ if (!existsSync(source2)) {
1116
1117
  throw new Error(`[vxrn] native.app icon source does not exist: ${source2}`);
1117
1118
  }
1118
1119
  const metadata2 = await sharp(source2).metadata();
@@ -1120,7 +1121,7 @@ async function generateAppIcons(args) {
1120
1121
  throw new Error(`[vxrn] native.app icon source must be a square image at least 1024px wide: ${source2}`);
1121
1122
  }
1122
1123
  const iconDir = path.join(assetsDir, `${name}.appiconset`);
1123
- FSExtra.mkdirSync(iconDir, { recursive: true });
1124
+ mkdirSync(iconDir, { recursive: true });
1124
1125
  if (icon.dark || icon.tinted) {
1125
1126
  await writeAppearanceIcon({
1126
1127
  root,
@@ -1148,13 +1149,13 @@ async function generateAppIcons(args) {
1148
1149
  image.filename = filename;
1149
1150
  await sharp(source2).rotate().resize(pixels, pixels, { fit: "cover" }).flatten({ background: icon.backgroundColor }).png().toFile(path.join(iconDir, filename));
1150
1151
  }
1151
- FSExtra.writeFileSync(path.join(iconDir, "Contents.json"), `${JSON.stringify(contents, null, 2)}
1152
+ writeFileSync(path.join(iconDir, "Contents.json"), `${JSON.stringify(contents, null, 2)}
1152
1153
  `);
1153
1154
  }
1154
1155
  return;
1155
1156
  }
1156
1157
  const source = path.resolve(root, app.icon.source);
1157
- if (!FSExtra.existsSync(source)) {
1158
+ if (!existsSync(source)) {
1158
1159
  throw new Error(`[vxrn] native.app.icon source does not exist: ${source}`);
1159
1160
  }
1160
1161
  const metadata = await sharp(source).metadata();
@@ -1167,7 +1168,7 @@ async function generateAppIcons(args) {
1167
1168
  source
1168
1169
  ], ...await Promise.all(Object.entries(app.alternateIcons ?? {}).map(async ([name, icon]) => {
1169
1170
  const alternateSource = path.resolve(root, icon.source);
1170
- if (!FSExtra.existsSync(alternateSource)) {
1171
+ if (!existsSync(alternateSource)) {
1171
1172
  throw new Error(`[vxrn] native.app icon source does not exist: ${alternateSource}`);
1172
1173
  }
1173
1174
  const alternate = await sharp(alternateSource).metadata();
@@ -1234,8 +1235,8 @@ function generateAndroidIconForwarder(dest, app) {
1234
1235
  if (!app.alternateIcons || !app.android) return;
1235
1236
  const packageName = app.android.applicationId;
1236
1237
  const file = path.join(dest, "app", "src", "main", "java", ...packageName.split("."), "AppIconLauncherActivity.kt");
1237
- FSExtra.mkdirSync(path.dirname(file), { recursive: true });
1238
- FSExtra.writeFileSync(file, `package ${packageName}
1238
+ mkdirSync(path.dirname(file), { recursive: true });
1239
+ writeFileSync(file, `package ${packageName}
1239
1240
 
1240
1241
  import android.app.Activity
1241
1242
  import android.content.Intent
@@ -1262,12 +1263,12 @@ async function generateAppIconPreviews(args) {
1262
1263
  const resources = appIconPreviewResources(name);
1263
1264
  if (platform === "android") {
1264
1265
  const dir2 = path.join(dest, "app", "src", "main", "res", "drawable-nodpi");
1265
- FSExtra.mkdirSync(dir2, { recursive: true });
1266
+ mkdirSync(dir2, { recursive: true });
1266
1267
  await preview(3).toFile(path.join(dir2, `${resources.android}.png`));
1267
1268
  continue;
1268
1269
  }
1269
1270
  const dir = path.join(dest, app.name, "Images.xcassets", `${resources.ios}.imageset`);
1270
- FSExtra.mkdirSync(dir, { recursive: true });
1271
+ mkdirSync(dir, { recursive: true });
1271
1272
  const images = [];
1272
1273
  for (const scale of [
1273
1274
  1,
@@ -1282,7 +1283,7 @@ async function generateAppIconPreviews(args) {
1282
1283
  scale: `${scale}x`
1283
1284
  });
1284
1285
  }
1285
- FSExtra.writeFileSync(path.join(dir, "Contents.json"), `${JSON.stringify({
1286
+ writeFileSync(path.join(dir, "Contents.json"), `${JSON.stringify({
1286
1287
  images,
1287
1288
  info: {
1288
1289
  author: "xcode",
@@ -1305,7 +1306,7 @@ async function generateAdaptiveIcon(args) {
1305
1306
  for (const [layer, file] of Object.entries(layers)) {
1306
1307
  if (!file) continue;
1307
1308
  const source = path.resolve(root, file);
1308
- if (!FSExtra.existsSync(source)) {
1309
+ if (!existsSync(source)) {
1309
1310
  throw new Error(`[vxrn] native.app.android.adaptiveIcon.${layer} does not exist: ${source}`);
1310
1311
  }
1311
1312
  for (const [density, multiplier] of Object.entries(ANDROID_DENSITIES)) {
@@ -1314,7 +1315,7 @@ async function generateAdaptiveIcon(args) {
1314
1315
  }
1315
1316
  }
1316
1317
  if (!adaptiveIcon.background) {
1317
- FSExtra.writeFileSync(path.join(res, "values", "ic_launcher_background.xml"), `<?xml version="1.0" encoding="utf-8"?>
1318
+ writeFileSync(path.join(res, "values", "ic_launcher_background.xml"), `<?xml version="1.0" encoding="utf-8"?>
1318
1319
  <resources>
1319
1320
  <color name="ic_launcher_background">${adaptiveIcon.backgroundColor ?? "#FFFFFF"}</color>
1320
1321
  </resources>
@@ -1327,9 +1328,9 @@ async function generateAdaptiveIcon(args) {
1327
1328
  ${adaptiveIcon.monochrome ? " <monochrome android:drawable=\"@mipmap/ic_launcher_monochrome\"/>\n" : ""}</adaptive-icon>
1328
1329
  `;
1329
1330
  const anydpi = path.join(res, "mipmap-anydpi-v26");
1330
- FSExtra.mkdirSync(anydpi, { recursive: true });
1331
+ mkdirSync(anydpi, { recursive: true });
1331
1332
  for (const filename of ["ic_launcher.xml", "ic_launcher_round.xml"]) {
1332
- FSExtra.writeFileSync(path.join(anydpi, filename), adaptiveXml);
1333
+ writeFileSync(path.join(anydpi, filename), adaptiveXml);
1333
1334
  }
1334
1335
  }
1335
1336
  const IOS_DARK_APPEARANCE = [{
@@ -1375,8 +1376,8 @@ function generateAccentColor(args) {
1375
1376
  const accent = args.app.ios?.accentColor;
1376
1377
  if (!accent) return;
1377
1378
  const colorDir = path.join(args.dest, args.app.name, "Images.xcassets", "AccentColor.colorset");
1378
- FSExtra.mkdirSync(colorDir, { recursive: true });
1379
- FSExtra.writeFileSync(path.join(colorDir, "Contents.json"), xcodeColorSet(accent.light, accent.dark));
1379
+ mkdirSync(colorDir, { recursive: true });
1380
+ writeFileSync(path.join(colorDir, "Contents.json"), xcodeColorSet(accent.light, accent.dark));
1380
1381
  }
1381
1382
  async function generateSplashScreen(args) {
1382
1383
  const { root, dest, platform, app } = args;
@@ -1384,7 +1385,7 @@ async function generateSplashScreen(args) {
1384
1385
  const cover = app.splash.resizeMode === "cover";
1385
1386
  const prepareArtwork = async (sourcePath, backgroundColor) => {
1386
1387
  const source = path.resolve(root, sourcePath);
1387
- if (!FSExtra.existsSync(source)) {
1388
+ if (!existsSync(source)) {
1388
1389
  throw new Error(`[vxrn] native.app.splash source does not exist: ${source}`);
1389
1390
  }
1390
1391
  const { width: sourceWidth, format } = await sharp(source).metadata();
@@ -1403,7 +1404,7 @@ async function generateSplashScreen(args) {
1403
1404
  const artworkHeight = Number((artworkWidth * (metadata.height / metadata.width)).toFixed(3));
1404
1405
  const readBackground = (sourcePath) => {
1405
1406
  const source = path.resolve(root, sourcePath);
1406
- if (!FSExtra.existsSync(source)) {
1407
+ if (!existsSync(source)) {
1407
1408
  throw new Error(`[vxrn] native.app.splash backgroundImage does not exist: ${source}`);
1408
1409
  }
1409
1410
  return sharp(source).rotate().png().toBuffer({ resolveWithObject: true });
@@ -1413,7 +1414,7 @@ async function generateSplashScreen(args) {
1413
1414
  const assets = path.join(appDir, "Images.xcassets");
1414
1415
  const writeImageSet = async (name, light, dark2, pointWidth) => {
1415
1416
  const dir = path.join(assets, `${name}.imageset`);
1416
- FSExtra.mkdirSync(dir, { recursive: true });
1417
+ mkdirSync(dir, { recursive: true });
1417
1418
  const scales = pointWidth === void 0 ? [1] : [
1418
1419
  1,
1419
1420
  2,
@@ -1442,7 +1443,7 @@ async function generateSplashScreen(args) {
1442
1443
  });
1443
1444
  }
1444
1445
  }
1445
- FSExtra.writeFileSync(path.join(dir, "Contents.json"), `${JSON.stringify({
1446
+ writeFileSync(path.join(dir, "Contents.json"), `${JSON.stringify({
1446
1447
  images,
1447
1448
  info: {
1448
1449
  author: "xcode",
@@ -1458,10 +1459,10 @@ async function generateSplashScreen(args) {
1458
1459
  await writeImageSet("SplashBackgroundImage", background2.data, darkBackground2, void 0);
1459
1460
  }
1460
1461
  const colorDir = path.join(assets, "SplashBackground.colorset");
1461
- FSExtra.mkdirSync(colorDir, { recursive: true });
1462
- FSExtra.writeFileSync(path.join(colorDir, "Contents.json"), xcodeColorSet(app.splash.backgroundColor, dark?.backgroundColor));
1462
+ mkdirSync(colorDir, { recursive: true });
1463
+ writeFileSync(path.join(colorDir, "Contents.json"), xcodeColorSet(app.splash.backgroundColor, dark?.backgroundColor));
1463
1464
  const { red, green, blue } = srgb(app.splash.backgroundColor);
1464
- FSExtra.writeFileSync(path.join(appDir, "LaunchScreen.storyboard"), `<?xml version="1.0" encoding="UTF-8"?>
1465
+ writeFileSync(path.join(appDir, "LaunchScreen.storyboard"), `<?xml version="1.0" encoding="UTF-8"?>
1465
1466
  <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="launch-controller">
1466
1467
  <device id="retina6_12" orientation="portrait" appearance="light"/>
1467
1468
  <dependencies>
@@ -1528,7 +1529,7 @@ ${cover ? ` <constraint firstItem="splash-image" firstAttribute="le
1528
1529
  }
1529
1530
  }).png().toBuffer();
1530
1531
  const drawableDensity = path.join(mainRes, `${drawablePrefix}-${density}`);
1531
- FSExtra.mkdirSync(drawableDensity, { recursive: true });
1532
+ mkdirSync(drawableDensity, { recursive: true });
1532
1533
  await sharp({ create: {
1533
1534
  width: canvasSize,
1534
1535
  height: canvasSize,
@@ -1550,15 +1551,15 @@ ${cover ? ` <constraint firstItem="splash-image" firstAttribute="le
1550
1551
  const darkBackground = dark?.backgroundImage ? (await readBackground(dark.backgroundImage)).data : void 0;
1551
1552
  if (background) {
1552
1553
  const nodpi = path.join(mainRes, "drawable-nodpi");
1553
- FSExtra.mkdirSync(nodpi, { recursive: true });
1554
- FSExtra.writeFileSync(path.join(nodpi, "splash_background.png"), background.data);
1554
+ mkdirSync(nodpi, { recursive: true });
1555
+ writeFileSync(path.join(nodpi, "splash_background.png"), background.data);
1555
1556
  if (darkBackground) {
1556
1557
  const nightNodpi = path.join(mainRes, "drawable-night-nodpi");
1557
- FSExtra.mkdirSync(nightNodpi, { recursive: true });
1558
- FSExtra.writeFileSync(path.join(nightNodpi, "splash_background.png"), darkBackground);
1558
+ mkdirSync(nightNodpi, { recursive: true });
1559
+ writeFileSync(path.join(nightNodpi, "splash_background.png"), darkBackground);
1559
1560
  }
1560
1561
  }
1561
- FSExtra.writeFileSync(path.join(drawable, "launch_screen.xml"), `<?xml version="1.0" encoding="utf-8"?>
1562
+ writeFileSync(path.join(drawable, "launch_screen.xml"), `<?xml version="1.0" encoding="utf-8"?>
1562
1563
  <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
1563
1564
  <item android:drawable="@color/splash_background" />
1564
1565
  ${background ? ` <item>
@@ -1569,28 +1570,28 @@ ${background ? ` <item>
1569
1570
  </item>
1570
1571
  </layer-list>
1571
1572
  `);
1572
- FSExtra.writeFileSync(path.join(mainRes, "values", "colors.xml"), `<?xml version="1.0" encoding="utf-8"?>
1573
+ writeFileSync(path.join(mainRes, "values", "colors.xml"), `<?xml version="1.0" encoding="utf-8"?>
1573
1574
  <resources>
1574
1575
  <color name="splash_background">${app.splash.backgroundColor}</color>
1575
1576
  </resources>
1576
1577
  `);
1577
1578
  if (dark) {
1578
- FSExtra.mkdirSync(path.join(mainRes, "values-night"), { recursive: true });
1579
- FSExtra.writeFileSync(path.join(mainRes, "values-night", "colors.xml"), `<?xml version="1.0" encoding="utf-8"?>
1579
+ mkdirSync(path.join(mainRes, "values-night"), { recursive: true });
1580
+ writeFileSync(path.join(mainRes, "values-night", "colors.xml"), `<?xml version="1.0" encoding="utf-8"?>
1580
1581
  <resources>
1581
1582
  <color name="splash_background">${dark.backgroundColor}</color>
1582
1583
  </resources>
1583
1584
  `);
1584
1585
  }
1585
1586
  const stylesPath = path.join(mainRes, "values", "styles.xml");
1586
- const styles = FSExtra.readFileSync(stylesPath, "utf8").replace(" <!-- Customize your theme here. -->", " <item name=\"android:windowBackground\">@drawable/launch_screen</item>");
1587
- FSExtra.writeFileSync(stylesPath, styles);
1587
+ const styles = readFileSync(stylesPath, "utf8").replace(" <!-- Customize your theme here. -->", " <item name=\"android:windowBackground\">@drawable/launch_screen</item>");
1588
+ writeFileSync(stylesPath, styles);
1588
1589
  const stylesV31 = path.join(mainRes, "values-v31");
1589
- FSExtra.mkdirSync(stylesV31, { recursive: true });
1590
+ mkdirSync(stylesV31, { recursive: true });
1590
1591
  if (!styles.includes("</style>")) {
1591
1592
  throw new Error("[vxrn] prebuild template styles.xml lost its AppTheme </style> anchor");
1592
1593
  }
1593
- FSExtra.writeFileSync(path.join(stylesV31, "styles.xml"), styles.replace("</style>", ` <item name="android:windowSplashScreenBackground">@color/splash_background</item>
1594
+ writeFileSync(path.join(stylesV31, "styles.xml"), styles.replace("</style>", ` <item name="android:windowSplashScreenBackground">@color/splash_background</item>
1594
1595
  <item name="android:windowSplashScreenAnimatedIcon">@drawable/splash</item>
1595
1596
  </style>`));
1596
1597
  }
@@ -2126,17 +2127,20 @@ const generateForPlatform = async (root, platform, app, outDir = path.resolve(ro
2126
2127
  }
2127
2128
  const files = [...walkFn(src)].sort();
2128
2129
  const nitroWebImage = platform === "ios" && nativeProjectPatches.hasNitroWebImage(root);
2129
- FSExtra.removeSync(dest);
2130
+ rmSync(dest, {
2131
+ recursive: true,
2132
+ force: true
2133
+ });
2130
2134
  for (const absoluteSrc of files) {
2131
2135
  const relativeFilePath = path.relative(src, absoluteSrc);
2132
- const stat = FSExtra.lstatSync(absoluteSrc);
2136
+ const stat = lstatSync(absoluteSrc);
2133
2137
  if (stat.isDirectory()) continue;
2134
2138
  const extension = path.extname(absoluteSrc);
2135
2139
  const raw = [
2136
2140
  ".png",
2137
2141
  ".jar",
2138
2142
  ".keystore"
2139
- ].includes(extension) ? null : FSExtra.readFileSync(absoluteSrc, "utf8");
2143
+ ].includes(extension) ? null : readFileSync(absoluteSrc, "utf8");
2140
2144
  const { destRelativePath, content } = renderPrebuildFile({
2141
2145
  relativePath: relativeFilePath,
2142
2146
  content: raw,
@@ -2145,13 +2149,13 @@ const generateForPlatform = async (root, platform, app, outDir = path.resolve(ro
2145
2149
  nitroWebImage
2146
2150
  });
2147
2151
  const destPath = path.resolve(dest, destRelativePath);
2148
- FSExtra.mkdirSync(path.dirname(destPath), { recursive: true });
2152
+ mkdirSync(path.dirname(destPath), { recursive: true });
2149
2153
  console.info("copying", "\"" + absoluteSrc + "\"", "to", "\"" + destPath + "\"");
2150
2154
  if (content === null) {
2151
- FSExtra.copyFileSync(absoluteSrc, destPath);
2155
+ copyFileSync(absoluteSrc, destPath);
2152
2156
  continue;
2153
2157
  }
2154
- FSExtra.writeFileSync(destPath, content, {
2158
+ writeFileSync(destPath, content, {
2155
2159
  encoding: "utf8",
2156
2160
  mode: stat.mode
2157
2161
  });
@@ -2215,14 +2219,14 @@ const KOTLIN_IMPORT_ARTIFACTS = [{
2215
2219
  }];
2216
2220
  function kotlinSourceImports(dir) {
2217
2221
  const imports = /* @__PURE__ */ new Set();
2218
- if (!FSExtra.existsSync(dir)) return imports;
2222
+ if (!existsSync(dir)) return imports;
2219
2223
  const visit = (entry) => {
2220
- if (FSExtra.statSync(entry).isDirectory()) {
2221
- for (const child of FSExtra.readdirSync(entry)) visit(path.join(entry, child));
2224
+ if (statSync(entry).isDirectory()) {
2225
+ for (const child of readdirSync(entry)) visit(path.join(entry, child));
2222
2226
  return;
2223
2227
  }
2224
2228
  if (!entry.endsWith(".kt")) return;
2225
- for (const line of FSExtra.readFileSync(entry, "utf8").split("\n")) {
2229
+ for (const line of readFileSync(entry, "utf8").split("\n")) {
2226
2230
  const match = /^\s*import\s+([A-Za-z0-9_.]+)/.exec(line);
2227
2231
  if (match) imports.add(match[1]);
2228
2232
  }
@@ -2232,18 +2236,18 @@ function kotlinSourceImports(dir) {
2232
2236
  }
2233
2237
  function enableAppComposeIntegration(dest) {
2234
2238
  const rootBuildGradlePath = path.join(dest, "build.gradle");
2235
- if (FSExtra.existsSync(rootBuildGradlePath)) {
2236
- let content = FSExtra.readFileSync(rootBuildGradlePath, "utf8");
2239
+ if (existsSync(rootBuildGradlePath)) {
2240
+ let content = readFileSync(rootBuildGradlePath, "utf8");
2237
2241
  const composePluginClasspath = " classpath(\"org.jetbrains.kotlin.plugin.compose:org.jetbrains.kotlin.plugin.compose.gradle.plugin:$kotlinVersion\")";
2238
2242
  if (!content.includes("org.jetbrains.kotlin.plugin.compose")) {
2239
2243
  const anchor = content.includes("classpath(\"org.jetbrains.kotlin:kotlin-gradle-plugin\")") ? "classpath(\"org.jetbrains.kotlin:kotlin-gradle-plugin\")" : "classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin\"";
2240
2244
  content = insertAfterLine(content, anchor, composePluginClasspath);
2241
- FSExtra.writeFileSync(rootBuildGradlePath, content, "utf8");
2245
+ writeFileSync(rootBuildGradlePath, content, "utf8");
2242
2246
  }
2243
2247
  }
2244
2248
  const appBuildGradlePath = path.join(dest, "app/build.gradle");
2245
- if (FSExtra.existsSync(appBuildGradlePath)) {
2246
- let content = FSExtra.readFileSync(appBuildGradlePath, "utf8");
2249
+ if (existsSync(appBuildGradlePath)) {
2250
+ let content = readFileSync(appBuildGradlePath, "utf8");
2247
2251
  if (!content.includes("org.jetbrains.kotlin.plugin.compose")) {
2248
2252
  const pluginAnchor = content.includes("apply plugin: \"org.jetbrains.kotlin.android\"") ? "apply plugin: \"org.jetbrains.kotlin.android\"" : "apply plugin: 'org.jetbrains.kotlin.android'";
2249
2253
  content = insertAfterLine(content, pluginAnchor, "apply plugin: \"org.jetbrains.kotlin.plugin.compose\"");
@@ -2272,7 +2276,7 @@ function enableAppComposeIntegration(dest) {
2272
2276
  const anchor = content.includes("androidx.compose.material3:material3") ? "androidx.compose.material3:material3" : reactAnchor;
2273
2277
  content = insertAfterLine(content, anchor, [` def ${rule.versionKey} = rootProject.ext.has("${rule.versionKey}") ? rootProject.ext.get("${rule.versionKey}") : "${rule.version}"`, ` implementation "${rule.artifact}:$${rule.versionKey}"`].join("\n"));
2274
2278
  }
2275
- FSExtra.writeFileSync(appBuildGradlePath, content, "utf8");
2279
+ writeFileSync(appBuildGradlePath, content, "utf8");
2276
2280
  }
2277
2281
  }
2278
2282
  async function generateKotlinSources({ root, dest }) {
@@ -2289,7 +2293,7 @@ async function generateKotlinSources({ root, dest }) {
2289
2293
  "evidence"
2290
2294
  ]);
2291
2295
  const sources = [];
2292
- const manifest = FSExtra.existsSync(path.join(root, "package.json")) ? FSExtra.readJsonSync(path.join(root, "package.json")) : {};
2296
+ const manifest = existsSync(path.join(root, "package.json")) ? readJSONSync(path.join(root, "package.json")) : {};
2293
2297
  const workspacePatterns = Array.isArray(manifest.workspaces) ? manifest.workspaces : manifest.workspaces?.packages ?? [];
2294
2298
  const { default: glob } = await import("fast-glob");
2295
2299
  const workspaceRoots = new Set(glob.sync(workspacePatterns, {
@@ -2303,8 +2307,8 @@ async function generateKotlinSources({ root, dest }) {
2303
2307
  ]
2304
2308
  }).map((directory) => path.resolve(directory)));
2305
2309
  const collect = (dir) => {
2306
- if (dir !== root && FSExtra.existsSync(path.join(dir, "package.json")) && !workspaceRoots.has(dir)) return;
2307
- for (const entry of FSExtra.readdirSync(dir, { withFileTypes: true })) {
2310
+ if (dir !== root && existsSync(path.join(dir, "package.json")) && !workspaceRoots.has(dir)) return;
2311
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
2308
2312
  if (entry.name.startsWith(".") || skip.has(entry.name)) continue;
2309
2313
  const source = path.join(dir, entry.name);
2310
2314
  if (entry.isDirectory()) collect(source);
@@ -2313,19 +2317,22 @@ async function generateKotlinSources({ root, dest }) {
2313
2317
  };
2314
2318
  collect(root);
2315
2319
  const output = path.join(dest, "app/src/main/java/one/source");
2316
- FSExtra.removeSync(output);
2320
+ rmSync(output, {
2321
+ recursive: true,
2322
+ force: true
2323
+ });
2317
2324
  if (sources.length === 0) return;
2318
2325
  const { kotlinSourceId, renderKotlinSourceGlue, writeNativeSourceDeclaration } = await import("../utils/nativeSourceContract.mjs");
2319
2326
  let hasViews = false;
2320
2327
  for (const source of sources) {
2321
2328
  const id = kotlinSourceId(root, source);
2322
2329
  const target = path.join(output, id);
2323
- FSExtra.mkdirSync(target, { recursive: true });
2324
- FSExtra.copyFileSync(source, path.join(target, path.basename(source)));
2330
+ mkdirSync(target, { recursive: true });
2331
+ copyFileSync(source, path.join(target, path.basename(source)));
2325
2332
  const contract = writeNativeSourceDeclaration(source);
2326
2333
  if (contract.views.length > 0) hasViews = true;
2327
2334
  if (contract.modules.length > 0 || contract.views.length > 0) {
2328
- FSExtra.writeFileSync(path.join(target, `OneNativeSource_${id}.kt`), renderKotlinSourceGlue(id, contract).source);
2335
+ writeFileSync(path.join(target, `OneNativeSource_${id}.kt`), renderKotlinSourceGlue(id, contract).source);
2329
2336
  }
2330
2337
  }
2331
2338
  if (hasViews) {
@@ -2346,10 +2353,10 @@ async function generateSwiftPackages({ root, dest }) {
2346
2353
  const { swiftPodManifest, writeSwiftPackageArtifacts } = await import("../utils/nativeSourceContract.mjs");
2347
2354
  for (const [id, packageDir] of packages) {
2348
2355
  const podDir = path.join(dest, "OneSwiftPackages", id);
2349
- const manifest = swiftPodManifest(path.join(packageDir, "Package.swift"), FSExtra.readFileSync(path.join(packageDir, "Package.swift"), "utf8"));
2356
+ const manifest = swiftPodManifest(path.join(packageDir, "Package.swift"), readFileSync(path.join(packageDir, "Package.swift"), "utf8"));
2350
2357
  const sources = [];
2351
2358
  const collect = (dir) => {
2352
- for (const entry of FSExtra.readdirSync(dir, { withFileTypes: true })) {
2359
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
2353
2360
  if (entry.name.startsWith(".") || skip.has(entry.name)) continue;
2354
2361
  const full = path.join(dir, entry.name);
2355
2362
  if (entry.isDirectory()) collect(full);
@@ -2365,13 +2372,13 @@ async function generateSwiftPackages({ root, dest }) {
2365
2372
  }
2366
2373
  for (const source of sources) {
2367
2374
  const link = path.join(podDir, "Sources", path.relative(packageDir, source));
2368
- FSExtra.mkdirSync(path.dirname(link), { recursive: true });
2369
- FSExtra.symlinkSync(FSExtra.realpathSync(source), link);
2375
+ mkdirSync(path.dirname(link), { recursive: true });
2376
+ symlinkSync(realpathSync(source), link);
2370
2377
  }
2371
2378
  if (artifacts.glue) {
2372
- FSExtra.writeFileSync(path.join(podDir, "Sources", "OneNativeSource.generated.swift"), artifacts.glue);
2379
+ writeFileSync(path.join(podDir, "Sources", "OneNativeSource.generated.swift"), artifacts.glue);
2373
2380
  }
2374
- FSExtra.writeFileSync(path.join(podDir, `${id}.podspec`), `Pod::Spec.new do |s|
2381
+ writeFileSync(path.join(podDir, `${id}.podspec`), `Pod::Spec.new do |s|
2375
2382
  s.name = '${id}'
2376
2383
  s.version = '0.0.0'
2377
2384
  s.summary = 'swift package ${path.relative(root, packageDir) || "."}'
@@ -2387,7 +2394,7 @@ async function generateSwiftPackages({ root, dest }) {
2387
2394
  }
2388
2395
  end
2389
2396
  `);
2390
- FSExtra.writeFileSync(path.join(podDir, "Register.m"), hasView ? `#import <Foundation/Foundation.h>
2397
+ writeFileSync(path.join(podDir, "Register.m"), hasView ? `#import <Foundation/Foundation.h>
2391
2398
 
2392
2399
  extern int ${id}_main(int argc, char **argv);
2393
2400
  extern void OneSwiftRegisterPackage(const char *name, int (*entry)(int, char **));
@@ -2409,11 +2416,11 @@ function applyAndroidDependencyPatches(args) {
2409
2416
  return;
2410
2417
  }
2411
2418
  const activityPath = path.join(root, "android", "app", "src", "main", "java", ...app.android.applicationId.split("."), "MainActivity.kt");
2412
- const rendered = nativeProjectPatches.holdLaunchScreenInMainActivity(nativeProjectPatches.addReactNativeScreensFix(FSExtra.readFileSync(activityPath, "utf8")));
2419
+ const rendered = nativeProjectPatches.holdLaunchScreenInMainActivity(nativeProjectPatches.addReactNativeScreensFix(readFileSync(activityPath, "utf8")));
2413
2420
  if (!rendered.includes("RNScreensFragmentFactory")) {
2414
2421
  throw new Error("[vxrn] failed to apply the react-native-screens activity patch");
2415
2422
  }
2416
- FSExtra.writeFileSync(activityPath, rendered);
2423
+ writeFileSync(activityPath, rendered);
2417
2424
  }
2418
2425
  async function getNativeDependencyInventory(root) {
2419
2426
  const cliConfigPath = requireVxrn.resolve("@react-native-community/cli-config");
@@ -2425,7 +2432,7 @@ async function getNativeDependencyInventory(root) {
2425
2432
  const depRoot = dependency.root;
2426
2433
  let version = "unknown";
2427
2434
  try {
2428
- version = JSON.parse(FSExtra.readFileSync(path.join(depRoot, "package.json"), "utf8")).version ?? "unknown";
2435
+ version = JSON.parse(readFileSync(path.join(depRoot, "package.json"), "utf8")).version ?? "unknown";
2429
2436
  } catch {}
2430
2437
  const platforms = Object.entries(dependency.platforms).filter(([, platformConfig]) => platformConfig !== null).map(([platform]) => platform).sort();
2431
2438
  if (platforms.length > 0) inventory.push({