mirror of
https://github.com/valitydev/swag-url-shortener.git
synced 2024-11-06 01:15:19 +00:00
MSPF-321: Introduce swag proto for URL-shortener (#1)
This commit is contained in:
parent
44e803c2a3
commit
cba6775ece
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
# Dir for API portal deploy
|
||||
web_deploy
|
||||
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
|
||||
|
1
CODEOWNERS
Normal file
1
CODEOWNERS
Normal file
@ -0,0 +1 @@
|
||||
* @hackstep
|
8
Makefile
Normal file
8
Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
all: build
|
||||
|
||||
build:
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
start:
|
||||
npm start
|
50
gulpfile.js
Normal file
50
gulpfile.js
Normal file
@ -0,0 +1,50 @@
|
||||
var gulp = require('gulp');
|
||||
var util = require('gulp-util')
|
||||
var gulpConnect = require('gulp-connect');
|
||||
var connect = require('connect');
|
||||
var cors = require('cors');
|
||||
var path = require('path');
|
||||
var exec = require('child_process').exec;
|
||||
var portfinder = require('portfinder');
|
||||
var swaggerRepo = require('swagger-repo');
|
||||
|
||||
var DIST_DIR = 'web_deploy';
|
||||
|
||||
gulp.task('serve', ['build', 'watch', 'edit'], function() {
|
||||
portfinder.getPort({port: 3000}, function (err, port) {
|
||||
gulpConnect.server({
|
||||
root: [DIST_DIR],
|
||||
livereload: true,
|
||||
port: port,
|
||||
middleware: function (gulpConnect, opt) {
|
||||
return [
|
||||
cors()
|
||||
]
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('edit', function() {
|
||||
portfinder.getPort({port: 5000}, function (err, port) {
|
||||
var app = connect();
|
||||
app.use(swaggerRepo.swaggerEditorMiddleware());
|
||||
app.listen(port);
|
||||
util.log(util.colors.green('swagger-editor started http://localhost:' + port));
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('build', function (cb) {
|
||||
exec('npm run build', function (err, stdout, stderr) {
|
||||
console.log(stderr);
|
||||
cb(err);
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('reload', ['build'], function () {
|
||||
gulp.src(DIST_DIR).pipe(gulpConnect.reload())
|
||||
});
|
||||
|
||||
gulp.task('watch', function () {
|
||||
gulp.watch(['spec/**/*', 'web/**/*'], ['reload']);
|
||||
});
|
24
package.json
Normal file
24
package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "RBKmoney-openapi-spec",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"bower": "^1.7.7",
|
||||
"connect": "^3.4.1",
|
||||
"cors": "^2.7.1",
|
||||
"deploy-to-gh-pages": "^1.1.0",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-connect": "^4.2.0",
|
||||
"gulp-util": "^3.0.7",
|
||||
"portfinder": "^1.0.3",
|
||||
"shelljs": "^0.7.0",
|
||||
"swagger-repo": "^1.0.0",
|
||||
"swagger-ui": "^2.1.4"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "node ./scripts/build.js",
|
||||
"swagger": "swagger-repo",
|
||||
"test": "swagger-repo validate",
|
||||
"start": "gulp serve"
|
||||
}
|
||||
}
|
23
scripts/build.js
Normal file
23
scripts/build.js
Normal file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
var Path = require('path');
|
||||
|
||||
var 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');
|
||||
|
||||
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')
|
24
spec/README.md
Normal file
24
spec/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
## Global headers
|
||||
|
||||
In order to minimize duplications you can use `headers` global object (similar to `definitions`, `responses`).
|
||||
During build process all references to global `headers` will be inlined and `headers` will be removed form resulting spec so spec will be valid (global `headers` is not allowed by Swagger spec):
|
||||
|
||||
Example:
|
||||
```yaml
|
||||
...
|
||||
headers:
|
||||
Rate-Limit-Limit:
|
||||
description: The number of allowed requests in the current period
|
||||
type: integer
|
||||
...
|
||||
paths:
|
||||
/api-keys:
|
||||
get:
|
||||
summary: Retrieve a list of api keys
|
||||
responses:
|
||||
200:
|
||||
description: A list of api keys was retrieved successfully
|
||||
headers:
|
||||
Rate-Limit-Limit:
|
||||
$ref: "#/headers/Rate-Limit-Limit"
|
||||
```
|
9
spec/code_samples/README.md
Normal file
9
spec/code_samples/README.md
Normal file
@ -0,0 +1,9 @@
|
||||
Code samples
|
||||
=====
|
||||
|
||||
Generate [x-code-samples](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-code-samples)
|
||||
Path `<lang>/<path>/<HTTP verb>.<extension>` where:
|
||||
* `<lang>` - name of the language from [this](https://github.com/github/linguist/blob/master/lib/linguist/popular.yml) list.
|
||||
* `<path>` - path of target method, where all slashes replaced with `@` sign.
|
||||
* `<HTTP verb>` - verb of target method.
|
||||
* `<extension>` - ignored.
|
18
spec/definitions/ShortenedUrl.yaml
Normal file
18
spec/definitions/ShortenedUrl.yaml
Normal file
@ -0,0 +1,18 @@
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
- shortenedUrl
|
||||
- sourceUrl
|
||||
- expiresAt
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
shortenedUrl:
|
||||
type: string
|
||||
format: uri
|
||||
sourceUrl:
|
||||
type: string
|
||||
format: uri
|
||||
expiresAt:
|
||||
type: string
|
||||
format: date-time
|
27
spec/paths/shortened-urls.yaml
Normal file
27
spec/paths/shortened-urls.yaml
Normal file
@ -0,0 +1,27 @@
|
||||
post:
|
||||
description: Создать новую короткую ссылку
|
||||
tags:
|
||||
- Shortener
|
||||
operationId: shortenUrl
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestID'
|
||||
- name: shortenedUrlParams
|
||||
description: Параметры для создания короткой ссылки
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
sourceUrl:
|
||||
type: string
|
||||
format: uri
|
||||
expiresAt:
|
||||
type: string
|
||||
format: date-time
|
||||
responses:
|
||||
'201':
|
||||
description: Короткая ссылка создана
|
||||
schema:
|
||||
$ref: '#/definitions/ShortenedUrl'
|
||||
'400':
|
||||
$ref: '#/responses/BadRequest'
|
32
spec/paths/shortened-urls@{shortenedUrlID}.yaml
Normal file
32
spec/paths/shortened-urls@{shortenedUrlID}.yaml
Normal file
@ -0,0 +1,32 @@
|
||||
get:
|
||||
description: Получить данные созданной короткой ссылки
|
||||
operationId: getShortenedUrl
|
||||
tags:
|
||||
- Shortener
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestID'
|
||||
- $ref: '#/parameters/shortenedUrlID'
|
||||
responses:
|
||||
'200':
|
||||
description: Данные короткой ссылки
|
||||
schema:
|
||||
$ref: '#/definitions/ShortenedUrl'
|
||||
'400':
|
||||
$ref: '#/responses/BadRequest'
|
||||
'404':
|
||||
$ref: '#/responses/NotFound'
|
||||
delete:
|
||||
description: Удалить короткую ссылку
|
||||
operationId: deleteShortenedUrl
|
||||
tags:
|
||||
- Shortener
|
||||
parameters:
|
||||
- $ref: '#/parameters/requestID'
|
||||
- $ref: '#/parameters/shortenedUrlID'
|
||||
responses:
|
||||
'204':
|
||||
description: Короткая ссылка удалена
|
||||
'400':
|
||||
$ref: '#/responses/BadRequest'
|
||||
'404':
|
||||
$ref: '#/responses/NotFound'
|
81
spec/swagger.yaml
Normal file
81
spec/swagger.yaml
Normal file
@ -0,0 +1,81 @@
|
||||
swagger: '2.0'
|
||||
host: rbk.mn
|
||||
basePath: /v1
|
||||
info:
|
||||
version: '1.0'
|
||||
title: RBKmoney URL shortener API
|
||||
termsOfService: 'http://rbkmoney.com/'
|
||||
contact:
|
||||
name: RBKmoney support team
|
||||
email: tech-support@rbkmoney.com
|
||||
url: 'https://api.rbk.money'
|
||||
description: |
|
||||
URL shortener API
|
||||
schemes:
|
||||
- https
|
||||
consumes:
|
||||
- application/json; charset=utf-8
|
||||
produces:
|
||||
- application/json; charset=utf-8
|
||||
securityDefinitions:
|
||||
bearer:
|
||||
type: apiKey
|
||||
name: Authorization
|
||||
in: header
|
||||
description: >
|
||||
Для аутентификации вызовов мы используем [JWT](https://jwt.io).
|
||||
Cоответствующий ключ передается в заголовке.
|
||||
|
||||
```shell
|
||||
Authorization: Bearer {TOKENIZATION|PRIVATE_JWT}
|
||||
```
|
||||
|
||||
Посмотреть ваш API-ключ вы можете в [личном
|
||||
кабинете](https://dashboard.rbk.money/api/key).
|
||||
Ключи не разделяются на тестовые и боевые, ваш API ключ открывает доступ
|
||||
ко всем функциям платформы. Для тестовых транзакций используйте ID
|
||||
тестовых магазинов.
|
||||
Помните, что вы никому не должны передавать ваш API ключ!
|
||||
security:
|
||||
- bearer: []
|
||||
responses:
|
||||
NotFound:
|
||||
description: Entity not found
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- message
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
BadRequest:
|
||||
description: Illegal input for operation
|
||||
schema:
|
||||
type: object
|
||||
required:
|
||||
- code
|
||||
- message
|
||||
properties:
|
||||
code:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
parameters:
|
||||
requestID:
|
||||
name: X-Request-ID
|
||||
in: header
|
||||
description: Уникальный идентификатор запроса к системе
|
||||
required: true
|
||||
type: string
|
||||
maxLength: 32
|
||||
minLength: 1
|
||||
shortenedUrlID:
|
||||
name: shortenedUrlID
|
||||
in: path
|
||||
description: Идентификатор короткой ссылки
|
||||
required: true
|
||||
type: string
|
||||
tags:
|
||||
- name: Shortener
|
||||
x-displayName: Короткие ссылки
|
||||
description: Получение и работа с короткими ссылками
|
59
web/index.html
Normal file
59
web/index.html
Normal file
@ -0,0 +1,59 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>RBKmoney URL shortener</title>
|
||||
<!-- needed for adaptive design -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!--
|
||||
ReDoc uses font options from the parent element
|
||||
So override default browser styles
|
||||
-->
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<redoc spec-url="./swagger.json" suppress-warnings="true" lazy-rendering="true">
|
||||
</redoc>
|
||||
<script src="//rebilly.github.io/ReDoc/releases/v1.x.x/redoc.min.js"> </script>
|
||||
<!-- GA -->
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', 'UA-92343978-1', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
<!-- Yandex.Metrika counter -->
|
||||
<script type="text/javascript">
|
||||
(function (d, w, c) {
|
||||
(w[c] = w[c] || []).push(function() {
|
||||
try {
|
||||
w.yaCounter42980494 = new Ya.Metrika({
|
||||
id:42980494,
|
||||
clickmap:true,
|
||||
trackLinks:true,
|
||||
accurateTrackBounce:true
|
||||
});
|
||||
} catch(e) { }
|
||||
});
|
||||
var n = d.getElementsByTagName("script")[0],
|
||||
s = d.createElement("script"),
|
||||
f = function () { n.parentNode.insertBefore(s, n); };
|
||||
s.type = "text/javascript";
|
||||
s.async = true;
|
||||
s.src = "https://mc.yandex.ru/metrika/watch.js";
|
||||
if (w.opera == "[object Opera]") {
|
||||
d.addEventListener("DOMContentLoaded", f, false);
|
||||
} else { f(); }
|
||||
})(document, window, "yandex_metrika_callbacks");
|
||||
</script>
|
||||
<noscript><div><img src="https://mc.yandex.ru/watch/42980494" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
<!-- /Yandex.Metrika counter -->
|
||||
</body>
|
||||
</html>
|
28
wercker.yml
Normal file
28
wercker.yml
Normal file
@ -0,0 +1,28 @@
|
||||
box: node:7
|
||||
|
||||
build:
|
||||
steps:
|
||||
- npm-install
|
||||
- npm-test
|
||||
- script:
|
||||
name: build docsite
|
||||
code: npm run build -- ${WERCKER_OUTPUT_DIR}
|
||||
after-steps:
|
||||
- slack-notifier:
|
||||
url: ${SLACK_WEBHOOK_URL}
|
||||
username: "wercker"
|
||||
|
||||
release:
|
||||
steps:
|
||||
- script:
|
||||
name: prepare release artifacts for branch master.
|
||||
code: mkdir -p out && cp ./swagger.{yaml,json} out/
|
||||
- lordlothar99/git-push:
|
||||
gh_oauth: ${GITHUB_API_TOKEN}
|
||||
branch: release/${WERCKER_GIT_BRANCH}
|
||||
basedir: out
|
||||
message: Release ${WERCKER_GIT_OWNER}/${WERCKER_GIT_REPOSITORY}@${WERCKER_GIT_COMMIT}
|
||||
after-steps:
|
||||
- slack-notifier:
|
||||
url: ${SLACK_WEBHOOK_URL}
|
||||
username: "wercker"
|
Loading…
Reference in New Issue
Block a user