From dcfe15a60fe62e3543ff84506936deb282651ccc Mon Sep 17 00:00:00 2001 From: Bret Comnes Date: Tue, 25 Sep 2018 10:02:43 -0700 Subject: [PATCH 1/4] CHANGELOG and CONTRIBUTING updates --- CHANGELOG.md | 10 ++++++++++ CONTRIBUTING.md | 44 +++++++++++++++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..689eea3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +# netlify Change Log +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + +## 2.0.1 - 2018-09-25 +* A whole new Netlify Node.js API client! 🎉 +* Client code was extracted from our forthcoming [2.0.0 CLI](https://www.netlify.com/blog/2018/09/10/netlify-cli-2.0-now-in-beta-/) release. +* A completely new API. Treat the 2.x.x and forward as a completely separate codebase and API. +* API calls are now derived from the [open-api](https://github.com/netlify/open-api) specification. See the [swagger-ui](https://open-api.netlify.com/#/default) and know that there is a matching API method for every operationID (the name on the right). See the README for full API docs. +* Includes a method for creating content based deploys. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7a7566d..d4e2b75 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,29 +5,51 @@ please read the [code of conduct](CODE_OF_CONDUCT.md). ## Setup -> Install NPM on your system: https://docs.npmjs.com/getting-started/installing-node +> Install Node.js + npm on your system: https://nodejs.org/en/download/ ```sh $ git clone https://github.com/netlify/js-client netlify-js-client $ cd netlify-js-client $ npm install +$ npm test ``` +You can also use yarn. + ## Testing -```sh -$ jasmine-node spec -``` +This repo uses [ava](https://github.com/avajs/ava) for testing. +Any files in the `src` directory that have a `.test.js` file extension are automatically detected and run as tests. + +We also test for a few other variables: + +- Dependencies (used an unused) +- Linting +- Coverage +- Must work with Windows + Unix environments. -## Pull Requests +## Architecture -We actively welcome your pull requests. +We target Node.js LTS and stable environments, and aim for basic modern browser support when possible. +In order to facilitate simple contributions, we avoided any kind of build steps. -1. Fork the repo and create your branch from `master`. -2. If you've added code that should be tested, add tests. -3. If you've changed APIs, update the documentation. -4. Ensure the test suite passes. -5. Make sure your code lints. +If you need to add new API routes, please add them to the [open-api](https://github.com/netlify/open-api) repo. +This client will automatically inherent the new routes from that module. + +Projects that depend heavily on this client that should be taken into consideration when making changes: + +- [netlify/cli](https://github.com/netlify/cli) + +## Releasing + +```console +# Make changes +# Update the changelog +$ npm version [major|minor|patch] +$ git push && git push --tags +# Create a github release with the changelog contents +$ npm publish +``` ## License From 7c1608052dc2eff86e38209e451d4beeb662e89e Mon Sep 17 00:00:00 2001 From: Bret Comnes Date: Tue, 25 Sep 2018 10:17:16 -0700 Subject: [PATCH 2/4] Change tomlPath to configPath --- CONTRIBUTING.md | 1 + README.md | 51 ++++++++++++++++++++++++++-------------- src/deploy/hash-files.js | 4 ++-- src/deploy/index.js | 6 ++--- 4 files changed, 39 insertions(+), 23 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d4e2b75..01560c0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -44,6 +44,7 @@ Projects that depend heavily on this client that should be taken into considerat ```console # Make changes +# Update README docs if they have changed. # Update the changelog $ npm version [major|minor|patch] $ git push && git push --tags diff --git a/README.md b/README.md index 4dcd2d0..6587fac 100644 --- a/README.md +++ b/README.md @@ -28,13 +28,15 @@ Create a new instance of the Netlify API client with the provided `accessToken`. scheme: 'https', host: 'api.netlify.com', pathPrefix: '/api/v1', - globalParams: {} // parameters you want available for every request + globalParams: {} // parameters you want available for every request. + // Global params are only sent of the open-api spec specifies the provided params. } ``` ### `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 newly set `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 newly set `accessToken`. ### `client.basePath` @@ -42,15 +44,22 @@ A getter that returns the formatted base URL of the endpoint the client is confi ### 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 operations see the [open-api website](https://open-api.netlify.com/)**. +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 operations 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. +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. +`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 @@ -63,7 +72,8 @@ Perform a call to the given endpoint corresponding with the `operationId`. Retu } ``` -Optional `opts` can include any property you want passed to `node-fetch`. The `headers` property is merged with some `defaultHeaders`. +Optional `opts` can include any property you want passed to `node-fetch`. +The `headers` property is merged with some `defaultHeaders`. ```js // example opts @@ -82,23 +92,28 @@ All methods are conveniently consumed with async/await: async function getSomeData () { // Calls may fail! try { - const resposnse = await client.getSites() - return response + return await client.getSiteDeploy({ + siteId: '1234abcd', + deploy_id: '4567' + }) } catch (e) { // handle error } } ``` -If the request response includes `json` in the `contentType` header, fetch will deserialize the JSON body. Otherwise the `text` of the response is returned. +If the request response includes `json` in the `contentType` header, fetch will deserialize the JSON body. +Otherwise the `text` of the response is returned. -### Convenience Methods +### API Flow 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`](https://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. +Pass in a [`ticket`](https://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: @@ -121,18 +136,18 @@ async function login () { await openBrowser(`https://app.netlify.com/authorize?response_type=ticket&ticket=${ticket.id}`) const accessToken = await api.getAccessToken(ticket) // API is also set up to use the returned access token as a side effect - return accessToken + return accessToken // Save this for later so you can quickly set up an authenticated client } ``` #### `promise(deploy) = client.deploy(siteId, buildDir, [opts])` **Node.js Only**: Pass in a `siteId`, a `buildDir` (the folder you want to deploy) and an options object to deploy the contents of that folder. -Sometimes need to write to a `tmpDir`. +Sometimes this method needs to write to a `tmpDir`. By default `tmpDir` is the default system default. The following paths can be passed in the options: -- `tomlPath` (a `netlify.toml` file that includes redirect rules for the deploy) +- `configPath` (path to a `netlify.toml` file that includes redirect rules for the deploy, etc.) - `functionsDir` (a folder with lambda functions to deploy) Optional `opts` include: @@ -140,15 +155,15 @@ Optional `opts` include: ```js { functionsDir: null, // path to a folder of functions to deploy - tomlPath: null, // path to a netlify.toml file to include in the deploy (e.g. redirect support for manual deploys) + configPath: null, // path to a netlify.toml file to include in the deploy (e.g. redirect support for manual deploys) draft: false, // draft deploy or production deploy message: undefined, // a short message to associate with the deploy deployTimeout: 1.2e6, // 20 mins parallelHash: 100, // number of parallel hashing calls - parallelUpload: 4, // number of files to upload in parallel + parallelUpload: 15, // number of files to upload in parallel maxRetry: 5, // number of times to try on failed file uploads - filter: filename => { /* return false to filter a file from the deploy */ }, - tmpDir: tempy.directory(), // a temporary directory to zip loose files into + filter: filepath => { /* return false to filter a file from the deploy */ }, + tmpDir: tempy.directory(), // a temporary directory to zip functions into statusCb: statusObj => { // a callback function to receive status events /* statusObj: { diff --git a/src/deploy/hash-files.js b/src/deploy/hash-files.js index c506bcd..dc7ab16 100644 --- a/src/deploy/hash-files.js +++ b/src/deploy/hash-files.js @@ -4,7 +4,7 @@ const pump = promisify(require('pump')) const { hasherCtor, manifestCollectorCtor, fileFilterCtor, fileNormalizerCtor } = require('./hasher-segments') module.exports = hashFiles -async function hashFiles(dir, tomlPath, opts) { +async function hashFiles(dir, configPath, opts) { opts = Object.assign( { concurrentHash: 100, @@ -15,7 +15,7 @@ async function hashFiles(dir, tomlPath, opts) { ) if (!opts.filter) throw new Error('Missing filter function option') - const fileStream = walker([tomlPath, dir], { filter: opts.filter }) + const fileStream = walker([configPath, dir], { filter: opts.filter }) const filter = fileFilterCtor() const hasher = hasherCtor(opts) const fileNormalizer = fileNormalizerCtor(opts) diff --git a/src/deploy/index.js b/src/deploy/index.js index 9fb8a6e..5f6d446 100644 --- a/src/deploy/index.js +++ b/src/deploy/index.js @@ -11,7 +11,7 @@ module.exports = async (api, siteId, dir, opts) => { opts = Object.assign( { fnDir: null, - tomlPath: null, + configPath: null, draft: false, message: undefined, // API calls this the 'title' tmpDir: tempy.directory(), @@ -34,7 +34,7 @@ module.exports = async (api, siteId, dir, opts) => { opts ) - const { fnDir, tomlPath, statusCb, message: title } = opts + const { fnDir, configPath, statusCb, message: title } = opts statusCb({ type: 'hashing', @@ -43,7 +43,7 @@ module.exports = async (api, siteId, dir, opts) => { }) const [{ files, filesShaMap }, { functions, fnShaMap }] = await Promise.all([ - hashFiles(dir, tomlPath, opts), + hashFiles(dir, configPath, opts), hashFns(fnDir, opts) ]) From c3e3c124f1b548bce2df09bddda7db5f8017fb74 Mon Sep 17 00:00:00 2001 From: Bret Comnes Date: Tue, 25 Sep 2018 10:22:47 -0700 Subject: [PATCH 3/4] MD formatting. --- CONTRIBUTING.md | 12 ++++-------- README.md | 28 +++++++++------------------- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 01560c0..d86f8c4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,6 @@ # CONTRIBUTING -Contributions are always welcome, no matter how large or small. Before contributing, -please read the [code of conduct](CODE_OF_CONDUCT.md). +Contributions are always welcome, no matter how large or small. Before contributing, please read the [code of conduct](CODE_OF_CONDUCT.md). ## Setup @@ -18,8 +17,7 @@ You can also use yarn. ## Testing -This repo uses [ava](https://github.com/avajs/ava) for testing. -Any files in the `src` directory that have a `.test.js` file extension are automatically detected and run as tests. +This repo uses [ava](https://github.com/avajs/ava) for testing. Any files in the `src` directory that have a `.test.js` file extension are automatically detected and run as tests. We also test for a few other variables: @@ -30,11 +28,9 @@ We also test for a few other variables: ## Architecture -We target Node.js LTS and stable environments, and aim for basic modern browser support when possible. -In order to facilitate simple contributions, we avoided any kind of build steps. +We target Node.js LTS and stable environments, and aim for basic modern browser support when possible. In order to facilitate simple contributions, we avoided any kind of build steps. -If you need to add new API routes, please add them to the [open-api](https://github.com/netlify/open-api) repo. -This client will automatically inherent the new routes from that module. +If you need to add new API routes, please add them to the [open-api](https://github.com/netlify/open-api) repo. This client will automatically inherent the new routes from that module. Projects that depend heavily on this client that should be taken into consideration when making changes: diff --git a/README.md b/README.md index 6587fac..ab79724 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,7 @@ Create a new instance of the Netlify API client with the provided `accessToken`. ### `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 newly set `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 newly set `accessToken`. ### `client.basePath` @@ -44,22 +43,17 @@ A getter that returns the formatted base URL of the endpoint the client is confi ### 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 operations see the [open-api website](https://open-api.netlify.com/)**. +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 operations 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. +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. +- `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 @@ -72,8 +66,7 @@ If the endpoint accepts `binary`, `params.body` can be a Node.js readable stream } ``` -Optional `opts` can include any property you want passed to `node-fetch`. -The `headers` property is merged with some `defaultHeaders`. +Optional `opts` can include any property you want passed to `node-fetch`. The `headers` property is merged with some `defaultHeaders`. ```js // example opts @@ -102,8 +95,7 @@ async function getSomeData () { } ``` -If the request response includes `json` in the `contentType` header, fetch will deserialize the JSON body. -Otherwise the `text` of the response is returned. +If the request response includes `json` in the `contentType` header, fetch will deserialize the JSON body. Otherwise the `text` of the response is returned. ### API Flow Methods @@ -111,9 +103,7 @@ Some methods have been added in addition to the open API methods that make certa #### `promise(accessToken) = client.getAccessToken(ticket, [opts])` -Pass in a [`ticket`](https://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. +Pass in a [`ticket`](https://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: From b56c3c038d371d575a2a109de15a48d304f30aed Mon Sep 17 00:00:00 2001 From: Bret Comnes Date: Tue, 25 Sep 2018 10:25:02 -0700 Subject: [PATCH 4/4] Grammar --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d86f8c4..38f3576 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,11 +19,11 @@ You can also use yarn. This repo uses [ava](https://github.com/avajs/ava) for testing. Any files in the `src` directory that have a `.test.js` file extension are automatically detected and run as tests. -We also test for a few other variables: +We also test for a few other things: - Dependencies (used an unused) - Linting -- Coverage +- Test coverage - Must work with Windows + Unix environments. ## Architecture