@absolutejs/absolute 0.20.0-beta.85 → 0.20.0-beta.86
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 +334 -13
- package/dist/build.js.map +5 -5
- package/dist/cli/{compile-d7g2fvqe.js → compile-e9cn3xpx.js} +3 -3
- package/dist/cli/{config-naw5fer4.js → config-z2kf085h.js} +1 -1
- package/dist/cli/{dev-skb8dz33.js → dev-3hweza3s.js} +2 -2
- package/dist/cli/{expoProject-3mmwtemn.js → expoProject-dac8fqhq.js} +1 -1
- package/dist/cli/{index-czw3jd8f.js → index-3tsmbyze.js} +22 -1
- package/dist/cli/{index-q78x1k9q.js → index-9rk7v35t.js} +2 -2
- package/dist/cli/{index-p8ezgd5e.js → index-tame6e2c.js} +65 -3
- package/dist/cli/{index-8gksmws3.js → index-x48brywr.js} +2 -2
- package/dist/cli/index.js +5 -5
- package/dist/cli/{mobile-pdck6a35.js → mobile-2p3z33t1.js} +85 -8
- package/dist/cli/{start-jbgfw27x.js → start-7t186mhg.js} +4 -4
- package/dist/index.js +334 -13
- package/dist/index.js.map +5 -5
- package/dist/mobile/index.js +480 -20
- package/dist/mobile/index.js.map +8 -8
- package/dist/mobile/remoteMacAgentEntry.js +237 -175
- package/dist/mobile/shellUpdate.js +138 -23
- package/dist/src/mobile/config.d.ts +5 -0
- package/dist/src/mobile/updateClient.d.ts +13 -0
- package/dist/src/mobile/updatePublisher.d.ts +12 -1
- package/dist/src/mobile/updateServer.d.ts +10 -0
- package/dist/types/build.d.ts +9 -0
- package/package.json +2 -2
|
@@ -200,6 +200,30 @@ var requestHeaders = (config) => ({
|
|
|
200
200
|
"x-absolute-mobile-release": config.currentReleaseId,
|
|
201
201
|
"x-absolute-mobile-runtime": config.runtimeFingerprint
|
|
202
202
|
});
|
|
203
|
+
var healthUrl = (manifestUrl) => new URL("./health", manifestUrl);
|
|
204
|
+
var reportAbsoluteMobileUpdateHealth = async (config, input, request = globalThis.fetch) => {
|
|
205
|
+
const manifestUrl = exactManifestUrl(config.manifestUrl);
|
|
206
|
+
const headers = new Headers(requestHeaders(config));
|
|
207
|
+
headers.set("content-type", "application/json");
|
|
208
|
+
headers.set("x-absolute-mobile-health-token", input.healthToken);
|
|
209
|
+
const response = await request(healthUrl(manifestUrl), {
|
|
210
|
+
body: JSON.stringify({
|
|
211
|
+
kind: input.kind,
|
|
212
|
+
...input.reason ? { reason: input.reason } : {},
|
|
213
|
+
releaseId: input.releaseId,
|
|
214
|
+
...input.transfer ? { transfer: input.transfer } : {}
|
|
215
|
+
}),
|
|
216
|
+
cache: "no-store",
|
|
217
|
+
credentials: "omit",
|
|
218
|
+
headers,
|
|
219
|
+
keepalive: true,
|
|
220
|
+
method: "POST",
|
|
221
|
+
redirect: "error",
|
|
222
|
+
signal: AbortSignal.timeout(15000)
|
|
223
|
+
});
|
|
224
|
+
if (response.status !== 202)
|
|
225
|
+
throw new TypeError(`Mobile update health report failed with HTTP ${response.status}.`);
|
|
226
|
+
};
|
|
203
227
|
var requireCompatible = (manifest, config) => {
|
|
204
228
|
if (manifest.appId !== config.appId)
|
|
205
229
|
throw new TypeError("Mobile update belongs to another app.");
|
|
@@ -395,15 +419,24 @@ var createAbsoluteMobileUpdateClient = (options) => {
|
|
|
395
419
|
throw new TypeError("Mobile update manifest is not valid JSON.");
|
|
396
420
|
}
|
|
397
421
|
const manifest = parseAbsoluteMobileUpdateManifest(manifestValue);
|
|
422
|
+
const healthToken = response.headers.get("x-absolute-mobile-health-token");
|
|
398
423
|
requireCompatible(manifest, options.config);
|
|
399
424
|
if (!await options.verifier.verify(manifest))
|
|
400
425
|
throw new TypeError("Mobile update signature verification failed.");
|
|
401
426
|
if (manifest.releaseId === options.config.currentReleaseId)
|
|
402
427
|
return { kind: "current" };
|
|
403
428
|
if (options.config.blockedReleaseIds?.includes(manifest.releaseId))
|
|
404
|
-
return {
|
|
429
|
+
return {
|
|
430
|
+
...healthToken ? { healthToken } : {},
|
|
431
|
+
kind: "quarantined",
|
|
432
|
+
releaseId: manifest.releaseId
|
|
433
|
+
};
|
|
405
434
|
if (!download)
|
|
406
|
-
return {
|
|
435
|
+
return {
|
|
436
|
+
...healthToken ? { healthToken } : {},
|
|
437
|
+
kind: "update-available",
|
|
438
|
+
manifest
|
|
439
|
+
};
|
|
407
440
|
await options.store.begin(manifest);
|
|
408
441
|
let transfer;
|
|
409
442
|
try {
|
|
@@ -414,14 +447,28 @@ var createAbsoluteMobileUpdateClient = (options) => {
|
|
|
414
447
|
await options.store.suspend(manifest.releaseId);
|
|
415
448
|
else
|
|
416
449
|
await options.store.abort(manifest.releaseId);
|
|
450
|
+
if (healthToken)
|
|
451
|
+
reportAbsoluteMobileUpdateHealth(options.config, {
|
|
452
|
+
healthToken,
|
|
453
|
+
kind: "download-failed",
|
|
454
|
+
releaseId: manifest.releaseId
|
|
455
|
+
}, request).catch(() => {
|
|
456
|
+
return;
|
|
457
|
+
});
|
|
417
458
|
throw error;
|
|
418
459
|
}
|
|
419
|
-
return {
|
|
460
|
+
return {
|
|
461
|
+
...healthToken ? { healthToken } : {},
|
|
462
|
+
kind: "downloaded",
|
|
463
|
+
manifest,
|
|
464
|
+
transfer
|
|
465
|
+
};
|
|
420
466
|
};
|
|
421
467
|
return {
|
|
422
468
|
check,
|
|
423
469
|
activate: (releaseId) => options.store.activate(releaseId),
|
|
424
|
-
download: () => check(true)
|
|
470
|
+
download: () => check(true),
|
|
471
|
+
report: (input) => reportAbsoluteMobileUpdateHealth(options.config, input, request)
|
|
425
472
|
};
|
|
426
473
|
};
|
|
427
474
|
|
|
@@ -478,12 +525,15 @@ var readState = async () => {
|
|
|
478
525
|
releaseId: recovery.releaseId
|
|
479
526
|
};
|
|
480
527
|
return {
|
|
528
|
+
...text("activeHealthToken") ? { activeHealthToken: text("activeHealthToken") } : {},
|
|
481
529
|
...text("activeRelease") ? { activeRelease: text("activeRelease") } : {},
|
|
482
530
|
...text("pendingRelease") ? { pendingRelease: text("pendingRelease") } : {},
|
|
531
|
+
...text("pendingHealthToken") ? { pendingHealthToken: text("pendingHealthToken") } : {},
|
|
483
532
|
...number("pendingStartedAt") === undefined ? {} : { pendingStartedAt: number("pendingStartedAt") },
|
|
484
533
|
...text("previousPath") ? { previousPath: text("previousPath") } : {},
|
|
485
534
|
...quarantinedReleases.length > 0 ? { quarantinedReleases } : {},
|
|
486
535
|
...text("readyRelease") ? { readyRelease: text("readyRelease") } : {},
|
|
536
|
+
...text("readyHealthToken") ? { readyHealthToken: text("readyHealthToken") } : {},
|
|
487
537
|
...validRecovery ? { recovery: validRecovery } : {}
|
|
488
538
|
};
|
|
489
539
|
} catch {
|
|
@@ -569,6 +619,7 @@ var createStore = () => {
|
|
|
569
619
|
const state = await readState();
|
|
570
620
|
if (state.readyRelease === releaseId || state.pendingRelease === releaseId)
|
|
571
621
|
await writeState({
|
|
622
|
+
activeHealthToken: state.activeHealthToken,
|
|
572
623
|
activeRelease: state.activeRelease,
|
|
573
624
|
quarantinedReleases: state.quarantinedReleases,
|
|
574
625
|
recovery: state.recovery
|
|
@@ -581,7 +632,9 @@ var createStore = () => {
|
|
|
581
632
|
const path = await releaseNativePath(releaseId);
|
|
582
633
|
const previousPath = await currentServerBasePath();
|
|
583
634
|
await writeState({
|
|
635
|
+
activeHealthToken: state.activeHealthToken,
|
|
584
636
|
activeRelease: state.activeRelease,
|
|
637
|
+
pendingHealthToken: state.readyHealthToken,
|
|
585
638
|
pendingRelease: releaseId,
|
|
586
639
|
pendingStartedAt: Date.now(),
|
|
587
640
|
previousPath,
|
|
@@ -596,6 +649,7 @@ var createStore = () => {
|
|
|
596
649
|
});
|
|
597
650
|
await removeRelease(releaseId);
|
|
598
651
|
await writeState({
|
|
652
|
+
activeHealthToken: state.activeHealthToken,
|
|
599
653
|
activeRelease: state.activeRelease,
|
|
600
654
|
quarantinedReleases: state.quarantinedReleases
|
|
601
655
|
});
|
|
@@ -653,14 +707,15 @@ var createStore = () => {
|
|
|
653
707
|
commit: async (manifest) => {
|
|
654
708
|
if (staging?.releaseId !== manifest.releaseId)
|
|
655
709
|
throw new TypeError("Mobile update staging transaction changed identity.");
|
|
656
|
-
await removeStaging(manifest.releaseId);
|
|
657
|
-
await Preferences.remove({ key: STAGING_KEY });
|
|
658
710
|
const state = await readState();
|
|
659
711
|
await writeState({
|
|
712
|
+
activeHealthToken: state.activeHealthToken,
|
|
660
713
|
activeRelease: state.activeRelease,
|
|
661
714
|
quarantinedReleases: state.quarantinedReleases,
|
|
662
715
|
readyRelease: manifest.releaseId
|
|
663
716
|
});
|
|
717
|
+
await removeStaging(manifest.releaseId);
|
|
718
|
+
await Preferences.remove({ key: STAGING_KEY });
|
|
664
719
|
staging = undefined;
|
|
665
720
|
},
|
|
666
721
|
readPartial: async (file) => {
|
|
@@ -738,29 +793,56 @@ var removePriorRelease = async (prior, active) => {
|
|
|
738
793
|
if (prior && prior !== active)
|
|
739
794
|
await removeRelease(prior);
|
|
740
795
|
};
|
|
741
|
-
var reconcilePendingRelease = async (store, state) => {
|
|
796
|
+
var reconcilePendingRelease = async (store, state, report) => {
|
|
742
797
|
if (!state.pendingRelease)
|
|
743
798
|
return state;
|
|
744
799
|
const pendingPath = await releaseNativePath(state.pendingRelease);
|
|
745
800
|
const currentPath = await currentServerBasePath();
|
|
746
801
|
if (currentPath !== pendingPath) {
|
|
747
802
|
const failed = state.pendingRelease;
|
|
803
|
+
if (state.pendingHealthToken)
|
|
804
|
+
report({
|
|
805
|
+
healthToken: state.pendingHealthToken,
|
|
806
|
+
kind: "rolled-back",
|
|
807
|
+
releaseId: failed
|
|
808
|
+
});
|
|
748
809
|
await store.abort(failed);
|
|
749
810
|
emitUpdateResult({ kind: "rolled-back", releaseId: failed });
|
|
750
811
|
return readState();
|
|
751
812
|
}
|
|
752
813
|
webView().persistServerBasePath();
|
|
753
|
-
const next = {
|
|
814
|
+
const next = {
|
|
815
|
+
activeHealthToken: state.pendingHealthToken,
|
|
816
|
+
activeRelease: state.pendingRelease
|
|
817
|
+
};
|
|
754
818
|
await writeState(next);
|
|
755
819
|
await watchdog.confirm({ releaseId: state.pendingRelease });
|
|
820
|
+
if (state.pendingHealthToken)
|
|
821
|
+
report({
|
|
822
|
+
healthToken: state.pendingHealthToken,
|
|
823
|
+
kind: "activated",
|
|
824
|
+
releaseId: state.pendingRelease
|
|
825
|
+
});
|
|
756
826
|
await removePriorRelease(state.activeRelease, next.activeRelease);
|
|
757
827
|
emitUpdateResult({ kind: "activated", releaseId: next.activeRelease });
|
|
758
828
|
return next;
|
|
759
829
|
};
|
|
760
|
-
var consumeNativeRecovery = async (state) => {
|
|
830
|
+
var consumeNativeRecovery = async (state, report) => {
|
|
761
831
|
if (!state.recovery)
|
|
762
832
|
return state;
|
|
763
|
-
const {
|
|
833
|
+
const {
|
|
834
|
+
pendingHealthToken,
|
|
835
|
+
readyHealthToken: _readyHealthToken,
|
|
836
|
+
recovery,
|
|
837
|
+
...next
|
|
838
|
+
} = state;
|
|
839
|
+
if (pendingHealthToken)
|
|
840
|
+
report({
|
|
841
|
+
healthToken: pendingHealthToken,
|
|
842
|
+
kind: "rolled-back",
|
|
843
|
+
reason: recovery.reason,
|
|
844
|
+
releaseId: recovery.releaseId
|
|
845
|
+
});
|
|
764
846
|
emitUpdateResult({
|
|
765
847
|
durationMs: Math.round(recovery.durationMs),
|
|
766
848
|
kind: "rolled-back",
|
|
@@ -771,28 +853,53 @@ var consumeNativeRecovery = async (state) => {
|
|
|
771
853
|
return next;
|
|
772
854
|
};
|
|
773
855
|
var installAbsoluteMobileShellUpdates = async (manifest) => {
|
|
774
|
-
|
|
856
|
+
const { updates } = manifest;
|
|
857
|
+
if (!updates)
|
|
775
858
|
return;
|
|
776
859
|
const store = createStore();
|
|
777
|
-
const
|
|
778
|
-
const
|
|
860
|
+
const identity = await installationId();
|
|
861
|
+
const clientConfig = (state2) => ({
|
|
862
|
+
appId: manifest.appId,
|
|
863
|
+
blockedReleaseIds: state2.quarantinedReleases ?? [],
|
|
864
|
+
channel: updates.channel,
|
|
865
|
+
currentReleaseId: state2.activeRelease ?? `embedded:${manifest.appBuild}`,
|
|
866
|
+
installationId: identity,
|
|
867
|
+
manifestUrl: updates.manifestUrl,
|
|
868
|
+
runtimeFingerprint: manifest.nativeRuntime
|
|
869
|
+
});
|
|
870
|
+
const reportFor = (state2) => async (evidence) => {
|
|
871
|
+
await reportAbsoluteMobileUpdateHealth(clientConfig(state2), evidence).catch(() => {
|
|
872
|
+
return;
|
|
873
|
+
});
|
|
874
|
+
};
|
|
875
|
+
const initial = await readState();
|
|
876
|
+
const recovered = await consumeNativeRecovery(initial, reportFor(initial));
|
|
877
|
+
const state = await reconcilePendingRelease(store, recovered, reportFor(recovered));
|
|
779
878
|
const client = createAbsoluteMobileUpdateClient({
|
|
780
|
-
config:
|
|
781
|
-
appId: manifest.appId,
|
|
782
|
-
blockedReleaseIds: state.quarantinedReleases ?? [],
|
|
783
|
-
channel: manifest.updates.channel,
|
|
784
|
-
currentReleaseId: state.activeRelease ?? `embedded:${manifest.appBuild}`,
|
|
785
|
-
installationId: await installationId(),
|
|
786
|
-
manifestUrl: manifest.updates.manifestUrl,
|
|
787
|
-
runtimeFingerprint: manifest.nativeRuntime
|
|
788
|
-
},
|
|
879
|
+
config: clientConfig(state),
|
|
789
880
|
store,
|
|
790
|
-
verifier: createVerifier(
|
|
881
|
+
verifier: createVerifier(updates.publicKeys),
|
|
791
882
|
onProgress: (progress) => emitUpdateResult(progress)
|
|
792
883
|
});
|
|
793
884
|
const activateDownloaded = async (result) => {
|
|
794
885
|
if (result.kind !== "downloaded")
|
|
795
886
|
return;
|
|
887
|
+
if (result.healthToken) {
|
|
888
|
+
const ready = await readState();
|
|
889
|
+
if (ready.readyRelease === result.manifest.releaseId)
|
|
890
|
+
await writeState({
|
|
891
|
+
...ready,
|
|
892
|
+
readyHealthToken: result.healthToken
|
|
893
|
+
});
|
|
894
|
+
client.report({
|
|
895
|
+
healthToken: result.healthToken,
|
|
896
|
+
kind: "downloaded",
|
|
897
|
+
releaseId: result.manifest.releaseId,
|
|
898
|
+
transfer: result.transfer
|
|
899
|
+
}).catch(() => {
|
|
900
|
+
return;
|
|
901
|
+
});
|
|
902
|
+
}
|
|
796
903
|
emitUpdateResult({
|
|
797
904
|
avoidedBytes: result.transfer.avoidedBytes,
|
|
798
905
|
completedFiles: result.transfer.completedFiles,
|
|
@@ -813,6 +920,14 @@ var installAbsoluteMobileShellUpdates = async (manifest) => {
|
|
|
813
920
|
};
|
|
814
921
|
client.download().then((result) => {
|
|
815
922
|
if (result.kind === "quarantined") {
|
|
923
|
+
if (result.healthToken)
|
|
924
|
+
client.report({
|
|
925
|
+
healthToken: result.healthToken,
|
|
926
|
+
kind: "quarantined",
|
|
927
|
+
releaseId: result.releaseId
|
|
928
|
+
}).catch(() => {
|
|
929
|
+
return;
|
|
930
|
+
});
|
|
816
931
|
emitUpdateResult({
|
|
817
932
|
kind: "quarantined",
|
|
818
933
|
releaseId: result.releaseId
|
|
@@ -36,6 +36,11 @@ export type NormalizedAbsoluteMobileConfig = {
|
|
|
36
36
|
};
|
|
37
37
|
updateServer?: {
|
|
38
38
|
autoMount: boolean;
|
|
39
|
+
health?: {
|
|
40
|
+
failureRate: number;
|
|
41
|
+
minimumReports: number;
|
|
42
|
+
secretEnv: string;
|
|
43
|
+
};
|
|
39
44
|
expoCodeSigningKeys: Record<string, {
|
|
40
45
|
certificatePem: string;
|
|
41
46
|
privateKeyEnv: string;
|
|
@@ -41,16 +41,27 @@ export type AbsoluteMobileUpdateClientOptions = {
|
|
|
41
41
|
export type AbsoluteMobileUpdateCheckResult = {
|
|
42
42
|
kind: 'current';
|
|
43
43
|
} | {
|
|
44
|
+
healthToken?: string;
|
|
44
45
|
kind: 'downloaded';
|
|
45
46
|
manifest: AbsoluteMobileUpdateManifest;
|
|
46
47
|
transfer: AbsoluteMobileUpdateTransfer;
|
|
47
48
|
} | {
|
|
49
|
+
healthToken?: string;
|
|
48
50
|
kind: 'quarantined';
|
|
49
51
|
releaseId: string;
|
|
50
52
|
} | {
|
|
53
|
+
healthToken?: string;
|
|
51
54
|
kind: 'update-available';
|
|
52
55
|
manifest: AbsoluteMobileUpdateManifest;
|
|
53
56
|
};
|
|
57
|
+
export type AbsoluteMobileUpdateHealthKind = 'activated' | 'downloaded' | 'download-failed' | 'quarantined' | 'rolled-back';
|
|
58
|
+
export type AbsoluteMobileUpdateHealthEvidence = {
|
|
59
|
+
healthToken: string;
|
|
60
|
+
kind: AbsoluteMobileUpdateHealthKind;
|
|
61
|
+
reason?: 'boot-interrupted' | 'boot-timeout';
|
|
62
|
+
releaseId: string;
|
|
63
|
+
transfer?: Pick<AbsoluteMobileUpdateTransfer, 'avoidedBytes' | 'downloadedBytes' | 'durationMs' | 'resumedBytes' | 'reusedBytes' | 'throughputBytesPerSecond'>;
|
|
64
|
+
};
|
|
54
65
|
export type AbsoluteMobileUpdateTransfer = {
|
|
55
66
|
avoidedBytes: number;
|
|
56
67
|
completedFiles: number;
|
|
@@ -68,8 +79,10 @@ export type AbsoluteMobileUpdateTransfer = {
|
|
|
68
79
|
export type AbsoluteMobileUpdateProgress = AbsoluteMobileUpdateTransfer & {
|
|
69
80
|
kind: 'download-progress';
|
|
70
81
|
};
|
|
82
|
+
export declare const reportAbsoluteMobileUpdateHealth: (config: AbsoluteMobileUpdateClientConfig, input: AbsoluteMobileUpdateHealthEvidence, request?: typeof globalThis.fetch) => Promise<void>;
|
|
71
83
|
export declare const createAbsoluteMobileUpdateClient: (options: AbsoluteMobileUpdateClientOptions) => {
|
|
72
84
|
check: (download?: boolean) => Promise<AbsoluteMobileUpdateCheckResult>;
|
|
73
85
|
activate: (releaseId: string) => Promise<void>;
|
|
74
86
|
download: () => Promise<AbsoluteMobileUpdateCheckResult>;
|
|
87
|
+
report: (input: AbsoluteMobileUpdateHealthEvidence) => Promise<void>;
|
|
75
88
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MobileUpdatePruneOptions, MobileUpdatePruneResult, MobileUpdateRetentionOptions, MobileUpdateStorageReport } from '@absolutejs/deploy/mobile-update';
|
|
1
|
+
import type { MobileUpdateHealthReport, MobileUpdatePruneOptions, MobileUpdatePruneResult, MobileUpdateRetentionOptions, MobileUpdateStorageReport } from '@absolutejs/deploy/mobile-update';
|
|
2
2
|
import { readAbsoluteMobileUpdate } from './updateSigning';
|
|
3
3
|
export type AbsoluteMobileUpdatePublication = {
|
|
4
4
|
appId: string;
|
|
@@ -26,6 +26,11 @@ export type AbsoluteMobileUpdateRollback = {
|
|
|
26
26
|
stage: 'rolled-back';
|
|
27
27
|
};
|
|
28
28
|
export type AbsoluteMobileUpdatePublisher = {
|
|
29
|
+
inspectUpdateHealth?: (options: {
|
|
30
|
+
appId: string;
|
|
31
|
+
channel: string;
|
|
32
|
+
releaseId?: string;
|
|
33
|
+
}) => Promise<MobileUpdateHealthReport | null>;
|
|
29
34
|
inspectUpdateStorage?: (options: MobileUpdateRetentionOptions) => Promise<MobileUpdateStorageReport>;
|
|
30
35
|
pruneUpdates?: (options: MobileUpdatePruneOptions) => Promise<MobileUpdatePruneResult>;
|
|
31
36
|
publishUpdate(options: {
|
|
@@ -48,6 +53,12 @@ export type AbsoluteMobileUpdatePublisher = {
|
|
|
48
53
|
signal?: AbortSignal;
|
|
49
54
|
}): Promise<AbsoluteMobileUpdateRollback>;
|
|
50
55
|
};
|
|
56
|
+
export declare const inspectAbsoluteMobileUpdateHealth: (options: {
|
|
57
|
+
appId: string;
|
|
58
|
+
channel: string;
|
|
59
|
+
publisher: AbsoluteMobileUpdatePublisher;
|
|
60
|
+
releaseId?: string;
|
|
61
|
+
}) => Promise<MobileUpdateHealthReport | null>;
|
|
51
62
|
export declare const inspectAbsoluteMobileUpdateStorage: (options: {
|
|
52
63
|
appId: string;
|
|
53
64
|
minAgeMs?: number;
|
|
@@ -22,11 +22,21 @@ export declare const createAbsoluteMobileUpdateServerPlugin: (config: Normalized
|
|
|
22
22
|
}, import("elysia/types").DefaultMetadata, {}, import("elysia/types").DefaultEphemeral, import("elysia/types").DefaultEphemeral>>;
|
|
23
23
|
export declare const inspectAbsoluteMobileUpdateServer: (config: NormalizedAbsoluteMobileConfig, projectRoot: string) => Promise<AbsoluteMobileUpdateServerMetadata | undefined>;
|
|
24
24
|
export declare const renderAbsoluteMobileUpdateRegistry: (options: {
|
|
25
|
+
health?: {
|
|
26
|
+
failureRate: number;
|
|
27
|
+
minimumReports: number;
|
|
28
|
+
secretEnv: string;
|
|
29
|
+
};
|
|
25
30
|
publicKeys: Readonly<Record<string, string>>;
|
|
26
31
|
storage: "local" | "s3";
|
|
27
32
|
}) => string;
|
|
28
33
|
export declare const writeAbsoluteMobileUpdateRegistry: (options: {
|
|
29
34
|
force?: boolean;
|
|
35
|
+
health?: {
|
|
36
|
+
failureRate: number;
|
|
37
|
+
minimumReports: number;
|
|
38
|
+
secretEnv: string;
|
|
39
|
+
};
|
|
30
40
|
modulePath?: string;
|
|
31
41
|
projectRoot: string;
|
|
32
42
|
publicKeys: Readonly<Record<string, string>>;
|
package/dist/types/build.d.ts
CHANGED
|
@@ -111,6 +111,15 @@ type MobileSharedConfig = {
|
|
|
111
111
|
server?: {
|
|
112
112
|
/** Mount the update endpoint in the AbsoluteJS runtime. Defaults to true. */
|
|
113
113
|
autoMount?: boolean;
|
|
114
|
+
/** Anonymous fleet-health receipts and automatic rollout protection. Enabled by default. */
|
|
115
|
+
health?: false | {
|
|
116
|
+
/** Failure fraction that pauses a promotion. Defaults to 0.2. */
|
|
117
|
+
failureRate?: number;
|
|
118
|
+
/** Terminal activation/rollback sample required before pausing. Defaults to 20. */
|
|
119
|
+
minimumReports?: number;
|
|
120
|
+
/** Trusted-server secret environment variable. */
|
|
121
|
+
secretEnv?: string;
|
|
122
|
+
};
|
|
114
123
|
/** Project-relative registry module. Defaults to `mobile.update.ts`. */
|
|
115
124
|
registry?: string;
|
|
116
125
|
/** Environment variable containing the Expo RSA private key PEM. */
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@absolutejs/auth": ">=0.75.0 <0.77.0",
|
|
11
11
|
"@absolutejs/beacon": ">=0.7.0-beta.4 <0.8.0",
|
|
12
|
-
"@absolutejs/deploy": "0.25.
|
|
12
|
+
"@absolutejs/deploy": "0.25.11",
|
|
13
13
|
"@absolutejs/devices": "0.7.0",
|
|
14
14
|
"@absolutejs/devices-capacitor": "0.8.0",
|
|
15
15
|
"@absolutejs/devices-expo": "0.0.2",
|
|
@@ -523,7 +523,7 @@
|
|
|
523
523
|
]
|
|
524
524
|
}
|
|
525
525
|
},
|
|
526
|
-
"version": "0.20.0-beta.
|
|
526
|
+
"version": "0.20.0-beta.86",
|
|
527
527
|
"workspaces": [
|
|
528
528
|
"tests/fixtures/*",
|
|
529
529
|
"tests/fixtures/_packages/*"
|