<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[RAML by Example - Medium]]></title>
        <description><![CDATA[RAML examples and APIs - Code &amp; snippets available at: https://github.com/raml-org/raml-by-example - Medium]]></description>
        <link>https://medium.com/raml-api?source=rss----9528792001c3---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>RAML by Example - Medium</title>
            <link>https://medium.com/raml-api?source=rss----9528792001c3---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Thu, 09 Apr 2026 21:47:56 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/raml-api" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[API Console version 6 is released]]></title>
            <link>https://medium.com/raml-api/api-console-version-6-is-released-2e266ba6ace1?source=rss----9528792001c3---4</link>
            <guid isPermaLink="false">https://medium.com/p/2e266ba6ace1</guid>
            <category><![CDATA[openapi-specification]]></category>
            <category><![CDATA[api-console]]></category>
            <category><![CDATA[raml]]></category>
            <category><![CDATA[api-documentation]]></category>
            <category><![CDATA[mulesoft]]></category>
            <dc:creator><![CDATA[Pawel Uchida-Psztyc]]></dc:creator>
            <pubDate>Tue, 28 Jan 2020 23:40:50 GMT</pubDate>
            <atom:updated>2020-01-28T23:40:50.444Z</atom:updated>
            <content:encoded><![CDATA[<h3>Document your RAML and Open API definitions with API Console v6</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dixsjuM3eFYDOHclncnjMg.png" /></figure><p>I am happy to announce that a new version of API Console is now available. It brings multiple changes and new tooling. Read more to learn what’s new in this release.</p><p>API Console is an application to automatically generates documentation for an API from a RAML or Open API definition. It is done by generating an AMF data model thanks to the AMF parser or the “<a href="https://github.com/raml-org/webapi-parser">webapi-parser</a>” module. The console is built on top of web platform APIs so it can be easily integrated with every web based application. It comes in two flavors: a stand-alone application and a web component. Depending on your use case you may use either of them.</p><p>The stand-alone application allow you to quickly generate documentation for an API and run it on a web server as a separate application. We are providing a CLI tool to generate the application from sources and a Docker image to simplify the deployment. The web component is to be used if you want to integrate the console with an existing application. This requires more setup and development process but allows for the most flexibility.</p><h3>What’s new in version 6?</h3><p>API Console is now WCAG compliant. During the development process we put a lot of effort into making sure that the console is accessible for users with disabilities. This version is tested via automated software and via manual testing.</p><p>The updated UI implements changes requested by our customers and the community. The navigation has a slightly different structure and now always renders a full path to the resource, even when it exceeds the size of a single line menu item. New examples and annotation widgets makes the UI more user friendly.</p><p>The request editor (aka “try it”) has been redesigned to simplify interaction with the API. It now only renders fields that require input from the user to make a successful request. This means, for example, if headers are not defined for an operation then they are not rendered.</p><p>With this release we added more security by sanitizing markdown data that are being rendered. Also, user input in the request editor is tested against invalid data.</p><h3>Improvements to the console</h3><p>Most improvements are related to performance. The size of the bundle has been reduced almost 4 times and now the bundled API Console weight is ~300KB. This speeds up console rendering time and improves memory footprint.</p><p>In the documentation view complex types are now hidden by default. This reduces potential crashes when the documentation has huge type declarations. In previous versions of the console this would lead to tabs crashing. Similarly, huge examples generated for such types are not highlighted by default. Previously it would require the browser to render unreasonable amount of markup that would hang the tab for minutes.</p><p>The console’s source has been rewritten to use the latest web standards which puts most of the work to the browser instead of JavaScript. This improves overall experience as the console runs smoothly regardless of the size of the API. The console still works with legacy browsers (down to IE11) with polyfills generated with the bundle.</p><h3>Developer improvements</h3><p>Being as close to standards as possible was rule #1 when designing architecture for API Console and the build tools. The console now follows <em>Open WC</em> standards for development and building processes. Application specific code related to the development and building process has been reduced to the minimum.</p><p>API Console has its own node module and CLI command to generate a bundle in a CI environment or manually. Besides that with this release we offer a Docker image that has bundled API Console, AMF parser, and a web server with it. As a developer you just need to pass an API project to generate data model from it and run the image on your Kubernetes instance.</p><h3>Reasons to choose API Console</h3><p>API Console is and will be in active development as it is one of the core Anypoint platform products while being an open source project. The console is tested in an enterprise environment and runs in both public and private clouds. It fulfills all requirements for an application to run in government’s cloud.</p><p>We have experience with building API documentation products supported by several years of development of API Console and other products like Advanced REST Client. We are open to suggestions and over the years we have listened to the voice of the community and our customers. Today we are proud of the final effect of our work and happy to share this experience with the community.</p><h3>How to get started?</h3><p>We’ve prepared a few demos with basic use cases for API Console. You can check it out at <a href="https://demo.api-console.io/">demo.api-console.io</a>. For developers we have prepared a documentation page at <a href="https://docs.api-console.io/">docs.api-console.io</a>.</p><p>Try API Console today and give us your feedback. We accept issue reports and feature requests on console’s <a href="https://github.com/mulesoft/api-console/issues">GitHub page</a>. If you are MuleSoft customer you can contact customer support and gives us your feedback directly.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2e266ba6ace1" width="1" height="1" alt=""><hr><p><a href="https://medium.com/raml-api/api-console-version-6-is-released-2e266ba6ace1">API Console version 6 is released</a> was originally published in <a href="https://medium.com/raml-api">RAML by Example</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[RAML And OAS Support In API Console]]></title>
            <link>https://medium.com/raml-api/oas-and-raml-support-in-api-console-4842fe009768?source=rss----9528792001c3---4</link>
            <guid isPermaLink="false">https://medium.com/p/4842fe009768</guid>
            <category><![CDATA[api-console]]></category>
            <category><![CDATA[nodejs]]></category>
            <category><![CDATA[aos]]></category>
            <category><![CDATA[raml]]></category>
            <category><![CDATA[api-portal]]></category>
            <dc:creator><![CDATA[Pawel Uchida-Psztyc]]></dc:creator>
            <pubDate>Wed, 16 Jan 2019 22:20:49 GMT</pubDate>
            <atom:updated>2019-01-18T02:03:19.831Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8IVvs_D7fdLiEyQLgv_omQ.png" /></figure><p>Last year the CTO of MuleSoft, Uri Sarid, <a href="https://blogs.mulesoft.com/dev/api-dev/open-api-raml-better-together/">announced</a> that the company is joining the Open API Initiative of the Linux Foundation. This extended MuleSoft’s investment in open specs (RAML) and open source API tooling to also embrace the Open API specification (OAS), as part of its investment in modeling any domain via the Anything Modeling Language (AML) and the open source AML Modeling Framework (AMF). AMF provides automatic interoperability between RAML, which is optimized for modeling HTTP APIs, and OAS, which is a ubiquitous description format for HTTP APIs.</p><p>Today I am proud to announce that MuleSoft’s open source <strong>API console</strong> now supports both RAML and OAS to automatically generate API documentation. This is a part of initiative we started a year ago to add OAS support to Anypoint Platform. Now you can use best in class API documentation tool without worrying about technicalities like API specification format.</p><p>This is possible thanks to <a href="https://a.ml/">AML</a> (Anything Modeling Language) and related AMF (AML Modeling Framework). AMF allows to parse RAML and OAS files and produces common data model which is then used in API console to generate the view.</p><p>API console comes as a standalone web application and as a set of web components that are highly embeddable in any web environment. This web components — the API components — are open source and can be used to embed API documentation into your existing web page without any limitations. Theming system based on CSS variables allows to style API console according to organization’s corporate style guide. Our developer build tools helps developers to create production ready bundles so the API console can be used across all browsers and web environments. Finally world class design and convenient request editor allows your customers experience the API and learn your products faster.</p><p>See our demo page for Google Drive API at <a href="https://mulesoft.github.io/api-console/">https://mulesoft.github.io/api-console/</a></p><h3>Build an API portal from your API specification</h3><p>It is very easy to build an API portal thanks to our CLI tool (Command Line Interface). This section demonstrates how to build an API portal with just few command line commands.</p><p>First make sure you have Node.js installed. Open you terminal and type</p><pre>node --version</pre><p>This should output something like:</p><pre>pawel@pawel-pc:~$ node --version<br>v8.11.2</pre><p>If it says that the program cannot be found then you have to install Node.js on your machine. To do this follow instructions from <a href="https://nodejs.org/en/download/">https://nodejs.org/en/download/</a></p><p>The next step is to install our CLI tool (no need for sudo command when using Windows)</p><pre>sudo npm i -g api-console-cli</pre><p>After few seconds the CLI tool is installed and we can build an API portal. Navigate to your API directory</p><pre>cd location/of/api</pre><p>Now run the build command to generate the API. The tool supports build command that has several options. Run api-console build --help to see description for all of them. The most important are:</p><ul><li>-a the location of the API main file</li><li>-t type of the API spec format, it can be RAML 0.8, RAML 1.0, OAS 2.0, or OAS 3.0 (currently in beta)</li><li>-o where to put the result, default to build folder in current directory</li></ul><p>Run the final command replacing parameters with your API file name and the type.</p><pre>api-console build -a api.raml -t &quot;RAML 1.0&quot; -o api-portal</pre><p>It may take about a minute to build the console. If you run into trouble caused by reaching memory limit, add NODE_OPTIONS=--max_old_space_size=2048 prefix to the command (MacOS, Linux) or set NODE_OPTIONS=--max_old_space_size=2048 on Windows. This prefix sets memory limit for node process to 2GB.</p><p>When ready run api-console serve command to see your portal</p><pre>api-console serve --open api-portal</pre><p>The --open argument tells the program to open the portal in the default browser.</p><p>That’s it! You can now copy generated files to your server and use them to publish your API portal. If you need more advanced build options (like in continuous integration pipeline) you can use our <a href="https://www.npmjs.com/package/@api-components/api-console-builder">npm module</a> to perform the build.</p><p>It is also possible to generate the API Console as a web component and use it to embed API documentation into existing web page. Refer to our <a href="https://github.com/mulesoft/api-console/blob/master/docs/api-console-element.md">docs</a> for more information.</p><p>We are happy to hear from you about your experience with API Console and our build tools. Leave us comment, create issue report at <a href="https://github.com/mulesoft/api-console">mulesoft/api-console</a> repository page or email us at api-console@mulesoft.com.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4842fe009768" width="1" height="1" alt=""><hr><p><a href="https://medium.com/raml-api/oas-and-raml-support-in-api-console-4842fe009768">RAML And OAS Support In API Console</a> was originally published in <a href="https://medium.com/raml-api">RAML by Example</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The future of SDKs for the web platform]]></title>
            <link>https://medium.com/raml-api/the-future-of-sdks-for-the-web-platform-911cb043e068?source=rss----9528792001c3---4</link>
            <guid isPermaLink="false">https://medium.com/p/911cb043e068</guid>
            <category><![CDATA[layered-api]]></category>
            <category><![CDATA[raml]]></category>
            <category><![CDATA[sdk]]></category>
            <category><![CDATA[proposal]]></category>
            <category><![CDATA[api]]></category>
            <dc:creator><![CDATA[Pawel Uchida-Psztyc]]></dc:creator>
            <pubDate>Wed, 21 Nov 2018 19:28:38 GMT</pubDate>
            <atom:updated>2018-11-26T21:59:29.426Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Vl7e2MS9uwQiQ-O5XcIigw.png" /></figure><p>Recently, at Chrome Dev Summit, <a href="https://medium.com/u/cd07b5efccce">Gray Norton</a> was talking about a new proposal for the web platform (a set of specifications for how browsers render web pages): <a href="https://www.chromestatus.com/feature/6555299569729536">Layered APIs</a>. It was a great talk about how we can standardise high level APIs using ES6 modules. At the end of the talk Gray asked if anyone had an idea for new primitives or modules for the web. I am answering that call.</p><p>At MuleSoft, I create tools to make REST API development easier for developers. I’ve spent the last 3 years creating a set of web components dedicated to API documentation and testing. Another area that interest me is SDKs. The current state of play is that the REST API owner has to produce the documentation for that API and the SDKs for each targeted platform. At Mulesoft, we responded to the first need by creating <a href="https://github.com/mulesoft/api-console">API Console</a>, a web component which generates documentation for an API. As long as you model your API using RAML or OAS, you can use it to create an API portal or embed the documentation to existing website. As for SDKs, there are tools that generate bundles for different platforms using API spec files. But still, the owner of the API has to publish and document the SDK. I’d like to change this state because I think it is inefficient and because we, as a community, can do better.</p><p>What if the <strong>browser was able to understand an API and auto-generate the web SDK</strong> for a website? In this world all SDKs generated by the browser have unified interface so a web developer has to learn how to use the web SDK once and then only the API structure using API documentation tool. To do this, 3 things would have to happen. First the browser has to get the API definition. We can use the existing &lt;link&gt; element for that.</p><pre>&lt;link rel=&quot;api&quot; type=&quot;RAML 1.0&quot; href=&quot;api.raml&quot; title=&quot;my-api&quot;&gt;</pre><p>I’m proposing a new value for the “rel” attribute: api. It means that the external resource is an API model and should be read as such. The “type” attribute refers to the API definition format. It can be RAML or OAS. Finally “title” would be used to reference the API in the JavaScript interface.</p><p>Second thing to do is to parse the API. MuleSoft developed an open source <a href="https://a.ml/">AML</a> (Anything Modeling Language) and <a href="https://github.com/aml-org/amf">AMF</a> (AML Modeling Framework). It provides a common programming interface that lets developers interact with any API specification. AMF can be used to generate a common API model from every API native format.</p><p>Finally the browser would generate a JavaScript interface for the API based on the information read from the referenced spec and cache the result locally so next time it skips the downloading and parsing process (that is a very high level description of this part).</p><p>API parsing and generating can take some time so the operation has to be asynchronous.</p><pre>&lt;script&gt;<br> await navigator.sdk.ready();<br> const sdk = await navigator.sdk.api(&#39;my-api&#39;);<br> const response = await sdk.api.profile.me.get();<br> const profile = await response.json();<br>&lt;/script&gt;</pre><p>The first step is to ensure that all referenced APIs in the head section has been downloaded by the browser. The second step is to parse a specific API and return a reference to the generated SDK. The SDK reflects the structure of the API. It contains the authentication methods, the model definitions, and the structure. For example, the api.profile.me.get() performs a GET request to /profile/me endpoint.</p><p>Functions that calls an endpoint can accept the init argument which is the same as the Request object of the Fetch API.</p><pre>&lt;script&gt;<br> const init = {<br>  headers: {&#39;x-api-key&#39;: &#39;....&#39;}, <br>  body: JSON.stringify({<br>    ...<br>  });<br> };<br> const response = await sdk.api.todos.post(init);<br>&lt;/script&gt;</pre><p>To validate user input against the API specification, we could use the validation property of the sdk object.</p><pre>&lt;script&gt;<br> const init = {<br>  headers: {&#39;x-api-key&#39;: &#39;....&#39;}, <br>  body: JSON.stringify({<br>    ...<br>  });<br> };<br> const validationResult = sdk.validation.todos.post(init);<br> console.log(validationResult.valid);<br> console.log(validationResult.messages);<br>&lt;/script&gt;</pre><p>Most of APIs requires some form of <strong>Authentication</strong>. This is modeled in the API specification. The browser would fail the request when the user is not Authenticated. The WebSDK also exposes the interface to perform authentication.</p><pre>&lt;script&gt;<br> const config = {<br>  type: &#39;OAuth 2.0&#39;, <br>  grantType: &#39;implicit&#39;, <br>  interactive: true, <br>  clientId: &#39;....&#39;,<br>  redirectUri: &#39;...&#39;<br> };<br> if (!sdk.auth.isAuthenticated(config)) {<br>  await sdk.auth.authenticate(config);<br> }<br>&lt;/script&gt;</pre><p>The isAuthenticated() function checks if the user is authenticated for a given configuration. The configuration structure depends on the authentication type. It requires providing configuration options for the authentication type and node defined in the API definition. Finally it allows to authenticate() the user by performing actions like rendering an auth popup or username/password dialog.</p><p>So far this was a brief description of the proposal for a web primitive. It gives a low level API so frameworks and developers can build on top of it. However with the “layered APIs” spec we could do better. Imagine declarative API calls using HTML, e.g.:</p><pre>&lt;script type=&quot;module&quot; src=&quot;std:web-sdk&quot;&gt;&lt;/script&gt;<br>&lt;script type=&quot;module&quot; src=&quot;std:web-sdk-authentication&quot;&gt;&lt;/script&gt;<br>&lt;script type=&quot;module&quot; src=&quot;std:web-sdk-request&quot;&gt;&lt;/script&gt;</pre><pre>&lt;web-sdk api=&quot;my-api&quot; id=&quot;api&quot;&gt;<br> &lt;web-sdk-authentication client-id=&quot;...&quot; redirect-url=&quot;...&quot; id=&quot;auth&quot;&gt;&lt;/web-sdk-authentication&gt;<br> &lt;web-sdk-request endpoint=&quot;/users/me&quot; method=&quot;GET&quot; id=&quot;profile&quot;&gt;&lt;/web-sdk-request&gt;<br>&lt;/web-sdk&gt;</pre><pre>&lt;script type=&quot;module&quot;&gt;<br> api.addEventListener(&#39;ready&#39;, () =&gt; {<br>  if (!auth.isAuthenticated()) {<br>    auth.authenticate();<br>  }<br> });</pre><pre> auth.addEventListener(&#39;authenticated-changed&#39;, (e) =&gt; {<br>  console.log(&#39;User authenticated: &#39;, e.target.authenticated);<br> });</pre><pre>profile.addEventListener(&#39;api-response&#39;, (e) =&gt; {<br>  e.target.response.json()<br>  .then((profile) =&gt; console.log(profile));<br> });<br>&lt;/script&gt;</pre><p>This would import 3 standard modules required for the web API to work: “web-sdk” would be the framework, “web-sdk-authentication” would manage user sessions and “web-sdk-request” would perform API calls. The framework takes care of downloading and parsing the API spec file. Once it is ready, all APIs are available to use. When the user is authenticated, or when the endpoint does not require authorization, the “web-sdk-request” module issues the request to the server. The application listens for an event that indicates the response is ready. The event is dispatched once the API call ends.</p><p>This is just a beginning of a web API proposal to the web platform spec. I hope we will be able to start the discussion with Chrome, Firefox, Edge and Safari teams on this proposal. This would change the way we consume APIs in the web platform.</p><p>Please leave a comment or feel free to contact me if you are interested in standardizing this API. Meanwhile check the project page for polyfills and technical description: <a href="https://github.com/advanced-rest-client/web-sdk">https://github.com/advanced-rest-client/web-sdk</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=911cb043e068" width="1" height="1" alt=""><hr><p><a href="https://medium.com/raml-api/the-future-of-sdks-for-the-web-platform-911cb043e068">The future of SDKs for the web platform</a> was originally published in <a href="https://medium.com/raml-api">RAML by Example</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using RAML-For-JAX-RS for Brewing (Part II): Building a better model]]></title>
            <link>https://medium.com/raml-api/using-raml-for-jax-rs-for-brewing-part-ii-building-a-better-model-d98112b12aac?source=rss----9528792001c3---4</link>
            <guid isPermaLink="false">https://medium.com/p/d98112b12aac</guid>
            <category><![CDATA[brewing]]></category>
            <category><![CDATA[jax-rs]]></category>
            <category><![CDATA[raml]]></category>
            <category><![CDATA[java]]></category>
            <dc:creator><![CDATA[JP Belanger]]></dc:creator>
            <pubDate>Tue, 31 Jul 2018 16:15:43 GMT</pubDate>
            <atom:updated>2018-07-31T16:15:42.550Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4ZcYv6GoVg-CgsnAKZk6NQ.png" /><figcaption><a href="https://github.com/mulesoft-labs/raml-for-jax-rs">raml-for-jax-rs on Github</a></figcaption></figure><p>Welcome back!</p><p>We <a href="https://medium.com/raml-api/using-raml-for-jax-rs-for-brewing-586eb041361c">left off our discussion</a> with a rather simple model that was somewhat too simple to be useful. It had only simple types and relatively little to help the developer handle changes. Let’s see if we can make this better.</p><p>Before we start, we’ll remove the plugin defined in the pom.xml file. Although it’s often simpler to activate the Jackson plugin in the pom.xml file, I’m of the opinion that having to run around the multiple files used in a build to figure out what to do is a bad practice. We’ll be controlling everything RAML from the RAML files. So we will be removing the generateWithTypes tag from our maven file <a href="https://github.com/jpbelang/BeerTrader/blob/better-model-medium/model/pom.xml#L41-L46">&lt;configuration/&gt;</a>.</p><pre>&lt;build&gt;<br>        &lt;plugins&gt;<br>            &lt;plugin&gt;<br>                &lt;groupId&gt;org.raml.jaxrs&lt;/groupId&gt;<br>                &lt;artifactId&gt;raml-to-jaxrs-maven-plugin&lt;/artifactId&gt;<br>                &lt;version&gt;3.0.2&lt;/version&gt;<br>                &lt;executions&gt;<br>                    &lt;execution&gt;<br>                        &lt;goals&gt;<br>                            &lt;goal&gt;generate&lt;/goal&gt;<br>                        &lt;/goals&gt;<br>                    &lt;/execution&gt;<br>                &lt;/executions&gt;<br>                &lt;configuration&gt;                    <br>                   &lt;ramlFile&gt;<br>                    ${project.build.resources[0].directory}/api.raml<br>                   &lt;/ramlFile&gt;<br>                  &lt;resourcePackage&gt;<br>                   org.raml.jaxrs.beertrader.resources<br>                  &lt;/resourcePackage&gt;                              <br>                  &lt;supportPackage&gt;<br>                    org.raml.jaxrs.beertrader.support<br>                  &lt;/supportPackage&gt;<br>                  &lt;modelPackage&gt;<br>                    org.raml.jaxrs.beertrader.model<br>                  &lt;/modelPackage&gt;<br>                &lt;/configuration&gt;<br>            &lt;/plugin&gt;<br>        &lt;/plugins&gt;<br>    &lt;/build&gt;</pre><p>We are still generating resource classes and objects, but right now we aren’t generating Jackson annotations. We’ll address this a bit later.</p><p>Back to the model. Firstly, we would like our key and reference types to be UUIDs. That’s what we are using in our database system, and it seems to be a good idea to expose this. The problem here is that UUIDs are not part of the RAML specification. All we have are strings. Hmmm.</p><p>We’ll start by declaring a type called UUID in our RAML specification. UUIDs are, after all, strings. So we’ll start here.</p><pre>UUID:<br>   type: string<br>   pattern: &quot;[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}&quot;</pre><p>We could then use this type like so, in a RAML spec:</p><pre>Beer:<br>  properties:<br>   id: UUID</pre><p>This would be a valid declaration, and the parser handles it correctly. But <a href="https://github.com/mulesoft-labs/raml-for-jax-rs/tree/master/raml-to-jaxrs">raml-to-jaxrs</a> still sees it as a string type, and will, by default generate a java.lang.String. If only we could tell it otherwise…</p><p>Well, quite obviously, we can. I wouldn’t be typing all of this without a reason.</p><p><a href="https://github.com/mulesoft-labs/raml-for-jax-rs/tree/master/raml-to-jaxrs">raml-to-jaxrs</a> allows us to change some of these types (among other things) through a plugin system. The plugin system is activated through RAML annotations. We need to import a RAML Library fragment that defines those annotations in order for raml-to-jaxrs to change its behaviour. In the <a href="https://github.com/mulesoft-labs/raml-java-tools">raml-java-tools</a> project, we’ll find a file called <a href="https://github.com/jpbelang/BeerTrader/blob/better-model-medium/model/src/main/resources/ramltopojo.raml">ramltopojo.raml</a>. We can add it to our project and bring it into our <a href="https://github.com/jpbelang/BeerTrader/blob/better-model-medium/model/src/main/resources/api.raml#L10">spec</a> with:</p><pre>#%RAML 1.0<br>title: The BeerTrader api<br>description: This is the API for the world famous Beer Trader API<br>version: v1<br>baseUri:<br>  value: <a href="http://www.beertrader.com/services/{version">http://www.beertrader.com/services</a><br>protocols: [  HTTP, HTTPS ]<br>mediaType: [ application/json ]<br>uses:<br>  <strong>ramltopojo: ramltopojo.raml</strong></pre><p>This file pulls in plugin support for raml-to-pojo, the library that handles RAML types. We will then <a href="https://github.com/jpbelang/BeerTrader/blob/better-model-medium/model/src/main/resources/api.raml#L42-L45">activate</a> the core.changeType plugin to tell the code generator to use the java.util.UUID type instead of java.lang.String.</p><pre><strong>UUID:<br>    (ramltopojo.types):<br>      plugins:<br>        </strong>- <strong>name: </strong>core.changeType<br>          <strong>arguments: </strong><em>[ </em>java.util.UUID <em>]<br>      </em><strong>type: </strong>string<br>      <strong>pattern: </strong>&quot;[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}&quot;</pre><p>The good thing about this is that Jackson will handle UUIDs properly without any more adjustments, so it’s a pretty simple way of using proper types. Had Jackson not supported the type, we would have had to <strong>write</strong> a plugin to use annotations or some such. But we don’t, so we won’t this week.</p><p>Ok, we’ve moved one step closer to a better model. Huzzah.</p><p>Here’s another thing I like to do: have a top-level class for my objects. All my objects will have an ID (think of it like a URN). So let’s <a href="https://github.com/jpbelang/BeerTrader/blob/better-model-medium/model/src/main/resources/api.raml#L50-L52">build</a> that top class:</p><pre>Identified:<br><strong>    (ramltopojo.types):<br>      plugins:<br>        - core.makeAbstract<br></strong>    additionalProperties: false<br>    properties:<br>      id: UUID</pre><p>This object will never travel through the wire: it will only be used as a component of other objects. Therefor we don’t want to build an actual implementation of this object, so we will use another plugin: makeAbstract. This makes it so that only the “interface” half of the object will be generated, without an implementation.</p><p>We are getting closer to our target. Well my target at least.</p><p>Another thing that annoys me is the manual copying from transfer objects to database objects. The thing is that not all fields should be copied: very often the “plain” properties (strings, number, dates and such) are easy to copy through several libraries. For example, Spring has many methods that allow this.</p><p>So we will extract the plain properties of our objects and pull them out to a superinterface. This allows me to reuse this interface in my database objects. I can also use this interface to implement some automatic copying mechanism instead of copying them by hand. That way I can:</p><ol><li>Make sure that properties are copied from my database objects to my transfer objects and vice-versa.</li><li>Exclude the more complex members of my objects by not having them in the topmost interface</li></ol><p>Let’s just look at the resulting <a href="https://github.com/jpbelang/BeerTrader/blob/better-model-medium/model/src/main/resources/api.raml#L100">RAML</a>:</p><pre>InventoryEntryProperties:<br>    (ramltopojo.types):<br>      plugins:<br>        - core.makeAbstract<br>    additionalProperties: false<br>    type: Identified<br>    properties:<br>      count: integer<br>      availableCount: integer<br>InventoryEntry:<br><strong>    (ramltopojo.types):<br>      plugins:<br>        - core.jackson    <br></strong>    type: InventoryEntryProperties<br>    additionalProperties: true<br>    properties:<br>       beerReference: UUID</pre><p>In this example, InventoryEntryProperties is the common interface between database objects and the RAML objects. Notice that it is extending type Identified. This will make both our database objects and RAML objects Identified through its “id” property. It has two more simple properties: “count” — which counts the total number of a particular kind of beer — and “availableCount — which counts the bottles that aren’t committed to trades yet. It is also an abstract object.</p><p>InventoryEntry inherits from InventoryEntryProperties. First, this is the actual over-the-wire implementation RAML object. For this reason, we need to make sure that the Jackson annotations are added to this generated class. This is added to all the RAML objects that will go over the wire (including the enumerations). Notice that the beerReference property is only accessible through the transfer object: this is because our JPA objects will not be implementing a beerReference property. On the network side, we will use UUIDs, but on the database side we will be using a regular hibernate relationship.</p><p>All the objects are built using this model. Our <a href="https://github.com/jpbelang/BeerTrader/blob/better-model-medium/server/src/main/java/org/raml/jaxrs/beertrader/data/InventoryObject.java">database</a> objects will look like this:</p><pre>@Entity<br>public class InventoryObject extends PersistentObject implements InventoryEntryProperties {</pre><pre>    @Basic<br>    private int count;<br>    private int availableCount;</pre><pre>    @OneToOne<br>    private BeerObject beer;<br>}</pre><p>With this model we can build fairly simple resource <a href="https://github.com/jpbelang/BeerTrader/blob/better-model-medium/server/src/main/java/org/raml/jaxrs/beertrader/resources/impl/InventoryImpl.java">implementations</a>.</p><pre>@Override<br>public GetUsersInventoryByUserIdResponse getUsersInventoryByUserId<em>(</em>String userId<em>) {</em></pre><pre><em>    // Load from DB.<br>    </em>List<em>&lt;</em>InventoryObject<em>&gt; </em>inventoryObjects = context<br>        .createQuery<em>( </em>&quot;from  InventoryObject&quot;,<br>                       InventoryObject.class<em>)<br>        </em>.getResultList<em>()</em>;</pre><pre>    // Copy DB objects to RAML<br>    List<em>&lt;</em>InventoryEntry<em>&gt; </em>beers =    <br>        inventoryObjects.stream<em>()<br>            </em>.map<em>(</em>this::inventoryObjectToInventory<em>)<br>            </em>.collect<em>(</em>Collectors.<em>toList())</em>;<br><br>    return GetUsersInventoryByUserIdResponse<br>               .<em>respond200WithApplicationJson(</em>beers<em>)</em>;<br><em>}</em></pre><pre>InventoryEntry inventoryObjectToInventory(InventoryObject db) {<br>    InventoryEntry inventoryEntry = this.dbToTransfer(db);<br>    inventoryEntry.setBeerReference(db.getId());</pre><pre>    return inventoryEntry;<br>}</pre><p>The “dbToTransfer” method exists and copies the properties. Trust me. Or even better download this phase of the project from <a href="https://github.com/jpbelang/BeerTrader/tree/better-model/model">https://github.com/jpbelang/BeerTrader/tree/better-model/model</a>.</p><p>So we’ve managed to write a RAML model that represents both our business and implementation logic. Sure, it could have been built differently. We could have written a plugin to add JPA annotations to the generated code. Or even simpler, we could have done something using MongoDB and just stored the objects. Or SpringData. Sure. But this is what we did. I like it :-)</p><p>Next time, we’ll look into some testing strategies that could leverage the RAML spec.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d98112b12aac" width="1" height="1" alt=""><hr><p><a href="https://medium.com/raml-api/using-raml-for-jax-rs-for-brewing-part-ii-building-a-better-model-d98112b12aac">Using RAML-For-JAX-RS for Brewing (Part II): Building a better model</a> was originally published in <a href="https://medium.com/raml-api">RAML by Example</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Conditional JSON properties (Part 2)]]></title>
            <link>https://medium.com/raml-api/conditional-json-properties-part-2-10357e6060cd?source=rss----9528792001c3---4</link>
            <guid isPermaLink="false">https://medium.com/p/10357e6060cd</guid>
            <category><![CDATA[json]]></category>
            <category><![CDATA[raml]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[data]]></category>
            <category><![CDATA[api-design]]></category>
            <dc:creator><![CDATA[Jonathan Stoikovitch]]></dc:creator>
            <pubDate>Fri, 27 Jul 2018 00:04:40 GMT</pubDate>
            <atom:updated>2018-07-27T00:04:40.046Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KWDylRQQu1wOAr9BPyRDGQ.png" /><figcaption>Read the RAML 1.0 Spec <a href="https://github.com/raml-org/raml-spec">here</a></figcaption></figure><p>In <a href="https://medium.com/raml-api/conditional-json-properties-part-1-31c705787367">Part 1</a>, we covered several scenarios in which we defined sets of JSON properties that were either valid or invalid depending on the presence or absence of other properties. In this Part 2, we will focus on validating object properties based on their value and the value of other properties in that object.</p><h4>Sets of Properties</h4><p>Sometimes we want objects to have a certain set of properties. Here, we have two properties foo and bar, that may be either respectively equal to Foo and false or to Bar and true.</p><pre>#%RAML 1.0 DataType<br><br>type: object<br>properties:<br>  foo: string<br>  bar: boolean<br>enum:<br>  - foo: &quot;Foo&quot;<br>    bar: false<br>  - foo: &quot;Bar&quot;<br>    bar: true</pre><p>which validates as follows:</p><pre>{&quot;foo&quot;: &quot;Foo&quot;, &quot;bar&quot;: false} # valid<br>{&quot;foo&quot;: true, &quot;bar&quot;: &quot;Bar&quot;} # invalid<br>{&quot;foo&quot;: &quot;Bar&quot;} # invalid<br>{&quot;foo&quot;: &quot;Bar&quot;, &quot;bar&quot;: true} # valid<br>{&quot;qux&quot;: true} # invalid<br>{} # invalid</pre><h4>Opposite values</h4><p>In this scenario, we want the object to have at least two properties foo and bar, that may be either respectively of type string and boolean or boolean and string.</p><p>This object can be defined like this:</p><pre>#%RAML 1.0 Library<br><br>Option1:<br>  properties:<br>    foo: <br>      type: string<br>      enum: [Foo]<br>    bar: <br>      type: boolean<br>      enum: [false]<br>Option2:<br>  properties:<br>    foo: <br>      type: boolean<br>      enum: [true]<br>    bar: <br>      type: string<br>      enum: [Bar]<br><br>MyObject: Option1 | Option2</pre><p>which validates as follows:</p><pre>{&quot;foo&quot;: &quot;Foo&quot;, &quot;bar&quot;: false} # valid<br>{&quot;foo&quot;: true, &quot;bar&quot;: &quot;Bar&quot;} # valid<br>{&quot;foo&quot;: &quot;Bar&quot;} # invalid<br>{&quot;foo&quot;: &quot;Bar&quot;, &quot;bar&quot;: true} # valid<br>{&quot;qux&quot;: true} # invalid<br>{} # invalid</pre><h4>Any value</h4><p>In this scenario, we have an object that must contain the two properies foo and bar, and only those two properties. Their respective value, however, can be of any type.</p><pre>#%RAML 1.0 DataType<br><br>type: object<br>properties:<br>  foo: any<br>  bar: any<br>additionalProperties: false</pre><p>which validates as follows:</p><pre>{&quot;foo&quot;: &quot;Foo&quot;, &quot;bar&quot;: false} # valid<br>{&quot;foo&quot;: true, &quot;bar&quot;: &quot;Bar&quot;} # valid<br>{&quot;foo&quot;: &quot;Bar&quot;} # invalid<br>{&quot;foo&quot;: &quot;Bar&quot;, &quot;bar&quot;: true} # valid<br>{&quot;qux&quot;: true} # invalid<br>{} # invalid</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=10357e6060cd" width="1" height="1" alt=""><hr><p><a href="https://medium.com/raml-api/conditional-json-properties-part-2-10357e6060cd">Conditional JSON properties (Part 2)</a> was originally published in <a href="https://medium.com/raml-api">RAML by Example</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Conditional JSON properties (Part 1)]]></title>
            <link>https://medium.com/raml-api/conditional-json-properties-part-1-31c705787367?source=rss----9528792001c3---4</link>
            <guid isPermaLink="false">https://medium.com/p/31c705787367</guid>
            <category><![CDATA[data]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[json]]></category>
            <category><![CDATA[api-design]]></category>
            <category><![CDATA[raml]]></category>
            <dc:creator><![CDATA[Jonathan Stoikovitch]]></dc:creator>
            <pubDate>Thu, 19 Jul 2018 02:53:03 GMT</pubDate>
            <atom:updated>2018-07-19T03:03:47.985Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KWDylRQQu1wOAr9BPyRDGQ.png" /><figcaption><a href="https://github.com/raml-org/raml-spec">Read the RAML Spec</a></figcaption></figure><p>One of the most important aspect of designing Web APIs is modeling its data layer. The data layer can take different shapes and it can be found at different levels of the API: URI parameters, query parameters, request and response headers, request and response bodies.</p><p>When modeling a JSON object — the most common format for transmitting data these days — we may want sets of properties to be either valid or invalid depending on the presence or the absence of other properties.</p><p>Let’s take a look at different scenarios.</p><h4>All and only defined properties</h4><p>This is the most common one. We want an object to contain all and only defined properties, here foo and bar. These properties must be respectivly string and boolean.</p><p>This object can be defined like this:</p><pre>#%RAML 1.0 DataType<br><br>additionalProperties: false<br>properties:<br>  foo: string<br>  bar: boolean</pre><p>which validates as follows:</p><pre>{&quot;foo&quot;: &quot;lorem ipsum&quot;, &quot;bar&quot;: false} # valid<br>{&quot;foo&quot;: true, &quot;bar&quot;: false} # invalid<br>{&quot;foo&quot;: &quot;lorem ipsum&quot;} # invalid<br>{&quot;bar&quot;: &quot;lorem ipsum&quot;, &quot;foo&quot;: false} # invalid<br>{&quot;qux&quot;: 1} # invalid<br>{} # invalid</pre><h4>Any of either defined or undefined properties</h4><p>In some cases, we want to allow an object to contain any number of properties. However, if some specific properties are defined, here foo and bar, we want those properties to be of a certain type.</p><p>This object can be defined like this:</p><pre>#%RAML 1.0 DataType<br><br>properties:<br>  foo?: string<br>  bar?: boolean</pre><p>which validates as follows:</p><pre>{&quot;foo&quot;: &quot;lorem ipsum&quot;, &quot;bar&quot;: false} # valid<br>{&quot;foo&quot;: true, &quot;bar&quot;: false} # invalid<br>{&quot;foo&quot;: &quot;lorem ipsum&quot;} # valid<br>{&quot;bar&quot;: &quot;lorem ipsum&quot;, &quot;foo&quot;: false} # invalid<br>{&quot;qux&quot;: 1} # valid<br>{&quot;foo&quot;: null, &quot;bar&quot;: null} # invalid<br>{} # valid</pre><h4>Making sure at least one property is defined</h4><p>Building on the previous scenario, we want all of the above conditions and we also want to ensure at least one property is defined.</p><p>This object can be defined like this:</p><pre>#%RAML 1.0 DataType<br><br>minProperties: 1<br>properties:<br>  foo?: string<br>  bar?: boolean</pre><p>which validates as follows:</p><pre>{&quot;foo&quot;: &quot;lorem ipsum&quot;, &quot;bar&quot;: false} # valid<br>{&quot;foo&quot;: true, &quot;bar&quot;: false} # invalid<br>{&quot;foo&quot;: &quot;lorem ipsum&quot;} # valid<br>{&quot;bar&quot;: &quot;lorem ipsum&quot;, &quot;foo&quot;: false} # invalid<br>{&quot;qux&quot;: 1} # valid<br>{} # invalid</pre><h4>Any of only defined properties</h4><p>Building again on the previous scenario, we want all of the above defined conditions but we also want to restrict the properties to only the ones defined.</p><p>This object can be defined like this:</p><pre>#%RAML 1.0 DataType<br><br>additionalProperties: false<br>minProperties: 1<br>properties:<br>  foo?: string<br>  bar?: boolean</pre><p>which validates as follows:</p><pre>{&quot;foo&quot;: &quot;lorem ipsum&quot;, &quot;bar&quot;: false} # valid<br>{&quot;foo&quot;: true, &quot;bar&quot;: false} # invalid<br>{&quot;foo&quot;: &quot;lorem ipsum&quot;} # valid<br>{&quot;bar&quot;: &quot;lorem ipsum&quot;, &quot;foo&quot;: false} # invalid<br>{&quot;qux&quot;: 1} # invalid<br>{} # invalid</pre><h4>Any defined properties, any defined types</h4><p>Here, we want the object to contain at least one property, either foo or bar, but no additional properties. Either property can be string or boolean.</p><p>This object can be defined like this:</p><pre>#%RAML 1.0 DataType<br><br>minProperties: 1<br>properties:<br>  /^(foo|bar)$/: string | boolean</pre><p>which is equivalent to:</p><pre>#%RAML 1.0 DataType<br><br>additionalProperties: false<br>minProperties: 1<br>properties:<br>  foo?: string | boolean<br>  bar?: string | boolean</pre><p>and which validates as follows:</p><pre>{&quot;foo&quot;: &quot;lorem ipsum&quot;, &quot;bar&quot;: false} # valid<br>{&quot;foo&quot;: true, &quot;bar&quot;: false} # valid<br>{&quot;foo&quot;: &quot;lorem ipsum&quot;} # valid<br>{&quot;bar&quot;: &quot;lorem ipsum&quot;, &quot;foo&quot;: false} # valid<br>{&quot;qux&quot;: 1} # invalid<br>{} # invalid</pre><h4>Mirror properties</h4><p>In this scenario, we want the object to have at least two properties foo and bar, which may be either string or boolean, but never at the same time.</p><p>This object can be defined like this:</p><pre>#%RAML 1.0 Library<br><br>Option1:<br>  properties:<br>    foo: string<br>    bar: boolean<br>Option2:<br>  properties:<br>    foo: boolean<br>    bar: string<br>MyObject: Option1 | Option2</pre><p>which validates as follows:</p><pre>{&quot;foo&quot;: &quot;lorem ipsum&quot;, &quot;bar&quot;: false} # valid<br>{&quot;foo&quot;: true, &quot;bar&quot;: false} # invalid<br>{&quot;foo&quot;: &quot;lorem ipsum&quot;} # invalid<br>{&quot;bar&quot;: &quot;lorem ipsum&quot;, &quot;foo&quot;: false} # valid<br>{&quot;qux&quot;: 1} # invalid<br>{} # invalid</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=31c705787367" width="1" height="1" alt=""><hr><p><a href="https://medium.com/raml-api/conditional-json-properties-part-1-31c705787367">Conditional JSON properties (Part 1)</a> was originally published in <a href="https://medium.com/raml-api">RAML by Example</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[raml-javascript-generator Quick Start]]></title>
            <link>https://medium.com/raml-api/raml-javascript-generator-quick-start-5a9ad62a330b?source=rss----9528792001c3---4</link>
            <guid isPermaLink="false">https://medium.com/p/5a9ad62a330b</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[npm]]></category>
            <category><![CDATA[raml]]></category>
            <category><![CDATA[quickstart]]></category>
            <dc:creator><![CDATA[Jonathan Stoikovitch]]></dc:creator>
            <pubDate>Wed, 11 Jul 2018 00:31:46 GMT</pubDate>
            <atom:updated>2018-07-11T00:31:45.568Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OP9zPd_tcY8eHZja014tmg.png" /><figcaption><a href="https://raml.org">RAML.org</a></figcaption></figure><p><a href="https://github.com/mulesoft-labs/raml-javascript-generator">raml-javascript-generator</a> is a tool that generates JavaScript API clients from RAML API definitions. It takes a RAML file as input and outputs a NPM package.</p><p>Let’s start by installing raml-javascript-generator:</p><pre>$ npm install raml-javascript-generator -g</pre><p>We now need a RAML file, let’s use the world-music-api from the <a href="https://github.com/raml-org/raml-examples">raml-org/raml-examples</a> repository. At this point, we can either reference a local RAML file or point to a remote one using an URL:</p><pre>$ raml-javascript-generator https://raw.githubusercontent.com/raml-org/raml-examples/e91308b/others/world-music-api/api.raml -o world-music-api</pre><p>Let’s take a closer look inside:</p><pre>$ cd world-music-api/<br>$ ls -1 ./<br>INSTALL.md<br>README.md<br>index.js<br>package.json</pre><p>The result is an installable NPM package with all its dependencies defined in package.json.</p><pre>$ cat package.json | jq .dependencies<br>{<br>  &quot;client-oauth2&quot;: &quot;^2.1.0&quot;,<br>  &quot;xtend&quot;: &quot;^4.0.1&quot;,<br>  &quot;request-promise&quot;: &quot;^4.2.2&quot;,<br>  &quot;request&quot;: &quot;^2.34&quot;,<br>  &quot;setprototypeof&quot;: &quot;^1.0.1&quot;,<br>  &quot;query-string&quot;: &quot;^5.0.0&quot;<br>}</pre><p>It also generates a README with basic usage instructions. Let&#39;s take a look at some of those instructions:</p><pre>$ grep -o &#39;#### `.*&#39; README.md <br>#### `api.get([query, [options]])`<br>#### `api.post([body, [options]])`<br>#### `entry.post([body, [options]])`<br>#### `entry.get([query, [options]])`<br>#### `songs.get([query, [options]])`<br>#### `songs.post([body, [options]])`<br>#### `songs.songId({ songId }).get([query, [options]])`</pre><p>Great! Now, we can install the generated library:</p><pre>$ npm install</pre><p>and use it in our JavaScript code.</p><p>But before playing further, we’ll need to have an API backend running. We’ll use osprey-mock-service for that (don&#39;t forget to check-out this <a href="https://medium.com/raml-api/quick-mocks-with-osprey-mock-service-ef46d72491b7">osprey-mock-service post</a>):</p><pre>$ osprey-mock-service -f https://raw.githubusercontent.com/raml-org/raml-examples/e91308b/others/world-music-api/api.raml -p 1234<br>Mock service running at <a href="http://localhost:1234">http://localhost:1234</a></pre><p>Now that we have an API backend running, we can query using our world-music-api library:</p><pre># test.js<br>const WorldMusicAPI = require(&#39;.&#39;)<br>const client = new WorldMusicAPI({baseUri: &#39;http://localhost:1234/v1&#39;})<br><br>client.songs.songId({&#39;songId&#39;: 1}).get().then((response) =&gt; {<br>  console.log(response.body)<br>})</pre><p>Then, running this snippet will output:</p><pre>node test.js <br>{ title: &#39;My Song&#39;, length: 12 }</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5a9ad62a330b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/raml-api/raml-javascript-generator-quick-start-5a9ad62a330b">raml-javascript-generator Quick Start</a> was originally published in <a href="https://medium.com/raml-api">RAML by Example</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[raml-cop Quick Start]]></title>
            <link>https://medium.com/raml-api/raml-cop-quick-start-4fbdb18748e?source=rss----9528792001c3---4</link>
            <guid isPermaLink="false">https://medium.com/p/4fbdb18748e</guid>
            <category><![CDATA[validation]]></category>
            <category><![CDATA[parsing]]></category>
            <category><![CDATA[quickstart]]></category>
            <category><![CDATA[raml]]></category>
            <dc:creator><![CDATA[Jonathan Stoikovitch]]></dc:creator>
            <pubDate>Tue, 03 Jul 2018 00:45:07 GMT</pubDate>
            <atom:updated>2018-07-03T00:45:19.334Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2UT3n2RMmc6d_DgCaKjUtQ.png" /><figcaption><a href="https://github.com/raml-org/raml-spec">Read the RAML Spec</a></figcaption></figure><p><a href="https://github.com/thebinarypenguin/raml-cop">raml-cop</a> is a command-line tool for validating RAML files. It supports both RAML 0.8 and 1.0. It can validate included files as well as RAML 1.0 Fragments.</p><p>Let’s give it a try. We’ll start by installing raml-cop globally so that it&#39;s permanently availble in the terminal:</p><pre>$ npm i -g raml-cop</pre><p>Now, let’s download a simple RAML example:</p><pre>$ curl -o api.raml <a href="https://raw.githubusercontent.com/raml-org/raml-examples/master/typesystem/simple.raml">https://raw.githubusercontent.com/raml-org/raml-examples/master/typesystem/simple.raml</a></pre><p>And let’s validate it:</p><pre>$ raml-cop api.raml<br>[api.raml] VALID</pre><p>Now, let’s make that RAML file invalid by removing its first line:</p><pre>$ tail -n +2 api.raml &gt; api-invalid.raml</pre><p>and let’s validate that invalid RAML again:</p><pre>$ raml-cop api-invalid.raml<br>[api-invalid.raml] ERROR Invalid first line. A RAML document is expected to start with &#39;#%RAML &lt;version&gt; &lt;?fragment type&gt;&#39;.</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4fbdb18748e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/raml-api/raml-cop-quick-start-4fbdb18748e">raml-cop Quick Start</a> was originally published in <a href="https://medium.com/raml-api">RAML by Example</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using RAML-For-JAX-RS for Brewing (Part I)]]></title>
            <link>https://medium.com/raml-api/using-raml-for-jax-rs-for-brewing-586eb041361c?source=rss----9528792001c3---4</link>
            <guid isPermaLink="false">https://medium.com/p/586eb041361c</guid>
            <category><![CDATA[java]]></category>
            <category><![CDATA[jax-rs]]></category>
            <category><![CDATA[brewing]]></category>
            <category><![CDATA[raml]]></category>
            <dc:creator><![CDATA[JP Belanger]]></dc:creator>
            <pubDate>Sun, 01 Jul 2018 02:45:15 GMT</pubDate>
            <atom:updated>2018-07-31T16:14:27.706Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZVR4qmj0feJFQVVR7mpwyQ.png" /><figcaption><a href="https://github.com/mulesoft-labs/raml-for-jax-rs">raml-for-jax-rs on Github</a></figcaption></figure><p>This is a tutorial on how to use <a href="https://github.com/mulesoft-labs/raml-for-jax-rs">raml-for-jaxrs</a> to develop a real-life application. We will try to cover every aspect of application development and build on our application base. I’ll break this down into sections. They’ll be clear, don’t worry.</p><p>It seems to me that everyone and their brother-in-law is brewing beer these days. All sorts of beers (mostly IPAs, honestly) being made off different recipes and some rather original ideas. It seems that beer has brought out the artist in a lot of people.</p><p>And artists like to show off their stuff. And show off they do. They’ll bring their home-brewed stuff to parties and other types of social gatherings and share. Which is all good, until the sheer volume of their production creates a backlog of bottles that will soon overrun your house. Or at least your basement.</p><p>Well, there’s <em>BeerTrader</em> to the rescue. <em>BeerTrader</em> will allow you to both keep an inventory of your brews and allow you to setup trades with other users of the site, allowing you to rotate your overstock into different types of beer, just so you don’t go nuts drinking that apricot based recipe that you thought would turn out great.</p><p>So the first iteration of the server will be just about useless: it will just be a server that takes messages, translates it to DB objects and persists it in the database. That’s it: no great model, no real security, no real testing. We will then try to organize our data better, add validation, add security features and such. At the end, we should have a good simple implementation of our server.</p><h3>Stuff you need to know</h3><p>Well, the first thing you need to know is RAML 1.0. No deep knowledge required. I don’t have a deep knowledge myself and I probably refer to the spec more often than I should. You also probably need to know about JAX-RS. Again, nothing complicated. There will be some hibernate stuff, but we won’t get into the nitty gritty. And the project will be bootstrapped with spring-boot, because it’s magical.</p><p>I’m guessing that you’d like to know where the server code is right now: well it’s <a href="https://github.com/jpbelang/BeerTrader">here</a>. The master branch contains the finished code for our tutorial. I’ll be referring to it all through this post.</p><h3>The Setup</h3><p>We are going to be using maven to setup our project. There will be two submodules: the model submodule, where the model objects and JAX-RS stubs will be generated. This is the part we should NOT be editing. In fact, the only files we’ll be editing are the <a href="https://github.com/jpbelang/BeerTrader/blob/master/model/src/main/resources/api.raml">api.raml</a> and the <a href="https://github.com/jpbelang/BeerTrader/blob/master/model/pom.xml">maven</a> POM files.</p><p>The second module is the server module, where everything else lives: <a href="https://github.com/jpbelang/BeerTrader/blob/master/server/src/main/java/org/raml/jaxrs/beertrader/spring/JerseyConfig.java">Spring</a>, <a href="https://github.com/jpbelang/BeerTrader/blob/master/server/src/main/resources/META-INF/persistence.xml">hibernate</a> and its <a href="https://github.com/jpbelang/BeerTrader/tree/master/server/src/main/java/org/raml/jaxrs/beertrader/data">objects</a> and our <a href="https://github.com/jpbelang/BeerTrader/tree/master/server/src/main/java/org/raml/jaxrs/beertrader/resources/impl">implementations of the JAX-RS interface</a>. The database schema is automatically built and stored in memory (using HSQLDB).</p><pre>BeerTrader<br> model<br>   src<br>    main<br>      resources<br>        api.raml          &lt;-- Our RAML model<br>   pom.xml                &lt;-- The pom.xml using raml-for-jaxrs<br> server<br>   src<br>     main<br>      java<br>        org<br>          raml<br>            jaxrs<br>              beertrader<br>                data      &lt;-- Database model<br>                resources &lt;-- implementations of JAX-RS<br>                spring    &lt;-- String configuration for resources<br>     resources<br>       META-INF<br>         persistence.xml  &lt;-- Database configuration<br>    pom.xml</pre><h3>Our model objects</h3><p>For now, we’ll create a very simple REST model. Objects will only use simple properties and use no form of inheritance. We will be improving the model as we go.</p><p>All our objects will have an ID.</p><p>The first object in the model is, as in most systems, the <a href="https://github.com/jpbelang/BeerTrader/blob/b57d25b9afc1473f5374230d57f9713368b02bff/model/src/main/resources/api.raml#L32">User</a>. It’s the classic name and email kind. Nothing particularly innovative.</p><pre>User:<br>  properties:<br>    id: string<br>    name: string</pre><p>We have two <a href="https://github.com/jpbelang/BeerTrader/blob/b57d25b9afc1473f5374230d57f9713368b02bff/model/src/main/resources/api.raml#L10">enumerations</a> on how we define the kind of beer being used. Two different YAML list styles giving the same results. By the way, we’ll be storing these enumerations straight into the database. They are in fact shared between both the messages and database objects.</p><pre>BeerType:<br>    enum: [ALE, STOUT, LAGER, PORTER, MALTS, OTHER]<br>BeerStyle:<br>    enum:<br>      - AMBER<br>      - BLOND<br>      - BROWN<br>      - CREAM<br>      - DARK<br>      - FRUIT<br>      - GOLDEN<br>      - HONEY<br>      - IPA<br>      - LIGHT<br>      - LIME<br>      - PALE<br>      - PILSNER<br>      - STRONG<br>      - RED<br>      - PILSNER<br>      - WHEAT<br>      - OTHER</pre><p>We then have the <a href="https://github.com/jpbelang/BeerTrader/blob/b57d25b9afc1473f5374230d57f9713368b02bff/model/src/main/resources/api.raml#L37">Beer</a> object. This object uses our two enumerations by referring to BeerType and BeerStyle.</p><pre>Beer:<br>  properties:<br>    id: string<br>    name: string<br>    description: string<br>    type: BeerType<br>    style: BeerStyle</pre><p>The next object is the <a href="https://github.com/jpbelang/BeerTrader/blob/b57d25b9afc1473f5374230d57f9713368b02bff/model/src/main/resources/api.raml#L44">InventoryEntry</a> object. This object essentially contains a count for a given beer. The beerReference property contains the ID value of the counted beer.</p><pre>InventoryEntry:<br>  properties:<br>    id: string<br>    beerReference: string<br>    count: integer<br>    availableCount: integer</pre><p>Finally, a <a href="https://github.com/jpbelang/BeerTrader/blob/b57d25b9afc1473f5374230d57f9713368b02bff/model/src/main/resources/api.raml#L50">Trade</a> object. A very flat data structure containing “from” and “to” components. We have two references for the beers being traded matched to the users trading them away. We are still using the string IDs as references. Not much to see here either. We’ll make everything better in the next instalment.</p><pre>Trade:<br>  properties:<br>    id: string<br>    fromUserReference: string<br>    fromBeerReference: string<br>    fromCount: integer<br>    toUserReference: string<br>    toBeerReference: string<br>    toCount: integer</pre><h3>Our resources</h3><p>The resources used in our application will start straightforward. The only thing I will do here is separate them so that I have different Java classes. Should I model everything in one tree, it would create only one large Java interface to implement. That would be rather unwieldy structure to use.</p><p>So we will break our application down along the lines of operations on our model objects. They will be built in the expected collection/item fashion: the URI “/somethings” will list a collection of objects where we create objects, and “/somethings/{id}” will allow us to play with a specific object.</p><p>My first draft started as something like this:</p><pre>/users:<br>  get:<br>    responses:<br>      200:<br>        body:<br>          application/json: User[]<br>  post:<br>    body:<br>      application/json: User<br>    responses:<br>      201:<br>        body:<br>          application/json: User<br>  /{userId}:<br>    get:<br>      responses:<br>        200:<br>          body:<br>            application/json: User<br>        404:<br>    delete:<br>      responses:<br>        200:<br>        404:<br>    put:<br>      body:<br>        application/json: User<br>      responses:<br>        200:<br>        404:<br>/users/{userId}/inventory:<br>  get:<br>    responses:<br>      200:<br>        body:<br>          application/json: InventoryEntry[]<br>  post:<br>    body:<br>      application/json: InventoryEntry<br>    responses:<br>      201:<br>        body:<br>          application/json: InventoryEntry<br>  /{entryId}:<br>    get:<br>      responses:<br>        200:<br>          body:<br>            application/json: InventoryEntry<br>        404:<br>    delete:<br>      responses:<br>        200:<br>        404:<br>    put:<br>      body:<br>        application/json: InventoryEntry<br>      responses:<br>        200:<br>        404:<br>/users/{userId}/beers:<br>  get:<br>    responses:<br>      200:<br>        body:<br>          application/json: Beer[]<br>  post:<br>    body:<br>      application/json: Beer<br>    responses:<br>      201:<br>        body:<br>          application/json: Beer<br>  /{entryId}:<br>    get:<br>      responses:<br>        200:<br>          body:<br>            application/json: Beer<br>        404:<br>    delete:<br>      responses:<br>        200:<br>        404:<br>    put:<br>      body:<br>        application/json: Beer<br>      responses:<br>        200:<br>        404:</pre><p>However, this seems repetitive. So we’ll reach into the shallow part of our RAML bag of tricks and use a <a href="https://github.com/jpbelang/BeerTrader/blob/b57d25b9afc1473f5374230d57f9713368b02bff/model/src/main/resources/api.raml#L60">resourceType</a> to save repetition. <a href="https://github.com/raml-org/raml-spec/blob/master/versions/raml-10/raml-10.md#resource-types-and-traits">ResourceTypes</a> can be used like templates. They save typing.</p><pre>resourceTypes:<br>  collection:<br>    get:<br>      responses:<br>        200:<br>          body:<br>            application/json: &lt;&lt;targetType&gt;&gt;[]<br>    post:<br>      body:<br>        application/json: &lt;&lt;targetType&gt;&gt;<br>      responses:<br>        201:<br>          headers:<br>            Location: string<br>          body:<br>            application/json: &lt;&lt;targetType&gt;&gt;  item:<br>    get:<br>      responses:<br>        200:<br>          body:<br>            application/json: &lt;&lt;itemType&gt;&gt;<br>        404:<br>    delete:<br>      responses:<br>        200:<br>        404:<br>    put:<br>      body:<br>        application/json: &lt;&lt;itemType&gt;&gt;<br>      responses:<br>        200:<br>        404:</pre><p>Our <a href="https://github.com/jpbelang/BeerTrader/blob/a9ce980d7894c44ba61c5f0d0756ab92c4f84b18/model/src/main/resources/api.raml#L93">resources</a> now becomes:</p><pre>/users:<br>  type: { collection: { targetType: User } }<br>  /{userId}:<br>    type: { item: { itemType: User } }</pre><pre>/users/{userId}/inventory:<br>  type: { collection: { targetType: InventoryEntry } }<br>  /{entryId}:<br>    type: { item: { itemType: InventoryEntry } }</pre><pre>/users/{userId}/beers:<br>  type: { collection: { targetType: Beer } }<br>  /{entryId}:<br>    type: { item: { itemType: Beer } }</pre><pre>/users/{userId}/trades:<br>  type: { collection: { targetType: Trade } }<br>  /{tradeId}:<br>    type: { item: { itemType: Trade } }</pre><p>So we now have a RAML specification. From this, we’ll generate our objects and JAX-RS stubs. We’ll be using maven. To do this, all we need to set up is the appropriate maven <a href="https://github.com/jpbelang/BeerTrader/blob/b57d25b9afc1473f5374230d57f9713368b02bff/model/pom.xml#L30">plugin</a>.</p><pre>&lt;build&gt;<br>        &lt;plugins&gt;<br>            &lt;plugin&gt;<br>                &lt;groupId&gt;org.raml.jaxrs&lt;/groupId&gt;<br>                &lt;artifactId&gt;raml-to-jaxrs-maven-plugin&lt;/artifactId&gt;<br>                &lt;version&gt;3.0.2&lt;/version&gt;<br>                &lt;executions&gt;<br>                    &lt;execution&gt;<br>                        &lt;goals&gt;<br>                            &lt;goal&gt;generate&lt;/goal&gt;<br>                        &lt;/goals&gt;<br>                    &lt;/execution&gt;<br>                &lt;/executions&gt;<br>                &lt;configuration&gt;<br>                    &lt;ramlFile&gt;<br>                    ${project.build.resources[0].directory}/api.raml<br>                    &lt;/ramlFile&gt;<br>                    &lt;resourcePackage&gt;org.raml.jaxrs.beertrader.resources&lt;/resourcePackage&gt;<br>                    &lt;supportPackage&gt;org.raml.jaxrs.beertrader.support&lt;/supportPackage&gt;<br>                    &lt;modelPackage&gt;org.raml.jaxrs.beertrader.model&lt;/modelPackage&gt;<br>                    &lt;generateTypesWith&gt;<br>                        &lt;value&gt;<strong>jackson2</strong>&lt;/value&gt;<br>                    &lt;/generateTypesWith&gt;<br>                &lt;/configuration&gt;<br>            &lt;/plugin&gt;<br>       &lt;/plugins&gt;<br>&lt;/build&gt;</pre><p>We separate the generated code into three packages: the model package will contain the message objects, the resources package will contain our JAX-RS resource stubs, and finally the support package which is for somewhat internal raml-for-jaxrs usage.</p><p>The other important setup is the generateTypesWith section: here we set up plugins to the object and resource generation processes. It’s the simplest of three ways of setting up plugins. It’s also the least flexible: it applies to everything in the RAML spec. The only one we have in there for now is jackson2, which will generate Jackson 2 annotations on our objects for marshalling and unmarshalling.</p><p>Once this is done, we can go into our project directory and create the model.</p><pre>Biggly:BeerTrader jpbelang$ <strong>cd model</strong><br>Biggly:model jpbelang$ <strong>mvn clean install</strong><br>[INFO] Scanning for projects...<br>[INFO] <br>[INFO] -------------------------------------------------------------<br>[INFO] Building model 1.0-SNAPSHOT<br>[INFO] -------------------------------------------------------------</pre><p>This will generate the code in the target/generated-sources/raml-to-jaxrs directory. Go ahead, check it out.</p><h3>The implementation</h3><p>We will now implement our interfaces and bridge the calls to the database. Before we get into that though, I’d like to state that I’m not going to explain much of Spring, and I’m asking you to just believe in magic when it comes to injection. It works and it makes our life simpler.</p><p>Ok, so let’s look at UsersImpl. First thing we’ll have to do is implement the stub interface. Forces us to implement something that supports the resources in our RAML specification.</p><pre>import org.raml.jaxrs.beertrader.data.UserObject;<br>import org.raml.jaxrs.beertrader.model.User;<br>import org.raml.jaxrs.beertrader.model.UserImpl;<br>import org.raml.jaxrs.beertrader.resources.Users;<br>import org.springframework.stereotype.Component;</pre><pre>import javax.inject.Inject;<br>import javax.persistence.EntityManager;<br>import javax.persistence.NoResultException;<br>import javax.transaction.Transactional;<br>import java.util.List;<br>import java.util.stream.Collectors;</pre><pre>@Component<br>@Transactional<br>public class UsersImpl implements Users {</pre><pre>final private EntityManager context;</pre><pre>@Inject<br>    public UsersImpl(EntityManager context) {<br>        this.context = context;<br>    }</pre><pre>@Override<br>    public GetUsersResponse getUsers() {</pre><pre>List&lt;UserObject&gt; dbUsers = context<br>          .createQuery(&quot;from UserObject &quot;, UserObject.class)<br>          .getResultList();<br>       List&lt;User&gt; users = dbUsers<br>          .stream()<br>          .map(UsersImpl::userObjectToUser)<br>          .collect(Collectors.toList());</pre><pre>return GetUsersResponse<br>         .respond200WithApplicationJson(users);<br>    }<br>// ...</pre><p>We don’t return simple JAX-RS Responses. Returned responses must conform to what is in the RAML specification. The interface makes it simple to return the correct return codes and headers. So you should use it respectfully: don’t fool around with headers and such to break your own RAML spec.</p><p>So in this method, we fetch users from the database, transform them into transfer objects and return them with a RAML safe response.</p><h3>A quick simple run</h3><p>We can run the server in one of two ways: running from the IDE or from the command line. Either way, we will need to run the <a href="https://github.com/jpbelang/BeerTrader/blob/master/server/src/main/java/org/raml/jaxrs/beertrader/Main.java">main</a> class (in server/src/main/java/org/raml/jaxrs/beertrader/Main.java). To run from maven, from the server directory:</p><pre>java -jar target/server-1.0-SNAPSHOT.jar</pre><p>You should also be able to run it from your IDE.</p><pre>POST /services/users HTTP/1.1<br>Host: localhost:8080<br>Content-Type: application/json<br>Cache-Control: no-cache</pre><pre>{<br> &quot;name&quot;: &quot;JP Belanger&quot;,<br> &quot;email&quot;: &quot;<a href="mailto:jp@fun.com">jp@fun.com</a>&quot;<br>}</pre><p>returning the response:</p><pre>HTTP/1.1 201 Created<br>Content-Length: 43<br>Content-Type: application/json<br>Date: Sun, 27 May 2018 18:00:13 GMT<br>Location: <a href="http://localhost:8080/services/users/084586f3-3f22-4248-901a-522da0252fda">http://localhost:8080/services/users/084586f3-3f22-4248-901a-522da0252fda</a></pre><pre>{<br>    &quot;name&quot;: &quot;JP Belanger&quot;,<br>    &quot;email&quot;: &quot;<a href="mailto:jp@fun.com">jp@fun.com</a>&quot;<br>}</pre><p>So that’s it: this is a simple version of a currently simple service. We will be adding to it shortly.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=586eb041361c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/raml-api/using-raml-for-jax-rs-for-brewing-586eb041361c">Using RAML-For-JAX-RS for Brewing (Part I)</a> was originally published in <a href="https://medium.com/raml-api">RAML by Example</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[oas-raml-converter Quick Start]]></title>
            <link>https://medium.com/raml-api/oas-raml-converter-quick-start-3a20664fa94a?source=rss----9528792001c3---4</link>
            <guid isPermaLink="false">https://medium.com/p/3a20664fa94a</guid>
            <category><![CDATA[aos]]></category>
            <category><![CDATA[quickstart]]></category>
            <category><![CDATA[raml]]></category>
            <category><![CDATA[swagger]]></category>
            <dc:creator><![CDATA[Jonathan Stoikovitch]]></dc:creator>
            <pubDate>Wed, 27 Jun 2018 06:12:22 GMT</pubDate>
            <atom:updated>2018-06-27T06:12:21.972Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2UT3n2RMmc6d_DgCaKjUtQ.png" /><figcaption><a href="https://github.com/raml-org/raml-spec">Read the RAML Spec</a></figcaption></figure><p>This is an introduction to <a href="https://github.com/mulesoft/oas-raml-converter">oas-raml-converter</a>. oas-raml-converter is a command line tool that helps convert to and from RAML and OAS.</p><p>Let’s begin by installing oas-raml-converter as a command-line tool:</p><pre>$ npm i -g oas-raml-converter</pre><p>and let’s also grab a RAML file:</p><pre>$ curl https://raw.githubusercontent.com/raml-org/raml-examples/master/typesystem/simple.raml -o api.raml</pre><p>Now, we can convert it from RAML 1.0 to OAS 2.0 with the following command:</p><pre>$ oas-raml-converter --from RAML --to OAS20 ./api.raml &gt; api.oas2</pre><p>the output will look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5b299581120b4aae949ccd920bdf0e6c/href">https://medium.com/media/5b299581120b4aae949ccd920bdf0e6c/href</a></iframe><p>and we can even convert that same API Spec from RAML 1.0 to OAS 3.0 with:</p><pre>$ oas-raml-converter --from RAML --to OAS30 ./api.raml &gt; api.oas3</pre><h4>Using oas-raml-converter as a NodeJS library</h4><p>oas-raml-converter can also be used as a library! This is particularly useful when processing either the input or the output. Let&#39;s see how it works.</p><p>In this scenario, I’ll use oas-raml-converter to convert from RAML 1.0 to OAS 2.0, and then, use yamljs to convert the output to the YAML syntax.</p><p>I’ll start by initializing my project and installing both libraries:</p><pre>$ npm init --yes<br>(...)<br><br>$ npm install --save oas-raml-converter yamljs<br>(...)</pre><p>then, let’s create an index.js file with the following code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1ff6416945921d45262025b3283b6671/href">https://medium.com/media/1ff6416945921d45262025b3283b6671/href</a></iframe><p>and then run with node . which will output my API Spec in OAS 2.0 format with the YAML syntax:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b3bf8bdeb46d3b0a2f4d33fba46324fe/href">https://medium.com/media/b3bf8bdeb46d3b0a2f4d33fba46324fe/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3a20664fa94a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/raml-api/oas-raml-converter-quick-start-3a20664fa94a">oas-raml-converter Quick Start</a> was originally published in <a href="https://medium.com/raml-api">RAML by Example</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>