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

Commit

Permalink
Merge pull request #78 from raml-org/ix_expose_editing_pipeline
Browse files Browse the repository at this point in the history
Add ability to preserve root definitions on resolution
  • Loading branch information
jstoiko authored Jun 6, 2020
2 parents a01b071 + 23dd80c commit 2a71fb5
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 19 deletions.
75 changes: 71 additions & 4 deletions docs/resolving.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
This document describes `webapi-parser` process called "resolution". This process is performed by syntax-specific `.resolve()` methods of all supported API syntaxes (RAML, OAS, AMF Graph). Resolving produces a "flat" document/model with all the references replaced by redundant copies of an actual data.

## Input and Output
Input to `.resolve()` is an [WebApi Model](https://raml-org.github.io/webapi-parser/js/classes/webapibaseunit.html) either not resolved or already resolved (nothing happens in this case).
Input to `.resolve()` is a [WebApi Model](https://raml-org.github.io/webapi-parser/js/classes/webapibaseunit.html) either not resolved or already resolved (nothing happens in this case).

Output is a resolved(/flat/explicit) WebApi Model with all the references replaced by definitions.

Expand All @@ -22,9 +22,9 @@ A resolved WebApi Model has the following properties:
* All the constraints defined for the type are valid
* Unions can only appear at the top level of the type form

## Examples
### Examples

### RAML 1.0
#### RAML 1.0
Unresolved

```raml
Expand Down Expand Up @@ -80,7 +80,7 @@ version: v1
required: true
```
### OAS 2.0
#### OAS 2.0
Unresolved
```json
Expand Down Expand Up @@ -181,3 +181,70 @@ Resolved
}
}
```

## Preserving root definitions
When resolving a document it's possible to preserve RAML 1.0 root definitions: `types`, `annotationTypes`, `traits`, `resourceTypes`. This can be done by passing `true` boolean as the second argument to `.resolve()`. E.g. `.resolve(model, true)`.

Here's how RAML from the previous section would look like when resolved with preserving root definitions:

```raml
title: Albums API
version: v1
types:
Song:
additionalProperties: true
properties:
title:
type: string
required: true
Album:
additionalProperties: true
properties:
title:
type: string
required: true
songs:
items:
additionalProperties: true
properties:
title:
type: string
required: true
required: true
ReleasedAlbum:
type: object
additionalProperties: true
properties:
title:
type: string
required: true
songs:
items:
additionalProperties: true
properties:
title:
type: string
required: true
required: true
/released-albums:
get:
responses:
"200":
body:
application/json:
items:
type: object
additionalProperties: true
properties:
title:
type: string
required: true
songs:
items:
additionalProperties: true
properties:
title:
type: string
required: true
required: true
```
15 changes: 10 additions & 5 deletions js/module/typings/webapi-parser.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,10 @@ export namespace WebApiParser {
* Resolution process includes resolving references to all types, libraries, etc.
*
* @param model Parsed WebApi Model to be resolved.
* @param preserveDefinitions Preserve root definitions.
* @return Resolved parsed WebApi Model.
*/
static resolve(model: WebApiBaseUnit): Promise<WebApiBaseUnit>
static resolve(model: WebApiBaseUnit, preserveDefinitions: boolean): Promise<WebApiBaseUnit>
}

/** Provides methods for RAML 0.8 processing */
Expand Down Expand Up @@ -228,9 +229,10 @@ export namespace WebApiParser {
* Resolution process includes resolving references to all types, libraries, etc.
*
* @param model Parsed WebApi Model to be resolved.
* @param preserveDefinitions Preserve root definitions.
* @return Resolved parsed WebApi Model.
*/
static resolve(model: WebApiBaseUnit): Promise<WebApiBaseUnit>
static resolve(model: WebApiBaseUnit, preserveDefinitions: boolean): Promise<WebApiBaseUnit>
}

/** Provides methods for OAS 2.0 processing */
Expand Down Expand Up @@ -278,9 +280,10 @@ export namespace WebApiParser {
* Resolution process includes resolving references to all types, libraries, etc.
*
* @param model Parsed WebApi Model to be resolved.
* @param preserveDefinitions Preserve root definitions.
* @return Resolved parsed WebApi Model.
*/
static resolve(model: WebApiBaseUnit): Promise<WebApiBaseUnit>
static resolve(model: WebApiBaseUnit, preserveDefinitions: boolean): Promise<WebApiBaseUnit>

/** Parses OAS 2.0 YAML content from string or url.
*
Expand Down Expand Up @@ -358,9 +361,10 @@ export namespace WebApiParser {
* Resolution process includes resolving references to all types, libraries, etc.
*
* @param model Parsed WebApi Model to be resolved.
* @param preserveDefinitions Preserve root definitions.
* @return Resolved parsed WebApi Model.
*/
static resolve(model: WebApiBaseUnit): Promise<WebApiBaseUnit>
static resolve(model: WebApiBaseUnit, preserveDefinitions: boolean): Promise<WebApiBaseUnit>

/** BETA! Parses OAS 3.0 YAML content from string or url.
*
Expand Down Expand Up @@ -438,9 +442,10 @@ export namespace WebApiParser {
* Resolution process includes resolving references to all types, libraries, etc.
*
* @param model Parsed WebApi Model to be resolved.
* @param preserveDefinitions Preserve root definitions.
* @return Resolved parsed WebApi Model.
*/
static resolve(model: WebApiBaseUnit): Promise<WebApiBaseUnit>
static resolve(model: WebApiBaseUnit, preserveDefinitions: boolean): Promise<WebApiBaseUnit>
}
}

Expand Down
16 changes: 16 additions & 0 deletions jvm/src/test/scala/webapi/Oas20Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,22 @@ class Oas20Test extends AsyncFunSuite with Matchers with WaitingFileReader {
genStr <- Oas20.generateString(resolved).asInternal
} yield {
genStr should not include ("$ref")
genStr should not include ("definitions")
genStr should not include ("User")
genStr should include ("firstName")
genStr should include ("schema")
}
}

test("Resolution with preserving root definitions") {
for {
unit <- Oas20.parse(apiString).asInternal
resolved <- Oas20.resolve(unit, true).asInternal
genStr <- Oas20.generateString(resolved).asInternal
} yield {
genStr should not include ("$ref")
genStr should include ("definitions")
genStr should include ("User")
genStr should include ("firstName")
genStr should include ("schema")
}
Expand Down
16 changes: 16 additions & 0 deletions jvm/src/test/scala/webapi/Oas30Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,22 @@ class Oas30Test extends AsyncFunSuite with Matchers with WaitingFileReader {
genStr <- Oas30.generateString(resolved).asInternal
} yield {
genStr should not include ("$ref")
genStr should not include ("schemas")
genStr should not include ("User")
genStr should include ("firstName")
genStr should include ("schema")
}
}

test("Resolution with preserving root definitions") {
for {
unit <- Oas30.parse(apiString).asInternal
resolved <- Oas30.resolve(unit, true).asInternal
genStr <- Oas30.generateString(resolved).asInternal
} yield {
genStr should not include ("$ref")
genStr should include ("schemas")
genStr should include ("User")
genStr should include ("firstName")
genStr should include ("schema")
}
Expand Down
14 changes: 14 additions & 0 deletions jvm/src/test/scala/webapi/Raml10Test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ class Raml10Test extends AsyncFunSuite with Matchers with WaitingFileReader {
genStr should include ("firstName:")
genStr should not include ("type: User")
genStr should not include ("types:")
genStr should not include ("User:")
}
}

test("Resolution with preserving root definitions") {
for {
unit <- Raml10.parse(apiString).asInternal
resolved <- Raml10.resolve(unit, true).asInternal
genStr <- Raml10.generateString(resolved).asInternal
} yield {
genStr should include ("firstName:")
genStr should not include ("type: User")
genStr should include ("types:")
genStr should include ("User:")
}
}

Expand Down
50 changes: 40 additions & 10 deletions shared/src/main/scala/webapi/WebApiParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,18 @@ object Raml10 {
* Resolution process includes resolving references to all types, libraries, etc.
*
* @param model Parsed WebApi Model to be resolved.
* @param preserveDefinitions Preserve root definitions.
* @return Resolved parsed WebApi Model (future).
*/
def resolve(model: WebApiBaseUnit): ClientFuture[WebApiBaseUnit] = {
def resolve(model: WebApiBaseUnit, preserveDefinitions: Boolean = false): ClientFuture[WebApiBaseUnit] = {
WebApiParser.chainAfterInit(() => {
Future {
val resolved: InternalBaseUnit = new Raml10Resolver().resolve(model)
var resolved: InternalBaseUnit = null
if(preserveDefinitions) {
resolved = new Raml10Resolver().resolve(model, "editing")
} else {
resolved = new Raml10Resolver().resolve(model)
}
resolved
}
}).asClient
Expand Down Expand Up @@ -215,12 +221,18 @@ object Raml08 {
* Resolution process includes resolving references to all types, libraries, etc.
*
* @param model Parsed WebApi Model to be resolved.
* @param preserveDefinitions Preserve root definitions.
* @return Resolved parsed WebApi Model (future).
*/
def resolve(model: WebApiBaseUnit): ClientFuture[WebApiBaseUnit] = {
def resolve(model: WebApiBaseUnit, preserveDefinitions: Boolean = false): ClientFuture[WebApiBaseUnit] = {
WebApiParser.chainAfterInit(() => {
Future {
val resolved: InternalBaseUnit = new Raml08Resolver().resolve(model)
var resolved: InternalBaseUnit = null
if(preserveDefinitions) {
resolved = new Raml08Resolver().resolve(model, "editing")
} else {
resolved = new Raml08Resolver().resolve(model)
}
resolved
}
}).asClient
Expand Down Expand Up @@ -298,12 +310,18 @@ object Oas20 {
* Resolution process includes resolving references to all types, libraries, etc.
*
* @param model Parsed WebApi Model to be resolved.
* @param preserveDefinitions Preserve root definitions.
* @return Resolved parsed WebApi Model (future).
*/
def resolve(model: WebApiBaseUnit): ClientFuture[WebApiBaseUnit] = {
def resolve(model: WebApiBaseUnit, preserveDefinitions: Boolean = false): ClientFuture[WebApiBaseUnit] = {
WebApiParser.chainAfterInit(() => {
Future {
val resolved: InternalBaseUnit = new Oas20Resolver().resolve(model)
var resolved: InternalBaseUnit = null
if(preserveDefinitions) {
resolved = new Oas20Resolver().resolve(model, "editing")
} else {
resolved = new Oas20Resolver().resolve(model)
}
resolved
}
}).asClient
Expand Down Expand Up @@ -431,12 +449,18 @@ object Oas30 {
* Resolution process includes resolving references to all types, libraries, etc.
*
* @param model Parsed WebApi Model to be resolved.
* @param preserveDefinitions Preserve root definitions.
* @return Resolved parsed WebApi Model (future).
*/
def resolve(model: WebApiBaseUnit): ClientFuture[WebApiBaseUnit] = {
def resolve(model: WebApiBaseUnit, preserveDefinitions: Boolean = false): ClientFuture[WebApiBaseUnit] = {
WebApiParser.chainAfterInit(() => {
Future {
val resolved: InternalBaseUnit = new Oas30Resolver().resolve(model)
var resolved: InternalBaseUnit = null
if(preserveDefinitions) {
resolved = new Oas30Resolver().resolve(model, "editing")
} else {
resolved = new Oas30Resolver().resolve(model)
}
resolved
}
}).asClient
Expand Down Expand Up @@ -564,12 +588,18 @@ object AmfGraph {
* Resolution process includes resolving references to all types, libraries, etc.
*
* @param model Parsed WebApi Model to be resolved.
* @param preserveDefinitions Preserve root definitions.
* @return Resolved parsed WebApi Model (future).
*/
def resolve(model: WebApiBaseUnit): ClientFuture[WebApiBaseUnit] = {
def resolve(model: WebApiBaseUnit, preserveDefinitions: Boolean = false): ClientFuture[WebApiBaseUnit] = {
WebApiParser.chainAfterInit(() => {
Future {
val resolved: InternalBaseUnit = new AmfGraphResolver().resolve(model)
var resolved: InternalBaseUnit = null
if(preserveDefinitions) {
resolved = new AmfGraphResolver().resolve(model, "editing")
} else {
resolved = new AmfGraphResolver().resolve(model)
}
resolved
}
}).asClient
Expand Down

0 comments on commit 2a71fb5

Please sign in to comment.