Giter VIP home page Giter VIP logo

api-elements's Introduction

API Elements

API Elements is a structure for describing APIs and the complex data structures used within them. It also provides structures for defining parsing results for parsing API definitions from formats like API Blueprint and Swagger/OpenAPI Format.

Documentation and Reference

Please refer to the documentation and reference for more information.

api-elements's People

Contributors

danielgtaylor avatar earth2marsh avatar honzajavorek avatar jackub avatar klokane avatar kylef avatar pksunkara avatar smizell avatar tjanc avatar w-vi avatar zdne avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

api-elements's Issues

Exposing Deployment Information

This is an issue to propose / discuss how we should expose information on where a particular API is deployed.

Current Support

API Blueprint

The API Blueprint does not include any support for describing the deployment information. API Blueprint does allow metadata at the top of an API Blueprint. Many tools use the metadata HOST which can be a URL to where the API may be deployed.

HOST: https://example.com/v2/

This is translated to metadata attribute for an API Category in API Elements:

{
  "element": "member",
  "meta": {
    "classes": {
      "element": "array",
      "content": [
        {
          "element": "string",
          "content": "user"
        }
      ]
    }
  },
  "content": {
    "key": {
      "element": "string",
      "content": "HOST"
    },
    "value": {
      "element": "string",
      "content": "https://example.com/v2/"
    }
  }
}

Swagger 2

Swagger 2 provides support for deployment information with schemes (array) host and basePath. Our adapter takes the first schema and host and places that in the same metadata section as API Blueprint so that the value is in a format that is already used by tooling and didn't require tooling updates.

schemes: [https]
host: example.com
basePath: /v2/

The above Swagger 2 structure would result in a HOST metadata of https://example.com and basePath would be prepended into every href found in the parse result which perhaps isn't the most ideal way to handle it. The problem is that the basePath may be supplied without a host and thus couldn't be exposed as HOST metadata.

{
  "element": "member",
  "meta": {
    "classes": {
      "element": "array",
      "content": [
        {
          "element": "string",
          "content": "user"
        }
      ]
    }
  },
  "content": {
    "key": {
      "element": "string",
      "content": "HOST"
    },
    "value": {
      "element": "string",
      "content": "https://example.com"
    }
  }
}
basePath: /v2/
paths:
  /user
{
  "element": "resource",
  "attributes": {
    "href": {
      "element": "string",
      "content": "/v2/user"
    }
  },
  "content": [...]
}

OpenAPI 3

In OpenAPI 3 a lot of server information including server variables may be described. See https://github.com/OAI/OpenAPI-Specification/blob/50c152549263cda0f05608d514ba78546b390d0e/versions/3.0.0.md#server-object or more details.

API Elements evolution process

I'm opening this issue to create a discussion around how we should handle the evolution of API Elements. I would like to involve relevant parties when introducing new element types, the discussion on how new elements may be consumed by tools like console, dredd, governance etc can bring in design considerations to the element itself. It perhaps makes sense that someone from these respective tools provide any insight during the design of new elements.

The IRCv3 Working Group and the OpenAPI have been using "draft" proposals. The feature can be introduced as a draft so that the surrounding functionality can be tested out in implementations and ratified once the feature has been successfully implemented. Perhaps this isn't the flow that all changes should make. One future propsal for API Elements is regarding deployment information that can have a large impact on other tools like such as consoles, documentation renderers and API Gateways. The current proposal at #53 can grant a lot of flexibility and may be difficult to implement. This can also be a way to ensure that we are not introducing features into API Elements that will suffer from under-adoption, we don't want to be adding features into API Elements that are not going to be used in tooling. This is one problem that I can see with some of the new OpenAPI 3.0 features, the adoption rate is relatively low with various tooling not implementing some subset of the features.

Perhaps we can prefix elements with draft- and test them out in the surrounding tooling before committing to making them final. From IRCv3, there are three types of consumers (Servers, Bouncers and Clients). Finalising a new specification can require implementation in two of each kind, for example: ircv3/ircv3-specifications#378. Perhaps following a similiar model can make sense.

TL;DR: Who should we involve in the design of new API Element features?

Multiple responses

Hey team ๐Ÿ‘‹

As I'm reading the spec I'm trying to understand why a httpTransaction can only contain one httpResponse. Any insight you can share there?

Hypermedia Affordances

Hello friends :)

I'd like to propose adding functionality that would allow for defining hypermedia affordances in API Elements. This would require we have a section for defining affordances and a way to list what affordances we expect for a given response.

Reason

Right now, you need an additional format for defining hypermedia controls for an API, whether it's Swagger or API Blueprint. This would provide the ground work for this in those formats along with being a foundation for moving towards Resource Blueprint.

Specification Change Proposals

Category for Affordances

For this, we will simply need to specify a category class for for affordances. I would propose affordances for this. This category may be found in the API category or the resource category, allowing users to define global and resource-specific affordances.

Affordance Element

  • element: affordance
  • attributes
    • controlType (enum)
      • safe - A hypermedia control that triggers a safe, idempotent state transition (e.g. HTTP.GET or HTTP.HEAD).
      • unsafe - A hypermedia control that triggers an unsafe, non-idempotent state transition (e.g. HTTP.POST).
      • idempotent - A hypermedia control that triggers an unsafe, idempotent state transition (e.g. HTTP.PUT or HTTP.DELETE).
  • content (array)
    • (Copy)

The control types are borrowed from ALPS section 2.2.12. The meta.id value would be used to specify the name of the affordance.

For the element, the origin link SHOULD be used whenever an affordance (i.e. link relation) is being used that is defined elsewhere. For example, if the self link relation is being used, it could specific https://tools.ietf.org/html/rfc4287 as its origin.

The content of this element can later be used for defining other data for the affordance, such as fields for the affordance.

Response Affordances

We would then alter the HTTP response to allow for the new affordance category to be used in the content. There, ref elements will be used to reference already-defined affordances.

The presence of these affordances in a response tell the consumer that in the given transaction, these affordances SHOULD be found. This is also not specific to any hypermedia format, which goes along with the idea of data structures not being for a specific data format.

Transition Relation

Once affordances can be defined, they should be able to be used within the relation attribute for transitions. This would mean that we should add a clause specifying users that they SHOULD provide an affordance definition when using a relation. Consumers are free to throw errors in situations where a relation is used by not defined.

Other Considerations

API Blueprint

Once defined, API Blueprint could provide a section for defining link relations that would line up with the relations used within the transition. It could also be changed to provide an affordance/link relation section in a response.

Dredd Usage

Once this is in place, Dredd could be used to test expectations of hypermedia affordances. This kind of tooling is really missing in defining and testing hypermedia APIs. I've personally had to build my own tooling to make this work.

Final Thoughts

In addition to ALPS and Resource Blueprint, I have experimented with this idea here. I'd love to see formats make this available, and my proposal for adding this here in API Elements first to make that possible.

Also, I'd be happy to put together a pull request for this. Just want to put together this proposal to see what people think.

Annotation "fixits"

I've been thinking about this for a long time and I think it would be great if a warning or error annotations could provide hints to users on what to change to resolve the warning/error. Allowing editors to provide tool tips so a user can "fix" a problem with a single tap or keystroke.

In the future this would also pave the way allowing us to deprecate older syntaxes in API Blueprint providing users a "one click" upgrade button. "Parameter syntax is deprecated" -> "Fix: Migrate to new parameter syntax".

The Xcode IDE supports fixits and it looks something like this:

Xcode fixit

The IDE provides keyboard shortcuts to also "fix all" when there are numerous changes such as with deprecations or language changes.

For example, in API Blueprint there could be a warning about overshadowing an existing parameter name and the parser could offer an annotation to allow user to delete the existing parameter.

# View Posts [GET /posts{?since,abc}]

+ Parameters
    + since (datetime)
    + abc (string)
    + since (datetime)

A parser could warn the user that the since parameter was overshadowed and that they may delete the shadowed parameter.

I'm not too sure how to represent deletions, changes and additions in an element but something along the lines of the following:

{
    "element": "annotation",
    "content": [
        {
            "element": "copy",
            "content": "overshadowing previous parameter 'example' definition"
        },
        {
            "element": "fixit",
            "meta": {
                "title": "Delete shadowed 'since' parameter"
            },
            "content": [
                {
                    "element": "removal",
                    "content": [13, 24]
                }
            ]
        }
    }
}

Another example could be with the following API Blueprint snippet where a user has created a parameter but forgot to place it in the path.

# View Posts [GET /posts]

+ Parameters
    + since (datetime)

Warning: "since" parameter is not found in the path.
Fixit: Change path to /posts{?since}


As I said, I'm not too sure on how to represent diffs in a clear format that an editor would be able to easily apply onto a document so welcome to any suggestions.

Fixit types that should be supported

  • Deleting a block of code
  • Adding a block of code
  • Changing a block of code

/c @XVincentX You might be interested in this for Apiary editor and also your MS Code Plugin.

Provide information about the source ADD format and version

I think it would make sense that we provide information in the parse result (or API Element) that contains some information about the source document such as the format itself (Swagger, OpenAPI, API Blueprint) and the version of that format.

Although the goal of API Elements is that the format is canonical and the original source shouldn't matter. When telling users about the errors/warnings or linking to the underlying specification it can be needed. I believe Apiary editor for example tells the user the format used in the error/warning messages so it has to detect this itself.

I think this should be in form of a link element in the parse result to the specific format/version, the link element can contain a title. I am not entirely sure what link relation we should use, I've used via in the example, we should ensure that is semantically correct.

  1. The value "via" signifies that the IRI in the value of the href
    attribute identifies a resource that is the source of the
    information provided in the containing element.

For example:

This could perhaps look something like:

{
  "element": "parseResult",
  "meta": {
    "links": [
      {
        "element": "link",
        "attributes": {
          "title": {
            "element": "string",
            "content": "OpenAPI"
          },
          "relation": {
            "element": "string",
            "content": "via"
          },
          "href": {
            "element": "string",
            "content": "https://spec.openapis.org/oas/v3.0.1"
          }
        }
      }
    ]
  }
}

Make `HTTP Headers` an array of `HTTP Header`

Currently, HTTP Headers is a subtype of Object Element. But a HTTP Header can occur multiple times, which means HTTP Headers should be an array of HTTP Header.

Proposal

  1. Introduce new element named HTTP Header which is subtype of Member Element
  2. Make HTTP Headers array of HTTP Header

Single API Elements Package

Deprecate minim-parse-result and minim-api-description and have a single api-elements package which depends on minim, and contains code from the deprecated packages.

Remove `annotation` code

Annotation Code's are difficult to use for any meaning as they are not universally unique. One parser can treat one code with some meaning and another parser could treat the exact same code with another meaning.

This is already the case with the Fury Swagger adapter and API Blueprint parser. To the Swagger parser, code 3 is for features that are not supported (https://github.com/apiaryio/fury-adapter-swagger/blob/master/src/annotations.js#L17) and in Drafter code 3 is used for other validations (https://github.com/apiaryio/drafter/blob/4b5ae151e0a40f4a53bf07a86b4ea8fabb70ca7e/test/fixtures/parse-result/error-warning.json#L90). These code numbers provide real no benefit to consumers.

I believe that profile or origin links are better suited for a consumer to understand the semantics behind an annotation. Origin links are already available in the Swagger parser but are missing from Drafter API Blueprint parser. These links provide a reliable way for a consumer to understand the semantics behind an annotation, it also provides the consumer a way to follow a link for further information.

{
  "element": "annotation",
  "attributes": {
    "code": {
      "element": "number",
      "content": 5
    }
  },
  "content": "something was wrong"
}

vs

{
  "element": "annotation",
  "meta": {
    "links": [
      {
        "element": "link",
        "attributes": {
          "relation": { "element": "string", "content": "profile" },
          "href": { "element": "string", "content": "https://apielements.org/1/warnings/validation" },
        }
      }
    ]
  },
  "content": "something was wrong"
}

Would love to hear your opinions @smizell / @w-vi.

Issues with inital PR

This list is imported from #1, and should be updated with links to issues or pull requests as they are created. Checkboxes should be marked for completed items. When all items are complete, please close this issue!

  • When it is set, do you merge the values with those in the parent transition/resource or do the httpRequest hrefVariables completely override them? I think we should be explicit here.
  • MSON is introduced here with no explanation. Should we put a note about it or something?
  • #1 (comment)
  • #1 (comment)
  • #1 (comment)
  • #1 (diff)
  • #1 (comment)

Clarify source map type

There are discrepancies in the API Blueprint parser and Swagger adapter because of source map positions are treated differently (https://github.com/apiaryio/fury.js/issues/63).

In Swagger adapter, the source map represents the position of a character in a JavaScript string. Whereas the API Blueprint parser (snowcrash/drafter) will craft source maps based on the byte offset in the underlying buffer.

We need to decide how source maps should be represented and then align the adaptors.

/cc @w-vi

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.