stoplightio / api-spec-converter Goto Github PK
View Code? Open in Web Editor NEWThis package helps to convert between different API specifications (Postman, Swagger, RAML, StopLight).
License: MIT License
This package helps to convert between different API specifications (Postman, Swagger, RAML, StopLight).
License: MIT License
Whether the library is not very much buggy or not and to check if we can support RAML 1.0 decently.
Library's Github URL: https://github.com/raml-org/raml-js-parser-2
Taking the following Swagger YAML:
swagger: "2.0"
info:
version: "1.0"
title: "Hello World API"
paths:
/hello/{user}:
get:
description: Returns a greeting to the user!
parameters:
- name: user
in: path
type: string
required: true
description: The name of the user to greet.
responses:
200:
description: Returns the greeting.
schema:
type: string
400:
description: Invalid characters in "user" were provided.
I am getting a RAML generated that contains baseUri: "null"
. That obviously shouldn't happen. Am I right?
Right now, loadFile is callback, loadData is promise. Update loadFile to return a promise.
https://github.com/stoplightio/api-spec-converter/blob/master/lib/importers/auto.js#L141
We currently don't support importing array of references, which might look like this in a swagger yaml as follows:
parameters:
- $ref: "#/definitions/pet"
- $ref: "#/definitions/address"
We don't have support for thiis two attributes in the rool level swagger spec definition:
Current stoplight format is a raw independent format, only applicable/compatible with stoplight platform itself. This feature will help maintaining stoplight format as an swagger-extension format.
This will always be compatible anywhere swagger is supported and additionally, can be imported to stoplight platform with stoplight specific fields/attributes as well.
Here are the list of fields those need to be taken care of in swagger-extension(stoplight) format in addition to what are already supported:
Environment:
- middlewareBefore
- middlewareAfter
- proxy
Endpoint:
- _id
- middlewareBefore
- middlewareAfter
- mock
utilityFunctions:
-Everything
resourcesOrder:
-Everything
Problem: swagger spec doesn't support more than one ('in':'body') param.
Implications as per discussion:
I'm trying to run test that converts from swagger to raml to swagger using this file https://github.com/mulesoft/api-spec-converter/blob/master/example/source/swagger.json that is not working. Test results in a lot of differences.
Thanks.
Gaston
` 167 passing (2s)
46 pending
1 failing
AssertionError: expected { Object (swagger, schemes, ...) } to deeply equal { Object (swagger, info, ...) }
+ expected - actual
{
- "basePath": "//localhost:3000"
+ "basePath": ""
"consumes": [
"application/json"
]
"definitions": {
"name"
]
}
}
- "host": "http"
+ "host": "http://localhost:3000"
"info": {
"description": "A sample API"
"title": "Swagger petstore"
"version": "1.0.0"
}
"paths": {
"/pets": {
"delete": {
+ "consumes": [
+ "application/json"
+ ]
"description": "Deletes all pets, optionally filtered by one or more criteria"
"operationId": "deletePets"
"parameters": [
{
+ "description": "Filters pets by one or more tags"
+ "in": "query"
+ "items": {
+ "type": "string"
+ }
+ "name": "tags"
+ "type": "array"
+ }
+ {
"description": "Filters pets by type (dog, cat, or bird)"
"in": "query"
"name": "type"
- "required": false
"type": "string"
}
{
"description": "Filters pets by age"
"in": "query"
"name": "age"
- "required": false
"type": "integer"
}
{
"description": "Filters pets by date of birth"
"in": "query"
"name": "dob"
- "required": false
"type": "string"
}
{
"description": "Filters pets by city"
"in": "query"
"name": "address.city"
- "required": false
"type": "string"
}
{
"description": "Filters pets by state"
"in": "query"
"name": "address.state"
- "required": false
"type": "string"
}
{
"description": "Filters pets by zip code"
"in": "query"
"name": "address.zipcode"
- "required": false
"type": "integer"
}
{
"description": "Filters pets by veterinarian name"
"in": "query"
"name": "vet.name"
- "required": false
"type": "string"
}
{
"description": "Filters pets by veterinarian city"
"in": "query"
"name": "vet.address.city"
- "required": false
"type": "string"
}
{
"description": "Filters pets by veterinarian state"
"in": "query"
"name": "vet.address.state"
- "required": false
"type": "string"
}
{
"description": "Filters pets by veterinarian zip code"
"in": "query"
"name": "vet.address.zipcode"
- "required": false
"type": "integer"
}
{
"description": ""
"required": false
"type": "string"
}
]
+ "produces": [
+ "application/json"
+ ]
"responses": {
"400": {
"description": "Returns the pets that were deleted"
"schema": {
}
"summary": ""
}
"get": {
+ "consumes": [
+ "application/json"
+ ]
"description": "Returns all pets, optionally filtered by one or more criteria"
"operationId": "findPets"
"parameters": [
{
+ "description": "Filters pets by one or more tags"
+ "in": "query"
+ "items": {
+ "type": "string"
+ }
+ "name": "tags"
+ "type": "array"
+ }
+ {
"description": "Filters pets by type (dog, cat, or bird)"
"in": "query"
"name": "type"
- "required": false
"type": "string"
}
{
"description": "Filters pets by age"
"in": "query"
"name": "age"
- "required": false
"type": "integer"
}
{
"description": "Filters pets by date of birth"
"in": "query"
"name": "dob"
- "required": false
"type": "string"
}
{
"description": "Filters pets by city"
"in": "query"
"name": "address.city"
- "required": false
"type": "string"
}
{
"description": "Filters pets by state"
"in": "query"
"name": "address.state"
- "required": false
"type": "string"
}
{
"description": "Filters pets by zip code"
"in": "query"
"name": "address.zipcode"
- "required": false
"type": "integer"
}
{
"description": "Filters pets by veterinarian name"
"in": "query"
"name": "vet.name"
- "required": false
"type": "string"
}
{
"description": "Filters pets by veterinarian city"
"in": "query"
"name": "vet.address.city"
- "required": false
"type": "string"
}
{
"description": "Filters pets by veterinarian state"
"in": "query"
"name": "vet.address.state"
- "required": false
"type": "string"
}
{
"description": "Filters pets by veterinarian zip code"
"in": "query"
"name": "vet.address.zipcode"
- "required": false
"type": "integer"
}
{
"description": ""
"required": false
"type": "string"
}
]
+ "produces": [
+ "application/json"
+ ]
"responses": {
"400": {
"description": "Returns the matching pets"
"schema": {
}
}
"security": [
{
- "oauth2": true
+ "petstore_auth": [
+ "read:pets"
+ ]
}
]
"summary": ""
}
+ "parameters": []
"post": {
+ "consumes": [
+ "application/json"
+ ]
"description": "Creates a new pet in the store"
"operationId": "addPet"
"parameters": [
{
+ "description": "The pet to add to the store"
"in": "body"
- "name": "body"
+ "name": "pet"
+ "required": false
"schema": {
"$ref": "#/definitions/pet"
}
+ "type": "string"
}
]
+ "produces": [
+ "application/json"
+ ]
"responses": {
"201": {
"description": "Returns the newly-added pet"
"schema": {
}
}
"/pets/{petName}": {
"delete": {
+ "consumes": [
+ "application/json"
+ ]
"description": "Deletes a single pet based on the name supplied"
"operationId": "deletePet"
+ "parameters": []
+ "produces": [
+ "application/json"
+ ]
"responses": {
"400": {
"description": "Returns the pet that was deleted"
"schema": {
}
"summary": ""
}
"get": {
+ "consumes": [
+ "application/json"
+ ]
"description": "Returns a pet by name"
"operationId": "findPetByName"
+ "parameters": []
+ "produces": [
+ "application/json"
+ ]
"responses": {
"400": {
"description": "Returns the pet data"
"schema": {
}
}
"summary": ""
}
- "parameters": [
- {
- "description": "petName"
- "in": "path"
- "name": "petName"
- "required": true
- "type": "string"
- }
- ]
+ "parameters": []
"patch": {
+ "consumes": [
+ "application/json"
+ ]
"description": "Updates a pet by name"
- "operationId": "PATCH_pets-petName"
+ "operationId": ""
"parameters": [
{
+ "description": "The updated pet info"
"in": "body"
- "name": "body"
+ "name": "pet"
+ "required": false
"schema": {
"$ref": "#/definitions/pet"
}
+ "type": "string"
}
]
+ "produces": [
+ "application/json"
+ ]
"responses": {
"400": {
"description": "Returns the updated pet data"
"schema": {
}
}
"/pets/{petName}/photos": {
"get": {
+ "consumes": [
+ "application/json"
+ ]
"description": "Get a list of the photos for a pet"
- "operationId": "GET_pets-petName-photos"
+ "operationId": ""
+ "parameters": []
+ "produces": [
+ "application/json"
+ ]
"responses": {
"200": {
"description": "Returns the list of photos"
"schema": {
}
}
"summary": ""
}
- "parameters": [
- {
- "description": "petName"
- "in": "path"
- "name": "petName"
- "required": true
- "type": "string"
- }
- ]
+ "parameters": []
"post": {
"consumes": [
"multipart/form-data"
]
{
"description": "The photo ID (generated automatically)"
"in": "formData"
"name": "id"
+ "required": false
"type": "string"
}
{
"description": "A label for the photo"
"in": "formData"
"name": "label"
+ "required": false
"type": "string"
}
{
"description": "An optional description of the photo"
"in": "formData"
"name": "description"
+ "required": false
"type": "string"
}
{
"description": "The pet photo"
"required": true
"type": "string"
}
]
+ "produces": [
+ "application/json"
+ ]
"responses": {
"400": {
"description": "Returns the photo information"
"schema": {
}
}
"/pets/{petName}/photos/{id}": {
"delete": {
+ "consumes": [
+ "application/json"
+ ]
"description": "Deletes a pet photo"
"operationId": "deletePetPhoto"
+ "parameters": []
+ "produces": [
+ "application/json"
+ ]
"responses": {
"400": {
"description": "The photo was deleted successfully"
}
}
"summary": ""
}
"get": {
+ "consumes": [
+ "application/json"
+ ]
"description": "Gets a pet photo"
"operationId": "getPetPhoto"
+ "parameters": []
"produces": [
"image/jpeg"
]
"responses": {
"summary": ""
}
"parameters": [
{
- "description": "petName"
- "in": "path"
- "name": "petName"
- "required": true
- "type": "string"
- }
- {
"description": "The ID of the photo"
"in": "path"
"name": "id"
"required": true
]
"schemes": [
"http"
"https"
+ "ws"
]
"securityDefinitions": {
+ "api_key": {
+ "in": "header"
+ "name": "api_key"
+ "type": "apiKey"
+ }
"basic_auth": {
"description": "basic authentication support"
+ "name": "basic_auth"
"type": "basic"
}
- "oauth2": {
+ "petstore_auth": {
"authorizationUrl": "http://swagger.io/api/oauth/dialog"
"flow": "implicit"
- "scopes": {}
+ "scopes": {
+ "read:pets": "read your pets"
+ "write:pets": "modify pets in your account"
+ }
"type": "oauth2"
}
}
"swagger": "2.0"
at Assertion.assertEqual (node_modules/chai/lib/chai/core/assertions.js:485:19)
at Assertion.ctx.(anonymous function) [as equal] (node_modules/chai/lib/chai/utils/addMethod.js:41:25)
at test/lib/converter.js:121:49
at lib/converter.js:9:2241
Writing coverage object [/Users/gaston/stoplightio/api-spec-converter/coverage/coverage.json]
=============================== Coverage summary ===============================
Statements : 87.54% ( 1743/1991 )
Branches : 73.48% ( 690/939 )
Functions : 91.38% ( 350/383 )
Lines : 87.57% ( 1740/1987 )
================================================================================`
According to the raml10 spec, nil is the allowed type. The JSON schema spec uses the null primitive type, so this is what swagger specs will use. Thus, we need to change null -> nil when parsing types/schemas for raml 10.
RAML10
https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md#built-in-types
I could not find the allowed primitive types for raml08, so I am not sure if null is allowed (or nil). Perhaps @sichvoge could shed some light on this? This is what I could find:
https://github.com/raml-org/raml-spec/blob/master/versions/raml-08/raml-08.md#type
To replicate, here is an example input swagger that will lead to a (invalid) null property in the raml10 export:
{
"swagger": "2.0",
"info": {
"title": "Test",
},
"paths": {
"/users": {
"get": {
"responses": {
"200": {
"description": "",
"schema": {
"type": "object",
"properties": {
"foo": {
"type": "null"
}
}
}
}
}
}
}
},
}
raml10 is map of traits
Annotation info is generated but its declaration is not included.
This is the declaration that it's missing.
annotationTypes:
info:
properties:
termsOfService?: string
contact?:
properties:
name?: string
url?: string
email?: string
license?:
properties:
name?: string
url?: string
Here is what my RAML 1.0 types array looks like:
[
{
definitions:
dtype:
title: dtype
$ref: '#/definitions/integer'
}
]
When I convert it to swagger type property is being replaced with $ref:
definitions:
dtype:
title: dtype
$ref: '#/definitions/integer'
I found a quick fix for this. In exporters/swagger.js
I included var RAML = require('./baseraml');
and modified _mapSchema
function:
Swagger.prototype._mapSchema = function(schemas) {
return schemas.reduce(function(definitions, schema) {
var definition = {};
if (schema.name) {
definition.title = schema.name;
}
_.merge(definition, RAML.prototype.convertRefFromModel(jsonHelper.parse(schema.Definition)));
mapExample(schema, definition);
definitions[schema.NameSpace] = definition;
return definitions;
}, {});
};
So now when I convert RAML 1.0 to Swagger type property in Definition is being converted as expected:
definitions:
dtype:
title: dtype
type: integer
Is this a good way to fix the issue?
The following fields aren't supported yet, inside info
object:
RAML has some restricted list of supported types for parameters(https://github.com/raml-org/raml-spec/blob/master/raml-0.8.md#type). However, stoplight has some support for additional parameter types, for example: array.
Need to figure out how to map those params in exported RAML. ATM, such incompatible types can cause error in importing those exported raml.
We are using api-spec transformer version 0.2.6. We have identified security vulnerabilities identified in direct and transitive dependencies. Attached vulnerability details for reference.
artifactID Vulnerability name
cryptiles-0.2.2.tgz - CVE-2018-1000620
cryptiles-2.0.5.tgz - CVE-2018-1000620
sshpk-1.13.0.tgz - WS-2018-0084
hawk-1.1.1.tgz - CVE-2016-2515
tough-cookie-0.12.1.tgz -CVE-2017-15010
marked-0.3.6.tgz - CVE-2017-16114
tough-cookie-2.3.2.tgz - CVE-2017-15010
marked-0.3.6.tgz - WS-2017-0108
base64url-1.0.6.tgz WS-2018-0096
hoek-0.9.1.tgz CVE-2018-3728
hoek-2.16.3.tgz CVE-2018-3728
lodash-4.17.4.tgz CVE-2018-3721
request-2.51.0.tgz WS-2016-0025
marked-0.3.6.tgz CVE-2017-1000427
bl-0.9.4.tgz WS-2016-0059
http-signature-0.10.1.tgz WS-2017-0266
tough-cookie-0.12.1.tgz CVE-2016-1000232
debug-2.6.8.tgz CVE-2017-16137
stringstream-0.0.4.tgz WS-2018-0103
stringstream-0.0.5.tgz WS-2018-0103
bl-0.9.4.tgz WS-2018-0074
tunnel-agent-0.4.0.tgz WS-2018-0076
concat-stream-1.4.10.tgz WS-2018-0075
node-uuid-1.4.2.tgz WS-2016-0013
lodash-4.17.4.tgz WS-2018-0210
Kindly support with assessment of the reported issues and fixes is required.
A RAML 1.0 specification composed of multiple files does not properly convert to Swagger.
Example:
spec.raml (top level spec file)
types.raml (a RAML 1.0 library used by spec.raml)
Executing the converter on spec.raml does not convert the types in types.raml to Swagger definitions.
baseUri: https://api.example.com
title: Filesystem API
version: 0.1
schemas:
They're required by the spec.
Swagger defines an invalid format like:
format: uri
type: string
swagger doesn't convert nothing in this case, so export has the same values.
The problem is that format uri is not valid in RAML, so expected result is:
type: string
Right now it's only including description
and schema
. It looks like the mapResponseBody
is expecting a mimeType
that isn't getting passed in from _mapTraitResponses
.
Should be an easy fix
We don't have support for following fields for parameters yet: swagger parameter fields in spec
I'm trying to test the last release of this converter, but when I execute the RAML 1.0 to Swagger usage example, it is always returning 'undefined'. Any idea about what could be happening?
There are two format for Postman, and it's not clear which you support. Probably v1?
At api-spec-converter, update the raml parser to support RAML 1.0 (using the raml-1-parser instead of the old raml-js-parser)
I am not able to find released version for 0.2.6 in https://github.com/stoplightio/api-spec-converter/releases, however we see the same version available in npm.
Swagger response:
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "object",
"description": "List of all media with added `distance` property",
"properties": {
"data": {
"type": "array",
"items": {
"allOf": [
{
"$ref": "#/definitions/Media"
},
{
"properties": {
"distance": {
"type": "number"
}
}
}
]
}
}
}
}
}
}
converted to:
responses:
'200':
body:
application/json:
type: object
description: List of all media with added `distance` property
properties:
data:
type: array
items:
allOf:
- type: Media
- properties:
distance:
type: number
but correct conversion is:
responses:
'200':
body:
application/json:
type: object
description: List of all media with added `distance` property
properties:
data:
type: array
items:
type: Media
properties:
distance:
type: number
As stoplight app doesn't have the support.
Resource paths which use resourceTypes do not get converted to Swagger.
Check this section on swagger spec. Besides all other valid http status code, swagger also has concept of 'default' code, which represents all codes which aren't presented in the spec.
At this moment, this code is converted to '400' http code, when imported. But it has two potential problems:
@marbemac , I would like to hear about your thoughts on this.
(May be not anything urgent as on import functionality)
Would be nice to execute the converter from your CLI :)
Take the following Swagger example:
Manager:
allOf:
- $ref: '#/definitions/User'
- type: object
properties:
manager_attribute:
type: string
manager_attribute1:
type: string
This should be mapped as the following RAML:
Manager:
type: User
properties:
manager_attribute:
type: string
manager_attribute1:
type: string
Take this other Swagger example:
Manager:
allOf:
- $ref: '#/definitions/User'
- $ref: '#/definitions/Category'
This should be mapped as the following RAML:
Manager:
type: [User,Category]
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.