ALPS Helper Library
December 19, 2020Hi :).
The new ALPS Converter I developed makes it possible to convert an ALPS specification (spec short) to OpenApi, GraphQL or other APIs.
import { Alps, FormatType } from 'alps-unified-ts';
// loaded from a YAML file
Alps.unified(Alps.loadYaml('todo-alps.yaml'), { formatType: FormatType.OPENAPI })
Other great features of my ALPS unified library are:
The GitHub project were created using Projen. I will discuss what the ALPS Api and Projen is in more details in the next sections.
ALPS API
ALPS is a specification for describing the context of a service. ALPS can be used as specification input to generate low abstracted specifications like OpenApi / Swagger, WSDL, RAML, WADL.
The ALPS Converter converts an ALPS Api Spec into lower abstracted Api specifications. An example of such a conversion follows in the next section.
ALPS API Spec Example
The following example is a simple TODO ALPS API Spec.
alps:
version: '1.0'
doc:
value: 'Simple Todo list example'
####################################
# metadata
ext:
- type: metadata
name: title
value: simpleTodo
tags: 'oas'
- type: metadata
name: id
value: http://alps.io/profiles/mamund/simpleTodo
tags: 'oas'
- type: metadata
name: root
value: http://api.example.org/todo
tags: 'oas'
descriptor:
# properties
# - these are the data elements
- id: id
type: semantic
text: storage id of todo item
- id: body
type: semantic
text: content of todo item
# groupings
# - these are the storage objects
- id: todoItem
type: group
text: todo item
descriptor:
- href: '#id'
- href: '#body'
# actions
# - these are the operations
- id: todoList
type: safe
rt: todoItem
text: return list of todo items
- id: todoAdd
type: unsafe
rt: todoItem
text: create a new todo item
descriptor:
- href: '#todoItem'
- id: todoRemove
type: idempotent
tags: delete
rt: todoItem
text: remove a single todo item
descriptor:
- href: '#id'
The element todoItem consists of an id and a todo string body . Three actions are defined todoList to list the todo items, todoAdd to insert new todos and todoRemove to delete todo items.
From these, the Unified Convertor can generate this OpenApi specification:
openapi: 3.0.1
# *******************************************************************
# generated by "unified" from src/todo-alps.yaml
# date: Wed Nov 25 2020 18:47:05 GMT+0100 (Central European Standard Time)
# http://github.com/mamund/2020-11-unified
# *******************************************************************
info:
title: simpleTodo
description: Simple Todo list example
version: 1.0.0
servers:
- url: 'http://api.example.org/todo'
paths:
/todoList:
get:
summary: 'return list of todo items'
operationId: todoList
responses:
200:
description: todoList
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/todoItem'
/todoAdd:
post:
summary: 'create a new todo item'
operationId: todoAdd
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/todoItem'
responses:
200:
description: add todoAdd
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/todoItem'
/todoRemove/{id}:
delete:
summary: 'remove a single todo item'
operationId: todoRemove
parameters:
- name: id
in: path
description: id of todoRemove
required: true
schema:
type: string
responses:
204:
description: delete todoRemove
components:
schemas:
todoItem:
description: todo item
type: object
properties:
id:
type: string
example: 4572
body:
type: string
example: jn1ov7axj4kv560d0921xf
Or in GraphQL schema:
# *******************************************************************
# generated by "unified"
# date: Fri Dec 11 2020 16:51:00 GMT+0100 (Central European Standard Time)
# http://github.com/mamund/2020-11-unified
# *******************************************************************
type todoItem {
id: String!
body: String!
}
type Query {
todoList: [todoItem]
}
type Mutation {
todoAdd(todoItem: String!): todoItem
todoRemove(id: String!): todoItem
}
schema {
query: Query,
mutation: Mutation
}
Projen
Projen allows sophisticated management of project configuration files through code. With just a few lines of TypeScript code, an entire repository can be configured. Here is an example:
const { JsiiProject } = require('projen');
const project = new JsiiProject({
name: 'alps-unified-ts',
authorAddress: 'damadden88@googlemail.com',
authorName: 'Martin Mueller'
});
project.synth();
These few lines create all the GitHub project files your heart desires. Among them the package.json, .gitignore, tsconfig.json and many many more.
What's really cool is that Projen also comes with GitHub workflows that can publish new versions to registries like NPM or PYPI.
I fell in love with the Projen framework as it is a great abstraction and default for a setup of projects. I encourage you to give Projen a try and very soon you will experience the beauty of this framework yourself.
ALPS Library in Action
Here I would like to briefly introduce my new ALPS Unified Library. The TypeScript package can be used like this
import { Alps, FormatType } from 'alps-unified-ts';
// loaded from a YAML file
Alps.unified(Alps.loadYaml('./spec/todo-alps.yaml'), { formatType: FormatType.OPENAPI })
// or directly via TypeScript Object
Alps.unified(Alps.spec({
alps: {
version: '1.0',
doc: {
value: 'Simple Todo list example',
},
...
}
});
The Alps.unified(...) function always returns a string. Depending on the formType the returned string contains the desired format. In our example this is FormType.OPENAPI which is OpenApi in YAML. If you would now like to have OpenAPI returned in JSON, FormatType.OPENAPI_JSON would also work. For rendering the Graph QL schema you would have to use FormatType.DSL.
In Python, the library can be used like this:
import alps_unified_ts as alps
alps_def = alps.AlpsDef(
version='1.0',
descriptor=[alps.DescriptorDef(id="id", type="semantic", text="sotrage id of todo item")],
doc=alps.DocDef(
value="Simple Todo list example"),
ext=[
alps.ExtDef(
name="root",
tags="oas"
type="metadata",
value="http://api.example.org/todo"),
alps.ExtDef(
name="title",
tags="oas"
type="metadata",
value="simpleTodo")])
alps_converted = alps.Alps.unified(alps_document=alps.Alps.spec(alps=alps_def), format_type=alps.FormatType.OPENAPI)
Using it in Java and .NET should look similar.
In my previous blogpost ALPS combined with CDK, I explain how to optionally create an AWS Api Gateway or AWS Appsync from an ALPS Spec using the ALPS Todo example and the ALPS unified library.
Summary
Building a library with Projen was super fun! I used it to build a new, improved version of the alps unified library. It now comes with super cool new features that I introduced here.
By the way, one more info. If you are also interested in the ALPS topic, with the ALPS Community we regularly organize community meetings online. There you can meet exciting people from all over the world. Feel free to come by :) .
To the wonderful readers of this article I'm saying that feedback of any kind is welcome. In the future I will try to include a discussion and comment feature here. In the meantime, please feel free to send me feedback via my social media accounts such as Twitter or FaceBook. Thank you very much :).
I love to work on Content Management Open Source projects. A lot from my stuff you can already use on www.github.com/mmuller88 . If you like my work there and my blog posts, please consider supporting me on Patreon: