@noloco/google-spreadsheet
Version:
Google Sheets API -- simple interface to read/write data and manage sheets
2 lines (1 loc) • 31.4 kB
JavaScript
import v from"axios";import w from"lodash/compact.js";import u from"lodash/each.js";import P from"lodash/filter.js";import j from"lodash/find.js";import A from"lodash/flatten.js";import p from"lodash/get.js";import L from"lodash/groupBy.js";import f from"lodash/isArray.js";import U from"lodash/isBoolean.js";import q from"lodash/isEqual.js";import B from"lodash/isFinite.js";import x from"lodash/isInteger.js";import G from"lodash/isNil.js";import"lodash/isNumber.js";import y from"lodash/isObject.js";import g from"lodash/isString.js";import z from"lodash/keyBy.js";import R from"lodash/keys.js";import c from"lodash/map.js";import H from"lodash/omit.js";import W from"lodash/pickBy.js";import K from"lodash/set.js";import Y from"lodash/some.js";import Z from"lodash/sortBy.js";import J from"lodash/times.js";import X from"lodash/unset.js";import k from"lodash/values.js";function D(s){let e="";const t=Object.keys(s).filter(a=>a!=="gridProperties").join(",");return s.gridProperties&&(e=Object.keys(s.gridProperties).map(a=>`gridProperties.${a}`).join(","),e.length&&t.length&&(e=`${e},`)),e+t}function I(s){let e,t="",a=s;for(;a>0;)e=(a-1)%26,t=String.fromCharCode(e+65)+t,a=(a-e-1)/26;return t}function Q(s){let e=0;const{length:t}=s;for(let a=0;a<t;a++)e+=(s.charCodeAt(a)-64)*26**(t-a-1);return e}function S(s){let e="";return Object.keys(s).forEach(t=>{const a=typeof s[t]=="object",r=a&&s[t].length>=0;if(a||(e+=`${t}=${encodeURIComponent(s[t])}&`),a&&r)for(const i of s[t])e+=`${t}=${encodeURIComponent(i)}&`}),e&&e.slice(0,-1)}function F(s){const e=L(s);u(e,(t,a)=>{if(a&&t.length>1)throw new Error(`Duplicate header detected: "${a}". Please make sure all non-empty headers are unique`)})}class b{constructor(e,t,a){this._worksheet=e,this._rowNumber=t,this._rawData=a,this._deleted=!1}get deleted(){return this._deleted}get rowNumber(){return this._rowNumber}_updateRowNumber(e){this._rowNumber=e}get a1Range(){return[this._worksheet.a1SheetName,"!",`A${this._rowNumber}`,":",`${I(this._worksheet.headerValues.length)}${this._rowNumber}`].join("")}get(e){const t=this._worksheet.headerValues.indexOf(e);return this._rawData[t]}set(e,t){const a=this._worksheet.headerValues.indexOf(e);this._rawData[a]=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 a=this._worksheet.headerValues[t];a&&(e[a]=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,this._worksheet._shiftRowCache(this.rowNumber),e}async createDeveloperMetadata(e,t,a,r){return this._worksheet._spreadsheet.createRangeDeveloperMetadata(e,t,{dimension:"ROWS",sheetId:this._worksheet.sheetId,startIndex:this._rowNumber,endIndex:this._rowNumber+1},a,r)}async getDeveloperMetadata(){return this._worksheet._spreadsheet.getDeveloperMetadataByGridRange({sheetId:this._worksheet.sheetId,startRowIndex:this._rowNumber,endRowIndex:this._rowNumber+1})}_clearRowData(){for(let e=0;e<this._rawData.length;e++)this._rawData[e]=""}}class C{constructor(e){this.type=e.type,this.message=e.message}}class ${constructor(e,t,a,r){this._sheet=e,this._rowIndex=t,this._columnIndex=a,this._draftData={},this._updateRawData(r),this._rawData=r}_updateRawData(e){this._rawData=e,this._draftData={},this._rawData?.effectiveValue&&"errorValue"in this._rawData.effectiveValue?this._error=new C(this._rawData.effectiveValue.errorValue):this._error=void 0}get rowIndex(){return this._rowIndex}get columnIndex(){return this._columnIndex}get a1Column(){return I(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?k(this._rawData.effectiveValue)[0]:null}set value(e){if(e instanceof C)throw new Error("You can't manually set a value to an error");if(U(e))this._draftData.valueType="boolValue";else if(g(e))e.substring(0,1)==="="?this._draftData.valueType="formulaValue":this._draftData.valueType="stringValue";else if(B(e))this._draftData.valueType="numberValue";else if(G(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?R(this._rawData.effectiveValue)[0]:null}get formattedValue(){return this._rawData?.formattedValue||null}get formula(){return p(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=""),!g(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)}get dataValidation(){return Object.freeze(this._rawData?.dataValidation)}_getFormatParam(e){if(p(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){q(t,p(this._rawData,`userEnteredFormat.${e}`))?X(this._draftData,`userEnteredFormat.${e}`):(K(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||R(this._draftData.userEnteredFormat).length||this._draftData.clearFormat||this._draftData.value!==void 0)}discardUnsavedChanges(){this._draftData={}}async save(){await this._sheet.saveCells([this])}async createDeveloperMetadata(e,t,a,r){return this._sheet._spreadsheet.createRangeDeveloperMetadata(e,t,{dimension:"COLUMNS",sheetId:this._sheet.sheetId,startIndex:this._columnIndex,endIndex:this._columnIndex+1},a,r)}async getDeveloperMetadata(){return this._sheet._spreadsheet.getDeveloperMetadataByGridRange({sheetId:this._sheet.sheetId,startColumnIndex:this._columnIndex,endColumnIndex:this._columnIndex+1})}_getUpdateRequest(){const e=this._draftData.value!==void 0,t=this._draftData.note!==void 0,a=!!R(this._draftData.userEnteredFormat||{}).length,r=this._draftData.clearFormat;if(!Y([e,t,a,r]))return null;const i={...this._rawData?.userEnteredFormat,...this._draftData.userEnteredFormat};return p(this._draftData,"userEnteredFormat.backgroundColor")&&delete i.backgroundColorStyle,{updateCells:{rows:[{values:[{...e&&{userEnteredValue:{[this._draftData.valueType]:this._draftData.value}},...t&&{note:this._draftData.note},...a&&{userEnteredFormat:i},...r&&{userEnteredFormat:{}}}]}],fields:R(W({userEnteredValue:e,note:t,userEnteredFormat:a||r})).join(","),start:{sheetId:this._sheet.sheetId,rowIndex:this.rowIndex,columnIndex:this.columnIndex}}}}}class V{constructor(e,t,a){this._spreadsheet=e,this._headerRowIndex=1,this._rawProperties=null,this._cells=[],this._rowMetadata=[],this._columnMetadata=[],this._rowCache=[],this._headerRowIndex=1,this._rawProperties=t,this._cells=[],this._rowMetadata=[],this._columnMetadata=[],a&&this._fillCellData(a)}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){u(e,t=>{const a=t.startRow||0,r=t.startColumn||0,i=t.rowMetadata.length,o=t.columnMetadata.length;for(let n=0;n<i;n++){const d=a+n;for(let l=0;l<o;l++){const h=r+l;this._cells[d]||(this._cells[d]=[]);const _=p(t,`rowData[${n}].values[${l}]`);this._cells[d][h]?this._cells[d][h]._updateRawData(_):this._cells[d][h]=new $(this,d,h,_)}}for(let n=0;n<t.rowMetadata.length;n++)this._rowMetadata[a+n]=t.rowMetadata[n];for(let n=0;n<t.columnMetadata.length;n++)this._columnMetadata[r+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")}get rowMetadata(){return this._rowMetadata}get columnMetadata(){return this._columnMetadata}get _headerRange(){return`A${this._headerRowIndex}:${this.lastColumnLetter}${this._headerRowIndex}`}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?I(this.columnCount):""}get cellStats(){let e=A(this._cells);return e=w(e),{nonEmpty:P(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 a=Q(t[1]),r=parseInt(t[2]);return this.getCell(r-1,a-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(!p(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=f(e)?e:[e],a=c(t,r=>{if(g(r))return r.startsWith(this.a1SheetName)?r:`${this.a1SheetName}!${r}`;if(y(r)){const i=r;if(i.sheetId&&i.sheetId!==this.sheetId)throw new Error("Leave sheet ID blank or set to matching ID of this sheet");return{sheetId:this.sheetId,...r}}throw new Error("Each filter must be a A1 range string or gridrange object")});return this._spreadsheet.loadCells(a)}async saveUpdatedCells(){const e=P(A(this._cells),{_isDirty:!0});e.length&&await this.saveCells(e)}async saveCells(e){const t=c(e,r=>r._getUpdateRequest()),a=c(e,r=>`${this.a1SheetName}!${r.a1Address}`);if(!w(t).length)throw new Error("At least one cell must have something to update");await this._spreadsheet._makeBatchUpdateRequest(t,a)}async _ensureHeaderRowLoaded(){this._headerValues||await this.loadHeaderRow()}async loadHeaderRow(e,t){e!==void 0&&(this._headerRowIndex=e);const a=await this.getCellsInRange(this._headerRange,t);this._processHeaderRow(a)}_processHeaderRow(e){if(!e)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=c(e[0],t=>t?.toString()?.trim()),!w(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");F(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 a=c(e,i=>i?.toString()?.trim());if(F(a),!w(a).length)throw new Error("All your header cells are blank -");t&&(this._headerRowIndex=t);const r=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:[[...a,...J(this.columnCount-a.length,()=>"")]]}});this._headerValues=r.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(!f(e))throw new Error("You must pass in an array of row values to append");await this._ensureHeaderRowLoaded();const a=[];u(e,n=>{let d;if(f(n))d=n;else if(y(n)){d=[];for(let l=0;l<this.headerValues.length;l++){const h=this.headerValues[l];d[l]=n[h]}}else throw new Error("Each row must be an object or an array");a.push(d)});const r=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:a}}),{updatedRange:i}=r.data.updates;let o=i.match(/![A-Z]+([0-9]+):?/)[1];return o=parseInt(o),this._ensureInfoLoaded(),t.insert?this._rawProperties.gridProperties.rowCount+=e.length:o+e.length>this.rowCount&&(this._rawProperties.gridProperties.rowCount=o+e.length-1),c(r.data.updates.updatedData.values,n=>new b(this,o++,n))}async addRow(e,t){return(await this.addRows([e],t))[0]}async getRows(e){const t=e?.offset||0,a=e?.limit||this.rowCount-1;let r;e?.majorDimension&&(r={majorDimension:e.majorDimension}),e?.valueRenderOption&&(r?r.valueRenderOption=e.valueRenderOption:r={valueRenderOption:e.valueRenderOption});const i=1+this._headerRowIndex+t,o=i+a-1;let n;if(this._headerValues){const h=I(this.headerValues.length);n=await this.getCellsInRange(`A${i}:${h}${o}`,r)}else{const h=await this.batchGetCellsInRange([this._headerRange,`A${i}:${this.lastColumnLetter}${o}`],r);this._processHeaderRow(h[0]),n=h[1]}if(!n)return[];const d=[];let l=i;for(let h=0;h<n.length;h++){const _=new b(this,l++,n[h]);this._rowCache[_.rowNumber]=_,d.push(_)}return d}_shiftRowCache(e){delete this._rowCache[e],this._rowCache.forEach(t=>{t.rowNumber>e&&t._updateRowNumber(t.rowNumber-1)})}async clearRows(e){const t=e?.start||this._headerRowIndex+1,a=e?.end||this.rowCount;await this._spreadsheet.sheetsApi.post(`/values/${this.encodedA1SheetName}!${t}:${a}:clear`),this._rowCache.forEach(r=>{r.rowNumber>=t&&r.rowNumber<=a&&r._clearRowData()})}async updateProperties(e){return this._makeSingleUpdateRequest("updateSheetProperties",{properties:{sheetId:this.sheetId,...e},fields:D(e)})}async updateGridProperties(e){return this.updateProperties({gridProperties:e})}async resize(e){return this.updateGridProperties(e)}async updateDimensionProperties(e,t,a){return this._makeSingleUpdateRequest("updateDimensionProperties",{range:{sheetId:this.sheetId,dimension:e,...a},properties:t,fields:D(t)})}async getCellsInRange(e,t){return(await this._spreadsheet.sheetsApi.get(`/values/${this.encodedA1SheetName}!${e}`,{params:t})).data.values}async batchGetCellsInRange(e,t){const a=e.map(r=>`ranges=${this.encodedA1SheetName}!${r}`).join("&");return(await this._spreadsheet.sheetsApi.get(`/values:batchGet?${a}`,{params:t})).data.valueRanges.map(r=>r.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,a){if(!e)throw new Error("You need to specify a dimension. i.e. COLUMNS|ROWS");if(!y(t))throw new Error("`range` must be an object containing `startIndex` and `endIndex`");if(!x(t.startIndex)||t.startIndex<0)throw new Error("range.startIndex must be an integer >=0");if(!x(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(a===void 0&&(a=t.startIndex>0),a&&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:a})}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(e,t){return this._makeSingleUpdateRequest("setDataValidation",{range:{sheetId:this.sheetId,...e},...t&&{rule:t}})}async setBasicFilter(){}async addProtectedRange(){}async updateProtectedRange(){}async deleteProtectedRange(){}async autoResizeDimensions(){}async addChart(){}async updateChartSpec(){}async updateBanding(){}async addBanding(){}async deleteBanding(){}async createDeveloperMetadata(e,t,a,r){return this._spreadsheet.createSheetDeveloperMetadata(e,t,this.sheetId,a,r)}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 m=(s=>(s.GOOGLE_AUTH_CLIENT="google_auth",s.RAW_ACCESS_TOKEN="raw_access_token",s.API_KEY="api_key",s))(m||{});const T="https://sheets.googleapis.com/v4/spreadsheets",ee="https://www.googleapis.com/drive/v3/files",M={html:{},zip:{},xlsx:{},ods:{},csv:{singleWorksheet:!0},tsv:{singleWorksheet:!0},pdf:{singleWorksheet:!0}};function N(s){if("getRequestHeaders"in s)return m.GOOGLE_AUTH_CLIENT;if("token"in s&&s.token)return m.RAW_ACCESS_TOKEN;if("apiKey"in s&&s.apiKey)return m.API_KEY;throw new Error("Invalid auth")}async function O(s){if("getRequestHeaders"in s)return{headers:await s.getRequestHeaders()};if("apiKey"in s&&s.apiKey)return{params:{key:s.apiKey}};if("token"in s&&s.token)return{headers:{Authorization:`Bearer ${s.token}`}};throw new Error("Invalid auth")}class E{constructor(e,t){this._rawProperties=null,this._spreadsheetUrl=null,this._deleted=!1,this._rateLimitedRetries=0,this._initialRateLimitedRetryDelay=3e3,this.spreadsheetId=e,this.auth=t,this._rawSheets={},this._spreadsheetUrl=null,this.sheetsApi=v.create({baseURL:`${T}/${e}`,paramsSerializer:S,maxContentLength:1/0,maxBodyLength:1/0}),this.driveApi=v.create({baseURL:`${ee}/${e}`,paramsSerializer:S}),this.sheetsApi.interceptors.request.use(this._setAxiosRequestAuth.bind(this)),this.sheetsApi.interceptors.response.use(this._handleAxiosResponse.bind(this),this._handleAxiosErrors(this.sheetsApi).bind(this)),this.driveApi.interceptors.request.use(this._setAxiosRequestAuth.bind(this)),this.driveApi.interceptors.response.use(this._handleAxiosResponse.bind(this),this._handleAxiosErrors(this.driveApi).bind(this))}get authMode(){return N(this.auth)}setRetryOptions(e,t){this._rateLimitedRetries=e,this._initialRateLimitedRetryDelay=t}async _setAxiosRequestAuth(e){const t=await O(this.auth);return u(t.headers,(a,r)=>{e.headers.set(r,a)}),e.params={...e.params,...t.params},e}async _handleAxiosResponse(e){return e}_handleAxiosErrors(e){return async t=>{if(p(t,"response.status")===429){const r=t.config,i=r?.retryCount??0;if(this._rateLimitedRetries>0&&i<this._rateLimitedRetries)return r.retryCount=i+1,new Promise(o=>{setTimeout(()=>{o(e(r))},this._initialRateLimitedRetryDelay*(i+1))})}const a=t.response?.data;if(a){if(!a.error)throw t;const{code:r,message:i}=a.error;throw t.message=`Google API error - [${r}] ${i}`,t}throw p(t,"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)"):t}}async _makeSingleUpdateRequest(e,t){const a=await this.sheetsApi.post(":batchUpdate",{requests:[{[e]:t}],includeSpreadsheetInResponse:!0});return this._updateRawProperties(a.data.updatedSpreadsheet.properties),u(a.data.updatedSpreadsheet.sheets,r=>this._updateOrCreateSheet(r)),a.data.replies[0][e]}async _makeBatchUpdateRequest(e,t){const a=await this.sheetsApi.post(":batchUpdate",{requests:e,includeSpreadsheetInResponse:!0,...t&&{responseIncludeGridData:!0,...t!=="*"&&{responseRanges:t}}});this._updateRawProperties(a.data.updatedSpreadsheet.properties),u(a.data.updatedSpreadsheet.sheets,r=>this._updateOrCreateSheet(r))}_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:a}=e,{sheetId:r}=t;this._rawSheets[r]?this._rawSheets[r].updateRawData(t,a):this._rawSheets[r]=new V(this,t,a)}_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:D(e)})}async loadInfo(e=!1){const t=await this.sheetsApi.get("/",{params:{...e&&{includeGridData:!0}}});if(!t.data?.spreadsheetUrl)throw new Error(`Failed to load document info. Status: ${t.status}, Status Text: ${t.statusText}, Data: ${JSON.stringify(t.data)}`);this._spreadsheetUrl=t.data.spreadsheetUrl,this._rawProperties=t.data.properties,u(t.data.sheets,a=>this._updateOrCreateSheet(a))}resetLocalCache(){this._rawProperties=null,this._rawSheets={}}get sheetCount(){return this._ensureInfoLoaded(),k(this._rawSheets).length}get sheetsById(){return this._ensureInfoLoaded(),this._rawSheets}get sheetsByIndex(){return this._ensureInfoLoaded(),Z(this._rawSheets,"index")}get sheetsByTitle(){return this._ensureInfoLoaded(),z(this._rawSheets,"title")}async addSheet(e={}){const t=(await this._makeSingleUpdateRequest("addSheet",{properties:H(e,"headerValues","headerRowIndex")})).properties.sheetId,a=this.sheetsById[t];return e.headerValues&&await a.setHeaderRow(e.headerValues,e.headerRowIndex),a}async deleteSheet(e){await this._makeSingleUpdateRequest("deleteSheet",{sheetId:e}),delete this._rawSheets[e]}async addNamedRange(e,t,a){return this._makeSingleUpdateRequest("addNamedRange",{name:e,namedRangeId:a,range:t})}async deleteNamedRange(e){return this._makeSingleUpdateRequest("deleteNamedRange",{namedRangeId:e})}async loadCells(e){const t=this.authMode===m.API_KEY,a=f(e)?e:[e],r=c(a,n=>{if(g(n))return t?n:{a1Range:n};if(y(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 i;this.authMode===m.API_KEY?i=await this.sheetsApi.get("/",{params:{includeGridData:!0,ranges:r}}):i=await this.sheetsApi.post(":getByDataFilter",{includeGridData:!0,dataFilters:r});const{sheets:o}=i.data;u(o,n=>{this._updateOrCreateSheet(n)})}async _downloadAs(e,t,a){if(!M[e])throw new Error(`unsupported export fileType - ${e}`);if(M[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 r=this._spreadsheetUrl.replace("/edit","/export");return(await this.sheetsApi.get(r,{baseURL:"",params:{id:this.spreadsheetId,format:e,...t&&{gid:t}},responseType:a?"stream":"arraybuffer"})).data}async downloadAsZippedHTML(e){return this._downloadAs("html",void 0,e)}async downloadAsHTML(e){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(),a=j(t,r=>r.type==="anyone");if(e===!1){if(!a)return;await this.driveApi.request({method:"DELETE",url:`/permissions/${a.id}`})}else await this.driveApi.request({method:"POST",url:"/permissions",params:{},data:{role:e||"viewer",type:"anyone"}})}async share(e,t){let a,r;return e.includes("@")?a=e:r=e,(await this.driveApi.request({method:"POST",url:"/permissions",params:{...t?.emailMessage===!1&&{sendNotificationEmail:!1},...g(t?.emailMessage)&&{emailMessage:t?.emailMessage},...t?.role==="owner"&&{transferOwnership:!0}},data:{role:t?.role||"writer",...a&&{type:t?.isGroup?"group":"user",emailAddress:a},...r&&{type:"domain",domain:r}}})).data}static async createNewSpreadsheetDocument(e,t){if(N(e)===m.API_KEY)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 a=await O(e),r=await v.request({method:"POST",url:T,paramsSerializer:S,...a,data:{properties:t}}),i=new E(r.data.spreadsheetId,e);return i._spreadsheetUrl=r.data.spreadsheetUrl,i._rawProperties=r.data.properties,u(r.data.sheets,o=>i._updateOrCreateSheet(o)),i}async _createDeveloperMetadata(e,t,a,r,i){return this._makeSingleUpdateRequest("createDeveloperMetadata",{developerMetadata:{metadataKey:e,metadataValue:t,location:a,visibility:r||"PROJECT",metadataId:i}}).then(o=>o.developerMetadata)}async _getDeveloperMetadata(e){return this.sheetsApi.post("/developerMetadata:search",{dataFilters:[e]}).then(t=>t.data.matchedDeveloperMetadata)}async getMetadataById(e){return this.sheetsApi.get(`/developerMetadata/${e}`).then(t=>t.data)}async createSheetDeveloperMetadata(e,t,a,r,i){return this._createDeveloperMetadata(e,t,{sheetId:a??0},r,i)}async createRangeDeveloperMetadata(e,t,a,r,i){return this._createDeveloperMetadata(e,t,{dimensionRange:a},r,i)}async getDeveloperMetadataByA1Range(e){return this._getDeveloperMetadata({a1Range:e})}async getDeveloperMetadataByGridRange(e){return this._getDeveloperMetadata({gridRange:e})}}export{E as GoogleSpreadsheet,$ as GoogleSpreadsheetCell,C as GoogleSpreadsheetCellErrorValue,b as GoogleSpreadsheetRow,V as GoogleSpreadsheetWorksheet};