swagger: "2.0"
info:
  description: >
    Rest-in-contract Project is a product to let you embrace [Consumer-driven contracts](https://martinfowler.com/articles/consumerDrivenContracts.html).
    It is REST in nature so that it fits for integrating with all kind of programming languages.
    For more detail about [Project rest-in-contract](http://blog.airic-yu.com/2062/project-rest-in-contracts), you may have a look in our Project rest-in-contract's Homepage for detail introduction.
        
    This rest-in-contract node module is a module for the Local Contract Server which is the core part of the Rest-in-contract project.
  version: "1.0"
  title: "rest-in-contract"
  contact:
    email: "airic.yu@gmail.com"
  license:
    name: "Apache 2.0"
    url: "http://www.apache.org/licenses/LICENSE-2.0.html"
externalDocs:
  description: "Find out more in Github page"
  url: "https://github.com/airicyu/rest-in-contract"
host: "localhost:8000"
basePath: "/api/v1"
tags:
- name: "server"
  description: "Contract Server APIs"
- name: "app"
  description: "Apps"
- name: "app version"
  description: "App Versions"
- name: "contract"
  description: "API Contracts"
schemes:
- "http"
paths:
  /apps:
    post:
      tags:
      - "app"
      summary: "Add an App"
      description: ""
      operationId: "addApp"
      consumes:
      - "application/json"
      parameters:
      - in: body
        name: body
        description: "An App object that needs to be added"
        required: true
        schema:
          $ref: "#/definitions/App"
      responses:
        201:
          description: "App created"
    get:
      tags:
      - "app"
      summary: "Get all Apps"
      description: ""
      operationId: "getAllAppsId"
      responses:
        200:
          description: "OK"
          schema:
            type: array
            items:
              type: string
  /apps/{appId}:
    get:
      tags:
      - "app"
      summary: "Get an App"
      description: ""
      operationId: "getApp"
      produces:
      - application/json
      parameters:
      - in: path
        name: appId
        description: "App ID"
        required: true
        type: string
      responses:
        200:
          description: "OK"
          schema:
            $ref: '#/definitions/AppHal'
          examples:
            application/json+hal:
              _links:
                self:
                  href: "/api/v1/apps/80a69a44-3f3b-48c1-a7d1-b34b89117e75"
                versions:
                  href: "/api/v1/apps/80a69a44-3f3b-48c1-a7d1-b34b89117e75/versions"
              id: "80a69a44-3f3b-48c1-a7d1-b34b89117e75"
              name: "test"
              servers:
              - "http://example.com:8001"
              basepath: "/api"
              versionNumbers:
              - "0.0.1"
        404:
          description: "App not found"
    put:
      tags:
      - "app"
      summary: "Update an existing App"
      description: ""
      operationId: "updateApp"
      consumes:
      - application/json
      parameters:
      - in: body
        name: body
        description: "An App object that needs to be updated"
        required: true
        schema:
          $ref: '#/definitions/App'
      - in: path
        name: appId
        description: "App ID"
        required: true
        type: string
      responses:
        204:
          description: "Update success"
        404:
          description: "App not found"
    delete:
      tags:
      - "app"
      summary: "Delete an App"
      description: ""
      operationId: "deleteApp"
      produces:
      - application/json
      parameters:
      - in: path
        name: appId
        description: "App ID"
        required: true
        type: string
      responses:
        204:
          description: "Delete success"
        404:
          description: "App not found"
  /apps/{appId}/versions:
    post:
      tags:
      - "app"
      summary: "Add an App Version"
      description: ""
      operationId: "addAppVersion"
      consumes:
      - "application/json"
      parameters:
      - in: path
        name: appId
        description: "App ID"
        required: true
        type: string
      - in: body
        name: body
        description: "An App Version object that needs to be added"
        required: true
        schema:
          $ref: "#/definitions/AppVersion"
      responses:
        201:
          description: "App Version created"
    get:
      tags:
      - "app"
      summary: "Get all App Version Numbers"
      description: ""
      operationId: "getAllAppVersions"
      responses:
        200:
          description: "OK"
          schema:
            type: array
            items:
              type: string
        404:
          description: "App not found"
  /apps/{appId}/versions/{versionNo}:
    get:
      tags:
      - "app"
      summary: "Get an App Version"
      description: ""
      operationId: "getAppVersion"
      produces:
      - application/json
      parameters:
      - in: path
        name: appId
        description: "App ID"
        required: true
        type: string
      - in: path
        name: versionNo
        description: "Version number"
        required: true
        type: string
      responses:
        200:
          description: "OK"
          schema:
            $ref: '#/definitions/AppVersionHal'
          examples:
            application/json+hal:
              _links:
                self:
                  href: "/api/v1/apps/80a69a44-3f3b-48c1-a7d1-b34b89117e75/versions/0.0.1"
                parent:
                  href: "/api/v1/apps/80a69a44-3f3b-48c1-a7d1-b34b89117e75"
                contracts:
                  href: "/api/v1/apps/80a69a44-3f3b-48c1-a7d1-b34b89117e75/versions/0.0.1/contracts"
              v: "80a69a44-3f3b-48c1-a7d1-b34b89117e75"
              path: "{{app.basePath}}/v{{version.v}}"
              contracts:
              - "94923fbd-9092-4a46-ad65-0d8a2e2f551e"
        404:
          description: "App not found or App Version not found"
    put:
      tags:
      - "app"
      summary: "Update an existing App Version"
      description: ""
      operationId: "updateAppVersion"
      consumes:
      - application/json
      parameters:
      - in: body
        name: body
        description: "App Version object that needs to be updated"
        required: true
        schema:
          $ref: '#/definitions/AppVersion'
      - in: path
        name: appId
        description: "App ID"
        required: true
        type: string
      - in: path
        name: versionNo
        description: "Version number"
        required: true
        type: string
      responses:
        204:
          description: "Update success"
        404:
          description: "App not found or App Version not found"
    delete:
      tags:
      - "app"
      summary: "Delete an App Version"
      description: ""
      operationId: "deleteAppVersion"
      produces:
      - application/json
      parameters:
      - in: path
        name: appId
        description: "App ID"
        required: true
        type: string
      - in: path
        name: versionNo
        description: "Version number"
        required: true
        type: string
      responses:
        204:
          description: "Delete success"
        404:
          description: "App not found or App Version not found"
  /contracts:
    post:
      tags:
      - "contract"
      summary: "Add an Contract"
      description: ""
      operationId: "addContract"
      consumes:
      - "application/vnd.js.contract"
      parameters:
      - in: body
        name: body
        description: "An Contract object as JS script that needs to be added"
        required: true
        schema:
          type: string
          example: |-
            module.exports = {
              "name": "testing for hello contract",
              "request": {
                "method": "POST",
                "urlPath": "/hello/apple",
                "queryParameters": [{
                  "name": "a",
                  "value": "b"
                }],
                "body": {
                  "a": "b"
                },
                "headers": {}
              },
              "response": {
                "status": 200,
                "body": {
                  "ok"
                },
                "headers": {}
              }
            }
      responses:
        201:
          description: "Contract created"
    get:
      tags:
      - "contract"
      summary: "Get all Contracts"
      description: ""
      operationId: "getAllContracts"
      responses:
        200:
          description: "OK"
          schema:
            type: array
            items:
              type: string
  /contracts/{contractId}:
    get:
      tags:
      - "contract"
      summary: "Get an Contract"
      description: ""
      operationId: "getContract"
      produces:
      - application/json
      parameters:
      - in: path
        name: contractId
        description: "Contract ID"
        required: true
        type: string
      responses:
        200:
          description: "OK"
          schema:
            $ref: '#/definitions/ContractHal'
          examples:
            application/json+hal:
              _links:
                self:
                  href: "/api/v1/contracts/94923fbd-9092-4a46-ad65-0d8a2e2f551e"
              id: "94923fbd-9092-4a46-ad65-0d8a2e2f551e"
              name: "testing for hello contract"
              contractScript: "module.exports = { \"id\": \"94923fbd-9092-4a46-ad65-0d8a2e2f551e\", \"name\": \"testing for hello contract\", \"request\": { \"method\": \"POST\", \"urlPath\": \"/hello/apple\", \"queryParameters\": [{\"name\":\"a\",\"value\":\"b\"}], \"body\": { \"a\": \"b\" }, \"headers\": {  } }, \"response\": { \"status\": 200, \"body\": \"ok\", \"headers\": {} } }"
            application/vnd.js.contract: |-
              module.exports = {
                "name": "testing for hello contract",
                "request": {
                  "method": "POST",
                  "urlPath": "/hello/apple",
                  "queryParameters": [{
                    "name": "a",
                    "value": "b"
                  }],
                  "body": {
                    "a": "b"
                  },
                  "headers": {}
                },
                "response": {
                  "status": 200,
                  "body": {
                    "ok"
                  },
                  "headers": {}
                }
              }
        404:
          description: "App not found"
    put:
      tags:
      - "contract"
      summary: "Update an existing Contract"
      description: ""
      operationId: "updateContract"
      consumes:
      - "application/vnd.js.contract"
      parameters:
      - in: path
        name: contractId
        description: "Contract ID"
        required: true
        type: string
      - in: body
        name: body
        description: "An Contract object as JS script that needs to be added"
        required: true
        schema:
          type: string
          example: |-
            module.exports = {
              "name": "testing for hello contract",
              "request": {
                "method": "POST",
                "urlPath": "/hello/apple",
                "queryParameters": [{
                  "name": "a",
                  "value": "b"
                }],
                "body": {
                  "a": "b"
                },
                "headers": {}
              },
              "response": {
                "status": 200,
                "body": {
                  "ok"
                },
                "headers": {}
              }
            }
      responses:
        204:
          description: "Update success"
        404:
          description: "Contract not found"
    delete:
      tags:
      - "contract"
      summary: "Delete an Contract"
      description: ""
      operationId: "deleteContract"
      produces:
      - application/json
      parameters:
      - in: path
        name: contractId
        description: "Contract ID"
        required: true
        type: string
      responses:
        204:
          description: "Delete success"
        404:
          description: "Contract not found"
  /apps/{appId}/wirestubs:
    post:
      tags:
      - "wirestub"
      summary: "Wiring an App's' wirestub"
      description: ""
      operationId: "wireAppWirestub"
      consumes:
      - "application/json"
      parameters:
      - in: path
        name: appId
        description: "App ID"
        required: true
        type: string
      - in: body
        name: body
        description: "An App object that needs to be added"
        required: true
        schema:
          $ref: '#/definitions/Wirestub'
      responses:
        201:
          description: "Wirestub success"
        500:
          description: "Wirestub fail"
    get:
      tags:
      - "wirestub"
      summary: "Get the wirestub metadata"
      description: ""
      operationId: "getAppWirestub"
      consumes:
      - "application/json"
      parameters:
      - in: path
        name: appId
        description: "App ID"
        required: true
        type: string
      responses:
        200:
          description: "OK"
          schema:
            $ref: '#/definitions/Wirestub'
        404:
          description: "Wirestub not found"
    delete:
      tags:
      - "wirestub"
      summary: "Unwire the wirestub"
      description: ""
      operationId: "unwireAppWirestub"
      parameters:
      - in: path
        name: appId
        description: "App ID"
        required: true
        type: string
      responses:
        201:
          description: "Wire wirestub success"
          schema:
            $ref: '#/definitions/Wirestub'
        204:
          description: "Unwire wirestub success"
        404:
          description: "Wirestub not found"
  /apps/{appId}/wiretests:
    post:
      tags:
      - "wiretest"
      summary: "Testing App's contracts"
      description: ""
      operationId: "verifyAppContracts"
      consumes:
      - "application/json"
      parameters:
      - in: path
        name: appId
        description: "App ID"
        required: true
        type: string
      - in: body
        name: body
        description: "An App object that needs to be added"
        required: true
        schema:
          $ref: '#/definitions/Wiretest'
      responses:
        200:
          description: "Test finished"
          schema:
            $ref: '#/definitions/WiretestResult'
          example:
            application/json: |-
              {
                "app": {
                  "id": "80a69a44-3f3b-48c1-a7d1-b34b89117e75",
                  "name": "test"
                },
                "testInfo": {
                  "timeMS": 76.2579990029335,
                  "success": true
                },
                "results": [
                  {
                    "versionNo": "0.0.1",
                    "testInfo": {
                      "timeMS": 75.7432410120964,
                      "success": true
                    },
                    "results": [
                      {
                        "testInfo": {
                          "timeMS": 51.209954023361206,
                          "success": true,
                          "errors": [],
                          "appId": "80a69a44-3f3b-48c1-a7d1-b34b89117e75",
                          "version": "0.0.1",
                          "contract": {
                            "id": "b9135ab0-20d2-43f3-b947-3bac5b061f61",
                            "name": "function examples"
                          }
                        },
                        "request": {
                          "method": "POST",
                          "urlPath": "http://localhost:8001/api/v0.0.1/function_examples",
                          "queryParams": {},
                          "headers": {
                            "authorization": "Bearer 0a4b6c5d",
                            "Content-type": "application/json"
                          },
                          "body": {
                            "test": {
                              "numberString": "13579",
                              "number": 24680,
                              "arrayOfValues": [
                                "apple",
                                "orange",
                                "banana"
                              ],
                              "regular expression": "acp-113520",
                              "name": "Cristina Hayes",
                              "email": "Cristina.Hayes82@yahoo.com",
                              "phone": "1-454-765-8135",
                              "date": "2017-05-07",
                              "words": "reiciendis est minima",
                              "uuid4": "510552bc-c017-452a-bd51-7b1b3d3a5f13",
                              "multipleChoices": "class A",
                              "notAnyOf": "c"
                            }
                          }
                        },
                        "expectedResponseScript": "{ \"status\": 200, \"body\": { \"num\": integer({\"gt\":0,\"lt\":60000}), \"reqBodyJsonParams\": jsonpath(\"$.req.body.test\") }, \"headers\": { \"test-header\": \"dummy\", \"test-regex-header\": regex(\"\\\"/hello/[a-z]{3,5}\\\"\") } }",
                        "response": {
                          "status": 200,
                          "headers": {
                            "x-powered-by": "Express",
                            "test-header": "dummy",
                            "test-regex-header": "\"/hello/njm\"",
                            "content-type": "application/json; charset=utf-8",
                            "content-length": "381",
                            "etag": "W/\"17d-j5SCn3LsQSGqO0vZ5zj/AHLJ8qg\"",
                            "date": "Tue, 07 May 2017 09:11:28 GMT",
                            "connection": "close"
                          },
                          "body": "{\"num\":56789,\"reqBodyJsonParams\":[{\"numberString\":\"13579\",\"number\":24680,\"arrayOfValues\":[\"apple\",\"orange\",\"banana\"],\"regular expression\":\"acp-113520\",\"name\":\"Cristina Hayes\",\"email\":\"Cristina.Hayes82@yahoo.com\",\"phone\":\"1-454-765-8135\",\"date\":\"2017-05-07\",\"words\":\"reiciendis est minima\",\"uuid4\":\"510552bc-c017-452a-bd51-7b1b3d3a5f13\",\"multipleChoices\":\"class A\",\"notAnyOf\":\"c\"}]}"
                        }
                      },
                      {
                        "testInfo": {
                          "timeMS": 22.899529993534088,
                          "success": true,
                          "errors": [],
                          "appId": "80a69a44-3f3b-48c1-a7d1-b34b89117e75",
                          "version": "0.0.1",
                          "contract": {
                            "id": "94923fbd-9092-4a46-ad65-0d8a2e2f551e",
                            "name": "testing for hello contract"
                          }
                        },
                        "request": {
                          "method": "POST",
                          "urlPath": "http://localhost:8001/api/v0.0.1/hello/apple",
                          "queryParams": {
                            "a": "b"
                          },
                          "headers": {
                            "Content-type": "application/json"
                          },
                          "body": {
                            "test": {
                              "a": "13579",
                              "b": 24680,
                              "c": [
                                "apple",
                                "orange",
                                "banana"
                              ]
                            }
                          }
                        },
                        "expectedResponseScript": "{ \"status\": 200, \"body\": { \"num\": integer({\"gt\":0,\"lt\":60000}) }, \"headers\": { \"test-header\": \"dummy\", \"test-regex-header\": regex(\"\\\"/hello/[a-z]{3,5}\\\"\") } }",
                        "response": {
                          "status": 200,
                          "headers": {
                            "x-powered-by": "Express",
                            "test-header": "dummy",
                            "test-regex-header": "\"/hello/hsxuj\"",
                            "content-type": "application/json; charset=utf-8",
                            "content-length": "13",
                            "etag": "W/\"d-X7zzcBORmHVzBfO4n/4UzEkpfkY\"",
                            "date": "Tue, 07 May 2017 09:11:28 GMT",
                            "connection": "close"
                          },
                          "body": "{\"num\":56789}"
                        }
                      }
                    ]
                  }
                ]
              }
  /importAppsFiles:
    post:
      tags:
      - "utils"
      summary: "Import Apps Files"
      description: ""
      operationId: "importAppsFiles"
      consumes:
      - "application/json"
      parameters:
      - in: body
        name: body
        description: "An App object that needs to be added"
        required: true
        schema:
          type: object
          required:
          - port
          - appFolder
          properties:
            port:
              type: integer
            appFolder:
              type: string
          example:
            port: 8081
            appFolder: "C:/apps_root_import_folder"
      responses:
        201:
          description: "Import success"
definitions:
  App:
    type: object
    required:
    - "name"
    - "servers"
    - "basePath"
    properties:
      id:
        type: string
      name:
        type: string
      servers:
        type: array
        items:
          type: string
      basePath:
        type: string
  AppHal:
    type: object
    required:
    - id
    - name
    - servers
    - basePath
    - versionNumbers
    - _links
    properties:
      id:
        type: string
      name:
        type: string
      servers:
        type: array
        items:
          type: string
      basePath:
        type: string
      versionNumbers:
        type: array
        items:
          type: string
      _links:
        type: object
        properties:
          self:
            type: object
            properties:
              href:
                type: string
          versions:
            type: object
            properties:
              href:
                type: string
  AppVersion:
    type: object
    required:
    - "v"
    - "path"
    - "contracts"
    properties:
      v:
        type: string
      path:
        type: string
      contracts:
        type: array
        items:
          type: string
  AppVersionHal:
    type: object
    required:
    - v
    - path
    - contracts
    - _links
    properties:
      v:
        type: string
      path:
        type: string
      contracts:
        type: array
        items:
          type: string
      _links:
        type: object
        properties:
          self:
            type: object
            properties:
              href:
                type: string
          parent:
            type: object
            properties:
              href:
                type: string
          contracts:
            type: object
            properties:
              href:
                type: string
  ContractHal:
    type: object
    required:
    - id
    - name
    - contractScript
    - _links
    properties:
      id:
        type: string
      name:
        type: string
      contractScript:
        type: string
      _links:
        type: object
        properties:
          self:
            type: object
            properties:
              href:
                type: string
  Wirestub:
    type: object
    required:
    - port
    properties:
      port:
        type: integer
    example:
      port: 8081
  Wiretest:
    type: object
    required:
    - server
    properties:
      server:
        type: string
    example:
      port: "http://localhost:8001"
  WiretestResult:
    type: object
    properties:
      app:
        type: object
        properties:
          id:
            type: string
          name:
            type: string
      testInfo:
        type: object
        properties:
          timeMs:
            type: number
            format: float
          success:
            type: boolean
      results:
        type: array
        items:
          type: object
          properties:
            versionNo:
              type: string
            testInfo:
              type: object
              properties:
                timeMs:
                  type: number
                  format: float
                success:
                  type: boolean
            results:
              type: array
              items:
                type: object
                properties:
                  testInfo:
                    type: object
                    properties:
                      timeMs:
                        type: number
                        format: float
                      success:
                        type: boolean
                      errors:
                        type: array
                        items:
                          type: string
                      appId:
                        type: string
                      version:
                        type: string
                      contract:
                        type: object
                        properties:
                          id:
                            type: string
                          name:
                            type: string
                  request:
                    type: object
                    properties:
                      method:
                        type: string
                      urlPath:
                        type: string
                      queryParams:
                        type: object
                      headers:
                        type: object
                      body:
                        type: object
                  expectedResponseScript:
                    type: string
                  response:
                    type: object
                    properties:
                      status:
                        type: integer
                      headers:
                        type: object
                      body:
                        type: string