UNPKG

5.54 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const serializer_1 = require("./serializer");
4const schema_tree_1 = require("./schema-tree");
5const error_1 = require("./error");
6require("./mimetypes");
7class InvalidJsonPath extends error_1.JsonSchemaErrorBase {
8}
9exports.InvalidJsonPath = InvalidJsonPath;
10// The schema tree node property of the SchemaClass.
11const kSchemaNode = Symbol('schema-node');
12// The value property of the SchemaClass.
13const kOriginalRoot = Symbol('schema-value');
14/**
15 * Splits a JSON path string into fragments. Fragments can be used to get the value referenced
16 * by the path. For example, a path of "a[3].foo.bar[2]" would give you a fragment array of
17 * ["a", 3, "foo", "bar", 2].
18 * @param path The JSON string to parse.
19 * @returns {string[]} The fragments for the string.
20 * @private
21 */
22function _parseJsonPath(path) {
23 const fragments = (path || '').split(/\./g);
24 const result = [];
25 while (fragments.length > 0) {
26 const fragment = fragments.shift();
27 const match = fragment.match(/([^\[]+)((\[.*\])*)/);
28 if (!match) {
29 throw new InvalidJsonPath();
30 }
31 result.push(match[1]);
32 if (match[2]) {
33 const indices = match[2].slice(1, -1).split('][');
34 result.push(...indices);
35 }
36 }
37 return result.filter(fragment => !!fragment);
38}
39/** Get a SchemaTreeNode from the JSON path string. */
40function _getSchemaNodeForPath(rootMetaData, path) {
41 let fragments = _parseJsonPath(path);
42 // TODO: make this work with union (oneOf) schemas
43 return fragments.reduce((md, current) => {
44 if (md && md.children) {
45 return md.children[current];
46 }
47 else if (md && md.items) {
48 return md.items[parseInt(current, 10)];
49 }
50 else {
51 return md;
52 }
53 }, rootMetaData);
54}
55class SchemaClassBase {
56 constructor(schema, value, ...fallbacks) {
57 this[kOriginalRoot] = value;
58 const forward = fallbacks.length > 0
59 ? (new SchemaClassBase(schema, fallbacks.pop(), ...fallbacks).$$schema())
60 : null;
61 this[kSchemaNode] = new schema_tree_1.RootSchemaTreeNode(this, {
62 forward,
63 value,
64 schema
65 });
66 }
67 $$root() { return this; }
68 $$schema() { return this[kSchemaNode]; }
69 $$originalRoot() { return this[kOriginalRoot]; }
70 /** Sets the value of a destination if the value is currently undefined. */
71 $$alias(source, destination) {
72 let sourceSchemaTreeNode = _getSchemaNodeForPath(this.$$schema(), source);
73 if (!sourceSchemaTreeNode) {
74 return false;
75 }
76 const fragments = _parseJsonPath(destination);
77 const maybeValue = fragments.reduce((value, current) => {
78 return value && value[current];
79 }, this.$$originalRoot());
80 if (maybeValue !== undefined) {
81 sourceSchemaTreeNode.set(maybeValue);
82 return true;
83 }
84 return false;
85 }
86 /** Destroy all links between schemas to allow for GC. */
87 $$dispose() {
88 this.$$schema().dispose();
89 }
90 /** Get a value from a JSON path. */
91 $$get(path) {
92 const node = _getSchemaNodeForPath(this.$$schema(), path);
93 return node ? node.get() : undefined;
94 }
95 /** Set a value from a JSON path. */
96 $$set(path, value) {
97 const node = _getSchemaNodeForPath(this.$$schema(), path);
98 if (node) {
99 node.set(value);
100 }
101 else {
102 // This might be inside an object that can have additionalProperties, so
103 // a TreeNode would not exist.
104 const splitPath = _parseJsonPath(path);
105 if (!splitPath) {
106 return undefined;
107 }
108 const parent = splitPath
109 .slice(0, -1)
110 .reduce((parent, curr) => parent && parent[curr], this);
111 if (parent) {
112 parent[splitPath[splitPath.length - 1]] = value;
113 }
114 }
115 }
116 /** Get the Schema associated with a path. */
117 $$typeOf(path) {
118 const node = _getSchemaNodeForPath(this.$$schema(), path);
119 return node ? node.type : null;
120 }
121 $$defined(path) {
122 const node = _getSchemaNodeForPath(this.$$schema(), path);
123 return node ? node.defined : false;
124 }
125 $$delete(path) {
126 const node = _getSchemaNodeForPath(this.$$schema(), path);
127 if (node) {
128 node.destroy();
129 }
130 }
131 /** Serialize into a string. */
132 $$serialize(mimetype = 'application/json', ...options) {
133 let str = '';
134 const serializer = serializer_1.Serializer.fromMimetype(mimetype, (s) => str += s, ...options);
135 serializer.start();
136 this.$$schema().serialize(serializer);
137 serializer.end();
138 return str;
139 }
140}
141/**
142 * Create a class from a JSON SCHEMA object. Instanciating that class with an object
143 * allows for extended behaviour.
144 * This is the base API to access the Configuration in the CLI.
145 * @param schema
146 * @returns {GeneratedSchemaClass}
147 * @constructor
148 */
149function SchemaClassFactory(schema) {
150 class GeneratedSchemaClass extends SchemaClassBase {
151 constructor(value, ...fallbacks) {
152 super(schema, value, ...fallbacks);
153 }
154 }
155 return GeneratedSchemaClass;
156}
157exports.SchemaClassFactory = SchemaClassFactory;
158//# sourceMappingURL=/users/hansl/sources/angular-cli/src/schema-class-factory.js.map
\No newline at end of file