Initial + build

This commit is contained in:
PNV 2022-03-18 13:00:09 +03:00
commit 636958e702
44 changed files with 949 additions and 0 deletions

15
.github/workflows/basic-linters.yml vendored Normal file
View File

@ -0,0 +1,15 @@
name: Vality basic linters
on:
pull_request:
branches:
- master
- main
push:
branches:
- master
- main
jobs:
lint:
uses: valitydev/base-workflows/.github/workflows/basic-linters.yml@v1

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

@ -0,0 +1,10 @@
name: Maven Build Artifact
on:
pull_request:
branches:
- '*'
jobs:
build:
uses: valitydev/base-workflow/.github/workflows/maven-swag-build.yml@v1

18
.github/workflows/deploy.yml vendored Normal file
View File

@ -0,0 +1,18 @@
name: Maven Deploy Artifact
on:
push:
branches:
- 'master'
- 'main'
jobs:
deploy:
uses: valitydev/java-workflow/.github/workflows/maven-swag-deploy.yml@v1
secrets:
server-username: ${{ secrets.OSSRH_USERNAME }}
server-password: ${{ secrets.OSSRH_TOKEN }}
deploy-secret-key: ${{ secrets.OSSRH_GPG_SECRET_KEY }}
deploy-secret-key-password: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
github-token: ${{ secrets.GITHUB_TOKEN }}
mm-webhook-url: ${{ secrets.MATTERMOST_WEBHOOK_URL }}

2
.github/workflows/settings.yml vendored Normal file
View File

@ -0,0 +1,2 @@
# These settings are synced to GitHub by https://probot.github.io/apps/settings/
_extends: .github

61
.gitignore vendored Normal file
View File

@ -0,0 +1,61 @@
# 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
# CI
.wercker
# Generated
web_deploy/
package-lock.json
# User-specific stuff:
.idea/
.idea/workspace.xml
.idea/tasks.xml
.idea/dictionaries
.idea/vcs.xml
.idea/jsLibraryMappings.xml
# Sensitive or high-churn files:
.idea/dataSources.ids
.idea/dataSources.xml
.idea/dataSources.local.xml
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml
# Gradle:
.idea/gradle.xml
.idea/libraries

4
.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "build_utils"]
path = build_utils
url = git@github.com:rbkmoney/build_utils.git
branch = master

18
.redocly.yaml Normal file
View File

@ -0,0 +1,18 @@
# See https://docs.redoc.ly/cli/configuration/ for more information.
apiDefinitions:
core: 'openapi/openapi.yaml'
lint:
plugins:
- './plugins/local.js'
extends:
- recommended
rules:
tag-description: off
preprocessors:
local/merge-schemas: on
referenceDocs:
showConsole: true
layout:
scope: section
routingStrategy: browser
htmlTemplate: ./web/index.html

38
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,38 @@
#!groovy
build('swag-messages', 'docker-host') {
checkoutRepo()
loadBuildUtils()
def pipeDefault
def gitUtils
runStage('load pipeline') {
env.JENKINS_LIB = "build_utils/jenkins_lib"
pipeDefault = load("${env.JENKINS_LIB}/pipeDefault.groovy")
gitUtils = load("${env.JENKINS_LIB}/gitUtils.groovy")
}
pipeDefault() {
runStage('init') {
withGithubSshCredentials {
sh 'make wc_init'
}
}
runStage('build') {
sh 'make wc_build'
}
// Java
runStage('Build client & server') {
withCredentials([[$class: 'FileBinding', credentialsId: 'java-maven-settings.xml', variable: 'SETTINGS_XML']]) {
if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('epic/')) {
sh 'make SETTINGS_XML=${SETTINGS_XML} BRANCH_NAME=${BRANCH_NAME} java.swag.deploy_client'
sh 'make SETTINGS_XML=${SETTINGS_XML} BRANCH_NAME=${BRANCH_NAME} java.swag.deploy_server'
} else {
sh 'make SETTINGS_XML=${SETTINGS_XML} BRANCH_NAME=${BRANCH_NAME} java.swag.compile_client'
sh 'make SETTINGS_XML=${SETTINGS_XML} BRANCH_NAME=${BRANCH_NAME} java.swag.compile_server'
}
}
}
}
}

113
Makefile Normal file
View File

@ -0,0 +1,113 @@
SUBMODULES = build_utils
SUBTARGETS = $(patsubst %,%/.git,$(SUBMODULES))
UTILS_PATH := build_utils
TEMPLATES_PATH := .
# Name of the service
SERVICE_NAME := swag-messages
# Service image default tag
SERVICE_IMAGE_TAG ?= $(shell git rev-parse HEAD)
# The tag for service image to be pushed with
SERVICE_IMAGE_PUSH_TAG ?= $(SERVICE_IMAGE_TAG)
BUILD_IMAGE_TAG := bdc05544014b3475c8e0726d3b3d6fc81b09db96
CALL_ANYWHERE := \
all submodules init build java.compile java.deploy
CALL_W_CONTAINER := $(CALL_ANYWHERE)
all: compile
-include $(UTILS_PATH)/make_lib/utils_image.mk
-include $(UTILS_PATH)/make_lib/utils_container.mk
.PHONY: $(CALL_W_CONTAINER)
$(SUBTARGETS): %/.git: %
git submodule update --init $<
touch $@
submodules: $(SUBTARGETS)
# NPM
init:
npm install
build:
npm run build
# Java
ifdef SETTINGS_XML
DOCKER_RUN_OPTS = -v $(SETTINGS_XML):$(SETTINGS_XML)
DOCKER_RUN_OPTS += -e SETTINGS_XML=$(SETTINGS_XML)
endif
ifdef LOCAL_BUILD
DOCKER_RUN_OPTS += -v $$HOME/.m2:/home/$(UNAME)/.m2:rw
endif
COMMIT_HASH := $(shell git --no-pager log -1 --pretty=format:"%h")
NUMBER_COMMITS := $(shell git rev-list --count HEAD)
JAVA_PKG_VERSION := 1.$(NUMBER_COMMITS)-$(COMMIT_HASH)
ifdef BRANCH_NAME
ifeq "$(findstring epic,$(BRANCH_NAME))" "epic"
JAVA_PKG_VERSION := $(JAVA_PKG_VERSION)-epic
endif
endif
MVN = mvn -s $(SETTINGS_XML) -Dcommit.number="$(NUMBER_COMMITS)"
java.swag.compile_client:
$(if $(SETTINGS_XML),,echo "SETTINGS_XML not defined" ; exit 1)
$(MVN) clean && \
$(MVN) compile -P="client"
java.swag.deploy_client:
$(if $(SETTINGS_XML),,echo "SETTINGS_XML not defined" ; exit 1)
$(MVN) clean && \
$(MVN) versions:set versions:commit -DnewVersion="$(JAVA_PKG_VERSION)-client" && \
$(MVN) deploy -P="client"
java.swag.install_client:
$(if $(SETTINGS_XML),,echo "SETTINGS_XML not defined" ; exit 1)
$(MVN) clean && \
$(MVN) versions:set versions:commit -DnewVersion="$(JAVA_PKG_VERSION)-client" && \
$(MVN) install -P="client"
java.swag.compile_server:
$(if $(SETTINGS_XML),,echo "SETTINGS_XML not defined" ; exit 1)
$(MVN) clean && \
$(MVN) compile -P="server"
java.swag.deploy_server:
$(if $(SETTINGS_XML),,echo "SETTINGS_XML not defined" ; exit 1)
$(MVN) clean && \
$(MVN) versions:set versions:commit -DnewVersion="$(JAVA_PKG_VERSION)-server" && \
$(MVN) deploy -P="server"
java.swag.install_server:
$(if $(SETTINGS_XML),,echo "SETTINGS_XML not defined" ; exit 1)
$(MVN) clean && \
$(MVN) versions:set versions:commit -DnewVersion="$(JAVA_PKG_VERSION)-server" && \
$(MVN) install -P="server"
java.compile: java.settings
$(MVN) compile
java.deploy: java.settings
$(MVN) versions:set versions:commit -DnewVersion="$(JAVA_PKG_VERSION)" && \
$(MVN) deploy
java.install: java.settings
$(MVN) clean && \
$(MVN) versions:set versions:commit -DnewVersion="$(JAVA_PKG_VERSION)" && \
$(MVN) install
java.settings:
$(if $(SETTINGS_XML),, echo "SETTINGS_XML not defined"; exit 1)

1
README.md Normal file
View File

@ -0,0 +1 @@
# swag-messages

59
gulpfile.js Normal file
View File

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

28
package.json Normal file
View File

@ -0,0 +1,28 @@
{
"name": "swag-messages",
"version": "0.2.0",
"private": true,
"scripts": {
"build": "node ./scripts/build.js",
"swagger": "swagger-repo",
"validate": "swagger-repo validate",
"start": "gulp serve"
},
"devDependencies": {
"bower": "^1.8.8",
"connect": "^3.7.0",
"cors": "^2.8.5",
"deploy-to-gh-pages": "^1.3.7",
"gulp": "^4.0.2",
"gulp-connect": "^5.7.0",
"gulp-util": "^3.0.8",
"json-merge-patch": "^0.2.3",
"npm": "^6.13.0",
"portfinder": "^1.0.25",
"shelljs": "^0.8.3",
"swagger-repo": "^2.0.0-rc.15",
"swagger-ui": "^3.24.2",
"express": "^4.17.1",
"redoc-cli": "^0.10.2"
}
}

208
pom.xml Normal file
View File

@ -0,0 +1,208 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>dev.vality</groupId>
<artifactId>library-parent-pom</artifactId>
<version>1.0.2</version>
</parent>
<artifactId>swag-messages</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Messages</name>
<description>Generates jar artifact containing compiled swagger classes based on generated swagger yaml files
</description>
<properties>
<default.package>dev.vality.swag.messages</default.package>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<swagger-annotations-version>1.5.21</swagger-annotations-version>
<jodatime-version>2.7</jodatime-version>
<maven-plugin-version>1.0.0</maven-plugin-version>
<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<jetty-version>9.2.15.v20160210</jetty-version>
<slf4j-version>1.7.31</slf4j-version>
<junit-version>4.12</junit-version>
<servlet-api-version>2.5</servlet-api-version>
<springfox-version>3.0.0</springfox-version>
<jackson-version>2.12.3</jackson-version>
<jackson-threetenbp-version>2.6.4</jackson-threetenbp-version>
<spring-version>5.3.8</spring-version>
<javax-annotation-api-version>1.3.2</javax-annotation-api-version>
<javax-validation-api-version>1.1.0.Final</javax-validation-api-version>
<jaxb-version>2.3.1</jaxb-version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-version}</version>
<scope>provided</scope>
</dependency>
<!--Spring dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-version}</version>
<scope>provided</scope>
</dependency>
<!--SpringFox dependencies-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-version}</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson-version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet-api-version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>${javax-annotation-api-version}</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb-version}</version>
</dependency>
<!-- Bean Validation API support -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>${javax-validation-api-version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>2.0.10</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>server</id>
<build>
<plugins>
<plugin>
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>3.0.13</version>
<executions>
<execution>
<id>generate-server</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>web_deploy/swagger.yaml</inputSpec>
<language>java</language>
<configOptions>
<dateLibrary>java8</dateLibrary>
</configOptions>
<language>spring</language>
<library>spring-mvc</library>
<apiPackage>${default.package}.api</apiPackage>
<modelPackage>${default.package}.model</modelPackage>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>client</id>
<build>
<plugins>
<plugin>
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>3.0.13</version>
<executions>
<execution>
<id>generate-client</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>web_deploy/swagger.yaml</inputSpec>
<language>java</language>
<configOptions>
<dateLibrary>java8</dateLibrary>
</configOptions>
<language>java</language>
<library>resttemplate</library>
<apiPackage>${default.package}.api</apiPackage>
<modelPackage>${default.package}.model</modelPackage>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

18
scripts/build.js Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env node
'use strict';
const Path = require('path');
let TARGET_DIR = 'web_deploy';
if (process.argv[2]) {
TARGET_DIR = process.argv[2]
}
require('shelljs/global');
set('-e');
mkdir('-p', TARGET_DIR);
cp('-R', 'web/*', TARGET_DIR + '/');
exec('npm run swagger bundle -- -o ' + TARGET_DIR + '/swagger.json');
exec('npm run swagger bundle -- --yaml -o ' + TARGET_DIR + '/swagger.yaml');

View File

@ -0,0 +1,7 @@
name: conversationId
in: query
required: true
schema:
type: array
items:
$ref: '#/components/schemas/ConversationID'

View File

@ -0,0 +1,4 @@
name: conversationStatus
in: query
schema:
$ref: '#/components/schemas/ConversationStatus'

View File

@ -0,0 +1 @@
description: Ошибка авторизации

View File

@ -0,0 +1,5 @@
description: Комментарии не найдены
content:
application/json:
schema:
$ref: '#/components/schemas/GeneralError'

View File

@ -0,0 +1,5 @@
description: ConversationResponse
content:
application/json:
schema:
$ref: '#/components/schemas/ConversationResponse'

View File

@ -0,0 +1,5 @@
description: Заданный ресурс не найден
content:
application/json:
schema:
$ref: '#/components/schemas/GeneralError'

View File

@ -0,0 +1,6 @@
type: object
required:
- message
properties:
message:
type: string

View File

@ -0,0 +1,14 @@
type: object
required:
- conversationId
- messages
- status
properties:
conversationId:
$ref: '#/components/schemas/ConversationID'
messages:
type: array
items:
$ref: '#/components/schemas/Message'
status:
$ref: '#/components/schemas/ConversationStatus'

View File

@ -0,0 +1,4 @@
type: object
properties:
conversationStatus:
$ref: '#/components/schemas/ConversationStatus'

View File

@ -0,0 +1 @@
type: string

View File

@ -0,0 +1,11 @@
type: object
required:
- conversationId
- messages
properties:
conversationId:
$ref: '#/components/schemas/ConversationID'
messages:
type: array
items:
$ref: '#/components/schemas/MessageParam'

View File

@ -0,0 +1,20 @@
type: object
required:
- conversations
- users
properties:
conversations:
type: array
items:
$ref: '#/components/schemas/Conversation'
users:
type: object
additionalProperties:
type: object
properties:
userId:
type: object
$ref: '#/components/schemas/UserID'
user:
type: object
$ref: '#/components/schemas/User'

View File

@ -0,0 +1,4 @@
type: string
enum:
- Actual
- Outdated

View File

@ -0,0 +1,7 @@
description: |
Уникальный в рамках платформы идентификатор сущности для данного участника.
Используется для обеспечения идемпотентности запроса.
type: string
maxLength: 40
minLength: 1

View File

@ -0,0 +1,14 @@
type: object
required:
- externalID
properties:
externalID:
x-rebillyMerge:
- $ref: '#/components/schemas/ExternalID'
- description: Переданное значение `externalID`, для которого обнаружен конфликт параметров запроса
id:
description: Идентификатор сущности, созданной предыдущим запросом с указанным `externalID`
type: string
message:
description: Человекочитаемое описание ошибки
type: string

View File

@ -0,0 +1,15 @@
type: object
required:
- messageId
- text
- userId
- timestamp
properties:
messageId:
$ref: '#/components/schemas/MessageID'
text:
type: string
userId:
$ref: '#/components/schemas/UserID'
timestamp:
type: string

View File

@ -0,0 +1 @@
type: string

View File

@ -0,0 +1,9 @@
type: object
required:
- messageId
- text
properties:
messageId:
$ref: '#/components/schemas/MessageID'
text:
type: string

View File

@ -0,0 +1,3 @@
type: array
items:
$ref: '#/components/schemas/ConversationParam'

View File

@ -0,0 +1,11 @@
description: |
Детализация описания ошибки
type: object
required:
- code
properties:
code:
description: Детализация кода ошибки
type: string
subError:
$ref: '#/components/schemas/SubError'

View File

@ -0,0 +1,12 @@
type: object
required:
- userId
- email
- fullName
properties:
userId:
$ref: '#/components/schemas/UserID'
email:
type: string
fullName:
type: string

View File

@ -0,0 +1 @@
type: string

View File

@ -0,0 +1,8 @@
type: object
required:
- ids
properties:
ids:
type: array
items:
$ref: '#/components/schemas/UserID'

View File

@ -0,0 +1,10 @@
type: http
scheme: bearer
bearerFormat: JWT
description: >
Для аутентификации вызовов мы используем [JWT](https://jwt.io).
Cоответствующий ключ передается в заголовке.
```shell
Authorization: Bearer {TOKENIZATION|PRIVATE_JWT}
```

16
spec/openapi.yaml Normal file
View File

@ -0,0 +1,16 @@
openapi: 3.0.0
info:
version: 1.0.0
title: RBKmoney Messages API
description: Messages API
servers:
- url: 'https://{subdomain}.rbk.money/messages/{version}'
variables:
subdomain:
default: api
version:
enum:
- v1
default: v1
security:
- APIKey: []

View File

@ -0,0 +1,30 @@
get:
tags:
- Conversations
operationId: getConversations
parameters:
- $ref: '#/components/parameters/conversationId'
- $ref: '#/components/parameters/conversationStatus'
responses:
'200':
description: Комментарии
$ref: '#/components/responses/ConversationResponse'
'401':
$ref: '#/components/responses/AccessForbidden'
'404':
$ref: '#/components/responses/ConversationNotFound'
post:
tags:
- Conversations
operationId: saveConversations
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/SaveConversationParams'
required: true
responses:
'200':
description: Комментарии сохранены
'401':
$ref: '#/components/responses/AccessForbidden'

View File

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

View File

@ -0,0 +1,30 @@
var jpointer = require('json-pointer');
var mergePatch = require('json-merge-patch');
module.exports = {
pathExpression: '$..["x-rebillyMerge"]',
init: function(_swagger, options) {
if (options.verbose) {
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,24 @@
module.exports = {
pathExpression: '$..["x-sortableEnum"]',
init: function(_swagger, options) {
if (options.verbose) {
console.log('* x-sortableEnum plugin');
}
},
process: function(parent, name, jsonpath, swagger) {
var value = parent[name];
if (!Array.isArray(value)) {
throw Error('x-sortableEnum argument should be an array at ' + jsonpath);
}
res = [];
value.forEach(function(str) {
if (typeof str !== 'string') throw Error('x-sortableEnum supports only string enums ' + jsonpath);
res.push(str);
res.push('-' + str);
});
delete parent[name];
parent.enum = res;
},
finish: function(swagger) {
},
}

47
web/index.html Normal file
View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<title>RBKmoney Messages API</title>
<!-- needed for adaptive design -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
<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 = "./swagger.json";
}
Redoc.init(
spec,
{
theme: {
breakpoints: {
// 3-panel view fix
medium: '75rem'
}
}
},
document.getElementById('redoc')
);
</script>
</body>
</html>