1 | "use strict";
|
---|
2 | /**
|
---|
3 | * @license
|
---|
4 | * Copyright Google LLC All Rights Reserved.
|
---|
5 | *
|
---|
6 | * Use of this source code is governed by an MIT-style license that can be
|
---|
7 | * found in the LICENSE file at https://angular.io/license
|
---|
8 | */
|
---|
9 | Object.defineProperty(exports, "__esModule", { value: true });
|
---|
10 | exports.visitJsonSchema = exports.visitJson = void 0;
|
---|
11 | const rxjs_1 = require("rxjs");
|
---|
12 | const operators_1 = require("rxjs/operators");
|
---|
13 | const pointer_1 = require("./pointer");
|
---|
14 | function _getObjectSubSchema(schema, key) {
|
---|
15 | if (typeof schema !== 'object' || schema === null) {
|
---|
16 | return undefined;
|
---|
17 | }
|
---|
18 | // Is it an object schema?
|
---|
19 | if (typeof schema.properties == 'object' || schema.type == 'object') {
|
---|
20 | if (typeof schema.properties == 'object' &&
|
---|
21 | typeof schema.properties[key] == 'object') {
|
---|
22 | return schema.properties[key];
|
---|
23 | }
|
---|
24 | if (typeof schema.additionalProperties == 'object') {
|
---|
25 | return schema.additionalProperties;
|
---|
26 | }
|
---|
27 | return undefined;
|
---|
28 | }
|
---|
29 | // Is it an array schema?
|
---|
30 | if (typeof schema.items == 'object' || schema.type == 'array') {
|
---|
31 | return typeof schema.items == 'object' ? schema.items : undefined;
|
---|
32 | }
|
---|
33 | return undefined;
|
---|
34 | }
|
---|
35 | function _visitJsonRecursive(json, visitor, ptr, schema, refResolver, context, root) {
|
---|
36 | if (schema === true || schema === false) {
|
---|
37 | // There's no schema definition, so just visit the JSON recursively.
|
---|
38 | schema = undefined;
|
---|
39 | }
|
---|
40 | // eslint-disable-next-line no-prototype-builtins
|
---|
41 | if (schema && schema.hasOwnProperty('$ref') && typeof schema['$ref'] == 'string') {
|
---|
42 | if (refResolver) {
|
---|
43 | const resolved = refResolver(schema['$ref'], context);
|
---|
44 | schema = resolved.schema;
|
---|
45 | context = resolved.context;
|
---|
46 | }
|
---|
47 | }
|
---|
48 | const value = visitor(json, ptr, schema, root);
|
---|
49 | return (rxjs_1.isObservable(value) ? value : rxjs_1.of(value)).pipe(operators_1.concatMap((value) => {
|
---|
50 | if (Array.isArray(value)) {
|
---|
51 | return rxjs_1.concat(rxjs_1.from(value).pipe(operators_1.mergeMap((item, i) => {
|
---|
52 | return _visitJsonRecursive(item, visitor, pointer_1.joinJsonPointer(ptr, '' + i), _getObjectSubSchema(schema, '' + i), refResolver, context, root || value).pipe(operators_1.tap((x) => (value[i] = x)));
|
---|
53 | }), operators_1.ignoreElements()), rxjs_1.of(value));
|
---|
54 | }
|
---|
55 | else if (typeof value == 'object' && value !== null) {
|
---|
56 | return rxjs_1.concat(rxjs_1.from(Object.getOwnPropertyNames(value)).pipe(operators_1.mergeMap((key) => {
|
---|
57 | return _visitJsonRecursive(value[key], visitor, pointer_1.joinJsonPointer(ptr, key), _getObjectSubSchema(schema, key), refResolver, context, root || value).pipe(operators_1.tap((x) => {
|
---|
58 | const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
---|
59 | if (descriptor && descriptor.writable && value[key] !== x) {
|
---|
60 | value[key] = x;
|
---|
61 | }
|
---|
62 | }));
|
---|
63 | }), operators_1.ignoreElements()), rxjs_1.of(value));
|
---|
64 | }
|
---|
65 | else {
|
---|
66 | return rxjs_1.of(value);
|
---|
67 | }
|
---|
68 | }));
|
---|
69 | }
|
---|
70 | /**
|
---|
71 | * Visit all the properties in a JSON object, allowing to transform them. It supports calling
|
---|
72 | * properties synchronously or asynchronously (through Observables).
|
---|
73 | * The original object can be mutated or replaced entirely. In case where it's replaced, the new
|
---|
74 | * value is returned. When it's mutated though the original object will be changed.
|
---|
75 | *
|
---|
76 | * Please note it is possible to have an infinite loop here (which will result in a stack overflow)
|
---|
77 | * if you return 2 objects that references each others (or the same object all the time).
|
---|
78 | *
|
---|
79 | * @param {JsonValue} json The Json value to visit.
|
---|
80 | * @param {JsonVisitor} visitor A function that will be called on every items.
|
---|
81 | * @param {JsonObject} schema A JSON schema to pass through to the visitor (where possible).
|
---|
82 | * @param refResolver a function to resolve references in the schema.
|
---|
83 | * @returns {Observable< | undefined>} The observable of the new root, if the root changed.
|
---|
84 | */
|
---|
85 | function visitJson(json, visitor, schema, refResolver, context) {
|
---|
86 | return _visitJsonRecursive(json, visitor, pointer_1.buildJsonPointer([]), schema, refResolver, context);
|
---|
87 | }
|
---|
88 | exports.visitJson = visitJson;
|
---|
89 | function visitJsonSchema(schema, visitor) {
|
---|
90 | if (schema === false || schema === true) {
|
---|
91 | // Nothing to visit.
|
---|
92 | return;
|
---|
93 | }
|
---|
94 | const keywords = {
|
---|
95 | additionalItems: true,
|
---|
96 | items: true,
|
---|
97 | contains: true,
|
---|
98 | additionalProperties: true,
|
---|
99 | propertyNames: true,
|
---|
100 | not: true,
|
---|
101 | };
|
---|
102 | const arrayKeywords = {
|
---|
103 | items: true,
|
---|
104 | allOf: true,
|
---|
105 | anyOf: true,
|
---|
106 | oneOf: true,
|
---|
107 | };
|
---|
108 | const propsKeywords = {
|
---|
109 | definitions: true,
|
---|
110 | properties: true,
|
---|
111 | patternProperties: true,
|
---|
112 | additionalProperties: true,
|
---|
113 | dependencies: true,
|
---|
114 | items: true,
|
---|
115 | };
|
---|
116 | function _traverse(schema, jsonPtr, rootSchema, parentSchema, keyIndex) {
|
---|
117 | if (schema && typeof schema == 'object' && !Array.isArray(schema)) {
|
---|
118 | visitor(schema, jsonPtr, parentSchema, keyIndex);
|
---|
119 | for (const key of Object.keys(schema)) {
|
---|
120 | const sch = schema[key];
|
---|
121 | if (key in propsKeywords) {
|
---|
122 | if (sch && typeof sch == 'object') {
|
---|
123 | for (const prop of Object.keys(sch)) {
|
---|
124 | _traverse(sch[prop], pointer_1.joinJsonPointer(jsonPtr, key, prop), rootSchema, schema, prop);
|
---|
125 | }
|
---|
126 | }
|
---|
127 | }
|
---|
128 | else if (key in keywords) {
|
---|
129 | _traverse(sch, pointer_1.joinJsonPointer(jsonPtr, key), rootSchema, schema, key);
|
---|
130 | }
|
---|
131 | else if (key in arrayKeywords) {
|
---|
132 | if (Array.isArray(sch)) {
|
---|
133 | for (let i = 0; i < sch.length; i++) {
|
---|
134 | _traverse(sch[i], pointer_1.joinJsonPointer(jsonPtr, key, '' + i), rootSchema, sch, '' + i);
|
---|
135 | }
|
---|
136 | }
|
---|
137 | }
|
---|
138 | else if (Array.isArray(sch)) {
|
---|
139 | for (let i = 0; i < sch.length; i++) {
|
---|
140 | _traverse(sch[i], pointer_1.joinJsonPointer(jsonPtr, key, '' + i), rootSchema, sch, '' + i);
|
---|
141 | }
|
---|
142 | }
|
---|
143 | }
|
---|
144 | }
|
---|
145 | }
|
---|
146 | _traverse(schema, pointer_1.buildJsonPointer([]), schema);
|
---|
147 | }
|
---|
148 | exports.visitJsonSchema = visitJsonSchema;
|
---|