Blame view

node_modules/loopback-swagger/lib/specgen/model-helper.js 4.08 KB
f7563de62   Palak Handa   first commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  // Copyright IBM Corp. 2015,2016. All Rights Reserved.
  // Node module: loopback-swagger
  // This file is licensed under the MIT License.
  // License text available at https://opensource.org/licenses/MIT
  
  'use strict';
  
  /**
   * Module dependencies.
   */
  var schemaBuilder = require('./schema-builder');
  var typeConverter = require('./type-converter');
  var TypeRegistry = require('./type-registry');
  
  /**
   * Export the modelHelper singleton.
   */
  var modelHelper = module.exports = {
    /**
     * Given a class (from remotes.classes()), generate a model definition.
     * This is used to generate the schema at the top of many endpoints.
     * @param  {Class} modelClass Model class.
     * @param {TypeRegistry} typeRegistry Registry of types and models.
     * @return {Object} Associated model definition.
     */
    registerModelDefinition: function(modelCtor, typeRegistry) {
      var lbdef = modelCtor.definition;
  
      if (!lbdef) {
        // The model does not have any definition, it was most likely
        // created as a placeholder for an unknown property type
        return;
      }
  
      var name = lbdef.name;
      if (typeRegistry.isDefined(name)) {
        // The model is already included
        return;
      }
  
      typeRegistry.registerModel(name, function() {
        return definitionFunction(modelCtor, typeRegistry);
      });
    },
  
    isHiddenProperty: function(definition, propName) {
      return definition.settings &&
        Array.isArray(definition.settings.hidden) &&
        definition.settings.hidden.indexOf(propName) !== -1;
    },
  };
  
  var definitionFunction = function(modelCtor, typeRegistry) {
    var lbdef = modelCtor.definition;
  
    var swaggerDef = {
      description: typeConverter.convertText(
        lbdef.description || (lbdef.settings && lbdef.settings.description)),
      properties: {},
      required: [],
    };
    addSwaggerExtensions(lbdef.settings);
  
    var properties = lbdef.rawProperties || lbdef.properties;
  
    // Iterate through each property in the model definition.
    // Types may be defined as constructors (e.g. String, Date, etc.),
    // or as strings; swaggerSchema.buildFromLoopBackType() will take
    // care of the conversion.
    Object.keys(properties).forEach(function(key) {
      var prop = properties[key];
  
      // Hide hidden properties.
      if (modelHelper.isHiddenProperty(lbdef, key))
        return;
  
      // Get a type out of the constructors we were passed.
      var schema = schemaBuilder.buildFromLoopBackType(prop, typeRegistry);
  
      var desc = typeConverter.convertText(prop.description || prop.doc);
      if (desc) schema.description = desc;
  
      // Required props sit in a per-model array.
      if (prop.required || (prop.id && !prop.generated)) {
        swaggerDef.required.push(key);
      }
  
      // Assign the schema to the properties object.
      swaggerDef.properties[key] = schema;
    });
  
    if (lbdef.settings) {
      var strict = lbdef.settings.strict;
      var additionalProperties = lbdef.settings.additionalProperties;
      var notAllowAdditionalProperties = strict || (additionalProperties !== true);
      if (notAllowAdditionalProperties) {
        swaggerDef.additionalProperties = false;
      }
    }
  
    if (!swaggerDef.required.length) {
      // "required" must have at least one item when present
      delete swaggerDef.required;
    }
  
    // Add models from settings
    if (lbdef.settings && lbdef.settings.models) {
      for (var m in lbdef.settings.models) {
        var model = modelCtor[m];
        if (typeof model !== 'function' || !model.modelName) continue;
        modelHelper.registerModelDefinition(model, typeRegistry);
        typeRegistry.reference(model.modelName);
      }
    }
  
    // Generate model definitions for related models
    /* eslint-disable one-var */
    for (var r in modelCtor.relations) {
      var rel = modelCtor.relations[r];
      if (rel.modelTo) {
        modelHelper.registerModelDefinition(rel.modelTo, typeRegistry);
      }
      if (rel.modelThrough) {
        modelHelper.registerModelDefinition(rel.modelThrough, typeRegistry);
      }
    }
    /* eslint-enable one-var */
    return swaggerDef;
  
    function addSwaggerExtensions(defs) {
      for (var def in defs) {
        if (def.match(/^x\-/)) {
          swaggerDef[def] = defs[def];
        }
      }
    };
  };