vxrn 2.0.0-beta.111.1 → 2.0.0-beta.114.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.
- package/dist/exports/prebuildWithoutExpo.mjs +99 -18
- package/dist/exports/prebuildWithoutExpo.mjs.map +1 -1
- package/dist/exports/prebuildWithoutExpo.native.js +111 -49
- package/dist/exports/prebuildWithoutExpo.native.js.map +1 -1
- package/dist/utils/swiftPackageId.mjs +31 -2
- package/dist/utils/swiftPackageId.mjs.map +1 -1
- package/dist/utils/swiftPackageId.native.js +50 -2
- package/dist/utils/swiftPackageId.native.js.map +1 -1
- package/expo-plugin.cjs +82 -0
- package/native-project-patches.cjs +72 -0
- package/package.json +10 -10
- package/src/exports/prebuildWithoutExpo.test.ts +312 -0
- package/src/exports/prebuildWithoutExpo.ts +170 -20
- package/src/utils/swiftPackageId.ts +25 -1
- package/types/exports/prebuildWithoutExpo.d.ts.map +1 -1
- package/types/utils/swiftPackageId.d.ts +1 -0
- package/types/utils/swiftPackageId.d.ts.map +1 -1
|
@@ -5,10 +5,11 @@ import { pathToFileURL } from "node:url";
|
|
|
5
5
|
import { validateNativeApp } from "@vxrn/utils/nativeAppManifest";
|
|
6
6
|
import FSExtra from "fs-extra";
|
|
7
7
|
import sharp from "sharp";
|
|
8
|
-
import {
|
|
8
|
+
import { swiftPackageDirectories } from "../utils/swiftPackageId.mjs";
|
|
9
9
|
|
|
10
10
|
const nativeProjectPatches = module.createRequire(import.meta.url)("../../native-project-patches.cjs");
|
|
11
11
|
const notificationsHost = nativeProjectPatches.ONE_NOTIFICATIONS;
|
|
12
|
+
const updatesHost = nativeProjectPatches.ONE_UPDATES;
|
|
12
13
|
const validatePrebuildApp = validateNativeApp;
|
|
13
14
|
const ANDROID_DENSITIES = {
|
|
14
15
|
mdpi: 1,
|
|
@@ -20,7 +21,7 @@ const ANDROID_DENSITIES = {
|
|
|
20
21
|
const IOS_BUNDLE_PLACEHOLDER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
|
21
22
|
const ANDROID_PACKAGE_PLACEHOLDER = "com.helloworld";
|
|
22
23
|
const ANDROID_PACKAGE_PATH = "com/helloworld";
|
|
23
|
-
function patchIosBundlePhase(project) {
|
|
24
|
+
function patchIosBundlePhase(project, updatesRuntimeVersion) {
|
|
24
25
|
let patchedBundlePhases = 0;
|
|
25
26
|
const patchedProject = project.replace(/shellScript = ("(?:\\.|[^"\\])*");/g, (assignment, serializedScript) => {
|
|
26
27
|
let script;
|
|
@@ -39,6 +40,12 @@ function patchIosBundlePhase(project) {
|
|
|
39
40
|
if (!patched.includes("[vxrn/one] React Native now defaults CLI_PATH") || !patched.includes("[vxrn/one] use the hermes-engine pod") || !patched.includes("[vxrn/one] ensure patches are applied")) {
|
|
40
41
|
throw new Error("[vxrn] failed to apply required iOS bundle phase patches");
|
|
41
42
|
}
|
|
43
|
+
if (updatesRuntimeVersion !== void 0) {
|
|
44
|
+
patched = nativeProjectPatches.addEmbeddedUpdatesManifestToBundleReactNativeShellScript(patched, updatesRuntimeVersion);
|
|
45
|
+
if (!patched.includes("[vxrn/one] the embedded update manifest lands beside the release bundle")) {
|
|
46
|
+
throw new Error("[vxrn] failed to apply the iOS embedded updates manifest patch");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
42
49
|
patchedBundlePhases++;
|
|
43
50
|
return `shellScript = ${JSON.stringify(patched)};`;
|
|
44
51
|
});
|
|
@@ -198,6 +205,27 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|
|
198
205
|
}
|
|
199
206
|
}`);
|
|
200
207
|
}
|
|
208
|
+
const UPDATES_BRIDGING_HEADER_NAME = "OneUpdates-Bridging-Header.h";
|
|
209
|
+
function renderUpdatesBridgingHeader() {
|
|
210
|
+
return `// generated by one prebuild: exposes the updates launcher entry
|
|
211
|
+
// point to AppDelegate without importing the One module.
|
|
212
|
+
${updatesHost.bridgingHeaderImport}
|
|
213
|
+
`;
|
|
214
|
+
}
|
|
215
|
+
function generateUpdatesBridgingHeader(dest, app) {
|
|
216
|
+
if (app.updates === void 0) return;
|
|
217
|
+
FSExtra.writeFileSync(path.join(dest, app.name, UPDATES_BRIDGING_HEADER_NAME), renderUpdatesBridgingHeader());
|
|
218
|
+
}
|
|
219
|
+
function patchIosPbxprojUpdatesBridgingHeader(project, appName) {
|
|
220
|
+
const anchor = `INFOPLIST_FILE = ${appName}/Info.plist;`;
|
|
221
|
+
const setting = `SWIFT_OBJC_BRIDGING_HEADER = "${appName}/${UPDATES_BRIDGING_HEADER_NAME}";`;
|
|
222
|
+
const occurrences = project.split(anchor).length - 1;
|
|
223
|
+
if (occurrences !== 2) {
|
|
224
|
+
throw new Error("[vxrn] prebuild template project.pbxproj changed shape: cannot point the app target at the One.Updates bridging header");
|
|
225
|
+
}
|
|
226
|
+
return project.split(anchor).join(`${anchor}
|
|
227
|
+
${setting}`);
|
|
228
|
+
}
|
|
201
229
|
function patchIosPbxprojSceneDelegate(rendered, appName) {
|
|
202
230
|
const edits = [
|
|
203
231
|
["/* AppDelegate.swift in Sources */ = {isa = PBXBuildFile;", ` ${SCENE_DELEGATE_BUILD_FILE_ID} /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = ${SCENE_DELEGATE_FILE_REF_ID} /* SceneDelegate.swift */; };`],
|
|
@@ -243,6 +271,39 @@ function renderPushEntitlements() {
|
|
|
243
271
|
</plist>
|
|
244
272
|
`;
|
|
245
273
|
}
|
|
274
|
+
function patchAndroidMainApplicationUpdatesHost(rendered) {
|
|
275
|
+
const anchor = "import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost";
|
|
276
|
+
if (!rendered.includes(anchor)) {
|
|
277
|
+
throw new Error("[vxrn] prebuild template MainApplication.kt changed shape: cannot point the ReactHost at One.Updates");
|
|
278
|
+
}
|
|
279
|
+
return rendered.replace(anchor, "import com.margelo.nitro.one.OneUpdatesReactHost.getDefaultReactHost");
|
|
280
|
+
}
|
|
281
|
+
function escapeGradleString(value) {
|
|
282
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
283
|
+
}
|
|
284
|
+
function patchAndroidBuildGradleUpdatesManifest(rendered, runtimeVersion) {
|
|
285
|
+
const anchor = " autolinkLibrariesWithApp()\n}";
|
|
286
|
+
if (!rendered.includes(anchor)) {
|
|
287
|
+
throw new Error("[vxrn] cannot stamp the embedded updates manifest: expected the replaced react block in app/build.gradle");
|
|
288
|
+
}
|
|
289
|
+
const snippet = `${anchor}
|
|
290
|
+
|
|
291
|
+
// [vxrn/one] the embedded update manifest lands beside the release bundle
|
|
292
|
+
tasks.matching { it.name.startsWith("createBundle") && it.name.endsWith("JsAndAssets") }.configureEach { bundleTask ->
|
|
293
|
+
// capture the output directory provider at configuration time, so the
|
|
294
|
+
// action below holds no task reference at execution time.
|
|
295
|
+
def bundleDir = bundleTask.jsBundleDir
|
|
296
|
+
bundleTask.doLast {
|
|
297
|
+
def manifestFile = new File(bundleDir.get().asFile, "one-updates-embedded.json")
|
|
298
|
+
manifestFile.text = groovy.json.JsonOutput.toJson([
|
|
299
|
+
id: java.util.UUID.randomUUID().toString(),
|
|
300
|
+
createdAt: java.time.Instant.now().toString(),
|
|
301
|
+
runtimeVersion: "${escapeGradleString(runtimeVersion)}",
|
|
302
|
+
])
|
|
303
|
+
}
|
|
304
|
+
}`;
|
|
305
|
+
return rendered.replace(anchor, snippet);
|
|
306
|
+
}
|
|
246
307
|
function patchIosPbxprojWidgets(project, app) {
|
|
247
308
|
const name = app.name;
|
|
248
309
|
const bundleId = app.ios.bundleId;
|
|
@@ -1090,6 +1151,14 @@ ${schemes.map((scheme) => ` <string>${scheme}</string>`).join("\n")}
|
|
|
1090
1151
|
if (app.pictureInPicture) {
|
|
1091
1152
|
stamps.push(" <key>UIBackgroundModes</key>\n <array>\n <string>audio</string>\n </array>");
|
|
1092
1153
|
}
|
|
1154
|
+
if (app.updates !== void 0) {
|
|
1155
|
+
if (app.updates.url !== void 0) {
|
|
1156
|
+
stamps.push(` <key>${updatesHost.urlInfoPlistKey}</key>
|
|
1157
|
+
<string>${escapeXml(app.updates.url)}</string>`);
|
|
1158
|
+
}
|
|
1159
|
+
stamps.push(` <key>${updatesHost.runtimeVersionInfoPlistKey}</key>
|
|
1160
|
+
<string>${escapeXml(app.updates.runtimeVersion)}</string>`);
|
|
1161
|
+
}
|
|
1093
1162
|
if (stamps.length) {
|
|
1094
1163
|
const anchor = " <key>LSRequiresIPhoneOS</key>";
|
|
1095
1164
|
if (!rendered.includes(anchor)) throw new Error(`[vxrn] prebuild template ${relativePath} lost its LSRequiresIPhoneOS anchor`);
|
|
@@ -1148,6 +1217,22 @@ ${stamps.join("\n")}`);
|
|
|
1148
1217
|
throw new Error("[vxrn] failed to stamp the push service into app manifest");
|
|
1149
1218
|
}
|
|
1150
1219
|
}
|
|
1220
|
+
if (platform === "android" && relativePath === "app/src/main/java/com/helloworld/MainApplication.kt" && app.updates !== void 0) {
|
|
1221
|
+
rendered = patchAndroidMainApplicationUpdatesHost(rendered);
|
|
1222
|
+
}
|
|
1223
|
+
if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.updates !== void 0) {
|
|
1224
|
+
const anchor = " </application>";
|
|
1225
|
+
if (!rendered.includes(anchor)) {
|
|
1226
|
+
throw new Error("[vxrn] cannot stamp the updates config: expected </application> in app/src/main/AndroidManifest.xml");
|
|
1227
|
+
}
|
|
1228
|
+
const stamps = [];
|
|
1229
|
+
if (app.updates.url !== void 0) {
|
|
1230
|
+
stamps.push(` <meta-data android:name="dev.onejs.updates.url" android:value="${escapeXml(app.updates.url)}" />`);
|
|
1231
|
+
}
|
|
1232
|
+
stamps.push(` <meta-data android:name="dev.onejs.updates.runtimeVersion" android:value="${escapeXml(app.updates.runtimeVersion)}" />`);
|
|
1233
|
+
rendered = rendered.replace(anchor, `${stamps.join("\n")}
|
|
1234
|
+
${anchor}`);
|
|
1235
|
+
}
|
|
1151
1236
|
if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.android?.googleMapsApiKey !== void 0) {
|
|
1152
1237
|
const anchor = " </application>";
|
|
1153
1238
|
if (!rendered.includes(anchor)) {
|
|
@@ -1227,6 +1312,9 @@ ${schemes.map((scheme) => ` <data android:scheme="${scheme}" />`).joi
|
|
|
1227
1312
|
}
|
|
1228
1313
|
if (platform === "ios" && relativePath.endsWith("/AppDelegate.swift")) {
|
|
1229
1314
|
rendered = patchIosAppDelegateSceneLifecycle(rendered, appName);
|
|
1315
|
+
if (app.updates !== void 0) {
|
|
1316
|
+
rendered = nativeProjectPatches.pointReleaseBundleURLAtOneUpdates(rendered);
|
|
1317
|
+
}
|
|
1230
1318
|
}
|
|
1231
1319
|
if (platform === "ios" && app.ios?.deploymentTarget) {
|
|
1232
1320
|
rendered = rendered.replace("platform :ios, min_ios_version_supported", `platform :ios, '${app.ios.deploymentTarget}'`).replace(/IPHONEOS_DEPLOYMENT_TARGET = \d+(?:\.\d+)?;/g, `IPHONEOS_DEPLOYMENT_TARGET = ${app.ios.deploymentTarget};`);
|
|
@@ -1243,8 +1331,11 @@ end`);
|
|
|
1243
1331
|
}
|
|
1244
1332
|
}
|
|
1245
1333
|
if (platform === "ios" && relativePath.endsWith(".xcodeproj/project.pbxproj")) {
|
|
1246
|
-
rendered = patchIosBundlePhase(rendered);
|
|
1334
|
+
rendered = patchIosBundlePhase(rendered, app.updates?.runtimeVersion);
|
|
1247
1335
|
rendered = patchIosPbxprojSceneDelegate(rendered, appName);
|
|
1336
|
+
if (app.updates !== void 0) {
|
|
1337
|
+
rendered = patchIosPbxprojUpdatesBridgingHeader(rendered, appName);
|
|
1338
|
+
}
|
|
1248
1339
|
if (app.notifications?.push === true && !app.ios?.widgets) {
|
|
1249
1340
|
rendered = patchIosPbxprojPushEntitlements(rendered, appName);
|
|
1250
1341
|
}
|
|
@@ -1274,6 +1365,9 @@ use_frameworks! :linkage => :${app.ios.useFrameworks}`);
|
|
|
1274
1365
|
if (!rendered.includes("entryFile = file(\"../../package.json\")") || !rendered.includes("[vxrn/one] ensure patches are applied")) {
|
|
1275
1366
|
throw new Error("[vxrn] failed to apply required Android Gradle patches");
|
|
1276
1367
|
}
|
|
1368
|
+
if (app.updates !== void 0) {
|
|
1369
|
+
rendered = patchAndroidBuildGradleUpdatesManifest(rendered, app.updates.runtimeVersion);
|
|
1370
|
+
}
|
|
1277
1371
|
if (app.version !== void 0) {
|
|
1278
1372
|
rendered = rendered.replace(/versionName "[^"]*"/g, `versionName "${app.version}"`);
|
|
1279
1373
|
}
|
|
@@ -1357,6 +1451,7 @@ const generateForPlatform = async (root, platform, app, outDir = path.resolve(ro
|
|
|
1357
1451
|
platform,
|
|
1358
1452
|
app
|
|
1359
1453
|
});
|
|
1454
|
+
if (platform === "ios") generateUpdatesBridgingHeader(dest, app);
|
|
1360
1455
|
if (platform === "ios") generateIosWidgets(dest, app);
|
|
1361
1456
|
if (platform === "ios") generateSwiftPackages({
|
|
1362
1457
|
root,
|
|
@@ -1372,21 +1467,7 @@ function generateSwiftPackages({ root, dest }) {
|
|
|
1372
1467
|
"types",
|
|
1373
1468
|
"build"
|
|
1374
1469
|
]);
|
|
1375
|
-
const
|
|
1376
|
-
const walk = (dir) => {
|
|
1377
|
-
const entries = FSExtra.readdirSync(dir, { withFileTypes: true });
|
|
1378
|
-
if (entries.some((entry) => entry.isFile() && entry.name === "Package.swift")) {
|
|
1379
|
-
packageDirs.push(dir);
|
|
1380
|
-
return;
|
|
1381
|
-
}
|
|
1382
|
-
for (const entry of entries) {
|
|
1383
|
-
if (!entry.isDirectory() || entry.name.startsWith(".") || skip.has(entry.name)) continue;
|
|
1384
|
-
walk(path.join(dir, entry.name));
|
|
1385
|
-
}
|
|
1386
|
-
};
|
|
1387
|
-
walk(root);
|
|
1388
|
-
for (const packageDir of packageDirs) {
|
|
1389
|
-
const id = swiftPackageId(packageDir);
|
|
1470
|
+
for (const [id, packageDir] of swiftPackageDirectories(root)) {
|
|
1390
1471
|
const podDir = path.join(dest, "OneSwiftPackages", id);
|
|
1391
1472
|
const sources = [];
|
|
1392
1473
|
const collect = (dir) => {
|