google-spreadsheet 3.2.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,29 +1,24 @@
1
1
  # google-spreadsheet
2
- > The most popular [Google Sheets API](https://developers.google.com/sheets/api/reference/rest) wrapper for javascript
2
+ > The most popular [Google Sheets API](https://developers.google.com/sheets/api/guides/concepts) wrapper for javascript / typescript
3
3
 
4
4
  [![NPM version](https://img.shields.io/npm/v/google-spreadsheet)](https://www.npmjs.com/package/google-spreadsheet)
5
5
  [![CircleCI](https://circleci.com/gh/theoephraim/node-google-spreadsheet.svg?style=shield)](https://circleci.com/gh/theoephraim/node-google-spreadsheet)
6
6
  [![Known Vulnerabilities](https://snyk.io/test/github/theoephraim/node-google-spreadsheet/badge.svg?targetFile=package.json)](https://snyk.io/test/github/theoephraim/node-google-spreadsheet?targetFile=package.json)
7
7
  [![NPM](https://img.shields.io/npm/dw/google-spreadsheet)](https://www.npmtrends.com/google-spreadsheet)
8
8
 
9
- - multiple auth options - service account (w/ optional impersonation), OAuth 2.0, API key (read-only)
9
+ - multiple auth options (via [google-auth-library](https://www.npmjs.com/package/google-auth-library)) - service account, OAuth, API key, ADC, etc
10
10
  - cell-based API - read, write, bulk-updates, formatting
11
11
  - row-based API - read, update, delete (based on the old v3 row-based calls)
12
- - managing worksheets - add, remove, resize, change title, formatting
12
+ - managing worksheets - add, remove, resize, change title, formatting, duplicate, copy to other sheet
13
+ - managing docs - create new doc, delete doc, basic sharing/permissions
14
+ - export - download sheet/docs in various formats
13
15
 
14
16
  **Docs site -**
15
17
  Full docs available at [https://theoephraim.github.io/node-google-spreadsheet](https://theoephraim.github.io/node-google-spreadsheet)
16
18
 
17
- > **🚨 Google Deprecation Warning - affects older version (v2) of this module 🚨**
18
- >
19
- > 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. Originally they were going to shut it down on March 3rd 2020, but have pushed that date back to June 2021.
20
-
21
-
22
- **Regardless, please upgrade to the latest version of this module (v3) which uses the newer sheets v4 API**
23
-
24
19
  -------------
25
20
 
26
- > 🌈 **Installation** - `npm i google-spreadsheet --save` or `yarn add google-spreadsheet`
21
+ > 🌈 **Installation** - `pnpm i google-spreadsheet` (or `npm i google-spreadsheet --save` or `yarn add google-spreadsheet`)
27
22
 
28
23
  ## Examples
29
24
  _the following examples are meant to give you an idea of just some of the things you can do_
@@ -38,42 +33,46 @@ _the following examples are meant to give you an idea of just some of the things
38
33
 
39
34
 
40
35
  ### The Basics
41
- ```javascript
42
- const { GoogleSpreadsheet } = require('google-spreadsheet');
36
+ ```js
37
+ import { GoogleSpreadsheet } = from 'google-spreadsheet';
38
+ import { JWT } from 'google-auth-library'
43
39
 
44
- // Initialize the sheet - doc ID is the long id in the sheets URL
45
- const doc = new GoogleSpreadsheet('<the sheet ID from the url>');
46
40
 
47
- // Initialize Auth - see https://theoephraim.github.io/node-google-spreadsheet/#/getting-started/authentication
48
- await doc.useServiceAccountAuth({
49
- // env var values are copied from service account credentials generated by google
41
+ // Initialize auth - see https://theoephraim.github.io/node-google-spreadsheet/#/guides/authentication
42
+ const serviceAccountAuth = new JWT({
43
+ // env var values here are copied from service account credentials generated by google
50
44
  // see "Authentication" section in docs for more info
51
- client_email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
52
- private_key: process.env.GOOGLE_PRIVATE_KEY,
45
+ email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
46
+ key: process.env.GOOGLE_PRIVATE_KEY,
47
+ scopes: [
48
+ 'https://www.googleapis.com/auth/spreadsheets',
49
+ ],
53
50
  });
54
51
 
52
+ const doc = new GoogleSpreadsheet('<the sheet ID from the url>', serviceAccountAuth);
53
+
55
54
  await doc.loadInfo(); // loads document properties and worksheets
56
55
  console.log(doc.title);
57
56
  await doc.updateProperties({ title: 'renamed doc' });
58
57
 
59
- const sheet = doc.sheetsByIndex[0]; // or use doc.sheetsById[id] or doc.sheetsByTitle[title]
58
+ const sheet = doc.sheetsByIndex[0]; // or use `doc.sheetsById[id]` or `doc.sheetsByTitle[title]`
60
59
  console.log(sheet.title);
61
60
  console.log(sheet.rowCount);
62
61
 
63
62
  // adding / removing sheets
64
- const newSheet = await doc.addSheet({ title: 'hot new sheet!' });
63
+ const newSheet = await doc.addSheet({ title: 'another sheet' });
65
64
  await newSheet.delete();
66
65
  ```
67
66
  More info:
68
67
  - [GoogleSpreadsheet](https://theoephraim.github.io/node-google-spreadsheet/#/classes/google-spreadsheet)
69
68
  - [GoogleSpreadsheetWorksheet](https://theoephraim.github.io/node-google-spreadsheet/#/classes/google-spreadsheet-worksheet)
70
- - [Authentication](https://theoephraim.github.io/node-google-spreadsheet/#/getting-started/authentication)
69
+ - [Authentication](https://theoephraim.github.io/node-google-spreadsheet/#/guides/authentication)
71
70
 
72
71
 
73
72
 
74
73
  ### Working with rows
75
- ```javascript
76
- // create a sheet and set the header row
74
+ ```js
75
+ // if creating a new sheet, you can set the header row
77
76
  const sheet = await doc.addSheet({ headerValues: ['name', 'email'] });
78
77
 
79
78
  // append rows
@@ -87,11 +86,27 @@ const moreRows = await sheet.addRows([
87
86
  const rows = await sheet.getRows(); // can pass in { limit, offset }
88
87
 
89
88
  // read/write row values
90
- console.log(rows[0].name); // 'Larry Page'
91
- rows[1].email = 'sergey@abc.xyz'; // update a value
92
- await rows[1].save(); // save updates
93
- await rows[1].delete(); // delete a row
89
+ console.log(rows[0].get('name')); // 'Larry Page'
90
+ rows[1].set('email') = 'sergey@abc.xyz'; // update a value
91
+ rows[2].assign({ name: 'Sundar Pichai', email: 'sundar@google.com' }); // set multiple values
92
+ await rows[2].save(); // save updates on a row
93
+ await rows[2].delete(); // delete a row
94
+ ```
95
+
96
+ Row methods support explicit TypeScript types for shape of the data
97
+
98
+ ```typescript
99
+ type UsersRowData = {
100
+ name: string;
101
+ email: string;
102
+ type?: 'admin' | 'user';
103
+ };
104
+ const userRows = await sheet.getRows<UsersRowData>();
105
+
106
+ userRows[0].get('name'); // <- TS is happy, knows it will be a string
107
+ userRows[0].get('badColumn'); // <- will throw a type error
94
108
  ```
109
+
95
110
  More info:
96
111
  - [GoogleSpreadsheetWorksheet > Working With Rows](https://theoephraim.github.io/node-google-spreadsheet/#/classes/google-spreadsheet-worksheet#working-with-rows)
97
112
  - [GoogleSpreadsheetRow](https://theoephraim.github.io/node-google-spreadsheet/#/classes/google-spreadsheet-row)
@@ -99,8 +114,8 @@ More info:
99
114
 
100
115
 
101
116
  ### Working with cells
102
- ```javascript
103
- await sheet.loadCells('A1:E10'); // loads a range of cells
117
+ ```js
118
+ await sheet.loadCells('A1:E10'); // loads range of cells into local cache - DOES NOT RETURN THE CELLS
104
119
  console.log(sheet.cellStats); // total cells, loaded, how many non-empty
105
120
  const a1 = sheet.getCell(0, 0); // access cells using a zero-based index
106
121
  const c6 = sheet.getCellByA1('C6'); // or A1 style notation
@@ -120,15 +135,39 @@ More info:
120
135
  - [GoogleSpreadsheetCell](https://theoephraim.github.io/node-google-spreadsheet/#/classes/google-spreadsheet-cell)
121
136
 
122
137
 
138
+ ### Managing docs and sharing
139
+
140
+ ```js
141
+ const auth = new JWT({
142
+ email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
143
+ key: process.env.GOOGLE_PRIVATE_KEY,
144
+ scopes: [
145
+ 'https://www.googleapis.com/auth/spreadsheets',
146
+ // note that sharing-related calls require the google drive scope
147
+ 'https://www.googleapis.com/auth/drive.file',
148
+ ],
149
+ });
150
+
151
+ // create a new doc
152
+ const newDoc = await GoogleSpreadsheet.createNewSpreadsheetDocument(auth, { title: 'new fancy doc' });
153
+
154
+ // share with specific users, domains, or make public
155
+ await newDoc.share('someone.else@example.com');
156
+ await newDoc.share('mycorp.com');
157
+ await newDoc.setPublicAccessLevel('reader');
158
+
159
+ // delete doc
160
+ await newDoc.delete();
161
+ ```
123
162
 
124
163
  ## Why?
125
164
  > **This module provides an intuitive wrapper around Google's API to simplify common interactions**
126
165
 
127
- While Google's v4 sheets api is much easier to use than v3 was, the official [googleapis npm module](https://www.npmjs.com/package/googleapis) is a giant meta-tool that handles _every Google product_. The module and the API itself are awkward and the docs are pretty terrible, at least to get started.
166
+ While Google's v4 sheets api is much easier to use than v3 was, the official [googleapis npm module](https://www.npmjs.com/package/googleapis) is a giant autogenerated meta-tool that handles _every Google product_. The module and the API itself are awkward and the docs are pretty terrible, at least to get started.
128
167
 
129
168
  **In what situation should you use Google's API directly?**<br>
130
169
  This module makes trade-offs for simplicity of the interface.
131
- Google's API provides a mechanism to make many requests in parallel, so if speed and efficiency is extremely important to your use case, you may want to use their API directly. There are also several features of their API that are not implemented here yet.
170
+ Google's API provides a mechanism to make many requests in parallel, so if speed and efficiency is extremely important to your use case, you may want to use their API directly. There are also many lesser-used features of their API that are not implemented here yet.
132
171
 
133
172
 
134
173
  ## Support & Contributions
@@ -138,11 +177,11 @@ This module was written and is actively maintained by [Theo Ephraim](https://the
138
177
  **Are you actively using this module for a commercial project? Want to help support it?**<br>
139
178
  [Buy Theo a beer](https://paypal.me/theoephraim)
140
179
 
141
- #### Sponsors
180
+ ### Sponsors
142
181
 
143
182
  None yet - get in touch!
144
183
 
145
- #### Contributing
184
+ ### Contributing
146
185
 
147
186
  Contributions are welcome, but please follow the existing conventions, use the linter, add relevant tests, add relevant documentation.
148
187
 
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";const a=require("lodash-es"),p=require("axios");function _interopDefaultCompat(i){return i&&typeof i=="object"&&"default"in i?i.default:i}function _interopNamespaceCompat(i){if(i&&typeof i=="object"&&"default"in i)return i;const e=Object.create(null);if(i)for(const t in i)e[t]=i[t];return e.default=i,e}const a__namespace=_interopNamespaceCompat(a),p__default=_interopDefaultCompat(p);function getFieldMask(i){return Object.keys(i).join(",")}function columnToLetter(i){let e,t="",r=i;for(;r>0;)e=(r-1)%26,t=String.fromCharCode(e+65)+t,r=(r-e-1)/26;return t}function letterToColumn(i){let e=0;const{length:t}=i;for(let r=0;r<t;r++)e+=(i.charCodeAt(r)-64)*26**(t-r-1);return e}function axiosParamsSerializer(i){let e="";return Object.keys(i).forEach(t=>{const r=typeof i[t]=="object",s=r&&i[t].length>=0;if(r||(e+=`${t}=${encodeURIComponent(i[t])}&`),r&&s)for(const o of i[t])e+=`${t}=${encodeURIComponent(o)}&`}),e&&e.slice(0,-1)}function checkForDuplicateHeaders(i){const e=a__namespace.groupBy(i);a__namespace.each(e,(t,r)=>{if(r&&t.length>1)throw new Error(`Duplicate header detected: "${r}". Please make sure all non-empty headers are unique`)})}class GoogleSpreadsheetRow{constructor(e,t,r){this._worksheet=e,this._rowNumber=t,this._rawData=r,this._deleted=!1}get deleted(){return this._deleted}get rowNumber(){return this._rowNumber}get a1Range(){return[this._worksheet.a1SheetName,"!",`A${this._rowNumber}`,":",`${columnToLetter(this._worksheet.headerValues.length)}${this._rowNumber}`].join("")}get(e){const t=this._worksheet.headerValues.indexOf(e);return this._rawData[t]}set(e,t){const r=this._worksheet.headerValues.indexOf(e);this._rawData[r]=t}assign(e){for(const t in e)this.set(t,e[t])}toObject(){const e={};for(let t=0;t<this._worksheet.headerValues.length;t++){const r=this._worksheet.headerValues[t];r&&(e[r]=this._rawData[t])}return e}async save(e){if(this._deleted)throw new Error("This row has been deleted - call getRows again before making updates.");const t=await this._worksheet._spreadsheet.sheetsApi.request({method:"put",url:`/values/${encodeURIComponent(this.a1Range)}`,params:{valueInputOption:e?.raw?"RAW":"USER_ENTERED",includeValuesInResponse:!0},data:{range:this.a1Range,majorDimension:"ROWS",values:[this._rawData]}});this._rawData=t.data.updatedData.values[0]}async delete(){if(this._deleted)throw new Error("This row has been deleted - call getRows again before making updates.");const e=await this._worksheet._makeSingleUpdateRequest("deleteRange",{range:{sheetId:this._worksheet.sheetId,startRowIndex:this._rowNumber-1,endRowIndex:this._rowNumber},shiftDimension:"ROWS"});return this._deleted=!0,e}}class GoogleSpreadsheetCellErrorValue{constructor(e){this.type=e.type,this.message=e.message}}class GoogleSpreadsheetCell{constructor(e,t,r,s){this._sheet=e,this._rowIndex=t,this._columnIndex=r,this._draftData={},this._updateRawData(s),this._rawData=s}_updateRawData(e){this._rawData=e,this._draftData={},this._rawData?.effectiveValue&&"errorValue"in this._rawData.effectiveValue?this._error=new GoogleSpreadsheetCellErrorValue(this._rawData.effectiveValue.errorValue):this._error=void 0}get rowIndex(){return this._rowIndex}get columnIndex(){return this._columnIndex}get a1Column(){return columnToLetter(this._columnIndex+1)}get a1Row(){return this._rowIndex+1}get a1Address(){return`${this.a1Column}${this.a1Row}`}get value(){if(this._draftData.value!==void 0)throw new Error("Value has been changed");return this._error?this._error:this._rawData?.effectiveValue?a__namespace.values(this._rawData.effectiveValue)[0]:null}set value(e){if(e instanceof GoogleSpreadsheetCellErrorValue)throw new Error("You can't manually set a value to an error");if(a__namespace.isBoolean(e))this._draftData.valueType="boolValue";else if(a__namespace.isString(e))e.substring(0,1)==="="?this._draftData.valueType="formulaValue":this._draftData.valueType="stringValue";else if(a__namespace.isFinite(e))this._draftData.valueType="numberValue";else if(a__namespace.isNil(e))this._draftData.valueType="stringValue",e="";else throw new Error("Set value to boolean, string, or number");this._draftData.value=e}get valueType(){return this._error?"errorValue":this._rawData?.effectiveValue?a__namespace.keys(this._rawData.effectiveValue)[0]:null}get formattedValue(){return this._rawData?.formattedValue||null}get formula(){return a__namespace.get(this._rawData,"userEnteredValue.formulaValue",null)}set formula(e){if(!e)throw new Error("To clear a formula, set `cell.value = null`");if(e.substring(0,1)!=="=")throw new Error('formula must begin with "="');this.value=e}get formulaError(){return this._error}get errorValue(){return this._error}get numberValue(){if(this.valueType==="numberValue")return this.value}set numberValue(e){this.value=e}get boolValue(){if(this.valueType==="boolValue")return this.value}set boolValue(e){this.value=e}get stringValue(){if(this.valueType==="stringValue")return this.value}set stringValue(e){if(e?.startsWith("="))throw new Error("Use cell.formula to set formula values");this.value=e}get hyperlink(){if(this._draftData.value)throw new Error("Save cell to be able to read hyperlink");return this._rawData?.hyperlink}get note(){return this._draftData.note!==void 0?this._draftData.note:this._rawData?.note}set note(e){if((e==null||e===!1)&&(e=""),!a__namespace.isString(e))throw new Error("Note must be a string");e===this._rawData?.note?delete this._draftData.note:this._draftData.note=e}get userEnteredFormat(){return Object.freeze(this._rawData?.userEnteredFormat)}get effectiveFormat(){return Object.freeze(this._rawData?.effectiveFormat)}_getFormatParam(e){if(a__namespace.get(this._draftData,`userEnteredFormat.${e}`))throw new Error("User format is unsaved - save the cell to be able to read it again");return Object.freeze(this._rawData.userEnteredFormat[e])}_setFormatParam(e,t){a__namespace.isEqual(t,a__namespace.get(this._rawData,`userEnteredFormat.${e}`))?a__namespace.unset(this._draftData,`userEnteredFormat.${e}`):(a__namespace.set(this._draftData,`userEnteredFormat.${e}`,t),this._draftData.clearFormat=!1)}get numberFormat(){return this._getFormatParam("numberFormat")}get backgroundColor(){return this._getFormatParam("backgroundColor")}get backgroundColorStyle(){return this._getFormatParam("backgroundColorStyle")}get borders(){return this._getFormatParam("borders")}get padding(){return this._getFormatParam("padding")}get horizontalAlignment(){return this._getFormatParam("horizontalAlignment")}get verticalAlignment(){return this._getFormatParam("verticalAlignment")}get wrapStrategy(){return this._getFormatParam("wrapStrategy")}get textDirection(){return this._getFormatParam("textDirection")}get textFormat(){return this._getFormatParam("textFormat")}get hyperlinkDisplayType(){return this._getFormatParam("hyperlinkDisplayType")}get textRotation(){return this._getFormatParam("textRotation")}set numberFormat(e){this._setFormatParam("numberFormat",e)}set backgroundColor(e){this._setFormatParam("backgroundColor",e)}set backgroundColorStyle(e){this._setFormatParam("backgroundColorStyle",e)}set borders(e){this._setFormatParam("borders",e)}set padding(e){this._setFormatParam("padding",e)}set horizontalAlignment(e){this._setFormatParam("horizontalAlignment",e)}set verticalAlignment(e){this._setFormatParam("verticalAlignment",e)}set wrapStrategy(e){this._setFormatParam("wrapStrategy",e)}set textDirection(e){this._setFormatParam("textDirection",e)}set textFormat(e){this._setFormatParam("textFormat",e)}set hyperlinkDisplayType(e){this._setFormatParam("hyperlinkDisplayType",e)}set textRotation(e){this._setFormatParam("textRotation",e)}clearAllFormatting(){this._draftData.clearFormat=!0,delete this._draftData.userEnteredFormat}get _isDirty(){return!!(this._draftData.note!==void 0||a__namespace.keys(this._draftData.userEnteredFormat).length||this._draftData.clearFormat||this._draftData.value!==void 0)}discardUnsavedChanges(){this._draftData={}}async save(){await this._sheet.saveCells([this])}_getUpdateRequest(){const e=this._draftData.value!==void 0,t=this._draftData.note!==void 0,r=!!a__namespace.keys(this._draftData.userEnteredFormat||{}).length,s=this._draftData.clearFormat;if(!a__namespace.some([e,t,r,s]))return null;const o={...this._rawData?.userEnteredFormat,...this._draftData.userEnteredFormat};return a__namespace.get(this._draftData,"userEnteredFormat.backgroundColor")&&delete o.backgroundColorStyle,{updateCells:{rows:[{values:[{...e&&{userEnteredValue:{[this._draftData.valueType]:this._draftData.value}},...t&&{note:this._draftData.note},...r&&{userEnteredFormat:o},...s&&{userEnteredFormat:{}}}]}],fields:a__namespace.keys(a__namespace.pickBy({userEnteredValue:e,note:t,userEnteredFormat:r||s})).join(","),start:{sheetId:this._sheet.sheetId,rowIndex:this.rowIndex,columnIndex:this.columnIndex}}}}}class GoogleSpreadsheetWorksheet{constructor(e,t,r){this._spreadsheet=e,this._headerRowIndex=1,this._rawProperties=null,this._cells=[],this._rowMetadata=[],this._columnMetadata=[],this._headerRowIndex=1,this._rawProperties=t,this._cells=[],this._rowMetadata=[],this._columnMetadata=[],r&&this._fillCellData(r)}get headerValues(){if(!this._headerValues)throw new Error("Header values are not yet loaded");return this._headerValues}updateRawData(e,t){this._rawProperties=e,this._fillCellData(t)}async _makeSingleUpdateRequest(e,t){return this._spreadsheet._makeSingleUpdateRequest(e,{...t})}_ensureInfoLoaded(){if(!this._rawProperties)throw new Error("You must call `doc.loadInfo()` again before accessing this property")}resetLocalCache(e){e||(this._rawProperties=null),this._headerValues=void 0,this._headerRowIndex=1,this._cells=[]}_fillCellData(e){a__namespace.each(e,t=>{const r=t.startRow||0,s=t.startColumn||0,o=t.rowMetadata.length,d=t.columnMetadata.length;for(let n=0;n<o;n++){const h=r+n;for(let l=0;l<d;l++){const m=s+l;this._cells[h]||(this._cells[h]=[]);const w=a__namespace.get(t,`rowData[${n}].values[${l}]`);this._cells[h][m]?this._cells[h][m]._updateRawData(w):this._cells[h][m]=new GoogleSpreadsheetCell(this,h,m,w)}}for(let n=0;n<t.rowMetadata.length;n++)this._rowMetadata[r+n]=t.rowMetadata[n];for(let n=0;n<t.columnMetadata.length;n++)this._columnMetadata[s+n]=t.columnMetadata[n]})}_addSheetIdToRange(e){if(e.sheetId&&e.sheetId!==this.sheetId)throw new Error("Leave sheet ID blank or set to matching ID of this sheet");return{...e,sheetId:this.sheetId}}_getProp(e){return this._ensureInfoLoaded(),this._rawProperties[e]}_setProp(e,t){throw new Error("Do not update directly - use `updateProperties()`")}get sheetId(){return this._getProp("sheetId")}get title(){return this._getProp("title")}get index(){return this._getProp("index")}get sheetType(){return this._getProp("sheetType")}get gridProperties(){return this._getProp("gridProperties")}get hidden(){return this._getProp("hidden")}get tabColor(){return this._getProp("tabColor")}get rightToLeft(){return this._getProp("rightToLeft")}set sheetId(e){this._setProp("sheetId",e)}set title(e){this._setProp("title",e)}set index(e){this._setProp("index",e)}set sheetType(e){this._setProp("sheetType",e)}set gridProperties(e){this._setProp("gridProperties",e)}set hidden(e){this._setProp("hidden",e)}set tabColor(e){this._setProp("tabColor",e)}set rightToLeft(e){this._setProp("rightToLeft",e)}get rowCount(){return this._ensureInfoLoaded(),this.gridProperties.rowCount}get columnCount(){return this._ensureInfoLoaded(),this.gridProperties.columnCount}get a1SheetName(){return`'${this.title.replace(/'/g,"''")}'`}get encodedA1SheetName(){return encodeURIComponent(this.a1SheetName)}get lastColumnLetter(){return this.columnCount?columnToLetter(this.columnCount):""}get cellStats(){let e=a__namespace.flatten(this._cells);return e=a__namespace.compact(e),{nonEmpty:a__namespace.filter(e,t=>t.value).length,loaded:e.length,total:this.rowCount*this.columnCount}}getCellByA1(e){const t=e.match(/([A-Z]+)([0-9]+)/);if(!t)throw new Error(`Cell address "${e}" not valid`);const r=letterToColumn(t[1]),s=parseInt(t[2]);return this.getCell(s-1,r-1)}getCell(e,t){if(e<0||t<0)throw new Error("Min coordinate is 0, 0");if(e>=this.rowCount||t>=this.columnCount)throw new Error(`Out of bounds, sheet is ${this.rowCount} by ${this.columnCount}`);if(!a__namespace.get(this._cells,`[${e}][${t}]`))throw new Error("This cell has not been loaded yet");return this._cells[e][t]}async loadCells(e){if(!e)return this._spreadsheet.loadCells(this.a1SheetName);const t=a__namespace.isArray(e)?e:[e],r=a__namespace.map(t,s=>{if(a__namespace.isString(s))return s.startsWith(this.a1SheetName)?s:`${this.a1SheetName}!${s}`;if(a__namespace.isObject(s)){const o=s;if(o.sheetId&&o.sheetId!==this.sheetId)throw new Error("Leave sheet ID blank or set to matching ID of this sheet");return{sheetId:this.sheetId,...s}}throw new Error("Each filter must be a A1 range string or gridrange object")});return this._spreadsheet.loadCells(r)}async saveUpdatedCells(){const e=a__namespace.filter(a__namespace.flatten(this._cells),{_isDirty:!0});e.length&&await this.saveCells(e)}async saveCells(e){const t=a__namespace.map(e,s=>s._getUpdateRequest()),r=a__namespace.map(e,s=>`${this.a1SheetName}!${s.a1Address}`);if(!a__namespace.compact(t).length)throw new Error("At least one cell must have something to update");await this._spreadsheet._makeBatchUpdateRequest(t,r)}async _ensureHeaderRowLoaded(){this._headerValues||await this.loadHeaderRow()}async loadHeaderRow(e){e!==void 0&&(this._headerRowIndex=e);const t=await this.getCellsInRange(`A${this._headerRowIndex}:${this.lastColumnLetter}${this._headerRowIndex}`);if(!t)throw new Error("No values in the header row - fill the first row with header values before trying to interact with rows");if(this._headerValues=a__namespace.map(t[0],r=>r.trim()),!a__namespace.compact(this.headerValues).length)throw new Error("All your header cells are blank - fill the first row with header values before trying to interact with rows");checkForDuplicateHeaders(this.headerValues)}async setHeaderRow(e,t){if(!e)return;if(e.length>this.columnCount)throw new Error(`Sheet is not large enough to fit ${e.length} columns. Resize the sheet first.`);const r=a__namespace.map(e,o=>o.trim());if(checkForDuplicateHeaders(r),!a__namespace.compact(r).length)throw new Error("All your header cells are blank -");t&&(this._headerRowIndex=t);const s=await this._spreadsheet.sheetsApi.request({method:"put",url:`/values/${this.encodedA1SheetName}!${this._headerRowIndex}:${this._headerRowIndex}`,params:{valueInputOption:"USER_ENTERED",includeValuesInResponse:!0},data:{range:`${this.a1SheetName}!${this._headerRowIndex}:${this._headerRowIndex}`,majorDimension:"ROWS",values:[[...r,...a__namespace.times(this.columnCount-r.length,()=>"")]]}});this._headerValues=s.data.updatedData.values[0]}async addRows(e,t={}){if(this.title.includes(":"))throw new Error('Please remove the ":" from your sheet title. There is a bug with the google API which breaks appending rows if any colons are in the sheet title.');if(!a__namespace.isArray(e))throw new Error("You must pass in an array of row values to append");await this._ensureHeaderRowLoaded();const r=[];a__namespace.each(e,n=>{let h;if(a__namespace.isArray(n))h=n;else if(a__namespace.isObject(n)){h=[];for(let l=0;l<this.headerValues.length;l++){const m=this.headerValues[l];h[l]=n[m]}}else throw new Error("Each row must be an object or an array");r.push(h)});const s=await this._spreadsheet.sheetsApi.request({method:"post",url:`/values/${this.encodedA1SheetName}!A${this._headerRowIndex}:append`,params:{valueInputOption:t.raw?"RAW":"USER_ENTERED",insertDataOption:t.insert?"INSERT_ROWS":"OVERWRITE",includeValuesInResponse:!0},data:{values:r}}),{updatedRange:o}=s.data.updates;let d=o.match(/![A-Z]+([0-9]+):?/)[1];return d=parseInt(d),this._ensureInfoLoaded(),t.insert?this._rawProperties.gridProperties.rowCount+=e.length:d+e.length>this.rowCount&&(this._rawProperties.gridProperties.rowCount=d+e.length-1),a__namespace.map(s.data.updates.updatedData.values,n=>new GoogleSpreadsheetRow(this,d++,n))}async addRow(e,t){return(await this.addRows([e],t))[0]}async getRows(e){const t=e?.offset||0,r=e?.limit||this.rowCount-1;await this._ensureHeaderRowLoaded();const s=1+this._headerRowIndex+t,o=s+r-1,d=columnToLetter(this.headerValues.length),n=await this.getCellsInRange(`A${s}:${d}${o}`);if(!n)return[];const h=[];let l=s;for(let m=0;m<n.length;m++)h.push(new GoogleSpreadsheetRow(this,l++,n[m]));return h}async clearRows(e){const t=e?.start||this._headerRowIndex+1,r=e?.end||this.rowCount;await this._spreadsheet.sheetsApi.post(`/values/${this.encodedA1SheetName}!${t}:${r}:clear`)}async updateProperties(e){return this._makeSingleUpdateRequest("updateSheetProperties",{properties:{sheetId:this.sheetId,...e},fields:getFieldMask(e)})}async updateGridProperties(e){return this.updateProperties({gridProperties:e})}async resize(e){return this.updateGridProperties(e)}async updateDimensionProperties(e,t,r){return this._makeSingleUpdateRequest("updateDimensionProperties",{range:{sheetId:this.sheetId,dimension:e,...r},properties:t,fields:getFieldMask(t)})}async getCellsInRange(e,t){return(await this._spreadsheet.sheetsApi.get(`/values/${this.encodedA1SheetName}!${e}`,{params:t})).data.values}async updateNamedRange(){}async addNamedRange(){}async deleteNamedRange(){}async repeatCell(){}async autoFill(){}async cutPaste(){}async copyPaste(){}async mergeCells(e,t="MERGE_ALL"){await this._makeSingleUpdateRequest("mergeCells",{mergeType:t,range:this._addSheetIdToRange(e)})}async unmergeCells(e){await this._makeSingleUpdateRequest("unmergeCells",{range:this._addSheetIdToRange(e)})}async updateBorders(){}async addFilterView(){}async appendCells(){}async clearBasicFilter(){}async deleteDimension(){}async deleteEmbeddedObject(){}async deleteFilterView(){}async duplicateFilterView(){}async duplicate(e){const t=(await this._makeSingleUpdateRequest("duplicateSheet",{sourceSheetId:this.sheetId,...e?.index!==void 0&&{insertSheetIndex:e.index},...e?.id&&{newSheetId:e.id},...e?.title&&{newSheetName:e.title}})).properties.sheetId;return this._spreadsheet.sheetsById[t]}async findReplace(){}async insertDimension(e,t,r){if(!e)throw new Error("You need to specify a dimension. i.e. COLUMNS|ROWS");if(!a__namespace.isObject(t))throw new Error("`range` must be an object containing `startIndex` and `endIndex`");if(!a__namespace.isInteger(t.startIndex)||t.startIndex<0)throw new Error("range.startIndex must be an integer >=0");if(!a__namespace.isInteger(t.endIndex)||t.endIndex<0)throw new Error("range.endIndex must be an integer >=0");if(t.endIndex<=t.startIndex)throw new Error("range.endIndex must be greater than range.startIndex");if(r===void 0&&(r=t.startIndex>0),r&&t.startIndex===0)throw new Error("Cannot set inheritFromBefore to true if inserting in first row/column");return this._makeSingleUpdateRequest("insertDimension",{range:{sheetId:this.sheetId,dimension:e,startIndex:t.startIndex,endIndex:t.endIndex},inheritFromBefore:r})}async insertRange(){}async moveDimension(){}async updateEmbeddedObjectPosition(){}async pasteData(){}async textToColumns(){}async updateFilterView(){}async deleteRange(){}async appendDimension(){}async addConditionalFormatRule(){}async updateConditionalFormatRule(){}async deleteConditionalFormatRule(){}async sortRange(){}async setDataValidation(){}async setBasicFilter(){}async addProtectedRange(){}async updateProtectedRange(){}async deleteProtectedRange(){}async autoResizeDimensions(){}async addChart(){}async updateChartSpec(){}async updateBanding(){}async addBanding(){}async deleteBanding(){}async createDeveloperMetadata(){}async updateDeveloperMetadata(){}async deleteDeveloperMetadata(){}async randomizeRange(){}async addDimensionGroup(){}async deleteDimensionGroup(){}async updateDimensionGroup(){}async trimWhitespace(){}async deleteDuplicates(){}async addSlicer(){}async updateSlicerSpec(){}async delete(){return this._spreadsheet.deleteSheet(this.sheetId)}async copyToSpreadsheet(e){return this._spreadsheet.sheetsApi.post(`/sheets/${this.sheetId}:copyTo`,{destinationSpreadsheetId:e})}async clear(e){const t=e?`!${e}`:"";await this._spreadsheet.sheetsApi.post(`/values/${this.encodedA1SheetName}${t}:clear`),this.resetLocalCache(!0)}async downloadAsCSV(e=!1){return this._spreadsheet._downloadAs("csv",this.sheetId,e)}async downloadAsTSV(e=!1){return this._spreadsheet._downloadAs("tsv",this.sheetId,e)}async downloadAsPDF(e=!1){return this._spreadsheet._downloadAs("pdf",this.sheetId,e)}}var AUTH_MODES=(i=>(i.GOOGLE_AUTH_CLIENT="google_auth",i.RAW_ACCESS_TOKEN="raw_access_token",i.API_KEY="api_key",i))(AUTH_MODES||{});const u="https://sheets.googleapis.com/v4/spreadsheets",_="https://www.googleapis.com/drive/v3/files",c={html:{},zip:{},xlsx:{},ods:{},csv:{singleWorksheet:!0},tsv:{singleWorksheet:!0},pdf:{singleWorksheet:!0}};function A(i){if("getRequestHeaders"in i)return AUTH_MODES.GOOGLE_AUTH_CLIENT;if("token"in i)return AUTH_MODES.RAW_ACCESS_TOKEN;if("apiKey"in i)return AUTH_MODES.API_KEY;throw new Error("Invalid auth")}async function g(i){if("getRequestHeaders"in i)return{headers:await i.getRequestHeaders()};if("apiKey"in i)return{params:{key:i.apiKey}};if("token"in i)return{headers:{Authorization:`Bearer ${i.token}`}};throw new Error("Invalid auth")}class GoogleSpreadsheet{constructor(e,t){this._rawProperties=null,this._spreadsheetUrl=null,this._deleted=!1,this.spreadsheetId=e,this.auth=t,this._rawSheets={},this._spreadsheetUrl=null,this.sheetsApi=p__default.create({baseURL:`${u}/${e}`,paramsSerializer:axiosParamsSerializer,maxContentLength:1/0,maxBodyLength:1/0}),this.driveApi=p__default.create({baseURL:`${_}/${e}`,paramsSerializer:axiosParamsSerializer}),this.sheetsApi.interceptors.request.use(this._setAxiosRequestAuth.bind(this)),this.sheetsApi.interceptors.response.use(this._handleAxiosResponse.bind(this),this._handleAxiosErrors.bind(this)),this.driveApi.interceptors.request.use(this._setAxiosRequestAuth.bind(this)),this.driveApi.interceptors.response.use(this._handleAxiosResponse.bind(this),this._handleAxiosErrors.bind(this))}get authMode(){return A(this.auth)}async _setAxiosRequestAuth(e){const t=await g(this.auth);return a__namespace.each(t.headers,(r,s)=>{e.headers.set(s,r)}),e.params={...e.params,...t.params},e}async _handleAxiosResponse(e){return e}async _handleAxiosErrors(e){const t=e.response?.data;if(t){if(!t.error)throw e;const{code:r,message:s}=t.error;throw e.message=`Google API error - [${r}] ${s}`,e}throw a__namespace.get(e,"response.status")===403&&"apiKey"in this.auth?new Error("Sheet is private. Use authentication or make public. (see https://github.com/theoephraim/node-google-spreadsheet#a-note-on-authentication for details)"):e}async _makeSingleUpdateRequest(e,t){const r=await this.sheetsApi.post(":batchUpdate",{requests:[{[e]:t}],includeSpreadsheetInResponse:!0});return this._updateRawProperties(r.data.updatedSpreadsheet.properties),a__namespace.each(r.data.updatedSpreadsheet.sheets,s=>this._updateOrCreateSheet(s)),r.data.replies[0][e]}async _makeBatchUpdateRequest(e,t){const r=await this.sheetsApi.post(":batchUpdate",{requests:e,includeSpreadsheetInResponse:!0,...t&&{responseIncludeGridData:!0,...t!=="*"&&{responseRanges:t}}});this._updateRawProperties(r.data.updatedSpreadsheet.properties),a__namespace.each(r.data.updatedSpreadsheet.sheets,s=>this._updateOrCreateSheet(s))}_ensureInfoLoaded(){if(!this._rawProperties)throw new Error("You must call `doc.loadInfo()` before accessing this property")}_updateRawProperties(e){this._rawProperties=e}_updateOrCreateSheet(e){const{properties:t,data:r}=e,{sheetId:s}=t;this._rawSheets[s]?this._rawSheets[s].updateRawData(t,r):this._rawSheets[s]=new GoogleSpreadsheetWorksheet(this,t,r)}_getProp(e){return this._ensureInfoLoaded(),this._rawProperties[e]}get title(){return this._getProp("title")}get locale(){return this._getProp("locale")}get timeZone(){return this._getProp("timeZone")}get autoRecalc(){return this._getProp("autoRecalc")}get defaultFormat(){return this._getProp("defaultFormat")}get spreadsheetTheme(){return this._getProp("spreadsheetTheme")}get iterativeCalculationSettings(){return this._getProp("iterativeCalculationSettings")}async updateProperties(e){await this._makeSingleUpdateRequest("updateSpreadsheetProperties",{properties:e,fields:getFieldMask(e)})}async loadInfo(e=!1){const t=await this.sheetsApi.get("/",{params:{...e&&{includeGridData:!0}}});this._spreadsheetUrl=t.data.spreadsheetUrl,this._rawProperties=t.data.properties,a__namespace.each(t.data.sheets,r=>this._updateOrCreateSheet(r))}resetLocalCache(){this._rawProperties=null,this._rawSheets={}}get sheetCount(){return this._ensureInfoLoaded(),a__namespace.values(this._rawSheets).length}get sheetsById(){return this._ensureInfoLoaded(),this._rawSheets}get sheetsByIndex(){return this._ensureInfoLoaded(),a__namespace.sortBy(this._rawSheets,"index")}get sheetsByTitle(){return this._ensureInfoLoaded(),a__namespace.keyBy(this._rawSheets,"title")}async addSheet(e={}){const t=(await this._makeSingleUpdateRequest("addSheet",{properties:a__namespace.omit(e,"headerValues","headerRowIndex")})).properties.sheetId,r=this.sheetsById[t];return e.headerValues&&await r.setHeaderRow(e.headerValues,e.headerRowIndex),r}async deleteSheet(e){await this._makeSingleUpdateRequest("deleteSheet",{sheetId:e}),delete this._rawSheets[e]}async addNamedRange(e,t,r){return this._makeSingleUpdateRequest("addNamedRange",{name:e,namedRangeId:r,range:t})}async deleteNamedRange(e){return this._makeSingleUpdateRequest("deleteNamedRange",{namedRangeId:e})}async loadCells(e){const t=this.authMode===AUTH_MODES.API_KEY,r=a__namespace.isArray(e)?e:[e],s=a__namespace.map(r,n=>{if(a__namespace.isString(n))return t?n:{a1Range:n};if(a__namespace.isObject(n)){if(t)throw new Error("Only A1 ranges are supported when fetching cells with read-only access (using only an API key)");return{gridRange:n}}throw new Error("Each filter must be an A1 range string or a gridrange object")});let o;this.authMode===AUTH_MODES.API_KEY?o=await this.sheetsApi.get("/",{params:{includeGridData:!0,ranges:s}}):o=await this.sheetsApi.post(":getByDataFilter",{includeGridData:!0,dataFilters:s});const{sheets:d}=o.data;a__namespace.each(d,n=>{this._updateOrCreateSheet(n)})}async _downloadAs(e,t,r){if(!c[e])throw new Error(`unsupported export fileType - ${e}`);if(c[e].singleWorksheet){if(t===void 0)throw new Error(`Must specify worksheetId when exporting as ${e}`)}else if(t)throw new Error(`Cannot specify worksheetId when exporting as ${e}`);if(e==="html"&&(e="zip"),!this._spreadsheetUrl)throw new Error("Cannot export sheet that is not fully loaded");const s=this._spreadsheetUrl.replace("/edit","/export");return(await this.sheetsApi.get(s,{baseURL:"",params:{id:this.spreadsheetId,format:e,...t&&{gid:t}},responseType:r?"stream":"arraybuffer"})).data}async downloadAsHTML(e=!1){return this._downloadAs("html",void 0,e)}async downloadAsXLSX(e=!1){return this._downloadAs("xlsx",void 0,e)}async downloadAsODS(e=!1){return this._downloadAs("ods",void 0,e)}async delete(){const e=await this.driveApi.delete("");return this._deleted=!0,e.data}async listPermissions(){return(await this.driveApi.request({method:"GET",url:"/permissions",params:{fields:"permissions(id,type,emailAddress,domain,role,displayName,photoLink,deleted)"}})).data.permissions}async setPublicAccessLevel(e){const t=await this.listPermissions(),r=a__namespace.find(t,s=>s.type==="anyone");if(e===!1){if(!r)return;await this.driveApi.request({method:"DELETE",url:`/permissions/${r.id}`})}else await this.driveApi.request({method:"POST",url:"/permissions",params:{},data:{role:e||"viewer",type:"anyone"}})}async share(e,t){let r,s;return e.includes("@")?r=e:s=e,(await this.driveApi.request({method:"POST",url:"/permissions",params:{...t?.emailMessage===!1&&{sendNotificationEmail:!1},...a__namespace.isString(t?.emailMessage)&&{emailMessage:t?.emailMessage},...t?.role==="owner"&&{transferOwnership:!0}},data:{role:t?.role||"writer",...r&&{type:t?.isGroup?"group":"user",emailAddress:r},...s&&{type:"domain",domain:s}}})).data}static async createNewSpreadsheetDocument(e,t){if("apiKey"in e)throw new Error("Cannot use api key only to create a new spreadsheet - it is only usable for read-only access of public docs");const r=await g(e),s=await p__default.request({method:"POST",url:u,paramsSerializer:axiosParamsSerializer,...r,data:{properties:t}}),o=new GoogleSpreadsheet(s.data.spreadsheetId,e);return o._spreadsheetUrl=s.data.spreadsheetUrl,o._rawProperties=s.data.properties,a__namespace.each(s.data.sheets,d=>o._updateOrCreateSheet(d)),o}}exports.GoogleSpreadsheet=GoogleSpreadsheet,exports.GoogleSpreadsheetCell=GoogleSpreadsheetCell,exports.GoogleSpreadsheetCellErrorValue=GoogleSpreadsheetCellErrorValue,exports.GoogleSpreadsheetRow=GoogleSpreadsheetRow,exports.GoogleSpreadsheetWorksheet=GoogleSpreadsheetWorksheet;