1 |
|
2 | var async, baseTypes, ensureBaseType, ensureImplicitNestedTypes, inspect, isArray, isObject, resolveImplicitNestedTypes, resolveImplicitType, resolveInheritedType, resolveType, resolveTypes, simplifyNestedTypes, simplifyTypeSpecification,
|
3 | __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
4 |
|
5 | async = require('async');
|
6 |
|
7 | inspect = require('./inspect');
|
8 |
|
9 | baseTypes = ['boolean', 'string', 'number', 'array', 'enum', 'object'];
|
10 |
|
11 | ensureBaseType = function(type, cb) {
|
12 | if (__indexOf.call(baseTypes, type) < 0) {
|
13 | return cb(new Error("Unable to resolve type: " + type));
|
14 | } else {
|
15 | return cb(null);
|
16 | }
|
17 | };
|
18 |
|
19 | simplifyNestedTypes = function(typeSpec, cb) {
|
20 | var name, nested, _ref;
|
21 | if (((typeSpec != null ? (_ref = typeSpec.nestedTypes) != null ? _ref.length : void 0 : void 0) || 0) < 1) {
|
22 | return cb(null, []);
|
23 | }
|
24 | name = inspect.findTypeName(typeSpec);
|
25 | if (name !== 'array' && name !== 'enum') {
|
26 | return cb(new Error("Nested types are allowed only for array and enum types."));
|
27 | }
|
28 | nested = typeSpec.nestedTypes;
|
29 | return async.map(nested, ensureBaseType, function(err) {
|
30 | if (err) {
|
31 | return cb(err);
|
32 | }
|
33 | return cb(null, nested);
|
34 | });
|
35 | };
|
36 |
|
37 | simplifyTypeSpecification = function(typeSpec, cb) {
|
38 | var name;
|
39 | name = inspect.findTypeName(typeSpec);
|
40 | if (!name) {
|
41 | return cb(null, null);
|
42 | }
|
43 | return async.waterfall([
|
44 | function(next) {
|
45 | return ensureBaseType(name, next);
|
46 | }, function(next) {
|
47 | return simplifyNestedTypes(typeSpec, next);
|
48 | }
|
49 | ], function(err, nested) {
|
50 | return cb(err, (!err ? {
|
51 | name: name,
|
52 | nested: nested
|
53 | } : void 0));
|
54 | });
|
55 | };
|
56 |
|
57 | isArray = function(elementNode) {
|
58 | return inspect.hasMultipleValues(elementNode);
|
59 | };
|
60 |
|
61 | isObject = function(elementNode) {
|
62 | return inspect.hasAnyMemberSections(elementNode);
|
63 | };
|
64 |
|
65 | resolveImplicitNestedTypes = function(typeName, elementNode, cb) {
|
66 | if ((typeName === 'array' || typeName === 'enum') && (inspect.listValues(elementNode)).length) {
|
67 | return cb(null, ['string']);
|
68 | } else {
|
69 | return cb(null, []);
|
70 | }
|
71 | };
|
72 |
|
73 | resolveImplicitType = function(elementNode, cb) {
|
74 | var isArr, isObj, name;
|
75 | isArr = isArray(elementNode);
|
76 | isObj = isObject(elementNode);
|
77 | if (isObj && isArr) {
|
78 | return cb(new Error("Unable to resolve type. Ambiguous implicit type (seems to be both object and inline array)."));
|
79 | } else {
|
80 | name = (isArr ? 'array' : void 0) || (isObj ? 'object' : void 0) || 'string';
|
81 | return resolveImplicitNestedTypes(name, elementNode, function(err, nested) {
|
82 | return cb(err, (!err ? {
|
83 | name: name,
|
84 | nested: nested
|
85 | } : void 0));
|
86 | });
|
87 | }
|
88 | };
|
89 |
|
90 | resolveInheritedType = function(elementNode, inheritedTypeName, cb) {
|
91 | return cb(null, {
|
92 | name: inheritedTypeName,
|
93 | nested: []
|
94 | });
|
95 | };
|
96 |
|
97 | ensureImplicitNestedTypes = function(elementNode, simpleTypeSpec, cb) {
|
98 | var name, _ref;
|
99 | if ((_ref = simpleTypeSpec.nested) != null ? _ref.length : void 0) {
|
100 | return cb(null, simpleTypeSpec);
|
101 | } else {
|
102 | name = simpleTypeSpec.name;
|
103 | return resolveImplicitNestedTypes(name, elementNode, function(err, nested) {
|
104 | return cb(err, (!err ? {
|
105 | name: name,
|
106 | nested: nested
|
107 | } : void 0));
|
108 | });
|
109 | }
|
110 | };
|
111 |
|
112 | resolveType = function(elementNode, inheritedTypeName, cb) {
|
113 | var typeSpec;
|
114 | if (inheritedTypeName) {
|
115 | if (typeof inheritedTypeName === 'function') {
|
116 | cb = inheritedTypeName;
|
117 | } else {
|
118 | return resolveInheritedType(elementNode, inheritedTypeName, cb);
|
119 | }
|
120 | }
|
121 | typeSpec = inspect.findTypeSpecification(elementNode);
|
122 | return simplifyTypeSpecification(typeSpec, function(err, simpleTypeSpec) {
|
123 | if (err) {
|
124 | return cb(err);
|
125 | }
|
126 | if (!simpleTypeSpec) {
|
127 | return resolveImplicitType(elementNode, cb);
|
128 | }
|
129 | return ensureImplicitNestedTypes(elementNode, simpleTypeSpec, cb);
|
130 | });
|
131 | };
|
132 |
|
133 | resolveTypes = function(elementNodes, inheritedTypeName, cb) {
|
134 | return async.map(elementNodes, function(elementNode, next) {
|
135 | return resolveType(elementNode, inheritedTypeName, next);
|
136 | }, cb);
|
137 | };
|
138 |
|
139 | module.exports = {
|
140 | resolveType: resolveType,
|
141 | resolveTypes: resolveTypes
|
142 | };
|