TD-635: Add initial specs (#1)

* TD-635: Add initial specs

* Add workflows

* Fix tests

* Add 404 to listApiKeys
This commit is contained in:
ndiezel0 2023-06-08 12:49:29 +05:00 committed by GitHub
parent 4990362d67
commit 73d97d2d06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 17052 additions and 26 deletions

23
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,23 @@
name: build
on:
- pull_request
env:
NODEJS_VERSION: '16'
jobs:
bundle:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODEJS_VERSION }}
cache: npm
- run: npm install
- name: Bundle specification
run: npm run build
- name: Validate specification
run: npm run test

22
.github/workflows/frontend-pr.yml vendored Normal file
View File

@ -0,0 +1,22 @@
name: 'Frontend: PR'
on:
pull_request:
branches: ['*']
jobs:
configured:
uses: valitydev/action-frontend/.github/workflows/configured.yml@v0.1
check:
name: Check
runs-on: ubuntu-latest
needs: configured
if: needs.configured.outputs.exists == 'true'
steps:
- uses: actions/checkout@v3
- uses: valitydev/action-frontend/setup@v0.1
- run: npm ci
- name: Build
run: npm run build
- name: Codegen
run: npm run codegen

26
.github/workflows/frontend-publish.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: 'Frontend: Publish'
on:
push:
branches: ['master', 'main', 'v0']
jobs:
configured:
uses: valitydev/action-frontend/.github/workflows/configured.yml@v0.1
publish:
name: Publish
runs-on: ubuntu-latest
needs: configured
if: needs.configured.outputs.exists == 'true'
steps:
- uses: actions/checkout@v3
- uses: valitydev/action-frontend/setup@v0.1
- run: npm ci
- name: Build
run: npm run build
- name: Codegen
run: npm run codegen
- uses: valitydev/action-frontend/publish@v0.1
with:
npm-token: ${{ secrets.NPM_TOKEN }}
directory: ./lib

28
.github/workflows/gh-pages.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: gh-pages
on:
push:
branches: [master]
env:
NODEJS_VERSION: "16"
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODEJS_VERSION }}
cache: npm
- run: npm install
- name: Bundle specification
run: npm run build
- name: Publish ReDoc on Github Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
exclude_assets: "swagger-ui"

60
.github/workflows/release-erlang.yml vendored Normal file
View File

@ -0,0 +1,60 @@
name: Release Erlang Libraries
on:
push:
branches: [master]
pull_request:
branches: ['**']
env:
NODEJS_VERSION: '16'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup swagger-codegen
uses: valitydev/action-setup-swagger-codegen@v0.0.4
with:
codegen-version: "2.4.25"
generator-version: "1.0.3"
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODEJS_VERSION }}
cache: npm
- name: Install deps
run: npm install
- name: Bundle spec and build docsite
run: npm run build -- build_public
- name: Generate stubs
run: |
mkdir -p out
echo "Generate apikeys stubs"
swagger-codegen generate -l vality-erlang-client -i build_public/api/apikeys/swagger.json -o out/erlang-client-apikeys --additional-properties packageName=swag_client_apikeys
swagger-codegen generate -l vality-erlang-server -i build_public/api/apikeys/swagger.json -o out/erlang-server-apikeys --additional-properties packageName=swag_server_apikeys
#
- name: Deploy erlang-client-apikeys artifact to release branch
if: ${{ github.event_name == 'push' }}
uses: JamesIves/github-pages-deploy-action@v4.4.1
with:
branch: release/erlang/client/master
folder: out/erlang-client-apikeys
commit-message: Release ${{ github.repository }}@${{ github.sha }}
- name: Deploy erlang-server-apikeys artifact to release branch
if: ${{ github.event_name == 'push' }}
uses: JamesIves/github-pages-deploy-action@v4.4.1
with:
branch: release/erlang/server/master
folder: out/erlang-server-apikeys
commit-message: Release ${{ github.repository }}@${{ github.sha }}

30
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: release
on:
push:
branches: [master]
workflow_dispatch:
env:
NODEJS_VERSION: '16'
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODEJS_VERSION }}
cache: npm
- run: npm install
- name: Bundle specification
run: npm run build -- ../public
- name: Deploy to release branch
uses: JamesIves/github-pages-deploy-action@v4.4.1
with:
branch: release/master
folder: ../public/api
target-folder: api
commit-message: release ${{ github.repository }}@${{ github.sha }} by ${{ github.actor }}

40
.gitignore vendored Normal file
View File

@ -0,0 +1,40 @@
# Dir for API portal deploy
dist/
out/
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
node_modules
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
# Frontend
/lib
# Other
.DS_Store

25
LICENSE
View File

@ -174,28 +174,3 @@
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1 +1 @@
# swag-api-keys-v2
# 🔑 swag-api-keys-v2

View File

@ -0,0 +1,11 @@
type: object
required:
- accessToken
properties:
accessToken:
description: Токен доступа, ассоциированный с данным ключом
type: string
minLength: 1
maxLength: 4000
example: |
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0a2kiOiIxS2dJWUJHc0NncSIsImlhdCI6MTUxNjIzOTAyMn0.6YsaZQC9A7BjxXHwRbJfUO6VujOb4rHTKrqmMt64TbQ

View File

@ -0,0 +1,28 @@
description: Ключ для авторизации запросов к API
type: object
required:
- id
- createdAt
- name
- status
properties:
id:
$ref: '#/definitions/ApiKeyID'
createdAt:
description: Дата и время создания
type: string
format: date-time
readOnly: true
name:
description: Запоминающееся название ключа
type: string
minLength: 1
maxLength: 40
example: live-site-integration
status:
$ref: '#/definitions/ApiKeyStatus'
metadata:
description: |
Произвольный набор данных, специфичный для клиента API и
непрозрачный для системы
type: object

View File

@ -0,0 +1,6 @@
description: Идентификатор ключа
type: string
minLength: 1
maxLength: 40
example: 1KgIYBGsCgq
readOnly: true

View File

@ -0,0 +1,6 @@
description: Статус ключа
type: string
enum:
- Active
- Revoked
readOnly: true

View File

@ -0,0 +1,26 @@
type: object
required:
- errorType
properties:
errorType:
description: Error type
type: string
enum:
- SchemaViolated
- NotFound
- WrongType
- NotInRange
- WrongSize
- WrongLength
- WrongArray
- NoMatch
- InvalidToken
example: NotFound
name:
description: Name or identifier of message element containing invalid data
type: string
example: X-Request-ID
description:
description: Explanation of why the data is invalid
type: string
example: Required parameter was not sent

View File

@ -0,0 +1,49 @@
Vality API Keys Management API является интерфейсом для управления набором
API-ключей, используемых для авторизации запросов к основному API с ваших
бэкенд-сервисов. Любые сторонние приложения, включая ваш личный кабинет,
являются внешними приложениями-клиентами данного API.
Мы предоставляем REST API поверх HTTP-протокола, схема которого описывается в
соответствии со стандартом [OpenAPI 3][OAS3].
Коды возврата описываются соответствующими HTTP-статусами. Платформа принимает и
возвращает значения JSON в теле запросов и ответов.
[OAS3]: https://swagger.io/specification/
## Идентификатор запроса
При любом обращении к API в заголовке `X-Request-ID` соответствующего запроса необходимо
передать его уникальный идентификатор:
```
X-Request-ID: 37d735d4-0f42-4f05-89fa-eaa478fb5aa9
```
## Формат содержимого
Любой запрос к API должен выполняться в кодировке UTF-8 и с указанием
содержимого в формате JSON.
```
Content-Type: application/json; charset=utf-8
```
## Максимальное время обработки запроса
При любом обращении к API в заголовке `X-Request-Deadline` соответствующего запроса можно
передать параметр отсечки по времени, определяющий максимальное время ожидания завершения
операции по запросу:
```
X-Request-Deadline: 10s
```
По истечении указанного времени система прекращает обработку запроса. Рекомендуется указывать
значение не более одной минуты, но не менее трёх секунд.
`X-Request-Deadline` может:
* задаваться в формате `date-time` согласно
[RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339);
* задаваться в относительных величинах: в миллисекундах (`150000ms`), секундах (`540s`) или
минутах (`3.5m`).

View File

@ -0,0 +1,34 @@
## Общие ошибки
Ошибки возникающие при попытках совершения недопустимых операций, операций с невалидными объектами или несуществующими ресурсами. Имеют следующий вид:
```json
{
"code": "string",
"message": "string"
}
```
В поле `message` содержится информация по произошедшей ошибке. Например:
```json
{
"code": "invalidRequest",
"message": "Property 'name' is required."
}
```
## Ошибки обработки запросов
В процессе обработки запросов силами нашей платформы могут происходить различные непредвиденные ситуации. Об их появлении платформа сигнализирует по протоколу HTTP соответствующими [статусами][5xx], обозначающими ошибки сервера.
| Код | Описание |
| ------- | ---------- |
| **500** | В процессе обработки платформой запроса возникла непредвиденная ситуация. При получении подобного кода ответа мы рекомендуем обратиться в техническую поддержку. |
| **503** | Платформа временно недоступна и не готова обслуживать данный запрос. Запрос гарантированно не выполнен, при получении подобного кода ответа попробуйте выполнить его позднее, когда доступность платформы будет восстановлена. |
| **504** | Платформа превысила допустимое время обработки запроса, результат запроса не определён. Попробуйте отправить запрос повторно или выяснить результат выполнения исходного запроса, если повторное исполнение запроса нежелательно. |
[5xx]: https://tools.ietf.org/html/rfc7231#section-6.6
Если вы получили ошибку, которой нет в данном описании, обратитесь в техническую поддержку.

View File

@ -0,0 +1,61 @@
---
get:
summary: Перечислить ключи организации
operationId: listApiKeys
tags:
- apiKeys
parameters:
- $ref: '#/parameters/requestID'
- $ref: '#/parameters/deadline'
- $ref: '#/parameters/partyId'
- name: status
description: |
Фильтр по статусу ключа. По умолчанию `active`.
in: query
required: false
type: string
enum:
- Active
- Revoked
responses:
'200':
description: Ключи найдены
schema:
type: object
required:
- results
properties:
results:
type: array
items:
$ref: '#/definitions/ApiKey'
'401':
$ref: "#/responses/Unauthorized"
'404':
$ref: "#/responses/NotFound"
'400':
$ref: '#/responses/BadRequest'
post:
summary: Выпустить новый ключ
operationId: issueApiKey
tags:
- apiKeys
parameters:
- $ref: '#/parameters/partyId'
- name: apiKey
in: body
required: true
schema:
$ref: '#/definitions/ApiKey'
responses:
'200':
description: Ключ выпущен
schema:
allOf:
- $ref: '#/definitions/ApiKey'
- $ref: '#/definitions/AccessToken'
'401':
$ref: "#/responses/Unauthorized"
'400':
$ref: '#/responses/BadRequest'

View File

@ -0,0 +1,22 @@
---
get:
summary: Получить данные ключа
operationId: getApiKey
tags:
- apiKeys
parameters:
- $ref: '#/parameters/requestID'
- $ref: '#/parameters/deadline'
- $ref: '#/parameters/partyId'
- $ref: '#/parameters/apiKeyId'
responses:
'200':
description: Ключ найден
schema:
$ref: '#/definitions/ApiKey'
'404':
$ref: "#/responses/NotFound"
'401':
$ref: "#/responses/Unauthorized"
'400':
$ref: '#/responses/BadRequest'

View File

@ -0,0 +1,32 @@
---
put:
summary: Запросить отзыв ключа
description: |
Просит отозвать Api Key, для подтверждения запроса
посылает на почту запросившего письмо с ссылкой на
revokeApiKey для подтверждения операции
operationId: requestRevokeApiKey
tags:
- apiKeys
parameters:
- $ref: '#/parameters/requestID'
- $ref: '#/parameters/deadline'
- $ref: '#/parameters/partyId'
- $ref: '#/parameters/apiKeyId'
- name: status
description: Status to change Api Key into
in: body
required: true
schema:
type: string
enum:
- Revoked
responses:
'204':
description: Запрос на операцию получен
"404":
$ref: "#/responses/NotFound"
'401':
$ref: "#/responses/Unauthorized"
'400':
$ref: '#/responses/BadRequest'

View File

@ -0,0 +1,25 @@
---
get:
summary: Отозвать ключ
description: |
Ссылка на этот запрос приходит на почту запросившего
requestRevokeApiKey, в результате выполнения этого запроса
Api Key будет отозван
operationId: revokeApiKey
tags:
- apiKeys
parameters:
- $ref: '#/parameters/requestID'
- $ref: '#/parameters/deadline'
- $ref: '#/parameters/partyId'
- $ref: '#/parameters/apiKeyId'
- $ref: '#/parameters/apiKeyRevokeToken'
responses:
'204':
description: Ключ отозван
"404":
$ref: "#/responses/NotFound"
'401':
$ref: "#/responses/Unauthorized"
'400':
$ref: '#/responses/BadRequest'

View File

@ -0,0 +1,189 @@
---
swagger: "2.0"
info:
version: "0.1.0"
title: Vality Api Keys API
description: >
Vality API Keys Management API является интерфейсом для управления набором
API-ключей, используемых для авторизации запросов к основному API с ваших
бэкенд-сервисов. Любые сторонние приложения, включая ваш личный кабинет,
являются внешними приложениями-клиентами данного API.
Мы предоставляем REST API поверх HTTP-протокола, схема которого описывается в
соответствии со стандартом [OpenAPI 3][OAS3].
Коды возврата описываются соответствующими HTTP-статусами. Платформа принимает и
возвращает значения JSON в теле запросов и ответов.
[OAS3]: https://swagger.io/specification/
## Идентификатор запроса
При любом обращении к API в заголовке `X-Request-ID` соответствующего запроса необходимо
передать его уникальный идентификатор:
```
X-Request-ID: 37d735d4-0f42-4f05-89fa-eaa478fb5aa9
```
## Формат содержимого
Любой запрос к API должен выполняться в кодировке UTF-8 и с указанием
содержимого в формате JSON.
```
Content-Type: application/json; charset=utf-8
```
## Максимальное время обработки запроса
При любом обращении к API в заголовке `X-Request-Deadline` соответствующего запроса можно
передать параметр отсечки по времени, определяющий максимальное время ожидания завершения
операции по запросу:
```
X-Request-Deadline: 10s
```
По истечении указанного времени система прекращает обработку запроса. Рекомендуется указывать
значение не более одной минуты, но не менее трёх секунд.
`X-Request-Deadline` может:
* задаваться в формате `date-time` согласно
[RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339);
* задаваться в относительных величинах: в миллисекундах (`150000ms`), секундах (`540s`) или
минутах (`3.5m`).
termsOfService: "https://vality.dev/"
contact:
name: Technical support team
email: support@vality.dev
url: "https://api.vality.dev"
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
host: api.vality.dev
basePath: /apikeys/v2
schemes:
- https
consumes:
- application/json; charset=utf-8
produces:
- application/json; charset=utf-8
securityDefinitions:
bearer:
type: apiKey
name: Authorization
in: header
description: >
Use [JWT](https://jwt.io) for call authentication. The corresponding key is passed in the header.
```shell
Authorization: Bearer {YOUR_API_KEY_JWT}
```
security:
- bearer: []
responses:
BadRequest:
description: Invalid input data for operation
schema:
$ref: "#/definitions/BadRequest"
NotFound:
description: The content you are looking for was not found
Unauthorized:
description: Authorization error
parameters:
requestID:
name: X-Request-ID
in: header
description: Unique identifier of the request to the system
required: true
type: string
maxLength: 32
minLength: 1
deadline:
name: X-Request-Deadline
in: header
description: Maximum request processing time
required: false
type: string
maxLength: 40
minLength: 1
apiKeyId:
name: apiKeyId
in: path
description: Идентификатор ключа
required: true
type: string
# schema:
# $ref: '#/definitions/ApiKeyID'
# type: string
minLength: 1
maxLength: 40
# example: 1KgIYBGsCgq
apiKeyRevokeToken:
name: apiKeyRevokeToken
in: query
description: Токен отзыва ключа
required: true
type: string
# schema:
# $ref: '#/definitions/RevokeToken'
minLength: 1
maxLength: 4000
# example: |
# f767b77e-300f-47a7-84e2-e24ea585a9f0
partyId:
name: partyId
in: path
description: Идентификатор участника
required: true
type: string
minLength: 1
maxLength: 40
# example: |
# bdaf9e76-1c5b-4798-b154-19b87a61dc94
tags:
- name: apiKeys
x-displayName: API-ключи
- name: errorCodes
x-displayName: Коды ошибок
description: >
## Общие ошибки
Ошибки возникающие при попытках совершения недопустимых операций, операций с невалидными объектами или несуществующими ресурсами. Имеют следующий вид:
```json
{
"code": "string",
"message": "string"
}
```
В поле `message` содержится информация по произошедшей ошибке. Например:
```json
{
"code": "invalidRequest",
"message": "Property 'name' is required."
}
```
## Ошибки обработки запросов
В процессе обработки запросов силами нашей платформы могут происходить различные непредвиденные ситуации. Об их появлении платформа сигнализирует по протоколу HTTP соответствующими [статусами][5xx], обозначающими ошибки сервера.
| Код | Описание |
| ------- | ---------- |
| **500** | В процессе обработки платформой запроса возникла непредвиденная ситуация. При получении подобного кода ответа мы рекомендуем обратиться в техническую поддержку. |
| **503** | Платформа временно недоступна и не готова обслуживать данный запрос. Запрос гарантированно не выполнен, при получении подобного кода ответа попробуйте выполнить его позднее, когда доступность платформы будет восстановлена. |
| **504** | Платформа превысила допустимое время обработки запроса, результат запроса не определён. Попробуйте отправить запрос повторно или выяснить результат выполнения исходного запроса, если повторное исполнение запроса нежелательно. |
[5xx]: https://tools.ietf.org/html/rfc7231#section-6.6
Если вы получили ошибку, которой нет в данном описании, обратитесь в техническую поддержку.

51
gulpfile.js Normal file
View File

@ -0,0 +1,51 @@
const gulp = require('gulp');
const util = require('gulp-util');
const gulpConnect = require('gulp-connect');
const connect = require('connect');
const cors = require('cors');
const exec = require('child_process').exec;
const portfinder = require('portfinder');
const swaggerRepo = require('swagger-repo');
const DIST_DIR = 'dist';
const SPEC_DIR = 'spec';
gulp.task('build', function (cb) {
exec('npm run build', function (err, stdout, stderr) {
console.log(stderr);
cb(err);
});
});
gulp.task('edit', function () {
portfinder.getPort({ port: 5000 }, function (err, port) {
let app = connect();
app.use(swaggerRepo.swaggerEditorMiddleware());
app.listen(port);
util.log(util.colors.green('swagger-editor started http://localhost:' + port));
});
});
gulp.task('reload', gulp.series('build', function () {
gulp.src(DIST_DIR).pipe(gulpConnect.reload())
}));
gulp.task('watch', function () {
gulp.watch([`${SPEC_DIR}/**/*`, 'web/**/*'], gulp.series('reload'));
});
gulp.task('serve', gulp.parallel('build', 'edit', 'watch', function () {
portfinder.getPort({ port: 3000 }, function (err, port) {
gulpConnect.server({
root: [DIST_DIR],
livereload: true,
port: port,
middleware: function (gulpConnect, opt) {
return [
cors()
]
}
});
});
}));

7
openapitools.json Normal file
View File

@ -0,0 +1,7 @@
{
"$schema": "node_modules/@openapitools/openapi-generator-cli/config.schema.json",
"spaces": 2,
"generator-cli": {
"version": "6.0.0-beta"
}
}

16112
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

24
package.json Normal file
View File

@ -0,0 +1,24 @@
{
"name": "@vality/swag-api-keys-v2",
"version": "0.1.1",
"scripts": {
"build": "node ./scripts/build.js",
"swagger": "swagger-repo",
"test": "swagger-repo validate --basedir api/apikeys/spec/",
"start": "gulp serve",
"codegen": "vality-openapi generate ./dist/api/apikeys/swagger.json"
},
"devDependencies": {
"@vality/openapi-generator-cli": "0.1.1-fbfe66e.0",
"connect": "3.7.0",
"cors": "2.8.5",
"gulp": "github:gulpjs/gulp",
"gulp-connect": "5.7.0",
"gulp-util": "3.0.8",
"json-merge-patch": "1.0.2",
"portfinder": "1.0.32",
"shelljs": "0.8.5",
"swagger-repo": "1.5.1",
"swagger-ui": "4.15.5"
}
}

6
renovate.json Normal file
View File

@ -0,0 +1,6 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>valitydev/.github:renovate-config"
]
}

32
scripts/build.js Executable file
View File

@ -0,0 +1,32 @@
#!/usr/bin/env node
'use strict';
var Path = require('path');
require('shelljs/global');
set('-e');
var TARGET_DIR = 'dist'
if (process.argv[2]) {
TARGET_DIR = process.argv[2]
}
var APIS = ls('api')
if (process.argv[3]) {
APIS = [process.argv[3]]
}
mkdir('-p', TARGET_DIR);
cp('-R', 'web/*', TARGET_DIR + '/');
APIS.forEach(function (api) {
var basedir = 'api/' + api + '/spec/';
var targetdir = TARGET_DIR + '/api/' + api;
mkdir('-p', targetdir);
exec('npm run swagger bundle -- --basedir ' + basedir + ' -o ' + targetdir + '/swagger.json');
exec('npm run swagger bundle -- --basedir ' + basedir + ' --yaml -o ' + targetdir + '/swagger.yaml');
});
var SWAGGER_UI_DIST = Path.dirname(require.resolve('swagger-ui'));
rm('-rf', TARGET_DIR + '/swagger-ui/')
cp('-R', SWAGGER_UI_DIST, TARGET_DIR + '/swagger-ui/')
// sed('-i', 'http://petstore.swagger.io/v2/swagger.json', '../swagger.json', TARGET_DIR + '/swagger-ui/index.html')

View File

@ -0,0 +1,28 @@
var jpointer = require('json-pointer');
var mergePatch = require('json-merge-patch');
module.exports = {
pathExpression: '$..["x-rebillyMerge"]',
init: function(swagger) {
console.log('* x-rebillyMerge plugin');
},
process: function(parent, name, jsonpath, swagger) {
var value = parent[name];
if (!Array.isArray(value)) {
throw Error('x-rebillyMerge argument should be array at ' + jsonpath);
}
let res = null;
value.forEach(function(obj) {
if (typeof obj !== 'object') throw Error('Can\'t merge non-object values at ' + jsonpath);
if (obj.$ref && (typeof obj.$ref === 'string')) {
obj = jpointer.get(swagger, obj.$ref.substring(1));
}
res = mergePatch.apply(res, obj);
});
delete parent[name];
Object.assign(parent, res);
},
finish: function(swagger) {
// TODO: cleanup unused $refs
},
}

View File

@ -0,0 +1,27 @@
type: object
required:
- errorType
properties:
errorType:
description: Error type
type: string
enum:
- SchemaViolated
- NotFound
- WrongType
- NotInRange
- WrongSize
- WrongLength
- WrongArray
- NoMatch
- InvalidResourceToken
- InvalidToken
example: NotFound
name:
description: Name or identifier of message element containing invalid data
type: string
example: X-Request-ID
description:
description: Explanation of why the data is invalid
type: string
example: Required parameter was not sent

46
web/index.html Normal file
View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<title>Vality Api Keys Management API</title>
<!-- needed for adaptive design -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js">
</script>
<!--
ReDoc doesn't change outer page styles
-->
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id='redoc'></div>
<script type="text/javascript">
// Since we serve three different specs from a single domain we hack up a
// simple way to redirect user to one or another
var spec = window.location.search.substring(1);
if (spec.length == 0) {
spec = "api/apikeys/swagger.json";
}
Redoc.init(
spec,
{
theme: {
breakpoints: {
// 3-panel view fix
medium: '75rem'
}
}
},
document.getElementById('redoc')
);
</script>
</body>
</html>