-
-
Notifications
You must be signed in to change notification settings - Fork 82
/
Copy pathMSTGQLObject.ts
77 lines (70 loc) · 2.01 KB
/
MSTGQLObject.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
import {
types,
getParent,
getRoot,
IAnyModelType,
resolveIdentifier,
IReferenceType
} from "mobx-state-tree"
import { observable } from "mobx"
import { StoreType } from "./MSTGQLStore"
/*
For detached objects (objects that are not part of the Roots, or one of their children, for example: query results),
we cannot use the default resolution mechanism, since they are not part of the store. So, first fetch the store and resolve from there
*/
const MSTGQL_ID_DELIM = "::"
export function getMSTGQLRefLabelAndId(labeledId: string) {
if (labeledId.includes(MSTGQL_ID_DELIM)) {
const [label, ...id] = labeledId.split(MSTGQL_ID_DELIM)
return { label, id: id.join("") }
}
return { label: null, id: labeledId }
}
export function MSTGQLRef<T extends IAnyModelType>(
targetType: T,
label: string = targetType.name
): IReferenceType<T> {
return types.reference(targetType, {
get(labeledId: string, parent: any) {
const id = getMSTGQLRefLabelAndId(labeledId).id
const node = resolveIdentifier(
targetType,
parent.store || getParent<any>(parent).store,
id
)
if (!node) {
throw new Error(
`Failed to resolve reference ${id} to ${targetType.name}`
)
}
return node
},
set(value: any) {
const typeDef = value.store.getTypeDef(value.__typename)
const id = value[typeDef.identifierAttribute ?? 'id']
return [label, MSTGQL_ID_DELIM, id].join("")
}
})
}
export const MSTGQLObject = types.model("MSTGQLObject").extend((self) => {
let store: StoreType
function getStore(): StoreType {
// https://github.com/mobxjs/mobx-state-tree/issues/1408#issuecomment-547247080
return store || (store = getRoot(self))
}
return {
actions: {
__setStore(s: StoreType) {
store = s
}
},
views: {
__getStore<T>() {
return getStore() as any as T
},
hasLoaded(key: string): boolean {
return typeof (self as any)[key] !== "undefined"
}
}
}
})