@interop/was-react 0.1.5 → 0.1.7

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.
Files changed (81) hide show
  1. package/dist/auth/loginRequest.d.ts +4 -9
  2. package/dist/auth/loginRequest.d.ts.map +1 -1
  3. package/dist/auth/loginRequest.js +2 -13
  4. package/dist/auth/loginRequest.js.map +1 -1
  5. package/dist/auth/walletRequestTypes.d.ts +3 -2
  6. package/dist/auth/walletRequestTypes.d.ts.map +1 -1
  7. package/dist/config.d.ts +22 -0
  8. package/dist/config.d.ts.map +1 -1
  9. package/dist/config.js +5 -0
  10. package/dist/config.js.map +1 -1
  11. package/dist/grants.d.ts +10 -8
  12. package/dist/grants.d.ts.map +1 -1
  13. package/dist/grants.js +12 -9
  14. package/dist/grants.js.map +1 -1
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +4 -4
  18. package/dist/index.js.map +1 -1
  19. package/dist/mui/AdoptDialog.d.ts +12 -0
  20. package/dist/mui/AdoptDialog.d.ts.map +1 -0
  21. package/dist/mui/AdoptDialog.js +31 -0
  22. package/dist/mui/AdoptDialog.js.map +1 -0
  23. package/dist/mui/ClearDataDialog.d.ts +12 -0
  24. package/dist/mui/ClearDataDialog.d.ts.map +1 -0
  25. package/dist/mui/ClearDataDialog.js +30 -0
  26. package/dist/mui/ClearDataDialog.js.map +1 -0
  27. package/dist/mui/LogoutDialog.d.ts +12 -0
  28. package/dist/mui/LogoutDialog.d.ts.map +1 -0
  29. package/dist/mui/LogoutDialog.js +30 -0
  30. package/dist/mui/LogoutDialog.js.map +1 -0
  31. package/dist/mui/ProtectedRoute.d.ts +2 -2
  32. package/dist/mui/ProtectedRoute.d.ts.map +1 -1
  33. package/dist/mui/ProtectedRoute.js +30 -23
  34. package/dist/mui/ProtectedRoute.js.map +1 -1
  35. package/dist/mui/index.d.ts +3 -0
  36. package/dist/mui/index.d.ts.map +1 -1
  37. package/dist/mui/index.js +3 -0
  38. package/dist/mui/index.js.map +1 -1
  39. package/dist/react/WasSessionProvider.d.ts.map +1 -1
  40. package/dist/react/WasSessionProvider.js +8 -4
  41. package/dist/react/WasSessionProvider.js.map +1 -1
  42. package/dist/react/hooks.d.ts +33 -5
  43. package/dist/react/hooks.d.ts.map +1 -1
  44. package/dist/react/hooks.js +36 -6
  45. package/dist/react/hooks.js.map +1 -1
  46. package/dist/react/index.d.ts +1 -1
  47. package/dist/react/index.d.ts.map +1 -1
  48. package/dist/react/index.js +1 -1
  49. package/dist/react/index.js.map +1 -1
  50. package/dist/session/authStore.d.ts +111 -22
  51. package/dist/session/authStore.d.ts.map +1 -1
  52. package/dist/session/authStore.js +337 -81
  53. package/dist/session/authStore.js.map +1 -1
  54. package/dist/session/index.d.ts +3 -4
  55. package/dist/session/index.d.ts.map +1 -1
  56. package/dist/session/index.js +2 -3
  57. package/dist/session/index.js.map +1 -1
  58. package/dist/storage/adopt.d.ts +20 -0
  59. package/dist/storage/adopt.d.ts.map +1 -0
  60. package/dist/storage/adopt.js +78 -0
  61. package/dist/storage/adopt.js.map +1 -0
  62. package/dist/storage/entityStore.d.ts.map +1 -1
  63. package/dist/storage/entityStore.js +1 -15
  64. package/dist/storage/entityStore.js.map +1 -1
  65. package/dist/storage/localStore.d.ts +33 -3
  66. package/dist/storage/localStore.d.ts.map +1 -1
  67. package/dist/storage/localStore.js +35 -1
  68. package/dist/storage/localStore.js.map +1 -1
  69. package/dist/sync/index.d.ts +1 -1
  70. package/dist/sync/index.d.ts.map +1 -1
  71. package/dist/sync/index.js +1 -1
  72. package/dist/sync/index.js.map +1 -1
  73. package/dist/sync/lww.d.ts +12 -0
  74. package/dist/sync/lww.d.ts.map +1 -1
  75. package/dist/sync/lww.js +14 -0
  76. package/dist/sync/lww.js.map +1 -1
  77. package/package.json +1 -1
  78. package/dist/session/appReadyStore.d.ts +0 -10
  79. package/dist/session/appReadyStore.d.ts.map +0 -1
  80. package/dist/session/appReadyStore.js +0 -22
  81. package/dist/session/appReadyStore.js.map +0 -1
@@ -3,17 +3,26 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  * Copyright (c) 2026 Interop Alliance. All rights reserved.
4
4
  */
5
5
  /**
6
- * The auth + hydration gate (wallet mode). Attempts the zero-popup session
7
- * restore; an unauthenticated visitor is redirected to the login path, and the
8
- * routed pages render only once the restored session has hydrated the stores.
6
+ * The router gate: a thin switch over the app's `onboarding` mode. While the
7
+ * session is booting it shows a spinner; a `local-first` app then always renders
8
+ * the routed pages (over the anonymous replica), while a `login-gated` app
9
+ * renders them only once the wallet is connected and otherwise redirects to the
10
+ * login path. Uses react-router's `Navigate` / `Outlet`.
9
11
  *
10
- * Apps with a local dev mode wrap their own gate; this component is wallet-mode
11
- * only. Uses react-router's `Navigate` / `Outlet`.
12
+ * Boot is kicked off by {@link WasSessionProvider} on mount, not here, so a
13
+ * local-first app that never mounts this component still boots.
14
+ *
15
+ * The fatal-error alert (`data-testid="bootstrap-error"`) is scoped to
16
+ * boot/storage failures ONLY: it renders solely while `status === 'boot'` with
17
+ * an `error`, which the store only produces when even the anonymous local
18
+ * replica cannot be opened. A failed or cancelled wallet login (or a reconnect
19
+ * failure) sets the store's `error` too, but only after `status` has left `boot`
20
+ * (to `local` / `reconnect`), so it never blanks a local-first app with this
21
+ * alert -- the login page surfaces that error instead.
12
22
  */
13
- import { useEffect } from 'react';
14
23
  import { Navigate, Outlet } from 'react-router';
15
24
  import { Alert, Box, CircularProgress, Typography } from '@mui/material';
16
- import { useAppReady, useAuthStore, useSession } from '../react/hooks.js';
25
+ import { useSession } from '../react/hooks.js';
17
26
  function CenteredSpinner({ label }) {
18
27
  return (_jsxs(Box, { sx: {
19
28
  display: 'flex',
@@ -26,29 +35,27 @@ function CenteredSpinner({ label }) {
26
35
  }
27
36
  /**
28
37
  * @param props {object}
29
- * @param [props.loginPath] {string} where to send an unauthenticated visitor
30
- * (defaults to `/login`)
38
+ * @param [props.loginPath] {string} where to send a not-yet-connected visitor
39
+ * in a login-gated app (defaults to `/login`)
31
40
  * @returns {ReactNode}
32
41
  */
33
42
  export function ProtectedRoute({ loginPath = '/login' } = {}) {
34
- const store = useAuthStore();
35
- const { status } = useSession();
36
- const { ready, error } = useAppReady();
37
- useEffect(() => {
38
- void store.getState().restore();
39
- }, [store]);
40
- if (error) {
43
+ const { status, onboarding, error } = useSession();
44
+ // Only a boot/storage failure (error present while still in `boot`) replaces
45
+ // the app with the fatal alert; a login/reconnect error never reaches here.
46
+ if (status === 'boot' && error) {
41
47
  return (_jsx(Box, { sx: { p: 4 }, children: _jsxs(Alert, { severity: "error", "data-testid": "bootstrap-error", children: ["Failed to open local storage: ", error] }) }));
42
48
  }
43
- if (status === 'idle' || status === 'restoring') {
44
- return _jsx(CenteredSpinner, { label: "Restoring your session..." });
49
+ if (status === 'boot') {
50
+ return _jsx(CenteredSpinner, { label: "Loading..." });
45
51
  }
46
- if (status !== 'authenticated') {
47
- return _jsx(Navigate, { to: loginPath, replace: true });
52
+ if (onboarding === 'local-first') {
53
+ return _jsx(Outlet, {});
48
54
  }
49
- if (!ready) {
50
- return _jsx(CenteredSpinner, { label: "Opening your storage..." });
55
+ // login-gated: the app is reachable only once a wallet is connected.
56
+ if (status === 'connected' || status === 'reconnect') {
57
+ return _jsx(Outlet, {});
51
58
  }
52
- return _jsx(Outlet, {});
59
+ return _jsx(Navigate, { to: loginPath, replace: true });
53
60
  }
54
61
  //# sourceMappingURL=ProtectedRoute.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProtectedRoute.js","sourceRoot":"","sources":["../../src/mui/ProtectedRoute.tsx"],"names":[],"mappings":";AAAA;;GAEG;AACH;;;;;;;GAOG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AACxE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEzE,SAAS,eAAe,CAAC,EAAE,KAAK,EAAqB;IACnD,OAAO,CACL,MAAC,GAAG,IACF,EAAE,EAAE;YACF,OAAO,EAAE,MAAM;YACf,aAAa,EAAE,QAAQ;YACvB,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,GAAG,EAAE,CAAC;YACN,SAAS,EAAE,MAAM;SAClB,iBACW,mBAAmB,aAE/B,KAAC,gBAAgB,KAAG,EACpB,KAAC,UAAU,IAAC,KAAK,EAAC,gBAAgB,YAAE,KAAK,GAAc,IACnD,CACP,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,SAAS,GAAG,QAAQ,KAGlB,EAAE;IACJ,MAAM,KAAK,GAAG,YAAY,EAAE,CAAA;IAC5B,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,CAAA;IAC/B,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,WAAW,EAAE,CAAA;IAEtC,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAA;IACjC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAEX,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CACL,KAAC,GAAG,IAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,YACf,MAAC,KAAK,IAAC,QAAQ,EAAC,OAAO,iBAAa,iBAAiB,+CACpB,KAAK,IAC9B,GACJ,CACP,CAAA;IACH,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;QAChD,OAAO,KAAC,eAAe,IAAC,KAAK,EAAC,2BAA2B,GAAG,CAAA;IAC9D,CAAC;IACD,IAAI,MAAM,KAAK,eAAe,EAAE,CAAC;QAC/B,OAAO,KAAC,QAAQ,IAAC,EAAE,EAAE,SAAS,EAAE,OAAO,SAAG,CAAA;IAC5C,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,KAAC,eAAe,IAAC,KAAK,EAAC,yBAAyB,GAAG,CAAA;IAC5D,CAAC;IAED,OAAO,KAAC,MAAM,KAAG,CAAA;AACnB,CAAC"}
1
+ {"version":3,"file":"ProtectedRoute.js","sourceRoot":"","sources":["../../src/mui/ProtectedRoute.tsx"],"names":[],"mappings":";AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,SAAS,eAAe,CAAC,EAAE,KAAK,EAAqB;IACnD,OAAO,CACL,MAAC,GAAG,IACF,EAAE,EAAE;YACF,OAAO,EAAE,MAAM;YACf,aAAa,EAAE,QAAQ;YACvB,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,GAAG,EAAE,CAAC;YACN,SAAS,EAAE,MAAM;SAClB,iBACW,mBAAmB,aAE/B,KAAC,gBAAgB,KAAG,EACpB,KAAC,UAAU,IAAC,KAAK,EAAC,gBAAgB,YAAE,KAAK,GAAc,IACnD,CACP,CAAA;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,SAAS,GAAG,QAAQ,KAGlB,EAAE;IACJ,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,UAAU,EAAE,CAAA;IAElD,6EAA6E;IAC7E,4EAA4E;IAC5E,IAAI,MAAM,KAAK,MAAM,IAAI,KAAK,EAAE,CAAC;QAC/B,OAAO,CACL,KAAC,GAAG,IAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,YACf,MAAC,KAAK,IAAC,QAAQ,EAAC,OAAO,iBAAa,iBAAiB,+CACpB,KAAK,IAC9B,GACJ,CACP,CAAA;IACH,CAAC;IAED,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACtB,OAAO,KAAC,eAAe,IAAC,KAAK,EAAC,YAAY,GAAG,CAAA;IAC/C,CAAC;IACD,IAAI,UAAU,KAAK,aAAa,EAAE,CAAC;QACjC,OAAO,KAAC,MAAM,KAAG,CAAA;IACnB,CAAC;IACD,qEAAqE;IACrE,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,WAAW,EAAE,CAAC;QACrD,OAAO,KAAC,MAAM,KAAG,CAAA;IACnB,CAAC;IACD,OAAO,KAAC,QAAQ,IAAC,EAAE,EAAE,SAAS,EAAE,OAAO,SAAG,CAAA;AAC5C,CAAC"}
@@ -9,4 +9,7 @@
9
9
  export { ProtectedRoute } from './ProtectedRoute.js';
10
10
  export { ReconnectBanner } from './ReconnectBanner.js';
11
11
  export { SyncStatusChip } from './SyncStatusChip.js';
12
+ export { LogoutDialog } from './LogoutDialog.js';
13
+ export { ClearDataDialog } from './ClearDataDialog.js';
14
+ export { AdoptDialog } from './AdoptDialog.js';
12
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mui/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mui/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA"}
package/dist/mui/index.js CHANGED
@@ -9,4 +9,7 @@
9
9
  export { ProtectedRoute } from './ProtectedRoute.js';
10
10
  export { ReconnectBanner } from './ReconnectBanner.js';
11
11
  export { SyncStatusChip } from './SyncStatusChip.js';
12
+ export { LogoutDialog } from './LogoutDialog.js';
13
+ export { ClearDataDialog } from './ClearDataDialog.js';
14
+ export { AdoptDialog } from './AdoptDialog.js';
12
15
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mui/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mui/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"WasSessionProvider.d.ts","sourceRoot":"","sources":["../../src/react/WasSessionProvider.tsx"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;GAQG;AACH,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAE5E;;;GAGG;AACH,eAAO,MAAM,iBAAiB,8CAA2C,CAAA;AAEzE;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,QAAQ,EACR,QAAQ,EACT,EAAE;IACD,MAAM,EAAE,YAAY,CAAA;IACpB,QAAQ,EAAE,aAAa,CAAA;IACvB,QAAQ,EAAE,SAAS,CAAA;CACpB,GAAG,SAAS,CAkBZ"}
1
+ {"version":3,"file":"WasSessionProvider.d.ts","sourceRoot":"","sources":["../../src/react/WasSessionProvider.tsx"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;GAQG;AACH,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAE5E;;;GAGG;AACH,eAAO,MAAM,iBAAiB,8CAA2C,CAAA;AAEzE;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,QAAQ,EACR,QAAQ,EACT,EAAE;IACD,MAAM,EAAE,YAAY,CAAA;IACpB,QAAQ,EAAE,aAAa,CAAA;IACvB,QAAQ,EAAE,SAAS,CAAA;CACpB,GAAG,SAAS,CAsBZ"}
@@ -30,11 +30,15 @@ export const WasSessionContext = createContext(null);
30
30
  */
31
31
  export function WasSessionProvider({ config, registry, children }) {
32
32
  const [store] = useState(() => createAuthStore({ config, registry }));
33
- // Tear the live session down on unmount so an abandoned provider never leaves
34
- // the expiry-watch interval and the replication loop firing against a store no
35
- // one is reading (reliably hit by React StrictMode dev remounts and by tests).
36
- // The persisted record survives, so a remount's `restore()` re-opens it.
33
+ // Kick off boot on mount (so a local-first app that never renders
34
+ // `ProtectedRoute` still boots), and tear the live session down on unmount so
35
+ // an abandoned provider never leaves the expiry-watch interval and the
36
+ // replication loop firing against a store no one is reading (reliably hit by
37
+ // React StrictMode dev remounts and by tests). `destroy()` returns the store
38
+ // to `boot` with both persisted seeds intact, so a StrictMode remount's
39
+ // `boot()` re-opens the same session (or fresh local).
37
40
  useEffect(() => {
41
+ void store.getState().boot();
38
42
  return () => {
39
43
  void store.getState().destroy();
40
44
  };
@@ -1 +1 @@
1
- {"version":3,"file":"WasSessionProvider.js","sourceRoot":"","sources":["../../src/react/WasSessionProvider.tsx"],"names":[],"mappings":";AAAA;;GAEG;AACH;;;;;;;;GAQG;AACH,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AAE1E,OAAO,EAAE,eAAe,EAAqB,MAAM,yBAAyB,CAAA;AAE5E;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAsB,IAAI,CAAC,CAAA;AAEzE;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAAC,EACjC,MAAM,EACN,QAAQ,EACR,QAAQ,EAKT;IACC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAe,GAAG,EAAE,CAC1C,eAAe,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CACtC,CAAA;IACD,8EAA8E;IAC9E,+EAA+E;IAC/E,+EAA+E;IAC/E,yEAAyE;IACzE,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE;YACV,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAA;QACjC,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IACX,OAAO,CACL,KAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YACrC,QAAQ,GACkB,CAC9B,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"WasSessionProvider.js","sourceRoot":"","sources":["../../src/react/WasSessionProvider.tsx"],"names":[],"mappings":";AAAA;;GAEG;AACH;;;;;;;;GAQG;AACH,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAA;AAE1E,OAAO,EAAE,eAAe,EAAqB,MAAM,yBAAyB,CAAA;AAE5E;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAsB,IAAI,CAAC,CAAA;AAEzE;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAAC,EACjC,MAAM,EACN,QAAQ,EACR,QAAQ,EAKT;IACC,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAe,GAAG,EAAE,CAC1C,eAAe,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CACtC,CAAA;IACD,kEAAkE;IAClE,8EAA8E;IAC9E,uEAAuE;IACvE,6EAA6E;IAC7E,6EAA6E;IAC7E,wEAAwE;IACxE,uDAAuD;IACvD,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAA;QAC5B,OAAO,GAAG,EAAE;YACV,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAA;QACjC,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IACX,OAAO,CACL,KAAC,iBAAiB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YACrC,QAAQ,GACkB,CAC9B,CAAA;AACH,CAAC"}
@@ -1,6 +1,5 @@
1
1
  import type { WasAuthStore } from '../session/authStore.js';
2
2
  import { type SyncRollup } from '../storage/syncStatusStore.js';
3
- export { useAppReady } from '../session/appReadyStore.js';
4
3
  /**
5
4
  * The bound auth store from the nearest {@link WasSessionProvider}. Throws a
6
5
  * helpful error when used outside a provider.
@@ -16,6 +15,8 @@ export declare function useAuthStore(): WasAuthStore;
16
15
  */
17
16
  export declare function useSession(): {
18
17
  status: ReturnType<WasAuthStore['getState']>['status'];
18
+ onboarding: ReturnType<WasAuthStore['getState']>['onboarding'];
19
+ authenticating: boolean;
19
20
  phase: ReturnType<WasAuthStore['getState']>['phase'];
20
21
  error: string | null;
21
22
  controllerDid: string | null;
@@ -24,22 +25,49 @@ export declare function useSession(): {
24
25
  reconnecting: boolean;
25
26
  };
26
27
  /**
27
- * The login action plus the state the login page renders (status/phase/error).
28
+ * The login action plus the state the login page renders. `authenticating` is
29
+ * the in-flight flag (the `status` stays `local` during login); `status` is
30
+ * exposed so a login page can redirect once it reads `connected`. `login`
31
+ * accepts `{ adopt }` -- `'merge'` (default) migrates data created in `local`
32
+ * into the connected replica, `'leave'` sets it aside untouched.
28
33
  *
29
34
  * @returns {object}
30
35
  */
31
36
  export declare function useLogin(): {
32
- login: () => Promise<void>;
37
+ login: (options?: {
38
+ adopt?: 'merge' | 'leave';
39
+ }) => Promise<void>;
40
+ authenticating: boolean;
33
41
  status: ReturnType<WasAuthStore['getState']>['status'];
34
42
  phase: ReturnType<WasAuthStore['getState']>['phase'];
35
43
  error: string | null;
36
44
  };
37
45
  /**
38
- * The logout action.
46
+ * The logout action; accepts `{ wipe }` to delete the connected replica rather
47
+ * than keep it on the device.
48
+ *
49
+ * @returns {(options?: { wipe?: boolean }) => Promise<void>}
50
+ */
51
+ export declare function useLogout(): (options?: {
52
+ wipe?: boolean;
53
+ }) => Promise<void>;
54
+ /**
55
+ * The clear-data action: deletes the local replica, discards the anonymous
56
+ * seed, and mints a fresh anonymous seed/DID + replica (the `local`-mode
57
+ * "Clear data" affordance).
39
58
  *
40
59
  * @returns {() => Promise<void>}
41
60
  */
42
- export declare function useLogout(): () => Promise<void>;
61
+ export declare function useClearData(): () => Promise<void>;
62
+ /**
63
+ * Whether the anonymous `local` replica currently holds any documents -- the
64
+ * check a login affordance runs at decision time (e.g. on the login button
65
+ * click) to choose between opening the adoption dialog and calling `login()`
66
+ * directly. Returns the async check, not a subscription.
67
+ *
68
+ * @returns {() => Promise<boolean>}
69
+ */
70
+ export declare function useHasLocalData(): () => Promise<boolean>;
43
71
  /**
44
72
  * The expired-access reconnect: the banner flags plus the reconnect action.
45
73
  *
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/react/hooks.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,+BAA+B,CAAA;AAEtC,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAEzD;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,YAAY,CAS3C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI;IAC5B,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;IACtD,KAAK,EAAE,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IACpD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,aAAa,EAAE,OAAO,CAAA;IACtB,YAAY,EAAE,OAAO,CAAA;CACtB,CAcA;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI;IAC1B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;IACtD,KAAK,EAAE,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IACpD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB,CAYA;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,MAAM,OAAO,CAAC,IAAI,CAAC,CAG/C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI;IAC9B,aAAa,EAAE,OAAO,CAAA;IACtB,YAAY,EAAE,OAAO,CAAA;IACrB,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/B,CAWA;AAED;;;GAGG;AACH,YAAY,EAAE,UAAU,EAAE,CAAA;AAE1B;;;;;;;GAOG;AACH,wBAAgB,aAAa,IAAI;IAC/B,KAAK,EAAE,UAAU,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,CAKA"}
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/react/hooks.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,+BAA+B,CAAA;AAEtC;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,YAAY,CAS3C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI;IAC5B,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;IACtD,UAAU,EAAE,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAA;IAC9D,cAAc,EAAE,OAAO,CAAA;IACvB,KAAK,EAAE,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IACpD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,aAAa,EAAE,OAAO,CAAA;IACtB,YAAY,EAAE,OAAO,CAAA;CACtB,CAgBA;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,IAAI;IAC1B,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjE,cAAc,EAAE,OAAO,CAAA;IACvB,MAAM,EAAE,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;IACtD,KAAK,EAAE,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAA;IACpD,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB,CAaA;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,IAAI,CAAC,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAG3E;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,IAAI,MAAM,OAAO,CAAC,IAAI,CAAC,CAGlD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,IAAI,MAAM,OAAO,CAAC,OAAO,CAAC,CAGxD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI;IAC9B,aAAa,EAAE,OAAO,CAAA;IACtB,YAAY,EAAE,OAAO,CAAA;IACrB,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/B,CAWA;AAED;;;GAGG;AACH,YAAY,EAAE,UAAU,EAAE,CAAA;AAE1B;;;;;;;GAOG;AACH,wBAAgB,aAAa,IAAI;IAC/B,KAAK,EAAE,UAAU,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,CAKA"}
@@ -11,7 +11,6 @@ import { useStore } from 'zustand';
11
11
  import { useShallow } from 'zustand/react/shallow';
12
12
  import { WasSessionContext } from './WasSessionProvider.js';
13
13
  import { useSyncStatusStore, deriveSyncRollup } from '../storage/syncStatusStore.js';
14
- export { useAppReady } from '../session/appReadyStore.js';
15
14
  /**
16
15
  * The bound auth store from the nearest {@link WasSessionProvider}. Throws a
17
16
  * helpful error when used outside a provider.
@@ -36,6 +35,8 @@ export function useSession() {
36
35
  const store = useAuthStore();
37
36
  return useStore(store, useShallow(state => ({
38
37
  status: state.status,
38
+ onboarding: state.onboarding,
39
+ authenticating: state.authenticating,
39
40
  phase: state.phase,
40
41
  error: state.error,
41
42
  controllerDid: state.controllerDid,
@@ -45,29 +46,58 @@ export function useSession() {
45
46
  })));
46
47
  }
47
48
  /**
48
- * The login action plus the state the login page renders (status/phase/error).
49
+ * The login action plus the state the login page renders. `authenticating` is
50
+ * the in-flight flag (the `status` stays `local` during login); `status` is
51
+ * exposed so a login page can redirect once it reads `connected`. `login`
52
+ * accepts `{ adopt }` -- `'merge'` (default) migrates data created in `local`
53
+ * into the connected replica, `'leave'` sets it aside untouched.
49
54
  *
50
55
  * @returns {object}
51
56
  */
52
57
  export function useLogin() {
53
58
  const store = useAuthStore();
54
59
  const login = useStore(store, state => state.login);
55
- const { status, phase, error } = useStore(store, useShallow(state => ({
60
+ const { authenticating, status, phase, error } = useStore(store, useShallow(state => ({
61
+ authenticating: state.authenticating,
56
62
  status: state.status,
57
63
  phase: state.phase,
58
64
  error: state.error
59
65
  })));
60
- return { login, status, phase, error };
66
+ return { login, authenticating, status, phase, error };
61
67
  }
62
68
  /**
63
- * The logout action.
69
+ * The logout action; accepts `{ wipe }` to delete the connected replica rather
70
+ * than keep it on the device.
64
71
  *
65
- * @returns {() => Promise<void>}
72
+ * @returns {(options?: { wipe?: boolean }) => Promise<void>}
66
73
  */
67
74
  export function useLogout() {
68
75
  const store = useAuthStore();
69
76
  return useStore(store, state => state.logout);
70
77
  }
78
+ /**
79
+ * The clear-data action: deletes the local replica, discards the anonymous
80
+ * seed, and mints a fresh anonymous seed/DID + replica (the `local`-mode
81
+ * "Clear data" affordance).
82
+ *
83
+ * @returns {() => Promise<void>}
84
+ */
85
+ export function useClearData() {
86
+ const store = useAuthStore();
87
+ return useStore(store, state => state.clearLocalData);
88
+ }
89
+ /**
90
+ * Whether the anonymous `local` replica currently holds any documents -- the
91
+ * check a login affordance runs at decision time (e.g. on the login button
92
+ * click) to choose between opening the adoption dialog and calling `login()`
93
+ * directly. Returns the async check, not a subscription.
94
+ *
95
+ * @returns {() => Promise<boolean>}
96
+ */
97
+ export function useHasLocalData() {
98
+ const store = useAuthStore();
99
+ return useStore(store, state => state.hasLocalData);
100
+ }
71
101
  /**
72
102
  * The expired-access reconnect: the banner flags plus the reconnect action.
73
103
  *
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/react/hooks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/react/hooks.ts"],"names":[],"mappings":"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"}
@@ -7,5 +7,5 @@
7
7
  * `./mui` subpath.
8
8
  */
9
9
  export { WasSessionProvider, WasSessionContext } from './WasSessionProvider.js';
10
- export { useAuthStore, useSession, useLogin, useLogout, useReconnect, useSyncStatus, useAppReady, type SyncRollup } from './hooks.js';
10
+ export { useAuthStore, useSession, useLogin, useLogout, useClearData, useHasLocalData, useReconnect, useSyncStatus, type SyncRollup } from './hooks.js';
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC/E,OAAO,EACL,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,aAAa,EACb,WAAW,EACX,KAAK,UAAU,EAChB,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC/E,OAAO,EACL,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,aAAa,EACb,KAAK,UAAU,EAChB,MAAM,YAAY,CAAA"}
@@ -7,5 +7,5 @@
7
7
  * `./mui` subpath.
8
8
  */
9
9
  export { WasSessionProvider, WasSessionContext } from './WasSessionProvider.js';
10
- export { useAuthStore, useSession, useLogin, useLogout, useReconnect, useSyncStatus, useAppReady } from './hooks.js';
10
+ export { useAuthStore, useSession, useLogin, useLogout, useClearData, useHasLocalData, useReconnect, useSyncStatus } from './hooks.js';
11
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC/E,OAAO,EACL,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,aAAa,EACb,WAAW,EAEZ,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC/E,OAAO,EACL,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,aAAa,EAEd,MAAM,YAAY,CAAA"}
@@ -2,17 +2,29 @@
2
2
  * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
3
  */
4
4
  /**
5
- * The wallet-mode auth store (zustand): owns the session lifecycle -- hot
6
- * restore (zero popups), Login With Wallet, logout, and the expired-access
7
- * reconnect -- plus the open/hydrate/sync ordering.
5
+ * The session auth store (zustand): a four-state machine
6
+ * (`boot` | `local` | `connected` | `reconnect`) that owns the whole session
7
+ * lifecycle -- boot (hot restore or fall to an anonymous local replica), Login
8
+ * With Wallet, the non-CHAPI `connectWithGrants` path, logout, clear-data, and
9
+ * the expired-access reconnect -- plus the open/hydrate/sync ordering.
8
10
  *
9
- * On a successful login/restore it opens the encrypted {@link LocalStore} from
10
- * the session seed (a per-controller database name, so two wallet users on one
11
- * browser never collide), hydrates the entity stores, flips the shared
12
- * `useAppReady` gate, and starts WAS replication from the granted zcaps.
11
+ * `boot` attempts a zero-popup session restore. A restore hit opens the
12
+ * encrypted {@link LocalStore} under the session seed, hydrates the entity
13
+ * stores, starts WAS replication, and lands `connected`. A restore miss (or any
14
+ * error) opens the store under a persisted ANONYMOUS seed instead and lands
15
+ * `local`: a fully usable, encrypted, local-only replica with no remote. Both
16
+ * successors finish open+hydrate before leaving `boot`, so "app ready" is simply
17
+ * `status !== 'boot'`.
13
18
  *
14
- * `status` is the router gate: `ProtectedRoute` waits for the restore attempt to
15
- * settle before deciding between the app and the login page.
19
+ * Login (or `connectWithGrants`) tears the anonymous replica down and opens the
20
+ * connected replica under the wallet-derived seed. By default it ADOPTS the
21
+ * anonymous replica's data first (`adopt: 'merge'`): the decrypted payloads are
22
+ * collected before teardown, LWW-merged into the connected replica before its
23
+ * first hydrate/sync (so they reach the server as ordinary creates), and the
24
+ * anonymous seed + database are deleted once the activation lands. `adopt:
25
+ * 'leave'` sets the anonymous replica aside untouched instead (it returns after
26
+ * a logout). Logout returns to a fresh `local` (optionally wiping the connected
27
+ * replica); `clearLocalData` mints a brand-new anonymous seed and replica.
16
28
  *
17
29
  * The library cannot bind a module-level store to app config, so this is a
18
30
  * FACTORY: {@link createAuthStore} captures the app's {@link WasAppConfig} and
@@ -21,12 +33,34 @@
21
33
  */
22
34
  import { type StoreApi } from 'zustand/vanilla';
23
35
  import type { RxStorage } from 'rxdb/plugins/core';
36
+ import type { IZcap } from '@interop/data-integrity-core';
24
37
  import { type StoreRegistry, type WasAppConfig } from '../config.js';
25
38
  import { type SeedStore } from '../identity/seedStore.js';
26
39
  import { type LoginPhase } from '../auth/loginFlow.js';
27
- export type AuthStatus = 'idle' | 'restoring' | 'unauthenticated' | 'authenticating' | 'authenticated';
40
+ /**
41
+ * The four session states:
42
+ * - `boot`: attempting hot restore; both successors open + hydrate before this
43
+ * status is left.
44
+ * - `local`: an encrypted anonymous-seed replica, no remote (the pre-connection
45
+ * product state; tier-1 apps may stay here indefinitely).
46
+ * - `connected`: a wallet-derived identity, parsed grants, replication.
47
+ * - `reconnect`: connected but access expired/revoked; the replica stays usable,
48
+ * remote invocations paused until re-login.
49
+ */
50
+ export type SessionStatus = 'boot' | 'local' | 'connected' | 'reconnect';
28
51
  export interface AuthState {
29
- status: AuthStatus;
52
+ status: SessionStatus;
53
+ /**
54
+ * The app's onboarding mode. Read by `ProtectedRoute` to decide whether to
55
+ * render the app or redirect to login while in `local`; never affects the
56
+ * store's own transitions.
57
+ */
58
+ onboarding: 'local-first' | 'login-gated';
59
+ /**
60
+ * A Login With Wallet flow is in flight (the transient the login page's busy
61
+ * state keys off; distinct from the `status`, which stays `local` throughout).
62
+ */
63
+ authenticating: boolean;
30
64
  /**
31
65
  * The current login phase, for the login page's progress line.
32
66
  */
@@ -34,32 +68,87 @@ export interface AuthState {
34
68
  error: string | null;
35
69
  controllerDid: string | null;
36
70
  /**
37
- * ISO expiry of the current grant set (earliest zcap expiry).
71
+ * ISO expiry of the current grant set (earliest zcap expiry); `null` in
72
+ * `local` (no grants).
38
73
  */
39
74
  expires: string | null;
40
75
  /**
41
- * A live 401/403 was seen mid-session: show the reconnect banner.
76
+ * A live 401/403 was seen mid-session (or a proactive near-expiry): show the
77
+ * reconnect banner. Always true iff `status === 'reconnect'`.
42
78
  */
43
79
  accessExpired: boolean;
44
80
  reconnecting: boolean;
45
81
  /**
46
- * Hot restore from the persisted session; falls to `unauthenticated`.
82
+ * Attempt a zero-popup hot restore; a restore hit lands `connected`, any
83
+ * miss/error falls to `local` (a fresh anonymous replica), never a dead login
84
+ * screen. No-op once the status has left `boot`.
85
+ */
86
+ boot: () => Promise<void>;
87
+ /**
88
+ * Full Login With Wallet (first-run or returning). On success tears down the
89
+ * anonymous replica and opens the connected one. `adopt` decides what happens
90
+ * to data created in `local` before this login: `'merge'` (the default)
91
+ * LWW-merges it into the connected replica and then deletes the anonymous
92
+ * seed + database; `'leave'` sets the anonymous replica aside untouched (it
93
+ * returns after a logout). A cancel or failure leaves `local` intact either
94
+ * way.
95
+ *
96
+ * @param [options] {object}
97
+ * @param [options.adopt] {'merge' | 'leave'}
98
+ * @returns {Promise<void>}
47
99
  */
48
- restore: () => Promise<void>;
100
+ login: (options?: {
101
+ adopt?: 'merge' | 'leave';
102
+ }) => Promise<void>;
49
103
  /**
50
- * Full Login With Wallet (first-run or returning).
104
+ * Non-CHAPI connect from an explicit seed + grants (dev/test and provisioned
105
+ * grants). Tears down the current replica and opens the connected one, with
106
+ * the same `adopt` choice (and `'merge'` default) as `login`, so this path
107
+ * exercises adoption exactly as a wallet login does.
108
+ *
109
+ * @param options {object}
110
+ * @param options.seed {Uint8Array}
111
+ * @param options.grants {IZcap[]}
112
+ * @param [options.adopt] {'merge' | 'leave'}
113
+ * @returns {Promise<void>}
51
114
  */
52
- login: () => Promise<void>;
115
+ connectWithGrants: (options: {
116
+ seed: Uint8Array;
117
+ grants: IZcap[];
118
+ adopt?: 'merge' | 'leave';
119
+ }) => Promise<void>;
53
120
  /**
54
121
  * Re-run the grants flow with the existing seed (expired access).
55
122
  */
56
123
  reconnect: () => Promise<void>;
57
- logout: () => Promise<void>;
124
+ /**
125
+ * Detach the wallet and return to a fresh `local` replica. `wipe` deletes the
126
+ * connected replica's database; otherwise it is kept on the device.
127
+ *
128
+ * @param [options] {object}
129
+ * @param [options.wipe] {boolean}
130
+ * @returns {Promise<void>}
131
+ */
132
+ logout: (options?: {
133
+ wipe?: boolean;
134
+ }) => Promise<void>;
135
+ /**
136
+ * Delete the local replica, discard the anonymous seed, and mint a fresh
137
+ * anonymous seed/DID + replica. The shared reset primitive behind the
138
+ * `local`-mode "Clear data" button.
139
+ */
140
+ clearLocalData: () => Promise<void>;
141
+ /**
142
+ * Whether the anonymous `local` replica currently holds any documents -- the
143
+ * check a login screen runs to decide whether to offer the adoption choice
144
+ * before `login()`. Always false outside `local`.
145
+ */
146
+ hasLocalData: () => Promise<boolean>;
58
147
  notifyAccessExpired: () => void;
59
148
  /**
60
- * Tears down the live session (expiry watch, controller, local store) WITHOUT
61
- * wiping the persisted session record, and returns to `idle` so a fresh
62
- * `restore()` can re-open it. Called from the provider's unmount cleanup so an
149
+ * Tears down the live replica (expiry watch, controller, local store) WITHOUT
150
+ * wiping the persisted session record, and returns to `boot` so a fresh
151
+ * `boot()` can re-open it. Called from the provider's unmount cleanup so an
63
152
  * unmount (or a React StrictMode dev remount) never orphans the replication
64
153
  * loop or the expiry-watch interval.
65
154
  */
@@ -70,7 +159,7 @@ export interface AuthState {
70
159
  */
71
160
  export type WasAuthStore = StoreApi<AuthState>;
72
161
  /**
73
- * Builds the wallet-mode auth store bound to an app's config and store registry.
162
+ * Builds the session auth store bound to an app's config and store registry.
74
163
  * Call once (the React provider does) and share the returned store through
75
164
  * context; the hooks read it via `useStore`.
76
165
  *
@@ -1 +1 @@
1
- {"version":3,"file":"authStore.d.ts","sourceRoot":"","sources":["../../src/session/authStore.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAElD,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,cAAc,CAAA;AAIrB,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAO1E,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,sBAAsB,CAAA;AAwB7B,MAAM,MAAM,UAAU,GACpB,MAAM,GAAG,WAAW,GAAG,iBAAiB,GAAG,gBAAgB,GAAG,eAAe,CAAA;AAU/E,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,UAAU,CAAA;IAClB;;OAEG;IACH,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B;;OAEG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB;;OAEG;IACH,aAAa,EAAE,OAAO,CAAA;IACtB,YAAY,EAAE,OAAO,CAAA;IACrB;;OAEG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B;;OAEG;IACH,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B;;OAEG;IACH,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3B,mBAAmB,EAAE,MAAM,IAAI,CAAA;IAC/B;;;;;;OAMG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7B;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAA;AAE9C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,QAAQ,EACR,SAAS,EACT,OAAO,EACR,EAAE;IACD,MAAM,EAAE,YAAY,CAAA;IACpB,QAAQ,EAAE,aAAa,CAAA;IACvB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;CACtC,GAAG,YAAY,CA2Yf"}
1
+ {"version":3,"file":"authStore.d.ts","sourceRoot":"","sources":["../../src/session/authStore.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAA;AACzD,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,cAAc,CAAA;AAIrB,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAQ1E,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,sBAAsB,CAAA;AAwB7B;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,GAAG,WAAW,CAAA;AAqBxE,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,aAAa,CAAA;IACrB;;;;OAIG;IACH,UAAU,EAAE,aAAa,GAAG,aAAa,CAAA;IACzC;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAA;IACvB;;OAEG;IACH,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B;;;OAGG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB;;;OAGG;IACH,aAAa,EAAE,OAAO,CAAA;IACtB,YAAY,EAAE,OAAO,CAAA;IACrB;;;;OAIG;IACH,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACzB;;;;;;;;;;;;OAYG;IACH,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjE;;;;;;;;;;;OAWG;IACH,iBAAiB,EAAE,CAAC,OAAO,EAAE;QAC3B,IAAI,EAAE,UAAU,CAAA;QAChB,MAAM,EAAE,KAAK,EAAE,CAAA;QACf,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAA;KAC1B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACnB;;OAEG;IACH,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B;;;;;;;OAOG;IACH,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACvD;;;;OAIG;IACH,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACnC;;;;OAIG;IACH,YAAY,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;IACpC,mBAAmB,EAAE,MAAM,IAAI,CAAA;IAC/B;;;;;;OAMG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7B;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAA;AAQ9C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,QAAQ,EACR,SAAS,EACT,OAAO,EACR,EAAE;IACD,MAAM,EAAE,YAAY,CAAA;IACpB,QAAQ,EAAE,aAAa,CAAA;IACvB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,OAAO,CAAC,EAAE,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;CACtC,GAAG,YAAY,CAgpBf"}