@absolutejs/absolute 0.20.0-beta.114 → 0.20.0-beta.116

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.
@@ -6439,24 +6439,24 @@ var require_pem = __commonJS(function(exports, module) {
6439
6439
  options = options || {};
6440
6440
  var rval = "-----BEGIN " + msg.type + `-----\r
6441
6441
  `;
6442
- var header;
6442
+ var header2;
6443
6443
  if (msg.procType) {
6444
- header = {
6444
+ header2 = {
6445
6445
  name: "Proc-Type",
6446
6446
  values: [String(msg.procType.version), msg.procType.type]
6447
6447
  };
6448
- rval += foldHeader(header);
6448
+ rval += foldHeader(header2);
6449
6449
  }
6450
6450
  if (msg.contentDomain) {
6451
- header = { name: "Content-Domain", values: [msg.contentDomain] };
6452
- rval += foldHeader(header);
6451
+ header2 = { name: "Content-Domain", values: [msg.contentDomain] };
6452
+ rval += foldHeader(header2);
6453
6453
  }
6454
6454
  if (msg.dekInfo) {
6455
- header = { name: "DEK-Info", values: [msg.dekInfo.algorithm] };
6455
+ header2 = { name: "DEK-Info", values: [msg.dekInfo.algorithm] };
6456
6456
  if (msg.dekInfo.parameters) {
6457
- header.values.push(msg.dekInfo.parameters);
6457
+ header2.values.push(msg.dekInfo.parameters);
6458
6458
  }
6459
- rval += foldHeader(header);
6459
+ rval += foldHeader(header2);
6460
6460
  }
6461
6461
  if (msg.headers) {
6462
6462
  for (var i = 0;i < msg.headers.length; ++i) {
@@ -6514,27 +6514,27 @@ var require_pem = __commonJS(function(exports, module) {
6514
6514
  }
6515
6515
  match = line.match(rHeader);
6516
6516
  if (match) {
6517
- var header = { name: match[1], values: [] };
6517
+ var header2 = { name: match[1], values: [] };
6518
6518
  var values = match[2].split(",");
6519
6519
  for (var vi = 0;vi < values.length; ++vi) {
6520
- header.values.push(ltrim(values[vi]));
6520
+ header2.values.push(ltrim(values[vi]));
6521
6521
  }
6522
6522
  if (!msg.procType) {
6523
- if (header.name !== "Proc-Type") {
6523
+ if (header2.name !== "Proc-Type") {
6524
6524
  throw new Error("Invalid PEM formatted message. The first " + 'encapsulated header must be "Proc-Type".');
6525
- } else if (header.values.length !== 2) {
6525
+ } else if (header2.values.length !== 2) {
6526
6526
  throw new Error('Invalid PEM formatted message. The "Proc-Type" ' + "header must have two subfields.");
6527
6527
  }
6528
6528
  msg.procType = { version: values[0], type: values[1] };
6529
- } else if (!msg.contentDomain && header.name === "Content-Domain") {
6529
+ } else if (!msg.contentDomain && header2.name === "Content-Domain") {
6530
6530
  msg.contentDomain = values[0] || "";
6531
- } else if (!msg.dekInfo && header.name === "DEK-Info") {
6532
- if (header.values.length === 0) {
6531
+ } else if (!msg.dekInfo && header2.name === "DEK-Info") {
6532
+ if (header2.values.length === 0) {
6533
6533
  throw new Error('Invalid PEM formatted message. The "DEK-Info" ' + "header must have at least one subfield.");
6534
6534
  }
6535
6535
  msg.dekInfo = { algorithm: values[0], parameters: values[1] || null };
6536
6536
  } else {
6537
- msg.headers.push(header);
6537
+ msg.headers.push(header2);
6538
6538
  }
6539
6539
  }
6540
6540
  ++li;
@@ -6548,14 +6548,14 @@ var require_pem = __commonJS(function(exports, module) {
6548
6548
  }
6549
6549
  return rval;
6550
6550
  };
6551
- function foldHeader(header) {
6552
- var rval = header.name + ": ";
6551
+ function foldHeader(header2) {
6552
+ var rval = header2.name + ": ";
6553
6553
  var values = [];
6554
6554
  var insertSpace = function(match, $1) {
6555
6555
  return " " + $1;
6556
6556
  };
6557
- for (var i = 0;i < header.values.length; ++i) {
6558
- values.push(header.values[i].replace(/^(\S+\r\n)/, insertSpace));
6557
+ for (var i = 0;i < header2.values.length; ++i) {
6558
+ values.push(header2.values[i].replace(/^(\S+\r\n)/, insertSpace));
6559
6559
  }
6560
6560
  rval += values.join(",") + `\r
6561
6561
  `;
@@ -7172,9 +7172,9 @@ var require_prng = __commonJS(function(exports, module) {
7172
7172
  _crypto = __require("crypto");
7173
7173
  }
7174
7174
  var prng = module.exports = forge.prng = forge.prng || {};
7175
- prng.create = function(plugin) {
7175
+ prng.create = function(plugin2) {
7176
7176
  var ctx = {
7177
- plugin,
7177
+ plugin: plugin2,
7178
7178
  key: null,
7179
7179
  seed: null,
7180
7180
  time: null,
@@ -7182,7 +7182,7 @@ var require_prng = __commonJS(function(exports, module) {
7182
7182
  generated: 0,
7183
7183
  keyBytes: ""
7184
7184
  };
7185
- var md = plugin.md;
7185
+ var md = plugin2.md;
7186
7186
  var pools2 = new Array(32);
7187
7187
  for (var i = 0;i < 32; ++i) {
7188
7188
  pools2[i] = md.create();
@@ -19453,7 +19453,7 @@ var init_compatibilityDispatcher = __esm(() => {
19453
19453
  // src/cli/scripts/telemetry.ts
19454
19454
  import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync6, writeFileSync } from "fs";
19455
19455
  import { homedir as homedir4 } from "os";
19456
- import { join as join27 } from "path";
19456
+ import { join as join28 } from "path";
19457
19457
  var configDir, configPath, getTelemetryConfig = () => {
19458
19458
  try {
19459
19459
  if (!existsSync5(configPath))
@@ -19466,14 +19466,14 @@ var configDir, configPath, getTelemetryConfig = () => {
19466
19466
  }
19467
19467
  };
19468
19468
  var init_telemetry = __esm(() => {
19469
- configDir = join27(homedir4(), ".absolutejs");
19470
- configPath = join27(configDir, "telemetry.json");
19469
+ configDir = join28(homedir4(), ".absolutejs");
19470
+ configPath = join28(configDir, "telemetry.json");
19471
19471
  });
19472
19472
 
19473
19473
  // src/cli/telemetryEvent.ts
19474
19474
  import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
19475
19475
  import { arch, platform as platform3 } from "os";
19476
- import { dirname as dirname20, join as join28, parse } from "path";
19476
+ import { dirname as dirname20, join as join29, parse } from "path";
19477
19477
  var checkCandidate = (candidate) => {
19478
19478
  if (!existsSync6(candidate)) {
19479
19479
  return null;
@@ -19493,7 +19493,7 @@ var checkCandidate = (candidate) => {
19493
19493
  }, findPackageVersion = () => {
19494
19494
  let { dir } = import.meta;
19495
19495
  while (dir !== parse(dir).root) {
19496
- const candidate = join28(dir, "package.json");
19496
+ const candidate = join29(dir, "package.json");
19497
19497
  const version = checkCandidate(candidate);
19498
19498
  if (version) {
19499
19499
  return version;
@@ -25468,6 +25468,40 @@ var buildAbsoluteAndroidRelease = async (options) => {
25468
25468
  };
25469
25469
  // src/mobile/androidReleaseAcceptance.ts
25470
25470
  import { createHash as createHash6 } from "crypto";
25471
+
25472
+ // src/mobile/androidServiceReadiness.ts
25473
+ var SERVICE_TIMEOUT_MS = 180000;
25474
+ var SERVICE_POLL_MS = 500;
25475
+ var waitForAbsoluteAndroidNetworkServices = async (options) => {
25476
+ const startedAt = performance.now();
25477
+ const waitForServices = async () => {
25478
+ const states = await Promise.all(["wifi", "phone"].map(async (service) => {
25479
+ const result = await options.run([
25480
+ options.adb,
25481
+ "-s",
25482
+ options.serial,
25483
+ "shell",
25484
+ "service",
25485
+ "check",
25486
+ service
25487
+ ]);
25488
+ return {
25489
+ ready: result.exitCode === 0 && result.stdout.trim() === `Service ${service}: found`,
25490
+ service
25491
+ };
25492
+ }));
25493
+ const missing = states.filter(({ ready }) => !ready).map(({ service }) => service);
25494
+ if (missing.length === 0)
25495
+ return;
25496
+ if (performance.now() - startedAt >= (options.timeoutMs ?? SERVICE_TIMEOUT_MS))
25497
+ throw new Error(`Android network services did not become ready: ${missing.join(", ")}. Finish booting or restart the emulator before installed offline acceptance; no network settings were changed.`);
25498
+ await Bun.sleep(options.pollMs ?? SERVICE_POLL_MS);
25499
+ await waitForServices();
25500
+ };
25501
+ await waitForServices();
25502
+ };
25503
+
25504
+ // src/mobile/androidReleaseAcceptance.ts
25471
25505
  import {
25472
25506
  access as access7,
25473
25507
  mkdir as mkdir5,
@@ -25809,6 +25843,11 @@ var runAbsoluteAndroidReleaseAcceptance = async (options) => {
25809
25843
  if (options.release.metadata.versionCode !== undefined && installed.versionCode !== options.release.metadata.versionCode)
25810
25844
  throw new Error(`Installed Android versionCode ${installed.versionCode ?? "unknown"} does not match release ${options.release.metadata.versionCode}.`);
25811
25845
  await requireSuccess2(run, adb(options.adb, options.serial, "logcat", "-c"), "Android release log isolation");
25846
+ await waitForAbsoluteAndroidNetworkServices({
25847
+ adb: options.adb,
25848
+ run,
25849
+ serial: options.serial
25850
+ });
25812
25851
  const [wifi, mobile] = await Promise.all([
25813
25852
  requireSuccess2(run, adb(options.adb, options.serial, "shell", "settings", "get", "global", "wifi_on"), "Android Wi-Fi state inspection"),
25814
25853
  requireSuccess2(run, adb(options.adb, options.serial, "shell", "settings", "get", "global", "mobile_data"), "Android mobile-data state inspection")
@@ -29337,7 +29376,7 @@ var parseAbsoluteMobileBuildPageMetadata = (value) => {
29337
29376
  };
29338
29377
  // src/mobile/buildPipeline.ts
29339
29378
  import { readFile as readFile18 } from "fs/promises";
29340
- import { join as join21, resolve as resolve16 } from "path";
29379
+ import { join as join22, resolve as resolve16 } from "path";
29341
29380
  import { pathToFileURL as pathToFileURL2 } from "url";
29342
29381
 
29343
29382
  // src/mobile/buildRelease.ts
@@ -30115,7 +30154,7 @@ import {
30115
30154
  writeFile as writeFile14
30116
30155
  } from "fs/promises";
30117
30156
  import { createHash as createHash15 } from "crypto";
30118
- import { basename as basename6, dirname as dirname13, join as join20, relative as relative13, resolve as resolve15, sep as sep8 } from "path";
30157
+ import { basename as basename6, dirname as dirname13, join as join21, relative as relative13, resolve as resolve15, sep as sep8 } from "path";
30119
30158
 
30120
30159
  // src/mobile/updateRuntime.ts
30121
30160
  init_deviceCapabilities();
@@ -30256,6 +30295,7 @@ var createAbsoluteMobileUpdateRuntimeDescriptor = (options) => ({
30256
30295
  },
30257
30296
  deviceCapabilities: options.deviceCapabilities,
30258
30297
  engine: options.config.engine,
30298
+ ...options.config.engine === "expo" ? { expoEmbeddedAssetsAbi: 1 } : {},
30259
30299
  format: ABSOLUTE_MOBILE_UPDATE_RUNTIME_FORMAT,
30260
30300
  shellAbi: ABSOLUTE_MOBILE_SHELL_ABI,
30261
30301
  syncSchema: options.syncSchema ?? null,
@@ -31025,6 +31065,265 @@ var absoluteExpoActivityResultRecoveryFiles = (project) => new Map([
31025
31065
  ]
31026
31066
  ]);
31027
31067
 
31068
+ // src/mobile/expoEmbeddedAssets.ts
31069
+ import { join as join20 } from "path";
31070
+ var header = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
31071
+ `;
31072
+ var android = `${header}package expo.modules.absoluteembeddedassets
31073
+
31074
+ import android.content.Context
31075
+ import android.graphics.Bitmap
31076
+ import android.net.Uri
31077
+ import android.util.Log
31078
+ import android.webkit.WebResourceRequest
31079
+ import android.webkit.WebResourceResponse
31080
+ import android.webkit.WebView
31081
+ import androidx.webkit.WebViewAssetLoader
31082
+ import androidx.webkit.WebViewCompat
31083
+ import androidx.webkit.WebViewFeature
31084
+ import androidx.webkit.ScriptHandler
31085
+ import androidx.webkit.WebMessageCompat
31086
+ import com.facebook.react.ReactPackage
31087
+ import com.facebook.react.bridge.NativeModule
31088
+ import com.facebook.react.bridge.ReactApplicationContext
31089
+ import com.facebook.react.bridge.ReadableMap
31090
+ import com.facebook.react.uimanager.ThemedReactContext
31091
+ import com.facebook.react.uimanager.ViewManager
31092
+ import com.reactnativecommunity.webview.RNCWebViewClient
31093
+ import com.reactnativecommunity.webview.RNCWebViewManager
31094
+ import com.reactnativecommunity.webview.RNCWebViewWrapper
31095
+ import expo.modules.kotlin.modules.Module
31096
+ import expo.modules.kotlin.modules.ModuleDefinition
31097
+ import java.io.ByteArrayInputStream
31098
+ import java.io.File
31099
+ import java.util.concurrent.ConcurrentHashMap
31100
+ import java.util.WeakHashMap
31101
+
31102
+ private const val HOST = "appassets.androidplatform.net"
31103
+ private const val PREFIX = "/absolutejs/"
31104
+
31105
+ internal object AbsoluteEmbeddedAssets {
31106
+ private val bundles = ConcurrentHashMap<String, Map<String, File>>()
31107
+
31108
+ fun register(context: Context, rootUri: String, paths: List<String>): String {
31109
+ check(WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT) &&
31110
+ WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
31111
+ "Update Android System WebView to load this application."
31112
+ }
31113
+ val uri = Uri.parse(rootUri)
31114
+ require(uri.scheme == "file" && uri.authority.isNullOrEmpty() && uri.query == null && uri.fragment == null)
31115
+ val root = File(requireNotNull(uri.path)).canonicalFile
31116
+ val parent = File(context.filesDir, "absolutejs-web").canonicalFile
31117
+ require(root.parentFile == parent && root.name.matches(Regex("amexpo_[a-f0-9]{64}")))
31118
+ require(paths.isNotEmpty() && paths.size <= 100000 && paths.distinct().size == paths.size)
31119
+ val files = paths.associateWith { path ->
31120
+ require(path.isNotEmpty() && !path.contains('\\\\') && !path.contains('%') &&
31121
+ !path.contains('?') && !path.contains('#') && path.indexOf(0.toChar()) < 0 &&
31122
+ path.split('/').all { it.isNotEmpty() && it != "." && it != ".." })
31123
+ val file = File(root, path).canonicalFile
31124
+ require(file.path.startsWith(root.path + File.separator) && file.isFile)
31125
+ file
31126
+ }
31127
+ require(files.containsKey("index.html") && files.containsKey("absolute-mobile-manifest.json"))
31128
+ bundles[root.name] = files
31129
+ Log.i("AbsoluteJS", "Expo embedded web phase: asset-host-registered")
31130
+ return "https://" + HOST + PREFIX + root.name + "/index.html"
31131
+ }
31132
+
31133
+ private fun empty(status: Int, reason: String) = WebResourceResponse(
31134
+ "text/plain", "UTF-8", status, reason,
31135
+ mapOf("Cache-Control" to "no-store", "X-Content-Type-Options" to "nosniff"),
31136
+ ByteArrayInputStream(ByteArray(0))
31137
+ )
31138
+
31139
+ private fun resource(path: String): WebResourceResponse {
31140
+ val bundle = path.substringBefore('/')
31141
+ val name = path.substringAfter('/', "")
31142
+ val file = bundles[bundle]?.get(name) ?: return empty(404, "Not Found")
31143
+ // Recheck canonical location at read time. Never follow a replaced symlink.
31144
+ if (file.canonicalFile != file || !file.isFile) return empty(404, "Not Found")
31145
+ val mime = when (file.extension.lowercase()) {
31146
+ "html", "htm" -> "text/html"
31147
+ "js", "mjs" -> "text/javascript"
31148
+ "json", "map" -> "application/json"
31149
+ "css" -> "text/css"
31150
+ "svg" -> "image/svg+xml"
31151
+ "wasm" -> "application/wasm"
31152
+ else -> android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(file.extension.lowercase()) ?: "application/octet-stream"
31153
+ }
31154
+ return try {
31155
+ WebResourceResponse(mime, "UTF-8", 200, "OK",
31156
+ mapOf("Cache-Control" to "no-store", "X-Content-Type-Options" to "nosniff"), file.inputStream())
31157
+ } catch (_: Exception) { empty(404, "Not Found") }
31158
+ }
31159
+
31160
+ private val loader = WebViewAssetLoader.Builder()
31161
+ .setDomain(HOST).setHttpAllowed(false)
31162
+ .addPathHandler(PREFIX) { path -> resource(path) }.build()
31163
+
31164
+ fun intercept(request: WebResourceRequest, activeBundle: String?): WebResourceResponse? {
31165
+ val uri = request.url
31166
+ if (uri.host != HOST) return null
31167
+ if (uri.path.orEmpty().endsWith("/index.html")) Log.i("AbsoluteJS", "Expo embedded web phase: document-request")
31168
+ if (uri.path.orEmpty().endsWith("/absolute-mobile-bootstrap.js")) Log.i("AbsoluteJS", "Expo embedded web phase: bootstrap-request")
31169
+ // A reserved asset host must never fall through to DNS/network, even for
31170
+ // unknown bundles, wrong ports/schemes, methods, or malformed paths.
31171
+ if (uri.scheme != "https" || uri.port != -1 || uri.userInfo != null ||
31172
+ request.method != "GET") return empty(403, "Forbidden")
31173
+ // Root-relative image/font/CSS URLs retain their web meaning. Scope them
31174
+ // to this WebView's bundle, not the last bundle registered by another view.
31175
+ if (!uri.path.orEmpty().startsWith(PREFIX)) {
31176
+ if (request.isForMainFrame || activeBundle == null) return empty(404, "Not Found")
31177
+ return resource(activeBundle + "/" + uri.path.orEmpty().removePrefix("/"))
31178
+ }
31179
+ return loader.shouldInterceptRequest(uri) ?: empty(404, "Not Found")
31180
+ }
31181
+ }
31182
+
31183
+ class AbsoluteEmbeddedAssetsModule : Module() {
31184
+ override fun definition() = ModuleDefinition {
31185
+ Name("AbsoluteEmbeddedAssets")
31186
+ AsyncFunction("registerBundle") { root: String, paths: List<String> ->
31187
+ AbsoluteEmbeddedAssets.register(requireNotNull(appContext.reactContext), root, paths)
31188
+ }
31189
+ }
31190
+ }
31191
+
31192
+ class AbsoluteEmbeddedWebViewManager : RNCWebViewManager() {
31193
+ private val scripts = WeakHashMap<RNCWebViewWrapper, ScriptHandler>()
31194
+ override fun getName() = "AbsoluteEmbeddedWebView"
31195
+ override fun setNewSource(view: RNCWebViewWrapper, value: ReadableMap?) {
31196
+ Log.i("AbsoluteJS", "Expo embedded web phase: source-assigned")
31197
+ super.setNewSource(view, value)
31198
+ }
31199
+ override fun setMessagingEnabled(view: RNCWebViewWrapper, value: Boolean) {
31200
+ super.setMessagingEnabled(view, value)
31201
+ // Upstream reports sourceOrigin as event.url and accepts subframe messages.
31202
+ // Retain its event dispatch, but bind this bridge to our main-frame origin
31203
+ // and attach the native-observed document URL, never a JS-supplied URL.
31204
+ if (!WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) return
31205
+ WebViewCompat.removeWebMessageListener(view.webView, "ReactNativeWebView")
31206
+ if (!value) return
31207
+ WebViewCompat.addWebMessageListener(view.webView, "ReactNativeWebView", setOf("https://" + HOST)) {
31208
+ webView, message, sourceOrigin, isMainFrame, _ ->
31209
+ if (isMainFrame && sourceOrigin.scheme == "https" && sourceOrigin.host == HOST &&
31210
+ message.type == WebMessageCompat.TYPE_STRING) {
31211
+ val url = webView.url
31212
+ val data = message.data
31213
+ if (url != null && data != null) view.webView.onMessage(data, url)
31214
+ }
31215
+ }
31216
+ }
31217
+ override fun setInjectedJavaScriptBeforeContentLoaded(view: RNCWebViewWrapper, value: String?) {
31218
+ scripts.remove(view)?.remove()
31219
+ if (value == null) return
31220
+ // onPageStarted injection races module execution on Android. Register with
31221
+ // Chromium before navigation, scoped to our virtual asset origin only.
31222
+ check(WebViewFeature.isFeatureSupported(WebViewFeature.DOCUMENT_START_SCRIPT)) {
31223
+ "AbsoluteJS requires an Android System WebView with document-start script support."
31224
+ }
31225
+ scripts[view] = WebViewCompat.addDocumentStartJavaScript(view.webView, value, setOf("https://" + HOST))
31226
+ }
31227
+ override fun onDropViewInstance(view: RNCWebViewWrapper) {
31228
+ scripts.remove(view)?.remove()
31229
+ if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER))
31230
+ WebViewCompat.removeWebMessageListener(view.webView, "ReactNativeWebView")
31231
+ super.onDropViewInstance(view)
31232
+ }
31233
+ override fun addEventEmitters(context: ThemedReactContext, view: RNCWebViewWrapper) {
31234
+ Log.i("AbsoluteJS", "Expo embedded web phase: asset-host-view-created")
31235
+ view.webView.webViewClient = object : RNCWebViewClient() {
31236
+ @Volatile private var activeBundle: String? = null
31237
+ override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
31238
+ Log.i("AbsoluteJS", "Expo embedded web phase: document-started")
31239
+ val uri = Uri.parse(url)
31240
+ activeBundle = if (uri.scheme == "https" && uri.host == HOST && uri.path.orEmpty().startsWith(PREFIX))
31241
+ uri.path!!.removePrefix(PREFIX).substringBefore('/') else null
31242
+ super.onPageStarted(view, url, favicon)
31243
+ }
31244
+ override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? =
31245
+ AbsoluteEmbeddedAssets.intercept(request, activeBundle) ?: super.shouldInterceptRequest(view, request)
31246
+ }
31247
+ }
31248
+ }
31249
+
31250
+ class AbsoluteEmbeddedWebViewPackage : ReactPackage {
31251
+ override fun createNativeModules(context: ReactApplicationContext): List<NativeModule> = emptyList()
31252
+ override fun createViewManagers(context: ReactApplicationContext): List<ViewManager<*, *>> = listOf(AbsoluteEmbeddedWebViewManager())
31253
+ }
31254
+ `;
31255
+ var plugin = `${header}const { withMainApplication } = require('expo/config-plugins');
31256
+ module.exports = config => withMainApplication(config, value => {
31257
+ if (value.modResults.language !== 'kt') throw new Error('AbsoluteJS embedded assets require the managed Kotlin application.');
31258
+ const name = 'expo.modules.absoluteembeddedassets.AbsoluteEmbeddedWebViewPackage';
31259
+ const registration = 'add(' + name + '())';
31260
+ const source = value.modResults.contents;
31261
+ if (!source.includes(registration)) {
31262
+ const anchor = 'PackageList(this).packages.apply {';
31263
+ if (source.split(anchor).length !== 2) throw new Error('Cannot safely register AbsoluteJS embedded WebView in MainApplication.');
31264
+ value.modResults.contents = source.replace(anchor, anchor + '\\n ' + registration);
31265
+ }
31266
+ return value;
31267
+ });
31268
+ `;
31269
+ var runtime2 = `${header}import { requireNativeModule } from 'expo-modules-core';
31270
+ import { Platform, requireNativeComponent } from 'react-native';
31271
+
31272
+ export const absoluteEmbeddedNativeConfig = Platform.OS === 'android'
31273
+ ? { component: requireNativeComponent('AbsoluteEmbeddedWebView') }
31274
+ : undefined;
31275
+
31276
+ export const registerAbsoluteEmbeddedBundle = async (rootUri: string, paths: string[], indexUri: string): Promise<string> => {
31277
+ if (Platform.OS !== 'android') return indexUri;
31278
+ const native = requireNativeModule<{ registerBundle(root: string, paths: string[]): Promise<string> }>('AbsoluteEmbeddedAssets');
31279
+ return native.registerBundle(rootUri, paths);
31280
+ };
31281
+ `;
31282
+ var absoluteExpoEmbeddedAssetsFiles = (project) => {
31283
+ const root = join20(project, "modules/absolute-embedded-assets");
31284
+ return new Map([
31285
+ [
31286
+ join20(root, "expo-module.config.json"),
31287
+ `${JSON.stringify({
31288
+ android: {
31289
+ modules: [
31290
+ "expo.modules.absoluteembeddedassets.AbsoluteEmbeddedAssetsModule"
31291
+ ]
31292
+ },
31293
+ platforms: ["android"]
31294
+ }, null, 2)}
31295
+ `
31296
+ ],
31297
+ [
31298
+ join20(root, "android/build.gradle"),
31299
+ `${header}plugins { id 'com.android.library'; id 'expo-module-gradle-plugin' }
31300
+ group = 'expo.modules.absoluteembeddedassets'
31301
+ version = '0.0.1'
31302
+ android {
31303
+ namespace 'expo.modules.absoluteembeddedassets'
31304
+ defaultConfig { versionCode 1; versionName '0.0.1' }
31305
+ }
31306
+ dependencies {
31307
+ implementation 'com.facebook.react:react-android'
31308
+ implementation project(':react-native-webview')
31309
+ implementation 'androidx.webkit:webkit:1.14.0'
31310
+ }
31311
+ `
31312
+ ],
31313
+ [
31314
+ join20(root, "android/src/main/AndroidManifest.xml"),
31315
+ `<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
31316
+ `
31317
+ ],
31318
+ [
31319
+ join20(root, "android/src/main/java/expo/modules/absoluteembeddedassets/AbsoluteEmbeddedAssetsModule.kt"),
31320
+ android
31321
+ ],
31322
+ [join20(project, "plugins/withAbsoluteEmbeddedAssets.js"), plugin],
31323
+ [join20(project, "src/generated/AbsoluteEmbeddedAssets.ts"), runtime2]
31324
+ ]);
31325
+ };
31326
+
31028
31327
  // src/mobile/expoProject.ts
31029
31328
  var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
31030
31329
  `;
@@ -31105,7 +31404,7 @@ var routeSegments = (route) => {
31105
31404
  return segment;
31106
31405
  });
31107
31406
  };
31108
- var routeFile = (project, route) => join20(project, "app", ...routeSegments(route), "index.tsx");
31407
+ var routeFile = (project, route) => join21(project, "app", ...routeSegments(route), "index.tsx");
31109
31408
  var packageDependencies = (plan) => Object.fromEntries(plan.requiredPackages.map((spec) => {
31110
31409
  const separator = spec.lastIndexOf("@");
31111
31410
  return [spec.slice(0, separator), spec.slice(separator + 1)];
@@ -31194,24 +31493,24 @@ var expoAppConfig = (config, auth, sync, devices, runtimeFingerprint) => {
31194
31493
  const devicePlugins = [
31195
31494
  ...new Set(devices.capabilities.flatMap((name) => devices.providers[name]?.plugins ?? []))
31196
31495
  ];
31197
- const configuredPlugins = devicePlugins.map((plugin) => {
31198
- if (plugin === "expo-image-picker")
31496
+ const configuredPlugins = devicePlugins.map((plugin2) => {
31497
+ if (plugin2 === "expo-image-picker")
31199
31498
  return [
31200
- plugin,
31499
+ plugin2,
31201
31500
  {
31202
31501
  cameraPermission: descriptions.NSCameraUsageDescription,
31203
31502
  microphonePermission: false,
31204
31503
  photosPermission: descriptions.NSPhotoLibraryUsageDescription
31205
31504
  }
31206
31505
  ];
31207
- if (plugin === "expo-location")
31506
+ if (plugin2 === "expo-location")
31208
31507
  return [
31209
- plugin,
31508
+ plugin2,
31210
31509
  {
31211
31510
  locationWhenInUsePermission: descriptions.NSLocationWhenInUseUsageDescription
31212
31511
  }
31213
31512
  ];
31214
- return plugin;
31513
+ return plugin2;
31215
31514
  });
31216
31515
  return {
31217
31516
  expo: {
@@ -31233,7 +31532,7 @@ var expoAppConfig = (config, auth, sync, devices, runtimeFingerprint) => {
31233
31532
  package: config.appId,
31234
31533
  permissions: requirements.androidPermissions
31235
31534
  },
31236
- experiments: { typedRoutes: true },
31535
+ experiments: { tsconfigPaths: false, typedRoutes: true },
31237
31536
  ios: {
31238
31537
  ...branding?.ios ?? {},
31239
31538
  associatedDomains: config.deepLinkHosts.map((host2) => `applinks:${host2}`),
@@ -31256,6 +31555,7 @@ var expoAppConfig = (config, auth, sync, devices, runtimeFingerprint) => {
31256
31555
  ["expo-dev-client", { launchMode: "most-recent" }],
31257
31556
  ...branding ? [branding.splashPlugin] : [],
31258
31557
  "./plugins/withAbsoluteActivityResultRecovery",
31558
+ "./plugins/withAbsoluteEmbeddedAssets",
31259
31559
  ...auth || config.updates ? ["expo-secure-store"] : [],
31260
31560
  ...sync ? [
31261
31561
  "expo-sqlite",
@@ -31820,6 +32120,7 @@ import { ActivityIndicator, BackHandler, Platform, Pressable, StyleSheet, Text,
31820
32120
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
31821
32121
  import { WebView, type WebViewMessageEvent } from 'react-native-webview';
31822
32122
  import { materializeAbsoluteWebBundle } from './webAssets';
32123
+ import { absoluteEmbeddedNativeConfig } from './AbsoluteEmbeddedAssets';
31823
32124
  import { markAbsoluteEmbeddedWebPhase, markAbsoluteEmbeddedWebReady } from './AbsoluteActivityResultRecovery';
31824
32125
  import { createExpoDevicesBridgeHost } from '@absolutejs/devices-expo/bridge';
31825
32126
  import { absoluteExpoDevices, beforeAbsoluteExpoDeviceSignOut } from './AbsoluteDevices';
@@ -31939,7 +32240,16 @@ const bridgeBootstrap = (path: string, safeAreaInsets: { bottom: number; left: n
31939
32240
  event.preventDefault();
31940
32241
  send({ format: 3, kind: 'event', event: 'navigation', path: url.pathname + url.search + url.hash });
31941
32242
  }, true);
31942
- send({ format: 3, kind: 'event', event: 'ready', path: currentPath });
32243
+ let shellRendered = false;
32244
+ addEventListener('absolute:shell-rendered', () => {
32245
+ shellRendered = true;
32246
+ send({ format: 3, kind: 'event', event: 'shell-rendered', path: currentPath });
32247
+ });
32248
+ const startupFailed = () => {
32249
+ if (!shellRendered) send({ format: 3, kind: 'event', event: 'startup-failed', path: currentPath });
32250
+ };
32251
+ addEventListener('error', startupFailed);
32252
+ addEventListener('unhandledrejection', startupFailed);
31943
32253
  })(); true;\`;
31944
32254
  };
31945
32255
 
@@ -31984,11 +32294,18 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
31984
32294
  const canGoBack = useRef(false);
31985
32295
  const [runtimeReady, setRuntimeReady] = useState(!AUTH_ENABLED && !SYNC_ENABLED);
31986
32296
  const [devicesReady, setDevicesReady] = useState(false);
31987
- const [startupError, setStartupError] = useState<'assets' | 'devices'>();
32297
+ const [startupError, setStartupError] = useState<'assets' | 'devices' | 'content'>();
31988
32298
  const [startupRevision, setStartupRevision] = useState(0);
31989
32299
  const activeWebPath = useRef(pathname);
31990
32300
  const embeddedReadyReported = useRef(false);
31991
32301
  const webSource = useMemo(() => indexUri ? { uri: indexUri } : undefined, [indexUri]);
32302
+ useEffect(() => {
32303
+ if (!indexUri || DEV_ORIGIN) return;
32304
+ const timeout = setTimeout(() => {
32305
+ if (!embeddedReadyReported.current) setStartupError('content');
32306
+ }, 60000);
32307
+ return () => clearTimeout(timeout);
32308
+ }, [indexUri]);
31992
32309
 
31993
32310
  useEffect(() => {
31994
32311
  if (!AUTH_ENABLED && !SYNC_ENABLED) return;
@@ -32024,6 +32341,7 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
32024
32341
  markAbsoluteEmbeddedWebPhase('assets-start');
32025
32342
  void materializeAbsoluteWebBundle().then(uri => {
32026
32343
  markAbsoluteEmbeddedWebPhase('assets-ready');
32344
+ embeddedReadyReported.current = false;
32027
32345
  setIndexUri(uri + '?absolutePath=' + encodeURIComponent(pathname));
32028
32346
  }).catch(error => {
32029
32347
  const phase = error instanceof Error && (error.message === 'assets-root-failed' || error.message === 'assets-directory-failed' || error.message === 'assets-destination-failed' || error.message === 'assets-module-failed' || error.message === 'assets-source-failed' || error.message === 'assets-download-failed' || error.message === 'assets-copy-failed' || error.message === 'assets-read-failed' || error.message === 'assets-write-failed' || error.message === 'assets-finalize-failed')
@@ -32077,15 +32395,23 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
32077
32395
  try { return new URL(source).origin === origin; } catch { return false; }
32078
32396
  };
32079
32397
  const onMessage = async (event: WebViewMessageEvent) => {
32398
+ // Bridge authority belongs only to the currently loaded embedded bundle
32399
+ // (or the explicitly configured development origin), never remote pages.
32400
+ const sourceUrl = event.nativeEvent.url;
32401
+ if (!indexUri || typeof sourceUrl !== 'string' || (DEV_ORIGIN ? !hasOrigin(sourceUrl, DEV_ORIGIN) : !sourceUrl.startsWith(indexUri.slice(0, indexUri.lastIndexOf('/') + 1)))) return;
32080
32402
  const source = event.nativeEvent.data;
32081
32403
  if (new TextEncoder().encode(source).byteLength > MAX_MESSAGE_BYTES) return;
32082
32404
  let message: Record<string, unknown>;
32083
32405
  try { message = JSON.parse(source); } catch { return; }
32084
32406
  if (message.format !== BRIDGE_FORMAT || typeof message.path !== 'string' || !message.path.startsWith('/') || message.path.startsWith('//')) return;
32085
- if (message.kind === 'event' && (message.event === 'navigation' || message.event === 'ready')) {
32407
+ if (message.kind === 'event' && message.event === 'startup-failed') {
32408
+ if (!embeddedReadyReported.current) setStartupError('content');
32409
+ return;
32410
+ }
32411
+ if (message.kind === 'event' && (message.event === 'navigation' || message.event === 'shell-rendered')) {
32086
32412
  const target = new URL(message.path, PRODUCTION_ORIGIN);
32087
32413
  if (target.origin !== PRODUCTION_ORIGIN) return;
32088
- if (message.event === 'ready' && !DEV_ORIGIN && !embeddedReadyReported.current) {
32414
+ if (message.event === 'shell-rendered' && !DEV_ORIGIN && !embeddedReadyReported.current) {
32089
32415
  embeddedReadyReported.current = true;
32090
32416
  markAbsoluteEmbeddedWebReady();
32091
32417
  }
@@ -32139,12 +32465,17 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
32139
32465
  </View>;
32140
32466
  if (!webSource || !runtimeReady || !devicesReady) return <View style={styles.loading}><ActivityIndicator /></View>;
32141
32467
  return <WebView
32142
- allowFileAccess
32143
- allowFileAccessFromFileURLs
32468
+ nativeConfig={!DEV_ORIGIN ? absoluteEmbeddedNativeConfig : undefined}
32469
+ allowFileAccess={Platform.OS !== 'android'}
32470
+ allowFileAccessFromFileURLs={Platform.OS !== 'android'}
32144
32471
  allowUniversalAccessFromFileURLs={false}
32472
+ originWhitelist={DEV_ORIGIN ? [DEV_ORIGIN] : [Platform.OS === 'android' ? 'https://appassets.androidplatform.net' : 'file://*']}
32145
32473
  allowingReadAccessToURL={webSource.uri.slice(0, webSource.uri.lastIndexOf('/') + 1)}
32146
32474
  injectedJavaScriptBeforeContentLoaded={bridgeBootstrap(pathname, safeAreaInsets)}
32147
32475
  onMessage={onMessage}
32476
+ onError={() => setStartupError('content')}
32477
+ onRenderProcessGone={() => setStartupError('content')}
32478
+ onContentProcessDidTerminate={() => setStartupError('content')}
32148
32479
  onNavigationStateChange={state => {
32149
32480
  canGoBack.current = state.canGoBack;
32150
32481
  if (!DEV_ORIGIN || !hasOrigin(state.url, DEV_ORIGIN)) return;
@@ -32152,8 +32483,8 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
32152
32483
  activeWebPath.current = route.pathname + route.search + route.hash;
32153
32484
  }}
32154
32485
  onShouldStartLoadWithRequest={request => {
32155
- if (request.url.startsWith('file:') || hasOrigin(request.url, PRODUCTION_ORIGIN) || DEV_ORIGIN && hasOrigin(request.url, DEV_ORIGIN)) return true;
32156
- void Linking.openURL(request.url);
32486
+ if (DEV_ORIGIN ? hasOrigin(request.url, DEV_ORIGIN) : request.url.startsWith(webSource.uri.slice(0, webSource.uri.lastIndexOf('/') + 1))) return true;
32487
+ if (/^https?:/.test(request.url)) void Linking.openURL(request.url);
32157
32488
  return false;
32158
32489
  }}
32159
32490
  ref={webView}
@@ -32356,8 +32687,8 @@ const styles = StyleSheet.create({
32356
32687
  error: { color: '#b91c1c', fontSize: 16, textAlign: 'center' }
32357
32688
  });
32358
32689
  `;
32359
- var nativeWrapperSource = (wrapper, module, runtime2, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative3(dirname13(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
32360
- import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative3(dirname13(wrapper), runtime2).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
32690
+ var nativeWrapperSource = (wrapper, module, runtime3, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative3(dirname13(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
32691
+ import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative3(dirname13(wrapper), runtime3).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
32361
32692
 
32362
32693
  export const ErrorBoundary = createAbsoluteNativeRouteErrorBoundary(${JSON.stringify(route)});
32363
32694
  export default createAbsoluteNativeRoute(ApplicationNativeRoute, ${JSON.stringify(route)});
@@ -32426,7 +32757,7 @@ var pruneManagedFiles = async (paths) => {
32426
32757
  return removed.filter(Boolean).length;
32427
32758
  };
32428
32759
  var pruneStaleManagedExpoRoutes = async (project, expected) => {
32429
- const appDirectory = join20(project, "app");
32760
+ const appDirectory = join21(project, "app");
32430
32761
  if (!await exists6(appDirectory))
32431
32762
  return 0;
32432
32763
  const files = await walkFiles(appDirectory);
@@ -32474,7 +32805,7 @@ var writeAbsoluteExpoProject = async (config, options) => {
32474
32805
  if (missing) {
32475
32806
  throw new TypeError(`Expo native route ${missing.route} references missing module ${missing.module}.`);
32476
32807
  }
32477
- const marker = join20(project, EXPO_PROJECT_MARKER);
32808
+ const marker = join21(project, EXPO_PROJECT_MARKER);
32478
32809
  if (await exists6(project) && !await exists6(marker)) {
32479
32810
  const entries = await readdir5(project);
32480
32811
  if (entries.length > 0 && !options.force) {
@@ -32487,7 +32818,7 @@ var writeAbsoluteExpoProject = async (config, options) => {
32487
32818
  const authEnabled = Boolean(auth);
32488
32819
  const files = new Map([
32489
32820
  [
32490
- join20(project, ".gitignore"),
32821
+ join21(project, ".gitignore"),
32491
32822
  `.expo/
32492
32823
  android/
32493
32824
  ios/
@@ -32495,80 +32826,82 @@ node_modules/
32495
32826
  `
32496
32827
  ],
32497
32828
  [
32498
- join20(project, "app.json"),
32829
+ join21(project, "app.json"),
32499
32830
  jsonSource(expoAppConfig(config, authEnabled, syncEnabled, devices, runtimeFingerprint))
32500
32831
  ],
32501
- [join20(project, "app.config.js"), expoDynamicAppConfig],
32832
+ [join21(project, "app.config.js"), expoDynamicAppConfig],
32502
32833
  [
32503
- join20(project, "package.json"),
32834
+ join21(project, "package.json"),
32504
32835
  jsonSource(expoPackage(authEnabled, config.branding !== undefined, syncEnabled, devices, config.updates !== undefined))
32505
32836
  ],
32506
- [join20(project, "metro.config.js"), metroConfig(projectRoot)],
32837
+ [join21(project, "metro.config.js"), metroConfig(projectRoot)],
32507
32838
  [
32508
- join20(project, "plugins", "withAbsoluteDevelopmentCa.js"),
32839
+ join21(project, "plugins", "withAbsoluteDevelopmentCa.js"),
32509
32840
  expoDevelopmentCaPlugin
32510
32841
  ],
32511
32842
  [
32512
- join20(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
32843
+ join21(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
32513
32844
  expoActivityResultRecoveryPlugin
32514
32845
  ],
32515
32846
  [
32516
- join20(project, "tsconfig.json"),
32847
+ join21(project, "tsconfig.json"),
32517
32848
  jsonSource(expoTsConfig(projectRoot, project, authEnabled, syncEnabled))
32518
32849
  ],
32519
32850
  [
32520
- join20(project, "app", "_layout.tsx"),
32851
+ join21(project, "app", "_layout.tsx"),
32521
32852
  layoutSource(authEnabled, syncEnabled, config.updates !== undefined, config.observability !== undefined)
32522
32853
  ],
32523
32854
  [
32524
- join20(project, "app", "__absolute", "native", "index.tsx"),
32855
+ join21(project, "app", "__absolute", "native", "index.tsx"),
32525
32856
  nativeDiagnosticSource
32526
32857
  ],
32527
32858
  [
32528
- join20(project, "src", "generated", "AbsoluteDevices.ts"),
32859
+ join21(project, "src", "generated", "AbsoluteDevices.ts"),
32529
32860
  devicesRuntimeSource(config, devices, authEnabled)
32530
32861
  ],
32531
32862
  [
32532
- join20(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
32863
+ join21(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
32533
32864
  nativeRouteRuntimeSource(authEnabled)
32534
32865
  ],
32535
32866
  [
32536
- join20(project, "src", "generated", "AbsoluteWebHost.tsx"),
32867
+ join21(project, "src", "generated", "AbsoluteWebHost.tsx"),
32537
32868
  webHostSource(config, auth, syncEnabled)
32538
32869
  ]
32539
32870
  ]);
32540
32871
  for (const [path, source] of absoluteExpoActivityResultRecoveryFiles(project))
32541
32872
  files.set(path, source);
32873
+ for (const [path, source] of absoluteExpoEmbeddedAssetsFiles(project))
32874
+ files.set(path, source);
32542
32875
  if (config.observability) {
32543
32876
  for (const [path, source] of absoluteExpoNativeObservabilityFiles(project))
32544
32877
  files.set(path, source);
32545
32878
  }
32546
32879
  if (config.updates) {
32547
- files.set(join20(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
32880
+ files.set(join21(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
32548
32881
  }
32549
32882
  const expoCodeSigning = config.updates?.expoCodeSigning;
32550
32883
  if (expoCodeSigning)
32551
- files.set(join20(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
32884
+ files.set(join21(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
32552
32885
  if (auth) {
32553
- files.set(join20(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
32886
+ files.set(join21(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
32554
32887
  }
32555
32888
  if (syncSchema) {
32556
- files.set(join20(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
32889
+ files.set(join21(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
32557
32890
  }
32558
- const webAssetsPath = join20(project, "src", "generated", "webAssets.ts");
32891
+ const webAssetsPath = join21(project, "src", "generated", "webAssets.ts");
32559
32892
  if (!await exists6(webAssetsPath)) {
32560
32893
  files.set(webAssetsPath, emptyWebAssetsSource);
32561
32894
  }
32562
32895
  if (!config.expoNativeRoutes["/"]) {
32563
- files.set(join20(project, "app", "index.tsx"), webRouteSource);
32896
+ files.set(join21(project, "app", "index.tsx"), webRouteSource);
32564
32897
  }
32565
- files.set(join20(project, "app", "[...absolute].tsx"), catchAllRouteSource);
32566
- const nativeRouteRuntime = join20(project, "src", "generated", "AbsoluteNativeRoute.tsx");
32898
+ files.set(join21(project, "app", "[...absolute].tsx"), catchAllRouteSource);
32899
+ const nativeRouteRuntime = join21(project, "src", "generated", "AbsoluteNativeRoute.tsx");
32567
32900
  for (const [route, module] of routeModules) {
32568
- const wrapper = route === "/" ? join20(project, "app", "index.tsx") : routeFile(project, route);
32901
+ const wrapper = route === "/" ? join21(project, "app", "index.tsx") : routeFile(project, route);
32569
32902
  files.set(wrapper, nativeWrapperSource(wrapper, module, nativeRouteRuntime, route));
32570
32903
  }
32571
- const removedRoutes = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${join20(project, "app")}${sep8}`))));
32904
+ const removedRoutes = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${join21(project, "app")}${sep8}`))));
32572
32905
  const removedObservability = config.observability ? 0 : await pruneManagedFiles(absoluteExpoNativeObservabilityPaths(project));
32573
32906
  const changes = await Promise.all([...files].map(([path, source]) => writeManagedFile(path, source, true)));
32574
32907
  await writeAbsoluteExpoBrandingInputs(config, projectRoot);
@@ -32578,7 +32911,7 @@ node_modules/
32578
32911
  var walkFiles = async (root, directory = root) => {
32579
32912
  const entries = await readdir5(directory, { withFileTypes: true });
32580
32913
  const nested = await Promise.all(entries.map((entry) => {
32581
- const path = join20(directory, entry.name);
32914
+ const path = join21(directory, entry.name);
32582
32915
  if (entry.isDirectory())
32583
32916
  return walkFiles(root, path);
32584
32917
  if (entry.isFile())
@@ -32611,13 +32944,16 @@ var installStagedDirectory = async (staging, destination) => {
32611
32944
  throw error;
32612
32945
  }
32613
32946
  };
32614
- var assetModuleSource = (assets, archiveAsset, bundleId, manifest) => `${EXPO_GENERATED_HEADER}import { Asset } from 'expo-asset';
32947
+ var assetModuleSource = (assets, archiveAsset, bundleId, archiveMd5, manifest) => `${EXPO_GENERATED_HEADER}import { Asset } from 'expo-asset';
32615
32948
  import { Directory, File, Paths } from 'expo-file-system';
32616
32949
  import { copyAsync as copyLegacyAsync } from 'expo-file-system/legacy';
32950
+ import { registerAbsoluteEmbeddedBundle } from './AbsoluteEmbeddedAssets';
32617
32951
 
32618
32952
  ${nativeDataManifestTypeSource}
32619
32953
  declare const require: (path: string) => number;
32620
32954
  const BUNDLE_ID = ${JSON.stringify(bundleId)};
32955
+ const ARCHIVE_MD5 = ${JSON.stringify(archiveMd5)};
32956
+ const ARCHIVE_LENGTH = ${assets.reduce((sum, entry) => sum + entry.length, 0)};
32621
32957
  export const ABSOLUTE_MOBILE_MANIFEST: AbsoluteMobileManifest = ${JSON.stringify(manifest)};
32622
32958
  const ARCHIVE_MODULE = require(${JSON.stringify(archiveAsset)});
32623
32959
  const ASSETS = [
@@ -32634,10 +32970,12 @@ export const materializeAbsoluteWebBundle = async () => {
32634
32970
  let archive: File;
32635
32971
  try { archive = new File(root, '.absolutejs-bundle.absasset'); }
32636
32972
  catch { throw new Error('assets-destination-failed'); }
32973
+ if (archive.exists && (archive.size !== ARCHIVE_LENGTH || archive.md5 !== ARCHIVE_MD5)) archive.delete();
32637
32974
  if (!archive.exists) {
32638
32975
  let asset: Asset;
32639
32976
  try { asset = Asset.fromModule(ARCHIVE_MODULE); }
32640
32977
  catch { throw new Error('assets-module-failed'); }
32978
+ if (asset.type !== 'absasset' || asset.hash !== ARCHIVE_MD5) throw new Error('assets-identity-failed');
32641
32979
  try { if (!asset.localUri) asset = await asset.downloadAsync(); }
32642
32980
  catch { throw new Error('assets-download-failed'); }
32643
32981
  if (!asset.localUri) throw new Error('assets-download-failed');
@@ -32650,9 +32988,16 @@ export const materializeAbsoluteWebBundle = async () => {
32650
32988
  catch { throw new Error('assets-copy-failed'); }
32651
32989
  }
32652
32990
  }
32991
+ // Checksums detect accidental corruption/registry mismatches, not authenticity;
32992
+ // authenticity comes from the signed application/update containing this table.
32993
+ if (archive.size !== ARCHIVE_LENGTH || archive.md5 !== ARCHIVE_MD5) {
32994
+ archive.delete();
32995
+ throw new Error('assets-integrity-failed');
32996
+ }
32653
32997
  let contents: Uint8Array;
32654
32998
  try { contents = await archive.bytes(); }
32655
32999
  catch { throw new Error('assets-read-failed'); }
33000
+ if (contents.byteLength !== ARCHIVE_LENGTH) throw new Error('assets-integrity-failed');
32656
33001
  for (const entry of ASSETS) {
32657
33002
  const parts = entry.path.split('/');
32658
33003
  const name = parts.pop();
@@ -32666,27 +33011,28 @@ export const materializeAbsoluteWebBundle = async () => {
32666
33011
  let destination: File;
32667
33012
  try {
32668
33013
  destination = new File(directory, name);
32669
- if (destination.exists && destination.size === entry.length) continue;
33014
+ if (destination.exists && destination.size === entry.length && destination.md5 === entry.md5) continue;
32670
33015
  if (destination.exists) destination.delete();
32671
33016
  } catch { throw new Error('assets-destination-failed'); }
32672
33017
  try { destination.write(contents.slice(entry.offset, entry.offset + entry.length)); }
32673
33018
  catch { throw new Error('assets-write-failed'); }
33019
+ if (destination.size !== entry.length || destination.md5 !== entry.md5) throw new Error('assets-integrity-failed');
32674
33020
  }
32675
33021
  try { archive.delete(); }
32676
33022
  catch { throw new Error('assets-finalize-failed'); }
32677
33023
 
32678
- try { return new File(root, 'index.html').uri; }
33024
+ try { return await registerAbsoluteEmbeddedBundle(root.uri, ASSETS.map(entry => entry.path), new File(root, 'index.html').uri); }
32679
33025
  catch { throw new Error('assets-finalize-failed'); }
32680
33026
  };
32681
33027
  `;
32682
33028
  var syncAbsoluteExpoWebAssets = async (config) => {
32683
33029
  if (config.engine !== "expo")
32684
33030
  throw new TypeError("Expo asset sync requires mobile.engine: expo.");
32685
- const marker = join20(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
33031
+ const marker = join21(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
32686
33032
  if (!await exists6(marker)) {
32687
33033
  throw new TypeError("Expo asset sync requires an AbsoluteJS-managed Expo project. Run mobile init first.");
32688
33034
  }
32689
- const manifestPath = join20(config.bundleDirectory, "absolute-mobile-manifest.json");
33035
+ const manifestPath = join21(config.bundleDirectory, "absolute-mobile-manifest.json");
32690
33036
  const manifest = JSON.parse(await readFile17(manifestPath, "utf8"));
32691
33037
  const nativeDataManifest = expoNativeDataManifest(manifest);
32692
33038
  const { appBuild } = nativeDataManifest;
@@ -32700,16 +33046,18 @@ var syncAbsoluteExpoWebAssets = async (config) => {
32700
33046
  bundleHash.update("\x00");
32701
33047
  });
32702
33048
  const bundleId = `amexpo_${bundleHash.digest("hex")}`;
32703
- const destination = join20(config.nativeProjectDirectory, "assets", "absolute");
33049
+ const destination = join21(config.nativeProjectDirectory, "assets", "absolute");
32704
33050
  await mkdir14(dirname13(destination), { recursive: true });
32705
- const staging = await mkdtemp9(join20(dirname13(destination), `.${basename6(destination)}.stage-`));
33051
+ const staging = await mkdtemp9(join21(dirname13(destination), `.${basename6(destination)}.stage-`));
32706
33052
  let assets;
32707
33053
  let archiveAsset;
33054
+ let archiveMd5;
32708
33055
  try {
32709
33056
  let offset = 0;
32710
33057
  assets = filesWithContents.map(({ contents, file }) => {
32711
33058
  const entry = {
32712
33059
  length: contents.byteLength,
33060
+ md5: createHash15("md5").update(contents).digest("hex"),
32713
33061
  offset,
32714
33062
  path: relative13(config.bundleDirectory, file).replaceAll("\\", "/")
32715
33063
  };
@@ -32717,15 +33065,17 @@ var syncAbsoluteExpoWebAssets = async (config) => {
32717
33065
  return entry;
32718
33066
  });
32719
33067
  const name = `bundle${EXPO_ASSET_EXTENSION}`;
32720
- await writeFile14(join20(staging, name), Buffer.concat(filesWithContents.map(({ contents }) => contents)));
32721
- archiveAsset = portableRelative3(join20(config.nativeProjectDirectory, "src", "generated"), join20(destination, name));
33068
+ const archiveContents = Buffer.concat(filesWithContents.map(({ contents }) => contents));
33069
+ archiveMd5 = createHash15("md5").update(archiveContents).digest("hex");
33070
+ await writeFile14(join21(staging, name), archiveContents);
33071
+ archiveAsset = portableRelative3(join21(config.nativeProjectDirectory, "src", "generated"), join21(destination, name));
32722
33072
  await installStagedDirectory(staging, destination);
32723
33073
  } catch (error) {
32724
33074
  await rm13(staging, { force: true, recursive: true });
32725
33075
  throw error;
32726
33076
  }
32727
- const generated = join20(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
32728
- await writeManagedFile(generated, assetModuleSource(assets, archiveAsset, bundleId, nativeDataManifest), true);
33077
+ const generated = join21(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
33078
+ await writeManagedFile(generated, assetModuleSource(assets, archiveAsset, bundleId, archiveMd5, nativeDataManifest), true);
32729
33079
  return { appBuild, assets: assets.length, bundleId, path: destination };
32730
33080
  };
32731
33081
 
@@ -32765,9 +33115,9 @@ var loadServerApp = async (producerPath) => {
32765
33115
  var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
32766
33116
  const buildDirectory = resolve16(options.buildDirectory);
32767
33117
  const mobile = normalizeAbsoluteMobileConfig(options.mobile, options.projectRoot);
32768
- const root = join21(buildDirectory, ".absolutejs", "mobile-compatibility");
33118
+ const root = join22(buildDirectory, ".absolutejs", "mobile-compatibility");
32769
33119
  const [manifestSource, previous] = await Promise.all([
32770
- readFile18(join21(buildDirectory, "manifest.json"), "utf8"),
33120
+ readFile18(join22(buildDirectory, "manifest.json"), "utf8"),
32771
33121
  readAbsoluteMobileMaterializedReleases(root)
32772
33122
  ]);
32773
33123
  const manifest = JSON.parse(manifestSource);
@@ -33095,7 +33445,7 @@ var parseRequest = (value) => {
33095
33445
  throw new TypeError("Expo bridge HTTP method cannot contain a body.");
33096
33446
  if (!isRecord10(value.params.headers))
33097
33447
  throw new TypeError("Expo bridge HTTP headers must be an object.");
33098
- const headersAllowed = Object.entries(value.params.headers).every(([name, header]) => typeof header === "string" && (name.toLowerCase() === "accept" || name.toLowerCase() === "content-type" || name.toLowerCase().startsWith("x-absolute-mobile-")));
33448
+ const headersAllowed = Object.entries(value.params.headers).every(([name, header2]) => typeof header2 === "string" && (name.toLowerCase() === "accept" || name.toLowerCase() === "content-type" || name.toLowerCase().startsWith("x-absolute-mobile-")));
33099
33449
  if (!headersAllowed) {
33100
33450
  throw new TypeError("Expo bridge HTTP header is not allowed.");
33101
33451
  }
@@ -33344,7 +33694,7 @@ var parseAbsoluteAndroidAccessibilityHierarchy = (source) => [...source.matchAll
33344
33694
  // src/mobile/expoNativeWatcher.ts
33345
33695
  import { watch as watch2 } from "fs";
33346
33696
  import { access as access15, readdir as readdir6, readFile as readFile19 } from "fs/promises";
33347
- import { basename as basename7, join as join22, relative as relative15 } from "path";
33697
+ import { basename as basename7, join as join23, relative as relative15 } from "path";
33348
33698
  import { createHash as createHash16 } from "crypto";
33349
33699
  var NATIVE_CHANGE_DEBOUNCE_MS2 = 500;
33350
33700
  var ROOT_NATIVE_INPUTS2 = new Set([
@@ -33365,7 +33715,7 @@ var filesIn = async (directory, prefix) => {
33365
33715
  return [];
33366
33716
  const entries = await readdir6(directory, { withFileTypes: true });
33367
33717
  const nested = await Promise.all(entries.map((entry) => {
33368
- const path = join22(directory, entry.name);
33718
+ const path = join23(directory, entry.name);
33369
33719
  const name = `${prefix}/${entry.name}`;
33370
33720
  if (entry.isDirectory())
33371
33721
  return filesIn(path, name);
@@ -33376,10 +33726,10 @@ var filesIn = async (directory, prefix) => {
33376
33726
  var fingerprintAbsoluteExpoNativeInputs = async (options) => {
33377
33727
  const hash = createHash16("sha256");
33378
33728
  const rootFiles = await Promise.all([...ROOT_NATIVE_INPUTS2].sort().map(async (name) => {
33379
- const path = join22(options.projectRoot, name);
33729
+ const path = join23(options.projectRoot, name);
33380
33730
  return await exists8(path) ? [{ name: `root/${name}`, path }] : [];
33381
33731
  }));
33382
- const nativeFiles = await Promise.all(EXPO_NATIVE_DIRECTORIES.map((name) => filesIn(join22(options.expoProjectDirectory, name), name)));
33732
+ const nativeFiles = await Promise.all(EXPO_NATIVE_DIRECTORIES.map((name) => filesIn(join23(options.expoProjectDirectory, name), name)));
33383
33733
  const files = [...rootFiles.flat(), ...nativeFiles.flat()].sort((left, right) => left.name.localeCompare(right.name));
33384
33734
  const contents = await Promise.all(files.map(({ path }) => readFile19(path)));
33385
33735
  files.forEach(({ name }, index) => {
@@ -33450,14 +33800,14 @@ var createAbsoluteExpoNativeWatcher = async (options) => {
33450
33800
  }
33451
33801
  };
33452
33802
  const nativeDirectories = (await Promise.all(EXPO_NATIVE_DIRECTORIES.map(async (name) => {
33453
- const directory = join22(options.expoProjectDirectory, name);
33803
+ const directory = join23(options.expoProjectDirectory, name);
33454
33804
  return await exists8(directory) ? [directory] : [];
33455
33805
  }))).flat();
33456
33806
  nativeDirectories.forEach((directory) => {
33457
33807
  watchers.push(watch2(directory, { recursive: true }, (_event, filename) => {
33458
33808
  if (!filename)
33459
33809
  return;
33460
- record(relative15(options.expoProjectDirectory, join22(directory, String(filename))), false);
33810
+ record(relative15(options.expoProjectDirectory, join23(directory, String(filename))), false);
33461
33811
  }));
33462
33812
  });
33463
33813
  watchers.push(watch2(options.projectRoot, (_event, filename) => {
@@ -33473,7 +33823,7 @@ var createAbsoluteExpoNativeWatcher = async (options) => {
33473
33823
  };
33474
33824
  // src/mobile/expoUpdate.ts
33475
33825
  import { access as access16, mkdir as mkdir16, readFile as readFile20, writeFile as writeFile16 } from "fs/promises";
33476
- import { dirname as dirname15, extname as extname4, join as join23 } from "path";
33826
+ import { dirname as dirname15, extname as extname4, join as join24 } from "path";
33477
33827
  var ABSOLUTE_EXPO_UPDATE_DESCRIPTOR = "_absolute/expo-update.json";
33478
33828
  var ABSOLUTE_EXPO_UPDATE_FORMAT = 1;
33479
33829
  var object4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -33539,7 +33889,7 @@ var parseAbsoluteExpoUpdateDescriptor = (value) => {
33539
33889
  };
33540
33890
  };
33541
33891
  var finalizeAbsoluteExpoUpdateExport = async (options) => {
33542
- const metadata = JSON.parse(await readFile20(join23(options.exportDirectory, "metadata.json"), "utf8"));
33892
+ const metadata = JSON.parse(await readFile20(join24(options.exportDirectory, "metadata.json"), "utf8"));
33543
33893
  if (!object4(metadata) || !object4(metadata.fileMetadata))
33544
33894
  throw new TypeError("Expo export metadata.json is invalid.");
33545
33895
  const descriptor = parseAbsoluteExpoUpdateDescriptor({
@@ -33550,10 +33900,10 @@ var finalizeAbsoluteExpoUpdateExport = async (options) => {
33550
33900
  runtimeVersion: options.runtimeVersion
33551
33901
  });
33552
33902
  const referenced = Object.values(descriptor.platforms).flatMap((entry) => entry ? [entry.launchAsset, ...entry.assets] : []);
33553
- await Promise.all(referenced.map(({ path }) => access16(join23(options.exportDirectory, path)).catch(() => {
33903
+ await Promise.all(referenced.map(({ path }) => access16(join24(options.exportDirectory, path)).catch(() => {
33554
33904
  throw new TypeError(`Expo export metadata references missing asset ${path}.`);
33555
33905
  })));
33556
- const destination = join23(options.exportDirectory, ABSOLUTE_EXPO_UPDATE_DESCRIPTOR);
33906
+ const destination = join24(options.exportDirectory, ABSOLUTE_EXPO_UPDATE_DESCRIPTOR);
33557
33907
  await mkdir16(dirname15(destination), { recursive: true });
33558
33908
  await writeFile16(destination, `${JSON.stringify(descriptor, null, "\t")}
33559
33909
  `);
@@ -33575,7 +33925,7 @@ import {
33575
33925
  stat as stat7,
33576
33926
  writeFile as writeFile19
33577
33927
  } from "fs/promises";
33578
- import { dirname as dirname17, isAbsolute as isAbsolute11, join as join25, relative as relative18, resolve as resolve20, sep as sep12 } from "path";
33928
+ import { dirname as dirname17, isAbsolute as isAbsolute11, join as join26, relative as relative18, resolve as resolve20, sep as sep12 } from "path";
33579
33929
 
33580
33930
  // src/mobile/certificationVerification.ts
33581
33931
  import { access as access17, mkdir as mkdir17, readFile as readFile21, stat as stat6, writeFile as writeFile17 } from "fs/promises";
@@ -33690,7 +34040,7 @@ import {
33690
34040
  rm as rm14,
33691
34041
  writeFile as writeFile18
33692
34042
  } from "fs/promises";
33693
- import { basename as basename8, isAbsolute as isAbsolute10, join as join24, relative as relative17, resolve as resolve19, sep as sep11 } from "path";
34043
+ import { basename as basename8, isAbsolute as isAbsolute10, join as join25, relative as relative17, resolve as resolve19, sep as sep11 } from "path";
33694
34044
  var ABSOLUTE_MOBILE_RELEASE_CERTIFICATION_FORMAT = 1;
33695
34045
  var CERTIFICATION_PREFIX = "amobile_cert_";
33696
34046
  var SHA256 = /^[a-f0-9]{64}$/u;
@@ -33734,7 +34084,7 @@ var resolveEvidencePath = async (projectRoot, requested) => {
33734
34084
  throw new TypeError("Mobile certification evidence must remain inside the project.");
33735
34085
  if (basename8(selected) === "report.json")
33736
34086
  return selected;
33737
- const report = join24(selected, "report.json");
34087
+ const report = join25(selected, "report.json");
33738
34088
  if (!await exists9(report))
33739
34089
  throw new TypeError(`Mobile certification evidence does not contain report.json: ${requested}`);
33740
34090
  return report;
@@ -33999,7 +34349,7 @@ var readAbsoluteMobileReleaseCertification = async (projectRoot, requested) => {
33999
34349
  const selected = resolve19(projectRoot, requested);
34000
34350
  if (!inside4(projectRoot, selected))
34001
34351
  throw new TypeError("Mobile release certification must remain inside the project.");
34002
- const path = basename8(selected) === "certification.json" ? selected : join24(selected, "certification.json");
34352
+ const path = basename8(selected) === "certification.json" ? selected : join25(selected, "certification.json");
34003
34353
  const value = JSON.parse(await readFile22(path, "utf8"));
34004
34354
  return { certification: parseCertification(value), path };
34005
34355
  };
@@ -34046,15 +34396,15 @@ var verifyAbsoluteMobileReleaseCertification = (certification, release, requirem
34046
34396
  };
34047
34397
  var writeAbsoluteMobileReleaseCertification = async (projectRoot, certification, outputDirectory) => {
34048
34398
  const root = resolve19(projectRoot);
34049
- const parent = resolve19(root, outputDirectory ?? join24(".absolutejs", "mobile", "certifications", certification.release.platform, certification.release.releaseId));
34399
+ const parent = resolve19(root, outputDirectory ?? join25(".absolutejs", "mobile", "certifications", certification.release.platform, certification.release.releaseId));
34050
34400
  if (!inside4(root, parent))
34051
34401
  throw new TypeError("Mobile certification output must remain inside the project.");
34052
34402
  await mkdir18(parent, { recursive: true });
34053
- const destination = join24(parent, certification.certificationId);
34403
+ const destination = join25(parent, certification.certificationId);
34054
34404
  const paths = {
34055
34405
  directory: destination,
34056
- jsonPath: join24(destination, "certification.json"),
34057
- markdownPath: join24(destination, "certification.md")
34406
+ jsonPath: join25(destination, "certification.json"),
34407
+ markdownPath: join25(destination, "certification.md")
34058
34408
  };
34059
34409
  const json = serializeAbsoluteMobileReleaseCertification(certification);
34060
34410
  const markdown = renderAbsoluteMobileReleaseCertification(certification);
@@ -34070,13 +34420,13 @@ var writeAbsoluteMobileReleaseCertification = async (projectRoot, certification,
34070
34420
  await verifyExisting();
34071
34421
  return paths;
34072
34422
  }
34073
- const staging = await mkdtemp10(join24(parent, ".certification-"));
34423
+ const staging = await mkdtemp10(join25(parent, ".certification-"));
34074
34424
  try {
34075
34425
  await Promise.all([
34076
- writeFile18(join24(staging, "certification.json"), json, {
34426
+ writeFile18(join25(staging, "certification.json"), json, {
34077
34427
  flag: "wx"
34078
34428
  }),
34079
- writeFile18(join24(staging, "certification.md"), markdown, {
34429
+ writeFile18(join25(staging, "certification.md"), markdown, {
34080
34430
  flag: "wx"
34081
34431
  })
34082
34432
  ]);
@@ -34308,7 +34658,7 @@ var findFiles = async (root, name) => {
34308
34658
  visited += 1;
34309
34659
  if (visited > MAX_SEARCH_FILES)
34310
34660
  throw new TypeError("Downloaded GitHub artifact contains too many files.");
34311
- const path = join25(directory, entry.name);
34661
+ const path = join26(directory, entry.name);
34312
34662
  if (entry.isDirectory()) {
34313
34663
  await walk(path);
34314
34664
  return;
@@ -34423,9 +34773,9 @@ var auditAbsoluteMobileCiPromotion = async (options) => {
34423
34773
  if (await access19(output).then(() => true).catch(() => false))
34424
34774
  throw new TypeError(`Mobile CI audit output already exists: ${output}`);
34425
34775
  await mkdir19(dirname17(output), { recursive: true });
34426
- const staging = await mkdtemp11(join25(dirname17(output), ".promotion-audit-"));
34776
+ const staging = await mkdtemp11(join26(dirname17(output), ".promotion-audit-"));
34427
34777
  try {
34428
- const evidenceRoot = join25(staging, "promotion-evidence");
34778
+ const evidenceRoot = join26(staging, "promotion-evidence");
34429
34779
  await mkdir19(evidenceRoot);
34430
34780
  await requireCommand(runner, [
34431
34781
  "gh",
@@ -34456,7 +34806,7 @@ var auditAbsoluteMobileCiPromotion = async (options) => {
34456
34806
  if (context && options.sourceRunId && context.sourceRunId !== sourceRunId)
34457
34807
  throw new TypeError("Requested source run does not match promotion context.");
34458
34808
  const sourceArtifact = context?.sourceArtifact ?? `absolute-mobile-${platform3}`;
34459
- const sourceRoot = join25(staging, "source-release");
34809
+ const sourceRoot = join26(staging, "source-release");
34460
34810
  await mkdir19(sourceRoot);
34461
34811
  await requireCommand(runner, [
34462
34812
  "gh",
@@ -34540,9 +34890,9 @@ var auditAbsoluteMobileCiPromotion = async (options) => {
34540
34890
  verifiedAt: new Date().toISOString()
34541
34891
  };
34542
34892
  await Promise.all([
34543
- writeFile19(join25(staging, "audit.json"), `${JSON.stringify(audit, null, 2)}
34893
+ writeFile19(join26(staging, "audit.json"), `${JSON.stringify(audit, null, 2)}
34544
34894
  `, { mode: 384 }),
34545
- writeFile19(join25(staging, "audit.md"), renderAuditMarkdown(audit), {
34895
+ writeFile19(join26(staging, "audit.md"), renderAuditMarkdown(audit), {
34546
34896
  mode: 384
34547
34897
  })
34548
34898
  ]);
@@ -34565,7 +34915,7 @@ import {
34565
34915
  rename as rename16,
34566
34916
  rm as rm16
34567
34917
  } from "fs/promises";
34568
- import { dirname as dirname18, isAbsolute as isAbsolute12, join as join26, relative as relative19, resolve as resolve21, sep as sep13 } from "path";
34918
+ import { dirname as dirname18, isAbsolute as isAbsolute12, join as join27, relative as relative19, resolve as resolve21, sep as sep13 } from "path";
34569
34919
  import { randomUUID as randomUUID5 } from "crypto";
34570
34920
  var ABSOLUTE_MOBILE_CI_PROMOTION_OPERATION_FORMAT = 1;
34571
34921
  var MAX_OPERATION_BYTES = 65536;
@@ -34631,8 +34981,8 @@ var runId2 = (value, label) => {
34631
34981
  return parsed;
34632
34982
  };
34633
34983
  var nullableRunId = (value, label) => value === null ? null : runId2(value, label);
34634
- var operationRoot = (projectRoot) => join26(resolve21(projectRoot), ".absolutejs", "mobile-ci", "promotions");
34635
- var absoluteMobilePromotionOperationPath = (projectRoot, requestedDispatchId) => join26(operationRoot(projectRoot), dispatchId2(requestedDispatchId), "operation.json");
34984
+ var operationRoot = (projectRoot) => join27(resolve21(projectRoot), ".absolutejs", "mobile-ci", "promotions");
34985
+ var absoluteMobilePromotionOperationPath = (projectRoot, requestedDispatchId) => join27(operationRoot(projectRoot), dispatchId2(requestedDispatchId), "operation.json");
34636
34986
  var operationPhase = (value) => {
34637
34987
  const phase = PHASES.find((candidate) => candidate === value);
34638
34988
  if (!phase)
@@ -34703,7 +35053,7 @@ var writeSynced = async (path, source) => {
34703
35053
  };
34704
35054
  var atomicWrite = async (path, source, exclusive) => {
34705
35055
  await mkdir20(dirname18(path), { recursive: true });
34706
- const temporary = join26(dirname18(path), `.operation-${randomUUID5()}.tmp`);
35056
+ const temporary = join27(dirname18(path), `.operation-${randomUUID5()}.tmp`);
34707
35057
  try {
34708
35058
  await writeSynced(temporary, source);
34709
35059
  if (exclusive)
@@ -35605,7 +35955,7 @@ init_mobilePreview();
35605
35955
 
35606
35956
  // src/mobile/nativeDeepLinks.ts
35607
35957
  import { readFile as readFile26, rename as rename17, writeFile as writeFile21 } from "fs/promises";
35608
- import { join as join29 } from "path";
35958
+ import { join as join30 } from "path";
35609
35959
  var START_MARKER = "<!-- absolutejs:deep-links:start -->";
35610
35960
  var END_MARKER = "<!-- absolutejs:deep-links:end -->";
35611
35961
  var IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements";
@@ -35662,7 +36012,7 @@ ${hosts}
35662
36012
  `;
35663
36013
  };
35664
36014
  var configureAndroid = async (config) => {
35665
- const path = join29(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
36015
+ const path = join30(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
35666
36016
  const source = await readFile26(path, "utf8");
35667
36017
  const mainActivity = source.indexOf('android:name=".MainActivity"');
35668
36018
  if (mainActivity === NOT_FOUND) {
@@ -35688,7 +36038,7 @@ var iosSchemeRegion = (scheme) => ` ${START_MARKER}
35688
36038
  ${END_MARKER}
35689
36039
  `;
35690
36040
  var configureIosInfo = async (config) => {
35691
- const path = join29(config.nativeProjectDirectory, "ios/App/App/Info.plist");
36041
+ const path = join30(config.nativeProjectDirectory, "ios/App/App/Info.plist");
35692
36042
  const source = await readFile26(path, "utf8");
35693
36043
  const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
35694
36044
  ${END_MARKER}
@@ -35712,7 +36062,7 @@ ${domains}
35712
36062
  `;
35713
36063
  };
35714
36064
  var configureIosEntitlements = async (config) => {
35715
- const path = join29(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
36065
+ const path = join30(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
35716
36066
  let current = "";
35717
36067
  try {
35718
36068
  current = await readFile26(path, "utf8");
@@ -35730,7 +36080,7 @@ var configureIosEntitlements = async (config) => {
35730
36080
  return true;
35731
36081
  };
35732
36082
  var configureIosProject = async (config) => {
35733
- const path = join29(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
36083
+ const path = join30(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
35734
36084
  const source = await readFile26(path, "utf8");
35735
36085
  const declarations = [
35736
36086
  ...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
@@ -35771,7 +36121,7 @@ var applyAbsoluteNativeDeepLinks = async (config, platforms = config.platforms)
35771
36121
  // src/mobile/nativeDeviceCapabilities.ts
35772
36122
  init_deviceCapabilities();
35773
36123
  import { readFile as readFile27, rename as rename18, writeFile as writeFile22 } from "fs/promises";
35774
- import { join as join30 } from "path";
36124
+ import { join as join31 } from "path";
35775
36125
  var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->";
35776
36126
  var END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->";
35777
36127
  var NOT_FOUND2 = -1;
@@ -35921,7 +36271,7 @@ var writeIosPrivacyManifest = async (path, current, source) => {
35921
36271
  var configureIosPrivacyProject = async (config, requirements) => {
35922
36272
  if (requirements.iosPrivacyAccessedApis.length === 0)
35923
36273
  return false;
35924
- const projectPath3 = join30(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
36274
+ const projectPath3 = join31(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
35925
36275
  const project = await readFile27(projectPath3, "utf8");
35926
36276
  return writeChangedFile2(projectPath3, addIosPrivacyProjectReference(project));
35927
36277
  };
@@ -35974,7 +36324,7 @@ ${next.slice(index)}`;
35974
36324
  return next;
35975
36325
  };
35976
36326
  var configureIos2 = async (config, plan) => {
35977
- const path = join30(config.nativeProjectDirectory, "ios/App/App/Info.plist");
36327
+ const path = join31(config.nativeProjectDirectory, "ios/App/App/Info.plist");
35978
36328
  const source = await readFile27(path, "utf8");
35979
36329
  const requirements = absoluteDeviceNativeRequirements(plan);
35980
36330
  const existingSystemBars = source.match(/<key>UIViewControllerBasedStatusBarAppearance<\/key>\s*<(true|false)\s*\/>/u);
@@ -35995,7 +36345,7 @@ ${content}
35995
36345
  ${END_MARKER2}
35996
36346
  ` : "";
35997
36347
  const infoChanged = await writeChangedFile2(path, managed(source, region, source.lastIndexOf("</dict>")));
35998
- const privacyPath = join30(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
36348
+ const privacyPath = join31(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
35999
36349
  const privacyCurrent = await optionalSource(privacyPath);
36000
36350
  const privacySource = privacyManifestSource(privacyCurrent, requirements);
36001
36351
  const [privacyChanged, projectChanged, pushChanged] = await Promise.all([
@@ -36006,7 +36356,7 @@ ${content}
36006
36356
  return infoChanged || privacyChanged || projectChanged || pushChanged;
36007
36357
  };
36008
36358
  var configureIosPushNotifications = async (config, enabled) => {
36009
- const entitlementsPath = join30(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
36359
+ const entitlementsPath = join31(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
36010
36360
  const entitlements = await optionalSource(entitlementsPath);
36011
36361
  if (entitlements === null && !enabled)
36012
36362
  return false;
@@ -36018,7 +36368,7 @@ var configureIosPushNotifications = async (config, enabled) => {
36018
36368
  <!-- ${PUSH_END_MARKER} -->
36019
36369
  ` : "";
36020
36370
  const nextEntitlements = replacePushRegion(entitlements, entitlementRegion, entitlements.lastIndexOf("</dict>"));
36021
- const delegatePath = join30(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36371
+ const delegatePath = join31(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36022
36372
  const delegate = await optionalSource(delegatePath);
36023
36373
  if (delegate === null && !enabled)
36024
36374
  return false;
@@ -36067,7 +36417,7 @@ var replacePushRegion = (source, region, insertion) => {
36067
36417
  return `${source.slice(0, insertion)}${region}${source.slice(insertion)}`;
36068
36418
  };
36069
36419
  var configureAndroid2 = async (config, plan) => {
36070
- const path = join30(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
36420
+ const path = join31(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
36071
36421
  const source = await readFile27(path, "utf8");
36072
36422
  const permissions = absoluteDeviceNativeRequirements(plan).androidPermissions;
36073
36423
  const content = permissions.map((permission) => ` <uses-permission android:name="${escapeXml2(permission)}" />`).join(`
@@ -36096,14 +36446,14 @@ ${content}
36096
36446
  const clients = typeof firebase === "object" && firebase !== null ? Reflect.get(firebase, "client") : undefined;
36097
36447
  const matchesApp = Array.isArray(clients) && clients.some((client) => {
36098
36448
  const info = typeof client === "object" && client !== null ? Reflect.get(client, "client_info") : undefined;
36099
- const android = typeof info === "object" && info !== null ? Reflect.get(info, "android_client_info") : undefined;
36100
- return typeof android === "object" && android !== null && Reflect.get(android, "package_name") === config.appId;
36449
+ const android2 = typeof info === "object" && info !== null ? Reflect.get(info, "android_client_info") : undefined;
36450
+ return typeof android2 === "object" && android2 !== null && Reflect.get(android2, "package_name") === config.appId;
36101
36451
  });
36102
36452
  if (!matchesApp)
36103
36453
  throw new TypeError(`Android google-services.json does not contain package ${config.appId}.`);
36104
36454
  const [manifestChanged, firebaseChanged] = await Promise.all([
36105
36455
  writeChangedFile2(path, nextManifest),
36106
- writeOptionalChangedFile(join30(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
36456
+ writeOptionalChangedFile(join31(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
36107
36457
  ]);
36108
36458
  return manifestChanged || firebaseChanged;
36109
36459
  };
@@ -36129,7 +36479,7 @@ import {
36129
36479
  rm as rm17,
36130
36480
  writeFile as writeFile23
36131
36481
  } from "fs/promises";
36132
- import { dirname as dirname21, join as join31 } from "path";
36482
+ import { dirname as dirname21, join as join32 } from "path";
36133
36483
  var START = "// absolutejs:mobile-updates:start";
36134
36484
  var END = "// absolutejs:mobile-updates:end";
36135
36485
  var PLUGIN_START = "// absolutejs:mobile-update-plugin:start";
@@ -36299,8 +36649,8 @@ public final class AbsoluteMobileUpdateWatchdogPlugin: CAPPlugin, CAPBridgedPlug
36299
36649
  ${PLUGIN_END}
36300
36650
  `;
36301
36651
  var configureIos3 = async (config, enabled) => {
36302
- const path = join31(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36303
- const capacitorConfigPath = join31(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
36652
+ const path = join32(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36653
+ const capacitorConfigPath = join32(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
36304
36654
  let source = await readFile28(path, "utf8");
36305
36655
  const launch2 = source.indexOf("didFinishLaunchingWithOptions");
36306
36656
  const brace = launch2 < 0 ? -1 : source.indexOf("{", launch2);
@@ -36310,8 +36660,8 @@ var configureIos3 = async (config, enabled) => {
36310
36660
  ` : "";
36311
36661
  source = replaceMarkedRegion(source, START, END, launchRegion, brace < 0 ? -1 : source.indexOf(`
36312
36662
  `, brace) + 1, "Could not find a safe iOS location for mobile update recovery.");
36313
- const plugin = enabled ? iosPluginRegion(config.updates?.bootTimeoutMs ?? 20000) : "";
36314
- source = replaceMarkedRegion(source, PLUGIN_START, PLUGIN_END, plugin, source.length, "Could not find a safe iOS location for the mobile update watchdog.");
36663
+ const plugin2 = enabled ? iosPluginRegion(config.updates?.bootTimeoutMs ?? 20000) : "";
36664
+ source = replaceMarkedRegion(source, PLUGIN_START, PLUGIN_END, plugin2, source.length, "Could not find a safe iOS location for the mobile update watchdog.");
36315
36665
  const capacitorConfigSource2 = await readFile28(capacitorConfigPath, "utf8");
36316
36666
  let capacitorConfig;
36317
36667
  try {
@@ -36492,12 +36842,12 @@ var androidActivityInRoot = async (root) => {
36492
36842
  throw error;
36493
36843
  }
36494
36844
  const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
36495
- return candidate ? join31(root, candidate) : undefined;
36845
+ return candidate ? join32(root, candidate) : undefined;
36496
36846
  };
36497
36847
  var androidActivity = async (config) => {
36498
36848
  const roots = [
36499
- join31(config.nativeProjectDirectory, "android/app/src/main/java"),
36500
- join31(config.nativeProjectDirectory, "android/app/src/main/kotlin")
36849
+ join32(config.nativeProjectDirectory, "android/app/src/main/java"),
36850
+ join32(config.nativeProjectDirectory, "android/app/src/main/kotlin")
36501
36851
  ];
36502
36852
  const candidates = await Promise.all(roots.map(androidActivityInRoot));
36503
36853
  const candidate = candidates.find((value) => value !== undefined);
@@ -36601,7 +36951,7 @@ var configureAndroid3 = async (config, enabled) => {
36601
36951
  if (!packageName)
36602
36952
  throw new TypeError("Android MainActivity package declaration was not found.");
36603
36953
  const packagePath = packageName.replaceAll(".", "/");
36604
- const pluginPath = join31(config.nativeProjectDirectory, "android/app/src/main/java", packagePath, ANDROID_PLUGIN);
36954
+ const pluginPath = join32(config.nativeProjectDirectory, "android/app/src/main/java", packagePath, ANDROID_PLUGIN);
36605
36955
  const changed = await Promise.all([
36606
36956
  writeChanged(activityPath, injectAndroidActivity(activity, enabled)),
36607
36957
  enabled ? writeChanged(pluginPath, androidPluginSource(packageName, config.updates?.bootTimeoutMs ?? 20000)) : removeOwnedFile(pluginPath)
@@ -36628,7 +36978,7 @@ import {
36628
36978
  rm as rm18,
36629
36979
  writeFile as writeFile24
36630
36980
  } from "fs/promises";
36631
- import { dirname as dirname22, join as join32 } from "path";
36981
+ import { dirname as dirname22, join as join33 } from "path";
36632
36982
  var START2 = "// absolutejs:native-observability:start";
36633
36983
  var END2 = "// absolutejs:native-observability:end";
36634
36984
  var PLUGIN_START2 = "// absolutejs:native-observability-plugin:start";
@@ -36796,8 +37146,8 @@ public final class AbsoluteMobileObservabilityPlugin: CAPPlugin, CAPBridgedPlugi
36796
37146
  ${PLUGIN_END2}
36797
37147
  `;
36798
37148
  var configureIos4 = async (config, enabled) => {
36799
- const path = join32(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36800
- const capacitorConfigPath = join32(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
37149
+ const path = join33(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
37150
+ const capacitorConfigPath = join33(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
36801
37151
  let source = await readFile29(path, "utf8");
36802
37152
  if (enabled && !source.includes("import MetricKit")) {
36803
37153
  const capacitorImport = source.lastIndexOf("import Capacitor");
@@ -37057,12 +37407,12 @@ var androidActivityInRoot2 = async (root) => {
37057
37407
  throw error;
37058
37408
  }
37059
37409
  const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
37060
- return candidate ? join32(root, candidate) : undefined;
37410
+ return candidate ? join33(root, candidate) : undefined;
37061
37411
  };
37062
37412
  var androidActivity2 = async (config) => {
37063
37413
  const roots = [
37064
- join32(config.nativeProjectDirectory, "android/app/src/main/java"),
37065
- join32(config.nativeProjectDirectory, "android/app/src/main/kotlin")
37414
+ join33(config.nativeProjectDirectory, "android/app/src/main/java"),
37415
+ join33(config.nativeProjectDirectory, "android/app/src/main/kotlin")
37066
37416
  ];
37067
37417
  const candidates = await Promise.all(roots.map(androidActivityInRoot2));
37068
37418
  const candidate = candidates.find((value) => value !== undefined);
@@ -37134,7 +37484,7 @@ var configureAndroid4 = async (config, enabled) => {
37134
37484
  const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
37135
37485
  if (!packageName)
37136
37486
  throw new TypeError("Android MainActivity package declaration was not found.");
37137
- const pluginPath = join32(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN2);
37487
+ const pluginPath = join33(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN2);
37138
37488
  const changed = await Promise.all([
37139
37489
  writeChanged2(activityPath, injectAndroidActivity2(activity, enabled)),
37140
37490
  enabled ? writeChanged2(pluginPath, androidPluginSource2(packageName)) : removeOwnedFile2(pluginPath)
@@ -37154,7 +37504,7 @@ var applyAbsoluteNativeObservability = async (config, platforms = config.platfor
37154
37504
  };
37155
37505
  // src/mobile/nativeReleaseReadiness.ts
37156
37506
  import { mkdir as mkdir24, readFile as readFile30, readdir as readdir11, rename as rename21, writeFile as writeFile25 } from "fs/promises";
37157
- import { dirname as dirname23, join as join33 } from "path";
37507
+ import { dirname as dirname23, join as join34 } from "path";
37158
37508
  var START3 = "// absolutejs:release-readiness:start";
37159
37509
  var END3 = "// absolutejs:release-readiness:end";
37160
37510
  var IOS_PLUGIN_START = "// absolutejs:release-readiness-plugin:start";
@@ -37193,12 +37543,12 @@ var activityInRoot = async (root) => {
37193
37543
  throw error;
37194
37544
  }
37195
37545
  const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
37196
- return candidate ? join33(root, candidate) : undefined;
37546
+ return candidate ? join34(root, candidate) : undefined;
37197
37547
  };
37198
37548
  var activityPath = async (config) => {
37199
37549
  const roots = [
37200
- join33(config.nativeProjectDirectory, "android/app/src/main/java"),
37201
- join33(config.nativeProjectDirectory, "android/app/src/main/kotlin")
37550
+ join34(config.nativeProjectDirectory, "android/app/src/main/java"),
37551
+ join34(config.nativeProjectDirectory, "android/app/src/main/kotlin")
37202
37552
  ];
37203
37553
  const candidates = await Promise.all(roots.map(activityInRoot));
37204
37554
  const candidate = candidates.find((value) => value !== undefined);
@@ -37308,8 +37658,8 @@ var replaceIosPluginRegion = (appDelegate, existingStart, existingEnd) => {
37308
37658
  return `${appDelegate.slice(0, from)}${iosPluginRegion3}${appDelegate.slice(through)}`;
37309
37659
  };
37310
37660
  var configureIos5 = async (config) => {
37311
- const appDelegatePath = join33(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
37312
- const capacitorConfigPath = join33(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
37661
+ const appDelegatePath = join34(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
37662
+ const capacitorConfigPath = join34(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
37313
37663
  const appDelegate = await readFile30(appDelegatePath, "utf8");
37314
37664
  const existingStart = appDelegate.indexOf(IOS_PLUGIN_START);
37315
37665
  const existingEnd = appDelegate.indexOf(IOS_PLUGIN_END);
@@ -37349,7 +37699,7 @@ var configureAndroid5 = async (config) => {
37349
37699
  const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
37350
37700
  if (!packageName)
37351
37701
  throw new TypeError("Android MainActivity package declaration was not found.");
37352
- const pluginPath = join33(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN3);
37702
+ const pluginPath = join34(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN3);
37353
37703
  const changed = await Promise.all([
37354
37704
  writeChanged3(mainActivityPath, injectRegistration(activity)),
37355
37705
  writeChanged3(pluginPath, pluginSource(packageName))
@@ -38090,11 +38440,11 @@ var resolveAbsoluteHttpUrl = (target, origin) => {
38090
38440
  var createAbsoluteHttpTransport = ({
38091
38441
  fetch: fetchImpl = globalThis.fetch,
38092
38442
  origin,
38093
- runtime: runtime2
38443
+ runtime: runtime3
38094
38444
  }) => ({
38095
38445
  fetch: fetchImpl,
38096
38446
  origin: normalizeAbsoluteHttpOrigin(origin),
38097
- runtime: runtime2
38447
+ runtime: runtime3
38098
38448
  });
38099
38449
  var createWebHttpTransport = (options = {}) => {
38100
38450
  const origin = options.origin ?? globalThis.location?.origin;
@@ -38277,8 +38627,8 @@ var createCapacitor = (win) => {
38277
38627
  };
38278
38628
  const isNativePlatform = () => getPlatform() !== "web";
38279
38629
  const isPluginAvailable = (pluginName) => {
38280
- const plugin = registeredPlugins.get(pluginName);
38281
- if (plugin === null || plugin === undefined ? undefined : plugin.platforms.has(getPlatform())) {
38630
+ const plugin2 = registeredPlugins.get(pluginName);
38631
+ if (plugin2 === null || plugin2 === undefined ? undefined : plugin2.platforms.has(getPlatform())) {
38282
38632
  return true;
38283
38633
  }
38284
38634
  if (getPluginHeader(pluginName)) {
@@ -38833,12 +39183,12 @@ var drainAbsoluteMobileNativeObservability = async (manifest, fetch2, options =
38833
39183
  const config = manifest.observability;
38834
39184
  if (!config || !(options.native ?? Capacitor.isNativePlatform()))
38835
39185
  return 0;
38836
- const plugin = options.plugin ?? nativeObservability;
38837
- const pending = await plugin.pending();
39186
+ const plugin2 = options.plugin ?? nativeObservability;
39187
+ const pending = await plugin2.pending();
38838
39188
  const reports = pending.reports.slice(0, MAX_REPORTS).map(parseReport).filter((report) => report !== undefined);
38839
39189
  const discarded = reports.filter((report) => !sampled(report.id, config.sampleRate));
38840
39190
  if (discarded.length > 0)
38841
- await plugin.acknowledge({
39191
+ await plugin2.acknowledge({
38842
39192
  ids: discarded.map(({ id }) => id)
38843
39193
  });
38844
39194
  const selected = reports.filter((report) => sampled(report.id, config.sampleRate));
@@ -38858,7 +39208,7 @@ var drainAbsoluteMobileNativeObservability = async (manifest, fetch2, options =
38858
39208
  });
38859
39209
  if (!response.ok)
38860
39210
  return 0;
38861
- await plugin.acknowledge({
39211
+ await plugin2.acknowledge({
38862
39212
  ids: selected.map(({ id }) => id)
38863
39213
  });
38864
39214
  return selected.length;
@@ -44240,14 +44590,14 @@ import {
44240
44590
  stat as stat8,
44241
44591
  writeFile as writeFile26
44242
44592
  } from "fs/promises";
44243
- import { dirname as dirname25, join as join34, relative as relative23, resolve as resolve25 } from "path";
44593
+ import { dirname as dirname25, join as join35, relative as relative23, resolve as resolve25 } from "path";
44244
44594
  var UPDATE_MANIFEST_FILE = "update.json";
44245
44595
  var UPDATE_FILES_DIRECTORY = "files";
44246
44596
  var sha2565 = (value) => createHash18("sha256").update(value).digest("hex");
44247
44597
  var listFiles = async (root, directory = root) => {
44248
44598
  const entries = await readdir12(directory, { withFileTypes: true });
44249
44599
  const paths = await Promise.all(entries.map(async (entry) => {
44250
- const path = join34(directory, entry.name);
44600
+ const path = join35(directory, entry.name);
44251
44601
  if (entry.isDirectory())
44252
44602
  return listFiles(root, path);
44253
44603
  if (!entry.isFile())
@@ -44257,7 +44607,7 @@ var listFiles = async (root, directory = root) => {
44257
44607
  return paths.flat().sort((left, right) => left.localeCompare(right));
44258
44608
  };
44259
44609
  var inspectFiles = async (root, paths) => Promise.all(paths.map(async (path) => {
44260
- const source = join34(root, path);
44610
+ const source = join35(root, path);
44261
44611
  const [metadata, contents] = await Promise.all([
44262
44612
  stat8(source),
44263
44613
  readFile31(source)
@@ -44296,14 +44646,14 @@ var buildAbsoluteMobileUpdate = async (options) => {
44296
44646
  }
44297
44647
  });
44298
44648
  await mkdir25(outputRoot, { recursive: true });
44299
- const outputDirectory = join34(outputRoot, manifest.releaseId);
44300
- const staging = await mkdtemp12(join34(outputRoot, ".stage-"));
44649
+ const outputDirectory = join35(outputRoot, manifest.releaseId);
44650
+ const staging = await mkdtemp12(join35(outputRoot, ".stage-"));
44301
44651
  try {
44302
- await cp2(bundleDirectory, join34(staging, UPDATE_FILES_DIRECTORY), {
44652
+ await cp2(bundleDirectory, join35(staging, UPDATE_FILES_DIRECTORY), {
44303
44653
  force: true,
44304
44654
  recursive: true
44305
44655
  });
44306
- await writeFile26(join34(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
44656
+ await writeFile26(join35(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
44307
44657
  `);
44308
44658
  await rename22(staging, outputDirectory);
44309
44659
  } catch (error) {
@@ -44314,7 +44664,7 @@ var buildAbsoluteMobileUpdate = async (options) => {
44314
44664
  }
44315
44665
  return {
44316
44666
  manifest,
44317
- manifestPath: join34(outputDirectory, UPDATE_MANIFEST_FILE),
44667
+ manifestPath: join35(outputDirectory, UPDATE_MANIFEST_FILE),
44318
44668
  outputDirectory
44319
44669
  };
44320
44670
  };
@@ -44326,7 +44676,7 @@ var copyAbsoluteMobileUpdateFile = async (updateDirectory, path, destination) =>
44326
44676
  await mkdir25(dirname25(destination), { recursive: true });
44327
44677
  await cp2(source, destination, { force: true });
44328
44678
  };
44329
- var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile31(join34(resolve25(directory), UPDATE_MANIFEST_FILE), "utf8")));
44679
+ var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile31(join35(resolve25(directory), UPDATE_MANIFEST_FILE), "utf8")));
44330
44680
  var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
44331
44681
  const manifest = parseAbsoluteMobileUpdateManifest(manifestValue);
44332
44682
  const valid = verify("sha256", absoluteMobileUpdateSigningPayload(unsignedAbsoluteMobileUpdate(manifest)), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64"));
@@ -44851,5 +45201,5 @@ export {
44851
45201
  writeAbsoluteMobileUpdateRegistry
44852
45202
  };
44853
45203
 
44854
- //# debugId=A1067DC3426F4EF264756E2164756E21
45204
+ //# debugId=F06A772036512CCC64756E2164756E21
44855
45205
  //# sourceMappingURL=index.js.map