1
0
mirror of https://github.com/oceanprotocol/docs.git synced 2024-11-01 15:55:34 +01:00

Merge branch 'master' into publish-data-set-react

This commit is contained in:
Troy McConaghy 2018-12-05 12:21:58 +01:00 committed by GitHub
commit 9d221294e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 1607 additions and 141 deletions

View File

@ -2,7 +2,7 @@
<h1 align="center">docs</h1>
> 🐍 Ocean Protocol's official documentation.
> 🐍 Ocean Protocol's official documentation. https://docs.oceanprotocol.com
[![Build Status](https://travis-ci.com/oceanprotocol/docs.svg?token=3psqw6c8KMDqfdGQ2x6d&branch=master)](https://travis-ci.com/oceanprotocol/docs)
[![code style: prettier](https://img.shields.io/badge/code_style-prettier-7b1173.svg?style=flat-square)](https://github.com/prettier/prettier)
@ -27,6 +27,9 @@
- [Repositories](#repositories)
- [Add Links to a Repository](#add-links-to-a-repository)
- [Release Versions](#release-versions)
- [API & Library References](#api--library-references)
- [Swagger specs](#swagger-specs)
- [TypeDoc specs](#typedoc-specs)
- [Development](#development)
- [Using npm](#using-npm)
- [Using Docker](#using-docker)
@ -186,6 +189,33 @@ The GitHub link is automatically added for every repository and will always be d
The displayed version number is based on the tag name of the latest release for a given repository. That means only GitHub releases will trigger a version number update, creating a new Git tag alone is not sufficient.
### API & Library References
You can add more Markdown documents under `/content/references/`, link to them from the [`/data/sidebars/references.yml`](./data/sidebars/references.yml), and they will appear just like in all the other sections.
But the actual reference pages in this section are constructed from data files during site build (as defined in [`gatsby-node.js`](./gatsby-node.js)) with their own little rules. Generally, you can't edit their content within this site, you have to go to the respective repository and edit the documentation strings living with the source code.
The sidebar for those generated reference pages will automatically switch to include the table of contents of those pages so no need to define additional links in the [`/data/sidebars/references.yml`](./data/sidebars/references.yml) file for them.
#### Swagger specs
Reference pages based on Swagger specs are sourced from a Swagger spec `json` file, at the moment they simply live as manual copies under `/data/`:
- [`aquarius.json`](./data/aquarius.json)
- [`brizo.json`](./data/brizo.json)
There's no automation setup around updating those files so [until this is setup](https://github.com/oceanprotocol/docs/issues/74), they need to be manually updated with copy & paste, like they did in the middle ages. You can copy them from a running instance of Aquarius or Brizo which will expose those spec files, e.g. under `localhost:5000/spec` for Aquarius and `localhost:8030/spec` for Brizo.
For more information about stylistic issues, take a look at the section in the test page:
- [Swagger spec references](https://docs.oceanprotocol.com/test#swagger-spec-references)
#### TypeDoc specs
Reference pages based on generated `json` file from TypeDoc.
_Coming soon... see [#45](https://github.com/oceanprotocol/docs/issues/45)_
## Development
The site is a React app built with [Gatsby](https://www.gatsbyjs.org).
@ -198,8 +228,8 @@ This Git repo has [Git submodules](https://git-scm.com/book/en/v2/Git-Tools-Subm
git clone --recurse-submodules git@github.com:oceanprotocol/docs.git
```
1. Don't edit anything in the submodules (i.e. in `external/`). Instead, edit it over in the other Git repository and merge your changes over there.
1. Get all the submodules up-to-date using:
2. Don't edit anything in the submodules (i.e. in `external/`). Instead, edit it over in the other Git repository and merge your changes over there.
3. Get all the submodules up-to-date using:
```bash
git submodule update --remote --recursive
@ -207,7 +237,7 @@ This Git repo has [Git submodules](https://git-scm.com/book/en/v2/Git-Tools-Subm
That will get each submodule up-to-date with the HEAD commit of some branch in a remote repository. Which branch? That's set in the `.gitmodules` file. You can check the current commit hashes of all the submodules using `git submodule status`
1. Before doing any `git checkout ...` or other normal Git operations, do this:
4. Before doing any `git checkout ...` or other normal Git operations, do this:
```bash
git config --global submodule.recurse true

View File

@ -31,6 +31,10 @@ module.exports = {
{
from: '/tutorials/',
to: '/tutorials/introduction/'
},
{
from: '/references/',
to: '/references/introduction/'
}
]
}

View File

@ -11,16 +11,12 @@ The [Kovan Testnet](https://github.com/kovan-testnet/proposal) (or just "Kovan")
Moreover, there is a [Secret Store](/concepts/components/#secret-store) operated by the Ocean Protocol Foundation which is connected to the Kovan Testnet: the Ocean Secret Store for Kovan.
There's a [tutorial about how to get set up to use a testnet](/tutorials/use-a-testnet/).
## Ocean Testnet
The Ocean Testnet (also called the Ocean POA Testnet) is similar to the Kovan Testnet, except all the nodes are operated by the Ocean Protocol Foundation. The Ocean Protocol [keeper contracts](https://github.com/oceanprotocol/keeper-contracts) (smart contracts) are deployed there.
Moreover, there is a [Secret Store](/concepts/components/#secret-store) operated by the Ocean Protocol Foundation which is connected to the Ocean Testnet: the Ocean Secret Store.
For now, there's no easy way to get Ether for the Ocean Testnet, so we recommend using the Kovan Testnet (for now).
## Technical Details about the Public Testnets
- [Details about the Ocean Testnet](https://github.com/oceanprotocol/dev-ocean/blob/master/doc/devops/secret-store-cluster.md) (which is called the "Parity Secret Store Cluster" on that page).

View File

@ -0,0 +1,19 @@
---
title: API & Library References
description: All the references for Ocean Protocol components.
---
**Heads Up! This reference section is in heavy development and updated as we integrate data from various code reference tools into this site.**
The following components expose a consumable REST API which are documented on this site:
<repo name="aquarius"></repo>
<repo name="brizo"></repo>
Those are sourced from their respective Swagger specs. On this site you can't execute the documented API calls yet. If you need this, you can run a component's local Swagger UI as outlined in the repository instructions on GitHub.
References of all the functions and methods used in our libraries are not yet integrated here. For now, have a look at the respective repos for more infos:
<repo name="squid-js"></repo>
<repo name="squid-py"></repo>
<repo name="squid-java"></repo>

View File

@ -366,3 +366,14 @@ GITHUB-EMBED https://github.com/oceanprotocol/squid-js/blob/develop/src/keeper/W
Resulting in:
GITHUB-EMBED https://github.com/oceanprotocol/squid-js/blob/develop/src/keeper/Web3Provider.ts js GITHUB-EMBED
## Swagger spec references
Many Swagger fields like the description (`info.description`) are rendered through Markdown so you can write actual Markdown in those fields.
- [Aquarius API reference](/references/aquarius/)
- [Brizo API reference](/references/brizo/)
For a complete overview of everything supported by Swagger and implemented in this site, take a look at the hidden Pet Store example:
- [Pet Store Example](/references/pet-store/)

View File

@ -0,0 +1,51 @@
---
title: Get Ether and Ocean Tokens for Testnets
description: A tutorial about how to get Ether and Ocean Tokens for testnets.
---
If you want to interact with a testnet, then you'll eventually need Ether or Ocean Tokens _for that testnet_. (Every Ethereum-based network has its own Ether and its own Ocean Tokens, and you can't use those in other networks, or at least it wasn't possible when we wrote this.)
At the time of writing, there were two public testnets you could use to test an Ocean Protocol application: the Kovan Testnet and the Ocean Testnet. For more information about those, see the page about [testnets](/concepts/testnets/). You could also run a local testnet (i.e. on your local machine).
## Get a Compatible Wallet
You will need a wallet that can hold Ether (for any Ethereum network) and Ocean Tokens (for any Ethereum network). For now, we recommend using [MetaMask](https://metamask.io/).
- Follow the MetaMask instructions to install it on your machine.
- In MetaMask, switch from the **Main Ethereum Network** to the **Kovan Test Network** or the test network you're using.
## Get Ether
### Get Ether for the Kovan Testnet
You can get Kovan Ether (KEth), for the Kovan Testnet, from a Kovan faucet: see [the official list of Kovan faucets](https://github.com/kovan-testnet/faucet). You have to give the faucet your Kovan address (wallet account address). You can get that from MetaMask. It's a string that looks like:
```text
0xa0A9d7f78bF293514e7cA2789A0Af689eEC99282
```
### Get Ether for the Ocean Testnet
At the time of writing, there was no easy way to get Ether for the Ocean Testnet.
### Get Ether for a Local Ganache-Based Testnet
If you're running a local Ganache-based testnet, then it creates several accounts at network launch time, and gives each of them some Ether. The addresses and private keys of those accounts should be shared (to logs or the console) during the launch process. You can use those accounts and their Ether.
### Get Ether for a Local Parity-Ethereum-Based Testnet
If you're running a local Parity-Ethereum-based testnet based on [docker-images](https://github.com/oceanprotocol/docker-images), then you can send some Ether to `<YOUR ADDRESS>` using the command:
```bash
curl --data '{"jsonrpc":"2.0","method":"personal_sendTransaction","params":[{"from":"0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e","to":"<YOUR ADDRESS>","value":"0x7FFFFFFFFFFFFFFFFFF"}, "node0"],"id":0}' -H "Content-Type: application/json" -X POST localhost:8545
```
That command uses [Ethereum's JSON RPC API](https://wiki.parity.io/JSONRPC.html). You can also create a new account using the Parity Ethereum CLI. See [the Parity Ethereum CLI documentation](https://wiki.parity.io/CLI-Sub-commands).
## Get Ocean Tokens
One way to get some Ocean Tokens, for the network you're connected to, is by running Pleuston (a demo Ocean marketplace web app) and then clicking in the top right corner of the Pleuston user interface. If you see "Make it rain" then click that.
Running Pleuston, along with all the software it needs to work, is beyond the scope of this tutorial. If you want to do _that_, then the current best option is to use the scripts and Docker Compose files in the [🐳 docker-images repository](https://github.com/oceanprotocol/docker-images).
<repo name="docker-images"></repo>

View File

@ -1,31 +0,0 @@
---
title: How to Use a Testnet
description: A tutorial showing how to get set up to use one of the public testnets.
---
At the time of writing, there were two public testnets you could use to test an Ocean Protocol application: the Kovan Testnet and the Ocean Testnet. For more information about those, see the page about [testnets](/concepts/testnets/). Also at the time of writing, there was no easy was to get Ether for the Ocean Testnet, so this tutorial is for the Kovan Testnet (for now).
## Get a Compatible Wallet
You will need a wallet that can hold Ether (for any Ethereum network) and Ocean Tokens (for any Ethereum network). For now, we recommend using [MetaMask](https://metamask.io/).
- Follow the MetaMask instructions to install it on your machine.
- In MetaMask, switch from the **Main Ethereum Network** to the **Kovan Test Network**.
## Get Kovan Ether (KEth)
You can get Kovan Ether (KEth) from a Kovan faucet: see [the official list of Kovan faucets](https://github.com/kovan-testnet/faucet). You have to give the faucet your Kovan address (wallet account address). You can get that from MetaMask. It's a string that looks like:
```text
0xa0A9d7f78bF293514e7cA2789A0Af689eEC99282
```
## Next Steps
You may want to get some Ocean Tokens for the Kovan Testnet (e.g. so you can buy assets). Currently, the easiest way to get some Ocean Tokens is by running Pleuston (a demo Ocean marketplace web app) and then clicking in the top right corner of the Pleuston user interface. If you see "Make it rain" then click that.
Running Pleuston, along with all the software it needs to work, and configuring everything to work together (and connect to Kovan) is beyond the scope of this tutorial. If you want to do _that_, then the current best option is to use the scripts and Docker Compose files in the [🐳 docker-images repository](https://github.com/oceanprotocol/docker-images).
<repo name="docker-images"></repo>
Note that Kovan Ocean Tokens can't be transferred to or used in other Ethereum networks (or at least it wasn't possible at the time of writing).

532
data/aquarius.json Normal file
View File

@ -0,0 +1,532 @@
{
"basePath":"/api/v1/aquarius",
"definitions":{
},
"host":"myfancyaquarius.com",
"info":{
"description":"Aquarius provides an off-chain database store for metadata about data assets. When running with our Docker images, it is exposed under `http://localhost:5000`.",
"title":"Aquarius",
"version":"0.1.4"
},
"paths":{
"/api/v1/aquarius/assets":{
"get":{
"description":"",
"responses":{
"200":{
"description":"successful action"
}
},
"summary":"Get all asset IDs.",
"tags":[
"ddo"
]
}
},
"/api/v1/aquarius/assets/ddo":{
"get":{
"description":"",
"responses":{
"200":{
"description":"successful action"
}
},
"summary":"Get DDO of all assets.",
"tags":[
"ddo"
]
},
"post":{
"consumes":[
"application/json"
],
"description":"",
"parameters":[
{
"description":"DDO of the asset.",
"in":"body",
"name":"body",
"required":true,
"schema":{
"properties":{
"@context":{
"description":null,
"example":"https://w3id.org/future-method/v1",
"type":"string"
},
"authentication":{
"description":"List of authentication mechanisms.",
"example":[
{
"type":"RsaSignatureAuthentication2018"
},
{
"publicKey":"did:op:123456789abcdefghi#keys-1"
}
],
"type":"array"
},
"id":{
"description":"ID of the asset.",
"example":"did:op:123456789abcdefghi",
"type":"string"
},
"publicKey":{
"description":"List of public keys.",
"example":[
{
"id":"did:op:123456789abcdefghi#keys-1"
},
{
"type":"Ed25519VerificationKey2018"
},
{
"owner":"did:op:123456789abcdefghi"
},
{
"publicKeyBase58":"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
}
],
"type":"array"
},
"service":{
"description":"List of services.",
"example":[
{
"serviceEndpoint":"http://mybrizo.org/api/v1/brizo/services/consume?pubKey=${pubKey}&serviceId={serviceId}&url={url}",
"type":"Consume"
},
{
"serviceEndpoint":"http://mybrizo.org/api/v1/brizo/services/compute?pubKey=${pubKey}&serviceId={serviceId}&algo={algo}&container={container}",
"type":"Compute"
},
{
"metadata":{
"additionalInformation":{
"structuredMarkup":[
{
"mediaType":"application/ld+json",
"uri":"http://skos.um.es/unescothes/C01194/jsonld"
},
{
"mediaType":"text/turtle",
"uri":"http://skos.um.es/unescothes/C01194/turtle"
}
],
"updateFrecuency":"yearly"
},
"base":{
"author":"Met Office",
"compression":"zip",
"contentType":"text/csv",
"contentUrls":[
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip"
],
"copyrightHolder":"Met Office",
"dateCreated":"2012-10-10T17:00:000Z",
"description":"Weather information of UK including temperature and humidity",
"encoding":"UTF-8",
"inLanguage":"en",
"license":"CC-BY",
"links":[
{
"sample1":"http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/"
},
{
"sample2":"http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-averages-25km/"
},
{
"fieldsDescription":"http://data.ceda.ac.uk/badc/ukcp09/"
}
],
"name":"UK Weather information 2011",
"price":10,
"size":"3.1gb",
"tags":"weather, uk, 2011, temperature, humidity",
"type":"dataset",
"workExample":"423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68"
},
"curation":{
"numVotes":123,
"rating":0.93,
"schema":"Binary Votting"
}
},
"serviceEndpoint":"http://myaquarius.org/api/v1/provider/assets/metadata/{did}",
"type":"Metadata"
}
],
"type":"array"
}
},
"required":[
"@context",
"id",
"publicKey",
"authentication",
"service"
],
"type":"object"
}
}
],
"responses":{
"201":{
"description":"Asset successfully registered."
},
"400":{
"description":"One of the required attributes is missing."
},
"404":{
"description":"Invalid asset data."
},
"500":{
"description":"Error"
}
},
"summary":"Register DDO of a new asset",
"tags":[
"ddo"
]
}
},
"/api/v1/aquarius/assets/ddo/query":{
"get":{
"description":"",
"parameters":[
{
"description":"ID of the asset.",
"in":"query",
"name":"text",
"required":true,
"type":"string"
},
{
"description":"Key or list of keys to sort the result",
"example":{
"value":1
},
"in":"query",
"name":"sort",
"type":"object"
},
{
"description":"Number of records per page",
"example":100,
"in":"query",
"name":"offset",
"type":"int"
},
{
"description":"Page showed",
"example":0,
"in":"query",
"name":"page",
"type":"int"
}
],
"responses":{
"200":{
"description":"successful action"
}
},
"summary":"Get a list of DDOs that match with the given text.",
"tags":[
"ddo"
]
},
"post":{
"consumes":[
"application/json"
],
"description":"",
"parameters":[
{
"description":"Asset metadata.",
"in":"body",
"name":"body",
"required":true,
"schema":{
"properties":{
"offset":{
"description":"Number of records per page",
"example":100,
"type":"int"
},
"page":{
"description":"Page showed",
"example":0,
"type":"int"
},
"query":{
"description":"Query to realize",
"example":{
"value":1
},
"type":"string"
},
"sort":{
"description":"Key or list of keys to sort the result",
"example":{
"value":1
},
"type":"object"
}
},
"type":"object"
}
}
],
"responses":{
"200":{
"description":"successful action"
}
},
"summary":"Get a list of DDOs that match with the executed query.",
"tags":[
"ddo"
]
}
},
"/api/v1/aquarius/assets/ddo/{did}":{
"put":{
"consumes":[
"application/json"
],
"description":"",
"parameters":[
{
"description":"DDO of the asset.",
"in":"body",
"name":"body",
"required":true,
"schema":{
"properties":{
"@context":{
"description":null,
"example":"https://w3id.org/future-method/v1",
"type":"string"
},
"authentication":{
"description":"List of authentication mechanisms.",
"example":[
{
"type":"RsaSignatureAuthentication2018"
},
{
"publicKey":"did:op:123456789abcdefghi#keys-1"
}
],
"type":"array"
},
"id":{
"description":"ID of the asset.",
"example":"did:op:123456789abcdefghi",
"type":"string"
},
"publicKey":{
"description":"List of public keys.",
"example":[
{
"id":"did:op:123456789abcdefghi#keys-1"
},
{
"type":"Ed25519VerificationKey2018"
},
{
"owner":"did:op:123456789abcdefghi"
},
{
"publicKeyBase58":"H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
}
],
"type":"array"
},
"service":{
"description":"List of services.",
"example":[
{
"serviceEndpoint":"http://mybrizo.org/api/v1/brizo/services/consume?pubKey=${pubKey}&serviceId={serviceId}&url={url}",
"type":"Consume"
},
{
"serviceEndpoint":"http://mybrizo.org/api/v1/brizo/services/compute?pubKey=${pubKey}&serviceId={serviceId}&algo={algo}&container={container}",
"type":"Compute"
},
{
"metadata":{
"additionalInformation":{
"structuredMarkup":[
{
"mediaType":"application/ld+json",
"uri":"http://skos.um.es/unescothes/C01194/jsonld"
},
{
"mediaType":"text/turtle",
"uri":"http://skos.um.es/unescothes/C01194/turtle"
}
],
"updateFrecuency":"yearly"
},
"base":{
"author":"Met Office",
"compression":"zip",
"contentType":"text/csv",
"contentUrls":[
"https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip"
],
"copyrightHolder":"Met Office",
"dateCreated":"2012-10-10T17:00:000Z",
"description":"Weather information of UK including temperature and humidity",
"encoding":"UTF-8",
"inLanguage":"en",
"license":"CC-BY",
"links":[
{
"name":"Sample of Asset Data",
"type":"sample",
"url":"https://foo.com/sample.csv"
},
{
"AssetID":"4d517500da0acb0d65a716f61330969334630363ce4a6a9d39691026ac7908ea",
"name":"Data Format Definition",
"type":"format"
}
],
"name":"UK Weather information 2011",
"price":10,
"size":"3.1gb",
"tags":"weather, uk, 2011, temperature, humidity",
"type":"dataset",
"workExample":"423432fsd,51.509865,-0.118092,2011-01-01T10:55:11+00:00,7.2,68"
},
"curation":{
"numVotes":123,
"rating":0.93,
"schema":"Binary Voting"
}
},
"serviceEndpoint":"http://myaquarius.org/api/v1/aquarius/assets/metadata/{did}",
"type":"Metadata"
}
],
"type":"array"
}
},
"required":[
"@context",
"id",
"publicKey",
"authentication",
"service"
],
"type":"object"
}
}
],
"responses":{
"200":{
"description":"Asset successfully updated."
},
"201":{
"description":"Asset successfully registered."
},
"400":{
"description":"One of the required attributes is missing."
},
"404":{
"description":"Invalid asset data."
},
"500":{
"description":"Error"
}
},
"summary":"Update DDO of an existing asset",
"tags":[
"ddo"
]
}
},
"/api/v1/aquarius/assets/ddo/{id}":{
"delete":{
"description":"",
"parameters":[
{
"description":"ID of the asset.",
"in":"path",
"name":"id",
"required":true,
"type":"string"
}
],
"responses":{
"200":{
"description":"successfully deleted"
},
"404":{
"description":"This asset ID is not in OceanDB"
},
"500":{
"description":"Error"
}
},
"summary":"Retire metadata of an asset",
"tags":[
"ddo"
]
},
"get":{
"description":"",
"parameters":[
{
"description":"ID of the asset.",
"in":"path",
"name":"id",
"required":true,
"type":"string"
}
],
"responses":{
"200":{
"description":"successful operation"
},
"404":{
"description":"This asset ID is not in OceanDB"
}
},
"summary":"Get DDO of a particular asset.",
"tags":[
"ddo"
]
}
},
"/api/v1/aquarius/assets/metadata/{id}":{
"get":{
"description":"",
"parameters":[
{
"description":"ID of the asset.",
"in":"path",
"name":"id",
"required":true,
"type":"string"
}
],
"responses":{
"200":{
"description":"successful operation."
},
"404":{
"description":"This asset ID is not in OceanDB."
}
},
"summary":"Get metadata of a particular asset",
"tags":[
"metadata"
]
}
}
},
"swagger":"2.0"
}

200
data/brizo.json Normal file
View File

@ -0,0 +1,200 @@
{
"basePath":"/api/v1/brizo",
"definitions":{
},
"host":"myfancybrizo.com",
"info":{
"description":"Brizo is the technical component executed by Publishers allowing them to provide extended data services. When running with our Docker images, it is exposed under `http://localhost:8030`.",
"title":"Brizo",
"version":"0.1.2"
},
"paths":{
"/api/v1/brizo/services/access/initialize":{
"post":{
"consumes":[
"application/json"
],
"description":"",
"parameters":[
{
"description":"Service agreement initialization.",
"in":"body",
"name":"body",
"required":true,
"schema":{
"properties":{
"consumerAddress":{
"description":"Consumer address.",
"example":"0x00a329c0648769A73afAc7F9381E08FB43dBEA72",
"type":"string"
},
"did":{
"description":"Identifier of the asset registered in ocean.",
"example":"did:op:08a429b8529856d59867503f8056903a680935a76950bb9649785cc97869a43d",
"type":"string"
},
"serviceAgreementId":{
"description":"Identifier of the service agreement.",
"example":"bb23s87856d59867503f80a690357406857698570b964ac8dcc9d86da4ada010",
"type":"string"
},
"serviceDefinitionId":{
"description":"Identifier of the service definition.",
"example":"0",
"type":"string"
},
"signature":{
"description":"Signature",
"example":"cade376598342cdae231321a0097876aeda656a567a67c6767fd8710129a9dc1",
"type":"string"
}
},
"required":[
"did",
"serviceAgreementId",
"serviceDefinitionId",
"signature",
{
"consumerAddress":null
}
],
"type":"object"
}
}
],
"responses":{
"201":{
"description":"Service agreement successfully initialized."
},
"400":{
"description":"One of the required attributes is missing."
},
"404":{
"description":"Invalid signature."
},
"500":{
"description":"Error"
}
},
"summary":"Initialize the SLA between the publisher and the consumer.",
"tags":[
"services"
]
}
},
"/api/v1/brizo/services/compute":{
"post":{
"consumes":[
"application/json"
],
"description":"",
"parameters":[
{
"description":"Asset metadata.",
"in":"body",
"name":"body",
"required":true,
"schema":{
"properties":{
"algorithm_did":{
"description":"Identifier of the algorithm to execute",
"example":"0x0234242345",
"type":"string"
},
"asset_did":{
"description":"Identifier of the asset registered in Ocean",
"example":"0x0234242345",
"type":"string"
},
"consumer_wallet":{
"description":"Address of the wallet of the asset consumer. Ex. data-science...",
"example":"0x0234242345",
"type":"string"
},
"cpu":{
"description":"Number of CPUs to execute the algorithm.",
"example":1,
"type":"integer"
},
"docker_image":{
"description":"Docker image where the algorithm is going to be executed. Docker image must include all the libraries needed to run it.",
"example":"python:3.6-alpine",
"type":"string"
},
"memory":{
"description":"Ammout of memory in GB to run the algorithm",
"example":1.5,
"type":"number"
}
},
"required":[
"asset_did",
"algorithm_did",
"consumer_wallet"
],
"type":"object"
}
}
],
"responses":{
},
"summary":"Allows to execute an algorithm inside a Docker instance in the cloud. Requires the publisher of the assets to provide this service in the service agreement related with the requested `asset_did`.",
"tags":[
"services"
]
}
},
"/api/v1/brizo/services/consume":{
"get":{
"consumes":[
"application/json"
],
"description":"",
"parameters":[
{
"description":"The consumer address.",
"in":"query",
"name":"consumerAddress",
"required":true,
"type":"string"
},
{
"description":"The ID of the service agreement.",
"in":"query",
"name":"serviceAgreementId",
"required":true,
"type":"string"
},
{
"description":"This URL is only valid if Brizo acts as a proxy. Consumer can't download using the URL if it's not through Brizo.",
"in":"query",
"name":"url",
"required":true,
"type":"string"
}
],
"responses":{
"302":{
"description":"Redirect to valid asset url."
},
"400":{
"description":"One of the required attributes is missing."
},
"404":{
"description":"Invalid asset data."
},
"500":{
"description":"Error"
}
},
"summary":"Allows download of asset data file.",
"tags":[
"services"
]
}
}
},
"swagger":"2.0"
}

View File

@ -8,9 +8,13 @@
- name: aquarius
links:
- name: API reference
url: https://github.com/oceanprotocol/aquarius/blob/develop/docs/for_api_users/API.md
url: /references/aquarius/
- name: brizo
links:
- name: API reference
url: /references/brizo/
- name: pleuston
- group: Libraries

View File

@ -13,8 +13,7 @@
link: /tutorials/introduction/
color: orange
- title: API References
#description: Get the API references for all relevant components.
description: Coming soon.
#link: /api/introduction/
- title: API & Library References
description: Get the references for REST APIs and library methods for all relevant components.
link: /references/introduction/
color: green

View File

@ -0,0 +1,19 @@
- group: Overview
items:
- title: API References
link: /references/introduction/
# - group: squid-js
# items:
# - title: API reference
# link: /api/squid-js/
- group: aquarius
items:
- title: API reference
link: /references/aquarius/
- group: brizo
items:
- title: API reference
link: /references/brizo/

View File

@ -2,8 +2,8 @@
items:
- title: Introduction
link: /tutorials/introduction/
- title: How to Use a Testnet
link: /tutorials/use-a-testnet/
- title: Get Ether and Ocean Tokens for Testnets
link: /tutorials/get-ether-and-ocean-tokens/
- title: Set Up Azure Storage
link: /tutorials/azure-for-brizo/

View File

@ -131,7 +131,7 @@ module.exports = {
{
resolve: 'gatsby-plugin-sitemap',
options: {
exclude: ['/test/']
exclude: ['/test/', '/references/petstore/']
}
},
{

View File

@ -2,6 +2,7 @@
const path = require('path')
const { createFilePath } = require('gatsby-source-filesystem')
const Swagger = require('swagger-client')
const { redirects } = require('./config')
exports.onCreateNode = ({ node, getNode, actions }) => {
@ -36,6 +37,26 @@ exports.onCreateNode = ({ node, getNode, actions }) => {
}
}
// https://github.com/swagger-api/swagger-js
const getSpec = async () => {
const spec = await Swagger(
'http://petstore.swagger.io/v2/swagger.json'
).then(client => {
return client.spec // The resolved spec
// client.originalSpec // In case you need it
// client.errors // Any resolver errors
// Tags interface
// client.apis.pet.addPet({id: 1, name: "bobby"}).then(...)
// TryItOut Executor, with the `spec` already provided
// client.execute({operationId: 'addPet', parameters: {id: 1, name: "bobby") }).then(...)
})
return spec
}
exports.createPages = ({ graphql, actions }) => {
const { createPage, createRedirect } = actions
@ -43,7 +64,7 @@ exports.createPages = ({ graphql, actions }) => {
resolve(
graphql(
`
{
query {
allMarkdownRemark(
filter: { fileAbsolutePath: { regex: "/content/" } }
) {
@ -79,9 +100,8 @@ exports.createPages = ({ graphql, actions }) => {
}
}
`
).then(result => {
).then(async result => {
if (result.errors) {
/* eslint-disable-next-line no-console */
console.log(result.errors)
reject(result.errors)
}
@ -89,7 +109,9 @@ exports.createPages = ({ graphql, actions }) => {
const docTemplate = path.resolve('./src/templates/Doc.jsx')
const posts = result.data.allMarkdownRemark.edges
//
// Create Doc pages
//
posts.forEach(post => {
createPage({
path: `${post.node.fields.slug}`,
@ -101,7 +123,9 @@ exports.createPages = ({ graphql, actions }) => {
})
})
//
// Create pages from dev-ocean contents
//
const postsDevOcean = result.data.devOceanDocs.edges
postsDevOcean
@ -125,6 +149,54 @@ exports.createPages = ({ graphql, actions }) => {
})
})
//
// Create pages from swagger json files
//
const apiSwaggerTemplate = path.resolve(
'./src/templates/ApiSwagger.jsx'
)
const petStoreSlug = '/references/petstore/'
try {
const spec = await getSpec()
createPage({
path: petStoreSlug,
component: apiSwaggerTemplate,
context: {
slug: petStoreSlug,
api: spec
}
})
} catch (error) {
console.log(error)
}
const aquariusSpecs = require('./data/aquarius.json')
const aquariusSlug = '/references/aquarius/'
createPage({
path: aquariusSlug,
component: apiSwaggerTemplate,
context: {
slug: aquariusSlug,
api: aquariusSpecs
}
})
const brizoSpecs = require('./data/brizo.json')
const brizoSlug = '/references/brizo/'
createPage({
path: brizoSlug,
component: apiSwaggerTemplate,
context: {
slug: brizoSlug,
api: brizoSpecs
}
})
//
// create redirects
//

View File

@ -59,7 +59,9 @@
"react-helmet": "^5.2.0",
"rehype-react": "^3.1.0",
"remark": "^10.0.1",
"remark-react": "^5.0.0"
"remark-react": "^5.0.0",
"slugify": "^1.3.3",
"swagger-client": "^3.8.22"
},
"devDependencies": {
"@svgr/webpack": "^4.1.0",

View File

@ -4,31 +4,31 @@ import { ReactComponent as Pencil } from '../images/pencil.svg'
import styles from './DocFooter.module.scss'
import { githubContentPath, githubDevOceanPath } from '../../config'
const DocFooter = ({ post }) => {
const { sourceInstanceName } = post.parent
const DocFooter = ({ post, url, externalName }) => {
let path
let externalRepoName
switch (sourceInstanceName) {
case 'dev-ocean':
path = githubDevOceanPath
externalRepoName = sourceInstanceName
break
default:
path = githubContentPath
if (post) {
const { sourceInstanceName } = post.parent
switch (sourceInstanceName) {
case 'dev-ocean':
path = githubDevOceanPath
externalName = sourceInstanceName
break
default:
path = githubContentPath
}
url = `${path}/${post.parent.relativePath}`
}
return (
<footer className={styles.footer}>
<a
href={`${path}/${post.parent.relativePath}`}
className={!post.html ? styles.active : null}
>
<a href={url} className={post && !post.html ? styles.active : null}>
<Pencil /> Edit this page on GitHub
{externalRepoName && (
{externalName && (
<span className={styles.externalRepoName}>
{externalRepoName}
{externalName}
</span>
)}
</a>
@ -37,7 +37,9 @@ const DocFooter = ({ post }) => {
}
DocFooter.propTypes = {
post: PropTypes.object.isRequired
post: PropTypes.object,
url: PropTypes.string,
externalName: PropTypes.string
}
export default DocFooter

View File

@ -4,7 +4,7 @@ import remark from 'remark'
import remarkReact from 'remark-react'
import styles from './DocHeader.module.scss'
const DocHeader = ({ title, description }) => {
const DocHeader = ({ title, description, prepend }) => {
const descriptionHtml =
description &&
remark()
@ -13,7 +13,9 @@ const DocHeader = ({ title, description }) => {
return (
<header className={styles.header}>
<h1 className={styles.title}>{title}</h1>
<h1 className={styles.title}>
{title} {prepend && prepend}
</h1>
{description && (
<div className={styles.lead}>{descriptionHtml}</div>
)}
@ -23,7 +25,8 @@ const DocHeader = ({ title, description }) => {
DocHeader.propTypes = {
title: PropTypes.string.isRequired,
description: PropTypes.string
description: PropTypes.string,
prepend: PropTypes.any
}
export default DocHeader

View File

@ -39,20 +39,15 @@ const Header = () => (
</Link>
<nav className={styles.headerMenu}>
{sections
.filter(
({ node }) =>
node.title !== 'API References'
)
.map(({ node }) => (
<Link
key={node.title}
to={node.link}
className={styles.section}
>
{node.title}
</Link>
))}
{sections.map(({ node }) => (
<Link
key={node.title}
to={node.link}
className={styles.section}
>
{node.title}
</Link>
))}
</nav>
</div>
</header>

View File

@ -22,6 +22,10 @@
:global(.tutorials) & {
color: $orange;
}
:global(.references) & {
color: $green;
}
}
.rootLink {

View File

@ -7,7 +7,12 @@ const SidebarLink = ({ link, title, linkClasses }) => {
if (link) {
if (link.match(/^\s?http(s?)/gi)) {
return (
<a href={link} target="_blank" rel="noopener noreferrer">
<a
href={link}
className={linkClasses}
target="_blank"
rel="noopener noreferrer"
>
{title}
</a>
)
@ -23,40 +28,103 @@ const SidebarLink = ({ link, title, linkClasses }) => {
}
}
const SidebarList = ({ items, location }) => (
<ul className={styles.list}>
{items.map((item, j) => (
<li key={j}>
<SidebarLink
link={item.link}
title={item.title}
linkClasses={
item.link === location.pathname
? styles.active
: styles.link
}
/>
</li>
))}
</ul>
SidebarLink.propTypes = {
link: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
linkClasses: PropTypes.string
}
const SidebarList = ({ items, location, toc, tableOfContents }) => (
<div className={styles.list}>
{toc ? (
<div
className={styles.toc}
dangerouslySetInnerHTML={{ __html: tableOfContents }}
/>
) : (
<ul>
{items.map((item, j) => (
<li key={j}>
<SidebarLink
link={item.link}
title={item.title}
linkClasses={
item.link === location.pathname
? styles.active
: styles.link
}
/>
</li>
))}
</ul>
)}
</div>
)
SidebarList.propTypes = {
items: PropTypes.array.isRequired,
location: PropTypes.object.isRequired,
toc: PropTypes.bool,
tableOfContents: PropTypes.string
}
const SidebarGroupTitle = ({ group }) => (
<h4 className={styles.groupTitle}>
{group.items[0].link ? (
<SidebarLink
link={group.items[0].link}
title={group.group}
linkClasses={styles.groupTitleLink}
/>
) : (
group.group
)}
</h4>
)
SidebarGroupTitle.propTypes = {
group: PropTypes.object.isRequired
}
const SidebarGroup = ({ i, group, location, ...props }) => (
<>
<SidebarGroupTitle group={group} />
<SidebarList
key={i}
items={group.items}
location={location}
{...props}
/>
</>
)
export default class Sidebar extends Component {
static propTypes = {
sidebar: PropTypes.string,
location: PropTypes.object.isRequired
location: PropTypes.object.isRequired,
collapsed: PropTypes.bool,
toc: PropTypes.bool,
tableOfContents: PropTypes.string
}
static defaultProps = {
location: { pathname: `/` }
}
static defaultProps = { location: { pathname: '/' } }
render() {
const { sidebar, location } = this.props
const {
sidebar,
location,
collapsed,
toc,
tableOfContents
} = this.props
const sidebarfile = sidebar
? require(`../../data/sidebars/${sidebar}.yml`) // eslint-disable-line
: []
if (sidebar) {
try {
var sidebarfile = require(`../../data/sidebars/${sidebar}.yml`) // eslint-disable-line
} catch (e) {
throw e
}
}
if (!sidebarfile) {
return null
@ -66,36 +134,30 @@ export default class Sidebar extends Component {
<nav className={styles.sidebar}>
{sidebarfile.map((group, i) => (
<div key={i}>
<h4 className={styles.groupTitle}>
{group.items[0].link ? (
<SidebarLink
link={group.items[0].link}
title={group.group}
linkClasses={styles.groupTitleLink}
{collapsed ? (
group.items.some(
item => item.link === location.pathname
) ? (
<SidebarGroup
i={i}
group={group}
location={location}
toc={toc}
tableOfContents={tableOfContents}
/>
) : (
group.group
)}
</h4>
<SidebarList
key={i}
items={group.items}
location={location}
/>
<SidebarGroupTitle group={group} />
)
) : (
<SidebarGroup
i={i}
group={group}
location={location}
/>
)}
</div>
))}
</nav>
)
}
}
SidebarLink.propTypes = {
link: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
linkClasses: PropTypes.string
}
SidebarList.propTypes = {
items: PropTypes.array.isRequired,
location: PropTypes.object.isRequired
}

View File

@ -54,6 +54,10 @@
border-left: 1px solid $brand-grey-lighter;
margin-left: $spacer / 2;
> ul {
padding-left: 0;
}
li {
display: block;
@ -63,7 +67,8 @@
}
}
.link {
.link,
.toc a {
color: $brand-grey;
display: inline-block;
padding: $spacer / 6 $spacer / 2;
@ -77,6 +82,21 @@
}
}
.toc {
ul {
padding-left: 0;
ul {
padding-left: $spacer / 2;
margin: 0;
}
}
li {
margin: 0;
}
}
.active {
composes: link;
color: $brand-purple;

View File

@ -38,8 +38,6 @@
&:last-child {
flex-basis: 100%;
text-align: center;
opacity: .5;
pointer-events: none;
}
}

View File

@ -272,6 +272,14 @@ samp {
font-size: $font-size-small !important;
border-radius: $border-radius !important;
text-shadow: none !important;
h1 &,
h2 &,
h3 &,
h4 &,
h5 & {
font-size: inherit !important;
}
}
:not(pre) > code {

View File

@ -0,0 +1,321 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { graphql } from 'gatsby'
import Helmet from 'react-helmet'
import slugify from 'slugify'
import Layout from '../components/Layout'
import Content from '../components/Content'
import HeaderSection from '../components/HeaderSection'
import Sidebar from '../components/Sidebar'
import DocHeader from '../components/DocHeader'
import DocFooter from '../components/DocFooter'
import SEO from '../components/Seo'
import stylesDoc from './Doc.module.scss'
import styles from './ApiSwagger.module.scss'
const cleanKey = key => {
let keyCleaned = key
if (key.includes('aquarius')) {
keyCleaned = key.replace(/\/api\/v1\/aquarius/gi, '')
}
if (key.includes('brizo')) {
keyCleaned = key.replace(/\/api\/v1\/brizo/gi, '')
}
return keyCleaned
}
const toc = api => {
const items = Object.keys(api.paths).map(
key => `<li key=${key}>
<a href="#${slugify(cleanKey(key))}"><code>${cleanKey(
key
)}</code></a>
</li>`
)
return `<ul>${items}</ul>`
}
const SwaggerMeta = ({ contact, license }) => (
<ul className={styles.swaggerMeta}>
{contact && (
<li>
<a href={`mailto:${contact.email}`}>{contact.email}</a>
</li>
)}
{license && (
<li>
<a href={license.url}>{license.name}</a>
</li>
)}
</ul>
)
SwaggerMeta.propTypes = {
contact: PropTypes.object,
license: PropTypes.object
}
const ParameterExample = ({ properties }) => (
//
// HEADS UP!
//
// Constructing the example request body here based on the defined properties
// where `key` is the name of the property, and `properties[key].example` is
// the value for it.
//
// Making prism.js pick up on the strings only output didn't work out so well
// so the spans and classes this plugin would add are added manually here. Since we
// include the prism css file globally this is picked up by that.
//
// But this can only work if all keys and values are manually constructed here, which
// is almost impossible to do for deep nested objects or arrays as example value. Running
// that code through `JSON.stringify` won't syntax highlight that part of the code.
//
<pre className="language-json">
<code className="language-json">
{'{'}
{properties &&
Object.keys(properties).map(key => (
<div key={key}>
<span className="token property">{` "${key}"`}</span>
<span className="token operator">{`: `}</span>
{properties[key].type === 'string' && (
<span className="token string">{`"${
properties[key].example
}"`}</span>
)}
{(properties[key].type === 'integer' ||
properties[key].type === 'number') && (
<span className="token number">
{`${properties[key].example}`}
</span>
)}
{(properties[key].type === 'array' ||
properties[key].type === 'object') &&
JSON.stringify(properties[key].example, null, 2)}
,
</div>
))}
{'}'}
</code>
</pre>
)
ParameterExample.propTypes = {
properties: PropTypes.object
}
const Parameters = ({ parameters }) => (
<>
<h4 className={styles.subHeading}>Parameters</h4>
{parameters.map(parameter => {
const { name, type, required, description, schema } = parameter
return (
<div className={styles.parameters} key={parameter.name}>
<h5>
<code>{name}</code>
{required && (
<span
className={styles.parameterRequired}
title="required parameter"
>
*
</span>
)}
<span className={styles.parameterType}>{type}</span>
</h5>
<p>{description}</p>
{schema && (
<ParameterExample properties={schema.properties} />
)}
</div>
)
})}
</>
)
const Responses = ({ responses }) => (
<>
<h4 className={styles.subHeading}>Responses</h4>
{Object.keys(responses).map(key => (
<div key={key} className={styles.response}>
<code>{key}</code> {responses[key].description}
</div>
))}
</>
)
const Method = ({ keyName, value }) => {
const { summary, description, parameters, responses } = value
return (
<div className={styles.method}>
<h3 className={styles.pathMethod} data-type={keyName}>
{keyName}
</h3>
<p>{summary}</p>
{description && <p>{description}</p>}
{/*
{consumes &&
consumes.map((item, i) => (
<div key={i}>
<code>{item}</code>
</div>
))}
*/}
{parameters && parameters.length && (
<Parameters parameters={parameters} />
)}
{responses && Object.keys(responses).length !== 0 && (
<Responses responses={responses} />
)}
</div>
)
}
Method.propTypes = {
keyName: PropTypes.string,
value: PropTypes.object
}
const Paths = ({ paths }) =>
Object.entries(paths).map(([key, value]) => (
<div key={key}>
<h2 id={slugify(cleanKey(key))} className={styles.pathName}>
<code>{cleanKey(key)}</code>
</h2>
{Object.entries(value).map(([key, value]) => (
<Method key={key} keyName={key} value={value} />
))}
</div>
))
const BasePath = ({ host, basePath }) => (
<div className={styles.basePath}>
<h2>Base Path</h2>
<code>
<span>{host}</span>
{basePath}
</code>
</div>
)
BasePath.propTypes = {
host: PropTypes.string,
basePath: PropTypes.string
}
export default class ApiSwaggerTemplate extends Component {
static propTypes = {
data: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
pageContext: PropTypes.object.isRequired
}
render() {
const { location, data, pageContext } = this.props
const sections = data.allSectionsYaml.edges
const { api } = pageContext
const { host, basePath, info, paths } = api
const { title, description, version, license, contact } = info
// output section title as defined in sections.yml
const sectionTitle = sections.map(({ node }) => {
// compare section against section title from sections.yml
if (node.title.toLowerCase().includes('references')) {
return node.title
}
})
return (
<>
<Helmet>
<body className={'references'} />
</Helmet>
<SEO
title={title}
description={description}
slug={pageContext.slug}
article
/>
<Layout location={location}>
<HeaderSection title={sectionTitle} />
<Content>
<main className={stylesDoc.wrapper}>
<aside className={stylesDoc.sidebar}>
<Sidebar
location={location}
sidebar={'references'}
collapsed
toc
tableOfContents={toc(api)
.split(',')
.join('')}
/>
</aside>
<article className={stylesDoc.main}>
<DocHeader
title={title}
description={description}
prepend={
<span className={styles.version}>
{version}
</span>
}
/>
{(contact || license) && (
<SwaggerMeta
contact={contact}
license={license}
/>
)}
{(host || basePath) && (
<BasePath host={host} basePath={basePath} />
)}
<Paths paths={paths} />
<DocFooter
url={`https://github.com/oceanprotocol/${title.toLowerCase()}`}
externalName={`${title} Swagger spec`}
/>
</article>
</main>
</Content>
</Layout>
</>
)
}
}
export const apiSwaggerQuery = graphql`
query {
allSectionsYaml {
edges {
node {
title
description
link
}
}
}
}
`

View File

@ -0,0 +1,132 @@
@import 'variables';
.version {
font-size: $font-size-base;
font-family: $font-family-monospace;
color: $brand-grey-light;
}
.swaggerMeta {
margin-top: -($spacer);
padding: 0;
font-size: $font-size-small;
li {
display: inline-block;
margin-left: $spacer;
&:first-child {
margin-left: 0;
}
&:before { display: none;}
}
}
.basePath {
margin-top: $spacer;
h2 {
font-size: $font-size-h3;
border-bottom: 1px solid $brand-grey-lighter;
padding-bottom: $spacer / 2;
margin-top: $spacer * 2;
margin-bottom: $spacer;
}
span {
color: $brand-grey-light;
}
code {
// stylelint-disable-next-line
font-size: $font-size-large !important;
font-weight: $font-weight-bold;
}
}
.pathName {
font-size: $font-size-h3;
border-bottom: 1px solid $brand-grey-lighter;
padding-bottom: $spacer / 2;
margin-top: $spacer * 2;
margin-bottom: $spacer;
code {
// stylelint-disable-next-line
background: none !important;
}
}
.pathMethod {
font-size: $font-size-base;
font-family: $font-family-monospace;
margin-bottom: $spacer / 4;
margin-top: 0;
display: inline-block;
padding: $spacer / 8 $spacer / 3;
border-radius: $border-radius;
text-transform: uppercase;
&[data-type='get'] {
background: rgba($green, .4);
}
&[data-type='post'] {
background: rgba($brand-blue, .4);
}
&[data-type='put'] {
background: rgba($brand-violet, .3);
}
&[data-type='delete'] {
background: rgba($red, .4);
}
}
.method {
padding: $spacer / 2;
border: 1px solid $brand-grey-lighter;
margin-bottom: $spacer;
border-radius: $border-radius;
}
.subHeading {
font-size: $font-size-h5;
}
.parameters {
h5 {
font-size: $font-size-small;
margin-bottom: $spacer / 4;
}
pre {
max-height: 80vh;
code {
padding: $spacer / $line-height;
}
}
}
.parameterRequired {
font-size: $font-size-small;
vertical-align: top;
color: $brand-purple;
}
.parameterType {
font-weight: $font-weight-base;
margin-left: $spacer / 4;
color: $brand-grey-light;
}
.response {
margin-bottom: $spacer / 4;
code {
margin-right: $spacer / 4;
}
}

View File

@ -27,7 +27,7 @@ const DocMain = ({ title, description, tableOfContents, post, single }) => (
DocMain.propTypes = {
title: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
tableOfContents: PropTypes.string.isRequired,
tableOfContents: PropTypes.string,
post: PropTypes.object.isRequired,
single: PropTypes.bool
}
@ -54,6 +54,8 @@ export default class DocTemplate extends Component {
}
})
const isApiSection = location.pathname.includes('/references/')
return (
<>
<Helmet>
@ -77,12 +79,22 @@ export default class DocTemplate extends Component {
<Sidebar
location={location}
sidebar={section}
collapsed={isApiSection}
toc={
isApiSection &&
!location.pathname.includes(
'/references/introduction/'
)
}
tableOfContents={tableOfContents}
/>
</aside>
<DocMain
title={title}
description={description}
tableOfContents={tableOfContents}
tableOfContents={
!isApiSection && tableOfContents
}
post={post}
/>
</main>

View File

@ -1,4 +1,5 @@
User-agent: *
Disallow: */test
Disallow: */references/petstore
sitemap: https://docs.oceanprotocol.com/sitemap.xml