2018-08-29 01:57:18 +02:00
"use strict" ;
2018-10-01 22:47:10 +02:00
2018-11-30 21:46:22 +01:00
// I M P O R T S
2018-10-01 22:47:10 +02:00
2018-08-29 18:58:55 +02:00
import asyncHtml from "choo-async/html" ;
2018-08-29 01:57:18 +02:00
import dedent from "dedent" ;
2019-01-08 18:25:34 +01:00
import got from "got" ;
2018-10-01 22:47:10 +02:00
2018-10-10 19:56:35 +02:00
// U T I L S
2018-08-29 01:57:18 +02:00
2019-04-12 22:17:39 +02:00
import headerBlockchain from "~component/api/header-blockchain" ;
import headerSdk from "~component/api/header-sdk" ;
import redirects from "~data/redirects.json" ;
2018-11-30 21:46:22 +01:00
2019-04-22 21:49:00 +02:00
const blockchainApi = "https://raw.githubusercontent.com/lbryio/lbrycrd/master/contrib/devtools/generated/api_v1.json" ;
2019-04-16 21:52:51 +02:00
const cache = new Map ( ) ;
2019-04-22 21:49:00 +02:00
const sdkApi = "https://raw.githubusercontent.com/lbryio/lbry/master/docs/api.json" ;
2018-10-01 22:47:10 +02:00
// E X P O R T
2018-08-29 01:57:18 +02:00
2018-11-30 21:46:22 +01:00
export default async ( state ) => {
2019-02-15 17:50:56 +01:00
// below is evil, I just inherited it -- Jeremy
2019-04-12 21:08:35 +02:00
const apilabel = state . params . wildcard === "sdk" ?
"SDK" :
state . params . wildcard . charAt ( 0 ) . toLocaleUpperCase ( ) + state . params . wildcard . substring ( 1 ) ;
2019-02-15 17:50:56 +01:00
state . lbry = {
title : apilabel + " API Documentation" ,
description : "See API documentation, signatures, and sample calls for the LBRY " + apilabel + " APIs."
} ;
2018-11-30 21:46:22 +01:00
try {
const apiResponse = await parseApiFile ( state . params . wildcard ) ;
return asyncHtml `
< div class = "__slate" >
2019-01-30 23:15:10 +01:00
< aside class = "api-toc" >
< div class = "api-toc__search" >
< input class = "api-toc__search-field" id = "input-search" placeholder = "Search" type = "search" / >
< div class = "api-toc__search-clear" id = "clear-search" title = "Clear search query" > & times ; < / d i v >
< ul class = "api-toc__search-results" > < / u l >
2018-11-30 21:46:22 +01:00
< / d i v >
2019-04-12 21:08:35 +02:00
< ul class = "api-toc__commands" id = "toc" role = "navigation" >
$ { apilabel === "SDK" ? createSdkSidebar ( apiResponse ) : createApiSidebar ( apiResponse ) }
< / u l >
2018-11-30 21:46:22 +01:00
< / a s i d e >
2019-01-30 23:15:10 +01:00
< section class = "api-content" >
< div class = "api-documentation" id = "toc-content" >
2019-02-20 00:42:52 +01:00
< div > < / d i v >
2019-01-30 23:15:10 +01:00
< nav class = "api-content__items" >
2019-05-10 00:37:52 +02:00
$ { renderToggles ( apilabel === "SDK" ) }
2019-01-30 23:15:10 +01:00
< / n a v >
$ { createApiHeader ( state . params . wildcard ) }
2019-04-12 21:08:35 +02:00
$ { apilabel === "SDK" ? createSdkContent ( apiResponse ) : createApiContent ( apiResponse ) }
2018-11-30 21:46:22 +01:00
< / d i v >
< / s e c t i o n >
< / d i v >
< script src = "/assets/scripts/plugins/jets.js" > < / s c r i p t >
< script src = "/assets/scripts/api.js" > < / s c r i p t >
2019-01-30 23:15:10 +01:00
< script >
2019-05-10 00:37:52 +02:00
if ( window . location . pathname === "/api/blockchain" )
document . getElementById ( "toggle-cli" ) . click ( ) ;
else
document . getElementById ( "toggle-curl" ) . click ( ) ;
2019-01-30 23:15:10 +01:00
< / s c r i p t >
2018-11-30 21:46:22 +01:00
` ;
}
2019-01-08 18:25:34 +01:00
catch ( error ) {
2018-10-06 22:53:01 +02:00
const redirectUrl = redirects [ state . href ] ;
2018-08-29 01:57:18 +02:00
2018-10-06 22:53:01 +02:00
return asyncHtml `
2018-10-06 22:59:46 +02:00
< article class = "page" itemtype = "http://schema.org/BlogPosting" >
< header class = "page__header" >
< div class = "page__header-wrap" >
< div class = "inner-wrap" >
< h1 class = "page__header__title" itemprop = "name headline" > 404 < / h 1 >
< / d i v >
2018-10-01 22:47:10 +02:00
< / d i v >
2018-10-06 22:59:46 +02:00
< / h e a d e r >
2018-08-29 01:57:18 +02:00
2018-10-06 22:59:46 +02:00
< section class = "page__content page__markup" itemprop = "articleBody" >
< div class = "inner-wrap" >
< p > Redirecting you to < strong > $ { redirectUrl } < / s t r o n g > < / p >
< / d i v >
< / s e c t i o n >
< / a r t i c l e >
< script >
setTimeout ( ( ) => {
window . location . href = "${redirectUrl}" ;
} , 2000 ) ;
< / s c r i p t >
` ;
2018-11-30 21:46:22 +01:00
}
} ;
2018-09-30 19:34:29 +02:00
2018-08-29 01:57:18 +02:00
2018-10-01 22:47:10 +02:00
// H E L P E R S
2018-10-01 06:40:24 +02:00
2018-08-29 01:57:18 +02:00
function createApiContent ( apiDetails ) {
const apiContent = [ ] ;
2019-05-10 00:37:52 +02:00
apiDetails . forEach ( apiDetail => {
2018-08-29 01:57:18 +02:00
let apiDetailsReturns = "" ;
2018-10-06 22:53:01 +02:00
2018-11-30 21:46:22 +01:00
if ( apiDetail . returns )
apiDetailsReturns = JSON . parse ( JSON . stringify ( apiDetail . returns ) ) ;
2018-08-29 01:57:18 +02:00
apiContent . push ( `
2019-01-30 23:15:10 +01:00
< div class = "api-content__body" >
2018-08-29 01:57:18 +02:00
< h2 id = "${apiDetail.name}" > $ { apiDetail . name } < / h 2 >
< p > $ { apiDetail . description } < / p >
2019-01-30 23:15:10 +01:00
$ { apiDetail . arguments . length ? ` <h3>Arguments</h3><ul class="api-content__body-arguments"> ${ renderArguments ( apiDetail . arguments ) . join ( "" ) } </ul> ` : "" }
2019-05-10 00:37:52 +02:00
$ { apiDetail . returns ? ` <h3>Returns</h3><pre><code> ${ dedent ( apiDetailsReturns ) } </code></pre> ` : "" }
2018-08-29 01:57:18 +02:00
< / d i v >
2019-01-30 23:15:10 +01:00
< div class = "api-content__example" >
$ { apiDetail . examples && apiDetail . examples . length ? renderExamples ( apiDetail . examples ) . join ( "" ) : ` <pre><code>// example(s) for ${ apiDetail . name } to come later</code></pre> ` }
2018-08-29 01:57:18 +02:00
< / d i v >
` );
2019-05-10 00:37:52 +02:00
} ) ;
2018-08-29 01:57:18 +02:00
return apiContent ;
}
2018-10-01 22:47:10 +02:00
function createApiHeader ( slug ) {
switch ( slug ) {
case "blockchain" :
return headerBlockchain ( ) ;
case "sdk" :
return headerSdk ( ) ;
default :
break ;
}
}
2018-08-29 01:57:18 +02:00
function createApiSidebar ( apiDetails ) {
const apiSidebar = [ ] ;
2019-05-10 00:37:52 +02:00
apiDetails . forEach ( apiDetail => {
2018-08-29 01:57:18 +02:00
apiSidebar . push ( `
2019-04-12 21:08:35 +02:00
< li class = "api-toc__command" >
2018-08-29 01:57:18 +02:00
< a href = "#${apiDetail.name}" title = "Go to ${apiDetail.name} section" >
$ { apiDetail . name }
< / a >
< / l i >
` );
2019-05-10 00:37:52 +02:00
} ) ;
2018-08-29 01:57:18 +02:00
return apiSidebar ;
}
2019-04-12 21:08:35 +02:00
function createSdkContent ( apiDetails ) {
const apiContent = [ ] ;
const sectionTitles = Object . keys ( apiDetails ) ;
2019-05-10 00:37:52 +02:00
sectionTitles . forEach ( title => {
2019-04-12 21:08:35 +02:00
const commands = apiDetails [ title ] . commands ;
const description = apiDetails [ title ] . doc ;
apiContent . push (
commands . length ?
commands . map ( command => createSdkContentSections ( title , description , command ) ) . join ( "" ) :
""
) ;
2019-05-10 00:37:52 +02:00
} ) ;
2019-04-12 21:08:35 +02:00
return apiContent ;
}
function createSdkContentSections ( sectionTitle , sectionDescription , sectionDetails ) {
return `
< div class = "api-content__body" >
< h2 id = "${sectionDetails.name}" > $ { sectionDetails . name } < / h 2 >
< p > $ { sectionDetails . description } < / p >
< h3 > Arguments < / h 3 >
< ul class = "api-content__body-arguments" >
$ { renderArguments ( sectionDetails . arguments ) . join ( "" ) }
< / u l >
< h3 > Returns < / h 3 >
< pre > < code > $ { renderReturns ( sectionDetails . returns ) } < / c o d e > < / p r e >
< / d i v >
< div class = "api-content__example" >
$ { renderExamples ( sectionDetails . examples ) . join ( "" ) }
< / d i v >
` ;
}
function createSdkSidebar ( apiDetails ) {
const sectionTitles = Object . keys ( apiDetails ) ;
const apiSidebar = [ ] ;
2019-05-10 00:37:52 +02:00
sectionTitles . forEach ( title => {
2019-04-12 21:08:35 +02:00
const commands = apiDetails [ title ] . commands ;
apiSidebar . push ( `
< ul class = "api-toc__section" >
< li class = "api-toc__title" > $ { title } < / l i >
$ { ( commands . map ( command => ` <li class="api-toc__command"><a href="# ${ command . name } " title="Go to ${ command . name } section"> ${ command . name } </a></li> ` ) ) . join ( "" ) }
< / u l >
` );
2019-05-10 00:37:52 +02:00
} ) ;
2019-04-12 21:08:35 +02:00
return apiSidebar ;
}
2019-01-08 18:25:34 +01:00
async function parseApiFile ( urlSlug ) {
2018-08-29 01:57:18 +02:00
let apiFileLink ;
2018-10-01 22:47:10 +02:00
switch ( true ) {
case ( urlSlug === "blockchain" ) :
2018-12-12 19:32:05 +01:00
apiFileLink = blockchainApi ;
2018-10-01 22:47:10 +02:00
break ;
2018-08-29 01:57:18 +02:00
2018-10-01 22:47:10 +02:00
case ( urlSlug === "sdk" ) :
2018-12-12 19:32:05 +01:00
apiFileLink = sdkApi ;
2018-10-01 22:47:10 +02:00
break ;
default :
break ;
}
2018-08-29 01:57:18 +02:00
2019-01-08 18:25:34 +01:00
if ( ! apiFileLink )
return Promise . reject ( new Error ( "Failed to fetch API docs" ) ) ;
2019-04-16 21:52:51 +02:00
const response = await got ( apiFileLink , { cache , json : true } ) ;
2019-01-08 18:25:34 +01:00
try {
return response . body ;
} catch ( error ) {
return "Issue loading API documentation" ;
}
2018-08-29 01:57:18 +02:00
}
function renderArguments ( args ) {
const argumentContent = [ ] ;
2019-04-12 21:08:35 +02:00
if ( ! args || args . length === 0 )
return argumentContent ;
2019-05-10 00:37:52 +02:00
args . forEach ( arg => {
2018-08-29 01:57:18 +02:00
argumentContent . push ( `
2019-01-30 23:15:10 +01:00
< li class = "api-content__body-argument" >
2018-08-29 01:57:18 +02:00
< div class = "left" >
< strong > $ { arg . name } < /strong><br/ >
$ { arg . is _required === true ? "" : "<span>optional</span>" } < span > $ { arg . type } < / s p a n >
< / d i v >
< div class = "right" > $ { typeof arg . description === "string" ? arg . description . replace ( /</g , "<" ) . replace ( />/g , ">" ) : "" } < / d i v >
< / l i >
` );
2019-05-10 00:37:52 +02:00
} ) ;
2018-08-29 01:57:18 +02:00
return argumentContent ;
}
2019-01-30 23:15:10 +01:00
function renderExamples ( args ) {
const exampleContent = [ ] ;
2019-04-12 21:08:35 +02:00
if ( ! args || args . length === 0 ) {
exampleContent . push ( "<pre><code>// example(s) to come later</code></pre>" ) ;
return exampleContent ;
}
2019-05-10 00:37:52 +02:00
args . forEach ( arg => {
2019-01-30 23:15:10 +01:00
exampleContent . push ( `
2019-05-10 00:37:52 +02:00
$ { arg . title ? ` <h3> ${ arg . title } </h3><br/> ` : "" }
$ { arg . cli ? ` <pre data-api-example-type="cli"><code> ${ arg . cli } </code></pre> ` : "" }
$ { arg . curl ? ` <pre data-api-example-type="curl"><code> ${ arg . curl } </code></pre> ` : "" }
$ { arg . lbrynet ? ` <pre data-api-example-type="lbrynet"><code> ${ arg . lbrynet } </code></pre> ` : "" }
$ { arg . python ? ` <pre data-api-example-type="python"><code> ${ arg . python } </code></pre> ` : "" }
$ { arg . output ? `
< h3 > Output < /h3><br/ >
< pre > < code > $ { arg . output } < / c o d e > < / p r e >
< hr / >
` : ""}
2019-01-30 23:15:10 +01:00
` );
2019-05-10 00:37:52 +02:00
} ) ;
2019-01-30 23:15:10 +01:00
return exampleContent ;
}
2019-04-12 21:08:35 +02:00
function renderReturns ( args ) {
let returnContent = [ ] ;
if ( ! args || args . length === 0 )
return returnContent ;
returnContent = dedent ( JSON . parse ( JSON . stringify ( args ) ) ) ;
return returnContent ;
}
2019-05-10 00:37:52 +02:00
function renderToggles ( onSdkPage ) {
return [
2019-05-14 21:40:35 +02:00
"<button class='api-content__item menu' id='toggle-menu'>menu</button>" ,
2019-05-10 00:37:52 +02:00
! onSdkPage ? "<button class='api-content__item' id='toggle-cli' type='button'>cli</button>" : "" ,
"<button class='api-content__item' id='toggle-curl' type='button'>curl</button>" ,
onSdkPage ? "<button class='api-content__item' id='toggle-lbrynet' type='button'>lbrynet</button>" : "" ,
onSdkPage ? "<button class='api-content__item' id='toggle-python' type='button'>python</button>" : ""
] ;
}