Skip to content

Commit

Permalink
Merge pull request #44 from netlify/tweak-api
Browse files Browse the repository at this point in the history
Use open-api spec directly
  • Loading branch information
bcomnes authored Jul 27, 2018
2 parents b36c25e + e6b2789 commit cc80d36
Show file tree
Hide file tree
Showing 24 changed files with 623 additions and 128 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ vendor
.DS_STORE
.vscode
site
.netlify
.netlify
coverage
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ USAGE
<!-- commands -->
# Command Topics

* [`netlify-cli deploy`](docs/deploy.md) - Create a new deploy from the contents of a folder
* [`netlify-cli deploy`](docs/deploy.md) - Create a new deploy from the contents of a folder.
* [`netlify-cli forms`](docs/forms.md) - Handle form operations
* [`netlify-cli functions`](docs/functions.md) - Manage netlify functions
* [`netlify-cli link`](docs/link.md) - Link a local repo or project folder to an existing site on Netlify
* [`netlify-cli login`](docs/login.md) - Login to account
* [`netlify-cli logout`](docs/logout.md) - Logout of account
* [`netlify-cli sites`](docs/sites.md) - Handle site operations
* [`netlify-cli status`](docs/status.md) - Print currently logged in use
* [`netlify-cli whoami`](docs/whoami.md) - Print currently logged in use
* [`netlify-cli whoami`](docs/whoami.md) - Print currently logged in user and account info

<!-- commandsstop -->

Expand Down
6 changes: 3 additions & 3 deletions docs/deploy.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
`netlify-cli deploy`
====================

Create a new deploy from the contents of a folder
Create a new deploy from the contents of a folder.

* [`netlify-cli deploy [PUBLISHFOLDER]`](#netlify-cli-deploy-publishfolder)

## `netlify-cli deploy [PUBLISHFOLDER]`

Create a new deploy from the contents of a folder
Create a new deploy from the contents of a folder.

```
USAGE
$ netlify-cli deploy [PUBLISHFOLDER]
ARGUMENTS
PUBLISHFOLDER folder to deploy
PUBLISHFOLDER folder to deploy (optional)
```

_See code: [src/commands/deploy/index.js](https://github.com/netlify/cli/blob/v0.0.0/src/commands/deploy/index.js)_
6 changes: 4 additions & 2 deletions docs/sites.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ DESCRIPTION
The sites command will help you manage all your sites
EXAMPLES
$ netlify sites:create -name my-new-site
$ netlify sites:update -name my-new-site
$ netlify sites:create --name my-new-site
$ netlify sites:update --name my-new-site
$ netlify sites:delete --name my-new-site
$ netlify sites:list
```

_See code: [src/commands/sites/index.js](https://github.com/netlify/cli/blob/v0.0.0/src/commands/sites/index.js)_
Expand Down
4 changes: 2 additions & 2 deletions docs/whoami.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
`netlify-cli whoami`
====================

Print currently logged in use
Print currently logged in user and account info

* [`netlify-cli whoami`](#netlify-cli-whoami)

## `netlify-cli whoami`

Print currently logged in use
Print currently logged in user and account info

```
USAGE
Expand Down
15 changes: 11 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"failFast": false,
"failWithoutAssertions": false,
"tap": false,
"compileEnhancements": true
"babel": false,
"compileEnhancements": false
},
"bin": {
"ntl": "./bin/run",
Expand All @@ -25,6 +26,7 @@
"bugs": "https://github.com/netlify/cli/issues",
"dependencies": {
"@iarna/toml": "^1.7.1",
"@netlify/open-api": "^0.1.1",
"@oclif/command": "^1",
"@oclif/config": "^1",
"@oclif/errors": "^1.1.2",
Expand All @@ -41,12 +43,12 @@
"folder-walker": "^3.1.0",
"hasha": "^3.0.0",
"is-docker": "^1.1.0",
"lodash.camelcase": "^4.3.0",
"lodash.flatten": "^4.4.0",
"lodash.get": "^4.4.2",
"lodash.set": "^4.3.2",
"lodash.snakecase": "^4.1.1",
"make-dir": "^1.3.0",
"netlifys_api_definition": "^0.2.0",
"open": "0.0.5",
"opn": "^5.3.0",
"p-all": "^1.0.0",
Expand All @@ -57,6 +59,8 @@
"parallel-transform": "^1.1.0",
"prettyjson": "^1.2.1",
"pump": "^3.0.0",
"qs": "^6.5.2",
"r2": "^2.0.1",
"request": "^2.87.0",
"through2-filter": "^3.0.0",
"through2-map": "^3.0.0",
Expand All @@ -67,13 +71,16 @@
"devDependencies": {
"@oclif/dev-cli": "^1.13.31",
"ava": "1.0.0-beta.6",
"body": "^5.1.0",
"eslint": "^4.19.1",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-import": "^2.13.0",
"eslint-plugin-node": "^6.0.1",
"eslint-plugin-prettier": "^2.6.1",
"from2-string": "^1.1.0",
"mkdirp": "^0.5.1",
"npm-run-all": "^4.1.3",
"nyc": "^12.0.2",
"prettier": "^1.13.7",
"rimraf": "^2.6.2",
"sitedown": "^3.3.0"
Expand Down Expand Up @@ -115,9 +122,9 @@
"clean": "rimraf site && mkdirp site",
"start": "node ./bin/run",
"test": "run-s test:*",
"test:ava": "ava -vvvv",
"test:ava": "nyc --reporter=lcov ava --verbose && nyc report",
"test:lint": "eslint src",
"watch": "run-p watch:*",
"watch:ava": "npm run test:ava -- --watch"
"watch:ava": "nyc --reporter=lcov ava --watch"
}
}
4 changes: 2 additions & 2 deletions src/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ class BaseCommand extends Command {
}
this.log(`Logging into your Netlify account...`)
const client = this.netlify
const ticket = await client.api.createTicket(this.global.get('clientId'))
const ticket = await client.createTicket({ clientId: this.global.get('clientId') })
openBrowser(`https://app.netlify.com/authorize?response_type=ticket&ticket=${ticket.id}`)
const accessToken = await client.waitForAccessToken(ticket)
const accessToken = await client.getAccessToken(ticket)
this.global.set('accessToken', accessToken)
this.log('Logged in...')
}
Expand Down
6 changes: 3 additions & 3 deletions src/commands/deploy/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class DeployCommand extends Command {
this.exit()
} else {
try {
await this.netlify.api.getSite(siteId)
await this.netlify.getSite({ siteId })
} catch (e) {
this.error(e.message)
}
Expand All @@ -56,7 +56,7 @@ class DeployCommand extends Command {
const deployFolder =
args.publishFolder ||
get(this.site.toml, 'build.publish') ||
get(await this.netlify.api.getSite(siteId), 'build_settings.dir')
get(await this.netlify.getSite({ siteId }), 'build_settings.dir')

if (!deployFolder) {
this.error(
Expand All @@ -72,7 +72,7 @@ class DeployCommand extends Command {
try {
results = await this.netlify.deploy(siteId, resolvedDeployPath)
} catch (e) {
this.error(JSON.stringify(e, null, ' '))
this.error(e)
}
cliUx.action.stop(`Finished deploy ${results.deployId}`)
this.log(
Expand Down
6 changes: 3 additions & 3 deletions src/commands/link/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class LinkCommand extends Command {
const siteId = this.site.get('siteId')

if (siteId && !flags.force) {
const site = await this.netlify.api.getSite(siteId)
const site = await this.netlify.getSite(siteId)
this.log(`Site already linked to ${site.name}`)
this.log(`Link: ${site.admin_url}`)
return this.exit()
Expand All @@ -19,7 +19,7 @@ class LinkCommand extends Command {
if (flags.id) {
let site
try {
site = await this.netlify.api.getSite(flags.id)
site = await this.netlify.getSite(flags.id)
} catch (e) {
if (e.status === 404) throw new CLIError(`Site id ${flags.id} not found`)
else throw new CLIError(e)
Expand All @@ -32,7 +32,7 @@ class LinkCommand extends Command {
if (flags.name) {
let results
try {
results = await this.netlify.api.listSites({
results = await this.netlify.listSites({
name: flags.name,
filter: 'all'
})
Expand Down
2 changes: 1 addition & 1 deletion src/commands/open/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class OpenCommand extends Command {

let site
try {
site = await this.netlify.api.getSite(siteId)
site = await this.netlify.getSite(siteId)
} catch (e) {
if (e.status === 401 /* unauthorized*/) {
this.warn(`Log in with a different account or re-link to a site you have permission for`)
Expand Down
2 changes: 1 addition & 1 deletion src/commands/sites/list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class SitesListCommand extends Command {
const client = this.netlify

// Fetch all sites!
client.api.listSites(null, (err, sites) => {
client.listSites(null, (err, sites) => {
if (err) {
throw new CLIError(err)
}
Expand Down
7 changes: 3 additions & 4 deletions src/commands/status/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const Command = require('../../base')
const renderShortDesc = require('../../utils/renderShortDescription')
const { CLIError } = require('@oclif/errors')
const prettyjson = require('prettyjson')

class StatusCommand extends Command {
Expand All @@ -9,7 +8,7 @@ class StatusCommand extends Command {
const siteId = this.site.get('siteId')
let personal
if (accessToken) {
const accounts = await this.netlify.api.listAccountsForUser()
const accounts = await this.netlify.listAccountsForUser()
personal = accounts.find(account => account.type === 'PERSONAL')
// TODO: use users endpoint
} else {
Expand All @@ -23,13 +22,13 @@ class StatusCommand extends Command {

let site
try {
site = await this.netlify.api.getSite(siteId)
site = await this.netlify.getSite({ siteId })
} catch (e) {
if (e.status === 401 /* unauthorized*/) {
this.warn(`Log in with a different account or re-link to a site you have permission for`)
this.error(`Not authorized to view the currently linked site (${siteId})`)
}
throw new CLIError(e)
this.error(e)
}

const statusData = {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/whoami/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class WhoamiCommand extends Command {
async run() {
const accessToken = this.global.get('accessToken')
if (accessToken) {
const accounts = await this.netlify.api.listAccountsForUser()
const accounts = await this.netlify.listAccountsForUser()
const personal = accounts.find(account => account.type === 'PERSONAL')
const teams = accounts.filter(account => account.type !== 'PERSONAL')
const data = {
Expand Down
111 changes: 111 additions & 0 deletions src/utils/api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# @netlify/js-api

A Netlify [open-api](https://github.com/netlify/open-api) client that works in the browser and Node.js.

## Usage

```js
const NetlifyAPI = require('../utils/api')
const client = new NetlifyAPI('1234myAccessToken')
const sites = await client.listSites()
```

## API

### `client = new NetlifyAPI([accessToken], [opts])`

Create a new instance of the Netlify API client with the provided `accessToken`.

`accessToken` is optional. Without it, you can't make authorized requests.

`opts` includes:

```js
{
userAgent: 'netlify-js-client',
scheme: 'https',
host: 'api.netlify.com',
pathPrefix: '/api/v1',
globalParams: {} // parameters you want available for every request
}
```

### `client.accessToken`

A setter/getter that returns the `accessToken` that the client is configured to use. You can set this after the class is instantiated, and all subsequent calls will use the new `accessToken`.

### `client.basePath`

A getter that returns the formatted base URL of the endpoint the client is configured to use.

### Open API Client methods

The client is dynamically generated from the [open-api](https://github.com/netlify/open-api) definition file. Each method is is named after the `operationId` name of each endpoint action. **To see list of available operation see the [open-api website](https://open-api.netlify.com/)**.

Every open-api method has the following signature:

#### `promise(response) = client.operationId([params], [opts])`

Perform a call to the given endpoint corresponding with the `operationId`. Returns promise that will resolve with the body of the response, or reject with an error with details about the request attached. Rejects if the `status` > 400. Successful response objects have `status` and `statusText` properties on their prototype.

`params` is an object that includes any of the required or optional endpoint parameters. `params.body` should be an object which gets serialized to JSON automatically. If the endpoint accepts `binary`, `params.body` can be a Node.js readable stream.

```js
// example params
{
any_param_needed,
paramsCanAlsoBeCamelCase,
body: {
an: 'arbitrary js object'
}
}
```

Optional `opts` can include any property you want passed to `node-fetch`. The `headers` propety is merged with some `defaultHeaders`.

```js
// example opts
{
headers
// any other properties for node-fetch
}
```

```js
// default headers
{
'User-agent': 'netlify-js-client',
accept: 'application/json'
}
```

### Convenience Methods

Some methods have been added in addition to the open API methods that make certain actions simpler to perform.

#### `promise(accessToken) = client.getAccessToken(ticket, [opts])`

Pass in a [`ticket`](open-api.netlify.com#model-ticket) and get back an `accessToken`. Call this with the response from a `client.createTicket({ client_id })` call. Automatically sets the `accessToken` to `this.accessToken` and returns `accessToken` for the consumer to save for later.

Optional `opts` include:

```js
{
poll: 1000, // number of ms to wait between polling
timeout: 3.6e6 // number of ms to wait before timing out
}
```

#### `promise(deploy) = client.deploy(siteId, buildDir, [opts])`

**Node.js Only**: Pass in a `siteId` and a path to a folder you wan't to deploy. This creates a new deploy for the `siteId`, scans the folder and begins an upload of changed files.

Optional `opts` include:

```js
{
deployTimeout: 1.2e6, // 20 mins
parallelHash: 100, // number of parallel hashing calls
parallelUpload: 4 // number of files to upload in parallel
}
```
Loading

0 comments on commit cc80d36

Please sign in to comment.