@buoy-gg/time-machine 7.0.20 → 7.0.22
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/lib/commonjs/components/TimeMachineBody.js +103 -8
- package/lib/commonjs/components/TimeMachineBody.js.map +1 -1
- package/lib/commonjs/index.js +55 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/store/routeRestore.js +188 -0
- package/lib/commonjs/store/routeRestore.js.map +1 -0
- package/lib/commonjs/store/snapshotVault.js.map +1 -1
- package/lib/commonjs/store/timeMachineStore.js +41 -3
- package/lib/commonjs/store/timeMachineStore.js.map +1 -1
- package/lib/commonjs/sync/timeMachineSyncAdapter.js +18 -4
- package/lib/commonjs/sync/timeMachineSyncAdapter.js.map +1 -1
- package/lib/module/components/TimeMachineBody.js +104 -9
- package/lib/module/components/TimeMachineBody.js.map +1 -1
- package/lib/module/index.js +11 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/store/routeRestore.js +176 -0
- package/lib/module/store/routeRestore.js.map +1 -0
- package/lib/module/store/snapshotVault.js.map +1 -1
- package/lib/module/store/timeMachineStore.js +41 -3
- package/lib/module/store/timeMachineStore.js.map +1 -1
- package/lib/module/sync/timeMachineSyncAdapter.js +18 -4
- package/lib/module/sync/timeMachineSyncAdapter.js.map +1 -1
- package/lib/typescript/components/TimeMachineBody.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/store/routeRestore.d.ts +51 -0
- package/lib/typescript/store/routeRestore.d.ts.map +1 -0
- package/lib/typescript/store/snapshotVault.d.ts +7 -0
- package/lib/typescript/store/snapshotVault.d.ts.map +1 -1
- package/lib/typescript/store/timeMachineStore.d.ts +29 -1
- package/lib/typescript/store/timeMachineStore.d.ts.map +1 -1
- package/lib/typescript/sync/timeMachineSyncAdapter.d.ts +8 -0
- package/lib/typescript/sync/timeMachineSyncAdapter.d.ts.map +1 -1
- package/package.json +12 -8
- package/src/components/TimeMachineBody.tsx +146 -10
- package/src/index.tsx +22 -0
- package/src/store/routeRestore.ts +194 -0
- package/src/store/snapshotVault.ts +7 -0
- package/src/store/timeMachineStore.ts +60 -1
- package/src/sync/timeMachineSyncAdapter.ts +27 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["getStateSnapshotProviders","subscribeToStateSnapshotProviders","superJsonDeserialize","jsonLikelyLargerThan","timeMachineStore","loadSnapshot","providerStatuses","map","p","s","status","id","label","canCapture","canRestore","detail","metadata","snapshots","busy","lastOutcome","getState","providers","timeMachineSyncAdapter","version","getSnapshot","subscribe","onChange","unsubStore","unsubProviders","actions","list","capture","params","name","sourceIds","meta","captured","snapshot","captureBaseline","wipeAll","restore","mode","excludeKeys","Error","delete","deleted","rename","renamed","setScope","scope","scoped","count","length","preview","compareTo","right","snapshotId","left","buildPreview","VALUE_BUDGET","builtAt","sources","src","items","item","oldBig","oldValue","undefined","newBig","newValue","valueOmitted","inspect","sourceId","stored","payload","data","warnings"],"sourceRoot":"../../../src","sources":["sync/timeMachineSyncAdapter.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SACEA,yBAAyB,EACzBC,iCAAiC,EACjCC,oBAAoB,QACf,oBAAoB;AAC3B,SAASC,oBAAoB,QAAQ,+BAA+B;AACpE,SACEC,gBAAgB,QAGX,2BAA2B;AAClC,SAASC,YAAY,QAAQ,wBAAwB;
|
|
1
|
+
{"version":3,"names":["getStateSnapshotProviders","subscribeToStateSnapshotProviders","superJsonDeserialize","jsonLikelyLargerThan","timeMachineStore","loadSnapshot","canNavigate","currentRoute","providerStatuses","map","p","s","status","id","label","canCapture","canRestore","detail","metadata","snapshots","busy","lastOutcome","getState","current","providers","route","available","href","timeMachineSyncAdapter","version","getSnapshot","subscribe","onChange","unsubStore","unsubProviders","actions","list","capture","params","name","sourceIds","meta","captured","snapshot","captureBaseline","wipeAll","restore","mode","excludeKeys","restoreRoute","Error","delete","deleted","rename","renamed","setScope","scope","scoped","count","length","preview","compareTo","right","snapshotId","left","buildPreview","VALUE_BUDGET","builtAt","sources","src","items","item","oldBig","oldValue","undefined","newBig","newValue","valueOmitted","inspect","sourceId","stored","payload","data","warnings"],"sourceRoot":"../../../src","sources":["sync/timeMachineSyncAdapter.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeMachineBody.d.ts","sourceRoot":"","sources":["../../../src/components/TimeMachineBody.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"TimeMachineBody.d.ts","sourceRoot":"","sources":["../../../src/components/TimeMachineBody.tsx"],"names":[],"mappings":"AAqOA,wBAAgB,eAAe,gCAwa9B"}
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
export { timeMachineToolPreset, createTimeMachineTool } from "./preset";
|
|
13
13
|
export { TimeMachineModal, TimeMachineToolView, type TimeMachineModalProps, } from "./components/TimeMachineModal";
|
|
14
14
|
export { timeMachineSyncAdapter } from "./sync/timeMachineSyncAdapter";
|
|
15
|
-
export { timeMachineStore, RESTORE_ORDER, type RestoreMode, type RestoreOutcome, type TimeMachineState, type RemoteProviderStatus, } from "./store/timeMachineStore";
|
|
15
|
+
export { timeMachineStore, RESTORE_ORDER, type RestoreMode, type RestoreOptions, type RestoreOutcome, type TimeMachineState, type RemoteProviderStatus, } from "./store/timeMachineStore";
|
|
16
|
+
export { armPendingRouteRestore, captureCurrentRoute, navigateToRoute, canNavigate as canRestoreRoute, type SnapshotRoute, type RouteRestoreResult, type RouteRestoreStatus, } from "./store/routeRestore";
|
|
16
17
|
export { setRemoteTimeMachineHandler, replaceTimeMachineFromSnapshot, } from "./store/timeMachineStore";
|
|
17
18
|
export type { SnapshotMeta, SnapshotSourceMeta, StoredSnapshot, } from "./store/snapshotVault";
|
|
18
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGxE,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,qBAAqB,GAC3B,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAGvE,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,GAC1B,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,eAAe,EACf,WAAW,IAAI,eAAe,EAC9B,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,GACxB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,GAC/B,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,cAAc,GACf,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The route a snapshot was captured on. Only the URL is stored — imperative
|
|
3
|
+
* params passed as objects (`navigate(path, { user })`) are not part of a
|
|
4
|
+
* route and are not restored.
|
|
5
|
+
*/
|
|
6
|
+
export interface SnapshotRoute {
|
|
7
|
+
/** Pathname with dynamic segments resolved, e.g. `/pokemon/25`. */
|
|
8
|
+
pathname: string;
|
|
9
|
+
/** What we navigate to — pathname plus search params. */
|
|
10
|
+
href: string;
|
|
11
|
+
}
|
|
12
|
+
/** How a restore's route leg ended, reported back in the RestoreOutcome. */
|
|
13
|
+
export type RouteRestoreStatus = "navigated" | "deferred" | "failed" | "unavailable";
|
|
14
|
+
export interface RouteRestoreResult {
|
|
15
|
+
pathname: string;
|
|
16
|
+
href: string;
|
|
17
|
+
status: RouteRestoreStatus;
|
|
18
|
+
/** Present when status is "failed" / "unavailable". */
|
|
19
|
+
error?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A pending route older than this belongs to a reload that never happened
|
|
23
|
+
* (the app was killed, the user moved on). Boot-time navigation into a screen
|
|
24
|
+
* someone left minutes ago is worse than doing nothing.
|
|
25
|
+
*/
|
|
26
|
+
export declare const PENDING_ROUTE_TTL_MS = 60000;
|
|
27
|
+
/** The route to stamp on a snapshot being captured, or null when unavailable. */
|
|
28
|
+
export declare function captureCurrentRoute(): SnapshotRoute | null;
|
|
29
|
+
/** The live route, for "you're already here" checks in the UI. */
|
|
30
|
+
export declare function currentRoute(): SnapshotRoute | null;
|
|
31
|
+
/** True when imperative navigation is possible on this device. */
|
|
32
|
+
export declare function canNavigate(): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Navigate to a captured route now. Uses `navigate` (not `push`) so restoring
|
|
35
|
+
* the same route twice doesn't stack duplicate screens.
|
|
36
|
+
*/
|
|
37
|
+
export declare function navigateToRoute(route: SnapshotRoute): RouteRestoreResult;
|
|
38
|
+
export declare function savePendingRoute(route: SnapshotRoute, snapshotName?: string): Promise<void>;
|
|
39
|
+
export declare function clearPendingRoute(): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Boot-time consumer of a pending route: called once when the package loads
|
|
42
|
+
* (core requires it while mounting the floating menu), it navigates to the
|
|
43
|
+
* route a reload-mode restore asked for and clears the slot.
|
|
44
|
+
*
|
|
45
|
+
* Idempotent and self-limiting — the slot is cleared before navigating, so a
|
|
46
|
+
* route that crashes the app on arrival can't put it in a boot loop.
|
|
47
|
+
*/
|
|
48
|
+
export declare function armPendingRouteRestore(): void;
|
|
49
|
+
/** @internal test seam — re-arms the boot-time consumer. */
|
|
50
|
+
export declare function resetPendingRouteArm(): void;
|
|
51
|
+
//# sourceMappingURL=routeRestore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routeRestore.d.ts","sourceRoot":"","sources":["../../../src/store/routeRestore.ts"],"names":[],"mappings":"AAuBA;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,4EAA4E;AAC5E,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,UAAU,GACV,QAAQ,GACR,aAAa,CAAC;AAElB,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,kBAAkB,CAAC;IAC3B,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAUD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAiB3C,iFAAiF;AACjF,wBAAgB,mBAAmB,IAAI,aAAa,GAAG,IAAI,CAG1D;AAED,kEAAkE;AAClE,wBAAgB,YAAY,IAAI,aAAa,GAAG,IAAI,CAEnD;AAED,kEAAkE;AAClE,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,GAAG,kBAAkB,CAgBxE;AAID,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,aAAa,EACpB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMvD;AAwBD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAkB7C;AAED,4DAA4D;AAC5D,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* snapshots — a snapshot must never contain snapshots.
|
|
16
16
|
*/
|
|
17
17
|
import { type SuperJSONResult } from "@buoy-gg/shared-ui";
|
|
18
|
+
import type { SnapshotRoute } from "./routeRestore";
|
|
18
19
|
export interface SnapshotSourceMeta {
|
|
19
20
|
warnings: string[];
|
|
20
21
|
}
|
|
@@ -35,6 +36,12 @@ export interface SnapshotMeta {
|
|
|
35
36
|
* means just my cart". Absent = full restore.
|
|
36
37
|
*/
|
|
37
38
|
scope?: string[];
|
|
39
|
+
/**
|
|
40
|
+
* The route the app was on when this snapshot was captured. Absent when the
|
|
41
|
+
* app has no expo-router (nothing to return to). A restore can navigate back
|
|
42
|
+
* to it — see routeRestore.ts.
|
|
43
|
+
*/
|
|
44
|
+
route?: SnapshotRoute;
|
|
38
45
|
/** Source ids captured, with their capture warnings. */
|
|
39
46
|
sources: Record<string, SnapshotSourceMeta>;
|
|
40
47
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshotVault.d.ts","sourceRoot":"","sources":["../../../src/store/snapshotVault.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"snapshotVault.d.ts","sourceRoot":"","sources":["../../../src/store/snapshotVault.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAKpD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;;;;OAIG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,YAAY,CAAC;IACnB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CACvC;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CASzD;AAMD,2EAA2E;AAC3E,wBAAsB,YAAY,CAChC,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,YAAY,EAAE,GACpB,OAAO,CAAC,YAAY,EAAE,CAAC,CAczB;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAO7E;AAED,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,YAAY,EAAE,GACpB,OAAO,CAAC,YAAY,EAAE,CAAC,CAKzB;AAED,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EACtB,KAAK,EAAE,YAAY,EAAE,GACpB,OAAO,CAAC,YAAY,EAAE,CAAC,CAgBzB;AAED,wBAAsB,cAAc,CAClC,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,YAAY,EAAE,GACpB,OAAO,CAAC,YAAY,EAAE,CAAC,CASzB"}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { type StateSnapshotRestoreResult, type StateSnapshotPreviewItem } from "@buoy-gg/shared-ui";
|
|
18
18
|
import { type SnapshotMeta } from "./snapshotVault";
|
|
19
|
+
import { type RouteRestoreResult } from "./routeRestore";
|
|
19
20
|
export declare const RESTORE_ORDER: string[];
|
|
20
21
|
export type RestoreMode = "live" | "reload";
|
|
21
22
|
export interface RestoreOutcome {
|
|
@@ -26,6 +27,20 @@ export interface RestoreOutcome {
|
|
|
26
27
|
/** True when a JS reload was scheduled as part of this restore. */
|
|
27
28
|
willReload: boolean;
|
|
28
29
|
results: Record<string, StateSnapshotRestoreResult>;
|
|
30
|
+
/**
|
|
31
|
+
* Present when the caller asked to also return to the snapshot's route.
|
|
32
|
+
* "deferred" means the navigation is queued for the post-reload boot.
|
|
33
|
+
*/
|
|
34
|
+
route?: RouteRestoreResult;
|
|
35
|
+
}
|
|
36
|
+
/** Extra knobs a restore accepts beyond mode + exclusions. */
|
|
37
|
+
export interface RestoreOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Also navigate back to the route the snapshot was captured on. Ignored for
|
|
40
|
+
* snapshots with no captured route (and for baselines, which wipe to the
|
|
41
|
+
* app's own start route).
|
|
42
|
+
*/
|
|
43
|
+
restoreRoute?: boolean;
|
|
29
44
|
}
|
|
30
45
|
/** Provider capability row as mirrored to a remote dashboard. */
|
|
31
46
|
export interface RemoteProviderStatus {
|
|
@@ -66,6 +81,17 @@ export interface TimeMachineState {
|
|
|
66
81
|
* registry, and every operation forwards over the socket.
|
|
67
82
|
*/
|
|
68
83
|
remoteProviders: RemoteProviderStatus[] | null;
|
|
84
|
+
/**
|
|
85
|
+
* Route capture/restore availability, mirrored from the device's payload
|
|
86
|
+
* (Buoy Desktop). Null on-device, where the live router is probed directly.
|
|
87
|
+
*/
|
|
88
|
+
remoteRoute: RouteToolStatus | null;
|
|
89
|
+
}
|
|
90
|
+
/** Whether this device can capture and return to routes, and where it is now. */
|
|
91
|
+
export interface RouteToolStatus {
|
|
92
|
+
available: boolean;
|
|
93
|
+
/** The route the app is on right now, when one can be read. */
|
|
94
|
+
current?: string;
|
|
69
95
|
}
|
|
70
96
|
type RemoteHandler = (action: string, params?: Record<string, unknown>) => Promise<unknown>;
|
|
71
97
|
declare class TimeMachineStore {
|
|
@@ -85,6 +111,7 @@ declare class TimeMachineStore {
|
|
|
85
111
|
busy?: TimeMachineState["busy"];
|
|
86
112
|
lastOutcome?: RestoreOutcome | null;
|
|
87
113
|
providers?: RemoteProviderStatus[];
|
|
114
|
+
route?: RouteToolStatus;
|
|
88
115
|
}): void;
|
|
89
116
|
/** Capture all capturable sources (or a subset) into a named snapshot. */
|
|
90
117
|
capture(name: string, sourceIds?: string[]): Promise<SnapshotMeta>;
|
|
@@ -99,7 +126,7 @@ declare class TimeMachineStore {
|
|
|
99
126
|
* itemKey being what previewItems emitted) — split per source before each
|
|
100
127
|
* provider sees only its own keys.
|
|
101
128
|
*/
|
|
102
|
-
restore(id: string, mode: RestoreMode, excludeKeys?: readonly string[]): Promise<RestoreOutcome>;
|
|
129
|
+
restore(id: string, mode: RestoreMode, excludeKeys?: readonly string[], options?: RestoreOptions): Promise<RestoreOutcome>;
|
|
103
130
|
private restoreSource;
|
|
104
131
|
private scheduleReload;
|
|
105
132
|
delete(id: string): Promise<void>;
|
|
@@ -139,6 +166,7 @@ export declare function replaceTimeMachineFromSnapshot(payload: {
|
|
|
139
166
|
busy?: TimeMachineState["busy"];
|
|
140
167
|
lastOutcome?: RestoreOutcome | null;
|
|
141
168
|
providers?: RemoteProviderStatus[];
|
|
169
|
+
route?: RouteToolStatus;
|
|
142
170
|
}): void;
|
|
143
171
|
export {};
|
|
144
172
|
//# sourceMappingURL=timeMachineStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeMachineStore.d.ts","sourceRoot":"","sources":["../../../src/store/timeMachineStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAML,KAAK,0BAA0B,EAE/B,KAAK,wBAAwB,EAE9B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAOL,KAAK,YAAY,EAElB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"timeMachineStore.d.ts","sourceRoot":"","sources":["../../../src/store/timeMachineStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,10 @@ export declare const timeMachineSyncAdapter: {
|
|
|
12
12
|
canRestore: boolean;
|
|
13
13
|
detail: string | undefined;
|
|
14
14
|
}[];
|
|
15
|
+
route: {
|
|
16
|
+
current?: string | undefined;
|
|
17
|
+
available: boolean;
|
|
18
|
+
};
|
|
15
19
|
};
|
|
16
20
|
subscribe: (onChange: () => void) => () => void;
|
|
17
21
|
actions: {
|
|
@@ -26,6 +30,10 @@ export declare const timeMachineSyncAdapter: {
|
|
|
26
30
|
canRestore: boolean;
|
|
27
31
|
detail: string | undefined;
|
|
28
32
|
}[];
|
|
33
|
+
route: {
|
|
34
|
+
current?: string | undefined;
|
|
35
|
+
available: boolean;
|
|
36
|
+
};
|
|
29
37
|
};
|
|
30
38
|
capture: (params: unknown) => Promise<{
|
|
31
39
|
captured: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeMachineSyncAdapter.d.ts","sourceRoot":"","sources":["../../../src/sync/timeMachineSyncAdapter.ts"],"names":[],"mappings":"AAmBA,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"timeMachineSyncAdapter.d.ts","sourceRoot":"","sources":["../../../src/sync/timeMachineSyncAdapter.ts"],"names":[],"mappings":"AAmBA,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,2BAA2B,CAAC;AA0DnC,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;0BAIX,MAAM,IAAI;;;;;;;;;;;;;;;;;;0BAWN,OAAO;;;;;;;;QAW/B,uEAAuE;;QAGvE;;kCAE0B;0BACF,OAAO;yBAaR,OAAO;;;;yBAOP,OAAO;;;;;QAO9B,2EAA2E;2BAClD,OAAO;;;;;QAQhC;;;;WAIG;0BACqB,OAAO;;;;;;;;;;;;;;;;;;;;;;QAoC/B,2EAA2E;0BACnD,OAAO;;;;;;;CAmBlC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/time-machine",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.22",
|
|
4
4
|
"description": "Time Machine - snapshot & restore app state (storage, redux, zustand, jotai, react-query) for React Native DevTools",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
@@ -11,23 +11,27 @@
|
|
|
11
11
|
"src",
|
|
12
12
|
"lib"
|
|
13
13
|
],
|
|
14
|
-
"sideEffects":
|
|
14
|
+
"sideEffects": [
|
|
15
|
+
"./src/index.tsx",
|
|
16
|
+
"./lib/commonjs/index.js",
|
|
17
|
+
"./lib/module/index.js"
|
|
18
|
+
],
|
|
15
19
|
"dependencies": {
|
|
16
|
-
"@buoy-gg/floating-tools-core": "^7.0.
|
|
17
|
-
"@buoy-gg/shared-ui": "^7.0.
|
|
20
|
+
"@buoy-gg/floating-tools-core": "^7.0.22",
|
|
21
|
+
"@buoy-gg/shared-ui": "^7.0.22"
|
|
18
22
|
},
|
|
19
23
|
"peerDependencies": {
|
|
20
|
-
"@buoy-gg/license": "7.0.
|
|
24
|
+
"@buoy-gg/license": "7.0.22",
|
|
21
25
|
"react": "*",
|
|
22
26
|
"react-native": "*",
|
|
23
|
-
"@buoy-gg/core": "^7.0.
|
|
27
|
+
"@buoy-gg/core": "^7.0.22"
|
|
24
28
|
},
|
|
25
29
|
"devDependencies": {
|
|
26
30
|
"@types/react": "^19.1.0",
|
|
27
31
|
"@types/react-native": "^0.73.0",
|
|
28
32
|
"typescript": "~5.8.3",
|
|
29
|
-
"@buoy-gg/license": "^7.0.
|
|
30
|
-
"@buoy-gg/core": "^7.0.
|
|
33
|
+
"@buoy-gg/license": "^7.0.22",
|
|
34
|
+
"@buoy-gg/core": "^7.0.22"
|
|
31
35
|
},
|
|
32
36
|
"react-native-builder-bob": {
|
|
33
37
|
"source": "src",
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
JotaiIcon,
|
|
30
30
|
QueryIcon,
|
|
31
31
|
ReduxIcon,
|
|
32
|
+
RoutesIcon,
|
|
32
33
|
StorageIcon,
|
|
33
34
|
TimeMachineIcon,
|
|
34
35
|
ZustandIcon,
|
|
@@ -42,6 +43,7 @@ import { useIsPro } from "@buoy-gg/license";
|
|
|
42
43
|
import { useSnapshotProviders, useTimeMachineState } from "../hooks/useTimeMachine";
|
|
43
44
|
import { timeMachineStore } from "../store/timeMachineStore";
|
|
44
45
|
import type { PreviewSideRef, RestoreOutcome } from "../store/timeMachineStore";
|
|
46
|
+
import { canNavigate, currentRoute } from "../store/routeRestore";
|
|
45
47
|
import type { SnapshotMeta } from "../store/snapshotVault";
|
|
46
48
|
import { RestorePreviewScreen } from "./preview/RestorePreviewScreen";
|
|
47
49
|
import { ItemDetailScreen } from "./preview/ItemDetailScreen";
|
|
@@ -57,8 +59,12 @@ const SOURCE_ICONS: Record<
|
|
|
57
59
|
zustand: ZustandIcon,
|
|
58
60
|
jotai: JotaiIcon,
|
|
59
61
|
query: QueryIcon,
|
|
62
|
+
route: RoutesIcon,
|
|
60
63
|
};
|
|
61
64
|
|
|
65
|
+
/** Id of the route tile — a device capability, not a snapshot provider. */
|
|
66
|
+
const ROUTE_SOURCE_ID = "route";
|
|
67
|
+
|
|
62
68
|
function timeAgo(ts: number): string {
|
|
63
69
|
const s = Math.max(0, Math.round((Date.now() - ts) / 1000));
|
|
64
70
|
if (s < 60) return `${s}s ago`;
|
|
@@ -100,6 +106,60 @@ function confirmDestructive(
|
|
|
100
106
|
]);
|
|
101
107
|
}
|
|
102
108
|
|
|
109
|
+
/**
|
|
110
|
+
* "Also go back to the screen this was captured on?"
|
|
111
|
+
*
|
|
112
|
+
* Asked BEFORE the restore runs, because a reload-mode restore has to park the
|
|
113
|
+
* route in storage before the JS realm dies — there is no "after" to ask in.
|
|
114
|
+
* `onChoose(withRoute)` runs the restore; dismissing cancels it entirely.
|
|
115
|
+
*
|
|
116
|
+
* RN-web's Alert renders no buttons, so the web (Buoy Desktop) path uses the
|
|
117
|
+
* browser dialog: OK = state + route, Cancel = state only.
|
|
118
|
+
*/
|
|
119
|
+
function confirmRestoreRoute(
|
|
120
|
+
snapshotName: string,
|
|
121
|
+
href: string,
|
|
122
|
+
onChoose: (withRoute: boolean) => void
|
|
123
|
+
) {
|
|
124
|
+
const message = `“${snapshotName}” was captured on ${href}. Go back to that screen too, or restore state only?`;
|
|
125
|
+
if (Platform.OS === "web") {
|
|
126
|
+
const confirmFn = (globalThis as { confirm?: (msg: string) => boolean })
|
|
127
|
+
.confirm;
|
|
128
|
+
onChoose(
|
|
129
|
+
confirmFn
|
|
130
|
+
? confirmFn(`Also return to ${href}?\n\n${message}`)
|
|
131
|
+
: false
|
|
132
|
+
);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
Alert.alert("Restore route too?", message, [
|
|
136
|
+
{ text: "Cancel", style: "cancel" },
|
|
137
|
+
{ text: "State only", onPress: () => onChoose(false) },
|
|
138
|
+
{ text: `Go to ${href}`, onPress: () => onChoose(true) },
|
|
139
|
+
]);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Route leg of a restore: prompt when the snapshot has a captured route we
|
|
144
|
+
* aren't already sitting on, otherwise restore straight away. On Buoy Desktop
|
|
145
|
+
* the device's live route is unknown (no local router), so we always ask.
|
|
146
|
+
*/
|
|
147
|
+
function restoreWithRoutePrompt(
|
|
148
|
+
meta: SnapshotMeta,
|
|
149
|
+
run: (restoreRoute: boolean) => void
|
|
150
|
+
) {
|
|
151
|
+
const route = meta.route;
|
|
152
|
+
if (!route) {
|
|
153
|
+
run(false);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (currentRoute()?.href === route.href) {
|
|
157
|
+
run(false); // already on that screen — nothing to ask
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
confirmRestoreRoute(meta.name, route.href, run);
|
|
161
|
+
}
|
|
162
|
+
|
|
103
163
|
function OutcomePanel({ outcome }: { outcome: RestoreOutcome }) {
|
|
104
164
|
const entries = Object.entries(outcome.results);
|
|
105
165
|
return (
|
|
@@ -119,6 +179,22 @@ function OutcomePanel({ outcome }: { outcome: RestoreOutcome }) {
|
|
|
119
179
|
{entries.length === 0 && (
|
|
120
180
|
<Text style={styles.outcomeLine}>no sources restored</Text>
|
|
121
181
|
)}
|
|
182
|
+
{outcome.route && (
|
|
183
|
+
<Text
|
|
184
|
+
style={[
|
|
185
|
+
styles.outcomeLine,
|
|
186
|
+
(outcome.route.status === "failed" ||
|
|
187
|
+
outcome.route.status === "unavailable") &&
|
|
188
|
+
styles.outcomeLineBad,
|
|
189
|
+
]}
|
|
190
|
+
>
|
|
191
|
+
{outcome.route.status === "navigated"
|
|
192
|
+
? `✓ route — ${outcome.route.href}`
|
|
193
|
+
: outcome.route.status === "deferred"
|
|
194
|
+
? `↻ route — ${outcome.route.href} after reload`
|
|
195
|
+
: `✕ route — ${outcome.route.error ?? outcome.route.status}`}
|
|
196
|
+
</Text>
|
|
197
|
+
)}
|
|
122
198
|
{entries.map(([sourceId, r]) => (
|
|
123
199
|
<View key={sourceId} style={styles.outcomeSource}>
|
|
124
200
|
<Text style={[styles.outcomeLine, !r.ok && styles.outcomeLineBad]}>
|
|
@@ -152,8 +228,15 @@ type Screen =
|
|
|
152
228
|
};
|
|
153
229
|
|
|
154
230
|
export function TimeMachineBody() {
|
|
155
|
-
const {
|
|
156
|
-
|
|
231
|
+
const {
|
|
232
|
+
snapshots,
|
|
233
|
+
hasLoaded,
|
|
234
|
+
busy,
|
|
235
|
+
lastOutcome,
|
|
236
|
+
preview,
|
|
237
|
+
remoteProviders,
|
|
238
|
+
remoteRoute,
|
|
239
|
+
} = useTimeMachineState();
|
|
157
240
|
const localProviders = useSnapshotProviders();
|
|
158
241
|
const isPro = useIsPro();
|
|
159
242
|
const host = useToolHost();
|
|
@@ -173,6 +256,27 @@ export function TimeMachineBody() {
|
|
|
173
256
|
remoteProviders ??
|
|
174
257
|
localProviders.map((p) => ({ id: p.id, label: p.label, ...p.status() }));
|
|
175
258
|
|
|
259
|
+
// Route sits in the same strip as the state sources so its availability is
|
|
260
|
+
// visible before you ever open a restore point — but it's a device
|
|
261
|
+
// capability, not a registered provider, so it's derived separately (from
|
|
262
|
+
// the live router here, from the device's payload on Buoy Desktop).
|
|
263
|
+
const routeAvailable = remoteProviders
|
|
264
|
+
? remoteRoute?.available === true
|
|
265
|
+
: canNavigate();
|
|
266
|
+
const routeSource = {
|
|
267
|
+
id: ROUTE_SOURCE_ID,
|
|
268
|
+
label: "Route",
|
|
269
|
+
canCapture: routeAvailable,
|
|
270
|
+
canRestore: routeAvailable,
|
|
271
|
+
// No live route in the caption: this screen only re-renders on store
|
|
272
|
+
// changes, so a pathname printed here goes stale the moment you navigate
|
|
273
|
+
// with the tool still open. Each restore point shows the route it holds.
|
|
274
|
+
detail: routeAvailable
|
|
275
|
+
? "recorded with every snapshot — restore can take you back"
|
|
276
|
+
: "no Expo Router detected — snapshots record no route",
|
|
277
|
+
};
|
|
278
|
+
const sourceTiles = [...providers, routeSource];
|
|
279
|
+
|
|
176
280
|
const atFreeLimit = !isPro && snapshots.length >= FREE_SNAPSHOT_LIMIT;
|
|
177
281
|
const captureDisabled = busy !== null || atFreeLimit;
|
|
178
282
|
|
|
@@ -197,7 +301,11 @@ export function TimeMachineBody() {
|
|
|
197
301
|
);
|
|
198
302
|
return;
|
|
199
303
|
}
|
|
200
|
-
|
|
304
|
+
restoreWithRoutePrompt(meta, (restoreRoute) => {
|
|
305
|
+
void timeMachineStore.restore(meta.id, mode, excludeKeys, {
|
|
306
|
+
restoreRoute,
|
|
307
|
+
});
|
|
308
|
+
});
|
|
201
309
|
};
|
|
202
310
|
|
|
203
311
|
const remove = (meta: SnapshotMeta) => {
|
|
@@ -336,9 +444,11 @@ export function TimeMachineBody() {
|
|
|
336
444
|
}
|
|
337
445
|
// Land back on the list, where the outcome panel reports the
|
|
338
446
|
// results — the preview's diff is stale the moment restore runs.
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
447
|
+
restoreWithRoutePrompt(rightMeta, (restoreRoute) => {
|
|
448
|
+
void timeMachineStore
|
|
449
|
+
.restore(rightMeta.id, mode, excludeKeys, { restoreRoute })
|
|
450
|
+
.then(() => closePreview());
|
|
451
|
+
});
|
|
342
452
|
}}
|
|
343
453
|
onPickSide={setPicker}
|
|
344
454
|
onRefresh={() =>
|
|
@@ -360,7 +470,7 @@ export function TimeMachineBody() {
|
|
|
360
470
|
}
|
|
361
471
|
|
|
362
472
|
// ── List screen ──
|
|
363
|
-
const unavailable =
|
|
473
|
+
const unavailable = sourceTiles.filter(
|
|
364
474
|
(p) => p.detail && (!p.canCapture || !p.canRestore)
|
|
365
475
|
);
|
|
366
476
|
|
|
@@ -406,7 +516,7 @@ export function TimeMachineBody() {
|
|
|
406
516
|
<View style={styles.sectionRow}>
|
|
407
517
|
<Text style={styles.sectionTitle}>Sources</Text>
|
|
408
518
|
<View style={styles.sourceTiles}>
|
|
409
|
-
{
|
|
519
|
+
{sourceTiles.map((p) => {
|
|
410
520
|
const IconComp = SOURCE_ICONS[p.id] ?? TimeMachineIcon;
|
|
411
521
|
const dotColor = !p.canCapture
|
|
412
522
|
? buoyColors.textMuted
|
|
@@ -414,7 +524,18 @@ export function TimeMachineBody() {
|
|
|
414
524
|
? buoyColors.success
|
|
415
525
|
: buoyColors.warning;
|
|
416
526
|
return (
|
|
417
|
-
<View
|
|
527
|
+
<View
|
|
528
|
+
key={p.id}
|
|
529
|
+
style={styles.sourceTile}
|
|
530
|
+
testID={`time-machine-source-${p.id}`}
|
|
531
|
+
accessibilityLabel={`${p.label}: ${
|
|
532
|
+
p.canCapture
|
|
533
|
+
? p.canRestore
|
|
534
|
+
? "capture and restore"
|
|
535
|
+
: "capture only"
|
|
536
|
+
: "unavailable"
|
|
537
|
+
}`}
|
|
538
|
+
>
|
|
418
539
|
<IconComp size={16} />
|
|
419
540
|
<View
|
|
420
541
|
style={[styles.sourceTileDot, { backgroundColor: dotColor }]}
|
|
@@ -422,7 +543,7 @@ export function TimeMachineBody() {
|
|
|
422
543
|
</View>
|
|
423
544
|
);
|
|
424
545
|
})}
|
|
425
|
-
{providers.length === 0 && (
|
|
546
|
+
{providers.length === 0 && !routeAvailable && (
|
|
426
547
|
<Text style={styles.emptyText}>none registered</Text>
|
|
427
548
|
)}
|
|
428
549
|
</View>
|
|
@@ -432,6 +553,12 @@ export function TimeMachineBody() {
|
|
|
432
553
|
{p.label}: {p.detail}
|
|
433
554
|
</Text>
|
|
434
555
|
))}
|
|
556
|
+
{/* Route is opt-in per restore, so say so where the tiles are read. */}
|
|
557
|
+
{routeAvailable && (
|
|
558
|
+
<Text style={styles.providerDetail} numberOfLines={1}>
|
|
559
|
+
{routeSource.label}: {routeSource.detail}
|
|
560
|
+
</Text>
|
|
561
|
+
)}
|
|
435
562
|
|
|
436
563
|
{/* Restore points */}
|
|
437
564
|
<Text style={[styles.sectionTitle, styles.sectionSpacing]}>
|
|
@@ -472,6 +599,11 @@ export function TimeMachineBody() {
|
|
|
472
599
|
: ""}
|
|
473
600
|
{warnings > 0 ? ` · ⚠ ${warnings}` : ""}
|
|
474
601
|
</Text>
|
|
602
|
+
{!meta.baseline && meta.route && (
|
|
603
|
+
<Text style={styles.snapshotRoute} numberOfLines={1}>
|
|
604
|
+
⌖ {meta.route.href}
|
|
605
|
+
</Text>
|
|
606
|
+
)}
|
|
475
607
|
</View>
|
|
476
608
|
{!meta.baseline ? (
|
|
477
609
|
<TouchableOpacity
|
|
@@ -656,6 +788,10 @@ const styles = StyleSheet.create({
|
|
|
656
788
|
fontSize: 10,
|
|
657
789
|
fontVariant: ["tabular-nums"],
|
|
658
790
|
},
|
|
791
|
+
snapshotRoute: {
|
|
792
|
+
color: buoyColors.textSecondary,
|
|
793
|
+
fontSize: 10,
|
|
794
|
+
},
|
|
659
795
|
rowAction: {
|
|
660
796
|
padding: 4,
|
|
661
797
|
justifyContent: "center",
|
package/src/index.tsx
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* PUBLIC API - Only these exports are supported for external use.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { armPendingRouteRestore as armPendingRouteRestoreOnLoad } from "./store/routeRestore";
|
|
14
|
+
|
|
13
15
|
// Tool preset for FloatingDevTools
|
|
14
16
|
export { timeMachineToolPreset, createTimeMachineTool } from "./preset";
|
|
15
17
|
|
|
@@ -28,11 +30,23 @@ export {
|
|
|
28
30
|
timeMachineStore,
|
|
29
31
|
RESTORE_ORDER,
|
|
30
32
|
type RestoreMode,
|
|
33
|
+
type RestoreOptions,
|
|
31
34
|
type RestoreOutcome,
|
|
32
35
|
type TimeMachineState,
|
|
33
36
|
type RemoteProviderStatus,
|
|
34
37
|
} from "./store/timeMachineStore";
|
|
35
38
|
|
|
39
|
+
// Route capture / restore ("also take me back to the screen I was on")
|
|
40
|
+
export {
|
|
41
|
+
armPendingRouteRestore,
|
|
42
|
+
captureCurrentRoute,
|
|
43
|
+
navigateToRoute,
|
|
44
|
+
canNavigate as canRestoreRoute,
|
|
45
|
+
type SnapshotRoute,
|
|
46
|
+
type RouteRestoreResult,
|
|
47
|
+
type RouteRestoreStatus,
|
|
48
|
+
} from "./store/routeRestore";
|
|
49
|
+
|
|
36
50
|
// Buoy Desktop remote-mirror seam
|
|
37
51
|
export {
|
|
38
52
|
setRemoteTimeMachineHandler,
|
|
@@ -43,3 +57,11 @@ export type {
|
|
|
43
57
|
SnapshotSourceMeta,
|
|
44
58
|
StoredSnapshot,
|
|
45
59
|
} from "./store/snapshotVault";
|
|
60
|
+
|
|
61
|
+
// A reload-mode restore that also restores the route can't navigate itself —
|
|
62
|
+
// the JS realm dies with the reload. It parks the route in storage; this picks
|
|
63
|
+
// it up on the next boot. Core requires this module while mounting the
|
|
64
|
+
// floating menu, which is the earliest point we're guaranteed to run.
|
|
65
|
+
// Idempotent: repeated imports (or a host calling it explicitly) arm once.
|
|
66
|
+
armPendingRouteRestoreOnLoad();
|
|
67
|
+
|