-
Notifications
You must be signed in to change notification settings - Fork 268
/
getInterestingAtoms.ts
117 lines (102 loc) · 3.37 KB
/
getInterestingAtoms.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type {Atom} from 'jotai';
import type {Json} from 'shared/typeUtils';
import {latestSuccessorsMapAtom} from '../SuccessionTracker';
import {allDiffSummaries, codeReviewProvider} from '../codeReview/CodeReviewInfo';
import {readAtom} from '../jotaiUtils';
import {uncommittedSelection} from '../partialSelection';
import {selectedCommits} from '../selection';
import {
operationBeingPreviewed,
repositoryData,
latestCommitsData,
latestUncommittedChangesData,
mergeConflicts,
operationList,
queuedOperations,
} from '../serverAPIState';
import {SelfUpdate} from 'shared/immutableExt';
export type UIStateSnapshot = {[key: string]: Json};
export type AtomsState = {[key: string]: unknown};
function listInterestingAtoms(): Array<Atom<unknown>> {
return [
allDiffSummaries,
codeReviewProvider,
repositoryData,
latestCommitsData,
latestSuccessorsMapAtom,
latestUncommittedChangesData,
mergeConflicts,
operationBeingPreviewed,
operationList,
queuedOperations,
selectedCommits,
uncommittedSelection,
// This is an atomFamily. Need extra work to read it.
// unsavedFieldsBeingEdited,
];
}
/** Read all "interesting" atoms and returns a single object that contains them all. */
export function readInterestingAtoms(): AtomsState {
return Object.fromEntries(
listInterestingAtoms().map(a => [a.debugLabel ?? a.toString(), readAtom(a)]),
);
}
/** Try to serialize the `state` so they can be represented in plain JSON. */
export function serializeAtomsState(state: AtomsState): UIStateSnapshot {
const newEntries = Object.entries(state).map(([key, value]) => {
return [key, serialize(value as Serializable)];
});
return Object.fromEntries(newEntries);
}
type Serializable = Json | {toJSON: () => Serializable};
function serialize(initialArg: Serializable): Json {
let arg = initialArg;
// Unwrap SelfUpdate types.
if (arg instanceof SelfUpdate) {
arg = arg.inner;
}
// Convert known immutable types.
if (arg != null && typeof arg === 'object') {
const maybeToJSON = (arg as {toJSON?: () => Json}).toJSON;
if (maybeToJSON !== undefined) {
arg = maybeToJSON.call(arg);
}
}
if (arg === undefined) {
return null;
}
if (
typeof arg === 'number' ||
typeof arg === 'boolean' ||
typeof arg === 'string' ||
arg === null
) {
return arg;
}
if (arg instanceof Map) {
return Array.from(arg.entries()).map(([key, val]) => [serialize(key), serialize(val)]);
} else if (arg instanceof Set) {
return Array.from(arg.values()).map(serialize);
} else if (arg instanceof Error) {
return {message: arg.message ?? null, stack: arg.stack ?? null};
} else if (arg instanceof Date) {
return `Date: ${arg.valueOf()}`;
} else if (Array.isArray(arg)) {
return arg.map(a => serialize(a));
} else if (typeof arg === 'object') {
const newObj: Json = {};
for (const [propertyName, propertyValue] of Object.entries(arg)) {
newObj[propertyName] = serialize(propertyValue);
}
return newObj;
}
// Return a dummy value instead of throw so if an item in a container is "bad",
// it does not turn the whole container into an error.
return `<unserializable: ${arg}>`;
}