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
|
import { observable, action } from "mobx";
import { serializable, primitive, map, alias, list } from "serializr";
import { autoObject, SerializationHelper, Deserializable } from "../client/util/SerializationHelper";
import { Utils } from "../Utils";
import { DocServer } from "../client/DocServer";
import { setter, getter, getField } from "./util";
import { Cast, FieldCtor } from "./Types";
export const HandleUpdate = Symbol("HandleUpdate");
export const Id = Symbol("Id");
export abstract class RefField {
@serializable(alias("id", primitive()))
private __id: string;
readonly [Id]: string;
constructor(id?: string) {
this.__id = id || Utils.GenerateGuid();
this[Id] = this.__id;
}
protected [HandleUpdate]?(diff: any): void;
}
export const Update = Symbol("Update");
export const OnUpdate = Symbol("OnUpdate");
export const Parent = Symbol("Parent");
export class ObjectField {
protected [OnUpdate]?: (diff?: any) => void;
private [Parent]?: Doc;
}
export type Field = number | string | boolean | ObjectField | RefField;
export type Opt<T> = T | undefined;
export type FieldWaiting = null;
export const FieldWaiting: FieldWaiting = null;
export const Self = Symbol("Self");
@Deserializable("doc").withFields(["id"])
export class Doc extends RefField {
constructor(id?: string, forceSave?: boolean) {
super(id);
const doc = new Proxy<this>(this, {
set: setter,
get: getter,
deleteProperty: () => { throw new Error("Currently properties can't be deleted from documents, assign to undefined instead"); },
defineProperty: () => { throw new Error("Currently properties can't be defined on documents using Object.defineProperty"); },
});
if (!id || forceSave) {
DocServer.CreateField(SerializationHelper.Serialize(doc));
}
return doc;
}
[key: string]: Field | null | undefined;
@serializable(alias("fields", map(autoObject())))
@observable
private __fields: { [key: string]: Field | null | undefined } = {};
private [Update] = (diff: any) => {
DocServer.UpdateField(this[Id], diff);
}
private [Self] = this;
}
export namespace Doc {
export function GetAsync(doc: Doc, key: string, ignoreProto: boolean = false): Promise<Field | undefined> {
const self = doc[Self];
return new Promise(res => getField(self, key, ignoreProto, res));
}
export function GetTAsync<T extends Field>(doc: Doc, key: string, ctor: FieldCtor<T>, ignoreProto: boolean = false): Promise<T | undefined> {
const self = doc[Self];
return new Promise(async res => {
const field = await GetAsync(doc, key, ignoreProto);
return Cast(field, ctor);
});
}
export function Get(doc: Doc, key: string, ignoreProto: boolean = false): Field | null | undefined {
const self = doc[Self];
return getField(self, key, ignoreProto);
}
export function GetT<T extends Field>(doc: Doc, key: string, ctor: FieldCtor<T>, ignoreProto: boolean = false): Field | null | undefined {
return Cast(Get(doc, key, ignoreProto), ctor);
}
export function MakeDelegate(doc: Opt<Doc>): Opt<Doc> {
if (!doc) {
return undefined;
}
const delegate = new Doc();
delegate.prototype = doc;
return delegate;
}
export const Prototype = Symbol("Prototype");
}
export const GetAsync = Doc.GetAsync;
|