migrate Swagger 2.0 spec to OpenAPI 3.0.0

This commit is contained in:
Rigel Kent 2018-11-15 14:10:15 +01:00
parent 6cb3482ceb
commit 3e9e6f2f14
No known key found for this signature in database
GPG Key ID: EA12971B0E438F36
19 changed files with 1224 additions and 15698 deletions

View File

@ -183,9 +183,8 @@ See [ARCHITECTURE.md](/ARCHITECTURE.md) for a more detailed explanation of the a
#### Backend
* REST API:
* Quick Start: [/support/doc/api/quickstart.md](/support/doc/api/quickstart.md)
* Swagger/OpenAPI schema: [/support/doc/api/openapi.yaml](/support/doc/api/openapi.yaml)
* HTML explorer: [/support/doc/api/html/index.html](https://htmlpreview.github.io/?https://github.com/Chocobozzz/PeerTube/blob/develop/support/doc/api/html/index.html)
* OpenAPI 3.0.0 schema: [/support/doc/api/openapi.yaml](/support/doc/api/openapi.yaml)
* HTML explorer: [docs.joinpeertube.org/api.html](http://docs.joinpeertube.org/api.html)
* Servers communicate with each other with [Activity
Pub](https://www.w3.org/TR/activitypub/).
* Each server has its own users who query it (search videos, query where the

View File

@ -49,14 +49,12 @@
"create-import-video-file-job": "node ./dist/scripts/create-import-video-file-job.js",
"test": "scripty",
"help": "scripty",
"generate-api-doc": "scripty",
"generate-cli-doc": "scripty",
"parse-log": "node ./dist/scripts/parse-log.js",
"prune-storage": "node ./dist/scripts/prune-storage.js",
"optimize-old-videos": "node ./dist/scripts/optimize-old-videos.js",
"postinstall": "cd client && yarn install --pure-lockfile",
"tsc": "tsc",
"spectacle-docs": "node_modules/spectacle-docs/bin/spectacle.js",
"commander": "commander",
"ng": "ng",
"nodemon": "nodemon",
@ -72,13 +70,21 @@
},
"husky": {
"hooks": {
"pre-commit": "lint-staged && ./scripts/openapi-peertube-version.sh"
"pre-commit": "./scripts/openapi-peertube-version.sh && lint-staged"
}
},
"lint-staged": {
"*.scss": [
"sass-lint -c client/.sass-lint.yml",
"git add"
],
"support/doc/api/*.yaml": [
"node ./node_modules/swagger-cli/bin/swagger-cli.js validate support/doc/api/openapi.yaml",
"git add"
],
"server/tools/README.md": [
"npm run generate-cli-doc",
"git add"
]
},
"resolutions": {
@ -200,8 +206,8 @@
"nodemon": "^1.11.0",
"sass-lint": "^1.12.1",
"source-map-support": "^0.5.0",
"spectacle-docs": "^1.0.2",
"supertest": "^3.0.0",
"swagger-cli": "^2.2.0",
"ts-node": "7.0.1",
"tslint": "^5.7.0",
"tslint-config-standard": "^8.0.1",

View File

@ -1,5 +0,0 @@
#!/bin/sh
set -eu
npm run spectacle-docs -- -t support/doc/api/html support/doc/api/openapi.yaml

View File

@ -1,7 +0,0 @@
parameters:
name:
name: name
in: path
required: true
type: string
description: 'The name of the account (chocobozzz or chocobozzz@peertube.cpy.re for example)'

View File

@ -1,23 +0,0 @@
parameters:
start:
name: start
in: query
required: false
type: number
description: 'Offset'
count:
name: count
in: query
required: false
type: number
description: 'Number of items'
sort:
name: sort
in: query
required: false
type: string
description: 'Sort column (-createdAt for example)'
responses:
emptySuccess:
description: 'Successful operation'

File diff suppressed because it is too large Load Diff

View File

@ -1,242 +0,0 @@
$(function() {
// $(document).foundation();
var $sidebar = $('#sidebar');
if ($sidebar.length) {
var $docs = $('#docs');
var $nav = $sidebar.find('nav');
//
// Setup sidebar navigation
var traverse = new Traverse($nav, {
threshold: 10,
barOffset: $sidebar.position().top
});
$nav.on('update.traverse', function(event, element) {
$nav.find('section').removeClass('expand');
var $section = element.parents('section:first');
if ($section.length) {
$section.addClass('expand');
}
});
//
// Bind the drawer layout
var $drawerLayout = $('.drawer-layout'),
$drawer = $drawerLayout.find('.drawer'),
closeDrawer = function() {
$drawer.removeClass('slide-right slide-left');
$drawer.find('.drawer-overlay').remove();
$drawerLayout.removeClass('drawer-open drawer-slide-left-large drawer-slide-right-large');
return false;
};
// Drawer open buttons
$drawerLayout.find('[data-drawer-slide]').click(function(e) {
var $this = $(this),
direction = $this.data('drawer-slide');
$drawerLayout.addClass('drawer-open');
$drawer.addClass('slide-' + direction);
var $overlay = $('<a href="#" class="drawer-overlay"></a>')
$drawer.append($overlay);
$overlay.click(closeDrawer);
return false;
});
// Drawer close buttons
$drawerLayout.find('[data-drawer-close]').click(closeDrawer);
}
});
/**
* Creates a new instance of Traverse.
* @class
* @fires Traverse#init
* @param {Object} element - jQuery object to add the trigger to.
* @param {Object} options - Overrides to the default plugin settings.
*/
function Traverse(element, options) {
this.$element = element;
this.options = $.extend({}, Traverse.defaults, this.$element.data(), options);
this._init();
}
/**
* Default settings for plugin
*/
Traverse.defaults = {
/**
* Amount of time, in ms, the animated scrolling should take between locations.
* @option
* @example 500
*/
animationDuration: 500,
/**
* Animation style to use when scrolling between locations.
* @option
* @example 'ease-in-out'
*/
animationEasing: 'linear',
/**
* Number of pixels to use as a marker for location changes.
* @option
* @example 50
*/
threshold: 50,
/**
* Class applied to the active locations link on the traverse container.
* @option
* @example 'active'
*/
activeClass: 'active',
/**
* Allows the script to manipulate the url of the current page, and if supported, alter the history.
* @option
* @example true
*/
deepLinking: false,
/**
* Number of pixels to offset the scroll of the page on item click if using a sticky nav bar.
* @option
* @example 25
*/
barOffset: 0
};
/**
* Initializes the Traverse plugin and calls functions to get equalizer functioning on load.
* @private
*/
Traverse.prototype._init = function() {
var id = this.$element[0].id, // || Foundation.GetYoDigits(6, 'traverse'),
_this = this;
this.$targets = $('[data-traverse-target]');
this.$links = this.$element.find('a');
this.$element.attr({
'data-resize': id,
'data-scroll': id,
'id': id
});
this.$active = $();
this.scrollPos = parseInt(window.pageYOffset, 10);
this._events();
};
/**
* Calculates an array of pixel values that are the demarcation lines between locations on the page.
* Can be invoked if new elements are added or the size of a location changes.
* @function
*/
Traverse.prototype.calcPoints = function(){
var _this = this,
body = document.body,
html = document.documentElement;
this.points = [];
this.winHeight = Math.round(Math.max(window.innerHeight, html.clientHeight));
this.docHeight = Math.round(Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight));
this.$targets.each(function(){
var $tar = $(this),
pt = $tar.offset().top; // Math.round($tar.offset().top - _this.options.threshold);
$tar.targetPoint = pt;
_this.points.push(pt);
});
};
/**
* Initializes events for Traverse.
* @private
*/
Traverse.prototype._events = function() {
var _this = this,
$body = $('html, body'),
opts = {
duration: _this.options.animationDuration,
easing: _this.options.animationEasing
};
$(window).one('load', function(){
_this.calcPoints();
_this._updateActive();
$(this).resize(function(e) {
_this.reflow();
}).scroll(function(e) {
_this._updateActive();
});
})
this.$element.on('click', 'a[href^="#"]', function(e) { //'click.zf.traverse'
e.preventDefault();
var arrival = this.getAttribute('href').replace(".", "\\."),
scrollPos = $(arrival).offset().top - _this.options.barOffset; // - _this.options.threshold / 2 - _this.options.barOffset;
$body.stop(true).animate({
scrollTop: scrollPos
}, opts);
});
};
/**
* Calls necessary functions to update Traverse upon DOM change
* @function
*/
Traverse.prototype.reflow = function(){
this.calcPoints();
this._updateActive();
};
/**
* Updates the visibility of an active location link,
* and updates the url hash for the page, if deepLinking enabled.
* @private
* @function
* @fires Traverse#update
*/
Traverse.prototype._updateActive = function(){
var winPos = parseInt(window.pageYOffset, 10),
curIdx;
if(winPos + this.winHeight === this.docHeight){ curIdx = this.points.length - 1; }
else if(winPos < this.points[0]){ curIdx = 0; }
else{
var isDown = this.scrollPos < winPos,
_this = this,
curVisible = this.points.filter(function(p, i){
return isDown ?
p <= (winPos + _this.options.barOffset + _this.options.threshold) :
(p - (_this.options.barOffset + _this.options.threshold)) <= winPos;
// p <= (winPos - (offset - _this.options.threshold)) :
// (p - (-offset + _this.options.threshold)) <= winPos;
});
curIdx = curVisible.length ? curVisible.length - 1 : 0;
}
var $prev = this.$active;
var $next = this.$links.eq(curIdx);
this.$active.removeClass(this.options.activeClass);
this.$active = $next.addClass(this.options.activeClass);
if(this.options.deepLinking){
var hash = this.$active[0].getAttribute('href');
if(window.history.pushState){
window.history.pushState(null, null, hash);
}else{
window.location.hash = hash;
}
}
this.scrollPos = winPos;
// Fire event if the active element was changed
var changed = $prev[0] !== $next[0];
if (changed) {
this.$element.trigger('update.traverse', [this.$active]);
}
};

View File

@ -1 +0,0 @@
function Traverse(t,e){this.$element=t,this.options=$.extend({},Traverse.defaults,this.$element.data(),e),this._init()}$(function(){var t=$("#sidebar");if(t.length){$("#docs");var s=t.find("nav");new Traverse(s,{threshold:10,barOffset:t.position().top});s.on("update.traverse",function(t,e){s.find("section").removeClass("expand");var i=e.parents("section:first");i.length&&i.addClass("expand")});var a=$(".drawer-layout"),n=a.find(".drawer"),r=function(){return n.removeClass("slide-right slide-left"),n.find(".drawer-overlay").remove(),a.removeClass("drawer-open drawer-slide-left-large drawer-slide-right-large"),!1};a.find("[data-drawer-slide]").click(function(t){var e=$(this).data("drawer-slide");a.addClass("drawer-open"),n.addClass("slide-"+e);var i=$('<a href="#" class="drawer-overlay"></a>');return n.append(i),i.click(r),!1}),a.find("[data-drawer-close]").click(r)}}),Traverse.defaults={animationDuration:500,animationEasing:"linear",threshold:50,activeClass:"active",deepLinking:!1,barOffset:0},Traverse.prototype._init=function(){var t=this.$element[0].id;this.$targets=$("[data-traverse-target]"),this.$links=this.$element.find("a"),this.$element.attr({"data-resize":t,"data-scroll":t,id:t}),this.$active=$(),this.scrollPos=parseInt(window.pageYOffset,10),this._events()},Traverse.prototype.calcPoints=function(){var i=this,t=document.body,e=document.documentElement;this.points=[],this.winHeight=Math.round(Math.max(window.innerHeight,e.clientHeight)),this.docHeight=Math.round(Math.max(t.scrollHeight,t.offsetHeight,e.clientHeight,e.scrollHeight,e.offsetHeight)),this.$targets.each(function(){var t=$(this),e=t.offset().top;t.targetPoint=e,i.points.push(e)})},Traverse.prototype._events=function(){var s=this,a=$("html, body"),n={duration:s.options.animationDuration,easing:s.options.animationEasing};$(window).one("load",function(){s.calcPoints(),s._updateActive(),$(this).resize(function(t){s.reflow()}).scroll(function(t){s._updateActive()})}),this.$element.on("click",'a[href^="#"]',function(t){t.preventDefault();var e=this.getAttribute("href").replace(".","\\."),i=$(e).offset().top-s.options.barOffset;a.stop(!0).animate({scrollTop:i},n)})},Traverse.prototype.reflow=function(){this.calcPoints(),this._updateActive()},Traverse.prototype._updateActive=function(){var t,i=parseInt(window.pageYOffset,10);if(i+this.winHeight===this.docHeight)t=this.points.length-1;else if(i<this.points[0])t=0;else{var s=this.scrollPos<i,a=this,e=this.points.filter(function(t,e){return s?t<=i+a.options.barOffset+a.options.threshold:t-(a.options.barOffset+a.options.threshold)<=i});t=e.length?e.length-1:0}var n=this.$active,r=this.$links.eq(t);if(this.$active.removeClass(this.options.activeClass),this.$active=r.addClass(this.options.activeClass),this.options.deepLinking){var o=this.$active[0].getAttribute("href");window.history.pushState?window.history.pushState(null,null,o):window.location.hash=o}this.scrollPos=i,n[0]!==r[0]&&this.$element.trigger("update.traverse",[this.$active])};

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +0,0 @@
parameters:
id:
name: id
in: path
required: true
type: number
description: 'The user id'

View File

@ -1,7 +0,0 @@
parameters:
id:
name: id
in: path
required: true
type: string
description: 'The video channel id or uuid'

View File

@ -1,13 +0,0 @@
parameters:
threadId:
name: threadId
in: path
required: true
type: number
description: 'The thread id (root comment id)'
commentId:
name: threadId
in: path
required: true
type: number
description: 'The comment id'

View File

@ -1,87 +0,0 @@
parameters:
id:
name: id
in: path
required: true
type: string
description: 'The video id or uuid'
thumbnailfile:
name: thumbnailfile
in: formData
type: file
description: 'Video thumbnail file'
previewfile:
name: previewfile
in: formData
type: file
description: 'Video preview file'
category:
name: category
in: formData
type: number
description: 'Video category'
licence:
name: licence
in: formData
type: number
description: 'Video licence'
language:
name: language
in: formData
type: string
description: 'Video language'
description:
name: description
in: formData
type: string
description: 'Video description'
waitTranscoding:
name: waitTranscoding
in: formData
type: boolean
description: 'Whether or not we wait transcoding before publish the video'
support:
name: support
in: formData
type: string
description: 'Text describing how to support the video uploader'
nsfw:
name: nsfw
in: formData
type: boolean
description: 'Whether or not this video contains sensitive content'
name:
name: name
in: formData
type: string
description: 'Video name'
tags:
name: tags
in: formData
type: string[]
description: 'Video tags'
commentsEnabled:
name: commentsEnabled
in: formData
type: boolean
description: 'Enable or disable comments for this video'
privacy:
name: privacy
in: formData
type: string
enum: [Public, Unlisted]
description: 'Video privacy'
scheduleUpdate:
name: scheduleUpdate
in: formData
required: false
description: 'Schedule an update at a specific datetime'
properties:
updateAt:
type: dateTime
description: 'When to update the video'
required: true
privacy:
type: string
enum: [Public, Unlisted]
description: 'Video privacy target'

View File

@ -41,18 +41,18 @@ Uses [JavaScript Standard Style](http://standardjs.com/).
The server is composed by:
* a REST API (Express framework)
* a WebTorrent Tracker
* a REST API (relying on the Express framework) documented on http://docs.joinpeertube.org/api.html
* a WebTorrent Tracker (slightly custom version of [webtorrent/bittorrent-tracker](https://github.com/webtorrent/bittorrent-tracker#server))
A video is seeded by the server with the [WebSeed](http://www.bittorrent.org/beps/bep_0019.html) protocol (HTTP).
![Architecture scheme](/support/doc/development/server/upload-video.png)
When a user uploads a video, the rest API create the torrent file and then adds it to its database.
When a user uploads a video, the REST API creates the torrent file and then adds it to its database.
If a user wants to watch the video, the tracker will indicate all other users that are watching the video + the HTTP url for the WebSeed.
## Newcomers
The server entrypoint is [server.ts](/server.ts). You can begin to look at this file.
Then you can try to understand the [controllers](/server/controllers): they are the entrypoint of each API request.
The server entrypoint is [server.ts](/server.ts). Looking at this file is a good start.
Then you can try to understand the [controllers](/server/controllers): they are the entrypoints of each API request.

1795
yarn.lock

File diff suppressed because it is too large Load Diff