@absolutejs/absolute 0.20.0-beta.24 → 0.20.0-beta.26
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 +12 -1
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/build.js +1254 -977
- package/dist/build.js.map +5 -4
- package/dist/cli/index.js +128 -11
- package/dist/index.js +1316 -1038
- package/dist/index.js.map +6 -5
- package/dist/mobile/index.js +393 -269
- package/dist/mobile/index.js.map +8 -8
- package/dist/mobile/remoteMacAgentEntry.js +10 -10
- package/dist/mobile/shellAuth.js +2 -1
- package/dist/mobile/shellBootstrap.js +5 -1
- package/dist/src/mobile/config.d.ts +1 -0
- package/dist/src/mobile/deviceCapabilities.d.ts +5 -0
- package/dist/src/mobile/shellAuth.d.ts +3 -1
- package/dist/src/mobile/shellBootstrap.d.ts +5 -1
- package/dist/src/mobile/shellPush.d.ts +11 -0
- package/dist/types/build.d.ts +16 -1
- package/package.json +7 -5
package/dist/cli/index.js
CHANGED
|
@@ -813,7 +813,8 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
|
|
|
813
813
|
iosVersion: normalizeIosVersion(config.ios?.version),
|
|
814
814
|
nativeProjectDirectory: resolveProjectPath(projectRoot, config.nativeProject?.directory ?? "mobile", "mobile.nativeProject.directory"),
|
|
815
815
|
platforms: normalizePlatforms(config.platforms),
|
|
816
|
-
productionOrigin
|
|
816
|
+
productionOrigin,
|
|
817
|
+
pushAndroidGoogleServicesFile: resolveProjectPath(projectRoot, config.pushNotifications?.android?.googleServicesFile ?? "google-services.json", "mobile.pushNotifications.android.googleServicesFile")
|
|
817
818
|
};
|
|
818
819
|
};
|
|
819
820
|
var init_config = __esm(() => {
|
|
@@ -5945,6 +5946,11 @@ var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-
|
|
|
5945
5946
|
if (candidate)
|
|
5946
5947
|
return candidate;
|
|
5947
5948
|
throw new TypeError("AbsoluteJS mobile Sync shell module is missing.");
|
|
5949
|
+
}, shellPushModule = () => {
|
|
5950
|
+
const candidate = ["js", "ts"].map((extension) => join17(import.meta.dir, `shellPush.${extension}`)).find(existsSync9);
|
|
5951
|
+
if (candidate)
|
|
5952
|
+
return candidate;
|
|
5953
|
+
throw new TypeError("AbsoluteJS mobile push shell module is missing.");
|
|
5948
5954
|
}, escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """), indexHtml = (appName) => `<!doctype html>
|
|
5949
5955
|
<html>
|
|
5950
5956
|
<head>
|
|
@@ -5992,6 +5998,10 @@ var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-
|
|
|
5992
5998
|
` : "";
|
|
5993
5999
|
const options = auth ? `{ createAuth: createAbsoluteMobileShellAuth${sync ? ", installSync: installAbsoluteMobileShellSync" : ""} }` : "";
|
|
5994
6000
|
const syncImport = sync ? `import { installAbsoluteMobileShellSync } from ${JSON.stringify(shellSyncModule())};
|
|
6001
|
+
` : "";
|
|
6002
|
+
const pushIndex = deviceCapabilities.capabilities.indexOf("pushNotifications");
|
|
6003
|
+
const push = pushIndex !== -1;
|
|
6004
|
+
const pushImport = push ? `import { createAbsoluteMobileShellPush } from ${JSON.stringify(shellPushModule())};
|
|
5995
6005
|
` : "";
|
|
5996
6006
|
const capabilityImports = (await Promise.all(deviceCapabilities.capabilities.map(async (name, index) => {
|
|
5997
6007
|
const provider = deviceCapabilities.providers[name];
|
|
@@ -6000,14 +6010,17 @@ var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-
|
|
|
6000
6010
|
return `import { ${provider.factory} as absoluteDeviceCapability${index} } from ${JSON.stringify(await resolveProjectImport(projectRoot, provider.module))};`;
|
|
6001
6011
|
}))).join(`
|
|
6002
6012
|
`);
|
|
6003
|
-
const
|
|
6013
|
+
const pushSetup = push ? `const absoluteMobilePush = createAbsoluteMobileShellPush();
|
|
6014
|
+
const absoluteMobilePushCapability = absoluteDeviceCapability${pushIndex}(absoluteMobilePush.capabilityOptions);
|
|
6015
|
+
` : "";
|
|
6016
|
+
const capabilityOptions = deviceCapabilities.capabilities.map((name, index) => `${JSON.stringify(name)}: ${name === "pushNotifications" ? "absoluteMobilePushCapability" : `absoluteDeviceCapability${index}()`}`).join(", ");
|
|
6004
6017
|
const entryPath = join17(staging, ".absolute-mobile-entry.ts");
|
|
6005
6018
|
const baseAdapterModule = await resolveProjectImport(projectRoot, "@absolutejs/devices-capacitor");
|
|
6006
6019
|
await writeFile7(entryPath, `import { startAbsoluteMobileShell } from ${JSON.stringify(modulePath)};
|
|
6007
6020
|
import { installCapacitorDeviceAdapterIfNative } from ${JSON.stringify(baseAdapterModule)};
|
|
6008
|
-
${authImport}${syncImport}${capabilityImports}
|
|
6009
|
-
installCapacitorDeviceAdapterIfNative({ storagePrefix: ${JSON.stringify(storagePrefix)}${capabilityOptions ? `, ${capabilityOptions}` : ""} });
|
|
6010
|
-
void startAbsoluteMobileShell(${options});
|
|
6021
|
+
${authImport}${syncImport}${pushImport}${capabilityImports}
|
|
6022
|
+
${pushSetup}installCapacitorDeviceAdapterIfNative({ storagePrefix: ${JSON.stringify(storagePrefix)}${capabilityOptions ? `, ${capabilityOptions}` : ""} });
|
|
6023
|
+
void startAbsoluteMobileShell(${push ? `{ createAuth: (config, options) => createAbsoluteMobileShellAuth(config, options), beforeSignOut: absoluteMobilePush.beforeSignOut, connectPush: (auth) => absoluteMobilePush.connect(auth, absoluteMobilePushCapability)${sync ? ", installSync: installAbsoluteMobileShellSync" : ""} }` : options});
|
|
6011
6024
|
`);
|
|
6012
6025
|
const build = await Bun.build({
|
|
6013
6026
|
entrypoints: [entryPath],
|
|
@@ -6804,12 +6817,15 @@ var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/de
|
|
|
6804
6817
|
return;
|
|
6805
6818
|
if (!object2(value))
|
|
6806
6819
|
throw new TypeError(`${field} must be an object.`);
|
|
6807
|
-
const { privacyAccessedApis, usageDescriptions } = value;
|
|
6820
|
+
const { privacyAccessedApis, pushNotifications, usageDescriptions } = value;
|
|
6821
|
+
if (pushNotifications !== undefined && pushNotifications !== true)
|
|
6822
|
+
throw new TypeError(`${field}.pushNotifications must be true.`);
|
|
6808
6823
|
if (usageDescriptions !== undefined && (!Array.isArray(usageDescriptions) || !usageDescriptions.every((purpose) => typeof purpose === "string" && IOS_USAGE_DESCRIPTIONS.has(purpose))))
|
|
6809
6824
|
throw new TypeError(`${field}.usageDescriptions contains an unsupported purpose.`);
|
|
6810
6825
|
const privacy = iosPrivacyAccessedApis(privacyAccessedApis, `${field}.privacyAccessedApis`);
|
|
6811
6826
|
return {
|
|
6812
6827
|
...privacy === undefined ? {} : { privacyAccessedApis: privacy },
|
|
6828
|
+
...pushNotifications === true ? { pushNotifications: true } : {},
|
|
6813
6829
|
...usageDescriptions === undefined ? {} : { usageDescriptions: [...usageDescriptions] }
|
|
6814
6830
|
};
|
|
6815
6831
|
}, parseProvider = (name, value) => {
|
|
@@ -6865,6 +6881,7 @@ var DEVICES_PACKAGE = "@absolutejs/devices", CAPACITOR_ADAPTER = "@absolutejs/de
|
|
|
6865
6881
|
const reasons = privacy[api];
|
|
6866
6882
|
return reasons ? [{ api, reasons: [...reasons].sort() }] : [];
|
|
6867
6883
|
}),
|
|
6884
|
+
iosPushNotifications: plan.capabilities.some((name) => plan.providers[name]?.native?.ios?.pushNotifications === true),
|
|
6868
6885
|
iosUsageDescriptions: [
|
|
6869
6886
|
...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.ios?.usageDescriptions ?? []))
|
|
6870
6887
|
].sort()
|
|
@@ -7073,6 +7090,11 @@ var isElysiaApp = (value) => typeof value === "object" && value !== null && type
|
|
|
7073
7090
|
const sync = auth !== undefined && projectUsesAbsoluteSync(options.projectRoot);
|
|
7074
7091
|
const syncSchema = sync ? discoverAbsoluteSyncSchema(options.projectRoot) : undefined;
|
|
7075
7092
|
const deviceCapabilities = resolveAbsoluteDeviceCapabilityPlan(options.projectRoot);
|
|
7093
|
+
const usesPush = deviceCapabilities.capabilities.includes("pushNotifications");
|
|
7094
|
+
if (usesPush && !auth)
|
|
7095
|
+
throw new TypeError("Portable push notifications require @absolutejs/auth so provider tokens can be registered without exposing identity controls to page code.");
|
|
7096
|
+
if (usesPush && !loaded.app.routes.some((route) => route.path === "/auth/push" || route.path === "/auth/mobile/push"))
|
|
7097
|
+
throw new TypeError("@absolutejs/devices pushNotifications is used, but Auth push is not configured. Pass a trusted server-side registrar to auth({ push: ... }).");
|
|
7076
7098
|
assertAbsoluteDeviceCapabilityPackages(options.projectRoot, deviceCapabilities);
|
|
7077
7099
|
if (auth && !loaded.app.routes.some((route) => route.path === "/.well-known/openid-configuration")) {
|
|
7078
7100
|
throw new TypeError("@absolutejs/auth is installed, but its OIDC provider is not mounted. Native authentication requires the auth oidc configuration so AbsoluteJS can provision a public PKCE client.");
|
|
@@ -16515,7 +16537,7 @@ var init_nativeDeepLinks = () => {};
|
|
|
16515
16537
|
// src/mobile/nativeDeviceCapabilities.ts
|
|
16516
16538
|
import { readFile as readFile12, rename as rename9, writeFile as writeFile10 } from "fs/promises";
|
|
16517
16539
|
import { join as join47 } from "path";
|
|
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) => {
|
|
16540
|
+
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", PUSH_START_MARKER = "absolutejs:push-notifications:start", PUSH_END_MARKER = "absolutejs:push-notifications:end", escapeXml2 = (value) => value.replaceAll("&", "&").replaceAll('"', """).replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">"), writeChangedFile2 = async (path, source) => {
|
|
16519
16541
|
const current = await readFile12(path, "utf8");
|
|
16520
16542
|
if (current === source)
|
|
16521
16543
|
return false;
|
|
@@ -16523,6 +16545,15 @@ var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->", END_MARKER2
|
|
|
16523
16545
|
await writeFile10(temporary, source, { flag: "wx" });
|
|
16524
16546
|
await rename9(temporary, path);
|
|
16525
16547
|
return true;
|
|
16548
|
+
}, writeOptionalChangedFile = async (path, source) => {
|
|
16549
|
+
const current = await optionalSource(path);
|
|
16550
|
+
if (current === source)
|
|
16551
|
+
return false;
|
|
16552
|
+
if (current === null) {
|
|
16553
|
+
await writeFile10(path, source, { flag: "wx" });
|
|
16554
|
+
return true;
|
|
16555
|
+
}
|
|
16556
|
+
return writeChangedFile2(path, source);
|
|
16526
16557
|
}, optionalSource = async (path) => {
|
|
16527
16558
|
try {
|
|
16528
16559
|
return await readFile12(path, "utf8");
|
|
@@ -16697,11 +16728,71 @@ ${content}
|
|
|
16697
16728
|
const privacyPath = join47(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
|
|
16698
16729
|
const privacyCurrent = await optionalSource(privacyPath);
|
|
16699
16730
|
const privacySource = privacyManifestSource(privacyCurrent, requirements);
|
|
16700
|
-
const [privacyChanged, projectChanged] = await Promise.all([
|
|
16731
|
+
const [privacyChanged, projectChanged, pushChanged] = await Promise.all([
|
|
16701
16732
|
writeIosPrivacyManifest(privacyPath, privacyCurrent, privacySource),
|
|
16702
|
-
configureIosPrivacyProject(config, requirements)
|
|
16733
|
+
configureIosPrivacyProject(config, requirements),
|
|
16734
|
+
configureIosPushNotifications(config, requirements.iosPushNotifications)
|
|
16703
16735
|
]);
|
|
16704
|
-
return infoChanged || privacyChanged || projectChanged;
|
|
16736
|
+
return infoChanged || privacyChanged || projectChanged || pushChanged;
|
|
16737
|
+
}, configureIosPushNotifications = async (config, enabled) => {
|
|
16738
|
+
const entitlementsPath = join47(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
|
|
16739
|
+
const entitlements = await optionalSource(entitlementsPath);
|
|
16740
|
+
if (entitlements === null && !enabled)
|
|
16741
|
+
return false;
|
|
16742
|
+
if (entitlements === null)
|
|
16743
|
+
throw new TypeError("AbsoluteJS iOS entitlements are missing. Run native deep-link projection before device capabilities.");
|
|
16744
|
+
const entitlementRegion = enabled ? ` <!-- ${PUSH_START_MARKER} -->
|
|
16745
|
+
<key>aps-environment</key>
|
|
16746
|
+
<string>development</string>
|
|
16747
|
+
<!-- ${PUSH_END_MARKER} -->
|
|
16748
|
+
` : "";
|
|
16749
|
+
const nextEntitlements = replacePushRegion(entitlements, entitlementRegion, entitlements.lastIndexOf("</dict>"));
|
|
16750
|
+
const delegatePath = join47(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
|
|
16751
|
+
const delegate = await optionalSource(delegatePath);
|
|
16752
|
+
if (delegate === null && !enabled)
|
|
16753
|
+
return false;
|
|
16754
|
+
if (delegate === null)
|
|
16755
|
+
throw new TypeError("Capacitor AppDelegate.swift is missing for iOS push notifications.");
|
|
16756
|
+
const hasSuccess = delegate.includes("didRegisterForRemoteNotificationsWithDeviceToken");
|
|
16757
|
+
const hasFailure = delegate.includes("didFailToRegisterForRemoteNotificationsWithError");
|
|
16758
|
+
if (enabled && hasSuccess !== hasFailure && !delegate.includes(PUSH_START_MARKER))
|
|
16759
|
+
throw new TypeError("iOS AppDelegate has a partial custom remote-notification registration implementation.");
|
|
16760
|
+
const alreadyForwarded = enabled && hasSuccess && hasFailure && delegate.includes("capacitorDidRegisterForRemoteNotifications") && delegate.includes("capacitorDidFailToRegisterForRemoteNotifications");
|
|
16761
|
+
const swiftRegion = enabled && !alreadyForwarded ? `
|
|
16762
|
+
// ${PUSH_START_MARKER}
|
|
16763
|
+
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
|
|
16764
|
+
NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: deviceToken)
|
|
16765
|
+
}
|
|
16766
|
+
|
|
16767
|
+
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
|
|
16768
|
+
NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
|
|
16769
|
+
}
|
|
16770
|
+
// ${PUSH_END_MARKER}
|
|
16771
|
+
` : "";
|
|
16772
|
+
const nextDelegate = alreadyForwarded ? delegate : replacePushRegion(delegate, swiftRegion, delegate.lastIndexOf("}"));
|
|
16773
|
+
const changed = await Promise.all([
|
|
16774
|
+
writeChangedFile2(entitlementsPath, nextEntitlements),
|
|
16775
|
+
writeChangedFile2(delegatePath, nextDelegate)
|
|
16776
|
+
]);
|
|
16777
|
+
return changed.some(Boolean);
|
|
16778
|
+
}, replacePushRegion = (source, region, insertion) => {
|
|
16779
|
+
const start2 = source.indexOf(PUSH_START_MARKER);
|
|
16780
|
+
const end = source.indexOf(PUSH_END_MARKER);
|
|
16781
|
+
if (start2 < 0 !== end < 0 || start2 >= 0 && end < start2)
|
|
16782
|
+
throw new TypeError("AbsoluteJS push-notification ownership markers are malformed.");
|
|
16783
|
+
if (start2 >= 0) {
|
|
16784
|
+
const lineStart = source.lastIndexOf(`
|
|
16785
|
+
`, start2) + 1;
|
|
16786
|
+
const nextLine = source.indexOf(`
|
|
16787
|
+
`, end + PUSH_END_MARKER.length);
|
|
16788
|
+
const lineEnd = nextLine < 0 ? source.length : nextLine + 1;
|
|
16789
|
+
return `${source.slice(0, lineStart)}${region}${source.slice(lineEnd)}`;
|
|
16790
|
+
}
|
|
16791
|
+
if (!region)
|
|
16792
|
+
return source;
|
|
16793
|
+
if (insertion < 0)
|
|
16794
|
+
throw new TypeError("Could not find a safe native project location for push notifications.");
|
|
16795
|
+
return `${source.slice(0, insertion)}${region}${source.slice(insertion)}`;
|
|
16705
16796
|
}, configureAndroid2 = async (config, plan) => {
|
|
16706
16797
|
const path = join47(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
16707
16798
|
const source = await readFile12(path, "utf8");
|
|
@@ -16715,7 +16806,33 @@ ${content}
|
|
|
16715
16806
|
const application = source.indexOf("<application");
|
|
16716
16807
|
const insertion = application === NOT_FOUND2 ? NOT_FOUND2 : source.lastIndexOf(`
|
|
16717
16808
|
`, application) + 1;
|
|
16718
|
-
|
|
16809
|
+
const nextManifest = managed(source, region, insertion);
|
|
16810
|
+
if (!plan.capabilities.includes("pushNotifications"))
|
|
16811
|
+
return writeChangedFile2(path, nextManifest);
|
|
16812
|
+
const firebaseSource = await optionalSource(config.pushAndroidGoogleServicesFile);
|
|
16813
|
+
if (firebaseSource === null)
|
|
16814
|
+
throw new TypeError(`Push notifications require Firebase config at ${config.pushAndroidGoogleServicesFile}. Set mobile.pushNotifications.android.googleServicesFile to override it.`);
|
|
16815
|
+
let firebase;
|
|
16816
|
+
try {
|
|
16817
|
+
firebase = JSON.parse(firebaseSource);
|
|
16818
|
+
} catch (error) {
|
|
16819
|
+
throw new TypeError("Android google-services.json is invalid JSON.", {
|
|
16820
|
+
cause: error
|
|
16821
|
+
});
|
|
16822
|
+
}
|
|
16823
|
+
const clients = typeof firebase === "object" && firebase !== null ? Reflect.get(firebase, "client") : undefined;
|
|
16824
|
+
const matchesApp = Array.isArray(clients) && clients.some((client) => {
|
|
16825
|
+
const info2 = typeof client === "object" && client !== null ? Reflect.get(client, "client_info") : undefined;
|
|
16826
|
+
const android = typeof info2 === "object" && info2 !== null ? Reflect.get(info2, "android_client_info") : undefined;
|
|
16827
|
+
return typeof android === "object" && android !== null && Reflect.get(android, "package_name") === config.appId;
|
|
16828
|
+
});
|
|
16829
|
+
if (!matchesApp)
|
|
16830
|
+
throw new TypeError(`Android google-services.json does not contain package ${config.appId}.`);
|
|
16831
|
+
const [manifestChanged, firebaseChanged] = await Promise.all([
|
|
16832
|
+
writeChangedFile2(path, nextManifest),
|
|
16833
|
+
writeOptionalChangedFile(join47(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
|
|
16834
|
+
]);
|
|
16835
|
+
return manifestChanged || firebaseChanged;
|
|
16719
16836
|
}, applyAbsoluteNativeDeviceCapabilities = async (projectRoot, config, platforms = config.platforms, plan = resolveAbsoluteDeviceCapabilityPlan(projectRoot)) => {
|
|
16720
16837
|
const results = await Promise.all(platforms.map(async (platform6) => ({
|
|
16721
16838
|
didChange: platform6 === "ios" ? await configureIos2(config, plan) : await configureAndroid2(config, plan),
|