@absolutejs/absolute 0.20.0-beta.17 → 0.20.0-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3927,7 +3927,7 @@ var parseAbsoluteMobileBuildPageMetadata = (value) => {
3927
3927
  };
3928
3928
  // src/mobile/buildPipeline.ts
3929
3929
  import { readFile as readFile13 } from "fs/promises";
3930
- import { join as join13, resolve as resolve11 } from "path";
3930
+ import { join as join14, resolve as resolve12 } from "path";
3931
3931
  import { pathToFileURL as pathToFileURL2 } from "url";
3932
3932
 
3933
3933
  // src/mobile/buildRelease.ts
@@ -4598,16 +4598,51 @@ var sourceAssetPath = (buildDirectory, bundlePath) => {
4598
4598
  }
4599
4599
  return asset;
4600
4600
  };
4601
- var buildShellBootstrap = async (staging, auth, sync) => {
4601
+ var importEntryTarget = (entry) => {
4602
+ if (typeof entry === "string")
4603
+ return entry;
4604
+ if (typeof entry === "object" && entry !== null)
4605
+ return Reflect.get(entry, "import");
4606
+ return;
4607
+ };
4608
+ var resolveProjectImport = async (projectRoot, specifier) => {
4609
+ const segments = specifier.split("/");
4610
+ const packageName = specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0] ?? "";
4611
+ const subpath = specifier.slice(packageName.length);
4612
+ const packageDirectory = join9(resolve9(projectRoot), "node_modules", packageName);
4613
+ const manifest = JSON.parse(await readFile11(join9(packageDirectory, "package.json"), "utf8"));
4614
+ const exports = typeof manifest === "object" && manifest !== null ? Reflect.get(manifest, "exports") : undefined;
4615
+ const entry = typeof exports === "object" && exports !== null ? Reflect.get(exports, subpath ? `.${subpath}` : ".") : undefined;
4616
+ const target = importEntryTarget(entry);
4617
+ if (typeof target !== "string" || !target.startsWith("./"))
4618
+ throw new TypeError(`${specifier} does not publish an import entry.`);
4619
+ const resolved = resolve9(packageDirectory, target);
4620
+ if (!resolved.startsWith(`${resolve9(packageDirectory)}/`))
4621
+ throw new TypeError(`${specifier} has an unsafe import entry.`);
4622
+ return resolved;
4623
+ };
4624
+ var buildShellBootstrap = async (staging, auth, sync, storagePrefix, deviceCapabilities, projectRoot) => {
4602
4625
  const modulePath = shellBootstrapModule();
4603
4626
  const authImport = auth ? `import { createAbsoluteMobileShellAuth } from ${JSON.stringify(shellAuthModule())};
4604
4627
  ` : "";
4605
4628
  const options = auth ? `{ createAuth: createAbsoluteMobileShellAuth${sync ? ", installSync: installAbsoluteMobileShellSync" : ""} }` : "";
4606
4629
  const syncImport = sync ? `import { installAbsoluteMobileShellSync } from ${JSON.stringify(shellSyncModule())};
4607
4630
  ` : "";
4631
+ const capabilityImports = (await Promise.all(deviceCapabilities.capabilities.map(async (name, index) => {
4632
+ const provider = deviceCapabilities.providers[name];
4633
+ if (!provider)
4634
+ throw new TypeError(`Missing device capability provider ${name}.`);
4635
+ return `import { ${provider.factory} as absoluteDeviceCapability${index} } from ${JSON.stringify(await resolveProjectImport(projectRoot, provider.module))};`;
4636
+ }))).join(`
4637
+ `);
4638
+ const capabilityOptions = deviceCapabilities.capabilities.map((name, index) => `${JSON.stringify(name)}: absoluteDeviceCapability${index}()`).join(", ");
4608
4639
  const entryPath = join9(staging, ".absolute-mobile-entry.ts");
4640
+ const baseAdapterModule = await resolveProjectImport(projectRoot, "@absolutejs/devices-capacitor");
4609
4641
  await writeFile10(entryPath, `import { startAbsoluteMobileShell } from ${JSON.stringify(modulePath)};
4610
- ${authImport}${syncImport}void startAbsoluteMobileShell(${options});
4642
+ import { installCapacitorDeviceAdapterIfNative } from ${JSON.stringify(baseAdapterModule)};
4643
+ ${authImport}${syncImport}${capabilityImports}
4644
+ installCapacitorDeviceAdapterIfNative({ storagePrefix: ${JSON.stringify(storagePrefix)}${capabilityOptions ? `, ${capabilityOptions}` : ""} });
4645
+ void startAbsoluteMobileShell(${options});
4611
4646
  `);
4612
4647
  const build = await Bun.build({
4613
4648
  entrypoints: [entryPath],
@@ -4745,6 +4780,7 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
4745
4780
  appName: options.config.appName,
4746
4781
  deepLinkHosts: options.config.deepLinkHosts,
4747
4782
  deepLinkScheme: options.config.deepLinkScheme,
4783
+ deviceCapabilities: options.deviceCapabilities.capabilities,
4748
4784
  entry: options.config.entry,
4749
4785
  format: ABSOLUTE_MOBILE_CLIENT_MANIFEST_FORMAT,
4750
4786
  pages,
@@ -4770,7 +4806,7 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
4770
4806
  writeFile10(join9(staging, MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
4771
4807
  `),
4772
4808
  writeFile10(join9(staging, INDEX_FILE), indexHtml(options.config.appName)),
4773
- buildShellBootstrap(staging, options.auth !== undefined, options.auth !== undefined && options.sync === true)
4809
+ buildShellBootstrap(staging, options.auth !== undefined, options.auth !== undefined && options.sync === true, `absolutejs.${options.auth?.clientId ?? options.config.appId}.`, options.deviceCapabilities, options.projectRoot)
4774
4810
  ]);
4775
4811
  await installBundle(staging, destination);
4776
4812
  return manifest;
@@ -5011,6 +5047,216 @@ var serializeAbsoluteMobileAuthEnvironment = (config, auth) => auth === undefine
5011
5047
 
5012
5048
  // src/mobile/buildPipeline.ts
5013
5049
  init_syncSchema();
5050
+
5051
+ // src/mobile/deviceCapabilities.ts
5052
+ import { readFileSync as readFileSync4 } from "fs";
5053
+ import { extname as extname3, join as join13, relative as relative9, resolve as resolve11 } from "path";
5054
+ import ts from "typescript";
5055
+ var DEVICES_PACKAGE = "@absolutejs/devices";
5056
+ var CAPACITOR_ADAPTER = "@absolutejs/devices-capacitor";
5057
+ var SOURCE_GLOB = new Bun.Glob("**/*.{js,jsx,ts,tsx,svelte,vue}");
5058
+ var IGNORED_DIRECTORIES = new Set([
5059
+ ".absolutejs",
5060
+ ".git",
5061
+ ".test-builds",
5062
+ ".test-shards",
5063
+ "build",
5064
+ "dist",
5065
+ "node_modules",
5066
+ "test",
5067
+ "tests"
5068
+ ]);
5069
+ var IDENTIFIER_PATTERN = /^[A-Za-z_$][\w$]*$/u;
5070
+ var CAPACITOR_MODULE_PATTERN = /^@absolutejs\/devices-capacitor\/[a-z][a-z0-9-]*$/u;
5071
+ var CAPACITOR_PACKAGE_PATTERN = /^@capacitor\/[a-z][a-z0-9-]*@\d+\.\d+\.\d+$/u;
5072
+ var ANDROID_PERMISSION_PATTERN = /^android\.permission\.[A-Z][A-Z0-9_]*$/u;
5073
+ var IOS_USAGE_DESCRIPTIONS = new Set([
5074
+ "camera",
5075
+ "photo-library",
5076
+ "photo-library-add"
5077
+ ]);
5078
+ var object2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
5079
+ var readJson = (path) => {
5080
+ const value = JSON.parse(readFileSync4(path, "utf8"));
5081
+ if (!object2(value))
5082
+ throw new TypeError(`${path} must contain an object.`);
5083
+ return value;
5084
+ };
5085
+ var text = (value, field) => {
5086
+ if (typeof value !== "string" || value.length === 0)
5087
+ throw new TypeError(`${field} must be a non-empty string.`);
5088
+ return value;
5089
+ };
5090
+ var androidPermissions = (value, field) => {
5091
+ if (value === undefined)
5092
+ return;
5093
+ if (!object2(value))
5094
+ throw new TypeError(`${field} must be an object.`);
5095
+ const { permissions } = value;
5096
+ if (!Array.isArray(permissions) || !permissions.every((permission) => typeof permission === "string" && ANDROID_PERMISSION_PATTERN.test(permission)))
5097
+ throw new TypeError(`${field}.permissions must contain Android permission names.`);
5098
+ return [...permissions];
5099
+ };
5100
+ var iosUsageDescriptions = (value, field) => {
5101
+ if (value === undefined)
5102
+ return;
5103
+ if (!object2(value))
5104
+ throw new TypeError(`${field} must be an object.`);
5105
+ const { usageDescriptions } = value;
5106
+ if (!Array.isArray(usageDescriptions) || !usageDescriptions.every((purpose) => typeof purpose === "string" && IOS_USAGE_DESCRIPTIONS.has(purpose)))
5107
+ throw new TypeError(`${field}.usageDescriptions contains an unsupported purpose.`);
5108
+ return [...usageDescriptions];
5109
+ };
5110
+ var parseProvider = (name, value) => {
5111
+ if (!IDENTIFIER_PATTERN.test(name))
5112
+ throw new TypeError("Device capability names must be identifiers.");
5113
+ if (!object2(value))
5114
+ throw new TypeError(`Device capability ${name} must be an object.`);
5115
+ const factory = text(value.factory, `${name}.factory`);
5116
+ const module = text(value.module, `${name}.module`);
5117
+ if (!IDENTIFIER_PATTERN.test(factory))
5118
+ throw new TypeError(`${name}.factory must be a JavaScript identifier.`);
5119
+ if (!CAPACITOR_MODULE_PATTERN.test(module))
5120
+ throw new TypeError(`${name}.module must be an official devices-capacitor subpath.`);
5121
+ if (!Array.isArray(value.packages) || !value.packages.every((spec) => typeof spec === "string" && CAPACITOR_PACKAGE_PATTERN.test(spec)))
5122
+ throw new TypeError(`${name}.packages must contain exact official Capacitor package versions.`);
5123
+ let native;
5124
+ const { native: nativeMetadata } = value;
5125
+ if (nativeMetadata !== undefined) {
5126
+ if (!object2(nativeMetadata))
5127
+ throw new TypeError(`${name}.native must be an object.`);
5128
+ const { android, ios } = nativeMetadata;
5129
+ const permissions = androidPermissions(android, `${name}.native.android`);
5130
+ const usageDescriptions = iosUsageDescriptions(ios, `${name}.native.ios`);
5131
+ native = {
5132
+ ...permissions === undefined ? {} : { android: { permissions } },
5133
+ ...usageDescriptions === undefined ? {} : { ios: { usageDescriptions } }
5134
+ };
5135
+ }
5136
+ return {
5137
+ factory,
5138
+ module,
5139
+ ...native === undefined ? {} : { native },
5140
+ packages: [...value.packages]
5141
+ };
5142
+ };
5143
+ var absoluteDeviceNativeRequirements = (plan) => ({
5144
+ androidPermissions: [
5145
+ ...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.android?.permissions ?? []))
5146
+ ].sort(),
5147
+ iosUsageDescriptions: [
5148
+ ...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.ios?.usageDescriptions ?? []))
5149
+ ].sort()
5150
+ });
5151
+ var loadAbsoluteDeviceCapabilityProviders = (projectRoot) => {
5152
+ const path = join13(resolve11(projectRoot), "node_modules", CAPACITOR_ADAPTER, "package.json");
5153
+ const manifest = readJson(path);
5154
+ const { absolutejs } = manifest;
5155
+ const devices = object2(absolutejs) ? absolutejs.devices : undefined;
5156
+ if (!object2(devices) || devices.format !== 1 || devices.provider !== "capacitor" || !object2(devices.capabilities))
5157
+ throw new TypeError(`${CAPACITOR_ADAPTER} does not publish supported capability metadata.`);
5158
+ const entries = Object.entries(devices.capabilities).map(([name, provider]) => ({
5159
+ name,
5160
+ provider: parseProvider(name, provider)
5161
+ }));
5162
+ return Object.fromEntries(entries.sort((left, right) => left.name.localeCompare(right.name)).map(({ name, provider }) => [name, provider]));
5163
+ };
5164
+ var isIgnored = (path) => path.split("/").some((segment) => IGNORED_DIRECTORIES.has(segment));
5165
+ var importedCapabilities = (source, file) => {
5166
+ const names = new Set;
5167
+ const namespaces = new Set;
5168
+ const visit = (node) => {
5169
+ if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier) && node.moduleSpecifier.text === DEVICES_PACKAGE && !node.importClause?.isTypeOnly) {
5170
+ const bindings = node.importClause?.namedBindings;
5171
+ if (bindings && ts.isNamedImports(bindings)) {
5172
+ for (const element of bindings.elements)
5173
+ if (!element.isTypeOnly)
5174
+ names.add((element.propertyName ?? element.name).text);
5175
+ }
5176
+ if (bindings && ts.isNamespaceImport(bindings))
5177
+ namespaces.add(bindings.name.text);
5178
+ }
5179
+ if (ts.isExportDeclaration(node) && !node.isTypeOnly && node.moduleSpecifier !== undefined && ts.isStringLiteral(node.moduleSpecifier) && node.moduleSpecifier.text === DEVICES_PACKAGE && node.exportClause && ts.isNamedExports(node.exportClause)) {
5180
+ for (const element of node.exportClause.elements)
5181
+ if (!element.isTypeOnly)
5182
+ names.add((element.propertyName ?? element.name).text);
5183
+ }
5184
+ if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression) && namespaces.has(node.expression.text))
5185
+ names.add(node.name.text);
5186
+ ts.forEachChild(node, visit);
5187
+ };
5188
+ const extension = extname3(file).toLowerCase();
5189
+ const sources = extension === ".svelte" || extension === ".vue" ? [...source.matchAll(/<script\b[^>]*>([\s\S]*?)<\/script\s*>/giu)].map((match) => match[1]).filter((value) => value !== undefined) : [source];
5190
+ for (const [index, script] of sources.entries())
5191
+ visit(ts.createSourceFile(`${file}#script-${index}`, script, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX));
5192
+ return names;
5193
+ };
5194
+ var assertAbsoluteDeviceCapabilityPackages = (projectRoot, plan) => {
5195
+ const missing = missingAbsoluteDeviceCapabilityPackages(plan, directAbsoluteProjectPackages(projectRoot));
5196
+ const mismatched = plan.requiredPackages.filter((spec) => {
5197
+ const separator = spec.lastIndexOf("@");
5198
+ const packageName = spec.slice(0, separator);
5199
+ if (missing.includes(spec))
5200
+ return false;
5201
+ try {
5202
+ return readJson(join13(resolve11(projectRoot), "node_modules", packageName, "package.json")).version !== spec.slice(separator + 1);
5203
+ } catch {
5204
+ return true;
5205
+ }
5206
+ });
5207
+ const unmet = [...missing, ...mismatched];
5208
+ if (unmet.length > 0)
5209
+ throw new TypeError(`Device capabilities ${plan.capabilities.join(", ")} require ${unmet.join(", ")}. Run absolute mobile sync and approve the detected capability plugins.`);
5210
+ };
5211
+ var directAbsoluteProjectPackages = (projectRoot) => {
5212
+ const manifest = readJson(join13(resolve11(projectRoot), "package.json"));
5213
+ const packages = new Set;
5214
+ for (const field of ["dependencies", "devDependencies"]) {
5215
+ const dependencies = manifest[field];
5216
+ if (object2(dependencies))
5217
+ for (const name of Object.keys(dependencies))
5218
+ packages.add(name);
5219
+ }
5220
+ return packages;
5221
+ };
5222
+ var discoverAbsoluteDeviceCapabilities = (projectRoot, providers = loadAbsoluteDeviceCapabilityProviders(projectRoot)) => {
5223
+ const root = resolve11(projectRoot);
5224
+ const known = new Set(Object.keys(providers));
5225
+ const capabilities = new Set;
5226
+ for (const path of SOURCE_GLOB.scanSync({ cwd: root })) {
5227
+ const portable = relative9(root, resolve11(root, path)).replaceAll("\\", "/");
5228
+ if (isIgnored(portable))
5229
+ continue;
5230
+ const source = readFileSync4(resolve11(root, portable), "utf8");
5231
+ for (const name of importedCapabilities(source, portable))
5232
+ if (known.has(name))
5233
+ capabilities.add(name);
5234
+ }
5235
+ return [...capabilities].sort();
5236
+ };
5237
+ var missingAbsoluteDeviceCapabilityPackages = (plan, directPackages) => plan.requiredPackages.filter((spec) => {
5238
+ const packageName = spec.slice(0, spec.lastIndexOf("@"));
5239
+ return !directPackages.has(packageName);
5240
+ });
5241
+ var resolveAbsoluteDeviceCapabilityPlan = (projectRoot) => {
5242
+ const allProviders = loadAbsoluteDeviceCapabilityProviders(projectRoot);
5243
+ const capabilities = discoverAbsoluteDeviceCapabilities(projectRoot, allProviders);
5244
+ const providers = {};
5245
+ for (const name of capabilities) {
5246
+ const provider = allProviders[name];
5247
+ if (provider)
5248
+ providers[name] = provider;
5249
+ }
5250
+ return {
5251
+ capabilities,
5252
+ providers,
5253
+ requiredPackages: [
5254
+ ...new Set(capabilities.flatMap((name) => providers[name]?.packages ?? []))
5255
+ ].sort()
5256
+ };
5257
+ };
5258
+
5259
+ // src/mobile/buildPipeline.ts
5014
5260
  var isElysiaApp = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "compile") === "function" && Array.isArray(Reflect.get(value, "routes"));
5015
5261
  var isStringRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
5016
5262
  var serverExportName = (loaded, app) => {
@@ -5044,11 +5290,11 @@ var loadServerApp = async (producerPath) => {
5044
5290
  return { app, exportName };
5045
5291
  };
5046
5292
  var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
5047
- const buildDirectory = resolve11(options.buildDirectory);
5293
+ const buildDirectory = resolve12(options.buildDirectory);
5048
5294
  const mobile = normalizeAbsoluteMobileConfig(options.mobile, options.projectRoot);
5049
- const root = join13(buildDirectory, ".absolutejs", "mobile-compatibility");
5295
+ const root = join14(buildDirectory, ".absolutejs", "mobile-compatibility");
5050
5296
  const [manifestSource, previous] = await Promise.all([
5051
- readFile13(join13(buildDirectory, "manifest.json"), "utf8"),
5297
+ readFile13(join14(buildDirectory, "manifest.json"), "utf8"),
5052
5298
  readAbsoluteMobileMaterializedReleases(root)
5053
5299
  ]);
5054
5300
  const manifest = JSON.parse(manifestSource);
@@ -5061,11 +5307,11 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
5061
5307
  process.env.ABSOLUTE_BUILD_DIR = buildDirectory;
5062
5308
  process.env.ABSOLUTE_COMPILED_RUNTIME = "1";
5063
5309
  if (options.configPath) {
5064
- process.env.ABSOLUTE_CONFIG = resolve11(options.projectRoot, options.configPath);
5310
+ process.env.ABSOLUTE_CONFIG = resolve12(options.projectRoot, options.configPath);
5065
5311
  }
5066
5312
  let loaded;
5067
5313
  try {
5068
- loaded = await loadServerApp(resolve11(options.producerPath));
5314
+ loaded = await loadServerApp(resolve12(options.producerPath));
5069
5315
  } finally {
5070
5316
  restoreEnvironmentVariable("ABSOLUTE_BUILD_DIR", previousBuildDirectory);
5071
5317
  restoreEnvironmentVariable("ABSOLUTE_COMPILED_RUNTIME", previousCompiledRuntime);
@@ -5078,12 +5324,14 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
5078
5324
  manifest,
5079
5325
  previousArtifacts: previous.map(({ artifact }) => artifact),
5080
5326
  producerExport: loaded.exportName,
5081
- producerPath: resolve11(options.producerPath),
5327
+ producerPath: resolve12(options.producerPath),
5082
5328
  runtime: String(ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION)
5083
5329
  });
5084
5330
  const auth = resolveAbsoluteMobileAuthManifest(options.projectRoot, mobile);
5085
5331
  const sync = auth !== undefined && projectUsesAbsoluteSync(options.projectRoot);
5086
5332
  const syncSchema = sync ? discoverAbsoluteSyncSchema(options.projectRoot) : undefined;
5333
+ const deviceCapabilities = resolveAbsoluteDeviceCapabilityPlan(options.projectRoot);
5334
+ assertAbsoluteDeviceCapabilityPackages(options.projectRoot, deviceCapabilities);
5087
5335
  if (auth && !loaded.app.routes.some((route) => route.path === "/.well-known/openid-configuration")) {
5088
5336
  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.");
5089
5337
  }
@@ -5102,6 +5350,8 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
5102
5350
  ...auth ? { auth } : {},
5103
5351
  buildDirectory,
5104
5352
  config: mobile,
5353
+ deviceCapabilities,
5354
+ projectRoot: options.projectRoot,
5105
5355
  ...sync ? { sync: true } : {},
5106
5356
  ...syncSchema ? { syncSchema: { components: syncSchema.components } } : {}
5107
5357
  });
@@ -5359,7 +5609,7 @@ var createAbsoluteMobileCompatibilityDispatcher = (options) => {
5359
5609
  };
5360
5610
  // src/mobile/nativeDeepLinks.ts
5361
5611
  import { readFile as readFile14, rename as rename11, writeFile as writeFile12 } from "fs/promises";
5362
- import { join as join14 } from "path";
5612
+ import { join as join15 } from "path";
5363
5613
  var START_MARKER = "<!-- absolutejs:deep-links:start -->";
5364
5614
  var END_MARKER = "<!-- absolutejs:deep-links:end -->";
5365
5615
  var IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements";
@@ -5416,7 +5666,7 @@ ${hosts}
5416
5666
  `;
5417
5667
  };
5418
5668
  var configureAndroid = async (config) => {
5419
- const path = join14(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
5669
+ const path = join15(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
5420
5670
  const source = await readFile14(path, "utf8");
5421
5671
  const mainActivity = source.indexOf('android:name=".MainActivity"');
5422
5672
  if (mainActivity === NOT_FOUND) {
@@ -5442,7 +5692,7 @@ var iosSchemeRegion = (scheme) => ` ${START_MARKER}
5442
5692
  ${END_MARKER}
5443
5693
  `;
5444
5694
  var configureIosInfo = async (config) => {
5445
- const path = join14(config.nativeProjectDirectory, "ios/App/App/Info.plist");
5695
+ const path = join15(config.nativeProjectDirectory, "ios/App/App/Info.plist");
5446
5696
  const source = await readFile14(path, "utf8");
5447
5697
  const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
5448
5698
  ${END_MARKER}
@@ -5466,7 +5716,7 @@ ${domains}
5466
5716
  `;
5467
5717
  };
5468
5718
  var configureIosEntitlements = async (config) => {
5469
- const path = join14(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
5719
+ const path = join15(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
5470
5720
  let current = "";
5471
5721
  try {
5472
5722
  current = await readFile14(path, "utf8");
@@ -5484,7 +5734,7 @@ var configureIosEntitlements = async (config) => {
5484
5734
  return true;
5485
5735
  };
5486
5736
  var configureIosProject = async (config) => {
5487
- const path = join14(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
5737
+ const path = join15(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
5488
5738
  const source = await readFile14(path, "utf8");
5489
5739
  const declarations = [
5490
5740
  ...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
@@ -5522,9 +5772,93 @@ var applyAbsoluteNativeDeepLinks = async (config, platforms = config.platforms)
5522
5772
  changed: results.filter(({ didChange }) => didChange).map(({ platform }) => platform)
5523
5773
  };
5524
5774
  };
5775
+ // src/mobile/nativeDeviceCapabilities.ts
5776
+ import { readFile as readFile15, rename as rename12, writeFile as writeFile13 } from "fs/promises";
5777
+ import { join as join16 } from "path";
5778
+ var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->";
5779
+ var END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->";
5780
+ var NOT_FOUND2 = -1;
5781
+ var escapeXml2 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
5782
+ var writeChangedFile2 = async (path, source) => {
5783
+ const current = await readFile15(path, "utf8");
5784
+ if (current === source)
5785
+ return false;
5786
+ const temporary = `${path}.${crypto.randomUUID()}.tmp`;
5787
+ await writeFile13(temporary, source, { flag: "wx" });
5788
+ await rename12(temporary, path);
5789
+ return true;
5790
+ };
5791
+ var managed = (source, region, insertion) => {
5792
+ const start = source.indexOf(START_MARKER2);
5793
+ const end = source.indexOf(END_MARKER2);
5794
+ if (start === NOT_FOUND2 !== (end === NOT_FOUND2) || start !== NOT_FOUND2 && end < start)
5795
+ throw new TypeError("AbsoluteJS device-capability ownership markers are malformed.");
5796
+ if (start !== NOT_FOUND2) {
5797
+ const lineStart = source.lastIndexOf(`
5798
+ `, start) + 1;
5799
+ const nextLine = source.indexOf(`
5800
+ `, end + END_MARKER2.length);
5801
+ const lineEnd = nextLine === NOT_FOUND2 ? source.length : nextLine + 1;
5802
+ return `${source.slice(0, lineStart)}${region}${source.slice(lineEnd)}`;
5803
+ }
5804
+ if (region.length === 0)
5805
+ return source;
5806
+ if (insertion === NOT_FOUND2)
5807
+ throw new TypeError("Could not find a safe native project location for device permissions.");
5808
+ return `${source.slice(0, insertion)}${region}${source.slice(insertion)}`;
5809
+ };
5810
+ var IOS_KEYS = {
5811
+ camera: "NSCameraUsageDescription",
5812
+ "photo-library": "NSPhotoLibraryUsageDescription",
5813
+ "photo-library-add": "NSPhotoLibraryAddUsageDescription"
5814
+ };
5815
+ var iosDescription = (appName, purpose) => {
5816
+ if (purpose === "camera")
5817
+ return `${appName} uses your camera when you choose to take a photo.`;
5818
+ if (purpose === "photo-library")
5819
+ return `${appName} accesses your photo library only for photo actions you choose.`;
5820
+ return `${appName} adds to your photo library only for photo actions you choose.`;
5821
+ };
5822
+ var configureIos2 = async (config, plan) => {
5823
+ const path = join16(config.nativeProjectDirectory, "ios/App/App/Info.plist");
5824
+ const source = await readFile15(path, "utf8");
5825
+ const requirements = absoluteDeviceNativeRequirements(plan);
5826
+ const content = requirements.iosUsageDescriptions.map((purpose) => ` <key>${IOS_KEYS[purpose]}</key>
5827
+ <string>${escapeXml2(iosDescription(config.appName, purpose))}</string>`).join(`
5828
+ `);
5829
+ const region = content ? ` ${START_MARKER2}
5830
+ ${content}
5831
+ ${END_MARKER2}
5832
+ ` : "";
5833
+ return writeChangedFile2(path, managed(source, region, source.lastIndexOf("</dict>")));
5834
+ };
5835
+ var configureAndroid2 = async (config, plan) => {
5836
+ const path = join16(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
5837
+ const source = await readFile15(path, "utf8");
5838
+ const permissions = absoluteDeviceNativeRequirements(plan).androidPermissions;
5839
+ const content = permissions.map((permission) => ` <uses-permission android:name="${escapeXml2(permission)}" />`).join(`
5840
+ `);
5841
+ const region = content ? ` ${START_MARKER2}
5842
+ ${content}
5843
+ ${END_MARKER2}
5844
+ ` : "";
5845
+ const application = source.indexOf("<application");
5846
+ const insertion = application === NOT_FOUND2 ? NOT_FOUND2 : source.lastIndexOf(`
5847
+ `, application) + 1;
5848
+ return writeChangedFile2(path, managed(source, region, insertion));
5849
+ };
5850
+ var applyAbsoluteNativeDeviceCapabilities = async (projectRoot, config, platforms = config.platforms, plan = resolveAbsoluteDeviceCapabilityPlan(projectRoot)) => {
5851
+ const results = await Promise.all(platforms.map(async (platform) => ({
5852
+ didChange: platform === "ios" ? await configureIos2(config, plan) : await configureAndroid2(config, plan),
5853
+ platform
5854
+ })));
5855
+ return {
5856
+ changed: results.filter(({ didChange }) => didChange).map(({ platform }) => platform)
5857
+ };
5858
+ };
5525
5859
  // src/mobile/releasePublisher.ts
5526
5860
  import { access as access9 } from "fs/promises";
5527
- import { isAbsolute as isAbsolute6, relative as relative9, resolve as resolve12, sep as sep6 } from "path";
5861
+ import { isAbsolute as isAbsolute6, relative as relative10, resolve as resolve13, sep as sep6 } from "path";
5528
5862
  import { pathToFileURL as pathToFileURL3 } from "url";
5529
5863
  var prepareAbsoluteIosRelease = async (publisher, options) => {
5530
5864
  if (typeof publisher.prepareIosRelease !== "function") {
@@ -5550,9 +5884,9 @@ var prepareAbsoluteAndroidRelease = async (publisher, options) => {
5550
5884
  var isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
5551
5885
  var isPublisher = (value) => isRecord8(value) && typeof value.publish === "function";
5552
5886
  var publisherModulePath = (projectRoot, requested) => {
5553
- const root = resolve12(projectRoot);
5554
- const path = resolve12(root, requested);
5555
- const projectRelative = relative9(root, path);
5887
+ const root = resolve13(projectRoot);
5888
+ const path = resolve13(root, requested);
5889
+ const projectRelative = relative10(root, path);
5556
5890
  if (projectRelative === ".." || projectRelative.startsWith(`..${sep6}`) || isAbsolute6(projectRelative)) {
5557
5891
  throw new TypeError("mobile publish --registry must remain inside the project.");
5558
5892
  }
@@ -5621,9 +5955,9 @@ var publishAbsoluteIosRelease = async (options) => {
5621
5955
  return publication;
5622
5956
  };
5623
5957
  // src/mobile/routeMetadataTransform.ts
5624
- import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
5625
- import { dirname as dirname10, extname as extname3, relative as relative10, resolve as resolve13 } from "path";
5626
- import ts from "typescript";
5958
+ import { existsSync as existsSync3, readFileSync as readFileSync5 } from "fs";
5959
+ import { dirname as dirname10, extname as extname4, relative as relative11, resolve as resolve14 } from "path";
5960
+ import ts2 from "typescript";
5627
5961
  var ROUTE_METHODS = new Set(["get", "head"]);
5628
5962
  var SOURCE_FILTER = /\.[cm]?[jt]sx?$/;
5629
5963
  var PAGE_HANDLERS = new Map([
@@ -5673,60 +6007,60 @@ var PAGE_HANDLERS = new Map([
5673
6007
  ]
5674
6008
  ]);
5675
6009
  var posixPath = (value) => value.replace(/\\/g, "/");
5676
- var findTsconfig = (entry, projectRoot) => ts.findConfigFile(dirname10(entry), existsSync3, "tsconfig.json") ?? ts.findConfigFile(projectRoot, existsSync3, "tsconfig.json");
6010
+ var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(dirname10(entry), existsSync3, "tsconfig.json") ?? ts2.findConfigFile(projectRoot, existsSync3, "tsconfig.json");
5677
6011
  var createProgram = (entry, projectRoot) => {
5678
6012
  const configPath = findTsconfig(entry, projectRoot);
5679
6013
  if (!configPath) {
5680
- return ts.createProgram([entry], {
6014
+ return ts2.createProgram([entry], {
5681
6015
  allowJs: true,
5682
- jsx: ts.JsxEmit.ReactJSX,
5683
- module: ts.ModuleKind.ESNext,
5684
- moduleResolution: ts.ModuleResolutionKind.Bundler,
5685
- target: ts.ScriptTarget.ESNext
6016
+ jsx: ts2.JsxEmit.ReactJSX,
6017
+ module: ts2.ModuleKind.ESNext,
6018
+ moduleResolution: ts2.ModuleResolutionKind.Bundler,
6019
+ target: ts2.ScriptTarget.ESNext
5686
6020
  });
5687
6021
  }
5688
- const parsed = ts.parseJsonConfigFileContent(ts.readConfigFile(configPath, (path) => readFileSync4(path, "utf8")).config, ts.sys, dirname10(configPath));
6022
+ const parsed = ts2.parseJsonConfigFileContent(ts2.readConfigFile(configPath, (path) => readFileSync5(path, "utf8")).config, ts2.sys, dirname10(configPath));
5689
6023
  if (!parsed.fileNames.includes(entry))
5690
6024
  parsed.fileNames.push(entry);
5691
- return ts.createProgram(parsed.fileNames, parsed.options);
6025
+ return ts2.createProgram(parsed.fileNames, parsed.options);
5692
6026
  };
5693
6027
  var propertyName = (property) => {
5694
6028
  if (!("name" in property) || !property.name)
5695
6029
  return;
5696
- if (ts.isIdentifier(property.name))
6030
+ if (ts2.isIdentifier(property.name))
5697
6031
  return property.name.text;
5698
- if (ts.isStringLiteralLike(property.name))
6032
+ if (ts2.isStringLiteralLike(property.name))
5699
6033
  return property.name.text;
5700
6034
  return;
5701
6035
  };
5702
- var objectPropertyExpression = (object2, name) => {
5703
- const property = object2.properties.find((candidate) => propertyName(candidate) === name);
5704
- if (property && ts.isPropertyAssignment(property)) {
6036
+ var objectPropertyExpression = (object3, name) => {
6037
+ const property = object3.properties.find((candidate) => propertyName(candidate) === name);
6038
+ if (property && ts2.isPropertyAssignment(property)) {
5705
6039
  return property.initializer;
5706
6040
  }
5707
- if (property && ts.isShorthandPropertyAssignment(property)) {
6041
+ if (property && ts2.isShorthandPropertyAssignment(property)) {
5708
6042
  return property.name;
5709
6043
  }
5710
6044
  return;
5711
6045
  };
5712
6046
  var serializeType = (type, checker, ancestors = new Set) => {
5713
- if (type.flags & ts.TypeFlags.Any)
6047
+ if (type.flags & ts2.TypeFlags.Any)
5714
6048
  return { type: "any" };
5715
- if (type.flags & ts.TypeFlags.Unknown)
6049
+ if (type.flags & ts2.TypeFlags.Unknown)
5716
6050
  return { type: "unknown" };
5717
- if (type.flags & ts.TypeFlags.Never)
6051
+ if (type.flags & ts2.TypeFlags.Never)
5718
6052
  return { type: "never" };
5719
- if (type.flags & ts.TypeFlags.StringLike)
6053
+ if (type.flags & ts2.TypeFlags.StringLike)
5720
6054
  return { type: "string" };
5721
- if (type.flags & ts.TypeFlags.NumberLike)
6055
+ if (type.flags & ts2.TypeFlags.NumberLike)
5722
6056
  return { type: "number" };
5723
- if (type.flags & ts.TypeFlags.BooleanLike)
6057
+ if (type.flags & ts2.TypeFlags.BooleanLike)
5724
6058
  return { type: "boolean" };
5725
- if (type.flags & ts.TypeFlags.BigIntLike)
6059
+ if (type.flags & ts2.TypeFlags.BigIntLike)
5726
6060
  return { type: "bigint" };
5727
- if (type.flags & ts.TypeFlags.Null)
6061
+ if (type.flags & ts2.TypeFlags.Null)
5728
6062
  return { type: "null" };
5729
- if (type.flags & ts.TypeFlags.Undefined)
6063
+ if (type.flags & ts2.TypeFlags.Undefined)
5730
6064
  return { type: "undefined" };
5731
6065
  if (type.isUnion()) {
5732
6066
  return {
@@ -5740,11 +6074,11 @@ var serializeType = (type, checker, ancestors = new Set) => {
5740
6074
  }
5741
6075
  if (ancestors.has(type)) {
5742
6076
  return {
5743
- ref: checker.typeToString(type, undefined, ts.TypeFormatFlags.NoTruncation)
6077
+ ref: checker.typeToString(type, undefined, ts2.TypeFormatFlags.NoTruncation)
5744
6078
  };
5745
6079
  }
5746
6080
  ancestors.add(type);
5747
- const arrayElement = checker.getIndexTypeOfType(type, ts.IndexKind.Number);
6081
+ const arrayElement = checker.getIndexTypeOfType(type, ts2.IndexKind.Number);
5748
6082
  const properties = checker.getPropertiesOfType(type);
5749
6083
  let schema;
5750
6084
  if (arrayElement && properties.some(({ name }) => name === "length")) {
@@ -5759,7 +6093,7 @@ var serializeType = (type, checker, ancestors = new Set) => {
5759
6093
  return [
5760
6094
  property.name,
5761
6095
  {
5762
- optional: Boolean(property.flags & ts.SymbolFlags.Optional),
6096
+ optional: Boolean(property.flags & ts2.SymbolFlags.Optional),
5763
6097
  schema: serializeType(propertyType, checker, ancestors)
5764
6098
  }
5765
6099
  ];
@@ -5767,7 +6101,7 @@ var serializeType = (type, checker, ancestors = new Set) => {
5767
6101
  schema = { properties: Object.fromEntries(entries), type: "object" };
5768
6102
  } else {
5769
6103
  schema = {
5770
- type: checker.typeToString(type, undefined, ts.TypeFormatFlags.NoTruncation)
6104
+ type: checker.typeToString(type, undefined, ts2.TypeFormatFlags.NoTruncation)
5771
6105
  };
5772
6106
  }
5773
6107
  ancestors.delete(type);
@@ -5785,25 +6119,25 @@ var pagePropsType = (pageExpression, propsExpression, checker) => {
5785
6119
  };
5786
6120
  var resolvePageIdentity = (expression, sourceFile, checker, projectRoot) => {
5787
6121
  let symbol = checker.getSymbolAtLocation(expression);
5788
- if (symbol?.flags && symbol.flags & ts.SymbolFlags.Alias) {
6122
+ if (symbol?.flags && symbol.flags & ts2.SymbolFlags.Alias) {
5789
6123
  symbol = checker.getAliasedSymbol(symbol);
5790
6124
  }
5791
6125
  const declaration = symbol?.declarations?.[0];
5792
6126
  const file = declaration?.getSourceFile().fileName ?? sourceFile.fileName;
5793
6127
  const exportedName = symbol?.name ?? expression.getText(sourceFile);
5794
- const source = posixPath(relative10(projectRoot, file));
6128
+ const source = posixPath(relative11(projectRoot, file));
5795
6129
  return `${source}#${exportedName}`;
5796
6130
  };
5797
6131
  var resolveAlias = (symbol, checker) => {
5798
- if (!(symbol.flags & ts.SymbolFlags.Alias))
6132
+ if (!(symbol.flags & ts2.SymbolFlags.Alias))
5799
6133
  return symbol;
5800
6134
  return checker.getAliasedSymbol(symbol);
5801
6135
  };
5802
6136
  var assetKey = (expression, checker, seen = new Set) => {
5803
6137
  if (!expression)
5804
6138
  return;
5805
- if (ts.isIdentifier(expression)) {
5806
- const unresolved = ts.isShorthandPropertyAssignment(expression.parent) ? checker.getShorthandAssignmentValueSymbol(expression.parent) : checker.getSymbolAtLocation(expression);
6139
+ if (ts2.isIdentifier(expression)) {
6140
+ const unresolved = ts2.isShorthandPropertyAssignment(expression.parent) ? checker.getShorthandAssignmentValueSymbol(expression.parent) : checker.getSymbolAtLocation(expression);
5807
6141
  if (!unresolved)
5808
6142
  return;
5809
6143
  const symbol = resolveAlias(unresolved, checker);
@@ -5811,26 +6145,26 @@ var assetKey = (expression, checker, seen = new Set) => {
5811
6145
  return;
5812
6146
  seen.add(symbol);
5813
6147
  const declaration = symbol.valueDeclaration ?? symbol.declarations?.[0];
5814
- if (!declaration || !ts.isVariableDeclaration(declaration))
6148
+ if (!declaration || !ts2.isVariableDeclaration(declaration))
5815
6149
  return;
5816
6150
  return assetKey(declaration.initializer, checker, seen);
5817
6151
  }
5818
- if (!ts.isCallExpression(expression))
6152
+ if (!ts2.isCallExpression(expression))
5819
6153
  return;
5820
- if (!ts.isIdentifier(expression.expression) || expression.expression.text !== "asset") {
6154
+ if (!ts2.isIdentifier(expression.expression) || expression.expression.text !== "asset") {
5821
6155
  return;
5822
6156
  }
5823
6157
  const [, key] = expression.arguments;
5824
- return key && ts.isStringLiteralLike(key) ? key.text : undefined;
6158
+ return key && ts2.isStringLiteralLike(key) ? key.text : undefined;
5825
6159
  };
5826
6160
  var staticString = (expression, bindings) => {
5827
- if (ts.isStringLiteralLike(expression))
6161
+ if (ts2.isStringLiteralLike(expression))
5828
6162
  return expression.text;
5829
- if (ts.isIdentifier(expression))
6163
+ if (ts2.isIdentifier(expression))
5830
6164
  return bindings.get(expression.text);
5831
- if (ts.isNoSubstitutionTemplateLiteral(expression))
6165
+ if (ts2.isNoSubstitutionTemplateLiteral(expression))
5832
6166
  return expression.text;
5833
- if (!ts.isTemplateExpression(expression))
6167
+ if (!ts2.isTemplateExpression(expression))
5834
6168
  return;
5835
6169
  let value = expression.head.text;
5836
6170
  for (const span of expression.templateSpans) {
@@ -5844,7 +6178,7 @@ var staticString = (expression, bindings) => {
5844
6178
  var assetKeyWithBindings = (expression, checker, bindings = new Map) => {
5845
6179
  if (!expression)
5846
6180
  return;
5847
- if (ts.isCallExpression(expression) && ts.isIdentifier(expression.expression) && expression.expression.text === "asset") {
6181
+ if (ts2.isCallExpression(expression) && ts2.isIdentifier(expression.expression) && expression.expression.text === "asset") {
5848
6182
  const [, key] = expression.arguments;
5849
6183
  return key ? staticString(key, bindings) : undefined;
5850
6184
  }
@@ -5855,16 +6189,16 @@ var callableObject = (call, checker) => {
5855
6189
  const resolved = symbol ? resolveAlias(symbol, checker) : undefined;
5856
6190
  const declaration = resolved?.valueDeclaration ?? resolved?.declarations?.[0];
5857
6191
  let callable;
5858
- if (declaration && ts.isFunctionDeclaration(declaration)) {
6192
+ if (declaration && ts2.isFunctionDeclaration(declaration)) {
5859
6193
  callable = declaration;
5860
- } else if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer && (ts.isArrowFunction(declaration.initializer) || ts.isFunctionExpression(declaration.initializer))) {
6194
+ } else if (declaration && ts2.isVariableDeclaration(declaration) && declaration.initializer && (ts2.isArrowFunction(declaration.initializer) || ts2.isFunctionExpression(declaration.initializer))) {
5861
6195
  callable = declaration.initializer;
5862
6196
  }
5863
6197
  if (!callable)
5864
6198
  return;
5865
6199
  const bindings = new Map;
5866
6200
  callable.parameters.forEach((parameter, index) => {
5867
- if (!ts.isIdentifier(parameter.name))
6201
+ if (!ts2.isIdentifier(parameter.name))
5868
6202
  return;
5869
6203
  const argument = call.arguments[index];
5870
6204
  if (!argument)
@@ -5876,35 +6210,35 @@ var callableObject = (call, checker) => {
5876
6210
  const { body } = callable;
5877
6211
  if (!body)
5878
6212
  return;
5879
- const expressionBody = ts.isParenthesizedExpression(body) ? body.expression : body;
5880
- if (ts.isObjectLiteralExpression(expressionBody)) {
6213
+ const expressionBody = ts2.isParenthesizedExpression(body) ? body.expression : body;
6214
+ if (ts2.isObjectLiteralExpression(expressionBody)) {
5881
6215
  return { bindings, object: expressionBody };
5882
6216
  }
5883
- if (ts.isBlock(body)) {
5884
- const returned = body.statements.find(ts.isReturnStatement)?.expression;
5885
- if (returned && ts.isObjectLiteralExpression(returned)) {
6217
+ if (ts2.isBlock(body)) {
6218
+ const returned = body.statements.find(ts2.isReturnStatement)?.expression;
6219
+ if (returned && ts2.isObjectLiteralExpression(returned)) {
5886
6220
  return { bindings, object: returned };
5887
6221
  }
5888
6222
  }
5889
6223
  return;
5890
6224
  };
5891
6225
  var spreadObject = (expression, checker, bindings) => {
5892
- if (ts.isObjectLiteralExpression(expression)) {
6226
+ if (ts2.isObjectLiteralExpression(expression)) {
5893
6227
  return { bindings, object: expression };
5894
6228
  }
5895
- if (!ts.isCallExpression(expression))
6229
+ if (!ts2.isCallExpression(expression))
5896
6230
  return;
5897
6231
  return callableObject(expression, checker);
5898
6232
  };
5899
- var objectAssetKey = (object2, name, checker, bindings = new Map) => {
5900
- for (const property of [...object2.properties].reverse()) {
5901
- if (propertyName(property) === name && ts.isShorthandPropertyAssignment(property)) {
6233
+ var objectAssetKey = (object3, name, checker, bindings = new Map) => {
6234
+ for (const property of [...object3.properties].reverse()) {
6235
+ if (propertyName(property) === name && ts2.isShorthandPropertyAssignment(property)) {
5902
6236
  return assetKeyWithBindings(property.name, checker, bindings);
5903
6237
  }
5904
- if (propertyName(property) === name && ts.isPropertyAssignment(property)) {
6238
+ if (propertyName(property) === name && ts2.isPropertyAssignment(property)) {
5905
6239
  return assetKeyWithBindings(property.initializer, checker, bindings);
5906
6240
  }
5907
- if (!ts.isSpreadAssignment(property))
6241
+ if (!ts2.isSpreadAssignment(property))
5908
6242
  continue;
5909
6243
  const nestedObject = spreadObject(property.expression, checker, bindings);
5910
6244
  if (!nestedObject)
@@ -5920,14 +6254,14 @@ var findPageCall = (nodes) => {
5920
6254
  const visit = (candidate) => {
5921
6255
  if (found)
5922
6256
  return;
5923
- if (ts.isCallExpression(candidate) && ts.isIdentifier(candidate.expression) && PAGE_HANDLERS.has(candidate.expression.text)) {
6257
+ if (ts2.isCallExpression(candidate) && ts2.isIdentifier(candidate.expression) && PAGE_HANDLERS.has(candidate.expression.text)) {
5924
6258
  const definition = PAGE_HANDLERS.get(candidate.expression.text);
5925
6259
  if (!definition)
5926
6260
  return;
5927
6261
  found = { definition, node: candidate };
5928
6262
  return;
5929
6263
  }
5930
- ts.forEachChild(candidate, visit);
6264
+ ts2.forEachChild(candidate, visit);
5931
6265
  };
5932
6266
  for (const node of nodes)
5933
6267
  visit(node);
@@ -5936,12 +6270,12 @@ var findPageCall = (nodes) => {
5936
6270
  var isProjectSource = (sourceFile, resolvedFile, projectRoot) => !sourceFile.isDeclarationFile && !resolvedFile.includes("/node_modules/") && resolvedFile.startsWith(`${projectRoot}/`);
5937
6271
  var analyzeRouteCall = (node, sourceFile, checker, projectRoot) => {
5938
6272
  const callee = node.expression;
5939
- if (!ts.isPropertyAccessExpression(callee))
6273
+ if (!ts2.isPropertyAccessExpression(callee))
5940
6274
  return;
5941
6275
  if (!ROUTE_METHODS.has(callee.name.text))
5942
6276
  return;
5943
6277
  const [routePath] = node.arguments;
5944
- if (!routePath || !ts.isStringLiteralLike(routePath))
6278
+ if (!routePath || !ts2.isStringLiteralLike(routePath))
5945
6279
  return;
5946
6280
  const foundPageCall = findPageCall(node.arguments.slice(1));
5947
6281
  const pageCall = foundPageCall?.node;
@@ -5974,7 +6308,7 @@ var analyzeRouteCall = (node, sourceFile, checker, projectRoot) => {
5974
6308
  routeCallSpan: `${node.getStart(sourceFile)}:${node.end}`
5975
6309
  };
5976
6310
  }
5977
- if (!ts.isObjectLiteralExpression(input) || !definition.bundleProperty) {
6311
+ if (!ts2.isObjectLiteralExpression(input) || !definition.bundleProperty) {
5978
6312
  return;
5979
6313
  }
5980
6314
  const page = definition.pageProperty ? objectPropertyExpression(input, definition.pageProperty) : undefined;
@@ -6016,21 +6350,21 @@ var analyzeSourceFile = (sourceFile, checker, projectRoot) => {
6016
6350
  byRouteCall: new Map
6017
6351
  };
6018
6352
  const visit = (node) => {
6019
- const result = ts.isCallExpression(node) ? analyzeRouteCall(node, sourceFile, checker, projectRoot) : undefined;
6353
+ const result = ts2.isCallExpression(node) ? analyzeRouteCall(node, sourceFile, checker, projectRoot) : undefined;
6020
6354
  if (result) {
6021
6355
  analysis.byPageCall.set(result.pageCallStart, result);
6022
6356
  analysis.byRouteCall.set(result.routeCallSpan, result);
6023
6357
  }
6024
- ts.forEachChild(node, visit);
6358
+ ts2.forEachChild(node, visit);
6025
6359
  };
6026
- ts.forEachChild(sourceFile, visit);
6360
+ ts2.forEachChild(sourceFile, visit);
6027
6361
  return analysis;
6028
6362
  };
6029
6363
  var analyzeProgram = (program, projectRoot) => {
6030
6364
  const checker = program.getTypeChecker();
6031
6365
  const analyzed = new Map;
6032
6366
  for (const sourceFile of program.getSourceFiles()) {
6033
- const resolvedFile = resolve13(sourceFile.fileName);
6367
+ const resolvedFile = resolve14(sourceFile.fileName);
6034
6368
  if (!isProjectSource(sourceFile, resolvedFile, projectRoot))
6035
6369
  continue;
6036
6370
  const analysis = analyzeSourceFile(sourceFile, checker, projectRoot);
@@ -6039,21 +6373,21 @@ var analyzeProgram = (program, projectRoot) => {
6039
6373
  }
6040
6374
  return analyzed;
6041
6375
  };
6042
- var metadataExpression = (metadata) => ts.factory.createObjectLiteralExpression(Object.entries(metadata).map(([key, item]) => ts.factory.createPropertyAssignment(ts.factory.createStringLiteral(key), ts.factory.createStringLiteral(item))), false);
6376
+ var metadataExpression = (metadata) => ts2.factory.createObjectLiteralExpression(Object.entries(metadata).map(([key, item]) => ts2.factory.createPropertyAssignment(ts2.factory.createStringLiteral(key), ts2.factory.createStringLiteral(item))), false);
6043
6377
  var routeOptions = (existing, metadata) => {
6044
- const detail = ts.factory.createObjectLiteralExpression([
6045
- ts.factory.createPropertyAssignment(ts.factory.createStringLiteral(ABSOLUTE_MOBILE_ROUTE_DETAIL), metadataExpression(metadata))
6378
+ const detail = ts2.factory.createObjectLiteralExpression([
6379
+ ts2.factory.createPropertyAssignment(ts2.factory.createStringLiteral(ABSOLUTE_MOBILE_ROUTE_DETAIL), metadataExpression(metadata))
6046
6380
  ]);
6047
6381
  if (!existing) {
6048
- return ts.factory.createObjectLiteralExpression([
6049
- ts.factory.createPropertyAssignment("detail", detail)
6382
+ return ts2.factory.createObjectLiteralExpression([
6383
+ ts2.factory.createPropertyAssignment("detail", detail)
6050
6384
  ]);
6051
6385
  }
6052
- return ts.factory.createObjectLiteralExpression([
6053
- ts.factory.createSpreadAssignment(existing),
6054
- ts.factory.createPropertyAssignment("detail", ts.factory.createObjectLiteralExpression([
6055
- ts.factory.createSpreadAssignment(ts.factory.createPropertyAccessExpression(existing, "detail")),
6056
- ts.factory.createPropertyAssignment(ts.factory.createStringLiteral(ABSOLUTE_MOBILE_ROUTE_DETAIL), metadataExpression(metadata))
6386
+ return ts2.factory.createObjectLiteralExpression([
6387
+ ts2.factory.createSpreadAssignment(existing),
6388
+ ts2.factory.createPropertyAssignment("detail", ts2.factory.createObjectLiteralExpression([
6389
+ ts2.factory.createSpreadAssignment(ts2.factory.createPropertyAccessExpression(existing, "detail")),
6390
+ ts2.factory.createPropertyAssignment(ts2.factory.createStringLiteral(ABSOLUTE_MOBILE_ROUTE_DETAIL), metadataExpression(metadata))
6057
6391
  ]))
6058
6392
  ]);
6059
6393
  };
@@ -6064,19 +6398,19 @@ var transformPageCall = (node, page) => {
6064
6398
  const [pagePath, existingOptions, ...rest] = node.arguments;
6065
6399
  if (!pagePath)
6066
6400
  return;
6067
- const options = ts.factory.createObjectLiteralExpression([
6068
- ...existingOptions ? [ts.factory.createSpreadAssignment(existingOptions)] : [],
6069
- ts.factory.createPropertyAssignment("__absoluteMobile", metadataExpression(page.metadata))
6401
+ const options = ts2.factory.createObjectLiteralExpression([
6402
+ ...existingOptions ? [ts2.factory.createSpreadAssignment(existingOptions)] : [],
6403
+ ts2.factory.createPropertyAssignment("__absoluteMobile", metadataExpression(page.metadata))
6070
6404
  ]);
6071
- return ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [pagePath, options, ...rest]);
6405
+ return ts2.factory.updateCallExpression(node, node.expression, node.typeArguments, [pagePath, options, ...rest]);
6072
6406
  }
6073
6407
  const [input] = node.arguments;
6074
- if (!input || !ts.isObjectLiteralExpression(input))
6408
+ if (!input || !ts2.isObjectLiteralExpression(input))
6075
6409
  return;
6076
- return ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [
6077
- ts.factory.updateObjectLiteralExpression(input, [
6410
+ return ts2.factory.updateCallExpression(node, node.expression, node.typeArguments, [
6411
+ ts2.factory.updateObjectLiteralExpression(input, [
6078
6412
  ...input.properties,
6079
- ts.factory.createPropertyAssignment("__absoluteMobile", metadataExpression(page.metadata))
6413
+ ts2.factory.createPropertyAssignment("__absoluteMobile", metadataExpression(page.metadata))
6080
6414
  ]),
6081
6415
  ...node.arguments.slice(1)
6082
6416
  ]);
@@ -6089,16 +6423,16 @@ var transformRouteCall = (node, route) => {
6089
6423
  return;
6090
6424
  const options = maybeHandler ? maybeOptions : undefined;
6091
6425
  const handler = maybeHandler ?? maybeOptions;
6092
- return ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [path, routeOptions(options, route.metadata), handler, ...rest]);
6426
+ return ts2.factory.updateCallExpression(node, node.expression, node.typeArguments, [path, routeOptions(options, route.metadata), handler, ...rest]);
6093
6427
  };
6094
6428
  var transformFile = (source, fileName, analysis) => {
6095
- const sourceFile = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, true, fileName.endsWith("x") ? ts.ScriptKind.TSX : ts.ScriptKind.TS);
6429
+ const sourceFile = ts2.createSourceFile(fileName, source, ts2.ScriptTarget.Latest, true, fileName.endsWith("x") ? ts2.ScriptKind.TSX : ts2.ScriptKind.TS);
6096
6430
  const transformer = (context) => {
6097
6431
  const visit = (node) => {
6098
- if (!ts.isCallExpression(node)) {
6099
- return ts.visitEachChild(node, visit, context);
6432
+ if (!ts2.isCallExpression(node)) {
6433
+ return ts2.visitEachChild(node, visit, context);
6100
6434
  }
6101
- const transformedChildren = ts.visitEachChild(node, visit, context);
6435
+ const transformedChildren = ts2.visitEachChild(node, visit, context);
6102
6436
  const page = analysis.byPageCall.get(node.getStart(sourceFile));
6103
6437
  const transformedPage = transformPageCall(transformedChildren, page);
6104
6438
  if (transformedPage)
@@ -6109,45 +6443,45 @@ var transformFile = (source, fileName, analysis) => {
6109
6443
  return transformedRoute;
6110
6444
  return transformedChildren;
6111
6445
  };
6112
- return (node) => ts.visitNode(node, visit, ts.isSourceFile) ?? node;
6446
+ return (node) => ts2.visitNode(node, visit, ts2.isSourceFile) ?? node;
6113
6447
  };
6114
- const result = ts.transform(sourceFile, [transformer]);
6448
+ const result = ts2.transform(sourceFile, [transformer]);
6115
6449
  try {
6116
6450
  const [transformed] = result.transformed;
6117
6451
  if (!transformed)
6118
6452
  throw new TypeError("Mobile route transform failed.");
6119
- return ts.createPrinter().printFile(transformed);
6453
+ return ts2.createPrinter().printFile(transformed);
6120
6454
  } finally {
6121
6455
  result.dispose();
6122
6456
  }
6123
6457
  };
6124
6458
  var ABSOLUTE_MOBILE_TRANSFORM_PROTOCOL = ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION;
6125
6459
  var createAbsoluteMobileRouteMetadataPlugin = (options) => {
6126
- const projectRoot = resolve13(options.projectRoot ?? process.cwd());
6127
- const entry = resolve13(options.entry);
6460
+ const projectRoot = resolve14(options.projectRoot ?? process.cwd());
6461
+ const entry = resolve14(options.entry);
6128
6462
  const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
6129
6463
  return {
6130
6464
  name: "absolute-mobile-route-metadata",
6131
6465
  setup(build) {
6132
6466
  build.onLoad({ filter: SOURCE_FILTER }, async ({ path }) => {
6133
- const analysis = analyzed.get(resolve13(path));
6467
+ const analysis = analyzed.get(resolve14(path));
6134
6468
  if (!analysis)
6135
6469
  return;
6136
6470
  const source = await Bun.file(path).text();
6137
6471
  return {
6138
6472
  contents: transformFile(source, path, analysis),
6139
- loader: extname3(path).endsWith("x") ? "tsx" : "ts"
6473
+ loader: extname4(path).endsWith("x") ? "tsx" : "ts"
6140
6474
  };
6141
6475
  });
6142
6476
  }
6143
6477
  };
6144
6478
  };
6145
6479
  var inspectAbsoluteMobileRouteMetadata = (options) => {
6146
- const projectRoot = resolve13(options.projectRoot ?? process.cwd());
6147
- const entry = resolve13(options.entry);
6480
+ const projectRoot = resolve14(options.projectRoot ?? process.cwd());
6481
+ const entry = resolve14(options.entry);
6148
6482
  const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
6149
6483
  return [...analyzed.entries()].flatMap(([file, analysis]) => [...analysis.byRouteCall.values()].map(({ metadata }) => ({
6150
- file: posixPath(relative10(projectRoot, file)),
6484
+ file: posixPath(relative11(projectRoot, file)),
6151
6485
  metadata
6152
6486
  })));
6153
6487
  };
@@ -6169,6 +6503,7 @@ export {
6169
6503
  resolveAbsoluteMobileDeepLink,
6170
6504
  resolveAbsoluteMobileCompatibilityRelease,
6171
6505
  resolveAbsoluteMobileAuthManifest,
6506
+ resolveAbsoluteDeviceCapabilityPlan,
6172
6507
  repairAbsoluteIosDevSession,
6173
6508
  removeAbsoluteRemoteMacProfile,
6174
6509
  redactAbsoluteIosLog,
@@ -6192,6 +6527,7 @@ export {
6192
6527
  pairAbsoluteRemoteMac,
6193
6528
  normalizeAbsoluteMobileConfig,
6194
6529
  navigateAbsoluteMobilePage,
6530
+ missingAbsoluteDeviceCapabilityPackages,
6195
6531
  materializeAbsoluteRemoteMacAgent,
6196
6532
  materializeAbsoluteMobileCompatibilityBundle,
6197
6533
  materializeAbsoluteMobileAssociationFiles,
@@ -6199,6 +6535,7 @@ export {
6199
6535
  matchesAbsoluteMobileRoutePattern,
6200
6536
  loadAbsoluteNativeReleasePublisher,
6201
6537
  loadAbsoluteMobileMaterializedBundle,
6538
+ loadAbsoluteDeviceCapabilityProviders,
6202
6539
  listAbsoluteRemoteMacProfiles,
6203
6540
  isAbsoluteIosNativeRootInput,
6204
6541
  installAbsoluteRemoteMacAgent,
@@ -6217,6 +6554,8 @@ export {
6217
6554
  fetchAbsoluteMobilePage,
6218
6555
  disposeAbsoluteMobilePage,
6219
6556
  discoverAbsoluteSyncSchema,
6557
+ discoverAbsoluteDeviceCapabilities,
6558
+ directAbsoluteProjectPackages,
6220
6559
  createAbsoluteRemoteIosDevProject,
6221
6560
  createAbsoluteMobileUpgradeResponse,
6222
6561
  createAbsoluteMobileRouteMetadataPlugin,
@@ -6236,11 +6575,14 @@ export {
6236
6575
  buildAbsoluteMobileCompatibilityRelease,
6237
6576
  buildAbsoluteIosRelease,
6238
6577
  buildAbsoluteAndroidRelease,
6578
+ assertAbsoluteDeviceCapabilityPackages,
6579
+ applyAbsoluteNativeDeviceCapabilities,
6239
6580
  applyAbsoluteNativeDeepLinks,
6240
6581
  activateAbsoluteMobilePage,
6241
6582
  acceptsAbsoluteMobilePage,
6242
6583
  absoluteRemoteProjectSyncCommands,
6243
6584
  absoluteRemoteMacSshBase,
6585
+ absoluteDeviceNativeRequirements,
6244
6586
  MOBILE_PAGE_REQUEST_HEADERS,
6245
6587
  AbsoluteMobilePageProtocolError,
6246
6588
  APPLE_ASSOCIATION_PATH,
@@ -6264,5 +6606,5 @@ export {
6264
6606
  ABSOLUTE_ANDROID_RELEASE_FORMAT
6265
6607
  };
6266
6608
 
6267
- //# debugId=1458CD3F41FC684D64756E2164756E21
6609
+ //# debugId=8F3479AD17C2968F64756E2164756E21
6268
6610
  //# sourceMappingURL=index.js.map