@absolutejs/absolute 0.20.0-beta.60 → 0.20.0-beta.61
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/cli/index.js +547 -94
- package/dist/index.js +11 -3
- package/dist/index.js.map +3 -3
- package/dist/mobile/index.js +495 -50
- package/dist/mobile/index.js.map +7 -7
- package/dist/mobile/remoteMacAgentEntry.js +195 -195
- package/dist/mobile/shellUpdate.js +82 -6
- package/dist/src/mobile/capacitorBundle.d.ts +1 -0
- package/dist/src/mobile/config.d.ts +1 -0
- package/dist/src/mobile/transport.d.ts +1 -0
- package/dist/src/mobile/updateClient.d.ts +4 -0
- package/dist/src/mobile/updateRuntime.d.ts +1 -1
- package/dist/types/build.d.ts +2 -0
- package/package.json +7 -7
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/mobile/shellUpdate.ts
|
|
2
2
|
import { Directory, Filesystem } from "@capacitor/filesystem";
|
|
3
3
|
import { Preferences } from "@capacitor/preferences";
|
|
4
|
+
import { registerPlugin } from "@capacitor/core";
|
|
4
5
|
|
|
5
6
|
// src/mobile/updateProtocol.ts
|
|
6
7
|
var ABSOLUTE_MOBILE_UPDATE_FORMAT = 1;
|
|
@@ -238,6 +239,8 @@ var createAbsoluteMobileUpdateClient = (options) => {
|
|
|
238
239
|
throw new TypeError("Mobile update signature verification failed.");
|
|
239
240
|
if (manifest.releaseId === options.config.currentReleaseId)
|
|
240
241
|
return { kind: "current" };
|
|
242
|
+
if (options.config.blockedReleaseIds?.includes(manifest.releaseId))
|
|
243
|
+
return { kind: "quarantined", releaseId: manifest.releaseId };
|
|
241
244
|
if (!download)
|
|
242
245
|
return { kind: "update-available", manifest };
|
|
243
246
|
await options.store.begin(manifest);
|
|
@@ -261,6 +264,7 @@ var createAbsoluteMobileUpdateClient = (options) => {
|
|
|
261
264
|
var STATE_KEY = "absolute.mobile.update.state.v1";
|
|
262
265
|
var INSTALLATION_KEY = "absolute.mobile.update.installation.v1";
|
|
263
266
|
var ROOT = "NoCloud/ionic_built_snapshots";
|
|
267
|
+
var watchdog = registerPlugin("AbsoluteMobileUpdateWatchdog");
|
|
264
268
|
var base64Bytes = (value) => Uint8Array.from(atob(value), (character) => character.charCodeAt(0));
|
|
265
269
|
var arrayBuffer = (value) => new Uint8Array(value).buffer;
|
|
266
270
|
var bytesBase64 = (value) => {
|
|
@@ -283,10 +287,35 @@ var readState = async () => {
|
|
|
283
287
|
const candidate = Reflect.get(parsed, key);
|
|
284
288
|
return typeof candidate === "string" ? candidate : undefined;
|
|
285
289
|
};
|
|
290
|
+
const number = (key) => {
|
|
291
|
+
const candidate = Reflect.get(parsed, key);
|
|
292
|
+
return typeof candidate === "number" && Number.isFinite(candidate) ? candidate : undefined;
|
|
293
|
+
};
|
|
294
|
+
const recoveryValue = Reflect.get(parsed, "recovery");
|
|
295
|
+
const quarantineValue = Reflect.get(parsed, "quarantinedReleases");
|
|
296
|
+
const quarantinedReleases = Array.isArray(quarantineValue) ? [
|
|
297
|
+
...new Set(quarantineValue.filter((candidateRelease) => typeof candidateRelease === "string" && /^amu_[a-f0-9]{64}$/u.test(candidateRelease)))
|
|
298
|
+
].slice(-8) : [];
|
|
299
|
+
const recovery = typeof recoveryValue === "object" && recoveryValue !== null ? {
|
|
300
|
+
durationMs: Reflect.get(recoveryValue, "durationMs"),
|
|
301
|
+
reason: Reflect.get(recoveryValue, "reason"),
|
|
302
|
+
releaseId: Reflect.get(recoveryValue, "releaseId")
|
|
303
|
+
} : undefined;
|
|
304
|
+
let validRecovery;
|
|
305
|
+
if (recovery && typeof recovery.durationMs === "number" && Number.isFinite(recovery.durationMs) && recovery.durationMs >= 0 && (recovery.reason === "boot-interrupted" || recovery.reason === "boot-timeout") && typeof recovery.releaseId === "string")
|
|
306
|
+
validRecovery = {
|
|
307
|
+
durationMs: recovery.durationMs,
|
|
308
|
+
reason: recovery.reason,
|
|
309
|
+
releaseId: recovery.releaseId
|
|
310
|
+
};
|
|
286
311
|
return {
|
|
287
312
|
...text("activeRelease") ? { activeRelease: text("activeRelease") } : {},
|
|
288
313
|
...text("pendingRelease") ? { pendingRelease: text("pendingRelease") } : {},
|
|
289
|
-
...
|
|
314
|
+
...number("pendingStartedAt") === undefined ? {} : { pendingStartedAt: number("pendingStartedAt") },
|
|
315
|
+
...text("previousPath") ? { previousPath: text("previousPath") } : {},
|
|
316
|
+
...quarantinedReleases.length > 0 ? { quarantinedReleases } : {},
|
|
317
|
+
...text("readyRelease") ? { readyRelease: text("readyRelease") } : {},
|
|
318
|
+
...validRecovery ? { recovery: validRecovery } : {}
|
|
290
319
|
};
|
|
291
320
|
} catch {
|
|
292
321
|
return {};
|
|
@@ -336,18 +365,39 @@ var createStore = () => {
|
|
|
336
365
|
await removeRelease(releaseId);
|
|
337
366
|
const state = await readState();
|
|
338
367
|
if (state.readyRelease === releaseId || state.pendingRelease === releaseId)
|
|
339
|
-
await writeState({
|
|
368
|
+
await writeState({
|
|
369
|
+
activeRelease: state.activeRelease,
|
|
370
|
+
quarantinedReleases: state.quarantinedReleases,
|
|
371
|
+
recovery: state.recovery
|
|
372
|
+
});
|
|
340
373
|
},
|
|
341
374
|
activate: async (releaseId) => {
|
|
342
375
|
const state = await readState();
|
|
343
376
|
if (state.readyRelease !== releaseId)
|
|
344
377
|
throw new TypeError("Mobile update is not committed and ready to activate.");
|
|
345
378
|
const path = await releaseNativePath(releaseId);
|
|
379
|
+
const previousPath = await currentServerBasePath();
|
|
346
380
|
await writeState({
|
|
347
381
|
activeRelease: state.activeRelease,
|
|
348
|
-
pendingRelease: releaseId
|
|
382
|
+
pendingRelease: releaseId,
|
|
383
|
+
pendingStartedAt: Date.now(),
|
|
384
|
+
previousPath,
|
|
385
|
+
quarantinedReleases: state.quarantinedReleases
|
|
349
386
|
});
|
|
350
|
-
|
|
387
|
+
try {
|
|
388
|
+
await watchdog.arm({ releaseId });
|
|
389
|
+
webView().setServerBasePath(path);
|
|
390
|
+
} catch (error) {
|
|
391
|
+
await watchdog.confirm({ releaseId }).catch(() => {
|
|
392
|
+
return;
|
|
393
|
+
});
|
|
394
|
+
await removeRelease(releaseId);
|
|
395
|
+
await writeState({
|
|
396
|
+
activeRelease: state.activeRelease,
|
|
397
|
+
quarantinedReleases: state.quarantinedReleases
|
|
398
|
+
});
|
|
399
|
+
throw error;
|
|
400
|
+
}
|
|
351
401
|
},
|
|
352
402
|
begin: async (manifest) => {
|
|
353
403
|
await removeRelease(manifest.releaseId);
|
|
@@ -364,6 +414,7 @@ var createStore = () => {
|
|
|
364
414
|
const state = await readState();
|
|
365
415
|
await writeState({
|
|
366
416
|
activeRelease: state.activeRelease,
|
|
417
|
+
quarantinedReleases: state.quarantinedReleases,
|
|
367
418
|
readyRelease: manifest.releaseId
|
|
368
419
|
});
|
|
369
420
|
staging = undefined;
|
|
@@ -416,18 +467,34 @@ var reconcilePendingRelease = async (store, state) => {
|
|
|
416
467
|
webView().persistServerBasePath();
|
|
417
468
|
const next = { activeRelease: state.pendingRelease };
|
|
418
469
|
await writeState(next);
|
|
470
|
+
await watchdog.confirm({ releaseId: state.pendingRelease });
|
|
419
471
|
await removePriorRelease(state.activeRelease, next.activeRelease);
|
|
420
472
|
emitUpdateResult({ kind: "activated", releaseId: next.activeRelease });
|
|
421
473
|
return next;
|
|
422
474
|
};
|
|
475
|
+
var consumeNativeRecovery = async (state) => {
|
|
476
|
+
if (!state.recovery)
|
|
477
|
+
return state;
|
|
478
|
+
const { recovery, ...next } = state;
|
|
479
|
+
emitUpdateResult({
|
|
480
|
+
durationMs: Math.round(recovery.durationMs),
|
|
481
|
+
kind: "rolled-back",
|
|
482
|
+
reason: recovery.reason,
|
|
483
|
+
releaseId: recovery.releaseId
|
|
484
|
+
});
|
|
485
|
+
await writeState(next);
|
|
486
|
+
return next;
|
|
487
|
+
};
|
|
423
488
|
var installAbsoluteMobileShellUpdates = async (manifest) => {
|
|
424
489
|
if (!manifest.updates)
|
|
425
490
|
return;
|
|
426
491
|
const store = createStore();
|
|
427
|
-
const
|
|
492
|
+
const recovered = await consumeNativeRecovery(await readState());
|
|
493
|
+
const state = await reconcilePendingRelease(store, recovered);
|
|
428
494
|
const client = createAbsoluteMobileUpdateClient({
|
|
429
495
|
config: {
|
|
430
496
|
appId: manifest.appId,
|
|
497
|
+
blockedReleaseIds: state.quarantinedReleases ?? [],
|
|
431
498
|
channel: manifest.updates.channel,
|
|
432
499
|
currentReleaseId: state.activeRelease ?? `embedded:${manifest.appBuild}`,
|
|
433
500
|
installationId: await installationId(),
|
|
@@ -446,7 +513,16 @@ var installAbsoluteMobileShellUpdates = async (manifest) => {
|
|
|
446
513
|
});
|
|
447
514
|
await client.activate(result.manifest.releaseId);
|
|
448
515
|
};
|
|
449
|
-
client.download().then(
|
|
516
|
+
client.download().then((result) => {
|
|
517
|
+
if (result.kind === "quarantined") {
|
|
518
|
+
emitUpdateResult({
|
|
519
|
+
kind: "quarantined",
|
|
520
|
+
releaseId: result.releaseId
|
|
521
|
+
});
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
return activateDownloaded(result);
|
|
525
|
+
}).catch((error) => {
|
|
450
526
|
console.error("[Absolute Mobile] Update failed:", error);
|
|
451
527
|
emitUpdateResult({ kind: "failed" });
|
|
452
528
|
});
|
|
@@ -24,6 +24,7 @@ export declare const materializeAbsoluteCapacitorWebBundle: (options: AbsoluteCa
|
|
|
24
24
|
storageSchema: SyncLocalStoreSchemaBundle;
|
|
25
25
|
} | undefined;
|
|
26
26
|
updates?: {
|
|
27
|
+
bootTimeoutMs: number;
|
|
27
28
|
channel: string;
|
|
28
29
|
manifestUrl: string;
|
|
29
30
|
publicKeys: Record<string, string>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type AbsoluteMobileUpdateFile, type AbsoluteMobileUpdateManifest } from './updateProtocol';
|
|
2
2
|
export type AbsoluteMobileUpdateClientConfig = {
|
|
3
3
|
appId: string;
|
|
4
|
+
blockedReleaseIds?: readonly string[];
|
|
4
5
|
channel: string;
|
|
5
6
|
currentReleaseId: string;
|
|
6
7
|
installationId: string;
|
|
@@ -29,6 +30,9 @@ export type AbsoluteMobileUpdateCheckResult = {
|
|
|
29
30
|
} | {
|
|
30
31
|
kind: 'downloaded';
|
|
31
32
|
manifest: AbsoluteMobileUpdateManifest;
|
|
33
|
+
} | {
|
|
34
|
+
kind: 'quarantined';
|
|
35
|
+
releaseId: string;
|
|
32
36
|
} | {
|
|
33
37
|
kind: 'update-available';
|
|
34
38
|
manifest: AbsoluteMobileUpdateManifest;
|
|
@@ -2,7 +2,7 @@ import type { AbsoluteDeviceCapabilityPlan } from './deviceCapabilities';
|
|
|
2
2
|
import type { NormalizedAbsoluteMobileConfig } from './config';
|
|
3
3
|
import type { AbsoluteMobileAuthManifest } from './nativeAuth';
|
|
4
4
|
import type { SyncLocalStoreSchemaBundle } from '@absolutejs/sync/client';
|
|
5
|
-
export declare const ABSOLUTE_MOBILE_SHELL_ABI:
|
|
5
|
+
export declare const ABSOLUTE_MOBILE_SHELL_ABI: 2;
|
|
6
6
|
export declare const ABSOLUTE_MOBILE_UPDATE_RUNTIME_FORMAT: 1;
|
|
7
7
|
export type AbsoluteMobileUpdateRuntimeDescriptor = {
|
|
8
8
|
appId: string;
|
package/dist/types/build.d.ts
CHANGED
|
@@ -57,6 +57,8 @@ type MobileSharedConfig = {
|
|
|
57
57
|
};
|
|
58
58
|
/** Signed over-the-air web-bundle updates. Native capability changes still require a store build. */
|
|
59
59
|
updates?: {
|
|
60
|
+
/** Maximum time an activated bundle may take to render its first page before native rollback. Defaults to 20 seconds. */
|
|
61
|
+
bootTimeoutMs?: number;
|
|
60
62
|
/** Release channel. Defaults to `production`. */
|
|
61
63
|
channel?: string;
|
|
62
64
|
/** Exact signed-manifest URL. Defaults to the AbsoluteJS production origin. */
|
package/package.json
CHANGED
|
@@ -293,12 +293,12 @@
|
|
|
293
293
|
"main": "./dist/index.js",
|
|
294
294
|
"name": "@absolutejs/absolute",
|
|
295
295
|
"optionalDependencies": {
|
|
296
|
-
"@absolutejs/native-darwin-arm64": "0.20.0-beta.
|
|
297
|
-
"@absolutejs/native-darwin-x64": "0.20.0-beta.
|
|
298
|
-
"@absolutejs/native-linux-arm64": "0.20.0-beta.
|
|
299
|
-
"@absolutejs/native-linux-x64": "0.20.0-beta.
|
|
300
|
-
"@absolutejs/native-windows-arm64": "0.20.0-beta.
|
|
301
|
-
"@absolutejs/native-windows-x64": "0.20.0-beta.
|
|
296
|
+
"@absolutejs/native-darwin-arm64": "0.20.0-beta.61",
|
|
297
|
+
"@absolutejs/native-darwin-x64": "0.20.0-beta.61",
|
|
298
|
+
"@absolutejs/native-linux-arm64": "0.20.0-beta.61",
|
|
299
|
+
"@absolutejs/native-linux-x64": "0.20.0-beta.61",
|
|
300
|
+
"@absolutejs/native-windows-arm64": "0.20.0-beta.61",
|
|
301
|
+
"@absolutejs/native-windows-x64": "0.20.0-beta.61"
|
|
302
302
|
},
|
|
303
303
|
"overrides": {
|
|
304
304
|
"@sinclair/typebox": "0.34.52",
|
|
@@ -514,7 +514,7 @@
|
|
|
514
514
|
]
|
|
515
515
|
}
|
|
516
516
|
},
|
|
517
|
-
"version": "0.20.0-beta.
|
|
517
|
+
"version": "0.20.0-beta.61",
|
|
518
518
|
"workspaces": [
|
|
519
519
|
"tests/fixtures/*",
|
|
520
520
|
"tests/fixtures/_packages/*"
|