@backstage/plugin-config-schema 0.1.34 → 0.1.35-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,571 +0,0 @@
1
- import React, { createContext, useContext, useRef, useEffect, useMemo } from 'react';
2
- import useObservable from 'react-use/lib/useObservable';
3
- import { configSchemaApiRef } from '../index.esm.js';
4
- import 'zen-observable';
5
- import '@backstage/errors';
6
- import { makeStyles, Chip, Box, Divider, Typography, Paper, Table, TableBody, TableRow, TableCell, withStyles, createStyles, alpha } from '@material-ui/core';
7
- import ChevronRightIcon from '@material-ui/icons/ChevronRight';
8
- import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
9
- import { TreeItem, TreeView } from '@material-ui/lab';
10
- import { Page, Header, Content, Progress } from '@backstage/core-components';
11
- import { useApi } from '@backstage/core-plugin-api';
12
-
13
- class ScrollTargetsForwarder {
14
- constructor() {
15
- this.listeners = /* @__PURE__ */ new Map();
16
- }
17
- setScrollListener(id, listener) {
18
- this.listeners.set(id, listener);
19
- return () => {
20
- if (this.listeners.get(id) === listener) {
21
- this.listeners.delete(id);
22
- }
23
- };
24
- }
25
- scrollTo(id) {
26
- var _a;
27
- (_a = this.listeners.get(id)) == null ? void 0 : _a();
28
- }
29
- }
30
- const ScrollTargetsContext = createContext(
31
- void 0
32
- );
33
- function ScrollTargetsProvider({ children }) {
34
- return /* @__PURE__ */ React.createElement(ScrollTargetsContext.Provider, {
35
- value: new ScrollTargetsForwarder(),
36
- children
37
- });
38
- }
39
- function useScrollTargets() {
40
- return useContext(ScrollTargetsContext);
41
- }
42
-
43
- function titleVariant(depth) {
44
- if (depth <= 1) {
45
- return "h2";
46
- } else if (depth === 2) {
47
- return "h3";
48
- } else if (depth === 3) {
49
- return "h4";
50
- } else if (depth === 4) {
51
- return "h5";
52
- }
53
- return "h6";
54
- }
55
- const useChildViewStyles = makeStyles((theme) => ({
56
- title: {
57
- marginBottom: 0
58
- },
59
- chip: {
60
- marginLeft: theme.spacing(1),
61
- marginRight: 0,
62
- marginBottom: 0
63
- }
64
- }));
65
- function ChildView({
66
- path,
67
- depth,
68
- schema,
69
- required,
70
- lastChild
71
- }) {
72
- const classes = useChildViewStyles();
73
- const titleRef = useRef(null);
74
- const scroll = useScrollTargets();
75
- useEffect(() => {
76
- return scroll == null ? void 0 : scroll.setScrollListener(path, () => {
77
- var _a;
78
- (_a = titleRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
79
- });
80
- }, [scroll, path]);
81
- const chips = new Array();
82
- const chipProps = { size: "small", classes: { root: classes.chip } };
83
- if (required) {
84
- chips.push(
85
- /* @__PURE__ */ React.createElement(Chip, {
86
- label: "required",
87
- color: "default",
88
- key: "required",
89
- ...chipProps
90
- })
91
- );
92
- }
93
- const visibility = schema == null ? void 0 : schema.visibility;
94
- if (visibility === "frontend") {
95
- chips.push(
96
- /* @__PURE__ */ React.createElement(Chip, {
97
- label: "frontend",
98
- color: "primary",
99
- key: "visibility",
100
- ...chipProps
101
- })
102
- );
103
- } else if (visibility === "secret") {
104
- chips.push(
105
- /* @__PURE__ */ React.createElement(Chip, {
106
- label: "secret",
107
- color: "secondary",
108
- key: "visibility",
109
- ...chipProps
110
- })
111
- );
112
- }
113
- return /* @__PURE__ */ React.createElement(Box, {
114
- paddingBottom: lastChild ? 4 : 8,
115
- display: "flex",
116
- flexDirection: "row"
117
- }, /* @__PURE__ */ React.createElement(Divider, {
118
- orientation: "vertical",
119
- flexItem: true
120
- }), /* @__PURE__ */ React.createElement(Box, {
121
- paddingLeft: 2,
122
- flex: 1
123
- }, /* @__PURE__ */ React.createElement(Box, {
124
- display: "flex",
125
- flexDirection: "row",
126
- marginBottom: 2,
127
- alignItems: "center"
128
- }, /* @__PURE__ */ React.createElement(Typography, {
129
- ref: titleRef,
130
- variant: titleVariant(depth),
131
- classes: { root: classes.title }
132
- }, path), chips.length > 0 && /* @__PURE__ */ React.createElement(Box, {
133
- marginLeft: 1
134
- }), chips), schema && /* @__PURE__ */ React.createElement(SchemaView, {
135
- path,
136
- depth,
137
- schema
138
- })));
139
- }
140
-
141
- function MetadataViewRow({ label, text, data }) {
142
- if (text === void 0 && data === void 0) {
143
- return null;
144
- }
145
- return /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, {
146
- style: { width: 160 }
147
- }, /* @__PURE__ */ React.createElement(Typography, {
148
- variant: "body1",
149
- noWrap: true,
150
- style: { fontWeight: 900 }
151
- }, label)), /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(Typography, {
152
- variant: "body1"
153
- }, data ? JSON.stringify(data) : text)));
154
- }
155
- function MetadataView({ schema }) {
156
- return /* @__PURE__ */ React.createElement(Paper, {
157
- variant: "outlined",
158
- square: true,
159
- style: { width: "100%" }
160
- }, /* @__PURE__ */ React.createElement(Table, {
161
- size: "small"
162
- }, /* @__PURE__ */ React.createElement(TableBody, null, /* @__PURE__ */ React.createElement(MetadataViewRow, {
163
- label: "Type",
164
- data: schema.type
165
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
166
- label: "Allowed values",
167
- data: schema.enum
168
- }), schema.additionalProperties === true && /* @__PURE__ */ React.createElement(MetadataViewRow, {
169
- label: "Additional Properties",
170
- text: "true"
171
- }), schema.additionalItems === true && /* @__PURE__ */ React.createElement(MetadataViewRow, {
172
- label: "Additional Items",
173
- text: "true"
174
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
175
- label: "Format",
176
- text: schema.format
177
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
178
- label: "Pattern",
179
- text: schema.pattern && String(schema.pattern)
180
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
181
- label: "Minimum",
182
- data: schema.minimum
183
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
184
- label: "Maximum",
185
- data: schema.maximum
186
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
187
- label: "Exclusive minimum",
188
- data: schema.exclusiveMinimum
189
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
190
- label: "Exclusive maximum",
191
- data: schema.exclusiveMaximum
192
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
193
- label: "Multiple of",
194
- data: schema.multipleOf
195
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
196
- label: "Maximum number of items",
197
- data: schema.maxItems
198
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
199
- label: "Minimum number of items",
200
- data: schema.minItems
201
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
202
- label: "Maximum number of properties",
203
- data: schema.maxProperties
204
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
205
- label: "Minimum number of properties",
206
- data: schema.minProperties
207
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
208
- label: "Maximum Length",
209
- data: schema.maxLength
210
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
211
- label: "Minimum Length",
212
- data: schema.minLength
213
- }), /* @__PURE__ */ React.createElement(MetadataViewRow, {
214
- label: "Items must be unique",
215
- data: schema.uniqueItems
216
- }))));
217
- }
218
-
219
- function ArrayView({ path, depth, schema }) {
220
- const itemDepth = depth + 1;
221
- const itemPath = path ? `${path}[]` : "[]";
222
- const itemSchema = schema.items;
223
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, {
224
- marginBottom: 4
225
- }, schema.description && /* @__PURE__ */ React.createElement(Box, {
226
- marginBottom: 4
227
- }, /* @__PURE__ */ React.createElement(Typography, {
228
- variant: "body1"
229
- }, schema.description)), /* @__PURE__ */ React.createElement(MetadataView, {
230
- schema
231
- })), /* @__PURE__ */ React.createElement(Typography, {
232
- variant: "overline"
233
- }, "Items"), /* @__PURE__ */ React.createElement(ChildView, {
234
- lastChild: true,
235
- path: itemPath,
236
- depth: itemDepth,
237
- schema: itemSchema
238
- }), schema.additionalItems && schema.additionalItems !== true && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Typography, {
239
- variant: "overline"
240
- }, "Additional Items"), /* @__PURE__ */ React.createElement(ChildView, {
241
- path: itemPath,
242
- depth: itemDepth,
243
- schema: schema.additionalItems,
244
- lastChild: true
245
- })));
246
- }
247
-
248
- function MatchView({
249
- path,
250
- depth,
251
- schema,
252
- label
253
- }) {
254
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Typography, {
255
- variant: "overline"
256
- }, label), schema.map((optionSchema, index) => /* @__PURE__ */ React.createElement(ChildView, {
257
- key: index,
258
- path: `${path}/${index + 1}`,
259
- depth: depth + 1,
260
- schema: optionSchema,
261
- lastChild: index === schema.length - 1
262
- })));
263
- }
264
-
265
- function isRequired(name, required) {
266
- if (required === true) {
267
- return true;
268
- }
269
- if (Array.isArray(required)) {
270
- return required.includes(name);
271
- }
272
- return false;
273
- }
274
- function ObjectView({ path, depth, schema }) {
275
- var _a, _b;
276
- const properties = Object.entries((_a = schema.properties) != null ? _a : {});
277
- const patternProperties = Object.entries((_b = schema.patternProperties) != null ? _b : {});
278
- return /* @__PURE__ */ React.createElement(React.Fragment, null, depth > 0 && /* @__PURE__ */ React.createElement(Box, {
279
- marginBottom: 4
280
- }, schema.description && /* @__PURE__ */ React.createElement(Box, {
281
- marginBottom: 4
282
- }, /* @__PURE__ */ React.createElement(Typography, {
283
- variant: "body1"
284
- }, schema.description)), /* @__PURE__ */ React.createElement(MetadataView, {
285
- schema
286
- })), properties.length > 0 && /* @__PURE__ */ React.createElement(React.Fragment, null, depth > 0 && /* @__PURE__ */ React.createElement(Typography, {
287
- variant: "overline"
288
- }, "Properties"), properties.map(([name, propSchema], index) => /* @__PURE__ */ React.createElement(ChildView, {
289
- key: name,
290
- path: path ? `${path}.${name}` : name,
291
- depth: depth + 1,
292
- schema: propSchema,
293
- lastChild: index === properties.length - 1,
294
- required: isRequired(name, schema.required)
295
- }))), patternProperties.length > 0 && /* @__PURE__ */ React.createElement(React.Fragment, null, depth > 0 && /* @__PURE__ */ React.createElement(Typography, {
296
- variant: "overline"
297
- }, "Pattern Properties"), patternProperties.map(([name, propSchema], index) => /* @__PURE__ */ React.createElement(ChildView, {
298
- key: name,
299
- path: path ? `${path}.<${name}>` : name,
300
- depth: depth + 1,
301
- schema: propSchema,
302
- lastChild: index === patternProperties.length - 1,
303
- required: isRequired(name, schema.required)
304
- }))), schema.additionalProperties && schema.additionalProperties !== true && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Typography, {
305
- variant: "overline"
306
- }, "Additional Properties"), /* @__PURE__ */ React.createElement(ChildView, {
307
- path: `${path}.*`,
308
- depth: depth + 1,
309
- schema: schema.additionalProperties,
310
- lastChild: true
311
- })));
312
- }
313
-
314
- function ScalarView({ schema }) {
315
- return /* @__PURE__ */ React.createElement(React.Fragment, null, schema.description && /* @__PURE__ */ React.createElement(Box, {
316
- marginBottom: 4
317
- }, /* @__PURE__ */ React.createElement(Typography, {
318
- variant: "body1"
319
- }, schema.description)), /* @__PURE__ */ React.createElement(MetadataView, {
320
- schema
321
- }));
322
- }
323
-
324
- function SchemaView(props) {
325
- const { schema } = props;
326
- if (schema.anyOf) {
327
- return /* @__PURE__ */ React.createElement(MatchView, {
328
- ...props,
329
- schema: schema.anyOf,
330
- label: "Any of the following"
331
- });
332
- }
333
- if (schema.oneOf) {
334
- return /* @__PURE__ */ React.createElement(MatchView, {
335
- ...props,
336
- schema: schema.oneOf,
337
- label: "One of the following"
338
- });
339
- }
340
- if (schema.allOf) {
341
- return /* @__PURE__ */ React.createElement(MatchView, {
342
- ...props,
343
- schema: schema.allOf,
344
- label: "All of the following"
345
- });
346
- }
347
- switch (schema.type) {
348
- case "array":
349
- return /* @__PURE__ */ React.createElement(ArrayView, {
350
- ...props
351
- });
352
- case "object":
353
- case void 0:
354
- return /* @__PURE__ */ React.createElement(ObjectView, {
355
- ...props
356
- });
357
- default:
358
- return /* @__PURE__ */ React.createElement(ScalarView, {
359
- ...props
360
- });
361
- }
362
- }
363
-
364
- const StyledTreeItem = withStyles(
365
- (theme) => createStyles({
366
- label: {
367
- userSelect: "none"
368
- },
369
- group: {
370
- marginLeft: 7,
371
- paddingLeft: theme.spacing(1),
372
- borderLeft: `1px solid ${alpha(theme.palette.text.primary, 0.15)}`
373
- }
374
- })
375
- )((props) => /* @__PURE__ */ React.createElement(TreeItem, {
376
- ...props
377
- }));
378
- function createSchemaBrowserItems(expanded, schema, path = "", depth = 0) {
379
- let matchArr;
380
- if (schema.anyOf) {
381
- matchArr = schema.anyOf;
382
- } else if (schema.oneOf) {
383
- matchArr = schema.oneOf;
384
- } else if (schema.allOf) {
385
- matchArr = schema.allOf;
386
- }
387
- if (matchArr) {
388
- return matchArr.map((childSchema, index) => {
389
- const childPath = `${path}/${index + 1}`;
390
- if (depth > 0)
391
- expanded.push(childPath);
392
- return /* @__PURE__ */ React.createElement(StyledTreeItem, {
393
- key: childPath,
394
- nodeId: childPath,
395
- label: `<Option ${index + 1}>`
396
- }, createSchemaBrowserItems(
397
- expanded,
398
- childSchema,
399
- childPath,
400
- depth + 1
401
- ));
402
- });
403
- }
404
- switch (schema.type) {
405
- case "array": {
406
- const childPath = `${path}[]`;
407
- if (depth > 0)
408
- expanded.push(childPath);
409
- return /* @__PURE__ */ React.createElement(StyledTreeItem, {
410
- nodeId: childPath,
411
- label: "[]"
412
- }, schema.items && createSchemaBrowserItems(
413
- expanded,
414
- schema.items,
415
- childPath,
416
- depth + 1
417
- ));
418
- }
419
- case "object":
420
- case void 0: {
421
- const children = [];
422
- if (schema.properties) {
423
- children.push(
424
- ...Object.entries(schema.properties).map(([name, childSchema]) => {
425
- const childPath = path ? `${path}.${name}` : name;
426
- if (depth > 0)
427
- expanded.push(childPath);
428
- return /* @__PURE__ */ React.createElement(StyledTreeItem, {
429
- key: childPath,
430
- nodeId: childPath,
431
- label: name
432
- }, createSchemaBrowserItems(
433
- expanded,
434
- childSchema,
435
- childPath,
436
- depth + 1
437
- ));
438
- })
439
- );
440
- }
441
- if (schema.patternProperties) {
442
- children.push(
443
- ...Object.entries(schema.patternProperties).map(
444
- ([name, childSchema]) => {
445
- const childPath = `${path}.<${name}>`;
446
- if (depth > 0)
447
- expanded.push(childPath);
448
- return /* @__PURE__ */ React.createElement(StyledTreeItem, {
449
- key: childPath,
450
- nodeId: childPath,
451
- label: `<${name}>`
452
- }, createSchemaBrowserItems(
453
- expanded,
454
- childSchema,
455
- childPath,
456
- depth + 1
457
- ));
458
- }
459
- )
460
- );
461
- }
462
- if (schema.additionalProperties && schema.additionalProperties !== true) {
463
- const childPath = `${path}.*`;
464
- if (depth > 0)
465
- expanded.push(childPath);
466
- children.push(
467
- /* @__PURE__ */ React.createElement(StyledTreeItem, {
468
- key: childPath,
469
- nodeId: childPath,
470
- label: "*"
471
- }, createSchemaBrowserItems(
472
- expanded,
473
- schema.additionalProperties,
474
- childPath,
475
- depth + 1
476
- ))
477
- );
478
- }
479
- return /* @__PURE__ */ React.createElement(React.Fragment, null, children);
480
- }
481
- default:
482
- return null;
483
- }
484
- }
485
- function SchemaBrowser({ schema }) {
486
- const scroll = useScrollTargets();
487
- const expandedRef = useRef([]);
488
- const data = useMemo(() => {
489
- const expanded = new Array();
490
- const items = createSchemaBrowserItems(expanded, schema);
491
- return { items, expanded };
492
- }, [schema]);
493
- if (!scroll) {
494
- throw new Error("No scroll handler available");
495
- }
496
- const handleToggle = (_event, expanded) => {
497
- expandedRef.current = expanded;
498
- };
499
- const handleSelect = (_event, nodeId) => {
500
- if (expandedRef.current.includes(nodeId)) {
501
- scroll.scrollTo(nodeId);
502
- }
503
- };
504
- return /* @__PURE__ */ React.createElement(TreeView, {
505
- defaultExpanded: data.expanded,
506
- defaultCollapseIcon: /* @__PURE__ */ React.createElement(ExpandMoreIcon, null),
507
- defaultExpandIcon: /* @__PURE__ */ React.createElement(ChevronRightIcon, null),
508
- onNodeToggle: handleToggle,
509
- onNodeSelect: handleSelect
510
- }, data.items);
511
- }
512
-
513
- const SchemaViewer = ({ schema }) => {
514
- return /* @__PURE__ */ React.createElement(Box, {
515
- flex: "1",
516
- position: "relative"
517
- }, /* @__PURE__ */ React.createElement(Box, {
518
- clone: true,
519
- position: "absolute",
520
- display: "flex",
521
- flexDirection: "row",
522
- flexWrap: "nowrap",
523
- maxHeight: "100%"
524
- }, /* @__PURE__ */ React.createElement(Paper, {
525
- elevation: 3
526
- }, /* @__PURE__ */ React.createElement(ScrollTargetsProvider, null, /* @__PURE__ */ React.createElement(Box, {
527
- padding: 1,
528
- overflow: "auto",
529
- width: 300
530
- }, /* @__PURE__ */ React.createElement(SchemaBrowser, {
531
- schema
532
- })), /* @__PURE__ */ React.createElement(Box, {
533
- flex: "1",
534
- overflow: "auto"
535
- }, /* @__PURE__ */ React.createElement(SchemaView, {
536
- schema,
537
- path: "",
538
- depth: 0
539
- }))))));
540
- };
541
-
542
- const ConfigSchemaPage = () => {
543
- const configSchemaApi = useApi(configSchemaApiRef);
544
- const schemaResult = useObservable(
545
- useMemo(() => configSchemaApi.schema$(), [configSchemaApi])
546
- );
547
- let content;
548
- if (schemaResult) {
549
- if (schemaResult.schema) {
550
- content = /* @__PURE__ */ React.createElement(SchemaViewer, {
551
- schema: schemaResult.schema
552
- });
553
- } else {
554
- content = /* @__PURE__ */ React.createElement(Typography, {
555
- variant: "h4"
556
- }, "No configuration schema available");
557
- }
558
- } else {
559
- content = /* @__PURE__ */ React.createElement(Progress, null);
560
- }
561
- return /* @__PURE__ */ React.createElement(Page, {
562
- themeId: "tool"
563
- }, /* @__PURE__ */ React.createElement(Header, {
564
- title: "Configuration Reference"
565
- }), /* @__PURE__ */ React.createElement(Content, {
566
- stretch: true
567
- }, content));
568
- };
569
-
570
- export { ConfigSchemaPage };
571
- //# sourceMappingURL=index-8fca4f13.esm.js.map