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 { ObjectField } from "../new_fields/ObjectField";
import { CompiledScript, CompileScript } from "../client/util/Scripting";
import { Copy, ToScriptString, Parent, SelfProxy } from "../new_fields/FieldSymbols";
import { serializable, createSimpleSchema, map, primitive, object, deserialize, PropSchema, custom, SKIP } from "serializr";
import { Deserializable } from "../client/util/SerializationHelper";
import { Doc } from "../new_fields/Doc";
function optional(propSchema: PropSchema) {
return custom(value => {
if (value !== undefined) {
return propSchema.serializer(value);
}
return SKIP;
}, (jsonValue: any, context: any, oldValue: any, callback: (err: any, result: any) => void) => {
if (jsonValue !== undefined) {
return propSchema.deserializer(jsonValue, callback, context, oldValue);
}
return SKIP;
});
}
const optionsSchema = createSimpleSchema({
requiredType: true,
addReturn: true,
typecheck: true,
readonly: true,
params: optional(map(primitive()))
});
function deserializeScript(script: ScriptField) {
const comp = CompileScript(script.scriptString, script.options);
if (!comp.compiled) {
throw new Error("Couldn't compile loaded script");
}
(script as any)._script = comp;
}
@Deserializable("script", deserializeScript)
export class ScriptField extends ObjectField {
protected readonly _script: CompiledScript;
constructor(script: CompiledScript) {
super();
this._script = script;
}
@serializable(custom(object(optionsSchema).serializer, () => SKIP))
get options() {
return this._script && this._script.options;
}
@serializable(custom(primitive().serializer, () => SKIP))
get scriptString(): string {
return this._script && this._script.originalScript;
}
// init(callback: (res: Field) => any) {
// const options = this.options!;
// const keys = Object.keys(options.options.capturedIds);
// Server.GetFields(keys).then(fields => {
// let captured: { [name: string]: Field } = {};
// keys.forEach(key => captured[options.options.capturedIds[key]] = fields[key]);
// const opts: ScriptOptions = {
// addReturn: options.options.addReturn,
// params: options.options.params,
// requiredType: options.options.requiredType,
// capturedVariables: captured
// };
// const script = CompileScript(options.script, opts);
// if (!script.compiled) {
// throw new Error("Can't compile script");
// }
// this._script = script;
// callback(this);
// });
// }
[Copy](): ObjectField {
return new ScriptField(this._script);
}
[ToScriptString]() {
return "script field";
}
}
@Deserializable("computed", deserializeScript)
export class ComputedField extends ScriptField {
//TODO maybe add an observable cache based on what is passed in for doc, considering there shouldn't really be that many possible values for doc
value(doc: Doc) {
const val = this._script.run({ this: doc });
if (val.success) {
return val.result;
}
return undefined;
}
}
|