@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.
- package/CHANGELOG.md +7 -0
- package/changelog.json +15 -1
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/cli/{compile-ya4kd2sg.js → compile-kbhxgjat.js} +2 -2
- package/dist/cli/{dev-5cqmf7za.js → dev-daa7tdht.js} +1 -1
- package/dist/cli/{expoProject-f5j20xms.js → expoProject-kcfcmfba.js} +1 -1
- package/dist/cli/{index-6mbm4n3g.js → index-82wpxhvv.js} +1 -1
- package/dist/cli/{index-dr21p6ae.js → index-bhcxtf1x.js} +389 -78
- package/dist/cli/{index-5fmgn0nx.js → index-vjepnxr0.js} +1 -1
- package/dist/cli/index.js +5 -5
- package/dist/cli/{mobile-fg2226vv.js → mobile-03zwncxx.js} +22 -20
- package/dist/cli/{start-jt61f40d.js → start-r606d5v9.js} +3 -3
- package/dist/mobile/index.js +486 -175
- package/dist/mobile/index.js.map +6 -5
- package/dist/mobile/remoteMacAgentEntry.js +475 -209
- package/dist/mobile/shellBootstrap.js +6 -1
- package/dist/react/hooks/index.js.map +2 -2
- package/dist/src/mobile/expoEmbeddedAssets.d.ts +1 -0
- package/dist/src/mobile/updateRuntime.d.ts +1 -0
- package/package.json +3 -1
package/dist/mobile/index.js
CHANGED
|
@@ -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
|
|
6442
|
+
var header2;
|
|
6443
6443
|
if (msg.procType) {
|
|
6444
|
-
|
|
6444
|
+
header2 = {
|
|
6445
6445
|
name: "Proc-Type",
|
|
6446
6446
|
values: [String(msg.procType.version), msg.procType.type]
|
|
6447
6447
|
};
|
|
6448
|
-
rval += foldHeader(
|
|
6448
|
+
rval += foldHeader(header2);
|
|
6449
6449
|
}
|
|
6450
6450
|
if (msg.contentDomain) {
|
|
6451
|
-
|
|
6452
|
-
rval += foldHeader(
|
|
6451
|
+
header2 = { name: "Content-Domain", values: [msg.contentDomain] };
|
|
6452
|
+
rval += foldHeader(header2);
|
|
6453
6453
|
}
|
|
6454
6454
|
if (msg.dekInfo) {
|
|
6455
|
-
|
|
6455
|
+
header2 = { name: "DEK-Info", values: [msg.dekInfo.algorithm] };
|
|
6456
6456
|
if (msg.dekInfo.parameters) {
|
|
6457
|
-
|
|
6457
|
+
header2.values.push(msg.dekInfo.parameters);
|
|
6458
6458
|
}
|
|
6459
|
-
rval += foldHeader(
|
|
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
|
|
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
|
-
|
|
6520
|
+
header2.values.push(ltrim(values[vi]));
|
|
6521
6521
|
}
|
|
6522
6522
|
if (!msg.procType) {
|
|
6523
|
-
if (
|
|
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 (
|
|
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 &&
|
|
6529
|
+
} else if (!msg.contentDomain && header2.name === "Content-Domain") {
|
|
6530
6530
|
msg.contentDomain = values[0] || "";
|
|
6531
|
-
} else if (!msg.dekInfo &&
|
|
6532
|
-
if (
|
|
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(
|
|
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(
|
|
6552
|
-
var rval =
|
|
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 <
|
|
6558
|
-
values.push(
|
|
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(
|
|
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 =
|
|
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
|
|
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 =
|
|
19470
|
-
configPath =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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) =>
|
|
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((
|
|
31237
|
-
if (
|
|
31496
|
+
const configuredPlugins = devicePlugins.map((plugin2) => {
|
|
31497
|
+
if (plugin2 === "expo-image-picker")
|
|
31238
31498
|
return [
|
|
31239
|
-
|
|
31499
|
+
plugin2,
|
|
31240
31500
|
{
|
|
31241
31501
|
cameraPermission: descriptions.NSCameraUsageDescription,
|
|
31242
31502
|
microphonePermission: false,
|
|
31243
31503
|
photosPermission: descriptions.NSPhotoLibraryUsageDescription
|
|
31244
31504
|
}
|
|
31245
31505
|
];
|
|
31246
|
-
if (
|
|
31506
|
+
if (plugin2 === "expo-location")
|
|
31247
31507
|
return [
|
|
31248
|
-
|
|
31508
|
+
plugin2,
|
|
31249
31509
|
{
|
|
31250
31510
|
locationWhenInUsePermission: descriptions.NSLocationWhenInUseUsageDescription
|
|
31251
31511
|
}
|
|
31252
31512
|
];
|
|
31253
|
-
return
|
|
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
|
-
|
|
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' &&
|
|
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 === '
|
|
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
|
-
|
|
32182
|
-
|
|
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 (
|
|
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,
|
|
32399
|
-
import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative3(dirname13(wrapper),
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
32829
|
+
join21(project, "app.json"),
|
|
32538
32830
|
jsonSource(expoAppConfig(config, authEnabled, syncEnabled, devices, runtimeFingerprint))
|
|
32539
32831
|
],
|
|
32540
|
-
[
|
|
32832
|
+
[join21(project, "app.config.js"), expoDynamicAppConfig],
|
|
32541
32833
|
[
|
|
32542
|
-
|
|
32834
|
+
join21(project, "package.json"),
|
|
32543
32835
|
jsonSource(expoPackage(authEnabled, config.branding !== undefined, syncEnabled, devices, config.updates !== undefined))
|
|
32544
32836
|
],
|
|
32545
|
-
[
|
|
32837
|
+
[join21(project, "metro.config.js"), metroConfig(projectRoot)],
|
|
32546
32838
|
[
|
|
32547
|
-
|
|
32839
|
+
join21(project, "plugins", "withAbsoluteDevelopmentCa.js"),
|
|
32548
32840
|
expoDevelopmentCaPlugin
|
|
32549
32841
|
],
|
|
32550
32842
|
[
|
|
32551
|
-
|
|
32843
|
+
join21(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
|
|
32552
32844
|
expoActivityResultRecoveryPlugin
|
|
32553
32845
|
],
|
|
32554
32846
|
[
|
|
32555
|
-
|
|
32847
|
+
join21(project, "tsconfig.json"),
|
|
32556
32848
|
jsonSource(expoTsConfig(projectRoot, project, authEnabled, syncEnabled))
|
|
32557
32849
|
],
|
|
32558
32850
|
[
|
|
32559
|
-
|
|
32851
|
+
join21(project, "app", "_layout.tsx"),
|
|
32560
32852
|
layoutSource(authEnabled, syncEnabled, config.updates !== undefined, config.observability !== undefined)
|
|
32561
32853
|
],
|
|
32562
32854
|
[
|
|
32563
|
-
|
|
32855
|
+
join21(project, "app", "__absolute", "native", "index.tsx"),
|
|
32564
32856
|
nativeDiagnosticSource
|
|
32565
32857
|
],
|
|
32566
32858
|
[
|
|
32567
|
-
|
|
32859
|
+
join21(project, "src", "generated", "AbsoluteDevices.ts"),
|
|
32568
32860
|
devicesRuntimeSource(config, devices, authEnabled)
|
|
32569
32861
|
],
|
|
32570
32862
|
[
|
|
32571
|
-
|
|
32863
|
+
join21(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
|
|
32572
32864
|
nativeRouteRuntimeSource(authEnabled)
|
|
32573
32865
|
],
|
|
32574
32866
|
[
|
|
32575
|
-
|
|
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(
|
|
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(
|
|
32884
|
+
files.set(join21(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
|
|
32591
32885
|
if (auth) {
|
|
32592
|
-
files.set(
|
|
32886
|
+
files.set(join21(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
|
|
32593
32887
|
}
|
|
32594
32888
|
if (syncSchema) {
|
|
32595
|
-
files.set(
|
|
32889
|
+
files.set(join21(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
|
|
32596
32890
|
}
|
|
32597
|
-
const webAssetsPath =
|
|
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(
|
|
32896
|
+
files.set(join21(project, "app", "index.tsx"), webRouteSource);
|
|
32603
32897
|
}
|
|
32604
|
-
files.set(
|
|
32605
|
-
const nativeRouteRuntime =
|
|
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 === "/" ?
|
|
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(`${
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
33049
|
+
const destination = join21(config.nativeProjectDirectory, "assets", "absolute");
|
|
32743
33050
|
await mkdir14(dirname13(destination), { recursive: true });
|
|
32744
|
-
const staging = await mkdtemp9(
|
|
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
|
-
|
|
32760
|
-
|
|
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 =
|
|
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 =
|
|
33118
|
+
const root = join22(buildDirectory, ".absolutejs", "mobile-compatibility");
|
|
32808
33119
|
const [manifestSource, previous] = await Promise.all([
|
|
32809
|
-
readFile18(
|
|
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,
|
|
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
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 =
|
|
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,
|
|
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
|
|
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(
|
|
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(
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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 :
|
|
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 ??
|
|
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 =
|
|
34403
|
+
const destination = join25(parent, certification.certificationId);
|
|
34093
34404
|
const paths = {
|
|
34094
34405
|
directory: destination,
|
|
34095
|
-
jsonPath:
|
|
34096
|
-
markdownPath:
|
|
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(
|
|
34423
|
+
const staging = await mkdtemp10(join25(parent, ".certification-"));
|
|
34113
34424
|
try {
|
|
34114
34425
|
await Promise.all([
|
|
34115
|
-
writeFile18(
|
|
34426
|
+
writeFile18(join25(staging, "certification.json"), json, {
|
|
34116
34427
|
flag: "wx"
|
|
34117
34428
|
}),
|
|
34118
|
-
writeFile18(
|
|
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 =
|
|
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(
|
|
34776
|
+
const staging = await mkdtemp11(join26(dirname17(output), ".promotion-audit-"));
|
|
34466
34777
|
try {
|
|
34467
|
-
const evidenceRoot =
|
|
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 =
|
|
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(
|
|
34893
|
+
writeFile19(join26(staging, "audit.json"), `${JSON.stringify(audit, null, 2)}
|
|
34583
34894
|
`, { mode: 384 }),
|
|
34584
|
-
writeFile19(
|
|
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
|
|
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) =>
|
|
34674
|
-
var absoluteMobilePromotionOperationPath = (projectRoot, requestedDispatchId) =>
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
36139
|
-
return typeof
|
|
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(
|
|
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
|
|
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 =
|
|
36342
|
-
const capacitorConfigPath =
|
|
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
|
|
36353
|
-
source = replaceMarkedRegion(source, PLUGIN_START, PLUGIN_END,
|
|
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 ?
|
|
36845
|
+
return candidate ? join32(root, candidate) : undefined;
|
|
36535
36846
|
};
|
|
36536
36847
|
var androidActivity = async (config) => {
|
|
36537
36848
|
const roots = [
|
|
36538
|
-
|
|
36539
|
-
|
|
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 =
|
|
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
|
|
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 =
|
|
36839
|
-
const capacitorConfigPath =
|
|
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 ?
|
|
37410
|
+
return candidate ? join33(root, candidate) : undefined;
|
|
37100
37411
|
};
|
|
37101
37412
|
var androidActivity2 = async (config) => {
|
|
37102
37413
|
const roots = [
|
|
37103
|
-
|
|
37104
|
-
|
|
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 =
|
|
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
|
|
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 ?
|
|
37546
|
+
return candidate ? join34(root, candidate) : undefined;
|
|
37236
37547
|
};
|
|
37237
37548
|
var activityPath = async (config) => {
|
|
37238
37549
|
const roots = [
|
|
37239
|
-
|
|
37240
|
-
|
|
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 =
|
|
37351
|
-
const capacitorConfigPath =
|
|
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 =
|
|
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:
|
|
38443
|
+
runtime: runtime3
|
|
38133
38444
|
}) => ({
|
|
38134
38445
|
fetch: fetchImpl,
|
|
38135
38446
|
origin: normalizeAbsoluteHttpOrigin(origin),
|
|
38136
|
-
runtime:
|
|
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
|
|
38320
|
-
if (
|
|
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
|
|
38876
|
-
const pending = await
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
44339
|
-
const staging = await mkdtemp12(
|
|
44649
|
+
const outputDirectory = join35(outputRoot, manifest.releaseId);
|
|
44650
|
+
const staging = await mkdtemp12(join35(outputRoot, ".stage-"));
|
|
44340
44651
|
try {
|
|
44341
|
-
await cp2(bundleDirectory,
|
|
44652
|
+
await cp2(bundleDirectory, join35(staging, UPDATE_FILES_DIRECTORY), {
|
|
44342
44653
|
force: true,
|
|
44343
44654
|
recursive: true
|
|
44344
44655
|
});
|
|
44345
|
-
await writeFile26(
|
|
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:
|
|
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(
|
|
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=
|
|
45204
|
+
//# debugId=F06A772036512CCC64756E2164756E21
|
|
44894
45205
|
//# sourceMappingURL=index.js.map
|