@absolutejs/absolute 0.20.0-beta.25 → 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 +2 -2
- package/dist/index.js +1314 -1037
- package/dist/index.js.map +5 -4
- package/dist/mobile/index.js +267 -266
- package/dist/mobile/index.js.map +5 -5
- package/dist/src/mobile/deviceCapabilities.d.ts +3 -0
- package/dist/src/mobile/shellPush.d.ts +1 -1
- package/dist/types/build.d.ts +9 -1
- package/package.json +4 -4
package/dist/mobile/index.js
CHANGED
|
@@ -589,6 +589,263 @@ var init_syncSchema = __esm(() => {
|
|
|
589
589
|
init_client();
|
|
590
590
|
});
|
|
591
591
|
|
|
592
|
+
// src/mobile/deviceCapabilities.ts
|
|
593
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
594
|
+
import { extname as extname3, join as join13, relative as relative9, resolve as resolve11 } from "path";
|
|
595
|
+
import ts from "typescript";
|
|
596
|
+
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) => {
|
|
597
|
+
const value = JSON.parse(readFileSync4(path, "utf8"));
|
|
598
|
+
if (!object2(value))
|
|
599
|
+
throw new TypeError(`${path} must contain an object.`);
|
|
600
|
+
return value;
|
|
601
|
+
}, text = (value, field) => {
|
|
602
|
+
if (typeof value !== "string" || value.length === 0)
|
|
603
|
+
throw new TypeError(`${field} must be a non-empty string.`);
|
|
604
|
+
return value;
|
|
605
|
+
}, androidPermissions = (value, field) => {
|
|
606
|
+
if (value === undefined)
|
|
607
|
+
return;
|
|
608
|
+
if (!object2(value))
|
|
609
|
+
throw new TypeError(`${field} must be an object.`);
|
|
610
|
+
const { permissions } = value;
|
|
611
|
+
if (!Array.isArray(permissions) || !permissions.every((permission) => typeof permission === "string" && ANDROID_PERMISSION_PATTERN.test(permission)))
|
|
612
|
+
throw new TypeError(`${field}.permissions must contain Android permission names.`);
|
|
613
|
+
return [...permissions];
|
|
614
|
+
}, iosPrivacyAccessedApis = (value, field) => {
|
|
615
|
+
if (value === undefined)
|
|
616
|
+
return;
|
|
617
|
+
if (!object2(value))
|
|
618
|
+
throw new TypeError(`${field} must be an object.`);
|
|
619
|
+
const privacy = {};
|
|
620
|
+
for (const api of IOS_PRIVACY_ACCESSED_APIS) {
|
|
621
|
+
const reasons = value[api];
|
|
622
|
+
if (reasons === undefined)
|
|
623
|
+
continue;
|
|
624
|
+
const supported = IOS_PRIVACY_ACCESSED_API_REASONS[api];
|
|
625
|
+
if (!Array.isArray(reasons) || reasons.length === 0 || !reasons.every((reason) => typeof reason === "string" && supported.has(reason)))
|
|
626
|
+
throw new TypeError(`${field} contains an unsupported API or reason.`);
|
|
627
|
+
privacy[api] = [...reasons];
|
|
628
|
+
}
|
|
629
|
+
if (Object.keys(value).some((api) => !IOS_PRIVACY_ACCESSED_APIS.some((known) => known === api)))
|
|
630
|
+
throw new TypeError(`${field} contains an unsupported API or reason.`);
|
|
631
|
+
return privacy;
|
|
632
|
+
}, iosNativeRequirements = (value, field) => {
|
|
633
|
+
if (value === undefined)
|
|
634
|
+
return;
|
|
635
|
+
if (!object2(value))
|
|
636
|
+
throw new TypeError(`${field} must be an object.`);
|
|
637
|
+
const { privacyAccessedApis, pushNotifications, usageDescriptions } = value;
|
|
638
|
+
if (pushNotifications !== undefined && pushNotifications !== true)
|
|
639
|
+
throw new TypeError(`${field}.pushNotifications must be true.`);
|
|
640
|
+
if (usageDescriptions !== undefined && (!Array.isArray(usageDescriptions) || !usageDescriptions.every((purpose) => typeof purpose === "string" && IOS_USAGE_DESCRIPTIONS.has(purpose))))
|
|
641
|
+
throw new TypeError(`${field}.usageDescriptions contains an unsupported purpose.`);
|
|
642
|
+
const privacy = iosPrivacyAccessedApis(privacyAccessedApis, `${field}.privacyAccessedApis`);
|
|
643
|
+
return {
|
|
644
|
+
...privacy === undefined ? {} : { privacyAccessedApis: privacy },
|
|
645
|
+
...pushNotifications === true ? { pushNotifications: true } : {},
|
|
646
|
+
...usageDescriptions === undefined ? {} : { usageDescriptions: [...usageDescriptions] }
|
|
647
|
+
};
|
|
648
|
+
}, parseProvider = (name, value) => {
|
|
649
|
+
if (!IDENTIFIER_PATTERN.test(name))
|
|
650
|
+
throw new TypeError("Device capability names must be identifiers.");
|
|
651
|
+
if (!object2(value))
|
|
652
|
+
throw new TypeError(`Device capability ${name} must be an object.`);
|
|
653
|
+
const factory = text(value.factory, `${name}.factory`);
|
|
654
|
+
const module = text(value.module, `${name}.module`);
|
|
655
|
+
if (!IDENTIFIER_PATTERN.test(factory))
|
|
656
|
+
throw new TypeError(`${name}.factory must be a JavaScript identifier.`);
|
|
657
|
+
if (!CAPACITOR_MODULE_PATTERN.test(module))
|
|
658
|
+
throw new TypeError(`${name}.module must be an official devices-capacitor subpath.`);
|
|
659
|
+
if (!Array.isArray(value.packages) || !value.packages.every((spec) => typeof spec === "string" && CAPACITOR_PACKAGE_PATTERN.test(spec)))
|
|
660
|
+
throw new TypeError(`${name}.packages must contain exact official Capacitor package versions.`);
|
|
661
|
+
let native;
|
|
662
|
+
const { native: nativeMetadata } = value;
|
|
663
|
+
if (nativeMetadata !== undefined) {
|
|
664
|
+
if (!object2(nativeMetadata))
|
|
665
|
+
throw new TypeError(`${name}.native must be an object.`);
|
|
666
|
+
const { android, ios } = nativeMetadata;
|
|
667
|
+
const permissions = androidPermissions(android, `${name}.native.android`);
|
|
668
|
+
const iosRequirements = iosNativeRequirements(ios, `${name}.native.ios`);
|
|
669
|
+
native = {
|
|
670
|
+
...permissions === undefined ? {} : { android: { permissions } },
|
|
671
|
+
...iosRequirements === undefined ? {} : { ios: iosRequirements }
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
return {
|
|
675
|
+
factory,
|
|
676
|
+
module,
|
|
677
|
+
...native === undefined ? {} : { native },
|
|
678
|
+
packages: [...value.packages]
|
|
679
|
+
};
|
|
680
|
+
}, absoluteDeviceNativeRequirements = (plan) => {
|
|
681
|
+
const privacy = plan.capabilities.reduce((requirements, name) => {
|
|
682
|
+
for (const api of IOS_PRIVACY_ACCESSED_APIS) {
|
|
683
|
+
const reasons = plan.providers[name]?.native?.ios?.privacyAccessedApis?.[api] ?? [];
|
|
684
|
+
if (reasons.length === 0)
|
|
685
|
+
continue;
|
|
686
|
+
const current = requirements[api] ?? new Set;
|
|
687
|
+
for (const reason of reasons)
|
|
688
|
+
current.add(reason);
|
|
689
|
+
requirements[api] = current;
|
|
690
|
+
}
|
|
691
|
+
return requirements;
|
|
692
|
+
}, {});
|
|
693
|
+
return {
|
|
694
|
+
androidPermissions: [
|
|
695
|
+
...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.android?.permissions ?? []))
|
|
696
|
+
].sort(),
|
|
697
|
+
iosPrivacyAccessedApis: IOS_PRIVACY_ACCESSED_APIS.flatMap((api) => {
|
|
698
|
+
const reasons = privacy[api];
|
|
699
|
+
return reasons ? [{ api, reasons: [...reasons].sort() }] : [];
|
|
700
|
+
}),
|
|
701
|
+
iosPushNotifications: plan.capabilities.some((name) => plan.providers[name]?.native?.ios?.pushNotifications === true),
|
|
702
|
+
iosUsageDescriptions: [
|
|
703
|
+
...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.ios?.usageDescriptions ?? []))
|
|
704
|
+
].sort()
|
|
705
|
+
};
|
|
706
|
+
}, loadAbsoluteDeviceCapabilityProviders = (projectRoot) => {
|
|
707
|
+
const path = join13(resolve11(projectRoot), "node_modules", CAPACITOR_ADAPTER, "package.json");
|
|
708
|
+
const manifest = readJson(path);
|
|
709
|
+
const { absolutejs } = manifest;
|
|
710
|
+
const devices = object2(absolutejs) ? absolutejs.devices : undefined;
|
|
711
|
+
if (!object2(devices) || devices.format !== 1 || devices.provider !== "capacitor" || !object2(devices.capabilities))
|
|
712
|
+
throw new TypeError(`${CAPACITOR_ADAPTER} does not publish supported capability metadata.`);
|
|
713
|
+
const entries = Object.entries(devices.capabilities).map(([name, provider]) => ({
|
|
714
|
+
name,
|
|
715
|
+
provider: parseProvider(name, provider)
|
|
716
|
+
}));
|
|
717
|
+
return Object.fromEntries(entries.sort((left, right) => left.name.localeCompare(right.name)).map(({ name, provider }) => [name, provider]));
|
|
718
|
+
}, isIgnored = (path) => path.split("/").some((segment) => IGNORED_DIRECTORIES.has(segment)), importedCapabilities = (source, file) => {
|
|
719
|
+
const names = new Set;
|
|
720
|
+
const namespaces = new Set;
|
|
721
|
+
const visit = (node) => {
|
|
722
|
+
if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier) && node.moduleSpecifier.text === DEVICES_PACKAGE && !node.importClause?.isTypeOnly) {
|
|
723
|
+
const bindings = node.importClause?.namedBindings;
|
|
724
|
+
if (bindings && ts.isNamedImports(bindings)) {
|
|
725
|
+
for (const element of bindings.elements)
|
|
726
|
+
if (!element.isTypeOnly)
|
|
727
|
+
names.add((element.propertyName ?? element.name).text);
|
|
728
|
+
}
|
|
729
|
+
if (bindings && ts.isNamespaceImport(bindings))
|
|
730
|
+
namespaces.add(bindings.name.text);
|
|
731
|
+
}
|
|
732
|
+
if (ts.isExportDeclaration(node) && !node.isTypeOnly && node.moduleSpecifier !== undefined && ts.isStringLiteral(node.moduleSpecifier) && node.moduleSpecifier.text === DEVICES_PACKAGE && node.exportClause && ts.isNamedExports(node.exportClause)) {
|
|
733
|
+
for (const element of node.exportClause.elements)
|
|
734
|
+
if (!element.isTypeOnly)
|
|
735
|
+
names.add((element.propertyName ?? element.name).text);
|
|
736
|
+
}
|
|
737
|
+
if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && namespaces.has(node.expression.text))
|
|
738
|
+
names.add(node.name.text);
|
|
739
|
+
ts.forEachChild(node, visit);
|
|
740
|
+
};
|
|
741
|
+
const extension = extname3(file).toLowerCase();
|
|
742
|
+
const sources = extension === ".svelte" || extension === ".vue" ? [...source.matchAll(/<script\b[^>]*>([\s\S]*?)<\/script\s*>/giu)].map((match) => match[1]).filter((value) => value !== undefined) : [source];
|
|
743
|
+
for (const [index, script] of sources.entries())
|
|
744
|
+
visit(ts.createSourceFile(`${file}#script-${index}`, script, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX));
|
|
745
|
+
return names;
|
|
746
|
+
}, assertAbsoluteDeviceCapabilityPackages = (projectRoot, plan) => {
|
|
747
|
+
const missing = missingAbsoluteDeviceCapabilityPackages(plan, directAbsoluteProjectPackages(projectRoot));
|
|
748
|
+
const mismatched = plan.requiredPackages.filter((spec) => {
|
|
749
|
+
const separator = spec.lastIndexOf("@");
|
|
750
|
+
const packageName = spec.slice(0, separator);
|
|
751
|
+
if (missing.includes(spec))
|
|
752
|
+
return false;
|
|
753
|
+
try {
|
|
754
|
+
return readJson(join13(resolve11(projectRoot), "node_modules", packageName, "package.json")).version !== spec.slice(separator + 1);
|
|
755
|
+
} catch {
|
|
756
|
+
return true;
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
const unmet = [...missing, ...mismatched];
|
|
760
|
+
if (unmet.length > 0)
|
|
761
|
+
throw new TypeError(`Device capabilities ${plan.capabilities.join(", ")} require ${unmet.join(", ")}. Run absolute mobile sync and approve the detected capability plugins.`);
|
|
762
|
+
}, directAbsoluteProjectPackages = (projectRoot) => {
|
|
763
|
+
const manifest = readJson(join13(resolve11(projectRoot), "package.json"));
|
|
764
|
+
const packages = new Set;
|
|
765
|
+
for (const field of ["dependencies", "devDependencies"]) {
|
|
766
|
+
const dependencies = manifest[field];
|
|
767
|
+
if (object2(dependencies))
|
|
768
|
+
for (const name of Object.keys(dependencies))
|
|
769
|
+
packages.add(name);
|
|
770
|
+
}
|
|
771
|
+
return packages;
|
|
772
|
+
}, discoverAbsoluteDeviceCapabilities = (projectRoot, providers = loadAbsoluteDeviceCapabilityProviders(projectRoot)) => {
|
|
773
|
+
const root = resolve11(projectRoot);
|
|
774
|
+
const known = new Set(Object.keys(providers));
|
|
775
|
+
const capabilities = new Set;
|
|
776
|
+
for (const path of SOURCE_GLOB.scanSync({ cwd: root })) {
|
|
777
|
+
const portable = relative9(root, resolve11(root, path)).replaceAll("\\", "/");
|
|
778
|
+
if (isIgnored(portable))
|
|
779
|
+
continue;
|
|
780
|
+
const source = readFileSync4(resolve11(root, portable), "utf8");
|
|
781
|
+
for (const name of importedCapabilities(source, portable))
|
|
782
|
+
if (known.has(name))
|
|
783
|
+
capabilities.add(name);
|
|
784
|
+
}
|
|
785
|
+
return [...capabilities].sort();
|
|
786
|
+
}, missingAbsoluteDeviceCapabilityPackages = (plan, directPackages) => plan.requiredPackages.filter((spec) => {
|
|
787
|
+
const packageName = spec.slice(0, spec.lastIndexOf("@"));
|
|
788
|
+
return !directPackages.has(packageName);
|
|
789
|
+
}), projectImportsAbsoluteDeviceCapability = (projectRoot, capability) => {
|
|
790
|
+
const root = resolve11(projectRoot);
|
|
791
|
+
for (const path of SOURCE_GLOB.scanSync({ cwd: root })) {
|
|
792
|
+
const portable = relative9(root, resolve11(root, path)).replaceAll("\\", "/");
|
|
793
|
+
if (isIgnored(portable))
|
|
794
|
+
continue;
|
|
795
|
+
const source = readFileSync4(resolve11(root, portable), "utf8");
|
|
796
|
+
if (importedCapabilities(source, portable).has(capability))
|
|
797
|
+
return true;
|
|
798
|
+
}
|
|
799
|
+
return false;
|
|
800
|
+
}, resolveAbsoluteDeviceCapabilityPlan = (projectRoot) => {
|
|
801
|
+
const allProviders = loadAbsoluteDeviceCapabilityProviders(projectRoot);
|
|
802
|
+
const capabilities = discoverAbsoluteDeviceCapabilities(projectRoot, allProviders);
|
|
803
|
+
const providers = {};
|
|
804
|
+
for (const name of capabilities) {
|
|
805
|
+
const provider = allProviders[name];
|
|
806
|
+
if (provider)
|
|
807
|
+
providers[name] = provider;
|
|
808
|
+
}
|
|
809
|
+
return {
|
|
810
|
+
capabilities,
|
|
811
|
+
providers,
|
|
812
|
+
requiredPackages: [
|
|
813
|
+
...new Set(capabilities.flatMap((name) => providers[name]?.packages ?? []))
|
|
814
|
+
].sort()
|
|
815
|
+
};
|
|
816
|
+
};
|
|
817
|
+
var init_deviceCapabilities = __esm(() => {
|
|
818
|
+
SOURCE_GLOB = new Bun.Glob("**/*.{js,jsx,ts,tsx,svelte,vue}");
|
|
819
|
+
IGNORED_DIRECTORIES = new Set([
|
|
820
|
+
".absolutejs",
|
|
821
|
+
".git",
|
|
822
|
+
".test-builds",
|
|
823
|
+
".test-shards",
|
|
824
|
+
"build",
|
|
825
|
+
"dist",
|
|
826
|
+
"node_modules",
|
|
827
|
+
"test",
|
|
828
|
+
"tests"
|
|
829
|
+
]);
|
|
830
|
+
IDENTIFIER_PATTERN = /^[A-Za-z_$][\w$]*$/u;
|
|
831
|
+
CAPACITOR_MODULE_PATTERN = /^@absolutejs\/devices-capacitor\/[a-z][a-z0-9-]*$/u;
|
|
832
|
+
CAPACITOR_PACKAGE_PATTERN = /^@capacitor\/[a-z][a-z0-9-]*@\d+\.\d+\.\d+$/u;
|
|
833
|
+
ANDROID_PERMISSION_PATTERN = /^android\.permission\.[A-Z][A-Z0-9_]*$/u;
|
|
834
|
+
IOS_USAGE_DESCRIPTIONS = new Set([
|
|
835
|
+
"camera",
|
|
836
|
+
"location-always",
|
|
837
|
+
"location-when-in-use",
|
|
838
|
+
"photo-library",
|
|
839
|
+
"photo-library-add"
|
|
840
|
+
]);
|
|
841
|
+
IOS_PRIVACY_ACCESSED_API_REASONS = {
|
|
842
|
+
NSPrivacyAccessedAPICategoryFileTimestamp: new Set(["C617.1"])
|
|
843
|
+
};
|
|
844
|
+
IOS_PRIVACY_ACCESSED_APIS = [
|
|
845
|
+
"NSPrivacyAccessedAPICategoryFileTimestamp"
|
|
846
|
+
];
|
|
847
|
+
});
|
|
848
|
+
|
|
592
849
|
// src/mobile/artifactStore.ts
|
|
593
850
|
import { createHash as createHash2 } from "crypto";
|
|
594
851
|
import {
|
|
@@ -5061,269 +5318,7 @@ var serializeAbsoluteMobileAuthEnvironment = (config, auth) => auth === undefine
|
|
|
5061
5318
|
|
|
5062
5319
|
// src/mobile/buildPipeline.ts
|
|
5063
5320
|
init_syncSchema();
|
|
5064
|
-
|
|
5065
|
-
// src/mobile/deviceCapabilities.ts
|
|
5066
|
-
import { readFileSync as readFileSync4 } from "fs";
|
|
5067
|
-
import { extname as extname3, join as join13, relative as relative9, resolve as resolve11 } from "path";
|
|
5068
|
-
import ts from "typescript";
|
|
5069
|
-
var DEVICES_PACKAGE = "@absolutejs/devices";
|
|
5070
|
-
var CAPACITOR_ADAPTER = "@absolutejs/devices-capacitor";
|
|
5071
|
-
var SOURCE_GLOB = new Bun.Glob("**/*.{js,jsx,ts,tsx,svelte,vue}");
|
|
5072
|
-
var IGNORED_DIRECTORIES = new Set([
|
|
5073
|
-
".absolutejs",
|
|
5074
|
-
".git",
|
|
5075
|
-
".test-builds",
|
|
5076
|
-
".test-shards",
|
|
5077
|
-
"build",
|
|
5078
|
-
"dist",
|
|
5079
|
-
"node_modules",
|
|
5080
|
-
"test",
|
|
5081
|
-
"tests"
|
|
5082
|
-
]);
|
|
5083
|
-
var IDENTIFIER_PATTERN = /^[A-Za-z_$][\w$]*$/u;
|
|
5084
|
-
var CAPACITOR_MODULE_PATTERN = /^@absolutejs\/devices-capacitor\/[a-z][a-z0-9-]*$/u;
|
|
5085
|
-
var CAPACITOR_PACKAGE_PATTERN = /^@capacitor\/[a-z][a-z0-9-]*@\d+\.\d+\.\d+$/u;
|
|
5086
|
-
var ANDROID_PERMISSION_PATTERN = /^android\.permission\.[A-Z][A-Z0-9_]*$/u;
|
|
5087
|
-
var IOS_USAGE_DESCRIPTIONS = new Set([
|
|
5088
|
-
"camera",
|
|
5089
|
-
"location-always",
|
|
5090
|
-
"location-when-in-use",
|
|
5091
|
-
"photo-library",
|
|
5092
|
-
"photo-library-add"
|
|
5093
|
-
]);
|
|
5094
|
-
var IOS_PRIVACY_ACCESSED_API_REASONS = {
|
|
5095
|
-
NSPrivacyAccessedAPICategoryFileTimestamp: new Set(["C617.1"])
|
|
5096
|
-
};
|
|
5097
|
-
var IOS_PRIVACY_ACCESSED_APIS = [
|
|
5098
|
-
"NSPrivacyAccessedAPICategoryFileTimestamp"
|
|
5099
|
-
];
|
|
5100
|
-
var object2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5101
|
-
var readJson = (path) => {
|
|
5102
|
-
const value = JSON.parse(readFileSync4(path, "utf8"));
|
|
5103
|
-
if (!object2(value))
|
|
5104
|
-
throw new TypeError(`${path} must contain an object.`);
|
|
5105
|
-
return value;
|
|
5106
|
-
};
|
|
5107
|
-
var text = (value, field) => {
|
|
5108
|
-
if (typeof value !== "string" || value.length === 0)
|
|
5109
|
-
throw new TypeError(`${field} must be a non-empty string.`);
|
|
5110
|
-
return value;
|
|
5111
|
-
};
|
|
5112
|
-
var androidPermissions = (value, field) => {
|
|
5113
|
-
if (value === undefined)
|
|
5114
|
-
return;
|
|
5115
|
-
if (!object2(value))
|
|
5116
|
-
throw new TypeError(`${field} must be an object.`);
|
|
5117
|
-
const { permissions } = value;
|
|
5118
|
-
if (!Array.isArray(permissions) || !permissions.every((permission) => typeof permission === "string" && ANDROID_PERMISSION_PATTERN.test(permission)))
|
|
5119
|
-
throw new TypeError(`${field}.permissions must contain Android permission names.`);
|
|
5120
|
-
return [...permissions];
|
|
5121
|
-
};
|
|
5122
|
-
var iosPrivacyAccessedApis = (value, field) => {
|
|
5123
|
-
if (value === undefined)
|
|
5124
|
-
return;
|
|
5125
|
-
if (!object2(value))
|
|
5126
|
-
throw new TypeError(`${field} must be an object.`);
|
|
5127
|
-
const privacy = {};
|
|
5128
|
-
for (const api of IOS_PRIVACY_ACCESSED_APIS) {
|
|
5129
|
-
const reasons = value[api];
|
|
5130
|
-
if (reasons === undefined)
|
|
5131
|
-
continue;
|
|
5132
|
-
const supported = IOS_PRIVACY_ACCESSED_API_REASONS[api];
|
|
5133
|
-
if (!Array.isArray(reasons) || reasons.length === 0 || !reasons.every((reason) => typeof reason === "string" && supported.has(reason)))
|
|
5134
|
-
throw new TypeError(`${field} contains an unsupported API or reason.`);
|
|
5135
|
-
privacy[api] = [...reasons];
|
|
5136
|
-
}
|
|
5137
|
-
if (Object.keys(value).some((api) => !IOS_PRIVACY_ACCESSED_APIS.some((known) => known === api)))
|
|
5138
|
-
throw new TypeError(`${field} contains an unsupported API or reason.`);
|
|
5139
|
-
return privacy;
|
|
5140
|
-
};
|
|
5141
|
-
var iosNativeRequirements = (value, field) => {
|
|
5142
|
-
if (value === undefined)
|
|
5143
|
-
return;
|
|
5144
|
-
if (!object2(value))
|
|
5145
|
-
throw new TypeError(`${field} must be an object.`);
|
|
5146
|
-
const { privacyAccessedApis, pushNotifications, usageDescriptions } = value;
|
|
5147
|
-
if (pushNotifications !== undefined && pushNotifications !== true)
|
|
5148
|
-
throw new TypeError(`${field}.pushNotifications must be true.`);
|
|
5149
|
-
if (usageDescriptions !== undefined && (!Array.isArray(usageDescriptions) || !usageDescriptions.every((purpose) => typeof purpose === "string" && IOS_USAGE_DESCRIPTIONS.has(purpose))))
|
|
5150
|
-
throw new TypeError(`${field}.usageDescriptions contains an unsupported purpose.`);
|
|
5151
|
-
const privacy = iosPrivacyAccessedApis(privacyAccessedApis, `${field}.privacyAccessedApis`);
|
|
5152
|
-
return {
|
|
5153
|
-
...privacy === undefined ? {} : { privacyAccessedApis: privacy },
|
|
5154
|
-
...pushNotifications === true ? { pushNotifications: true } : {},
|
|
5155
|
-
...usageDescriptions === undefined ? {} : { usageDescriptions: [...usageDescriptions] }
|
|
5156
|
-
};
|
|
5157
|
-
};
|
|
5158
|
-
var parseProvider = (name, value) => {
|
|
5159
|
-
if (!IDENTIFIER_PATTERN.test(name))
|
|
5160
|
-
throw new TypeError("Device capability names must be identifiers.");
|
|
5161
|
-
if (!object2(value))
|
|
5162
|
-
throw new TypeError(`Device capability ${name} must be an object.`);
|
|
5163
|
-
const factory = text(value.factory, `${name}.factory`);
|
|
5164
|
-
const module = text(value.module, `${name}.module`);
|
|
5165
|
-
if (!IDENTIFIER_PATTERN.test(factory))
|
|
5166
|
-
throw new TypeError(`${name}.factory must be a JavaScript identifier.`);
|
|
5167
|
-
if (!CAPACITOR_MODULE_PATTERN.test(module))
|
|
5168
|
-
throw new TypeError(`${name}.module must be an official devices-capacitor subpath.`);
|
|
5169
|
-
if (!Array.isArray(value.packages) || !value.packages.every((spec) => typeof spec === "string" && CAPACITOR_PACKAGE_PATTERN.test(spec)))
|
|
5170
|
-
throw new TypeError(`${name}.packages must contain exact official Capacitor package versions.`);
|
|
5171
|
-
let native;
|
|
5172
|
-
const { native: nativeMetadata } = value;
|
|
5173
|
-
if (nativeMetadata !== undefined) {
|
|
5174
|
-
if (!object2(nativeMetadata))
|
|
5175
|
-
throw new TypeError(`${name}.native must be an object.`);
|
|
5176
|
-
const { android, ios } = nativeMetadata;
|
|
5177
|
-
const permissions = androidPermissions(android, `${name}.native.android`);
|
|
5178
|
-
const iosRequirements = iosNativeRequirements(ios, `${name}.native.ios`);
|
|
5179
|
-
native = {
|
|
5180
|
-
...permissions === undefined ? {} : { android: { permissions } },
|
|
5181
|
-
...iosRequirements === undefined ? {} : { ios: iosRequirements }
|
|
5182
|
-
};
|
|
5183
|
-
}
|
|
5184
|
-
return {
|
|
5185
|
-
factory,
|
|
5186
|
-
module,
|
|
5187
|
-
...native === undefined ? {} : { native },
|
|
5188
|
-
packages: [...value.packages]
|
|
5189
|
-
};
|
|
5190
|
-
};
|
|
5191
|
-
var absoluteDeviceNativeRequirements = (plan) => {
|
|
5192
|
-
const privacy = plan.capabilities.reduce((requirements, name) => {
|
|
5193
|
-
for (const api of IOS_PRIVACY_ACCESSED_APIS) {
|
|
5194
|
-
const reasons = plan.providers[name]?.native?.ios?.privacyAccessedApis?.[api] ?? [];
|
|
5195
|
-
if (reasons.length === 0)
|
|
5196
|
-
continue;
|
|
5197
|
-
const current = requirements[api] ?? new Set;
|
|
5198
|
-
for (const reason of reasons)
|
|
5199
|
-
current.add(reason);
|
|
5200
|
-
requirements[api] = current;
|
|
5201
|
-
}
|
|
5202
|
-
return requirements;
|
|
5203
|
-
}, {});
|
|
5204
|
-
return {
|
|
5205
|
-
androidPermissions: [
|
|
5206
|
-
...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.android?.permissions ?? []))
|
|
5207
|
-
].sort(),
|
|
5208
|
-
iosPrivacyAccessedApis: IOS_PRIVACY_ACCESSED_APIS.flatMap((api) => {
|
|
5209
|
-
const reasons = privacy[api];
|
|
5210
|
-
return reasons ? [{ api, reasons: [...reasons].sort() }] : [];
|
|
5211
|
-
}),
|
|
5212
|
-
iosPushNotifications: plan.capabilities.some((name) => plan.providers[name]?.native?.ios?.pushNotifications === true),
|
|
5213
|
-
iosUsageDescriptions: [
|
|
5214
|
-
...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.ios?.usageDescriptions ?? []))
|
|
5215
|
-
].sort()
|
|
5216
|
-
};
|
|
5217
|
-
};
|
|
5218
|
-
var loadAbsoluteDeviceCapabilityProviders = (projectRoot) => {
|
|
5219
|
-
const path = join13(resolve11(projectRoot), "node_modules", CAPACITOR_ADAPTER, "package.json");
|
|
5220
|
-
const manifest = readJson(path);
|
|
5221
|
-
const { absolutejs } = manifest;
|
|
5222
|
-
const devices = object2(absolutejs) ? absolutejs.devices : undefined;
|
|
5223
|
-
if (!object2(devices) || devices.format !== 1 || devices.provider !== "capacitor" || !object2(devices.capabilities))
|
|
5224
|
-
throw new TypeError(`${CAPACITOR_ADAPTER} does not publish supported capability metadata.`);
|
|
5225
|
-
const entries = Object.entries(devices.capabilities).map(([name, provider]) => ({
|
|
5226
|
-
name,
|
|
5227
|
-
provider: parseProvider(name, provider)
|
|
5228
|
-
}));
|
|
5229
|
-
return Object.fromEntries(entries.sort((left, right) => left.name.localeCompare(right.name)).map(({ name, provider }) => [name, provider]));
|
|
5230
|
-
};
|
|
5231
|
-
var isIgnored = (path) => path.split("/").some((segment) => IGNORED_DIRECTORIES.has(segment));
|
|
5232
|
-
var importedCapabilities = (source, file) => {
|
|
5233
|
-
const names = new Set;
|
|
5234
|
-
const namespaces = new Set;
|
|
5235
|
-
const visit = (node) => {
|
|
5236
|
-
if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier) && node.moduleSpecifier.text === DEVICES_PACKAGE && !node.importClause?.isTypeOnly) {
|
|
5237
|
-
const bindings = node.importClause?.namedBindings;
|
|
5238
|
-
if (bindings && ts.isNamedImports(bindings)) {
|
|
5239
|
-
for (const element of bindings.elements)
|
|
5240
|
-
if (!element.isTypeOnly)
|
|
5241
|
-
names.add((element.propertyName ?? element.name).text);
|
|
5242
|
-
}
|
|
5243
|
-
if (bindings && ts.isNamespaceImport(bindings))
|
|
5244
|
-
namespaces.add(bindings.name.text);
|
|
5245
|
-
}
|
|
5246
|
-
if (ts.isExportDeclaration(node) && !node.isTypeOnly && node.moduleSpecifier !== undefined && ts.isStringLiteral(node.moduleSpecifier) && node.moduleSpecifier.text === DEVICES_PACKAGE && node.exportClause && ts.isNamedExports(node.exportClause)) {
|
|
5247
|
-
for (const element of node.exportClause.elements)
|
|
5248
|
-
if (!element.isTypeOnly)
|
|
5249
|
-
names.add((element.propertyName ?? element.name).text);
|
|
5250
|
-
}
|
|
5251
|
-
if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && namespaces.has(node.expression.text))
|
|
5252
|
-
names.add(node.name.text);
|
|
5253
|
-
ts.forEachChild(node, visit);
|
|
5254
|
-
};
|
|
5255
|
-
const extension = extname3(file).toLowerCase();
|
|
5256
|
-
const sources = extension === ".svelte" || extension === ".vue" ? [...source.matchAll(/<script\b[^>]*>([\s\S]*?)<\/script\s*>/giu)].map((match) => match[1]).filter((value) => value !== undefined) : [source];
|
|
5257
|
-
for (const [index, script] of sources.entries())
|
|
5258
|
-
visit(ts.createSourceFile(`${file}#script-${index}`, script, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX));
|
|
5259
|
-
return names;
|
|
5260
|
-
};
|
|
5261
|
-
var assertAbsoluteDeviceCapabilityPackages = (projectRoot, plan) => {
|
|
5262
|
-
const missing = missingAbsoluteDeviceCapabilityPackages(plan, directAbsoluteProjectPackages(projectRoot));
|
|
5263
|
-
const mismatched = plan.requiredPackages.filter((spec) => {
|
|
5264
|
-
const separator = spec.lastIndexOf("@");
|
|
5265
|
-
const packageName = spec.slice(0, separator);
|
|
5266
|
-
if (missing.includes(spec))
|
|
5267
|
-
return false;
|
|
5268
|
-
try {
|
|
5269
|
-
return readJson(join13(resolve11(projectRoot), "node_modules", packageName, "package.json")).version !== spec.slice(separator + 1);
|
|
5270
|
-
} catch {
|
|
5271
|
-
return true;
|
|
5272
|
-
}
|
|
5273
|
-
});
|
|
5274
|
-
const unmet = [...missing, ...mismatched];
|
|
5275
|
-
if (unmet.length > 0)
|
|
5276
|
-
throw new TypeError(`Device capabilities ${plan.capabilities.join(", ")} require ${unmet.join(", ")}. Run absolute mobile sync and approve the detected capability plugins.`);
|
|
5277
|
-
};
|
|
5278
|
-
var directAbsoluteProjectPackages = (projectRoot) => {
|
|
5279
|
-
const manifest = readJson(join13(resolve11(projectRoot), "package.json"));
|
|
5280
|
-
const packages = new Set;
|
|
5281
|
-
for (const field of ["dependencies", "devDependencies"]) {
|
|
5282
|
-
const dependencies = manifest[field];
|
|
5283
|
-
if (object2(dependencies))
|
|
5284
|
-
for (const name of Object.keys(dependencies))
|
|
5285
|
-
packages.add(name);
|
|
5286
|
-
}
|
|
5287
|
-
return packages;
|
|
5288
|
-
};
|
|
5289
|
-
var discoverAbsoluteDeviceCapabilities = (projectRoot, providers = loadAbsoluteDeviceCapabilityProviders(projectRoot)) => {
|
|
5290
|
-
const root = resolve11(projectRoot);
|
|
5291
|
-
const known = new Set(Object.keys(providers));
|
|
5292
|
-
const capabilities = new Set;
|
|
5293
|
-
for (const path of SOURCE_GLOB.scanSync({ cwd: root })) {
|
|
5294
|
-
const portable = relative9(root, resolve11(root, path)).replaceAll("\\", "/");
|
|
5295
|
-
if (isIgnored(portable))
|
|
5296
|
-
continue;
|
|
5297
|
-
const source = readFileSync4(resolve11(root, portable), "utf8");
|
|
5298
|
-
for (const name of importedCapabilities(source, portable))
|
|
5299
|
-
if (known.has(name))
|
|
5300
|
-
capabilities.add(name);
|
|
5301
|
-
}
|
|
5302
|
-
return [...capabilities].sort();
|
|
5303
|
-
};
|
|
5304
|
-
var missingAbsoluteDeviceCapabilityPackages = (plan, directPackages) => plan.requiredPackages.filter((spec) => {
|
|
5305
|
-
const packageName = spec.slice(0, spec.lastIndexOf("@"));
|
|
5306
|
-
return !directPackages.has(packageName);
|
|
5307
|
-
});
|
|
5308
|
-
var resolveAbsoluteDeviceCapabilityPlan = (projectRoot) => {
|
|
5309
|
-
const allProviders = loadAbsoluteDeviceCapabilityProviders(projectRoot);
|
|
5310
|
-
const capabilities = discoverAbsoluteDeviceCapabilities(projectRoot, allProviders);
|
|
5311
|
-
const providers = {};
|
|
5312
|
-
for (const name of capabilities) {
|
|
5313
|
-
const provider = allProviders[name];
|
|
5314
|
-
if (provider)
|
|
5315
|
-
providers[name] = provider;
|
|
5316
|
-
}
|
|
5317
|
-
return {
|
|
5318
|
-
capabilities,
|
|
5319
|
-
providers,
|
|
5320
|
-
requiredPackages: [
|
|
5321
|
-
...new Set(capabilities.flatMap((name) => providers[name]?.packages ?? []))
|
|
5322
|
-
].sort()
|
|
5323
|
-
};
|
|
5324
|
-
};
|
|
5325
|
-
|
|
5326
|
-
// src/mobile/buildPipeline.ts
|
|
5321
|
+
init_deviceCapabilities();
|
|
5327
5322
|
var isElysiaApp = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "compile") === "function" && Array.isArray(Reflect.get(value, "routes"));
|
|
5328
5323
|
var isStringRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
|
|
5329
5324
|
var serverExportName = (loaded, app) => {
|
|
@@ -5401,8 +5396,8 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
|
5401
5396
|
const usesPush = deviceCapabilities.capabilities.includes("pushNotifications");
|
|
5402
5397
|
if (usesPush && !auth)
|
|
5403
5398
|
throw new TypeError("Portable push notifications require @absolutejs/auth so provider tokens can be registered without exposing identity controls to page code.");
|
|
5404
|
-
if (usesPush && !loaded.app.routes.some((route) => route.path === "/auth/mobile/push"))
|
|
5405
|
-
throw new TypeError("@absolutejs/devices pushNotifications is used, but Auth
|
|
5399
|
+
if (usesPush && !loaded.app.routes.some((route) => route.path === "/auth/push" || route.path === "/auth/mobile/push"))
|
|
5400
|
+
throw new TypeError("@absolutejs/devices pushNotifications is used, but Auth push is not configured. Pass a trusted server-side registrar to auth({ push: ... }).");
|
|
5406
5401
|
assertAbsoluteDeviceCapabilityPackages(options.projectRoot, deviceCapabilities);
|
|
5407
5402
|
if (auth && !loaded.app.routes.some((route) => route.path === "/.well-known/openid-configuration")) {
|
|
5408
5403
|
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.");
|
|
@@ -5540,6 +5535,10 @@ var installAbsoluteMobileSyncRemediation = (bridge = {
|
|
|
5540
5535
|
registry3.installations.splice(index, 1);
|
|
5541
5536
|
};
|
|
5542
5537
|
};
|
|
5538
|
+
|
|
5539
|
+
// src/mobile/index.ts
|
|
5540
|
+
init_deviceCapabilities();
|
|
5541
|
+
|
|
5543
5542
|
// src/mobile/compatibilityDispatcher.ts
|
|
5544
5543
|
import { Elysia as Elysia2 } from "elysia";
|
|
5545
5544
|
|
|
@@ -5845,6 +5844,7 @@ var applyAbsoluteNativeDeepLinks = async (config, platforms = config.platforms)
|
|
|
5845
5844
|
};
|
|
5846
5845
|
};
|
|
5847
5846
|
// src/mobile/nativeDeviceCapabilities.ts
|
|
5847
|
+
init_deviceCapabilities();
|
|
5848
5848
|
import { readFile as readFile15, rename as rename12, writeFile as writeFile13 } from "fs/promises";
|
|
5849
5849
|
import { join as join16 } from "path";
|
|
5850
5850
|
var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->";
|
|
@@ -6837,6 +6837,7 @@ export {
|
|
|
6837
6837
|
publishAbsoluteAndroidRelease,
|
|
6838
6838
|
projectUsesAbsoluteSync,
|
|
6839
6839
|
projectUsesAbsoluteAuth,
|
|
6840
|
+
projectImportsAbsoluteDeviceCapability,
|
|
6840
6841
|
prepareAbsoluteIosRelease,
|
|
6841
6842
|
prepareAbsoluteIosDevProject,
|
|
6842
6843
|
prepareAbsoluteAndroidRelease,
|
|
@@ -6931,5 +6932,5 @@ export {
|
|
|
6931
6932
|
ABSOLUTE_ANDROID_RELEASE_FORMAT
|
|
6932
6933
|
};
|
|
6933
6934
|
|
|
6934
|
-
//# debugId=
|
|
6935
|
+
//# debugId=17F8DCA356CF789D64756E2164756E21
|
|
6935
6936
|
//# sourceMappingURL=index.js.map
|