google-sheets-mapper 1.0.1 → 2.1.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 +27 -20
- package/dist/index.cjs +103 -0
- package/dist/index.d.cts +22 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +22 -6
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +98 -6
- package/package.json +39 -44
- package/src/index.ts +8 -13
- package/src/types.ts +9 -4
- package/src/utils.ts +59 -51
- package/dist/google-sheets-mapper.cjs.development.js +0 -1150
- package/dist/google-sheets-mapper.cjs.development.js.map +0 -1
- package/dist/google-sheets-mapper.cjs.production.min.js +0 -2
- package/dist/google-sheets-mapper.cjs.production.min.js.map +0 -1
- package/dist/google-sheets-mapper.esm.js +0 -1146
- package/dist/google-sheets-mapper.esm.js.map +0 -1
- package/dist/types.d.ts +0 -35
- package/dist/utils.d.ts +0 -4
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {
|
|
2
2
|
MapperOptions,
|
|
3
3
|
MapperState,
|
|
4
4
|
ApiResponse,
|
|
@@ -6,83 +6,90 @@ import {
|
|
|
6
6
|
SheetsResponse,
|
|
7
7
|
SheetFromResponse,
|
|
8
8
|
ValueRangesResponse,
|
|
9
|
-
|
|
9
|
+
SheetsOption,
|
|
10
|
+
} from "./types";
|
|
10
11
|
|
|
11
|
-
const GOOGLE_API_URL =
|
|
12
|
+
const GOOGLE_API_URL = "https://sheets.googleapis.com/v4/spreadsheets";
|
|
12
13
|
|
|
13
|
-
const getRanges = (sheetNames:
|
|
14
|
+
const getRanges = (sheetNames: string[] = []): string => {
|
|
14
15
|
// ranges=Sheet1&ranges=Sheet2
|
|
15
|
-
return sheetNames.map((sheetName) => `ranges=${sheetName}`).join(
|
|
16
|
+
return sheetNames.map((sheetName) => `ranges=${sheetName}`).join("&");
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
const getSheetsTitleUrl = (sheetId: string, apiKey: string): string => {
|
|
19
20
|
return `${GOOGLE_API_URL}/${sheetId}?fields=sheets%2Fproperties%2Ftitle&key=${apiKey}`;
|
|
20
21
|
};
|
|
21
22
|
|
|
22
|
-
const getBatchUrl = (
|
|
23
|
-
sheetId: string,
|
|
24
|
-
ranges: Array<string>,
|
|
25
|
-
apiKey: string,
|
|
26
|
-
): string => {
|
|
23
|
+
const getBatchUrl = (sheetId: string, ranges: Array<string>, apiKey: string): string => {
|
|
27
24
|
const rangesQueryString = getRanges(ranges);
|
|
28
25
|
|
|
29
|
-
return `${GOOGLE_API_URL}/${sheetId}
|
|
26
|
+
return `${GOOGLE_API_URL}/${sheetId}?${rangesQueryString}&key=${apiKey}&includeGridData=true`;
|
|
30
27
|
};
|
|
31
28
|
|
|
32
29
|
class ApiResponseError extends Error {
|
|
33
|
-
|
|
30
|
+
response: ApiResponse;
|
|
31
|
+
constructor(message: string, response: ApiResponse) {
|
|
34
32
|
super(message);
|
|
35
33
|
Object.setPrototypeOf(this, ApiResponseError.prototype);
|
|
36
34
|
this.response = response;
|
|
37
|
-
Error.captureStackTrace
|
|
35
|
+
if (Error.captureStackTrace) {
|
|
36
|
+
Error.captureStackTrace(this, ApiResponseError);
|
|
37
|
+
}
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
const makeFetch = async (url: string, config = {}): Promise<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return await response.json();
|
|
59
|
-
} catch (error) {
|
|
60
|
-
console.error(error);
|
|
61
|
-
throw error;
|
|
41
|
+
const makeFetch = async <T>(url: string, config = {}): Promise<T> => {
|
|
42
|
+
const response = await fetch(url, config);
|
|
43
|
+
|
|
44
|
+
if (!response.ok) {
|
|
45
|
+
throw new ApiResponseError(
|
|
46
|
+
`Request to '${url}' failed with ${response.status}${
|
|
47
|
+
response.statusText ? `: ${response.statusText}` : ""
|
|
48
|
+
}`,
|
|
49
|
+
{
|
|
50
|
+
status: response.status,
|
|
51
|
+
statusText: response.statusText,
|
|
52
|
+
url: response.url,
|
|
53
|
+
},
|
|
54
|
+
);
|
|
62
55
|
}
|
|
56
|
+
|
|
57
|
+
return await response.json();
|
|
63
58
|
};
|
|
64
59
|
|
|
65
60
|
const mapRecords = (
|
|
66
|
-
records: ValueRange[
|
|
67
|
-
headerData:
|
|
68
|
-
) => {
|
|
61
|
+
records: ValueRange["values"],
|
|
62
|
+
headerData: string[],
|
|
63
|
+
): Record<string, string>[] => {
|
|
69
64
|
return records
|
|
70
|
-
.filter((record:
|
|
71
|
-
.map((record:
|
|
72
|
-
|
|
73
|
-
|
|
65
|
+
.filter((record: string[]) => record.length > 0)
|
|
66
|
+
.map((record: string[]) =>
|
|
67
|
+
record.reduce((obj: Record<string, string>, item: string, index: number) => {
|
|
68
|
+
const key = headerData[index];
|
|
69
|
+
if (key !== undefined) {
|
|
70
|
+
obj[key] = item;
|
|
71
|
+
}
|
|
74
72
|
return obj;
|
|
75
|
-
}, {})
|
|
76
|
-
|
|
73
|
+
}, {}),
|
|
74
|
+
);
|
|
77
75
|
};
|
|
78
76
|
|
|
79
|
-
export const mapData = (
|
|
77
|
+
export const mapData = ({
|
|
78
|
+
sheets,
|
|
79
|
+
sheetsOptions = [],
|
|
80
|
+
}: {
|
|
81
|
+
sheets: ValueRange[];
|
|
82
|
+
sheetsOptions?: SheetsOption[];
|
|
83
|
+
}): MapperState[] => {
|
|
80
84
|
return sheets.map((sheet: ValueRange) => {
|
|
81
|
-
const id = sheet.range.split(
|
|
85
|
+
const id = sheet.range.split("!")[0].replace(/'/g, "");
|
|
82
86
|
const rows = sheet.values || [];
|
|
83
87
|
|
|
84
88
|
if (rows.length > 0) {
|
|
85
|
-
const
|
|
89
|
+
const sheetsOptionsSheet = sheetsOptions.find((option: SheetsOption) => option.id === id);
|
|
90
|
+
const headerRowIndex = sheetsOptionsSheet?.headerRowIndex ?? 0;
|
|
91
|
+
const header = rows[headerRowIndex];
|
|
92
|
+
const records = rows.filter((_, index: number) => index > headerRowIndex);
|
|
86
93
|
const recordsData = mapRecords(records, header);
|
|
87
94
|
|
|
88
95
|
return {
|
|
@@ -101,8 +108,9 @@ export const mapData = (sheets: ValueRange[]): MapperState[] => {
|
|
|
101
108
|
export const fetchBatchData = async ({
|
|
102
109
|
apiKey,
|
|
103
110
|
sheetId,
|
|
104
|
-
|
|
111
|
+
sheetsOptions = [],
|
|
105
112
|
}: MapperOptions): Promise<ValueRangesResponse> => {
|
|
113
|
+
const sheetsNames = sheetsOptions.map((option: SheetsOption) => option.id);
|
|
106
114
|
const url = getBatchUrl(sheetId, sheetsNames, apiKey);
|
|
107
115
|
|
|
108
116
|
return await makeFetch(url);
|
|
@@ -114,9 +122,9 @@ export const fetchAllSheetsData = async ({
|
|
|
114
122
|
}: MapperOptions): Promise<ValueRangesResponse> => {
|
|
115
123
|
const urlTitles = getSheetsTitleUrl(sheetId, apiKey);
|
|
116
124
|
const { sheets }: SheetsResponse = await makeFetch(urlTitles);
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
);
|
|
125
|
+
const sheetsOptions = sheets.map((sheet: SheetFromResponse) => ({
|
|
126
|
+
id: sheet.properties.title,
|
|
127
|
+
}));
|
|
120
128
|
|
|
121
|
-
return await fetchBatchData({
|
|
129
|
+
return await fetchBatchData({ apiKey, sheetId, sheetsOptions });
|
|
122
130
|
};
|