├── images ├── 2020-04-13-proto.png ├── 2020-04-13-story.png ├── 2020-04-13-swaggerhub.png └── 2020-04-13-graphql-editor.png ├── slides ├── README.md └── 2020-04-unified-api-design.pdf ├── src ├── todo-async.yaml ├── todo-gql.sdl ├── todo-grpc.proto ├── package.json ├── test-sdl.json ├── todo-alps.yaml ├── todo-alps.json ├── test-proto.proto ├── todo-oas.yaml ├── company-ext-alps.yaml ├── company-oas.yaml ├── test-oas.yaml ├── company-ext-alps.json ├── index.js └── package-lock.json ├── README.md ├── .gitignore ├── todo-story.md └── run └── todo-alps.yaml /images/2020-04-13-proto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mamund/2020-04-unified-api-design/HEAD/images/2020-04-13-proto.png -------------------------------------------------------------------------------- /images/2020-04-13-story.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mamund/2020-04-unified-api-design/HEAD/images/2020-04-13-story.png -------------------------------------------------------------------------------- /slides/README.md: -------------------------------------------------------------------------------- 1 | ## Unified API Design Slides 2 | 3 | These are the slides from the 2020-04 GOTO Chicago event. 4 | 5 | -------------------------------------------------------------------------------- /images/2020-04-13-swaggerhub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mamund/2020-04-unified-api-design/HEAD/images/2020-04-13-swaggerhub.png -------------------------------------------------------------------------------- /images/2020-04-13-graphql-editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mamund/2020-04-unified-api-design/HEAD/images/2020-04-13-graphql-editor.png -------------------------------------------------------------------------------- /slides/2020-04-unified-api-design.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mamund/2020-04-unified-api-design/HEAD/slides/2020-04-unified-api-design.pdf -------------------------------------------------------------------------------- /src/todo-async.yaml: -------------------------------------------------------------------------------- 1 | async: 2.0.0 2 | 3 | # ******************************************************************* 4 | # generated by "unified" from todo-alps.yaml 5 | # date: Sun Apr 12 2020 20:50:50 GMT-0400 (Eastern Daylight Time) 6 | # http://github.com/mamund/2020-04-unified-api-design 7 | # ******************************************************************* 8 | 9 | id: 'http://alps.io/profiles/mamund/todo' 10 | 11 | info: 12 | title: simpleTodo 13 | description: Simple Todo list example 14 | version: '1.0.0' 15 | baseTopic: simpleTodo 16 | host: http://api.example.org/todo 17 | schemes: 18 | - 'amqp' 19 | - 'mqtt' 20 | 21 | topics: 22 | -------------------------------------------------------------------------------- /src/todo-gql.sdl: -------------------------------------------------------------------------------- 1 | // ******************************************************************* 2 | // generated by "unified" from todo-alps.yaml 3 | // date: Sun Apr 12 2020 19:41:44 GMT-0400 (Eastern Daylight Time) 4 | // http://github.com/mamund/2020-04-unified-api-design 5 | // ******************************************************************* 6 | 7 | type todoItem { 8 | id: String! 9 | body: String! 10 | } 11 | 12 | type Query { 13 | todoList: [todoItem] 14 | } 15 | 16 | type Mutation { 17 | todoAdd(id: String!, body: String!): todoItem 18 | todoRemove(id: String!): todoItem 19 | } 20 | 21 | schema { 22 | query: Query, 23 | mutation: Mutation 24 | } 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 2020-04-unified-api-design 2 | 3 | Examples for Unified API Design Method talk 4 | 5 | **NOTE** 6 | 7 | > The source code here is *old*. You'll find the active source project for the `unified` utility here: https://github.com/mamund/alps-unified 8 | 9 | 10 | ``` 11 | // **************************************************** 12 | // unified - an ALPS-to-??? translator 13 | // 14 | // author: @mamund 15 | // date: 2020-04 16 | // 17 | // desc: translates ALPS.yaml into: 18 | // - ALPS.json 19 | // - SDL 20 | // - protobuf 21 | // - openAPI 22 | // - asyncAPI 23 | // 24 | // notes install as npm install -g . 25 | // **************************************************** 26 | ``` 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | 10 | # Packages # 11 | ############ 12 | # it's better to unpack these files and commit the raw source 13 | # git has its own built in compression methods 14 | *.7z 15 | *.dmg 16 | *.gz 17 | *.iso 18 | *.jar 19 | *.rar 20 | *.tar 21 | *.zip 22 | node_modules/ 23 | 24 | # Logs and databases # 25 | ###################### 26 | *.log 27 | *.sql 28 | *.sqlite 29 | 30 | # OS generated files # 31 | ###################### 32 | .DS_Store 33 | .DS_Store? 34 | ._* 35 | .Spotlight-V100 36 | .Trashes 37 | ehthumbs.db 38 | Thumbs.db 39 | *~ 40 | 41 | # local environment data # 42 | ########################## 43 | *.postman_environment.json 44 | *.env 45 | -------------------------------------------------------------------------------- /src/todo-grpc.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package simpleTodo; 3 | 4 | // ******************************************************************* 5 | // generated by "unified" from todo-alps.yaml 6 | // date: Sun Apr 12 2020 22:00:02 GMT-0400 (Eastern Daylight Time) 7 | // http://github.com/mamund/2020-04-unified-api-design 8 | // ******************************************************************* 9 | 10 | message idParams { 11 | string id = 1; 12 | } 13 | message bodyParams { 14 | string body = 1; 15 | } 16 | 17 | message todoItem { 18 | string id = 1; 19 | string body = 2; 20 | } 21 | message todoItemResponse { 22 | repeated todoItem todoItemCollection = 1; 23 | } 24 | message todoItemEmpty {} 25 | 26 | service simpleTodoService { 27 | rpc todoList(todoItemEmpty) returns (todoItemResponse) {}; 28 | rpc todoAdd(todoItem) returns (todoItemResponse) {}; 29 | rpc todoRemove(idParams) returns (todoItemResponse) {}; 30 | } 31 | -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2020-04-unified-api-design", 3 | "version": "1.0.0", 4 | "description": "CLI utility for ALPS translations", 5 | "main": "index.js", 6 | "bin": { 7 | "unified": "index.js" 8 | }, 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/mamund/2020-04-unified-api-design.git" 15 | }, 16 | "keywords": [ 17 | "mamund", 18 | "ALPS", 19 | "gRPC", 20 | "REST", 21 | "SDL", 22 | "GraphQL", 23 | "OpenAPI", 24 | "AsyncAPI" 25 | ], 26 | "author": "Mike Amundsen (@mamund)", 27 | "license": "ISC", 28 | "bugs": { 29 | "url": "https://github.com/mamund/2020-04-unified-api-design/issues" 30 | }, 31 | "homepage": "https://github.com/mamund/2020-04-unified-api-design#readme", 32 | "dependencies": { 33 | "boxen": "^4.0.0", 34 | "chalk": "^2.4.2", 35 | "jstoxml": "^1.6.5", 36 | "yamljs": "^0.3.0", 37 | "yargs": "^13.3.2" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test-sdl.json: -------------------------------------------------------------------------------- 1 | # ******************************************************************* 2 | # generated by "unified" from company-alps.yaml 3 | # date: Sun Aug 30 2020 18:24:03 GMT-0400 (Eastern Daylight Time) 4 | # http://github.com/mamund/2020-04-unified-api-design 5 | # ******************************************************************* 6 | 7 | type company { 8 | id: String! 9 | status: String! 10 | legalName: String! 11 | streetAddress: String! 12 | locality: String! 13 | addressRegion: String! 14 | postalCode: String! 15 | accressCountry: String! 16 | telephone: String! 17 | email: String! 18 | dateCreated: String! 19 | dateUpdated: String! 20 | } 21 | 22 | type Query { 23 | home: [company] 24 | } 25 | type Query { 26 | listCompanies: [company] 27 | } 28 | type Query { 29 | filterCompanies: [company] 30 | } 31 | type Query { 32 | readCompany: [company] 33 | } 34 | 35 | type Mutation { 36 | createCompany(id: String!): company 37 | updateCompany(id: String!): company 38 | removeCompany(id: String!): company 39 | } 40 | 41 | schema { 42 | query: Query, 43 | mutation: Mutation 44 | } 45 | 46 | -------------------------------------------------------------------------------- /todo-story.md: -------------------------------------------------------------------------------- 1 | # Simple ToDo 2 | 3 | ## Purpose 4 | We need to track 'ToDo' records in order to improve both timeliness and accuracy of customer follow-up activity. 5 | 6 | ## Data 7 | In this first pass at the application, we need to keep track of the following data properties: 8 | 9 | * **id** : a globally unique value for each ToDo record 10 | * **body** : the text content of the ToDo record 11 | 12 | ## Actions 13 | This edition of the application needs to support the following operations: 14 | 15 | * **List** : return a list of all active ToDo records in the system 16 | * **Add** : add a new ToDo record to the system 17 | * **Remove** : remove a completed ToDo record from the system 18 | 19 | NOTE: In this edition, we will not track any history of completed ToDo items. 20 | 21 | ## Rules 22 | When creating a record, the client SHOULD generate and send a value for the **id** property. If the client does not send a value for the **id**, the service MUST generate one for that record. In both cases, the service MUST ensure the **id** value is unqiue and reject any writes that would result in duplicate **id** values. 23 | 24 | -------------------------------------------------------------------------------- /src/todo-alps.yaml: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | # TODO .....: Application-Level Profile Semantics doc 3 | # Author ...: Mike Amundsen (@mamund) 4 | # Date .....: 2020-04-30 5 | ###################################################### 6 | 7 | alps: 8 | version: '1.0' 9 | doc: 10 | value: 'Simple Todo list example' 11 | 12 | # metadata 13 | # - various service-related stuff 14 | name: simpleTodo 15 | id: http://alps.io/profiles/mamund/simpleTodo 16 | root: http://api.example.org/todo 17 | 18 | descriptor: 19 | # properties 20 | # - these are the data elements 21 | - id: id 22 | type: semantic 23 | text: storage id of todo item 24 | 25 | - id: body 26 | type: semantic 27 | text: content of todo item 28 | 29 | # groupings 30 | # - these are the storage objects 31 | - id: todoItem 32 | type: group 33 | text: todo item 34 | descriptor: 35 | - href: '#id' 36 | - href: '#body' 37 | 38 | # actions 39 | # - these are the operations 40 | - id: todoList 41 | type: safe 42 | rt: todoItem 43 | text: return list of todo items 44 | 45 | - id: todoAdd 46 | type: unsafe 47 | rt: todoItem 48 | text: create a new todo item 49 | descriptor: 50 | - href: '#todoItem' 51 | 52 | - id: todoRemove 53 | type: idempotent 54 | tags: delete 55 | rt: todoItem 56 | text: remove a single todo item 57 | descriptor: 58 | - href: '#id' 59 | 60 | -------------------------------------------------------------------------------- /src/todo-alps.json: -------------------------------------------------------------------------------- 1 | { 2 | "alps": { 3 | "version": "1.0", 4 | "doc": { 5 | "value": "Simple Todo list example" 6 | }, 7 | "name": "simpleTodo", 8 | "id": "http://alps.io/profiles/mamund/todo", 9 | "root": "http://api.example.org/todo", 10 | "descriptor": [ 11 | { 12 | "id": "id", 13 | "type": "semantic", 14 | "text": "storage id of todo item" 15 | }, 16 | { 17 | "id": "body", 18 | "type": "semantic", 19 | "text": "content of todo item" 20 | }, 21 | { 22 | "id": "todoItem", 23 | "type": "group", 24 | "text": "todo item", 25 | "descriptor": [ 26 | { 27 | "href": "#id" 28 | }, 29 | { 30 | "href": "#body" 31 | } 32 | ] 33 | }, 34 | { 35 | "id": "todoList", 36 | "type": "safe", 37 | "rt": "todoItem", 38 | "text": "return list of todo items" 39 | }, 40 | { 41 | "id": "todoAdd", 42 | "type": "unsafe", 43 | "rt": "todoItem", 44 | "text": "create a new todo item", 45 | "descriptor": [ 46 | { 47 | "href": "#todoItem" 48 | } 49 | ] 50 | }, 51 | { 52 | "id": "todoRemove", 53 | "type": "idempotent", 54 | "ex": "delete", 55 | "rt": "todoItem", 56 | "text": "remove a single todo item", 57 | "descriptor": [ 58 | { 59 | "href": "#id" 60 | } 61 | ] 62 | } 63 | ] 64 | } 65 | } -------------------------------------------------------------------------------- /run/todo-alps.yaml: -------------------------------------------------------------------------------- 1 | ###################################################### 2 | # TODO .....: Application-Level Profile Semantics doc 3 | # Author ...: Mike Amundsen (@mamund) 4 | # Date .....: 2020-04-30 5 | ###################################################### 6 | 7 | alps: 8 | version: '1.0' 9 | doc: 10 | value: 'Simple Todo list example' 11 | 12 | # metadata 13 | # - various service-related stuff 14 | ext: 15 | - type: metadata 16 | name: title 17 | value: ToDo API 18 | tags: 'oas' 19 | - type: metadata 20 | name: id 21 | value: http://alps.io/profiles/mamund/simpleTodo 22 | tags: 'oas' 23 | - type: metadata 24 | name: root 25 | value: http://api.example.org/todo 26 | tags: 'oas' 27 | 28 | descriptor: 29 | # properties 30 | # - these are the data elements 31 | - id: id 32 | type: semantic 33 | text: storage id of todo item 34 | 35 | - id: body 36 | type: semantic 37 | text: content of todo item 38 | 39 | # groupings 40 | # - these are the storage objects 41 | - id: todoItem 42 | type: group 43 | text: todo item 44 | descriptor: 45 | - href: '#id' 46 | - href: '#body' 47 | 48 | # actions 49 | # - these are the operations 50 | - id: todoList 51 | type: safe 52 | rt: todoItem 53 | text: return list of todo items 54 | 55 | - id: todoAdd 56 | type: unsafe 57 | rt: todoItem 58 | text: create a new todo item 59 | descriptor: 60 | - href: '#todoItem' 61 | 62 | - id: todoRemove 63 | type: idempotent 64 | tags: delete 65 | rt: todoItem 66 | text: remove a single todo item 67 | descriptor: 68 | - href: '#id' 69 | 70 | -------------------------------------------------------------------------------- /src/test-proto.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package Company_API; 3 | 4 | // ******************************************************************* 5 | // generated by "unified" from company-alps.yaml 6 | // date: Sun Aug 30 2020 18:33:57 GMT-0400 (Eastern Daylight Time) 7 | // http://github.com/mamund/2020-04-unified-api-design 8 | // ******************************************************************* 9 | 10 | message idParams { 11 | string id = 1; 12 | } 13 | message statusParams { 14 | string status = 1; 15 | } 16 | message legalNameParams { 17 | string legalName = 1; 18 | } 19 | message streetAddressParams { 20 | string streetAddress = 1; 21 | } 22 | message localityParams { 23 | string locality = 1; 24 | } 25 | message addressRegionParams { 26 | string addressRegion = 1; 27 | } 28 | message postalCodeParams { 29 | string postalCode = 1; 30 | } 31 | message addressCountryParams { 32 | string addressCountry = 1; 33 | } 34 | message telephoneParams { 35 | string telephone = 1; 36 | } 37 | message emailParams { 38 | string email = 1; 39 | } 40 | message dateCreatedParams { 41 | string dateCreated = 1; 42 | } 43 | message dateUpdatedParams { 44 | string dateUpdated = 1; 45 | } 46 | 47 | message company { 48 | string id = 1; 49 | string status = 2; 50 | string legalName = 3; 51 | string streetAddress = 4; 52 | string locality = 5; 53 | string addressRegion = 6; 54 | string postalCode = 7; 55 | string accressCountry = 8; 56 | string telephone = 9; 57 | string email = 10; 58 | string dateCreated = 11; 59 | string dateUpdated = 12; 60 | } 61 | message companyResponse { 62 | repeated company companyCollection = 1; 63 | } 64 | message companyEmpty {} 65 | 66 | service Company APIService { 67 | rpc home(companyEmpty) returns (companyResponse) {}; 68 | rpc listCompanies(companyEmpty) returns (companyResponse) {}; 69 | rpc filterCompanies(legalName) returns (companyResponse) {}; 70 | rpc readCompany(id) returns (companyResponse) {}; 71 | rpc createCompany(id) returns (companyResponse) {}; 72 | rpc updateCompany(idParams) returns (companyResponse) {}; 73 | rpc removeCompany(idParams) returns (companyResponse) {}; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /src/todo-oas.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.1 2 | 3 | # ******************************************************************* 4 | # generated by "unified" from todo-alps.yaml 5 | # date: Mon Apr 13 2020 21:15:38 GMT-0400 (Eastern Daylight Time) 6 | # http://github.com/mamund/2020-04-unified-api-design 7 | # ******************************************************************* 8 | 9 | info: 10 | title: simpleTodo 11 | description: Simple Todo list example 12 | version: 1.0.0 13 | 14 | servers: 15 | - url: 'http://api.example.org/todo' 16 | 17 | paths: 18 | /todoList: 19 | get: 20 | summary: 'return list of todo items' 21 | operationId: todoList 22 | responses: 23 | 200: 24 | description: get todoList 25 | content: 26 | application/json: 27 | schema: 28 | type: array 29 | items: 30 | $ref: '#/components/schemas/todoItem' 31 | /todoAdd: 32 | post: 33 | summary: 'create a new todo item' 34 | operationId: todoAdd 35 | requestBody: 36 | content: 37 | application/json: 38 | schema: 39 | $ref: '#/components/schemas/todoItem' 40 | responses: 41 | 200: 42 | description: add todoAdd 43 | content: 44 | application/json: 45 | schema: 46 | type: array 47 | items: 48 | $ref: '#/components/schemas/todoItem' 49 | /todoRemove/{id}: 50 | delete: 51 | summary: 'remove a single todo item' 52 | operationId: todoRemove 53 | parameters: 54 | - name: id 55 | in: path 56 | description: id of todoRemove 57 | required: true 58 | schema: 59 | type: string 60 | responses: 61 | 204: 62 | description: delete todoRemove 63 | 64 | components: 65 | schemas: 66 | todoItem: 67 | description: todo item 68 | type: object 69 | properties: 70 | id: 71 | type: string 72 | example: 8545 73 | body: 74 | type: string 75 | example: 01oqjycmwd3nkf13sies1x 76 | -------------------------------------------------------------------------------- /src/company-ext-alps.yaml: -------------------------------------------------------------------------------- 1 | alps: 2 | version: '1.0' 3 | doc: 4 | value: ALPS document for BigCo Company API 5 | 6 | #################################### 7 | # metadata 8 | ext: 9 | - type: metadata 10 | name: title 11 | value: Company API 12 | tags: 'oas' 13 | - type: metadata 14 | name: id 15 | value: http://alps.io/profiles/mamund/company 16 | tags: 'oas' 17 | - type: metadata 18 | name: root 19 | value: http://api.example.org/company 20 | tags: 'oas' 21 | 22 | descriptor: 23 | ################################## 24 | # properties 25 | - id: id 26 | type: semantic 27 | 28 | - id: status 29 | type: semantic 30 | text: 'suspended, pending, active, closed' 31 | 32 | - id: legalName 33 | type: semantic 34 | 35 | - id: streetAddress 36 | type: semantic 37 | 38 | - id: locality 39 | type: semantic 40 | 41 | - id: addressRegion 42 | type: semantic 43 | 44 | - id: postalCode 45 | type: semantic 46 | 47 | - id: addressCountry 48 | type: semantic 49 | 50 | - id: telephone 51 | type: semantic 52 | 53 | - id: email 54 | type: semantic 55 | 56 | - id: dateCreated 57 | type: semantic 58 | 59 | - id: dateUpdated 60 | type: semantic 61 | 62 | ################################ 63 | # groups 64 | - id: company 65 | type: group 66 | text: company item 67 | descriptor: 68 | - href: '#id' 69 | - href: '#status' 70 | - href: '#legalName' 71 | - href: '#streetAddress' 72 | - href: '#locality' 73 | - href: '#addressRegion' 74 | - href: '#postalCode' 75 | - href: '#accressCountry' 76 | - href: '#telephone' 77 | - href: '#email' 78 | - href: '#dateCreated' 79 | - href: '#dateUpdated' 80 | 81 | ############################### 82 | # actions 83 | - id: home 84 | type: safe 85 | rt: '#company' 86 | 87 | - id: listCompanies 88 | type: safe 89 | rt: '#company' 90 | 91 | - id: filterCompanies 92 | type: safe 93 | rt: '#company' 94 | descriptor: 95 | - href: '#legalName' 96 | - href: '#addressCountry' 97 | - href: '#status' 98 | - href: '#locality' 99 | 100 | - id: readCompany 101 | type: safe 102 | rt: '#company' 103 | descriptor: 104 | - href: '#id' 105 | 106 | - id: createCompany 107 | type: unsafe 108 | rt: '#company' 109 | descriptor: 110 | - href: '#id' 111 | - href: '#status' 112 | - href: '#legalName' 113 | - href: '#streetAddress' 114 | - href: '#locality' 115 | - href: '#addressRegion' 116 | - href: '#postalCode' 117 | - href: '#telephone' 118 | - href: '#email' 119 | 120 | - id: updateCompany 121 | type: idempotent 122 | tags: update 123 | rt: '#company' 124 | descriptor: 125 | - href: '#id' 126 | - href: '#status' 127 | - href: '#legalName' 128 | - href: '#streetAddress' 129 | - href: '#locality' 130 | - href: '#addressRegion' 131 | - href: '#postalCode' 132 | - href: '#telephone' 133 | - href: '#email' 134 | 135 | - id: removeCompany 136 | type: idempotent 137 | tags: delete 138 | rt: '#company' 139 | descriptor: 140 | - href: '#id' 141 | 142 | ################################### 143 | # EOF 144 | ################################### 145 | -------------------------------------------------------------------------------- /src/company-oas.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.1 2 | 3 | # ******************************************************************* 4 | # generated by "unified" from company-alps.yaml 5 | # date: Thu Apr 30 2020 04:21:23 GMT-0400 (Eastern Daylight Time) 6 | # http://github.com/mamund/2020-04-unified-api-design 7 | # ******************************************************************* 8 | 9 | info: 10 | title: Company API 11 | description: ALPS document for BigCo Company API 12 | version: 1.0.0 13 | 14 | servers: 15 | - url: 'http://api.example.org/company' 16 | 17 | paths: 18 | /home: 19 | get: 20 | summary: 'home' 21 | operationId: home 22 | responses: 23 | 200: 24 | description: home 25 | content: 26 | application/json: 27 | schema: 28 | type: array 29 | items: 30 | $ref: '#/components/schemas/company' 31 | /listCompanies: 32 | get: 33 | summary: 'listCompanies' 34 | operationId: listCompanies 35 | responses: 36 | 200: 37 | description: listCompanies 38 | content: 39 | application/json: 40 | schema: 41 | type: array 42 | items: 43 | $ref: '#/components/schemas/company' 44 | /filterCompanies: 45 | get: 46 | summary: 'filterCompanies' 47 | operationId: filterCompanies 48 | responses: 49 | 200: 50 | description: filterCompanies 51 | content: 52 | application/json: 53 | schema: 54 | type: array 55 | items: 56 | $ref: '#/components/schemas/company' 57 | /readCompany: 58 | get: 59 | summary: 'readCompany' 60 | operationId: readCompany 61 | responses: 62 | 200: 63 | description: readCompany 64 | content: 65 | application/json: 66 | schema: 67 | type: array 68 | items: 69 | $ref: '#/components/schemas/company' 70 | /createCompany: 71 | post: 72 | summary: 'createCompany' 73 | operationId: createCompany 74 | requestBody: 75 | content: 76 | application/json: 77 | schema: 78 | $ref: '#/components/schemas/company' 79 | responses: 80 | 200: 81 | description: add createCompany 82 | content: 83 | application/json: 84 | schema: 85 | type: array 86 | items: 87 | $ref: '#/components/schemas/company' 88 | /updateCompany: 89 | put: 90 | summary: 'updateCompany' 91 | operationId: updateCompany 92 | requestBody: 93 | content: 94 | application/json: 95 | schema: 96 | $ref: '#/components/schemas/company' 97 | responses: 98 | 200: 99 | description: add updateCompany 100 | content: 101 | application/json: 102 | schema: 103 | type: array 104 | items: 105 | $ref: '#/components/schemas/company' 106 | /removeCompany/{id}: 107 | delete: 108 | summary: 'removeCompany' 109 | operationId: removeCompany 110 | parameters: 111 | - name: id 112 | in: path 113 | description: id of removeCompany 114 | required: true 115 | schema: 116 | type: string 117 | responses: 118 | 204: 119 | description: delete removeCompany 120 | 121 | components: 122 | schemas: 123 | company: 124 | description: company item 125 | type: object 126 | properties: 127 | id: 128 | type: string 129 | example: 6256 130 | status: 131 | type: string 132 | example: azze3ir476t122c69eyx 133 | legalName: 134 | type: string 135 | example: tkgm4yk3x99rxhxmu7hop 136 | streetAddress: 137 | type: string 138 | example: 70qch0lbm2fcu4w9c8f3xb 139 | locality: 140 | type: string 141 | example: 2tix6nno9wns61m0stav8h 142 | addressRegion: 143 | type: string 144 | example: 2xor46jylmor67drc9t6l8 145 | postalCode: 146 | type: string 147 | example: ovo80rnzkiyt4qbvc1wm9 148 | accressCountry: 149 | type: string 150 | example: irodelk9rjnwrrdzcist 151 | telephone: 152 | type: string 153 | example: 585w1nfulzksvyhr86iqnt 154 | email: 155 | type: string 156 | example: z7rh07d9hokbl3i8wqlbee 157 | dateCreated: 158 | type: string 159 | example: cnu4ijeuedii8dsr8eqbqn 160 | dateUpdated: 161 | type: string 162 | example: g9q43y79609h1evckjstym 163 | 164 | -------------------------------------------------------------------------------- /src/test-oas.yaml: -------------------------------------------------------------------------------- 1 | openapi: 3.0.1 2 | 3 | # ******************************************************************* 4 | # generated by "unified" from company-alps.yaml 5 | # date: Sun Aug 30 2020 18:23:17 GMT-0400 (Eastern Daylight Time) 6 | # http://github.com/mamund/2020-04-unified-api-design 7 | # ******************************************************************* 8 | 9 | info: 10 | title: Company API 11 | description: ALPS document for BigCo Company API 12 | version: 1.0.0 13 | 14 | servers: 15 | - url: 'http://api.example.org/company' 16 | 17 | paths: 18 | /home: 19 | get: 20 | summary: 'home' 21 | operationId: home 22 | responses: 23 | 200: 24 | description: home 25 | content: 26 | application/json: 27 | schema: 28 | type: array 29 | items: 30 | $ref: '#/components/schemas/company' 31 | /listCompanies: 32 | get: 33 | summary: 'listCompanies' 34 | operationId: listCompanies 35 | responses: 36 | 200: 37 | description: listCompanies 38 | content: 39 | application/json: 40 | schema: 41 | type: array 42 | items: 43 | $ref: '#/components/schemas/company' 44 | /filterCompanies: 45 | get: 46 | summary: 'filterCompanies' 47 | operationId: filterCompanies 48 | responses: 49 | 200: 50 | description: filterCompanies 51 | content: 52 | application/json: 53 | schema: 54 | type: array 55 | items: 56 | $ref: '#/components/schemas/company' 57 | /readCompany: 58 | get: 59 | summary: 'readCompany' 60 | operationId: readCompany 61 | responses: 62 | 200: 63 | description: readCompany 64 | content: 65 | application/json: 66 | schema: 67 | type: array 68 | items: 69 | $ref: '#/components/schemas/company' 70 | /createCompany: 71 | post: 72 | summary: 'createCompany' 73 | operationId: createCompany 74 | requestBody: 75 | content: 76 | application/json: 77 | schema: 78 | $ref: '#/components/schemas/company' 79 | responses: 80 | 200: 81 | description: add createCompany 82 | content: 83 | application/json: 84 | schema: 85 | type: array 86 | items: 87 | $ref: '#/components/schemas/company' 88 | /updateCompany: 89 | put: 90 | summary: 'updateCompany' 91 | operationId: updateCompany 92 | requestBody: 93 | content: 94 | application/json: 95 | schema: 96 | $ref: '#/components/schemas/company' 97 | responses: 98 | 200: 99 | description: add updateCompany 100 | content: 101 | application/json: 102 | schema: 103 | type: array 104 | items: 105 | $ref: '#/components/schemas/company' 106 | /removeCompany/{id}: 107 | delete: 108 | summary: 'removeCompany' 109 | operationId: removeCompany 110 | parameters: 111 | - name: id 112 | in: path 113 | description: id of removeCompany 114 | required: true 115 | schema: 116 | type: string 117 | responses: 118 | 204: 119 | description: delete removeCompany 120 | 121 | components: 122 | schemas: 123 | company: 124 | description: company item 125 | type: object 126 | properties: 127 | id: 128 | type: string 129 | example: 3341 130 | status: 131 | type: string 132 | example: 7yebun913rd70dieg45fvc 133 | legalName: 134 | type: string 135 | example: f03xrrnh9rsh86ukqrsp3 136 | streetAddress: 137 | type: string 138 | example: 6a915xczk36wl0a5o6kdz 139 | locality: 140 | type: string 141 | example: cbtbnpq8uef8hfzsaw4q8p 142 | addressRegion: 143 | type: string 144 | example: 416pil1mqst8ytzx2z8lhf 145 | postalCode: 146 | type: string 147 | example: qffan6iz8pior0dmy7f9c 148 | accressCountry: 149 | type: string 150 | example: 3d3mnce0p2fp6gk81jf67l 151 | telephone: 152 | type: string 153 | example: eo9bj45qremx6tlqyo0iis 154 | email: 155 | type: string 156 | example: 6zknvhxlibodscma25ievg 157 | dateCreated: 158 | type: string 159 | example: yrr9ghno4t9zt9y20m3doj 160 | dateUpdated: 161 | type: string 162 | example: lmof4n2ou7rhbg1it3vec 163 | 164 | -------------------------------------------------------------------------------- /src/company-ext-alps.json: -------------------------------------------------------------------------------- 1 | { 2 | "alps": { 3 | "version": "1.0", 4 | "doc": { 5 | "value": "ALPS document for BigCo Company API" 6 | }, 7 | "ext": [ 8 | { 9 | "type": "metadata", 10 | "name": "title", 11 | "value": "Company API", 12 | "tags": "oas" 13 | }, 14 | { 15 | "type": "metadata", 16 | "name": "id", 17 | "value": "http://alps.io/profiles/mamund/company", 18 | "tags": "oas" 19 | }, 20 | { 21 | "type": "metadata", 22 | "name": "root", 23 | "value": "http://api.example.org/company", 24 | "tags": "oas" 25 | } 26 | ], 27 | "descriptor": [ 28 | { 29 | "id": "id", 30 | "type": "semantic" 31 | }, 32 | { 33 | "id": "status", 34 | "type": "semantic", 35 | "text": "suspended, pending, active, closed" 36 | }, 37 | { 38 | "id": "legalName", 39 | "type": "semantic" 40 | }, 41 | { 42 | "id": "streetAddress", 43 | "type": "semantic" 44 | }, 45 | { 46 | "id": "locality", 47 | "type": "semantic" 48 | }, 49 | { 50 | "id": "addressRegion", 51 | "type": "semantic" 52 | }, 53 | { 54 | "id": "postalCode", 55 | "type": "semantic" 56 | }, 57 | { 58 | "id": "addressCountry", 59 | "type": "semantic" 60 | }, 61 | { 62 | "id": "telephone", 63 | "type": "semantic" 64 | }, 65 | { 66 | "id": "email", 67 | "type": "semantic" 68 | }, 69 | { 70 | "id": "dateCreated", 71 | "type": "semantic" 72 | }, 73 | { 74 | "id": "dateUpdated", 75 | "type": "semantic" 76 | }, 77 | { 78 | "id": "company", 79 | "type": "group", 80 | "text": "company item", 81 | "descriptor": [ 82 | { 83 | "href": "#id" 84 | }, 85 | { 86 | "href": "#status" 87 | }, 88 | { 89 | "href": "#legalName" 90 | }, 91 | { 92 | "href": "#streetAddress" 93 | }, 94 | { 95 | "href": "#locality" 96 | }, 97 | { 98 | "href": "#addressRegion" 99 | }, 100 | { 101 | "href": "#postalCode" 102 | }, 103 | { 104 | "href": "#accressCountry" 105 | }, 106 | { 107 | "href": "#telephone" 108 | }, 109 | { 110 | "href": "#email" 111 | }, 112 | { 113 | "href": "#dateCreated" 114 | }, 115 | { 116 | "href": "#dateUpdated" 117 | } 118 | ] 119 | }, 120 | { 121 | "id": "home", 122 | "type": "safe", 123 | "rt": "#company" 124 | }, 125 | { 126 | "id": "listCompanies", 127 | "type": "safe", 128 | "rt": "#company" 129 | }, 130 | { 131 | "id": "filterCompanies", 132 | "type": "safe", 133 | "rt": "#company", 134 | "descriptor": [ 135 | { 136 | "href": "#legalName" 137 | }, 138 | { 139 | "href": "#addressCountry" 140 | }, 141 | { 142 | "href": "#status" 143 | }, 144 | { 145 | "href": "#locality" 146 | } 147 | ] 148 | }, 149 | { 150 | "id": "readCompany", 151 | "type": "safe", 152 | "rt": "#company", 153 | "descriptor": [ 154 | { 155 | "href": "#id" 156 | } 157 | ] 158 | }, 159 | { 160 | "id": "createCompany", 161 | "type": "unsafe", 162 | "rt": "#company", 163 | "descriptor": [ 164 | { 165 | "href": "#id" 166 | }, 167 | { 168 | "href": "#status" 169 | }, 170 | { 171 | "href": "#legalName" 172 | }, 173 | { 174 | "href": "#streetAddress" 175 | }, 176 | { 177 | "href": "#locality" 178 | }, 179 | { 180 | "href": "#addressRegion" 181 | }, 182 | { 183 | "href": "#postalCode" 184 | }, 185 | { 186 | "href": "#telephone" 187 | }, 188 | { 189 | "href": "#email" 190 | } 191 | ] 192 | }, 193 | { 194 | "id": "updateCompany", 195 | "type": "idempotent", 196 | "tags": "update", 197 | "rt": "#company", 198 | "descriptor": [ 199 | { 200 | "href": "#id" 201 | }, 202 | { 203 | "href": "#status" 204 | }, 205 | { 206 | "href": "#legalName" 207 | }, 208 | { 209 | "href": "#streetAddress" 210 | }, 211 | { 212 | "href": "#locality" 213 | }, 214 | { 215 | "href": "#addressRegion" 216 | }, 217 | { 218 | "href": "#postalCode" 219 | }, 220 | { 221 | "href": "#telephone" 222 | }, 223 | { 224 | "href": "#email" 225 | } 226 | ] 227 | }, 228 | { 229 | "id": "removeCompany", 230 | "type": "idempotent", 231 | "tags": "delete", 232 | "rt": "#company", 233 | "descriptor": [ 234 | { 235 | "href": "#id" 236 | } 237 | ] 238 | } 239 | ] 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // **************************************************** 4 | // unified - an ALPS-to-??? translator 5 | // 6 | // author: @mamund 7 | // date: 2020-04 8 | // 9 | // desc: translates ALPS.yaml into: 10 | // - ALPS.json 11 | // - SDL 12 | // - protobuf 13 | // - openAPI 14 | // - asyncAPI 15 | // 16 | // notes install as npm install -g . 17 | // proof-of-concept utility (needs work) 18 | // **************************************************** 19 | 20 | // modules 21 | const chalk = require("chalk"); 22 | const boxen = require("boxen"); 23 | const yargs = require("yargs"); 24 | const YAML = require("yamljs"); 25 | const fs = require('fs'); 26 | 27 | // args 28 | const options = yargs 29 | .usage("Usage: -f -t -o ") 30 | .option("f", { alias: "file", 31 | describe: "Input file (alps.yaml)", 32 | type: "string", demandOption: true }) 33 | .option("t", { alias: "type", 34 | describe: "Format Type \n([j]son, [p]roto, [s]dl, [a]syncapi, [o]penapi)", 35 | type: "string", demandOption: false}) 36 | .option("o", { alias: "out", 37 | describe: "Output file", 38 | type: "string", demandOption: false}) 39 | .argv; 40 | 41 | // cleanup regex 42 | const rxHash = /#/g; 43 | const rxQ = /\?\?/g; 44 | 45 | // init vars 46 | var alps_document = {}; 47 | var format = "json"; 48 | var rtn = ""; 49 | 50 | // convert YAML into JSON 51 | try { 52 | var file = `${process.cwd()}/${options.file}`; 53 | alps_document = YAML.load(file); 54 | } 55 | catch(err) { 56 | console.log(`ERROR: ${err}`); 57 | } 58 | 59 | // selection translation 60 | try { 61 | format = options.type.toLowerCase(); 62 | } 63 | catch { 64 | format = "json"; 65 | } 66 | 67 | //console.log(alps_document.alps.ext.filter(oasMetadata)); 68 | //return; 69 | 70 | // process requested translation 71 | switch (format) { 72 | case "s": 73 | case "sdl": 74 | rtn = toSDL(alps_document); 75 | break; 76 | case "a": 77 | case "async": 78 | case "asyncapi": 79 | rtn = toAsync(alps_document); 80 | break; 81 | case "o": 82 | case "oas": 83 | case "open": 84 | case "openapi": 85 | rtn = toOAS(alps_document); 86 | break; 87 | case "p": 88 | case "proto": 89 | rtn = toProto(alps_document); 90 | break; 91 | case "j": 92 | case "json": 93 | rtn = toJSON(alps_document); 94 | break; 95 | default: 96 | console.log(`ERROR: unknown format: ${format}`); 97 | } 98 | 99 | // output directly 100 | if(options.out) { 101 | try { 102 | fs.writeFileSync(options.out, rtn); 103 | } 104 | catch(err) { 105 | console.log(`ERROR: ${err}`); 106 | } 107 | } 108 | else { 109 | console.log(rtn); 110 | } 111 | 112 | // ******************************************* 113 | // translators 114 | // ******************************************* 115 | 116 | // **************************************************** 117 | // to ALPS JSON 118 | // **************************************************** 119 | function toJSON(doc) { 120 | var rtn = ""; 121 | rtn = JSON.stringify(doc, null, 2); 122 | return rtn 123 | } 124 | 125 | // **************************************************** 126 | // to proto file 127 | // passes https://protogen.marcgravell.com/ validator 128 | // **************************************************** 129 | function toProto(doc) { 130 | var rtn = ""; 131 | var obj; 132 | var coll; 133 | 134 | // preamble 135 | rtn += 'syntax = "proto3";\n'; 136 | rtn += `package ${doc.alps.ext.filter(metadata_title)[0].value.replace(/ /g,'_')||"ALPS_API"};\n`; 137 | rtn += '\n'; 138 | 139 | // signature 140 | rtn += '// *******************************************************************\n'; 141 | rtn += `// generated by "unified" from ${options.file}\n`; 142 | rtn += `// date: ${new Date()}`; 143 | rtn += '\n'; 144 | rtn += '// http://github.com/mamund/2020-04-unified-api-design\n'; 145 | rtn += '// *******************************************************************\n'; 146 | rtn += '\n'; 147 | 148 | // params 149 | coll = doc.alps.descriptor.filter(semantic); 150 | coll.forEach(function(msg) { 151 | rtn += `message ${msg.id}Params {\n`; 152 | var c = 0; 153 | c++; 154 | rtn += ` string ${msg.id} = ${c};\n`; 155 | rtn += '}\n'; 156 | }); 157 | rtn += '\n'; 158 | 159 | // objects 160 | coll = doc.alps.descriptor.filter(groups); 161 | coll.forEach(function(msg) { 162 | rtn += `message ${msg.id} {\n`; 163 | var c = 0; 164 | msg.descriptor.forEach(function(prop) { 165 | c++; 166 | rtn += ` string ${prop.href} = ${c};\n`; 167 | }); 168 | rtn += '}\n'; 169 | rtn += `message ${msg.id}Response {\n`; 170 | rtn += ` repeated ${msg.id} ${msg.id}Collection = 1;\n` 171 | rtn += '}\n'; 172 | rtn += `message ${msg.id}Empty {}\n`; 173 | }); 174 | rtn += '\n'; 175 | 176 | // procedures 177 | rtn += `service ${doc.alps.ext.filter(metadata_title)[0].value.replace(/ /g,'_')||"ALPS_API"}_Service {\n`; 178 | 179 | coll = doc.alps.descriptor.filter(safe); 180 | coll.forEach(function(item) { 181 | rtn += ` rpc ${item.id}(` 182 | if(item.descriptor) { 183 | rtn += item.descriptor[0].href; 184 | } 185 | else { 186 | rtn += `${item.rt}Empty`; 187 | } 188 | rtn += `) returns (${item.rt}Response) {};\n`; 189 | }); 190 | 191 | coll = doc.alps.descriptor.filter(unsafe); 192 | coll.forEach(function(item) { 193 | rtn += ` rpc ${item.id}(` 194 | if(item.descriptor) { 195 | rtn += item.descriptor[0].href; 196 | } 197 | rtn += `) returns (${item.rt}Response) {};\n`; 198 | }); 199 | 200 | coll = doc.alps.descriptor.filter(idempotent); 201 | coll.forEach(function(item) { 202 | rtn += ` rpc ${item.id}(` 203 | if(item.descriptor) { 204 | rtn += item.descriptor[0].href; 205 | if(item.descriptor[0].href === "#id") { 206 | rtn += "Params"; 207 | } 208 | } 209 | rtn += `) returns (${item.rt}Response) {};\n`; 210 | }); 211 | 212 | rtn += '}\n'; 213 | 214 | // clean up 215 | rtn = rtn.replace(rxHash,""); 216 | rtn = rtn.replace(rxQ,"#"); 217 | 218 | return rtn; 219 | } 220 | 221 | // ******************************************* 222 | // to graphql sdl 223 | // passes https://app.graphqleditor.com/ 224 | // ******************************************* 225 | function toSDL(doc) { 226 | var rtn = ""; 227 | var coll; 228 | 229 | // signature 230 | rtn += '?? *******************************************************************\n'; 231 | rtn += `?? generated by "unified" from ${options.file}\n`; 232 | rtn += `?? date: ${new Date()}`; 233 | rtn += '\n'; 234 | rtn += '?? http://github.com/mamund/2020-04-unified-api-design\n'; 235 | rtn += '?? *******************************************************************\n'; 236 | rtn += '\n'; 237 | 238 | // types 239 | coll = doc.alps.descriptor.filter(groups); 240 | coll.forEach(function(item) { 241 | rtn += `type ${item.id} {\n`; 242 | item.descriptor.forEach(function(prop) { 243 | rtn += ` ${prop.href}: String!\n`; 244 | }); 245 | rtn += '}\n'; 246 | }); 247 | rtn += '\n'; 248 | 249 | // query 250 | coll = doc.alps.descriptor.filter(safe); 251 | coll.forEach(function(item) { 252 | rtn += 'type Query {\n'; 253 | rtn += ` ${item.id}: [${item.rt}]\n`; 254 | rtn += '}\n'; 255 | }); 256 | rtn += '\n'; 257 | 258 | // mutations 259 | rtn += 'type Mutation {\n'; 260 | coll = doc.alps.descriptor.filter(unsafe); 261 | coll.forEach(function(item) { 262 | rtn += ` ${item.id}(`; 263 | if(item.descriptor) { 264 | rtn += `${item.descriptor[0].href}: String!`; 265 | } 266 | rtn += `): ${item.rt}\n`; 267 | }); 268 | coll = doc.alps.descriptor.filter(idempotent); 269 | coll.forEach(function(item) { 270 | rtn += ` ${item.id}(`; 271 | if(item.descriptor) { 272 | rtn += `${item.descriptor[0].href}: String!`; 273 | } 274 | rtn += `): ${item.rt}\n`; 275 | }); 276 | rtn += '}\n'; 277 | 278 | // final schema declaration 279 | rtn += '\n'; 280 | rtn += 'schema {\n'; 281 | rtn += ' query: Query,\n'; 282 | rtn += ' mutation: Mutation\n'; 283 | rtn += '}\n'; 284 | 285 | rtn = rtn.replace(rxHash,""); 286 | rtn = rtn.replace(rxQ,"#"); 287 | 288 | return rtn; 289 | } 290 | 291 | // *************************************************** 292 | // to OpenAPI document 293 | // passes https://apitools.dev/swagger-parser/online/ 294 | // *************************************************** 295 | function toOAS(doc) { 296 | var rtn = ""; 297 | 298 | // preamble 299 | rtn += "openapi: 3.0.1\n"; 300 | rtn += "\n"; 301 | 302 | // signature 303 | rtn += '?? *******************************************************************\n'; 304 | rtn += `?? generated by "unified" from ${options.file}\n`; 305 | rtn += `?? date: ${new Date()}`; 306 | rtn += '\n'; 307 | rtn += '?? http://github.com/mamund/2020-04-unified-api-design\n'; 308 | rtn += '?? *******************************************************************\n'; 309 | rtn += '\n'; 310 | 311 | 312 | // info section 313 | rtn += "info:\n"; 314 | rtn += ` title: ${doc.alps.ext.filter(metadata_title)[0].value||"ALPS API"}\n`; 315 | rtn += ` description: ${doc.alps.doc.value||`Generated from ALPS file ${options.file}`}\n`; 316 | rtn += " version: 1.0.0\n"; 317 | rtn += "\n"; 318 | 319 | if(doc.alps.ext.filter(metadata_root)) { 320 | rtn += "servers:\n" 321 | rtn += `- url: '${doc.alps.ext.filter(metadata_root)[0].value}'\n`; 322 | rtn += "\n"; 323 | } 324 | 325 | // paths 326 | rtn += "paths:\n"; 327 | 328 | // gets 329 | coll = doc.alps.descriptor.filter(safe); 330 | coll.forEach(function(item) { 331 | rtn += ` /${item.id}:\n`; 332 | rtn += " get:\n"; 333 | rtn += ` summary: '${item.text||item.id}'\n`; 334 | rtn += ` operationId: ${item.id}\n`; 335 | rtn += " responses:\n"; 336 | rtn += " 200:\n"; 337 | rtn += ` description: ${item.id}\n`; 338 | rtn += " content:\n"; 339 | rtn += " application/json:\n"; 340 | rtn += " schema:\n"; 341 | rtn += " type: array\n"; 342 | rtn += " items:\n"; 343 | rtn += ` $ref: '??/components/schemas/${item.rt||item.returns}'\n`; 344 | }); 345 | 346 | // posts 347 | coll = doc.alps.descriptor.filter(unsafe); 348 | coll.forEach(function(item) { 349 | rtn += ` /${item.id}:\n`; 350 | rtn += " post:\n"; 351 | rtn += ` summary: '${item.text||item.id}'\n`; 352 | rtn += ` operationId: ${item.id}\n`; 353 | rtn += " requestBody:\n"; 354 | rtn += " content:\n"; 355 | rtn += " application/json:\n"; 356 | rtn += " schema:\n"; 357 | rtn += ` $ref: '??/components/schemas/${item.rt||item.returns}'\n`; 358 | rtn += " responses:\n"; 359 | rtn += " 200:\n"; 360 | rtn += ` description: add ${item.id}\n`; 361 | rtn += " content:\n"; 362 | rtn += " application/json:\n"; 363 | rtn += " schema:\n"; 364 | rtn += " type: array\n"; 365 | rtn += " items:\n"; 366 | rtn += ` $ref: '??/components/schemas/${item.rt||item.returns}'\n`; 367 | }); 368 | 369 | // put 370 | coll = doc.alps.descriptor.filter(update); 371 | coll.forEach(function(item) { 372 | rtn += ` /${item.id}:\n`; 373 | rtn += " put:\n"; 374 | rtn += ` summary: '${item.text||item.id}'\n`; 375 | rtn += ` operationId: ${item.id}\n`; 376 | rtn += " requestBody:\n"; 377 | rtn += " content:\n"; 378 | rtn += " application/json:\n"; 379 | rtn += " schema:\n"; 380 | rtn += ` $ref: '??/components/schemas/${item.rt||item.returns}'\n`; 381 | rtn += " responses:\n"; 382 | rtn += " 200:\n"; 383 | rtn += ` description: add ${item.id}\n`; 384 | rtn += " content:\n"; 385 | rtn += " application/json:\n"; 386 | rtn += " schema:\n"; 387 | rtn += " type: array\n"; 388 | rtn += " items:\n"; 389 | rtn += ` $ref: '??/components/schemas/${item.rt||item.returns}'\n`; 390 | }); 391 | 392 | // deletes 393 | coll = doc.alps.descriptor.filter(remove); 394 | coll.forEach(function(item) { 395 | rtn += ` /${item.id}/{id}:\n`; 396 | rtn += " delete:\n"; 397 | rtn += ` summary: '${item.text||item.id}'\n`; 398 | rtn += ` operationId: ${item.id}\n`; 399 | rtn += " parameters:\n"; 400 | item.descriptor.forEach(function(prop) { 401 | rtn += ` - name: ${prop.href}\n`; 402 | rtn += " in: path\n"; 403 | rtn += ` description: ${prop.href} of ${item.id}\n`; 404 | rtn += " required: true\n"; 405 | rtn += " schema:\n"; 406 | rtn += " type: string\n"; 407 | }); 408 | rtn += " responses:\n"; 409 | rtn += " 204:\n"; 410 | rtn += ` description: delete ${item.id}\n`; 411 | }); 412 | rtn += "\n"; 413 | 414 | // components 415 | rtn += "components:\n"; 416 | rtn += " schemas:\n"; 417 | coll = doc.alps.descriptor.filter(groups); 418 | coll.forEach(function(item) { 419 | rtn += ` ${item.id}:\n`; 420 | if(item.text) { 421 | rtn += ` description: ${item.text}\n`; 422 | } 423 | rtn += " type: object\n"; 424 | rtn += " properties:\n"; 425 | item.descriptor.forEach(function(prop) { 426 | rtn += ` ${prop.href}:\n`; 427 | rtn += " type: string\n"; 428 | rtn += ` example: ${rString(prop.href)}\n`; 429 | }); 430 | }); 431 | 432 | // clean up doc 433 | rtn = rtn.replace(rxHash,""); 434 | rtn = rtn.replace(rxQ,"#"); 435 | 436 | return rtn; 437 | } 438 | 439 | // **************************************************** 440 | // to AsyncAPI document (incomplete) 441 | // **************************************************** 442 | function toAsync(doc) { 443 | var rtn = ""; 444 | // preamble 445 | rtn += "async: 2.0.0\n"; 446 | rtn += "\n"; 447 | 448 | // signature 449 | rtn += '?? *******************************************************************\n'; 450 | rtn += `?? generated by "unified" from ${options.file}\n`; 451 | rtn += `?? date: ${new Date()}`; 452 | rtn += '\n'; 453 | rtn += '?? http://github.com/mamund/2020-04-unified-api-design\n'; 454 | rtn += '?? *******************************************************************\n'; 455 | rtn += '\n'; 456 | 457 | rtn += `id: '${doc.alps.id}'\n`; 458 | rtn += '\n'; 459 | 460 | // info section 461 | rtn += "info:\n"; 462 | rtn += ` title: ${doc.alps.name||"ALPS API"}\n`; 463 | rtn += ` description: ${doc.alps.doc.value||`Generated from ALPS file ${options.file}`}\n`; 464 | rtn += " version: '1.0.0'\n"; 465 | rtn += ` baseTopic: ${doc.alps.name}\n`; 466 | rtn += ` host: ${doc.alps.root}\n`; 467 | rtn += " schemes:\n"; 468 | rtn += " - 'amqp'\n"; 469 | rtn += " - 'mqtt'\n"; 470 | rtn += "\n"; 471 | 472 | rtn += "# topics:\n"; 473 | rtn += "# **** TBD ****"; 474 | 475 | // clean up doc 476 | rtn = rtn.replace(rxHash,""); 477 | rtn = rtn.replace(rxQ,"#"); 478 | 479 | return rtn; 480 | } 481 | 482 | //******************************************* 483 | // collection filters 484 | //******************************************* 485 | function semantic(doc) { 486 | return doc.type === "semantic"; 487 | } 488 | 489 | function groups(doc) { 490 | return doc.type === "group"; 491 | } 492 | 493 | function safe(doc) { 494 | return doc.type === "safe"; 495 | } 496 | 497 | function unsafe(doc) { 498 | return doc.type === "unsafe"; 499 | } 500 | 501 | function idempotent(doc) { 502 | return doc.type === "idempotent"; 503 | } 504 | 505 | function remove(doc) { 506 | return (doc.type === "idempotent" && (doc.tags && doc.tags.indexOf("delete")!=-1)); 507 | } 508 | 509 | function update(doc) { 510 | return (doc.type === "idempotent" && (doc.tags && doc.tags.indexOf("update")!=-1)); 511 | } 512 | 513 | function metadata_id(doc) { 514 | return (doc.type ==="metadata" && (doc.name && doc.name === ("id"))); 515 | } 516 | function metadata_title(doc) { 517 | return (doc.type ==="metadata" && (doc.name && doc.name === ("title"))); 518 | } 519 | function metadata_root(doc) { 520 | return (doc.type ==="metadata" && (doc.name && doc.name === ("root"))); 521 | } 522 | 523 | function rString(id) { 524 | var rtn = ""; 525 | if(id && id.indexOf("id")!=-1) { 526 | rtn = Math.random().toString(9).substring(2, 4) + Math.random().toString(9).substring(2, 4); 527 | } 528 | else { 529 | rtn = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); 530 | } 531 | return rtn; 532 | } 533 | -------------------------------------------------------------------------------- /src/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2020-04-unified-api-design", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "ansi-align": { 8 | "version": "3.0.0", 9 | "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", 10 | "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", 11 | "requires": { 12 | "string-width": "^3.0.0" 13 | } 14 | }, 15 | "ansi-regex": { 16 | "version": "4.1.1", 17 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", 18 | "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==" 19 | }, 20 | "ansi-styles": { 21 | "version": "3.2.1", 22 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 23 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 24 | "requires": { 25 | "color-convert": "^1.9.0" 26 | } 27 | }, 28 | "argparse": { 29 | "version": "1.0.10", 30 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 31 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 32 | "requires": { 33 | "sprintf-js": "~1.0.2" 34 | } 35 | }, 36 | "balanced-match": { 37 | "version": "1.0.0", 38 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 39 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 40 | }, 41 | "boxen": { 42 | "version": "4.0.0", 43 | "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.0.0.tgz", 44 | "integrity": "sha512-gBklgJ9hxaEG8AvEq6JmHns0qQh7JS0uRQtpk4r0OW9AJFKfvP0PVoltH0xzZt/OIio2Iy48xkiV3OaIun7GUw==", 45 | "requires": { 46 | "ansi-align": "^3.0.0", 47 | "camelcase": "^5.3.1", 48 | "chalk": "^2.4.2", 49 | "cli-boxes": "^2.2.0", 50 | "string-width": "^3.1.0", 51 | "term-size": "^2.1.0", 52 | "type-fest": "^0.5.2", 53 | "widest-line": "^3.1.0" 54 | } 55 | }, 56 | "brace-expansion": { 57 | "version": "1.1.11", 58 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 59 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 60 | "requires": { 61 | "balanced-match": "^1.0.0", 62 | "concat-map": "0.0.1" 63 | } 64 | }, 65 | "camelcase": { 66 | "version": "5.3.1", 67 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 68 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" 69 | }, 70 | "chalk": { 71 | "version": "2.4.2", 72 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 73 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 74 | "requires": { 75 | "ansi-styles": "^3.2.1", 76 | "escape-string-regexp": "^1.0.5", 77 | "supports-color": "^5.3.0" 78 | } 79 | }, 80 | "cli-boxes": { 81 | "version": "2.2.0", 82 | "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", 83 | "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==" 84 | }, 85 | "cliui": { 86 | "version": "5.0.0", 87 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 88 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 89 | "requires": { 90 | "string-width": "^3.1.0", 91 | "strip-ansi": "^5.2.0", 92 | "wrap-ansi": "^5.1.0" 93 | } 94 | }, 95 | "color-convert": { 96 | "version": "1.9.3", 97 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 98 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 99 | "requires": { 100 | "color-name": "1.1.3" 101 | } 102 | }, 103 | "color-name": { 104 | "version": "1.1.3", 105 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 106 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 107 | }, 108 | "concat-map": { 109 | "version": "0.0.1", 110 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 111 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 112 | }, 113 | "decamelize": { 114 | "version": "1.2.0", 115 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 116 | "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" 117 | }, 118 | "emoji-regex": { 119 | "version": "7.0.3", 120 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 121 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" 122 | }, 123 | "escape-string-regexp": { 124 | "version": "1.0.5", 125 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 126 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 127 | }, 128 | "find-up": { 129 | "version": "3.0.0", 130 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 131 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 132 | "requires": { 133 | "locate-path": "^3.0.0" 134 | } 135 | }, 136 | "fs.realpath": { 137 | "version": "1.0.0", 138 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 139 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 140 | }, 141 | "get-caller-file": { 142 | "version": "2.0.5", 143 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 144 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" 145 | }, 146 | "glob": { 147 | "version": "7.1.6", 148 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 149 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 150 | "requires": { 151 | "fs.realpath": "^1.0.0", 152 | "inflight": "^1.0.4", 153 | "inherits": "2", 154 | "minimatch": "^3.0.4", 155 | "once": "^1.3.0", 156 | "path-is-absolute": "^1.0.0" 157 | } 158 | }, 159 | "has-flag": { 160 | "version": "3.0.0", 161 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 162 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 163 | }, 164 | "inflight": { 165 | "version": "1.0.6", 166 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 167 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 168 | "requires": { 169 | "once": "^1.3.0", 170 | "wrappy": "1" 171 | } 172 | }, 173 | "inherits": { 174 | "version": "2.0.4", 175 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 176 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 177 | }, 178 | "is-fullwidth-code-point": { 179 | "version": "2.0.0", 180 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 181 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" 182 | }, 183 | "jstoxml": { 184 | "version": "1.6.5", 185 | "resolved": "https://registry.npmjs.org/jstoxml/-/jstoxml-1.6.5.tgz", 186 | "integrity": "sha512-ozA5AwbLnsm6ft6hHh/raabjwGN7FekIwa42WAFEkF3ZKEeXJLfS6/4GlkbOZglFBfadM75nowCRfhw/ojmd9g==" 187 | }, 188 | "locate-path": { 189 | "version": "3.0.0", 190 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 191 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 192 | "requires": { 193 | "p-locate": "^3.0.0", 194 | "path-exists": "^3.0.0" 195 | } 196 | }, 197 | "minimatch": { 198 | "version": "3.1.2", 199 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 200 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 201 | "requires": { 202 | "brace-expansion": "^1.1.7" 203 | } 204 | }, 205 | "once": { 206 | "version": "1.4.0", 207 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 208 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 209 | "requires": { 210 | "wrappy": "1" 211 | } 212 | }, 213 | "p-limit": { 214 | "version": "2.3.0", 215 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 216 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 217 | "requires": { 218 | "p-try": "^2.0.0" 219 | } 220 | }, 221 | "p-locate": { 222 | "version": "3.0.0", 223 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 224 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 225 | "requires": { 226 | "p-limit": "^2.0.0" 227 | } 228 | }, 229 | "p-try": { 230 | "version": "2.2.0", 231 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 232 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" 233 | }, 234 | "path-exists": { 235 | "version": "3.0.0", 236 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 237 | "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" 238 | }, 239 | "path-is-absolute": { 240 | "version": "1.0.1", 241 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 242 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 243 | }, 244 | "require-directory": { 245 | "version": "2.1.1", 246 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 247 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" 248 | }, 249 | "require-main-filename": { 250 | "version": "2.0.0", 251 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 252 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" 253 | }, 254 | "set-blocking": { 255 | "version": "2.0.0", 256 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 257 | "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" 258 | }, 259 | "sprintf-js": { 260 | "version": "1.0.3", 261 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 262 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" 263 | }, 264 | "string-width": { 265 | "version": "3.1.0", 266 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 267 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 268 | "requires": { 269 | "emoji-regex": "^7.0.1", 270 | "is-fullwidth-code-point": "^2.0.0", 271 | "strip-ansi": "^5.1.0" 272 | } 273 | }, 274 | "strip-ansi": { 275 | "version": "5.2.0", 276 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 277 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 278 | "requires": { 279 | "ansi-regex": "^4.1.0" 280 | } 281 | }, 282 | "supports-color": { 283 | "version": "5.5.0", 284 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 285 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 286 | "requires": { 287 | "has-flag": "^3.0.0" 288 | } 289 | }, 290 | "term-size": { 291 | "version": "2.2.0", 292 | "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", 293 | "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==" 294 | }, 295 | "type-fest": { 296 | "version": "0.5.2", 297 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz", 298 | "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==" 299 | }, 300 | "which-module": { 301 | "version": "2.0.1", 302 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", 303 | "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" 304 | }, 305 | "widest-line": { 306 | "version": "3.1.0", 307 | "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", 308 | "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", 309 | "requires": { 310 | "string-width": "^4.0.0" 311 | }, 312 | "dependencies": { 313 | "ansi-regex": { 314 | "version": "5.0.1", 315 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 316 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" 317 | }, 318 | "emoji-regex": { 319 | "version": "8.0.0", 320 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 321 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 322 | }, 323 | "is-fullwidth-code-point": { 324 | "version": "3.0.0", 325 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 326 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" 327 | }, 328 | "string-width": { 329 | "version": "4.2.0", 330 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 331 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 332 | "requires": { 333 | "emoji-regex": "^8.0.0", 334 | "is-fullwidth-code-point": "^3.0.0", 335 | "strip-ansi": "^6.0.0" 336 | } 337 | }, 338 | "strip-ansi": { 339 | "version": "6.0.0", 340 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 341 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 342 | "requires": { 343 | "ansi-regex": "^5.0.0" 344 | } 345 | } 346 | } 347 | }, 348 | "wrap-ansi": { 349 | "version": "5.1.0", 350 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 351 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 352 | "requires": { 353 | "ansi-styles": "^3.2.0", 354 | "string-width": "^3.0.0", 355 | "strip-ansi": "^5.0.0" 356 | } 357 | }, 358 | "wrappy": { 359 | "version": "1.0.2", 360 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 361 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 362 | }, 363 | "y18n": { 364 | "version": "4.0.3", 365 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", 366 | "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" 367 | }, 368 | "yamljs": { 369 | "version": "0.3.0", 370 | "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", 371 | "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", 372 | "requires": { 373 | "argparse": "^1.0.7", 374 | "glob": "^7.0.5" 375 | } 376 | }, 377 | "yargs": { 378 | "version": "13.3.2", 379 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", 380 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", 381 | "requires": { 382 | "cliui": "^5.0.0", 383 | "find-up": "^3.0.0", 384 | "get-caller-file": "^2.0.1", 385 | "require-directory": "^2.1.1", 386 | "require-main-filename": "^2.0.0", 387 | "set-blocking": "^2.0.0", 388 | "string-width": "^3.0.0", 389 | "which-module": "^2.0.0", 390 | "y18n": "^4.0.0", 391 | "yargs-parser": "^13.1.2" 392 | } 393 | }, 394 | "yargs-parser": { 395 | "version": "13.1.2", 396 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 397 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 398 | "requires": { 399 | "camelcase": "^5.0.0", 400 | "decamelize": "^1.2.0" 401 | } 402 | } 403 | } 404 | } 405 | --------------------------------------------------------------------------------