@azteam/google-api
Version:
N/A
261 lines (230 loc) • 8.43 kB
JavaScript
import _ from 'lodash';
import {genCharArray} from '@azteam/util';
import GoogleDriveAPI, {DRIVE_FILE_TYPE} from './GoogleDriveAPI';
import {DRIVE_SCOPE, SHEET_SCOPE} from './scope';
const SHEET_ENDPOINT = 'https://sheets.googleapis.com/v4';
class GoogleSheetAPI extends GoogleDriveAPI {
constructor(accountType, credential, options = {}) {
super(
accountType,
{
...credential,
scope: SHEET_SCOPE,
},
options
);
}
getAuthLink(redirectURI, state, arrayScope = [DRIVE_SCOPE, SHEET_SCOPE]) {
return super.getAuthLink(redirectURI, state, arrayScope);
}
async hasScope(arrayScope = [DRIVE_SCOPE, SHEET_SCOPE]) {
return super.hasScope(arrayScope);
}
static parseRange(range) {
const matches = range.match(/(\w+?)(\d*):(\w+?)(\d*)/),
colStart = matches[1] || null,
rowStart = matches[2] ? Number(matches[2]) : null,
colEnd = matches[3] || null,
rowEnd = matches[4] ? Number(matches[4]) : null;
if (colStart > colEnd || rowStart > rowEnd) {
throw new Error('[range]: Syntax error');
}
return {
colStart,
rowStart,
colEnd,
rowEnd,
startRowIndex: rowStart - 1,
endRowIndex: rowEnd,
startColumnIndex: colStart.toUpperCase().charCodeAt(0) - 65,
endColumnIndex: colEnd.toUpperCase().charCodeAt(0) - 65 + 1,
};
}
static parseValues(values, range) {
const {colStart, colEnd, rowStart} = GoogleSheetAPI.parseRange(range),
arrayColChar = genCharArray(colStart, colEnd),
result = {};
for (let r = 0; r < values.length; r += 1) {
const rowArray = values[r];
for (let c = 0; c < rowArray.length; c += 1) {
const cell = rowArray[c],
cellKey = arrayColChar[c] + (rowStart + r);
result[cellKey] = cell;
}
}
return result;
}
async getAllSpreadsheet(containsName = null, parentId = null) {
let query = `mimeType='${DRIVE_FILE_TYPE.SHEET}' and trashed=false and '${parentId || 'root'}' in parents`;
if (containsName) {
query = `name contains '${containsName}' and ${query}`;
}
return this._getAllItem({
q: query,
});
}
async createSpreadsheet(title) {
const client = await this._getAuthClient(),
res = await client.post(
`${SHEET_ENDPOINT}/spreadsheets`,
{
properties: {
title,
},
},
false
);
if (res.error) {
throw new Error(res.error.message);
}
if (res.spreadsheetId) {
return {
spreadsheetId: res.spreadsheetId,
spreadsheetUrl: res.spreadsheetUrl,
title: res.properties.title,
};
}
return null;
}
async getSpreadsheet(spreadsheetId) {
const client = await this._getAuthClient(),
res = await client.get(`${SHEET_ENDPOINT}/spreadsheets/${spreadsheetId}`);
if (res.error) {
throw new Error(res.error.message);
}
return {
title: res.properties.title,
sheets: res.sheets,
link: res.spreadsheetUrl,
};
}
async createSheet(spreadsheetId, sheetName) {
const client = await this._getAuthClient(),
res = await client.post(
`${SHEET_ENDPOINT}/spreadsheets/${spreadsheetId}:batchUpdate`,
{requests: [{addSheet: {properties: {title: String(sheetName)}}}]},
false
);
if (res.error) {
throw new Error(res.error.message);
}
return res.replies[0].addSheet.properties;
}
async deleteSheet(spreadsheetId, sheetId) {
const client = await this._getAuthClient(),
res = await client.post(
`${SHEET_ENDPOINT}/spreadsheets/${spreadsheetId}:batchUpdate`,
{
requests: [
{
deleteSheet: {
sheetId,
},
},
],
},
false
);
if (res.error) {
throw new Error(res.error.message);
}
}
async getSheetInfo(spreadsheetId, sheetName) {
const {sheets} = await this.getSpreadsheet(spreadsheetId),
data = sheets.find((obj) => obj.properties.title === sheetName);
if (data) {
return data.properties;
}
return {};
}
async addRowsSheet(spreadsheetId, sheetId, numberRows) {
const client = await this._getAuthClient(),
res = await client.post(
`${SHEET_ENDPOINT}/spreadsheets/${spreadsheetId}:batchUpdate`,
{
requests: [
{
appendDimension: {
sheetId,
dimension: 'ROWS',
length: numberRows,
},
},
],
},
false
);
if (res.error) {
throw new Error(res.error.message);
}
return true;
}
async getValuesInSheet(spreadsheetId, sheetName, range, isParseValues = false) {
const rangeQuery = `${sheetName}!${range}`,
client = await this._getAuthClient(),
res = await client.get(`${SHEET_ENDPOINT}/spreadsheets/${spreadsheetId}/values/${encodeURIComponent(rangeQuery)}`);
if (res.error) {
throw new Error(res.error.message);
}
const values = res.values || [];
return isParseValues ? GoogleSheetAPI.parseValues(values, range) : values;
}
async validateSheet(spreadsheetId, sheetName, range, data = []) {
const isParseValues = !Array.isArray(data),
row = await this.getValuesInSheet(spreadsheetId, sheetName, range, isParseValues);
if (!_.isEqual(row, data)) {
return false;
}
return true;
}
async insertToSheet(spreadsheetId, sheetName, range, data = []) {
const rangeQuery = `${sheetName}!${range}`,
client = await this._getAuthClient(),
res = await client.post(
`${SHEET_ENDPOINT}/spreadsheets/${spreadsheetId}/values:batchUpdate`,
{
valueInputOption: 'RAW',
data: [
{
range: rangeQuery,
values: data,
},
],
},
false
);
if (res.totalUpdatedRows && res.totalUpdatedRows === data.length) {
return true;
}
console.error(res);
throw new Error(`[insert]: Failed insert`);
}
async mergeCell(spreadsheetId, sheetId, range) {
const {startColumnIndex, startRowIndex, endColumnIndex, endRowIndex} = GoogleSheetAPI.parseRange(range),
client = await this._getAuthClient(),
res = await client.post(
`${SHEET_ENDPOINT}/spreadsheets/${spreadsheetId}:batchUpdate`,
{
requests: [
{
mergeCells: {
mergeType: 'MERGE_ALL',
range: {
sheetId,
endRowIndex,
endColumnIndex,
startColumnIndex,
startRowIndex,
},
},
},
],
},
false
);
if (res.error) {
throw new Error(`${res.error.message}`);
}
}
}
export default GoogleSheetAPI;