@absolutejs/absolute 0.20.0-beta.22 → 0.20.0-beta.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/cli/index.js +403 -80
- package/dist/mobile/index.js +210 -16
- package/dist/mobile/index.js.map +4 -4
- package/dist/src/mobile/androidTestReport.d.ts +14 -0
- package/dist/src/mobile/deviceCapabilities.d.ts +7 -1
- package/dist/src/mobile/iosTestReport.d.ts +7 -41
- package/dist/src/mobile/nativeTestReport.d.ts +72 -0
- package/package.json +5 -3
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, ANDROID_PERMISSION_PATTERN, IOS_USAGE_DESCRIPTIONS, 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, IOS_PRIVACY_ACCESSED_API_REASONS, IOS_PRIVACY_ACCESSED_APIS, 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.`);
|
|
@@ -6781,15 +6781,37 @@ var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/de
|
|
|
6781
6781
|
if (!Array.isArray(permissions) || !permissions.every((permission) => typeof permission === "string" && ANDROID_PERMISSION_PATTERN.test(permission)))
|
|
6782
6782
|
throw new TypeError(`${field}.permissions must contain Android permission names.`);
|
|
6783
6783
|
return [...permissions];
|
|
6784
|
-
},
|
|
6784
|
+
}, iosPrivacyAccessedApis = (value, field) => {
|
|
6785
6785
|
if (value === undefined)
|
|
6786
6786
|
return;
|
|
6787
6787
|
if (!object2(value))
|
|
6788
6788
|
throw new TypeError(`${field} must be an object.`);
|
|
6789
|
-
const
|
|
6790
|
-
|
|
6789
|
+
const privacy = {};
|
|
6790
|
+
for (const api of IOS_PRIVACY_ACCESSED_APIS) {
|
|
6791
|
+
const reasons = value[api];
|
|
6792
|
+
if (reasons === undefined)
|
|
6793
|
+
continue;
|
|
6794
|
+
const supported = IOS_PRIVACY_ACCESSED_API_REASONS[api];
|
|
6795
|
+
if (!Array.isArray(reasons) || reasons.length === 0 || !reasons.every((reason) => typeof reason === "string" && supported.has(reason)))
|
|
6796
|
+
throw new TypeError(`${field} contains an unsupported API or reason.`);
|
|
6797
|
+
privacy[api] = [...reasons];
|
|
6798
|
+
}
|
|
6799
|
+
if (Object.keys(value).some((api) => !IOS_PRIVACY_ACCESSED_APIS.some((known) => known === api)))
|
|
6800
|
+
throw new TypeError(`${field} contains an unsupported API or reason.`);
|
|
6801
|
+
return privacy;
|
|
6802
|
+
}, iosNativeRequirements = (value, field) => {
|
|
6803
|
+
if (value === undefined)
|
|
6804
|
+
return;
|
|
6805
|
+
if (!object2(value))
|
|
6806
|
+
throw new TypeError(`${field} must be an object.`);
|
|
6807
|
+
const { privacyAccessedApis, usageDescriptions } = value;
|
|
6808
|
+
if (usageDescriptions !== undefined && (!Array.isArray(usageDescriptions) || !usageDescriptions.every((purpose) => typeof purpose === "string" && IOS_USAGE_DESCRIPTIONS.has(purpose))))
|
|
6791
6809
|
throw new TypeError(`${field}.usageDescriptions contains an unsupported purpose.`);
|
|
6792
|
-
|
|
6810
|
+
const privacy = iosPrivacyAccessedApis(privacyAccessedApis, `${field}.privacyAccessedApis`);
|
|
6811
|
+
return {
|
|
6812
|
+
...privacy === undefined ? {} : { privacyAccessedApis: privacy },
|
|
6813
|
+
...usageDescriptions === undefined ? {} : { usageDescriptions: [...usageDescriptions] }
|
|
6814
|
+
};
|
|
6793
6815
|
}, parseProvider = (name, value) => {
|
|
6794
6816
|
if (!IDENTIFIER_PATTERN.test(name))
|
|
6795
6817
|
throw new TypeError("Device capability names must be identifiers.");
|
|
@@ -6810,10 +6832,10 @@ var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/de
|
|
|
6810
6832
|
throw new TypeError(`${name}.native must be an object.`);
|
|
6811
6833
|
const { android, ios } = nativeMetadata;
|
|
6812
6834
|
const permissions = androidPermissions(android, `${name}.native.android`);
|
|
6813
|
-
const
|
|
6835
|
+
const iosRequirements = iosNativeRequirements(ios, `${name}.native.ios`);
|
|
6814
6836
|
native = {
|
|
6815
6837
|
...permissions === undefined ? {} : { android: { permissions } },
|
|
6816
|
-
...
|
|
6838
|
+
...iosRequirements === undefined ? {} : { ios: iosRequirements }
|
|
6817
6839
|
};
|
|
6818
6840
|
}
|
|
6819
6841
|
return {
|
|
@@ -6822,14 +6844,32 @@ var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/de
|
|
|
6822
6844
|
...native === undefined ? {} : { native },
|
|
6823
6845
|
packages: [...value.packages]
|
|
6824
6846
|
};
|
|
6825
|
-
}, absoluteDeviceNativeRequirements = (plan) =>
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6847
|
+
}, absoluteDeviceNativeRequirements = (plan) => {
|
|
6848
|
+
const privacy = plan.capabilities.reduce((requirements, name) => {
|
|
6849
|
+
for (const api of IOS_PRIVACY_ACCESSED_APIS) {
|
|
6850
|
+
const reasons = plan.providers[name]?.native?.ios?.privacyAccessedApis?.[api] ?? [];
|
|
6851
|
+
if (reasons.length === 0)
|
|
6852
|
+
continue;
|
|
6853
|
+
const current = requirements[api] ?? new Set;
|
|
6854
|
+
for (const reason of reasons)
|
|
6855
|
+
current.add(reason);
|
|
6856
|
+
requirements[api] = current;
|
|
6857
|
+
}
|
|
6858
|
+
return requirements;
|
|
6859
|
+
}, {});
|
|
6860
|
+
return {
|
|
6861
|
+
androidPermissions: [
|
|
6862
|
+
...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.android?.permissions ?? []))
|
|
6863
|
+
].sort(),
|
|
6864
|
+
iosPrivacyAccessedApis: IOS_PRIVACY_ACCESSED_APIS.flatMap((api) => {
|
|
6865
|
+
const reasons = privacy[api];
|
|
6866
|
+
return reasons ? [{ api, reasons: [...reasons].sort() }] : [];
|
|
6867
|
+
}),
|
|
6868
|
+
iosUsageDescriptions: [
|
|
6869
|
+
...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.ios?.usageDescriptions ?? []))
|
|
6870
|
+
].sort()
|
|
6871
|
+
};
|
|
6872
|
+
}, loadAbsoluteDeviceCapabilityProviders = (projectRoot) => {
|
|
6833
6873
|
const path = join20(resolve16(projectRoot), "node_modules", CAPACITOR_ADAPTER, "package.json");
|
|
6834
6874
|
const manifest = readJson(path);
|
|
6835
6875
|
const { absolutejs } = manifest;
|
|
@@ -6953,6 +6993,12 @@ var init_deviceCapabilities = __esm(() => {
|
|
|
6953
6993
|
"photo-library",
|
|
6954
6994
|
"photo-library-add"
|
|
6955
6995
|
]);
|
|
6996
|
+
IOS_PRIVACY_ACCESSED_API_REASONS = {
|
|
6997
|
+
NSPrivacyAccessedAPICategoryFileTimestamp: new Set(["C617.1"])
|
|
6998
|
+
};
|
|
6999
|
+
IOS_PRIVACY_ACCESSED_APIS = [
|
|
7000
|
+
"NSPrivacyAccessedAPICategoryFileTimestamp"
|
|
7001
|
+
];
|
|
6956
7002
|
});
|
|
6957
7003
|
|
|
6958
7004
|
// src/mobile/buildPipeline.ts
|
|
@@ -16469,7 +16515,7 @@ var init_nativeDeepLinks = () => {};
|
|
|
16469
16515
|
// src/mobile/nativeDeviceCapabilities.ts
|
|
16470
16516
|
import { readFile as readFile12, rename as rename9, writeFile as writeFile10 } from "fs/promises";
|
|
16471
16517
|
import { join as join47 } from "path";
|
|
16472
|
-
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) => {
|
|
16518
|
+
var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->", END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->", NOT_FOUND2 = -1, IOS_PRIVACY_FILE_REFERENCE = "A85D0C000000000000000001", IOS_PRIVACY_BUILD_FILE = "A85D0C000000000000000002", escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">"), writeChangedFile2 = async (path, source) => {
|
|
16473
16519
|
const current = await readFile12(path, "utf8");
|
|
16474
16520
|
if (current === source)
|
|
16475
16521
|
return false;
|
|
@@ -16477,6 +16523,14 @@ var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->", END_MARKER2
|
|
|
16477
16523
|
await writeFile10(temporary, source, { flag: "wx" });
|
|
16478
16524
|
await rename9(temporary, path);
|
|
16479
16525
|
return true;
|
|
16526
|
+
}, optionalSource = async (path) => {
|
|
16527
|
+
try {
|
|
16528
|
+
return await readFile12(path, "utf8");
|
|
16529
|
+
} catch (error) {
|
|
16530
|
+
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
|
|
16531
|
+
return null;
|
|
16532
|
+
throw error;
|
|
16533
|
+
}
|
|
16480
16534
|
}, managed = (source, region, insertion) => {
|
|
16481
16535
|
const start2 = source.indexOf(START_MARKER2);
|
|
16482
16536
|
const end = source.indexOf(END_MARKER2);
|
|
@@ -16505,6 +16559,129 @@ var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->", END_MARKER2
|
|
|
16505
16559
|
if (purpose === "location-always")
|
|
16506
16560
|
return `${appName} does not track location in the background; this description supports the foreground location provider required by the native runtime.`;
|
|
16507
16561
|
return `${appName} adds to your photo library only for photo actions you choose.`;
|
|
16562
|
+
}, privacyEntries = (requirements) => requirements.iosPrivacyAccessedApis.map(({ api, reasons }) => ` <dict>
|
|
16563
|
+
<key>NSPrivacyAccessedAPIType</key>
|
|
16564
|
+
<string>${escapeXml2(api)}</string>
|
|
16565
|
+
<key>NSPrivacyAccessedAPITypeReasons</key>
|
|
16566
|
+
<array>
|
|
16567
|
+
${reasons.map((reason) => ` <string>${escapeXml2(reason)}</string>`).join(`
|
|
16568
|
+
`)}
|
|
16569
|
+
</array>
|
|
16570
|
+
</dict>`).join(`
|
|
16571
|
+
`), privacyManifestSource = (source, requirements) => {
|
|
16572
|
+
const entries = privacyEntries(requirements);
|
|
16573
|
+
const wholeRegion = entries ? ` ${START_MARKER2}
|
|
16574
|
+
<key>NSPrivacyAccessedAPITypes</key>
|
|
16575
|
+
<array>
|
|
16576
|
+
${entries}
|
|
16577
|
+
</array>
|
|
16578
|
+
${END_MARKER2}
|
|
16579
|
+
` : "";
|
|
16580
|
+
if (source === null)
|
|
16581
|
+
return entries ? `<?xml version="1.0" encoding="UTF-8"?>
|
|
16582
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
16583
|
+
<plist version="1.0">
|
|
16584
|
+
<dict>
|
|
16585
|
+
${wholeRegion} <key>NSPrivacyCollectedDataTypes</key>
|
|
16586
|
+
<array/>
|
|
16587
|
+
<key>NSPrivacyTracking</key>
|
|
16588
|
+
<false/>
|
|
16589
|
+
</dict>
|
|
16590
|
+
</plist>
|
|
16591
|
+
` : null;
|
|
16592
|
+
const start2 = source.indexOf(START_MARKER2);
|
|
16593
|
+
if (start2 !== NOT_FOUND2) {
|
|
16594
|
+
const end = source.indexOf(END_MARKER2);
|
|
16595
|
+
if (end === NOT_FOUND2)
|
|
16596
|
+
throw new TypeError("AbsoluteJS device-capability ownership markers are malformed.");
|
|
16597
|
+
const owned = source.slice(start2, end);
|
|
16598
|
+
const ownsWholeKey = owned.includes("NSPrivacyAccessedAPITypes");
|
|
16599
|
+
let region = "";
|
|
16600
|
+
if (ownsWholeKey)
|
|
16601
|
+
region = wholeRegion;
|
|
16602
|
+
else if (entries)
|
|
16603
|
+
region = ` ${START_MARKER2}
|
|
16604
|
+
${entries}
|
|
16605
|
+
${END_MARKER2}
|
|
16606
|
+
`;
|
|
16607
|
+
return managed(source, region, source.lastIndexOf("</dict>"));
|
|
16608
|
+
}
|
|
16609
|
+
const key = source.indexOf("<key>NSPrivacyAccessedAPITypes</key>");
|
|
16610
|
+
if (key === NOT_FOUND2)
|
|
16611
|
+
return managed(source, wholeRegion, source.lastIndexOf("</dict>"));
|
|
16612
|
+
if (!entries)
|
|
16613
|
+
return source;
|
|
16614
|
+
const array = source.indexOf("<array>", key);
|
|
16615
|
+
if (array === NOT_FOUND2)
|
|
16616
|
+
throw new TypeError("iOS PrivacyInfo.xcprivacy has a malformed NSPrivacyAccessedAPITypes value.");
|
|
16617
|
+
const insertion = source.indexOf(`
|
|
16618
|
+
`, array);
|
|
16619
|
+
if (insertion === NOT_FOUND2)
|
|
16620
|
+
throw new TypeError("iOS PrivacyInfo.xcprivacy array is malformed.");
|
|
16621
|
+
return managed(source, ` ${START_MARKER2}
|
|
16622
|
+
${entries}
|
|
16623
|
+
${END_MARKER2}
|
|
16624
|
+
`, insertion + 1);
|
|
16625
|
+
}, writeIosPrivacyManifest = async (path, current, source) => {
|
|
16626
|
+
if (source === null)
|
|
16627
|
+
return false;
|
|
16628
|
+
if (current !== null)
|
|
16629
|
+
return writeChangedFile2(path, source);
|
|
16630
|
+
await writeFile10(path, source, { flag: "wx" });
|
|
16631
|
+
return true;
|
|
16632
|
+
}, configureIosPrivacyProject = async (config, requirements) => {
|
|
16633
|
+
if (requirements.iosPrivacyAccessedApis.length === 0)
|
|
16634
|
+
return false;
|
|
16635
|
+
const projectPath = join47(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
16636
|
+
const project = await readFile12(projectPath, "utf8");
|
|
16637
|
+
return writeChangedFile2(projectPath, addIosPrivacyProjectReference(project));
|
|
16638
|
+
}, addIosPrivacyProjectReference = (source) => {
|
|
16639
|
+
const fileMatch = source.match(/([A-F0-9]{24}) \/\* PrivacyInfo\.xcprivacy \*\/ = \{isa = PBXFileReference;/u);
|
|
16640
|
+
const fileReference = fileMatch?.[1] ?? IOS_PRIVACY_FILE_REFERENCE;
|
|
16641
|
+
const buildMatch = source.match(/([A-F0-9]{24}) \/\* PrivacyInfo\.xcprivacy in Resources \*\/ = \{isa = PBXBuildFile;/u);
|
|
16642
|
+
const buildFile = buildMatch?.[1] ?? IOS_PRIVACY_BUILD_FILE;
|
|
16643
|
+
if (!fileMatch && source.includes(fileReference) || !buildMatch && source.includes(buildFile))
|
|
16644
|
+
throw new TypeError("AbsoluteJS iOS privacy-manifest identifiers collide.");
|
|
16645
|
+
let next = source;
|
|
16646
|
+
if (!buildMatch) {
|
|
16647
|
+
const marker = "/* End PBXBuildFile section */";
|
|
16648
|
+
const index = next.indexOf(marker);
|
|
16649
|
+
if (index === NOT_FOUND2)
|
|
16650
|
+
throw new TypeError("Could not find the iOS PBXBuildFile section.");
|
|
16651
|
+
next = `${next.slice(0, index)} ${buildFile} /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = ${fileReference} /* PrivacyInfo.xcprivacy */; };
|
|
16652
|
+
${next.slice(index)}`;
|
|
16653
|
+
}
|
|
16654
|
+
if (!fileMatch) {
|
|
16655
|
+
const marker = "/* End PBXFileReference section */";
|
|
16656
|
+
const index = next.indexOf(marker);
|
|
16657
|
+
if (index === NOT_FOUND2)
|
|
16658
|
+
throw new TypeError("Could not find the iOS PBXFileReference section.");
|
|
16659
|
+
next = `${next.slice(0, index)} ${fileReference} /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
|
16660
|
+
${next.slice(index)}`;
|
|
16661
|
+
}
|
|
16662
|
+
const groupsStart = next.indexOf("/* Begin PBXGroup section */");
|
|
16663
|
+
const groupsEnd = next.indexOf("/* End PBXGroup section */");
|
|
16664
|
+
const groups = next.slice(groupsStart, groupsEnd);
|
|
16665
|
+
if (!groups.includes(`${fileReference} /* PrivacyInfo.xcprivacy */`)) {
|
|
16666
|
+
const appGroup = groups.match(/[A-F0-9]{24} \/\* App \*\/ = \{\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = \(\n/u);
|
|
16667
|
+
if (!appGroup || appGroup.index === undefined)
|
|
16668
|
+
throw new TypeError("Could not find the iOS App PBXGroup.");
|
|
16669
|
+
const index = groupsStart + appGroup.index + appGroup[0].length;
|
|
16670
|
+
next = `${next.slice(0, index)} ${fileReference} /* PrivacyInfo.xcprivacy */,
|
|
16671
|
+
${next.slice(index)}`;
|
|
16672
|
+
}
|
|
16673
|
+
const resourcesStart = next.indexOf("/* Begin PBXResourcesBuildPhase section */");
|
|
16674
|
+
const resourcesEnd = next.indexOf("/* End PBXResourcesBuildPhase section */");
|
|
16675
|
+
const resources = next.slice(resourcesStart, resourcesEnd);
|
|
16676
|
+
if (!resources.includes(`${buildFile} /* PrivacyInfo.xcprivacy in Resources */`)) {
|
|
16677
|
+
const files = resources.match(/isa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = \d+;\n\t\t\tfiles = \(\n/u);
|
|
16678
|
+
if (!files || files.index === undefined)
|
|
16679
|
+
throw new TypeError("Could not find the iOS Resources build phase.");
|
|
16680
|
+
const index = resourcesStart + files.index + files[0].length;
|
|
16681
|
+
next = `${next.slice(0, index)} ${buildFile} /* PrivacyInfo.xcprivacy in Resources */,
|
|
16682
|
+
${next.slice(index)}`;
|
|
16683
|
+
}
|
|
16684
|
+
return next;
|
|
16508
16685
|
}, configureIos2 = async (config, plan) => {
|
|
16509
16686
|
const path = join47(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
16510
16687
|
const source = await readFile12(path, "utf8");
|
|
@@ -16516,7 +16693,15 @@ var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->", END_MARKER2
|
|
|
16516
16693
|
${content}
|
|
16517
16694
|
${END_MARKER2}
|
|
16518
16695
|
` : "";
|
|
16519
|
-
|
|
16696
|
+
const infoChanged = await writeChangedFile2(path, managed(source, region, source.lastIndexOf("</dict>")));
|
|
16697
|
+
const privacyPath = join47(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
|
|
16698
|
+
const privacyCurrent = await optionalSource(privacyPath);
|
|
16699
|
+
const privacySource = privacyManifestSource(privacyCurrent, requirements);
|
|
16700
|
+
const [privacyChanged, projectChanged] = await Promise.all([
|
|
16701
|
+
writeIosPrivacyManifest(privacyPath, privacyCurrent, privacySource),
|
|
16702
|
+
configureIosPrivacyProject(config, requirements)
|
|
16703
|
+
]);
|
|
16704
|
+
return infoChanged || privacyChanged || projectChanged;
|
|
16520
16705
|
}, configureAndroid2 = async (config, plan) => {
|
|
16521
16706
|
const path = join47(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
16522
16707
|
const source = await readFile12(path, "utf8");
|
|
@@ -17706,24 +17891,25 @@ var init_iosConformance = __esm(() => {
|
|
|
17706
17891
|
HMR_LINE = new RegExp(String.raw`\[hmr:ios\]\s+([^\n]*?)\s+(applied in|falling back to reload after|failed after)\s+(\d+)ms(?:; server\s+(\d+)ms, client\s+(\d+)ms)?`, "u");
|
|
17707
17892
|
});
|
|
17708
17893
|
|
|
17709
|
-
// src/mobile/
|
|
17894
|
+
// src/mobile/nativeTestReport.ts
|
|
17710
17895
|
import { mkdir as mkdir13, readFile as readFile18, writeFile as writeFile15 } from "fs/promises";
|
|
17711
17896
|
import { join as join51 } from "path";
|
|
17712
|
-
var
|
|
17713
|
-
`, "<br>"),
|
|
17714
|
-
const { run
|
|
17715
|
-
const evidence = run.screenshot ? `
|
|
17897
|
+
var secretPattern, bearerPattern, coordinatePattern, sanitizeNativeReportText = (value) => value.replace(bearerPattern, "Bearer [REDACTED]").replace(secretPattern, "$1$2[REDACTED]").replace(coordinatePattern, "$1$2[REDACTED]").replace(/(https?:\/\/[^\s?#]+)[?#][^\s]*/giu, "$1?[REDACTED]"), markdownCell = (value) => sanitizeNativeReportText(value).replaceAll("|", "\\|").replaceAll(`
|
|
17898
|
+
`, "<br>"), createAbsoluteNativeAutomatedChecks = (run) => {
|
|
17899
|
+
const target = `${run.targetKind} ${run.targetId}`;
|
|
17900
|
+
const evidence = run.screenshot ? `Screenshot: ${run.screenshot}` : undefined;
|
|
17716
17901
|
let hmrResult = "NOT_RUN";
|
|
17717
17902
|
if (run.hmr)
|
|
17718
17903
|
hmrResult = run.hmr.outcome === "failed" ? "FAIL" : "PASS";
|
|
17719
|
-
const
|
|
17904
|
+
const routeDetails = run.routes?.length ? ` Routes: ${run.routes.join(", ")}.` : "";
|
|
17905
|
+
return [
|
|
17720
17906
|
{
|
|
17721
|
-
details: `Captured
|
|
17907
|
+
details: `Captured host, toolchain, Bun, and AbsoluteJS metadata for ${target}.`,
|
|
17722
17908
|
id: "AUTO-SETUP-01",
|
|
17723
17909
|
result: "PASS"
|
|
17724
17910
|
},
|
|
17725
17911
|
{
|
|
17726
|
-
details: run.status === "pass" ? `The app
|
|
17912
|
+
details: run.status === "pass" ? `The app launched and connected to native HMR in ${run.durationMs}ms.${routeDetails}` : `The automated native run failed after ${run.durationMs}ms: ${run.error ?? "No error detail was available."}`,
|
|
17727
17913
|
...evidence ? { evidence } : {},
|
|
17728
17914
|
id: "AUTO-DEV-01",
|
|
17729
17915
|
result: run.status === "pass" ? "PASS" : "FAIL"
|
|
@@ -17734,55 +17920,46 @@ var MANUAL_CHECKS, secretPattern, bearerPattern, coordinatePattern, sanitizeIosR
|
|
|
17734
17920
|
result: hmrResult
|
|
17735
17921
|
},
|
|
17736
17922
|
{
|
|
17737
|
-
details: run.screenshot ? "A
|
|
17923
|
+
details: run.screenshot ? "A target screenshot was captured. Visually review it before sharing this directory." : "No target screenshot was captured.",
|
|
17738
17924
|
...evidence ? { evidence } : {},
|
|
17739
17925
|
id: "AUTO-ARTIFACT-01",
|
|
17740
17926
|
result: run.screenshot ? "PASS" : "FAIL"
|
|
17741
17927
|
}
|
|
17742
17928
|
];
|
|
17743
|
-
|
|
17929
|
+
}, createAbsoluteNativeTestReport = (options) => ({
|
|
17930
|
+
automatedChecks: options.automatedChecks ?? createAbsoluteNativeAutomatedChecks(options.run),
|
|
17931
|
+
generatedAt: options.generatedAt ?? new Date().toISOString(),
|
|
17932
|
+
manualChecks: options.manualChecks.map(([id, details]) => ({
|
|
17744
17933
|
details,
|
|
17745
17934
|
id,
|
|
17746
17935
|
result: "NOT_RUN"
|
|
17747
|
-
}))
|
|
17748
|
-
|
|
17749
|
-
|
|
17750
|
-
|
|
17751
|
-
|
|
17752
|
-
|
|
17753
|
-
|
|
17754
|
-
bunVersion: options.bunVersion,
|
|
17755
|
-
macosVersion: options.macosVersion,
|
|
17756
|
-
provider: "capacitor",
|
|
17757
|
-
xcodeVersion: options.xcodeVersion
|
|
17758
|
-
},
|
|
17759
|
-
overallResult: run.status === "fail" ? "FAIL" : "INCOMPLETE",
|
|
17760
|
-
platform: "ios",
|
|
17761
|
-
reportVersion: 1,
|
|
17762
|
-
run
|
|
17763
|
-
};
|
|
17764
|
-
}, readPackageVersionForIosReport = async (packageJsonPath) => {
|
|
17936
|
+
})),
|
|
17937
|
+
metadata: options.metadata,
|
|
17938
|
+
overallResult: options.run.status === "fail" ? "FAIL" : "INCOMPLETE",
|
|
17939
|
+
platform: options.run.platform,
|
|
17940
|
+
reportVersion: 1,
|
|
17941
|
+
run: options.run
|
|
17942
|
+
}), readPackageVersionForNativeReport = async (packageJsonPath) => {
|
|
17765
17943
|
const manifest = JSON.parse(await readFile18(packageJsonPath, "utf8"));
|
|
17766
17944
|
if (typeof manifest !== "object" || manifest === null)
|
|
17767
17945
|
return "unknown";
|
|
17768
17946
|
const version2 = Reflect.get(manifest, "version");
|
|
17769
17947
|
return typeof version2 === "string" ? version2 : "unknown";
|
|
17770
|
-
},
|
|
17948
|
+
}, renderAbsoluteNativeTestReport = (report) => {
|
|
17771
17949
|
const table = (checks) => checks.map((check2) => `| ${check2.id} | ${check2.result} | ${markdownCell(check2.details)} | ${markdownCell(check2.evidence ?? "")} |`).join(`
|
|
17772
17950
|
`);
|
|
17773
|
-
|
|
17951
|
+
const metadata = Object.entries(report.metadata).sort(([left], [right]) => left.localeCompare(right)).map(([key, value]) => `- ${key}: ${markdownCell(value)}`).join(`
|
|
17952
|
+
`);
|
|
17953
|
+
return `# AbsoluteJS ${report.platform} test report
|
|
17774
17954
|
|
|
17775
17955
|
- Overall result: ${report.overallResult}
|
|
17776
17956
|
- Generated: ${report.generatedAt}
|
|
17777
|
-
- AbsoluteJS: ${markdownCell(report.metadata.absolutejsVersion)}
|
|
17778
|
-
- macOS: ${markdownCell(report.metadata.macosVersion)}
|
|
17779
|
-
- Xcode: ${markdownCell(report.metadata.xcodeVersion)}
|
|
17780
|
-
- Bun: ${markdownCell(report.metadata.bunVersion)}
|
|
17781
17957
|
- App bundle ID: ${markdownCell(report.run.appId)}
|
|
17782
|
-
-
|
|
17958
|
+
- Target: ${report.run.targetKind} ${markdownCell(report.run.targetId)}
|
|
17783
17959
|
- Automated run: ${report.run.status.toUpperCase()} (${report.run.durationMs}ms)
|
|
17960
|
+
${metadata}
|
|
17784
17961
|
|
|
17785
|
-
|
|
17962
|
+
This report is local and is never uploaded by AbsoluteJS. Before sharing its directory, visually inspect screenshots and logs. Never add passwords, signing material, tokens, cookies, private Sync data, or exact coordinates.
|
|
17786
17963
|
|
|
17787
17964
|
## Automated checks
|
|
17788
17965
|
|
|
@@ -17790,26 +17967,54 @@ var MANUAL_CHECKS, secretPattern, bearerPattern, coordinatePattern, sanitizeIosR
|
|
|
17790
17967
|
| --- | --- | --- | --- |
|
|
17791
17968
|
${table(report.automatedChecks)}
|
|
17792
17969
|
|
|
17793
|
-
##
|
|
17970
|
+
## Manual checklist
|
|
17794
17971
|
|
|
17795
|
-
Replace each \`NOT_RUN\` with \`PASS\`, \`FAIL\`, or \`SKIPPED\` after
|
|
17972
|
+
Replace each \`NOT_RUN\` with \`PASS\`, \`FAIL\`, or \`SKIPPED\` after completing the platform runbook. A failure must name sanitized evidence and state actual versus expected behavior.
|
|
17796
17973
|
|
|
17797
17974
|
| Test ID | Result | Observed result / timing | Evidence or failure details |
|
|
17798
17975
|
| --- | --- | --- | --- |
|
|
17799
17976
|
${table(report.manualChecks)}
|
|
17800
17977
|
`;
|
|
17801
|
-
},
|
|
17978
|
+
}, writeAbsoluteNativeTestReport = async (directory, report) => {
|
|
17802
17979
|
await mkdir13(directory, { recursive: true });
|
|
17803
17980
|
const jsonPath = join51(directory, "report.json");
|
|
17804
17981
|
const markdownPath = join51(directory, "report.md");
|
|
17805
17982
|
await Promise.all([
|
|
17806
17983
|
writeFile15(jsonPath, `${JSON.stringify(report, null, 2)}
|
|
17807
17984
|
`),
|
|
17808
|
-
writeFile15(markdownPath,
|
|
17985
|
+
writeFile15(markdownPath, renderAbsoluteNativeTestReport(report))
|
|
17809
17986
|
]);
|
|
17810
17987
|
return { directory, jsonPath, markdownPath };
|
|
17811
17988
|
};
|
|
17989
|
+
var init_nativeTestReport = __esm(() => {
|
|
17990
|
+
secretPattern = /(authorization|access[_ -]?token|refresh[_ -]?token|socket[_ -]?ticket|password|cookie)(\s*[=:]\s*)([^\s,;]+)/giu;
|
|
17991
|
+
bearerPattern = /bearer\s+[^\s,;]+/giu;
|
|
17992
|
+
coordinatePattern = /\b(latitude|longitude|lat|lng)(\s*[=:]\s*)-?\d+(?:\.\d+)?/giu;
|
|
17993
|
+
});
|
|
17994
|
+
|
|
17995
|
+
// src/mobile/iosTestReport.ts
|
|
17996
|
+
var MANUAL_CHECKS, readPackageVersionForIosReport, sanitizeIosReportText, writeAbsoluteIosPartnerReport, createAbsoluteIosPartnerReport = (options) => {
|
|
17997
|
+
const { udid, ...run } = options.run;
|
|
17998
|
+
return createAbsoluteNativeTestReport({
|
|
17999
|
+
...options.generatedAt ? { generatedAt: options.generatedAt } : {},
|
|
18000
|
+
manualChecks: MANUAL_CHECKS,
|
|
18001
|
+
metadata: {
|
|
18002
|
+
absolutejsVersion: options.absolutejsVersion,
|
|
18003
|
+
bunVersion: options.bunVersion,
|
|
18004
|
+
macosVersion: options.macosVersion,
|
|
18005
|
+
provider: "capacitor",
|
|
18006
|
+
xcodeVersion: options.xcodeVersion
|
|
18007
|
+
},
|
|
18008
|
+
run: {
|
|
18009
|
+
...run,
|
|
18010
|
+
platform: "ios",
|
|
18011
|
+
targetId: udid,
|
|
18012
|
+
targetKind: "simulator"
|
|
18013
|
+
}
|
|
18014
|
+
});
|
|
18015
|
+
};
|
|
17812
18016
|
var init_iosTestReport = __esm(() => {
|
|
18017
|
+
init_nativeTestReport();
|
|
17813
18018
|
MANUAL_CHECKS = [
|
|
17814
18019
|
[
|
|
17815
18020
|
"SETUP-01",
|
|
@@ -17822,6 +18027,10 @@ var init_iosTestReport = __esm(() => {
|
|
|
17822
18027
|
["DEV-01", "Record cold and warm bun dev startup timings."],
|
|
17823
18028
|
["DEV-02", "Complete route traversal, HMR, relaunch, and recovery checks."],
|
|
17824
18029
|
["CAP-01", "Complete automatic device-capability provisioning checks."],
|
|
18030
|
+
...Array.from({ length: 8 }, (_, index) => [
|
|
18031
|
+
`FILES-${String(index + 1).padStart(2, "0")}`,
|
|
18032
|
+
`Complete provider-neutral Documents runbook check FILES-${String(index + 1).padStart(2, "0")}.`
|
|
18033
|
+
]),
|
|
17825
18034
|
...Array.from({ length: 14 }, (_, index) => [
|
|
17826
18035
|
`LOC-${String(index + 1).padStart(2, "0")}`,
|
|
17827
18036
|
`Complete foreground-location runbook check LOC-${String(index + 1).padStart(2, "0")} without recording exact coordinates.`
|
|
@@ -17847,9 +18056,61 @@ var init_iosTestReport = __esm(() => {
|
|
|
17847
18056
|
"Review this directory for sensitive content and complete every row."
|
|
17848
18057
|
]
|
|
17849
18058
|
];
|
|
17850
|
-
|
|
17851
|
-
|
|
17852
|
-
|
|
18059
|
+
readPackageVersionForIosReport = readPackageVersionForNativeReport;
|
|
18060
|
+
sanitizeIosReportText = sanitizeNativeReportText;
|
|
18061
|
+
writeAbsoluteIosPartnerReport = writeAbsoluteNativeTestReport;
|
|
18062
|
+
});
|
|
18063
|
+
|
|
18064
|
+
// src/mobile/androidTestReport.ts
|
|
18065
|
+
var MANUAL_CHECKS2, createAbsoluteAndroidTestReport = (options) => {
|
|
18066
|
+
const { serial, ...run } = options.run;
|
|
18067
|
+
return createAbsoluteNativeTestReport({
|
|
18068
|
+
...options.generatedAt ? { generatedAt: options.generatedAt } : {},
|
|
18069
|
+
manualChecks: MANUAL_CHECKS2,
|
|
18070
|
+
metadata: {
|
|
18071
|
+
absolutejsVersion: options.absolutejsVersion,
|
|
18072
|
+
adbVersion: options.adbVersion,
|
|
18073
|
+
bunVersion: options.bunVersion,
|
|
18074
|
+
host: options.host,
|
|
18075
|
+
provider: "capacitor"
|
|
18076
|
+
},
|
|
18077
|
+
run: {
|
|
18078
|
+
...run,
|
|
18079
|
+
platform: "android",
|
|
18080
|
+
targetId: serial,
|
|
18081
|
+
targetKind: serial.startsWith("emulator-") ? "emulator" : "device"
|
|
18082
|
+
}
|
|
18083
|
+
});
|
|
18084
|
+
};
|
|
18085
|
+
var init_androidTestReport = __esm(() => {
|
|
18086
|
+
init_nativeTestReport();
|
|
18087
|
+
MANUAL_CHECKS2 = [
|
|
18088
|
+
[
|
|
18089
|
+
"SETUP-01",
|
|
18090
|
+
"Confirm Android SDK, emulator/device, Bun, and package versions."
|
|
18091
|
+
],
|
|
18092
|
+
["DEV-01", "Record cold and warm native startup timings."],
|
|
18093
|
+
["DEV-02", "Complete route traversal, HMR, relaunch, and recovery checks."],
|
|
18094
|
+
["CAP-01", "Complete automatic device-capability provisioning checks."],
|
|
18095
|
+
[
|
|
18096
|
+
"FILES-01",
|
|
18097
|
+
"Complete provider-neutral file pick, export, open, and cleanup checks."
|
|
18098
|
+
],
|
|
18099
|
+
[
|
|
18100
|
+
"AUTH-01",
|
|
18101
|
+
"Complete system-browser sign-in, callback, restore, and sign-out checks."
|
|
18102
|
+
],
|
|
18103
|
+
[
|
|
18104
|
+
"SYNC-01",
|
|
18105
|
+
"Complete online, offline, reconnect, isolation, and conflict checks."
|
|
18106
|
+
],
|
|
18107
|
+
["BGSYNC-01", "Complete WorkManager background Sync acceptance."],
|
|
18108
|
+
["BUILD-01", "Pass release doctor and produce a signed AAB."],
|
|
18109
|
+
[
|
|
18110
|
+
"REPORT-01",
|
|
18111
|
+
"Review this directory for sensitive content and complete every row."
|
|
18112
|
+
]
|
|
18113
|
+
];
|
|
17853
18114
|
});
|
|
17854
18115
|
|
|
17855
18116
|
// src/mobile/releasePublisher.ts
|
|
@@ -18728,7 +18989,8 @@ Emulator setup verification:`);
|
|
|
18728
18989
|
const routes = valuesAfter(args, "--route");
|
|
18729
18990
|
if (routes.length === 0)
|
|
18730
18991
|
routes.push(mobile.entry);
|
|
18731
|
-
const
|
|
18992
|
+
const reportRoot = nativeReportRoot(args, projectRoot, "android");
|
|
18993
|
+
const artifactRoot = reportRoot ?? safeArtifactRoot(projectRoot, valueAfter(args, "--artifacts"));
|
|
18732
18994
|
const startedAt = performance.now();
|
|
18733
18995
|
let session;
|
|
18734
18996
|
try {
|
|
@@ -18767,6 +19029,30 @@ Emulator setup verification:`);
|
|
|
18767
19029
|
console.log(JSON.stringify(report, null, 2));
|
|
18768
19030
|
else
|
|
18769
19031
|
printAndroidTestReport(report);
|
|
19032
|
+
const screenshot = reportRoot ? await session.screenshot(join52(artifactRoot, "android-emulator.png")) : undefined;
|
|
19033
|
+
await writeRequestedAndroidReport({
|
|
19034
|
+
adb,
|
|
19035
|
+
args,
|
|
19036
|
+
projectRoot,
|
|
19037
|
+
run: {
|
|
19038
|
+
appId: mobile.appId,
|
|
19039
|
+
durationMs: report.durationMs,
|
|
19040
|
+
...hmrApply ? {
|
|
19041
|
+
hmr: {
|
|
19042
|
+
clientMs: hmrApply.clientMs,
|
|
19043
|
+
durationMs: hmrApply.duration,
|
|
19044
|
+
outcome: hmrApply.outcome,
|
|
19045
|
+
serverMs: hmrApply.serverMs
|
|
19046
|
+
}
|
|
19047
|
+
} : {},
|
|
19048
|
+
hmrConnected: true,
|
|
19049
|
+
port,
|
|
19050
|
+
routes: checks.map(({ route }) => route),
|
|
19051
|
+
...screenshot ? { screenshot } : {},
|
|
19052
|
+
serial,
|
|
19053
|
+
status: "pass"
|
|
19054
|
+
}
|
|
19055
|
+
});
|
|
18770
19056
|
return report;
|
|
18771
19057
|
} catch (error) {
|
|
18772
19058
|
const durationMs = Math.round(performance.now() - startedAt);
|
|
@@ -18785,6 +19071,22 @@ Emulator setup verification:`);
|
|
|
18785
19071
|
serial,
|
|
18786
19072
|
session
|
|
18787
19073
|
});
|
|
19074
|
+
await writeRequestedAndroidReport({
|
|
19075
|
+
adb,
|
|
19076
|
+
args,
|
|
19077
|
+
projectRoot,
|
|
19078
|
+
run: {
|
|
19079
|
+
appId: mobile.appId,
|
|
19080
|
+
durationMs,
|
|
19081
|
+
error: sanitizeNativeReportText(error instanceof Error ? error.message : String(error)),
|
|
19082
|
+
hmrConnected: false,
|
|
19083
|
+
port,
|
|
19084
|
+
routes,
|
|
19085
|
+
...screenshot ? { screenshot } : {},
|
|
19086
|
+
serial,
|
|
19087
|
+
status: "fail"
|
|
19088
|
+
}
|
|
19089
|
+
});
|
|
18788
19090
|
throw new Error(`${error instanceof Error ? error.message : String(error)} Failure diagnostics: ${diagnosticPath}${screenshot ? `; screenshot: ${screenshot}` : ""}`, { cause: error });
|
|
18789
19091
|
} finally {
|
|
18790
19092
|
await session?.close();
|
|
@@ -18875,7 +19177,7 @@ Emulator setup verification:`);
|
|
|
18875
19177
|
if (!selected)
|
|
18876
19178
|
throw new TypeError("No ready AbsoluteJS iOS simulator was found. Start `bun dev` and wait for the iOS target to become ready.");
|
|
18877
19179
|
return selected;
|
|
18878
|
-
},
|
|
19180
|
+
}, requireCapturedCommand = (command, label) => {
|
|
18879
19181
|
const result = captureCommand4(command);
|
|
18880
19182
|
if (result.exitCode !== 0)
|
|
18881
19183
|
throw new Error(`${label} failed: ${result.stderr.trim() || result.stdout.trim() || `status ${result.exitCode}`}`);
|
|
@@ -18906,37 +19208,56 @@ Emulator setup verification:`);
|
|
|
18906
19208
|
diagnosticPath,
|
|
18907
19209
|
screenshot: screenshotResult.exitCode === 0 ? screenshot : undefined
|
|
18908
19210
|
};
|
|
18909
|
-
},
|
|
19211
|
+
}, nativeReportRoot = (args, projectRoot, platform6) => {
|
|
18910
19212
|
const index = args.indexOf("--report");
|
|
18911
19213
|
if (index === NOT_FOUND3)
|
|
18912
19214
|
return;
|
|
18913
19215
|
const candidate = args[index + 1];
|
|
18914
19216
|
const explicit = candidate?.startsWith("--") ? undefined : candidate;
|
|
18915
19217
|
const timestamp = new Date().toISOString().replaceAll(":", "-");
|
|
18916
|
-
return safeArtifactRoot(projectRoot, explicit ?? `.absolutejs/mobile/test-reports
|
|
18917
|
-
},
|
|
18918
|
-
const xcodebuildPath = requireCapturedIosCommand([xcrun, "--find", "xcodebuild"], "Xcode version inspection").stdout.trim();
|
|
18919
|
-
const xcodeVersion = requireCapturedIosCommand([xcodebuildPath, "-version"], "Xcode version inspection").stdout.trim();
|
|
18920
|
-
const macosVersion = requireCapturedIosCommand(["/usr/bin/sw_vers", "-productVersion"], "macOS version inspection").stdout.trim();
|
|
19218
|
+
return safeArtifactRoot(projectRoot, explicit ?? `.absolutejs/mobile/test-reports/${platform6}-${timestamp}`);
|
|
19219
|
+
}, absolutejsVersionForReport = async () => {
|
|
18921
19220
|
let absolutejsVersion = process.env.ABSOLUTE_VERSION ?? "unknown";
|
|
18922
|
-
|
|
19221
|
+
const versions = await Promise.all([
|
|
18923
19222
|
resolve41(import.meta.dir, "..", "..", "package.json"),
|
|
18924
19223
|
resolve41(import.meta.dir, "..", "..", "..", "package.json")
|
|
18925
|
-
])
|
|
18926
|
-
|
|
19224
|
+
].map((candidate) => readPackageVersionForIosReport(candidate).catch(() => "unknown")));
|
|
19225
|
+
for (const version2 of versions) {
|
|
18927
19226
|
if (version2 === "unknown")
|
|
18928
19227
|
continue;
|
|
18929
19228
|
absolutejsVersion = version2;
|
|
18930
19229
|
break;
|
|
18931
19230
|
}
|
|
19231
|
+
return absolutejsVersion;
|
|
19232
|
+
}, writeRequestedAndroidReport = async (options) => {
|
|
19233
|
+
const reportRoot = nativeReportRoot(options.args, options.projectRoot, "android");
|
|
19234
|
+
if (!reportRoot)
|
|
19235
|
+
return;
|
|
19236
|
+
const adbVersion = requireCapturedCommand([options.adb, "version"], "ADB version inspection").stdout.trim();
|
|
19237
|
+
const report = createAbsoluteAndroidTestReport({
|
|
19238
|
+
absolutejsVersion: await absolutejsVersionForReport(),
|
|
19239
|
+
adbVersion,
|
|
19240
|
+
bunVersion: Bun.version,
|
|
19241
|
+
host: `${process.platform}-${process.arch}`,
|
|
19242
|
+
run: options.run
|
|
19243
|
+
});
|
|
19244
|
+
const paths = await writeAbsoluteNativeTestReport(reportRoot, report);
|
|
19245
|
+
const print = options.args.includes("--json") ? console.error : console.log;
|
|
19246
|
+
print(`Android test report: ${paths.markdownPath}`);
|
|
19247
|
+
print(`Return this report directory: ${paths.directory}`);
|
|
19248
|
+
return paths;
|
|
19249
|
+
}, iosReportMetadata = async (xcrun) => {
|
|
19250
|
+
const xcodebuildPath = requireCapturedCommand([xcrun, "--find", "xcodebuild"], "Xcode version inspection").stdout.trim();
|
|
19251
|
+
const xcodeVersion = requireCapturedCommand([xcodebuildPath, "-version"], "Xcode version inspection").stdout.trim();
|
|
19252
|
+
const macosVersion = requireCapturedCommand(["/usr/bin/sw_vers", "-productVersion"], "macOS version inspection").stdout.trim();
|
|
18932
19253
|
return {
|
|
18933
|
-
absolutejsVersion,
|
|
19254
|
+
absolutejsVersion: await absolutejsVersionForReport(),
|
|
18934
19255
|
bunVersion: Bun.version,
|
|
18935
19256
|
macosVersion,
|
|
18936
19257
|
xcodeVersion
|
|
18937
19258
|
};
|
|
18938
19259
|
}, writeRequestedIosReport = async (options) => {
|
|
18939
|
-
const reportRoot =
|
|
19260
|
+
const reportRoot = nativeReportRoot(options.args, options.projectRoot, "ios");
|
|
18940
19261
|
if (!reportRoot)
|
|
18941
19262
|
return;
|
|
18942
19263
|
const metadata = await iosReportMetadata(options.xcrun);
|
|
@@ -18955,11 +19276,11 @@ Emulator setup verification:`);
|
|
|
18955
19276
|
const timeoutMs = androidTestTimeout(args);
|
|
18956
19277
|
const xcrun = await requireIosXcrun();
|
|
18957
19278
|
const simulator = selectIosSimulator(xcrun, valueAfter(args, "--udid") ?? valueAfter(args, "--serial"));
|
|
18958
|
-
const reportRoot =
|
|
19279
|
+
const reportRoot = nativeReportRoot(args, projectRoot, "ios");
|
|
18959
19280
|
const artifactRoot = reportRoot ?? safeArtifactRoot(projectRoot, valueAfter(args, "--artifacts"));
|
|
18960
19281
|
const startedAt = performance.now();
|
|
18961
19282
|
try {
|
|
18962
|
-
|
|
19283
|
+
requireCapturedCommand([
|
|
18963
19284
|
xcrun,
|
|
18964
19285
|
"simctl",
|
|
18965
19286
|
"get_app_container",
|
|
@@ -18967,7 +19288,7 @@ Emulator setup verification:`);
|
|
|
18967
19288
|
mobile.appId,
|
|
18968
19289
|
"app"
|
|
18969
19290
|
], "iOS installed-app inspection");
|
|
18970
|
-
|
|
19291
|
+
requireCapturedCommand([
|
|
18971
19292
|
xcrun,
|
|
18972
19293
|
"simctl",
|
|
18973
19294
|
"launch",
|
|
@@ -18978,7 +19299,7 @@ Emulator setup verification:`);
|
|
|
18978
19299
|
await waitForIosHmrClient({ https, port, timeoutMs });
|
|
18979
19300
|
await mkdir14(artifactRoot, { recursive: true });
|
|
18980
19301
|
const screenshot = join52(artifactRoot, "ios-simulator.png");
|
|
18981
|
-
|
|
19302
|
+
requireCapturedCommand([xcrun, "simctl", "io", simulator.udid, "screenshot", screenshot], "iOS simulator screenshot");
|
|
18982
19303
|
const hmrApply = await waitForRequestedIosHmr(args, instance, timeoutMs);
|
|
18983
19304
|
const report = {
|
|
18984
19305
|
appId: mobile.appId,
|
|
@@ -19111,7 +19432,7 @@ Emulator setup verification:`);
|
|
|
19111
19432
|
await publishIos(args.slice(2));
|
|
19112
19433
|
return;
|
|
19113
19434
|
}
|
|
19114
|
-
throw new TypeError("Usage: absolute mobile <pair mac <name> <user@host> [--port n] [--workspace path] | remotes [--json] | unpair mac <name> | init [--no-native] [--force] | sync [ios|android] | associations [--outdir dir] [--verify] | doctor [ios|android|release] [--remote name] [--json|--fix [--yes]] | build <android|ios> [server-entry] [--outdir dir] [--web-outdir dir] [--unsigned] | publish android [server-entry] [--registry module] [--channel name] [--play-track track] [--play-status completed|draft|halted|in-progress] [--play-rollout fraction] [--play-name name] [--play-notes language=text] [--play-update-priority 0..5] [--play-hold-review] [--play-cancel-existing-review] [--outdir dir] [--web-outdir dir] [--unsigned] | publish ios [server-entry] [--registry module] [--channel name] [--testflight-group name-or-id] [--testflight-notes locale=text] [--testflight-submit-review] [--outdir dir] [--web-outdir dir] [--unsigned] | test android [--route path] [--wait-for-hmr] [--timeout ms] [--port n] [--serial id] [--artifacts dir] [--json] | test ios [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--udid id] [--artifacts dir] [--json]> [--config path]");
|
|
19435
|
+
throw new TypeError("Usage: absolute mobile <pair mac <name> <user@host> [--port n] [--workspace path] | remotes [--json] | unpair mac <name> | init [--no-native] [--force] | sync [ios|android] | associations [--outdir dir] [--verify] | doctor [ios|android|release] [--remote name] [--json|--fix [--yes]] | build <android|ios> [server-entry] [--outdir dir] [--web-outdir dir] [--unsigned] | publish android [server-entry] [--registry module] [--channel name] [--play-track track] [--play-status completed|draft|halted|in-progress] [--play-rollout fraction] [--play-name name] [--play-notes language=text] [--play-update-priority 0..5] [--play-hold-review] [--play-cancel-existing-review] [--outdir dir] [--web-outdir dir] [--unsigned] | publish ios [server-entry] [--registry module] [--channel name] [--testflight-group name-or-id] [--testflight-notes locale=text] [--testflight-submit-review] [--outdir dir] [--web-outdir dir] [--unsigned] | test android [--route path] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--serial id] [--artifacts dir] [--json] | test ios [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--udid id] [--artifacts dir] [--json]> [--config path]");
|
|
19115
19436
|
};
|
|
19116
19437
|
var init_mobile = __esm(() => {
|
|
19117
19438
|
init_dependencies();
|
|
@@ -19134,6 +19455,8 @@ var init_mobile = __esm(() => {
|
|
|
19134
19455
|
init_iosSimulatorController();
|
|
19135
19456
|
init_iosConformance();
|
|
19136
19457
|
init_iosTestReport();
|
|
19458
|
+
init_androidTestReport();
|
|
19459
|
+
init_nativeTestReport();
|
|
19137
19460
|
init_releasePublisher();
|
|
19138
19461
|
init_start();
|
|
19139
19462
|
init_utils();
|
|
@@ -19163,8 +19486,8 @@ var init_mobile = __esm(() => {
|
|
|
19163
19486
|
"@capacitor/cli@8.5.0",
|
|
19164
19487
|
"@capacitor/android@8.5.0",
|
|
19165
19488
|
"@capacitor/ios@8.5.0",
|
|
19166
|
-
"@absolutejs/devices@0.
|
|
19167
|
-
"@absolutejs/devices-capacitor@0.
|
|
19489
|
+
"@absolutejs/devices@0.4.0",
|
|
19490
|
+
"@absolutejs/devices-capacitor@0.5.0"
|
|
19168
19491
|
];
|
|
19169
19492
|
CAPACITOR_SYNC_PACKAGE_SPECS = [
|
|
19170
19493
|
"@absolutejs/sync-capacitor@0.9.1",
|