@absolutejs/absolute 0.20.0-beta.81 → 0.20.0-beta.83
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/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/build.js +269 -17
- package/dist/build.js.map +4 -4
- package/dist/cli/index.js +1 -1
- package/dist/cli/{mobile-rdwdcks1.js → mobile-9dx39bd3.js} +184 -12
- package/dist/index.js +269 -17
- package/dist/index.js.map +4 -4
- package/dist/mobile/index.js +310 -17
- package/dist/mobile/index.js.map +5 -5
- package/dist/mobile/remoteMacAgentEntry.js +102 -102
- package/dist/src/mobile/updatePublisher.d.ts +19 -0
- package/dist/src/mobile/updateServer.d.ts +1 -0
- package/package.json +6 -2
package/dist/cli/index.js
CHANGED
|
@@ -203,7 +203,7 @@ if (command === "dev") {
|
|
|
203
203
|
sendTelemetryEvent("cli:command", {
|
|
204
204
|
command: `mobile:${workspaceCommand ?? "unknown"}`
|
|
205
205
|
});
|
|
206
|
-
const { runMobile } = await import("./mobile-
|
|
206
|
+
const { runMobile } = await import("./mobile-9dx39bd3.js");
|
|
207
207
|
try {
|
|
208
208
|
await runMobile(args);
|
|
209
209
|
} catch (error) {
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
installPackages
|
|
4
4
|
} from "./index-zh6hhrwy.js";
|
|
5
|
+
import {
|
|
6
|
+
formatBytes
|
|
7
|
+
} from "./index-9r7n9dqp.js";
|
|
5
8
|
import {
|
|
6
9
|
start
|
|
7
10
|
} from "./index-q78x1k9q.js";
|
|
@@ -19292,11 +19295,29 @@ var loadAbsoluteMobileUpdateServerModule = async (projectRoot, requestedModulePa
|
|
|
19292
19295
|
const registry = loaded.default ?? loaded.registry;
|
|
19293
19296
|
if (!isRegistry(registry))
|
|
19294
19297
|
throw new TypeError("Mobile update registry must implement publication, promotion, rollback, resolution, and file reads.");
|
|
19298
|
+
const metadata = serverMetadata(loaded.absoluteMobileUpdateServer);
|
|
19299
|
+
const verifier = loaded.verifyAbsoluteMobileUpdateServer;
|
|
19300
|
+
if (metadata.storage === "durable" && typeof verifier !== "function")
|
|
19301
|
+
throw new TypeError("Mobile update registries marked durable must export verifyAbsoluteMobileUpdateServer(). Re-run `absolute mobile update provision --storage s3 --force` or provide an active durability check.");
|
|
19295
19302
|
return {
|
|
19296
|
-
metadata
|
|
19297
|
-
registry
|
|
19303
|
+
metadata,
|
|
19304
|
+
registry,
|
|
19305
|
+
...typeof verifier === "function" ? {
|
|
19306
|
+
verifyDurability: async () => {
|
|
19307
|
+
await verifier();
|
|
19308
|
+
}
|
|
19309
|
+
} : {}
|
|
19298
19310
|
};
|
|
19299
19311
|
};
|
|
19312
|
+
var verifyDurableModule = async (module) => {
|
|
19313
|
+
if (module.metadata.storage !== "durable")
|
|
19314
|
+
throw new TypeError("Mobile production updates require durable object storage. Re-run `absolute mobile update provision --storage s3 --force` or configure a durable adapter.");
|
|
19315
|
+
try {
|
|
19316
|
+
await module.verifyDurability?.();
|
|
19317
|
+
} catch (error) {
|
|
19318
|
+
throw new TypeError(`Durable mobile update storage verification failed for ${module.metadata.provider}. Check the bucket, endpoint, credentials, and read/write/delete permissions.`, { cause: error });
|
|
19319
|
+
}
|
|
19320
|
+
};
|
|
19300
19321
|
var expoSigningOptions = (config) => {
|
|
19301
19322
|
if (!config.updates?.expoCodeSigning)
|
|
19302
19323
|
return;
|
|
@@ -19328,8 +19349,7 @@ var inspectAbsoluteMobileUpdateServer = async (config, projectRoot) => {
|
|
|
19328
19349
|
if (!config.updates)
|
|
19329
19350
|
return;
|
|
19330
19351
|
const module = await loadAbsoluteMobileUpdateServerModule(projectRoot, config.updateServer?.registryModule);
|
|
19331
|
-
|
|
19332
|
-
throw new TypeError("Mobile production updates require durable object storage; the configured registry is local-only.");
|
|
19352
|
+
await verifyDurableModule(module);
|
|
19333
19353
|
if (config.engine === "expo")
|
|
19334
19354
|
expoSigningOptions(config);
|
|
19335
19355
|
return module.metadata;
|
|
@@ -19358,7 +19378,8 @@ export default createMobileUpdateRegistry({
|
|
|
19358
19378
|
store
|
|
19359
19379
|
});
|
|
19360
19380
|
`;
|
|
19361
|
-
return `import {
|
|
19381
|
+
return `import { randomUUID } from 'node:crypto';
|
|
19382
|
+
import { DeleteObjectCommand, GetObjectCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
|
|
19362
19383
|
import { awsS3BlobStore } from '@absolutejs/blob/aws-s3';
|
|
19363
19384
|
import { createMobileUpdateRegistry } from '@absolutejs/deploy/mobile-update';
|
|
19364
19385
|
|
|
@@ -19370,6 +19391,7 @@ const required = (name: string) => {
|
|
|
19370
19391
|
return value;
|
|
19371
19392
|
};
|
|
19372
19393
|
|
|
19394
|
+
const bucket = required('ABSOLUTE_MOBILE_UPDATE_S3_BUCKET');
|
|
19373
19395
|
const client = new S3Client({
|
|
19374
19396
|
region: process.env.ABSOLUTE_MOBILE_UPDATE_S3_REGION ?? 'auto',
|
|
19375
19397
|
forcePathStyle: process.env.ABSOLUTE_MOBILE_UPDATE_S3_FORCE_PATH_STYLE === '1',
|
|
@@ -19377,10 +19399,22 @@ const client = new S3Client({
|
|
|
19377
19399
|
? { endpoint: process.env.ABSOLUTE_MOBILE_UPDATE_S3_ENDPOINT }
|
|
19378
19400
|
: {})
|
|
19379
19401
|
});
|
|
19380
|
-
const store = awsS3BlobStore({
|
|
19381
|
-
|
|
19382
|
-
|
|
19383
|
-
}
|
|
19402
|
+
const store = awsS3BlobStore({ bucket, client });
|
|
19403
|
+
|
|
19404
|
+
export const verifyAbsoluteMobileUpdateServer = async () => {
|
|
19405
|
+
const key = \`absolutejs/mobile-updates/_health/\${randomUUID()}\`;
|
|
19406
|
+
const expected = randomUUID();
|
|
19407
|
+
let stored = false;
|
|
19408
|
+
try {
|
|
19409
|
+
await client.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: expected }));
|
|
19410
|
+
stored = true;
|
|
19411
|
+
const response = await client.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
|
|
19412
|
+
if ((await response.Body?.transformToString()) !== expected)
|
|
19413
|
+
throw new Error('Durability probe read did not match its write.');
|
|
19414
|
+
} finally {
|
|
19415
|
+
if (stored) await client.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));
|
|
19416
|
+
}
|
|
19417
|
+
};
|
|
19384
19418
|
|
|
19385
19419
|
export default createMobileUpdateRegistry({
|
|
19386
19420
|
publicKeys: ${publicKeysSource(options.publicKeys)},
|
|
@@ -19468,7 +19502,7 @@ var mobileUpdateServerCheck = async (config, projectRoot) => {
|
|
|
19468
19502
|
return;
|
|
19469
19503
|
try {
|
|
19470
19504
|
const metadata = await inspectAbsoluteMobileUpdateServer(config, projectRoot);
|
|
19471
|
-
return pass("updates.trusted-server", `The trusted update server
|
|
19505
|
+
return pass("updates.trusted-server", `The trusted update server proved durable ${metadata?.provider ?? "object"} storage read/write/delete access, supports publish/promote/rollback, and has valid server-only signing material.`, config.updateServer?.registryModule);
|
|
19472
19506
|
} catch (error) {
|
|
19473
19507
|
return fail("updates.trusted-server", error instanceof Error ? error.message : "The trusted mobile update server is not release-ready.", config.updateServer?.registryModule ?? "mobile.update.ts", "Run `absolute mobile update provision --storage s3 --force`, provision its environment variables on the trusted server, and rerun the release doctor.");
|
|
19474
19508
|
}
|
|
@@ -21954,6 +21988,45 @@ var generateAbsoluteExpoCodeSigning = async (options) => {
|
|
|
21954
21988
|
import { access as access11 } from "fs/promises";
|
|
21955
21989
|
import { isAbsolute as isAbsolute5, relative as relative10, resolve as resolve11, sep as sep6 } from "path";
|
|
21956
21990
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
21991
|
+
var lifecycleMethod = (publisher, name) => {
|
|
21992
|
+
const method = publisher[name];
|
|
21993
|
+
if (typeof method !== "function")
|
|
21994
|
+
throw new TypeError(`Mobile update registry does not support ${name}. Re-run \`absolute mobile update provision --force\` after upgrading @absolutejs/deploy.`);
|
|
21995
|
+
return method;
|
|
21996
|
+
};
|
|
21997
|
+
var validateStorageIdentity = (result, appId) => {
|
|
21998
|
+
if (!object3(result) || result.appId !== appId || !Array.isArray(result.releases) || ![
|
|
21999
|
+
result.channelCount,
|
|
22000
|
+
result.reclaimableBytes,
|
|
22001
|
+
result.releaseBytes,
|
|
22002
|
+
result.releaseCount,
|
|
22003
|
+
result.totalBytes,
|
|
22004
|
+
result.totalObjectCount,
|
|
22005
|
+
result.untrackedBytes
|
|
22006
|
+
].every((value) => Number.isSafeInteger(value) && value >= 0))
|
|
22007
|
+
throw new TypeError("Mobile update registry returned an invalid storage report.");
|
|
22008
|
+
return result;
|
|
22009
|
+
};
|
|
22010
|
+
var inspectAbsoluteMobileUpdateStorage = async (options) => validateStorageIdentity(await lifecycleMethod(options.publisher, "inspectUpdateStorage")({
|
|
22011
|
+
appId: options.appId,
|
|
22012
|
+
...options.minAgeMs === undefined ? {} : { minAgeMs: options.minAgeMs },
|
|
22013
|
+
...options.retainRecent === undefined ? {} : { retainRecent: options.retainRecent },
|
|
22014
|
+
...options.signal ? { signal: options.signal } : {}
|
|
22015
|
+
}), options.appId);
|
|
22016
|
+
var pruneAbsoluteMobileUpdates = async (options) => {
|
|
22017
|
+
const result = await lifecycleMethod(options.publisher, "pruneUpdates")({
|
|
22018
|
+
appId: options.appId,
|
|
22019
|
+
...options.apply === undefined ? {} : { apply: options.apply },
|
|
22020
|
+
...options.gracePeriodMs === undefined ? {} : { gracePeriodMs: options.gracePeriodMs },
|
|
22021
|
+
...options.minAgeMs === undefined ? {} : { minAgeMs: options.minAgeMs },
|
|
22022
|
+
...options.retainRecent === undefined ? {} : { retainRecent: options.retainRecent },
|
|
22023
|
+
...options.signal ? { signal: options.signal } : {}
|
|
22024
|
+
});
|
|
22025
|
+
validateStorageIdentity(result, options.appId);
|
|
22026
|
+
if (!Array.isArray(result.marked) || !Array.isArray(result.restored) || !Array.isArray(result.swept) || typeof result.dryRun !== "boolean" || !Number.isSafeInteger(result.reclaimedBytes) || result.reclaimedBytes < 0)
|
|
22027
|
+
throw new TypeError("Mobile update registry returned an invalid collection report.");
|
|
22028
|
+
return result;
|
|
22029
|
+
};
|
|
21957
22030
|
var object3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21958
22031
|
var isPublisher2 = (value) => object3(value) && typeof value.publishUpdate === "function" && typeof value.promoteUpdate === "function" && typeof value.rollbackUpdate === "function";
|
|
21959
22032
|
var projectPath3 = (projectRoot, requested, label) => {
|
|
@@ -22710,7 +22783,7 @@ var provisionMobileUpdate = async (args) => {
|
|
|
22710
22783
|
throw new TypeError("--storage must be local or s3.");
|
|
22711
22784
|
const modulePath = valueAfter(args, "--registry") ?? mobile.updateServer.registryModule;
|
|
22712
22785
|
const packages = [
|
|
22713
|
-
"@absolutejs/deploy@0.25.
|
|
22786
|
+
"@absolutejs/deploy@0.25.7",
|
|
22714
22787
|
"@absolutejs/blob@0.5.2",
|
|
22715
22788
|
...requestedStorage === "s3" ? [
|
|
22716
22789
|
"@aws-sdk/client-s3@3.1095.0",
|
|
@@ -22794,6 +22867,97 @@ var rollbackMobileUpdate = async (args) => {
|
|
|
22794
22867
|
console.log(result.releaseId ? `Rolled ${result.channel} back to ${result.releaseId}.` : `Rolled ${result.channel} back to the embedded store build.`);
|
|
22795
22868
|
return result;
|
|
22796
22869
|
};
|
|
22870
|
+
var mobileUpdateDays = (args, flag) => {
|
|
22871
|
+
const value = valueAfter(args, flag);
|
|
22872
|
+
if (value === undefined)
|
|
22873
|
+
return;
|
|
22874
|
+
const parsed = Number(value);
|
|
22875
|
+
const milliseconds = parsed * 24 * 60 * 60 * 1000;
|
|
22876
|
+
if (!Number.isFinite(parsed) || parsed < 0 || !Number.isSafeInteger(milliseconds))
|
|
22877
|
+
throw new TypeError(`${flag} must be a non-negative number of days.`);
|
|
22878
|
+
return milliseconds;
|
|
22879
|
+
};
|
|
22880
|
+
var mobileUpdateRetention = (args) => {
|
|
22881
|
+
const retainedValue = valueAfter(args, "--retain");
|
|
22882
|
+
const retainRecent = retainedValue === undefined ? undefined : Number(retainedValue);
|
|
22883
|
+
if (retainRecent !== undefined && (!Number.isSafeInteger(retainRecent) || retainRecent < 0))
|
|
22884
|
+
throw new TypeError("--retain must be a non-negative integer.");
|
|
22885
|
+
return {
|
|
22886
|
+
minAgeMs: mobileUpdateDays(args, "--min-age-days"),
|
|
22887
|
+
retainRecent
|
|
22888
|
+
};
|
|
22889
|
+
};
|
|
22890
|
+
var printMobileUpdateStorage = (report) => {
|
|
22891
|
+
console.log(`${report.appId}: ${report.releaseCount} releases use ${formatBytes(report.releaseBytes)}; ${formatBytes(report.reclaimableBytes)} is eligible across ${report.totalObjectCount} stored objects.`);
|
|
22892
|
+
for (const release of report.releases) {
|
|
22893
|
+
let state = "eligible";
|
|
22894
|
+
if (release.protectedBy.length > 0)
|
|
22895
|
+
state = `kept: ${release.protectedBy.join(", ")}`;
|
|
22896
|
+
else if (release.markedAt)
|
|
22897
|
+
state = `marked ${release.markedAt}`;
|
|
22898
|
+
console.log(` ${release.releaseId} ${release.channel} ${formatBytes(release.bytes)} (${state})`);
|
|
22899
|
+
}
|
|
22900
|
+
if (report.untrackedBytes > 0)
|
|
22901
|
+
console.log(`${formatBytes(report.untrackedBytes)} is used by channels, collection markers, or incomplete/unrecognized objects and will not be swept as a release.`);
|
|
22902
|
+
};
|
|
22903
|
+
var inspectMobileUpdateStorage = async (args) => {
|
|
22904
|
+
const startedAt = performance.now();
|
|
22905
|
+
const { mobile } = await loadMobile(valueAfter(args, "--config"));
|
|
22906
|
+
if (!mobile.updates)
|
|
22907
|
+
throw new TypeError("mobile update storage requires mobile.updates config.");
|
|
22908
|
+
const policy = mobileUpdateRetention(args);
|
|
22909
|
+
const { publisher } = await mobileUpdatePublisher(args);
|
|
22910
|
+
const report = await inspectAbsoluteMobileUpdateStorage({
|
|
22911
|
+
appId: mobile.appId,
|
|
22912
|
+
publisher,
|
|
22913
|
+
...policy.minAgeMs === undefined ? {} : { minAgeMs: policy.minAgeMs },
|
|
22914
|
+
...policy.retainRecent === undefined ? {} : { retainRecent: policy.retainRecent }
|
|
22915
|
+
});
|
|
22916
|
+
if (args.includes("--json"))
|
|
22917
|
+
console.log(JSON.stringify(report, null, 2));
|
|
22918
|
+
else
|
|
22919
|
+
printMobileUpdateStorage(report);
|
|
22920
|
+
sendTelemetryEvent("mobile:update-storage", {
|
|
22921
|
+
durationMs: Math.round(performance.now() - startedAt),
|
|
22922
|
+
reclaimableReleaseCount: report.releases.filter((release) => release.protectedBy.length === 0).length,
|
|
22923
|
+
releaseCount: report.releaseCount
|
|
22924
|
+
});
|
|
22925
|
+
return report;
|
|
22926
|
+
};
|
|
22927
|
+
var collectMobileUpdates = async (args) => {
|
|
22928
|
+
const startedAt = performance.now();
|
|
22929
|
+
const { mobile } = await loadMobile(valueAfter(args, "--config"));
|
|
22930
|
+
if (!mobile.updates)
|
|
22931
|
+
throw new TypeError("mobile update gc requires mobile.updates config.");
|
|
22932
|
+
const policy = mobileUpdateRetention(args);
|
|
22933
|
+
const gracePeriodMs = mobileUpdateDays(args, "--grace-days");
|
|
22934
|
+
const { publisher } = await mobileUpdatePublisher(args);
|
|
22935
|
+
const result = await pruneAbsoluteMobileUpdates({
|
|
22936
|
+
appId: mobile.appId,
|
|
22937
|
+
apply: args.includes("--apply"),
|
|
22938
|
+
publisher,
|
|
22939
|
+
...gracePeriodMs === undefined ? {} : { gracePeriodMs },
|
|
22940
|
+
...policy.minAgeMs === undefined ? {} : { minAgeMs: policy.minAgeMs },
|
|
22941
|
+
...policy.retainRecent === undefined ? {} : { retainRecent: policy.retainRecent }
|
|
22942
|
+
});
|
|
22943
|
+
if (args.includes("--json"))
|
|
22944
|
+
console.log(JSON.stringify(result, null, 2));
|
|
22945
|
+
else {
|
|
22946
|
+
printMobileUpdateStorage(result);
|
|
22947
|
+
if (result.dryRun)
|
|
22948
|
+
console.log("No storage was changed. Re-run with --apply to mark eligible releases and sweep releases whose grace period has elapsed.");
|
|
22949
|
+
else
|
|
22950
|
+
console.log(`Collection applied: ${result.marked.length} marked, ${result.restored.length} restored, ${result.swept.length} swept, ${formatBytes(result.reclaimedBytes)} reclaimed.`);
|
|
22951
|
+
}
|
|
22952
|
+
sendTelemetryEvent("mobile:update-gc", {
|
|
22953
|
+
applied: !result.dryRun,
|
|
22954
|
+
durationMs: Math.round(performance.now() - startedAt),
|
|
22955
|
+
markedCount: result.marked.length,
|
|
22956
|
+
restoredCount: result.restored.length,
|
|
22957
|
+
sweptCount: result.swept.length
|
|
22958
|
+
});
|
|
22959
|
+
return result;
|
|
22960
|
+
};
|
|
22797
22961
|
var requireValueAfter = (args, flag) => {
|
|
22798
22962
|
const value = valueAfter(args, flag);
|
|
22799
22963
|
if (!value || value.startsWith("-")) {
|
|
@@ -24134,6 +24298,14 @@ var runMobile = async (args) => {
|
|
|
24134
24298
|
await rollbackMobileUpdate(args.slice(2));
|
|
24135
24299
|
return;
|
|
24136
24300
|
}
|
|
24301
|
+
if (command === "update" && args[1] === "storage") {
|
|
24302
|
+
await inspectMobileUpdateStorage(args.slice(2));
|
|
24303
|
+
return;
|
|
24304
|
+
}
|
|
24305
|
+
if (command === "update" && args[1] === "gc") {
|
|
24306
|
+
await collectMobileUpdates(args.slice(2));
|
|
24307
|
+
return;
|
|
24308
|
+
}
|
|
24137
24309
|
if (command === "publish" && args[1] === "android") {
|
|
24138
24310
|
await publishAndroid(args.slice(2));
|
|
24139
24311
|
return;
|
|
@@ -24142,7 +24314,7 @@ var runMobile = async (args) => {
|
|
|
24142
24314
|
await publishIos(args.slice(2));
|
|
24143
24315
|
return;
|
|
24144
24316
|
}
|
|
24145
|
-
throw new TypeError("Usage: absolute mobile <pair mac <name> <user@host> [--port n] [--workspace path] | remotes [inspect [name] [--json] | clean [name] --yes | --json] | unpair mac <name> | init [--no-native] [--force] | sync [ios|android] | inspect [--json] [--require-bundle] | associations [--outdir dir] [--verify] | ci github [server-entry] [--publish] [--registry module] [--secret-env NAME] [--output path] [--force] [--json] | doctor [ios|android|release [ios|android]] [--remote name] [--json|--fix [--yes]] | build <android|ios> [server-entry] [--remote name] [--outdir dir] [--web-outdir dir] [--unsigned] | update provision [--storage local|s3] [--registry module] [--force] [--yes] | update signing generate --private-key path [--certificate path] [--public-key path] [--key-id id] [--common-name name] [--validity-years n] | update build [server-entry] --classification bug-fix|content|security --key-id id --signing-key path --within-submitted-purpose [--outdir dir] [--web-outdir dir] | update publish <release-directory> [--rollout fraction] [--registry module] | update promote --release id --rollout fraction [--registry module] | update rollback [--release id] [--registry module] | publish android [server-entry] [--registry module] [--channel name] [--play-track track] [--play-status completed|draft|halted|in-progress] [--play-rollout fraction] [--play-name name] [--play-notes language=text] [--play-update-priority 0..5] [--play-hold-review] [--play-cancel-existing-review] [--outdir dir] [--web-outdir dir] [--unsigned] | publish ios [server-entry] [--remote name] [--registry module] [--channel name] [--testflight-group name-or-id] [--testflight-notes locale=text] [--testflight-submit-review] [--outdir dir] [--web-outdir dir] [--unsigned] | test android [--route path] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--serial id] [--artifacts dir] [--json] | test ios [--device identifier [--remote name] | --udid id] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--artifacts dir] [--json]> [--config path]");
|
|
24317
|
+
throw new TypeError("Usage: absolute mobile <pair mac <name> <user@host> [--port n] [--workspace path] | remotes [inspect [name] [--json] | clean [name] --yes | --json] | unpair mac <name> | init [--no-native] [--force] | sync [ios|android] | inspect [--json] [--require-bundle] | associations [--outdir dir] [--verify] | ci github [server-entry] [--publish] [--registry module] [--secret-env NAME] [--output path] [--force] [--json] | doctor [ios|android|release [ios|android]] [--remote name] [--json|--fix [--yes]] | build <android|ios> [server-entry] [--remote name] [--outdir dir] [--web-outdir dir] [--unsigned] | update provision [--storage local|s3] [--registry module] [--force] [--yes] | update signing generate --private-key path [--certificate path] [--public-key path] [--key-id id] [--common-name name] [--validity-years n] | update build [server-entry] --classification bug-fix|content|security --key-id id --signing-key path --within-submitted-purpose [--outdir dir] [--web-outdir dir] | update publish <release-directory> [--rollout fraction] [--registry module] | update promote --release id --rollout fraction [--registry module] | update rollback [--release id] [--registry module] | update storage [--retain count] [--min-age-days days] [--registry module] [--json] | update gc [--retain count] [--min-age-days days] [--grace-days days] [--apply] [--registry module] [--json] | publish android [server-entry] [--registry module] [--channel name] [--play-track track] [--play-status completed|draft|halted|in-progress] [--play-rollout fraction] [--play-name name] [--play-notes language=text] [--play-update-priority 0..5] [--play-hold-review] [--play-cancel-existing-review] [--outdir dir] [--web-outdir dir] [--unsigned] | publish ios [server-entry] [--remote name] [--registry module] [--channel name] [--testflight-group name-or-id] [--testflight-notes locale=text] [--testflight-submit-review] [--outdir dir] [--web-outdir dir] [--unsigned] | test android [--route path] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--serial id] [--artifacts dir] [--json] | test ios [--device identifier [--remote name] | --udid id] [--wait-for-hmr] [--report [dir]] [--timeout ms] [--port n] [--artifacts dir] [--json]> [--config path]");
|
|
24146
24318
|
};
|
|
24147
24319
|
export {
|
|
24148
24320
|
runMobile
|