@romstar/gas-client-typescript
Version:
A client-side utility class that can call server-side Google Apps Script functions
169 lines (116 loc) • 5.81 kB
Markdown
# gas-client
A client-side utility class that uses promises to call server-side Google Apps Script functions. This is a user-friendly wrapper of [google.script.run](https://developers.google.com/apps-script/guides/html/reference/run).
It can also optionally be used in local development and is designed to interact with the [Google Apps Script Dev Server](https://github.com/enuchi/Google-Apps-Script-Webpack-Dev-Server) used in the [React / Google Apps Script](https://github.com/enuchi/React-Google-Apps-Script) project.
---
## Installation
Install
```bash
> npm install gas-client
# or
> yarn add gas-client
```
```javascript
import { GASClient } from 'gas-client';
const { serverFunctions } = new GASClient();
// We now have access to all our server functions, which return promises
serverFunctions
.addSheet(sheetTitle)
.then((response) => doSomething(response))
.catch((err) => handleError(err));
```
### Development mode
To use with [Google Apps Script Dev Server](https://github.com/enuchi/Google-Apps-Script-Webpack-Dev-Server), pass in a config object with `allowedDevelopmentDomains` indicating the localhost port you are using. This setting will be ignored in production (see below for more details).
```javascript
import { GASClient } from 'gas-client';
const { serverFunctions } = new GASClient({
allowedDevelopmentDomains: 'https://localhost:3000',
});
serverFunctions
.addSheet(sheetTitle)
.then((response) => doSomething(response))
.catch((err) => handleError(err));
```
---
## How to use
### Using the gas-client utility class
The `gas-client` file lets you use promises to call and handle responses from the server, instead of using `google.script.run`:
```javascript
// Google's client-side utility "google.script.run" works like this:
google.script.run
.withSuccessHandler((response) => doSomething(response))
.withFailureHandler((err) => handleError(err))
.addSheet(sheetTitle);
```
```javascript
// With this package we can now do this:
import { GASClient } from 'gas-client';
const { serverFunctions } = new GASClient();
// We now have access to all our server functions, which return promises
serverFunctions
.addSheet(sheetTitle)
.then((response) => doSomething(response))
.catch((err) => handleError(err));
// Or we can use async/await syntax:
async () => {
try {
const response = await serverFunctions.addSheet(sheetTitle);
doSomething(response);
} catch (err) {
handleError(err);
}
};
```
Now we can use familiar Promises in our client-side code and have easy access to all server functions.
---
## [New!] Typescript
This project now supports typescript!
To use it, simply import your server functions and pass them as a type parameter when creating your server
### On your server-side code
```typescript
// src/server/index.ts
interface SheetData {
name: string;
numOfRows: number;
}
const getSheetData = (): SheetData => {
const sheet = SpreadsheetApp.getActiveSheet();
return {
name: sheet.getName(),
numOfRows: sheet.getMaxRows(),
};
};
const appendRowsToSheet = (sheetName: string, rowsToAdd: number): void => {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
sheet.insertRowsAfter(sheet.getMaxRows(), rowsToAdd);
};
export { getSheetData, appendRowsToSheet };
```
### On your server-side code
```typescript
// src/client/add-rows.ts
import { GASClient } from 'gas-client';
import { showUserPrompt } from './show-user-prompt';
import * as server from '../server';
const { serverFunctions } = new GASClient<typeof server>();
const promptUser = async (): Promise<void> => {
const { name, numOfRows } = await serverFunctions.getSheetData();
const response = await showUserPrompt(`Sheet ${name} has ${numOfRows} rows. How many would you like to add?`);
serverFunctions.appendRowsToSheet(name, numOfRows);
};
```
Now you can have your function names, parameters and return types checked.
### Get better IDE support and catch errors ahead!

---
## API
The config object takes:
`allowedDevelopmentDomains`: A config to specifiy which domains are permitted for communication with Google Apps Script Webpack Dev Server development tool. This is a security setting, and if not specified, will block functionality in development.
`allowedDevelopmentDomains` will accept either a space-separated string of allowed subdomains, e.g. `'https://localhost:3000 https://localhost:8080'` (notice no trailing slashes); or a function that takes in the requesting origin and should return `true` to allow communication, e.g. `(origin) => /localhost:\d+$/.test(origin);`
### Production mode
In the normal Google Apps Script production environment, `new GASClient()` will have one available method:
- `serverFunctions`: an object containing all publicly exposed server functions (see example above).
Note that the `allowedDevelopmentDomains` configuration will be ignored in production, so the same code can and should be used for development and production.
### Development mode
Development mode for the `gas-client` helper class will be run when the `google` client API cannot be found, i.e. an error is thrown with the message "google is not defined"
Calling `new GASClient({ allowedDevelopmentDomains })` will create an instance with the following method in development mode:
- `serverFunctions`: a proxy object, used for development purposes, that mimics calling `google.script.run`. It will dispatch a message to the parent iframe (our custom Dev Server), which will call an app that actually interacts with the `google.script.run` API. Development mode will also handle the response and resolve or reject based on the response type. See the implementation for details on the event signature.