📄 Template to build Google Apps Script projects with TypeScript.
MIT License
This repository provides a simple template to start a new Google Apps Script project with TypeScript. Building, linting, formatting, and pushing to Google Apps are all built in.
The project is set up with a TypeScript configuration that transforms your TypeScript files in the
src
directory into JavaScript files in the build
directory. It's not enough to upload those
files as-is to Google Apps, however, because Apps Script doesn't support installing and running
dependencies, and uploaded files are run in random order - they aren't linked together at all. To
solve this problem, a second build step uses Webpack to combine all files and depdendencies into a
single minified Code.js
file, which is the only file that is actually pushed to Google Apps.
npm install
. Alternatively, start a Codespace in your new repositorySCRIPT_ID
in .clasp.json
with your project's ID. This ID is not asrc
folder. Note that index.ts
is the entrypoint for yourindex.ts
file will be compiled into the script.npm run lint
and/or auto-format your code with npm run format
.npm run login
. Make sure to use the same accountnpm run deploy
. Run this every time you make changes.ericanastas/deploy-google-app-script-action
.You can run the following scripts by opening the project directory in your terminal (as long as you have Node & npm installed):
npm install
Install all required dependencies.npm run build
Build your project to ensure it compiles properly.npm run format
Format your code automatically using Prettier.npm run lint
Check your code for common errors using ESLint.npm run login
Login to the Google Apps Script client so you can push/pull. You will need to runnpm run pull
Fetch the latest changes from Google Apps Script. You should only need to do thisnpm run push
Build your project and push it to Google Apps in one step. The first time younpm run deploy
Build and push your code, then create a new versionedYou can also run any Clasp command with
npx clasp <command>
.
The template comes with a built-in configuration file for
GitHub Workflows. The
workflow is configured to run on every push to the main
branch as well as on every Pull Request as
a Check, and it simply checks the code to ensure that it passes linting and is buildable (has no
type/syntax errors). This is known as continuous integration and provides a form of automated
testing to ensure that your project's code is always valid.
For larger projects where more than one developer will be collaborating, it is reccomended to
protect the main
branch and only allow changes to it through Pull Requests in which all checks
pass. You can learn more about this from GitHub's
help articles.
If you would like to disable the workflow, simply delete the
checks.yml
file.
The following notes have important information for writing code for Google Apps Script using this template. Please read through them before you start.
In order for your Google Apps to run any of your code, you'll need to expose one or more functions to the engine. In the traditional Google Apps Script environment, you'd do this by declaring global functions, however in this setup there is no concept of 'global' as all files are modules.
Instead, only functions exported from index.ts
will be available to Google Apps Script.
Any function exported from index.ts
will be accessible by all
triggers and anywhere else Google Apps
might need to call your function, such as from a
custom menu.
Due to a bug in the Webpack plugin, only exports in export {...}
form are supported:
// ❌ Does NOT work
export function bad1() { /* ... */ }
export const bad2 = () => { /* ... */ }
// ✅ Does work:
export {good1} from "./good1.ts"
function good2() { /* ... */ }
const good3 = () => { /* ... */ }
export {good2, good3}
Examples for all the simple triggers are given in
index.ts
.
For cleaner, more usable code, it may be useful to reference functions by their name
property instead of hardcoding the name into code.
For example:
const createButton = CardService.newTextButton()
.setText("Create")
.setOnClickAction(
// Here we use `onClickCreateEvent.name` instead of hardcoding `"onClickCreateEvent"`
CardService.newAction().setFunctionName(onClickCreateEvent.name)
);
Circular dependencies (files that depend on each other in a circular manner) can cause unexpected
issues like "X is not a function" or "X is not defined". If you are seeing these errors in your
project and you know they are wrong, try checking for circular dependencies using
madge
(not included in this template):
madge
globally with npm i --global madge
.madge src/index.ts --circular
..github
workflows
All GitHub workflows are configured using YAML files in this directory.
checks.yml
This is where the continuous integration workflow is configured.src
This is where you'll put all your TypeScript files.
example.ts
Gives an example of how to export something from a local file.index.ts
Provides you with the five basic triggers prebuilt, as well as an example of how to.clasp.json
Provides the configuration for Clasp, the command-line tool which pushes code to.claspignore
Tells Clasp to ignore every file except for Code.js
, appsscript.json
, andreadme_appsscript.md
..gitignore
Tells Git to ignore output files and node_modules
..prettierrc
Configures Prettier, the code formatter.appsscript.json
Controls the project setup and Apps Script environment. You can change thepackage.json
Lists the project dependencies and scripts.readme_appsscript.md
If anyone opens your project in the Apps Script editor, they'll just see areadme.md
This file.tsconfig.json
Configures the TypeScript compiler to enable strict mode and compile to CommonJSsrc
folder to the build
folder.webpack.config.js
Configures Webpack to take files from the build
folder and dependencies andCode.js
file.