google-spreadsheet 5.0.3 → 5.2.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/dist/index.cjs CHANGED
@@ -72,6 +72,12 @@ var GoogleSpreadsheetRow = class {
72
72
  this._worksheet = _worksheet;
73
73
  this._rowNumber = _rowNumber;
74
74
  this._rawData = _rawData;
75
+ this._padRawData();
76
+ }
77
+ /** pad _rawData with empty strings so it always matches header length */
78
+ _padRawData() {
79
+ const headerLength = this._worksheet.headerValues.length;
80
+ while (this._rawData.length < headerLength) this._rawData.push("");
75
81
  }
76
82
  _deleted = false;
77
83
  get deleted() {
@@ -89,6 +95,14 @@ var GoogleSpreadsheetRow = class {
89
95
  _updateRowNumber(newRowNumber) {
90
96
  this._rowNumber = newRowNumber;
91
97
  }
98
+ /**
99
+ * @internal
100
+ * Used internally to mark row as deleted.
101
+ * Should not be called directly.
102
+ */
103
+ _markDeleted() {
104
+ this._deleted = true;
105
+ }
92
106
  get a1Range() {
93
107
  return [
94
108
  this._worksheet.a1SheetName,
@@ -135,7 +149,8 @@ var GoogleSpreadsheetRow = class {
135
149
  majorDimension: "ROWS",
136
150
  values: [this._rawData]
137
151
  }
138
- })).json()).updatedData.values[0];
152
+ })).json()).updatedData.values?.[0] || [];
153
+ this._padRawData();
139
154
  }
140
155
  /** delete this row */
141
156
  async delete() {
@@ -192,6 +207,7 @@ var GoogleSpreadsheetCell = class {
192
207
  _rawData;
193
208
  _draftData = {};
194
209
  _error;
210
+ _deleted = false;
195
211
  constructor(_sheet, _rowIndex, _columnIndex, rawCellData) {
196
212
  this._sheet = _sheet;
197
213
  this._rowIndex = _rowIndex;
@@ -199,6 +215,9 @@ var GoogleSpreadsheetCell = class {
199
215
  this._updateRawData(rawCellData);
200
216
  this._rawData = rawCellData;
201
217
  }
218
+ get deleted() {
219
+ return this._deleted;
220
+ }
202
221
  /**
203
222
  * update cell using raw CellData coming back from sheets API
204
223
  * @internal
@@ -224,6 +243,23 @@ var GoogleSpreadsheetCell = class {
224
243
  get a1Address() {
225
244
  return `${this.a1Column}${this.a1Row}`;
226
245
  }
246
+ /**
247
+ * @internal
248
+ * Used internally to update cell indices after deleting rows/columns.
249
+ * Should not be called directly.
250
+ */
251
+ _updateIndices(rowIndex, columnIndex) {
252
+ this._rowIndex = rowIndex;
253
+ this._columnIndex = columnIndex;
254
+ }
255
+ /**
256
+ * @internal
257
+ * Used internally to mark cell as deleted.
258
+ * Should not be called directly.
259
+ */
260
+ _markDeleted() {
261
+ this._deleted = true;
262
+ }
227
263
  get value() {
228
264
  if (this._draftData.value !== void 0) throw new Error("Value has been changed");
229
265
  if (this._error) return this._error;
@@ -231,6 +267,7 @@ var GoogleSpreadsheetCell = class {
231
267
  return es_toolkit_compat.values(this._rawData.effectiveValue)[0];
232
268
  }
233
269
  set value(newValue) {
270
+ if (this._deleted) throw new Error("This cell has been deleted - reload cells before making updates.");
234
271
  if (newValue instanceof GoogleSpreadsheetCellErrorValue) throw new Error("You can't manually set a value to an error");
235
272
  if (es_toolkit_compat.isBoolean(newValue)) this._draftData.valueType = "boolValue";
236
273
  else if (es_toolkit_compat.isString(newValue)) if (newValue.substring(0, 1) === "=") this._draftData.valueType = "formulaValue";
@@ -290,8 +327,8 @@ var GoogleSpreadsheetCell = class {
290
327
  return this.value;
291
328
  }
292
329
  set stringValue(val) {
293
- if (val?.startsWith("=")) throw new Error("Use cell.formula to set formula values");
294
- this.value = val;
330
+ this._draftData.valueType = "stringValue";
331
+ this._draftData.value = val || "";
295
332
  }
296
333
  /**
297
334
  * Hyperlink contained within the cell.
@@ -499,7 +536,9 @@ var GoogleSpreadsheetWorksheet = class {
499
536
  _ensureInfoLoaded() {
500
537
  if (!this._rawProperties) throw new Error("You must call `doc.loadInfo()` again before accessing this property");
501
538
  }
502
- /** clear local cache of sheet data/properties */
539
+ /**
540
+ * clear local cache of sheet data/properties
541
+ */
503
542
  resetLocalCache(dataOnly) {
504
543
  if (!dataOnly) this._rawProperties = null;
505
544
  this._headerValues = void 0;
@@ -642,6 +681,7 @@ var GoogleSpreadsheetWorksheet = class {
642
681
  return `${this.a1SheetName}!${filter}`;
643
682
  }
644
683
  if (es_toolkit_compat.isObject(filter)) {
684
+ if ("developerMetadataLookup" in filter) return filter;
645
685
  const filterAny = filter;
646
686
  if (filterAny.sheetId && filterAny.sheetId !== this.sheetId) throw new Error("Leave sheet ID blank or set to matching ID of this sheet");
647
687
  return {
@@ -731,7 +771,9 @@ var GoogleSpreadsheetWorksheet = class {
731
771
  return new GoogleSpreadsheetRow(this, rowNumber++, rowValues);
732
772
  });
733
773
  }
734
- /** add a single row - see addRows for more info */
774
+ /**
775
+ * add a single row - see addRows for more info
776
+ */
735
777
  async addRow(rowValues, options) {
736
778
  return (await this.addRows([rowValues], options))[0];
737
779
  }
@@ -771,6 +813,79 @@ var GoogleSpreadsheetWorksheet = class {
771
813
  if (row.rowNumber > deletedRowNumber) row._updateRowNumber(row.rowNumber - 1);
772
814
  });
773
815
  }
816
+ /**
817
+ * @internal
818
+ * Used internally to update row numbers after deleting multiple rows.
819
+ * Should not be called directly.
820
+ * */
821
+ _shiftRowCacheBulk(startIndex, endIndex) {
822
+ const numDeleted = endIndex - startIndex;
823
+ const startRow = startIndex + 1;
824
+ const endRow = endIndex;
825
+ for (let rowNum = startRow; rowNum <= endRow; rowNum++) {
826
+ const row = this._rowCache[rowNum];
827
+ if (row) row._markDeleted();
828
+ delete this._rowCache[rowNum];
829
+ }
830
+ this._rowCache.forEach((row) => {
831
+ if (row.rowNumber > endRow) row._updateRowNumber(row.rowNumber - numDeleted);
832
+ });
833
+ }
834
+ /**
835
+ * @internal
836
+ * Used internally to shift cell cache after deleting rows.
837
+ * Should not be called directly.
838
+ * */
839
+ _shiftCellCacheRows(startIndex, endIndex) {
840
+ const numDeleted = endIndex - startIndex;
841
+ for (let rowIndex = startIndex; rowIndex < endIndex; rowIndex++) {
842
+ const row = this._cells[rowIndex];
843
+ if (row) row.forEach((cell) => {
844
+ if (cell) cell._markDeleted();
845
+ });
846
+ delete this._cells[rowIndex];
847
+ }
848
+ const rowsToShift = [];
849
+ for (let rowIndex = endIndex; rowIndex < this._cells.length; rowIndex++) if (this._cells[rowIndex]) rowsToShift.push({
850
+ oldRowIndex: rowIndex,
851
+ cells: this._cells[rowIndex]
852
+ });
853
+ rowsToShift.forEach(({ oldRowIndex, cells }) => {
854
+ delete this._cells[oldRowIndex];
855
+ const newRowIndex = oldRowIndex - numDeleted;
856
+ this._cells[newRowIndex] = cells;
857
+ cells.forEach((cell, colIndex) => {
858
+ if (cell) cell._updateIndices(newRowIndex, colIndex);
859
+ });
860
+ });
861
+ }
862
+ /**
863
+ * @internal
864
+ * Used internally to shift cell cache after deleting columns.
865
+ * Should not be called directly.
866
+ * */
867
+ _shiftCellCacheColumns(startIndex, endIndex) {
868
+ const numDeleted = endIndex - startIndex;
869
+ this._cells.forEach((row, rowIndex) => {
870
+ if (!row) return;
871
+ for (let colIndex = startIndex; colIndex < endIndex; colIndex++) {
872
+ const cell = row[colIndex];
873
+ if (cell) cell._markDeleted();
874
+ delete row[colIndex];
875
+ }
876
+ const cellsToShift = [];
877
+ for (let colIndex = endIndex; colIndex < row.length; colIndex++) if (row[colIndex]) cellsToShift.push({
878
+ oldColIndex: colIndex,
879
+ cell: row[colIndex]
880
+ });
881
+ cellsToShift.forEach(({ oldColIndex, cell }) => {
882
+ delete row[oldColIndex];
883
+ const newColIndex = oldColIndex - numDeleted;
884
+ row[newColIndex] = cell;
885
+ cell._updateIndices(rowIndex, newColIndex);
886
+ });
887
+ });
888
+ }
774
889
  async clearRows(options) {
775
890
  const startRowIndex = options?.start || this._headerRowIndex + 1;
776
891
  const endRowIndex = options?.end || this.rowCount;
@@ -795,12 +910,13 @@ var GoogleSpreadsheetWorksheet = class {
795
910
  async updateGridProperties(gridProperties) {
796
911
  return this.updateProperties({ gridProperties });
797
912
  }
798
- /** resize, internally just calls updateGridProperties */
913
+ /**
914
+ * resize, internally just calls updateGridProperties
915
+ */
799
916
  async resize(gridProperties) {
800
917
  return this.updateGridProperties(gridProperties);
801
918
  }
802
919
  /**
803
- *
804
920
  * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#updatedimensionpropertiesrequest
805
921
  */
806
922
  async updateDimensionProperties(columnsOrRows, properties, bounds) {
@@ -821,15 +937,96 @@ var GoogleSpreadsheetWorksheet = class {
821
937
  const ranges = a1Ranges.map((r) => `ranges=${this.encodedA1SheetName}!${r}`).join("&");
822
938
  return (await (await this._spreadsheet.sheetsApi.get(`values:batchGet?${ranges}`, { searchParams: options })).json()).valueRanges.map((r) => r.values);
823
939
  }
824
- async updateNamedRange() {}
825
- async addNamedRange() {}
826
- async deleteNamedRange() {}
827
- async repeatCell() {}
828
- async autoFill() {}
829
- async cutPaste() {}
830
- async copyPaste() {}
940
+ /**
941
+ * Updates an existing named range
942
+ *
943
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateNamedRangeRequest
944
+ */
945
+ async updateNamedRange(namedRangeId, namedRange, fields) {
946
+ return this._makeSingleUpdateRequest("updateNamedRange", {
947
+ namedRange: {
948
+ namedRangeId,
949
+ ...namedRange.name && { name: namedRange.name },
950
+ ...namedRange.range && { range: this._addSheetIdToRange(namedRange.range) }
951
+ },
952
+ fields
953
+ });
954
+ }
955
+ /**
956
+ * Creates a new named range in this worksheet (convenience method that auto-fills sheetId)
957
+ *
958
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddNamedRangeRequest
959
+ */
960
+ async addNamedRange(name, range, namedRangeId) {
961
+ return this._spreadsheet.addNamedRange(name, this._addSheetIdToRange(range), namedRangeId);
962
+ }
963
+ /**
964
+ * Deletes a named range (convenience wrapper)
965
+ *
966
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteNamedRangeRequest
967
+ */
968
+ async deleteNamedRange(namedRangeId) {
969
+ return this._spreadsheet.deleteNamedRange(namedRangeId);
970
+ }
971
+ /**
972
+ * Updates all cells in a range with the same cell data
973
+ *
974
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#RepeatCellRequest
975
+ */
976
+ async repeatCell(range, cell, fields) {
977
+ await this._makeSingleUpdateRequest("repeatCell", {
978
+ range: this._addSheetIdToRange(range),
979
+ cell,
980
+ fields
981
+ });
982
+ }
983
+ /**
984
+ * Auto-fills cells with data following a pattern (like dragging the fill handle)
985
+ *
986
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AutoFillRequest
987
+ */
988
+ async autoFill(rangeOrSource, useAlternateSeries) {
989
+ const isSourceAndDestination = "dimension" in rangeOrSource;
990
+ await this._makeSingleUpdateRequest("autoFill", {
991
+ ...isSourceAndDestination ? { sourceAndDestination: {
992
+ ...rangeOrSource,
993
+ source: this._addSheetIdToRange(rangeOrSource.source)
994
+ } } : { range: this._addSheetIdToRange(rangeOrSource) },
995
+ ...useAlternateSeries !== void 0 && { useAlternateSeries }
996
+ });
997
+ }
998
+ /**
999
+ * Cuts data from a source range and pastes it to a destination coordinate
1000
+ *
1001
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#CutPasteRequest
1002
+ */
1003
+ async cutPaste(source, destination, pasteType = "PASTE_NORMAL") {
1004
+ await this._makeSingleUpdateRequest("cutPaste", {
1005
+ source: this._addSheetIdToRange(source),
1006
+ destination: {
1007
+ sheetId: this.sheetId,
1008
+ rowIndex: destination.rowIndex,
1009
+ columnIndex: destination.columnIndex
1010
+ },
1011
+ pasteType
1012
+ });
1013
+ }
1014
+ /**
1015
+ * Copies data from a source range and pastes it to a destination range
1016
+ *
1017
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#CopyPasteRequest
1018
+ */
1019
+ async copyPaste(source, destination, pasteType = "PASTE_NORMAL", pasteOrientation = "NORMAL") {
1020
+ await this._makeSingleUpdateRequest("copyPaste", {
1021
+ source: this._addSheetIdToRange(source),
1022
+ destination: this._addSheetIdToRange(destination),
1023
+ pasteType,
1024
+ pasteOrientation
1025
+ });
1026
+ }
831
1027
  /**
832
1028
  * Merges all cells in the range
1029
+ *
833
1030
  * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#MergeCellsRequest
834
1031
  */
835
1032
  async mergeCells(range, mergeType = "MERGE_ALL") {
@@ -840,21 +1037,114 @@ var GoogleSpreadsheetWorksheet = class {
840
1037
  }
841
1038
  /**
842
1039
  * Unmerges cells in the given range
1040
+ *
843
1041
  * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UnmergeCellsRequest
844
1042
  */
845
1043
  async unmergeCells(range) {
846
1044
  await this._makeSingleUpdateRequest("unmergeCells", { range: this._addSheetIdToRange(range) });
847
1045
  }
848
- async updateBorders() {}
849
- async addFilterView() {}
850
- async appendCells() {}
851
- async clearBasicFilter() {}
852
- async deleteDimension() {}
853
- async deleteEmbeddedObject() {}
854
- async deleteFilterView() {}
855
- async duplicateFilterView() {}
1046
+ /**
1047
+ * Updates borders for a range
1048
+ *
1049
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateBordersRequest
1050
+ */
1051
+ async updateBorders(range, borders) {
1052
+ await this._makeSingleUpdateRequest("updateBorders", {
1053
+ range: this._addSheetIdToRange(range),
1054
+ ...borders
1055
+ });
1056
+ }
1057
+ /**
1058
+ * Adds a filter view to the sheet
1059
+ *
1060
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddFilterViewRequest
1061
+ */
1062
+ async addFilterView(filter) {
1063
+ return this._makeSingleUpdateRequest("addFilterView", { filter });
1064
+ }
1065
+ /**
1066
+ * Appends cells after the last row with data in a sheet
1067
+ *
1068
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AppendCellsRequest
1069
+ */
1070
+ async appendCells(rows, fields) {
1071
+ await this._makeSingleUpdateRequest("appendCells", {
1072
+ sheetId: this.sheetId,
1073
+ rows,
1074
+ fields
1075
+ });
1076
+ }
1077
+ /**
1078
+ * Clears the basic filter on this sheet
1079
+ *
1080
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#ClearBasicFilterRequest
1081
+ */
1082
+ async clearBasicFilter() {
1083
+ await this._makeSingleUpdateRequest("clearBasicFilter", { sheetId: this.sheetId });
1084
+ }
1085
+ /**
1086
+ * Delete rows or columns in a given range
1087
+ *
1088
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteDimensionRequest
1089
+ */
1090
+ async deleteDimension(columnsOrRows, rangeIndexes) {
1091
+ if (!columnsOrRows) throw new Error("You need to specify a dimension. i.e. COLUMNS|ROWS");
1092
+ if (!es_toolkit_compat.isObject(rangeIndexes)) throw new Error("`range` must be an object containing `startIndex` and `endIndex`");
1093
+ if (!es_toolkit_compat.isInteger(rangeIndexes.startIndex) || rangeIndexes.startIndex < 0) throw new Error("range.startIndex must be an integer >=0");
1094
+ if (!es_toolkit_compat.isInteger(rangeIndexes.endIndex) || rangeIndexes.endIndex < 0) throw new Error("range.endIndex must be an integer >=0");
1095
+ if (rangeIndexes.endIndex <= rangeIndexes.startIndex) throw new Error("range.endIndex must be greater than range.startIndex");
1096
+ const result = await this._makeSingleUpdateRequest("deleteDimension", { range: {
1097
+ sheetId: this.sheetId,
1098
+ dimension: columnsOrRows,
1099
+ startIndex: rangeIndexes.startIndex,
1100
+ endIndex: rangeIndexes.endIndex
1101
+ } });
1102
+ if (columnsOrRows === "ROWS") {
1103
+ this._shiftRowCacheBulk(rangeIndexes.startIndex, rangeIndexes.endIndex);
1104
+ this._shiftCellCacheRows(rangeIndexes.startIndex, rangeIndexes.endIndex);
1105
+ } else this._shiftCellCacheColumns(rangeIndexes.startIndex, rangeIndexes.endIndex);
1106
+ return result;
1107
+ }
1108
+ /**
1109
+ * Delete rows by index
1110
+ */
1111
+ async deleteRows(startIndex, endIndex) {
1112
+ return this.deleteDimension("ROWS", {
1113
+ startIndex,
1114
+ endIndex
1115
+ });
1116
+ }
1117
+ /**
1118
+ * Delete columns by index
1119
+ */
1120
+ async deleteColumns(startIndex, endIndex) {
1121
+ return this.deleteDimension("COLUMNS", {
1122
+ startIndex,
1123
+ endIndex
1124
+ });
1125
+ }
1126
+ async deleteEmbeddedObject() {
1127
+ throw new Error("Not implemented yet");
1128
+ }
1129
+ /**
1130
+ * Deletes a filter view from the sheet
1131
+ *
1132
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteFilterViewRequest
1133
+ */
1134
+ async deleteFilterView(filterId) {
1135
+ await this._makeSingleUpdateRequest("deleteFilterView", { filterId });
1136
+ }
1137
+ /**
1138
+ * Duplicates a filter view
1139
+ *
1140
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DuplicateFilterViewRequest
1141
+ */
1142
+ async duplicateFilterView(filterId) {
1143
+ await this._makeSingleUpdateRequest("duplicateFilterView", { filterId });
1144
+ }
856
1145
  /**
857
1146
  * Duplicate worksheet within the document
1147
+ *
858
1148
  * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DuplicateSheetRequest
859
1149
  */
860
1150
  async duplicate(options) {
@@ -866,9 +1156,22 @@ var GoogleSpreadsheetWorksheet = class {
866
1156
  })).properties.sheetId;
867
1157
  return this._spreadsheet.sheetsById[newSheetId];
868
1158
  }
869
- async findReplace() {}
1159
+ /**
1160
+ * Finds and replaces text in cells
1161
+ *
1162
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#FindReplaceRequest
1163
+ */
1164
+ async findReplace(find, replacement, options, range) {
1165
+ await this._makeSingleUpdateRequest("findReplace", {
1166
+ find,
1167
+ replacement,
1168
+ ...options,
1169
+ ...range ? { range: this._addSheetIdToRange(range) } : { sheetId: this.sheetId }
1170
+ });
1171
+ }
870
1172
  /**
871
1173
  * Inserts rows or columns at a particular index
1174
+ *
872
1175
  * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#InsertDimensionRequest
873
1176
  */
874
1177
  async insertDimension(columnsOrRows, rangeIndexes, inheritFromBefore) {
@@ -891,27 +1194,143 @@ var GoogleSpreadsheetWorksheet = class {
891
1194
  }
892
1195
  /**
893
1196
  * insert empty cells in a range, shifting existing cells in the specified direction
1197
+ *
894
1198
  * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#InsertRangeRequest
895
1199
  */
896
1200
  async insertRange(range, shiftDimension) {
897
- return this._makeSingleUpdateRequest("insertRange", {
1201
+ await this._makeSingleUpdateRequest("insertRange", {
1202
+ range: this._addSheetIdToRange(range),
1203
+ shiftDimension
1204
+ });
1205
+ }
1206
+ /**
1207
+ * Moves rows or columns to a different position within the sheet
1208
+ *
1209
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#MoveDimensionRequest
1210
+ */
1211
+ async moveDimension(dimension, source, destinationIndex) {
1212
+ await this._makeSingleUpdateRequest("moveDimension", {
1213
+ source: {
1214
+ sheetId: this.sheetId,
1215
+ dimension,
1216
+ startIndex: source.startIndex,
1217
+ endIndex: source.endIndex
1218
+ },
1219
+ destinationIndex
1220
+ });
1221
+ }
1222
+ async updateEmbeddedObjectPosition() {
1223
+ throw new Error("Not implemented yet");
1224
+ }
1225
+ /**
1226
+ * Inserts data into the spreadsheet starting at the specified coordinate
1227
+ *
1228
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#PasteDataRequest
1229
+ */
1230
+ async pasteData(coordinate, data, delimiter, type = "PASTE_NORMAL") {
1231
+ await this._makeSingleUpdateRequest("pasteData", {
1232
+ coordinate: {
1233
+ sheetId: this.sheetId,
1234
+ rowIndex: coordinate.rowIndex,
1235
+ columnIndex: coordinate.columnIndex
1236
+ },
1237
+ data,
1238
+ delimiter,
1239
+ type
1240
+ });
1241
+ }
1242
+ /**
1243
+ * Splits a column of text into multiple columns based on a delimiter
1244
+ *
1245
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#TextToColumnsRequest
1246
+ */
1247
+ async textToColumns(source, delimiterType, delimiter) {
1248
+ await this._makeSingleUpdateRequest("textToColumns", {
1249
+ source: this._addSheetIdToRange(source),
1250
+ delimiterType,
1251
+ ...delimiter && { delimiter }
1252
+ });
1253
+ }
1254
+ /**
1255
+ * Updates properties of a filter view
1256
+ *
1257
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateFilterViewRequest
1258
+ */
1259
+ async updateFilterView(filter, fields) {
1260
+ await this._makeSingleUpdateRequest("updateFilterView", {
1261
+ filter,
1262
+ fields
1263
+ });
1264
+ }
1265
+ /**
1266
+ * Deletes a range of cells and shifts remaining cells
1267
+ *
1268
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteRangeRequest
1269
+ */
1270
+ async deleteRange(range, shiftDimension) {
1271
+ await this._makeSingleUpdateRequest("deleteRange", {
898
1272
  range: this._addSheetIdToRange(range),
899
1273
  shiftDimension
900
1274
  });
901
1275
  }
902
- async moveDimension() {}
903
- async updateEmbeddedObjectPosition() {}
904
- async pasteData() {}
905
- async textToColumns() {}
906
- async updateFilterView() {}
907
- async deleteRange() {}
908
- async appendDimension() {}
909
- async addConditionalFormatRule() {}
910
- async updateConditionalFormatRule() {}
911
- async deleteConditionalFormatRule() {}
912
- async sortRange() {}
1276
+ /**
1277
+ * Appends rows or columns to the end of a sheet
1278
+ *
1279
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AppendDimensionRequest
1280
+ */
1281
+ async appendDimension(dimension, length) {
1282
+ await this._makeSingleUpdateRequest("appendDimension", {
1283
+ sheetId: this.sheetId,
1284
+ dimension,
1285
+ length
1286
+ });
1287
+ }
1288
+ /**
1289
+ * Adds a new conditional formatting rule at the given index
1290
+ * All subsequent rules' indexes are incremented
1291
+ *
1292
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddConditionalFormatRuleRequest
1293
+ */
1294
+ async addConditionalFormatRule(rule, index) {
1295
+ await this._makeSingleUpdateRequest("addConditionalFormatRule", {
1296
+ rule,
1297
+ index
1298
+ });
1299
+ }
1300
+ /**
1301
+ * Updates a conditional format rule at the given index, or moves a conditional format rule to another index
1302
+ *
1303
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateConditionalFormatRuleRequest
1304
+ */
1305
+ async updateConditionalFormatRule(options) {
1306
+ await this._makeSingleUpdateRequest("updateConditionalFormatRule", options);
1307
+ }
1308
+ /**
1309
+ * Deletes a conditional format rule at the given index
1310
+ * All subsequent rules' indexes are decremented
1311
+ *
1312
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteConditionalFormatRuleRequest
1313
+ */
1314
+ async deleteConditionalFormatRule(index, sheetId) {
1315
+ await this._makeSingleUpdateRequest("deleteConditionalFormatRule", {
1316
+ index,
1317
+ sheetId: sheetId ?? this.sheetId
1318
+ });
1319
+ }
1320
+ /**
1321
+ * Sorts data in rows based on sort order per column
1322
+ *
1323
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#SortRangeRequest
1324
+ */
1325
+ async sortRange(range, sortSpecs) {
1326
+ await this._makeSingleUpdateRequest("sortRange", {
1327
+ range: this._addSheetIdToRange(range),
1328
+ sortSpecs
1329
+ });
1330
+ }
913
1331
  /**
914
1332
  * Sets (or unsets) a data validation rule to every cell in the range
1333
+ *
915
1334
  * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#SetDataValidationRequest
916
1335
  */
917
1336
  async setDataValidation(range, rule) {
@@ -923,9 +1342,20 @@ var GoogleSpreadsheetWorksheet = class {
923
1342
  ...rule && { rule }
924
1343
  });
925
1344
  }
926
- async setBasicFilter() {}
1345
+ /**
1346
+ * Sets the basic filter on this sheet
1347
+ *
1348
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#SetBasicFilterRequest
1349
+ */
1350
+ async setBasicFilter(filter) {
1351
+ await this._makeSingleUpdateRequest("setBasicFilter", { filter: {
1352
+ ...filter,
1353
+ ...filter.range && { range: this._addSheetIdToRange(filter.range) }
1354
+ } });
1355
+ }
927
1356
  /**
928
1357
  * add a new protected range to the sheet
1358
+ *
929
1359
  * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddProtectedRangeRequest
930
1360
  */
931
1361
  async addProtectedRange(protectedRange) {
@@ -934,6 +1364,7 @@ var GoogleSpreadsheetWorksheet = class {
934
1364
  }
935
1365
  /**
936
1366
  * update an existing protected range
1367
+ *
937
1368
  * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateProtectedRangeRequest
938
1369
  */
939
1370
  async updateProtectedRange(protectedRangeId, protectedRange) {
@@ -947,6 +1378,7 @@ var GoogleSpreadsheetWorksheet = class {
947
1378
  }
948
1379
  /**
949
1380
  * delete a protected range by ID
1381
+ *
950
1382
  * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteProtectedRangeRequest
951
1383
  */
952
1384
  async deleteProtectedRange(protectedRangeId) {
@@ -954,6 +1386,7 @@ var GoogleSpreadsheetWorksheet = class {
954
1386
  }
955
1387
  /**
956
1388
  * auto-resize rows or columns to fit their contents
1389
+ *
957
1390
  * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AutoResizeDimensionsRequest
958
1391
  */
959
1392
  async autoResizeDimensions(columnsOrRows, rangeIndexes) {
@@ -963,34 +1396,126 @@ var GoogleSpreadsheetWorksheet = class {
963
1396
  ...rangeIndexes
964
1397
  } });
965
1398
  }
966
- async addChart() {}
967
- async updateChartSpec() {}
968
- async updateBanding() {}
969
- async addBanding() {}
970
- async deleteBanding() {}
971
- async createDeveloperMetadata() {}
972
- async updateDeveloperMetadata() {}
973
- async deleteDeveloperMetadata() {}
974
- async randomizeRange() {}
975
- async addDimensionGroup() {}
976
- async deleteDimensionGroup() {}
977
- async updateDimensionGroup() {}
978
- async trimWhitespace() {}
979
- async deleteDuplicates() {}
980
- async addSlicer() {}
981
- async updateSlicerSpec() {}
982
- /** delete this worksheet */
1399
+ async addChart() {
1400
+ throw new Error("Not implemented yet");
1401
+ }
1402
+ async updateChartSpec() {
1403
+ throw new Error("Not implemented yet");
1404
+ }
1405
+ /**
1406
+ * Updates properties of a banded range
1407
+ *
1408
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateBandingRequest
1409
+ */
1410
+ async updateBanding(bandedRange, fields) {
1411
+ await this._makeSingleUpdateRequest("updateBanding", {
1412
+ bandedRange,
1413
+ fields
1414
+ });
1415
+ }
1416
+ /**
1417
+ * Adds a new banded range to the sheet
1418
+ *
1419
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddBandingRequest
1420
+ */
1421
+ async addBanding(bandedRange) {
1422
+ return this._makeSingleUpdateRequest("addBanding", { bandedRange });
1423
+ }
1424
+ /**
1425
+ * Deletes a banded range from the sheet
1426
+ *
1427
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteBandingRequest
1428
+ */
1429
+ async deleteBanding(bandedRangeId) {
1430
+ await this._makeSingleUpdateRequest("deleteBanding", { bandedRangeId });
1431
+ }
1432
+ /**
1433
+ * Creates developer metadata
1434
+ *
1435
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#CreateDeveloperMetadataRequest
1436
+ */
1437
+ async createDeveloperMetadata(developerMetadata) {
1438
+ return this._makeSingleUpdateRequest("createDeveloperMetadata", { developerMetadata });
1439
+ }
1440
+ /**
1441
+ * Updates developer metadata that matches the specified filters
1442
+ *
1443
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateDeveloperMetadataRequest
1444
+ */
1445
+ async updateDeveloperMetadata(dataFilters, developerMetadata, fields) {
1446
+ await this._makeSingleUpdateRequest("updateDeveloperMetadata", {
1447
+ dataFilters,
1448
+ developerMetadata,
1449
+ fields
1450
+ });
1451
+ }
1452
+ /**
1453
+ * Deletes developer metadata that matches the specified filter
1454
+ *
1455
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteDeveloperMetadataRequest
1456
+ */
1457
+ async deleteDeveloperMetadata(dataFilter) {
1458
+ await this._makeSingleUpdateRequest("deleteDeveloperMetadata", { dataFilter });
1459
+ }
1460
+ /**
1461
+ * Randomizes the order of rows in a range
1462
+ *
1463
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#RandomizeRangeRequest
1464
+ */
1465
+ async randomizeRange(range) {
1466
+ await this._makeSingleUpdateRequest("randomizeRange", { range: this._addSheetIdToRange(range) });
1467
+ }
1468
+ async addDimensionGroup() {
1469
+ throw new Error("Not implemented yet");
1470
+ }
1471
+ async deleteDimensionGroup() {
1472
+ throw new Error("Not implemented yet");
1473
+ }
1474
+ async updateDimensionGroup() {
1475
+ throw new Error("Not implemented yet");
1476
+ }
1477
+ /**
1478
+ * Trims whitespace from the start and end of each cell's text
1479
+ *
1480
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#TrimWhitespaceRequest
1481
+ */
1482
+ async trimWhitespace(range) {
1483
+ await this._makeSingleUpdateRequest("trimWhitespace", { range: this._addSheetIdToRange(range) });
1484
+ }
1485
+ /**
1486
+ * Removes duplicate rows from a range based on specified columns
1487
+ *
1488
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteDuplicatesRequest
1489
+ */
1490
+ async deleteDuplicates(range, comparisonColumns) {
1491
+ await this._makeSingleUpdateRequest("deleteDuplicates", {
1492
+ range: this._addSheetIdToRange(range),
1493
+ ...comparisonColumns && { comparisonColumns }
1494
+ });
1495
+ }
1496
+ async addSlicer() {
1497
+ throw new Error("Not implemented yet");
1498
+ }
1499
+ async updateSlicerSpec() {
1500
+ throw new Error("Not implemented yet");
1501
+ }
1502
+ /**
1503
+ * delete this worksheet
1504
+ */
983
1505
  async delete() {
984
1506
  return this._spreadsheet.deleteSheet(this.sheetId);
985
1507
  }
986
1508
  /**
987
1509
  * copies this worksheet into another document/spreadsheet
1510
+ *
988
1511
  * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.sheets/copyTo
989
- * */
1512
+ */
990
1513
  async copyToSpreadsheet(destinationSpreadsheetId) {
991
1514
  return await this._spreadsheet.sheetsApi.post(`sheets/${this.sheetId}:copyTo`, { json: { destinationSpreadsheetId } }).json();
992
1515
  }
993
- /** clear data in the sheet - either the entire sheet or a specific range */
1516
+ /**
1517
+ * clear data in the sheet - either the entire sheet or a specific range
1518
+ */
994
1519
  async clear(a1Range) {
995
1520
  const range = a1Range ? `!${a1Range}` : "";
996
1521
  await this._spreadsheet.sheetsApi.post(`values/${this.encodedA1SheetName}${range}:clear`);
@@ -1083,7 +1608,8 @@ var GoogleSpreadsheet = class GoogleSpreadsheet {
1083
1608
  * initialize new GoogleSpreadsheet
1084
1609
  * @category Initialization
1085
1610
  * */
1086
- constructor(spreadsheetId, auth) {
1611
+ constructor(spreadsheetId, auth, options) {
1612
+ const { retryConfig } = options || {};
1087
1613
  this.spreadsheetId = spreadsheetId;
1088
1614
  this.auth = auth;
1089
1615
  this._rawSheets = {};
@@ -1094,14 +1620,16 @@ var GoogleSpreadsheet = class GoogleSpreadsheet {
1094
1620
  hooks: {
1095
1621
  beforeRequest: [(r) => this._setAuthRequestHook(r)],
1096
1622
  beforeError: [(e) => this._errorHook(e)]
1097
- }
1623
+ },
1624
+ retry: retryConfig
1098
1625
  });
1099
1626
  this.driveApi = ky.default.create({
1100
1627
  prefixUrl: `${DRIVE_API_BASE_URL}/${spreadsheetId}`,
1101
1628
  hooks: {
1102
1629
  beforeRequest: [(r) => this._setAuthRequestHook(r)],
1103
1630
  beforeError: [(e) => this._errorHook(e)]
1104
- }
1631
+ },
1632
+ retry: retryConfig
1105
1633
  });
1106
1634
  }
1107
1635
  /** @internal */
@@ -1281,6 +1809,7 @@ var GoogleSpreadsheet = class GoogleSpreadsheet {
1281
1809
  if (es_toolkit_compat.isString(filter)) return readOnlyMode ? filter : { a1Range: filter };
1282
1810
  if (es_toolkit_compat.isObject(filter)) {
1283
1811
  if (readOnlyMode) throw new Error("Only A1 ranges are supported when fetching cells with read-only access (using only an API key)");
1812
+ if ("developerMetadataLookup" in filter) return { developerMetadataLookup: filter.developerMetadataLookup };
1284
1813
  return { gridRange: filter };
1285
1814
  }
1286
1815
  throw new Error("Each filter must be an A1 range string or a gridrange object");
@@ -1395,6 +1924,15 @@ var GoogleSpreadsheet = class GoogleSpreadsheet {
1395
1924
  async deletePermission(permissionId) {
1396
1925
  await this.driveApi.delete(`permissions/${permissionId}`);
1397
1926
  }
1927
+ /**
1928
+ * search for developer metadata entries matching the given filters
1929
+ * @see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.developerMetadata/search
1930
+ */
1931
+ async searchDeveloperMetadata(filters) {
1932
+ const data = await (await this.sheetsApi.post("developerMetadata:search", { json: { dataFilters: filters } })).json();
1933
+ if (!data.matchedDeveloperMetadata) return [];
1934
+ return data.matchedDeveloperMetadata.map((m) => m.developerMetadata);
1935
+ }
1398
1936
  static async createNewSpreadsheetDocument(auth, properties) {
1399
1937
  if (getAuthMode(auth) === AUTH_MODES.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");
1400
1938
  const authConfig = await getRequestAuthConfig(auth);