aboutsummaryrefslogtreecommitdiff
path: root/src/fields/ScriptField.ts
blob: 34c8a754409913dde16c8940a822a215b24e6ae1 (plain)
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
import { Field, FieldId } from "./Field";
import { Types } from "../server/Message";
import { CompileScript, ScriptOptions, CompiledScript } from "../client/util/Scripting";
import { Server } from "../client/Server";
import { Without } from "../Utils";

export interface SerializableOptions extends Without<ScriptOptions, "capturedVariables"> {
    capturedIds: { [id: string]: string };
}

export interface ScriptData {
    script: string;
    options: SerializableOptions;
}

export class ScriptField extends Field {
    private _script?: CompiledScript;
    get script(): CompiledScript {
        return this._script!;
    }
    private options?: ScriptData;

    constructor(script?: CompiledScript, id?: FieldId, save: boolean = true) {
        super(id);

        this._script = script;

        if (save) {
            Server.UpdateField(this);
        }
    }

    ToScriptString() {
        return "new ScriptField(...)";
    }

    GetValue() {
        return this.script;
    }

    TrySetValue(): boolean {
        throw new Error("Script fields currently can't be modified");
    }

    UpdateFromServer() {
        throw new Error("Script fields currently can't be updated");
    }

    static FromJson(id: string, data: ScriptData): ScriptField {
        let field = new ScriptField(undefined, id, false);
        field.options = data;
        return field;
    }

    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);
        });
    }

    ToJson(): { _id: string, type: Types, data: ScriptData } {
        const { options, originalScript } = this.script;
        let capturedIds: { [id: string]: string } = {};
        for (const capt in options.capturedVariables) {
            capturedIds[options.capturedVariables[capt].Id] = capt;
        }
        const opts: SerializableOptions = {
            ...options,
            capturedIds
        };
        delete (opts as any).capturedVariables;
        return {
            _id: this.Id,
            type: Types.Script,
            data: {
                script: originalScript,
                options: opts,
            },
        };
    }

    Copy(): Field {
        //Script fields are currently immutable, so we can fake copy them
        return this;
    }
}