@absolutejs/absolute 0.20.0-beta.18 → 0.20.0-beta.19
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/README.md +14 -1
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/cli/index.js +260 -93
- package/dist/mobile/index.js +140 -2
- package/dist/mobile/index.js.map +6 -5
- package/dist/src/mobile/deviceCapabilities.d.ts +13 -0
- package/dist/src/mobile/index.d.ts +1 -0
- package/dist/src/mobile/nativeDeviceCapabilities.d.ts +6 -0
- package/package.json +11 -10
package/dist/cli/index.js
CHANGED
|
@@ -6763,7 +6763,7 @@ var init_syncSchema = __esm(() => {
|
|
|
6763
6763
|
import { readFileSync as readFileSync12 } from "fs";
|
|
6764
6764
|
import { extname as extname5, join as join20, relative as relative11, resolve as resolve16 } from "path";
|
|
6765
6765
|
import ts4 from "typescript";
|
|
6766
|
-
var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/devices-capacitor", SOURCE_GLOB, IGNORED_DIRECTORIES, IDENTIFIER_PATTERN, CAPACITOR_MODULE_PATTERN, CAPACITOR_PACKAGE_PATTERN, object2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), readJson = (path) => {
|
|
6766
|
+
var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/devices-capacitor", SOURCE_GLOB, IGNORED_DIRECTORIES, IDENTIFIER_PATTERN, CAPACITOR_MODULE_PATTERN, CAPACITOR_PACKAGE_PATTERN, ANDROID_PERMISSION_PATTERN, IOS_USAGE_DESCRIPTIONS, object2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), readJson = (path) => {
|
|
6767
6767
|
const value = JSON.parse(readFileSync12(path, "utf8"));
|
|
6768
6768
|
if (!object2(value))
|
|
6769
6769
|
throw new TypeError(`${path} must contain an object.`);
|
|
@@ -6772,6 +6772,24 @@ var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/de
|
|
|
6772
6772
|
if (typeof value !== "string" || value.length === 0)
|
|
6773
6773
|
throw new TypeError(`${field} must be a non-empty string.`);
|
|
6774
6774
|
return value;
|
|
6775
|
+
}, androidPermissions = (value, field) => {
|
|
6776
|
+
if (value === undefined)
|
|
6777
|
+
return;
|
|
6778
|
+
if (!object2(value))
|
|
6779
|
+
throw new TypeError(`${field} must be an object.`);
|
|
6780
|
+
const { permissions } = value;
|
|
6781
|
+
if (!Array.isArray(permissions) || !permissions.every((permission) => typeof permission === "string" && ANDROID_PERMISSION_PATTERN.test(permission)))
|
|
6782
|
+
throw new TypeError(`${field}.permissions must contain Android permission names.`);
|
|
6783
|
+
return [...permissions];
|
|
6784
|
+
}, iosUsageDescriptions = (value, field) => {
|
|
6785
|
+
if (value === undefined)
|
|
6786
|
+
return;
|
|
6787
|
+
if (!object2(value))
|
|
6788
|
+
throw new TypeError(`${field} must be an object.`);
|
|
6789
|
+
const { usageDescriptions } = value;
|
|
6790
|
+
if (!Array.isArray(usageDescriptions) || !usageDescriptions.every((purpose) => typeof purpose === "string" && IOS_USAGE_DESCRIPTIONS.has(purpose)))
|
|
6791
|
+
throw new TypeError(`${field}.usageDescriptions contains an unsupported purpose.`);
|
|
6792
|
+
return [...usageDescriptions];
|
|
6775
6793
|
}, parseProvider = (name, value) => {
|
|
6776
6794
|
if (!IDENTIFIER_PATTERN.test(name))
|
|
6777
6795
|
throw new TypeError("Device capability names must be identifiers.");
|
|
@@ -6785,8 +6803,33 @@ var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/de
|
|
|
6785
6803
|
throw new TypeError(`${name}.module must be an official devices-capacitor subpath.`);
|
|
6786
6804
|
if (!Array.isArray(value.packages) || !value.packages.every((spec) => typeof spec === "string" && CAPACITOR_PACKAGE_PATTERN.test(spec)))
|
|
6787
6805
|
throw new TypeError(`${name}.packages must contain exact official Capacitor package versions.`);
|
|
6788
|
-
|
|
6789
|
-
|
|
6806
|
+
let native;
|
|
6807
|
+
const { native: nativeMetadata } = value;
|
|
6808
|
+
if (nativeMetadata !== undefined) {
|
|
6809
|
+
if (!object2(nativeMetadata))
|
|
6810
|
+
throw new TypeError(`${name}.native must be an object.`);
|
|
6811
|
+
const { android, ios } = nativeMetadata;
|
|
6812
|
+
const permissions = androidPermissions(android, `${name}.native.android`);
|
|
6813
|
+
const usageDescriptions = iosUsageDescriptions(ios, `${name}.native.ios`);
|
|
6814
|
+
native = {
|
|
6815
|
+
...permissions === undefined ? {} : { android: { permissions } },
|
|
6816
|
+
...usageDescriptions === undefined ? {} : { ios: { usageDescriptions } }
|
|
6817
|
+
};
|
|
6818
|
+
}
|
|
6819
|
+
return {
|
|
6820
|
+
factory,
|
|
6821
|
+
module,
|
|
6822
|
+
...native === undefined ? {} : { native },
|
|
6823
|
+
packages: [...value.packages]
|
|
6824
|
+
};
|
|
6825
|
+
}, absoluteDeviceNativeRequirements = (plan) => ({
|
|
6826
|
+
androidPermissions: [
|
|
6827
|
+
...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.android?.permissions ?? []))
|
|
6828
|
+
].sort(),
|
|
6829
|
+
iosUsageDescriptions: [
|
|
6830
|
+
...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.ios?.usageDescriptions ?? []))
|
|
6831
|
+
].sort()
|
|
6832
|
+
}), loadAbsoluteDeviceCapabilityProviders = (projectRoot) => {
|
|
6790
6833
|
const path = join20(resolve16(projectRoot), "node_modules", CAPACITOR_ADAPTER, "package.json");
|
|
6791
6834
|
const manifest = readJson(path);
|
|
6792
6835
|
const { absolutejs } = manifest;
|
|
@@ -6902,6 +6945,12 @@ var init_deviceCapabilities = __esm(() => {
|
|
|
6902
6945
|
IDENTIFIER_PATTERN = /^[A-Za-z_$][\w$]*$/u;
|
|
6903
6946
|
CAPACITOR_MODULE_PATTERN = /^@absolutejs\/devices-capacitor\/[a-z][a-z0-9-]*$/u;
|
|
6904
6947
|
CAPACITOR_PACKAGE_PATTERN = /^@capacitor\/[a-z][a-z0-9-]*@\d+\.\d+\.\d+$/u;
|
|
6948
|
+
ANDROID_PERMISSION_PATTERN = /^android\.permission\.[A-Z][A-Z0-9_]*$/u;
|
|
6949
|
+
IOS_USAGE_DESCRIPTIONS = new Set([
|
|
6950
|
+
"camera",
|
|
6951
|
+
"photo-library",
|
|
6952
|
+
"photo-library-add"
|
|
6953
|
+
]);
|
|
6905
6954
|
});
|
|
6906
6955
|
|
|
6907
6956
|
// src/mobile/buildPipeline.ts
|
|
@@ -16415,10 +16464,10 @@ ${domains}
|
|
|
16415
16464
|
};
|
|
16416
16465
|
var init_nativeDeepLinks = () => {};
|
|
16417
16466
|
|
|
16418
|
-
// src/mobile/
|
|
16467
|
+
// src/mobile/nativeDeviceCapabilities.ts
|
|
16419
16468
|
import { readFile as readFile12, rename as rename9, writeFile as writeFile10 } from "fs/promises";
|
|
16420
16469
|
import { join as join47 } from "path";
|
|
16421
|
-
var
|
|
16470
|
+
var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->", END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->", NOT_FOUND2 = -1, escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">"), writeChangedFile2 = async (path, source) => {
|
|
16422
16471
|
const current = await readFile12(path, "utf8");
|
|
16423
16472
|
if (current === source)
|
|
16424
16473
|
return false;
|
|
@@ -16426,6 +16475,85 @@ var writeChanged = async (path, source) => {
|
|
|
16426
16475
|
await writeFile10(temporary, source, { flag: "wx" });
|
|
16427
16476
|
await rename9(temporary, path);
|
|
16428
16477
|
return true;
|
|
16478
|
+
}, managed = (source, region, insertion) => {
|
|
16479
|
+
const start2 = source.indexOf(START_MARKER2);
|
|
16480
|
+
const end = source.indexOf(END_MARKER2);
|
|
16481
|
+
if (start2 === NOT_FOUND2 !== (end === NOT_FOUND2) || start2 !== NOT_FOUND2 && end < start2)
|
|
16482
|
+
throw new TypeError("AbsoluteJS device-capability ownership markers are malformed.");
|
|
16483
|
+
if (start2 !== NOT_FOUND2) {
|
|
16484
|
+
const lineStart = source.lastIndexOf(`
|
|
16485
|
+
`, start2) + 1;
|
|
16486
|
+
const nextLine = source.indexOf(`
|
|
16487
|
+
`, end + END_MARKER2.length);
|
|
16488
|
+
const lineEnd = nextLine === NOT_FOUND2 ? source.length : nextLine + 1;
|
|
16489
|
+
return `${source.slice(0, lineStart)}${region}${source.slice(lineEnd)}`;
|
|
16490
|
+
}
|
|
16491
|
+
if (region.length === 0)
|
|
16492
|
+
return source;
|
|
16493
|
+
if (insertion === NOT_FOUND2)
|
|
16494
|
+
throw new TypeError("Could not find a safe native project location for device permissions.");
|
|
16495
|
+
return `${source.slice(0, insertion)}${region}${source.slice(insertion)}`;
|
|
16496
|
+
}, IOS_KEYS, iosDescription = (appName, purpose) => {
|
|
16497
|
+
if (purpose === "camera")
|
|
16498
|
+
return `${appName} uses your camera when you choose to take a photo.`;
|
|
16499
|
+
if (purpose === "photo-library")
|
|
16500
|
+
return `${appName} accesses your photo library only for photo actions you choose.`;
|
|
16501
|
+
return `${appName} adds to your photo library only for photo actions you choose.`;
|
|
16502
|
+
}, configureIos2 = async (config, plan) => {
|
|
16503
|
+
const path = join47(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
16504
|
+
const source = await readFile12(path, "utf8");
|
|
16505
|
+
const requirements = absoluteDeviceNativeRequirements(plan);
|
|
16506
|
+
const content = requirements.iosUsageDescriptions.map((purpose) => ` <key>${IOS_KEYS[purpose]}</key>
|
|
16507
|
+
<string>${escapeXml2(iosDescription(config.appName, purpose))}</string>`).join(`
|
|
16508
|
+
`);
|
|
16509
|
+
const region = content ? ` ${START_MARKER2}
|
|
16510
|
+
${content}
|
|
16511
|
+
${END_MARKER2}
|
|
16512
|
+
` : "";
|
|
16513
|
+
return writeChangedFile2(path, managed(source, region, source.lastIndexOf("</dict>")));
|
|
16514
|
+
}, configureAndroid2 = async (config, plan) => {
|
|
16515
|
+
const path = join47(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
16516
|
+
const source = await readFile12(path, "utf8");
|
|
16517
|
+
const permissions = absoluteDeviceNativeRequirements(plan).androidPermissions;
|
|
16518
|
+
const content = permissions.map((permission) => ` <uses-permission android:name="${escapeXml2(permission)}" />`).join(`
|
|
16519
|
+
`);
|
|
16520
|
+
const region = content ? ` ${START_MARKER2}
|
|
16521
|
+
${content}
|
|
16522
|
+
${END_MARKER2}
|
|
16523
|
+
` : "";
|
|
16524
|
+
const application = source.indexOf("<application");
|
|
16525
|
+
const insertion = application === NOT_FOUND2 ? NOT_FOUND2 : source.lastIndexOf(`
|
|
16526
|
+
`, application) + 1;
|
|
16527
|
+
return writeChangedFile2(path, managed(source, region, insertion));
|
|
16528
|
+
}, applyAbsoluteNativeDeviceCapabilities = async (projectRoot, config, platforms = config.platforms, plan = resolveAbsoluteDeviceCapabilityPlan(projectRoot)) => {
|
|
16529
|
+
const results = await Promise.all(platforms.map(async (platform6) => ({
|
|
16530
|
+
didChange: platform6 === "ios" ? await configureIos2(config, plan) : await configureAndroid2(config, plan),
|
|
16531
|
+
platform: platform6
|
|
16532
|
+
})));
|
|
16533
|
+
return {
|
|
16534
|
+
changed: results.filter(({ didChange }) => didChange).map(({ platform: platform6 }) => platform6)
|
|
16535
|
+
};
|
|
16536
|
+
};
|
|
16537
|
+
var init_nativeDeviceCapabilities = __esm(() => {
|
|
16538
|
+
init_deviceCapabilities();
|
|
16539
|
+
IOS_KEYS = {
|
|
16540
|
+
camera: "NSCameraUsageDescription",
|
|
16541
|
+
"photo-library": "NSPhotoLibraryUsageDescription",
|
|
16542
|
+
"photo-library-add": "NSPhotoLibraryAddUsageDescription"
|
|
16543
|
+
};
|
|
16544
|
+
});
|
|
16545
|
+
|
|
16546
|
+
// src/mobile/nativeBackgroundSync.ts
|
|
16547
|
+
import { readFile as readFile13, rename as rename10, writeFile as writeFile11 } from "fs/promises";
|
|
16548
|
+
import { join as join48 } from "path";
|
|
16549
|
+
var writeChanged = async (path, source) => {
|
|
16550
|
+
const current = await readFile13(path, "utf8");
|
|
16551
|
+
if (current === source)
|
|
16552
|
+
return false;
|
|
16553
|
+
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
16554
|
+
await writeFile11(temporary, source, { flag: "wx" });
|
|
16555
|
+
await rename10(temporary, path);
|
|
16556
|
+
return true;
|
|
16429
16557
|
}, replaceRegion = (source, start2, end, region, insert) => {
|
|
16430
16558
|
const existingStart = source.indexOf(start2);
|
|
16431
16559
|
const existingEnd = source.indexOf(end);
|
|
@@ -16500,11 +16628,11 @@ ${makeRegion(values)} </array>
|
|
|
16500
16628
|
if (!platforms.includes("ios") || !projectUsesAbsoluteAuth(projectRoot) || !projectUsesAbsoluteSync(projectRoot))
|
|
16501
16629
|
return { changed: false };
|
|
16502
16630
|
const identifier = `${config.appId}.absolutejs.background-sync`;
|
|
16503
|
-
const infoPath =
|
|
16504
|
-
const info2 = await
|
|
16631
|
+
const infoPath = join48(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
16632
|
+
const info2 = await readFile13(infoPath, "utf8");
|
|
16505
16633
|
const nextInfo = ensurePlistArrayValues(ensurePlistArrayValues(info2, "BGTaskSchedulerPermittedIdentifiers", [identifier], "background-sync-identifiers"), "UIBackgroundModes", ["fetch", "processing"], "background-sync-modes");
|
|
16506
|
-
const delegatePath =
|
|
16507
|
-
let delegate = await
|
|
16634
|
+
const delegatePath = join48(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
16635
|
+
let delegate = await readFile13(delegatePath, "utf8");
|
|
16508
16636
|
if (!delegate.includes("import AbsoluteSyncCapacitor")) {
|
|
16509
16637
|
const importIndex = delegate.lastIndexOf("import Capacitor");
|
|
16510
16638
|
if (importIndex < 0)
|
|
@@ -16538,10 +16666,10 @@ var init_nativeBackgroundSync = __esm(() => {
|
|
|
16538
16666
|
import {
|
|
16539
16667
|
access as access7,
|
|
16540
16668
|
mkdir as mkdir10,
|
|
16541
|
-
readFile as
|
|
16542
|
-
rename as
|
|
16669
|
+
readFile as readFile14,
|
|
16670
|
+
rename as rename11,
|
|
16543
16671
|
rm as rm7,
|
|
16544
|
-
writeFile as
|
|
16672
|
+
writeFile as writeFile12
|
|
16545
16673
|
} from "fs/promises";
|
|
16546
16674
|
import { resolve as resolve37 } from "path";
|
|
16547
16675
|
import { Elysia } from "elysia";
|
|
@@ -16596,7 +16724,7 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
|
|
|
16596
16724
|
}, writeAtomic = async (path, source) => {
|
|
16597
16725
|
let current;
|
|
16598
16726
|
try {
|
|
16599
|
-
current = await
|
|
16727
|
+
current = await readFile14(path, "utf8");
|
|
16600
16728
|
} catch (error) {
|
|
16601
16729
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
|
|
16602
16730
|
throw error;
|
|
@@ -16605,8 +16733,8 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
|
|
|
16605
16733
|
if (current === source)
|
|
16606
16734
|
return false;
|
|
16607
16735
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
16608
|
-
await
|
|
16609
|
-
await
|
|
16736
|
+
await writeFile12(temporary, source, { flag: "wx" });
|
|
16737
|
+
await rename11(temporary, path);
|
|
16610
16738
|
return true;
|
|
16611
16739
|
}, exists2 = async (path) => {
|
|
16612
16740
|
try {
|
|
@@ -16619,7 +16747,7 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
|
|
|
16619
16747
|
const path = resolve37(root, OWNERSHIP_FILE);
|
|
16620
16748
|
let ownership;
|
|
16621
16749
|
try {
|
|
16622
|
-
ownership = JSON.parse(await
|
|
16750
|
+
ownership = JSON.parse(await readFile14(path, "utf8"));
|
|
16623
16751
|
} catch {
|
|
16624
16752
|
throw new TypeError(`Association output ${root} already exists and is not owned by AbsoluteJS.`);
|
|
16625
16753
|
}
|
|
@@ -16632,12 +16760,12 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
|
|
|
16632
16760
|
await assertOwnedOutput(root);
|
|
16633
16761
|
const backup = `${root}.${crypto.randomUUID()}.previous`;
|
|
16634
16762
|
if (hasCurrent)
|
|
16635
|
-
await
|
|
16763
|
+
await rename11(root, backup);
|
|
16636
16764
|
try {
|
|
16637
|
-
await
|
|
16765
|
+
await rename11(temporary, root);
|
|
16638
16766
|
} catch (error) {
|
|
16639
16767
|
if (hasCurrent)
|
|
16640
|
-
await
|
|
16768
|
+
await rename11(backup, root);
|
|
16641
16769
|
throw error;
|
|
16642
16770
|
}
|
|
16643
16771
|
if (hasCurrent)
|
|
@@ -16727,7 +16855,7 @@ var init_associationFiles = __esm(() => {
|
|
|
16727
16855
|
});
|
|
16728
16856
|
|
|
16729
16857
|
// src/mobile/androidWebView.ts
|
|
16730
|
-
import { mkdir as mkdir11, writeFile as
|
|
16858
|
+
import { mkdir as mkdir11, writeFile as writeFile13 } from "fs/promises";
|
|
16731
16859
|
import { dirname as dirname28, resolve as resolve38 } from "path";
|
|
16732
16860
|
|
|
16733
16861
|
class CdpConnection {
|
|
@@ -17001,7 +17129,7 @@ var CDP_COMMAND_TIMEOUT_MS = 1e4, WEBVIEW_ATTACH_TIMEOUT_MS = 30000, WEBVIEW_POL
|
|
|
17001
17129
|
}
|
|
17002
17130
|
const absolutePath = resolve38(path);
|
|
17003
17131
|
await mkdir11(dirname28(absolutePath), { recursive: true });
|
|
17004
|
-
await
|
|
17132
|
+
await writeFile13(absolutePath, Buffer.from(data, "base64"));
|
|
17005
17133
|
return absolutePath;
|
|
17006
17134
|
}
|
|
17007
17135
|
};
|
|
@@ -17119,8 +17247,8 @@ var DEFAULT_ROUTE_TIMEOUT_MS = 30000, DEFAULT_HMR_TIMEOUT_MS = 30000, routeExpre
|
|
|
17119
17247
|
};
|
|
17120
17248
|
|
|
17121
17249
|
// src/mobile/releaseDoctor.ts
|
|
17122
|
-
import { access as access8, readFile as
|
|
17123
|
-
import { extname as extname8, join as
|
|
17250
|
+
import { access as access8, readFile as readFile15, readdir as readdir4 } from "fs/promises";
|
|
17251
|
+
import { extname as extname8, join as join49, relative as relative24 } from "path";
|
|
17124
17252
|
var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
|
|
17125
17253
|
try {
|
|
17126
17254
|
await access8(path);
|
|
@@ -17133,13 +17261,13 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
|
|
|
17133
17261
|
return findHmrAsset(path);
|
|
17134
17262
|
if (!isFile2 || !RELEASE_ASSET_EXTENSIONS.has(extname8(path)))
|
|
17135
17263
|
return;
|
|
17136
|
-
const source = await
|
|
17264
|
+
const source = await readFile15(path, "utf8");
|
|
17137
17265
|
return HMR_ASSET_PATTERN.test(source) ? path : undefined;
|
|
17138
17266
|
}, findHmrAsset = async (root) => {
|
|
17139
17267
|
if (!await pathExists5(root))
|
|
17140
17268
|
return;
|
|
17141
17269
|
const entries = await readdir4(root, { withFileTypes: true });
|
|
17142
|
-
const matches = await Promise.all(entries.map((entry) => inspectReleaseAsset(
|
|
17270
|
+
const matches = await Promise.all(entries.map((entry) => inspectReleaseAsset(join49(root, entry.name), entry.isDirectory(), entry.isFile())));
|
|
17143
17271
|
return matches.find((match) => match !== undefined);
|
|
17144
17272
|
}, pass = (id, detail, path) => ({ detail, id, path, status: "pass" }), fail5 = (id, detail, path, remediation) => ({
|
|
17145
17273
|
detail,
|
|
@@ -17172,13 +17300,13 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
|
|
|
17172
17300
|
if (!await pathExists5(nativeConfigPath)) {
|
|
17173
17301
|
return fail5("android.capacitor-config", "The generated Android Capacitor config is missing.", nativeConfigPath, "Run `absolute mobile sync android` before release validation.");
|
|
17174
17302
|
}
|
|
17175
|
-
const unsafe = isUnsafeCapacitorConfig(await
|
|
17303
|
+
const unsafe = isUnsafeCapacitorConfig(await readFile15(nativeConfigPath, "utf8"));
|
|
17176
17304
|
return unsafe ? fail5("android.capacitor-config", "Android Capacitor config contains a development server URL, cleartext transport, navigation allowlist, or invalid JSON.", nativeConfigPath, "Run `absolute mobile sync android`; do not ship development transport overrides.") : pass("android.capacitor-config", "Android Capacitor config contains no development transport overrides.", nativeConfigPath);
|
|
17177
17305
|
}, manifestReleaseCheck = async (manifestPath) => {
|
|
17178
17306
|
if (!await pathExists5(manifestPath)) {
|
|
17179
17307
|
return fail5("android.cleartext", "The Android manifest is missing.", manifestPath, "Run `absolute mobile sync android` before release validation.");
|
|
17180
17308
|
}
|
|
17181
|
-
const source = await
|
|
17309
|
+
const source = await readFile15(manifestPath, "utf8");
|
|
17182
17310
|
return /android:usesCleartextTraffic=["']true["']/u.test(source) ? fail5("android.cleartext", "Android explicitly permits cleartext traffic.", manifestPath, 'Remove usesCleartextTraffic="true" from the release manifest.') : pass("android.cleartext", "Android does not explicitly permit cleartext traffic.", manifestPath);
|
|
17183
17311
|
}, hmrAssetsReleaseCheck = async (publicRoot) => {
|
|
17184
17312
|
const hmrAsset = await findHmrAsset(publicRoot);
|
|
@@ -17186,7 +17314,7 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
|
|
|
17186
17314
|
}, syncSchemaReleaseCheck = (projectRoot) => {
|
|
17187
17315
|
if (!projectUsesAbsoluteSync(projectRoot))
|
|
17188
17316
|
return;
|
|
17189
|
-
const manifestPath =
|
|
17317
|
+
const manifestPath = join49(projectRoot, "package.json");
|
|
17190
17318
|
try {
|
|
17191
17319
|
const schema = discoverAbsoluteSyncSchema(projectRoot);
|
|
17192
17320
|
const versions = schema.components.map((component2) => `${component2.id}@${component2.version}`).join(", ");
|
|
@@ -17205,21 +17333,46 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
|
|
|
17205
17333
|
} catch (error) {
|
|
17206
17334
|
return fail5("sync.storage-schema", error instanceof Error ? error.message : "Generated offline schema metadata is invalid.", manifestPath, "Fix absolutejs.sync.localSchema metadata in the named app or package before releasing.");
|
|
17207
17335
|
}
|
|
17208
|
-
},
|
|
17209
|
-
|
|
17336
|
+
}, IOS_USAGE_KEYS, androidDevicePermissionCheck = async (config, permissions) => {
|
|
17337
|
+
if (!config.platforms.includes("android") || permissions.length === 0)
|
|
17338
|
+
return;
|
|
17339
|
+
const path = join49(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
17340
|
+
const source = await readFile15(path, "utf8");
|
|
17341
|
+
const missing = permissions.filter((permission) => !source.includes(`android:name="${permission}"`) && !source.includes(`android:name='${permission}'`));
|
|
17342
|
+
if (missing.length === 0)
|
|
17343
|
+
return;
|
|
17344
|
+
return fail5("mobile.device-capabilities", `Android is missing native declarations for: ${missing.join(", ")}.`, path, "Run `absolute mobile sync android` to regenerate detected device permissions.");
|
|
17345
|
+
}, iosDevicePermissionCheck = async (config, purposes) => {
|
|
17346
|
+
if (!config.platforms.includes("ios") || purposes.length === 0)
|
|
17347
|
+
return;
|
|
17348
|
+
const path = join49(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
17349
|
+
const source = await readFile15(path, "utf8");
|
|
17350
|
+
const missing = purposes.filter((purpose) => !source.includes(`<key>${IOS_USAGE_KEYS[purpose]}</key>`));
|
|
17351
|
+
if (missing.length === 0)
|
|
17352
|
+
return;
|
|
17353
|
+
return fail5("mobile.device-capabilities", `iOS is missing usage descriptions for: ${missing.join(", ")}.`, path, "Run `absolute mobile sync ios` to regenerate detected device usage descriptions.");
|
|
17354
|
+
}, deviceCapabilityReleaseCheck = async (config, projectRoot) => {
|
|
17355
|
+
const manifestPath = join49(projectRoot, "package.json");
|
|
17210
17356
|
try {
|
|
17211
17357
|
const plan = resolveAbsoluteDeviceCapabilityPlan(projectRoot);
|
|
17212
17358
|
assertAbsoluteDeviceCapabilityPackages(projectRoot, plan);
|
|
17213
|
-
|
|
17359
|
+
const requirements = absoluteDeviceNativeRequirements(plan);
|
|
17360
|
+
const androidCheck = await androidDevicePermissionCheck(config, requirements.androidPermissions);
|
|
17361
|
+
if (androidCheck)
|
|
17362
|
+
return androidCheck;
|
|
17363
|
+
const iosCheck = await iosDevicePermissionCheck(config, requirements.iosUsageDescriptions);
|
|
17364
|
+
if (iosCheck)
|
|
17365
|
+
return iosCheck;
|
|
17366
|
+
return pass("mobile.device-capabilities", plan.capabilities.length > 0 ? `Native provider packages and permission declarations match detected capabilities: ${plan.capabilities.join(", ")}.` : "No optional native device capabilities are used.", manifestPath);
|
|
17214
17367
|
} catch (error) {
|
|
17215
17368
|
return fail5("mobile.device-capabilities", error instanceof Error ? error.message : "Native device capability provisioning is invalid.", manifestPath, "Run `absolute mobile sync` and approve the exact capability plugins before releasing.");
|
|
17216
17369
|
}
|
|
17217
17370
|
}, inspectAndroidRelease = async (config, projectRoot) => {
|
|
17218
|
-
const androidRoot =
|
|
17219
|
-
const nativeConfigPath =
|
|
17220
|
-
const manifestPath =
|
|
17221
|
-
const publicRoot =
|
|
17222
|
-
const journalPath =
|
|
17371
|
+
const androidRoot = join49(config.nativeProjectDirectory, "android");
|
|
17372
|
+
const nativeConfigPath = join49(androidRoot, "app", "src", "main", "assets", "capacitor.config.json");
|
|
17373
|
+
const manifestPath = join49(androidRoot, "app", "src", "main", "AndroidManifest.xml");
|
|
17374
|
+
const publicRoot = join49(androidRoot, "app", "src", "main", "assets", "public");
|
|
17375
|
+
const journalPath = join49(projectRoot, ".absolutejs", "mobile", "dev-session", "journal.json");
|
|
17223
17376
|
const checks = await Promise.all([
|
|
17224
17377
|
journalReleaseCheck(journalPath, "android"),
|
|
17225
17378
|
capacitorConfigReleaseCheck(nativeConfigPath),
|
|
@@ -17231,11 +17384,11 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
|
|
|
17231
17384
|
path: check2.path ? relative24(projectRoot, check2.path).replaceAll("\\", "/") || "." : undefined
|
|
17232
17385
|
}));
|
|
17233
17386
|
}, inspectIosRelease = async (config, projectRoot) => {
|
|
17234
|
-
const iosAppRoot =
|
|
17235
|
-
const nativeConfigPath =
|
|
17236
|
-
const infoPath =
|
|
17237
|
-
const publicRoot =
|
|
17238
|
-
const journalPath =
|
|
17387
|
+
const iosAppRoot = join49(config.nativeProjectDirectory, "ios", "App", "App");
|
|
17388
|
+
const nativeConfigPath = join49(iosAppRoot, "capacitor.config.json");
|
|
17389
|
+
const infoPath = join49(iosAppRoot, "Info.plist");
|
|
17390
|
+
const publicRoot = join49(iosAppRoot, "public");
|
|
17391
|
+
const journalPath = join49(projectRoot, ".absolutejs", "mobile", "ios-dev-session", "journal.json");
|
|
17239
17392
|
const checks = [
|
|
17240
17393
|
await journalReleaseCheck(journalPath, "ios")
|
|
17241
17394
|
];
|
|
@@ -17246,7 +17399,7 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
|
|
|
17246
17399
|
}
|
|
17247
17400
|
if (!await pathExists5(nativeConfigPath)) {
|
|
17248
17401
|
checks.push(fail5("ios.capacitor-config", "The generated iOS Capacitor config is missing.", nativeConfigPath, "Run `absolute mobile sync ios` before release validation."));
|
|
17249
|
-
} else if (isUnsafeCapacitorConfig(await
|
|
17402
|
+
} else if (isUnsafeCapacitorConfig(await readFile15(nativeConfigPath, "utf8"))) {
|
|
17250
17403
|
checks.push(fail5("ios.capacitor-config", "iOS Capacitor config contains a development server URL, cleartext transport, navigation allowlist, or invalid JSON.", nativeConfigPath, "Run `absolute mobile sync ios`; do not ship development transport overrides."));
|
|
17251
17404
|
} else {
|
|
17252
17405
|
checks.push(pass("ios.capacitor-config", "iOS Capacitor config contains no development transport overrides.", nativeConfigPath));
|
|
@@ -17254,7 +17407,7 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
|
|
|
17254
17407
|
if (!await pathExists5(infoPath)) {
|
|
17255
17408
|
checks.push(fail5("ios.transport-security", "The iOS Info.plist is missing.", infoPath, "Run `absolute mobile sync ios` before release validation."));
|
|
17256
17409
|
} else {
|
|
17257
|
-
const info2 = await
|
|
17410
|
+
const info2 = await readFile15(infoPath, "utf8");
|
|
17258
17411
|
checks.push(/<key>NSAllowsArbitraryLoads<\/key>\s*<true\s*\/>/u.test(info2) ? fail5("ios.transport-security", "iOS App Transport Security permits arbitrary network loads.", infoPath, "Remove NSAllowsArbitraryLoads from the release Info.plist.") : pass("ios.transport-security", "iOS App Transport Security does not permit arbitrary loads.", infoPath));
|
|
17259
17412
|
}
|
|
17260
17413
|
const hmrAsset = await findHmrAsset(publicRoot);
|
|
@@ -17275,7 +17428,7 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
|
|
|
17275
17428
|
path: syncSchema.path ? relative24(projectRoot, syncSchema.path).replaceAll("\\", "/") || "." : undefined
|
|
17276
17429
|
});
|
|
17277
17430
|
}
|
|
17278
|
-
const deviceCapabilities = deviceCapabilityReleaseCheck(projectRoot);
|
|
17431
|
+
const deviceCapabilities = await deviceCapabilityReleaseCheck(config, projectRoot);
|
|
17279
17432
|
checks.push({
|
|
17280
17433
|
...deviceCapabilities,
|
|
17281
17434
|
path: deviceCapabilities.path ? relative24(projectRoot, deviceCapabilities.path).replaceAll("\\", "/") || "." : undefined
|
|
@@ -17291,6 +17444,11 @@ var init_releaseDoctor = __esm(() => {
|
|
|
17291
17444
|
init_deviceCapabilities();
|
|
17292
17445
|
HMR_ASSET_PATTERN = /(?:__HMR_WS__|hmr-timing|__absolute_target|absolutejs-error-overlay)/u;
|
|
17293
17446
|
RELEASE_ASSET_EXTENSIONS = new Set([".html", ".js", ".mjs"]);
|
|
17447
|
+
IOS_USAGE_KEYS = {
|
|
17448
|
+
camera: "NSCameraUsageDescription",
|
|
17449
|
+
"photo-library": "NSPhotoLibraryUsageDescription",
|
|
17450
|
+
"photo-library-add": "NSPhotoLibraryAddUsageDescription"
|
|
17451
|
+
};
|
|
17294
17452
|
});
|
|
17295
17453
|
|
|
17296
17454
|
// src/mobile/androidRelease.ts
|
|
@@ -17300,13 +17458,13 @@ import {
|
|
|
17300
17458
|
copyFile as copyFile5,
|
|
17301
17459
|
mkdir as mkdir12,
|
|
17302
17460
|
mkdtemp as mkdtemp5,
|
|
17303
|
-
readFile as
|
|
17304
|
-
rename as
|
|
17461
|
+
readFile as readFile16,
|
|
17462
|
+
rename as rename12,
|
|
17305
17463
|
rm as rm8,
|
|
17306
17464
|
stat as stat2,
|
|
17307
|
-
writeFile as
|
|
17465
|
+
writeFile as writeFile14
|
|
17308
17466
|
} from "fs/promises";
|
|
17309
|
-
import { dirname as dirname29, isAbsolute as isAbsolute7, join as
|
|
17467
|
+
import { dirname as dirname29, isAbsolute as isAbsolute7, join as join50, relative as relative25, resolve as resolve39, sep as sep6 } from "path";
|
|
17310
17468
|
var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), requireManifest2 = (value) => {
|
|
17311
17469
|
if (!isRecord13(value) || typeof value.appBuild !== "string" || typeof value.appId !== "string" || typeof value.runtime !== "string") {
|
|
17312
17470
|
throw new TypeError("Invalid embedded AbsoluteJS mobile manifest.");
|
|
@@ -17356,7 +17514,7 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
|
|
|
17356
17514
|
artifactPath
|
|
17357
17515
|
]);
|
|
17358
17516
|
return result.exitCode === 0 && /jar verified/iu.test(result.stdout);
|
|
17359
|
-
}, sha256File2 = async (path) => createHash12("sha256").update(await
|
|
17517
|
+
}, sha256File2 = async (path) => createHash12("sha256").update(await readFile16(path)).digest("hex"), safeOutputDirectory2 = (projectRoot, requested) => {
|
|
17360
17518
|
const root = resolve39(projectRoot);
|
|
17361
17519
|
const output = resolve39(root, requested ?? ".absolutejs/mobile/releases/android");
|
|
17362
17520
|
const projectRelative = relative25(root, output);
|
|
@@ -17365,11 +17523,11 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
|
|
|
17365
17523
|
}
|
|
17366
17524
|
return output;
|
|
17367
17525
|
}, installRelease2 = async (artifactPath, metadata, outputRoot) => {
|
|
17368
|
-
const releaseRoot =
|
|
17526
|
+
const releaseRoot = join50(outputRoot, metadata.releaseId);
|
|
17369
17527
|
const artifactName = "app-release.aab";
|
|
17370
|
-
const destination =
|
|
17528
|
+
const destination = join50(releaseRoot, artifactName);
|
|
17371
17529
|
if (await pathExists6(releaseRoot)) {
|
|
17372
|
-
const existing = requireManifestIdentity(JSON.parse(await
|
|
17530
|
+
const existing = requireManifestIdentity(JSON.parse(await readFile16(join50(releaseRoot, "release.json"), "utf8")), metadata);
|
|
17373
17531
|
const [installedBytes, installedSha256] = await Promise.all([
|
|
17374
17532
|
stat2(destination).then(({ size }) => size),
|
|
17375
17533
|
sha256File2(destination)
|
|
@@ -17380,16 +17538,16 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
|
|
|
17380
17538
|
return { artifactPath: destination, metadata: existing, releaseRoot };
|
|
17381
17539
|
}
|
|
17382
17540
|
await mkdir12(dirname29(releaseRoot), { recursive: true });
|
|
17383
|
-
const staging = await mkdtemp5(
|
|
17541
|
+
const staging = await mkdtemp5(join50(dirname29(releaseRoot), ".android-stage-"));
|
|
17384
17542
|
try {
|
|
17385
|
-
await copyFile5(artifactPath,
|
|
17543
|
+
await copyFile5(artifactPath, join50(staging, artifactName));
|
|
17386
17544
|
const complete = {
|
|
17387
17545
|
...metadata,
|
|
17388
17546
|
artifact: artifactName
|
|
17389
17547
|
};
|
|
17390
|
-
await
|
|
17548
|
+
await writeFile14(join50(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
|
|
17391
17549
|
`, { flag: "wx" });
|
|
17392
|
-
await
|
|
17550
|
+
await rename12(staging, releaseRoot);
|
|
17393
17551
|
return { artifactPath: destination, metadata: complete, releaseRoot };
|
|
17394
17552
|
} finally {
|
|
17395
17553
|
await rm8(staging, { force: true, recursive: true }).catch(() => {
|
|
@@ -17415,8 +17573,8 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
|
|
|
17415
17573
|
const projectRoot = resolve39(options.projectRoot);
|
|
17416
17574
|
const host2 = options.host ?? detectAbsoluteMobileHost();
|
|
17417
17575
|
const androidRoot = options.androidRoot ?? process.env.ANDROID_HOME ?? process.env.ANDROID_SDK_ROOT ?? absoluteManagedAndroidSdkRoot(host2);
|
|
17418
|
-
const nativeDirectory =
|
|
17419
|
-
const manifest = requireManifest2(JSON.parse(await
|
|
17576
|
+
const nativeDirectory = join50(options.config.nativeProjectDirectory, "android");
|
|
17577
|
+
const manifest = requireManifest2(JSON.parse(await readFile16(join50(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
|
|
17420
17578
|
if (manifest.appId !== options.config.appId) {
|
|
17421
17579
|
throw new TypeError("Embedded mobile manifest appId does not match mobile.appId.");
|
|
17422
17580
|
}
|
|
@@ -17480,7 +17638,7 @@ var init_androidRelease = __esm(() => {
|
|
|
17480
17638
|
});
|
|
17481
17639
|
|
|
17482
17640
|
// src/mobile/iosConformance.ts
|
|
17483
|
-
import { readFile as
|
|
17641
|
+
import { readFile as readFile17, stat as stat3 } from "fs/promises";
|
|
17484
17642
|
var HMR_LINE, parseAbsoluteIosHmrLog = (line) => {
|
|
17485
17643
|
const match = HMR_LINE.exec(line);
|
|
17486
17644
|
if (!match)
|
|
@@ -17515,7 +17673,7 @@ var HMR_LINE, parseAbsoluteIosHmrLog = (line) => {
|
|
|
17515
17673
|
if (Date.now() > deadline)
|
|
17516
17674
|
throw new Error(`No iOS native HMR acknowledgement was observed within ${timeoutMs}ms.`);
|
|
17517
17675
|
options.signal?.throwIfAborted();
|
|
17518
|
-
const contents = await
|
|
17676
|
+
const contents = await readFile17(options.logPath).catch(() => Buffer.alloc(0));
|
|
17519
17677
|
if (contents.byteLength < offset) {
|
|
17520
17678
|
offset = 0;
|
|
17521
17679
|
buffered = "";
|
|
@@ -17636,11 +17794,11 @@ var exports_mobile = {};
|
|
|
17636
17794
|
__export(exports_mobile, {
|
|
17637
17795
|
runMobile: () => runMobile
|
|
17638
17796
|
});
|
|
17639
|
-
import { access as access11, mkdir as mkdir13, readFile as
|
|
17640
|
-
import { join as
|
|
17797
|
+
import { access as access11, mkdir as mkdir13, readFile as readFile18, writeFile as writeFile15 } from "fs/promises";
|
|
17798
|
+
import { join as join51, resolve as resolve41 } from "path";
|
|
17641
17799
|
import { createInterface } from "readline/promises";
|
|
17642
|
-
var
|
|
17643
|
-
const manifest = JSON.parse(await
|
|
17800
|
+
var NOT_FOUND3 = -1, isRecord15 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), CAPACITOR_PACKAGES, CAPACITOR_PACKAGE_SPECS, CAPACITOR_SYNC_PACKAGE_SPECS, packageNameFromSpec = (spec) => spec.slice(0, spec.lastIndexOf("@")), directProjectPackages = async (projectRoot) => {
|
|
17801
|
+
const manifest = JSON.parse(await readFile18(join51(projectRoot, "package.json"), "utf8"));
|
|
17644
17802
|
if (!isRecord15(manifest))
|
|
17645
17803
|
throw new TypeError("Application package.json must contain an object.");
|
|
17646
17804
|
const names = new Set;
|
|
@@ -17653,7 +17811,7 @@ var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
17653
17811
|
return names;
|
|
17654
17812
|
}, resolvedPackageVersion = async (projectRoot, packageName) => {
|
|
17655
17813
|
try {
|
|
17656
|
-
const manifest = JSON.parse(await
|
|
17814
|
+
const manifest = JSON.parse(await readFile18(join51(projectRoot, "node_modules", packageName, "package.json"), "utf8"));
|
|
17657
17815
|
return isRecord15(manifest) && typeof manifest.version === "string" ? manifest.version : undefined;
|
|
17658
17816
|
} catch {
|
|
17659
17817
|
return;
|
|
@@ -17684,7 +17842,7 @@ var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
17684
17842
|
await installApprovedPackages(projectRoot, args, `AbsoluteJS detected native device capabilities (${capabilityPlan.capabilities.join(", ")}). Install only their required Capacitor plugins now?`, capabilityPackages);
|
|
17685
17843
|
}, valueAfter = (args, flag) => {
|
|
17686
17844
|
const index = args.indexOf(flag);
|
|
17687
|
-
return index ===
|
|
17845
|
+
return index === NOT_FOUND3 ? undefined : args[index + 1];
|
|
17688
17846
|
}, valuesAfter = (args, flag) => args.flatMap((value, index) => {
|
|
17689
17847
|
const next = args[index + 1];
|
|
17690
17848
|
return value === flag && next !== undefined ? [next] : [];
|
|
@@ -17694,7 +17852,7 @@ var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
17694
17852
|
}
|
|
17695
17853
|
return value;
|
|
17696
17854
|
}, capacitorExecutable = async (projectRoot) => {
|
|
17697
|
-
const executable =
|
|
17855
|
+
const executable = join51(projectRoot, "node_modules", ".bin", "cap");
|
|
17698
17856
|
try {
|
|
17699
17857
|
await access11(executable);
|
|
17700
17858
|
return executable;
|
|
@@ -17765,6 +17923,7 @@ var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
17765
17923
|
return;
|
|
17766
17924
|
await runCapacitorForPlatforms(projectRoot, "add", mobile.platforms);
|
|
17767
17925
|
await applyAbsoluteNativeDeepLinks(mobile);
|
|
17926
|
+
await applyAbsoluteNativeDeviceCapabilities(projectRoot, mobile);
|
|
17768
17927
|
await applyAbsoluteNativeBackgroundSync(projectRoot, mobile);
|
|
17769
17928
|
}, sync = async (args) => {
|
|
17770
17929
|
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
@@ -17777,6 +17936,7 @@ var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
17777
17936
|
await repairAbsoluteIosDevSession(projectRoot);
|
|
17778
17937
|
await runCapacitorForPlatforms(projectRoot, "sync", platforms);
|
|
17779
17938
|
await applyAbsoluteNativeDeepLinks(mobile, platforms);
|
|
17939
|
+
await applyAbsoluteNativeDeviceCapabilities(projectRoot, mobile, platforms);
|
|
17780
17940
|
await applyAbsoluteNativeBackgroundSync(projectRoot, mobile, platforms);
|
|
17781
17941
|
}, associations = async (args) => {
|
|
17782
17942
|
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
@@ -17995,6 +18155,9 @@ Mobile release transport checks failed.`);
|
|
|
17995
18155
|
await writeAbsoluteCapacitorConfig(mobile, { projectRoot });
|
|
17996
18156
|
await runCapacitorForPlatforms(projectRoot, "sync", ["android"]);
|
|
17997
18157
|
await applyAbsoluteNativeDeepLinks(mobile, ["android"]);
|
|
18158
|
+
await applyAbsoluteNativeDeviceCapabilities(projectRoot, mobile, [
|
|
18159
|
+
"android"
|
|
18160
|
+
]);
|
|
17998
18161
|
await applyAbsoluteNativeBackgroundSync(projectRoot, mobile, [
|
|
17999
18162
|
"android"
|
|
18000
18163
|
]);
|
|
@@ -18010,7 +18173,7 @@ Mobile release transport checks failed.`);
|
|
|
18010
18173
|
const durationMs = Math.round(performance.now() - startedAt);
|
|
18011
18174
|
console.log(`Built ${release.metadata.signed ? "signed" : "unsigned"} Android App Bundle in ${getDurationString(durationMs)}.`);
|
|
18012
18175
|
console.log(`Artifact: ${release.artifactPath}`);
|
|
18013
|
-
console.log(`Metadata: ${
|
|
18176
|
+
console.log(`Metadata: ${join51(release.releaseRoot, "release.json")}`);
|
|
18014
18177
|
return release;
|
|
18015
18178
|
} finally {
|
|
18016
18179
|
sendTelemetryEvent("mobile:android-release-build", {
|
|
@@ -18097,6 +18260,9 @@ Mobile release transport checks failed.`);
|
|
|
18097
18260
|
await writeAbsoluteCapacitorConfig(mobile, { projectRoot });
|
|
18098
18261
|
await runCapacitorForPlatforms(projectRoot, "sync", ["ios"]);
|
|
18099
18262
|
await applyAbsoluteNativeDeepLinks(mobile, ["ios"]);
|
|
18263
|
+
await applyAbsoluteNativeDeviceCapabilities(projectRoot, mobile, [
|
|
18264
|
+
"ios"
|
|
18265
|
+
]);
|
|
18100
18266
|
await applyAbsoluteNativeBackgroundSync(projectRoot, mobile, ["ios"]);
|
|
18101
18267
|
await requireIosReleaseReady(mobile, projectRoot);
|
|
18102
18268
|
const release = await buildAbsoluteIosRelease({
|
|
@@ -18110,7 +18276,7 @@ Mobile release transport checks failed.`);
|
|
|
18110
18276
|
const durationMs = Math.round(performance.now() - startedAt);
|
|
18111
18277
|
console.log(`Built ${release.metadata.signed ? "signed" : "unsigned"} iOS IPA ${release.metadata.marketingVersion}${release.metadata.buildNumber ? ` (${release.metadata.buildNumber})` : ""} in ${getDurationString(durationMs)}.`);
|
|
18112
18278
|
console.log(`Artifact: ${release.artifactPath}`);
|
|
18113
|
-
console.log(`Metadata: ${
|
|
18279
|
+
console.log(`Metadata: ${join51(release.releaseRoot, "release.json")}`);
|
|
18114
18280
|
return release;
|
|
18115
18281
|
} finally {
|
|
18116
18282
|
sendTelemetryEvent("mobile:ios-release-build", {
|
|
@@ -18217,7 +18383,7 @@ Mobile release transport checks failed.`);
|
|
|
18217
18383
|
checks.push({
|
|
18218
18384
|
id: "sync.storage-schema",
|
|
18219
18385
|
label: `Offline schema ${schema.components.map((component2) => `${component2.id}@${component2.version}`).join(", ")}`,
|
|
18220
|
-
path:
|
|
18386
|
+
path: join51(projectRoot, "package.json"),
|
|
18221
18387
|
platform: "host",
|
|
18222
18388
|
status: "pass"
|
|
18223
18389
|
});
|
|
@@ -18225,7 +18391,7 @@ Mobile release transport checks failed.`);
|
|
|
18225
18391
|
checks.push({
|
|
18226
18392
|
id: "sync.storage-schema",
|
|
18227
18393
|
label: "Offline schema metadata is invalid",
|
|
18228
|
-
path:
|
|
18394
|
+
path: join51(projectRoot, "package.json"),
|
|
18229
18395
|
platform: "host",
|
|
18230
18396
|
remediation: error instanceof Error ? error.message : String(error),
|
|
18231
18397
|
status: "fail"
|
|
@@ -18379,11 +18545,11 @@ Emulator setup verification:`);
|
|
|
18379
18545
|
});
|
|
18380
18546
|
}, writeAndroidFailureArtifacts = async (options) => {
|
|
18381
18547
|
await mkdir13(options.artifactRoot, { recursive: true });
|
|
18382
|
-
const screenshot = options.session ? await options.session.screenshot(
|
|
18548
|
+
const screenshot = options.session ? await options.session.screenshot(join51(options.artifactRoot, "android-failure.png")).catch(() => {
|
|
18383
18549
|
return;
|
|
18384
18550
|
}) : undefined;
|
|
18385
|
-
const diagnosticPath =
|
|
18386
|
-
await
|
|
18551
|
+
const diagnosticPath = join51(options.artifactRoot, "android-failure.json");
|
|
18552
|
+
await writeFile15(diagnosticPath, `${JSON.stringify({
|
|
18387
18553
|
diagnostics: options.session?.diagnostics ?? [],
|
|
18388
18554
|
error: options.error instanceof Error ? options.error.message : String(options.error),
|
|
18389
18555
|
platform: "android",
|
|
@@ -18560,7 +18726,7 @@ Emulator setup verification:`);
|
|
|
18560
18726
|
return result;
|
|
18561
18727
|
}, writeIosFailureArtifacts = async (options) => {
|
|
18562
18728
|
await mkdir13(options.artifactRoot, { recursive: true });
|
|
18563
|
-
const screenshot =
|
|
18729
|
+
const screenshot = join51(options.artifactRoot, "ios-failure.png");
|
|
18564
18730
|
const screenshotResult = captureCommand4([
|
|
18565
18731
|
options.xcrun,
|
|
18566
18732
|
"simctl",
|
|
@@ -18569,8 +18735,8 @@ Emulator setup verification:`);
|
|
|
18569
18735
|
"screenshot",
|
|
18570
18736
|
screenshot
|
|
18571
18737
|
]);
|
|
18572
|
-
const diagnosticPath =
|
|
18573
|
-
await
|
|
18738
|
+
const diagnosticPath = join51(options.artifactRoot, "ios-failure.json");
|
|
18739
|
+
await writeFile15(diagnosticPath, `${JSON.stringify({
|
|
18574
18740
|
appId: options.appId,
|
|
18575
18741
|
error: options.error instanceof Error ? options.error.message : String(options.error),
|
|
18576
18742
|
platform: "ios",
|
|
@@ -18615,7 +18781,7 @@ Emulator setup verification:`);
|
|
|
18615
18781
|
], "iOS app launch");
|
|
18616
18782
|
await waitForIosHmrClient({ https, port, timeoutMs });
|
|
18617
18783
|
await mkdir13(artifactRoot, { recursive: true });
|
|
18618
|
-
const screenshot =
|
|
18784
|
+
const screenshot = join51(artifactRoot, "ios-simulator.png");
|
|
18619
18785
|
requireCapturedIosCommand([xcrun, "simctl", "io", simulator.udid, "screenshot", screenshot], "iOS simulator screenshot");
|
|
18620
18786
|
const hmrApply = await waitForRequestedIosHmr(args, instance, timeoutMs);
|
|
18621
18787
|
const report = {
|
|
@@ -18719,6 +18885,7 @@ var init_mobile = __esm(() => {
|
|
|
18719
18885
|
init_capacitorProject();
|
|
18720
18886
|
init_config();
|
|
18721
18887
|
init_nativeDeepLinks();
|
|
18888
|
+
init_nativeDeviceCapabilities();
|
|
18722
18889
|
init_nativeBackgroundSync();
|
|
18723
18890
|
init_emulatorDoctor();
|
|
18724
18891
|
init_emulatorInstaller();
|
|
@@ -18762,11 +18929,11 @@ var init_mobile = __esm(() => {
|
|
|
18762
18929
|
"@capacitor/cli@8.5.0",
|
|
18763
18930
|
"@capacitor/android@8.5.0",
|
|
18764
18931
|
"@capacitor/ios@8.5.0",
|
|
18765
|
-
"@absolutejs/devices@0.
|
|
18766
|
-
"@absolutejs/devices-capacitor@0.
|
|
18932
|
+
"@absolutejs/devices@0.2.0",
|
|
18933
|
+
"@absolutejs/devices-capacitor@0.3.1"
|
|
18767
18934
|
];
|
|
18768
18935
|
CAPACITOR_SYNC_PACKAGE_SPECS = [
|
|
18769
|
-
"@absolutejs/sync-capacitor@0.
|
|
18936
|
+
"@absolutejs/sync-capacitor@0.9.0",
|
|
18770
18937
|
"@capacitor-community/sqlite@8.1.1"
|
|
18771
18938
|
];
|
|
18772
18939
|
});
|
|
@@ -18776,9 +18943,9 @@ var exports_typecheck = {};
|
|
|
18776
18943
|
__export(exports_typecheck, {
|
|
18777
18944
|
typecheck: () => typecheck
|
|
18778
18945
|
});
|
|
18779
|
-
import { resolve as resolve42, join as
|
|
18946
|
+
import { resolve as resolve42, join as join52 } from "path";
|
|
18780
18947
|
import { existsSync as existsSync42, readFileSync as readFileSync40 } from "fs";
|
|
18781
|
-
import { mkdir as mkdir14, writeFile as
|
|
18948
|
+
import { mkdir as mkdir14, writeFile as writeFile16 } from "fs/promises";
|
|
18782
18949
|
var isCommandService3 = (service) => service.kind === "command" || Array.isArray(service.command), resolveConfigPath = (configPath2) => resolve42(configPath2 ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts"), getTypecheckTargets = async (configPath2) => {
|
|
18783
18950
|
if (!existsSync42(resolveConfigPath(configPath2))) {
|
|
18784
18951
|
const defaultService = {};
|
|
@@ -18885,8 +19052,8 @@ Found ${errorCount} error${suffix}.`;
|
|
|
18885
19052
|
console.error("\x1B[31m\u2717\x1B[0m vue-tsc is required for Vue type checking. Install it: bun add -d vue-tsc");
|
|
18886
19053
|
process.exit(1);
|
|
18887
19054
|
}
|
|
18888
|
-
const vueTsconfigPath =
|
|
18889
|
-
await
|
|
19055
|
+
const vueTsconfigPath = join52(cacheDir, "tsconfig.vue-check.json");
|
|
19056
|
+
await writeFile16(vueTsconfigPath, JSON.stringify({
|
|
18890
19057
|
compilerOptions: {
|
|
18891
19058
|
rootDir: ".."
|
|
18892
19059
|
},
|
|
@@ -18905,7 +19072,7 @@ Found ${errorCount} error${suffix}.`;
|
|
|
18905
19072
|
...base,
|
|
18906
19073
|
"--incremental",
|
|
18907
19074
|
"--tsBuildInfoFile",
|
|
18908
|
-
|
|
19075
|
+
join52(cacheDir, "vue-tsc.tsbuildinfo")
|
|
18909
19076
|
]);
|
|
18910
19077
|
if (cached.exitCode === 0 || cached.output.length > 0)
|
|
18911
19078
|
return cached;
|
|
@@ -18916,8 +19083,8 @@ Found ${errorCount} error${suffix}.`;
|
|
|
18916
19083
|
console.error("\x1B[31m\u2717\x1B[0m @angular/compiler-cli is required for Angular type checking. Install it: bun add -d @angular/compiler-cli");
|
|
18917
19084
|
process.exit(1);
|
|
18918
19085
|
}
|
|
18919
|
-
const angularTsconfigPath =
|
|
18920
|
-
await
|
|
19086
|
+
const angularTsconfigPath = join52(cacheDir, "tsconfig.angular-check.json");
|
|
19087
|
+
await writeFile16(angularTsconfigPath, JSON.stringify({
|
|
18921
19088
|
angularCompilerOptions: {
|
|
18922
19089
|
strictTemplates: true
|
|
18923
19090
|
},
|
|
@@ -18936,8 +19103,8 @@ Found ${errorCount} error${suffix}.`;
|
|
|
18936
19103
|
console.error("\x1B[31m\u2717\x1B[0m typescript is required for type checking. Install it: bun add -d typescript");
|
|
18937
19104
|
process.exit(1);
|
|
18938
19105
|
}
|
|
18939
|
-
const tscConfigPath =
|
|
18940
|
-
return
|
|
19106
|
+
const tscConfigPath = join52(cacheDir, "tsconfig.typecheck.json");
|
|
19107
|
+
return writeFile16(tscConfigPath, JSON.stringify({
|
|
18941
19108
|
compilerOptions: {
|
|
18942
19109
|
rootDir: ".."
|
|
18943
19110
|
},
|
|
@@ -18951,7 +19118,7 @@ Found ${errorCount} error${suffix}.`;
|
|
|
18951
19118
|
resolve42(tscConfigPath),
|
|
18952
19119
|
"--incremental",
|
|
18953
19120
|
"--tsBuildInfoFile",
|
|
18954
|
-
|
|
19121
|
+
join52(cacheDir, "tsc.tsbuildinfo"),
|
|
18955
19122
|
"--pretty"
|
|
18956
19123
|
]));
|
|
18957
19124
|
}, buildSvelteCheck = async (cacheDir, svelteDir) => {
|
|
@@ -18960,8 +19127,8 @@ Found ${errorCount} error${suffix}.`;
|
|
|
18960
19127
|
console.error("\x1B[31m\u2717\x1B[0m svelte-check is required for Svelte type checking. Install it: bun add -d svelte-check");
|
|
18961
19128
|
process.exit(1);
|
|
18962
19129
|
}
|
|
18963
|
-
const svelteTsconfigPath =
|
|
18964
|
-
await
|
|
19130
|
+
const svelteTsconfigPath = join52(cacheDir, "tsconfig.svelte-check.json");
|
|
19131
|
+
await writeFile16(svelteTsconfigPath, JSON.stringify({
|
|
18965
19132
|
extends: resolve42("tsconfig.json"),
|
|
18966
19133
|
files: ABSOLUTE_TYPECHECK_FILES,
|
|
18967
19134
|
include: [`../${svelteDir}/**/*`]
|