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

jumpinjackie / mapguide-react-layout / 29921515611

22 Jul 2026 12:53PM UTC coverage: 62.625% (+1.5%) from 61.081%
29921515611

push

github

web-flow
Update to React 18 + other package updates (#1683)

* Update to React 18 and other assorted package updates

* More package updates

* Update react-redux

* Fix TS error

3301 of 6236 branches covered (52.93%)

1 of 2 new or added lines in 2 files covered. (50.0%)

145 existing lines in 29 files now uncovered.

6910 of 11034 relevant lines covered (62.62%)

15.05 hits per line

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

83.46
/src/api/builders/deArrayify.ts
1
/**
2
 * deArrayify.ts
3
 *
4
 * This module provides JSON sanitization of JSON responses from the mapagent
5
 *
6
 * Being a transformation of the XML form, and taking a lowest-common-denominator
7
 * approach to JSON conversion, the JSON responses from MapGuide are un-wieldy to
8
 * use from the client-side due to:
9
 *
10
 *  a) All properties being arrays
11
 *  b) All property values being strings
12
 *
13
 * These functions help "clean" those responses to be of the form we expect (and prefer)
14
 */
15
import { MgError } from "../error";
16
import { ActiveSelectedFeature } from "../common";
17
import { RuleInfo, FeatureStyleInfo, ScaleRangeInfo, FeatureSourceInfo, MapLayer, MapGroup, CoordinateSystemType, EnvCoordinate, Envelope, RuntimeMap } from '../contracts/runtime-map';
18
import { FeatureSetClass, FeatureSetLayer, FeatureSet, SelectionImage, FeatureProperty, SelectedFeature, LayerPropertyMetadata, LayerMetadata, SelectedLayer, SelectedFeatureSet, QueryMapFeaturesResponse } from '../contracts/query';
19
import { WebLayoutMap, WebLayoutControl, WebLayoutInfoPane, MapView, TaskButton, WebLayoutTaskBar, UIItem, WebLayoutTaskPane, CommandUIItem, FlyoutUIItem, ResultColumnSet, ResultColumn, LayerSet, ParameterPair, CommandDef, BasicCommandDef, InvokeScriptCommandDef, InvokeURLCommandDef, SearchCommandDef, WebLayoutCommandSet, WebLayout, WebLayoutToolbar, WebLayoutContextMenu, WebLayoutStatusBar, WebLayoutZoomControl } from '../contracts/weblayout';
20
import { MapSetGroup, MapInitialView, MapConfiguration, MapSet, ContainerItem, FlyoutItem, WidgetItem, ContainerDefinition, Widget, UIWidget, MapWidget, WidgetSet, ApplicationDefinition } from '../contracts/fusion';
21
import { MDF_INFINITY } from '../../constants';
22
import { MapDefinition, MapDefinitionLayerGroup, MapDefinitionLayer as MdfLayer, TileSetSource } from "../contracts/map-definition";
23
import { BaseMapLayer, BaseMapLayerGroup, TileSetDefinition, TileStoreParameters } from "../contracts/tile-set-definition";
24
import { SiteVersionResponse } from '../contracts/common';
25

26
type ElementType = "string" | "boolean" | "int" | "float";
27

28
function buildPropertyGetter<T>() {
29
    return (el: any, name: keyof T, type: ElementType = "string") => {
995✔
30
        return tryGetAsProperty<T>(el, name, type);
6,609✔
31
    }
32
}
33

34
function tryGetAsProperty<T>(el: any, name: keyof T, type: ElementType = "string"): any {
6,609✔
35
    if (!el[name]) {
6,609✔
36
        return null;
663✔
37
    } else if (el[name].length === 1) {
5,946!
38
        const val: string = el[name][0];
5,946✔
39
        switch (type) {
5,946✔
40
            case "int":
41
                return parseInt(val, 10);
124✔
42
            case "float":
43
                return parseFloat(val);
133✔
44
            case "boolean":
45
                return val.toLowerCase() === "true";
811✔
46
            default:
47
                return val;
4,878✔
48
        }
49
    }
50
}
51

52
function deArrayifyRules(rules: any[]): RuleInfo[] {
53
    const getter = buildPropertyGetter<RuleInfo>();
46✔
54
    return rules.map(r => {
46✔
55
        const rule: RuleInfo = {
101✔
56
            LegendLabel: getter(r, "LegendLabel"),
57
            Filter: getter(r, "Filter"),
58
            Icon: getter(r, "Icon")
59
        };
60
        return rule;
101✔
61
    });
62
}
63

64
function deArrayifyFeatureStyles(fts: any[]): FeatureStyleInfo[] {
65
    if (!fts) {
46!
66
        return [];
×
67
    }
68
    const getter = buildPropertyGetter<FeatureStyleInfo>();
46✔
69
    return fts.map(ft => {
46✔
70
        const featureStyle: FeatureStyleInfo = {
46✔
71
            Type: getter(ft, "Type", "int"),
72
            Rule: deArrayifyRules(ft.Rule)
73
        };
74
        return featureStyle;
46✔
75
    });
76
}
77

78
function deArrayifyScaleRanges(scales: any[]): ScaleRangeInfo[] {
79
    if (!scales) { //Happens with raster layers (this is probably a bug in CREATERUNTIMEMAP)
44!
80
        const defaultRange: ScaleRangeInfo = {
×
81
            MinScale: 0,
82
            MaxScale: MDF_INFINITY,
83
            FeatureStyle: []
84
        };
85
        return [defaultRange];
×
86
    }
87
    
88
    const getter = buildPropertyGetter<ScaleRangeInfo>();
44✔
89
    return scales.map(sc => {
44✔
90
        const scale: ScaleRangeInfo = {
46✔
91
            MinScale: getter(sc, "MinScale", "float"),
92
            MaxScale: getter(sc, "MaxScale", "float"),
93
            FeatureStyle: deArrayifyFeatureStyles(sc.FeatureStyle)
94
        };
95
        return scale;
46✔
96
    });
97
}
98

99
function deArrayifyFeatureSourceInfo(fs: any[]): FeatureSourceInfo | undefined {
100
    if (!fs || fs.length !== 1) {
44!
101
        return undefined;
×
102
    }
103
    const getter = buildPropertyGetter<FeatureSourceInfo>();
44✔
104
    return {
44✔
105
        ResourceId: getter(fs[0], "ResourceId"),
106
        ClassName: getter(fs[0], "ClassName"),
107
        Geometry: getter(fs[0], "Geometry")
108
    };
109
}
110

111
function deArrayifyLayers(layers: any[]): MapLayer[] {
112
    if (!layers)
3!
UNCOV
113
        return layers;
×
114

115
    const getter = buildPropertyGetter<MapLayer>();
3✔
116
    return layers.map(lyr => {
3✔
117
        const layer: MapLayer = {
44✔
118
            Type: getter(lyr, "Type", "int"),
119
            Selectable: getter(lyr, "Selectable", "boolean"),
120
            LayerDefinition: getter(lyr, "LayerDefinition"),
121
            Name: getter(lyr, "Name"),
122
            LegendLabel: getter(lyr, "LegendLabel"),
123
            ObjectId: getter(lyr, "ObjectId"),
124
            ParentId: getter(lyr, "ParentId"),
125
            DisplayInLegend: getter(lyr, "DisplayInLegend", "boolean"),
126
            ExpandInLegend: getter(lyr, "ExpandInLegend", "boolean"),
127
            Visible: getter(lyr, "Visible", "boolean"),
128
            ActuallyVisible: getter(lyr, "ActuallyVisible", "boolean"),
129
            FeatureSource: deArrayifyFeatureSourceInfo(lyr.FeatureSource),
130
            ScaleRange: deArrayifyScaleRanges(lyr.ScaleRange)
131
        };
132
        //This is either a raster or drawing layer, in this case disregard the
133
        //selectability flag (and set it to false). This is to prevent false positive
134
        //errors trying to do tooltip/selections against raster/drawing layers
135
        if (!lyr.ScaleRange) {
44!
136
            layer.Selectable = false;
×
137
        }
138
        return layer;
44✔
139
    });
140
}
141

142
function deArrayifyGroups(groups: any[]): MapGroup[] | undefined {
143
    if (!groups)
3!
UNCOV
144
        return undefined;
×
145

146
    const getter = buildPropertyGetter<MapGroup>();
3✔
147
    return groups.map(grp => {
3✔
148
        const group: MapGroup = {
16✔
149
            Type: getter(grp, "Type", "int"),
150
            Name: getter(grp, "Name"),
151
            LegendLabel: getter(grp, "LegendLabel"),
152
            ObjectId: getter(grp, "ObjectId"),
153
            ParentId: getter(grp, "ParentId"),
154
            DisplayInLegend: getter(grp, "DisplayInLegend", "boolean"),
155
            ExpandInLegend: getter(grp, "ExpandInLegend", "boolean"),
156
            Visible: getter(grp, "Visible", "boolean"),
157
            ActuallyVisible: getter(grp, "ActuallyVisible", "boolean")
158
        };
159
        return group;
16✔
160
    });
161
}
162

163
function deArrayifyCoordinateSystem(cs: any[]): CoordinateSystemType {
164
    if (!cs || cs.length !== 1) {
3!
165
        throw new MgError("Malformed input. Expected CoordinateSystem element");
×
166
    }
167
    const getter = buildPropertyGetter<CoordinateSystemType>();
3✔
168
    const res: CoordinateSystemType = {
3✔
169
        Wkt: getter(cs[0], "Wkt"),
170
        MentorCode: getter(cs[0], "MentorCode"),
171
        EpsgCode: getter(cs[0], "EpsgCode"),
172
        MetersPerUnit: getter(cs[0], "MetersPerUnit", "float")
173
    };
174
    return res;
3✔
175
}
176

177
function deArrayifyCoordinate(coord: any[]): EnvCoordinate {
178
    if (!coord || coord.length !== 1) {
6!
179
        throw new MgError("Malformed input. Expected coordinate array");
×
180
    }
181
    const getter = buildPropertyGetter<EnvCoordinate>();
6✔
182
    return {
6✔
183
        X: getter(coord[0], "X", "float"),
184
        Y: getter(coord[0], "Y", "float")
185
    };
186
}
187

188
function deArrayifyExtents(extents: any[]): Envelope {
189
    if (!extents || extents.length !== 1) {
3!
190
        throw new MgError("Malformed input. Expected extent element");
×
191
    }
192
    const env: Envelope = {
3✔
193
        LowerLeftCoordinate: deArrayifyCoordinate(extents[0].LowerLeftCoordinate),
194
        UpperRightCoordinate: deArrayifyCoordinate(extents[0].UpperRightCoordinate)
195
    };
196
    return env;
3✔
197
}
198

199
function deArrayifyFiniteDisplayScales(fds: any[]): number[] | undefined {
200
    if (!fds)
3!
201
        return undefined;
3✔
202

203
    return fds.map(parseFloat);
×
204
}
205

206
function deArrayifyRuntimeMap(json: any): RuntimeMap {
207
    const root = json;
3✔
208
    const getter = buildPropertyGetter<RuntimeMap>();
3✔
209
    const rtMap: RuntimeMap = {
3✔
210
        SessionId: getter(root, "SessionId"),
211
        SiteVersion: getter(root, "SiteVersion"),
212
        Name: getter(root, "Name"),
213
        MapDefinition: getter(root, "MapDefinition"),
214
        TileSetDefinition: getter(root, "TileSetDefinition"),
215
        TileWidth: getter(root, "TileWidth", "int"),
216
        TileHeight: getter(root, "TileHeight", "int"),
217
        BackgroundColor: getter(root, "BackgroundColor"),
218
        DisplayDpi: getter(root, "DisplayDpi", "int"),
219
        IconMimeType: getter(root, "IconMimeType"),
220
        CoordinateSystem: deArrayifyCoordinateSystem(root.CoordinateSystem),
221
        Extents: deArrayifyExtents(root.Extents),
222
        Group: deArrayifyGroups(root.Group),
223
        Layer: deArrayifyLayers(root.Layer),
224
        FiniteDisplayScale: deArrayifyFiniteDisplayScales(root.FiniteDisplayScale),
225
        TilePixelRatio: getter(root, "TilePixelRatio", "int"),
226
        TileSetProvider: getter(root, "TileSetProvider")
227
    };
228
    return rtMap;
3✔
229
}
230

231
function deArrayifyFeatureSetClass(json: any): FeatureSetClass {
232
    const root = json;
1✔
233
    const getter = buildPropertyGetter<FeatureSetClass>();
1✔
234
    if (root.length != 1) {
1!
235
        throw new MgError("Malformed input. Expected Class element");
×
236
    }
237
    const cls = {
1✔
238
        "@id": getter(root[0], "@id"),
239
        ID: root[0].ID
240
    };
241
    return cls;
1✔
242
}
243

244
function deArrayifyFeatureSetLayers(json: any[]): FeatureSetLayer[] {
245
    const getter = buildPropertyGetter<FeatureSetLayer>();
1✔
246
    return (json || []).map(root => {
1!
247
        const layer = {
1✔
248
            "@id": getter(root, "@id"),
249
            "@name": getter(root, "@name"),
250
            Class: deArrayifyFeatureSetClass(root.Class)
251
        };
252
        return layer;
1✔
253
    });
254
}
255

256
function deArrayifyFeatureSet(json: any): FeatureSet | undefined {
257
    const root = json;
2✔
258
    if (root == null || root.length != 1) {
2✔
259
        return undefined;
1✔
260
    }
261
    const fs = {
1✔
262
        Layer: deArrayifyFeatureSetLayers(root[0].Layer)
263
    };
264
    return fs;
1✔
265
}
266

267
function deArrayifyInlineSelectionImage(json: any): SelectionImage | undefined {
268
    const root = json;
2✔
269
    if (root == null || root.length != 1) {
2!
270
        return undefined;
2✔
271
    }
272
    const getter = buildPropertyGetter<SelectionImage>();
×
273
    const img = {
×
274
        MimeType: getter(root[0], "MimeType"),
275
        Content: getter(root[0], "Content")
276
    };
277
    return img;
×
278
}
279

280
function deArrayifyFeatureProperties(json: any[]): FeatureProperty[] {
281
    const getter = buildPropertyGetter<FeatureProperty>();
21✔
282
    return (json || []).map(root => {
21!
283
        const prop = {
210✔
284
            Name: getter(root, "Name"),
285
            Value: getter(root, "Value")
286
        };
287
        return prop;
210✔
288
    });
289
}
290

291
function deArrayifyFeatures(json: any[]): SelectedFeature[] {
292
    const getter = buildPropertyGetter<SelectedFeature>();
1✔
293
    return (json || []).map(root => {
1!
294
        const feat = {
21✔
295
            Bounds: getter(root, "Bounds"),
296
            Property: deArrayifyFeatureProperties(root.Property),
297
            SelectionKey: getter(root, "SelectionKey")
298
        };
299
        return feat;
21✔
300
    });
301
}
302

303
function deArrayifyLayerMetadataProperties(json: any[]): LayerPropertyMetadata[] {
304
    const getter = buildPropertyGetter<LayerPropertyMetadata>();
1✔
305
    return (json || []).map(root => {
1!
306
        const prop = {
10✔
307
            DisplayName: getter(root, "DisplayName"),
308
            Name: getter(root, "Name"),
309
            Type: getter(root, "Type", "int")
310
        };
311
        return prop;
10✔
312
    });
313
}
314

315
function deArrayifyLayerMetadata(json: any): LayerMetadata | undefined {
316
    const root = json;
1✔
317
    //NOTE: root could be null if the layer selected has no properties beyond id/geom
318
    if (root == null || root.length != 1) {
1!
319
        return undefined;
×
320
    }
321
    const meta = {
1✔
322
        Property: deArrayifyLayerMetadataProperties(root[0].Property)
323
    };
324
    return meta;
1✔
325
}
326

327
function deArrayifySelectedLayer(json: any[]): SelectedLayer[] {
328
    const getter = buildPropertyGetter<SelectedLayer>();
1✔
329
    return (json || []).map(root => {
1!
330
        const layer = {
1✔
331
            "@id": getter(root, "@id"),
332
            "@name": getter(root, "@name"),
333
            Feature: deArrayifyFeatures(root.Feature),
334
            LayerMetadata: deArrayifyLayerMetadata(root.LayerMetadata)
335
        };
336
        return layer;
1✔
337
    });
338
}
339

340
function deArrayifySelectedFeatures(json: any): SelectedFeatureSet | undefined {
341
    const root = json;
2✔
342
    if (root == null || root.length != 1) {
2✔
343
        return undefined;
1✔
344
    }
345
    const sf = {
1✔
346
        SelectedLayer: deArrayifySelectedLayer(root[0].SelectedLayer)
347
    };
348
    return sf;
1✔
349
}
350

351
function deArrayifyFeatureInformation(json: any): QueryMapFeaturesResponse {
352
    const root = json;
2✔
353
    const getter = buildPropertyGetter<QueryMapFeaturesResponse>();
2✔
354
    const resp = {
2✔
355
        FeatureSet: deArrayifyFeatureSet(root.FeatureSet),
356
        Hyperlink: getter(root, "Hyperlink"),
357
        InlineSelectionImage: deArrayifyInlineSelectionImage(root.InlineSelectionImage),
358
        SelectedFeatures: deArrayifySelectedFeatures(root.SelectedFeatures),
359
        Tooltip: getter(root, "Tooltip")
360
    };
361
    return resp;
2✔
362
}
363

364
function deArrayifyWebLayoutControl<T extends WebLayoutControl>(json: any): T {
365
    const root = json;
4✔
366
    if (root == null || root.length != 1) {
4!
367
        throw new MgError("Malformed input. Expected control element");
×
368
    }
369
    const getter = buildPropertyGetter<T>();
4✔
370
    const control: any = {
4✔
371
        Visible: getter(root[0], "Visible", "boolean")
372
    };
373
    return control;
4✔
374
}
375

376
function deArrayifyWebLayoutInfoPane(json: any): WebLayoutInfoPane {
377
    const root = json;
2✔
378
    if (root == null || root.length != 1) {
2!
379
        throw new MgError("Malformed input. Expected InformationPane element");
×
380
    }
381
    const getter = buildPropertyGetter<WebLayoutInfoPane>();
2✔
382
    const infoPane = {
2✔
383
        Visible: getter(root[0], "Visible", "boolean"),
384
        Width: getter(root[0], "Width", "int"),
385
        LegendVisible: getter(root[0], "LegendVisible", "boolean"),
386
        PropertiesVisible: getter(root[0], "PropertiesVisible", "boolean")
387
    };
388
    return infoPane;
2✔
389
}
390

391
function deArrayifyWebLayoutInitialView(json: any): MapView | undefined {
392
    const root = json;
2✔
393
    if (root == null || root.length != 1) {
2!
394
        return undefined;
2✔
395
    }
396
    const getter = buildPropertyGetter<MapView>();
×
397
    const view = {
×
398
        CenterX: getter(root[0], "CenterX", "float"),
399
        CenterY: getter(root[0], "CenterY", "float"),
400
        Scale: getter(root[0], "Scale", "float")
401
    };
402
    return view;
×
403
}
404

405
function deArrayifyWebLayoutMap(json: any): WebLayoutMap {
406
    const root = json;
2✔
407
    if (root == null || root.length != 1) {
2!
408
        throw new MgError("Malformed input. Expected Map element");
×
409
    }
410
    const getter = buildPropertyGetter<WebLayoutMap>();
2✔
411
    const map = {
2✔
412
        ResourceId: getter(root[0], "ResourceId"),
413
        InitialView: deArrayifyWebLayoutInitialView(root[0].InitialView),
414
        HyperlinkTarget: getter(root[0], "HyperlinkTarget"),
415
        HyperlinkTargetFrame: getter(root[0], "HyperlinkTargetFrame")
416
    };
417
    return map;
2✔
418
}
419

420
function deArrayifyTaskButton(json: any): TaskButton {
421
    const root = json;
8✔
422
    if (root == null || root.length != 1) {
8!
423
        throw new MgError("Malformed input. Expected TaskButton element");
×
424
    }
425
    const getter = buildPropertyGetter<TaskButton>();
8✔
426
    const button = {
8✔
427
        Name: getter(root[0], "Name"),
428
        Tooltip: getter(root[0], "Tooltip"),
429
        Description: getter(root[0], "Description"),
430
        ImageURL: getter(root[0], "ImageURL"),
431
        DisabledImageURL: getter(root[0], "DisabledImageURL")
432
    };
433
    return button;
8✔
434
}
435

436
function deArrayifyWebLayoutTaskBar(json: any): WebLayoutTaskBar {
437
    const root = json;
2✔
438
    if (root == null || root.length != 1) {
2!
439
        throw new MgError("Malformed input. Expected TaskBar element");
×
440
    }
441
    const getter = buildPropertyGetter<WebLayoutTaskBar>();
2✔
442
    const taskbar = {
2✔
443
        Visible: getter(root[0], "Visible", "boolean"),
444
        Home: deArrayifyTaskButton(root[0].Home),
445
        Forward: deArrayifyTaskButton(root[0].Forward),
446
        Back: deArrayifyTaskButton(root[0].Back),
447
        Tasks: deArrayifyTaskButton(root[0].Tasks),
448
        MenuButton: [] as UIItem[]
449
    };
450
    if (root[0].MenuButton) {
2!
451
        for (const mb of root[0].MenuButton) {
2✔
452
            taskbar.MenuButton.push(deArrayifyUIItem(mb));
8✔
453
        }
454
    }
455
    return taskbar;
2✔
456
}
457

458
function deArrayifyWebLayoutTaskPane(json: any): WebLayoutTaskPane {
459
    const root = json;
2✔
460
    if (root == null || root.length != 1) {
2!
461
        throw new MgError("Malformed input. Expected TaskPane element");
×
462
    }
463
    const getter = buildPropertyGetter<WebLayoutTaskPane>();
2✔
464
    const taskPane = {
2✔
465
        Visible: getter(root[0], "Visible", "boolean"),
466
        InitialTask: getter(root[0], "InitialTask"),
467
        Width: getter(root[0], "Width", "int"),
468
        TaskBar: deArrayifyWebLayoutTaskBar(root[0].TaskBar)
469
    };
470
    return taskPane;
2✔
471
}
472

473
function deArrayifyUIItem(json: any): UIItem {
474
    const root = json;
58✔
475
    const getter = buildPropertyGetter<UIItem & CommandUIItem & FlyoutUIItem>();
58✔
476
    const func: string = getter(root, "Function");
58✔
477
    //Wouldn't it be nice if we could incrementally build up a union type that then becomes a specific
478
    //type once certain properties are set?
479
    //
480
    //Well, that's currently not possible. So we have to resort to "any"
481
    const item: any = {
58✔
482
        Function: func
483
    };
484
    switch (func) {
58✔
485
        case "Command":
486
            item.Command = getter(root, "Command");
43✔
487
            break;
43✔
488
        case "Flyout":
489
            item.Label = getter(root, "Label");
3✔
490
            item.Tooltip = getter(root, "Tooltip");
3✔
491
            item.Description = getter(root, "Description");
3✔
492
            item.ImageURL = getter(root, "ImageURL");
3✔
493
            item.DisabledImageURL = getter(root, "DisabledImageURL");
3✔
494
            item.SubItem = [];
3✔
495
            for (const si of root.SubItem) {
3✔
496
                item.SubItem.push(deArrayifyUIItem(si));
11✔
497
            }
498
            break;
3✔
499
    }
500
    return item;
58✔
501
}
502

503
function deArrayifyItemContainer<T extends WebLayoutControl>(json: any, name: string): T {
504
    const root = json;
4✔
505
    if (root == null || root.length != 1) {
4!
506
        throw new MgError("Malformed input. Expected container element");
×
507
    }
508
    const getter = buildPropertyGetter<T>();
4✔
509
    const container: any = {};
4✔
510
    container[name] = [];
4✔
511
    for (const item of root[0][name]) {
4✔
512
        container[name].push(deArrayifyUIItem(item));
39✔
513
    }
514
    if (typeof (root[0].Visible) != 'undefined') {
4!
515
        container.Visible = getter(root[0], "Visible", "boolean");
4✔
516
    }
517
    return container;
4✔
518
}
519

520
function deArrayifyWebLayoutSearchResultColumnSet(json: any): ResultColumnSet {
521
    const root = json;
×
522
    if (root == null || root.length != 1) {
×
523
        throw new MgError("Malformed input. Expected ResultColumns element");
×
524
    }
525
    const getter = buildPropertyGetter<ResultColumn>();
×
526
    const res = {
×
527
        Column: [] as ResultColumn[]
528
    };
529
    for (const col of root[0].Column) {
×
530
        res.Column.push({
×
531
            Name: getter(col, "Name"),
532
            Property: getter(col, "Property")
533
        });
534
    }
535
    return res;
×
536
}
537

538
function deArrayifyWebLayoutInvokeURLLayerSet(json: any): LayerSet | undefined {
539
    const root = json;
5✔
540
    if (root == null || root.length != 1) {
5!
541
        return undefined;
5✔
542
    }
543
    const layerset = {
×
544
        Layer: root[0].Layer
545
    };
546
    return layerset;
×
547
}
548

549
function deArrayifyWebLayoutParameterPairs(json: any): ParameterPair[] {
550
    const root = json;
5✔
551
    const pairs = [] as ParameterPair[]
5✔
552
    if (!root) {
5!
553
        return pairs;
5✔
554
    }
555
    const getter = buildPropertyGetter<ParameterPair>();
×
556
    for (const kvp of root) {
×
557
        pairs.push({
×
558
            Key: getter(kvp, "Key"),
559
            Value: getter(kvp, "Value")
560
        });
561
    }
562
    return pairs;
×
563
}
564

565
function deArrayifyCommand(json: any): CommandDef {
566
    const root = json;
33✔
567
    const getter = buildPropertyGetter<CommandDef & BasicCommandDef & InvokeScriptCommandDef & InvokeURLCommandDef & SearchCommandDef>();
33✔
568
    const cmd: any = {
33✔
569
        "@xsi:type": getter(root, "@xsi:type"),
570
        Name: getter(root, "Name"),
571
        Label: getter(root, "Label"),
572
        Tooltip: getter(root, "Tooltip"),
573
        Description: getter(root, "Description"),
574
        ImageURL: getter(root, "ImageURL"),
575
        DisabledImageURL: getter(root, "DisabledImageURL"),
576
        TargetViewer: getter(root, "TargetViewer")
577
    };
578
    //Basic
579
    if (typeof (root.Action) != 'undefined') {
33✔
580
        cmd.Action = getter(root, "Action");
21✔
581
    }
582
    //Targeted
583
    if (typeof (root.Target) != 'undefined') {
33✔
584
        cmd.Target = getter(root, "Target");
11✔
585
    }
586
    if (typeof (root.TargetFrame) != 'undefined') {
33!
587
        cmd.TargetFrame = getter(root, "TargetFrame");
×
588
    }
589
    //Search
590
    if (typeof (root.Layer) != 'undefined') {
33!
591
        cmd.Layer = getter(root, "Layer");
×
592
        cmd.Prompt = getter(root, "Prompt");
×
593
        cmd.ResultColumns = deArrayifyWebLayoutSearchResultColumnSet(root.ResultColumns);
×
594
        cmd.Filter = getter(root, "Filter");
×
595
        cmd.MatchLimit = getter(root, "MatchLimit", "int");
×
596
    }
597
    //InvokeURL | Help
598
    if (typeof (root.URL) != 'undefined') {
33✔
599
        cmd.URL = getter(root, "URL");
5✔
600
    }
601
    if (typeof (root.DisableIfSelectionEmpty) != 'undefined') {
33✔
602
        cmd.LayerSet = deArrayifyWebLayoutInvokeURLLayerSet(root.LayerSet);
5✔
603
        cmd.AdditionalParameter = deArrayifyWebLayoutParameterPairs(root.AdditionalParameter);
5✔
604
        cmd.DisableIfSelectionEmpty = getter(root, "DisableIfSelectionEmpty", "boolean");
5✔
605
    }
606
    //InvokeScript
607
    if (typeof (root.Script) != 'undefined') {
33!
608
        cmd.Script = getter(root, "Script");
×
609
    }
610
    return cmd;
33✔
611
}
612

613
function deArrayifyWebLayoutCommandSet(json: any): WebLayoutCommandSet {
614
    const root = json;
2✔
615
    if (root == null || root.length != 1) {
2!
616
        throw new MgError("Malformed input. Expected CommandSet element");
×
617
    }
618
    const set = {
2✔
619
        Command: [] as CommandDef[]
620
    };
621
    if (root[0].Command) {
2!
622
        for (const cmd of root[0].Command) {
2✔
623
            set.Command.push(deArrayifyCommand(cmd));
33✔
624
        }
625
    }
626
    return set;
2✔
627
}
628

629
function deArrayifyWebLayout(json: any): WebLayout {
630
    const root = json;
2✔
631
    const getter = buildPropertyGetter<WebLayout>();
2✔
632
    const resp = {
2✔
633
        Title: getter(root, "Title"),
634
        Map: deArrayifyWebLayoutMap(root.Map),
635
        EnablePingServer: getter(root, "EnablePingServer", "boolean"),
636
        SelectionColor: getter(root, "SelectionColor"),
637
        PointSelectionBuffer: getter(root, "PointSelectionBuffer", "int"),
638
        MapImageFormat: getter(root, "MapImageFormat"),
639
        SelectionImageFormat: getter(root, "SelectionImageFormat"),
640
        StartupScript: getter(root, "StartupScript"),
641
        ToolBar: deArrayifyItemContainer<WebLayoutToolbar>(root.ToolBar, "Button"),
642
        InformationPane: deArrayifyWebLayoutInfoPane(root.InformationPane),
643
        ContextMenu: deArrayifyItemContainer<WebLayoutContextMenu>(root.ContextMenu, "MenuItem"),
644
        TaskPane: deArrayifyWebLayoutTaskPane(root.TaskPane),
645
        StatusBar: deArrayifyWebLayoutControl<WebLayoutStatusBar>(root.StatusBar),
646
        ZoomControl: deArrayifyWebLayoutControl<WebLayoutZoomControl>(root.ZoomControl),
647
        CommandSet: deArrayifyWebLayoutCommandSet(root.CommandSet)
648
    };
649
    return resp;
2✔
650
}
651

652
function deArrayifyMapGroup(json: any): MapSetGroup {
653
    const root = json;
15✔
654
    if (root == null) {
15!
655
        throw new MgError("Malformed input. Expected MapGroup element");
×
656
    }
657
    const getter = buildPropertyGetter<MapSetGroup & MapInitialView & MapConfiguration>();
15✔
658
    const mapGroup: MapSetGroup = {
15✔
659
        "@id": getter(root, "@id", "string"),
660
        InitialView: undefined,
661
        Map: [] as MapConfiguration[]
662
    };
663
    if (root.InitialView) {
15✔
664
        const iview = root.InitialView[0];
2✔
665
        mapGroup.InitialView = {
2✔
666
            CenterX: getter(iview, "CenterX", "float"),
667
            CenterY: getter(iview, "CenterY", "float"),
668
            Scale: getter(iview, "Scale", "float")
669
        };
670
    }
671
    if (root.Map) {
15!
672
        for (const m of root.Map) {
15✔
673
            mapGroup.Map.push({
29✔
674
                Type: getter(m, "Type", "string"),
675
                //SingleTile: getter(m, "SingleTile", "boolean"),
676
                Extension: deArrayifyExtension(m.Extension)
677
            });
678
        }
679
    }
680
    if (root.Extension) {
15!
681
        mapGroup.Extension = deArrayifyExtension(root.Extension);
×
682
    }
683
    return mapGroup;
15✔
684
}
685

686
function deArrayifyMapSet(json: any): MapSet | undefined {
687
    const root = json;
5✔
688
    if (root == null || root.length != 1) {
5!
689
        throw new MgError("Malformed input. Expected MapSet element");
×
690
    }
691
    const set = {
5✔
692
        MapGroup: [] as MapSetGroup[]
693
    };
694
    if (root[0].MapGroup) {
5!
695
        for (const map of root[0].MapGroup) {
5✔
696
            set.MapGroup.push(deArrayifyMapGroup(map));
15✔
697
        }
698
    }
699
    return set;
5✔
700
}
701

702
function deArrayifyContainerItems(json: any[]): ContainerItem[] {
703
    const items = [] as ContainerItem[];
45✔
704
    const getter = buildPropertyGetter<ContainerItem & FlyoutItem & WidgetItem>();
45✔
705
    if (json && json.length) {
45✔
706
        for (const i of json) {
38✔
707
            const func = getter(i, "Function", "string");
347✔
708
            switch (func) {
347✔
709
                case "Separator":
710
                    items.push({
33✔
711
                        Function: "Separator"
712
                    });
713
                    break;
33✔
714
                case "Widget":
715
                    items.push({
297✔
716
                        Function: "Widget",
717
                        Widget: getter(i, "Widget", "string")
718
                    })
719
                    break;
297✔
720
                case "Flyout":
721
                    items.push({
17✔
722
                        Function: "Flyout",
723
                        Label: getter(i, "Label", "string"),
724
                        Tooltip: getter(i, "Tooltip", "string"),
725
                        ImageUrl: getter(i, "ImageUrl", "string"),
726
                        ImageClass: getter(i, "ImageClass", "string"),
727
                        Item: deArrayifyContainerItems(i.Item || [])
23✔
728
                    })
729
                    break;
17✔
730
            }
731
        }
732
    }
733
    return items;
45✔
734
}
735

736
function deArrayifyContainer(json: any[]): ContainerDefinition[] {
737
    const containers = [] as ContainerDefinition[];
4✔
738
    const getter = buildPropertyGetter<ContainerDefinition>();
4✔
739
    for (const c of json) {
4✔
740
        containers.push({
28✔
741
            Name: getter(c, "Name", "string"),
742
            Type: getter(c, "Type", "string"),
743
            //Position: getter(c, "Position", "string"),
744
            Extension: deArrayifyExtension(c.Extension),
745
            Item: deArrayifyContainerItems(c.Item)
746
        });
747
    }
748
    return containers;
4✔
749
}
750

751
function deArrayifyWidgets(json: any[]): Widget[] {
752
    const widgets = [] as Widget[];
4✔
753
    for (const w of json) {
4✔
754
        if (w["@xsi:type"] == "UiWidgetType") {
281✔
755
            const uiw = deArrayifyUiWidget(w);
231✔
756
            widgets.push(uiw);
231✔
757
        } else {
758
            widgets.push(deArrayifyWidget(w));
50✔
759
        }
760
    }
761
    return widgets;
4✔
762
}
763

764
function deArrayifyWidget(json: any): Widget {
765
    const root = json;
50✔
766
    if (root == null) {
50!
767
        throw new MgError("Malformed input. Expected Widget element");
×
768
    }
769
    const getter = buildPropertyGetter<Widget & { "@xsi:type": string }>();
50✔
770
    const w: Widget = {
50✔
771
        WidgetType: getter(root, "@xsi:type", "string"),
772
        Name: getter(root, "Name", "string"),
773
        Type: getter(root, "Type", "string"),
774
        //Location: getter(root, "Location", "string"),
775
        Extension: deArrayifyExtension(root.Extension)
776
    };
777
    return w;
50✔
778
}
779

780
function deArrayifyExtension(json: any, arrayCheck: boolean = true): any {
393✔
781
    const root = json;
393✔
782
    if (root == null) {
393✔
783
        return null;
116✔
784
    }
785
    if (arrayCheck && root.length != 1) {
277!
786
        throw new MgError("Malformed input. Expected Extension element");
×
787
    }
788
    const getter = buildPropertyGetter<{ Key: string, Value: string, [key: string]: string}>();
277✔
789
    const ext: any = {};
277✔
790
    for (const key in root[0]) {
277✔
791
        if (Array.isArray(root[0][key])) {
741✔
792
            //Special case handling
793
            switch (key) {
695!
794
                case "AdditionalParameter":
795
                    {
796
                        const params = [];
×
797
                        for (const p of root[0][key]) {
×
798
                            params.push({
×
799
                                Key: getter(p, "Key", "string"),
800
                                Value: getter(p, "Value", "string")
801
                            });
802
                        }
803
                        ext[key] = params;
×
804
                    }
805
                    break;
×
806
                case "Projection":
807
                    {
808
                        ext[key] = root[0][key];
3✔
809
                    }
810
                    break;
3✔
811
                default:
812
                    ext[key] = getter(root[0], key, "string");
692✔
813
                    break;
692✔
814
            }
815
        } else {
816
            ext[key] = deArrayifyExtension(root[0][key], false);
46✔
817
        }
818
    }
819
    return ext;
277✔
820
}
821

822
function deArrayifyUiWidget(json: any): UIWidget {
823
    const root = json;
231✔
824
    if (root == null) {
231!
825
        throw new MgError("Malformed input. Expected Widget element");
×
826
    }
827
    const getter = buildPropertyGetter<UIWidget & { "@xsi:type": string }>();
231✔
828
    const w: UIWidget = {
231✔
829
        WidgetType: getter(root, "@xsi:type", "string"),
830
        ImageUrl: getter(root, "ImageUrl", "string"),
831
        ImageClass: getter(root, "ImageClass", "string"),
832
        Label: getter(root, "Label", "string"),
833
        Tooltip: getter(root, "Tooltip", "string"),
834
        StatusText: getter(root, "StatusText", "string"),
835
        Disabled: getter(root, "Disabled", "boolean"),
836
        Name: getter(root, "Name", "string"),
837
        Type: getter(root, "Type", "string"),
838
        //Location: getter(root, "Location", "string"),
839
        Extension: deArrayifyExtension(root.Extension)
840
    };
841
    return w;
231✔
842
}
843

844
function deArrayifyMapWidget(json: any): MapWidget {
845
    const root = json;
4✔
846
    if (root == null || root.length != 1) {
4!
847
        throw new MgError("Malformed input. Expected MapWidget element");
×
848
    }
849
    const getter = buildPropertyGetter<MapWidget & { "@xsi:type": string }>();
4✔
850
    const mw: MapWidget = {
4✔
851
        WidgetType: getter(root, "@xsi:type", "string"),
852
        MapId: getter(root, "MapId", "string"),
853
        Name: getter(root, "Name", "string"),
854
        Type: getter(root, "Type", "string"),
855
        //Location: getter(root, "Location", "string"),
856
        Extension: deArrayifyExtension(root.Extension)
857
    };
858
    return mw;
4✔
859
}
860

861
function deArrayifyWidgetSet(json: any): WidgetSet[] {
862
    const widgetSet = [] as WidgetSet[];
5✔
863
    for (const ws of json) {
5✔
864
        widgetSet.push({
4✔
865
            Container: deArrayifyContainer(ws.Container),
866
            MapWidget: deArrayifyMapWidget(ws.MapWidget),
867
            Widget: deArrayifyWidgets(ws.Widget)
868
        })
869
    }
870
    return widgetSet;
5✔
871
}
872

873
function deArrayifyFlexibleLayout(json: any): ApplicationDefinition {
874
    const root = json;
5✔
875
    const getter = buildPropertyGetter<ApplicationDefinition>();
5✔
876
    const resp = {
5✔
877
        Title: getter(root, "Title"),
878
        TemplateUrl: getter(root, "TemplateUrl"),
879
        MapSet: deArrayifyMapSet(root.MapSet),
880
        WidgetSet: deArrayifyWidgetSet(root.WidgetSet),
881
        Extension: deArrayifyExtension(root.Extension)
882
    };
883
    return resp;
5✔
884
}
885

886
function deArrayifyMapDefinitionGroups(json: any): MapDefinitionLayerGroup[] {
887
    const groups = [] as MapDefinitionLayerGroup[];
4✔
888
    const getter = buildPropertyGetter<MapDefinitionLayerGroup>();
4✔
889
    for (const g of json) {
4✔
890
        groups.push({
16✔
891
            Name: getter(g, "Name"),
892
            ExpandInLegend: getter(g, "ExpandInLegend", "boolean"),
893
            ShowInLegend: getter(g, "ShowInLegend", "boolean"),
894
            Visible: getter(g, "Visible", "boolean"),
895
            LegendLabel: getter(g, "LegendLabel"),
896
            Group: getter(g, "Group")
897
        });
898
    }
899
    return groups;
4✔
900
}
901

902
function deArrayifyMapDefinitionLayers(json: any): MdfLayer[] {
903
    const layers = [] as MdfLayer[];
4✔
904
    const getter = buildPropertyGetter<MdfLayer>();
4✔
905
    for (const g of json) {
4✔
906
        layers.push({
50✔
907
            Name: getter(g, "Name"),
908
            ResourceId: getter(g, "ResourceId"),
909
            ExpandInLegend: getter(g, "ExpandInLegend", "boolean"),
910
            ShowInLegend: getter(g, "ShowInLegend", "boolean"),
911
            Selectable: getter(g, "Selectable", "boolean"),
912
            Visible: getter(g, "Visible", "boolean"),
913
            LegendLabel: getter(g, "LegendLabel"),
914
            Group: getter(g, "Group"),
915
        });
916
    }
917
    return layers;
4✔
918
}
919

920
function deArrayifyMapDefinition(json: any): MapDefinition {
921
    const root = json;
4✔
922
    const getter = buildPropertyGetter<MapDefinition>();
4✔
923
    const eGetter = buildPropertyGetter<MapDefinition["Extents"]>();
4✔
924
    const resp: MapDefinition = {
4✔
925
        BackgroundColor: getter(root, "BackgroundColor"),
926
        CoordinateSystem: getter(root, "CoordinateSystem"),
927
        Extents: {
928
            MinX: eGetter(root.Extents[0], "MinX", "float"),
929
            MinY: eGetter(root.Extents[0], "MinY", "float"),
930
            MaxX: eGetter(root.Extents[0], "MaxX", "float"),
931
            MaxY: eGetter(root.Extents[0], "MaxY", "float")
932
        },
933
        MapLayer: deArrayifyMapDefinitionLayers(root.MapLayer ?? []),
4!
934
        MapLayerGroup: deArrayifyMapDefinitionGroups(root.MapLayerGroup ?? [])
5✔
935
    };
936
    if (root.TileSetSource) {
4!
937
        const tGetter = buildPropertyGetter<TileSetSource>();
×
938
        resp.TileSetSource = {
×
939
            ResourceId: tGetter(root.TileSetSource, "ResourceId")
940
        };
941
    }
942
    return resp;
4✔
943
}
944

945
function deArrayifyTileSetDefinitionLayers(json: any): BaseMapLayer[] {
946
    const getter = buildPropertyGetter<BaseMapLayer>();
1✔
947
    const layers = [] as BaseMapLayer[];
1✔
948
    for (const l of json) {
1✔
949
        layers.push({
7✔
950
            Name: getter(l, "Name"),
951
            ResourceId: getter(l, "ResourceId"),
952
            Selectable: getter(l, "Selectable", "boolean"),
953
            ShowInLegend: getter(l, "ShowInLegend", "boolean"),
954
            LegendLabel: getter(l, "LegendLabel"),
955
            ExpandInLegend: getter(l, "ExpandInLegend", "boolean")
956
        })
957
    }
958
    return layers;
1✔
959
}
960

961
function deArrayifyTileSetDefinitionGroups(json: any): BaseMapLayerGroup[] {
962
    const getter = buildPropertyGetter<BaseMapLayerGroup>();
1✔
963
    const groups = []  as BaseMapLayerGroup[];
1✔
964
    for (const g of json) {
1✔
965
        groups.push({
1✔
966
            Name: getter(g, "Name"),
967
            Visible: getter(g, "Visible", "boolean"),
968
            ShowInLegend: getter(g, "ShowInLegend", "boolean"),
969
            ExpandInLegend: getter(g, "ExpandInLegend", "boolean"),
970
            LegendLabel: getter(g, "LegendLabel"),
971
            BaseMapLayer: deArrayifyTileSetDefinitionLayers(g.BaseMapLayer)
972
        });
973
    }
974
    return groups;
1✔
975
}
976

977
function deArrayifyTileSetDefinitionParamList(root: any): { Name: string, Value: string }[] {
978
    const getter = buildPropertyGetter<{ Name: string, Value: string }>();
1✔
979
    const params = [] as { Name: string, Value: string }[];
1✔
980
    for (const p of root) {
1✔
981
        params.push({
2✔
982
            Name: getter(p, "Name"),
983
            Value: getter(p, "Value")
984
        });
985
    }
986
    return params;
1✔
987
}
988

989
function deArrayifyTileSetDefinitionParams(root: any): TileStoreParameters {
990
    const getter = buildPropertyGetter<TileStoreParameters>();
1✔
991
    const tsp: TileStoreParameters = {
1✔
992
        TileProvider: getter(root, "TileProvider"),
993
        Parameter: deArrayifyTileSetDefinitionParamList(root[0].Parameter)
994
    };
995
    return tsp;
1✔
996
}
997

998
function deArrayifyTileSetDefinition(json: any): TileSetDefinition {
999
    const root = json;
1✔
1000
    const eGetter = buildPropertyGetter<TileSetDefinition["Extents"]>();
1✔
1001
    const resp: TileSetDefinition = {
1✔
1002
        Extents: {
1003
            MinX: eGetter(root.Extents[0], "MinX", "float"),
1004
            MinY: eGetter(root.Extents[0], "MinY", "float"),
1005
            MaxX: eGetter(root.Extents[0], "MaxX", "float"),
1006
            MaxY: eGetter(root.Extents[0], "MaxY", "float")
1007
        },
1008
        TileStoreParameters: deArrayifyTileSetDefinitionParams(json.TileStoreParameters),
1009
        BaseMapLayerGroup: deArrayifyTileSetDefinitionGroups(json.BaseMapLayerGroup)
1010
    };
1011
    return resp;
1✔
1012
}
1013

1014
/**
1015
 * Indicates if the de-arrayified result is a {@link WebLayout}
1016
 * 
1017
 * @since 0.14
1018
 */
1019
export function isWebLayout(arg: DeArrayifiedResult): arg is WebLayout {
1020
    return (arg as any).CommandSet != null
1✔
1021
        && (arg as any).ContextMenu != null
1022
        && (arg as any).Map != null
1023
}
1024

1025
/**
1026
 * Indicates if the de-arrayified result is an {@link ApplicationDefinition}
1027
 * 
1028
 * @since 0.14
1029
 */
1030
export function isAppDef(arg: DeArrayifiedResult): arg is ApplicationDefinition {
1031
    return (arg as any).WidgetSet != null;
7✔
1032
}
1033

1034
/**
1035
 * Indicates if the de-arrayified result is a {@link MapDefinition}
1036
 * 
1037
 * @since 0.14
1038
 */
1039
export function isMapDef(arg: DeArrayifiedResult): arg is MapDefinition {
1040
    return (arg as any).Extents != null
4✔
1041
        && (arg as any).BackgroundColor != null
1042
        && (arg as any).CoordinateSystem != null
1043
        && (arg as any).MapLayer != null
1044
        && (arg as any).MapLayerGroup != null;
1045
}
1046

1047
/**
1048
 * Indicates if the de-arrayified result is a {@link TileSetDefinition}
1049
 * 
1050
 * @since 0.14
1051
 */
1052
export function isTileSet(arg: DeArrayifiedResult): arg is TileSetDefinition {
1053
    return (arg as any).Extents != null
1✔
1054
        && (arg as any).TileStoreParameters != null
1055
        && (arg as any).BaseMapLayerGroup != null;
1056
}
1057

1058
/**
1059
 * Indicates if the de-arrayified result is a {@link SiteVersionResponse}
1060
 * 
1061
 * @since 0.14
1062
 */
1063
export function isSiteVersion(arg: DeArrayifiedResult): arg is SiteVersionResponse {
1064
    return (arg as any).Version != null;
×
1065
}
1066

1067
/**
1068
 * Indicates if the de-arrayified result is a {@link QueryMapFeaturesResponse}
1069
 * 
1070
 * @since 0.14
1071
 */
1072
export function isQueryMapFeaturesResponse(arg: DeArrayifiedResult): arg is QueryMapFeaturesResponse {
1073
    return (arg as any).FeatureSet != null
2✔
1074
        || (arg as any).Hyperlink != null
1075
        || (arg as any).InlineSelectionImage != null
1076
        || (arg as any).SelectedFeatures != null
1077
        || (arg as any).Tooltip != null;
1078
}
1079

1080
/**
1081
 * The result of the normalization of JSON from the mapagent
1082
 * 
1083
 * @since 0.14
1084
 */
1085
export type DeArrayifiedResult = RuntimeMap | QueryMapFeaturesResponse | WebLayout | ApplicationDefinition | MapDefinition | TileSetDefinition | SiteVersionResponse;
1086

1087
/**
1088
 * Normalizes the given JSON object to match the content model of its original XML form
1089
 *
1090
 * @param {*} json The JSON object to normalize
1091
 * @returns {*} The normalized JSON object
1092
 */
1093
export function deArrayify(json: any): DeArrayifiedResult {
1094
    if (json["RuntimeMap"]) {
21✔
1095
        return deArrayifyRuntimeMap(json.RuntimeMap);
3✔
1096
    }
1097
    if (json["FeatureInformation"]) {
18✔
1098
        return deArrayifyFeatureInformation(json.FeatureInformation);
2✔
1099
    }
1100
    if (json["WebLayout"]) {
16✔
1101
        return deArrayifyWebLayout(json.WebLayout);
2✔
1102
    }
1103
    if (json["ApplicationDefinition"]) {
14✔
1104
        return deArrayifyFlexibleLayout(json.ApplicationDefinition);
5✔
1105
    }
1106
    if (json["MapDefinition"]) {
9✔
1107
        return deArrayifyMapDefinition(json.MapDefinition);
4✔
1108
    }
1109
    if (json["TileSetDefinition"]) {
5✔
1110
        return deArrayifyTileSetDefinition(json.TileSetDefinition);
1✔
1111
    }
1112
    if (json["SiteVersion"]) {
4!
1113
        return {
4✔
1114
            Version: json.SiteVersion.Version[0]
1115
        } as SiteVersionResponse;
1116
    }
1117
    const keys = [] as string[];
×
1118
    for (const k in json) {
×
1119
        keys.push(k);
×
1120
    }
1121
    throw new MgError(`Unsure how to process JSON response. Root elements are: (${keys.join(", ")})`);
×
1122
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc