@absolutejs/absolute 0.20.0-beta.106 → 0.20.0-beta.108
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +6 -0
- package/changelog.json +37 -0
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/build.js +645 -622
- package/dist/build.js.map +7 -6
- package/dist/cli/index.js +1 -1
- package/dist/cli/{mobile-w4my2dc7.js → mobile-7v8hfmdq.js} +673 -161
- package/dist/index.js +603 -580
- package/dist/index.js.map +7 -6
- package/dist/mobile/index.js +504 -95
- package/dist/mobile/index.js.map +5 -4
- package/dist/src/build/injectVueComposableTracking.d.ts +2 -28
- package/dist/src/build/vueModuleOutputPath.d.ts +7 -0
- package/dist/src/mobile/index.d.ts +1 -0
- package/dist/src/mobile/releaseCertification.d.ts +59 -0
- package/package.json +1 -1
package/dist/mobile/index.js
CHANGED
|
@@ -20032,7 +20032,7 @@ __export(exports_mobileUpdate, {
|
|
|
20032
20032
|
parseMobileUpdateManifest: () => parseMobileUpdateManifest
|
|
20033
20033
|
});
|
|
20034
20034
|
import {
|
|
20035
|
-
createHash as
|
|
20035
|
+
createHash as createHash19,
|
|
20036
20036
|
createHmac,
|
|
20037
20037
|
createPrivateKey,
|
|
20038
20038
|
createPublicKey as createPublicKey2,
|
|
@@ -20042,7 +20042,7 @@ import {
|
|
|
20042
20042
|
verify as verify2,
|
|
20043
20043
|
X509Certificate as X509Certificate3
|
|
20044
20044
|
} from "crypto";
|
|
20045
|
-
import { readFile as
|
|
20045
|
+
import { readFile as readFile28, stat as stat7 } from "fs/promises";
|
|
20046
20046
|
import path from "path";
|
|
20047
20047
|
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) => {
|
|
20048
20048
|
if (typeof value !== "string" || value.length === 0)
|
|
@@ -20192,7 +20192,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
|
|
|
20192
20192
|
if (!prefix || prefix.split("/").some((segment) => segment === "." || segment === ".."))
|
|
20193
20193
|
throw new MobileUpdateRegistryError("Mobile update prefix is invalid");
|
|
20194
20194
|
return prefix;
|
|
20195
|
-
}, appHash = (appId) =>
|
|
20195
|
+
}, appHash = (appId) => createHash19("sha256").update(appId).digest("hex"), digest = (bytes) => createHash19("sha256").update(bytes).digest("hex"), json = (value) => new TextEncoder().encode(`${JSON.stringify(value, null, 2)}
|
|
20196
20196
|
`), decode2 = (value) => JSON.parse(new TextDecoder().decode(value)), fileDigest = async (file) => {
|
|
20197
20197
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
20198
20198
|
for await (const chunk of file.stream())
|
|
@@ -20203,7 +20203,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
|
|
|
20203
20203
|
return false;
|
|
20204
20204
|
if (input.rollout === 1)
|
|
20205
20205
|
return true;
|
|
20206
|
-
const value =
|
|
20206
|
+
const value = createHash19("sha256").update(`${input.appId}\x00${input.channel}\x00${input.releaseId}\x00${input.installationId}`).digest().readUInt32BE(0);
|
|
20207
20207
|
return value / 4294967296 < input.rollout;
|
|
20208
20208
|
}, base64Url = (value) => Buffer.from(value).toString("base64url"), healthPromotionId = (channel) => channel.promotionId ?? digest(new TextEncoder().encode(`${channel.appId}\x00${channel.channel}\x00${channel.releaseId ?? "embedded"}\x00${channel.promotedAt}`)), finiteMetric = (value, field2) => {
|
|
20209
20209
|
if (typeof value !== "number" || !Number.isFinite(value) || value < 0)
|
|
@@ -20243,7 +20243,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
|
|
|
20243
20243
|
const releaseRoot = (manifest) => `${root(manifest.appId)}/releases/${manifest.releaseId}`;
|
|
20244
20244
|
const manifestKey = (manifest) => `${releaseRoot(manifest)}/update.json`;
|
|
20245
20245
|
const fileKey = (manifest, file) => `${releaseRoot(manifest)}/files/${file.path}`;
|
|
20246
|
-
const contentBlobKey = (appId,
|
|
20246
|
+
const contentBlobKey = (appId, sha2566) => `${root(appId)}/blobs/${sha2566}`;
|
|
20247
20247
|
const tombstoneKey = (appId, releaseId) => `${root(appId)}/gc/${releaseId}.json`;
|
|
20248
20248
|
const healthRoot = (appId, promotionId, releaseId) => `${root(appId)}/health/${promotionId}/${releaseId}`;
|
|
20249
20249
|
const pauseKey = (appId, promotionId, releaseId) => `${healthRoot(appId, promotionId, releaseId)}/paused.json`;
|
|
@@ -20864,10 +20864,10 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
|
|
|
20864
20864
|
const objectBytesByDigest = new Map;
|
|
20865
20865
|
for (const blobObject of objects) {
|
|
20866
20866
|
if (blobObject.key.startsWith(blobPrefix)) {
|
|
20867
|
-
const
|
|
20868
|
-
if (HASH.test(
|
|
20869
|
-
objectKeysByDigest.set(
|
|
20870
|
-
objectBytesByDigest.set(
|
|
20867
|
+
const sha2566 = blobObject.key.slice(blobPrefix.length);
|
|
20868
|
+
if (HASH.test(sha2566)) {
|
|
20869
|
+
objectKeysByDigest.set(sha2566, blobObject.key);
|
|
20870
|
+
objectBytesByDigest.set(sha2566, blobObject.size);
|
|
20871
20871
|
}
|
|
20872
20872
|
}
|
|
20873
20873
|
if (!blobObject.key.startsWith(releasePrefix))
|
|
@@ -20950,7 +20950,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
|
|
|
20950
20950
|
}).toSorted((left, right) => right.createdAt.localeCompare(left.createdAt));
|
|
20951
20951
|
const protectedReleaseIds = new Set(releases.filter((release) => release.protectedBy.length > 0).map((release) => release.releaseId));
|
|
20952
20952
|
const protectedDigests = new Set(manifests.filter((manifest) => protectedReleaseIds.has(manifest.releaseId)).flatMap((manifest) => manifest.files.map((file) => file.sha256)));
|
|
20953
|
-
const reclaimableContentBytes = [...objectBytesByDigest].filter(([
|
|
20953
|
+
const reclaimableContentBytes = [...objectBytesByDigest].filter(([sha2566]) => !protectedDigests.has(sha2566)).reduce((total, [, bytes]) => total + bytes, 0);
|
|
20954
20954
|
const contentBlobBytes = [...objectBytesByDigest.values()].reduce((total, bytes) => total + bytes, 0);
|
|
20955
20955
|
const releaseBytes = releases.reduce((total, release) => total + release.bytes, 0);
|
|
20956
20956
|
const totalBytes = objects.reduce((total, object22) => total + object22.size, 0);
|
|
@@ -21047,13 +21047,13 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
|
|
|
21047
21047
|
for (const file of manifest?.manifest.files ?? [])
|
|
21048
21048
|
referencedDigests.add(file.sha256);
|
|
21049
21049
|
}
|
|
21050
|
-
for (const [
|
|
21051
|
-
if (referencedDigests.has(
|
|
21050
|
+
for (const [sha2566, key] of afterReleaseSweep.objectKeysByDigest) {
|
|
21051
|
+
if (referencedDigests.has(sha2566))
|
|
21052
21052
|
continue;
|
|
21053
21053
|
const head = await options.store.head(key);
|
|
21054
21054
|
await remove(key);
|
|
21055
21055
|
result.reclaimedBytes += head?.size ?? 0;
|
|
21056
|
-
result.sweptContentBlobs.push(
|
|
21056
|
+
result.sweptContentBlobs.push(sha2566);
|
|
21057
21057
|
}
|
|
21058
21058
|
return result;
|
|
21059
21059
|
};
|
|
@@ -21075,7 +21075,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
|
|
|
21075
21075
|
verifyManifestSignature(manifest, options.publicKeys);
|
|
21076
21076
|
await assertNotMarked(manifest.appId, manifest.releaseId);
|
|
21077
21077
|
const localRoot = path.resolve(input.releaseDirectory);
|
|
21078
|
-
const localManifest = parseMobileUpdateManifest(JSON.parse(await
|
|
21078
|
+
const localManifest = parseMobileUpdateManifest(JSON.parse(await readFile28(path.join(localRoot, "update.json"), "utf8")));
|
|
21079
21079
|
if (JSON.stringify(localManifest) !== JSON.stringify(manifest))
|
|
21080
21080
|
throw new MobileUpdateRegistryError("Local mobile update manifest changed");
|
|
21081
21081
|
const existing = await readManifest(manifest.appId, manifest.releaseId);
|
|
@@ -21208,7 +21208,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
|
|
|
21208
21208
|
}
|
|
21209
21209
|
};
|
|
21210
21210
|
}, expoUpdateId = (releaseId) => {
|
|
21211
|
-
const hash = RELEASE.test(releaseId) ? releaseId.slice("amu_".length, "amu_".length + 32) :
|
|
21211
|
+
const hash = RELEASE.test(releaseId) ? releaseId.slice("amu_".length, "amu_".length + 32) : createHash19("sha256").update(releaseId).digest("hex").slice(0, 32);
|
|
21212
21212
|
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-${hash.slice(12, 16)}-${hash.slice(16, 20)}-${hash.slice(20)}`;
|
|
21213
21213
|
}, expoContentType = (extension2, launch2) => {
|
|
21214
21214
|
if (launch2)
|
|
@@ -21361,8 +21361,8 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
|
|
|
21361
21361
|
});
|
|
21362
21362
|
}
|
|
21363
21363
|
const pathname = new URL(request.url).pathname.replace(/^\/+/, "");
|
|
21364
|
-
const
|
|
21365
|
-
if (request.method === "POST" &&
|
|
21364
|
+
const relative21 = pathname.startsWith(`${route}/`) ? pathname.slice(route.length + 1) : "";
|
|
21365
|
+
if (request.method === "POST" && relative21 === "health") {
|
|
21366
21366
|
if (!options.registry.recordUpdateHealth)
|
|
21367
21367
|
return new Response(null, { status: 404 });
|
|
21368
21368
|
const appId = request.headers.get("x-absolute-mobile-app");
|
|
@@ -21405,7 +21405,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
|
|
|
21405
21405
|
}
|
|
21406
21406
|
if (request.method !== "GET")
|
|
21407
21407
|
return new Response(null, { status: 405 });
|
|
21408
|
-
if (
|
|
21408
|
+
if (relative21 === "update.json") {
|
|
21409
21409
|
const expoProtocolVersion = request.headers.get("expo-protocol-version");
|
|
21410
21410
|
const expoProtocol = expoProtocolVersion !== null;
|
|
21411
21411
|
if (expoProtocol && expoProtocolVersion !== "1")
|
|
@@ -21523,7 +21523,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
|
|
|
21523
21523
|
}
|
|
21524
21524
|
});
|
|
21525
21525
|
}
|
|
21526
|
-
const match = /^(amu_[a-f0-9]{64})\/files\/(.+)$/.exec(
|
|
21526
|
+
const match = /^(amu_[a-f0-9]{64})\/files\/(.+)$/.exec(relative21);
|
|
21527
21527
|
if (!match?.[1] || !match[2])
|
|
21528
21528
|
return new Response(null, { status: 404 });
|
|
21529
21529
|
const file = await options.registry.readUpdateFile({
|
|
@@ -21616,15 +21616,15 @@ import {
|
|
|
21616
21616
|
createPublicKey as createPublicKey3,
|
|
21617
21617
|
X509Certificate as X509Certificate4
|
|
21618
21618
|
} from "crypto";
|
|
21619
|
-
import { access as
|
|
21620
|
-
import { dirname as dirname22, isAbsolute as
|
|
21619
|
+
import { access as access20, mkdir as mkdir22 } from "fs/promises";
|
|
21620
|
+
import { dirname as dirname22, isAbsolute as isAbsolute12, relative as relative21, resolve as resolve23, sep as sep14 } from "path";
|
|
21621
21621
|
import { pathToFileURL as pathToFileURL5 } from "url";
|
|
21622
21622
|
import { Elysia as Elysia4 } from "elysia";
|
|
21623
21623
|
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), projectPath3 = (projectRoot, requested) => {
|
|
21624
|
-
const root =
|
|
21625
|
-
const path2 =
|
|
21626
|
-
const projectRelative =
|
|
21627
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
21624
|
+
const root = resolve23(projectRoot);
|
|
21625
|
+
const path2 = resolve23(root, requested);
|
|
21626
|
+
const projectRelative = relative21(root, path2);
|
|
21627
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep14}`) || isAbsolute12(projectRelative))
|
|
21628
21628
|
throw new TypeError("mobile.updates.server.registry must remain inside the project.");
|
|
21629
21629
|
return path2;
|
|
21630
21630
|
}, isRegistry4 = (value) => object7(value) && [
|
|
@@ -21647,7 +21647,7 @@ var ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT = 1, DEFAULT_MOBILE_UPDATE_REGISTRY_MOD
|
|
|
21647
21647
|
return metadata;
|
|
21648
21648
|
}, loadAbsoluteMobileUpdateServerModule = async (projectRoot, requestedModulePath = DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE) => {
|
|
21649
21649
|
const modulePath = projectPath3(projectRoot, requestedModulePath);
|
|
21650
|
-
await
|
|
21650
|
+
await access20(modulePath).catch(() => {
|
|
21651
21651
|
throw new TypeError(`Mobile update server registry does not exist: ${modulePath}. Run \`absolute mobile update provision\`.`);
|
|
21652
21652
|
});
|
|
21653
21653
|
const loaded = await import(pathToFileURL5(modulePath).href);
|
|
@@ -21836,13 +21836,13 @@ ${generated}`);
|
|
|
21836
21836
|
}, writeAbsoluteMobileUpdateRegistry = async (options) => {
|
|
21837
21837
|
const path2 = projectPath3(options.projectRoot, options.modulePath ?? DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE);
|
|
21838
21838
|
if (!options.force) {
|
|
21839
|
-
await
|
|
21839
|
+
await access20(path2).then(() => {
|
|
21840
21840
|
throw new TypeError(`Mobile update registry already exists: ${path2}. Pass --force to replace it.`);
|
|
21841
21841
|
}, () => {
|
|
21842
21842
|
return;
|
|
21843
21843
|
});
|
|
21844
21844
|
}
|
|
21845
|
-
await
|
|
21845
|
+
await mkdir22(dirname22(path2), { recursive: true });
|
|
21846
21846
|
await Bun.write(path2, renderAbsoluteMobileUpdateRegistry({
|
|
21847
21847
|
...options.health ? { health: options.health } : {},
|
|
21848
21848
|
...options.rollout ? { rollout: options.rollout } : {},
|
|
@@ -35247,9 +35247,412 @@ init_pageProtocol();
|
|
|
35247
35247
|
init_producerContext();
|
|
35248
35248
|
init_releaseArtifact();
|
|
35249
35249
|
|
|
35250
|
+
// src/mobile/releaseCertification.ts
|
|
35251
|
+
import { createHash as createHash16 } from "crypto";
|
|
35252
|
+
import {
|
|
35253
|
+
access as access17,
|
|
35254
|
+
mkdir as mkdir20,
|
|
35255
|
+
mkdtemp as mkdtemp10,
|
|
35256
|
+
readFile as readFile26,
|
|
35257
|
+
rename as rename18,
|
|
35258
|
+
rm as rm15,
|
|
35259
|
+
writeFile as writeFile22
|
|
35260
|
+
} from "fs/promises";
|
|
35261
|
+
import { basename as basename8, isAbsolute as isAbsolute9, join as join30, relative as relative16, resolve as resolve18, sep as sep11 } from "path";
|
|
35262
|
+
var ABSOLUTE_MOBILE_RELEASE_CERTIFICATION_FORMAT = 1;
|
|
35263
|
+
var CERTIFICATION_PREFIX = "amobile_cert_";
|
|
35264
|
+
var SHA256 = /^[a-f0-9]{64}$/u;
|
|
35265
|
+
var STRENGTH_RANK = {
|
|
35266
|
+
device: 1,
|
|
35267
|
+
installed: 0,
|
|
35268
|
+
simulator: 0,
|
|
35269
|
+
store: 2
|
|
35270
|
+
};
|
|
35271
|
+
var isRequirement = (value) => value === "installed" || value === "simulator" || value === "device" || value === "store";
|
|
35272
|
+
var isStrength = (value) => value === "installed" || value === "simulator" || value === "device" || value === "store";
|
|
35273
|
+
var isArtifactExactness = (value) => value === "archive-equivalent" || value === "source-equivalent" || value === "store-delivered";
|
|
35274
|
+
var isDistribution = (value) => value === "apple-processed" || value === "registered-device" || value === "simulator-release";
|
|
35275
|
+
var isRecord14 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
35276
|
+
var inside4 = (root, candidate) => {
|
|
35277
|
+
const path = relative16(resolve18(root), resolve18(candidate));
|
|
35278
|
+
return path === "" || !isAbsolute9(path) && path !== ".." && !path.startsWith(`..${sep11}`);
|
|
35279
|
+
};
|
|
35280
|
+
var exists9 = async (path) => {
|
|
35281
|
+
try {
|
|
35282
|
+
await access17(path);
|
|
35283
|
+
return true;
|
|
35284
|
+
} catch {
|
|
35285
|
+
return false;
|
|
35286
|
+
}
|
|
35287
|
+
};
|
|
35288
|
+
var sha2564 = (bytes) => createHash16("sha256").update(bytes).digest("hex");
|
|
35289
|
+
var requireString2 = (value, name) => {
|
|
35290
|
+
if (typeof value !== "string" || !value)
|
|
35291
|
+
throw new TypeError(`Mobile certification ${name} is invalid.`);
|
|
35292
|
+
return value;
|
|
35293
|
+
};
|
|
35294
|
+
var requirePositiveInteger = (value, name) => {
|
|
35295
|
+
if (!Number.isSafeInteger(value) || Number(value) < 1)
|
|
35296
|
+
throw new TypeError(`Mobile certification ${name} is invalid.`);
|
|
35297
|
+
return Number(value);
|
|
35298
|
+
};
|
|
35299
|
+
var resolveEvidencePath = async (projectRoot, requested) => {
|
|
35300
|
+
const selected = resolve18(projectRoot, requested);
|
|
35301
|
+
if (!inside4(projectRoot, selected))
|
|
35302
|
+
throw new TypeError("Mobile certification evidence must remain inside the project.");
|
|
35303
|
+
if (basename8(selected) === "report.json")
|
|
35304
|
+
return selected;
|
|
35305
|
+
const report = join30(selected, "report.json");
|
|
35306
|
+
if (!await exists9(report))
|
|
35307
|
+
throw new TypeError(`Mobile certification evidence does not contain report.json: ${requested}`);
|
|
35308
|
+
return report;
|
|
35309
|
+
};
|
|
35310
|
+
var releaseIdentity = (release) => {
|
|
35311
|
+
const { metadata } = release;
|
|
35312
|
+
if (!metadata.signed)
|
|
35313
|
+
throw new TypeError("Mobile release certification requires a signed native release.");
|
|
35314
|
+
const common = {
|
|
35315
|
+
appBuild: metadata.appBuild,
|
|
35316
|
+
appId: metadata.appId,
|
|
35317
|
+
artifactBytes: metadata.bytes,
|
|
35318
|
+
artifactSha256: metadata.sha256,
|
|
35319
|
+
engine: metadata.engine,
|
|
35320
|
+
platform: metadata.platform,
|
|
35321
|
+
releaseId: metadata.releaseId,
|
|
35322
|
+
runtime: metadata.runtime,
|
|
35323
|
+
signed: true
|
|
35324
|
+
};
|
|
35325
|
+
if (metadata.platform === "android")
|
|
35326
|
+
return {
|
|
35327
|
+
...common,
|
|
35328
|
+
...metadata.versionCode === undefined ? {} : { versionCode: metadata.versionCode }
|
|
35329
|
+
};
|
|
35330
|
+
return {
|
|
35331
|
+
...common,
|
|
35332
|
+
...metadata.buildNumber === undefined ? {} : { buildNumber: metadata.buildNumber },
|
|
35333
|
+
marketingVersion: metadata.marketingVersion
|
|
35334
|
+
};
|
|
35335
|
+
};
|
|
35336
|
+
var requireCheck = (report, id, accepted = ["PASS"]) => {
|
|
35337
|
+
const checks = report.automatedChecks;
|
|
35338
|
+
if (!Array.isArray(checks))
|
|
35339
|
+
throw new TypeError("Mobile certification evidence has invalid automated checks.");
|
|
35340
|
+
const check = checks.find((candidate) => isRecord14(candidate) && candidate.id === id);
|
|
35341
|
+
if (!isRecord14(check) || !accepted.includes(String(check.result)))
|
|
35342
|
+
throw new TypeError(`Mobile certification evidence does not satisfy ${id}.`);
|
|
35343
|
+
};
|
|
35344
|
+
var validateCommonReport = (report, release) => {
|
|
35345
|
+
if (report.reportVersion !== 1 || report.platform !== release.platform || !isRecord14(report.metadata) || report.metadata.provider !== release.engine || !isRecord14(report.run) || report.run.status !== "pass" || report.run.appId !== release.appId)
|
|
35346
|
+
throw new TypeError("Mobile certification evidence does not match the release platform, provider, application, or successful-run contract.");
|
|
35347
|
+
requireCheck(report, "AUTO-DEV-01");
|
|
35348
|
+
return {
|
|
35349
|
+
generatedAt: requireString2(report.generatedAt, "evidence generatedAt"),
|
|
35350
|
+
run: report.run
|
|
35351
|
+
};
|
|
35352
|
+
};
|
|
35353
|
+
var validateReleaseFields = (value, release) => {
|
|
35354
|
+
if (value.releaseId !== release.releaseId || value.artifactSha256 !== release.artifactSha256 || value.artifactBytes !== release.artifactBytes || value.engine !== release.engine || value.signed !== true)
|
|
35355
|
+
throw new TypeError("Mobile certification evidence does not match the immutable release identity.");
|
|
35356
|
+
};
|
|
35357
|
+
var validateAndroidEvidence = (report, run, release, reportSha256, generatedAt) => {
|
|
35358
|
+
if (!isRecord14(run.release))
|
|
35359
|
+
throw new TypeError("Android certification evidence has no installed release result.");
|
|
35360
|
+
validateReleaseFields(run.release, release);
|
|
35361
|
+
if (run.release.embeddedOffline !== true)
|
|
35362
|
+
throw new TypeError("Android certification evidence did not prove embedded offline relaunch.");
|
|
35363
|
+
requireCheck(report, "AUTO-RELEASE-01");
|
|
35364
|
+
requireCheck(report, "AUTO-RELEASE-OFFLINE-01");
|
|
35365
|
+
return {
|
|
35366
|
+
generatedAt,
|
|
35367
|
+
networkUnavailable: "proven",
|
|
35368
|
+
remote: false,
|
|
35369
|
+
reportSha256,
|
|
35370
|
+
strength: "installed"
|
|
35371
|
+
};
|
|
35372
|
+
};
|
|
35373
|
+
var validateIosEvidence = (report, run, release, reportSha256, generatedAt) => {
|
|
35374
|
+
if (!isRecord14(run.iosRelease))
|
|
35375
|
+
throw new TypeError("iOS certification evidence has no installed release result.");
|
|
35376
|
+
const ios = run.iosRelease;
|
|
35377
|
+
validateReleaseFields(ios, release);
|
|
35378
|
+
if (ios.embeddedLocal !== true)
|
|
35379
|
+
throw new TypeError("iOS certification evidence did not prove embedded local rendering.");
|
|
35380
|
+
requireCheck(report, "AUTO-IOS-RELEASE-01");
|
|
35381
|
+
let strength;
|
|
35382
|
+
if (ios.distribution === "simulator-release" && ios.artifactExactness === "source-equivalent" && run.targetKind === "simulator" && ios.networkUnavailable === "not-proven")
|
|
35383
|
+
strength = "simulator";
|
|
35384
|
+
else if (ios.distribution === "registered-device" && ios.artifactExactness === "archive-equivalent" && run.targetKind === "device" && ios.networkUnavailable === "user-confirmed")
|
|
35385
|
+
strength = "device";
|
|
35386
|
+
else if (ios.distribution === "apple-processed" && ios.artifactExactness === "store-delivered" && run.targetKind === "device" && ios.networkUnavailable === "user-confirmed")
|
|
35387
|
+
strength = "store";
|
|
35388
|
+
else
|
|
35389
|
+
throw new TypeError("iOS certification evidence contains an invalid target, distribution, exactness, or offline-strength combination.");
|
|
35390
|
+
if (strength === "simulator")
|
|
35391
|
+
requireCheck(report, "AUTO-IOS-RELEASE-OFFLINE-01", ["SKIPPED"]);
|
|
35392
|
+
else
|
|
35393
|
+
requireCheck(report, "AUTO-IOS-RELEASE-OFFLINE-01");
|
|
35394
|
+
return {
|
|
35395
|
+
artifactExactness: ios.artifactExactness,
|
|
35396
|
+
distribution: ios.distribution,
|
|
35397
|
+
generatedAt,
|
|
35398
|
+
networkUnavailable: ios.networkUnavailable === "user-confirmed" ? "proven" : "not-proven",
|
|
35399
|
+
remote: ios.remote === true,
|
|
35400
|
+
reportSha256,
|
|
35401
|
+
strength
|
|
35402
|
+
};
|
|
35403
|
+
};
|
|
35404
|
+
var validateEvidence = async (projectRoot, requested, release) => {
|
|
35405
|
+
const path = await resolveEvidencePath(projectRoot, requested);
|
|
35406
|
+
const bytes = await readFile26(path);
|
|
35407
|
+
let value;
|
|
35408
|
+
try {
|
|
35409
|
+
value = JSON.parse(bytes.toString("utf8"));
|
|
35410
|
+
} catch {
|
|
35411
|
+
throw new TypeError("Mobile certification evidence report is not valid JSON.");
|
|
35412
|
+
}
|
|
35413
|
+
if (!isRecord14(value))
|
|
35414
|
+
throw new TypeError("Mobile certification evidence report must contain an object.");
|
|
35415
|
+
const { generatedAt, run } = validateCommonReport(value, release);
|
|
35416
|
+
const digest = sha2564(bytes);
|
|
35417
|
+
return release.platform === "android" ? validateAndroidEvidence(value, run, release, digest, generatedAt) : validateIosEvidence(value, run, release, digest, generatedAt);
|
|
35418
|
+
};
|
|
35419
|
+
var defaultRequirement = (platform4) => platform4 === "android" ? "installed" : "simulator";
|
|
35420
|
+
var validateRequirement = (platform4, requirement) => {
|
|
35421
|
+
if (platform4 === "android" && requirement !== "installed")
|
|
35422
|
+
throw new TypeError("Android certification currently uses its fixed installed/offline requirement; --require simulator, device, and store are iOS policies.");
|
|
35423
|
+
if (platform4 === "ios" && requirement === "installed")
|
|
35424
|
+
throw new TypeError("iOS certification requires simulator, device, or store evidence.");
|
|
35425
|
+
};
|
|
35426
|
+
var satisfiesRequirement = (strength, requirement) => {
|
|
35427
|
+
if (requirement === "installed")
|
|
35428
|
+
return strength === "installed";
|
|
35429
|
+
if (strength === "installed")
|
|
35430
|
+
return false;
|
|
35431
|
+
return STRENGTH_RANK[strength] >= STRENGTH_RANK[requirement];
|
|
35432
|
+
};
|
|
35433
|
+
var validateCertifiedEvidence = (platform4, evidence) => {
|
|
35434
|
+
if (platform4 === "android") {
|
|
35435
|
+
if (evidence.strength !== "installed" || evidence.networkUnavailable !== "proven" || evidence.artifactExactness !== undefined || evidence.distribution !== undefined || evidence.remote)
|
|
35436
|
+
throw new TypeError("Android release certification contains invalid evidence strength.");
|
|
35437
|
+
return;
|
|
35438
|
+
}
|
|
35439
|
+
const simulator = evidence.strength === "simulator" && evidence.artifactExactness === "source-equivalent" && evidence.distribution === "simulator-release" && evidence.networkUnavailable === "not-proven";
|
|
35440
|
+
const device = evidence.strength === "device" && evidence.artifactExactness === "archive-equivalent" && evidence.distribution === "registered-device" && evidence.networkUnavailable === "proven";
|
|
35441
|
+
const store = evidence.strength === "store" && evidence.artifactExactness === "store-delivered" && evidence.distribution === "apple-processed" && evidence.networkUnavailable === "proven";
|
|
35442
|
+
if (!simulator && !device && !store)
|
|
35443
|
+
throw new TypeError("iOS release certification contains invalid evidence strength.");
|
|
35444
|
+
};
|
|
35445
|
+
var canonicalJsonValue = (value) => {
|
|
35446
|
+
if (Array.isArray(value))
|
|
35447
|
+
return value.map(canonicalJsonValue);
|
|
35448
|
+
if (!isRecord14(value))
|
|
35449
|
+
return value;
|
|
35450
|
+
const sorted = {};
|
|
35451
|
+
for (const key of Object.keys(value).sort())
|
|
35452
|
+
sorted[key] = canonicalJsonValue(value[key]);
|
|
35453
|
+
return sorted;
|
|
35454
|
+
};
|
|
35455
|
+
var certificationBody = (certification) => JSON.stringify(canonicalJsonValue(certification));
|
|
35456
|
+
var createAbsoluteMobileReleaseCertification = async (options) => {
|
|
35457
|
+
if (options.evidencePaths.length === 0)
|
|
35458
|
+
throw new TypeError("Mobile release certification requires at least one --evidence report.");
|
|
35459
|
+
const release = releaseIdentity(options.release);
|
|
35460
|
+
const requirement = options.requirement ?? defaultRequirement(release.platform);
|
|
35461
|
+
validateRequirement(release.platform, requirement);
|
|
35462
|
+
const evidence = await Promise.all(options.evidencePaths.map((path) => validateEvidence(options.projectRoot, path, release)));
|
|
35463
|
+
evidence.sort((left, right) => left.reportSha256.localeCompare(right.reportSha256));
|
|
35464
|
+
const [firstEvidence] = evidence;
|
|
35465
|
+
if (!firstEvidence)
|
|
35466
|
+
throw new TypeError("Mobile release certification requires valid evidence.");
|
|
35467
|
+
const strength = evidence.reduce((strongest, candidate) => STRENGTH_RANK[candidate.strength] > STRENGTH_RANK[strongest] ? candidate.strength : strongest, firstEvidence.strength);
|
|
35468
|
+
if (!satisfiesRequirement(strength, requirement))
|
|
35469
|
+
throw new TypeError(`Mobile release evidence strength ${strength} does not satisfy required ${requirement} certification.`);
|
|
35470
|
+
const body = {
|
|
35471
|
+
evidence,
|
|
35472
|
+
format: ABSOLUTE_MOBILE_RELEASE_CERTIFICATION_FORMAT,
|
|
35473
|
+
generatedAt: options.generatedAt ?? evidence.reduce((latest, candidate) => candidate.generatedAt > latest ? candidate.generatedAt : latest, firstEvidence.generatedAt),
|
|
35474
|
+
release,
|
|
35475
|
+
requirement,
|
|
35476
|
+
status: "certified",
|
|
35477
|
+
strength
|
|
35478
|
+
};
|
|
35479
|
+
return {
|
|
35480
|
+
certificationId: `${CERTIFICATION_PREFIX}${sha2564(certificationBody(body))}`,
|
|
35481
|
+
...body
|
|
35482
|
+
};
|
|
35483
|
+
};
|
|
35484
|
+
var parseCertification = (value) => {
|
|
35485
|
+
if (!isRecord14(value) || value.format !== ABSOLUTE_MOBILE_RELEASE_CERTIFICATION_FORMAT || value.status !== "certified" || !isRecord14(value.release) || !Array.isArray(value.evidence))
|
|
35486
|
+
throw new TypeError("Mobile release certification contract is invalid.");
|
|
35487
|
+
const { release } = value;
|
|
35488
|
+
const { platform: platform4 } = release;
|
|
35489
|
+
const { engine } = release;
|
|
35490
|
+
if (platform4 !== "android" && platform4 !== "ios" || engine !== "capacitor" && engine !== "expo" || release.signed !== true)
|
|
35491
|
+
throw new TypeError("Mobile release certification identity is invalid.");
|
|
35492
|
+
const { requirement } = value;
|
|
35493
|
+
const { strength } = value;
|
|
35494
|
+
if (!isRequirement(requirement) || !isStrength(strength))
|
|
35495
|
+
throw new TypeError("Mobile release certification policy is invalid.");
|
|
35496
|
+
validateRequirement(platform4, requirement);
|
|
35497
|
+
if (!satisfiesRequirement(strength, requirement))
|
|
35498
|
+
throw new TypeError("Mobile release certification does not satisfy its declared policy.");
|
|
35499
|
+
const artifactBytes = requirePositiveInteger(release.artifactBytes, "release artifactBytes");
|
|
35500
|
+
const artifactSha256 = requireString2(release.artifactSha256, "release artifactSha256");
|
|
35501
|
+
if (!SHA256.test(artifactSha256))
|
|
35502
|
+
throw new TypeError("Mobile release certification artifact digest is invalid.");
|
|
35503
|
+
const parsedRelease = {
|
|
35504
|
+
appBuild: requireString2(release.appBuild, "release appBuild"),
|
|
35505
|
+
appId: requireString2(release.appId, "release appId"),
|
|
35506
|
+
artifactBytes,
|
|
35507
|
+
artifactSha256,
|
|
35508
|
+
engine,
|
|
35509
|
+
platform: platform4,
|
|
35510
|
+
releaseId: requireString2(release.releaseId, "release releaseId"),
|
|
35511
|
+
runtime: requireString2(release.runtime, "release runtime"),
|
|
35512
|
+
signed: true,
|
|
35513
|
+
...release.buildNumber === undefined ? {} : {
|
|
35514
|
+
buildNumber: requirePositiveInteger(release.buildNumber, "release buildNumber")
|
|
35515
|
+
},
|
|
35516
|
+
...release.marketingVersion === undefined ? {} : {
|
|
35517
|
+
marketingVersion: requireString2(release.marketingVersion, "release marketingVersion")
|
|
35518
|
+
},
|
|
35519
|
+
...release.versionCode === undefined ? {} : {
|
|
35520
|
+
versionCode: requirePositiveInteger(release.versionCode, "release versionCode")
|
|
35521
|
+
}
|
|
35522
|
+
};
|
|
35523
|
+
const evidence = value.evidence.map((candidate) => {
|
|
35524
|
+
if (!isRecord14(candidate) || !SHA256.test(String(candidate.reportSha256)) || !isStrength(candidate.strength) || candidate.networkUnavailable !== "not-proven" && candidate.networkUnavailable !== "proven" || typeof candidate.remote !== "boolean" || typeof candidate.generatedAt !== "string" || candidate.artifactExactness !== undefined && !isArtifactExactness(candidate.artifactExactness) || candidate.distribution !== undefined && !isDistribution(candidate.distribution))
|
|
35525
|
+
throw new TypeError("Mobile release certification evidence is invalid.");
|
|
35526
|
+
const parsedEvidence = {
|
|
35527
|
+
generatedAt: candidate.generatedAt,
|
|
35528
|
+
networkUnavailable: candidate.networkUnavailable,
|
|
35529
|
+
remote: candidate.remote,
|
|
35530
|
+
reportSha256: String(candidate.reportSha256),
|
|
35531
|
+
strength: candidate.strength,
|
|
35532
|
+
...candidate.artifactExactness === undefined ? {} : {
|
|
35533
|
+
artifactExactness: candidate.artifactExactness
|
|
35534
|
+
},
|
|
35535
|
+
...candidate.distribution === undefined ? {} : { distribution: candidate.distribution }
|
|
35536
|
+
};
|
|
35537
|
+
validateCertifiedEvidence(platform4, parsedEvidence);
|
|
35538
|
+
return parsedEvidence;
|
|
35539
|
+
});
|
|
35540
|
+
const strongestEvidence = evidence.reduce((strongest, candidate) => STRENGTH_RANK[candidate.strength] > STRENGTH_RANK[strongest] ? candidate.strength : strongest, evidence[0]?.strength ?? "installed");
|
|
35541
|
+
if (evidence.length === 0 || strongestEvidence !== strength)
|
|
35542
|
+
throw new TypeError("Mobile release certification evidence does not support its declared strength.");
|
|
35543
|
+
const parsed = {
|
|
35544
|
+
certificationId: requireString2(value.certificationId, "certificationId"),
|
|
35545
|
+
evidence,
|
|
35546
|
+
format: ABSOLUTE_MOBILE_RELEASE_CERTIFICATION_FORMAT,
|
|
35547
|
+
generatedAt: requireString2(value.generatedAt, "generatedAt"),
|
|
35548
|
+
release: parsedRelease,
|
|
35549
|
+
requirement,
|
|
35550
|
+
status: "certified",
|
|
35551
|
+
strength
|
|
35552
|
+
};
|
|
35553
|
+
const { certificationId, ...body } = parsed;
|
|
35554
|
+
if (certificationId !== `${CERTIFICATION_PREFIX}${sha2564(certificationBody(body))}`)
|
|
35555
|
+
throw new TypeError("Mobile release certification content digest is invalid.");
|
|
35556
|
+
return parsed;
|
|
35557
|
+
};
|
|
35558
|
+
var readAbsoluteMobileReleaseCertification = async (projectRoot, requested) => {
|
|
35559
|
+
const selected = resolve18(projectRoot, requested);
|
|
35560
|
+
if (!inside4(projectRoot, selected))
|
|
35561
|
+
throw new TypeError("Mobile release certification must remain inside the project.");
|
|
35562
|
+
const path = basename8(selected) === "certification.json" ? selected : join30(selected, "certification.json");
|
|
35563
|
+
const value = JSON.parse(await readFile26(path, "utf8"));
|
|
35564
|
+
return { certification: parseCertification(value), path };
|
|
35565
|
+
};
|
|
35566
|
+
var renderAbsoluteMobileReleaseCertification = (certification) => {
|
|
35567
|
+
const { release } = certification;
|
|
35568
|
+
const version = release.platform === "ios" ? `${release.marketingVersion ?? "unknown"} (${release.buildNumber ?? "unallocated"})` : String(release.versionCode ?? "unallocated");
|
|
35569
|
+
const evidence = certification.evidence.map((item) => `| ${item.strength} | ${item.networkUnavailable} | ${item.remote ? "paired Mac" : "local host"} | ${item.reportSha256} |`).join(`
|
|
35570
|
+
`);
|
|
35571
|
+
return `# AbsoluteJS mobile release certification
|
|
35572
|
+
|
|
35573
|
+
- Status: CERTIFIED
|
|
35574
|
+
- Certification: ${certification.certificationId}
|
|
35575
|
+
- Generated: ${certification.generatedAt}
|
|
35576
|
+
- Platform: ${release.platform}
|
|
35577
|
+
- Engine: ${release.engine}
|
|
35578
|
+
- Requirement: ${certification.requirement}
|
|
35579
|
+
- Evidence strength: ${certification.strength}
|
|
35580
|
+
- Release: ${release.releaseId}
|
|
35581
|
+
- Artifact SHA-256: ${release.artifactSha256}
|
|
35582
|
+
- Runtime fingerprint: ${release.runtime}
|
|
35583
|
+
- Embedded app build: ${release.appBuild}
|
|
35584
|
+
- Version/build: ${version}
|
|
35585
|
+
|
|
35586
|
+
This certification is local and contains no signing credentials, device identifiers, SSH destinations, report paths, application data, or page contents. Re-run verification against the immutable release before using it as a CI or promotion gate.
|
|
35587
|
+
|
|
35588
|
+
| Strength | Network unavailable | Execution | Report SHA-256 |
|
|
35589
|
+
| --- | --- | --- | --- |
|
|
35590
|
+
${evidence}
|
|
35591
|
+
`;
|
|
35592
|
+
};
|
|
35593
|
+
var verifyAbsoluteMobileReleaseCertification = (certification, release, requirement) => {
|
|
35594
|
+
const parsed = parseCertification(certification);
|
|
35595
|
+
const expected = releaseIdentity(release);
|
|
35596
|
+
if (JSON.stringify(parsed.release) !== JSON.stringify(expected))
|
|
35597
|
+
throw new TypeError("Mobile release certification was invalidated by a release identity, artifact, runtime, signing, version, build, or embedded-bundle change.");
|
|
35598
|
+
if (requirement) {
|
|
35599
|
+
validateRequirement(expected.platform, requirement);
|
|
35600
|
+
if (!satisfiesRequirement(parsed.strength, requirement))
|
|
35601
|
+
throw new TypeError(`Mobile release certification strength ${parsed.strength} does not satisfy required ${requirement} policy.`);
|
|
35602
|
+
}
|
|
35603
|
+
return parsed;
|
|
35604
|
+
};
|
|
35605
|
+
var writeAbsoluteMobileReleaseCertification = async (projectRoot, certification, outputDirectory) => {
|
|
35606
|
+
const root = resolve18(projectRoot);
|
|
35607
|
+
const parent = resolve18(root, outputDirectory ?? join30(".absolutejs", "mobile", "certifications", certification.release.platform, certification.release.releaseId));
|
|
35608
|
+
if (!inside4(root, parent))
|
|
35609
|
+
throw new TypeError("Mobile certification output must remain inside the project.");
|
|
35610
|
+
await mkdir20(parent, { recursive: true });
|
|
35611
|
+
const destination = join30(parent, certification.certificationId);
|
|
35612
|
+
const paths = {
|
|
35613
|
+
directory: destination,
|
|
35614
|
+
jsonPath: join30(destination, "certification.json"),
|
|
35615
|
+
markdownPath: join30(destination, "certification.md")
|
|
35616
|
+
};
|
|
35617
|
+
const json = `${JSON.stringify(certification, null, 2)}
|
|
35618
|
+
`;
|
|
35619
|
+
const markdown = renderAbsoluteMobileReleaseCertification(certification);
|
|
35620
|
+
const verifyExisting = async () => {
|
|
35621
|
+
const [existingJson, existingMarkdown] = await Promise.all([
|
|
35622
|
+
readFile26(paths.jsonPath, "utf8"),
|
|
35623
|
+
readFile26(paths.markdownPath, "utf8")
|
|
35624
|
+
]);
|
|
35625
|
+
if (existingJson !== json || existingMarkdown !== markdown)
|
|
35626
|
+
throw new TypeError(`Immutable mobile certification ${certification.certificationId} already exists with different content.`);
|
|
35627
|
+
};
|
|
35628
|
+
if (await exists9(destination)) {
|
|
35629
|
+
await verifyExisting();
|
|
35630
|
+
return paths;
|
|
35631
|
+
}
|
|
35632
|
+
const staging = await mkdtemp10(join30(parent, ".certification-"));
|
|
35633
|
+
try {
|
|
35634
|
+
await Promise.all([
|
|
35635
|
+
writeFile22(join30(staging, "certification.json"), json, {
|
|
35636
|
+
flag: "wx"
|
|
35637
|
+
}),
|
|
35638
|
+
writeFile22(join30(staging, "certification.md"), markdown, {
|
|
35639
|
+
flag: "wx"
|
|
35640
|
+
})
|
|
35641
|
+
]);
|
|
35642
|
+
await rename18(staging, destination).catch(async (error) => {
|
|
35643
|
+
if (await exists9(destination))
|
|
35644
|
+
return;
|
|
35645
|
+
throw error;
|
|
35646
|
+
});
|
|
35647
|
+
} finally {
|
|
35648
|
+
await rm15(staging, { force: true, recursive: true });
|
|
35649
|
+
}
|
|
35650
|
+
await verifyExisting();
|
|
35651
|
+
return paths;
|
|
35652
|
+
};
|
|
35250
35653
|
// src/mobile/releasePublisher.ts
|
|
35251
|
-
import { access as
|
|
35252
|
-
import { isAbsolute as
|
|
35654
|
+
import { access as access18 } from "fs/promises";
|
|
35655
|
+
import { isAbsolute as isAbsolute10, relative as relative17, resolve as resolve19, sep as sep12 } from "path";
|
|
35253
35656
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
35254
35657
|
var prepareAbsoluteIosRelease = async (publisher, options) => {
|
|
35255
35658
|
if (typeof publisher.prepareIosRelease !== "function") {
|
|
@@ -35272,24 +35675,24 @@ var prepareAbsoluteAndroidRelease = async (publisher, options) => {
|
|
|
35272
35675
|
}
|
|
35273
35676
|
return versionCode;
|
|
35274
35677
|
};
|
|
35275
|
-
var
|
|
35276
|
-
var isPublisher = (value) =>
|
|
35678
|
+
var isRecord15 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
35679
|
+
var isPublisher = (value) => isRecord15(value) && typeof value.publish === "function";
|
|
35277
35680
|
var publisherModulePath = (projectRoot, requested) => {
|
|
35278
|
-
const root =
|
|
35279
|
-
const path =
|
|
35280
|
-
const projectRelative =
|
|
35281
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
35681
|
+
const root = resolve19(projectRoot);
|
|
35682
|
+
const path = resolve19(root, requested);
|
|
35683
|
+
const projectRelative = relative17(root, path);
|
|
35684
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep12}`) || isAbsolute10(projectRelative)) {
|
|
35282
35685
|
throw new TypeError("mobile publish --registry must remain inside the project.");
|
|
35283
35686
|
}
|
|
35284
35687
|
return path;
|
|
35285
35688
|
};
|
|
35286
35689
|
var loadAbsoluteNativeReleasePublisher = async (projectRoot, requestedModulePath) => {
|
|
35287
35690
|
const modulePath = publisherModulePath(projectRoot, requestedModulePath);
|
|
35288
|
-
await
|
|
35691
|
+
await access18(modulePath).catch(() => {
|
|
35289
35692
|
throw new TypeError(`Native release registry module does not exist: ${modulePath}`);
|
|
35290
35693
|
});
|
|
35291
35694
|
const loaded = await import(pathToFileURL3(modulePath).href);
|
|
35292
|
-
const publisher =
|
|
35695
|
+
const publisher = isRecord15(loaded) ? loaded.default ?? loaded.registry : undefined;
|
|
35293
35696
|
if (!isPublisher(publisher)) {
|
|
35294
35697
|
throw new TypeError("Native release registry module must default-export a registry with publish(options).");
|
|
35295
35698
|
}
|
|
@@ -35349,7 +35752,7 @@ var publishAbsoluteIosRelease = async (options) => {
|
|
|
35349
35752
|
init_pageProtocol();
|
|
35350
35753
|
init_releaseArtifact();
|
|
35351
35754
|
import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
|
|
35352
|
-
import { dirname as dirname20, extname as extname6, relative as
|
|
35755
|
+
import { dirname as dirname20, extname as extname6, relative as relative18, resolve as resolve20 } from "path";
|
|
35353
35756
|
import ts2 from "typescript";
|
|
35354
35757
|
var ROUTE_METHODS = new Set(["get", "head"]);
|
|
35355
35758
|
var SOURCE_FILTER = /\.[cm]?[jt]sx?$/;
|
|
@@ -35518,7 +35921,7 @@ var resolvePageIdentity = (expression, sourceFile, checker, projectRoot) => {
|
|
|
35518
35921
|
const declaration = symbol?.declarations?.[0];
|
|
35519
35922
|
const file = declaration?.getSourceFile().fileName ?? sourceFile.fileName;
|
|
35520
35923
|
const exportedName = symbol?.name ?? expression.getText(sourceFile);
|
|
35521
|
-
const source = posixPath(
|
|
35924
|
+
const source = posixPath(relative18(projectRoot, file));
|
|
35522
35925
|
return `${source}#${exportedName}`;
|
|
35523
35926
|
};
|
|
35524
35927
|
var resolveAlias = (symbol, checker) => {
|
|
@@ -35757,7 +36160,7 @@ var analyzeProgram = (program, projectRoot) => {
|
|
|
35757
36160
|
const checker = program.getTypeChecker();
|
|
35758
36161
|
const analyzed = new Map;
|
|
35759
36162
|
for (const sourceFile of program.getSourceFiles()) {
|
|
35760
|
-
const resolvedFile =
|
|
36163
|
+
const resolvedFile = resolve20(sourceFile.fileName);
|
|
35761
36164
|
if (!isProjectSource(sourceFile, resolvedFile, projectRoot))
|
|
35762
36165
|
continue;
|
|
35763
36166
|
const analysis = analyzeSourceFile(sourceFile, checker, projectRoot);
|
|
@@ -35850,14 +36253,14 @@ var transformFile = (source, fileName, analysis) => {
|
|
|
35850
36253
|
};
|
|
35851
36254
|
var ABSOLUTE_MOBILE_TRANSFORM_PROTOCOL = ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION;
|
|
35852
36255
|
var createAbsoluteMobileRouteMetadataPlugin = (options) => {
|
|
35853
|
-
const projectRoot =
|
|
35854
|
-
const entry =
|
|
36256
|
+
const projectRoot = resolve20(options.projectRoot ?? process.cwd());
|
|
36257
|
+
const entry = resolve20(options.entry);
|
|
35855
36258
|
const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
|
|
35856
36259
|
return {
|
|
35857
36260
|
name: "absolute-mobile-route-metadata",
|
|
35858
36261
|
setup(build) {
|
|
35859
36262
|
build.onLoad({ filter: SOURCE_FILTER }, async ({ path }) => {
|
|
35860
|
-
const analysis = analyzed.get(
|
|
36263
|
+
const analysis = analyzed.get(resolve20(path));
|
|
35861
36264
|
if (!analysis)
|
|
35862
36265
|
return;
|
|
35863
36266
|
const source = await Bun.file(path).text();
|
|
@@ -35870,11 +36273,11 @@ var createAbsoluteMobileRouteMetadataPlugin = (options) => {
|
|
|
35870
36273
|
};
|
|
35871
36274
|
};
|
|
35872
36275
|
var inspectAbsoluteMobileRouteMetadata = (options) => {
|
|
35873
|
-
const projectRoot =
|
|
35874
|
-
const entry =
|
|
36276
|
+
const projectRoot = resolve20(options.projectRoot ?? process.cwd());
|
|
36277
|
+
const entry = resolve20(options.entry);
|
|
35875
36278
|
const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
|
|
35876
36279
|
return [...analyzed.entries()].flatMap(([file, analysis]) => [...analysis.byRouteCall.values()].map(({ metadata }) => ({
|
|
35877
|
-
file: posixPath(
|
|
36280
|
+
file: posixPath(relative18(projectRoot, file)),
|
|
35878
36281
|
metadata
|
|
35879
36282
|
})));
|
|
35880
36283
|
};
|
|
@@ -36208,7 +36611,7 @@ var createCapacitor = (win) => {
|
|
|
36208
36611
|
callbackId
|
|
36209
36612
|
}, callback);
|
|
36210
36613
|
};
|
|
36211
|
-
const p = new Promise((
|
|
36614
|
+
const p = new Promise((resolve21) => call.then(() => resolve21({ remove })));
|
|
36212
36615
|
p.remove = async () => {
|
|
36213
36616
|
console.warn(`Using addListener() without 'await' is deprecated.`);
|
|
36214
36617
|
await remove();
|
|
@@ -36413,11 +36816,11 @@ class CapacitorCookiesPluginWeb extends WebPlugin {
|
|
|
36413
36816
|
var CapacitorCookies = registerPlugin("CapacitorCookies", {
|
|
36414
36817
|
web: () => new CapacitorCookiesPluginWeb
|
|
36415
36818
|
});
|
|
36416
|
-
var readBlobAsBase64 = async (blob) => new Promise((
|
|
36819
|
+
var readBlobAsBase64 = async (blob) => new Promise((resolve21, reject) => {
|
|
36417
36820
|
const reader = new FileReader;
|
|
36418
36821
|
reader.onload = () => {
|
|
36419
36822
|
const base64String = reader.result;
|
|
36420
|
-
|
|
36823
|
+
resolve21(base64String.indexOf(",") >= 0 ? base64String.split(",")[1] : base64String);
|
|
36421
36824
|
};
|
|
36422
36825
|
reader.onerror = (error) => reject(error);
|
|
36423
36826
|
reader.readAsDataURL(blob);
|
|
@@ -36593,7 +36996,7 @@ var REPORT_KINDS = new Set([
|
|
|
36593
36996
|
"signal"
|
|
36594
36997
|
]);
|
|
36595
36998
|
var nativeObservability = registerPlugin("AbsoluteMobileObservability");
|
|
36596
|
-
var
|
|
36999
|
+
var isRecord16 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36597
37000
|
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]");
|
|
36598
37001
|
var redactValue = (value, depth = 0) => {
|
|
36599
37002
|
if (depth >= MAX_REDACTION_DEPTH)
|
|
@@ -36604,7 +37007,7 @@ var redactValue = (value, depth = 0) => {
|
|
|
36604
37007
|
return value;
|
|
36605
37008
|
if (Array.isArray(value))
|
|
36606
37009
|
return value.slice(0, 64).map((entry) => redactValue(entry, depth + 1));
|
|
36607
|
-
if (!
|
|
37010
|
+
if (!isRecord16(value))
|
|
36608
37011
|
return String(value).slice(0, MAX_STRING_LENGTH);
|
|
36609
37012
|
return Object.fromEntries(Object.entries(value).slice(0, 128).map(([key, entry]) => [
|
|
36610
37013
|
key,
|
|
@@ -36612,7 +37015,7 @@ var redactValue = (value, depth = 0) => {
|
|
|
36612
37015
|
]));
|
|
36613
37016
|
};
|
|
36614
37017
|
var parseReport = (value) => {
|
|
36615
|
-
if (!
|
|
37018
|
+
if (!isRecord16(value) || !isRecord16(value.details))
|
|
36616
37019
|
return;
|
|
36617
37020
|
if (typeof value.id !== "string" || !REPORT_ID.test(value.id))
|
|
36618
37021
|
return;
|
|
@@ -36623,7 +37026,7 @@ var parseReport = (value) => {
|
|
|
36623
37026
|
if (value.platform !== "android" && value.platform !== "ios")
|
|
36624
37027
|
return;
|
|
36625
37028
|
const details = redactValue(value.details);
|
|
36626
|
-
if (!
|
|
37029
|
+
if (!isRecord16(details))
|
|
36627
37030
|
return;
|
|
36628
37031
|
if (new TextEncoder().encode(JSON.stringify(details)).byteLength > MAX_DETAIL_BYTES)
|
|
36629
37032
|
return;
|
|
@@ -41077,8 +41480,8 @@ var createBeacon = (options) => {
|
|
|
41077
41480
|
if (await fontAvailable(element))
|
|
41078
41481
|
return;
|
|
41079
41482
|
if (confirmationMs > 0) {
|
|
41080
|
-
await new Promise((
|
|
41081
|
-
const timer2 = window.setTimeout(
|
|
41483
|
+
await new Promise((resolve21) => {
|
|
41484
|
+
const timer2 = window.setTimeout(resolve21, confirmationMs);
|
|
41082
41485
|
cleanups.push(() => window.clearTimeout(timer2));
|
|
41083
41486
|
});
|
|
41084
41487
|
if (document.visibilityState === "hidden")
|
|
@@ -42066,51 +42469,51 @@ var createAbsoluteMobileUpdateClient = (options) => {
|
|
|
42066
42469
|
};
|
|
42067
42470
|
};
|
|
42068
42471
|
// src/mobile/updatePublisher.ts
|
|
42069
|
-
import { access as
|
|
42070
|
-
import { isAbsolute as
|
|
42472
|
+
import { access as access19 } from "fs/promises";
|
|
42473
|
+
import { isAbsolute as isAbsolute11, relative as relative20, resolve as resolve22, sep as sep13 } from "path";
|
|
42071
42474
|
import { pathToFileURL as pathToFileURL4 } from "url";
|
|
42072
42475
|
|
|
42073
42476
|
// src/mobile/updateSigning.ts
|
|
42074
|
-
import { createHash as
|
|
42477
|
+
import { createHash as createHash17, sign, verify } from "crypto";
|
|
42075
42478
|
import {
|
|
42076
42479
|
cp as cp2,
|
|
42077
|
-
mkdir as
|
|
42078
|
-
mkdtemp as
|
|
42480
|
+
mkdir as mkdir21,
|
|
42481
|
+
mkdtemp as mkdtemp11,
|
|
42079
42482
|
readdir as readdir10,
|
|
42080
|
-
readFile as
|
|
42081
|
-
rename as
|
|
42082
|
-
rm as
|
|
42483
|
+
readFile as readFile27,
|
|
42484
|
+
rename as rename19,
|
|
42485
|
+
rm as rm16,
|
|
42083
42486
|
stat as stat6,
|
|
42084
|
-
writeFile as
|
|
42487
|
+
writeFile as writeFile23
|
|
42085
42488
|
} from "fs/promises";
|
|
42086
|
-
import { dirname as dirname21, join as
|
|
42489
|
+
import { dirname as dirname21, join as join31, relative as relative19, resolve as resolve21 } from "path";
|
|
42087
42490
|
var UPDATE_MANIFEST_FILE = "update.json";
|
|
42088
42491
|
var UPDATE_FILES_DIRECTORY = "files";
|
|
42089
|
-
var
|
|
42492
|
+
var sha2565 = (value) => createHash17("sha256").update(value).digest("hex");
|
|
42090
42493
|
var listFiles = async (root, directory = root) => {
|
|
42091
42494
|
const entries = await readdir10(directory, { withFileTypes: true });
|
|
42092
42495
|
const paths = await Promise.all(entries.map(async (entry) => {
|
|
42093
|
-
const path =
|
|
42496
|
+
const path = join31(directory, entry.name);
|
|
42094
42497
|
if (entry.isDirectory())
|
|
42095
42498
|
return listFiles(root, path);
|
|
42096
42499
|
if (!entry.isFile())
|
|
42097
42500
|
throw new TypeError("Mobile updates cannot contain links or special files.");
|
|
42098
|
-
return [
|
|
42501
|
+
return [relative19(root, path).replaceAll("\\", "/")];
|
|
42099
42502
|
}));
|
|
42100
42503
|
return paths.flat().sort((left, right) => left.localeCompare(right));
|
|
42101
42504
|
};
|
|
42102
42505
|
var inspectFiles = async (root, paths) => Promise.all(paths.map(async (path) => {
|
|
42103
|
-
const source =
|
|
42506
|
+
const source = join31(root, path);
|
|
42104
42507
|
const [metadata, contents] = await Promise.all([
|
|
42105
42508
|
stat6(source),
|
|
42106
|
-
|
|
42509
|
+
readFile27(source)
|
|
42107
42510
|
]);
|
|
42108
|
-
return { bytes: metadata.size, path, sha256:
|
|
42511
|
+
return { bytes: metadata.size, path, sha256: sha2565(contents) };
|
|
42109
42512
|
}));
|
|
42110
|
-
var releaseIdFor = (value) => `amu_${
|
|
42513
|
+
var releaseIdFor = (value) => `amu_${sha2565(canonicalizeAbsoluteMobileUpdate(value))}`;
|
|
42111
42514
|
var buildAbsoluteMobileUpdate = async (options) => {
|
|
42112
|
-
const bundleDirectory =
|
|
42113
|
-
const outputRoot =
|
|
42515
|
+
const bundleDirectory = resolve21(options.bundleDirectory);
|
|
42516
|
+
const outputRoot = resolve21(options.outputDirectory);
|
|
42114
42517
|
if (outputRoot === bundleDirectory || outputRoot.startsWith(`${bundleDirectory}/`))
|
|
42115
42518
|
throw new TypeError("Mobile update output must be outside the embedded bundle.");
|
|
42116
42519
|
const paths = await listFiles(bundleDirectory);
|
|
@@ -42138,38 +42541,38 @@ var buildAbsoluteMobileUpdate = async (options) => {
|
|
|
42138
42541
|
value: signature.toString("base64")
|
|
42139
42542
|
}
|
|
42140
42543
|
});
|
|
42141
|
-
await
|
|
42142
|
-
const outputDirectory =
|
|
42143
|
-
const staging = await
|
|
42544
|
+
await mkdir21(outputRoot, { recursive: true });
|
|
42545
|
+
const outputDirectory = join31(outputRoot, manifest.releaseId);
|
|
42546
|
+
const staging = await mkdtemp11(join31(outputRoot, ".stage-"));
|
|
42144
42547
|
try {
|
|
42145
|
-
await cp2(bundleDirectory,
|
|
42548
|
+
await cp2(bundleDirectory, join31(staging, UPDATE_FILES_DIRECTORY), {
|
|
42146
42549
|
force: true,
|
|
42147
42550
|
recursive: true
|
|
42148
42551
|
});
|
|
42149
|
-
await
|
|
42552
|
+
await writeFile23(join31(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
|
|
42150
42553
|
`);
|
|
42151
|
-
await
|
|
42554
|
+
await rename19(staging, outputDirectory);
|
|
42152
42555
|
} catch (error) {
|
|
42153
|
-
await
|
|
42556
|
+
await rm16(staging, { force: true, recursive: true });
|
|
42154
42557
|
if (typeof error === "object" && error !== null && Reflect.get(error, "code") === "EEXIST")
|
|
42155
42558
|
throw new TypeError(`Mobile update ${manifest.releaseId} already exists.`, { cause: error });
|
|
42156
42559
|
throw error;
|
|
42157
42560
|
}
|
|
42158
42561
|
return {
|
|
42159
42562
|
manifest,
|
|
42160
|
-
manifestPath:
|
|
42563
|
+
manifestPath: join31(outputDirectory, UPDATE_MANIFEST_FILE),
|
|
42161
42564
|
outputDirectory
|
|
42162
42565
|
};
|
|
42163
42566
|
};
|
|
42164
42567
|
var copyAbsoluteMobileUpdateFile = async (updateDirectory, path, destination) => {
|
|
42165
|
-
const source =
|
|
42166
|
-
const root =
|
|
42568
|
+
const source = resolve21(updateDirectory, UPDATE_FILES_DIRECTORY, path);
|
|
42569
|
+
const root = resolve21(updateDirectory, UPDATE_FILES_DIRECTORY);
|
|
42167
42570
|
if (!source.startsWith(`${root}/`))
|
|
42168
42571
|
throw new TypeError("Update file escaped its release.");
|
|
42169
|
-
await
|
|
42572
|
+
await mkdir21(dirname21(destination), { recursive: true });
|
|
42170
42573
|
await cp2(source, destination, { force: true });
|
|
42171
42574
|
};
|
|
42172
|
-
var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await
|
|
42575
|
+
var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile27(join31(resolve21(directory), UPDATE_MANIFEST_FILE), "utf8")));
|
|
42173
42576
|
var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
|
|
42174
42577
|
const manifest = parseAbsoluteMobileUpdateManifest(manifestValue);
|
|
42175
42578
|
const valid = verify("sha256", absoluteMobileUpdateSigningPayload(unsignedAbsoluteMobileUpdate(manifest)), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64"));
|
|
@@ -42286,16 +42689,16 @@ var pruneAbsoluteMobileUpdates = async (options) => {
|
|
|
42286
42689
|
var object5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
42287
42690
|
var isPublisher2 = (value) => object5(value) && typeof value.publishUpdate === "function" && typeof value.promoteUpdate === "function" && typeof value.rollbackUpdate === "function";
|
|
42288
42691
|
var projectPath2 = (projectRoot, requested, label) => {
|
|
42289
|
-
const root =
|
|
42290
|
-
const path =
|
|
42291
|
-
const projectRelative =
|
|
42292
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
42692
|
+
const root = resolve22(projectRoot);
|
|
42693
|
+
const path = resolve22(root, requested);
|
|
42694
|
+
const projectRelative = relative20(root, path);
|
|
42695
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep13}`) || isAbsolute11(projectRelative))
|
|
42293
42696
|
throw new TypeError(`${label} must remain inside the project.`);
|
|
42294
42697
|
return path;
|
|
42295
42698
|
};
|
|
42296
42699
|
var loadAbsoluteMobileUpdatePublisher = async (projectRoot, requestedModulePath) => {
|
|
42297
42700
|
const modulePath = projectPath2(projectRoot, requestedModulePath, "mobile update registry");
|
|
42298
|
-
await
|
|
42701
|
+
await access19(modulePath).catch(() => {
|
|
42299
42702
|
throw new TypeError(`Mobile update registry does not exist: ${modulePath}`);
|
|
42300
42703
|
});
|
|
42301
42704
|
const loaded = await import(pathToFileURL4(modulePath).href);
|
|
@@ -42346,7 +42749,7 @@ var rollbackAbsoluteMobileUpdate = async (options) => {
|
|
|
42346
42749
|
return result;
|
|
42347
42750
|
};
|
|
42348
42751
|
// src/mobile/updateRollout.ts
|
|
42349
|
-
import { createHash as
|
|
42752
|
+
import { createHash as createHash18 } from "crypto";
|
|
42350
42753
|
var UUID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[1-8][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/u;
|
|
42351
42754
|
var requireHeader = (headers, name) => {
|
|
42352
42755
|
const value = headers.get(name);
|
|
@@ -42361,7 +42764,7 @@ var isAbsoluteMobileUpdateRolloutMember = (options) => {
|
|
|
42361
42764
|
return false;
|
|
42362
42765
|
if (options.rollout === 1)
|
|
42363
42766
|
return true;
|
|
42364
|
-
const digest =
|
|
42767
|
+
const digest = createHash18("sha256").update(`${options.appId}\x00${options.channel}\x00${options.releaseId}\x00${options.installationId}`).digest();
|
|
42365
42768
|
const bucket = digest.readUInt32BE(0) / 4294967296;
|
|
42366
42769
|
return bucket < options.rollout;
|
|
42367
42770
|
};
|
|
@@ -42408,6 +42811,7 @@ export {
|
|
|
42408
42811
|
ABSOLUTE_MOBILE_PAGE_MEDIA_TYPE,
|
|
42409
42812
|
ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION,
|
|
42410
42813
|
ABSOLUTE_MOBILE_PREVIEW_PATH,
|
|
42814
|
+
ABSOLUTE_MOBILE_RELEASE_CERTIFICATION_FORMAT,
|
|
42411
42815
|
ABSOLUTE_MOBILE_RETAINED_GENERATIONS,
|
|
42412
42816
|
ABSOLUTE_MOBILE_ROUTE_DETAIL,
|
|
42413
42817
|
ABSOLUTE_MOBILE_SHELL_ABI,
|
|
@@ -42493,6 +42897,7 @@ export {
|
|
|
42493
42897
|
createAbsoluteMobilePageErrorResponse,
|
|
42494
42898
|
createAbsoluteMobilePageRequest,
|
|
42495
42899
|
createAbsoluteMobilePreviewPlugin,
|
|
42900
|
+
createAbsoluteMobileReleaseCertification,
|
|
42496
42901
|
createAbsoluteMobileRouteMetadataPlugin,
|
|
42497
42902
|
createAbsoluteMobileUpdateClient,
|
|
42498
42903
|
createAbsoluteMobileUpdateRuntimeDescriptor,
|
|
@@ -42602,10 +43007,12 @@ export {
|
|
|
42602
43007
|
readAbsoluteIosRelease,
|
|
42603
43008
|
readAbsoluteMobileLinkIntent,
|
|
42604
43009
|
readAbsoluteMobileMaterializedReleases,
|
|
43010
|
+
readAbsoluteMobileReleaseCertification,
|
|
42605
43011
|
readAbsoluteMobileUpdate,
|
|
42606
43012
|
reconcileAbsoluteMobileUpdateRollout,
|
|
42607
43013
|
redactAbsoluteIosLog,
|
|
42608
43014
|
removeAbsoluteRemoteMacProfile,
|
|
43015
|
+
renderAbsoluteMobileReleaseCertification,
|
|
42609
43016
|
renderAbsoluteMobileUpdateRegistry,
|
|
42610
43017
|
repairAbsoluteIosDevSession,
|
|
42611
43018
|
reportAbsoluteMobileUpdateHealth,
|
|
@@ -42645,13 +43052,15 @@ export {
|
|
|
42645
43052
|
validateAbsoluteSshDestination,
|
|
42646
43053
|
verifyAbsoluteMobileAssociationFiles,
|
|
42647
43054
|
verifyAbsoluteMobileCompatibilityProducer,
|
|
43055
|
+
verifyAbsoluteMobileReleaseCertification,
|
|
42648
43056
|
verifyAbsoluteMobileUpdateSignature,
|
|
42649
43057
|
waitForAbsoluteIosHmrLog,
|
|
42650
43058
|
writeAbsoluteCapacitorConfig,
|
|
42651
43059
|
writeAbsoluteExpoProject,
|
|
42652
43060
|
writeAbsoluteMobileGithubWorkflow,
|
|
43061
|
+
writeAbsoluteMobileReleaseCertification,
|
|
42653
43062
|
writeAbsoluteMobileUpdateRegistry
|
|
42654
43063
|
};
|
|
42655
43064
|
|
|
42656
|
-
//# debugId=
|
|
43065
|
+
//# debugId=DB53CC7C8DF0442B64756E2164756E21
|
|
42657
43066
|
//# sourceMappingURL=index.js.map
|