@absolutejs/absolute 0.20.0-beta.7 → 0.20.0-beta.9

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.
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  var __require = import.meta.require;
3
3
 
4
- // .angular-partial-tmp-J5Mrj0/src/core/streamingSlotRegistrar.ts
4
+ // .angular-partial-tmp-owQtHM/src/core/streamingSlotRegistrar.ts
5
5
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
6
6
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
7
7
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  var __require = import.meta.require;
3
3
 
4
- // .angular-partial-tmp-J5Mrj0/src/core/streamingSlotRegistrar.ts
4
+ // .angular-partial-tmp-owQtHM/src/core/streamingSlotRegistrar.ts
5
5
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
6
6
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
7
7
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -48,7 +48,7 @@ var warnMissingStreamingSlotCollector = (primitiveName) => {
48
48
  getWarningController()?.maybeWarn(primitiveName);
49
49
  };
50
50
 
51
- // .angular-partial-tmp-J5Mrj0/src/core/streamingSlotRegistry.ts
51
+ // .angular-partial-tmp-owQtHM/src/core/streamingSlotRegistry.ts
52
52
  var STREAMING_SLOT_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotAsyncLocalStorage");
53
53
  var isObjectRecord2 = (value) => Boolean(value) && typeof value === "object";
54
54
  var isAsyncLocalStorage = (value) => isObjectRecord2(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
package/dist/cli/index.js CHANGED
@@ -6101,7 +6101,15 @@ ${authImport}${syncImport}void startAbsoluteMobileShell(${options});
6101
6101
  productionOrigin: options.config.productionOrigin,
6102
6102
  routes: options.artifact.routes,
6103
6103
  runtime: options.artifact.runtime,
6104
- ...options.sync ? { sync: { socketTickets: true } } : {}
6104
+ ...options.sync ? {
6105
+ sync: {
6106
+ background: {
6107
+ endpoint: new URL("/__absolute/sync/background", options.config.productionOrigin).href,
6108
+ intervalMinutes: 15
6109
+ },
6110
+ socketTickets: true
6111
+ }
6112
+ } : {}
6105
6113
  };
6106
6114
  await Promise.all([
6107
6115
  writeFile7(join17(staging, MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
@@ -15784,14 +15792,133 @@ ${domains}
15784
15792
  };
15785
15793
  var init_nativeDeepLinks = () => {};
15786
15794
 
15795
+ // src/mobile/nativeBackgroundSync.ts
15796
+ import { readFile as readFile12, rename as rename9, writeFile as writeFile10 } from "fs/promises";
15797
+ import { join as join45 } from "path";
15798
+ var writeChanged = async (path, source) => {
15799
+ const current = await readFile12(path, "utf8");
15800
+ if (current === source)
15801
+ return false;
15802
+ const temporary = `${path}.${crypto.randomUUID()}.tmp`;
15803
+ await writeFile10(temporary, source, { flag: "wx" });
15804
+ await rename9(temporary, path);
15805
+ return true;
15806
+ }, replaceRegion = (source, start2, end, region, insert) => {
15807
+ const existingStart = source.indexOf(start2);
15808
+ const existingEnd = source.indexOf(end);
15809
+ if (existingStart < 0 !== existingEnd < 0 || existingEnd < existingStart)
15810
+ throw new TypeError("AbsoluteJS background Sync markers are malformed.");
15811
+ if (existingStart >= 0) {
15812
+ const from = source.lastIndexOf(`
15813
+ `, existingStart) + 1;
15814
+ const newline = source.indexOf(`
15815
+ `, existingEnd + end.length);
15816
+ return `${source.slice(0, from)}${region}${source.slice(newline < 0 ? source.length : newline + 1)}`;
15817
+ }
15818
+ if (insert < 0)
15819
+ throw new TypeError("Could not find a safe iOS location for background Sync.");
15820
+ return `${source.slice(0, insert)}${region}${source.slice(insert)}`;
15821
+ }, ensurePlistArrayValues = (source, key, values, marker) => {
15822
+ const start2 = `<!-- absolutejs:${marker}:start -->`;
15823
+ const end = `<!-- absolutejs:${marker}:end -->`;
15824
+ const makeRegion = (owned) => {
15825
+ if (owned.length === 0)
15826
+ return "";
15827
+ const entries = owned.map((value) => ` <string>${value}</string>`).join(`
15828
+ `);
15829
+ return ` ${start2}
15830
+ ${entries}
15831
+ ${end}
15832
+ `;
15833
+ };
15834
+ const existingStart = source.indexOf(start2);
15835
+ const existingEnd = source.indexOf(end);
15836
+ if (existingStart < 0 !== existingEnd < 0 || existingEnd < existingStart)
15837
+ throw new TypeError("AbsoluteJS background Sync plist markers are malformed.");
15838
+ if (existingStart >= 0) {
15839
+ const from = source.lastIndexOf(`
15840
+ `, existingStart) + 1;
15841
+ const newline = source.indexOf(`
15842
+ `, existingEnd + end.length);
15843
+ const through = newline < 0 ? source.length : newline + 1;
15844
+ const unmanaged = `${source.slice(0, from)}${source.slice(through)}`;
15845
+ const owned = values.filter((value) => !unmanaged.includes(`<string>${value}</string>`));
15846
+ return `${source.slice(0, from)}${makeRegion(owned)}${source.slice(through)}`;
15847
+ }
15848
+ const keyToken = `<key>${key}</key>`;
15849
+ const keyIndex = source.indexOf(keyToken);
15850
+ if (keyIndex >= 0) {
15851
+ if (source.indexOf(keyToken, keyIndex + keyToken.length) >= 0)
15852
+ throw new TypeError(`iOS Info.plist contains duplicate ${key} keys.`);
15853
+ const arrayStart = source.indexOf("<array>", keyIndex + keyToken.length);
15854
+ const nextKey = source.indexOf("<key>", keyIndex + keyToken.length);
15855
+ if (arrayStart < 0 || nextKey >= 0 && nextKey < arrayStart)
15856
+ throw new TypeError(`iOS Info.plist ${key} is not an array.`);
15857
+ const arrayEnd = source.indexOf("</array>", arrayStart);
15858
+ if (arrayEnd < 0)
15859
+ throw new TypeError(`iOS Info.plist ${key} array is malformed.`);
15860
+ const insert = source.lastIndexOf(`
15861
+ `, arrayEnd) + 1;
15862
+ const array = source.slice(arrayStart, arrayEnd);
15863
+ const owned = values.filter((value) => !array.includes(`<string>${value}</string>`));
15864
+ if (owned.length === 0)
15865
+ return source;
15866
+ return `${source.slice(0, insert)}${makeRegion(owned)}${source.slice(insert)}`;
15867
+ }
15868
+ const dictEnd = source.lastIndexOf("</dict>");
15869
+ if (dictEnd < 0)
15870
+ throw new TypeError("Could not find the iOS Info.plist root dictionary.");
15871
+ const declaration = ` <key>${key}</key>
15872
+ <array>
15873
+ ${makeRegion(values)} </array>
15874
+ `;
15875
+ return `${source.slice(0, dictEnd)}${declaration}${source.slice(dictEnd)}`;
15876
+ }, applyAbsoluteNativeBackgroundSync = async (projectRoot, config, platforms = config.platforms) => {
15877
+ if (!platforms.includes("ios") || !projectUsesAbsoluteAuth(projectRoot) || !projectUsesAbsoluteSync(projectRoot))
15878
+ return { changed: false };
15879
+ const identifier = `${config.appId}.absolutejs.background-sync`;
15880
+ const infoPath = join45(config.nativeProjectDirectory, "ios/App/App/Info.plist");
15881
+ const info2 = await readFile12(infoPath, "utf8");
15882
+ const nextInfo = ensurePlistArrayValues(ensurePlistArrayValues(info2, "BGTaskSchedulerPermittedIdentifiers", [identifier], "background-sync-identifiers"), "UIBackgroundModes", ["fetch", "processing"], "background-sync-modes");
15883
+ const delegatePath = join45(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
15884
+ let delegate = await readFile12(delegatePath, "utf8");
15885
+ if (!delegate.includes("import AbsoluteSyncCapacitor")) {
15886
+ const importIndex = delegate.lastIndexOf("import Capacitor");
15887
+ if (importIndex < 0)
15888
+ throw new TypeError("Capacitor AppDelegate import was not found.");
15889
+ const end = delegate.indexOf(`
15890
+ `, importIndex);
15891
+ delegate = `${delegate.slice(0, end + 1)}import AbsoluteSyncCapacitor
15892
+ ${delegate.slice(end + 1)}`;
15893
+ }
15894
+ const swiftStart = "// absolutejs:background-sync:start";
15895
+ const swiftEnd = "// absolutejs:background-sync:end";
15896
+ const swiftRegion = ` ${swiftStart}
15897
+ AbsoluteBackgroundSyncPlugin.registerBackgroundTask()
15898
+ ${swiftEnd}
15899
+ `;
15900
+ const launch = delegate.indexOf("didFinishLaunchingWithOptions");
15901
+ const brace = launch < 0 ? -1 : delegate.indexOf("{", launch);
15902
+ const nextDelegate = replaceRegion(delegate, swiftStart, swiftEnd, swiftRegion, brace < 0 ? -1 : delegate.indexOf(`
15903
+ `, brace) + 1);
15904
+ const changed = await Promise.all([
15905
+ writeChanged(infoPath, nextInfo),
15906
+ writeChanged(delegatePath, nextDelegate)
15907
+ ]);
15908
+ return { changed: changed.some(Boolean) };
15909
+ };
15910
+ var init_nativeBackgroundSync = __esm(() => {
15911
+ init_nativeAuth();
15912
+ });
15913
+
15787
15914
  // src/mobile/associationFiles.ts
15788
15915
  import {
15789
15916
  access as access7,
15790
15917
  mkdir as mkdir10,
15791
- readFile as readFile12,
15792
- rename as rename9,
15918
+ readFile as readFile13,
15919
+ rename as rename10,
15793
15920
  rm as rm7,
15794
- writeFile as writeFile10
15921
+ writeFile as writeFile11
15795
15922
  } from "fs/promises";
15796
15923
  import { resolve as resolve35 } from "path";
15797
15924
  import { Elysia } from "elysia";
@@ -15846,7 +15973,7 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
15846
15973
  }, writeAtomic = async (path, source) => {
15847
15974
  let current;
15848
15975
  try {
15849
- current = await readFile12(path, "utf8");
15976
+ current = await readFile13(path, "utf8");
15850
15977
  } catch (error) {
15851
15978
  if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
15852
15979
  throw error;
@@ -15855,8 +15982,8 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
15855
15982
  if (current === source)
15856
15983
  return false;
15857
15984
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
15858
- await writeFile10(temporary, source, { flag: "wx" });
15859
- await rename9(temporary, path);
15985
+ await writeFile11(temporary, source, { flag: "wx" });
15986
+ await rename10(temporary, path);
15860
15987
  return true;
15861
15988
  }, exists2 = async (path) => {
15862
15989
  try {
@@ -15869,7 +15996,7 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
15869
15996
  const path = resolve35(root, OWNERSHIP_FILE);
15870
15997
  let ownership;
15871
15998
  try {
15872
- ownership = JSON.parse(await readFile12(path, "utf8"));
15999
+ ownership = JSON.parse(await readFile13(path, "utf8"));
15873
16000
  } catch {
15874
16001
  throw new TypeError(`Association output ${root} already exists and is not owned by AbsoluteJS.`);
15875
16002
  }
@@ -15882,12 +16009,12 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
15882
16009
  await assertOwnedOutput(root);
15883
16010
  const backup = `${root}.${crypto.randomUUID()}.previous`;
15884
16011
  if (hasCurrent)
15885
- await rename9(root, backup);
16012
+ await rename10(root, backup);
15886
16013
  try {
15887
- await rename9(temporary, root);
16014
+ await rename10(temporary, root);
15888
16015
  } catch (error) {
15889
16016
  if (hasCurrent)
15890
- await rename9(backup, root);
16017
+ await rename10(backup, root);
15891
16018
  throw error;
15892
16019
  }
15893
16020
  if (hasCurrent)
@@ -15977,7 +16104,7 @@ var init_associationFiles = __esm(() => {
15977
16104
  });
15978
16105
 
15979
16106
  // src/mobile/androidWebView.ts
15980
- import { mkdir as mkdir11, writeFile as writeFile11 } from "fs/promises";
16107
+ import { mkdir as mkdir11, writeFile as writeFile12 } from "fs/promises";
15981
16108
  import { dirname as dirname27, resolve as resolve36 } from "path";
15982
16109
 
15983
16110
  class CdpConnection {
@@ -16251,7 +16378,7 @@ var CDP_COMMAND_TIMEOUT_MS = 1e4, WEBVIEW_ATTACH_TIMEOUT_MS = 30000, WEBVIEW_POL
16251
16378
  }
16252
16379
  const absolutePath = resolve36(path);
16253
16380
  await mkdir11(dirname27(absolutePath), { recursive: true });
16254
- await writeFile11(absolutePath, Buffer.from(data, "base64"));
16381
+ await writeFile12(absolutePath, Buffer.from(data, "base64"));
16255
16382
  return absolutePath;
16256
16383
  }
16257
16384
  };
@@ -16369,8 +16496,8 @@ var DEFAULT_ROUTE_TIMEOUT_MS = 30000, DEFAULT_HMR_TIMEOUT_MS = 30000, routeExpre
16369
16496
  };
16370
16497
 
16371
16498
  // src/mobile/releaseDoctor.ts
16372
- import { access as access8, readFile as readFile13, readdir as readdir4 } from "fs/promises";
16373
- import { extname as extname7, join as join45, relative as relative23 } from "path";
16499
+ import { access as access8, readFile as readFile14, readdir as readdir4 } from "fs/promises";
16500
+ import { extname as extname7, join as join46, relative as relative23 } from "path";
16374
16501
  var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
16375
16502
  try {
16376
16503
  await access8(path);
@@ -16383,13 +16510,13 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
16383
16510
  return findHmrAsset(path);
16384
16511
  if (!isFile2 || !RELEASE_ASSET_EXTENSIONS.has(extname7(path)))
16385
16512
  return;
16386
- const source = await readFile13(path, "utf8");
16513
+ const source = await readFile14(path, "utf8");
16387
16514
  return HMR_ASSET_PATTERN.test(source) ? path : undefined;
16388
16515
  }, findHmrAsset = async (root) => {
16389
16516
  if (!await pathExists5(root))
16390
16517
  return;
16391
16518
  const entries = await readdir4(root, { withFileTypes: true });
16392
- const matches = await Promise.all(entries.map((entry) => inspectReleaseAsset(join45(root, entry.name), entry.isDirectory(), entry.isFile())));
16519
+ const matches = await Promise.all(entries.map((entry) => inspectReleaseAsset(join46(root, entry.name), entry.isDirectory(), entry.isFile())));
16393
16520
  return matches.find((match) => match !== undefined);
16394
16521
  }, pass = (id, detail, path) => ({ detail, id, path, status: "pass" }), fail5 = (id, detail, path, remediation) => ({
16395
16522
  detail,
@@ -16422,23 +16549,23 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
16422
16549
  if (!await pathExists5(nativeConfigPath)) {
16423
16550
  return fail5("android.capacitor-config", "The generated Android Capacitor config is missing.", nativeConfigPath, "Run `absolute mobile sync android` before release validation.");
16424
16551
  }
16425
- const unsafe = isUnsafeCapacitorConfig(await readFile13(nativeConfigPath, "utf8"));
16552
+ const unsafe = isUnsafeCapacitorConfig(await readFile14(nativeConfigPath, "utf8"));
16426
16553
  return unsafe ? fail5("android.capacitor-config", "Android Capacitor config contains a development server URL, cleartext transport, navigation allowlist, or invalid JSON.", nativeConfigPath, "Run `absolute mobile sync android`; do not ship development transport overrides.") : pass("android.capacitor-config", "Android Capacitor config contains no development transport overrides.", nativeConfigPath);
16427
16554
  }, manifestReleaseCheck = async (manifestPath) => {
16428
16555
  if (!await pathExists5(manifestPath)) {
16429
16556
  return fail5("android.cleartext", "The Android manifest is missing.", manifestPath, "Run `absolute mobile sync android` before release validation.");
16430
16557
  }
16431
- const source = await readFile13(manifestPath, "utf8");
16558
+ const source = await readFile14(manifestPath, "utf8");
16432
16559
  return /android:usesCleartextTraffic=["']true["']/u.test(source) ? fail5("android.cleartext", "Android explicitly permits cleartext traffic.", manifestPath, 'Remove usesCleartextTraffic="true" from the release manifest.') : pass("android.cleartext", "Android does not explicitly permit cleartext traffic.", manifestPath);
16433
16560
  }, hmrAssetsReleaseCheck = async (publicRoot) => {
16434
16561
  const hmrAsset = await findHmrAsset(publicRoot);
16435
16562
  return hmrAsset ? fail5("android.hmr-assets", "A packaged Android asset contains the development HMR client.", hmrAsset, "Rebuild the production mobile bundle and run Capacitor sync again.") : pass("android.hmr-assets", "Packaged Android assets contain no development HMR markers.", publicRoot);
16436
16563
  }, inspectAndroidRelease = async (config, projectRoot) => {
16437
- const androidRoot = join45(config.nativeProjectDirectory, "android");
16438
- const nativeConfigPath = join45(androidRoot, "app", "src", "main", "assets", "capacitor.config.json");
16439
- const manifestPath = join45(androidRoot, "app", "src", "main", "AndroidManifest.xml");
16440
- const publicRoot = join45(androidRoot, "app", "src", "main", "assets", "public");
16441
- const journalPath = join45(projectRoot, ".absolutejs", "mobile", "dev-session", "journal.json");
16564
+ const androidRoot = join46(config.nativeProjectDirectory, "android");
16565
+ const nativeConfigPath = join46(androidRoot, "app", "src", "main", "assets", "capacitor.config.json");
16566
+ const manifestPath = join46(androidRoot, "app", "src", "main", "AndroidManifest.xml");
16567
+ const publicRoot = join46(androidRoot, "app", "src", "main", "assets", "public");
16568
+ const journalPath = join46(projectRoot, ".absolutejs", "mobile", "dev-session", "journal.json");
16442
16569
  const checks = await Promise.all([
16443
16570
  journalReleaseCheck(journalPath, "android"),
16444
16571
  capacitorConfigReleaseCheck(nativeConfigPath),
@@ -16450,11 +16577,11 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
16450
16577
  path: check2.path ? relative23(projectRoot, check2.path).replaceAll("\\", "/") || "." : undefined
16451
16578
  }));
16452
16579
  }, inspectIosRelease = async (config, projectRoot) => {
16453
- const iosAppRoot = join45(config.nativeProjectDirectory, "ios", "App", "App");
16454
- const nativeConfigPath = join45(iosAppRoot, "capacitor.config.json");
16455
- const infoPath = join45(iosAppRoot, "Info.plist");
16456
- const publicRoot = join45(iosAppRoot, "public");
16457
- const journalPath = join45(projectRoot, ".absolutejs", "mobile", "ios-dev-session", "journal.json");
16580
+ const iosAppRoot = join46(config.nativeProjectDirectory, "ios", "App", "App");
16581
+ const nativeConfigPath = join46(iosAppRoot, "capacitor.config.json");
16582
+ const infoPath = join46(iosAppRoot, "Info.plist");
16583
+ const publicRoot = join46(iosAppRoot, "public");
16584
+ const journalPath = join46(projectRoot, ".absolutejs", "mobile", "ios-dev-session", "journal.json");
16458
16585
  const checks = [
16459
16586
  await journalReleaseCheck(journalPath, "ios")
16460
16587
  ];
@@ -16465,7 +16592,7 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
16465
16592
  }
16466
16593
  if (!await pathExists5(nativeConfigPath)) {
16467
16594
  checks.push(fail5("ios.capacitor-config", "The generated iOS Capacitor config is missing.", nativeConfigPath, "Run `absolute mobile sync ios` before release validation."));
16468
- } else if (isUnsafeCapacitorConfig(await readFile13(nativeConfigPath, "utf8"))) {
16595
+ } else if (isUnsafeCapacitorConfig(await readFile14(nativeConfigPath, "utf8"))) {
16469
16596
  checks.push(fail5("ios.capacitor-config", "iOS Capacitor config contains a development server URL, cleartext transport, navigation allowlist, or invalid JSON.", nativeConfigPath, "Run `absolute mobile sync ios`; do not ship development transport overrides."));
16470
16597
  } else {
16471
16598
  checks.push(pass("ios.capacitor-config", "iOS Capacitor config contains no development transport overrides.", nativeConfigPath));
@@ -16473,7 +16600,7 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
16473
16600
  if (!await pathExists5(infoPath)) {
16474
16601
  checks.push(fail5("ios.transport-security", "The iOS Info.plist is missing.", infoPath, "Run `absolute mobile sync ios` before release validation."));
16475
16602
  } else {
16476
- const info2 = await readFile13(infoPath, "utf8");
16603
+ const info2 = await readFile14(infoPath, "utf8");
16477
16604
  checks.push(/<key>NSAllowsArbitraryLoads<\/key>\s*<true\s*\/>/u.test(info2) ? fail5("ios.transport-security", "iOS App Transport Security permits arbitrary network loads.", infoPath, "Remove NSAllowsArbitraryLoads from the release Info.plist.") : pass("ios.transport-security", "iOS App Transport Security does not permit arbitrary loads.", infoPath));
16478
16605
  }
16479
16606
  const hmrAsset = await findHmrAsset(publicRoot);
@@ -16504,13 +16631,13 @@ import {
16504
16631
  copyFile as copyFile5,
16505
16632
  mkdir as mkdir12,
16506
16633
  mkdtemp as mkdtemp5,
16507
- readFile as readFile14,
16508
- rename as rename10,
16634
+ readFile as readFile15,
16635
+ rename as rename11,
16509
16636
  rm as rm8,
16510
16637
  stat as stat2,
16511
- writeFile as writeFile12
16638
+ writeFile as writeFile13
16512
16639
  } from "fs/promises";
16513
- import { dirname as dirname28, isAbsolute as isAbsolute7, join as join46, relative as relative24, resolve as resolve37, sep as sep6 } from "path";
16640
+ import { dirname as dirname28, isAbsolute as isAbsolute7, join as join47, relative as relative24, resolve as resolve37, sep as sep6 } from "path";
16514
16641
  var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), requireManifest2 = (value) => {
16515
16642
  if (!isRecord13(value) || typeof value.appBuild !== "string" || typeof value.appId !== "string" || typeof value.runtime !== "string") {
16516
16643
  throw new TypeError("Invalid embedded AbsoluteJS mobile manifest.");
@@ -16560,7 +16687,7 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
16560
16687
  artifactPath
16561
16688
  ]);
16562
16689
  return result.exitCode === 0 && /jar verified/iu.test(result.stdout);
16563
- }, sha256File2 = async (path) => createHash12("sha256").update(await readFile14(path)).digest("hex"), safeOutputDirectory2 = (projectRoot, requested) => {
16690
+ }, sha256File2 = async (path) => createHash12("sha256").update(await readFile15(path)).digest("hex"), safeOutputDirectory2 = (projectRoot, requested) => {
16564
16691
  const root = resolve37(projectRoot);
16565
16692
  const output = resolve37(root, requested ?? ".absolutejs/mobile/releases/android");
16566
16693
  const projectRelative = relative24(root, output);
@@ -16569,11 +16696,11 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
16569
16696
  }
16570
16697
  return output;
16571
16698
  }, installRelease2 = async (artifactPath, metadata, outputRoot) => {
16572
- const releaseRoot = join46(outputRoot, metadata.releaseId);
16699
+ const releaseRoot = join47(outputRoot, metadata.releaseId);
16573
16700
  const artifactName = "app-release.aab";
16574
- const destination = join46(releaseRoot, artifactName);
16701
+ const destination = join47(releaseRoot, artifactName);
16575
16702
  if (await pathExists6(releaseRoot)) {
16576
- const existing = requireManifestIdentity(JSON.parse(await readFile14(join46(releaseRoot, "release.json"), "utf8")), metadata);
16703
+ const existing = requireManifestIdentity(JSON.parse(await readFile15(join47(releaseRoot, "release.json"), "utf8")), metadata);
16577
16704
  const [installedBytes, installedSha256] = await Promise.all([
16578
16705
  stat2(destination).then(({ size }) => size),
16579
16706
  sha256File2(destination)
@@ -16584,16 +16711,16 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
16584
16711
  return { artifactPath: destination, metadata: existing, releaseRoot };
16585
16712
  }
16586
16713
  await mkdir12(dirname28(releaseRoot), { recursive: true });
16587
- const staging = await mkdtemp5(join46(dirname28(releaseRoot), ".android-stage-"));
16714
+ const staging = await mkdtemp5(join47(dirname28(releaseRoot), ".android-stage-"));
16588
16715
  try {
16589
- await copyFile5(artifactPath, join46(staging, artifactName));
16716
+ await copyFile5(artifactPath, join47(staging, artifactName));
16590
16717
  const complete = {
16591
16718
  ...metadata,
16592
16719
  artifact: artifactName
16593
16720
  };
16594
- await writeFile12(join46(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
16721
+ await writeFile13(join47(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
16595
16722
  `, { flag: "wx" });
16596
- await rename10(staging, releaseRoot);
16723
+ await rename11(staging, releaseRoot);
16597
16724
  return { artifactPath: destination, metadata: complete, releaseRoot };
16598
16725
  } finally {
16599
16726
  await rm8(staging, { force: true, recursive: true }).catch(() => {
@@ -16619,8 +16746,8 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
16619
16746
  const projectRoot = resolve37(options.projectRoot);
16620
16747
  const host = options.host ?? detectAbsoluteMobileHost();
16621
16748
  const androidRoot = options.androidRoot ?? process.env.ANDROID_HOME ?? process.env.ANDROID_SDK_ROOT ?? absoluteManagedAndroidSdkRoot(host);
16622
- const nativeDirectory = join46(options.config.nativeProjectDirectory, "android");
16623
- const manifest = requireManifest2(JSON.parse(await readFile14(join46(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
16749
+ const nativeDirectory = join47(options.config.nativeProjectDirectory, "android");
16750
+ const manifest = requireManifest2(JSON.parse(await readFile15(join47(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
16624
16751
  if (manifest.appId !== options.config.appId) {
16625
16752
  throw new TypeError("Embedded mobile manifest appId does not match mobile.appId.");
16626
16753
  }
@@ -16684,7 +16811,7 @@ var init_androidRelease = __esm(() => {
16684
16811
  });
16685
16812
 
16686
16813
  // src/mobile/iosConformance.ts
16687
- import { readFile as readFile15, stat as stat3 } from "fs/promises";
16814
+ import { readFile as readFile16, stat as stat3 } from "fs/promises";
16688
16815
  var HMR_LINE, parseAbsoluteIosHmrLog = (line) => {
16689
16816
  const match = HMR_LINE.exec(line);
16690
16817
  if (!match)
@@ -16719,7 +16846,7 @@ var HMR_LINE, parseAbsoluteIosHmrLog = (line) => {
16719
16846
  if (Date.now() > deadline)
16720
16847
  throw new Error(`No iOS native HMR acknowledgement was observed within ${timeoutMs}ms.`);
16721
16848
  options.signal?.throwIfAborted();
16722
- const contents = await readFile15(options.logPath).catch(() => Buffer.alloc(0));
16849
+ const contents = await readFile16(options.logPath).catch(() => Buffer.alloc(0));
16723
16850
  if (contents.byteLength < offset) {
16724
16851
  offset = 0;
16725
16852
  buffered = "";
@@ -16840,11 +16967,11 @@ var exports_mobile = {};
16840
16967
  __export(exports_mobile, {
16841
16968
  runMobile: () => runMobile
16842
16969
  });
16843
- import { access as access11, mkdir as mkdir13, readFile as readFile16, writeFile as writeFile13 } from "fs/promises";
16844
- import { join as join47, resolve as resolve39 } from "path";
16970
+ import { access as access11, mkdir as mkdir13, readFile as readFile17, writeFile as writeFile14 } from "fs/promises";
16971
+ import { join as join48, resolve as resolve39 } from "path";
16845
16972
  import { createInterface } from "readline/promises";
16846
16973
  var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), CAPACITOR_PACKAGES, CAPACITOR_PACKAGE_SPECS, CAPACITOR_SYNC_PACKAGE_SPECS, packageNameFromSpec = (spec) => spec.slice(0, spec.lastIndexOf("@")), directProjectPackages = async (projectRoot) => {
16847
- const manifest = JSON.parse(await readFile16(join47(projectRoot, "package.json"), "utf8"));
16974
+ const manifest = JSON.parse(await readFile17(join48(projectRoot, "package.json"), "utf8"));
16848
16975
  if (!isRecord15(manifest))
16849
16976
  throw new TypeError("Application package.json must contain an object.");
16850
16977
  const names = new Set;
@@ -16881,7 +17008,7 @@ var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value
16881
17008
  }
16882
17009
  return value;
16883
17010
  }, capacitorExecutable = async (projectRoot) => {
16884
- const executable = join47(projectRoot, "node_modules", ".bin", "cap");
17011
+ const executable = join48(projectRoot, "node_modules", ".bin", "cap");
16885
17012
  try {
16886
17013
  await access11(executable);
16887
17014
  return executable;
@@ -16952,6 +17079,7 @@ var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value
16952
17079
  return;
16953
17080
  await runCapacitorForPlatforms(projectRoot, "add", mobile.platforms);
16954
17081
  await applyAbsoluteNativeDeepLinks(mobile);
17082
+ await applyAbsoluteNativeBackgroundSync(projectRoot, mobile);
16955
17083
  }, sync = async (args) => {
16956
17084
  const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
16957
17085
  await ensureCapacitorPackages(projectRoot, args);
@@ -16963,6 +17091,7 @@ var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value
16963
17091
  await repairAbsoluteIosDevSession(projectRoot);
16964
17092
  await runCapacitorForPlatforms(projectRoot, "sync", platforms);
16965
17093
  await applyAbsoluteNativeDeepLinks(mobile, platforms);
17094
+ await applyAbsoluteNativeBackgroundSync(projectRoot, mobile, platforms);
16966
17095
  }, associations = async (args) => {
16967
17096
  const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
16968
17097
  const outputDirectory = resolve39(projectRoot, valueAfter(args, "--outdir") ?? ".absolutejs/mobile/associations");
@@ -17180,6 +17309,9 @@ Mobile release transport checks failed.`);
17180
17309
  await writeAbsoluteCapacitorConfig(mobile, { projectRoot });
17181
17310
  await runCapacitorForPlatforms(projectRoot, "sync", ["android"]);
17182
17311
  await applyAbsoluteNativeDeepLinks(mobile, ["android"]);
17312
+ await applyAbsoluteNativeBackgroundSync(projectRoot, mobile, [
17313
+ "android"
17314
+ ]);
17183
17315
  await requireAndroidReleaseReady(mobile, projectRoot);
17184
17316
  const release = await buildAbsoluteAndroidRelease({
17185
17317
  allowUnsigned: args.includes("--unsigned"),
@@ -17192,7 +17324,7 @@ Mobile release transport checks failed.`);
17192
17324
  const durationMs = Math.round(performance.now() - startedAt);
17193
17325
  console.log(`Built ${release.metadata.signed ? "signed" : "unsigned"} Android App Bundle in ${getDurationString(durationMs)}.`);
17194
17326
  console.log(`Artifact: ${release.artifactPath}`);
17195
- console.log(`Metadata: ${join47(release.releaseRoot, "release.json")}`);
17327
+ console.log(`Metadata: ${join48(release.releaseRoot, "release.json")}`);
17196
17328
  return release;
17197
17329
  } finally {
17198
17330
  sendTelemetryEvent("mobile:android-release-build", {
@@ -17279,6 +17411,7 @@ Mobile release transport checks failed.`);
17279
17411
  await writeAbsoluteCapacitorConfig(mobile, { projectRoot });
17280
17412
  await runCapacitorForPlatforms(projectRoot, "sync", ["ios"]);
17281
17413
  await applyAbsoluteNativeDeepLinks(mobile, ["ios"]);
17414
+ await applyAbsoluteNativeBackgroundSync(projectRoot, mobile, ["ios"]);
17282
17415
  await requireIosReleaseReady(mobile, projectRoot);
17283
17416
  const release = await buildAbsoluteIosRelease({
17284
17417
  allowUnsigned: args.includes("--unsigned"),
@@ -17291,7 +17424,7 @@ Mobile release transport checks failed.`);
17291
17424
  const durationMs = Math.round(performance.now() - startedAt);
17292
17425
  console.log(`Built ${release.metadata.signed ? "signed" : "unsigned"} iOS IPA ${release.metadata.marketingVersion}${release.metadata.buildNumber ? ` (${release.metadata.buildNumber})` : ""} in ${getDurationString(durationMs)}.`);
17293
17426
  console.log(`Artifact: ${release.artifactPath}`);
17294
- console.log(`Metadata: ${join47(release.releaseRoot, "release.json")}`);
17427
+ console.log(`Metadata: ${join48(release.releaseRoot, "release.json")}`);
17295
17428
  return release;
17296
17429
  } finally {
17297
17430
  sendTelemetryEvent("mobile:ios-release-build", {
@@ -17537,11 +17670,11 @@ Emulator setup verification:`);
17537
17670
  });
17538
17671
  }, writeAndroidFailureArtifacts = async (options) => {
17539
17672
  await mkdir13(options.artifactRoot, { recursive: true });
17540
- const screenshot = options.session ? await options.session.screenshot(join47(options.artifactRoot, "android-failure.png")).catch(() => {
17673
+ const screenshot = options.session ? await options.session.screenshot(join48(options.artifactRoot, "android-failure.png")).catch(() => {
17541
17674
  return;
17542
17675
  }) : undefined;
17543
- const diagnosticPath = join47(options.artifactRoot, "android-failure.json");
17544
- await writeFile13(diagnosticPath, `${JSON.stringify({
17676
+ const diagnosticPath = join48(options.artifactRoot, "android-failure.json");
17677
+ await writeFile14(diagnosticPath, `${JSON.stringify({
17545
17678
  diagnostics: options.session?.diagnostics ?? [],
17546
17679
  error: options.error instanceof Error ? options.error.message : String(options.error),
17547
17680
  platform: "android",
@@ -17718,7 +17851,7 @@ Emulator setup verification:`);
17718
17851
  return result;
17719
17852
  }, writeIosFailureArtifacts = async (options) => {
17720
17853
  await mkdir13(options.artifactRoot, { recursive: true });
17721
- const screenshot = join47(options.artifactRoot, "ios-failure.png");
17854
+ const screenshot = join48(options.artifactRoot, "ios-failure.png");
17722
17855
  const screenshotResult = captureCommand4([
17723
17856
  options.xcrun,
17724
17857
  "simctl",
@@ -17727,8 +17860,8 @@ Emulator setup verification:`);
17727
17860
  "screenshot",
17728
17861
  screenshot
17729
17862
  ]);
17730
- const diagnosticPath = join47(options.artifactRoot, "ios-failure.json");
17731
- await writeFile13(diagnosticPath, `${JSON.stringify({
17863
+ const diagnosticPath = join48(options.artifactRoot, "ios-failure.json");
17864
+ await writeFile14(diagnosticPath, `${JSON.stringify({
17732
17865
  appId: options.appId,
17733
17866
  error: options.error instanceof Error ? options.error.message : String(options.error),
17734
17867
  platform: "ios",
@@ -17773,7 +17906,7 @@ Emulator setup verification:`);
17773
17906
  ], "iOS app launch");
17774
17907
  await waitForIosHmrClient({ https, port, timeoutMs });
17775
17908
  await mkdir13(artifactRoot, { recursive: true });
17776
- const screenshot = join47(artifactRoot, "ios-simulator.png");
17909
+ const screenshot = join48(artifactRoot, "ios-simulator.png");
17777
17910
  requireCapturedIosCommand([xcrun, "simctl", "io", simulator.udid, "screenshot", screenshot], "iOS simulator screenshot");
17778
17911
  const hmrApply = await waitForRequestedIosHmr(args, instance, timeoutMs);
17779
17912
  const report = {
@@ -17877,6 +18010,7 @@ var init_mobile = __esm(() => {
17877
18010
  init_capacitorProject();
17878
18011
  init_config();
17879
18012
  init_nativeDeepLinks();
18013
+ init_nativeBackgroundSync();
17880
18014
  init_emulatorDoctor();
17881
18015
  init_emulatorInstaller();
17882
18016
  init_associationFiles();
@@ -17917,11 +18051,11 @@ var init_mobile = __esm(() => {
17917
18051
  "@capacitor/cli@8.5.0",
17918
18052
  "@capacitor/android@8.5.0",
17919
18053
  "@capacitor/ios@8.5.0",
17920
- "@absolutejs/devices@0.0.2",
17921
- "@absolutejs/devices-capacitor@0.1.2"
18054
+ "@absolutejs/devices@0.0.3",
18055
+ "@absolutejs/devices-capacitor@0.1.3"
17922
18056
  ];
17923
18057
  CAPACITOR_SYNC_PACKAGE_SPECS = [
17924
- "@absolutejs/sync-capacitor@0.1.0",
18058
+ "@absolutejs/sync-capacitor@0.3.0",
17925
18059
  "@capacitor-community/sqlite@8.1.1"
17926
18060
  ];
17927
18061
  });
@@ -17931,9 +18065,9 @@ var exports_typecheck = {};
17931
18065
  __export(exports_typecheck, {
17932
18066
  typecheck: () => typecheck
17933
18067
  });
17934
- import { resolve as resolve40, join as join48 } from "path";
18068
+ import { resolve as resolve40, join as join49 } from "path";
17935
18069
  import { existsSync as existsSync42, readFileSync as readFileSync38 } from "fs";
17936
- import { mkdir as mkdir14, writeFile as writeFile14 } from "fs/promises";
18070
+ import { mkdir as mkdir14, writeFile as writeFile15 } from "fs/promises";
17937
18071
  var isCommandService3 = (service) => service.kind === "command" || Array.isArray(service.command), resolveConfigPath = (configPath2) => resolve40(configPath2 ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts"), getTypecheckTargets = async (configPath2) => {
17938
18072
  if (!existsSync42(resolveConfigPath(configPath2))) {
17939
18073
  const defaultService = {};
@@ -18040,8 +18174,8 @@ Found ${errorCount} error${suffix}.`;
18040
18174
  console.error("\x1B[31m\u2717\x1B[0m vue-tsc is required for Vue type checking. Install it: bun add -d vue-tsc");
18041
18175
  process.exit(1);
18042
18176
  }
18043
- const vueTsconfigPath = join48(cacheDir, "tsconfig.vue-check.json");
18044
- return writeFile14(vueTsconfigPath, JSON.stringify({
18177
+ const vueTsconfigPath = join49(cacheDir, "tsconfig.vue-check.json");
18178
+ return writeFile15(vueTsconfigPath, JSON.stringify({
18045
18179
  compilerOptions: {
18046
18180
  rootDir: ".."
18047
18181
  },
@@ -18055,7 +18189,7 @@ Found ${errorCount} error${suffix}.`;
18055
18189
  resolve40(vueTsconfigPath),
18056
18190
  "--incremental",
18057
18191
  "--tsBuildInfoFile",
18058
- join48(cacheDir, "vue-tsc.tsbuildinfo"),
18192
+ join49(cacheDir, "vue-tsc.tsbuildinfo"),
18059
18193
  "--pretty"
18060
18194
  ]));
18061
18195
  }, buildAngularCheck = async (cacheDir, angularDir) => {
@@ -18064,8 +18198,8 @@ Found ${errorCount} error${suffix}.`;
18064
18198
  console.error("\x1B[31m\u2717\x1B[0m @angular/compiler-cli is required for Angular type checking. Install it: bun add -d @angular/compiler-cli");
18065
18199
  process.exit(1);
18066
18200
  }
18067
- const angularTsconfigPath = join48(cacheDir, "tsconfig.angular-check.json");
18068
- await writeFile14(angularTsconfigPath, JSON.stringify({
18201
+ const angularTsconfigPath = join49(cacheDir, "tsconfig.angular-check.json");
18202
+ await writeFile15(angularTsconfigPath, JSON.stringify({
18069
18203
  angularCompilerOptions: {
18070
18204
  strictTemplates: true
18071
18205
  },
@@ -18084,8 +18218,8 @@ Found ${errorCount} error${suffix}.`;
18084
18218
  console.error("\x1B[31m\u2717\x1B[0m typescript is required for type checking. Install it: bun add -d typescript");
18085
18219
  process.exit(1);
18086
18220
  }
18087
- const tscConfigPath = join48(cacheDir, "tsconfig.typecheck.json");
18088
- return writeFile14(tscConfigPath, JSON.stringify({
18221
+ const tscConfigPath = join49(cacheDir, "tsconfig.typecheck.json");
18222
+ return writeFile15(tscConfigPath, JSON.stringify({
18089
18223
  compilerOptions: {
18090
18224
  rootDir: ".."
18091
18225
  },
@@ -18099,7 +18233,7 @@ Found ${errorCount} error${suffix}.`;
18099
18233
  resolve40(tscConfigPath),
18100
18234
  "--incremental",
18101
18235
  "--tsBuildInfoFile",
18102
- join48(cacheDir, "tsc.tsbuildinfo"),
18236
+ join49(cacheDir, "tsc.tsbuildinfo"),
18103
18237
  "--pretty"
18104
18238
  ]));
18105
18239
  }, buildSvelteCheck = async (cacheDir, svelteDir) => {
@@ -18108,8 +18242,8 @@ Found ${errorCount} error${suffix}.`;
18108
18242
  console.error("\x1B[31m\u2717\x1B[0m svelte-check is required for Svelte type checking. Install it: bun add -d svelte-check");
18109
18243
  process.exit(1);
18110
18244
  }
18111
- const svelteTsconfigPath = join48(cacheDir, "tsconfig.svelte-check.json");
18112
- await writeFile14(svelteTsconfigPath, JSON.stringify({
18245
+ const svelteTsconfigPath = join49(cacheDir, "tsconfig.svelte-check.json");
18246
+ await writeFile15(svelteTsconfigPath, JSON.stringify({
18113
18247
  extends: resolve40("tsconfig.json"),
18114
18248
  files: ABSOLUTE_TYPECHECK_FILES,
18115
18249
  include: [`../${svelteDir}/**/*`]