@absolutejs/absolute 0.20.0-beta.49 → 0.20.0-beta.50
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 +163 -38
- package/dist/mobile/index.js +53 -9
- package/dist/mobile/index.js.map +4 -4
- package/dist/mobile/remoteMacAgentEntry.js +60 -60
- package/dist/src/mobile/iosRelease.d.ts +12 -2
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
var __require = import.meta.require;
|
|
3
3
|
|
|
4
|
-
// .angular-partial-tmp-
|
|
4
|
+
// .angular-partial-tmp-fjProX/src/core/streamingSlotRegistrar.ts
|
|
5
5
|
var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
|
|
6
6
|
var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
|
|
7
7
|
var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
var __require = import.meta.require;
|
|
3
3
|
|
|
4
|
-
// .angular-partial-tmp-
|
|
4
|
+
// .angular-partial-tmp-fjProX/src/core/streamingSlotRegistrar.ts
|
|
5
5
|
var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
|
|
6
6
|
var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
|
|
7
7
|
var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
|
|
@@ -48,7 +48,7 @@ var warnMissingStreamingSlotCollector = (primitiveName) => {
|
|
|
48
48
|
getWarningController()?.maybeWarn(primitiveName);
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
-
// .angular-partial-tmp-
|
|
51
|
+
// .angular-partial-tmp-fjProX/src/core/streamingSlotRegistry.ts
|
|
52
52
|
var STREAMING_SLOT_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotAsyncLocalStorage");
|
|
53
53
|
var isObjectRecord2 = (value) => Boolean(value) && typeof value === "object";
|
|
54
54
|
var isAsyncLocalStorage = (value) => isObjectRecord2(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
|
package/dist/cli/index.js
CHANGED
|
@@ -4791,6 +4791,45 @@ var developmentTeamArgument = (value) => {
|
|
|
4791
4791
|
return entry.isDirectory() ? findByExtension(path, extension) : undefined;
|
|
4792
4792
|
}));
|
|
4793
4793
|
return matches.find((match) => match !== undefined);
|
|
4794
|
+
}, findAllByExtension = async (root, extension, options = {}) => {
|
|
4795
|
+
if (!await pathExists3(root))
|
|
4796
|
+
return [];
|
|
4797
|
+
const entries = await readdir3(root, { withFileTypes: true });
|
|
4798
|
+
const matches = await Promise.all(entries.map(async (entry) => {
|
|
4799
|
+
const path = join13(root, entry.name);
|
|
4800
|
+
if (entry.name.endsWith(extension))
|
|
4801
|
+
return [path];
|
|
4802
|
+
if (!entry.isDirectory() || options.excludedDirectories?.has(entry.name))
|
|
4803
|
+
return [];
|
|
4804
|
+
return findAllByExtension(path, extension, options);
|
|
4805
|
+
}));
|
|
4806
|
+
return matches.flat().sort();
|
|
4807
|
+
}, resolveAbsoluteIosXcodeProject = async (nativeDirectory, options = {}) => {
|
|
4808
|
+
const requestedWorkspace = options.workspacePath ? resolve9(nativeDirectory, options.workspacePath) : undefined;
|
|
4809
|
+
if (requestedWorkspace) {
|
|
4810
|
+
const requestedRelative = relative5(nativeDirectory, requestedWorkspace);
|
|
4811
|
+
if (requestedRelative === ".." || requestedRelative.startsWith(`..${sep3}`) || isAbsolute2(requestedRelative))
|
|
4812
|
+
throw new TypeError("iOS release workspacePath must remain inside the native iOS project.");
|
|
4813
|
+
}
|
|
4814
|
+
const workspaces = requestedWorkspace ? [requestedWorkspace] : await findAllByExtension(nativeDirectory, ".xcworkspace", {
|
|
4815
|
+
excludedDirectories: new Set(["Pods", "DerivedData", "build"])
|
|
4816
|
+
});
|
|
4817
|
+
if (workspaces.length !== 1)
|
|
4818
|
+
throw new TypeError(workspaces.length > 1 ? `iOS release found multiple Xcode workspaces: ${workspaces.map((path) => relative5(nativeDirectory, path)).join(", ")}. Pass an explicit workspacePath.` : "iOS release could not find an Xcode workspace.");
|
|
4819
|
+
const [workspacePath] = workspaces;
|
|
4820
|
+
if (!workspacePath || !await pathExists3(workspacePath))
|
|
4821
|
+
throw new TypeError("iOS release could not find an Xcode workspace.");
|
|
4822
|
+
if (options.scheme)
|
|
4823
|
+
return { scheme: options.scheme, workspacePath };
|
|
4824
|
+
const schemeFiles = await findAllByExtension(nativeDirectory, ".xcscheme", {
|
|
4825
|
+
excludedDirectories: new Set(["Pods", "DerivedData", "build"])
|
|
4826
|
+
});
|
|
4827
|
+
const schemes = [
|
|
4828
|
+
...new Set(schemeFiles.map((path) => path.slice(path.lastIndexOf(sep3) + 1, -".xcscheme".length)))
|
|
4829
|
+
];
|
|
4830
|
+
if (schemes.length !== 1 || !schemes[0])
|
|
4831
|
+
throw new TypeError(schemes.length > 1 ? `iOS release found multiple shared Xcode schemes: ${schemes.join(", ")}. Pass an explicit scheme.` : "iOS release could not find a shared Xcode scheme.");
|
|
4832
|
+
return { scheme: schemes[0], workspacePath };
|
|
4794
4833
|
}, exportOptions = () => `<?xml version="1.0" encoding="UTF-8"?>
|
|
4795
4834
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
4796
4835
|
<plist version="1.0"><dict>
|
|
@@ -4857,6 +4896,10 @@ var developmentTeamArgument = (value) => {
|
|
|
4857
4896
|
if (manifest.appId !== options.config.appId)
|
|
4858
4897
|
throw new TypeError("Embedded mobile manifest appId does not match mobile.appId.");
|
|
4859
4898
|
const nativeDirectory = join13(options.config.nativeProjectDirectory, "ios");
|
|
4899
|
+
const xcode = await resolveAbsoluteIosXcodeProject(nativeDirectory, {
|
|
4900
|
+
scheme: options.scheme,
|
|
4901
|
+
workspacePath: options.workspacePath
|
|
4902
|
+
});
|
|
4860
4903
|
let buildNumber = requireBuildNumber(options.buildNumber);
|
|
4861
4904
|
if (options.prepareBuildNumber) {
|
|
4862
4905
|
const nativeFingerprint = await fingerprintAbsoluteIosNativeProject(nativeDirectory);
|
|
@@ -4882,9 +4925,9 @@ var developmentTeamArgument = (value) => {
|
|
|
4882
4925
|
const archiveExit = await run([
|
|
4883
4926
|
"xcodebuild",
|
|
4884
4927
|
"-workspace",
|
|
4885
|
-
|
|
4928
|
+
xcode.workspacePath,
|
|
4886
4929
|
"-scheme",
|
|
4887
|
-
|
|
4930
|
+
xcode.scheme,
|
|
4888
4931
|
"-configuration",
|
|
4889
4932
|
"Release",
|
|
4890
4933
|
"-destination",
|
|
@@ -4893,7 +4936,7 @@ var developmentTeamArgument = (value) => {
|
|
|
4893
4936
|
archivePath,
|
|
4894
4937
|
...versionArguments,
|
|
4895
4938
|
"archive"
|
|
4896
|
-
], { cwd: nativeDirectory });
|
|
4939
|
+
], { cwd: nativeDirectory, env: options.env });
|
|
4897
4940
|
if (archiveExit !== 0)
|
|
4898
4941
|
throw new TypeError("Xcode failed to archive the iOS app.");
|
|
4899
4942
|
const archivedApp = await findByExtension(join13(archivePath, "Products", "Applications"), ".app");
|
|
@@ -4916,7 +4959,7 @@ var developmentTeamArgument = (value) => {
|
|
|
4916
4959
|
exportPath,
|
|
4917
4960
|
"-exportOptionsPlist",
|
|
4918
4961
|
exportPlist
|
|
4919
|
-
], { cwd: nativeDirectory });
|
|
4962
|
+
], { cwd: nativeDirectory, env: options.env });
|
|
4920
4963
|
if (exportExit !== 0)
|
|
4921
4964
|
throw new TypeError("Xcode failed to export the App Store IPA.");
|
|
4922
4965
|
const artifactPath = await findByExtension(exportPath, ".ipa");
|
|
@@ -4932,7 +4975,7 @@ var developmentTeamArgument = (value) => {
|
|
|
4932
4975
|
appId: manifest.appId,
|
|
4933
4976
|
...buildNumber === undefined ? {} : { buildNumber },
|
|
4934
4977
|
bytes,
|
|
4935
|
-
engine:
|
|
4978
|
+
engine: options.config.engine,
|
|
4936
4979
|
format: 1,
|
|
4937
4980
|
marketingVersion,
|
|
4938
4981
|
platform: "ios",
|
|
@@ -19888,8 +19931,8 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
19888
19931
|
if (!isRecord14(root.expo))
|
|
19889
19932
|
throw new TypeError("Generated Expo application config is invalid.");
|
|
19890
19933
|
const { expo } = root;
|
|
19891
|
-
if (expo.name !== config.appName || !isRecord14(expo.android) || expo.android.package !== config.appId) {
|
|
19892
|
-
throw new TypeError("Generated Expo
|
|
19934
|
+
if (expo.name !== config.appName || config.platforms.includes("android") && (!isRecord14(expo.android) || expo.android.package !== config.appId) || config.platforms.includes("ios") && (!isRecord14(expo.ios) || expo.ios.bundleIdentifier !== config.appId)) {
|
|
19935
|
+
throw new TypeError("Generated Expo application identity does not match mobile config.");
|
|
19893
19936
|
}
|
|
19894
19937
|
if (!isRecord14(expo.runtimeVersion) || expo.runtimeVersion.policy !== "appVersion") {
|
|
19895
19938
|
throw new TypeError("Generated Expo runtimeVersion must follow the native app version.");
|
|
@@ -19899,7 +19942,7 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
19899
19942
|
}
|
|
19900
19943
|
return pass("expo.app-config", "Expo application identity and runtime policy match the production mobile config.", path);
|
|
19901
19944
|
} catch (error) {
|
|
19902
|
-
return fail5("expo.app-config", error instanceof Error ? error.message : "Generated Expo application config could not be validated.", path, "Run `absolute mobile build
|
|
19945
|
+
return fail5("expo.app-config", error instanceof Error ? error.message : "Generated Expo application config could not be validated.", path, "Run `absolute mobile build <platform>`; do not edit the generated Expo project.");
|
|
19903
19946
|
}
|
|
19904
19947
|
}, expoEmbeddedAssetsCheck = async (config) => {
|
|
19905
19948
|
const generated = join52(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
|
|
@@ -19936,7 +19979,7 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
19936
19979
|
throw new TypeError("Generated Expo asset bytes differ from the prepared mobile bundle.");
|
|
19937
19980
|
return pass("expo.bundle-projection", `Expo embeds the complete signed mobile bundle as ${embeddedFiles.length} opaque asset(s).`, generated);
|
|
19938
19981
|
} catch (error) {
|
|
19939
|
-
return fail5("expo.bundle-projection", error instanceof Error ? error.message : "Generated Expo assets could not be validated.", generated, "Run `absolute mobile build
|
|
19982
|
+
return fail5("expo.bundle-projection", error instanceof Error ? error.message : "Generated Expo assets could not be validated.", generated, "Run `absolute mobile build <platform>` to regenerate and verify the production asset projection.");
|
|
19940
19983
|
}
|
|
19941
19984
|
}, sourceFiles = async (root, extensions) => {
|
|
19942
19985
|
if (!await pathExists6(root))
|
|
@@ -19978,15 +20021,16 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
19978
20021
|
return fail5("android.deep-links", error instanceof Error ? error.message : "Android deep-link projection could not be validated.", manifestPath, "Run `absolute mobile sync android` and review the AbsoluteJS-owned deep-link region.");
|
|
19979
20022
|
}
|
|
19980
20023
|
}, iosNativeSecurityCheck = async (iosRoot) => {
|
|
19981
|
-
const
|
|
19982
|
-
const
|
|
19983
|
-
|
|
19984
|
-
|
|
19985
|
-
|
|
20024
|
+
const applicationFiles = async (extensions) => (await sourceFiles(iosRoot, extensions)).filter((path) => !relative26(iosRoot, path).split(/[\\/]/u).some((part) => ["Pods", "DerivedData", "build"].includes(part)));
|
|
20025
|
+
const entitlementPaths = await applicationFiles(new Set([".entitlements"]));
|
|
20026
|
+
const unsafeEntitlements = await containsPattern(entitlementPaths, /<key>(?:com\.apple\.security\.)?get-task-allow<\/key>\s*<true\s*\/>/u);
|
|
20027
|
+
if (unsafeEntitlements)
|
|
20028
|
+
return fail5("ios.native-debugging", "iOS source entitlements explicitly permit debugger attachment.", unsafeEntitlements, "Remove get-task-allow from source entitlements; Xcode supplies development entitlements only to debug builds.");
|
|
20029
|
+
const sources = await applicationFiles(new Set([".m", ".mm", ".swift"]));
|
|
19986
20030
|
const debugSource = await containsPattern(sources, /\.isInspectable\s*=\s*true|setInspectable\s*\(\s*true\s*\)/u);
|
|
19987
20031
|
if (debugSource)
|
|
19988
20032
|
return fail5("ios.native-debugging", "iOS application source unconditionally enables WebView inspection.", debugSource, "Remove unconditional WebView inspection from release source.");
|
|
19989
|
-
return pass("ios.native-debugging", "iOS source does not enable release debugger attachment or WebView inspection.",
|
|
20033
|
+
return pass("ios.native-debugging", "iOS source does not enable release debugger attachment or WebView inspection.", entitlementPaths[0] ?? iosRoot);
|
|
19990
20034
|
}, iosDeepLinkProjectionCheck = async (config, iosRoot) => {
|
|
19991
20035
|
const infoPath = join52(iosRoot, "App/App/Info.plist");
|
|
19992
20036
|
const entitlementsPath = join52(iosRoot, "App/AbsoluteJS.entitlements");
|
|
@@ -20041,15 +20085,43 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
20041
20085
|
}, iosDevicePermissionCheck = async (config, purposes) => {
|
|
20042
20086
|
if (!config.platforms.includes("ios") || purposes.length === 0)
|
|
20043
20087
|
return;
|
|
20044
|
-
const
|
|
20088
|
+
const iosRoot = join52(config.nativeProjectDirectory, "ios");
|
|
20089
|
+
const path = config.engine === "expo" ? await uniqueExpoIosFile(iosRoot, "**/Info.plist", "Info.plist") : join52(iosRoot, "App/App/Info.plist");
|
|
20045
20090
|
const source = await readFile18(path, "utf8");
|
|
20046
20091
|
const missing = purposes.filter((purpose) => !source.includes(`<key>${IOS_USAGE_KEYS[purpose]}</key>`));
|
|
20047
20092
|
if (missing.length === 0)
|
|
20048
20093
|
return;
|
|
20049
20094
|
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.");
|
|
20095
|
+
}, expoIosPrivacyCapabilityCheck = async (iosRoot, project, requirements) => {
|
|
20096
|
+
if (requirements.iosPrivacyAccessedApis.length === 0)
|
|
20097
|
+
return;
|
|
20098
|
+
const privacyPath = await uniqueExpoIosFile(iosRoot, "**/PrivacyInfo.xcprivacy", "privacy manifest");
|
|
20099
|
+
const privacy = await readFile18(privacyPath, "utf8");
|
|
20100
|
+
const missing = requirements.iosPrivacyAccessedApis.some(({ api, reasons }) => !privacy.includes(`<string>${api}</string>`) || reasons.some((reason) => !privacy.includes(`<string>${reason}</string>`)));
|
|
20101
|
+
if (!missing && project.includes(privacyPath.split(/[\\/]/u).at(-1) ?? ""))
|
|
20102
|
+
return;
|
|
20103
|
+
return fail5("mobile.device-capabilities", "Expo iOS privacy manifest or target membership does not match detected capabilities.", privacyPath, "Run `absolute mobile build ios` to regenerate detected Expo privacy declarations.");
|
|
20104
|
+
}, expoIosPushCapabilityCheck = async (iosRoot, requirements) => {
|
|
20105
|
+
if (!requirements.iosPushNotifications)
|
|
20106
|
+
return;
|
|
20107
|
+
const entitlementsPath = await uniqueExpoIosFile(iosRoot, "**/*.entitlements", "entitlements");
|
|
20108
|
+
const entitlements = await readFile18(entitlementsPath, "utf8");
|
|
20109
|
+
if (entitlements.includes("<key>aps-environment</key>"))
|
|
20110
|
+
return;
|
|
20111
|
+
return fail5("mobile.device-capabilities", "Expo iOS push entitlement does not match detected capabilities.", entitlementsPath, "Run `absolute mobile build ios` to regenerate native push integration.");
|
|
20112
|
+
}, expoIosCapabilityProjectionCheck = async (config, requirements) => {
|
|
20113
|
+
const iosRoot = join52(config.nativeProjectDirectory, "ios");
|
|
20114
|
+
const projectPath = await uniqueExpoIosFile(iosRoot, "**/*.xcodeproj/project.pbxproj", "Xcode project");
|
|
20115
|
+
const project = await readFile18(projectPath, "utf8");
|
|
20116
|
+
const privacy = await expoIosPrivacyCapabilityCheck(iosRoot, project, requirements);
|
|
20117
|
+
if (privacy)
|
|
20118
|
+
return privacy;
|
|
20119
|
+
return expoIosPushCapabilityCheck(iosRoot, requirements);
|
|
20050
20120
|
}, iosCapabilityProjectionCheck = async (config, requirements) => {
|
|
20051
20121
|
if (!config.platforms.includes("ios"))
|
|
20052
20122
|
return;
|
|
20123
|
+
if (config.engine === "expo")
|
|
20124
|
+
return expoIosCapabilityProjectionCheck(config, requirements);
|
|
20053
20125
|
const appRoot = join52(config.nativeProjectDirectory, "ios/App/App");
|
|
20054
20126
|
const infoPath = join52(appRoot, "Info.plist");
|
|
20055
20127
|
const info2 = await readFile18(infoPath, "utf8").catch(() => "");
|
|
@@ -20151,6 +20223,58 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
20151
20223
|
...check2,
|
|
20152
20224
|
path: check2.path ? relative26(projectRoot, check2.path).replaceAll("\\", "/") || "." : undefined
|
|
20153
20225
|
}));
|
|
20226
|
+
}, uniqueExpoIosFile = async (iosRoot, pattern, label) => {
|
|
20227
|
+
const paths = (await Array.fromAsync(new Bun.Glob(pattern).scan({ cwd: iosRoot, onlyFiles: true }))).filter((path2) => !path2.split(/[\\/]/u).some((part) => ["Pods", "DerivedData", "build"].includes(part)));
|
|
20228
|
+
if (paths.length !== 1)
|
|
20229
|
+
throw new TypeError(paths.length === 0 ? `Generated Expo iOS project is missing its ${label}.` : `Generated Expo iOS project contains ambiguous ${label} files.`);
|
|
20230
|
+
const [path] = paths;
|
|
20231
|
+
if (!path)
|
|
20232
|
+
throw new TypeError(`Generated Expo iOS project is missing its ${label}.`);
|
|
20233
|
+
return join52(iosRoot, path);
|
|
20234
|
+
}, expoIosNativeProjectionCheck = async (config, iosRoot) => {
|
|
20235
|
+
try {
|
|
20236
|
+
const [infoPath, entitlementsPath, projectPath] = await Promise.all([
|
|
20237
|
+
uniqueExpoIosFile(iosRoot, "**/Info.plist", "Info.plist"),
|
|
20238
|
+
uniqueExpoIosFile(iosRoot, "**/*.entitlements", "entitlements"),
|
|
20239
|
+
uniqueExpoIosFile(iosRoot, "**/*.xcodeproj/project.pbxproj", "Xcode project")
|
|
20240
|
+
]);
|
|
20241
|
+
const [info2, entitlements, project] = await Promise.all([
|
|
20242
|
+
readFile18(infoPath, "utf8"),
|
|
20243
|
+
readFile18(entitlementsPath, "utf8"),
|
|
20244
|
+
readFile18(projectPath, "utf8")
|
|
20245
|
+
]);
|
|
20246
|
+
if (/<key>NSAllowsArbitraryLoads<\/key>\s*<true\s*\/>/u.test(info2))
|
|
20247
|
+
throw new TypeError("Expo iOS App Transport Security permits arbitrary network loads.");
|
|
20248
|
+
if (config.deepLinkScheme && (!info2.includes("<key>CFBundleURLTypes</key>") || !info2.includes(`<string>${config.deepLinkScheme}</string>`)))
|
|
20249
|
+
throw new TypeError("Expo iOS custom URL scheme does not match mobile config.");
|
|
20250
|
+
if (config.deepLinkHosts.some((host2) => !entitlements.includes(`<string>applinks:${host2}</string>`)))
|
|
20251
|
+
throw new TypeError("Expo iOS associated domains do not match mobile config.");
|
|
20252
|
+
if (!project.includes(entitlementsPath.split(/[\\/]/u).at(-1) ?? ""))
|
|
20253
|
+
throw new TypeError("Expo iOS target does not sign its generated entitlements file.");
|
|
20254
|
+
return pass("ios.expo-native-projection", "Expo iOS transport security, URL schemes, universal links, and signed entitlements match mobile config.", entitlementsPath);
|
|
20255
|
+
} catch (error) {
|
|
20256
|
+
return fail5("ios.expo-native-projection", error instanceof Error ? error.message : "Expo iOS native projection could not be validated.", iosRoot, "Run `absolute mobile build ios` to regenerate the production Expo CNG project.");
|
|
20257
|
+
}
|
|
20258
|
+
}, inspectExpoIosRelease = async (config, projectRoot) => {
|
|
20259
|
+
const iosRoot = join52(config.nativeProjectDirectory, "ios");
|
|
20260
|
+
const journalPath = join52(projectRoot, ".absolutejs", "mobile", "expo-dev-session", "journal.json");
|
|
20261
|
+
const checks = [
|
|
20262
|
+
await journalReleaseCheck(journalPath, "ios")
|
|
20263
|
+
];
|
|
20264
|
+
checks.push(config.iosVersion ? pass("ios.marketing-version", `The iOS marketing version is ${config.iosVersion}.`) : fail5("ios.marketing-version", "iOS has no explicit App Store marketing version.", projectRoot, "Add mobile.ios.version to absolutejs.config.ts, for example 1.0.0."));
|
|
20265
|
+
checks.push(...await Promise.all([
|
|
20266
|
+
expoApplicationConfigCheck(config),
|
|
20267
|
+
expoEmbeddedAssetsCheck(config),
|
|
20268
|
+
hmrAssetsReleaseCheck(config.bundleDirectory),
|
|
20269
|
+
embeddedBundleReleaseCheck(config, projectRoot, "ios", config.bundleDirectory),
|
|
20270
|
+
contentSecurityPolicyCheck(config, "ios", config.bundleDirectory),
|
|
20271
|
+
expoIosNativeProjectionCheck(config, iosRoot),
|
|
20272
|
+
iosNativeSecurityCheck(iosRoot)
|
|
20273
|
+
]));
|
|
20274
|
+
return checks.map((check2) => ({
|
|
20275
|
+
...check2,
|
|
20276
|
+
path: check2.path ? relative26(projectRoot, check2.path).replaceAll("\\", "/") || "." : undefined
|
|
20277
|
+
}));
|
|
20154
20278
|
}, inspectIosRelease = async (config, projectRoot) => {
|
|
20155
20279
|
const iosAppRoot = join52(config.nativeProjectDirectory, "ios", "App", "App");
|
|
20156
20280
|
const nativeConfigPath = join52(iosAppRoot, "capacitor.config.json");
|
|
@@ -20219,9 +20343,7 @@ var ABSOLUTE_MOBILE_COMPLIANCE_REPORT_FORMAT = 1, HMR_ASSET_PATTERN, RELEASE_ASS
|
|
|
20219
20343
|
if (config.platforms.includes("android"))
|
|
20220
20344
|
checks.push(...config.engine === "expo" ? await inspectExpoAndroidRelease(config, projectRoot) : await inspectAndroidRelease(config, projectRoot));
|
|
20221
20345
|
if (config.platforms.includes("ios"))
|
|
20222
|
-
checks.push(...config.engine === "expo" ?
|
|
20223
|
-
fail5("expo.ios-release", "Expo iOS production release automation is not implemented yet.", config.nativeProjectDirectory, "Build Android independently or wait for the Expo iOS signing checkpoint.")
|
|
20224
|
-
] : await inspectIosRelease(config, projectRoot));
|
|
20346
|
+
checks.push(...config.engine === "expo" ? await inspectExpoIosRelease(config, projectRoot) : await inspectIosRelease(config, projectRoot));
|
|
20225
20347
|
const syncSchema = syncSchemaReleaseCheck(projectRoot);
|
|
20226
20348
|
if (syncSchema) {
|
|
20227
20349
|
checks.push({
|
|
@@ -21545,10 +21667,8 @@ ${releaseAuditSteps("ios")}
|
|
|
21545
21667
|
...custom
|
|
21546
21668
|
], createAbsoluteMobileGithubWorkflow = (options) => {
|
|
21547
21669
|
const platforms = [
|
|
21548
|
-
...options.config.
|
|
21670
|
+
...options.config.platforms
|
|
21549
21671
|
].sort();
|
|
21550
|
-
if (platforms.length === 0)
|
|
21551
|
-
throw new TypeError("Generated Expo production CI currently requires android in mobile.platforms; Expo iOS release automation is the next checkpoint.");
|
|
21552
21672
|
const includePublishing = options.includePublishing === true;
|
|
21553
21673
|
const customSecrets = normalizeSecretEnvironment(options.secretEnvironment);
|
|
21554
21674
|
const serverEntry = projectPath(options.projectRoot, options.serverEntry ?? "server.ts", "mobile ci github server entry");
|
|
@@ -21746,13 +21866,13 @@ var NOT_FOUND4 = -1, isRecord17 = (value) => typeof value === "object" && value
|
|
|
21746
21866
|
}
|
|
21747
21867
|
}, runCapacitor = async (projectRoot, args) => {
|
|
21748
21868
|
const executable = await capacitorExecutable(projectRoot);
|
|
21749
|
-
const
|
|
21869
|
+
const process2 = Bun.spawn([executable, ...args], {
|
|
21750
21870
|
cwd: projectRoot,
|
|
21751
21871
|
stderr: "inherit",
|
|
21752
21872
|
stdin: "inherit",
|
|
21753
21873
|
stdout: "inherit"
|
|
21754
21874
|
});
|
|
21755
|
-
const exitCode = await
|
|
21875
|
+
const exitCode = await process2.exited;
|
|
21756
21876
|
if (exitCode !== 0) {
|
|
21757
21877
|
throw new TypeError(`Capacitor exited with status ${exitCode}.`);
|
|
21758
21878
|
}
|
|
@@ -22233,7 +22353,18 @@ Mobile release security and compliance checks failed.`);
|
|
|
22233
22353
|
await ensureExpoPackages(mobile.nativeProjectDirectory, [...args, "--yes"]);
|
|
22234
22354
|
await syncAbsoluteExpoWebAssets(mobile);
|
|
22235
22355
|
await runExpo(mobile.nativeProjectDirectory, ["prebuild", "--clean", "--no-install", "--platform", "android"], { production: true });
|
|
22236
|
-
},
|
|
22356
|
+
}, prepareExpoIosReleaseProject = async (mobile, projectRoot, args) => {
|
|
22357
|
+
await writeAbsoluteExpoProject(mobile, { projectRoot });
|
|
22358
|
+
await ensureExpoPackages(mobile.nativeProjectDirectory, [...args, "--yes"]);
|
|
22359
|
+
await syncAbsoluteExpoWebAssets(mobile);
|
|
22360
|
+
await runExpo(mobile.nativeProjectDirectory, ["prebuild", "--clean", "--no-install", "--platform", "ios"], { production: true });
|
|
22361
|
+
}, prepareCapacitorIosReleaseProject = async (mobile, projectRoot) => {
|
|
22362
|
+
await writeAbsoluteCapacitorConfig(mobile, { projectRoot });
|
|
22363
|
+
await runCapacitorForPlatforms(projectRoot, "sync", ["ios"]);
|
|
22364
|
+
await applyAbsoluteNativeDeepLinks(mobile, ["ios"]);
|
|
22365
|
+
await applyAbsoluteNativeDeviceCapabilities(projectRoot, mobile, ["ios"]);
|
|
22366
|
+
await applyAbsoluteNativeBackgroundSync(projectRoot, mobile, ["ios"]);
|
|
22367
|
+
}, prepareIosReleaseProject = (mobile, projectRoot, args) => mobile.engine === "expo" ? prepareExpoIosReleaseProject(mobile, projectRoot, args) : prepareCapacitorIosReleaseProject(mobile, projectRoot), prepareCapacitorAndroidReleaseProject = async (mobile, projectRoot) => {
|
|
22237
22368
|
await writeAbsoluteCapacitorConfig(mobile, { projectRoot });
|
|
22238
22369
|
await runCapacitorForPlatforms(projectRoot, "sync", ["android"]);
|
|
22239
22370
|
await applyAbsoluteNativeDeepLinks(mobile, ["android"]);
|
|
@@ -22319,7 +22450,7 @@ Mobile release security and compliance checks failed.`);
|
|
|
22319
22450
|
} finally {
|
|
22320
22451
|
sendTelemetryEvent("mobile:android-release-publish", {
|
|
22321
22452
|
durationMs: Math.round(performance.now() - startedAt),
|
|
22322
|
-
engine:
|
|
22453
|
+
engine: mobile.engine,
|
|
22323
22454
|
platform: "android",
|
|
22324
22455
|
provider: googlePlay ? "google-play" : "registry-module",
|
|
22325
22456
|
reused,
|
|
@@ -22344,27 +22475,22 @@ Mobile release security and compliance checks failed.`);
|
|
|
22344
22475
|
}, buildIos = async (args, prepareBuildNumber) => {
|
|
22345
22476
|
const configPath2 = valueAfter(args, "--config");
|
|
22346
22477
|
const { mobile, projectRoot } = await loadMobile(configPath2);
|
|
22347
|
-
requireCapacitorEngine(mobile, "mobile build ios");
|
|
22348
22478
|
if (!mobile.platforms.includes("ios")) {
|
|
22349
22479
|
throw new TypeError("mobile build ios requires ios in mobile.platforms.");
|
|
22350
22480
|
}
|
|
22351
22481
|
const startedAt = performance.now();
|
|
22352
22482
|
let success = false;
|
|
22353
22483
|
try {
|
|
22354
|
-
|
|
22484
|
+
if (mobile.engine === "capacitor")
|
|
22485
|
+
await repairAbsoluteIosDevSession(projectRoot);
|
|
22355
22486
|
await start(mobileBuildServerEntry(args), valueAfter(args, "--web-outdir"), configPath2, { prepareOnly: true });
|
|
22356
|
-
await
|
|
22357
|
-
await runCapacitorForPlatforms(projectRoot, "sync", ["ios"]);
|
|
22358
|
-
await applyAbsoluteNativeDeepLinks(mobile, ["ios"]);
|
|
22359
|
-
await applyAbsoluteNativeDeviceCapabilities(projectRoot, mobile, [
|
|
22360
|
-
"ios"
|
|
22361
|
-
]);
|
|
22362
|
-
await applyAbsoluteNativeBackgroundSync(projectRoot, mobile, ["ios"]);
|
|
22487
|
+
await prepareIosReleaseProject(mobile, projectRoot, args);
|
|
22363
22488
|
await requireIosReleaseReady(mobile, projectRoot);
|
|
22364
22489
|
const release = await buildAbsoluteIosRelease({
|
|
22365
22490
|
allowUnsigned: args.includes("--unsigned"),
|
|
22366
22491
|
config: mobile,
|
|
22367
22492
|
developmentTeam: process.env.ABSOLUTE_IOS_DEVELOPMENT_TEAM,
|
|
22493
|
+
...mobile.engine === "expo" ? { env: expoProductionEnvironment() } : {},
|
|
22368
22494
|
outputDirectory: valueAfter(args, "--outdir"),
|
|
22369
22495
|
...prepareBuildNumber === undefined ? {} : { prepareBuildNumber },
|
|
22370
22496
|
projectRoot
|
|
@@ -22378,7 +22504,7 @@ Mobile release security and compliance checks failed.`);
|
|
|
22378
22504
|
} finally {
|
|
22379
22505
|
sendTelemetryEvent("mobile:ios-release-build", {
|
|
22380
22506
|
durationMs: Math.round(performance.now() - startedAt),
|
|
22381
|
-
engine:
|
|
22507
|
+
engine: mobile.engine,
|
|
22382
22508
|
platform: "ios",
|
|
22383
22509
|
success,
|
|
22384
22510
|
type: "ipa",
|
|
@@ -22391,7 +22517,6 @@ Mobile release security and compliance checks failed.`);
|
|
|
22391
22517
|
const configPath2 = valueAfter(args, "--config");
|
|
22392
22518
|
const appStoreConnect = appStoreConnectTarget(args);
|
|
22393
22519
|
const { mobile, projectRoot } = await loadMobile(configPath2);
|
|
22394
|
-
requireCapacitorEngine(mobile, "mobile publish ios");
|
|
22395
22520
|
const startedAt = performance.now();
|
|
22396
22521
|
let reused = false;
|
|
22397
22522
|
let success = false;
|
|
@@ -22427,7 +22552,7 @@ Mobile release security and compliance checks failed.`);
|
|
|
22427
22552
|
} finally {
|
|
22428
22553
|
sendTelemetryEvent("mobile:ios-release-publish", {
|
|
22429
22554
|
durationMs: Math.round(performance.now() - startedAt),
|
|
22430
|
-
engine:
|
|
22555
|
+
engine: mobile.engine,
|
|
22431
22556
|
platform: "ios",
|
|
22432
22557
|
provider: appStoreConnect ? "app-store-connect" : "registry-module",
|
|
22433
22558
|
reused,
|
package/dist/mobile/index.js
CHANGED
|
@@ -2649,6 +2649,47 @@ var findByExtension = async (root, extension) => {
|
|
|
2649
2649
|
}));
|
|
2650
2650
|
return matches.find((match) => match !== undefined);
|
|
2651
2651
|
};
|
|
2652
|
+
var findAllByExtension = async (root, extension, options = {}) => {
|
|
2653
|
+
if (!await pathExists4(root))
|
|
2654
|
+
return [];
|
|
2655
|
+
const entries = await readdir3(root, { withFileTypes: true });
|
|
2656
|
+
const matches = await Promise.all(entries.map(async (entry) => {
|
|
2657
|
+
const path = join5(root, entry.name);
|
|
2658
|
+
if (entry.name.endsWith(extension))
|
|
2659
|
+
return [path];
|
|
2660
|
+
if (!entry.isDirectory() || options.excludedDirectories?.has(entry.name))
|
|
2661
|
+
return [];
|
|
2662
|
+
return findAllByExtension(path, extension, options);
|
|
2663
|
+
}));
|
|
2664
|
+
return matches.flat().sort();
|
|
2665
|
+
};
|
|
2666
|
+
var resolveAbsoluteIosXcodeProject = async (nativeDirectory, options = {}) => {
|
|
2667
|
+
const requestedWorkspace = options.workspacePath ? resolve4(nativeDirectory, options.workspacePath) : undefined;
|
|
2668
|
+
if (requestedWorkspace) {
|
|
2669
|
+
const requestedRelative = relative4(nativeDirectory, requestedWorkspace);
|
|
2670
|
+
if (requestedRelative === ".." || requestedRelative.startsWith(`..${sep3}`) || isAbsolute3(requestedRelative))
|
|
2671
|
+
throw new TypeError("iOS release workspacePath must remain inside the native iOS project.");
|
|
2672
|
+
}
|
|
2673
|
+
const workspaces = requestedWorkspace ? [requestedWorkspace] : await findAllByExtension(nativeDirectory, ".xcworkspace", {
|
|
2674
|
+
excludedDirectories: new Set(["Pods", "DerivedData", "build"])
|
|
2675
|
+
});
|
|
2676
|
+
if (workspaces.length !== 1)
|
|
2677
|
+
throw new TypeError(workspaces.length > 1 ? `iOS release found multiple Xcode workspaces: ${workspaces.map((path) => relative4(nativeDirectory, path)).join(", ")}. Pass an explicit workspacePath.` : "iOS release could not find an Xcode workspace.");
|
|
2678
|
+
const [workspacePath] = workspaces;
|
|
2679
|
+
if (!workspacePath || !await pathExists4(workspacePath))
|
|
2680
|
+
throw new TypeError("iOS release could not find an Xcode workspace.");
|
|
2681
|
+
if (options.scheme)
|
|
2682
|
+
return { scheme: options.scheme, workspacePath };
|
|
2683
|
+
const schemeFiles = await findAllByExtension(nativeDirectory, ".xcscheme", {
|
|
2684
|
+
excludedDirectories: new Set(["Pods", "DerivedData", "build"])
|
|
2685
|
+
});
|
|
2686
|
+
const schemes = [
|
|
2687
|
+
...new Set(schemeFiles.map((path) => path.slice(path.lastIndexOf(sep3) + 1, -".xcscheme".length)))
|
|
2688
|
+
];
|
|
2689
|
+
if (schemes.length !== 1 || !schemes[0])
|
|
2690
|
+
throw new TypeError(schemes.length > 1 ? `iOS release found multiple shared Xcode schemes: ${schemes.join(", ")}. Pass an explicit scheme.` : "iOS release could not find a shared Xcode scheme.");
|
|
2691
|
+
return { scheme: schemes[0], workspacePath };
|
|
2692
|
+
};
|
|
2652
2693
|
var exportOptions = () => `<?xml version="1.0" encoding="UTF-8"?>
|
|
2653
2694
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
2654
2695
|
<plist version="1.0"><dict>
|
|
@@ -2718,6 +2759,10 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
2718
2759
|
if (manifest.appId !== options.config.appId)
|
|
2719
2760
|
throw new TypeError("Embedded mobile manifest appId does not match mobile.appId.");
|
|
2720
2761
|
const nativeDirectory = join5(options.config.nativeProjectDirectory, "ios");
|
|
2762
|
+
const xcode = await resolveAbsoluteIosXcodeProject(nativeDirectory, {
|
|
2763
|
+
scheme: options.scheme,
|
|
2764
|
+
workspacePath: options.workspacePath
|
|
2765
|
+
});
|
|
2721
2766
|
let buildNumber = requireBuildNumber(options.buildNumber);
|
|
2722
2767
|
if (options.prepareBuildNumber) {
|
|
2723
2768
|
const nativeFingerprint = await fingerprintAbsoluteIosNativeProject(nativeDirectory);
|
|
@@ -2743,9 +2788,9 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
2743
2788
|
const archiveExit = await run([
|
|
2744
2789
|
"xcodebuild",
|
|
2745
2790
|
"-workspace",
|
|
2746
|
-
|
|
2791
|
+
xcode.workspacePath,
|
|
2747
2792
|
"-scheme",
|
|
2748
|
-
|
|
2793
|
+
xcode.scheme,
|
|
2749
2794
|
"-configuration",
|
|
2750
2795
|
"Release",
|
|
2751
2796
|
"-destination",
|
|
@@ -2754,7 +2799,7 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
2754
2799
|
archivePath,
|
|
2755
2800
|
...versionArguments,
|
|
2756
2801
|
"archive"
|
|
2757
|
-
], { cwd: nativeDirectory });
|
|
2802
|
+
], { cwd: nativeDirectory, env: options.env });
|
|
2758
2803
|
if (archiveExit !== 0)
|
|
2759
2804
|
throw new TypeError("Xcode failed to archive the iOS app.");
|
|
2760
2805
|
const archivedApp = await findByExtension(join5(archivePath, "Products", "Applications"), ".app");
|
|
@@ -2777,7 +2822,7 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
2777
2822
|
exportPath,
|
|
2778
2823
|
"-exportOptionsPlist",
|
|
2779
2824
|
exportPlist
|
|
2780
|
-
], { cwd: nativeDirectory });
|
|
2825
|
+
], { cwd: nativeDirectory, env: options.env });
|
|
2781
2826
|
if (exportExit !== 0)
|
|
2782
2827
|
throw new TypeError("Xcode failed to export the App Store IPA.");
|
|
2783
2828
|
const artifactPath = await findByExtension(exportPath, ".ipa");
|
|
@@ -2793,7 +2838,7 @@ var buildAbsoluteIosRelease = async (options) => {
|
|
|
2793
2838
|
appId: manifest.appId,
|
|
2794
2839
|
...buildNumber === undefined ? {} : { buildNumber },
|
|
2795
2840
|
bytes,
|
|
2796
|
-
engine:
|
|
2841
|
+
engine: options.config.engine,
|
|
2797
2842
|
format: 1,
|
|
2798
2843
|
marketingVersion,
|
|
2799
2844
|
platform: "ios",
|
|
@@ -8706,10 +8751,8 @@ var requiredSecrets = (platforms, includePublishing, custom) => [
|
|
|
8706
8751
|
];
|
|
8707
8752
|
var createAbsoluteMobileGithubWorkflow = (options) => {
|
|
8708
8753
|
const platforms = [
|
|
8709
|
-
...options.config.
|
|
8754
|
+
...options.config.platforms
|
|
8710
8755
|
].sort();
|
|
8711
|
-
if (platforms.length === 0)
|
|
8712
|
-
throw new TypeError("Generated Expo production CI currently requires android in mobile.platforms; Expo iOS release automation is the next checkpoint.");
|
|
8713
8756
|
const includePublishing = options.includePublishing === true;
|
|
8714
8757
|
const customSecrets = normalizeSecretEnvironment(options.secretEnvironment);
|
|
8715
8758
|
const serverEntry = projectPath(options.projectRoot, options.serverEntry ?? "server.ts", "mobile ci github server entry");
|
|
@@ -10487,6 +10530,7 @@ export {
|
|
|
10487
10530
|
removeAbsoluteRemoteMacProfile,
|
|
10488
10531
|
repairAbsoluteIosDevSession,
|
|
10489
10532
|
resolveAbsoluteDeviceCapabilityPlan,
|
|
10533
|
+
resolveAbsoluteIosXcodeProject,
|
|
10490
10534
|
resolveAbsoluteMobileAuthManifest,
|
|
10491
10535
|
resolveAbsoluteMobileCompatibilityRelease,
|
|
10492
10536
|
resolveAbsoluteMobileDeepLink,
|
|
@@ -10515,5 +10559,5 @@ export {
|
|
|
10515
10559
|
writeAbsoluteMobileGithubWorkflow
|
|
10516
10560
|
};
|
|
10517
10561
|
|
|
10518
|
-
//# debugId=
|
|
10562
|
+
//# debugId=25517EB0CBB1387F64756E2164756E21
|
|
10519
10563
|
//# sourceMappingURL=index.js.map
|