google-sheets-mapper 2.0.0 → 2.1.1

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
@@ -8,19 +8,19 @@
8
8
 
9
9
  ## Installation
10
10
 
11
- Package can be added using **yarn**:
12
-
13
11
  ```bash
14
- yarn add google-sheets-mapper
12
+ npm install google-sheets-mapper
15
13
  ```
16
14
 
17
- Or, use **NPM**:
15
+ ```bash
16
+ pnpm add google-sheets-mapper
17
+ ```
18
18
 
19
19
  ```bash
20
- npm install google-sheets-mapper
20
+ bun add google-sheets-mapper
21
21
  ```
22
22
 
23
- UMD build available on [unpkg](https://www.unpkg.com/browse/google-sheets-mapper@1.0.0/dist/google-sheets-mapper.cjs.production.min.js).
23
+ UMD build available on [unpkg](https://www.unpkg.com/browse/google-sheets-mapper/).
24
24
 
25
25
  ---
26
26
 
@@ -44,7 +44,7 @@ https://docs.google.com/spreadsheets/d/[THIS-IS-THE-SHEET-ID]/
44
44
  ### Get data from all sheets inside the spreadsheet
45
45
 
46
46
  ```js
47
- import { fetchGoogleSheetsData } from 'google-sheets-mapper';
47
+ import { fetchGoogleSheetsData } from "google-sheets-mapper";
48
48
 
49
49
  const getData = async () => {
50
50
  try {
@@ -63,14 +63,14 @@ const getData = async () => {
63
63
  Don't use single quotes on sheet names, they will be removed because when using space in sheet name it will be returned wrapped with single quotes and plugin will remove them for clean string id.
64
64
 
65
65
  ```js
66
- import { fetchGoogleSheetsData } from 'google-sheets-mapper';
66
+ import { fetchGoogleSheetsData } from "google-sheets-mapper";
67
67
 
68
68
  const getData = async () => {
69
69
  try {
70
70
  return await fetchGoogleSheetsData({
71
71
  apiKey: process.env.REACT_APP_GOOGLE_API_KEY,
72
72
  sheetId: process.env.REACT_APP_GOOGLE_SHEETS_ID,
73
- sheetsOptions: [{ id: 'Sheet1' }],
73
+ sheetsOptions: [{ id: "Sheet1" }],
74
74
  });
75
75
  } catch (error) {
76
76
  console.error(error);
@@ -119,10 +119,10 @@ try {
119
119
  ```js
120
120
  [
121
121
  {
122
- id: 'Sheet1',
122
+ id: "Sheet1",
123
123
  data: [
124
- { value: 'et', key: 'language' },
125
- { value: 'Test sheet', key: 'title' },
124
+ { value: "et", key: "language" },
125
+ { value: "Test sheet", key: "title" },
126
126
  ],
127
127
  },
128
128
  ];
package/dist/index.cjs ADDED
@@ -0,0 +1,95 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ const GOOGLE_API_URL = "https://sheets.googleapis.com/v4/spreadsheets";
4
+ const getRanges = (sheetNames = [])=>{
5
+ // ranges=Sheet1&ranges=Sheet2
6
+ return sheetNames.map((sheetName)=>`ranges=${sheetName}`).join("&");
7
+ };
8
+ const getSheetsTitleUrl = (sheetId, apiKey)=>{
9
+ return `${GOOGLE_API_URL}/${sheetId}?fields=sheets%2Fproperties%2Ftitle&key=${apiKey}`;
10
+ };
11
+ const getBatchUrl = (sheetId, ranges, apiKey)=>{
12
+ const rangesQueryString = getRanges(ranges);
13
+ return `${GOOGLE_API_URL}/${sheetId}?${rangesQueryString}&key=${apiKey}&includeGridData=true`;
14
+ };
15
+ const makeFetch = async (url, config = {})=>{
16
+ const response = await fetch(url, config);
17
+ if (!response.ok) {
18
+ throw new Error(`Request to '${url}' failed with ${response.status}${response.statusText ? `: ${response.statusText}` : ""}`, {
19
+ cause: {
20
+ status: response.status,
21
+ statusText: response.statusText,
22
+ url: response.url
23
+ }
24
+ });
25
+ }
26
+ return await response.json();
27
+ };
28
+ const mapRecords = (records, headerData)=>{
29
+ return records.filter((record)=>record.length > 0).map((record)=>record.reduce((obj, item, index)=>{
30
+ const key = headerData[index];
31
+ if (key !== undefined) {
32
+ obj[key] = item;
33
+ }
34
+ return obj;
35
+ }, {}));
36
+ };
37
+ const mapData = ({ sheets, sheetsOptions = [] })=>{
38
+ return sheets.map((sheet)=>{
39
+ const id = sheet.range.split("!")[0].replace(/'/g, "");
40
+ const rows = sheet.values || [];
41
+ if (rows.length > 0) {
42
+ const sheetsOptionsSheet = sheetsOptions.find((option)=>option.id === id);
43
+ const headerRowIndex = sheetsOptionsSheet?.headerRowIndex ?? 0;
44
+ const header = rows[headerRowIndex];
45
+ const records = rows.filter((_, index)=>index > headerRowIndex);
46
+ const recordsData = mapRecords(records, header);
47
+ return {
48
+ id,
49
+ data: recordsData
50
+ };
51
+ }
52
+ return {
53
+ id,
54
+ data: []
55
+ };
56
+ });
57
+ };
58
+ const fetchBatchData = async ({ apiKey, sheetId, sheetsOptions = [] })=>{
59
+ const sheetsNames = sheetsOptions.map((option)=>option.id);
60
+ const url = getBatchUrl(sheetId, sheetsNames, apiKey);
61
+ return await makeFetch(url);
62
+ };
63
+ const fetchAllSheetsData = async ({ apiKey, sheetId })=>{
64
+ const urlTitles = getSheetsTitleUrl(sheetId, apiKey);
65
+ const { sheets } = await makeFetch(urlTitles);
66
+ const sheetsOptions = sheets.map((sheet)=>({
67
+ id: sheet.properties.title
68
+ }));
69
+ return await fetchBatchData({
70
+ apiKey,
71
+ sheetId,
72
+ sheetsOptions
73
+ });
74
+ };
75
+
76
+ const GoogleSheetsMapper = {
77
+ async fetchGoogleSheetsData ({ apiKey, sheetId, sheetsOptions = [] }) {
78
+ const response = sheetsOptions.length === 0 ? await fetchAllSheetsData({
79
+ apiKey,
80
+ sheetId
81
+ }) : await fetchBatchData({
82
+ apiKey,
83
+ sheetId,
84
+ sheetsOptions
85
+ });
86
+ return mapData({
87
+ sheets: response.valueRanges,
88
+ sheetsOptions
89
+ });
90
+ }
91
+ };
92
+ const fetchGoogleSheetsData = GoogleSheetsMapper.fetchGoogleSheetsData;
93
+
94
+ exports.default = GoogleSheetsMapper;
95
+ exports.fetchGoogleSheetsData = fetchGoogleSheetsData;
@@ -0,0 +1,22 @@
1
+ interface SheetsOption {
2
+ id: string;
3
+ headerRowIndex?: number;
4
+ }
5
+ interface MapperOptions {
6
+ apiKey: string;
7
+ sheetId: string;
8
+ sheetsOptions?: SheetsOption[];
9
+ }
10
+ interface MapperState {
11
+ id: string;
12
+ data: Record<string, string>[];
13
+ }
14
+
15
+ declare const GoogleSheetsMapper: {
16
+ fetchGoogleSheetsData({ apiKey, sheetId, sheetsOptions, }: MapperOptions): Promise<MapperState[]>;
17
+ };
18
+
19
+ declare const fetchGoogleSheetsData: ({ apiKey, sheetId, sheetsOptions, }: MapperOptions) => Promise<MapperState[]>;
20
+
21
+ export { GoogleSheetsMapper as default, fetchGoogleSheetsData };
22
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","sources":["../src/types.ts","../src/index.ts"],"sourcesContent":["export interface SheetsOption {\n id: string;\n headerRowIndex?: number;\n}\n\nexport interface MapperOptions {\n apiKey: string;\n sheetId: string;\n sheetsOptions?: SheetsOption[];\n}\n\nexport interface ValueRange {\n majorDimensions: string;\n range: string;\n values: string[][];\n}\n\nexport interface ValueRangesResponse {\n spreadsheetId: string;\n valueRanges: ValueRange[];\n}\n\nexport interface PropertiesFromResponse {\n title: string;\n}\n\nexport interface SheetFromResponse {\n properties: PropertiesFromResponse;\n}\n\nexport interface SheetsResponse {\n sheets: SheetFromResponse[];\n}\n\nexport interface MapperState {\n id: string;\n data: Record<string, string>[];\n}\n","import type { MapperOptions, MapperState, ValueRangesResponse } from \"./types\";\nimport { fetchBatchData, fetchAllSheetsData, mapData } from \"./utils\";\n\nconst GoogleSheetsMapper = {\n async fetchGoogleSheetsData({\n apiKey,\n sheetId,\n sheetsOptions = [],\n }: MapperOptions): Promise<MapperState[]> {\n const response: ValueRangesResponse =\n sheetsOptions.length === 0\n ? await fetchAllSheetsData({ apiKey, sheetId })\n : await fetchBatchData({ apiKey, sheetId, sheetsOptions });\n return mapData({ sheets: response.valueRanges, sheetsOptions });\n },\n};\n\nexport default GoogleSheetsMapper;\nexport const fetchGoogleSheetsData = GoogleSheetsMapper.fetchGoogleSheetsData;\n"],"names":[],"mappings":"AAAO,UAAA,YAAA;AACP;AACA;AACA;AACO,UAAA,aAAA;AACP;AACA;AACA,oBAAA,YAAA;AACA;AAmBO,UAAA,WAAA;AACP;AACA,UAAA,MAAA;AACA;;AC7BA,cAAA,kBAAA;AACA,+DAAA,aAAA,GAAA,OAAA,CAAA,WAAA;AACA;;AAEO,cAAA,qBAAA,wCAAA,aAAA,KAAA,OAAA,CAAA,WAAA;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,22 @@
1
- import { MapperOptions, MapperState } from './types';
2
- declare const GoogleSheetsMapper: {
3
- fetchGoogleSheetsData({ apiKey, sheetId, sheetsOptions, }: MapperOptions): Promise<MapperState[]>;
4
- };
5
- export default GoogleSheetsMapper;
6
- export declare const fetchGoogleSheetsData: ({ apiKey, sheetId, sheetsOptions, }: MapperOptions) => Promise<MapperState[]>;
1
+ interface SheetsOption {
2
+ id: string;
3
+ headerRowIndex?: number;
4
+ }
5
+ interface MapperOptions {
6
+ apiKey: string;
7
+ sheetId: string;
8
+ sheetsOptions?: SheetsOption[];
9
+ }
10
+ interface MapperState {
11
+ id: string;
12
+ data: Record<string, string>[];
13
+ }
14
+
15
+ declare const GoogleSheetsMapper: {
16
+ fetchGoogleSheetsData({ apiKey, sheetId, sheetsOptions, }: MapperOptions): Promise<MapperState[]>;
17
+ };
18
+
19
+ declare const fetchGoogleSheetsData: ({ apiKey, sheetId, sheetsOptions, }: MapperOptions) => Promise<MapperState[]>;
20
+
21
+ export { GoogleSheetsMapper as default, fetchGoogleSheetsData };
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sources":["../src/types.ts","../src/index.ts"],"sourcesContent":["export interface SheetsOption {\n id: string;\n headerRowIndex?: number;\n}\n\nexport interface MapperOptions {\n apiKey: string;\n sheetId: string;\n sheetsOptions?: SheetsOption[];\n}\n\nexport interface ValueRange {\n majorDimensions: string;\n range: string;\n values: string[][];\n}\n\nexport interface ValueRangesResponse {\n spreadsheetId: string;\n valueRanges: ValueRange[];\n}\n\nexport interface PropertiesFromResponse {\n title: string;\n}\n\nexport interface SheetFromResponse {\n properties: PropertiesFromResponse;\n}\n\nexport interface SheetsResponse {\n sheets: SheetFromResponse[];\n}\n\nexport interface MapperState {\n id: string;\n data: Record<string, string>[];\n}\n","import type { MapperOptions, MapperState, ValueRangesResponse } from \"./types\";\nimport { fetchBatchData, fetchAllSheetsData, mapData } from \"./utils\";\n\nconst GoogleSheetsMapper = {\n async fetchGoogleSheetsData({\n apiKey,\n sheetId,\n sheetsOptions = [],\n }: MapperOptions): Promise<MapperState[]> {\n const response: ValueRangesResponse =\n sheetsOptions.length === 0\n ? await fetchAllSheetsData({ apiKey, sheetId })\n : await fetchBatchData({ apiKey, sheetId, sheetsOptions });\n return mapData({ sheets: response.valueRanges, sheetsOptions });\n },\n};\n\nexport default GoogleSheetsMapper;\nexport const fetchGoogleSheetsData = GoogleSheetsMapper.fetchGoogleSheetsData;\n"],"names":[],"mappings":"AAAO,UAAA,YAAA;AACP;AACA;AACA;AACO,UAAA,aAAA;AACP;AACA;AACA,oBAAA,YAAA;AACA;AAmBO,UAAA,WAAA;AACP;AACA,UAAA,MAAA;AACA;;AC7BA,cAAA,kBAAA;AACA,+DAAA,aAAA,GAAA,OAAA,CAAA,WAAA;AACA;;AAEO,cAAA,qBAAA,wCAAA,aAAA,KAAA,OAAA,CAAA,WAAA;;;;"}
package/dist/index.js CHANGED
@@ -1,8 +1,92 @@
1
+ const GOOGLE_API_URL = "https://sheets.googleapis.com/v4/spreadsheets";
2
+ const getRanges = (sheetNames = [])=>{
3
+ // ranges=Sheet1&ranges=Sheet2
4
+ return sheetNames.map((sheetName)=>`ranges=${sheetName}`).join("&");
5
+ };
6
+ const getSheetsTitleUrl = (sheetId, apiKey)=>{
7
+ return `${GOOGLE_API_URL}/${sheetId}?fields=sheets%2Fproperties%2Ftitle&key=${apiKey}`;
8
+ };
9
+ const getBatchUrl = (sheetId, ranges, apiKey)=>{
10
+ const rangesQueryString = getRanges(ranges);
11
+ return `${GOOGLE_API_URL}/${sheetId}?${rangesQueryString}&key=${apiKey}&includeGridData=true`;
12
+ };
13
+ const makeFetch = async (url, config = {})=>{
14
+ const response = await fetch(url, config);
15
+ if (!response.ok) {
16
+ throw new Error(`Request to '${url}' failed with ${response.status}${response.statusText ? `: ${response.statusText}` : ""}`, {
17
+ cause: {
18
+ status: response.status,
19
+ statusText: response.statusText,
20
+ url: response.url
21
+ }
22
+ });
23
+ }
24
+ return await response.json();
25
+ };
26
+ const mapRecords = (records, headerData)=>{
27
+ return records.filter((record)=>record.length > 0).map((record)=>record.reduce((obj, item, index)=>{
28
+ const key = headerData[index];
29
+ if (key !== undefined) {
30
+ obj[key] = item;
31
+ }
32
+ return obj;
33
+ }, {}));
34
+ };
35
+ const mapData = ({ sheets, sheetsOptions = [] })=>{
36
+ return sheets.map((sheet)=>{
37
+ const id = sheet.range.split("!")[0].replace(/'/g, "");
38
+ const rows = sheet.values || [];
39
+ if (rows.length > 0) {
40
+ const sheetsOptionsSheet = sheetsOptions.find((option)=>option.id === id);
41
+ const headerRowIndex = sheetsOptionsSheet?.headerRowIndex ?? 0;
42
+ const header = rows[headerRowIndex];
43
+ const records = rows.filter((_, index)=>index > headerRowIndex);
44
+ const recordsData = mapRecords(records, header);
45
+ return {
46
+ id,
47
+ data: recordsData
48
+ };
49
+ }
50
+ return {
51
+ id,
52
+ data: []
53
+ };
54
+ });
55
+ };
56
+ const fetchBatchData = async ({ apiKey, sheetId, sheetsOptions = [] })=>{
57
+ const sheetsNames = sheetsOptions.map((option)=>option.id);
58
+ const url = getBatchUrl(sheetId, sheetsNames, apiKey);
59
+ return await makeFetch(url);
60
+ };
61
+ const fetchAllSheetsData = async ({ apiKey, sheetId })=>{
62
+ const urlTitles = getSheetsTitleUrl(sheetId, apiKey);
63
+ const { sheets } = await makeFetch(urlTitles);
64
+ const sheetsOptions = sheets.map((sheet)=>({
65
+ id: sheet.properties.title
66
+ }));
67
+ return await fetchBatchData({
68
+ apiKey,
69
+ sheetId,
70
+ sheetsOptions
71
+ });
72
+ };
1
73
 
2
- 'use strict'
74
+ const GoogleSheetsMapper = {
75
+ async fetchGoogleSheetsData ({ apiKey, sheetId, sheetsOptions = [] }) {
76
+ const response = sheetsOptions.length === 0 ? await fetchAllSheetsData({
77
+ apiKey,
78
+ sheetId
79
+ }) : await fetchBatchData({
80
+ apiKey,
81
+ sheetId,
82
+ sheetsOptions
83
+ });
84
+ return mapData({
85
+ sheets: response.valueRanges,
86
+ sheetsOptions
87
+ });
88
+ }
89
+ };
90
+ const fetchGoogleSheetsData = GoogleSheetsMapper.fetchGoogleSheetsData;
3
91
 
4
- if (process.env.NODE_ENV === 'production') {
5
- module.exports = require('./google-sheets-mapper.cjs.production.min.js')
6
- } else {
7
- module.exports = require('./google-sheets-mapper.cjs.development.js')
8
- }
92
+ export { GoogleSheetsMapper as default, fetchGoogleSheetsData };
package/package.json CHANGED
@@ -1,47 +1,62 @@
1
1
  {
2
2
  "name": "google-sheets-mapper",
3
+ "version": "2.1.1",
3
4
  "description": "### A library for getting data from Google Sheets API v4",
4
- "version": "2.0.0",
5
- "author": "Gert Glükmann <gglukmann@gmail.com>",
6
- "license": "MIT",
5
+ "keywords": [
6
+ "google-sheets",
7
+ "google-sheets-api",
8
+ "google-sheets-api-v4",
9
+ "google-sheets-mapper"
10
+ ],
11
+ "homepage": "https://github.com/gglukmann/use-google-sheets#readme",
7
12
  "bugs": {
8
13
  "url": "https://github.com/gglukmann/use-google-sheets/issues"
9
14
  },
10
- "homepage": "https://github.com/gglukmann/use-google-sheets#readme",
11
- "directories": {
12
- "test": "test"
13
- },
15
+ "license": "MIT",
16
+ "author": "Gert Glükmann <gglukmann@gmail.com>",
14
17
  "repository": {
15
18
  "type": "git",
16
19
  "url": "git+https://github.com/gglukmann/google-sheets-mapper.git"
17
20
  },
18
- "keywords": [
19
- "google-sheets-mapper",
20
- "google-sheets",
21
- "google-sheets-api",
22
- "google-sheets-api-v4"
23
- ],
24
- "main": "dist/index.js",
25
- "typings": "dist/index.d.ts",
26
21
  "files": [
27
22
  "dist",
28
23
  "src"
29
24
  ],
30
- "engines": {
31
- "node": ">=16"
25
+ "type": "module",
26
+ "main": "./dist/index.cjs",
27
+ "module": "./dist/index.js",
28
+ "types": "./dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "import": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/index.d.cts",
37
+ "default": "./dist/index.cjs"
38
+ }
39
+ },
40
+ "./package.json": "./package.json"
32
41
  },
33
42
  "scripts": {
34
- "start": "tsdx watch",
43
+ "dev": "tsdx dev",
35
44
  "build": "tsdx build",
36
45
  "test": "tsdx test",
37
46
  "lint": "tsdx lint",
38
- "prepare": "tsdx build"
47
+ "format": "tsdx format",
48
+ "typecheck": "tsdx typecheck",
49
+ "prepublishOnly": "bun run build"
39
50
  },
40
- "peerDependencies": {},
41
- "module": "dist/google-sheets-mapper.esm.js",
42
51
  "devDependencies": {
43
- "tsdx": "^0.14.1",
44
- "tslib": "^2.4.0",
45
- "typescript": "^4.7.4"
52
+ "bunchee": "^6.9.4",
53
+ "oxfmt": "^0.27.0",
54
+ "oxlint": "^1.42.0",
55
+ "tsdx": "^2.0.0",
56
+ "typescript": "^5.9.3",
57
+ "vitest": "^4.0.18"
58
+ },
59
+ "engines": {
60
+ "node": ">=20"
46
61
  }
47
62
  }
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { MapperOptions, MapperState, ValueRangesResponse } from './types';
2
- import { fetchBatchData, fetchAllSheetsData, mapData } from './utils';
1
+ import type { MapperOptions, MapperState, ValueRangesResponse } from "./types";
2
+ import { fetchBatchData, fetchAllSheetsData, mapData } from "./utils";
3
3
 
4
4
  const GoogleSheetsMapper = {
5
5
  async fetchGoogleSheetsData({
@@ -7,16 +7,11 @@ const GoogleSheetsMapper = {
7
7
  sheetId,
8
8
  sheetsOptions = [],
9
9
  }: MapperOptions): Promise<MapperState[]> {
10
- try {
11
- const response: ValueRangesResponse =
12
- sheetsOptions.length === 0
13
- ? await fetchAllSheetsData({ apiKey, sheetId })
14
- : await fetchBatchData({ apiKey, sheetId, sheetsOptions });
15
-
16
- return mapData({ sheets: response.valueRanges, sheetsOptions });
17
- } catch (error) {
18
- throw error;
19
- }
10
+ const response: ValueRangesResponse =
11
+ sheetsOptions.length === 0
12
+ ? await fetchAllSheetsData({ apiKey, sheetId })
13
+ : await fetchBatchData({ apiKey, sheetId, sheetsOptions });
14
+ return mapData({ sheets: response.valueRanges, sheetsOptions });
20
15
  },
21
16
  };
22
17
 
package/src/types.ts CHANGED
@@ -34,15 +34,5 @@ export interface SheetsResponse {
34
34
 
35
35
  export interface MapperState {
36
36
  id: string;
37
- data: object[];
38
- }
39
-
40
- export interface ApiResponse {
41
- url: string;
42
- status: number;
43
- statusText: string;
44
- }
45
-
46
- export interface ErrorResponse {
47
- response: ApiResponse;
37
+ data: Record<string, string>[];
48
38
  }
package/src/utils.ts CHANGED
@@ -1,79 +1,65 @@
1
- import {
1
+ import type {
2
2
  MapperOptions,
3
3
  MapperState,
4
- ApiResponse,
5
4
  ValueRange,
6
5
  SheetsResponse,
7
6
  SheetFromResponse,
8
7
  ValueRangesResponse,
9
8
  SheetsOption,
10
- } from './types';
9
+ } from "./types";
11
10
 
12
- const GOOGLE_API_URL = 'https://sheets.googleapis.com/v4/spreadsheets';
11
+ const GOOGLE_API_URL = "https://sheets.googleapis.com/v4/spreadsheets";
13
12
 
14
13
  const getRanges = (sheetNames: string[] = []): string => {
15
14
  // ranges=Sheet1&ranges=Sheet2
16
- return sheetNames.map((sheetName) => `ranges=${sheetName}`).join('&');
15
+ return sheetNames.map((sheetName) => `ranges=${sheetName}`).join("&");
17
16
  };
18
17
 
19
18
  const getSheetsTitleUrl = (sheetId: string, apiKey: string): string => {
20
19
  return `${GOOGLE_API_URL}/${sheetId}?fields=sheets%2Fproperties%2Ftitle&key=${apiKey}`;
21
20
  };
22
21
 
23
- const getBatchUrl = (
24
- sheetId: string,
25
- ranges: Array<string>,
26
- apiKey: string,
27
- ): string => {
22
+ const getBatchUrl = (sheetId: string, ranges: Array<string>, apiKey: string): string => {
28
23
  const rangesQueryString = getRanges(ranges);
29
24
 
30
- return `${GOOGLE_API_URL}/${sheetId}/values:batchGet?${rangesQueryString}&key=${apiKey}`;
25
+ return `${GOOGLE_API_URL}/${sheetId}?${rangesQueryString}&key=${apiKey}&includeGridData=true`;
31
26
  };
32
27
 
33
- class ApiResponseError extends Error {
34
- constructor(message: string, public readonly response: ApiResponse) {
35
- super(message);
36
- Object.setPrototypeOf(this, ApiResponseError.prototype);
37
- this.response = response;
38
- Error.captureStackTrace(this, ApiResponseError);
39
- }
40
- }
41
-
42
- const makeFetch = async (url: string, config = {}): Promise<any> => {
43
- try {
44
- const response = await fetch(url, config);
45
-
46
- if (!response.ok) {
47
- throw new ApiResponseError(
48
- `Request to '${url}' failed with ${response.status}${
49
- response.statusText ? `: ${response.statusText}` : ''
50
- }`,
51
- {
28
+ const makeFetch = async <T>(url: string, config = {}): Promise<T> => {
29
+ const response = await fetch(url, config);
30
+
31
+ if (!response.ok) {
32
+ throw new Error(
33
+ `Request to '${url}' failed with ${response.status}${
34
+ response.statusText ? `: ${response.statusText}` : ""
35
+ }`,
36
+ {
37
+ cause: {
52
38
  status: response.status,
53
39
  statusText: response.statusText,
54
40
  url: response.url,
55
41
  },
56
- );
57
- }
58
-
59
- return await response.json();
60
- } catch (error) {
61
- console.error(error);
62
- throw error;
42
+ },
43
+ );
63
44
  }
45
+
46
+ return await response.json();
64
47
  };
65
48
 
66
- const mapRecords = (records: ValueRange['values'], headerData: string[]) => {
49
+ const mapRecords = (
50
+ records: ValueRange["values"],
51
+ headerData: string[],
52
+ ): Record<string, string>[] => {
67
53
  return records
68
54
  .filter((record: string[]) => record.length > 0)
69
55
  .map((record: string[]) =>
70
- record.reduce(
71
- (obj: { [key: string]: unknown }, item: string, index: number) => {
72
- obj[headerData[index]] = item;
73
- return obj;
74
- },
75
- {},
76
- ),
56
+ record.reduce((obj: Record<string, string>, item: string, index: number) => {
57
+ const key = headerData[index];
58
+ if (key !== undefined) {
59
+ obj[key] = item;
60
+ }
61
+ return obj;
62
+ }, {}),
77
63
  );
78
64
  };
79
65
 
@@ -85,13 +71,11 @@ export const mapData = ({
85
71
  sheetsOptions?: SheetsOption[];
86
72
  }): MapperState[] => {
87
73
  return sheets.map((sheet: ValueRange) => {
88
- const id = sheet.range.split('!')[0].replace(/'/g, '');
74
+ const id = sheet.range.split("!")[0].replace(/'/g, "");
89
75
  const rows = sheet.values || [];
90
76
 
91
77
  if (rows.length > 0) {
92
- const sheetsOptionsSheet = sheetsOptions.find(
93
- (sheet: SheetsOption) => sheet.id === id,
94
- );
78
+ const sheetsOptionsSheet = sheetsOptions.find((option: SheetsOption) => option.id === id);
95
79
  const headerRowIndex = sheetsOptionsSheet?.headerRowIndex ?? 0;
96
80
  const header = rows[headerRowIndex];
97
81
  const records = rows.filter((_, index: number) => index > headerRowIndex);