@pwa-platform/entry-resilience 0.1.0 → 0.2.1
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/README.md +68 -42
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,87 +1,113 @@
|
|
|
1
1
|
# @pwa-platform/entry-resilience
|
|
2
2
|
|
|
3
|
-
Optional entry recovery for
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Optional entry recovery for an installed PWA whose original address is moving or unavailable. The package emits a
|
|
4
|
+
precache-protected recovery page, validates application-supplied entry manifests, stores the newest accepted
|
|
5
|
+
manifest locally and shows a validated alternative URL only when recovery conditions are met. It supports Vite 5
|
|
6
|
+
and Vite 8 on Node.js 22 or later.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
validated alternative address; navigation happens only after the user clicks it. Neither cookies nor login state
|
|
10
|
-
move between origins.
|
|
8
|
+
This is not an automatic redirect, cross-origin session transfer or trust service. Navigation happens only after
|
|
9
|
+
the user clicks the recovery link, and cookies or login state never move between origins.
|
|
11
10
|
|
|
12
|
-
## Install and
|
|
11
|
+
## Install and build integration
|
|
13
12
|
|
|
14
13
|
```sh
|
|
15
14
|
npm install @pwa-platform/entry-resilience @pwa-platform/vite
|
|
16
15
|
```
|
|
17
16
|
|
|
18
17
|
```ts
|
|
19
|
-
// vite.config.ts — reuse the identity
|
|
18
|
+
// vite.config.ts — reuse the exact identity object passed to pwa()
|
|
20
19
|
import { pwa } from "@pwa-platform/vite";
|
|
21
20
|
import { pwaEntryResilience } from "@pwa-platform/entry-resilience/vite";
|
|
22
21
|
|
|
23
22
|
plugins: [
|
|
24
23
|
pwa({ identity, policy, install, topology }),
|
|
25
|
-
pwaEntryResilience({
|
|
24
|
+
pwaEntryResilience({
|
|
25
|
+
identity,
|
|
26
|
+
maxValidityDays: 30,
|
|
27
|
+
locale: "zh-CN",
|
|
28
|
+
messages: { heading: "应用入口已变更" },
|
|
29
|
+
css: ".pwa-entry { --pwa-entry-accent: #006e52; }",
|
|
30
|
+
}),
|
|
26
31
|
]
|
|
27
32
|
```
|
|
28
33
|
|
|
29
|
-
The PWA policy must classify
|
|
30
|
-
script
|
|
31
|
-
`"zh-CN"` or `"en"`; `messages` overrides individual strings
|
|
32
|
-
default
|
|
33
|
-
`--pwa-entry-accent-fg` in `.pwa-entry`; see the [integration guide](https://github.com/haigeerlab/pwa-platform/blob/main/docs/guides/entry-recovery-integration.md)
|
|
34
|
-
for light/dark theme selectors and strict CSP hashes.
|
|
34
|
+
The PWA policy must classify mount-relative `/pwa-entry.html` as a `cache-first` asset and cover its fingerprinted
|
|
35
|
+
script (normally through `/assets`). The build rejects a recovery page that is not precached. `maxValidityDays`
|
|
36
|
+
accepts 1–90 and defaults to 30. `locale` accepts `"zh-CN"` or `"en"`; `messages` overrides individual strings;
|
|
37
|
+
`css` is appended after the default page style and must not contain a closing `</style` sequence.
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
## Browser integration
|
|
40
|
+
|
|
41
|
+
The application owns fetching, authentication, authorization, decryption and polling. Hand the already-decoded
|
|
42
|
+
object to the package:
|
|
38
43
|
|
|
39
|
-
|
|
44
|
+
```ts
|
|
45
|
+
import {
|
|
46
|
+
checkEntryRecovery,
|
|
47
|
+
setPwaTheme,
|
|
48
|
+
updateEntryManifest,
|
|
49
|
+
} from "@pwa-platform/entry-resilience/client";
|
|
50
|
+
|
|
51
|
+
const response = await fetch("/api/pwa-entry", { credentials: "include" });
|
|
52
|
+
const result = await updateEntryManifest(await response.json());
|
|
40
53
|
if (!result.accepted) reportDiagnostics(result.diagnostics);
|
|
41
54
|
|
|
42
55
|
const recovery = await checkEntryRecovery({ returnPath: location.pathname });
|
|
43
56
|
if (recovery.kind === "available") showRecoveryLink(recovery.recoveryPageUrl);
|
|
44
57
|
|
|
45
|
-
setPwaTheme("system"); //
|
|
58
|
+
setPwaTheme("system"); // "light", "dark" or "system"
|
|
46
59
|
```
|
|
47
60
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
Call `updateEntryManifest()` after a successful application-controlled fetch and at the application's chosen refresh
|
|
62
|
+
interval. `checkEntryRecovery()` probes the current entry and decides whether a recovery suggestion is warranted;
|
|
63
|
+
it does not navigate. `setPwaTheme()` stores a same-origin preference read by the recovery page and silently no-ops
|
|
64
|
+
when storage is unavailable.
|
|
51
65
|
|
|
52
|
-
##
|
|
66
|
+
## Manifest contract and validation
|
|
53
67
|
|
|
54
|
-
|
|
55
|
-
instead of being silently rejected only by a browser page.
|
|
68
|
+
Validate a manifest in CI or backend code with the side-effect-free root entry:
|
|
56
69
|
|
|
57
|
-
```
|
|
70
|
+
```ts
|
|
58
71
|
import { parseEntryManifest } from "@pwa-platform/entry-resilience";
|
|
59
72
|
|
|
73
|
+
const now = Date.now();
|
|
60
74
|
const manifest = {
|
|
61
75
|
sequence: 7,
|
|
62
|
-
expiresAt: "
|
|
76
|
+
expiresAt: new Date(now + 7 * 86_400_000).toISOString().replace(/\.\d{3}Z$/, "Z"),
|
|
63
77
|
status: "migrating",
|
|
64
|
-
reason: { code: "planned-migration", message: "
|
|
78
|
+
reason: { code: "planned-migration", message: "The old domain is retiring." },
|
|
65
79
|
entries: [{ origin: "https://new.example.com", startPath: "/app/" }],
|
|
66
80
|
};
|
|
67
81
|
|
|
68
82
|
const result = parseEntryManifest(manifest, {
|
|
69
|
-
appId: "
|
|
83
|
+
appId: "exampleapp",
|
|
70
84
|
environment: "production",
|
|
71
|
-
// Match the maxValidityDays in this app's Vite config.
|
|
72
85
|
maxValidityDays: 30,
|
|
73
|
-
|
|
74
|
-
now: Date.now(),
|
|
86
|
+
now,
|
|
75
87
|
});
|
|
76
88
|
|
|
77
|
-
if (!result.ok)
|
|
78
|
-
for (const { code, path } of result.diagnostics) {
|
|
79
|
-
console.error(`${path || "(manifest)"}: ${code}`);
|
|
80
|
-
}
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
89
|
+
if (!result.ok) throw new Error(result.diagnostics.map((item) => item.code).join(", "));
|
|
83
90
|
```
|
|
84
91
|
|
|
85
|
-
`
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
Use UTC `YYYY-MM-DDTHH:mm:ssZ` timestamps without milliseconds. Browsers additionally reject expired manifests and
|
|
93
|
+
sequences that do not advance beyond the locally accepted value.
|
|
94
|
+
|
|
95
|
+
## Export map
|
|
96
|
+
|
|
97
|
+
| Entry | Intended use |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| `@pwa-platform/entry-resilience` | Manifest types/diagnostics, `parseEntryManifest`, pure recovery orchestration and advanced browser ports. |
|
|
100
|
+
| `@pwa-platform/entry-resilience/vite` | `pwaEntryResilience()` and build option/page message types. |
|
|
101
|
+
| `@pwa-platform/entry-resilience/client` | `updateEntryManifest()`, `checkEntryRecovery()` and `setPwaTheme()`. |
|
|
102
|
+
|
|
103
|
+
## Security boundary
|
|
104
|
+
|
|
105
|
+
- The package validates schema, sequence and expiry; it does not authenticate the manifest source or restrict the
|
|
106
|
+
destination origins. Your backend and request layer are the trust boundary.
|
|
107
|
+
- Never expose a debugging hook that lets arbitrary page visitors call `updateEntryManifest()` with their own data.
|
|
108
|
+
- The recovery page displays a destination before a user click. It does not auto-redirect or transfer credentials.
|
|
109
|
+
- A normal manifest plus device-wide loss of connectivity does not create a domain-outage suggestion.
|
|
110
|
+
- Keep `identity` identical across both Vite plugins and treat identity changes as a migration.
|
|
111
|
+
|
|
112
|
+
See the complete [entry-recovery integration guide](https://github.com/haigeerlab/pwa-platform/blob/main/docs/guides/entry-recovery-integration.md)
|
|
113
|
+
and [entry-resilience specification](https://github.com/haigeerlab/pwa-platform/blob/main/spec/pwa-entry-resilience.md).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pwa-platform/entry-resilience",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Validated fallback entries for installed PWA applications.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"dist"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@pwa-platform/vite": "0.1
|
|
27
|
+
"@pwa-platform/vite": "0.2.1"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
30
|
"vite": "^5.0.0 || ^8.0.0"
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@playwright/test": "1.63.0",
|
|
34
34
|
"@types/node": "24.13.4",
|
|
35
35
|
"vite": "8.3.0",
|
|
36
|
-
"@pwa-platform/contracts": "0.1
|
|
36
|
+
"@pwa-platform/contracts": "0.2.1",
|
|
37
37
|
"@pwa-platform/browser-test-harness": "0.0.0"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|