From 28d4f6ef4718bc3d8a2885f5edcd51cb935e75eb Mon Sep 17 00:00:00 2001 From: Theo Ephraim Date: Fri, 27 Nov 2020 12:41:56 -0800 Subject: [PATCH] create new doc functionality, readme updates --- README.md | 13 +++++++++++-- docs/README.md | 15 ++++++++++++--- docs/classes/google-spreadsheet.md | 28 ++++++++++++++++++++++++++++ docs/index.html | 2 +- lib/GoogleSpreadsheet.js | 19 ++++++++++++++++++- test/manage.test.js | 30 ++++++++++++++++++++++++++++-- 6 files changed, 98 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index fc2df7f..a516e77 100644 --- a/README.md +++ b/README.md @@ -16,18 +16,27 @@ Full docs available at [https://theoephraim.github.io/node-google-spreadsheet](h > **🚨 Google Deprecation Warning - affects older version (v2) of this module 🚨** > -> Google is [phasing out their old v3 api](https://cloud.google.com/blog/products/g-suite/migrate-your-apps-use-latest-sheets-api), which the older version of this module used to use. Originally they were going to shut it down on March 3rd 2020, but have pushed that date back to September 30th. +> Google is [phasing out their old v3 api](https://cloud.google.com/blog/products/g-suite/migrate-your-apps-use-latest-sheets-api), which the older version of this module used to use. Originally they were going to shut it down on March 3rd 2020, but have pushed that date back to January 2021. **Regardless, please upgrade to the latest version of this module (v3) which uses the newer sheets v4 API** ------------- -> 🌈 **Installation** - `npm i google-spreadsheet --save` +> 🌈 **Installation** - `npm i google-spreadsheet --save` or `yarn add google-spreadsheet` ## Examples _the following examples are meant to give you an idea of just some of the things you can do_ +!> NOTE - To keep the examples more concise, I'm calling await [at the top level](https://v8.dev/features/top-level-await) which is not allowed by default in most versions of node. If you need to call await in a script at the root level, you must instead wrap it in an async function like so: + +```javascript +(async function() { + await someAsyncFunction(); +}()); +``` + + ### The Basics ```javascript const { GoogleSpreadsheet } = require('google-spreadsheet'); diff --git a/docs/README.md b/docs/README.md index 68c0673..b5d11e9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -19,18 +19,27 @@ Full docs available at [https://theoephraim.github.io/node-google-spreadsheet](h > **🚨 Google Deprecation Warning - affects older version (v2) of this module 🚨** > -> Google is [phasing out their old v3 api](https://cloud.google.com/blog/products/g-suite/migrate-your-apps-use-latest-sheets-api), which the older version of this module used to use. Originally they were going to shut it down on March 3rd 2020, but have pushed that date back to September 30th. +> Google is [phasing out their old v3 api](https://cloud.google.com/blog/products/g-suite/migrate-your-apps-use-latest-sheets-api), which the older version of this module used to use. Originally they were going to shut it down on March 3rd 2020, but have pushed that date back to January 2021. **Regardless, please upgrade to the latest version of this module (v3) which uses the newer sheets v4 API** ------------- -> 🌈 **Installation** - `npm i google-spreadsheet --save` +> 🌈 **Installation** - `npm i google-spreadsheet --save` or `yarn add google-spreadsheet` ## Examples _the following examples are meant to give you an idea of just some of the things you can do_ +!> NOTE - To keep the examples more concise, I'm calling await [at the top level](https://v8.dev/features/top-level-await) which is not allowed by default in most versions of node. If you need to call await in a script at the root level, you must instead wrap it in an async function like so: + +```javascript +(async function() { + await someAsyncFunction(); +}()); +``` + + ### The Basics ```javascript const { GoogleSpreadsheet } = require('google-spreadsheet'); @@ -54,7 +63,7 @@ await doc.loadInfo(); // loads document properties and worksheets console.log(doc.title); await doc.updateProperties({ title: 'renamed doc' }); -const sheet = doc.sheetsByIndex[0]; // or use doc.sheetsById[id] +const sheet = doc.sheetsByIndex[0]; // or use doc.sheetsById[id] or doc.sheetsByTitle[title] console.log(sheet.title); console.log(sheet.rowCount); diff --git a/docs/classes/google-spreadsheet.md b/docs/classes/google-spreadsheet.md index 1cb0856..1c0d738 100644 --- a/docs/classes/google-spreadsheet.md +++ b/docs/classes/google-spreadsheet.md @@ -14,6 +14,34 @@ Param|Type|Description ---|---|--- `spreadsheetId`|String|Document ID from the URL of the spreadsheet + +### Creating a new document +Normally you will be working with an existing spreasheet document. However if you need to create a new one, you can accomplish this by initializing the GoogleSpreadsheet object without an id, initializing your preferred auth method, and then calling the following method. + +As this will create the document owned by the auth method you are using (which is often a service account), it may not be accessible to your google account. Therefore if it recommended to create documents ahead of time if possible rather than using this method. + +#### `createNewSpreadsheetDocument(properties)` :id=fn-createNewSpreadsheetDocument +> Create a new google spreadsheet document + +!> You must initialize the GoogleSpreadsheet without an id in order to call this method + +Param|Type|Required|Description +---|---|---|--- +`properties`|Object|-|Properties to use when creating the new doc + +See [basic document properties](#basic-document-properties) above for props documentation. + +- 🚨 **Warning** - The document will be owned by the authenticated user, which is a service account, may not be accessible to you personally. +- ✨ **Side effects** - all info (including `spreadsheetId`) and sheets loaded as if you called [`loadInfo()`](#fn-loadInfo) + +```javascript +const doc = new GoogleSpreadsheet(); +await doc.useServiceAccountAuth(creds); +await doc.createNewSpreadsheetDocument({ title: 'This is a new doc' }); +console.log(doc.spreadsheetId); +const sheet1 = doc.sheetsByIndex[0]; +``` + ## Properties ### Basic Document Properties diff --git a/docs/index.html b/docs/index.html index 0f3d9b5..5cfac8b 100644 --- a/docs/index.html +++ b/docs/index.html @@ -64,7 +64,7 @@ name: 'google-spreadsheet', repo: 'https://github.com/theoephraim/node-google-spreadsheet', loadSidebar: true, - subMaxLevel: 3, + subMaxLevel: 4, } diff --git a/lib/GoogleSpreadsheet.js b/lib/GoogleSpreadsheet.js index 7b5833b..a792bcd 100644 --- a/lib/GoogleSpreadsheet.js +++ b/lib/GoogleSpreadsheet.js @@ -31,7 +31,7 @@ class GoogleSpreadsheet { // create an axios instance with sheet root URL and interceptors to handle auth this.axios = Axios.create({ - baseURL: `https://sheets.googleapis.com/v4/spreadsheets/${sheetId}`, + baseURL: `https://sheets.googleapis.com/v4/spreadsheets/${sheetId || ''}`, // send arrays in params with duplicate keys - ie `?thing=1&thing=2` vs `?thing[]=1...` // solution taken from https://github.com/axios/axios/issues/604 paramsSerializer(params) { @@ -59,6 +59,23 @@ class GoogleSpreadsheet { return this; } + // CREATE NEW DOC //////////////////////////////////////////////////////////////////////////////// + async createNewSpreadsheetDocument(properties) { + // see updateProperties for more info about available properties + + if (this.spreadsheetId) { + throw new Error('Only call `createNewSpreadsheetDocument()` on a GoogleSpreadsheet object that has no spreadsheetId set'); + } + const response = await this.axios.post(this.url, { + properties, + }); + this.spreadsheetId = response.data.spreadsheetId; + this.axios.defaults.baseURL += this.spreadsheetId; + + this._rawProperties = response.data.properties; + _.each(response.data.sheets, (s) => this._updateOrCreateSheet(s)); + } + // AUTH RELATED FUNCTIONS //////////////////////////////////////////////////////////////////////// async useApiKey(key) { this.authMode = AUTH_MODES.API_KEY; diff --git a/test/manage.test.js b/test/manage.test.js index 03b53ff..59adc4e 100644 --- a/test/manage.test.js +++ b/test/manage.test.js @@ -1,7 +1,7 @@ const delay = require('delay'); const _ = require('lodash'); -const { GoogleSpreadsheetWorksheet } = require('../index.js'); +const { GoogleSpreadsheet, GoogleSpreadsheetWorksheet } = require('../index.js'); const docs = require('./load-test-docs')(); const creds = require('./service-account-creds.json'); @@ -190,7 +190,7 @@ describe('Managing doc info and sheets', () => { }); }); afterAll(async () => { - sheet.delete(); + await sheet.delete(); }); it('should fail without proper permissions', async () => { @@ -212,4 +212,30 @@ describe('Managing doc info and sheets', () => { await copiedSheet.delete(); }); }); + + describe('creating a new document', () => { + let newDoc; + + afterAll(async () => { + await newDoc.delete(); + }); + + it('should fail if GoogleSpreadsheet was initialized with an ID', async () => { + newDoc = new GoogleSpreadsheet('someid'); + await expect(newDoc.createNewSpreadsheetDocument()).rejects.toThrow(); + }); + it('should fail without auth', async () => { + newDoc = new GoogleSpreadsheet(); + await expect(newDoc.createNewSpreadsheetDocument()).rejects.toThrow(); + }); + it('should create a new sheet', async () => { + newDoc = new GoogleSpreadsheet(); + newDoc.useServiceAccountAuth(creds); + const newTitle = `New doc ${+new Date()}`; + await newDoc.createNewSpreadsheetDocument({ title: newTitle }); + expect(newDoc.title).toEqual(newTitle); + expect(newDoc.sheetsByIndex.length > 0).toBeTruthy(); + expect(newDoc.sheetsByIndex[0]).toBeInstanceOf(GoogleSpreadsheetWorksheet); + }); + }); });