Skip to content

bootgs/boot

Project banner for Google Apps Script Boot Framework

Artist: Daryna Mikhailenko

Boot Framework for Google Apps Script™

Built with clasp License Security Policy Roadmap Latest release

GitHub Stars GitHub Fork GitHub Sponsors

Introduction

Boot.gs is a lightweight framework designed to help build structured Google Apps Script applications. It aims to bring familiar development patterns, such as decorators and dependency injection, to the Apps Script environment to aid in code organization.

Installation

Install the framework via npm:

npm install bootgs

Quick Start

1. Define a Controller

Create a class to handle your application's logic. Decorators make it easy to map methods to specific endpoints or events.

import {Get, RestController} from "bootgs";

@RestController("api/sheet")
export class SheetController {
    /**
     * Handles GET requests to /api/sheet/active-range
     */
    @Get("active-range")
    getActiveRange(): string {
        return "This action returns the active sheet range.";
    }
}

2. Initialize the Application

Bootstrap your application by creating an App instance and delegating the standard Apps Script entry points (doGet, doPost) to it.

Synchronous Application

Use App for synchronous execution:

import {App} from "bootgs";
import {SheetController} from "./SheetController";

/**
 * Global entry point for GET requests.
 */
export function doGet(event: GoogleAppsScript.Events.DoGet) {
    const app = App.create({
        controllers: [SheetController]
    });
    return app.doGet(event);
}

/**
 * Global entry point for POST requests.
 */
export function doPost(event: GoogleAppsScript.Events.DoPost) {
    const app = App.create({
        controllers: [SheetController]
    });
    return app.doPost(event);
}

Asynchronous Application

Use AsyncApp when you need to handle asynchronous operations (e.g., UrlFetchApp promises or other async tasks) in your controllers:

import {AsyncApp} from "bootgs";
import {SheetController} from "./SheetController";

/**
 * Global entry point for GET requests.
 */
export async function doGet(event: GoogleAppsScript.Events.DoGet) {
    const app = AsyncApp.create({
        controllers: [SheetController]
    });
    return await app.doGet(event);
}

/**
 * Global entry point for POST requests.
 */
export async function doPost(event: GoogleAppsScript.Events.DoPost) {
    const app = AsyncApp.create({
        controllers: [SheetController]
    });
    return await app.doPost(event);
}

Features

  • Decorator-based Routing: Intuitive mapping of HTTP and Apps Script events (GET, POST, etc.).
  • Spring Boot & NestJS Patterns: Familiar decorators like @RequestMapping, @Autowired, @Value.
  • Validation: Declarative parameter validation using Spring Boot-style decorators like @Min, @Max, @Email, etc.
  • Pipes & Validation: Transform and validate incoming data with @UsePipes and built-in pipes (e.g., ParseNumberPipe).
  • Global Error Handling: Centralized exception management using @ControllerAdvice and @ExceptionHandler.
  • Dependency Injection: Fully-featured DI for better decoupling and testability.
  • Type Safety: Built with TypeScript for a robust development experience.
  • Modern Architecture: Inspired by frameworks like NestJS and Spring Boot.

Decorators

Class decorators

Class decorators
Decorator Returns Description
@Controller(type?: string, options?: object) ClassDecorator Marks a class as a general-purpose controller.
@RequestMapping(path?: string, method?: RequestMethod | RequestMethod[]) ClassDecorator & MethodDecorator Maps a specific request path onto a controller or a handler method.
@HttpController(basePath?: string) ClassDecorator Marks a class as an HTTP request controller. Default base path is /.
@ControllerAdvice() ClassDecorator Marks a class as a global exception handler and data binder.
@SheetController(sheetName?: string | string[] | RegExp) ClassDecorator Marks a class as a Google Sheets event controller. Can be filtered by sheet name (string, array, or RegExp).
@DocController() ClassDecorator Marks a class as a Google Docs event controller.
@SlideController() ClassDecorator Marks a class as a Google Slides event controller.
@FormController() ClassDecorator Marks a class as a Google Forms event controller.
@Service() ClassDecorator Marks a class as a service, typically holding business logic.
@Repository() ClassDecorator Marks a class as a repository, abstracting data access logic.
@Injectable() ClassDecorator Marks a class as available for dependency injection.
Aliases
@RestController(basePath?: string) ClassDecorator Alias for @HttpController().
@RestControllerAdvice() ClassDecorator Alias for @ControllerAdvice().
@SheetsController(sheetName?: string | string[] | RegExp) ClassDecorator Alias for @SheetController().
@DocsController() ClassDecorator Alias for @DocController().
@SlidesController() ClassDecorator Alias for @SlideController().
@FormsController() ClassDecorator Alias for @FormController().

Method decorators

Method decorators
Decorator Returns Description
@Install() MethodDecorator Handles onInstall event.
@Open() MethodDecorator Handles onOpen event.
@Edit(...range?: (string | RegExp | string[])[]) MethodDecorator Handles onEdit event. Filter by A1-notation, sheet name, or RegExp.
@Change(changeType?: SheetsOnChangeChangeType | SheetsOnChangeChangeType[]) MethodDecorator Handles onChange event. Filter by SheetsOnChangeChangeType.
@SelectionChange() MethodDecorator Handles onSelectionChange event.
@FormSubmit(...formId?: (string | string[])[]) MethodDecorator Handles onFormSubmit event. Filter by one or more form IDs.
HTTP Methods
@RequestMapping(path?: string, method?: RequestMethod | RequestMethod[]) ClassDecorator & MethodDecorator Maps a specific request path onto a controller or a handler method.
@Get(path?: string) MethodDecorator Maps a method to handle HTTP GET requests. Default path is /.
@Post(path?: string) MethodDecorator Maps a method to handle HTTP POST requests.
@Put(path?: string) MethodDecorator Maps a method to handle HTTP PUT requests.
@Patch(path?: string) MethodDecorator Maps a method to handle HTTP PATCH requests.
@Delete(path?: string) MethodDecorator Maps a method to handle HTTP DELETE requests.
@Head(path?: string) MethodDecorator Maps a method to handle HTTP HEAD requests.
@Options(path?: string) MethodDecorator Maps a method to handle HTTP OPTIONS requests.
Error Handling & Security
@ExceptionHandler(value?: Newable | Newable[]) MethodDecorator Annotation for handling exceptions in specific handler classes and/or handler methods.
@ResponseStatus(value: number) MethodDecorator & ClassDecorator Marks a method or exception class with the status code that should be returned.
@UsePipes(...pipes: any[]) MethodDecorator & ClassDecorator Specifies the pipes to be used for a controller or method.
Aliases
@GetMapping(path?: string) MethodDecorator Alias for @Get().
@PostMapping(path?: string) MethodDecorator Alias for @Post().
@PutMapping(path?: string) MethodDecorator Alias for @Put().
@PatchMapping(path?: string) MethodDecorator Alias for @Patch().
@DeleteMapping(path?: string) MethodDecorator Alias for @Delete().
@HeadMapping(path?: string) MethodDecorator Alias for @Head().
@OptionsMapping(path?: string) MethodDecorator Alias for @Options().

Parameter decorators

Parameter decorators
Decorator Returns Description
@Event() ParameterDecorator Injects the full Google Apps Script event object.
@Request(key?: string) ParameterDecorator Injects the full request object or a specific property.
@Headers(key?: string) ParameterDecorator Injects request headers or a specific header value.
@Body(key?: string, ...pipes: any[]) ParameterDecorator Injects the full request body or a specific key. Supports transformation pipes.
@Param(key?: string, ...pipes: any[]) ParameterDecorator Injects values from URL path parameters. Supports transformation pipes.
@Query(key?: string, ...pipes: any[]) ParameterDecorator Injects values from URL query parameters. Supports transformation pipes.
@Inject(token: any) ParameterDecorator Explicitly specifies an injection token for a dependency.
@Value(key: string) ParameterDecorator & PropertyDecorator Injects a value from the application configuration.
Aliases
@Autowired(token?: any) ParameterDecorator & PropertyDecorator Alias for @Inject().
@RequestBody(key?: string, ...pipes: any[]) ParameterDecorator Alias for @Body().
@PathVariable(key?: string, ...pipes: any[]) ParameterDecorator Alias for @Param().
@RequestParam(key?: string, ...pipes: any[]) ParameterDecorator Alias for @Query().
Validation Decorators (Spring Boot style)
@AssertFalse() ParameterDecorator Validates that the value is false.
@AssertTrue() ParameterDecorator Validates that the value is true.
@Email() ParameterDecorator Validates that the value is a valid email address.
@Max(value: number) ParameterDecorator Validates that the value is less than or equal to the specified maximum.
@Min(value: number) ParameterDecorator Validates that the value is greater than or equal to the specified minimum.
@Negative() ParameterDecorator Validates that the value is strictly negative.
@NegativeOrZero() ParameterDecorator Validates that the value is negative or zero.
@NotBlank() ParameterDecorator Validates that the value is not null and contains at least one non-whitespace character.
@NotEmpty() ParameterDecorator Validates that the value is not null and not empty (works for strings, arrays, and objects).
@Pattern(regexp: string | RegExp) ParameterDecorator Validates that the value matches the specified regular expression.
@Positive() ParameterDecorator Validates that the value is strictly positive.
@PositiveOrZero() ParameterDecorator Validates that the value is positive or zero.
@Size(options: { min?: number, max?: number }) ParameterDecorator Validates that the size of the value is between the specified minimum and maximum.

Built-in Pipes

Pipes can be used to transform data before it reaches your handler:

Pipe Description
ParseNumberPipe Transforms a string to a number.
ParseFloatPipe Transforms a string to a float.
ParseBooleanPipe Transforms a string to a boolean.
AssertFalsePipe Validates that the value is false.
AssertTruePipe Validates that the value is true.
EmailPipe Validates that the value is a valid email address.
MaxPipe Validates that the value is less than or equal to the specified maximum.
MinPipe Validates that the value is greater than or equal to the specified minimum.
NegativePipe Validates that the value is strictly negative.
NegativeOrZeroPipe Validates that the value is negative or zero.
NotBlankPipe Validates that the value is not blank.
NotEmptyPipe Validates that the value is not empty.
PatternPipe Validates that the value matches the specified regular expression.
PositivePipe Validates that the value is strictly positive.
PositiveOrZeroPipe Validates that the value is positive or zero.
SizePipe Validates that the size of the value is within range.

Advanced Examples

Pipes

Transform parameters with pipes:

import {Get, RestController, Query, ParseNumberPipe} from "bootgs";

@RestController("users")
export class UserController {

    @Get("details")
    getUserDetails(@Query("id", ParseNumberPipe) id: number): object {
        return {
            userId: id,
            message: "Success!"
        };
    }
}

Global Error Handling

Use @ControllerAdvice to handle exceptions globally across the whole application:

import {ControllerAdvice, ExceptionHandler, ResponseStatus} from "bootgs";

@ControllerAdvice()
export class GlobalExceptionHandler {

    @ExceptionHandler(Error)
    @ResponseStatus(500)
    handleError(error: Error): object {
        return {
            status: "Error",
            message: error.message
        };
    }
}

Contributors

felipepmdias kosmo-ds

Contributing

We welcome contributions! Please see our Contributing Guidelines for details on our code of conduct, and the process for submitting pull requests.

Roadmap

Check out our Roadmap to see what we have planned for future releases.

Changelog

For a detailed list of changes and updates, please refer to the CHANGELOG.

License

This project is licensed under the Apache-2.0 License.


Like this project? Give it a star on GitHub!