@absolutejs/absolute 0.20.0-beta.112 → 0.20.0-beta.113

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.
@@ -19401,7 +19401,7 @@ var init_compatibilityDispatcher = __esm(() => {
19401
19401
  // src/cli/scripts/telemetry.ts
19402
19402
  import { existsSync as existsSync5, mkdirSync, readFileSync as readFileSync6, writeFileSync } from "fs";
19403
19403
  import { homedir as homedir4 } from "os";
19404
- import { join as join25 } from "path";
19404
+ import { join as join26 } from "path";
19405
19405
  var configDir, configPath, getTelemetryConfig = () => {
19406
19406
  try {
19407
19407
  if (!existsSync5(configPath))
@@ -19414,14 +19414,14 @@ var configDir, configPath, getTelemetryConfig = () => {
19414
19414
  }
19415
19415
  };
19416
19416
  var init_telemetry = __esm(() => {
19417
- configDir = join25(homedir4(), ".absolutejs");
19418
- configPath = join25(configDir, "telemetry.json");
19417
+ configDir = join26(homedir4(), ".absolutejs");
19418
+ configPath = join26(configDir, "telemetry.json");
19419
19419
  });
19420
19420
 
19421
19421
  // src/cli/telemetryEvent.ts
19422
19422
  import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
19423
19423
  import { arch, platform as platform3 } from "os";
19424
- import { dirname as dirname18, join as join26, parse } from "path";
19424
+ import { dirname as dirname19, join as join27, parse } from "path";
19425
19425
  var checkCandidate = (candidate) => {
19426
19426
  if (!existsSync6(candidate)) {
19427
19427
  return null;
@@ -19441,12 +19441,12 @@ var checkCandidate = (candidate) => {
19441
19441
  }, findPackageVersion = () => {
19442
19442
  let { dir } = import.meta;
19443
19443
  while (dir !== parse(dir).root) {
19444
- const candidate = join26(dir, "package.json");
19444
+ const candidate = join27(dir, "package.json");
19445
19445
  const version = checkCandidate(candidate);
19446
19446
  if (version) {
19447
19447
  return version;
19448
19448
  }
19449
- dir = dirname18(dir);
19449
+ dir = dirname19(dir);
19450
19450
  }
19451
19451
  return "unknown";
19452
19452
  }, sendTelemetryEvent = (event, payload) => {
@@ -19487,7 +19487,7 @@ __export(exports_mobilePreview, {
19487
19487
  createAbsoluteMobilePreviewPlugin: () => createAbsoluteMobilePreviewPlugin
19488
19488
  });
19489
19489
  import { Elysia as Elysia3 } from "elysia";
19490
- var ABSOLUTE_MOBILE_PREVIEW_PATH = "/__absolute/mobile-preview", escapeHtml2 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;"), isRecord14 = (value) => typeof value === "object" && value !== null, normalizeEntry2 = (entry) => {
19490
+ var ABSOLUTE_MOBILE_PREVIEW_PATH = "/__absolute/mobile-preview", escapeHtml2 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;"), isRecord15 = (value) => typeof value === "object" && value !== null, normalizeEntry2 = (entry) => {
19491
19491
  const parsed = new URL(entry ?? "/", "https://absolute.invalid");
19492
19492
  return `${parsed.pathname}${parsed.search}${parsed.hash}`;
19493
19493
  }, absoluteMobilePreviewDocument = (mobile) => {
@@ -19535,7 +19535,7 @@ var ABSOLUTE_MOBILE_PREVIEW_PATH = "/__absolute/mobile-preview", escapeHtml2 = (
19535
19535
  "X-Robots-Tag": "noindex, nofollow"
19536
19536
  }
19537
19537
  })).post("/__absolute/mobile-preview-telemetry", ({ body, status }) => {
19538
- const value = isRecord14(body) ? body : undefined;
19538
+ const value = isRecord15(body) ? body : undefined;
19539
19539
  const durationMs = value?.durationMs;
19540
19540
  const platform4 = value?.platform;
19541
19541
  if (typeof durationMs !== "number" || !Number.isFinite(durationMs) || durationMs < 0 || durationMs > 300000 || platform4 !== "android" && platform4 !== "ios") {
@@ -20086,13 +20086,13 @@ import {
20086
20086
  createHmac,
20087
20087
  createPrivateKey,
20088
20088
  createPublicKey as createPublicKey2,
20089
- randomUUID as randomUUID5,
20089
+ randomUUID as randomUUID6,
20090
20090
  sign as sign2,
20091
20091
  timingSafeEqual,
20092
20092
  verify as verify2,
20093
20093
  X509Certificate as X509Certificate3
20094
20094
  } from "crypto";
20095
- import { readFile as readFile30, stat as stat9 } from "fs/promises";
20095
+ import { readFile as readFile31, stat as stat9 } from "fs/promises";
20096
20096
  import path from "path";
20097
20097
  var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updates", MAX_FILE_BYTES, MAX_TOTAL_BYTES, DAY_MS, DEFAULT_MIN_AGE_MS, DEFAULT_GRACE_PERIOD_MS, DEFAULT_RETAIN_RECENT = 5, HASH, RELEASE, APP_ID, NAME, EXPO_DESCRIPTOR = "_absolute/expo-update.json", EXPO_CODE_SIGNING_ALGORITHM = "rsa-v1_5-sha256", HEALTH_TOKEN_VERSION = 1, HEALTH_KINDS, FAILURE_HEALTH_KINDS, MobileUpdateRegistryError, object6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), text2 = (value, field2) => {
20098
20098
  if (typeof value !== "string" || value.length === 0)
@@ -20446,7 +20446,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
20446
20446
  ...input,
20447
20447
  format: MOBILE_UPDATE_REGISTRY_FORMAT,
20448
20448
  promotedAt,
20449
- promotionId: digest(new TextEncoder().encode(`${input.appId}\x00${input.channel}\x00${input.releaseId ?? "embedded"}\x00${promotedAt}\x00${randomUUID5()}`))
20449
+ promotionId: digest(new TextEncoder().encode(`${input.appId}\x00${input.channel}\x00${input.releaseId ?? "embedded"}\x00${promotedAt}\x00${randomUUID6()}`))
20450
20450
  };
20451
20451
  await beforeWrite?.(value);
20452
20452
  const bytes = json(value);
@@ -20548,7 +20548,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
20548
20548
  if (!releaseId)
20549
20549
  throw new MobileUpdateRegistryError("Mobile update channel does not have an active release");
20550
20550
  const createdAt = clock().toISOString();
20551
- const id = randomUUID5();
20551
+ const id = randomUUID6();
20552
20552
  const event = {
20553
20553
  action,
20554
20554
  createdAt,
@@ -21125,7 +21125,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
21125
21125
  verifyManifestSignature(manifest, options.publicKeys);
21126
21126
  await assertNotMarked(manifest.appId, manifest.releaseId);
21127
21127
  const localRoot = path.resolve(input.releaseDirectory);
21128
- const localManifest = parseMobileUpdateManifest(JSON.parse(await readFile30(path.join(localRoot, "update.json"), "utf8")));
21128
+ const localManifest = parseMobileUpdateManifest(JSON.parse(await readFile31(path.join(localRoot, "update.json"), "utf8")));
21129
21129
  if (JSON.stringify(localManifest) !== JSON.stringify(manifest))
21130
21130
  throw new MobileUpdateRegistryError("Local mobile update manifest changed");
21131
21131
  const existing = await readManifest(manifest.appId, manifest.releaseId);
@@ -21411,8 +21411,8 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
21411
21411
  });
21412
21412
  }
21413
21413
  const pathname = new URL(request.url).pathname.replace(/^\/+/, "");
21414
- const relative23 = pathname.startsWith(`${route}/`) ? pathname.slice(route.length + 1) : "";
21415
- if (request.method === "POST" && relative23 === "health") {
21414
+ const relative24 = pathname.startsWith(`${route}/`) ? pathname.slice(route.length + 1) : "";
21415
+ if (request.method === "POST" && relative24 === "health") {
21416
21416
  if (!options.registry.recordUpdateHealth)
21417
21417
  return new Response(null, { status: 404 });
21418
21418
  const appId = request.headers.get("x-absolute-mobile-app");
@@ -21455,7 +21455,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
21455
21455
  }
21456
21456
  if (request.method !== "GET")
21457
21457
  return new Response(null, { status: 405 });
21458
- if (relative23 === "update.json") {
21458
+ if (relative24 === "update.json") {
21459
21459
  const expoProtocolVersion = request.headers.get("expo-protocol-version");
21460
21460
  const expoProtocol = expoProtocolVersion !== null;
21461
21461
  if (expoProtocol && expoProtocolVersion !== "1")
@@ -21573,7 +21573,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
21573
21573
  }
21574
21574
  });
21575
21575
  }
21576
- const match = /^(amu_[a-f0-9]{64})\/files\/(.+)$/.exec(relative23);
21576
+ const match = /^(amu_[a-f0-9]{64})\/files\/(.+)$/.exec(relative24);
21577
21577
  if (!match?.[1] || !match[2])
21578
21578
  return new Response(null, { status: 404 });
21579
21579
  const file = await options.registry.readUpdateFile({
@@ -21666,15 +21666,15 @@ import {
21666
21666
  createPublicKey as createPublicKey3,
21667
21667
  X509Certificate as X509Certificate4
21668
21668
  } from "crypto";
21669
- import { access as access22, mkdir as mkdir24 } from "fs/promises";
21670
- import { dirname as dirname24, isAbsolute as isAbsolute14, relative as relative23, resolve as resolve25, sep as sep16 } from "path";
21669
+ import { access as access23, mkdir as mkdir25 } from "fs/promises";
21670
+ import { dirname as dirname25, isAbsolute as isAbsolute15, relative as relative24, resolve as resolve26, sep as sep17 } from "path";
21671
21671
  import { pathToFileURL as pathToFileURL5 } from "url";
21672
21672
  import { Elysia as Elysia4 } from "elysia";
21673
21673
  var ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT = 1, DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE = "mobile.update.ts", object7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), projectPath4 = (projectRoot, requested) => {
21674
- const root = resolve25(projectRoot);
21675
- const path2 = resolve25(root, requested);
21676
- const projectRelative = relative23(root, path2);
21677
- if (projectRelative === ".." || projectRelative.startsWith(`..${sep16}`) || isAbsolute14(projectRelative))
21674
+ const root = resolve26(projectRoot);
21675
+ const path2 = resolve26(root, requested);
21676
+ const projectRelative = relative24(root, path2);
21677
+ if (projectRelative === ".." || projectRelative.startsWith(`..${sep17}`) || isAbsolute15(projectRelative))
21678
21678
  throw new TypeError("mobile.updates.server.registry must remain inside the project.");
21679
21679
  return path2;
21680
21680
  }, isRegistry4 = (value) => object7(value) && [
@@ -21697,7 +21697,7 @@ var ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT = 1, DEFAULT_MOBILE_UPDATE_REGISTRY_MOD
21697
21697
  return metadata;
21698
21698
  }, loadAbsoluteMobileUpdateServerModule = async (projectRoot, requestedModulePath = DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE) => {
21699
21699
  const modulePath = projectPath4(projectRoot, requestedModulePath);
21700
- await access22(modulePath).catch(() => {
21700
+ await access23(modulePath).catch(() => {
21701
21701
  throw new TypeError(`Mobile update server registry does not exist: ${modulePath}. Run \`absolute mobile update provision\`.`);
21702
21702
  });
21703
21703
  const loaded = await import(pathToFileURL5(modulePath).href);
@@ -21886,13 +21886,13 @@ ${generated}`);
21886
21886
  }, writeAbsoluteMobileUpdateRegistry = async (options) => {
21887
21887
  const path2 = projectPath4(options.projectRoot, options.modulePath ?? DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE);
21888
21888
  if (!options.force) {
21889
- await access22(path2).then(() => {
21889
+ await access23(path2).then(() => {
21890
21890
  throw new TypeError(`Mobile update registry already exists: ${path2}. Pass --force to replace it.`);
21891
21891
  }, () => {
21892
21892
  return;
21893
21893
  });
21894
21894
  }
21895
- await mkdir24(dirname24(path2), { recursive: true });
21895
+ await mkdir25(dirname25(path2), { recursive: true });
21896
21896
  await Bun.write(path2, renderAbsoluteMobileUpdateRegistry({
21897
21897
  ...options.health ? { health: options.health } : {},
21898
21898
  ...options.rollout ? { rollout: options.rollout } : {},
@@ -34019,10 +34019,228 @@ var auditAbsoluteMobileCiPromotion = async (options) => {
34019
34019
  throw error;
34020
34020
  }
34021
34021
  };
34022
+ // src/mobile/ciPromotionLedger.ts
34023
+ import {
34024
+ access as access19,
34025
+ link,
34026
+ lstat as lstat2,
34027
+ mkdir as mkdir19,
34028
+ open,
34029
+ readFile as readFile23,
34030
+ readdir as readdir8,
34031
+ rename as rename15,
34032
+ rm as rm15
34033
+ } from "fs/promises";
34034
+ import { dirname as dirname17, isAbsolute as isAbsolute12, join as join25, relative as relative18, resolve as resolve20, sep as sep13 } from "path";
34035
+ import { randomUUID as randomUUID5 } from "crypto";
34036
+ var ABSOLUTE_MOBILE_CI_PROMOTION_OPERATION_FORMAT = 1;
34037
+ var MAX_OPERATION_BYTES = 65536;
34038
+ var MAX_OPERATIONS = 1000;
34039
+ var DISPATCH_ID_PATTERN2 = /^amp_[a-f0-9]{32}$/u;
34040
+ var RUN_ID_PATTERN2 = /^[1-9][0-9]*$/u;
34041
+ var SHA256_PATTERN = /^[a-f0-9]{64}$/u;
34042
+ var CERTIFICATION_ID_PATTERN = /^amobile_cert_[a-f0-9]{64}$/u;
34043
+ var RELEASE_ID_PATTERN2 = /^amobile_(?:android|ios)_[a-f0-9]{64}$/u;
34044
+ var REPOSITORY_PATTERN3 = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/u;
34045
+ var LAST_ASCII_CONTROL = 31;
34046
+ var DELETE_CHARACTER = 127;
34047
+ var PHASES = [
34048
+ "dispatching",
34049
+ "dispatched",
34050
+ "discovered",
34051
+ "completed",
34052
+ "audited"
34053
+ ];
34054
+ var isRecord14 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
34055
+ var requiredString2 = (value, label, max = 512) => {
34056
+ const hasControlCharacter = typeof value === "string" && Array.from(value).some((character) => {
34057
+ const code = character.codePointAt(0);
34058
+ return code !== undefined && (code <= LAST_ASCII_CONTROL || code === DELETE_CHARACTER);
34059
+ });
34060
+ if (typeof value !== "string" || value.trim() === "" || value !== value.trim() || value.length > max || hasControlCharacter)
34061
+ throw new TypeError(`${label} is invalid.`);
34062
+ return value;
34063
+ };
34064
+ var optionalString2 = (value, label, max = 512) => {
34065
+ if (value === null)
34066
+ return null;
34067
+ return requiredString2(value, label, max);
34068
+ };
34069
+ var boolean = (value, label) => {
34070
+ if (typeof value !== "boolean")
34071
+ throw new TypeError(`${label} is invalid.`);
34072
+ return value;
34073
+ };
34074
+ var timestamp = (value, label) => {
34075
+ const parsed = requiredString2(value, label, 64);
34076
+ if (!Number.isFinite(Date.parse(parsed)))
34077
+ throw new TypeError(`${label} is invalid.`);
34078
+ return parsed;
34079
+ };
34080
+ var projectRelativePath = (value, label) => {
34081
+ const parsed = requiredString2(value, label, 512);
34082
+ if (isAbsolute12(parsed) || parsed === ".." || parsed.startsWith(`..${sep13}`) || parsed.split(/[\\/]/u).includes(".."))
34083
+ throw new TypeError(`${label} must be project-relative.`);
34084
+ return parsed.replaceAll("\\", "/");
34085
+ };
34086
+ var nullableProjectRelativePath = (value, label) => value === null ? null : projectRelativePath(value, label);
34087
+ var dispatchId2 = (value) => {
34088
+ const parsed = requiredString2(value, "Promotion dispatch ID", 36);
34089
+ if (!DISPATCH_ID_PATTERN2.test(parsed))
34090
+ throw new TypeError("Promotion dispatch ID is invalid.");
34091
+ return parsed;
34092
+ };
34093
+ var runId2 = (value, label) => {
34094
+ const parsed = requiredString2(value, label, 32);
34095
+ if (!RUN_ID_PATTERN2.test(parsed))
34096
+ throw new TypeError(`${label} is invalid.`);
34097
+ return parsed;
34098
+ };
34099
+ var nullableRunId = (value, label) => value === null ? null : runId2(value, label);
34100
+ var operationRoot = (projectRoot) => join25(resolve20(projectRoot), ".absolutejs", "mobile-ci", "promotions");
34101
+ var absoluteMobilePromotionOperationPath = (projectRoot, requestedDispatchId) => join25(operationRoot(projectRoot), dispatchId2(requestedDispatchId), "operation.json");
34102
+ var operationPhase = (value) => {
34103
+ const phase = PHASES.find((candidate) => candidate === value);
34104
+ if (!phase)
34105
+ throw new TypeError("Mobile promotion operation phase is invalid.");
34106
+ return phase;
34107
+ };
34108
+ var parseAbsoluteMobilePromotionOperation = (value) => {
34109
+ if (!isRecord14(value) || value.format !== ABSOLUTE_MOBILE_CI_PROMOTION_OPERATION_FORMAT || value.platform !== "android" && value.platform !== "ios")
34110
+ throw new TypeError("Mobile promotion operation is invalid.");
34111
+ const parsed = {
34112
+ auditDirectory: nullableProjectRelativePath(value.auditDirectory, "Promotion audit directory"),
34113
+ auditOutputDirectory: nullableProjectRelativePath(value.auditOutputDirectory, "Promotion requested audit directory"),
34114
+ auditRequested: boolean(value.auditRequested, "Promotion audit request"),
34115
+ certificationId: requiredString2(value.certificationId, "Promotion certification ID", 256),
34116
+ certificationSha256: requiredString2(value.certificationSha256, "Promotion certification digest", 64),
34117
+ channel: optionalString2(value.channel, "Promotion channel", 128),
34118
+ conclusion: optionalString2(value.conclusion, "Promotion conclusion", 64),
34119
+ createdAt: timestamp(value.createdAt, "Promotion creation time"),
34120
+ dispatchId: dispatchId2(value.dispatchId),
34121
+ format: ABSOLUTE_MOBILE_CI_PROMOTION_OPERATION_FORMAT,
34122
+ githubStatus: optionalString2(value.githubStatus, "Promotion GitHub status", 64),
34123
+ phase: operationPhase(value.phase),
34124
+ platform: value.platform,
34125
+ playTrack: optionalString2(value.playTrack, "Promotion Play track", 128),
34126
+ ref: optionalString2(value.ref, "Promotion ref", 256),
34127
+ releaseId: requiredString2(value.releaseId, "Promotion release ID", 256),
34128
+ repository: optionalString2(value.repository, "Promotion repository", 256),
34129
+ runId: nullableRunId(value.runId, "Promotion run ID"),
34130
+ sourceRunId: runId2(value.sourceRunId, "Promotion source run ID"),
34131
+ testflightGroup: optionalString2(value.testflightGroup, "Promotion TestFlight group", 128),
34132
+ testflightSubmitReview: boolean(value.testflightSubmitReview, "Promotion TestFlight review setting"),
34133
+ updatedAt: timestamp(value.updatedAt, "Promotion update time"),
34134
+ url: optionalString2(value.url, "Promotion run URL", 1024),
34135
+ watchRequested: boolean(value.watchRequested, "Promotion watch request"),
34136
+ workflow: projectRelativePath(value.workflow, "Promotion workflow")
34137
+ };
34138
+ if (!SHA256_PATTERN.test(parsed.certificationSha256))
34139
+ throw new TypeError("Promotion certification digest is invalid.");
34140
+ if (!CERTIFICATION_ID_PATTERN.test(parsed.certificationId))
34141
+ throw new TypeError("Promotion certification ID is invalid.");
34142
+ if (!RELEASE_ID_PATTERN2.test(parsed.releaseId))
34143
+ throw new TypeError("Promotion release ID is invalid.");
34144
+ if (parsed.repository !== null && !REPOSITORY_PATTERN3.test(parsed.repository))
34145
+ throw new TypeError("Promotion repository is invalid.");
34146
+ const discovered = PHASES.indexOf(parsed.phase) >= PHASES.indexOf("discovered");
34147
+ const completed = PHASES.indexOf(parsed.phase) >= PHASES.indexOf("completed");
34148
+ if (discovered && (!parsed.runId || !parsed.url) || !discovered && (parsed.runId || parsed.url) || completed && (parsed.githubStatus !== "completed" || !parsed.conclusion) || !completed && (parsed.githubStatus || parsed.conclusion) || parsed.phase === "audited" && !parsed.auditDirectory || parsed.phase !== "audited" && parsed.auditDirectory)
34149
+ throw new TypeError("Mobile promotion operation phase is incomplete.");
34150
+ if (parsed.url && parsed.runId) {
34151
+ const url = new URL(parsed.url);
34152
+ if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.search !== "" || url.hash !== "" || !url.pathname.endsWith(`/actions/runs/${parsed.runId}`))
34153
+ throw new TypeError("Promotion run URL is invalid.");
34154
+ }
34155
+ if (Date.parse(parsed.updatedAt) < Date.parse(parsed.createdAt))
34156
+ throw new TypeError("Promotion operation time moved backwards.");
34157
+ return parsed;
34158
+ };
34159
+ var serialize = (operation2) => `${JSON.stringify(parseAbsoluteMobilePromotionOperation(operation2), null, 2)}
34160
+ `;
34161
+ var writeSynced = async (path, source) => {
34162
+ const handle = await open(path, "wx", 384);
34163
+ try {
34164
+ await handle.writeFile(source);
34165
+ await handle.sync();
34166
+ } finally {
34167
+ await handle.close();
34168
+ }
34169
+ };
34170
+ var atomicWrite = async (path, source, exclusive) => {
34171
+ await mkdir19(dirname17(path), { recursive: true });
34172
+ const temporary = join25(dirname17(path), `.operation-${randomUUID5()}.tmp`);
34173
+ try {
34174
+ await writeSynced(temporary, source);
34175
+ if (exclusive)
34176
+ await link(temporary, path);
34177
+ else
34178
+ await rename15(temporary, path);
34179
+ } finally {
34180
+ await rm15(temporary, { force: true });
34181
+ }
34182
+ };
34183
+ var advanceAbsoluteMobilePromotionOperation = async (projectRoot, requestedDispatchId, options, now = () => new Date) => {
34184
+ const current = await readAbsoluteMobilePromotionOperation(projectRoot, requestedDispatchId);
34185
+ if (PHASES.indexOf(options.phase) < PHASES.indexOf(current.phase))
34186
+ throw new TypeError("Mobile promotion operation cannot move backwards.");
34187
+ if (current.runId && options.runId && current.runId !== options.runId || current.url && options.url && current.url !== options.url || current.auditDirectory && options.auditDirectory && current.auditDirectory !== options.auditDirectory)
34188
+ throw new TypeError("Mobile promotion operation identity is immutable.");
34189
+ const next = parseAbsoluteMobilePromotionOperation({
34190
+ ...current,
34191
+ auditDirectory: options.auditDirectory === undefined ? current.auditDirectory : options.auditDirectory,
34192
+ conclusion: options.conclusion === undefined ? current.conclusion : options.conclusion,
34193
+ githubStatus: options.githubStatus === undefined ? current.githubStatus : options.githubStatus,
34194
+ phase: options.phase,
34195
+ runId: options.runId === undefined ? current.runId : options.runId,
34196
+ updatedAt: now().toISOString(),
34197
+ url: options.url === undefined ? current.url : options.url
34198
+ });
34199
+ await atomicWrite(absoluteMobilePromotionOperationPath(projectRoot, requestedDispatchId), serialize(next), false);
34200
+ return next;
34201
+ };
34202
+ var createAbsoluteMobilePromotionOperation = async (projectRoot, options) => {
34203
+ const now = (options.now ?? (() => new Date))().toISOString();
34204
+ const operation2 = parseAbsoluteMobilePromotionOperation({
34205
+ ...options,
34206
+ auditDirectory: null,
34207
+ conclusion: null,
34208
+ createdAt: now,
34209
+ format: ABSOLUTE_MOBILE_CI_PROMOTION_OPERATION_FORMAT,
34210
+ githubStatus: null,
34211
+ phase: "dispatching",
34212
+ runId: null,
34213
+ updatedAt: now,
34214
+ url: null
34215
+ });
34216
+ await atomicWrite(absoluteMobilePromotionOperationPath(projectRoot, operation2.dispatchId), serialize(operation2), true);
34217
+ return operation2;
34218
+ };
34219
+ var listAbsoluteMobilePromotionOperations = async (projectRoot) => {
34220
+ const root = operationRoot(projectRoot);
34221
+ if (!await access19(root).then(() => true).catch(() => false))
34222
+ return [];
34223
+ const entries = await readdir8(root, { withFileTypes: true });
34224
+ if (entries.length > MAX_OPERATIONS)
34225
+ throw new TypeError("Mobile promotion operation count exceeds the limit.");
34226
+ const operations = await Promise.all(entries.filter((entry) => entry.isDirectory() && DISPATCH_ID_PATTERN2.test(entry.name)).map((entry) => readAbsoluteMobilePromotionOperation(projectRoot, entry.name)));
34227
+ return operations.sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
34228
+ };
34229
+ var readAbsoluteMobilePromotionOperation = async (projectRoot, requestedDispatchId) => {
34230
+ const path = absoluteMobilePromotionOperationPath(projectRoot, requestedDispatchId);
34231
+ const metadata = await lstat2(path).catch(() => null);
34232
+ if (!metadata?.isFile() || metadata.size > MAX_OPERATION_BYTES)
34233
+ throw new TypeError(`Mobile promotion operation ${requestedDispatchId} was not found or is invalid.`);
34234
+ const operation2 = parseAbsoluteMobilePromotionOperation(JSON.parse(await readFile23(path, "utf8")));
34235
+ if (operation2.dispatchId !== requestedDispatchId)
34236
+ throw new TypeError("Mobile promotion operation identity does not match.");
34237
+ return operation2;
34238
+ };
34239
+ var relativeAbsoluteMobilePromotionOperationPath = (projectRoot, dispatchIdValue) => relative18(resolve20(projectRoot), absoluteMobilePromotionOperationPath(projectRoot, dispatchIdValue)).replaceAll("\\", "/");
34022
34240
  // src/mobile/ciWorkflow.ts
34023
34241
  import { existsSync as existsSync4 } from "fs";
34024
- import { access as access19, mkdir as mkdir19, readFile as readFile23, writeFile as writeFile19 } from "fs/promises";
34025
- import { dirname as dirname17, extname as extname5, relative as relative18, resolve as resolve20, sep as sep13 } from "path";
34242
+ import { access as access20, mkdir as mkdir20, readFile as readFile24, writeFile as writeFile19 } from "fs/promises";
34243
+ import { dirname as dirname18, extname as extname5, relative as relative19, resolve as resolve21, sep as sep14 } from "path";
34026
34244
  var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT = 4;
34027
34245
  var SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/u;
34028
34246
  var CI_ENV_INDENTATION = 6;
@@ -34043,7 +34261,7 @@ var RESERVED_SECRET_NAMES = new Set([
34043
34261
  ]);
34044
34262
  var exists9 = async (path) => {
34045
34263
  try {
34046
- await access19(path);
34264
+ await access20(path);
34047
34265
  return true;
34048
34266
  } catch {
34049
34267
  return false;
@@ -34051,10 +34269,10 @@ var exists9 = async (path) => {
34051
34269
  };
34052
34270
  var yamlString = (value) => `'${value.replaceAll("'", "''")}'`;
34053
34271
  var projectPath2 = (projectRoot, value, field2, options = {}) => {
34054
- const root = resolve20(projectRoot);
34055
- const path = resolve20(root, value);
34056
- const portable = relative18(root, path).replaceAll("\\", "/");
34057
- if (portable === ".." || portable.startsWith(`..${sep13}`) || portable.startsWith("../") || portable === "") {
34272
+ const root = resolve21(projectRoot);
34273
+ const path = resolve21(root, value);
34274
+ const portable = relative19(root, path).replaceAll("\\", "/");
34275
+ if (portable === ".." || portable.startsWith(`..${sep14}`) || portable.startsWith("../") || portable === "") {
34058
34276
  throw new TypeError(`${field2} must remain inside the project root.`);
34059
34277
  }
34060
34278
  if (/\r|\n/u.test(portable) || portable.startsWith("-"))
@@ -34064,11 +34282,11 @@ var projectPath2 = (projectRoot, value, field2, options = {}) => {
34064
34282
  return portable;
34065
34283
  };
34066
34284
  var workflowOutputPath = (projectRoot, value) => {
34067
- const root = resolve20(projectRoot);
34068
- const workflows = resolve20(root, ".github/workflows");
34069
- const path = resolve20(root, value ?? ".github/workflows/absolute-mobile.yml");
34070
- const portable = relative18(workflows, path);
34071
- if (portable === ".." || portable.startsWith(`..${sep13}`) || extname5(path) !== ".yml" && extname5(path) !== ".yaml") {
34285
+ const root = resolve21(projectRoot);
34286
+ const workflows = resolve21(root, ".github/workflows");
34287
+ const path = resolve21(root, value ?? ".github/workflows/absolute-mobile.yml");
34288
+ const portable = relative19(workflows, path);
34289
+ if (portable === ".." || portable.startsWith(`..${sep14}`) || extname5(path) !== ".yml" && extname5(path) !== ".yaml") {
34072
34290
  throw new TypeError("mobile ci github --output must be a .yml or .yaml file inside .github/workflows.");
34073
34291
  }
34074
34292
  return path;
@@ -34829,11 +35047,11 @@ ${bundleAuditSteps}${platforms.includes("android") ? androidJob({ customSecrets,
34829
35047
  var writeAbsoluteMobileGithubWorkflow = async (options) => {
34830
35048
  const path = workflowOutputPath(options.projectRoot, options.outputPath);
34831
35049
  const generated = createAbsoluteMobileGithubWorkflow(options);
34832
- const previous = await exists9(path) ? await readFile23(path, "utf8") : undefined;
35050
+ const previous = await exists9(path) ? await readFile24(path, "utf8") : undefined;
34833
35051
  if (previous !== undefined && previous !== generated.workflow && !options.force)
34834
- throw new TypeError(`${relative18(options.projectRoot, path)} already exists and differs. Rerun with --force to replace the generated workflow.`);
35052
+ throw new TypeError(`${relative19(options.projectRoot, path)} already exists and differs. Rerun with --force to replace the generated workflow.`);
34835
35053
  if (previous !== generated.workflow) {
34836
- await mkdir19(dirname17(path), { recursive: true });
35054
+ await mkdir20(dirname18(path), { recursive: true });
34837
35055
  await writeFile19(path, generated.workflow);
34838
35056
  }
34839
35057
  return {
@@ -34852,20 +35070,20 @@ init_materializedBundle();
34852
35070
  init_mobilePreview();
34853
35071
 
34854
35072
  // src/mobile/nativeDeepLinks.ts
34855
- import { readFile as readFile24, rename as rename15, writeFile as writeFile20 } from "fs/promises";
34856
- import { join as join27 } from "path";
35073
+ import { readFile as readFile25, rename as rename16, writeFile as writeFile20 } from "fs/promises";
35074
+ import { join as join28 } from "path";
34857
35075
  var START_MARKER = "<!-- absolutejs:deep-links:start -->";
34858
35076
  var END_MARKER = "<!-- absolutejs:deep-links:end -->";
34859
35077
  var IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements";
34860
35078
  var NOT_FOUND = -1;
34861
35079
  var escapeXml = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
34862
35080
  var writeChangedFile = async (path, source) => {
34863
- const current = await readFile24(path, "utf8");
35081
+ const current = await readFile25(path, "utf8");
34864
35082
  if (current === source)
34865
35083
  return false;
34866
35084
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
34867
35085
  await writeFile20(temporary, source, { flag: "wx" });
34868
- await rename15(temporary, path);
35086
+ await rename16(temporary, path);
34869
35087
  return true;
34870
35088
  };
34871
35089
  var replaceManagedRegion = (source, region, insertAt) => {
@@ -34910,8 +35128,8 @@ ${hosts}
34910
35128
  `;
34911
35129
  };
34912
35130
  var configureAndroid = async (config) => {
34913
- const path = join27(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
34914
- const source = await readFile24(path, "utf8");
35131
+ const path = join28(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
35132
+ const source = await readFile25(path, "utf8");
34915
35133
  const mainActivity = source.indexOf('android:name=".MainActivity"');
34916
35134
  if (mainActivity === NOT_FOUND) {
34917
35135
  throw new TypeError("Android MainActivity was not found.");
@@ -34936,8 +35154,8 @@ var iosSchemeRegion = (scheme) => ` ${START_MARKER}
34936
35154
  ${END_MARKER}
34937
35155
  `;
34938
35156
  var configureIosInfo = async (config) => {
34939
- const path = join27(config.nativeProjectDirectory, "ios/App/App/Info.plist");
34940
- const source = await readFile24(path, "utf8");
35157
+ const path = join28(config.nativeProjectDirectory, "ios/App/App/Info.plist");
35158
+ const source = await readFile25(path, "utf8");
34941
35159
  const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
34942
35160
  ${END_MARKER}
34943
35161
  `;
@@ -34960,10 +35178,10 @@ ${domains}
34960
35178
  `;
34961
35179
  };
34962
35180
  var configureIosEntitlements = async (config) => {
34963
- const path = join27(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
35181
+ const path = join28(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
34964
35182
  let current = "";
34965
35183
  try {
34966
- current = await readFile24(path, "utf8");
35184
+ current = await readFile25(path, "utf8");
34967
35185
  } catch (error) {
34968
35186
  if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") {
34969
35187
  throw error;
@@ -34974,12 +35192,12 @@ var configureIosEntitlements = async (config) => {
34974
35192
  return false;
34975
35193
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
34976
35194
  await writeFile20(temporary, source, { flag: "wx" });
34977
- await rename15(temporary, path);
35195
+ await rename16(temporary, path);
34978
35196
  return true;
34979
35197
  };
34980
35198
  var configureIosProject = async (config) => {
34981
- const path = join27(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
34982
- const source = await readFile24(path, "utf8");
35199
+ const path = join28(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
35200
+ const source = await readFile25(path, "utf8");
34983
35201
  const declarations = [
34984
35202
  ...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
34985
35203
  ].map((match) => match[1]);
@@ -35018,8 +35236,8 @@ var applyAbsoluteNativeDeepLinks = async (config, platforms = config.platforms)
35018
35236
  };
35019
35237
  // src/mobile/nativeDeviceCapabilities.ts
35020
35238
  init_deviceCapabilities();
35021
- import { readFile as readFile25, rename as rename16, writeFile as writeFile21 } from "fs/promises";
35022
- import { join as join28 } from "path";
35239
+ import { readFile as readFile26, rename as rename17, writeFile as writeFile21 } from "fs/promises";
35240
+ import { join as join29 } from "path";
35023
35241
  var START_MARKER2 = "<!-- absolutejs:device-capabilities:start -->";
35024
35242
  var END_MARKER2 = "<!-- absolutejs:device-capabilities:end -->";
35025
35243
  var NOT_FOUND2 = -1;
@@ -35029,12 +35247,12 @@ var PUSH_START_MARKER = "absolutejs:push-notifications:start";
35029
35247
  var PUSH_END_MARKER = "absolutejs:push-notifications:end";
35030
35248
  var escapeXml2 = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
35031
35249
  var writeChangedFile2 = async (path, source) => {
35032
- const current = await readFile25(path, "utf8");
35250
+ const current = await readFile26(path, "utf8");
35033
35251
  if (current === source)
35034
35252
  return false;
35035
35253
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
35036
35254
  await writeFile21(temporary, source, { flag: "wx" });
35037
- await rename16(temporary, path);
35255
+ await rename17(temporary, path);
35038
35256
  return true;
35039
35257
  };
35040
35258
  var writeOptionalChangedFile = async (path, source) => {
@@ -35049,7 +35267,7 @@ var writeOptionalChangedFile = async (path, source) => {
35049
35267
  };
35050
35268
  var optionalSource = async (path) => {
35051
35269
  try {
35052
- return await readFile25(path, "utf8");
35270
+ return await readFile26(path, "utf8");
35053
35271
  } catch (error) {
35054
35272
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
35055
35273
  return null;
@@ -35169,8 +35387,8 @@ var writeIosPrivacyManifest = async (path, current, source) => {
35169
35387
  var configureIosPrivacyProject = async (config, requirements) => {
35170
35388
  if (requirements.iosPrivacyAccessedApis.length === 0)
35171
35389
  return false;
35172
- const projectPath3 = join28(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
35173
- const project = await readFile25(projectPath3, "utf8");
35390
+ const projectPath3 = join29(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
35391
+ const project = await readFile26(projectPath3, "utf8");
35174
35392
  return writeChangedFile2(projectPath3, addIosPrivacyProjectReference(project));
35175
35393
  };
35176
35394
  var addIosPrivacyProjectReference = (source) => {
@@ -35222,8 +35440,8 @@ ${next.slice(index)}`;
35222
35440
  return next;
35223
35441
  };
35224
35442
  var configureIos2 = async (config, plan) => {
35225
- const path = join28(config.nativeProjectDirectory, "ios/App/App/Info.plist");
35226
- const source = await readFile25(path, "utf8");
35443
+ const path = join29(config.nativeProjectDirectory, "ios/App/App/Info.plist");
35444
+ const source = await readFile26(path, "utf8");
35227
35445
  const requirements = absoluteDeviceNativeRequirements(plan);
35228
35446
  const existingSystemBars = source.match(/<key>UIViewControllerBasedStatusBarAppearance<\/key>\s*<(true|false)\s*\/>/u);
35229
35447
  const ownedStart = source.indexOf(START_MARKER2);
@@ -35243,7 +35461,7 @@ ${content}
35243
35461
  ${END_MARKER2}
35244
35462
  ` : "";
35245
35463
  const infoChanged = await writeChangedFile2(path, managed(source, region, source.lastIndexOf("</dict>")));
35246
- const privacyPath = join28(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
35464
+ const privacyPath = join29(config.nativeProjectDirectory, "ios/App/App/PrivacyInfo.xcprivacy");
35247
35465
  const privacyCurrent = await optionalSource(privacyPath);
35248
35466
  const privacySource = privacyManifestSource(privacyCurrent, requirements);
35249
35467
  const [privacyChanged, projectChanged, pushChanged] = await Promise.all([
@@ -35254,7 +35472,7 @@ ${content}
35254
35472
  return infoChanged || privacyChanged || projectChanged || pushChanged;
35255
35473
  };
35256
35474
  var configureIosPushNotifications = async (config, enabled) => {
35257
- const entitlementsPath = join28(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
35475
+ const entitlementsPath = join29(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
35258
35476
  const entitlements = await optionalSource(entitlementsPath);
35259
35477
  if (entitlements === null && !enabled)
35260
35478
  return false;
@@ -35266,7 +35484,7 @@ var configureIosPushNotifications = async (config, enabled) => {
35266
35484
  <!-- ${PUSH_END_MARKER} -->
35267
35485
  ` : "";
35268
35486
  const nextEntitlements = replacePushRegion(entitlements, entitlementRegion, entitlements.lastIndexOf("</dict>"));
35269
- const delegatePath = join28(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
35487
+ const delegatePath = join29(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
35270
35488
  const delegate = await optionalSource(delegatePath);
35271
35489
  if (delegate === null && !enabled)
35272
35490
  return false;
@@ -35315,8 +35533,8 @@ var replacePushRegion = (source, region, insertion) => {
35315
35533
  return `${source.slice(0, insertion)}${region}${source.slice(insertion)}`;
35316
35534
  };
35317
35535
  var configureAndroid2 = async (config, plan) => {
35318
- const path = join28(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
35319
- const source = await readFile25(path, "utf8");
35536
+ const path = join29(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
35537
+ const source = await readFile26(path, "utf8");
35320
35538
  const permissions = absoluteDeviceNativeRequirements(plan).androidPermissions;
35321
35539
  const content = permissions.map((permission) => ` <uses-permission android:name="${escapeXml2(permission)}" />`).join(`
35322
35540
  `);
@@ -35351,7 +35569,7 @@ ${content}
35351
35569
  throw new TypeError(`Android google-services.json does not contain package ${config.appId}.`);
35352
35570
  const [manifestChanged, firebaseChanged] = await Promise.all([
35353
35571
  writeChangedFile2(path, nextManifest),
35354
- writeOptionalChangedFile(join28(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
35572
+ writeOptionalChangedFile(join29(config.nativeProjectDirectory, "android/app/google-services.json"), firebaseSource)
35355
35573
  ]);
35356
35574
  return manifestChanged || firebaseChanged;
35357
35575
  };
@@ -35370,14 +35588,14 @@ init_nativeAuth();
35370
35588
 
35371
35589
  // src/mobile/nativeUpdates.ts
35372
35590
  import {
35373
- mkdir as mkdir20,
35374
- readFile as readFile26,
35375
- readdir as readdir8,
35376
- rename as rename17,
35377
- rm as rm15,
35591
+ mkdir as mkdir21,
35592
+ readFile as readFile27,
35593
+ readdir as readdir9,
35594
+ rename as rename18,
35595
+ rm as rm16,
35378
35596
  writeFile as writeFile22
35379
35597
  } from "fs/promises";
35380
- import { dirname as dirname19, join as join29 } from "path";
35598
+ import { dirname as dirname20, join as join30 } from "path";
35381
35599
  var START = "// absolutejs:mobile-updates:start";
35382
35600
  var END = "// absolutejs:mobile-updates:end";
35383
35601
  var PLUGIN_START = "// absolutejs:mobile-update-plugin:start";
@@ -35385,32 +35603,32 @@ var PLUGIN_END = "// absolutejs:mobile-update-plugin:end";
35385
35603
  var ANDROID_PLUGIN = "AbsoluteMobileUpdateWatchdogPlugin.java";
35386
35604
  var optionalSource2 = async (path) => {
35387
35605
  try {
35388
- return await readFile26(path, "utf8");
35606
+ return await readFile27(path, "utf8");
35389
35607
  } catch (error) {
35390
35608
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
35391
35609
  return null;
35392
35610
  throw error;
35393
35611
  }
35394
35612
  };
35395
- var isRecord15 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
35613
+ var isRecord16 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
35396
35614
  var writeChanged = async (path, source) => {
35397
35615
  const current = await optionalSource2(path);
35398
35616
  if (current === source)
35399
35617
  return false;
35400
- await mkdir20(dirname19(path), { recursive: true });
35618
+ await mkdir21(dirname20(path), { recursive: true });
35401
35619
  if (current === null) {
35402
35620
  await writeFile22(path, source, { flag: "wx" });
35403
35621
  return true;
35404
35622
  }
35405
35623
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
35406
35624
  await writeFile22(temporary, source, { flag: "wx" });
35407
- await rename17(temporary, path);
35625
+ await rename18(temporary, path);
35408
35626
  return true;
35409
35627
  };
35410
35628
  var removeOwnedFile = async (path) => {
35411
35629
  if (await optionalSource2(path) === null)
35412
35630
  return false;
35413
- await rm15(path);
35631
+ await rm16(path);
35414
35632
  return true;
35415
35633
  };
35416
35634
  var replaceMarkedRegion = (source, start, end, region, insertion, error) => {
@@ -35547,9 +35765,9 @@ public final class AbsoluteMobileUpdateWatchdogPlugin: CAPPlugin, CAPBridgedPlug
35547
35765
  ${PLUGIN_END}
35548
35766
  `;
35549
35767
  var configureIos3 = async (config, enabled) => {
35550
- const path = join29(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
35551
- const capacitorConfigPath = join29(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
35552
- let source = await readFile26(path, "utf8");
35768
+ const path = join30(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
35769
+ const capacitorConfigPath = join30(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
35770
+ let source = await readFile27(path, "utf8");
35553
35771
  const launch2 = source.indexOf("didFinishLaunchingWithOptions");
35554
35772
  const brace = launch2 < 0 ? -1 : source.indexOf("{", launch2);
35555
35773
  const launchRegion = enabled ? ` ${START}
@@ -35560,11 +35778,11 @@ var configureIos3 = async (config, enabled) => {
35560
35778
  `, brace) + 1, "Could not find a safe iOS location for mobile update recovery.");
35561
35779
  const plugin = enabled ? iosPluginRegion(config.updates?.bootTimeoutMs ?? 20000) : "";
35562
35780
  source = replaceMarkedRegion(source, PLUGIN_START, PLUGIN_END, plugin, source.length, "Could not find a safe iOS location for the mobile update watchdog.");
35563
- const capacitorConfigSource2 = await readFile26(capacitorConfigPath, "utf8");
35781
+ const capacitorConfigSource2 = await readFile27(capacitorConfigPath, "utf8");
35564
35782
  let capacitorConfig;
35565
35783
  try {
35566
35784
  const value = JSON.parse(capacitorConfigSource2);
35567
- if (!isRecord15(value))
35785
+ if (!isRecord16(value))
35568
35786
  throw new TypeError;
35569
35787
  capacitorConfig = value;
35570
35788
  } catch {
@@ -35733,19 +35951,19 @@ public final class AbsoluteMobileUpdateWatchdogPlugin extends Plugin {
35733
35951
  var androidActivityInRoot = async (root) => {
35734
35952
  let entries;
35735
35953
  try {
35736
- entries = await readdir8(root, { recursive: true });
35954
+ entries = await readdir9(root, { recursive: true });
35737
35955
  } catch (error) {
35738
35956
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
35739
35957
  return;
35740
35958
  throw error;
35741
35959
  }
35742
35960
  const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
35743
- return candidate ? join29(root, candidate) : undefined;
35961
+ return candidate ? join30(root, candidate) : undefined;
35744
35962
  };
35745
35963
  var androidActivity = async (config) => {
35746
35964
  const roots = [
35747
- join29(config.nativeProjectDirectory, "android/app/src/main/java"),
35748
- join29(config.nativeProjectDirectory, "android/app/src/main/kotlin")
35965
+ join30(config.nativeProjectDirectory, "android/app/src/main/java"),
35966
+ join30(config.nativeProjectDirectory, "android/app/src/main/kotlin")
35749
35967
  ];
35750
35968
  const candidates = await Promise.all(roots.map(androidActivityInRoot));
35751
35969
  const candidate = candidates.find((value) => value !== undefined);
@@ -35844,12 +36062,12 @@ var injectAndroidActivity = (source, enabled) => {
35844
36062
  };
35845
36063
  var configureAndroid3 = async (config, enabled) => {
35846
36064
  const activityPath = await androidActivity(config);
35847
- const activity = await readFile26(activityPath, "utf8");
36065
+ const activity = await readFile27(activityPath, "utf8");
35848
36066
  const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
35849
36067
  if (!packageName)
35850
36068
  throw new TypeError("Android MainActivity package declaration was not found.");
35851
36069
  const packagePath = packageName.replaceAll(".", "/");
35852
- const pluginPath = join29(config.nativeProjectDirectory, "android/app/src/main/java", packagePath, ANDROID_PLUGIN);
36070
+ const pluginPath = join30(config.nativeProjectDirectory, "android/app/src/main/java", packagePath, ANDROID_PLUGIN);
35853
36071
  const changed = await Promise.all([
35854
36072
  writeChanged(activityPath, injectAndroidActivity(activity, enabled)),
35855
36073
  enabled ? writeChanged(pluginPath, androidPluginSource(packageName, config.updates?.bootTimeoutMs ?? 20000)) : removeOwnedFile(pluginPath)
@@ -35869,14 +36087,14 @@ var applyAbsoluteNativeUpdates = async (config, platforms = config.platforms) =>
35869
36087
  };
35870
36088
  // src/mobile/nativeObservability.ts
35871
36089
  import {
35872
- mkdir as mkdir21,
35873
- readFile as readFile27,
35874
- readdir as readdir9,
35875
- rename as rename18,
35876
- rm as rm16,
36090
+ mkdir as mkdir22,
36091
+ readFile as readFile28,
36092
+ readdir as readdir10,
36093
+ rename as rename19,
36094
+ rm as rm17,
35877
36095
  writeFile as writeFile23
35878
36096
  } from "fs/promises";
35879
- import { dirname as dirname20, join as join30 } from "path";
36097
+ import { dirname as dirname21, join as join31 } from "path";
35880
36098
  var START2 = "// absolutejs:native-observability:start";
35881
36099
  var END2 = "// absolutejs:native-observability:end";
35882
36100
  var PLUGIN_START2 = "// absolutejs:native-observability-plugin:start";
@@ -35884,7 +36102,7 @@ var PLUGIN_END2 = "// absolutejs:native-observability-plugin:end";
35884
36102
  var ANDROID_PLUGIN2 = "AbsoluteMobileObservabilityPlugin.java";
35885
36103
  var optionalSource3 = async (path) => {
35886
36104
  try {
35887
- return await readFile27(path, "utf8");
36105
+ return await readFile28(path, "utf8");
35888
36106
  } catch (error) {
35889
36107
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
35890
36108
  return null;
@@ -35895,23 +36113,23 @@ var writeChanged2 = async (path, source) => {
35895
36113
  const current = await optionalSource3(path);
35896
36114
  if (current === source)
35897
36115
  return false;
35898
- await mkdir21(dirname20(path), { recursive: true });
36116
+ await mkdir22(dirname21(path), { recursive: true });
35899
36117
  if (current === null) {
35900
36118
  await writeFile23(path, source, { flag: "wx" });
35901
36119
  return true;
35902
36120
  }
35903
36121
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
35904
36122
  await writeFile23(temporary, source, { flag: "wx" });
35905
- await rename18(temporary, path);
36123
+ await rename19(temporary, path);
35906
36124
  return true;
35907
36125
  };
35908
36126
  var removeOwnedFile2 = async (path) => {
35909
36127
  if (await optionalSource3(path) === null)
35910
36128
  return false;
35911
- await rm16(path);
36129
+ await rm17(path);
35912
36130
  return true;
35913
36131
  };
35914
- var isRecord16 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
36132
+ var isRecord17 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
35915
36133
  var replaceMarkedRegion2 = (source, start, end, region, insertion, error) => {
35916
36134
  const existingStart = source.indexOf(start);
35917
36135
  const existingEnd = source.indexOf(end);
@@ -36044,9 +36262,9 @@ public final class AbsoluteMobileObservabilityPlugin: CAPPlugin, CAPBridgedPlugi
36044
36262
  ${PLUGIN_END2}
36045
36263
  `;
36046
36264
  var configureIos4 = async (config, enabled) => {
36047
- const path = join30(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36048
- const capacitorConfigPath = join30(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
36049
- let source = await readFile27(path, "utf8");
36265
+ const path = join31(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36266
+ const capacitorConfigPath = join31(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
36267
+ let source = await readFile28(path, "utf8");
36050
36268
  if (enabled && !source.includes("import MetricKit")) {
36051
36269
  const capacitorImport = source.lastIndexOf("import Capacitor");
36052
36270
  if (capacitorImport < 0)
@@ -36060,11 +36278,11 @@ ${source.slice(newline + 1)}`;
36060
36278
  source = source.replace(`import MetricKit
36061
36279
  `, "");
36062
36280
  source = replaceMarkedRegion2(source, PLUGIN_START2, PLUGIN_END2, enabled ? iosPluginRegion2 : "", source.length, "Could not find a safe iOS location for native observability.");
36063
- const capacitorConfigSource2 = await readFile27(capacitorConfigPath, "utf8");
36281
+ const capacitorConfigSource2 = await readFile28(capacitorConfigPath, "utf8");
36064
36282
  let capacitorConfig;
36065
36283
  try {
36066
36284
  const value = JSON.parse(capacitorConfigSource2);
36067
- if (!isRecord16(value))
36285
+ if (!isRecord17(value))
36068
36286
  throw new TypeError;
36069
36287
  capacitorConfig = value;
36070
36288
  } catch {
@@ -36298,19 +36516,19 @@ public final class AbsoluteMobileObservabilityPlugin extends Plugin {
36298
36516
  var androidActivityInRoot2 = async (root) => {
36299
36517
  let entries;
36300
36518
  try {
36301
- entries = await readdir9(root, { recursive: true });
36519
+ entries = await readdir10(root, { recursive: true });
36302
36520
  } catch (error) {
36303
36521
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
36304
36522
  return;
36305
36523
  throw error;
36306
36524
  }
36307
36525
  const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
36308
- return candidate ? join30(root, candidate) : undefined;
36526
+ return candidate ? join31(root, candidate) : undefined;
36309
36527
  };
36310
36528
  var androidActivity2 = async (config) => {
36311
36529
  const roots = [
36312
- join30(config.nativeProjectDirectory, "android/app/src/main/java"),
36313
- join30(config.nativeProjectDirectory, "android/app/src/main/kotlin")
36530
+ join31(config.nativeProjectDirectory, "android/app/src/main/java"),
36531
+ join31(config.nativeProjectDirectory, "android/app/src/main/kotlin")
36314
36532
  ];
36315
36533
  const candidates = await Promise.all(roots.map(androidActivityInRoot2));
36316
36534
  const candidate = candidates.find((value) => value !== undefined);
@@ -36378,11 +36596,11 @@ var injectAndroidActivity2 = (source, enabled) => {
36378
36596
  };
36379
36597
  var configureAndroid4 = async (config, enabled) => {
36380
36598
  const activityPath = await androidActivity2(config);
36381
- const activity = await readFile27(activityPath, "utf8");
36599
+ const activity = await readFile28(activityPath, "utf8");
36382
36600
  const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
36383
36601
  if (!packageName)
36384
36602
  throw new TypeError("Android MainActivity package declaration was not found.");
36385
- const pluginPath = join30(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN2);
36603
+ const pluginPath = join31(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN2);
36386
36604
  const changed = await Promise.all([
36387
36605
  writeChanged2(activityPath, injectAndroidActivity2(activity, enabled)),
36388
36606
  enabled ? writeChanged2(pluginPath, androidPluginSource2(packageName)) : removeOwnedFile2(pluginPath)
@@ -36401,8 +36619,8 @@ var applyAbsoluteNativeObservability = async (config, platforms = config.platfor
36401
36619
  return { changed: changed.some(Boolean) };
36402
36620
  };
36403
36621
  // src/mobile/nativeReleaseReadiness.ts
36404
- import { mkdir as mkdir22, readFile as readFile28, readdir as readdir10, rename as rename19, writeFile as writeFile24 } from "fs/promises";
36405
- import { dirname as dirname21, join as join31 } from "path";
36622
+ import { mkdir as mkdir23, readFile as readFile29, readdir as readdir11, rename as rename20, writeFile as writeFile24 } from "fs/promises";
36623
+ import { dirname as dirname22, join as join32 } from "path";
36406
36624
  var START3 = "// absolutejs:release-readiness:start";
36407
36625
  var END3 = "// absolutejs:release-readiness:end";
36408
36626
  var IOS_PLUGIN_START = "// absolutejs:release-readiness-plugin:start";
@@ -36410,7 +36628,7 @@ var IOS_PLUGIN_END = "// absolutejs:release-readiness-plugin:end";
36410
36628
  var ANDROID_PLUGIN3 = "AbsoluteReleaseReadinessPlugin.java";
36411
36629
  var optionalSource4 = async (path) => {
36412
36630
  try {
36413
- return await readFile28(path, "utf8");
36631
+ return await readFile29(path, "utf8");
36414
36632
  } catch (error) {
36415
36633
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
36416
36634
  return null;
@@ -36421,32 +36639,32 @@ var writeChanged3 = async (path, source) => {
36421
36639
  const current = await optionalSource4(path);
36422
36640
  if (current === source)
36423
36641
  return false;
36424
- await mkdir22(dirname21(path), { recursive: true });
36642
+ await mkdir23(dirname22(path), { recursive: true });
36425
36643
  if (current === null) {
36426
36644
  await writeFile24(path, source, { flag: "wx" });
36427
36645
  return true;
36428
36646
  }
36429
36647
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
36430
36648
  await writeFile24(temporary, source, { flag: "wx" });
36431
- await rename19(temporary, path);
36649
+ await rename20(temporary, path);
36432
36650
  return true;
36433
36651
  };
36434
36652
  var activityInRoot = async (root) => {
36435
36653
  let entries;
36436
36654
  try {
36437
- entries = await readdir10(root, { recursive: true });
36655
+ entries = await readdir11(root, { recursive: true });
36438
36656
  } catch (error) {
36439
36657
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "ENOENT")
36440
36658
  return;
36441
36659
  throw error;
36442
36660
  }
36443
36661
  const candidate = entries.find((entry) => entry.endsWith("/MainActivity.java") || entry.endsWith("/MainActivity.kt") || entry === "MainActivity.java" || entry === "MainActivity.kt");
36444
- return candidate ? join31(root, candidate) : undefined;
36662
+ return candidate ? join32(root, candidate) : undefined;
36445
36663
  };
36446
36664
  var activityPath = async (config) => {
36447
36665
  const roots = [
36448
- join31(config.nativeProjectDirectory, "android/app/src/main/java"),
36449
- join31(config.nativeProjectDirectory, "android/app/src/main/kotlin")
36666
+ join32(config.nativeProjectDirectory, "android/app/src/main/java"),
36667
+ join32(config.nativeProjectDirectory, "android/app/src/main/kotlin")
36450
36668
  ];
36451
36669
  const candidates = await Promise.all(roots.map(activityInRoot));
36452
36670
  const candidate = candidates.find((value) => value !== undefined);
@@ -36556,9 +36774,9 @@ var replaceIosPluginRegion = (appDelegate, existingStart, existingEnd) => {
36556
36774
  return `${appDelegate.slice(0, from)}${iosPluginRegion3}${appDelegate.slice(through)}`;
36557
36775
  };
36558
36776
  var configureIos5 = async (config) => {
36559
- const appDelegatePath = join31(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36560
- const capacitorConfigPath = join31(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
36561
- const appDelegate = await readFile28(appDelegatePath, "utf8");
36777
+ const appDelegatePath = join32(config.nativeProjectDirectory, "ios/App/App/AppDelegate.swift");
36778
+ const capacitorConfigPath = join32(config.nativeProjectDirectory, "ios/App/App/capacitor.config.json");
36779
+ const appDelegate = await readFile29(appDelegatePath, "utf8");
36562
36780
  const existingStart = appDelegate.indexOf(IOS_PLUGIN_START);
36563
36781
  const existingEnd = appDelegate.indexOf(IOS_PLUGIN_END);
36564
36782
  if (existingStart < 0 !== existingEnd < 0 || existingStart >= 0 && existingEnd < existingStart)
@@ -36568,7 +36786,7 @@ var configureIos5 = async (config) => {
36568
36786
  ${iosPluginRegion3}` : replaceIosPluginRegion(appDelegate, existingStart, existingEnd);
36569
36787
  let capacitorConfig;
36570
36788
  try {
36571
- capacitorConfig = JSON.parse(await readFile28(capacitorConfigPath, "utf8"));
36789
+ capacitorConfig = JSON.parse(await readFile29(capacitorConfigPath, "utf8"));
36572
36790
  } catch {
36573
36791
  throw new TypeError("iOS capacitor.config.json is invalid; run Capacitor sync before projecting release readiness.");
36574
36792
  }
@@ -36593,11 +36811,11 @@ ${iosPluginRegion3}` : replaceIosPluginRegion(appDelegate, existingStart, existi
36593
36811
  };
36594
36812
  var configureAndroid5 = async (config) => {
36595
36813
  const mainActivityPath = await activityPath(config);
36596
- const activity = await readFile28(mainActivityPath, "utf8");
36814
+ const activity = await readFile29(mainActivityPath, "utf8");
36597
36815
  const packageName = activity.match(/^\s*package\s+([A-Za-z0-9_.]+)\s*[;\n]/mu)?.[1];
36598
36816
  if (!packageName)
36599
36817
  throw new TypeError("Android MainActivity package declaration was not found.");
36600
- const pluginPath = join31(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN3);
36818
+ const pluginPath = join32(config.nativeProjectDirectory, "android/app/src/main/java", packageName.replaceAll(".", "/"), ANDROID_PLUGIN3);
36601
36819
  const changed = await Promise.all([
36602
36820
  writeChanged3(mainActivityPath, injectRegistration(activity)),
36603
36821
  writeChanged3(pluginPath, pluginSource(packageName))
@@ -36620,8 +36838,8 @@ init_producerContext();
36620
36838
  init_releaseArtifact();
36621
36839
 
36622
36840
  // src/mobile/releasePublisher.ts
36623
- import { access as access20 } from "fs/promises";
36624
- import { isAbsolute as isAbsolute12, relative as relative19, resolve as resolve21, sep as sep14 } from "path";
36841
+ import { access as access21 } from "fs/promises";
36842
+ import { isAbsolute as isAbsolute13, relative as relative20, resolve as resolve22, sep as sep15 } from "path";
36625
36843
  import { pathToFileURL as pathToFileURL3 } from "url";
36626
36844
  var prepareAbsoluteIosRelease = async (publisher, options) => {
36627
36845
  if (typeof publisher.prepareIosRelease !== "function") {
@@ -36655,24 +36873,24 @@ var requireCertificationReceipt = (publication, certification, requirement, rele
36655
36873
  if (verification && (!receipt.provenance || receipt.provenance.subject !== releaseId))
36656
36874
  throw new TypeError("Native release registry did not retain trusted certification provenance.");
36657
36875
  };
36658
- var isRecord17 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
36659
- var isPublisher = (value) => isRecord17(value) && typeof value.publish === "function";
36876
+ var isRecord18 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
36877
+ var isPublisher = (value) => isRecord18(value) && typeof value.publish === "function";
36660
36878
  var publisherModulePath = (projectRoot, requested) => {
36661
- const root = resolve21(projectRoot);
36662
- const path = resolve21(root, requested);
36663
- const projectRelative = relative19(root, path);
36664
- if (projectRelative === ".." || projectRelative.startsWith(`..${sep14}`) || isAbsolute12(projectRelative)) {
36879
+ const root = resolve22(projectRoot);
36880
+ const path = resolve22(root, requested);
36881
+ const projectRelative = relative20(root, path);
36882
+ if (projectRelative === ".." || projectRelative.startsWith(`..${sep15}`) || isAbsolute13(projectRelative)) {
36665
36883
  throw new TypeError("mobile publish --registry must remain inside the project.");
36666
36884
  }
36667
36885
  return path;
36668
36886
  };
36669
36887
  var loadAbsoluteNativeReleasePublisher = async (projectRoot, requestedModulePath) => {
36670
36888
  const modulePath = publisherModulePath(projectRoot, requestedModulePath);
36671
- await access20(modulePath).catch(() => {
36889
+ await access21(modulePath).catch(() => {
36672
36890
  throw new TypeError(`Native release registry module does not exist: ${modulePath}`);
36673
36891
  });
36674
36892
  const loaded = await import(pathToFileURL3(modulePath).href);
36675
- const publisher = isRecord17(loaded) ? loaded.default ?? loaded.registry : undefined;
36893
+ const publisher = isRecord18(loaded) ? loaded.default ?? loaded.registry : undefined;
36676
36894
  if (!isPublisher(publisher)) {
36677
36895
  throw new TypeError("Native release registry module must default-export a registry with publish(options).");
36678
36896
  }
@@ -36754,7 +36972,7 @@ var publishAbsoluteIosRelease = async (options) => {
36754
36972
  init_pageProtocol();
36755
36973
  init_releaseArtifact();
36756
36974
  import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
36757
- import { dirname as dirname22, extname as extname6, relative as relative20, resolve as resolve22 } from "path";
36975
+ import { dirname as dirname23, extname as extname6, relative as relative21, resolve as resolve23 } from "path";
36758
36976
  import ts2 from "typescript";
36759
36977
  var ROUTE_METHODS = new Set(["get", "head"]);
36760
36978
  var SOURCE_FILTER = /\.[cm]?[jt]sx?$/;
@@ -36805,7 +37023,7 @@ var PAGE_HANDLERS = new Map([
36805
37023
  ]
36806
37024
  ]);
36807
37025
  var posixPath = (value) => value.replace(/\\/g, "/");
36808
- var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(dirname22(entry), existsSync7, "tsconfig.json") ?? ts2.findConfigFile(projectRoot, existsSync7, "tsconfig.json");
37026
+ var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(dirname23(entry), existsSync7, "tsconfig.json") ?? ts2.findConfigFile(projectRoot, existsSync7, "tsconfig.json");
36809
37027
  var createProgram = (entry, projectRoot) => {
36810
37028
  const configPath2 = findTsconfig(entry, projectRoot);
36811
37029
  if (!configPath2) {
@@ -36817,7 +37035,7 @@ var createProgram = (entry, projectRoot) => {
36817
37035
  target: ts2.ScriptTarget.ESNext
36818
37036
  });
36819
37037
  }
36820
- const parsed = ts2.parseJsonConfigFileContent(ts2.readConfigFile(configPath2, (path) => readFileSync8(path, "utf8")).config, ts2.sys, dirname22(configPath2));
37038
+ const parsed = ts2.parseJsonConfigFileContent(ts2.readConfigFile(configPath2, (path) => readFileSync8(path, "utf8")).config, ts2.sys, dirname23(configPath2));
36821
37039
  if (!parsed.fileNames.includes(entry))
36822
37040
  parsed.fileNames.push(entry);
36823
37041
  return ts2.createProgram(parsed.fileNames, parsed.options);
@@ -36923,7 +37141,7 @@ var resolvePageIdentity = (expression, sourceFile, checker, projectRoot) => {
36923
37141
  const declaration = symbol?.declarations?.[0];
36924
37142
  const file = declaration?.getSourceFile().fileName ?? sourceFile.fileName;
36925
37143
  const exportedName = symbol?.name ?? expression.getText(sourceFile);
36926
- const source = posixPath(relative20(projectRoot, file));
37144
+ const source = posixPath(relative21(projectRoot, file));
36927
37145
  return `${source}#${exportedName}`;
36928
37146
  };
36929
37147
  var resolveAlias = (symbol, checker) => {
@@ -37162,7 +37380,7 @@ var analyzeProgram = (program, projectRoot) => {
37162
37380
  const checker = program.getTypeChecker();
37163
37381
  const analyzed = new Map;
37164
37382
  for (const sourceFile of program.getSourceFiles()) {
37165
- const resolvedFile = resolve22(sourceFile.fileName);
37383
+ const resolvedFile = resolve23(sourceFile.fileName);
37166
37384
  if (!isProjectSource(sourceFile, resolvedFile, projectRoot))
37167
37385
  continue;
37168
37386
  const analysis = analyzeSourceFile(sourceFile, checker, projectRoot);
@@ -37255,14 +37473,14 @@ var transformFile = (source, fileName, analysis) => {
37255
37473
  };
37256
37474
  var ABSOLUTE_MOBILE_TRANSFORM_PROTOCOL = ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION;
37257
37475
  var createAbsoluteMobileRouteMetadataPlugin = (options) => {
37258
- const projectRoot = resolve22(options.projectRoot ?? process.cwd());
37259
- const entry = resolve22(options.entry);
37476
+ const projectRoot = resolve23(options.projectRoot ?? process.cwd());
37477
+ const entry = resolve23(options.entry);
37260
37478
  const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
37261
37479
  return {
37262
37480
  name: "absolute-mobile-route-metadata",
37263
37481
  setup(build) {
37264
37482
  build.onLoad({ filter: SOURCE_FILTER }, async ({ path }) => {
37265
- const analysis = analyzed.get(resolve22(path));
37483
+ const analysis = analyzed.get(resolve23(path));
37266
37484
  if (!analysis)
37267
37485
  return;
37268
37486
  const source = await Bun.file(path).text();
@@ -37275,11 +37493,11 @@ var createAbsoluteMobileRouteMetadataPlugin = (options) => {
37275
37493
  };
37276
37494
  };
37277
37495
  var inspectAbsoluteMobileRouteMetadata = (options) => {
37278
- const projectRoot = resolve22(options.projectRoot ?? process.cwd());
37279
- const entry = resolve22(options.entry);
37496
+ const projectRoot = resolve23(options.projectRoot ?? process.cwd());
37497
+ const entry = resolve23(options.entry);
37280
37498
  const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
37281
37499
  return [...analyzed.entries()].flatMap(([file, analysis]) => [...analysis.byRouteCall.values()].map(({ metadata }) => ({
37282
- file: posixPath(relative20(projectRoot, file)),
37500
+ file: posixPath(relative21(projectRoot, file)),
37283
37501
  metadata
37284
37502
  })));
37285
37503
  };
@@ -37613,7 +37831,7 @@ var createCapacitor = (win) => {
37613
37831
  callbackId
37614
37832
  }, callback);
37615
37833
  };
37616
- const p = new Promise((resolve23) => call.then(() => resolve23({ remove })));
37834
+ const p = new Promise((resolve24) => call.then(() => resolve24({ remove })));
37617
37835
  p.remove = async () => {
37618
37836
  console.warn(`Using addListener() without 'await' is deprecated.`);
37619
37837
  await remove();
@@ -37818,11 +38036,11 @@ class CapacitorCookiesPluginWeb extends WebPlugin {
37818
38036
  var CapacitorCookies = registerPlugin("CapacitorCookies", {
37819
38037
  web: () => new CapacitorCookiesPluginWeb
37820
38038
  });
37821
- var readBlobAsBase64 = async (blob) => new Promise((resolve23, reject) => {
38039
+ var readBlobAsBase64 = async (blob) => new Promise((resolve24, reject) => {
37822
38040
  const reader = new FileReader;
37823
38041
  reader.onload = () => {
37824
38042
  const base64String = reader.result;
37825
- resolve23(base64String.indexOf(",") >= 0 ? base64String.split(",")[1] : base64String);
38043
+ resolve24(base64String.indexOf(",") >= 0 ? base64String.split(",")[1] : base64String);
37826
38044
  };
37827
38045
  reader.onerror = (error) => reject(error);
37828
38046
  reader.readAsDataURL(blob);
@@ -37998,7 +38216,7 @@ var REPORT_KINDS = new Set([
37998
38216
  "signal"
37999
38217
  ]);
38000
38218
  var nativeObservability = registerPlugin("AbsoluteMobileObservability");
38001
- var isRecord18 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
38219
+ var isRecord19 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
38002
38220
  var redactText = (value) => value.slice(0, MAX_STRING_LENGTH).replace(/\b(Bearer)\s+[A-Za-z0-9._~+/-]+=*/giu, "$1 [REDACTED]").replace(/([?&](?:access_token|api_?key|authorization|code|id_token|password|refresh_token|secret|token)=)[^&#\s]*/giu, "$1[REDACTED]").replace(/\b((?:access_?token|api_?key|authorization|client_?secret|cookie|id_?token|password|passwd|refresh_?token|secret|token)\s*[:=]\s*)[^,\s;]+/giu, "$1[REDACTED]").replace(/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/gu, "[REDACTED]");
38003
38221
  var redactValue = (value, depth = 0) => {
38004
38222
  if (depth >= MAX_REDACTION_DEPTH)
@@ -38009,7 +38227,7 @@ var redactValue = (value, depth = 0) => {
38009
38227
  return value;
38010
38228
  if (Array.isArray(value))
38011
38229
  return value.slice(0, 64).map((entry) => redactValue(entry, depth + 1));
38012
- if (!isRecord18(value))
38230
+ if (!isRecord19(value))
38013
38231
  return String(value).slice(0, MAX_STRING_LENGTH);
38014
38232
  return Object.fromEntries(Object.entries(value).slice(0, 128).map(([key, entry]) => [
38015
38233
  key,
@@ -38017,7 +38235,7 @@ var redactValue = (value, depth = 0) => {
38017
38235
  ]));
38018
38236
  };
38019
38237
  var parseReport = (value) => {
38020
- if (!isRecord18(value) || !isRecord18(value.details))
38238
+ if (!isRecord19(value) || !isRecord19(value.details))
38021
38239
  return;
38022
38240
  if (typeof value.id !== "string" || !REPORT_ID.test(value.id))
38023
38241
  return;
@@ -38028,7 +38246,7 @@ var parseReport = (value) => {
38028
38246
  if (value.platform !== "android" && value.platform !== "ios")
38029
38247
  return;
38030
38248
  const details = redactValue(value.details);
38031
- if (!isRecord18(details))
38249
+ if (!isRecord19(details))
38032
38250
  return;
38033
38251
  if (new TextEncoder().encode(JSON.stringify(details)).byteLength > MAX_DETAIL_BYTES)
38034
38252
  return;
@@ -40840,13 +41058,13 @@ var createBeacon = (options) => {
40840
41058
  }
40841
41059
  };
40842
41060
  const documentStylesAreReady = () => {
40843
- const stylesheets = Array.from(document.querySelectorAll('link[rel~="stylesheet"]')).filter((link) => {
40844
- if (link.disabled)
41061
+ const stylesheets = Array.from(document.querySelectorAll('link[rel~="stylesheet"]')).filter((link2) => {
41062
+ if (link2.disabled)
40845
41063
  return false;
40846
- const media = link.media.trim();
41064
+ const media = link2.media.trim();
40847
41065
  return media === "" || typeof window.matchMedia !== "function" || window.matchMedia(media).matches;
40848
41066
  });
40849
- if (!stylesheets.every((link) => link.sheet !== null))
41067
+ if (!stylesheets.every((link2) => link2.sheet !== null))
40850
41068
  return false;
40851
41069
  if (stylesheets.length === 0)
40852
41070
  return true;
@@ -42482,8 +42700,8 @@ var createBeacon = (options) => {
42482
42700
  if (await fontAvailable(element))
42483
42701
  return;
42484
42702
  if (confirmationMs > 0) {
42485
- await new Promise((resolve23) => {
42486
- const timer2 = window.setTimeout(resolve23, confirmationMs);
42703
+ await new Promise((resolve24) => {
42704
+ const timer2 = window.setTimeout(resolve24, confirmationMs);
42487
42705
  cleanups.push(() => window.clearTimeout(timer2));
42488
42706
  });
42489
42707
  if (document.visibilityState === "hidden")
@@ -42976,8 +43194,8 @@ var sheetById = (id) => {
42976
43194
  const target = document.getElementById(id);
42977
43195
  return target instanceof HTMLDialogElement && target.dataset.absoluteSheet !== undefined ? target : undefined;
42978
43196
  };
42979
- var dispatchSheet = (sheet, open) => dispatchEvent(new CustomEvent(SHEET_EVENT, {
42980
- detail: { id: sheet.id, open }
43197
+ var dispatchSheet = (sheet, open2) => dispatchEvent(new CustomEvent(SHEET_EVENT, {
43198
+ detail: { id: sheet.id, open: open2 }
42981
43199
  }));
42982
43200
  var focusSheet = (sheet) => {
42983
43201
  const target = sheet.querySelector('[autofocus], button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
@@ -43471,51 +43689,51 @@ var createAbsoluteMobileUpdateClient = (options) => {
43471
43689
  };
43472
43690
  };
43473
43691
  // src/mobile/updatePublisher.ts
43474
- import { access as access21 } from "fs/promises";
43475
- import { isAbsolute as isAbsolute13, relative as relative22, resolve as resolve24, sep as sep15 } from "path";
43692
+ import { access as access22 } from "fs/promises";
43693
+ import { isAbsolute as isAbsolute14, relative as relative23, resolve as resolve25, sep as sep16 } from "path";
43476
43694
  import { pathToFileURL as pathToFileURL4 } from "url";
43477
43695
 
43478
43696
  // src/mobile/updateSigning.ts
43479
43697
  import { createHash as createHash17, sign, verify } from "crypto";
43480
43698
  import {
43481
43699
  cp as cp2,
43482
- mkdir as mkdir23,
43700
+ mkdir as mkdir24,
43483
43701
  mkdtemp as mkdtemp12,
43484
- readdir as readdir11,
43485
- readFile as readFile29,
43486
- rename as rename20,
43487
- rm as rm17,
43702
+ readdir as readdir12,
43703
+ readFile as readFile30,
43704
+ rename as rename21,
43705
+ rm as rm18,
43488
43706
  stat as stat8,
43489
43707
  writeFile as writeFile25
43490
43708
  } from "fs/promises";
43491
- import { dirname as dirname23, join as join32, relative as relative21, resolve as resolve23 } from "path";
43709
+ import { dirname as dirname24, join as join33, relative as relative22, resolve as resolve24 } from "path";
43492
43710
  var UPDATE_MANIFEST_FILE = "update.json";
43493
43711
  var UPDATE_FILES_DIRECTORY = "files";
43494
43712
  var sha2565 = (value) => createHash17("sha256").update(value).digest("hex");
43495
43713
  var listFiles = async (root, directory = root) => {
43496
- const entries = await readdir11(directory, { withFileTypes: true });
43714
+ const entries = await readdir12(directory, { withFileTypes: true });
43497
43715
  const paths = await Promise.all(entries.map(async (entry) => {
43498
- const path = join32(directory, entry.name);
43716
+ const path = join33(directory, entry.name);
43499
43717
  if (entry.isDirectory())
43500
43718
  return listFiles(root, path);
43501
43719
  if (!entry.isFile())
43502
43720
  throw new TypeError("Mobile updates cannot contain links or special files.");
43503
- return [relative21(root, path).replaceAll("\\", "/")];
43721
+ return [relative22(root, path).replaceAll("\\", "/")];
43504
43722
  }));
43505
43723
  return paths.flat().sort((left, right) => left.localeCompare(right));
43506
43724
  };
43507
43725
  var inspectFiles = async (root, paths) => Promise.all(paths.map(async (path) => {
43508
- const source = join32(root, path);
43726
+ const source = join33(root, path);
43509
43727
  const [metadata, contents] = await Promise.all([
43510
43728
  stat8(source),
43511
- readFile29(source)
43729
+ readFile30(source)
43512
43730
  ]);
43513
43731
  return { bytes: metadata.size, path, sha256: sha2565(contents) };
43514
43732
  }));
43515
43733
  var releaseIdFor = (value) => `amu_${sha2565(canonicalizeAbsoluteMobileUpdate(value))}`;
43516
43734
  var buildAbsoluteMobileUpdate = async (options) => {
43517
- const bundleDirectory = resolve23(options.bundleDirectory);
43518
- const outputRoot = resolve23(options.outputDirectory);
43735
+ const bundleDirectory = resolve24(options.bundleDirectory);
43736
+ const outputRoot = resolve24(options.outputDirectory);
43519
43737
  if (outputRoot === bundleDirectory || outputRoot.startsWith(`${bundleDirectory}/`))
43520
43738
  throw new TypeError("Mobile update output must be outside the embedded bundle.");
43521
43739
  const paths = await listFiles(bundleDirectory);
@@ -43543,38 +43761,38 @@ var buildAbsoluteMobileUpdate = async (options) => {
43543
43761
  value: signature.toString("base64")
43544
43762
  }
43545
43763
  });
43546
- await mkdir23(outputRoot, { recursive: true });
43547
- const outputDirectory = join32(outputRoot, manifest.releaseId);
43548
- const staging = await mkdtemp12(join32(outputRoot, ".stage-"));
43764
+ await mkdir24(outputRoot, { recursive: true });
43765
+ const outputDirectory = join33(outputRoot, manifest.releaseId);
43766
+ const staging = await mkdtemp12(join33(outputRoot, ".stage-"));
43549
43767
  try {
43550
- await cp2(bundleDirectory, join32(staging, UPDATE_FILES_DIRECTORY), {
43768
+ await cp2(bundleDirectory, join33(staging, UPDATE_FILES_DIRECTORY), {
43551
43769
  force: true,
43552
43770
  recursive: true
43553
43771
  });
43554
- await writeFile25(join32(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
43772
+ await writeFile25(join33(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
43555
43773
  `);
43556
- await rename20(staging, outputDirectory);
43774
+ await rename21(staging, outputDirectory);
43557
43775
  } catch (error) {
43558
- await rm17(staging, { force: true, recursive: true });
43776
+ await rm18(staging, { force: true, recursive: true });
43559
43777
  if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "EEXIST")
43560
43778
  throw new TypeError(`Mobile update ${manifest.releaseId} already exists.`, { cause: error });
43561
43779
  throw error;
43562
43780
  }
43563
43781
  return {
43564
43782
  manifest,
43565
- manifestPath: join32(outputDirectory, UPDATE_MANIFEST_FILE),
43783
+ manifestPath: join33(outputDirectory, UPDATE_MANIFEST_FILE),
43566
43784
  outputDirectory
43567
43785
  };
43568
43786
  };
43569
43787
  var copyAbsoluteMobileUpdateFile = async (updateDirectory, path, destination) => {
43570
- const source = resolve23(updateDirectory, UPDATE_FILES_DIRECTORY, path);
43571
- const root = resolve23(updateDirectory, UPDATE_FILES_DIRECTORY);
43788
+ const source = resolve24(updateDirectory, UPDATE_FILES_DIRECTORY, path);
43789
+ const root = resolve24(updateDirectory, UPDATE_FILES_DIRECTORY);
43572
43790
  if (!source.startsWith(`${root}/`))
43573
43791
  throw new TypeError("Update file escaped its release.");
43574
- await mkdir23(dirname23(destination), { recursive: true });
43792
+ await mkdir24(dirname24(destination), { recursive: true });
43575
43793
  await cp2(source, destination, { force: true });
43576
43794
  };
43577
- var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile29(join32(resolve23(directory), UPDATE_MANIFEST_FILE), "utf8")));
43795
+ var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile30(join33(resolve24(directory), UPDATE_MANIFEST_FILE), "utf8")));
43578
43796
  var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
43579
43797
  const manifest = parseAbsoluteMobileUpdateManifest(manifestValue);
43580
43798
  const valid = verify("sha256", absoluteMobileUpdateSigningPayload(unsignedAbsoluteMobileUpdate(manifest)), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64"));
@@ -43691,16 +43909,16 @@ var pruneAbsoluteMobileUpdates = async (options) => {
43691
43909
  var object5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
43692
43910
  var isPublisher2 = (value) => object5(value) && typeof value.publishUpdate === "function" && typeof value.promoteUpdate === "function" && typeof value.rollbackUpdate === "function";
43693
43911
  var projectPath3 = (projectRoot, requested, label) => {
43694
- const root = resolve24(projectRoot);
43695
- const path = resolve24(root, requested);
43696
- const projectRelative = relative22(root, path);
43697
- if (projectRelative === ".." || projectRelative.startsWith(`..${sep15}`) || isAbsolute13(projectRelative))
43912
+ const root = resolve25(projectRoot);
43913
+ const path = resolve25(root, requested);
43914
+ const projectRelative = relative23(root, path);
43915
+ if (projectRelative === ".." || projectRelative.startsWith(`..${sep16}`) || isAbsolute14(projectRelative))
43698
43916
  throw new TypeError(`${label} must remain inside the project.`);
43699
43917
  return path;
43700
43918
  };
43701
43919
  var loadAbsoluteMobileUpdatePublisher = async (projectRoot, requestedModulePath) => {
43702
43920
  const modulePath = projectPath3(projectRoot, requestedModulePath, "mobile update registry");
43703
- await access21(modulePath).catch(() => {
43921
+ await access22(modulePath).catch(() => {
43704
43922
  throw new TypeError(`Mobile update registry does not exist: ${modulePath}`);
43705
43923
  });
43706
43924
  const loaded = await import(pathToFileURL4(modulePath).href);
@@ -43809,6 +44027,7 @@ export {
43809
44027
  ABSOLUTE_MOBILE_CERTIFICATION_VERIFICATION_FORMAT,
43810
44028
  ABSOLUTE_MOBILE_CI_PROMOTION_AUDIT_FORMAT,
43811
44029
  ABSOLUTE_MOBILE_CI_PROMOTION_CONTEXT_FORMAT,
44030
+ ABSOLUTE_MOBILE_CI_PROMOTION_OPERATION_FORMAT,
43812
44031
  ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT,
43813
44032
  ABSOLUTE_MOBILE_CLIENT_MANIFEST_FORMAT,
43814
44033
  ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT,
@@ -43852,6 +44071,7 @@ export {
43852
44071
  absoluteExpoNativeObservabilityPaths,
43853
44072
  absoluteIosDeviceAcceptanceCommands,
43854
44073
  absoluteMobilePreviewDocument,
44074
+ absoluteMobilePromotionOperationPath,
43855
44075
  absoluteMobileUpdateSigningPayload,
43856
44076
  absolutePercentile,
43857
44077
  absolutePssMiB,
@@ -43863,6 +44083,7 @@ export {
43863
44083
  acceptsAbsoluteRouteData,
43864
44084
  acquireAbsoluteRemoteMacReleaseLease,
43865
44085
  activateAbsoluteMobilePage,
44086
+ advanceAbsoluteMobilePromotionOperation,
43866
44087
  advanceAbsoluteMobileUpdateRollout,
43867
44088
  applyAbsoluteNativeDeepLinks,
43868
44089
  applyAbsoluteNativeDeviceCapabilities,
@@ -43904,6 +44125,7 @@ export {
43904
44125
  createAbsoluteMobilePageErrorResponse,
43905
44126
  createAbsoluteMobilePageRequest,
43906
44127
  createAbsoluteMobilePreviewPlugin,
44128
+ createAbsoluteMobilePromotionOperation,
43907
44129
  createAbsoluteMobileReleaseCertification,
43908
44130
  createAbsoluteMobileRouteMetadataPlugin,
43909
44131
  createAbsoluteMobileUpdateClient,
@@ -43959,6 +44181,7 @@ export {
43959
44181
  isAbsoluteExpoNativeRootInput,
43960
44182
  isAbsoluteIosNativeRootInput,
43961
44183
  isAbsoluteMobileUpdateRolloutMember,
44184
+ listAbsoluteMobilePromotionOperations,
43962
44185
  listAbsoluteRemoteMacProfiles,
43963
44186
  loadAbsoluteDeviceCapabilityProviders,
43964
44187
  loadAbsoluteMobileMaterializedBundle,
@@ -43995,6 +44218,7 @@ export {
43995
44218
  parseAbsoluteMobilePageEnvelope,
43996
44219
  parseAbsoluteMobilePageRequest,
43997
44220
  parseAbsoluteMobilePromotionContext,
44221
+ parseAbsoluteMobilePromotionOperation,
43998
44222
  parseAbsoluteMobilePromotionRunList,
43999
44223
  parseAbsoluteMobileUnsignedUpdateManifest,
44000
44224
  parseAbsoluteMobileUpdateManifest,
@@ -44021,11 +44245,13 @@ export {
44021
44245
  readAbsoluteMobileCertificationVerification,
44022
44246
  readAbsoluteMobileLinkIntent,
44023
44247
  readAbsoluteMobileMaterializedReleases,
44248
+ readAbsoluteMobilePromotionOperation,
44024
44249
  readAbsoluteMobileReleaseCertification,
44025
44250
  readAbsoluteMobileUpdate,
44026
44251
  readAbsoluteSigstoreBundle,
44027
44252
  reconcileAbsoluteMobileUpdateRollout,
44028
44253
  redactAbsoluteIosLog,
44254
+ relativeAbsoluteMobilePromotionOperationPath,
44029
44255
  removeAbsoluteRemoteMacProfile,
44030
44256
  renderAbsoluteMobileReleaseCertification,
44031
44257
  renderAbsoluteMobileUpdateRegistry,
@@ -44081,5 +44307,5 @@ export {
44081
44307
  writeAbsoluteMobileUpdateRegistry
44082
44308
  };
44083
44309
 
44084
- //# debugId=199363435B745D2564756E2164756E21
44310
+ //# debugId=8439B99573B3AFB964756E2164756E21
44085
44311
  //# sourceMappingURL=index.js.map