@absolutejs/absolute 0.20.0-beta.86 → 0.20.0-beta.88
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 +350 -33
- package/dist/build.js.map +5 -5
- package/dist/cli/{compile-e9cn3xpx.js → compile-5hchbcbd.js} +2 -2
- package/dist/cli/{config-z2kf085h.js → config-vy04mqce.js} +1 -1
- package/dist/cli/{dev-3hweza3s.js → dev-6shm8qsn.js} +1 -1
- package/dist/cli/{index-9rk7v35t.js → index-39j0dhq7.js} +2 -2
- package/dist/cli/{index-x48brywr.js → index-jqdt7841.js} +1 -1
- package/dist/cli/{index-3tsmbyze.js → index-rd2hbttb.js} +45 -0
- package/dist/cli/index.js +5 -5
- package/dist/cli/{mobile-2p3z33t1.js → mobile-bg1jy34n.js} +151 -28
- package/dist/cli/{start-7t186mhg.js → start-7jg0csqy.js} +3 -3
- package/dist/index.js +350 -33
- package/dist/index.js.map +5 -5
- package/dist/mobile/index.js +405 -45
- package/dist/mobile/index.js.map +7 -7
- package/dist/mobile/remoteMacAgentEntry.js +167 -167
- package/dist/mobile/shellAuth.js +79 -1
- package/dist/mobile/shellUpdate.js +50 -11
- package/dist/src/mobile/config.d.ts +9 -0
- package/dist/src/mobile/shellAuth.d.ts +8 -0
- package/dist/src/mobile/updatePublisher.d.ts +67 -1
- package/dist/src/mobile/updateServer.d.ts +18 -0
- package/dist/types/build.d.ts +16 -0
- package/package.json +2 -2
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
createIslandRegistryDefinitionPlugin,
|
|
13
13
|
finalizeAbsoluteMobileCompatibilityBuild,
|
|
14
14
|
resolveServerBundleExternals
|
|
15
|
-
} from "./index-
|
|
15
|
+
} from "./index-jqdt7841.js";
|
|
16
16
|
import {
|
|
17
17
|
loadIslandRegistryBuildInfo
|
|
18
18
|
} from "./index-bzs19w3r.js";
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
import"./index-w5vswatm.js";
|
|
36
36
|
import {
|
|
37
37
|
normalizeAbsoluteMobileConfig
|
|
38
|
-
} from "./index-
|
|
38
|
+
} from "./index-rd2hbttb.js";
|
|
39
39
|
import"./index-tame6e2c.js";
|
|
40
40
|
import {
|
|
41
41
|
ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV,
|
|
@@ -1281,7 +1281,7 @@ var loadAbsoluteMobileDevModules = async () => {
|
|
|
1281
1281
|
remoteMacProtocol,
|
|
1282
1282
|
iosNativeWatcher
|
|
1283
1283
|
] = await Promise.all([
|
|
1284
|
-
import("./config-
|
|
1284
|
+
import("./config-vy04mqce.js"),
|
|
1285
1285
|
import("./expoProject-dac8fqhq.js"),
|
|
1286
1286
|
import("./expoDevController-n19kb5fr.js"),
|
|
1287
1287
|
import("./nativeAuth-zx4tsb1f.js"),
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
createIslandRegistryDefinitionPlugin,
|
|
7
7
|
finalizeAbsoluteMobileCompatibilityBuild,
|
|
8
8
|
resolveServerBundleExternals
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-jqdt7841.js";
|
|
10
10
|
import {
|
|
11
11
|
loadIslandRegistryBuildInfo
|
|
12
12
|
} from "./index-bzs19w3r.js";
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
} from "./index-9kwmb3c0.js";
|
|
27
27
|
import {
|
|
28
28
|
normalizeAbsoluteMobileConfig
|
|
29
|
-
} from "./index-
|
|
29
|
+
} from "./index-rd2hbttb.js";
|
|
30
30
|
import {
|
|
31
31
|
installAbsoluteMobileAuthEnvironment
|
|
32
32
|
} from "./index-ar4gz15x.js";
|
|
@@ -13,6 +13,14 @@ var ENVIRONMENT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/u;
|
|
|
13
13
|
var DEFAULT_UPDATE_BOOT_TIMEOUT_MS = 20000;
|
|
14
14
|
var DEFAULT_UPDATE_HEALTH_FAILURE_RATE = 0.2;
|
|
15
15
|
var DEFAULT_UPDATE_HEALTH_MINIMUM_REPORTS = 20;
|
|
16
|
+
var DEFAULT_UPDATE_ROLLOUT_FAILURE_RATE = 0.05;
|
|
17
|
+
var DEFAULT_UPDATE_ROLLOUT_OBSERVATION_MINUTES = 60;
|
|
18
|
+
var MINUTE_MS = 60 * 1000;
|
|
19
|
+
var DEFAULT_UPDATE_ROLLOUT_STAGES = [
|
|
20
|
+
{ minimumReports: 20, observationMinutes: 60, rollout: 0.05 },
|
|
21
|
+
{ minimumReports: 100, observationMinutes: 360, rollout: 0.25 },
|
|
22
|
+
{ minimumReports: 100, observationMinutes: 0, rollout: 1 }
|
|
23
|
+
];
|
|
16
24
|
var MINIMUM_UPDATE_BOOT_TIMEOUT_MS = 5000;
|
|
17
25
|
var MAXIMUM_UPDATE_BOOT_TIMEOUT_MS = 120000;
|
|
18
26
|
var HOSTNAME_PATTERN = /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:\.(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?))*$/;
|
|
@@ -246,6 +254,42 @@ var normalizeUpdateServer = (config, productionOrigin, projectRoot, updates) =>
|
|
|
246
254
|
throw new TypeError("mobile.updates.server.health.secretEnv must be a valid environment variable name.");
|
|
247
255
|
health = { failureRate, minimumReports, secretEnv };
|
|
248
256
|
}
|
|
257
|
+
const configuredRollout = config.updates.server?.rollout;
|
|
258
|
+
let rollout;
|
|
259
|
+
if (configuredRollout !== undefined && configuredRollout !== false) {
|
|
260
|
+
if (!health)
|
|
261
|
+
throw new TypeError("mobile.updates.server.rollout requires fleet health to be enabled.");
|
|
262
|
+
if (configuredRollout.automatic !== undefined && typeof configuredRollout.automatic !== "boolean")
|
|
263
|
+
throw new TypeError("mobile.updates.server.rollout.automatic must be boolean.");
|
|
264
|
+
const configuredStages = configuredRollout.stages ?? DEFAULT_UPDATE_ROLLOUT_STAGES;
|
|
265
|
+
const stages = configuredStages.map((stage, index) => {
|
|
266
|
+
const previousStage = configuredStages[index - 1];
|
|
267
|
+
const maximumFailureRate = stage.maximumFailureRate ?? DEFAULT_UPDATE_ROLLOUT_FAILURE_RATE;
|
|
268
|
+
const minimumReports = stage.minimumReports ?? DEFAULT_UPDATE_HEALTH_MINIMUM_REPORTS;
|
|
269
|
+
const observationMinutes = stage.observationMinutes ?? DEFAULT_UPDATE_ROLLOUT_OBSERVATION_MINUTES;
|
|
270
|
+
const observationMs = observationMinutes * MINUTE_MS;
|
|
271
|
+
if (!Number.isFinite(stage.rollout) || stage.rollout <= 0 || stage.rollout > 1 || previousStage !== undefined && stage.rollout <= previousStage.rollout)
|
|
272
|
+
throw new TypeError("mobile.updates.server.rollout stages must be strictly increasing fractions greater than 0 and at most 1.");
|
|
273
|
+
if (!Number.isFinite(maximumFailureRate) || maximumFailureRate < 0 || maximumFailureRate >= health.failureRate)
|
|
274
|
+
throw new TypeError("mobile.updates.server.rollout maximumFailureRate must be non-negative and lower than the fleet-health pause rate.");
|
|
275
|
+
if (!Number.isSafeInteger(minimumReports) || minimumReports < health.minimumReports)
|
|
276
|
+
throw new TypeError("mobile.updates.server.rollout minimumReports must be an integer at least as large as the fleet-health minimumReports.");
|
|
277
|
+
if (!Number.isFinite(observationMinutes) || observationMinutes < 0 || !Number.isSafeInteger(observationMs))
|
|
278
|
+
throw new TypeError("mobile.updates.server.rollout observationMinutes must produce a non-negative whole number of milliseconds.");
|
|
279
|
+
return {
|
|
280
|
+
maximumFailureRate,
|
|
281
|
+
minimumReports,
|
|
282
|
+
observationMs,
|
|
283
|
+
rollout: stage.rollout
|
|
284
|
+
};
|
|
285
|
+
});
|
|
286
|
+
if (stages.length === 0 || stages.at(-1)?.rollout !== 1)
|
|
287
|
+
throw new TypeError("mobile.updates.server.rollout stages must end at rollout 1.");
|
|
288
|
+
rollout = {
|
|
289
|
+
automatic: configuredRollout.automatic ?? false,
|
|
290
|
+
stages
|
|
291
|
+
};
|
|
292
|
+
}
|
|
249
293
|
if (autoMount) {
|
|
250
294
|
const manifest = new URL(updates.manifestUrl);
|
|
251
295
|
if (manifest.origin !== productionOrigin)
|
|
@@ -282,6 +326,7 @@ var normalizeUpdateServer = (config, productionOrigin, projectRoot, updates) =>
|
|
|
282
326
|
autoMount,
|
|
283
327
|
expoCodeSigningKeys,
|
|
284
328
|
...health ? { health } : {},
|
|
329
|
+
...rollout ? { rollout } : {},
|
|
285
330
|
registryModule
|
|
286
331
|
};
|
|
287
332
|
};
|
package/dist/cli/index.js
CHANGED
|
@@ -58,7 +58,7 @@ if (command === "dev") {
|
|
|
58
58
|
}
|
|
59
59
|
const positionalArgs = stripNamedArgs("--config", "--android-device", "--ios-device").filter((arg) => arg !== "--no-mobile" && arg !== "--eager");
|
|
60
60
|
const serverEntry = positionalArgs[0] ?? DEFAULT_SERVER_ENTRY;
|
|
61
|
-
const { dev } = await import("./dev-
|
|
61
|
+
const { dev } = await import("./dev-6shm8qsn.js");
|
|
62
62
|
await dev(serverEntry, configPath, {
|
|
63
63
|
androidDevice,
|
|
64
64
|
eager: args.includes("--eager"),
|
|
@@ -71,7 +71,7 @@ if (command === "dev") {
|
|
|
71
71
|
const configPath = parseNamedArg("--config");
|
|
72
72
|
const positionalArgs = stripNamedArgs("--outdir", "--config").filter((arg) => arg !== "--prebuilt");
|
|
73
73
|
const serverEntry = positionalArgs[0] ?? DEFAULT_SERVER_ENTRY;
|
|
74
|
-
const { start } = await import("./start-
|
|
74
|
+
const { start } = await import("./start-7jg0csqy.js");
|
|
75
75
|
await start(serverEntry, outdir, configPath, {
|
|
76
76
|
prebuilt: args.includes("--prebuilt")
|
|
77
77
|
});
|
|
@@ -81,7 +81,7 @@ if (command === "dev") {
|
|
|
81
81
|
const configPath = parseNamedArg("--config");
|
|
82
82
|
const positionalArgs = stripNamedArgs("--outdir", "--config");
|
|
83
83
|
const serverEntry = positionalArgs[0] ?? DEFAULT_SERVER_ENTRY;
|
|
84
|
-
const { start } = await import("./start-
|
|
84
|
+
const { start } = await import("./start-7jg0csqy.js");
|
|
85
85
|
await start(serverEntry, outdir, configPath, { prepareOnly: true });
|
|
86
86
|
} else if (command === "build") {
|
|
87
87
|
sendTelemetryEvent("cli:command", { command });
|
|
@@ -197,13 +197,13 @@ if (command === "dev") {
|
|
|
197
197
|
const configPath = parseNamedArg("--config");
|
|
198
198
|
const positionalArgs = stripNamedArgs("--outdir", "--outfile", "--config");
|
|
199
199
|
const serverEntry = positionalArgs[0] ?? DEFAULT_SERVER_ENTRY;
|
|
200
|
-
const { compile } = await import("./compile-
|
|
200
|
+
const { compile } = await import("./compile-5hchbcbd.js");
|
|
201
201
|
await compile(serverEntry, outdir, outfile, configPath);
|
|
202
202
|
} else if (command === "mobile") {
|
|
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-bg1jy34n.js");
|
|
207
207
|
try {
|
|
208
208
|
await runMobile(args);
|
|
209
209
|
} catch (error) {
|
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
} from "./index-9r7n9dqp.js";
|
|
8
8
|
import {
|
|
9
9
|
start
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-39j0dhq7.js";
|
|
11
11
|
import {
|
|
12
12
|
ABSOLUTE_MOBILE_CLIENT_MANIFEST_FORMAT,
|
|
13
13
|
ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION,
|
|
14
14
|
resolveAbsoluteMobileRoute
|
|
15
|
-
} from "./index-
|
|
15
|
+
} from "./index-jqdt7841.js";
|
|
16
16
|
import"./index-bzs19w3r.js";
|
|
17
17
|
import"./index-s2tazax7.js";
|
|
18
18
|
import {
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
import"./index-w5vswatm.js";
|
|
53
53
|
import {
|
|
54
54
|
normalizeAbsoluteMobileConfig
|
|
55
|
-
} from "./index-
|
|
55
|
+
} from "./index-rd2hbttb.js";
|
|
56
56
|
import {
|
|
57
57
|
ABSOLUTE_MOBILE_UPDATE_FORMAT,
|
|
58
58
|
absoluteDeviceNativeRequirements,
|
|
@@ -17519,9 +17519,12 @@ public final class AbsoluteMobileUpdateWatchdogPlugin: CAPPlugin, CAPBridgedPlug
|
|
|
17519
17519
|
private static func recover(_ reason: String) -> (String, String?, Bool)? {
|
|
17520
17520
|
var value = state()
|
|
17521
17521
|
guard let release = value["pendingRelease"] as? String, validRelease(release) else { return nil }
|
|
17522
|
-
let previous = value["previousPath"] as? String
|
|
17523
17522
|
let active = value["activeRelease"] as? String
|
|
17524
|
-
let
|
|
17523
|
+
let activePath = active.flatMap { candidate in
|
|
17524
|
+
validRelease(candidate) ? snapshotRoot()?.appendingPathComponent(candidate, isDirectory: true).path : nil
|
|
17525
|
+
}
|
|
17526
|
+
let hasActive = activePath.map { FileManager.default.fileExists(atPath: $0) } ?? false
|
|
17527
|
+
let previous = hasActive ? activePath : nil
|
|
17525
17528
|
let started = value["pendingStartedAt"] as? Double ?? Date().timeIntervalSince1970 * 1000
|
|
17526
17529
|
let duration = max(0, Date().timeIntervalSince1970 * 1000 - started)
|
|
17527
17530
|
value.removeValue(forKey: "pendingRelease")
|
|
@@ -17693,8 +17696,10 @@ public final class AbsoluteMobileUpdateWatchdogPlugin extends Plugin {
|
|
|
17693
17696
|
JSONObject value = state(context);
|
|
17694
17697
|
String release = value.optString("pendingRelease", "");
|
|
17695
17698
|
if (!validRelease(release)) return null;
|
|
17696
|
-
String
|
|
17697
|
-
|
|
17699
|
+
String activeRelease = value.optString("activeRelease", "");
|
|
17700
|
+
File activePath = new File(snapshotRoot(context), activeRelease);
|
|
17701
|
+
boolean hasActive = validRelease(activeRelease) && activePath.isDirectory();
|
|
17702
|
+
String previous = hasActive ? activePath.getAbsolutePath() : "";
|
|
17698
17703
|
long started = value.optLong("pendingStartedAt", System.currentTimeMillis());
|
|
17699
17704
|
long duration = Math.max(0, System.currentTimeMillis() - started);
|
|
17700
17705
|
value.remove("pendingRelease");
|
|
@@ -18888,7 +18893,7 @@ var connectTarget = async (target) => {
|
|
|
18888
18893
|
};
|
|
18889
18894
|
var isTransientEvaluationError = (error) => {
|
|
18890
18895
|
const message = error instanceof Error ? error.message : String(error);
|
|
18891
|
-
return /execution context|cannot find context|inspected target navigated|context.*destroyed/iu.test(message);
|
|
18896
|
+
return /execution context|cannot find context|inspected target navigated|context.*destroyed|CDP Runtime\.evaluate timed out/iu.test(message);
|
|
18892
18897
|
};
|
|
18893
18898
|
var createWaitFor = (evaluate) => async (expression, options = {}) => {
|
|
18894
18899
|
const timeoutMs = options.timeoutMs ?? CDP_COMMAND_TIMEOUT_MS;
|
|
@@ -19324,6 +19329,12 @@ var verifyHealthModule = (config, module) => {
|
|
|
19324
19329
|
if (typeof module.registry.inspectUpdateHealth !== "function" || typeof module.registry.issueUpdateHealthToken !== "function" || typeof module.registry.recordUpdateHealth !== "function")
|
|
19325
19330
|
throw new TypeError("Mobile update fleet health is enabled but the registry is not provisioned for it. Run `absolute mobile update provision --force`.");
|
|
19326
19331
|
};
|
|
19332
|
+
var verifyRolloutModule = (config, module) => {
|
|
19333
|
+
if (!config.updateServer?.rollout)
|
|
19334
|
+
return;
|
|
19335
|
+
if (typeof module.registry.advanceUpdateRollout !== "function" || typeof module.registry.cancelUpdateRollout !== "function" || typeof module.registry.inspectUpdateRollout !== "function" || typeof module.registry.pauseUpdateRollout !== "function" || typeof module.registry.reconcileUpdateRollout !== "function" || typeof module.registry.resumeUpdateRollout !== "function")
|
|
19336
|
+
throw new TypeError("Mobile update rollout orchestration is enabled but the registry is not provisioned for it. Run `absolute mobile update provision --force`.");
|
|
19337
|
+
};
|
|
19327
19338
|
var expoSigningOptions = (config) => {
|
|
19328
19339
|
if (!config.updates?.expoCodeSigning)
|
|
19329
19340
|
return;
|
|
@@ -19357,6 +19368,7 @@ var inspectAbsoluteMobileUpdateServer = async (config, projectRoot) => {
|
|
|
19357
19368
|
const module = await loadAbsoluteMobileUpdateServerModule(projectRoot, config.updateServer?.registryModule);
|
|
19358
19369
|
await verifyDurableModule(module);
|
|
19359
19370
|
verifyHealthModule(config, module);
|
|
19371
|
+
verifyRolloutModule(config, module);
|
|
19360
19372
|
if (config.engine === "expo")
|
|
19361
19373
|
expoSigningOptions(config);
|
|
19362
19374
|
return module.metadata;
|
|
@@ -19431,17 +19443,25 @@ export default createMobileUpdateRegistry({
|
|
|
19431
19443
|
};
|
|
19432
19444
|
var renderAbsoluteMobileUpdateRegistry = (options) => {
|
|
19433
19445
|
const source = renderAbsoluteMobileUpdateRegistryBase(options);
|
|
19434
|
-
|
|
19435
|
-
|
|
19436
|
-
|
|
19437
|
-
|
|
19446
|
+
let generated = "";
|
|
19447
|
+
if (options.health) {
|
|
19448
|
+
const secret = options.storage === "local" ? `process.env.${options.health.secretEnv} ?? 'absolutejs-local-health-secret-not-for-production'` : `required('${options.health.secretEnv}')`;
|
|
19449
|
+
generated += ` health: {
|
|
19438
19450
|
autoPause: { failureRate: ${options.health.failureRate}, minimumReports: ${options.health.minimumReports} },
|
|
19439
19451
|
secret: ${secret}
|
|
19440
19452
|
},
|
|
19441
19453
|
`;
|
|
19454
|
+
}
|
|
19455
|
+
if (options.rollout)
|
|
19456
|
+
generated += ` rollout: ${JSON.stringify(options.rollout, null, "\t").replaceAll(`
|
|
19457
|
+
`, `
|
|
19458
|
+
`)},
|
|
19459
|
+
`;
|
|
19460
|
+
if (!generated)
|
|
19461
|
+
return source;
|
|
19442
19462
|
return source.replace(`export default createMobileUpdateRegistry({
|
|
19443
19463
|
`, `export default createMobileUpdateRegistry({
|
|
19444
|
-
${
|
|
19464
|
+
${generated}`);
|
|
19445
19465
|
};
|
|
19446
19466
|
var writeAbsoluteMobileUpdateRegistry = async (options) => {
|
|
19447
19467
|
const path = projectPath(options.projectRoot, options.modulePath ?? DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE);
|
|
@@ -19455,6 +19475,7 @@ var writeAbsoluteMobileUpdateRegistry = async (options) => {
|
|
|
19455
19475
|
await mkdir5(dirname4(path), { recursive: true });
|
|
19456
19476
|
await Bun.write(path, renderAbsoluteMobileUpdateRegistry({
|
|
19457
19477
|
...options.health ? { health: options.health } : {},
|
|
19478
|
+
...options.rollout ? { rollout: options.rollout } : {},
|
|
19458
19479
|
publicKeys: options.publicKeys,
|
|
19459
19480
|
storage: options.storage
|
|
19460
19481
|
}));
|
|
@@ -22016,14 +22037,7 @@ var lifecycleMethod = (publisher, name) => {
|
|
|
22016
22037
|
throw new TypeError(`Mobile update registry does not support ${name}. Re-run \`absolute mobile update provision --force\` after upgrading @absolutejs/deploy.`);
|
|
22017
22038
|
return method;
|
|
22018
22039
|
};
|
|
22019
|
-
var
|
|
22020
|
-
const report = await lifecycleMethod(options.publisher, "inspectUpdateHealth")({
|
|
22021
|
-
appId: options.appId,
|
|
22022
|
-
channel: options.channel,
|
|
22023
|
-
...options.releaseId ? { releaseId: options.releaseId } : {}
|
|
22024
|
-
});
|
|
22025
|
-
if (report === null)
|
|
22026
|
-
return null;
|
|
22040
|
+
var validateHealthReport = (report, options) => {
|
|
22027
22041
|
if (!object3(report) || report.appId !== options.appId || report.channel !== options.channel || options.releaseId !== undefined && report.releaseId !== options.releaseId || typeof report.paused !== "boolean" || ![
|
|
22028
22042
|
report.activated,
|
|
22029
22043
|
report.downloaded,
|
|
@@ -22044,6 +22058,45 @@ var inspectAbsoluteMobileUpdateHealth = async (options) => {
|
|
|
22044
22058
|
throw new TypeError("Mobile update registry returned an invalid health report.");
|
|
22045
22059
|
return report;
|
|
22046
22060
|
};
|
|
22061
|
+
var inspectAbsoluteMobileUpdateHealth = async (options) => {
|
|
22062
|
+
const report = await lifecycleMethod(options.publisher, "inspectUpdateHealth")({
|
|
22063
|
+
appId: options.appId,
|
|
22064
|
+
channel: options.channel,
|
|
22065
|
+
...options.releaseId ? { releaseId: options.releaseId } : {}
|
|
22066
|
+
});
|
|
22067
|
+
if (report === null)
|
|
22068
|
+
return null;
|
|
22069
|
+
return validateHealthReport(report, options);
|
|
22070
|
+
};
|
|
22071
|
+
var validateRolloutReport = (report, options) => {
|
|
22072
|
+
validateHealthReport(report, options);
|
|
22073
|
+
const validStage = (stage) => stage === undefined || object3(stage) && Number.isFinite(stage.rollout) && stage.rollout > 0 && stage.rollout <= 1 && Number.isSafeInteger(stage.minimumReports) && stage.minimumReports > 0 && Number.isSafeInteger(stage.observationMs) && stage.observationMs >= 0 && Number.isFinite(stage.maximumFailureRate) && stage.maximumFailureRate >= 0 && stage.maximumFailureRate < 1;
|
|
22074
|
+
if (typeof report.automatic !== "boolean" || !Number.isSafeInteger(report.currentStage) || report.currentStage < 0 || !Number.isFinite(Date.parse(report.enteredAt)) || !["active", "cancelled", "complete", "paused"].includes(report.status) || report.pausedBy !== undefined && report.pausedBy !== "fleet-health" && report.pausedBy !== "operator" || !validStage(report.nextStage) || report.paused !== (report.status === "paused" || report.status === "cancelled"))
|
|
22075
|
+
throw new TypeError("Mobile update registry returned an invalid rollout report.");
|
|
22076
|
+
return report;
|
|
22077
|
+
};
|
|
22078
|
+
var inspectAbsoluteMobileUpdateRollout = async (options) => {
|
|
22079
|
+
const report = await lifecycleMethod(options.publisher, "inspectUpdateRollout")({ appId: options.appId, channel: options.channel });
|
|
22080
|
+
return report === null ? null : validateRolloutReport(report, options);
|
|
22081
|
+
};
|
|
22082
|
+
var mutateAbsoluteMobileUpdateRollout = async (method, options) => validateRolloutReport(await lifecycleMethod(options.publisher, method)({
|
|
22083
|
+
appId: options.appId,
|
|
22084
|
+
channel: options.channel,
|
|
22085
|
+
...method === "advanceUpdateRollout" && options.rollout !== undefined ? { rollout: options.rollout } : {},
|
|
22086
|
+
...options.signal ? { signal: options.signal } : {}
|
|
22087
|
+
}), options);
|
|
22088
|
+
var advanceAbsoluteMobileUpdateRollout = (options) => mutateAbsoluteMobileUpdateRollout("advanceUpdateRollout", options);
|
|
22089
|
+
var cancelAbsoluteMobileUpdateRollout = (options) => mutateAbsoluteMobileUpdateRollout("cancelUpdateRollout", options);
|
|
22090
|
+
var pauseAbsoluteMobileUpdateRollout = (options) => mutateAbsoluteMobileUpdateRollout("pauseUpdateRollout", options);
|
|
22091
|
+
var reconcileAbsoluteMobileUpdateRollout = async (options) => {
|
|
22092
|
+
const report = await lifecycleMethod(options.publisher, "reconcileUpdateRollout")({
|
|
22093
|
+
appId: options.appId,
|
|
22094
|
+
channel: options.channel,
|
|
22095
|
+
...options.signal ? { signal: options.signal } : {}
|
|
22096
|
+
});
|
|
22097
|
+
return report === null ? null : validateRolloutReport(report, options);
|
|
22098
|
+
};
|
|
22099
|
+
var resumeAbsoluteMobileUpdateRollout = (options) => mutateAbsoluteMobileUpdateRollout("resumeUpdateRollout", options);
|
|
22047
22100
|
var validOptionalCounters = (values) => values.every((value) => value === undefined) || values.every((value) => Number.isSafeInteger(value) && (value ?? -1) >= 0);
|
|
22048
22101
|
var validateStorageIdentity = (result, appId) => {
|
|
22049
22102
|
if (!object3(result) || result.appId !== appId || !Array.isArray(result.releases) || ![
|
|
@@ -22830,6 +22883,7 @@ var mobileUpdatePublisher = async (args) => {
|
|
|
22830
22883
|
throw new TypeError("Mobile updates are not configured.");
|
|
22831
22884
|
const modulePath = valueAfter(args, "--registry") ?? mobile.updateServer.registryModule;
|
|
22832
22885
|
return {
|
|
22886
|
+
mobile,
|
|
22833
22887
|
projectRoot,
|
|
22834
22888
|
publisher: await loadAbsoluteMobileUpdatePublisher(projectRoot, modulePath)
|
|
22835
22889
|
};
|
|
@@ -22843,7 +22897,7 @@ var provisionMobileUpdate = async (args) => {
|
|
|
22843
22897
|
throw new TypeError("--storage must be local or s3.");
|
|
22844
22898
|
const modulePath = valueAfter(args, "--registry") ?? mobile.updateServer.registryModule;
|
|
22845
22899
|
const packages = [
|
|
22846
|
-
"@absolutejs/deploy@0.25.
|
|
22900
|
+
"@absolutejs/deploy@0.25.13",
|
|
22847
22901
|
"@absolutejs/blob@0.5.2",
|
|
22848
22902
|
...requestedStorage === "s3" ? [
|
|
22849
22903
|
"@aws-sdk/client-s3@3.1095.0",
|
|
@@ -22857,6 +22911,7 @@ var provisionMobileUpdate = async (args) => {
|
|
|
22857
22911
|
const path = await writeAbsoluteMobileUpdateRegistry({
|
|
22858
22912
|
force: args.includes("--force"),
|
|
22859
22913
|
...mobile.updateServer.health ? { health: mobile.updateServer.health } : {},
|
|
22914
|
+
...mobile.updateServer.rollout ? { rollout: mobile.updateServer.rollout } : {},
|
|
22860
22915
|
modulePath,
|
|
22861
22916
|
projectRoot,
|
|
22862
22917
|
publicKeys: mobile.updates.publicKeys,
|
|
@@ -22885,12 +22940,12 @@ var publishMobileUpdate = async (args) => {
|
|
|
22885
22940
|
});
|
|
22886
22941
|
if (!releaseDirectory)
|
|
22887
22942
|
throw new TypeError("mobile update publish requires a release directory.");
|
|
22888
|
-
const { projectRoot, publisher } = await mobileUpdatePublisher(args);
|
|
22943
|
+
const { mobile, projectRoot, publisher } = await mobileUpdatePublisher(args);
|
|
22889
22944
|
const result = await publishAbsoluteMobileUpdate({
|
|
22890
22945
|
projectRoot,
|
|
22891
22946
|
publisher,
|
|
22892
22947
|
releaseDirectory,
|
|
22893
|
-
rollout: updateRollout(args, 0.05)
|
|
22948
|
+
rollout: updateRollout(args, mobile.updateServer?.rollout?.stages[0]?.rollout ?? 0.05)
|
|
22894
22949
|
});
|
|
22895
22950
|
console.log(`${result.reused ? "Reused" : "Published"} mobile update ${result.releaseId} to ${result.channel} at ${Math.round(result.rollout * 100)}%.`);
|
|
22896
22951
|
if (result.storedBytes !== undefined && result.reusedBytes !== undefined && result.storedFiles !== undefined && result.reusedFiles !== undefined)
|
|
@@ -22994,23 +23049,87 @@ var inspectMobileUpdateHealth = async (args) => {
|
|
|
22994
23049
|
if (!mobile.updates)
|
|
22995
23050
|
throw new TypeError("mobile update status requires mobile.updates config.");
|
|
22996
23051
|
const { publisher } = await mobileUpdatePublisher(args);
|
|
22997
|
-
const
|
|
23052
|
+
const releaseId = valueAfter(args, "--release");
|
|
23053
|
+
const rolloutReport = mobile.updateServer?.rollout ? await inspectAbsoluteMobileUpdateRollout({
|
|
23054
|
+
appId: mobile.appId,
|
|
23055
|
+
channel: mobile.updates.channel,
|
|
23056
|
+
publisher
|
|
23057
|
+
}) : undefined;
|
|
23058
|
+
const report = mobile.updateServer?.rollout ? rolloutReport : await inspectAbsoluteMobileUpdateHealth({
|
|
22998
23059
|
appId: mobile.appId,
|
|
22999
23060
|
channel: mobile.updates.channel,
|
|
23000
23061
|
publisher,
|
|
23001
|
-
...
|
|
23062
|
+
...releaseId ? { releaseId } : {}
|
|
23002
23063
|
});
|
|
23003
23064
|
if (args.includes("--json"))
|
|
23004
23065
|
console.log(JSON.stringify(report, null, 2));
|
|
23005
23066
|
else if (!report)
|
|
23006
23067
|
console.log(`No active mobile update exists on ${mobile.updates.channel}.`);
|
|
23007
23068
|
else {
|
|
23008
|
-
console.log(`${report.releaseId} is ${report.paused ? "PAUSED" : "
|
|
23069
|
+
console.log(`${report.releaseId} is ${rolloutReport?.status.toUpperCase() ?? (report.paused ? "PAUSED" : "ACTIVE")} at ${Math.round(report.rollout * 100)}%: ${report.terminalReports} terminal reports, ${report.failures} failures (${(report.failureRate * 100).toFixed(1)}%).`);
|
|
23070
|
+
if (rolloutReport)
|
|
23071
|
+
console.log(` Stage ${rolloutReport.currentStage + 1} entered ${rolloutReport.enteredAt}; advancement is ${rolloutReport.automatic ? "automatic" : "manual"}${rolloutReport.nextStage ? `, next ${Math.round(rolloutReport.nextStage.rollout * 100)}%` : ""}${rolloutReport.pausedBy ? `, paused by ${rolloutReport.pausedBy}` : ""}.`);
|
|
23009
23072
|
console.log(` ${report.activated} activated, ${report.rolledBack} rolled back, ${report.quarantined} quarantined, ${report.downloaded} downloaded, ${report.downloadFailed} download failures.`);
|
|
23010
23073
|
console.log(` Transfer: ${formatBytes(report.transfer.downloadedBytes)} downloaded, ${formatBytes(report.transfer.avoidedBytes)} avoided (${formatBytes(report.transfer.resumedBytes)} resumed, ${formatBytes(report.transfer.reusedBytes)} reused).`);
|
|
23011
23074
|
}
|
|
23012
23075
|
return report;
|
|
23013
23076
|
};
|
|
23077
|
+
var MOBILE_UPDATE_ROLLOUT_ACTION_LABEL = {
|
|
23078
|
+
advance: "Advanced",
|
|
23079
|
+
cancel: "Cancelled",
|
|
23080
|
+
pause: "Paused",
|
|
23081
|
+
reconcile: "Reconciled",
|
|
23082
|
+
resume: "Resumed"
|
|
23083
|
+
};
|
|
23084
|
+
var isMobileUpdateRolloutAction = (value) => value !== undefined && Object.hasOwn(MOBILE_UPDATE_ROLLOUT_ACTION_LABEL, value);
|
|
23085
|
+
var controlMobileUpdateRollout = async (action, args) => {
|
|
23086
|
+
const startedAt = performance.now();
|
|
23087
|
+
const { mobile } = await loadMobile(valueAfter(args, "--config"));
|
|
23088
|
+
if (!mobile.updates || !mobile.updateServer?.rollout)
|
|
23089
|
+
throw new TypeError(`mobile update ${action} requires mobile.updates.server.rollout config.`);
|
|
23090
|
+
const { publisher } = await mobileUpdatePublisher(args);
|
|
23091
|
+
const options = {
|
|
23092
|
+
appId: mobile.appId,
|
|
23093
|
+
channel: mobile.updates.channel,
|
|
23094
|
+
publisher
|
|
23095
|
+
};
|
|
23096
|
+
const requestedRollout = valueAfter(args, "--rollout");
|
|
23097
|
+
let report;
|
|
23098
|
+
switch (action) {
|
|
23099
|
+
case "advance":
|
|
23100
|
+
report = await advanceAbsoluteMobileUpdateRollout({
|
|
23101
|
+
...options,
|
|
23102
|
+
...requestedRollout ? { rollout: updateRollout(args) } : {}
|
|
23103
|
+
});
|
|
23104
|
+
break;
|
|
23105
|
+
case "cancel":
|
|
23106
|
+
report = await cancelAbsoluteMobileUpdateRollout(options);
|
|
23107
|
+
break;
|
|
23108
|
+
case "pause":
|
|
23109
|
+
report = await pauseAbsoluteMobileUpdateRollout(options);
|
|
23110
|
+
break;
|
|
23111
|
+
case "reconcile":
|
|
23112
|
+
report = await reconcileAbsoluteMobileUpdateRollout(options);
|
|
23113
|
+
break;
|
|
23114
|
+
case "resume":
|
|
23115
|
+
report = await resumeAbsoluteMobileUpdateRollout(options);
|
|
23116
|
+
}
|
|
23117
|
+
if (args.includes("--json"))
|
|
23118
|
+
console.log(JSON.stringify(report, null, 2));
|
|
23119
|
+
else if (!report)
|
|
23120
|
+
console.log(`No active mobile update exists on ${mobile.updates.channel}.`);
|
|
23121
|
+
else
|
|
23122
|
+
console.log(`${MOBILE_UPDATE_ROLLOUT_ACTION_LABEL[action]} ${report.releaseId}: ${report.status.toUpperCase()} at ${Math.round(report.rollout * 100)}% (stage ${report.currentStage + 1}).`);
|
|
23123
|
+
sendTelemetryEvent("mobile:update-rollout", {
|
|
23124
|
+
action,
|
|
23125
|
+
durationMs: Math.round(performance.now() - startedAt),
|
|
23126
|
+
...report ? {
|
|
23127
|
+
automatic: report.automatic,
|
|
23128
|
+
status: report.status
|
|
23129
|
+
} : { status: "empty" }
|
|
23130
|
+
});
|
|
23131
|
+
return report;
|
|
23132
|
+
};
|
|
23014
23133
|
var collectMobileUpdates = async (args) => {
|
|
23015
23134
|
const startedAt = performance.now();
|
|
23016
23135
|
const { mobile } = await loadMobile(valueAfter(args, "--config"));
|
|
@@ -24393,6 +24512,10 @@ var runMobile = async (args) => {
|
|
|
24393
24512
|
await inspectMobileUpdateHealth(args.slice(2));
|
|
24394
24513
|
return;
|
|
24395
24514
|
}
|
|
24515
|
+
if (command === "update" && isMobileUpdateRolloutAction(args[1])) {
|
|
24516
|
+
await controlMobileUpdateRollout(args[1], args.slice(2));
|
|
24517
|
+
return;
|
|
24518
|
+
}
|
|
24396
24519
|
if (command === "update" && args[1] === "gc") {
|
|
24397
24520
|
await collectMobileUpdates(args.slice(2));
|
|
24398
24521
|
return;
|
|
@@ -24405,7 +24528,7 @@ var runMobile = async (args) => {
|
|
|
24405
24528
|
await publishIos(args.slice(2));
|
|
24406
24529
|
return;
|
|
24407
24530
|
}
|
|
24408
|
-
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 status [--
|
|
24531
|
+
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 status [--registry module] [--json] | update advance [--rollout fraction] [--registry module] [--json] | update pause|resume|cancel|reconcile [--registry module] [--json] | 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]> [--config path]");
|
|
24409
24532
|
};
|
|
24410
24533
|
export {
|
|
24411
24534
|
runMobile
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
start
|
|
4
|
-
} from "./index-
|
|
5
|
-
import"./index-
|
|
4
|
+
} from "./index-39j0dhq7.js";
|
|
5
|
+
import"./index-jqdt7841.js";
|
|
6
6
|
import"./index-bzs19w3r.js";
|
|
7
7
|
import"./index-s2tazax7.js";
|
|
8
8
|
import"./index-fc9vxw56.js";
|
|
@@ -10,7 +10,7 @@ import"./index-r8x3839e.js";
|
|
|
10
10
|
import"./index-06cmrcdq.js";
|
|
11
11
|
import"./index-9kwmb3c0.js";
|
|
12
12
|
import"./index-w5vswatm.js";
|
|
13
|
-
import"./index-
|
|
13
|
+
import"./index-rd2hbttb.js";
|
|
14
14
|
import"./index-tame6e2c.js";
|
|
15
15
|
import"./index-ar4gz15x.js";
|
|
16
16
|
import"./index-t84wxk1p.js";
|