Skip to content
This repository has been archived by the owner on Nov 8, 2024. It is now read-only.

Commit

Permalink
Merge pull request #8 from apiaryio/pksunkara/resolved
Browse files Browse the repository at this point in the history
Use resolvedDataStructure instead of expanding data structures in place
  • Loading branch information
zdne committed Feb 18, 2015
2 parents 3547e34 + a1cf771 commit a97f928
Show file tree
Hide file tree
Showing 5 changed files with 762 additions and 47 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,22 @@ $ drafter blueprint.apib

## Resolved Named Types

Named Types (and anonymous named types) are expanded in-place in the AST. The three rules for when MSON AST is expanded are:
The three rules for when MSON AST is expanded are:

* If a named type is a sub-type of another named type
* If a named types includes a mixin
* If a value member or property member is referencing a named type

The expanded data structures are added to the array which has the original data structures with their element name set to `resolvedDataStructure`.

## Resolved Assets

The resolved assets for a *payload body example* and *payload body schema* are added to the array in the `content` key of the **Payload Object** with their element name set to `resolvedAsset` and `role` in `attributes` set as `bodyExample` and `bodySchema` respectively.

A sample part of payload object is given below

```json
{
// This is the payload object
"content": [
{
"element": "resolvedAsset",
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
"prepublish": "scripts/build"
},
"dependencies": {
"async": "~0.9.0",
"boutique": "git+ssh://[email protected]:apiaryio/boutique.git",
"coffee-script": "~1.7.1",
"yargs": "~1.3.3",
"deep-equal": "1.0.x",
"deepcopy": "0.4.x",
"protagonist-experimental": "0.18.6",
"async": "~0.9.0",
"boutique": "git+ssh://[email protected]:apiaryio/boutique.git"
"yargs": "~1.3.3"
},
"devDependencies": {
"chai": "~1.10.0",
Expand Down
58 changes: 49 additions & 9 deletions src/drafter.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ boutique = require 'boutique'
options = require './options'
fs = require 'fs'
async = require 'async'
deepcopy = require 'deepcopy'
deepEqual = require 'deep-equal'

# Gather all payloads from the given parse result
#
Expand All @@ -18,13 +20,17 @@ gatherPayloads = (result) ->

for action in subElement.actions
attributes = null
resolvedAttributes = null

for actionElement in action.content
attributes = actionElement if actionElement.element is 'dataStructure'
resolvedAttributes = actionElement if actionElement.element is 'resolvedDataStructure'

resolvedAttributes ?= attributes

for example in action.examples
payloads.push {payload: request, actionAttributes: attributes} for request in example.requests
payloads.push {payload: response, actionAttributes: attributes} for response in example.responses
payloads.push {payload: request, actionAttributes: resolvedAttributes} for request in example.requests
payloads.push {payload: response, actionAttributes: resolvedAttributes} for response in example.responses

return payloads

Expand Down Expand Up @@ -85,6 +91,10 @@ class Drafter

# List of data structures
@dataStructures: {}
@origDataStructures: {}

# References denoting where to append the resolved data structures
@appendResolved: {}

# Default configuration
@defaultConfig:
Expand Down Expand Up @@ -121,6 +131,9 @@ class Drafter
rules = (require './rules/' + rule for rule in ruleList)

@dataStructures = {}
@origDataStructures = {}
@appendResolved = {}

delete result.ast.resourceGroups

@expandNode result.ast, rules, 'blueprint'
Expand All @@ -133,19 +146,22 @@ class Drafter
# Resolve assets of a payload
resolvePayload: ({payload, actionAttributes}, callback) ->
attributes = null
resolvedAttributes = null
contentType = ''

for header in payload.headers
contentType = header.value if header.name is 'Content-Type'

for element in payload.content
attributes = element if element.element is 'dataStructure'
resolvedAttributes = element if element.element is 'resolvedDataStructure'

attributes ?= actionAttributes
resolvedAttributes ?= attributes
resolvedAttributes ?= actionAttributes

async.waterfall [
(cb) ->
cb null, payload, attributes, contentType
cb null, payload, resolvedAttributes, contentType
, generateBody
, generateSchema
], (error) ->
Expand All @@ -156,7 +172,8 @@ class Drafter
# @param node [Object] A node of API Blueprint
# @param rules [Array] List of rules to apply
# @param elementTye [String] The element type of the node
expandNode: (node, rules, elementType) ->
# @param parent [Object] Parent node's content of which the current node is a part of
expandNode: (node, rules, elementType, parentContent) ->
elementType ?= node.element

# On root node, Gather data structures first before applying rules to any of the children nodes
Expand All @@ -168,18 +185,41 @@ class Drafter

switch subElement.element
when 'dataStructure'
@dataStructures[subElement.name.literal] = subElement
@dataStructures[subElement.name.literal] = deepcopy subElement
@origDataStructures[subElement.name.literal] = subElement
@appendResolved[subElement.name.literal] = element.content
when 'resource'
for resourceSubElement in subElement.content
@dataStructures[resourceSubElement.name.literal] = resourceSubElement if resourceSubElement.element is 'dataStructure'
if resourceSubElement.element is 'dataStructure'

@dataStructures[resourceSubElement.name.literal] = deepcopy resourceSubElement
@origDataStructures[resourceSubElement.name.literal] = resourceSubElement
@appendResolved[resourceSubElement.name.literal] = subElement.content

# Expand the gathered data structures
for rule in rules
rule.init.call rule, @dataStructures if rule.init

# Append resolved data structures
for name, dataStructure of @dataStructures
if not deepEqual dataStructure, @origDataStructures[name]
dataStructure.element = 'resolvedDataStructure'
@appendResolved[name].push dataStructure

# Don't expand data structures in place
if elementType is 'dataStructure'
newNode = deepcopy node
else
newNode = node

# Apply rules to the current node
for rule in rules
rule[elementType].call rule, node if elementType in Object.keys(rule)
rule[elementType].call rule, newNode if elementType in Object.keys(rule)

# Append resolved data structures
if elementType is 'dataStructure' and not deepEqual node, newNode
newNode.element = 'resolvedDataStructure'
parentContent.push newNode

# Recursively do the same for children nodes
switch elementType
Expand All @@ -194,7 +234,7 @@ class Drafter
@expandNode response, rules, 'payload' for response in node.responses

if node.content and Array.isArray node.content
@expandNode element, rules for element in node.content
@expandNode element, rules, null, node.content for element in node.content

# Reconstruct deprecated resource groups key from elements
#
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/dataStructures.apib
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ A clone of Coupon to be used for testing
## Subscription
+ id: 1000 (number)
+ plan: `Startup` (string) - Subscription plan name
+ coupon (Coupon Base) - Coupon represting any existing discounts used by the customer during the subscription
+ coupon (Coupon Base) - Coupon representing any existing discounts used by the customer during the subscription
+ One Of
+ Include Timestamps
+ Properties
Expand Down
Loading

0 comments on commit a97f928

Please sign in to comment.