@absolutejs/absolute 0.20.0-beta.109 → 0.20.0-beta.110
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 +7 -0
- package/README.md +4 -3
- package/changelog.json +26 -0
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/cli/index.js +1 -1
- package/dist/cli/{mobile-e4ygngfk.js → mobile-12y4gtsq.js} +571 -131
- package/dist/dev/serverBootstrap.js +35 -6
- package/dist/mobile/index.js +417 -85
- package/dist/mobile/index.js.map +8 -7
- package/dist/src/dev/serverEntryCopies.d.ts +6 -0
- package/dist/src/mobile/certificationVerification.d.ts +24 -0
- package/dist/src/mobile/ciWorkflow.d.ts +1 -1
- package/dist/src/mobile/index.d.ts +1 -0
- package/dist/src/mobile/releaseCertification.d.ts +1 -0
- package/dist/src/mobile/releasePublisher.d.ts +10 -0
- package/package.json +2 -2
package/dist/mobile/index.js
CHANGED
|
@@ -20092,7 +20092,7 @@ import {
|
|
|
20092
20092
|
verify as verify2,
|
|
20093
20093
|
X509Certificate as X509Certificate3
|
|
20094
20094
|
} from "crypto";
|
|
20095
|
-
import { readFile as
|
|
20095
|
+
import { readFile as readFile29, stat as stat8 } 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)
|
|
@@ -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
|
|
21128
|
+
const localManifest = parseMobileUpdateManifest(JSON.parse(await readFile29(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);
|
|
@@ -21143,7 +21143,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
|
|
|
21143
21143
|
if (!existing) {
|
|
21144
21144
|
for (const file of manifest.files) {
|
|
21145
21145
|
const local = path.join(localRoot, "files", file.path);
|
|
21146
|
-
const metadata = await
|
|
21146
|
+
const metadata = await stat8(local).catch(() => null);
|
|
21147
21147
|
if (!metadata?.isFile() || metadata.size !== file.bytes)
|
|
21148
21148
|
throw new MobileUpdateRegistryError(`Mobile update file ${file.path} size changed`);
|
|
21149
21149
|
if (await fileDigest(Bun.file(local)) !== file.sha256)
|
|
@@ -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
|
|
21415
|
-
if (request.method === "POST" &&
|
|
21414
|
+
const relative22 = pathname.startsWith(`${route}/`) ? pathname.slice(route.length + 1) : "";
|
|
21415
|
+
if (request.method === "POST" && relative22 === "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 (
|
|
21458
|
+
if (relative22 === "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(
|
|
21576
|
+
const match = /^(amu_[a-f0-9]{64})\/files\/(.+)$/.exec(relative22);
|
|
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
|
|
21670
|
-
import { dirname as
|
|
21669
|
+
import { access as access21, mkdir as mkdir23 } from "fs/promises";
|
|
21670
|
+
import { dirname as dirname23, isAbsolute as isAbsolute13, relative as relative22, resolve as resolve24, sep as sep15 } 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), projectPath3 = (projectRoot, requested) => {
|
|
21674
|
-
const root =
|
|
21675
|
-
const path2 =
|
|
21676
|
-
const projectRelative =
|
|
21677
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
21674
|
+
const root = resolve24(projectRoot);
|
|
21675
|
+
const path2 = resolve24(root, requested);
|
|
21676
|
+
const projectRelative = relative22(root, path2);
|
|
21677
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep15}`) || isAbsolute13(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 = projectPath3(projectRoot, requestedModulePath);
|
|
21700
|
-
await
|
|
21700
|
+
await access21(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 = projectPath3(options.projectRoot, options.modulePath ?? DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE);
|
|
21888
21888
|
if (!options.force) {
|
|
21889
|
-
await
|
|
21889
|
+
await access21(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
|
|
21895
|
+
await mkdir23(dirname23(path2), { recursive: true });
|
|
21896
21896
|
await Bun.write(path2, renderAbsoluteMobileUpdateRegistry({
|
|
21897
21897
|
...options.health ? { health: options.health } : {},
|
|
21898
21898
|
...options.rollout ? { rollout: options.rollout } : {},
|
|
@@ -33033,7 +33033,7 @@ init_config();
|
|
|
33033
33033
|
import { existsSync as existsSync4 } from "fs";
|
|
33034
33034
|
import { access as access16, mkdir as mkdir16, readFile as readFile20, writeFile as writeFile16 } from "fs/promises";
|
|
33035
33035
|
import { dirname as dirname15, extname as extname5, relative as relative15, resolve as resolve17, sep as sep10 } from "path";
|
|
33036
|
-
var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT =
|
|
33036
|
+
var ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT = 2;
|
|
33037
33037
|
var SECRET_NAME_PATTERN = /^[A-Z][A-Z0-9_]*$/u;
|
|
33038
33038
|
var CI_ENV_INDENTATION = 6;
|
|
33039
33039
|
var RESERVED_SECRET_NAMES = new Set([
|
|
@@ -33171,6 +33171,14 @@ var publishingInputs = (platforms, includePublishing) => {
|
|
|
33171
33171
|
if (!includePublishing)
|
|
33172
33172
|
return "";
|
|
33173
33173
|
const fields = [
|
|
33174
|
+
` operation:
|
|
33175
|
+
description: Build a release or promote an exact artifact from an earlier run
|
|
33176
|
+
required: true
|
|
33177
|
+
type: choice
|
|
33178
|
+
default: build
|
|
33179
|
+
options:
|
|
33180
|
+
- build
|
|
33181
|
+
- promote`,
|
|
33174
33182
|
` publish:
|
|
33175
33183
|
description: Publish through mobile.release.ts after the signed build
|
|
33176
33184
|
required: true
|
|
@@ -33179,6 +33187,14 @@ var publishingInputs = (platforms, includePublishing) => {
|
|
|
33179
33187
|
` channel:
|
|
33180
33188
|
description: Optional AbsoluteJS immutable release channel
|
|
33181
33189
|
required: false
|
|
33190
|
+
type: string`,
|
|
33191
|
+
` source_run_id:
|
|
33192
|
+
description: Source workflow run ID for promotion without rebuilding
|
|
33193
|
+
required: false
|
|
33194
|
+
type: string`,
|
|
33195
|
+
` certification_base64:
|
|
33196
|
+
description: AbsoluteJS certification supplied by the promotion CLI
|
|
33197
|
+
required: false
|
|
33182
33198
|
type: string`
|
|
33183
33199
|
];
|
|
33184
33200
|
if (platforms.includes("android"))
|
|
@@ -33208,7 +33224,7 @@ var publishingInputs = (platforms, includePublishing) => {
|
|
|
33208
33224
|
${fields.join(`
|
|
33209
33225
|
`)}`;
|
|
33210
33226
|
};
|
|
33211
|
-
var jobCondition = (platform3) => `github.event_name == 'workflow_dispatch' && (inputs.platform == 'all' || inputs.platform == '${platform3}')`;
|
|
33227
|
+
var jobCondition = (platform3, includePublishing) => `github.event_name == 'workflow_dispatch' && ${includePublishing ? "inputs.operation == 'build' && " : ""}(inputs.platform == 'all' || inputs.platform == '${platform3}')`;
|
|
33212
33228
|
var androidJob = (options) => {
|
|
33213
33229
|
const custom = customSecretEnvironment(options.customSecrets);
|
|
33214
33230
|
const publishEnvironment = options.includePublishing ? `
|
|
@@ -33235,6 +33251,11 @@ var androidJob = (options) => {
|
|
|
33235
33251
|
chmod 600 "$GOOGLE_APPLICATION_CREDENTIALS"
|
|
33236
33252
|
fi` : "";
|
|
33237
33253
|
const certificationSteps = options.includePublishing ? `
|
|
33254
|
+
- name: Install pinned Cosign for Android certification
|
|
33255
|
+
if: inputs.publish
|
|
33256
|
+
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6
|
|
33257
|
+
with:
|
|
33258
|
+
cosign-release: v3.1.2
|
|
33238
33259
|
- name: Install-test and certify exact Android release
|
|
33239
33260
|
if: inputs.publish
|
|
33240
33261
|
shell: bash
|
|
@@ -33254,6 +33275,12 @@ var androidJob = (options) => {
|
|
|
33254
33275
|
"\${args[@]}"
|
|
33255
33276
|
args=(bunx absolute mobile certify "$RELEASE_DIRECTORY" --evidence .absolutejs/mobile-ci/acceptance/android --require installed --outdir .absolutejs/mobile-ci/certifications/android --json)
|
|
33256
33277
|
"\${args[@]}" > .absolutejs/mobile-ci/android-certification.json
|
|
33278
|
+
shopt -s nullglob
|
|
33279
|
+
certifications=(.absolutejs/mobile-ci/certifications/android/*)
|
|
33280
|
+
if [[ "\${#certifications[@]}" -ne 1 ]]; then echo "Expected exactly one Android certification." >&2; exit 1; fi
|
|
33281
|
+
CERTIFICATION_PATH="\${certifications[0]}/certification.json"
|
|
33282
|
+
bunx @absolutejs/attest@0.2.0 sign-blobs "$CERTIFICATION_PATH"
|
|
33283
|
+
bunx absolute mobile ci verification --bundle "$CERTIFICATION_PATH.sigstore.json" --out "\${certifications[0]}/verification.json"
|
|
33257
33284
|
- name: Publish certified Android release
|
|
33258
33285
|
if: inputs.publish
|
|
33259
33286
|
shell: bash
|
|
@@ -33265,7 +33292,7 @@ var androidJob = (options) => {
|
|
|
33265
33292
|
echo "Expected exactly one Android release and certification." >&2
|
|
33266
33293
|
exit 1
|
|
33267
33294
|
fi
|
|
33268
|
-
args=(bunx absolute mobile publish android --release "\${releases[0]}" --certification "\${certifications[0]}" --registry "$ABSOLUTE_REGISTRY_MODULE")
|
|
33295
|
+
args=(bunx absolute mobile publish android --release "\${releases[0]}" --certification "\${certifications[0]}" --certification-attestation "\${certifications[0]}/verification.json" --registry "$ABSOLUTE_REGISTRY_MODULE")
|
|
33269
33296
|
if [[ -n "$ABSOLUTE_RELEASE_CHANNEL" ]]; then
|
|
33270
33297
|
args+=(--channel "$ABSOLUTE_RELEASE_CHANNEL")
|
|
33271
33298
|
fi
|
|
@@ -33290,7 +33317,7 @@ var androidJob = (options) => {
|
|
|
33290
33317
|
android:
|
|
33291
33318
|
name: Signed Android release
|
|
33292
33319
|
needs: validate
|
|
33293
|
-
if: \${{ ${jobCondition("android")} }}
|
|
33320
|
+
if: \${{ ${jobCondition("android", options.includePublishing)} }}
|
|
33294
33321
|
runs-on: ubuntu-latest
|
|
33295
33322
|
environment: absolute-mobile-release
|
|
33296
33323
|
permissions:
|
|
@@ -33381,6 +33408,11 @@ var iosJob = (options) => {
|
|
|
33381
33408
|
chmod 600 "$APP_STORE_CONNECT_PRIVATE_KEY_PATH"
|
|
33382
33409
|
fi` : "";
|
|
33383
33410
|
const certificationSteps = options.includePublishing ? `
|
|
33411
|
+
- name: Install pinned Cosign for iOS certification
|
|
33412
|
+
if: inputs.publish
|
|
33413
|
+
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6
|
|
33414
|
+
with:
|
|
33415
|
+
cosign-release: v3.1.2
|
|
33384
33416
|
- name: Simulator-test and certify exact iOS release
|
|
33385
33417
|
if: inputs.publish
|
|
33386
33418
|
shell: bash
|
|
@@ -33397,6 +33429,12 @@ var iosJob = (options) => {
|
|
|
33397
33429
|
"\${args[@]}"
|
|
33398
33430
|
args=(bunx absolute mobile certify "$RELEASE_DIRECTORY" --evidence .absolutejs/mobile-ci/acceptance/ios --require simulator --outdir .absolutejs/mobile-ci/certifications/ios --json)
|
|
33399
33431
|
"\${args[@]}" > .absolutejs/mobile-ci/ios-certification.json
|
|
33432
|
+
shopt -s nullglob
|
|
33433
|
+
certifications=(.absolutejs/mobile-ci/certifications/ios/*)
|
|
33434
|
+
if [[ "\${#certifications[@]}" -ne 1 ]]; then echo "Expected exactly one iOS certification." >&2; exit 1; fi
|
|
33435
|
+
CERTIFICATION_PATH="\${certifications[0]}/certification.json"
|
|
33436
|
+
bunx @absolutejs/attest@0.2.0 sign-blobs "$CERTIFICATION_PATH"
|
|
33437
|
+
bunx absolute mobile ci verification --bundle "$CERTIFICATION_PATH.sigstore.json" --out "\${certifications[0]}/verification.json"
|
|
33400
33438
|
- name: Publish certified iOS release
|
|
33401
33439
|
if: inputs.publish
|
|
33402
33440
|
shell: bash
|
|
@@ -33408,7 +33446,7 @@ var iosJob = (options) => {
|
|
|
33408
33446
|
echo "Expected exactly one iOS release and certification." >&2
|
|
33409
33447
|
exit 1
|
|
33410
33448
|
fi
|
|
33411
|
-
args=(bunx absolute mobile publish ios --release "\${releases[0]}" --certification "\${certifications[0]}" --registry "$ABSOLUTE_REGISTRY_MODULE")
|
|
33449
|
+
args=(bunx absolute mobile publish ios --release "\${releases[0]}" --certification "\${certifications[0]}" --certification-attestation "\${certifications[0]}/verification.json" --registry "$ABSOLUTE_REGISTRY_MODULE")
|
|
33412
33450
|
if [[ -n "$ABSOLUTE_RELEASE_CHANNEL" ]]; then
|
|
33413
33451
|
args+=(--channel "$ABSOLUTE_RELEASE_CHANNEL")
|
|
33414
33452
|
fi
|
|
@@ -33436,7 +33474,7 @@ var iosJob = (options) => {
|
|
|
33436
33474
|
ios:
|
|
33437
33475
|
name: Signed iOS release
|
|
33438
33476
|
needs: validate
|
|
33439
|
-
if: \${{ ${jobCondition("ios")} }}
|
|
33477
|
+
if: \${{ ${jobCondition("ios", options.includePublishing)} }}
|
|
33440
33478
|
runs-on: macos-latest
|
|
33441
33479
|
environment: absolute-mobile-release
|
|
33442
33480
|
permissions:
|
|
@@ -33514,6 +33552,179 @@ ${certificationSteps}
|
|
|
33514
33552
|
rm -f "\${{ runner.temp }}/absolute.mobileprovision"
|
|
33515
33553
|
rm -f "\${{ runner.temp }}/AuthKey_AbsoluteJS.p8"`;
|
|
33516
33554
|
};
|
|
33555
|
+
var promotionValidationSteps = ` - name: Validate promotion handoff
|
|
33556
|
+
if: github.event_name == 'workflow_dispatch' && inputs.operation == 'promote'
|
|
33557
|
+
shell: bash
|
|
33558
|
+
run: |
|
|
33559
|
+
if [[ "$ABSOLUTE_PROMOTION_PLATFORM" == "all" ]]; then
|
|
33560
|
+
echo "Promotion requires one exact platform." >&2
|
|
33561
|
+
exit 1
|
|
33562
|
+
fi
|
|
33563
|
+
if [[ ! "$ABSOLUTE_SOURCE_RUN_ID" =~ ^[1-9][0-9]*$ ]]; then
|
|
33564
|
+
echo "Promotion requires a numeric source workflow run ID." >&2
|
|
33565
|
+
exit 1
|
|
33566
|
+
fi
|
|
33567
|
+
if [[ -z "$ABSOLUTE_CERTIFICATION_BASE64" ]]; then
|
|
33568
|
+
echo "Promotion requires certification supplied by absolute mobile ci promote." >&2
|
|
33569
|
+
exit 1
|
|
33570
|
+
fi`;
|
|
33571
|
+
var promotionSharedSteps = (platform3) => ` - name: Restore exact ${platform3 === "android" ? "Android" : "iOS"} release from source run
|
|
33572
|
+
uses: actions/download-artifact@v8
|
|
33573
|
+
with:
|
|
33574
|
+
name: absolute-mobile-${platform3}
|
|
33575
|
+
path: .absolutejs/mobile/releases/${platform3}
|
|
33576
|
+
run-id: \${{ inputs.source_run_id }}
|
|
33577
|
+
github-token: \${{ github.token }}
|
|
33578
|
+
- name: Import and verify exact certification
|
|
33579
|
+
shell: bash
|
|
33580
|
+
run: |
|
|
33581
|
+
mkdir -p .absolutejs/mobile-ci/imported-certification
|
|
33582
|
+
printf '%s' "$ABSOLUTE_CERTIFICATION_BASE64" | base64 --decode > .absolutejs/mobile-ci/imported-certification/certification.json
|
|
33583
|
+
shopt -s nullglob
|
|
33584
|
+
releases=(.absolutejs/mobile/releases/${platform3}/*)
|
|
33585
|
+
if [[ "\${#releases[@]}" -ne 1 || ! -d "\${releases[0]}" ]]; then
|
|
33586
|
+
echo "Expected exactly one immutable ${platform3} release directory from the source run." >&2
|
|
33587
|
+
exit 1
|
|
33588
|
+
fi
|
|
33589
|
+
args=(bunx absolute mobile certify "\${releases[0]}" --verify .absolutejs/mobile-ci/imported-certification/certification.json --json)
|
|
33590
|
+
"\${args[@]}" > .absolutejs/mobile-ci/imported-certification/verified.json
|
|
33591
|
+
- name: Install pinned Cosign
|
|
33592
|
+
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6
|
|
33593
|
+
with:
|
|
33594
|
+
cosign-release: v3.1.2
|
|
33595
|
+
- name: Sign certification with GitHub OIDC
|
|
33596
|
+
shell: bash
|
|
33597
|
+
run: |
|
|
33598
|
+
bunx @absolutejs/attest@0.2.0 sign-blobs .absolutejs/mobile-ci/imported-certification/certification.json
|
|
33599
|
+
bunx absolute mobile ci verification --bundle .absolutejs/mobile-ci/imported-certification/certification.json.sigstore.json --out .absolutejs/mobile-ci/imported-certification/verification.json`;
|
|
33600
|
+
var androidPromotionJob = (options) => {
|
|
33601
|
+
const custom = customSecretEnvironment(options.customSecrets);
|
|
33602
|
+
return `
|
|
33603
|
+
promote_android:
|
|
33604
|
+
name: Promote exact certified Android release
|
|
33605
|
+
needs: validate
|
|
33606
|
+
if: \${{ github.event_name == 'workflow_dispatch' && inputs.operation == 'promote' && inputs.platform == 'android' }}
|
|
33607
|
+
runs-on: ubuntu-latest
|
|
33608
|
+
environment: absolute-mobile-release
|
|
33609
|
+
permissions:
|
|
33610
|
+
actions: read
|
|
33611
|
+
contents: read
|
|
33612
|
+
id-token: write
|
|
33613
|
+
env:
|
|
33614
|
+
ABSOLUTE_CERTIFICATION_BASE64: \${{ inputs.certification_base64 }}
|
|
33615
|
+
ABSOLUTE_RELEASE_CHANNEL: \${{ inputs.channel }}
|
|
33616
|
+
ABSOLUTE_PLAY_TRACK: \${{ inputs.play_track }}
|
|
33617
|
+
ABSOLUTE_GOOGLE_CREDENTIALS_BASE64: \${{ secrets.ABSOLUTE_GOOGLE_CREDENTIALS_BASE64 }}
|
|
33618
|
+
GOOGLE_APPLICATION_CREDENTIALS: \${{ runner.temp }}/absolute-google-credentials.json${custom ? `
|
|
33619
|
+
${custom}` : ""}
|
|
33620
|
+
${commandEnvironment2({ configPath: undefined, registryModule: "", serverEntry: "" })}
|
|
33621
|
+
steps:
|
|
33622
|
+
${installSteps}
|
|
33623
|
+
${promotionSharedSteps("android")}
|
|
33624
|
+
- name: Publish restored Android release
|
|
33625
|
+
shell: bash
|
|
33626
|
+
run: |
|
|
33627
|
+
if [[ -n "$ABSOLUTE_RELEASE_CHANNEL" || "$ABSOLUTE_PLAY_TRACK" != "registry-only" ]]; then
|
|
33628
|
+
true
|
|
33629
|
+
else
|
|
33630
|
+
echo "Promotion requires a release channel or Google Play track." >&2
|
|
33631
|
+
exit 1
|
|
33632
|
+
fi
|
|
33633
|
+
if [[ "$ABSOLUTE_PLAY_TRACK" != "registry-only" ]]; then
|
|
33634
|
+
if [[ -z "$ABSOLUTE_GOOGLE_CREDENTIALS_BASE64" ]]; then
|
|
33635
|
+
echo "ABSOLUTE_GOOGLE_CREDENTIALS_BASE64 is required for Google Play publication." >&2
|
|
33636
|
+
exit 1
|
|
33637
|
+
fi
|
|
33638
|
+
printf '%s' "$ABSOLUTE_GOOGLE_CREDENTIALS_BASE64" | base64 --decode > "$GOOGLE_APPLICATION_CREDENTIALS"
|
|
33639
|
+
chmod 600 "$GOOGLE_APPLICATION_CREDENTIALS"
|
|
33640
|
+
fi
|
|
33641
|
+
shopt -s nullglob
|
|
33642
|
+
releases=(.absolutejs/mobile/releases/android/*)
|
|
33643
|
+
args=(bunx absolute mobile publish android --release "\${releases[0]}" --certification .absolutejs/mobile-ci/imported-certification/certification.json --certification-attestation .absolutejs/mobile-ci/imported-certification/verification.json --registry "$ABSOLUTE_REGISTRY_MODULE" --json)
|
|
33644
|
+
if [[ -n "$ABSOLUTE_RELEASE_CHANNEL" ]]; then args+=(--channel "$ABSOLUTE_RELEASE_CHANNEL"); fi
|
|
33645
|
+
if [[ "$ABSOLUTE_PLAY_TRACK" != "registry-only" ]]; then args+=(--play-track "$ABSOLUTE_PLAY_TRACK"); fi
|
|
33646
|
+
${appendConfigArgument}
|
|
33647
|
+
"\${args[@]}" > .absolutejs/mobile-ci/promotion-receipt.json
|
|
33648
|
+
- name: Upload Android promotion audit
|
|
33649
|
+
if: always()
|
|
33650
|
+
uses: actions/upload-artifact@v7
|
|
33651
|
+
with:
|
|
33652
|
+
name: absolute-mobile-android-promotion-\${{ github.run_id }}
|
|
33653
|
+
path: |
|
|
33654
|
+
.absolutejs/mobile-ci/imported-certification/
|
|
33655
|
+
.absolutejs/mobile-ci/promotion-receipt.json
|
|
33656
|
+
if-no-files-found: error
|
|
33657
|
+
retention-days: 90
|
|
33658
|
+
include-hidden-files: true
|
|
33659
|
+
- name: Remove Google credentials
|
|
33660
|
+
if: always()
|
|
33661
|
+
run: rm -f "\${{ runner.temp }}/absolute-google-credentials.json"`;
|
|
33662
|
+
};
|
|
33663
|
+
var iosPromotionJob = (options) => {
|
|
33664
|
+
const custom = customSecretEnvironment(options.customSecrets);
|
|
33665
|
+
return `
|
|
33666
|
+
promote_ios:
|
|
33667
|
+
name: Promote exact certified iOS release
|
|
33668
|
+
needs: validate
|
|
33669
|
+
if: \${{ github.event_name == 'workflow_dispatch' && inputs.operation == 'promote' && inputs.platform == 'ios' }}
|
|
33670
|
+
runs-on: ubuntu-latest
|
|
33671
|
+
environment: absolute-mobile-release
|
|
33672
|
+
permissions:
|
|
33673
|
+
actions: read
|
|
33674
|
+
contents: read
|
|
33675
|
+
id-token: write
|
|
33676
|
+
env:
|
|
33677
|
+
ABSOLUTE_CERTIFICATION_BASE64: \${{ inputs.certification_base64 }}
|
|
33678
|
+
ABSOLUTE_RELEASE_CHANNEL: \${{ inputs.channel }}
|
|
33679
|
+
ABSOLUTE_TESTFLIGHT_GROUP: \${{ inputs.testflight_group }}
|
|
33680
|
+
ABSOLUTE_TESTFLIGHT_SUBMIT_REVIEW: \${{ inputs.submit_testflight_review }}
|
|
33681
|
+
APP_STORE_CONNECT_ISSUER_ID: \${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
|
|
33682
|
+
APP_STORE_CONNECT_KEY_ID: \${{ secrets.APP_STORE_CONNECT_KEY_ID }}
|
|
33683
|
+
APP_STORE_CONNECT_PRIVATE_KEY_BASE64: \${{ secrets.APP_STORE_CONNECT_PRIVATE_KEY_BASE64 }}
|
|
33684
|
+
APP_STORE_CONNECT_PRIVATE_KEY_PATH: \${{ runner.temp }}/AuthKey_AbsoluteJS.p8${custom ? `
|
|
33685
|
+
${custom}` : ""}
|
|
33686
|
+
${commandEnvironment2({ configPath: undefined, registryModule: "", serverEntry: "" })}
|
|
33687
|
+
steps:
|
|
33688
|
+
${installSteps}
|
|
33689
|
+
${promotionSharedSteps("ios")}
|
|
33690
|
+
- name: Publish restored iOS release
|
|
33691
|
+
shell: bash
|
|
33692
|
+
run: |
|
|
33693
|
+
if [[ -z "$ABSOLUTE_RELEASE_CHANNEL" && -z "$ABSOLUTE_TESTFLIGHT_GROUP" ]]; then
|
|
33694
|
+
echo "Promotion requires a release channel or TestFlight group." >&2
|
|
33695
|
+
exit 1
|
|
33696
|
+
fi
|
|
33697
|
+
if [[ -n "$ABSOLUTE_TESTFLIGHT_GROUP" ]]; then
|
|
33698
|
+
required=(APP_STORE_CONNECT_ISSUER_ID APP_STORE_CONNECT_KEY_ID APP_STORE_CONNECT_PRIVATE_KEY_BASE64)
|
|
33699
|
+
for name in "\${required[@]}"; do
|
|
33700
|
+
if [[ -z "\${!name}" ]]; then echo "$name is required for TestFlight publication." >&2; exit 1; fi
|
|
33701
|
+
done
|
|
33702
|
+
printf '%s' "$APP_STORE_CONNECT_PRIVATE_KEY_BASE64" | base64 --decode > "$APP_STORE_CONNECT_PRIVATE_KEY_PATH"
|
|
33703
|
+
chmod 600 "$APP_STORE_CONNECT_PRIVATE_KEY_PATH"
|
|
33704
|
+
fi
|
|
33705
|
+
shopt -s nullglob
|
|
33706
|
+
releases=(.absolutejs/mobile/releases/ios/*)
|
|
33707
|
+
args=(bunx absolute mobile publish ios --release "\${releases[0]}" --certification .absolutejs/mobile-ci/imported-certification/certification.json --certification-attestation .absolutejs/mobile-ci/imported-certification/verification.json --registry "$ABSOLUTE_REGISTRY_MODULE" --json)
|
|
33708
|
+
if [[ -n "$ABSOLUTE_RELEASE_CHANNEL" ]]; then args+=(--channel "$ABSOLUTE_RELEASE_CHANNEL"); fi
|
|
33709
|
+
if [[ -n "$ABSOLUTE_TESTFLIGHT_GROUP" ]]; then args+=(--testflight-group "$ABSOLUTE_TESTFLIGHT_GROUP"); fi
|
|
33710
|
+
if [[ "$ABSOLUTE_TESTFLIGHT_SUBMIT_REVIEW" == "true" ]]; then args+=(--testflight-submit-review); fi
|
|
33711
|
+
${appendConfigArgument}
|
|
33712
|
+
"\${args[@]}" > .absolutejs/mobile-ci/promotion-receipt.json
|
|
33713
|
+
- name: Upload iOS promotion audit
|
|
33714
|
+
if: always()
|
|
33715
|
+
uses: actions/upload-artifact@v7
|
|
33716
|
+
with:
|
|
33717
|
+
name: absolute-mobile-ios-promotion-\${{ github.run_id }}
|
|
33718
|
+
path: |
|
|
33719
|
+
.absolutejs/mobile-ci/imported-certification/
|
|
33720
|
+
.absolutejs/mobile-ci/promotion-receipt.json
|
|
33721
|
+
if-no-files-found: error
|
|
33722
|
+
retention-days: 90
|
|
33723
|
+
include-hidden-files: true
|
|
33724
|
+
- name: Remove App Store Connect credentials
|
|
33725
|
+
if: always()
|
|
33726
|
+
run: rm -f "\${{ runner.temp }}/AuthKey_AbsoluteJS.p8"`;
|
|
33727
|
+
};
|
|
33517
33728
|
var requiredSecrets = (platforms, includePublishing, custom) => [
|
|
33518
33729
|
...platforms.includes("android") ? [
|
|
33519
33730
|
"ABSOLUTE_ANDROID_KEYSTORE_BASE64",
|
|
@@ -33575,10 +33786,14 @@ jobs:
|
|
|
33575
33786
|
permissions:
|
|
33576
33787
|
contents: read
|
|
33577
33788
|
env:
|
|
33578
|
-
${environment}
|
|
33789
|
+
${environment}${includePublishing ? `
|
|
33790
|
+
ABSOLUTE_PROMOTION_PLATFORM: \${{ inputs.platform }}
|
|
33791
|
+
ABSOLUTE_SOURCE_RUN_ID: \${{ inputs.source_run_id }}
|
|
33792
|
+
ABSOLUTE_CERTIFICATION_BASE64: \${{ inputs.certification_base64 }}` : ""}
|
|
33579
33793
|
steps:
|
|
33580
|
-
${installSteps}
|
|
33581
|
-
${
|
|
33794
|
+
${installSteps}${includePublishing ? `
|
|
33795
|
+
${promotionValidationSteps}` : ""}
|
|
33796
|
+
${bundleAuditSteps}${platforms.includes("android") ? androidJob({ customSecrets, includePublishing }) : ""}${platforms.includes("ios") ? iosJob({ customSecrets, includePublishing }) : ""}${includePublishing && platforms.includes("android") ? androidPromotionJob({ customSecrets, includePublishing }) : ""}${includePublishing && platforms.includes("ios") ? iosPromotionJob({ customSecrets, includePublishing }) : ""}
|
|
33582
33797
|
`;
|
|
33583
33798
|
const replacements = new Map([
|
|
33584
33799
|
[
|
|
@@ -35745,6 +35960,8 @@ This certification is local and contains no signing credentials, device identifi
|
|
|
35745
35960
|
${evidence}
|
|
35746
35961
|
`;
|
|
35747
35962
|
};
|
|
35963
|
+
var serializeAbsoluteMobileReleaseCertification = (certification) => `${JSON.stringify(certification, null, 2)}
|
|
35964
|
+
`;
|
|
35748
35965
|
var verifyAbsoluteMobileReleaseCertification = (certification, release, requirement) => {
|
|
35749
35966
|
const parsed = parseCertification(certification);
|
|
35750
35967
|
const expected = releaseIdentity(release);
|
|
@@ -35769,8 +35986,7 @@ var writeAbsoluteMobileReleaseCertification = async (projectRoot, certification,
|
|
|
35769
35986
|
jsonPath: join30(destination, "certification.json"),
|
|
35770
35987
|
markdownPath: join30(destination, "certification.md")
|
|
35771
35988
|
};
|
|
35772
|
-
const json =
|
|
35773
|
-
`;
|
|
35989
|
+
const json = serializeAbsoluteMobileReleaseCertification(certification);
|
|
35774
35990
|
const markdown = renderAbsoluteMobileReleaseCertification(certification);
|
|
35775
35991
|
const verifyExisting = async () => {
|
|
35776
35992
|
const [existingJson, existingMarkdown] = await Promise.all([
|
|
@@ -35805,9 +36021,110 @@ var writeAbsoluteMobileReleaseCertification = async (projectRoot, certification,
|
|
|
35805
36021
|
await verifyExisting();
|
|
35806
36022
|
return paths;
|
|
35807
36023
|
};
|
|
36024
|
+
// src/mobile/certificationVerification.ts
|
|
36025
|
+
import { access as access18, mkdir as mkdir21, readFile as readFile27, stat as stat6, writeFile as writeFile23 } from "fs/promises";
|
|
36026
|
+
import { dirname as dirname20, isAbsolute as isAbsolute10, relative as relative17, resolve as resolve19, sep as sep12 } from "path";
|
|
36027
|
+
var ABSOLUTE_MOBILE_CERTIFICATION_VERIFICATION_FORMAT = 1;
|
|
36028
|
+
var MAX_VERIFICATION_BYTES = 1048576;
|
|
36029
|
+
var SHA_PATTERN = /^[a-f0-9]{40}$/u;
|
|
36030
|
+
var REPOSITORY_PATTERN = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/u;
|
|
36031
|
+
var REF_PATTERN = /^refs\/(?:heads|tags)\/[^@\s]+$/u;
|
|
36032
|
+
var WORKFLOW_PATTERN = /^\.github\/workflows\/[^/@]+\.ya?ml$/u;
|
|
36033
|
+
var isRecord15 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36034
|
+
var required = (value, name) => {
|
|
36035
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
36036
|
+
throw new TypeError(`${name} is required.`);
|
|
36037
|
+
return value.trim();
|
|
36038
|
+
};
|
|
36039
|
+
var requireMatch = (value, pattern, name) => {
|
|
36040
|
+
if (!pattern.test(value))
|
|
36041
|
+
throw new TypeError(`${name} is invalid.`);
|
|
36042
|
+
return value;
|
|
36043
|
+
};
|
|
36044
|
+
var createAbsoluteMobileCertificationVerification = (bundle, environment) => {
|
|
36045
|
+
const repository = required(environment.GITHUB_REPOSITORY, "GITHUB_REPOSITORY");
|
|
36046
|
+
const workflowReference = required(environment.GITHUB_WORKFLOW_REF, "GITHUB_WORKFLOW_REF");
|
|
36047
|
+
const prefix = `${repository}/`;
|
|
36048
|
+
const separator = workflowReference.lastIndexOf("@");
|
|
36049
|
+
if (!workflowReference.startsWith(prefix) || separator <= prefix.length)
|
|
36050
|
+
throw new TypeError("GITHUB_WORKFLOW_REF is invalid.");
|
|
36051
|
+
return parseAbsoluteMobileCertificationVerification({
|
|
36052
|
+
bundle,
|
|
36053
|
+
format: ABSOLUTE_MOBILE_CERTIFICATION_VERIFICATION_FORMAT,
|
|
36054
|
+
identity: {
|
|
36055
|
+
issuer: "https://token.actions.githubusercontent.com",
|
|
36056
|
+
ref: environment.GITHUB_REF,
|
|
36057
|
+
repository,
|
|
36058
|
+
sha: environment.GITHUB_SHA,
|
|
36059
|
+
workflowPath: workflowReference.slice(prefix.length, separator)
|
|
36060
|
+
},
|
|
36061
|
+
kind: "sigstore-bundle"
|
|
36062
|
+
});
|
|
36063
|
+
};
|
|
36064
|
+
var parseAbsoluteMobileCertificationVerification = (value) => {
|
|
36065
|
+
if (!isRecord15(value) || value.format !== ABSOLUTE_MOBILE_CERTIFICATION_VERIFICATION_FORMAT || value.kind !== "sigstore-bundle" || !isRecord15(value.bundle) || !isRecord15(value.identity))
|
|
36066
|
+
throw new TypeError("Mobile certification verification contract is invalid.");
|
|
36067
|
+
const issuer = required(value.identity.issuer, "verification issuer");
|
|
36068
|
+
if (issuer !== "https://token.actions.githubusercontent.com")
|
|
36069
|
+
throw new TypeError("verification issuer is invalid.");
|
|
36070
|
+
const verification = {
|
|
36071
|
+
bundle: value.bundle,
|
|
36072
|
+
format: ABSOLUTE_MOBILE_CERTIFICATION_VERIFICATION_FORMAT,
|
|
36073
|
+
identity: {
|
|
36074
|
+
issuer,
|
|
36075
|
+
ref: requireMatch(required(value.identity.ref, "verification ref"), REF_PATTERN, "verification ref"),
|
|
36076
|
+
repository: requireMatch(required(value.identity.repository, "verification repository"), REPOSITORY_PATTERN, "verification repository"),
|
|
36077
|
+
sha: requireMatch(required(value.identity.sha, "verification sha"), SHA_PATTERN, "verification sha"),
|
|
36078
|
+
workflowPath: requireMatch(required(value.identity.workflowPath, "verification workflowPath"), WORKFLOW_PATTERN, "verification workflowPath")
|
|
36079
|
+
},
|
|
36080
|
+
kind: "sigstore-bundle"
|
|
36081
|
+
};
|
|
36082
|
+
const bytes = new TextEncoder().encode(JSON.stringify(verification));
|
|
36083
|
+
if (bytes.byteLength > MAX_VERIFICATION_BYTES)
|
|
36084
|
+
throw new TypeError("Mobile certification verification exceeds the 1 MiB limit.");
|
|
36085
|
+
return verification;
|
|
36086
|
+
};
|
|
36087
|
+
var projectFile = (projectRoot, requested) => {
|
|
36088
|
+
const root = resolve19(projectRoot);
|
|
36089
|
+
const path = resolve19(root, requested);
|
|
36090
|
+
const portable = relative17(root, path);
|
|
36091
|
+
if (portable === ".." || portable.startsWith(`..${sep12}`) || isAbsolute10(portable))
|
|
36092
|
+
throw new TypeError("Mobile certification verification path must remain inside the project.");
|
|
36093
|
+
return path;
|
|
36094
|
+
};
|
|
36095
|
+
var readAbsoluteMobileCertificationVerification = async (projectRoot, requested) => {
|
|
36096
|
+
const path = projectFile(projectRoot, requested);
|
|
36097
|
+
await access18(path).catch(() => {
|
|
36098
|
+
throw new TypeError(`Mobile certification verification does not exist: ${path}`);
|
|
36099
|
+
});
|
|
36100
|
+
const metadata = await stat6(path);
|
|
36101
|
+
if (!metadata.isFile() || metadata.size > MAX_VERIFICATION_BYTES)
|
|
36102
|
+
throw new TypeError("Mobile certification verification file is invalid.");
|
|
36103
|
+
return parseAbsoluteMobileCertificationVerification(JSON.parse(await readFile27(path, "utf8")));
|
|
36104
|
+
};
|
|
36105
|
+
var readAbsoluteSigstoreBundle = async (projectRoot, requested) => {
|
|
36106
|
+
const path = projectFile(projectRoot, requested);
|
|
36107
|
+
const metadata = await stat6(path).catch(() => null);
|
|
36108
|
+
if (!metadata?.isFile() || metadata.size > MAX_VERIFICATION_BYTES)
|
|
36109
|
+
throw new TypeError("Sigstore bundle file is invalid.");
|
|
36110
|
+
const value = JSON.parse(await readFile27(path, "utf8"));
|
|
36111
|
+
if (!isRecord15(value))
|
|
36112
|
+
throw new TypeError("Sigstore bundle is invalid.");
|
|
36113
|
+
return value;
|
|
36114
|
+
};
|
|
36115
|
+
var writeAbsoluteMobileCertificationVerification = async (projectRoot, requested, verification) => {
|
|
36116
|
+
const path = projectFile(projectRoot, requested);
|
|
36117
|
+
const parsed = parseAbsoluteMobileCertificationVerification(verification);
|
|
36118
|
+
await mkdir21(dirname20(path), { recursive: true });
|
|
36119
|
+
await writeFile23(path, `${JSON.stringify(parsed, null, 2)}
|
|
36120
|
+
`, {
|
|
36121
|
+
mode: 384
|
|
36122
|
+
});
|
|
36123
|
+
return path;
|
|
36124
|
+
};
|
|
35808
36125
|
// src/mobile/releasePublisher.ts
|
|
35809
|
-
import { access as
|
|
35810
|
-
import { isAbsolute as
|
|
36126
|
+
import { access as access19 } from "fs/promises";
|
|
36127
|
+
import { isAbsolute as isAbsolute11, relative as relative18, resolve as resolve20, sep as sep13 } from "path";
|
|
35811
36128
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
35812
36129
|
var prepareAbsoluteIosRelease = async (publisher, options) => {
|
|
35813
36130
|
if (typeof publisher.prepareIosRelease !== "function") {
|
|
@@ -35830,33 +36147,35 @@ var prepareAbsoluteAndroidRelease = async (publisher, options) => {
|
|
|
35830
36147
|
}
|
|
35831
36148
|
return versionCode;
|
|
35832
36149
|
};
|
|
35833
|
-
var requireCertificationReceipt = (publication, certification, requirement, releaseId) => {
|
|
35834
|
-
if (!certification && !requirement)
|
|
36150
|
+
var requireCertificationReceipt = (publication, certification, requirement, releaseId, verification) => {
|
|
36151
|
+
if (!certification && !requirement && !verification)
|
|
35835
36152
|
return;
|
|
35836
36153
|
if (!certification || !requirement)
|
|
35837
36154
|
throw new TypeError("Native release publication certification contract is incomplete.");
|
|
35838
36155
|
const receipt = publication.certification;
|
|
35839
36156
|
if (!receipt || receipt.certificationId !== certification.certificationId || receipt.releaseId !== releaseId || receipt.requirement !== requirement || receipt.strength !== certification.strength)
|
|
35840
36157
|
throw new TypeError("Native release registry did not retain the required release certification.");
|
|
36158
|
+
if (verification && (!receipt.provenance || receipt.provenance.subject !== releaseId))
|
|
36159
|
+
throw new TypeError("Native release registry did not retain trusted certification provenance.");
|
|
35841
36160
|
};
|
|
35842
|
-
var
|
|
35843
|
-
var isPublisher = (value) =>
|
|
36161
|
+
var isRecord16 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36162
|
+
var isPublisher = (value) => isRecord16(value) && typeof value.publish === "function";
|
|
35844
36163
|
var publisherModulePath = (projectRoot, requested) => {
|
|
35845
|
-
const root =
|
|
35846
|
-
const path =
|
|
35847
|
-
const projectRelative =
|
|
35848
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
36164
|
+
const root = resolve20(projectRoot);
|
|
36165
|
+
const path = resolve20(root, requested);
|
|
36166
|
+
const projectRelative = relative18(root, path);
|
|
36167
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep13}`) || isAbsolute11(projectRelative)) {
|
|
35849
36168
|
throw new TypeError("mobile publish --registry must remain inside the project.");
|
|
35850
36169
|
}
|
|
35851
36170
|
return path;
|
|
35852
36171
|
};
|
|
35853
36172
|
var loadAbsoluteNativeReleasePublisher = async (projectRoot, requestedModulePath) => {
|
|
35854
36173
|
const modulePath = publisherModulePath(projectRoot, requestedModulePath);
|
|
35855
|
-
await
|
|
36174
|
+
await access19(modulePath).catch(() => {
|
|
35856
36175
|
throw new TypeError(`Native release registry module does not exist: ${modulePath}`);
|
|
35857
36176
|
});
|
|
35858
36177
|
const loaded = await import(pathToFileURL3(modulePath).href);
|
|
35859
|
-
const publisher =
|
|
36178
|
+
const publisher = isRecord16(loaded) ? loaded.default ?? loaded.registry : undefined;
|
|
35860
36179
|
if (!isPublisher(publisher)) {
|
|
35861
36180
|
throw new TypeError("Native release registry module must default-export a registry with publish(options).");
|
|
35862
36181
|
}
|
|
@@ -35864,6 +36183,8 @@ var loadAbsoluteNativeReleasePublisher = async (projectRoot, requestedModulePath
|
|
|
35864
36183
|
};
|
|
35865
36184
|
var publishAbsoluteAndroidRelease = async (options) => {
|
|
35866
36185
|
const certificationRequirement = options.certificationRequirement ?? options.certification?.requirement;
|
|
36186
|
+
if (options.certificationVerification && !options.certification)
|
|
36187
|
+
throw new TypeError("Android certification verification requires certification.");
|
|
35867
36188
|
if (options.certification)
|
|
35868
36189
|
verifyAbsoluteMobileReleaseCertification(options.certification, options.release, certificationRequirement);
|
|
35869
36190
|
else if (certificationRequirement)
|
|
@@ -35873,6 +36194,7 @@ var publishAbsoluteAndroidRelease = async (options) => {
|
|
|
35873
36194
|
allowUnsigned: options.allowUnsigned,
|
|
35874
36195
|
certification: options.certification,
|
|
35875
36196
|
certificationRequirement,
|
|
36197
|
+
certificationVerification: options.certificationVerification,
|
|
35876
36198
|
channel: options.channel,
|
|
35877
36199
|
googlePlay: options.googlePlay,
|
|
35878
36200
|
releaseRoot: options.release.releaseRoot,
|
|
@@ -35883,7 +36205,7 @@ var publishAbsoluteAndroidRelease = async (options) => {
|
|
|
35883
36205
|
if (!actual || actual.appId !== expected.appId || actual.platform !== "android" || actual.releaseId !== expected.releaseId || actual.sha256 !== expected.sha256 || actual.signed !== expected.signed || actual.versionCode !== expected.versionCode || typeof publication.reused !== "boolean") {
|
|
35884
36206
|
throw new TypeError("Native release registry returned a different Android release identity.");
|
|
35885
36207
|
}
|
|
35886
|
-
requireCertificationReceipt(publication, options.certification, certificationRequirement, expected.releaseId);
|
|
36208
|
+
requireCertificationReceipt(publication, options.certification, certificationRequirement, expected.releaseId, options.certificationVerification);
|
|
35887
36209
|
if (options.channel !== undefined && (publication.channel?.channel !== options.channel || publication.channel.releaseId !== expected.releaseId)) {
|
|
35888
36210
|
throw new TypeError("Native release registry did not promote the requested channel.");
|
|
35889
36211
|
}
|
|
@@ -35897,6 +36219,8 @@ var publishAbsoluteAndroidRelease = async (options) => {
|
|
|
35897
36219
|
};
|
|
35898
36220
|
var publishAbsoluteIosRelease = async (options) => {
|
|
35899
36221
|
const certificationRequirement = options.certificationRequirement ?? options.certification?.requirement;
|
|
36222
|
+
if (options.certificationVerification && !options.certification)
|
|
36223
|
+
throw new TypeError("iOS certification verification requires certification.");
|
|
35900
36224
|
if (options.certification)
|
|
35901
36225
|
verifyAbsoluteMobileReleaseCertification(options.certification, options.release, certificationRequirement);
|
|
35902
36226
|
else if (certificationRequirement)
|
|
@@ -35907,6 +36231,7 @@ var publishAbsoluteIosRelease = async (options) => {
|
|
|
35907
36231
|
appStoreConnect: options.appStoreConnect,
|
|
35908
36232
|
certification: options.certification,
|
|
35909
36233
|
certificationRequirement,
|
|
36234
|
+
certificationVerification: options.certificationVerification,
|
|
35910
36235
|
channel: options.channel,
|
|
35911
36236
|
releaseRoot: options.release.releaseRoot,
|
|
35912
36237
|
signal: options.signal
|
|
@@ -35916,7 +36241,7 @@ var publishAbsoluteIosRelease = async (options) => {
|
|
|
35916
36241
|
if (!actual || actual.appId !== expected.appId || actual.platform !== "ios" || actual.releaseId !== expected.releaseId || actual.sha256 !== expected.sha256 || actual.signed !== expected.signed || actual.buildNumber !== expected.buildNumber || actual.marketingVersion !== expected.marketingVersion || typeof publication.reused !== "boolean") {
|
|
35917
36242
|
throw new TypeError("Native release registry returned a different iOS release identity.");
|
|
35918
36243
|
}
|
|
35919
|
-
requireCertificationReceipt(publication, options.certification, certificationRequirement, expected.releaseId);
|
|
36244
|
+
requireCertificationReceipt(publication, options.certification, certificationRequirement, expected.releaseId, options.certificationVerification);
|
|
35920
36245
|
if (options.channel !== undefined && (publication.channel?.channel !== options.channel || publication.channel.releaseId !== expected.releaseId)) {
|
|
35921
36246
|
throw new TypeError("Native release registry did not promote the requested channel.");
|
|
35922
36247
|
}
|
|
@@ -35932,7 +36257,7 @@ var publishAbsoluteIosRelease = async (options) => {
|
|
|
35932
36257
|
init_pageProtocol();
|
|
35933
36258
|
init_releaseArtifact();
|
|
35934
36259
|
import { existsSync as existsSync7, readFileSync as readFileSync8 } from "fs";
|
|
35935
|
-
import { dirname as
|
|
36260
|
+
import { dirname as dirname21, extname as extname6, relative as relative19, resolve as resolve21 } from "path";
|
|
35936
36261
|
import ts2 from "typescript";
|
|
35937
36262
|
var ROUTE_METHODS = new Set(["get", "head"]);
|
|
35938
36263
|
var SOURCE_FILTER = /\.[cm]?[jt]sx?$/;
|
|
@@ -35983,7 +36308,7 @@ var PAGE_HANDLERS = new Map([
|
|
|
35983
36308
|
]
|
|
35984
36309
|
]);
|
|
35985
36310
|
var posixPath = (value) => value.replace(/\\/g, "/");
|
|
35986
|
-
var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(
|
|
36311
|
+
var findTsconfig = (entry, projectRoot) => ts2.findConfigFile(dirname21(entry), existsSync7, "tsconfig.json") ?? ts2.findConfigFile(projectRoot, existsSync7, "tsconfig.json");
|
|
35987
36312
|
var createProgram = (entry, projectRoot) => {
|
|
35988
36313
|
const configPath2 = findTsconfig(entry, projectRoot);
|
|
35989
36314
|
if (!configPath2) {
|
|
@@ -35995,7 +36320,7 @@ var createProgram = (entry, projectRoot) => {
|
|
|
35995
36320
|
target: ts2.ScriptTarget.ESNext
|
|
35996
36321
|
});
|
|
35997
36322
|
}
|
|
35998
|
-
const parsed = ts2.parseJsonConfigFileContent(ts2.readConfigFile(configPath2, (path) => readFileSync8(path, "utf8")).config, ts2.sys,
|
|
36323
|
+
const parsed = ts2.parseJsonConfigFileContent(ts2.readConfigFile(configPath2, (path) => readFileSync8(path, "utf8")).config, ts2.sys, dirname21(configPath2));
|
|
35999
36324
|
if (!parsed.fileNames.includes(entry))
|
|
36000
36325
|
parsed.fileNames.push(entry);
|
|
36001
36326
|
return ts2.createProgram(parsed.fileNames, parsed.options);
|
|
@@ -36101,7 +36426,7 @@ var resolvePageIdentity = (expression, sourceFile, checker, projectRoot) => {
|
|
|
36101
36426
|
const declaration = symbol?.declarations?.[0];
|
|
36102
36427
|
const file = declaration?.getSourceFile().fileName ?? sourceFile.fileName;
|
|
36103
36428
|
const exportedName = symbol?.name ?? expression.getText(sourceFile);
|
|
36104
|
-
const source = posixPath(
|
|
36429
|
+
const source = posixPath(relative19(projectRoot, file));
|
|
36105
36430
|
return `${source}#${exportedName}`;
|
|
36106
36431
|
};
|
|
36107
36432
|
var resolveAlias = (symbol, checker) => {
|
|
@@ -36340,7 +36665,7 @@ var analyzeProgram = (program, projectRoot) => {
|
|
|
36340
36665
|
const checker = program.getTypeChecker();
|
|
36341
36666
|
const analyzed = new Map;
|
|
36342
36667
|
for (const sourceFile of program.getSourceFiles()) {
|
|
36343
|
-
const resolvedFile =
|
|
36668
|
+
const resolvedFile = resolve21(sourceFile.fileName);
|
|
36344
36669
|
if (!isProjectSource(sourceFile, resolvedFile, projectRoot))
|
|
36345
36670
|
continue;
|
|
36346
36671
|
const analysis = analyzeSourceFile(sourceFile, checker, projectRoot);
|
|
@@ -36433,14 +36758,14 @@ var transformFile = (source, fileName, analysis) => {
|
|
|
36433
36758
|
};
|
|
36434
36759
|
var ABSOLUTE_MOBILE_TRANSFORM_PROTOCOL = ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION;
|
|
36435
36760
|
var createAbsoluteMobileRouteMetadataPlugin = (options) => {
|
|
36436
|
-
const projectRoot =
|
|
36437
|
-
const entry =
|
|
36761
|
+
const projectRoot = resolve21(options.projectRoot ?? process.cwd());
|
|
36762
|
+
const entry = resolve21(options.entry);
|
|
36438
36763
|
const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
|
|
36439
36764
|
return {
|
|
36440
36765
|
name: "absolute-mobile-route-metadata",
|
|
36441
36766
|
setup(build) {
|
|
36442
36767
|
build.onLoad({ filter: SOURCE_FILTER }, async ({ path }) => {
|
|
36443
|
-
const analysis = analyzed.get(
|
|
36768
|
+
const analysis = analyzed.get(resolve21(path));
|
|
36444
36769
|
if (!analysis)
|
|
36445
36770
|
return;
|
|
36446
36771
|
const source = await Bun.file(path).text();
|
|
@@ -36453,11 +36778,11 @@ var createAbsoluteMobileRouteMetadataPlugin = (options) => {
|
|
|
36453
36778
|
};
|
|
36454
36779
|
};
|
|
36455
36780
|
var inspectAbsoluteMobileRouteMetadata = (options) => {
|
|
36456
|
-
const projectRoot =
|
|
36457
|
-
const entry =
|
|
36781
|
+
const projectRoot = resolve21(options.projectRoot ?? process.cwd());
|
|
36782
|
+
const entry = resolve21(options.entry);
|
|
36458
36783
|
const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
|
|
36459
36784
|
return [...analyzed.entries()].flatMap(([file, analysis]) => [...analysis.byRouteCall.values()].map(({ metadata }) => ({
|
|
36460
|
-
file: posixPath(
|
|
36785
|
+
file: posixPath(relative19(projectRoot, file)),
|
|
36461
36786
|
metadata
|
|
36462
36787
|
})));
|
|
36463
36788
|
};
|
|
@@ -36791,7 +37116,7 @@ var createCapacitor = (win) => {
|
|
|
36791
37116
|
callbackId
|
|
36792
37117
|
}, callback);
|
|
36793
37118
|
};
|
|
36794
|
-
const p = new Promise((
|
|
37119
|
+
const p = new Promise((resolve22) => call.then(() => resolve22({ remove })));
|
|
36795
37120
|
p.remove = async () => {
|
|
36796
37121
|
console.warn(`Using addListener() without 'await' is deprecated.`);
|
|
36797
37122
|
await remove();
|
|
@@ -36996,11 +37321,11 @@ class CapacitorCookiesPluginWeb extends WebPlugin {
|
|
|
36996
37321
|
var CapacitorCookies = registerPlugin("CapacitorCookies", {
|
|
36997
37322
|
web: () => new CapacitorCookiesPluginWeb
|
|
36998
37323
|
});
|
|
36999
|
-
var readBlobAsBase64 = async (blob) => new Promise((
|
|
37324
|
+
var readBlobAsBase64 = async (blob) => new Promise((resolve22, reject) => {
|
|
37000
37325
|
const reader = new FileReader;
|
|
37001
37326
|
reader.onload = () => {
|
|
37002
37327
|
const base64String = reader.result;
|
|
37003
|
-
|
|
37328
|
+
resolve22(base64String.indexOf(",") >= 0 ? base64String.split(",")[1] : base64String);
|
|
37004
37329
|
};
|
|
37005
37330
|
reader.onerror = (error) => reject(error);
|
|
37006
37331
|
reader.readAsDataURL(blob);
|
|
@@ -37176,7 +37501,7 @@ var REPORT_KINDS = new Set([
|
|
|
37176
37501
|
"signal"
|
|
37177
37502
|
]);
|
|
37178
37503
|
var nativeObservability = registerPlugin("AbsoluteMobileObservability");
|
|
37179
|
-
var
|
|
37504
|
+
var isRecord17 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
37180
37505
|
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]");
|
|
37181
37506
|
var redactValue = (value, depth = 0) => {
|
|
37182
37507
|
if (depth >= MAX_REDACTION_DEPTH)
|
|
@@ -37187,7 +37512,7 @@ var redactValue = (value, depth = 0) => {
|
|
|
37187
37512
|
return value;
|
|
37188
37513
|
if (Array.isArray(value))
|
|
37189
37514
|
return value.slice(0, 64).map((entry) => redactValue(entry, depth + 1));
|
|
37190
|
-
if (!
|
|
37515
|
+
if (!isRecord17(value))
|
|
37191
37516
|
return String(value).slice(0, MAX_STRING_LENGTH);
|
|
37192
37517
|
return Object.fromEntries(Object.entries(value).slice(0, 128).map(([key, entry]) => [
|
|
37193
37518
|
key,
|
|
@@ -37195,7 +37520,7 @@ var redactValue = (value, depth = 0) => {
|
|
|
37195
37520
|
]));
|
|
37196
37521
|
};
|
|
37197
37522
|
var parseReport = (value) => {
|
|
37198
|
-
if (!
|
|
37523
|
+
if (!isRecord17(value) || !isRecord17(value.details))
|
|
37199
37524
|
return;
|
|
37200
37525
|
if (typeof value.id !== "string" || !REPORT_ID.test(value.id))
|
|
37201
37526
|
return;
|
|
@@ -37206,7 +37531,7 @@ var parseReport = (value) => {
|
|
|
37206
37531
|
if (value.platform !== "android" && value.platform !== "ios")
|
|
37207
37532
|
return;
|
|
37208
37533
|
const details = redactValue(value.details);
|
|
37209
|
-
if (!
|
|
37534
|
+
if (!isRecord17(details))
|
|
37210
37535
|
return;
|
|
37211
37536
|
if (new TextEncoder().encode(JSON.stringify(details)).byteLength > MAX_DETAIL_BYTES)
|
|
37212
37537
|
return;
|
|
@@ -41660,8 +41985,8 @@ var createBeacon = (options) => {
|
|
|
41660
41985
|
if (await fontAvailable(element))
|
|
41661
41986
|
return;
|
|
41662
41987
|
if (confirmationMs > 0) {
|
|
41663
|
-
await new Promise((
|
|
41664
|
-
const timer2 = window.setTimeout(
|
|
41988
|
+
await new Promise((resolve22) => {
|
|
41989
|
+
const timer2 = window.setTimeout(resolve22, confirmationMs);
|
|
41665
41990
|
cleanups.push(() => window.clearTimeout(timer2));
|
|
41666
41991
|
});
|
|
41667
41992
|
if (document.visibilityState === "hidden")
|
|
@@ -42649,24 +42974,24 @@ var createAbsoluteMobileUpdateClient = (options) => {
|
|
|
42649
42974
|
};
|
|
42650
42975
|
};
|
|
42651
42976
|
// src/mobile/updatePublisher.ts
|
|
42652
|
-
import { access as
|
|
42653
|
-
import { isAbsolute as
|
|
42977
|
+
import { access as access20 } from "fs/promises";
|
|
42978
|
+
import { isAbsolute as isAbsolute12, relative as relative21, resolve as resolve23, sep as sep14 } from "path";
|
|
42654
42979
|
import { pathToFileURL as pathToFileURL4 } from "url";
|
|
42655
42980
|
|
|
42656
42981
|
// src/mobile/updateSigning.ts
|
|
42657
42982
|
import { createHash as createHash17, sign, verify } from "crypto";
|
|
42658
42983
|
import {
|
|
42659
42984
|
cp as cp2,
|
|
42660
|
-
mkdir as
|
|
42985
|
+
mkdir as mkdir22,
|
|
42661
42986
|
mkdtemp as mkdtemp11,
|
|
42662
42987
|
readdir as readdir10,
|
|
42663
|
-
readFile as
|
|
42988
|
+
readFile as readFile28,
|
|
42664
42989
|
rename as rename19,
|
|
42665
42990
|
rm as rm16,
|
|
42666
|
-
stat as
|
|
42667
|
-
writeFile as
|
|
42991
|
+
stat as stat7,
|
|
42992
|
+
writeFile as writeFile24
|
|
42668
42993
|
} from "fs/promises";
|
|
42669
|
-
import { dirname as
|
|
42994
|
+
import { dirname as dirname22, join as join31, relative as relative20, resolve as resolve22 } from "path";
|
|
42670
42995
|
var UPDATE_MANIFEST_FILE = "update.json";
|
|
42671
42996
|
var UPDATE_FILES_DIRECTORY = "files";
|
|
42672
42997
|
var sha2565 = (value) => createHash17("sha256").update(value).digest("hex");
|
|
@@ -42678,22 +43003,22 @@ var listFiles = async (root, directory = root) => {
|
|
|
42678
43003
|
return listFiles(root, path);
|
|
42679
43004
|
if (!entry.isFile())
|
|
42680
43005
|
throw new TypeError("Mobile updates cannot contain links or special files.");
|
|
42681
|
-
return [
|
|
43006
|
+
return [relative20(root, path).replaceAll("\\", "/")];
|
|
42682
43007
|
}));
|
|
42683
43008
|
return paths.flat().sort((left, right) => left.localeCompare(right));
|
|
42684
43009
|
};
|
|
42685
43010
|
var inspectFiles = async (root, paths) => Promise.all(paths.map(async (path) => {
|
|
42686
43011
|
const source = join31(root, path);
|
|
42687
43012
|
const [metadata, contents] = await Promise.all([
|
|
42688
|
-
|
|
42689
|
-
|
|
43013
|
+
stat7(source),
|
|
43014
|
+
readFile28(source)
|
|
42690
43015
|
]);
|
|
42691
43016
|
return { bytes: metadata.size, path, sha256: sha2565(contents) };
|
|
42692
43017
|
}));
|
|
42693
43018
|
var releaseIdFor = (value) => `amu_${sha2565(canonicalizeAbsoluteMobileUpdate(value))}`;
|
|
42694
43019
|
var buildAbsoluteMobileUpdate = async (options) => {
|
|
42695
|
-
const bundleDirectory =
|
|
42696
|
-
const outputRoot =
|
|
43020
|
+
const bundleDirectory = resolve22(options.bundleDirectory);
|
|
43021
|
+
const outputRoot = resolve22(options.outputDirectory);
|
|
42697
43022
|
if (outputRoot === bundleDirectory || outputRoot.startsWith(`${bundleDirectory}/`))
|
|
42698
43023
|
throw new TypeError("Mobile update output must be outside the embedded bundle.");
|
|
42699
43024
|
const paths = await listFiles(bundleDirectory);
|
|
@@ -42721,7 +43046,7 @@ var buildAbsoluteMobileUpdate = async (options) => {
|
|
|
42721
43046
|
value: signature.toString("base64")
|
|
42722
43047
|
}
|
|
42723
43048
|
});
|
|
42724
|
-
await
|
|
43049
|
+
await mkdir22(outputRoot, { recursive: true });
|
|
42725
43050
|
const outputDirectory = join31(outputRoot, manifest.releaseId);
|
|
42726
43051
|
const staging = await mkdtemp11(join31(outputRoot, ".stage-"));
|
|
42727
43052
|
try {
|
|
@@ -42729,7 +43054,7 @@ var buildAbsoluteMobileUpdate = async (options) => {
|
|
|
42729
43054
|
force: true,
|
|
42730
43055
|
recursive: true
|
|
42731
43056
|
});
|
|
42732
|
-
await
|
|
43057
|
+
await writeFile24(join31(staging, UPDATE_MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
|
|
42733
43058
|
`);
|
|
42734
43059
|
await rename19(staging, outputDirectory);
|
|
42735
43060
|
} catch (error) {
|
|
@@ -42745,14 +43070,14 @@ var buildAbsoluteMobileUpdate = async (options) => {
|
|
|
42745
43070
|
};
|
|
42746
43071
|
};
|
|
42747
43072
|
var copyAbsoluteMobileUpdateFile = async (updateDirectory, path, destination) => {
|
|
42748
|
-
const source =
|
|
42749
|
-
const root =
|
|
43073
|
+
const source = resolve22(updateDirectory, UPDATE_FILES_DIRECTORY, path);
|
|
43074
|
+
const root = resolve22(updateDirectory, UPDATE_FILES_DIRECTORY);
|
|
42750
43075
|
if (!source.startsWith(`${root}/`))
|
|
42751
43076
|
throw new TypeError("Update file escaped its release.");
|
|
42752
|
-
await
|
|
43077
|
+
await mkdir22(dirname22(destination), { recursive: true });
|
|
42753
43078
|
await cp2(source, destination, { force: true });
|
|
42754
43079
|
};
|
|
42755
|
-
var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await
|
|
43080
|
+
var readAbsoluteMobileUpdate = async (directory) => parseAbsoluteMobileUpdateManifest(JSON.parse(await readFile28(join31(resolve22(directory), UPDATE_MANIFEST_FILE), "utf8")));
|
|
42756
43081
|
var verifyAbsoluteMobileUpdateSignature = (manifestValue, publicKey) => {
|
|
42757
43082
|
const manifest = parseAbsoluteMobileUpdateManifest(manifestValue);
|
|
42758
43083
|
const valid = verify("sha256", absoluteMobileUpdateSigningPayload(unsignedAbsoluteMobileUpdate(manifest)), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64"));
|
|
@@ -42869,16 +43194,16 @@ var pruneAbsoluteMobileUpdates = async (options) => {
|
|
|
42869
43194
|
var object5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
42870
43195
|
var isPublisher2 = (value) => object5(value) && typeof value.publishUpdate === "function" && typeof value.promoteUpdate === "function" && typeof value.rollbackUpdate === "function";
|
|
42871
43196
|
var projectPath2 = (projectRoot, requested, label) => {
|
|
42872
|
-
const root =
|
|
42873
|
-
const path =
|
|
42874
|
-
const projectRelative =
|
|
42875
|
-
if (projectRelative === ".." || projectRelative.startsWith(`..${
|
|
43197
|
+
const root = resolve23(projectRoot);
|
|
43198
|
+
const path = resolve23(root, requested);
|
|
43199
|
+
const projectRelative = relative21(root, path);
|
|
43200
|
+
if (projectRelative === ".." || projectRelative.startsWith(`..${sep14}`) || isAbsolute12(projectRelative))
|
|
42876
43201
|
throw new TypeError(`${label} must remain inside the project.`);
|
|
42877
43202
|
return path;
|
|
42878
43203
|
};
|
|
42879
43204
|
var loadAbsoluteMobileUpdatePublisher = async (projectRoot, requestedModulePath) => {
|
|
42880
43205
|
const modulePath = projectPath2(projectRoot, requestedModulePath, "mobile update registry");
|
|
42881
|
-
await
|
|
43206
|
+
await access20(modulePath).catch(() => {
|
|
42882
43207
|
throw new TypeError(`Mobile update registry does not exist: ${modulePath}`);
|
|
42883
43208
|
});
|
|
42884
43209
|
const loaded = await import(pathToFileURL4(modulePath).href);
|
|
@@ -42984,6 +43309,7 @@ export {
|
|
|
42984
43309
|
ABSOLUTE_EXPO_UPDATE_FORMAT,
|
|
42985
43310
|
ABSOLUTE_IOS_RELEASE_FORMAT,
|
|
42986
43311
|
ABSOLUTE_IOS_SIMULATOR_NAME,
|
|
43312
|
+
ABSOLUTE_MOBILE_CERTIFICATION_VERIFICATION_FORMAT,
|
|
42987
43313
|
ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT,
|
|
42988
43314
|
ABSOLUTE_MOBILE_CLIENT_MANIFEST_FORMAT,
|
|
42989
43315
|
ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT,
|
|
@@ -43069,6 +43395,7 @@ export {
|
|
|
43069
43395
|
createAbsoluteMobileAssociationPlugin,
|
|
43070
43396
|
createAbsoluteMobileAuthManifest,
|
|
43071
43397
|
createAbsoluteMobileBlobArtifactStore,
|
|
43398
|
+
createAbsoluteMobileCertificationVerification,
|
|
43072
43399
|
createAbsoluteMobileCompatibilityArtifact,
|
|
43073
43400
|
createAbsoluteMobileCompatibilityDispatcher,
|
|
43074
43401
|
createAbsoluteMobileFileArtifactStore,
|
|
@@ -43160,6 +43487,7 @@ export {
|
|
|
43160
43487
|
parseAbsoluteIosInstalledAppInfo,
|
|
43161
43488
|
parseAbsoluteIosLogLine,
|
|
43162
43489
|
parseAbsoluteMobileBuildPageMetadata,
|
|
43490
|
+
parseAbsoluteMobileCertificationVerification,
|
|
43163
43491
|
parseAbsoluteMobileCompatibilityArtifact,
|
|
43164
43492
|
parseAbsoluteMobilePageEnvelope,
|
|
43165
43493
|
parseAbsoluteMobilePageRequest,
|
|
@@ -43185,10 +43513,12 @@ export {
|
|
|
43185
43513
|
publishAbsoluteMobileUpdate,
|
|
43186
43514
|
readAbsoluteAndroidRelease,
|
|
43187
43515
|
readAbsoluteIosRelease,
|
|
43516
|
+
readAbsoluteMobileCertificationVerification,
|
|
43188
43517
|
readAbsoluteMobileLinkIntent,
|
|
43189
43518
|
readAbsoluteMobileMaterializedReleases,
|
|
43190
43519
|
readAbsoluteMobileReleaseCertification,
|
|
43191
43520
|
readAbsoluteMobileUpdate,
|
|
43521
|
+
readAbsoluteSigstoreBundle,
|
|
43192
43522
|
reconcileAbsoluteMobileUpdateRollout,
|
|
43193
43523
|
redactAbsoluteIosLog,
|
|
43194
43524
|
removeAbsoluteRemoteMacProfile,
|
|
@@ -43217,6 +43547,7 @@ export {
|
|
|
43217
43547
|
runAbsoluteRemoteIosReleaseAcceptance,
|
|
43218
43548
|
runWithAbsoluteMobileProducer,
|
|
43219
43549
|
serializeAbsoluteMobileAuthEnvironment,
|
|
43550
|
+
serializeAbsoluteMobileReleaseCertification,
|
|
43220
43551
|
startAbsoluteExpoDevSession,
|
|
43221
43552
|
startAbsoluteIosCaEnrollmentServer,
|
|
43222
43553
|
startAbsoluteIosDevSession,
|
|
@@ -43238,10 +43569,11 @@ export {
|
|
|
43238
43569
|
waitForAbsoluteIosHmrLog,
|
|
43239
43570
|
writeAbsoluteCapacitorConfig,
|
|
43240
43571
|
writeAbsoluteExpoProject,
|
|
43572
|
+
writeAbsoluteMobileCertificationVerification,
|
|
43241
43573
|
writeAbsoluteMobileGithubWorkflow,
|
|
43242
43574
|
writeAbsoluteMobileReleaseCertification,
|
|
43243
43575
|
writeAbsoluteMobileUpdateRegistry
|
|
43244
43576
|
};
|
|
43245
43577
|
|
|
43246
|
-
//# debugId=
|
|
43578
|
+
//# debugId=F05777F8BA048C6164756E2164756E21
|
|
43247
43579
|
//# sourceMappingURL=index.js.map
|