Skip to content

Commit

Permalink
Added first row as header option
Browse files Browse the repository at this point in the history
  • Loading branch information
M1chalS committed Jul 15, 2023
1 parent 6ce895f commit 54f138e
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 4 deletions.
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,35 @@ Cleared data will look like this:
<tr><td>A5</td><td>B5</td><td>C5</td><td>D5</td></tr>
</table>

#### Special Features
When getting data you can set `firstRowAsHeader` as true to get data formatted as object with keys from first row. You can do it in constructor or in `get` method.

Example normal response:
```typescript
[
["A1", "B1", "C1", "D1"],
["A2", "B2", "C2", "D2"],
["A3", "B3", "C3", "D3"],
]
```
Response with firstRowAsHeader set to true
```typescript
[
{
A1: "A2",
B1: "B2",
C1: "C2",
D1: "D2",
},
{
A1: "A3",
B1: "B3",
C1: "C3",
D1: "D3",
},
]
```

# Development setup

### Install dependencies
Expand All @@ -168,4 +197,4 @@ npm run test

Compiled JavaScript will be placed in `/build` folder.

_Made by Michał Szajner_
_Made by [Michał Szajner](https://github.com/M1chalS)_
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sheets-simplified",
"version": "1.0.0",
"version": "1.0.1",
"description": "TypeScript classes based package that eases and increases safety of working with Google Sheets API v4.",
"main": "./build/index.js",
"types": "./build/index.d.ts",
Expand Down
2 changes: 2 additions & 0 deletions src/config/configurations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface GetRequestConfiguration {
majorDimension?: Dimension;
valueRenderOption?: ValueRenderOption;
dateTimeRenderOption?: DateTimeRenderOption;
firstRowAsHeader?: boolean;
}

export interface AppendRequestConfiguration {
Expand Down Expand Up @@ -45,4 +46,5 @@ export interface Configuration {
includeValuesInResponse?: boolean;
responseDateTimeRenderOption?: DateTimeRenderOption;
responseValueRenderOption?: ValueRenderOption;
firstRowAsHeader?: boolean;
}
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./auth/google-sheets-auth";
export * from "./sheets/sheets-connection";
export * from "./sheets/sheets-connection"
export * from "./types/types";
16 changes: 16 additions & 0 deletions src/response-formatter/response-formatter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const responseFormatter = (res: any) => {
const {data, ...rest } = res;

data.values = data.values.map((row: any[], index: number) => {
const newRow: any = {};
row.forEach((value: any, index: number) => {
newRow[data.values[0][index]] = value;
});
return newRow;
}).filter((val: any[], index: number) => index !== 0);

return {
data,
...rest
}
};
107 changes: 107 additions & 0 deletions src/sheets/__tests__/sheets-connection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,111 @@ describe('Range logic checks', () => {
await expect(sheetsConnection.get({sheet: "Sheet2"})).rejects.toThrowError("Specify range or sheet in method or in constructor");
});

});

describe('Response formatter checks', () => {

test('Expect response to not be formatted', async () => {
const sheetsConnection = new SheetsConnection({
spreadsheetId: process.env.SHEET_ID!,
auth: googleAuthWrapper,
sheet: "Sheet1",
range: "A1:B"
});

await sheetsConnection.append([[
"test1",
"test2"
], [
"test3",
"test4"
]]);

const res = await sheetsConnection.get();

expect(res.data.values[0][0] === "test1").toBeTruthy();
expect(res.data.values[0][1] === "test2").toBeTruthy();
expect(res.data.values[1][0] === "test3").toBeTruthy();
expect(res.data.values[1][1] === "test4").toBeTruthy();

await sheetsConnection.clear();
});

test('Expect response to be formatted (set in constructor)', async () => {
const sheetsConnection = new SheetsConnection({
spreadsheetId: process.env.SHEET_ID!,
auth: googleAuthWrapper,
sheet: "Sheet1",
range: "A1:B",
firstRowAsHeader: true
});

await sheetsConnection.append([[
"test1",
"test2"
], [
"test3",
"test4"
]]);

const res = await sheetsConnection.get();

expect(res.data.values[0].test1 === "test3").toBeTruthy();
expect(res.data.values[0].test2 === "test4").toBeTruthy();

await sheetsConnection.clear();
});

test('Expect response to be formatted (set in method)', async () => {
const sheetsConnection = new SheetsConnection({
spreadsheetId: process.env.SHEET_ID!,
auth: googleAuthWrapper,
sheet: "Sheet1",
range: "A1:B",
});

await sheetsConnection.append([[
"test1",
"test2"
], [
"test3",
"test4"
]]);

const res = await sheetsConnection.get({
firstRowAsHeader: true
});

expect(res.data.values[0].test1 === "test3").toBeTruthy();
expect(res.data.values[0].test2 === "test4").toBeTruthy();

await sheetsConnection.clear();
});

test('Expect response to be formatted (set in both)', async () => {
const sheetsConnection = new SheetsConnection({
spreadsheetId: process.env.SHEET_ID!,
auth: googleAuthWrapper,
sheet: "Sheet1",
range: "A1:B",
firstRowAsHeader: true
});

await sheetsConnection.append([[
"test1",
"test2"
], [
"test3",
"test4"
]]);

const res = await sheetsConnection.get({
firstRowAsHeader: true
});

expect(res.data.values[0].test1 === "test3").toBeTruthy();
expect(res.data.values[0].test2 === "test4").toBeTruthy();

await sheetsConnection.clear();
});
});
7 changes: 6 additions & 1 deletion src/sheets/sheets-connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
GetRequestConfiguration,
UpdateRequestConfiguration
} from "../config/configurations";
import {responseFormatter} from "../response-formatter/response-formatter";

export class SheetsConnection {
private sheets: sheets_v4.Sheets = google.sheets("v4");
Expand All @@ -24,6 +25,7 @@ export class SheetsConnection {
private readonly includeValuesInResponse: boolean;
private readonly responseDateTimeRenderOption: DateTimeRenderOption;
private readonly responseValueRenderOption: ValueRenderOption;
private readonly firstRowAsHeader: boolean;

public constructor(cfg: Configuration) {
this.spreadsheetId = cfg.spreadsheetId;
Expand All @@ -38,6 +40,7 @@ export class SheetsConnection {
this.includeValuesInResponse = cfg.includeValuesInResponse ?? false;
this.responseDateTimeRenderOption = cfg.responseDateTimeRenderOption ?? DateTimeRenderOption.FORMATTED_STRING;
this.responseValueRenderOption = cfg.responseValueRenderOption ?? ValueRenderOption.FORMATTED_VALUE;
this.firstRowAsHeader = cfg.firstRowAsHeader ?? false;

if (this.sheet && this.range) {
this.sheetRange = `${this.sheet}!${this.range}`;
Expand All @@ -47,7 +50,9 @@ export class SheetsConnection {
}

public get = async (cfg?: GetRequestConfiguration) => {
return await this.sheets.spreadsheets.values.get(this.getRequestPayload(cfg));
const res = await this.sheets.spreadsheets.values.get(this.getRequestPayload(cfg));

return (this.firstRowAsHeader || cfg?.firstRowAsHeader) ? responseFormatter(res) : res;
};

public append = async (data: any[], cfg?: AppendRequestConfiguration) => {
Expand Down

0 comments on commit 54f138e

Please sign in to comment.