• 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

85.19
/src/data/JsonDataSource.ts
1
import jmespath from "jmespath";
3!
2
import {z} from "zod/v4";
3✔
3
import * as z4 from "zod/v4/core";
4

5
// import {JSONParser} from "@streamparser/json";
6
import type {PartiallyOptional} from "../config/common";
7
import {BaseDataSourceConfig, DataSource, DataSourceChunk} from "./DataSource";
3✔
8

9
const JsonNodeConfig = z.strictObject({
3✔
10
    path: z.string().default("nodes"),
3✔
11
    schema: z.custom<z4.$ZodObject>().or(z.null()).default(null),
3✔
12
}).prefault({});
3✔
13

14
const JsonEdgeConfig = z.strictObject({
3✔
15
    path: z.string().default("edges"),
3✔
16
    schema: z.custom<z4.$ZodObject>().or(z.null()).default(null),
3✔
17
}).prefault({});
3✔
18

19
export const JsonDataSourceConfig = z.object({
3✔
20
    data: z.string().optional(),
3✔
21
    file: z.instanceof(File).optional(),
3✔
22
    url: z.string().optional(),
3✔
23
    chunkSize: z.number().optional(),
3✔
24
    errorLimit: z.number().optional(),
3✔
25
    node: JsonNodeConfig,
3✔
26
    edge: JsonEdgeConfig,
3✔
27
});
3✔
28

29
export type JsonDataSourceConfigType = z.infer<typeof JsonDataSourceConfig>;
30
export type JsonDataSourceConfigOpts = PartiallyOptional<JsonDataSourceConfigType, "node" | "edge">;
31

32
export class JsonDataSource extends DataSource {
3✔
33
    static type = "json";
7✔
34
    opts: JsonDataSourceConfigType;
35

36
    constructor(anyOpts: object) {
7✔
37
        const opts = JsonDataSourceConfig.parse(anyOpts);
102✔
38

39
        // Pass errorLimit and chunkSize to base class
40
        super(opts.errorLimit ?? 100, opts.chunkSize ?? DataSource.DEFAULT_CHUNK_SIZE);
102✔
41

42
        this.opts = opts;
102✔
43
        if (opts.node.schema) {
102✔
44
            this.nodeSchema = opts.node.schema;
4✔
45
        }
4✔
46

47
        if (opts.edge.schema) {
102✔
48
            this.edgeSchema = opts.edge.schema;
1✔
49
        }
1✔
50
    }
102✔
51

52
    protected getConfig(): BaseDataSourceConfig {
7✔
53
        // JsonDataSource has special handling for 'data' field:
54
        // If data starts with http/https/data:, treat it as URL
55
        // Otherwise treat it as inline JSON
56
        const isUrl = (this.opts.data?.startsWith("http://") ?? false) ||
101✔
57
                     (this.opts.data?.startsWith("https://") ?? false) ||
101✔
58
                     (this.opts.data?.startsWith("data:") ?? false);
15✔
59

60
        return {
101✔
61
            data: isUrl ? undefined : this.opts.data,
101✔
62
            file: this.opts.file,
101✔
63
            url: isUrl ? this.opts.data : this.opts.url,
101✔
64
            chunkSize: this.opts.chunkSize,
101✔
65
            errorLimit: this.opts.errorLimit,
101✔
66
        };
101✔
67
    }
101✔
68

69
    async *sourceFetchData(): AsyncGenerator<DataSourceChunk, void, unknown> {
7✔
70
        let data: unknown;
101✔
71

72
        // Get JSON content (could be from data, file, or url)
73
        const jsonString = await this.getContent();
101✔
74

75
        // Parse JSON
76
        try {
100✔
77
            data = JSON.parse(jsonString);
100✔
78
        } catch (error) {
99!
79
            throw new Error(`Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`);
×
80
        }
✔
81

82
        // Extract nodes using JMESPath
83
        let nodes: unknown;
100✔
84
        try {
100✔
85
            nodes = jmespath.search(data, this.opts.node.path);
100✔
86
        } catch (error) {
99!
UNCOV
87
            throw new Error(`Failed to extract nodes using path '${this.opts.node.path}': ${error instanceof Error ? error.message : String(error)}`);
×
UNCOV
88
        }
✔
89

90
        if (!Array.isArray(nodes)) {
99!
UNCOV
91
            throw new TypeError(`JsonDataSource expected 'nodes' at path '${this.opts.node.path}' to be an array of objects, got ${typeof nodes}`);
×
UNCOV
92
        }
✔
93

94
        // Extract edges using JMESPath
95
        let edges: unknown;
100✔
96
        try {
100✔
97
            edges = jmespath.search(data, this.opts.edge.path);
100✔
98
        } catch (error) {
99!
UNCOV
99
            throw new Error(`Failed to extract edges using path '${this.opts.edge.path}': ${error instanceof Error ? error.message : String(error)}`);
×
100
        }
✔
101

102
        if (!Array.isArray(edges)) {
99!
UNCOV
103
            throw new TypeError(`JsonDataSource expected 'edges' at path '${this.opts.edge.path}' to be an array of objects, got ${typeof edges}`);
×
104
        }
✔
105

106
        // Yield data in chunks using inherited helper
107
        yield* this.chunkData(nodes, edges);
100✔
108
    }
101✔
109
}
7✔
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