@absolutejs/absolute 0.20.0-beta.115 → 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;
@@ -29376,7 +29376,7 @@ var parseAbsoluteMobileBuildPageMetadata = (value) => {
29376
29376
  };
29377
29377
  // src/mobile/buildPipeline.ts
29378
29378
  import { readFile as readFile18 } from "fs/promises";
29379
- import { join as join21, resolve as resolve16 } from "path";
29379
+ import { join as join22, resolve as resolve16 } from "path";
29380
29380
  import { pathToFileURL as pathToFileURL2 } from "url";
29381
29381
 
29382
29382
  // src/mobile/buildRelease.ts
@@ -30154,7 +30154,7 @@ import {
30154
30154
  writeFile as writeFile14
30155
30155
  } from "fs/promises";
30156
30156
  import { createHash as createHash15 } from "crypto";
30157
- 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";
30158
30158
 
30159
30159
  // src/mobile/updateRuntime.ts
30160
30160
  init_deviceCapabilities();
@@ -30295,6 +30295,7 @@ var createAbsoluteMobileUpdateRuntimeDescriptor = (options) => ({
30295
30295
  },
30296
30296
  deviceCapabilities: options.deviceCapabilities,
30297
30297
  engine: options.config.engine,
30298
+ ...options.config.engine === "expo" ? { expoEmbeddedAssetsAbi: 1 } : {},
30298
30299
  format: ABSOLUTE_MOBILE_UPDATE_RUNTIME_FORMAT,
30299
30300
  shellAbi: ABSOLUTE_MOBILE_SHELL_ABI,
30300
30301
  syncSchema: options.syncSchema ?? null,
@@ -31064,6 +31065,265 @@ var absoluteExpoActivityResultRecoveryFiles = (project) => new Map([
31064
31065
  ]
31065
31066
  ]);
31066
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
+
31067
31327
  // src/mobile/expoProject.ts
31068
31328
  var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
31069
31329
  `;
@@ -31144,7 +31404,7 @@ var routeSegments = (route) => {
31144
31404
  return segment;
31145
31405
  });
31146
31406
  };
31147
- var routeFile = (project, route) => join20(project, "app", ...routeSegments(route), "index.tsx");
31407
+ var routeFile = (project, route) => join21(project, "app", ...routeSegments(route), "index.tsx");
31148
31408
  var packageDependencies = (plan) => Object.fromEntries(plan.requiredPackages.map((spec) => {
31149
31409
  const separator = spec.lastIndexOf("@");
31150
31410
  return [spec.slice(0, separator), spec.slice(separator + 1)];
@@ -31233,24 +31493,24 @@ var expoAppConfig = (config, auth, sync, devices, runtimeFingerprint) => {
31233
31493
  const devicePlugins = [
31234
31494
  ...new Set(devices.capabilities.flatMap((name) => devices.providers[name]?.plugins ?? []))
31235
31495
  ];
31236
- const configuredPlugins = devicePlugins.map((plugin) => {
31237
- if (plugin === "expo-image-picker")
31496
+ const configuredPlugins = devicePlugins.map((plugin2) => {
31497
+ if (plugin2 === "expo-image-picker")
31238
31498
  return [
31239
- plugin,
31499
+ plugin2,
31240
31500
  {
31241
31501
  cameraPermission: descriptions.NSCameraUsageDescription,
31242
31502
  microphonePermission: false,
31243
31503
  photosPermission: descriptions.NSPhotoLibraryUsageDescription
31244
31504
  }
31245
31505
  ];
31246
- if (plugin === "expo-location")
31506
+ if (plugin2 === "expo-location")
31247
31507
  return [
31248
- plugin,
31508
+ plugin2,
31249
31509
  {
31250
31510
  locationWhenInUsePermission: descriptions.NSLocationWhenInUseUsageDescription
31251
31511
  }
31252
31512
  ];
31253
- return plugin;
31513
+ return plugin2;
31254
31514
  });
31255
31515
  return {
31256
31516
  expo: {
@@ -31272,7 +31532,7 @@ var expoAppConfig = (config, auth, sync, devices, runtimeFingerprint) => {
31272
31532
  package: config.appId,
31273
31533
  permissions: requirements.androidPermissions
31274
31534
  },
31275
- experiments: { typedRoutes: true },
31535
+ experiments: { tsconfigPaths: false, typedRoutes: true },
31276
31536
  ios: {
31277
31537
  ...branding?.ios ?? {},
31278
31538
  associatedDomains: config.deepLinkHosts.map((host2) => `applinks:${host2}`),
@@ -31295,6 +31555,7 @@ var expoAppConfig = (config, auth, sync, devices, runtimeFingerprint) => {
31295
31555
  ["expo-dev-client", { launchMode: "most-recent" }],
31296
31556
  ...branding ? [branding.splashPlugin] : [],
31297
31557
  "./plugins/withAbsoluteActivityResultRecovery",
31558
+ "./plugins/withAbsoluteEmbeddedAssets",
31298
31559
  ...auth || config.updates ? ["expo-secure-store"] : [],
31299
31560
  ...sync ? [
31300
31561
  "expo-sqlite",
@@ -31859,6 +32120,7 @@ import { ActivityIndicator, BackHandler, Platform, Pressable, StyleSheet, Text,
31859
32120
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
31860
32121
  import { WebView, type WebViewMessageEvent } from 'react-native-webview';
31861
32122
  import { materializeAbsoluteWebBundle } from './webAssets';
32123
+ import { absoluteEmbeddedNativeConfig } from './AbsoluteEmbeddedAssets';
31862
32124
  import { markAbsoluteEmbeddedWebPhase, markAbsoluteEmbeddedWebReady } from './AbsoluteActivityResultRecovery';
31863
32125
  import { createExpoDevicesBridgeHost } from '@absolutejs/devices-expo/bridge';
31864
32126
  import { absoluteExpoDevices, beforeAbsoluteExpoDeviceSignOut } from './AbsoluteDevices';
@@ -31978,7 +32240,16 @@ const bridgeBootstrap = (path: string, safeAreaInsets: { bottom: number; left: n
31978
32240
  event.preventDefault();
31979
32241
  send({ format: 3, kind: 'event', event: 'navigation', path: url.pathname + url.search + url.hash });
31980
32242
  }, true);
31981
- 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);
31982
32253
  })(); true;\`;
31983
32254
  };
31984
32255
 
@@ -32023,11 +32294,18 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
32023
32294
  const canGoBack = useRef(false);
32024
32295
  const [runtimeReady, setRuntimeReady] = useState(!AUTH_ENABLED && !SYNC_ENABLED);
32025
32296
  const [devicesReady, setDevicesReady] = useState(false);
32026
- const [startupError, setStartupError] = useState<'assets' | 'devices'>();
32297
+ const [startupError, setStartupError] = useState<'assets' | 'devices' | 'content'>();
32027
32298
  const [startupRevision, setStartupRevision] = useState(0);
32028
32299
  const activeWebPath = useRef(pathname);
32029
32300
  const embeddedReadyReported = useRef(false);
32030
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]);
32031
32309
 
32032
32310
  useEffect(() => {
32033
32311
  if (!AUTH_ENABLED && !SYNC_ENABLED) return;
@@ -32063,6 +32341,7 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
32063
32341
  markAbsoluteEmbeddedWebPhase('assets-start');
32064
32342
  void materializeAbsoluteWebBundle().then(uri => {
32065
32343
  markAbsoluteEmbeddedWebPhase('assets-ready');
32344
+ embeddedReadyReported.current = false;
32066
32345
  setIndexUri(uri + '?absolutePath=' + encodeURIComponent(pathname));
32067
32346
  }).catch(error => {
32068
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')
@@ -32116,15 +32395,23 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
32116
32395
  try { return new URL(source).origin === origin; } catch { return false; }
32117
32396
  };
32118
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;
32119
32402
  const source = event.nativeEvent.data;
32120
32403
  if (new TextEncoder().encode(source).byteLength > MAX_MESSAGE_BYTES) return;
32121
32404
  let message: Record<string, unknown>;
32122
32405
  try { message = JSON.parse(source); } catch { return; }
32123
32406
  if (message.format !== BRIDGE_FORMAT || typeof message.path !== 'string' || !message.path.startsWith('/') || message.path.startsWith('//')) return;
32124
- 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')) {
32125
32412
  const target = new URL(message.path, PRODUCTION_ORIGIN);
32126
32413
  if (target.origin !== PRODUCTION_ORIGIN) return;
32127
- if (message.event === 'ready' && !DEV_ORIGIN && !embeddedReadyReported.current) {
32414
+ if (message.event === 'shell-rendered' && !DEV_ORIGIN && !embeddedReadyReported.current) {
32128
32415
  embeddedReadyReported.current = true;
32129
32416
  markAbsoluteEmbeddedWebReady();
32130
32417
  }
@@ -32178,12 +32465,17 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
32178
32465
  </View>;
32179
32466
  if (!webSource || !runtimeReady || !devicesReady) return <View style={styles.loading}><ActivityIndicator /></View>;
32180
32467
  return <WebView
32181
- allowFileAccess
32182
- allowFileAccessFromFileURLs
32468
+ nativeConfig={!DEV_ORIGIN ? absoluteEmbeddedNativeConfig : undefined}
32469
+ allowFileAccess={Platform.OS !== 'android'}
32470
+ allowFileAccessFromFileURLs={Platform.OS !== 'android'}
32183
32471
  allowUniversalAccessFromFileURLs={false}
32472
+ originWhitelist={DEV_ORIGIN ? [DEV_ORIGIN] : [Platform.OS === 'android' ? 'https://appassets.androidplatform.net' : 'file://*']}
32184
32473
  allowingReadAccessToURL={webSource.uri.slice(0, webSource.uri.lastIndexOf('/') + 1)}
32185
32474
  injectedJavaScriptBeforeContentLoaded={bridgeBootstrap(pathname, safeAreaInsets)}
32186
32475
  onMessage={onMessage}
32476
+ onError={() => setStartupError('content')}
32477
+ onRenderProcessGone={() => setStartupError('content')}
32478
+ onContentProcessDidTerminate={() => setStartupError('content')}
32187
32479
  onNavigationStateChange={state => {
32188
32480
  canGoBack.current = state.canGoBack;
32189
32481
  if (!DEV_ORIGIN || !hasOrigin(state.url, DEV_ORIGIN)) return;
@@ -32191,8 +32483,8 @@ export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
32191
32483
  activeWebPath.current = route.pathname + route.search + route.hash;
32192
32484
  }}
32193
32485
  onShouldStartLoadWithRequest={request => {
32194
- if (request.url.startsWith('file:') || hasOrigin(request.url, PRODUCTION_ORIGIN) || DEV_ORIGIN && hasOrigin(request.url, DEV_ORIGIN)) return true;
32195
- 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);
32196
32488
  return false;
32197
32489
  }}
32198
32490
  ref={webView}
@@ -32395,8 +32687,8 @@ const styles = StyleSheet.create({
32395
32687
  error: { color: '#b91c1c', fontSize: 16, textAlign: 'center' }
32396
32688
  });
32397
32689
  `;
32398
- var nativeWrapperSource = (wrapper, module, runtime2, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative3(dirname13(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
32399
- 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, ""))};
32400
32692
 
32401
32693
  export const ErrorBoundary = createAbsoluteNativeRouteErrorBoundary(${JSON.stringify(route)});
32402
32694
  export default createAbsoluteNativeRoute(ApplicationNativeRoute, ${JSON.stringify(route)});
@@ -32465,7 +32757,7 @@ var pruneManagedFiles = async (paths) => {
32465
32757
  return removed.filter(Boolean).length;
32466
32758
  };
32467
32759
  var pruneStaleManagedExpoRoutes = async (project, expected) => {
32468
- const appDirectory = join20(project, "app");
32760
+ const appDirectory = join21(project, "app");
32469
32761
  if (!await exists6(appDirectory))
32470
32762
  return 0;
32471
32763
  const files = await walkFiles(appDirectory);
@@ -32513,7 +32805,7 @@ var writeAbsoluteExpoProject = async (config, options) => {
32513
32805
  if (missing) {
32514
32806
  throw new TypeError(`Expo native route ${missing.route} references missing module ${missing.module}.`);
32515
32807
  }
32516
- const marker = join20(project, EXPO_PROJECT_MARKER);
32808
+ const marker = join21(project, EXPO_PROJECT_MARKER);
32517
32809
  if (await exists6(project) && !await exists6(marker)) {
32518
32810
  const entries = await readdir5(project);
32519
32811
  if (entries.length > 0 && !options.force) {
@@ -32526,7 +32818,7 @@ var writeAbsoluteExpoProject = async (config, options) => {
32526
32818
  const authEnabled = Boolean(auth);
32527
32819
  const files = new Map([
32528
32820
  [
32529
- join20(project, ".gitignore"),
32821
+ join21(project, ".gitignore"),
32530
32822
  `.expo/
32531
32823
  android/
32532
32824
  ios/
@@ -32534,80 +32826,82 @@ node_modules/
32534
32826
  `
32535
32827
  ],
32536
32828
  [
32537
- join20(project, "app.json"),
32829
+ join21(project, "app.json"),
32538
32830
  jsonSource(expoAppConfig(config, authEnabled, syncEnabled, devices, runtimeFingerprint))
32539
32831
  ],
32540
- [join20(project, "app.config.js"), expoDynamicAppConfig],
32832
+ [join21(project, "app.config.js"), expoDynamicAppConfig],
32541
32833
  [
32542
- join20(project, "package.json"),
32834
+ join21(project, "package.json"),
32543
32835
  jsonSource(expoPackage(authEnabled, config.branding !== undefined, syncEnabled, devices, config.updates !== undefined))
32544
32836
  ],
32545
- [join20(project, "metro.config.js"), metroConfig(projectRoot)],
32837
+ [join21(project, "metro.config.js"), metroConfig(projectRoot)],
32546
32838
  [
32547
- join20(project, "plugins", "withAbsoluteDevelopmentCa.js"),
32839
+ join21(project, "plugins", "withAbsoluteDevelopmentCa.js"),
32548
32840
  expoDevelopmentCaPlugin
32549
32841
  ],
32550
32842
  [
32551
- join20(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
32843
+ join21(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
32552
32844
  expoActivityResultRecoveryPlugin
32553
32845
  ],
32554
32846
  [
32555
- join20(project, "tsconfig.json"),
32847
+ join21(project, "tsconfig.json"),
32556
32848
  jsonSource(expoTsConfig(projectRoot, project, authEnabled, syncEnabled))
32557
32849
  ],
32558
32850
  [
32559
- join20(project, "app", "_layout.tsx"),
32851
+ join21(project, "app", "_layout.tsx"),
32560
32852
  layoutSource(authEnabled, syncEnabled, config.updates !== undefined, config.observability !== undefined)
32561
32853
  ],
32562
32854
  [
32563
- join20(project, "app", "__absolute", "native", "index.tsx"),
32855
+ join21(project, "app", "__absolute", "native", "index.tsx"),
32564
32856
  nativeDiagnosticSource
32565
32857
  ],
32566
32858
  [
32567
- join20(project, "src", "generated", "AbsoluteDevices.ts"),
32859
+ join21(project, "src", "generated", "AbsoluteDevices.ts"),
32568
32860
  devicesRuntimeSource(config, devices, authEnabled)
32569
32861
  ],
32570
32862
  [
32571
- join20(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
32863
+ join21(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
32572
32864
  nativeRouteRuntimeSource(authEnabled)
32573
32865
  ],
32574
32866
  [
32575
- join20(project, "src", "generated", "AbsoluteWebHost.tsx"),
32867
+ join21(project, "src", "generated", "AbsoluteWebHost.tsx"),
32576
32868
  webHostSource(config, auth, syncEnabled)
32577
32869
  ]
32578
32870
  ]);
32579
32871
  for (const [path, source] of absoluteExpoActivityResultRecoveryFiles(project))
32580
32872
  files.set(path, source);
32873
+ for (const [path, source] of absoluteExpoEmbeddedAssetsFiles(project))
32874
+ files.set(path, source);
32581
32875
  if (config.observability) {
32582
32876
  for (const [path, source] of absoluteExpoNativeObservabilityFiles(project))
32583
32877
  files.set(path, source);
32584
32878
  }
32585
32879
  if (config.updates) {
32586
- files.set(join20(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
32880
+ files.set(join21(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
32587
32881
  }
32588
32882
  const expoCodeSigning = config.updates?.expoCodeSigning;
32589
32883
  if (expoCodeSigning)
32590
- files.set(join20(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
32884
+ files.set(join21(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
32591
32885
  if (auth) {
32592
- 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));
32593
32887
  }
32594
32888
  if (syncSchema) {
32595
- files.set(join20(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
32889
+ files.set(join21(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
32596
32890
  }
32597
- const webAssetsPath = join20(project, "src", "generated", "webAssets.ts");
32891
+ const webAssetsPath = join21(project, "src", "generated", "webAssets.ts");
32598
32892
  if (!await exists6(webAssetsPath)) {
32599
32893
  files.set(webAssetsPath, emptyWebAssetsSource);
32600
32894
  }
32601
32895
  if (!config.expoNativeRoutes["/"]) {
32602
- files.set(join20(project, "app", "index.tsx"), webRouteSource);
32896
+ files.set(join21(project, "app", "index.tsx"), webRouteSource);
32603
32897
  }
32604
- files.set(join20(project, "app", "[...absolute].tsx"), catchAllRouteSource);
32605
- 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");
32606
32900
  for (const [route, module] of routeModules) {
32607
- const wrapper = route === "/" ? join20(project, "app", "index.tsx") : routeFile(project, route);
32901
+ const wrapper = route === "/" ? join21(project, "app", "index.tsx") : routeFile(project, route);
32608
32902
  files.set(wrapper, nativeWrapperSource(wrapper, module, nativeRouteRuntime, route));
32609
32903
  }
32610
- 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}`))));
32611
32905
  const removedObservability = config.observability ? 0 : await pruneManagedFiles(absoluteExpoNativeObservabilityPaths(project));
32612
32906
  const changes = await Promise.all([...files].map(([path, source]) => writeManagedFile(path, source, true)));
32613
32907
  await writeAbsoluteExpoBrandingInputs(config, projectRoot);
@@ -32617,7 +32911,7 @@ node_modules/
32617
32911
  var walkFiles = async (root, directory = root) => {
32618
32912
  const entries = await readdir5(directory, { withFileTypes: true });
32619
32913
  const nested = await Promise.all(entries.map((entry) => {
32620
- const path = join20(directory, entry.name);
32914
+ const path = join21(directory, entry.name);
32621
32915
  if (entry.isDirectory())
32622
32916
  return walkFiles(root, path);
32623
32917
  if (entry.isFile())
@@ -32650,13 +32944,16 @@ var installStagedDirectory = async (staging, destination) => {
32650
32944
  throw error;
32651
32945
  }
32652
32946
  };
32653
- 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';
32654
32948
  import { Directory, File, Paths } from 'expo-file-system';
32655
32949
  import { copyAsync as copyLegacyAsync } from 'expo-file-system/legacy';
32950
+ import { registerAbsoluteEmbeddedBundle } from './AbsoluteEmbeddedAssets';
32656
32951
 
32657
32952
  ${nativeDataManifestTypeSource}
32658
32953
  declare const require: (path: string) => number;
32659
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)};
32660
32957
  export const ABSOLUTE_MOBILE_MANIFEST: AbsoluteMobileManifest = ${JSON.stringify(manifest)};
32661
32958
  const ARCHIVE_MODULE = require(${JSON.stringify(archiveAsset)});
32662
32959
  const ASSETS = [
@@ -32673,10 +32970,12 @@ export const materializeAbsoluteWebBundle = async () => {
32673
32970
  let archive: File;
32674
32971
  try { archive = new File(root, '.absolutejs-bundle.absasset'); }
32675
32972
  catch { throw new Error('assets-destination-failed'); }
32973
+ if (archive.exists && (archive.size !== ARCHIVE_LENGTH || archive.md5 !== ARCHIVE_MD5)) archive.delete();
32676
32974
  if (!archive.exists) {
32677
32975
  let asset: Asset;
32678
32976
  try { asset = Asset.fromModule(ARCHIVE_MODULE); }
32679
32977
  catch { throw new Error('assets-module-failed'); }
32978
+ if (asset.type !== 'absasset' || asset.hash !== ARCHIVE_MD5) throw new Error('assets-identity-failed');
32680
32979
  try { if (!asset.localUri) asset = await asset.downloadAsync(); }
32681
32980
  catch { throw new Error('assets-download-failed'); }
32682
32981
  if (!asset.localUri) throw new Error('assets-download-failed');
@@ -32689,9 +32988,16 @@ export const materializeAbsoluteWebBundle = async () => {
32689
32988
  catch { throw new Error('assets-copy-failed'); }
32690
32989
  }
32691
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
+ }
32692
32997
  let contents: Uint8Array;
32693
32998
  try { contents = await archive.bytes(); }
32694
32999
  catch { throw new Error('assets-read-failed'); }
33000
+ if (contents.byteLength !== ARCHIVE_LENGTH) throw new Error('assets-integrity-failed');
32695
33001
  for (const entry of ASSETS) {
32696
33002
  const parts = entry.path.split('/');
32697
33003
  const name = parts.pop();
@@ -32705,27 +33011,28 @@ export const materializeAbsoluteWebBundle = async () => {
32705
33011
  let destination: File;
32706
33012
  try {
32707
33013
  destination = new File(directory, name);
32708
- if (destination.exists && destination.size === entry.length) continue;
33014
+ if (destination.exists && destination.size === entry.length && destination.md5 === entry.md5) continue;
32709
33015
  if (destination.exists) destination.delete();
32710
33016
  } catch { throw new Error('assets-destination-failed'); }
32711
33017
  try { destination.write(contents.slice(entry.offset, entry.offset + entry.length)); }
32712
33018
  catch { throw new Error('assets-write-failed'); }
33019
+ if (destination.size !== entry.length || destination.md5 !== entry.md5) throw new Error('assets-integrity-failed');
32713
33020
  }
32714
33021
  try { archive.delete(); }
32715
33022
  catch { throw new Error('assets-finalize-failed'); }
32716
33023
 
32717
- 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); }
32718
33025
  catch { throw new Error('assets-finalize-failed'); }
32719
33026
  };
32720
33027
  `;
32721
33028
  var syncAbsoluteExpoWebAssets = async (config) => {
32722
33029
  if (config.engine !== "expo")
32723
33030
  throw new TypeError("Expo asset sync requires mobile.engine: expo.");
32724
- const marker = join20(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
33031
+ const marker = join21(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
32725
33032
  if (!await exists6(marker)) {
32726
33033
  throw new TypeError("Expo asset sync requires an AbsoluteJS-managed Expo project. Run mobile init first.");
32727
33034
  }
32728
- const manifestPath = join20(config.bundleDirectory, "absolute-mobile-manifest.json");
33035
+ const manifestPath = join21(config.bundleDirectory, "absolute-mobile-manifest.json");
32729
33036
  const manifest = JSON.parse(await readFile17(manifestPath, "utf8"));
32730
33037
  const nativeDataManifest = expoNativeDataManifest(manifest);
32731
33038
  const { appBuild } = nativeDataManifest;
@@ -32739,16 +33046,18 @@ var syncAbsoluteExpoWebAssets = async (config) => {
32739
33046
  bundleHash.update("\x00");
32740
33047
  });
32741
33048
  const bundleId = `amexpo_${bundleHash.digest("hex")}`;
32742
- const destination = join20(config.nativeProjectDirectory, "assets", "absolute");
33049
+ const destination = join21(config.nativeProjectDirectory, "assets", "absolute");
32743
33050
  await mkdir14(dirname13(destination), { recursive: true });
32744
- const staging = await mkdtemp9(join20(dirname13(destination), `.${basename6(destination)}.stage-`));
33051
+ const staging = await mkdtemp9(join21(dirname13(destination), `.${basename6(destination)}.stage-`));
32745
33052
  let assets;
32746
33053
  let archiveAsset;
33054
+ let archiveMd5;
32747
33055
  try {
32748
33056
  let offset = 0;
32749
33057
  assets = filesWithContents.map(({ contents, file }) => {
32750
33058
  const entry = {
32751
33059
  length: contents.byteLength,
33060
+ md5: createHash15("md5").update(contents).digest("hex"),
32752
33061
  offset,
32753
33062
  path: relative13(config.bundleDirectory, file).replaceAll("\\", "/")
32754
33063
  };
@@ -32756,15 +33065,17 @@ var syncAbsoluteExpoWebAssets = async (config) => {
32756
33065
  return entry;
32757
33066
  });
32758
33067
  const name = `bundle${EXPO_ASSET_EXTENSION}`;
32759
- await writeFile14(join20(staging, name), Buffer.concat(filesWithContents.map(({ contents }) => contents)));
32760
- 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));
32761
33072
  await installStagedDirectory(staging, destination);
32762
33073
  } catch (error) {
32763
33074
  await rm13(staging, { force: true, recursive: true });
32764
33075
  throw error;
32765
33076
  }
32766
- const generated = join20(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
32767
- 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);
32768
33079
  return { appBuild, assets: assets.length, bundleId, path: destination };
32769
33080
  };
32770
33081
 
@@ -32804,9 +33115,9 @@ var loadServerApp = async (producerPath) => {
32804
33115
  var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
32805
33116
  const buildDirectory = resolve16(options.buildDirectory);
32806
33117
  const mobile = normalizeAbsoluteMobileConfig(options.mobile, options.projectRoot);
32807
- const root = join21(buildDirectory, ".absolutejs", "mobile-compatibility");
33118
+ const root = join22(buildDirectory, ".absolutejs", "mobile-compatibility");
32808
33119
  const [manifestSource, previous] = await Promise.all([
32809
- readFile18(join21(buildDirectory, "manifest.json"), "utf8"),
33120
+ readFile18(join22(buildDirectory, "manifest.json"), "utf8"),
32810
33121
  readAbsoluteMobileMaterializedReleases(root)
32811
33122
  ]);
32812
33123
  const manifest = JSON.parse(manifestSource);
@@ -33134,7 +33445,7 @@ var parseRequest = (value) => {
33134
33445
  throw new TypeError("Expo bridge HTTP method cannot contain a body.");
33135
33446
  if (!isRecord10(value.params.headers))
33136
33447
  throw new TypeError("Expo bridge HTTP headers must be an object.");
33137
- 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-")));
33138
33449
  if (!headersAllowed) {
33139
33450
  throw new TypeError("Expo bridge HTTP header is not allowed.");
33140
33451
  }
@@ -33383,7 +33694,7 @@ var parseAbsoluteAndroidAccessibilityHierarchy = (source) => [...source.matchAll
33383
33694
  // src/mobile/expoNativeWatcher.ts
33384
33695
  import { watch as watch2 } from "fs";
33385
33696
  import { access as access15, readdir as readdir6, readFile as readFile19 } from "fs/promises";
33386
- 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";
33387
33698
  import { createHash as createHash16 } from "crypto";
33388
33699
  var NATIVE_CHANGE_DEBOUNCE_MS2 = 500;
33389
33700
  var ROOT_NATIVE_INPUTS2 = new Set([
@@ -33404,7 +33715,7 @@ var filesIn = async (directory, prefix) => {
33404
33715
  return [];
33405
33716
  const entries = await readdir6(directory, { withFileTypes: true });
33406
33717
  const nested = await Promise.all(entries.map((entry) => {
33407
- const path = join22(directory, entry.name);
33718
+ const path = join23(directory, entry.name);
33408
33719
  const name = `${prefix}/${entry.name}`;
33409
33720
  if (entry.isDirectory())
33410
33721
  return filesIn(path, name);
@@ -33415,10 +33726,10 @@ var filesIn = async (directory, prefix) => {
33415
33726
  var fingerprintAbsoluteExpoNativeInputs = async (options) => {
33416
33727
  const hash = createHash16("sha256");
33417
33728
  const rootFiles = await Promise.all([...ROOT_NATIVE_INPUTS2].sort().map(async (name) => {
33418
- const path = join22(options.projectRoot, name);
33729
+ const path = join23(options.projectRoot, name);
33419
33730
  return await exists8(path) ? [{ name: `root/${name}`, path }] : [];
33420
33731
  }));
33421
- 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)));
33422
33733
  const files = [...rootFiles.flat(), ...nativeFiles.flat()].sort((left, right) => left.name.localeCompare(right.name));
33423
33734
  const contents = await Promise.all(files.map(({ path }) => readFile19(path)));
33424
33735
  files.forEach(({ name }, index) => {
@@ -33489,14 +33800,14 @@ var createAbsoluteExpoNativeWatcher = async (options) => {
33489
33800
  }
33490
33801
  };
33491
33802
  const nativeDirectories = (await Promise.all(EXPO_NATIVE_DIRECTORIES.map(async (name) => {
33492
- const directory = join22(options.expoProjectDirectory, name);
33803
+ const directory = join23(options.expoProjectDirectory, name);
33493
33804
  return await exists8(directory) ? [directory] : [];
33494
33805
  }))).flat();
33495
33806
  nativeDirectories.forEach((directory) => {
33496
33807
  watchers.push(watch2(directory, { recursive: true }, (_event, filename) => {
33497
33808
  if (!filename)
33498
33809
  return;
33499
- record(relative15(options.expoProjectDirectory, join22(directory, String(filename))), false);
33810
+ record(relative15(options.expoProjectDirectory, join23(directory, String(filename))), false);
33500
33811
  }));
33501
33812
  });
33502
33813
  watchers.push(watch2(options.projectRoot, (_event, filename) => {
@@ -33512,7 +33823,7 @@ var createAbsoluteExpoNativeWatcher = async (options) => {
33512
33823
  };
33513
33824
  // src/mobile/expoUpdate.ts
33514
33825
  import { access as access16, mkdir as mkdir16, readFile as readFile20, writeFile as writeFile16 } from "fs/promises";
33515
- 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";
33516
33827
  var ABSOLUTE_EXPO_UPDATE_DESCRIPTOR = "_absolute/expo-update.json";
33517
33828
  var ABSOLUTE_EXPO_UPDATE_FORMAT = 1;
33518
33829
  var object4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -33578,7 +33889,7 @@ var parseAbsoluteExpoUpdateDescriptor = (value) => {
33578
33889
  };
33579
33890
  };
33580
33891
  var finalizeAbsoluteExpoUpdateExport = async (options) => {
33581
- 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"));
33582
33893
  if (!object4(metadata) || !object4(metadata.fileMetadata))
33583
33894
  throw new TypeError("Expo export metadata.json is invalid.");
33584
33895
  const descriptor = parseAbsoluteExpoUpdateDescriptor({
@@ -33589,10 +33900,10 @@ var finalizeAbsoluteExpoUpdateExport = async (options) => {
33589
33900
  runtimeVersion: options.runtimeVersion
33590
33901
  });
33591
33902
  const referenced = Object.values(descriptor.platforms).flatMap((entry) => entry ? [entry.launchAsset, ...entry.assets] : []);
33592
- 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(() => {
33593
33904
  throw new TypeError(`Expo export metadata references missing asset ${path}.`);
33594
33905
  })));
33595
- const destination = join23(options.exportDirectory, ABSOLUTE_EXPO_UPDATE_DESCRIPTOR);
33906
+ const destination = join24(options.exportDirectory, ABSOLUTE_EXPO_UPDATE_DESCRIPTOR);
33596
33907
  await mkdir16(dirname15(destination), { recursive: true });
33597
33908
  await writeFile16(destination, `${JSON.stringify(descriptor, null, "\t")}
33598
33909
  `);
@@ -33614,7 +33925,7 @@ import {
33614
33925
  stat as stat7,
33615
33926
  writeFile as writeFile19
33616
33927
  } from "fs/promises";
33617
- 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";
33618
33929
 
33619
33930
  // src/mobile/certificationVerification.ts
33620
33931
  import { access as access17, mkdir as mkdir17, readFile as readFile21, stat as stat6, writeFile as writeFile17 } from "fs/promises";
@@ -33729,7 +34040,7 @@ import {
33729
34040
  rm as rm14,
33730
34041
  writeFile as writeFile18
33731
34042
  } from "fs/promises";
33732
- 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";
33733
34044
  var ABSOLUTE_MOBILE_RELEASE_CERTIFICATION_FORMAT = 1;
33734
34045
  var CERTIFICATION_PREFIX = "amobile_cert_";
33735
34046
  var SHA256 = /^[a-f0-9]{64}$/u;
@@ -33773,7 +34084,7 @@ var resolveEvidencePath = async (projectRoot, requested) => {
33773
34084
  throw new TypeError("Mobile certification evidence must remain inside the project.");
33774
34085
  if (basename8(selected) === "report.json")
33775
34086
  return selected;
33776
- const report = join24(selected, "report.json");
34087
+ const report = join25(selected, "report.json");
33777
34088
  if (!await exists9(report))
33778
34089
  throw new TypeError(`Mobile certification evidence does not contain report.json: ${requested}`);
33779
34090
  return report;
@@ -34038,7 +34349,7 @@ var readAbsoluteMobileReleaseCertification = async (projectRoot, requested) => {
34038
34349
  const selected = resolve19(projectRoot, requested);
34039
34350
  if (!inside4(projectRoot, selected))
34040
34351
  throw new TypeError("Mobile release certification must remain inside the project.");
34041
- const path = basename8(selected) === "certification.json" ? selected : join24(selected, "certification.json");
34352
+ const path = basename8(selected) === "certification.json" ? selected : join25(selected, "certification.json");
34042
34353
  const value = JSON.parse(await readFile22(path, "utf8"));
34043
34354
  return { certification: parseCertification(value), path };
34044
34355
  };
@@ -34085,15 +34396,15 @@ var verifyAbsoluteMobileReleaseCertification = (certification, release, requirem
34085
34396
  };
34086
34397
  var writeAbsoluteMobileReleaseCertification = async (projectRoot, certification, outputDirectory) => {
34087
34398
  const root = resolve19(projectRoot);
34088
- 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));
34089
34400
  if (!inside4(root, parent))
34090
34401
  throw new TypeError("Mobile certification output must remain inside the project.");
34091
34402
  await mkdir18(parent, { recursive: true });
34092
- const destination = join24(parent, certification.certificationId);
34403
+ const destination = join25(parent, certification.certificationId);
34093
34404
  const paths = {
34094
34405
  directory: destination,
34095
- jsonPath: join24(destination, "certification.json"),
34096
- markdownPath: join24(destination, "certification.md")
34406
+ jsonPath: join25(destination, "certification.json"),
34407
+ markdownPath: join25(destination, "certification.md")
34097
34408
  };
34098
34409
  const json = serializeAbsoluteMobileReleaseCertification(certification);
34099
34410
  const markdown = renderAbsoluteMobileReleaseCertification(certification);
@@ -34109,13 +34420,13 @@ var writeAbsoluteMobileReleaseCertification = async (projectRoot, certification,
34109
34420
  await verifyExisting();
34110
34421
  return paths;
34111
34422
  }
34112
- const staging = await mkdtemp10(join24(parent, ".certification-"));
34423
+ const staging = await mkdtemp10(join25(parent, ".certification-"));
34113
34424
  try {
34114
34425
  await Promise.all([
34115
- writeFile18(join24(staging, "certification.json"), json, {
34426
+ writeFile18(join25(staging, "certification.json"), json, {
34116
34427
  flag: "wx"
34117
34428
  }),
34118
- writeFile18(join24(staging, "certification.md"), markdown, {
34429
+ writeFile18(join25(staging, "certification.md"), markdown, {
34119
34430
  flag: "wx"
34120
34431
  })
34121
34432
  ]);
@@ -34347,7 +34658,7 @@ var findFiles = async (root, name) => {
34347
34658
  visited += 1;
34348
34659
  if (visited > MAX_SEARCH_FILES)
34349
34660
  throw new TypeError("Downloaded GitHub artifact contains too many files.");
34350
- const path = join25(directory, entry.name);
34661
+ const path = join26(directory, entry.name);
34351
34662
  if (entry.isDirectory()) {
34352
34663
  await walk(path);
34353
34664
  return;
@@ -34462,9 +34773,9 @@ var auditAbsoluteMobileCiPromotion = async (options) => {
34462
34773
  if (await access19(output).then(() => true).catch(() => false))
34463
34774
  throw new TypeError(`Mobile CI audit output already exists: ${output}`);
34464
34775
  await mkdir19(dirname17(output), { recursive: true });
34465
- const staging = await mkdtemp11(join25(dirname17(output), ".promotion-audit-"));
34776
+ const staging = await mkdtemp11(join26(dirname17(output), ".promotion-audit-"));
34466
34777
  try {
34467
- const evidenceRoot = join25(staging, "promotion-evidence");
34778
+ const evidenceRoot = join26(staging, "promotion-evidence");
34468
34779
  await mkdir19(evidenceRoot);
34469
34780
  await requireCommand(runner, [
34470
34781
  "gh",
@@ -34495,7 +34806,7 @@ var auditAbsoluteMobileCiPromotion = async (options) => {
34495
34806
  if (context && options.sourceRunId && context.sourceRunId !== sourceRunId)
34496
34807
  throw new TypeError("Requested source run does not match promotion context.");
34497
34808
  const sourceArtifact = context?.sourceArtifact ?? `absolute-mobile-${platform3}`;
34498
- const sourceRoot = join25(staging, "source-release");
34809
+ const sourceRoot = join26(staging, "source-release");
34499
34810
  await mkdir19(sourceRoot);
34500
34811
  await requireCommand(runner, [
34501
34812
  "gh",
@@ -34579,9 +34890,9 @@ var auditAbsoluteMobileCiPromotion = async (options) => {
34579
34890
  verifiedAt: new Date().toISOString()
34580
34891
  };
34581
34892
  await Promise.all([
34582
- writeFile19(join25(staging, "audit.json"), `${JSON.stringify(audit, null, 2)}
34893
+ writeFile19(join26(staging, "audit.json"), `${JSON.stringify(audit, null, 2)}
34583
34894
  `, { mode: 384 }),
34584
- writeFile19(join25(staging, "audit.md"), renderAuditMarkdown(audit), {
34895
+ writeFile19(join26(staging, "audit.md"), renderAuditMarkdown(audit), {
34585
34896
  mode: 384
34586
34897
  })
34587
34898
  ]);
@@ -34604,7 +34915,7 @@ import {
34604
34915
  rename as rename16,
34605
34916
  rm as rm16
34606
34917
  } from "fs/promises";
34607
- 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";
34608
34919
  import { randomUUID as randomUUID5 } from "crypto";
34609
34920
  var ABSOLUTE_MOBILE_CI_PROMOTION_OPERATION_FORMAT = 1;
34610
34921
  var MAX_OPERATION_BYTES = 65536;
@@ -34670,8 +34981,8 @@ var runId2 = (value, label) => {
34670
34981
  return parsed;
34671
34982
  };
34672
34983
  var nullableRunId = (value, label) => value === null ? null : runId2(value, label);
34673
- var operationRoot = (projectRoot) => join26(resolve21(projectRoot), ".absolutejs", "mobile-ci", "promotions");
34674
- 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");
34675
34986
  var operationPhase = (value) => {
34676
34987
  const phase = PHASES.find((candidate) => candidate === value);
34677
34988
  if (!phase)
@@ -34742,7 +35053,7 @@ var writeSynced = async (path, source) => {
34742
35053
  };
34743
35054
  var atomicWrite = async (path, source, exclusive) => {
34744
35055
  await mkdir20(dirname18(path), { recursive: true });
34745
- const temporary = join26(dirname18(path), `.operation-${randomUUID5()}.tmp`);
35056
+ const temporary = join27(dirname18(path), `.operation-${randomUUID5()}.tmp`);
34746
35057
  try {
34747
35058
  await writeSynced(temporary, source);
34748
35059
  if (exclusive)
@@ -35644,7 +35955,7 @@ init_mobilePreview();
35644
35955
 
35645
35956
  // src/mobile/nativeDeepLinks.ts
35646
35957
  import { readFile as readFile26, rename as rename17, writeFile as writeFile21 } from "fs/promises";
35647
- import { join as join29 } from "path";
35958
+ import { join as join30 } from "path";
35648
35959
  var START_MARKER = "<!-- absolutejs:deep-links:start -->";
35649
35960
  var END_MARKER = "<!-- absolutejs:deep-links:end -->";
35650
35961
  var IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements";
@@ -35701,7 +36012,7 @@ ${hosts}
35701
36012
  `;
35702
36013
  };
35703
36014
  var configureAndroid = async (config) => {
35704
- const path = join29(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
36015
+ const path = join30(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
35705
36016
  const source = await readFile26(path, "utf8");
35706
36017
  const mainActivity = source.indexOf('android:name=".MainActivity"');
35707
36018
  if (mainActivity === NOT_FOUND) {
@@ -35727,7 +36038,7 @@ var iosSchemeRegion = (scheme) => ` ${START_MARKER}
35727
36038
  ${END_MARKER}
35728
36039
  `;
35729
36040
  var configureIosInfo = async (config) => {
35730
- const path = join29(config.nativeProjectDirectory, "ios/App/App/Info.plist");
36041
+ const path = join30(config.nativeProjectDirectory, "ios/App/App/Info.plist");
35731
36042
  const source = await readFile26(path, "utf8");
35732
36043
  const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
35733
36044
  ${END_MARKER}
@@ -35751,7 +36062,7 @@ ${domains}
35751
36062
  `;
35752
36063
  };
35753
36064
  var configureIosEntitlements = async (config) => {
35754
- const path = join29(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
36065
+ const path = join30(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
35755
36066
  let current = "";
35756
36067
  try {
35757
36068
  current = await readFile26(path, "utf8");
@@ -35769,7 +36080,7 @@ var configureIosEntitlements = async (config) => {
35769
36080
  return true;
35770
36081
  };
35771
36082
  var configureIosProject = async (config) => {
35772
- const path = join29(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
36083
+ const path = join30(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
35773
36084
  const source = await readFile26(path, "utf8");
35774
36085
  const declarations = [
35775
36086
  ...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
@@ -35810,7 +36121,7 @@ var applyAbsoluteNativeDeepLinks = async (config, platforms = config.platforms)
35810
36121
  // src/mobile/nativeDeviceCapabilities.ts
35811
36122
  init_deviceCapabilities();
35812
36123
  import { readFile as readFile27, rename as rename18, writeFile as writeFile22 } from "fs/promises";
35813
- import { join as join30 } from "path";
36124
+ import { join as join31 } from "path";
35814
36125
  var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->";
35815
36126
  var END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->";
35816
36127
  var NOT_FOUND2 = -1;
@@ -35960,7 +36271,7 @@ var writeIosPrivacyManifest = async (path, current, source) => {
35960
36271
  var configureIosPrivacyProject = async (config, requirements) => {
35961
36272
  if (requirements.iosPrivacyAccessedApis.length === 0)
35962
36273
  return false;
35963
- const projectPath3 = join30(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
36274
+ const projectPath3 = join31(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
35964
36275
  const project = await readFile27(projectPath3, "utf8");
35965
36276
  return writeChangedFile2(projectPath3, addIosPrivacyProjectReference(project));
35966
36277
  };
@@ -36013,7 +36324,7 @@ ${next.slice(index)}`;
36013
36324
  return next;
36014
36325
  };
36015
36326
  var configureIos2 = async (config, plan) => {
36016
- const path = join30(config.nativeProjectDirectory, "ios/App/App/Info.plist");
36327
+ const path = join31(config.nativeProjectDirectory, "ios/App/App/Info.plist");
36017
36328
  const source = await readFile27(path, "utf8");
36018
36329
  const requirements = absoluteDeviceNativeRequirements(plan);
36019
36330
  const existingSystemBars = source.match(/<key>UIViewControllerBasedStatusBarAppearance<\/key>\s*<(true|false)\s*\/>/u);
@@ -36034,7 +36345,7 @@ ${content}
36034
36345
  ${END_MARKER2}
36035
36346
  ` : "";
36036
36347
  const infoChanged = await writeChangedFile2(path, managed(source, region, source.lastIndexOf("</dict>")));
36037
- const privacyPath = join30(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
36348
+ const privacyPath = join31(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
36038
36349
  const privacyCurrent = await optionalSource(privacyPath);
36039
36350
  const privacySource = privacyManifestSource(privacyCurrent, requirements);
36040
36351
  const [privacyChanged, projectChanged, pushChanged] = await Promise.all([
@@ -36045,7 +36356,7 @@ ${content}
36045
36356
  return infoChanged || privacyChanged || projectChanged || pushChanged;
36046
36357
  };
36047
36358
  var configureIosPushNotifications = async (config, enabled) => {
36048
- const entitlementsPath = join30(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
36359
+ const entitlementsPath = join31(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
36049
36360
  const entitlements = await optionalSource(entitlementsPath);
36050
36361
  if (entitlements === null && !enabled)
36051
36362
  return false;
@@ -36057,7 +36368,7 @@ var configureIosPushNotifications = async (config, enabled) => {
36057
36368
  <!-- ${PUSH_END_MARKER} -->
36058
36369
  ` : "";
36059
36370
  const nextEntitlements = replacePushRegion(entitlements, entitlementRegion, entitlements.lastIndexOf("</dict>"));
36060
- const delegatePath = join30(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36371
+ const delegatePath = join31(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36061
36372
  const delegate = await optionalSource(delegatePath);
36062
36373
  if (delegate === null && !enabled)
36063
36374
  return false;
@@ -36106,7 +36417,7 @@ var replacePushRegion = (source, region, insertion) => {
36106
36417
  return `${source.slice(0, insertion)}${region}${source.slice(insertion)}`;
36107
36418
  };
36108
36419
  var configureAndroid2 = async (config, plan) => {
36109
- const path = join30(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
36420
+ const path = join31(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
36110
36421
  const source = await readFile27(path, "utf8");
36111
36422
  const permissions = absoluteDeviceNativeRequirements(plan).androidPermissions;
36112
36423
  const content = permissions.map((permission) => ` <uses-permission android:name="${escapeXml2(permission)}" />`).join(`
@@ -36135,14 +36446,14 @@ ${content}
36135
36446
  const clients = typeof firebase === "object" && firebase !== null ? Reflect.get(firebase, "client") : undefined;
36136
36447
  const matchesApp = Array.isArray(clients) && clients.some((client) => {
36137
36448
  const info = typeof client === "object" && client !== null ? Reflect.get(client, "client_info") : undefined;
36138
- const android = typeof info === "object" && info !== null ? Reflect.get(info, "android_client_info") : undefined;
36139
- 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;
36140
36451
  });
36141
36452
  if (!matchesApp)
36142
36453
  throw new TypeError(`Android google-services.json does not contain package ${config.appId}.`);
36143
36454
  const [manifestChanged, firebaseChanged] = await Promise.all([
36144
36455
  writeChangedFile2(path, nextManifest),
36145
- writeOptionalChangedFile(join30(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
36456
+ writeOptionalChangedFile(join31(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
36146
36457
  ]);
36147
36458
  return manifestChanged || firebaseChanged;
36148
36459
  };
@@ -36168,7 +36479,7 @@ import {
36168
36479
  rm as rm17,
36169
36480
  writeFile as writeFile23
36170
36481
  } from "fs/promises";
36171
- import { dirname as dirname21, join as join31 } from "path";
36482
+ import { dirname as dirname21, join as join32 } from "path";
36172
36483
  var START = "// absolutejs:mobile-updates:start";
36173
36484
  var END = "// absolutejs:mobile-updates:end";
36174
36485
  var PLUGIN_START = "// absolutejs:mobile-update-plugin:start";
@@ -36338,8 +36649,8 @@ public final class AbsoluteMobileUpdateWatchdogPlugin: CAPPlugin, CAPBridgedPlug
36338
36649
  ${PLUGIN_END}
36339
36650
  `;
36340
36651
  var configureIos3 = async (config, enabled) => {
36341
- const path = join31(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36342
- 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");
36343
36654
  let source = await readFile28(path, "utf8");
36344
36655
  const launch2 = source.indexOf("didFinishLaunchingWithOptions");
36345
36656
  const brace = launch2 < 0 ? -1 : source.indexOf("{", launch2);
@@ -36349,8 +36660,8 @@ var configureIos3 = async (config, enabled) => {
36349
36660
  ` : "";
36350
36661
  source = replaceMarkedRegion(source, START, END, launchRegion, brace < 0 ? -1 : source.indexOf(`
36351
36662
  `, brace) + 1, "Could not find a safe iOS location for mobile update recovery.");
36352
- const plugin = enabled ? iosPluginRegion(config.updates?.bootTimeoutMs ?? 20000) : "";
36353
- 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.");
36354
36665
  const capacitorConfigSource2 = await readFile28(capacitorConfigPath, "utf8");
36355
36666
  let capacitorConfig;
36356
36667
  try {
@@ -36531,12 +36842,12 @@ var androidActivityInRoot = async (root) => {
36531
36842
  throw error;
36532
36843
  }
36533
36844
  const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
36534
- return candidate ? join31(root, candidate) : undefined;
36845
+ return candidate ? join32(root, candidate) : undefined;
36535
36846
  };
36536
36847
  var androidActivity = async (config) => {
36537
36848
  const roots = [
36538
- join31(config.nativeProjectDirectory, "android/app/src/main/java"),
36539
- 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")
36540
36851
  ];
36541
36852
  const candidates = await Promise.all(roots.map(androidActivityInRoot));
36542
36853
  const candidate = candidates.find((value) => value !== undefined);
@@ -36640,7 +36951,7 @@ var configureAndroid3 = async (config, enabled) => {
36640
36951
  if (!packageName)
36641
36952
  throw new TypeError("Android MainActivity package declaration was not found.");
36642
36953
  const packagePath = packageName.replaceAll(".", "/");
36643
- 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);
36644
36955
  const changed = await Promise.all([
36645
36956
  writeChanged(activityPath, injectAndroidActivity(activity, enabled)),
36646
36957
  enabled ? writeChanged(pluginPath, androidPluginSource(packageName, config.updates?.bootTimeoutMs ?? 20000)) : removeOwnedFile(pluginPath)
@@ -36667,7 +36978,7 @@ import {
36667
36978
  rm as rm18,
36668
36979
  writeFile as writeFile24
36669
36980
  } from "fs/promises";
36670
- import { dirname as dirname22, join as join32 } from "path";
36981
+ import { dirname as dirname22, join as join33 } from "path";
36671
36982
  var START2 = "// absolutejs:native-observability:start";
36672
36983
  var END2 = "// absolutejs:native-observability:end";
36673
36984
  var PLUGIN_START2 = "// absolutejs:native-observability-plugin:start";
@@ -36835,8 +37146,8 @@ public final class AbsoluteMobileObservabilityPlugin: CAPPlugin, CAPBridgedPlugi
36835
37146
  ${PLUGIN_END2}
36836
37147
  `;
36837
37148
  var configureIos4 = async (config, enabled) => {
36838
- const path = join32(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36839
- 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");
36840
37151
  let source = await readFile29(path, "utf8");
36841
37152
  if (enabled && !source.includes("import MetricKit")) {
36842
37153
  const capacitorImport = source.lastIndexOf("import Capacitor");
@@ -37096,12 +37407,12 @@ var androidActivityInRoot2 = async (root) => {
37096
37407
  throw error;
37097
37408
  }
37098
37409
  const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
37099
- return candidate ? join32(root, candidate) : undefined;
37410
+ return candidate ? join33(root, candidate) : undefined;
37100
37411
  };
37101
37412
  var androidActivity2 = async (config) => {
37102
37413
  const roots = [
37103
- join32(config.nativeProjectDirectory, "android/app/src/main/java"),
37104
- 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")
37105
37416
  ];
37106
37417
  const candidates = await Promise.all(roots.map(androidActivityInRoot2));
37107
37418
  const candidate = candidates.find((value) => value !== undefined);
@@ -37173,7 +37484,7 @@ var configureAndroid4 = async (config, enabled) => {
37173
37484
  const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
37174
37485
  if (!packageName)
37175
37486
  throw new TypeError("Android MainActivity package declaration was not found.");
37176
- 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);
37177
37488
  const changed = await Promise.all([
37178
37489
  writeChanged2(activityPath, injectAndroidActivity2(activity, enabled)),
37179
37490
  enabled ? writeChanged2(pluginPath, androidPluginSource2(packageName)) : removeOwnedFile2(pluginPath)
@@ -37193,7 +37504,7 @@ var applyAbsoluteNativeObservability = async (config, platforms = config.platfor
37193
37504
  };
37194
37505
  // src/mobile/nativeReleaseReadiness.ts
37195
37506
  import { mkdir as mkdir24, readFile as readFile30, readdir as readdir11, rename as rename21, writeFile as writeFile25 } from "fs/promises";
37196
- import { dirname as dirname23, join as join33 } from "path";
37507
+ import { dirname as dirname23, join as join34 } from "path";
37197
37508
  var START3 = "// absolutejs:release-readiness:start";
37198
37509
  var END3 = "// absolutejs:release-readiness:end";
37199
37510
  var IOS_PLUGIN_START = "// absolutejs:release-readiness-plugin:start";
@@ -37232,12 +37543,12 @@ var activityInRoot = async (root) => {
37232
37543
  throw error;
37233
37544
  }
37234
37545
  const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
37235
- return candidate ? join33(root, candidate) : undefined;
37546
+ return candidate ? join34(root, candidate) : undefined;
37236
37547
  };
37237
37548
  var activityPath = async (config) => {
37238
37549
  const roots = [
37239
- join33(config.nativeProjectDirectory, "android/app/src/main/java"),
37240
- 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")
37241
37552
  ];
37242
37553
  const candidates = await Promise.all(roots.map(activityInRoot));
37243
37554
  const candidate = candidates.find((value) => value !== undefined);
@@ -37347,8 +37658,8 @@ var replaceIosPluginRegion = (appDelegate, existingStart, existingEnd) => {
37347
37658
  return `${appDelegate.slice(0, from)}${iosPluginRegion3}${appDelegate.slice(through)}`;
37348
37659
  };
37349
37660
  var configureIos5 = async (config) => {
37350
- const appDelegatePath = join33(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
37351
- 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");
37352
37663
  const appDelegate = await readFile30(appDelegatePath, "utf8");
37353
37664
  const existingStart = appDelegate.indexOf(IOS_PLUGIN_START);
37354
37665
  const existingEnd = appDelegate.indexOf(IOS_PLUGIN_END);
@@ -37388,7 +37699,7 @@ var configureAndroid5 = async (config) => {
37388
37699
  const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
37389
37700
  if (!packageName)
37390
37701
  throw new TypeError("Android MainActivity package declaration was not found.");
37391
- 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);
37392
37703
  const changed = await Promise.all([
37393
37704
  writeChanged3(mainActivityPath, injectRegistration(activity)),
37394
37705
  writeChanged3(pluginPath, pluginSource(packageName))
@@ -38129,11 +38440,11 @@ var resolveAbsoluteHttpUrl = (target, origin) => {
38129
38440
  var createAbsoluteHttpTransport = ({
38130
38441
  fetch: fetchImpl = globalThis.fetch,
38131
38442
  origin,
38132
- runtime: runtime2
38443
+ runtime: runtime3
38133
38444
  }) => ({
38134
38445
  fetch: fetchImpl,
38135
38446
  origin: normalizeAbsoluteHttpOrigin(origin),
38136
- runtime: runtime2
38447
+ runtime: runtime3
38137
38448
  });
38138
38449
  var createWebHttpTransport = (options = {}) => {
38139
38450
  const origin = options.origin ?? globalThis.location?.origin;
@@ -38316,8 +38627,8 @@ var createCapacitor = (win) => {
38316
38627
  };
38317
38628
  const isNativePlatform = () => getPlatform() !== "web";
38318
38629
  const isPluginAvailable = (pluginName) => {
38319
- const plugin = registeredPlugins.get(pluginName);
38320
- 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())) {
38321
38632
  return true;
38322
38633
  }
38323
38634
  if (getPluginHeader(pluginName)) {
@@ -38872,12 +39183,12 @@ var drainAbsoluteMobileNativeObservability = async (manifest, fetch2, options =
38872
39183
  const config = manifest.observability;
38873
39184
  if (!config || !(options.native ?? Capacitor.isNativePlatform()))
38874
39185
  return 0;
38875
- const plugin = options.plugin ?? nativeObservability;
38876
- const pending = await plugin.pending();
39186
+ const plugin2 = options.plugin ?? nativeObservability;
39187
+ const pending = await plugin2.pending();
38877
39188
  const reports = pending.reports.slice(0, MAX_REPORTS).map(parseReport).filter((report) => report !== undefined);
38878
39189
  const discarded = reports.filter((report) => !sampled(report.id, config.sampleRate));
38879
39190
  if (discarded.length > 0)
38880
- await plugin.acknowledge({
39191
+ await plugin2.acknowledge({
38881
39192
  ids: discarded.map(({ id }) => id)
38882
39193
  });
38883
39194
  const selected = reports.filter((report) => sampled(report.id, config.sampleRate));
@@ -38897,7 +39208,7 @@ var drainAbsoluteMobileNativeObservability = async (manifest, fetch2, options =
38897
39208
  });
38898
39209
  if (!response.ok)
38899
39210
  return 0;
38900
- await plugin.acknowledge({
39211
+ await plugin2.acknowledge({
38901
39212
  ids: selected.map(({ id }) => id)
38902
39213
  });
38903
39214
  return selected.length;
@@ -44279,14 +44590,14 @@ import {
44279
44590
  stat as stat8,
44280
44591
  writeFile as writeFile26
44281
44592
  } from "fs/promises";
44282
- 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";
44283
44594
  var UPDATE_MANIFEST_FILE = "update.json";
44284
44595
  var UPDATE_FILES_DIRECTORY = "files";
44285
44596
  var sha2565 = (value) => createHash18("sha256").update(value).digest("hex");
44286
44597
  var listFiles = async (root, directory = root) => {
44287
44598
  const entries = await readdir12(directory, { withFileTypes: true });
44288
44599
  const paths = await Promise.all(entries.map(async (entry) => {
44289
- const path = join34(directory, entry.name);
44600
+ const path = join35(directory, entry.name);
44290
44601
  if (entry.isDirectory())
44291
44602
  return listFiles(root, path);
44292
44603
  if (!entry.isFile())
@@ -44296,7 +44607,7 @@ var listFiles = async (root, directory = root) => {
44296
44607
  return paths.flat().sort((left, right) => left.localeCompare(right));
44297
44608
  };
44298
44609
  var inspectFiles = async (root, paths) => Promise.all(paths.map(async (path) => {
44299
- const source = join34(root, path);
44610
+ const source = join35(root, path);
44300
44611
  const [metadata, contents] = await Promise.all([
44301
44612
  stat8(source),
44302
44613
  readFile31(source)
@@ -44335,14 +44646,14 @@ var buildAbsoluteMobileUpdate = async (options) => {
44335
44646
  }
44336
44647
  });
44337
44648
  await mkdir25(outputRoot, { recursive: true });
44338
- const outputDirectory = join34(outputRoot, manifest.releaseId);
44339
- const staging = await mkdtemp12(join34(outputRoot, ".stage-"));
44649
+ const outputDirectory = join35(outputRoot, manifest.releaseId);
44650
+ const staging = await mkdtemp12(join35(outputRoot, ".stage-"));
44340
44651
  try {
44341
- await cp2(bundleDirectory, join34(staging, UPDATE_FILES_DIRECTORY), {
44652
+ await cp2(bundleDirectory, join35(staging, UPDATE_FILES_DIRECTORY), {
44342
44653
  force: true,
44343
44654
  recursive: true
44344
44655
  });
44345
- 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")}
44346
44657
  `);
44347
44658
  await rename22(staging, outputDirectory);
44348
44659
  } catch (error) {
@@ -44353,7 +44664,7 @@ var buildAbsoluteMobileUpdate = async (options) => {
44353
44664
  }
44354
44665
  return {
44355
44666
  manifest,
44356
- manifestPath: join34(outputDirectory, UPDATE_MANIFEST_FILE),
44667
+ manifestPath: join35(outputDirectory, UPDATE_MANIFEST_FILE),
44357
44668
  outputDirectory
44358
44669
  };
44359
44670
  };
@@ -44365,7 +44676,7 @@ var copyAbsoluteMobileUpdateFile = async (updateDirectory, path, destination) =>
44365
44676
  await mkdir25(dirname25(destination), { recursive: true });
44366
44677
  await cp2(source, destination, { force: true });
44367
44678
  };
44368
- 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")));
44369
44680
  var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
44370
44681
  const manifest = parseAbsoluteMobileUpdateManifest(manifestValue);
44371
44682
  const valid = verify("sha256", absoluteMobileUpdateSigningPayload(unsignedAbsoluteMobileUpdate(manifest)), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64"));
@@ -44890,5 +45201,5 @@ export {
44890
45201
  writeAbsoluteMobileUpdateRegistry
44891
45202
  };
44892
45203
 
44893
- //# debugId=B5D4F1D4350A15F564756E2164756E21
45204
+ //# debugId=F06A772036512CCC64756E2164756E21
44894
45205
  //# sourceMappingURL=index.js.map