UNPKG

json-api-schema

Version:

JSON Api Schema is a JSON dialect that can describe any Web Based API that uses JSON to exchange data.

178 lines (142 loc) 5 kB
EntityIterator = require "./iterators/entity_iterator" ObjectIterator = require "./iterators/object_iterator" ArrayIterator = require "./iterators/array_iterator" NullIterator = require "./iterators/null_iterator" IteratorsIterator = require "./iterators/iterators_iterator" null_iterator = new NullIterator() # The base class of API model. # # Provides facilities for traversing, and adding external behaviour # class Entity # Part of mixins implementation taken from http://arcturo.github.io/library/coffeescript/03_classes.html # @extend: (obj) -> for key, value of obj when key not in ['extended', 'included'] @[key] = value obj.extended?.apply(@) this # Part of mixins implementation taken from http://arcturo.github.io/library/coffeescript/03_classes.html # @include: (obj) -> for key, value of obj when key not in ['extended', 'included'] @::[key] = value obj.included?.apply(@) this @accessors: (properties..., templates) -> camelize = (string) -> string.replace /(?:^|[-_])(\w)/g, (_, c) -> (if c then c.toUpperCase() else "") singularize = (string) -> string.replace /s$/, "" propertyToMethod = (prefix, property) -> prefix + camelize(property.replace(/^_+/, "")) propertyToSingularizedMethod = (prefix, property) -> singularize(propertyToMethod(prefix,property)) proto = @:: templates.forEach (template) -> switch template when "get" properties.forEach (prop) -> methodName = propertyToMethod("get", prop) proto[methodName] = -> @[prop] when "set" properties.forEach (prop) -> methodName = propertyToMethod("set", prop) proto[methodName] = (value) -> if value instanceof Entity value.setParent(@) @[prop] = value when "get-key" properties.forEach (prop) -> methodName = propertyToSingularizedMethod("get", prop) proto[methodName] = (k) -> m = @[prop] or {} m[k] when "put-key" properties.forEach (prop) -> methodName = propertyToSingularizedMethod("put", prop) proto[methodName] = (k, v) -> if v instanceof Entity v.setParent(@) m = @[prop] ?= {} m[k] = v when "delete-key" properties.forEach (prop) -> methodName = propertyToSingularizedMethod("delete", prop) proto[methodName] = (k) -> m = @[prop] v = m[k] if v instanceof Entity v.setParent(undefined) delete m[k] v when "put-keys" properties.forEach (prop) -> methodName = propertyToMethod("put", prop) proto[methodName] = (obj) -> for k, v of obj if v instanceof Entity v.setParent(@) m = @[prop] m[k] = v prop @children: (children...) -> isArray = (array) -> not (not array or (not array.length or array.length is 0) or typeof array isnt "object" or not array.constructor or array.nodeType or array.item) iteratorFor = (object) -> if object instanceof Entity new EntityIterator(object) else if isArray(object) new ArrayIterator(object) else if typeof object is "object" new ObjectIterator(object) else null_iterator @::getChildrenIterator = -> if children.length == 0 null_iterator else if children.length == 1 iteratorFor(@[children[0]]) else subIterators = [] for child in children if @[child] subIterators.push(iteratorFor(@[child])) new IteratorsIterator(subIterators) @accessors "title", "description", [ "get", "set" ] @accessors "annotations", ["get-key", "put-key", "put-keys", "delete-key"] @accessors "locals", ["get-key", "put-key", "put-keys", "delete-key"] @entity: (name) -> @::getEntityType = -> name @::isInstanceOfEntity = (type) -> type is name or super(name) constructor: (options) -> for k, v of options @[k] = v getEntityType: () -> "Entity" isInstanceOfEntity: (type) -> type is "Entity" # Create a composite traversable structure # getParent: -> @parent setParent: (parent) -> @parent = parent isRoot: () -> !! @parent getAncestors: -> ancestors = [] e = @ while parent = e.getParent() ancestors.unshift(parent) e = parent ancestors getChildrenIterator: -> null_iterator isLeaf: () -> not @getChildrenIterator().hasNext() module.exports = Entity