• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

graphty-org / graphty-element / 19792929756

30 Nov 2025 02:57AM UTC coverage: 86.308% (+3.9%) from 82.377%
19792929756

push

github

apowers313
docs: fix stories for chromatic

3676 of 4303 branches covered (85.43%)

Branch coverage included in aggregate %.

17 of 17 new or added lines in 2 files covered. (100.0%)

1093 existing lines in 30 files now uncovered.

17371 of 20083 relevant lines covered (86.5%)

7075.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.74
/src/ChangeManager.ts
1
import onChange from "on-change";
3✔
2
import * as z4 from "zod/v4/core";
3✔
3

4
import {CalculatedValue} from "./CalculatedValue";
5
import {AdHocData} from "./config";
6

7
export class ChangeManager {
3✔
8
    readonly watchedInputs = new Map<string, Set<CalculatedValue>>();
12,843✔
9
    readonly dataObjects: Record<string, AdHocData | undefined> = {};
12,843✔
10
    readonly calculatedValues = new Set<CalculatedValue>();
12,843✔
11
    readonly schemas: Record<string, z4.$ZodType | undefined> = {};
12,843✔
12

13
    watch(dataType: string, data: AdHocData, schema?: z4.$ZodType): AdHocData {
3✔
14
        const watchedData = onChange(data, (path, value, prevVal /* applyData */) => {
25,676✔
15
            // ignore all the intermediate steps of setting a new deep path on
16
            // an object
17
            if (typeof value === "object" &&
4,283✔
18
                value !== null &&
1,487✔
19
                Object.keys(value).length === 0 &&
1,487✔
20
                prevVal === undefined
1,487✔
21
            ) {
4,283✔
22
                return;
1,487✔
23
            }
1,487✔
24

25
            // see if this data change triggers calculated values,
26
            // and run the calculated values if it does
27
            const cvs = this.watchedInputs.get(`${dataType}.${path}`);
2,796✔
28
            // console.log("onChange:", this.watchedInputs, `${dataType}.${path}`, cvs);
29
            if (cvs) {
4,283✔
30
                // Run ALL calculated values watching this input path
31
                for (const cv of cvs) {
123✔
32
                    // find schema for validation, if it exists
33
                    const s = getSchema(this.schemas, cv.output);
124✔
34
                    cv.run(this.dataObjects as unknown as AdHocData, s);
124✔
35
                }
124✔
36
            }
122✔
37
        });
25,676✔
38

39
        // TODO: Consider whether schema should be passed here or obtained from local context
40
        return this.addData(dataType, watchedData, schema);
25,676✔
41
    }
25,676✔
42

43
    addData(dataType: string, data: AdHocData, schema?: z4.$ZodType): AdHocData {
3✔
44
        if (this.dataObjects[dataType] !== undefined) {
38,518!
UNCOV
45
            throw new TypeError(`data type: ${dataType} already exists in change manager`);
×
UNCOV
46
        }
×
47

48
        this.dataObjects[dataType] = data;
38,518✔
49
        if (schema) {
38,518✔
50
            this.schemas[dataType] = schema;
12,836✔
51
        }
12,836✔
52

53
        return data;
38,518✔
54
    }
38,518✔
55

56
    addCalculatedValue(cv: CalculatedValue): void {
3✔
57
        this.calculatedValues.add(cv);
1,146✔
58

59
        // Add this calculated value to the set of CVs watching each input
60
        cv.inputs.forEach((i) => {
1,146✔
61
            let cvSet = this.watchedInputs.get(i);
1,166✔
62
            if (!cvSet) {
1,166✔
63
                cvSet = new Set<CalculatedValue>();
1,058✔
64
                this.watchedInputs.set(i, cvSet);
1,058✔
65
            }
1,058✔
66

67
            cvSet.add(cv);
1,166✔
68
        });
1,146✔
69
    }
1,146✔
70

71
    addCalculatedValues(cvs: CalculatedValue[]): void {
3✔
72
        cvs.forEach((cv) => {
18,456✔
73
            this.addCalculatedValue(cv);
1,137✔
74
        });
18,456✔
75
    }
18,456✔
76

77
    loadCalculatedValues(cvs: CalculatedValue[], runImmediately = false): void {
3✔
78
        this.watchedInputs.clear();
18,456✔
79
        this.addCalculatedValues(cvs);
18,456✔
80

81
        // Optionally run all calculated values immediately
82
        // This is needed when calculated values are loaded after their input data is already populated
83
        if (runImmediately) {
18,456✔
84
            this.runAllCalculatedValues();
13,800✔
85
        }
13,800✔
86
    }
18,456✔
87

88
    /**
89
     * Run all calculated values immediately
90
     * This is needed when calculated values are loaded after their input data is already populated
91
     */
92
    runAllCalculatedValues(): void {
3✔
93
        for (const cv of this.calculatedValues) {
13,828✔
94
            const s = getSchema(this.schemas, cv.output);
1,391✔
95
            cv.run(this.dataObjects as unknown as AdHocData, s);
1,391✔
96
        }
1,391✔
97
    }
13,828✔
98
}
3✔
99

100
function getSchema(schemas: Record<string, z4.$ZodType | undefined>, output: string): z4.$ZodType | undefined {
1,515✔
101
    const outputPath = output.split(".");
1,515✔
102
    const outputDataType = outputPath.shift();
1,515✔
103
    if (!outputDataType) {
1,515!
UNCOV
104
        throw new Error("error getting data type of output for calculated value");
×
105
    }
×
106

107
    const topSchema = schemas[outputDataType];
1,515✔
108
    if (!topSchema) {
1,515✔
109
        // console.log("schema.def.shape", schema.def.shape);
110
        // console.log("outputPath", outputPath);
111
        return undefined;
8✔
112
    }
8✔
113

114
    return getSchemaItemFromPath(topSchema, outputPath);
1,507✔
115
}
1,507✔
116

117
function getSchemaItemFromPath(schema: z4.$ZodType, path: string[]): z4.$ZodType | undefined {
4,501✔
118
    if (schema instanceof z4.$ZodOptional) {
4,501✔
119
        // @ts-expect-error unwrap exists on optional, not sure why it doesn't show up here
120
        schema = schema.unwrap();
2,974✔
121
    }
2,974✔
122

123
    const currentItem = path.shift();
4,501✔
124
    if (!currentItem) {
4,501✔
125
        return schema;
1,507✔
126
    }
1,507✔
127

128
    if (schema instanceof z4.$ZodObject) {
2,994✔
129
        // @ts-expect-error shape exists on object, not sure why it doesn't show up here
130
        const schemaItem = schema.shape[currentItem];
2,994✔
131
        return getSchemaItemFromPath(schemaItem, path);
2,994✔
132
    }
2,994!
133

UNCOV
134
    throw new Error(`don't know how to retreive path for: ${currentItem}.${path.join(".")}`);
×
UNCOV
135
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc