uniqueItemProperties.js 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. 'use strict';
  2. var SCALAR_TYPES = ['number', 'integer', 'string', 'boolean', 'null'];
  3. module.exports = function defFunc(ajv) {
  4. defFunc.definition = {
  5. type: 'array',
  6. compile: function(keys, parentSchema, it) {
  7. var equal = it.util.equal;
  8. var scalar = getScalarKeys(keys, parentSchema);
  9. return function(data) {
  10. if (data.length > 1) {
  11. for (var k=0; k < keys.length; k++) {
  12. var i, key = keys[k];
  13. if (scalar[k]) {
  14. var hash = {};
  15. for (i = data.length; i--;) {
  16. if (!data[i] || typeof data[i] != 'object') continue;
  17. var prop = data[i][key];
  18. if (prop && typeof prop == 'object') continue;
  19. if (typeof prop == 'string') prop = '"' + prop;
  20. if (hash[prop]) return false;
  21. hash[prop] = true;
  22. }
  23. } else {
  24. for (i = data.length; i--;) {
  25. if (!data[i] || typeof data[i] != 'object') continue;
  26. for (var j = i; j--;) {
  27. if (data[j] && typeof data[j] == 'object' && equal(data[i][key], data[j][key]))
  28. return false;
  29. }
  30. }
  31. }
  32. }
  33. }
  34. return true;
  35. };
  36. },
  37. metaSchema: {
  38. type: 'array',
  39. items: {type: 'string'}
  40. }
  41. };
  42. ajv.addKeyword('uniqueItemProperties', defFunc.definition);
  43. return ajv;
  44. };
  45. function getScalarKeys(keys, schema) {
  46. return keys.map(function(key) {
  47. var properties = schema.items && schema.items.properties;
  48. var propType = properties && properties[key] && properties[key].type;
  49. return Array.isArray(propType)
  50. ? propType.indexOf('object') < 0 && propType.indexOf('array') < 0
  51. : SCALAR_TYPES.indexOf(propType) >= 0;
  52. });
  53. }