Skip to content

Latest commit

 

History

History
1289 lines (899 loc) · 45.7 KB

README.md

File metadata and controls

1289 lines (899 loc) · 45.7 KB

Boostr

Overview

Boostr is a companion tool for Layr.

In a nutshell, Boostr takes care of everything you need to build and deploy a Layr app so you can focus on what really matters — your app's code.

Features

Here are the main features provided by Boostr:

  • App templates so you can bootstrap an app with a single command
  • Fully managed local development environment:
    • Automatic frontend build and refresh
    • Automatic backend build and restart
    • Local development database (limited to MongoDB for now)
  • Configuration management:
    • Environment variables with inheritance and cross-service references
    • Multiple stages (e.g., 'development', 'staging', and 'production')
    • Public and private configurations
  • Database migrations (limited to MongoDB for now)
  • Serverless deployment with a single command (limited to AWS for now)

Getting Started

Prerequisites

  • You use a Mac with a recent version of macOS. Everything should work fine on Linux, but we haven't tested it yet. It may work on Windows, but we haven't tested it and don't plan to provide support for now.
  • You have Node.js v16 or newer installed.

Installation

npm install --global boostr

Note: Installing an NPM package globally is usually not recommended. But it's not a problem in this case because each app managed by Boostr uses a local Boostr package which is automatically installed. So the global Boostr package can be seen as a shortcut to the local Boostr packages installed in your apps, and, therefore, you can have different apps using different versions of Boostr.

Creating a Layr App

Boostr provides an initialize command to bootstrap an app from a template.

For example, you can bootstrap a Layr web app using TypeScript with the following commands:

mkdir my-app
cd my-app
boostr initialize @boostr/web-app-ts

Then, you can open the my-app directory in your favorite IDE to explore the initial codebase.

Note: You can use any IDE you want, but if you use Visual Studio Code, you can profit from the VS Code configuration included in the supported app templates. Otherwise, you may have to set up your IDE to get a suitable configuration.

Check out the initialize command for details.

Starting a Layr App

You can start your app in development mode with the following command:

boostr start

In the case of a web app, the terminal should output something like this:

[database] MongoDB server started at mongodb://localhost:18160/
[backend] Build succeeded (bundle size: 2.06MB)
[backend] Component HTTP server started at http://localhost:18159/
[frontend] Build succeeded (bundle size: 1.34MB)
[frontend] Single-page application server started at http://localhost:18158/

Notes:

  • The TCP ports used for each local development URL were randomly set when the initialize command was executed to create your app in the previous section. So, it's normal if they are different for your app.
  • Don't be freaked out by the size of the generated bundles in development mode. When you deploy your apps, the generated bundles are a lot smaller.

The last line in the terminal output should include an URL you can open in a browser to display your app.

Check out the start command for details.

Deploying a Layr App

First, make sure that your frontend and backend Boostr configuration files (frontend/boostr.config.mjs and backend/boostr.config.mjs) specify the URLs you want to use for your app.

So, if you just created a web app with the initialize command, replace all the occurrences of 'example.com' with your domain name (e.g., 'awesome.app') or subdomain name (e.g., 'project1.awesome.app').

Then, run the following command to deploy your app to production:

boostr deploy --production

Check out the deploy command for details.

Configuration Files

A Layr app managed by Boostr is usually composed of different services, and each service is associated with a configuration file named boostr.config.mjs.

For example, a typical web app comprises the following directories and files:

Note: The name of the directories (e.g., frontend, backend, database) are specified in the root configuration file, so they can be anything you want.

Any configuration file is a JavaScript ESM module exporting a function (as default export) which should return a plain object representing the configuration.

Here's an example of a simple root configuration file:

export default () => ({
  type: 'application',

  services: {
    frontend: './frontend',
    backend: './backend',
    database: './database'
  }
});

The type property specifies a string representing the type of the service and is required for each configuration file. In the case of a root configuration file, the value of type should be 'application'.

The services property specifies an object allowing to match the name of the services used by the app with the path of the directories containing these services.

Application Service

The application service (also called "root service") is represented by a configuration file that specifies all the services used by your app and some general properties such as environment and stages.

Here's an example of an application service configuration file:

// boostr.config.mjs

export default () => ({
  type: 'application',

  services: {
    frontend: './frontend',
    backend: './backend',
    database: './database'
  },

  environment: {
    APPLICATION_NAME: 'Layr App',
    APPLICATION_DESCRIPTION: 'A Layr app managed by Boostr.'
  },

  stages: {
    staging: {
      environment: {
        NODE_ENV: 'production'
      }
    },
    production: {
      environment: {
        NODE_ENV: 'production'
      }
    }
  }
});

The object returned by the exported function contains the following properties:

  • type: Specifies the type of service, which should always be 'application' in the case of an application service.
  • services:
    • frontend: Specifies the directory's path (./frontend) of a web-frontend service simply named 'frontend'.
    • backend: Specifies the directory's path (./backend) of a backend service incidentally named 'backend'.
    • database: Specifies the directory's path (./database) of a database service incidentally named 'database'.
  • environment: An object allowing you to define some global environment variables.
  • stages:
    • staging: An object allowing you to define some properties when the 'staging' stage is used.
    • production: An object allowing you to define some properties when the 'production' stage is used.

Web-Frontend Service

A web-frontend service is represented by a configuration file that specifies some properties related to the nature of a web frontend and some general properties, such as environment, stages, and dependsOn.

Here's an example of a web-frontend service configuration file:

// frontend/boostr.config.mjs

export default ({services}) => ({
  type: 'web-frontend',

  dependsOn: 'backend',

  environment: {
    FRONTEND_URL: services.frontend.url,
    BACKEND_URL: services.backend.url
  },

  rootComponent: './src/index.ts',

  html: {
    language: 'en',
    head: {
      title: services.frontend.environment.APPLICATION_NAME,
      metas: [
        {
          name: 'description',
          content: services.frontend.environment.APPLICATION_DESCRIPTION
        },
        {charset: 'utf-8'},
        {name: 'viewport', content: 'width=device-width, initial-scale=1'},
        {'http-equiv': 'x-ua-compatible', 'content': 'ie=edge'}
      ],
      links: [
        {
          rel: 'icon',
          href: '/boostr-favicon-3NjLR7w1Mu8UAIqq05vVG3.immutable.png'
        }
      ]
    }
  },

  stages: {
    development: {
      url: 'http://localhost:10742/',
      platform: 'local'
    },
    staging: {
      url: 'https://staging.example.com/',
      platform: 'aws',
      aws: {
        region: 'us-east-1',
        cloudFront: {
          priceClass: 'PriceClass_100'
        }
      }
    },
    production: {
      url: 'https://example.com/',
      platform: 'aws',
      aws: {
        region: 'us-east-1',
        cloudFront: {
          priceClass: 'PriceClass_100'
        }
      }
    }
  }
});

The object returned by the exported function contains the following properties:

  • type: Specifies the type of service, which should always be 'web-frontend' in the case of a web-frontend service.
  • dependsOn: Specifies that the 'frontend' service depends on the 'backend' service. See "Service Dependencies" for details.
  • environment: An object allowing you to define some environment variables specific to the 'frontend' service. Note that 'FRONTEND_URL' and 'BACKEND_URL' are determined according to some service properties fetched from the services parameter of the configuration function. See "Service Property References" for a detailed explanation.
  • rootComponent: Specifies the file's path implementing the root Layr component of your web frontend.
  • html: An object allowing you to customize the index.html file automatically generated by Boostr. See "Autogenerated index.html File" for details.
  • stages:
    • development: An object allowing you to define some properties when the 'development' stage is used.
      • We define the url property so you can access the web frontend locally (see "Local Development URLs" for details).
      • We set the value of the platform property to 'local' to indicate that Boostr should manage a local frontend server.
    • staging and production: An object allowing you to define some properties when the 'staging' or 'production' stage is used.
      • We set the value of the url property to an URL where Boostr can deploy the web frontend (see "Deployment URLs" for details).
      • We set the value of the platform property to 'aws' to indicate that Boostr should use AWS as a deployment target.
      • Optionally, we can specify an aws object to customize the AWS configuration (see "Web-Frontend AWS Configuration" for details).

Autogenerated index.html File

In the codebase of a Layr web app managed by Boostr, you will not see any index.html file because this file is autogenerated.

We made this choice so that Boostr could abstract away the execution environment (e.g., browser, React Native, or Electron) in which the app runs.

So, your app should be mainly composed of configuration files and Layr components.

However, in most cases, it is necessary to customize the index.html file so your web app can have, for example, a title and a favicon.

As seen in the above example, you can do so by setting the html property in your web-frontend service configuration file.

The html property should be an object composed of the following properties:

  • language: A string specifying your web app's language (e.g., 'en'). When the index.html file is autogenerated, this property determines the value of the lang attribute of the <html> tag (e.g., <html lang="en">).
  • head:
    • title: A string specifying your web app's title (e.g., 'My Awesome App'). When the index.html file is autogenerated, this property determines the content of the <title> tag in the <head> section (e.g., <title>My Awesome App</title>).
    • metas: An array of objects specifying the attributes of some <meta> tags to include in the <head> section of the autogenerated index.html file. See an example of use in the above example.
    • links: An array of objects specifying the attributes of some <link> tags to include in the <head> section of the autogenerated index.html file. See an example of use in the above example.
    • style: A string specifying the content of a <style> tag to include in the <head> section of the autogenerated index.html file. You can see an example of use in the web-frontend service configuration file of the Layr website.
    • scripts: An array of objects specifying the attributes of some <script> tags to include in the <head> section of the autogenerated index.html file. You can see an example of use in the web-frontend service configuration file of the Layr website.
  • body:
    • scripts: An array of objects specifying the attributes of some <script> tags to include in the <body> section of the autogenerated index.html file.

Web-Frontend AWS Configuration

You can customize the AWS configuration of a web frontend by specifying an object containing the following properties:

  • region: Specifies the AWS region (e.g., 'us-east-1') where the web frontend is deployed.
  • profile: Specifies an AWS configuration profile (e.g., 'my-company') used to get your AWS credentials. If not specified, your default AWS configuration profile is used.
  • accessKeyId: Allows you to specify your AWS Access Key ID when the profile property is not used, or you don't have a default AWS configuration profile.
  • secretAccessKey: Allows you to specify your AWS Secret Access Key when the profile property is not used, or you don't have a default AWS configuration profile.
  • cloudFront:
    • priceClass: Specifies the Amazon CloudFront price class to use (default: 'PriceClass_100').

Backend Service

A backend service is represented by a configuration file that specifies some properties related to the nature of a backend and some general properties, such as environment, stages, and dependsOn.

Here's an example of a backend service configuration file:

// backend/boostr.config.mjs

export default ({services}) => ({
  type: 'backend',

  dependsOn: 'database',

  environment: {
    FRONTEND_URL: services.frontend.url,
    BACKEND_URL: services.backend.url,
    DATABASE_URL: services.database.url
  },

  rootComponent: './src/index.ts',

  stages: {
    development: {
      url: 'http://localhost:10743/',
      platform: 'local'
    },
    staging: {
      url: 'https://staging.backend.example.com/',
      platform: 'aws',
      aws: {
        region: 'us-east-1',
        lambda: {
          memorySize: 1024
        }
      }
    },
    production: {
      url: 'https://backend.example.com/',
      platform: 'aws',
      aws: {
        region: 'us-east-1',
        lambda: {
          memorySize: 1024
        }
      }
    }
  }
});

The object returned by the exported function contains the following properties:

  • type: Specifies the type of service, which should always be 'backend' in the case of a backend service.
  • dependsOn: Specifies that the 'backend' service depends on the 'database' service. See "Service Dependencies" for details.
  • environment: An object allowing you to define some environment variables specific to the 'backend' service. Note that 'FRONTEND_URL', 'BACKEND_URL', and 'DATABASE_URL' are determined according to some service properties fetched from the services parameter of the configuration function. See "Service Property References" for a detailed explanation.
  • rootComponent: Specifies the file's path implementing the root Layr component of your backend.
  • stages:
    • development: An object allowing you to define some properties when the 'development' stage is used.
      • We define the url property so the frontend can access the backend locally (see "Local Development URLs" for details).
      • We set the value of the platform property to 'local' to indicate that Boostr should manage a local backend server.
    • staging and production: An object allowing you to define some properties when the 'staging' or 'production' stage is used.
      • We set the value of the url property to an URL where Boostr can deploy the backend (see "Deployment URLs" for details).
      • We set the value of the platform property to 'aws' to indicate that Boostr should use AWS as a deployment target.
      • Optionally, we can specify an aws object to customize the AWS configuration (see "Backend AWS Configuration" below for details).

Backend AWS Configuration

You can customize the AWS configuration of a backend by specifying an object containing the following properties:

  • region: Specifies the AWS region (e.g., 'us-east-1') where the backend is deployed.
  • profile: Specifies an AWS configuration profile (e.g., 'my-company') used to get your AWS credentials. If not specified, your default AWS configuration profile is used.
  • accessKeyId: Allows you to specify your AWS Access Key ID when the profile property is not used, or you don't have a default AWS configuration profile.
  • secretAccessKey: Allows you to specify your AWS Secret Access Key when the profile property is not used, or you don't have a default AWS configuration profile.
  • lambda:

Database Service

A database service is represented by a configuration file that specifies some properties related to the nature of a database and some general properties, such as stages.

Here's an example of a database service configuration file:

// database/boostr.config.mjs

export default () => ({
  type: 'database',

  stages: {
    development: {
      url: 'mongodb://localhost:10744/dev',
      platform: 'local'
    }
  }
});

The object returned by the exported function contains the following properties:

  • type: Specifies the type of service, which should always be 'database' in the case of a database service.
  • stages:
    • development: An object allowing you to define some properties when the 'development' stage is used.
      • We define the url property so the backend can access the database locally (see "Local Development URLs" for details).
      • We set the value of the platform property to 'local' to indicate that Boostr should manage a local database server.

You may wonder where are the URLs of the staging and production databases. Well, the problem is that we cannot put these URLs in database/boostr.config.mjs because they may contain sensitive information, such as access credentials.

Thankfully, we can add a private configuration file to solve the issue:

// database/boostr.config.private.mjs

export default () => ({
  stages: {
    staging: {
      url: 'mongodb+srv://user:[email protected]/exampleStaging?retryWrites=true&w=majority'
    },
    production: {
      url: 'mongodb+srv://user:[email protected]/exampleProduction?retryWrites=true&w=majority'
    }
  }
});

Environment Variables

Defining Environment Variables

Using the environment object property, you can define environment variables in any configuration file.

For example, here's how you would define an APPLICATION_NAME environment variable in the root configuration:

// boostr.config.mjs

export default () => ({
  // ...

  environment: {
    APPLICATION_NAME: 'Layr App'
  }

  // ...
});

Ahd here's how you would define an APPLICATION_DESCRIPTION environment variable in a web-frontend service configuration:

// frontend/boostr.config.mjs

export default () => ({
  // ...

  environment: {
    APPLICATION_DESCRIPTION: 'A Layr app managed by Boostr.'
  }

  // ...
});

And finally, here's how you would define a DATABASE_URL environment variable in a backend service configuration:

// backend/boostr.config.mjs

export default ({services}) => ({
  // ...

  environment: {
    DATABASE_URL: services.database.url
  }

  // ...
});

Note that the value of 'DATABASE_URL' is determined according to a 'database' service property fetched from the services parameter of the configuration function. See "Service Property References" for a detailed explanation.

Global Environment Variables

The environment variables defined in the root configuration are global, and therefore, they are accessible from all the services of your app.

So, in the examples above, the web-frontend service has access to APPLICATION_NAME in addition to APPLICATION_DESCRIPTION, and the backend service has access to APPLICATION_NAME in addition to DATABASE_URL.

Accessing Environment Variables

You can access environment variables from your app's code via the process.env object.

For example, here's how you would get the value of APPLICATION_NAME from your frontend code:

// frontend/src/components/application.jsx

// ...

class Application extends Base {
  @view() static HeaderView() {
    return <h1>{process.env.APPLICATION_NAME}</h1>;
  }
}

And here's how you would get the value of DATABASE_URL from your backend code:

// backend/src/index.ts

// ...

const store = new MongoDBStore(process.env.DATABASE_URL);

Environment variables are also accessible when you run commands, such as test, eval, or repl.

For example, if you run the following command:

boostr backend eval process.env.APPLICATION_NAME

The terminal should output something like this:

[database] MongoDB server started at mongodb://localhost:14128/
[backend] Build succeeded (bundle size: 2.06MB)
[backend] Evaluating code...
[backend] Result:
[backend] "Layr App"
[database] MongoDB server stopped

Stages

Generally, a Layr app managed by Boostr uses several stages, allowing you to define (or redefine) some configuration properties according to each stage.

For example, a typical app has the following stages:

  • 'development': A stage used when you run your app in development mode on your local machine.
  • 'staging': A stage used when you deploy your app to your staging hosting environment.
  • 'production': A stage used when you deploy your app to production.

Note: You can define as many stages as you want and name them according to your preferences. However, if you use unconventional stage names, you won't be able to use a shorthand option, such as --staging or --production, to select a stage.

Defining Stages

Using the stages property, you can define stages in any configuration file.

The stages property should be an object composed of:

  • Keys that represent the name of your stages.
  • Values that allow you to define (or redefine) any configuration property according to each stage.

Here's an example of a root configuration file using the stages property to change the value of the global APPLICATION_NAME environment variable for the 'development' and 'staging' stages:

// boostr.config.mjs

export default () => ({
  // ...

  environment: {
    APPLICATION_NAME: 'Layr App',
    APPLICATION_DESCRIPTION: 'A Layr app managed by Boostr.'
  },

  stages: {
    development: {
      environment: {
        APPLICATION_NAME: 'Layr App (development)'
      }
    },
    staging: {
      environment: {
        APPLICATION_NAME: 'Layr App (staging)'
      }
    }
  }
});

Note that in the example above:

  • Since APPLICATION_NAME is not specified in a 'production' stage, its value will be 'Layr App' when the app is deployed to the 'production' stage.
  • Since APPLICATION_DESCRIPTION is not specified in any stage, its value will always be 'A Layr app managed by Boostr.'.

Selecting Stages

When you run a Boostr command, you can use the --stage option to select a stage.

Alternatively, you can use one of the following shorthand options:

  • --development: A shorthand for --stage=development.
  • --staging: A shorthand for --stage=staging.
  • --production: A shorthand for --stage=production.

Note: The default stage is 'development', which will be used if you don't explicitly select another stage.

Examples:

# Starts the app while using the 'development' stage
boostr start --stage=development

# Since 'development' is the default stage, the following is equivalent
boostr start
# Deploys the app while using the 'production' stage
boostr deploy --stage=production

# Does the same thing by using the shorthand option
boostr deploy --production

Service Dependencies

Using the dependsOn property, you can specify dependencies between the services of your Layr app.

So, for example, you can specify that a web-frontend service depends on a backend service, which itself depends on a database service.

When you start your app with the start command, Boostr analyses the dependencies between your services and ensures that each dependency starts before each dependent.

So, in the example above, the services will start in the following order:

  1. Database service
  2. Backend service
  3. Web-frontend service

The same logic applies to other commands, such as the deploy command.

Here's an example showing how to specify a dependency between a web-frontend service and a backend service:

// frontend/boostr.config.mjs

export default () => ({
  type: 'web-frontend',

  dependsOn: 'backend'

  // ...
});

And here's an example showing how to specify a dependency between a backend service and a database service:

// backend/boostr.config.mjs

export default () => ({
  type: 'backend',

  dependsOn: 'database'

  // ...
});

Service Property References

Using the services parameter of a configuration function, the services of your Layr app can reference each other.

This feature allows you to configure your app in a way that is 100% DRY.

For example, let's take some configuration files:

// boostr.config.mjs

export default () => ({
  type: 'application',

  services: {
    frontend: './frontend',
    backend: './backend'
  }
});
// frontend/boostr.config.mjs

export default ({services}) => ({
  type: 'web-frontend',

  environment: {
    BACKEND_URL: services.backend.url
  },

  // ...

  stages: {
    development: {
      url: 'http://localhost:10742/',
      platform: 'local'
    }
  }
});
// backend/boostr.config.mjs

export default ({services}) => ({
  type: 'backend',

  environment: {
    FRONTEND_URL: services.frontend.url
  },

  // ...

  stages: {
    development: {
      url: 'http://localhost:10743/',
      platform: 'local'
    }
  }
});

In the web-frontend service, the value of the 'BACKEND_URL' environment variable is fetched from the backend service (incidentally named 'backend' in the root configuration), which is accessible thanks to the services parameter of the configuration function.

You can see the same mechanism used in the backend service. The value of the 'FRONTEND_URL' environment variable is fetched from the web-frontend service (simply named 'frontend' in the root configuration).

Note that a service can even reference itself. For example, if, for some reason, you need a web-frontend service to be aware of its own URL through an environment variable, you can do so with the following configuration file:

// frontend/boostr.config.mjs

export default ({services}) => ({
  type: 'web-frontend',

  environment: {
    FRONTEND_URL: services.frontend.url
  },

  // ...

  stages: {
    development: {
      url: 'http://localhost:10742/',
      platform: 'local'
    }
  }
});

Local Development URLs

A local development URL looks like 'http://localhost:10742/' for a web-frontend or backend service and 'mongodb://localhost:10744/dev' for a database service.

When you initialize an app with the initialize command, the TCP ports (e.g., 10742) used for each service are randomly set. It ensures that you will never encounter port conflicts while working on several apps simultaneously.

Deployment URLs

A deployment URL (e.g., 'https://example.com/' or 'https://staging.example.com/') indicates where Boostr should deploy a service. Note that currently, the DNS associated with your base domain names (e.g., 'example.com') must be managed by Amazon Route 53.

Private Configuration Files

Most apps use secrets that must remain private and never be included in your Git repositories (even if these repositories are private).

Your app configuration files should be included in your Git repositories and, therefore, cannot contain any secrets.

So how could you configure secrets without exposing them?

Boostr supports private configuration files that work like any configuration file but should be named boostr.config.private.mjs and stored next to your public configuration files named boostr.config.mjs.

Private configuration files are automatically excluded from Git thanks to a line (e.g., *.private.*) in a .gitignore file at the root of your repositories.

When Boostr evaluates your app's configuration, it reads both public and private configuration files and deeply merges them.

Note: Private configurations precede public configurations, so a property found in a private configuration can override a property of the same name found in a public configuration.

Example

Let's say your app implements an authentication mechanism using a JWT library to sign and verify users' access tokens.

JWT relies on a secret that should be accessible from your backend. So, in your backend directory, you could specify this secret in a private configuration file next to your public configuration file.

Here's what your public configuration file would look like:

// backend/boostr.config.mjs

export default () => ({
  type: 'backend',

  environment: {
    EMAIL_ADDRESS: '[email protected]'
  },

  // ...

  stages: {
    development: {
      // ...
    },
    production: {
      // ...
    }
  }
});

And here's what your private configuration file would look like:

// backend/boostr.config.private.mjs

export default () => ({
  stages: {
    development: {
      environment: {
        JWT_SECRET: '26d9c27e799aba1b047ec16450a51418...'
      }
    },
    production: {
      environment: {
        JWT_SECRET: '537df3079d44e066bf0195433863ec34...'
      }
    }
  }
});

Inline Help

You can get some help from the Boostr CLI by using the --help option.

Get some general help by running the following:

boostr --help

Get some help for a global command (e.g., start) by running the following:

boostr start --help

Get some help for a specific service (e.g., 'frontend') by running the following:

boostr frontend --help

Get some help for a command of a specific service (e.g., the import command of the 'database' service) by running the following:

boostr database import --help

Global Commands

The global commands are available for all services, including the root of your app, which is represented by a service of type 'application'.

boostr initialize <template> [options]

Alias: boostr init

Initializes your app within the current directory from the specified template.

The <template> argument specifies the template to use, which should be a published npm package.

Currently, two templates are available:

  • @boostr/web-app-js for initializing a web app using JavaScript
  • @boostr/web-app-ts for initializing a web app using TypeScript

We will publish more templates in the future. For example, some React Native or Electron app templates should soon be available.

A template is simply an npm package. So, the community can publish any new template, and if needed, you can create some templates for your personal use.

Options

In addition to the global options, the initialize command accepts the following option:

  • --name: Specifies the name of your app (defaults to the name of the current directory).

Examples

# Creates a web app named `my-app` using TypeScript
mkdir my-app
cd my-app
boostr initialize @boostr/web-app-ts

You can check out the outcome of the above example in the Boostr repository.

# Creates a web app named `my-awesome-app` using JavaScript
mkdir my-directory
cd my-directory
boostr init @boostr/web-app-js --name=my-awesome-app

You can check out the outcome of the above example in the Boostr repository.

boostr [<service>] install [options]

Installs all the npm dependencies used in your app (or a specified service).

Under the hood, this command runs npm install.

Options

See the global options.

Examples

# Installs all the npm dependencies used in your app
boostr install
# Installs all the npm dependencies used in the 'frontend' service
boostr frontend install

boostr [<service>] update [options]

Updates all the npm dependencies used in your app (or a specified service).

Under the hood, this command runs npm update.

Options

See the global options.

Examples

# Updates all the npm dependencies used in your app (including Boostr itself)
boostr update
# Updates all the npm dependencies used in the 'backend' service
boostr backend update

boostr [<service>] check [options]

Checks the TypeScript code of your app (or a specified service).

Under the hood, this command runs tsc --noEmit.

Options

See the global options.

Examples

# Checks the TypeScript code of your app
boostr check
# Checks the TypeScript code of the 'backend' service
boostr backend check

boostr [<service>] build [options]

Builds runnable artifacts from the source code of your app (or a specified service).

Note: This command is automatically executed when you run some other commands, such as start or deploy. So, unless you want to check out the built runnable artifacts for debugging purposes, you should not have to use the build command explicitly.

Options

See the global options.

Examples

# Builds runnable artifacts from the source code of your app
boostr build
# Builds runnable artifacts from the source code of the 'frontend' service
boostr frontend build
# Builds runnable artifacts from the source code of your app while using
# the 'production' stage configuration
boostr build --production

boostr [<service>] test [options]

Tests all the services of your app (or a specified service) in development mode.

Under the hood, this command runs npm test.

Options

See the global options.

Examples

# Tests all the services of your app
boostr test
# Tests the 'backend' service
boostr backend test

boostr [<service>] start [options]

Starts your app (or a specified service) in development mode.

Options

See the global options.

Examples

# Starts all the services of your app in development mode
boostr start
# Starts the 'backend' service (and the services it depends on)
# in development mode
boostr backend start

boostr [<service>] migrate [options]

Migrates one or more databases used by your app.

Note: Database migrations are limited to MongoDB for now.

Options

See the global options.

Examples

# Migrates all the databases used by your app in the 'development' environment
boostr migrate
# Migrates all the databases used by your app in the 'staging' environment
boostr migrate --staging
# Migrates the 'customers' database in the 'development' environment
boostr customers migrate

boostr [<service>] deploy [options]

Deploys your app (or a specified service) to a specific stage.

Options

In addition to the global options, the deploy command accepts the following option:

  • --skip: Skips the specified service when deploying. Note that you can repeat this option several times to skip multiple services.

Notes

  • Currently, only AWS is supported as a deployment target.
  • The DNS associated with your base domain name must be managed by Amazon Route 53.
  • The first deployment may take a while because several AWS services have to be set up, but subsequent deployments should be much faster.
  • Boostr manages the deployment of the web-frontend and backend services, but the database services are not. So, you will have to set up the databases by yourself on some cloud services, such as MongoDB Atlas or Amazon DocumentDB.

Examples

# Deploys all the services of your app to the 'staging' stage
boostr deploy --stage=staging

# Does the same thing by using the shorthand option
boostr deploy --staging
# Deploys all the services of your app to the 'production' stage
boostr deploy --stage=production

# Does the same thing by using the shorthand option
boostr deploy --production
# Deploys the 'backend' service (and the services it depends on)
# to the 'production' stage
boostr backend deploy --production
# Deploys all the services of your app to the 'staging' stage while
# skipping the 'legacyBackend' service
boostr deploy --staging --skip=legacyBackend

boostr [<service>] config [options]

Displays the root (or a specified service) configuration.

Note: The displayed configuration considers all the property references and resolves them according to a specific stage ('development' by default).

Options

See the global options.

Examples

# Displays the root configuration for the 'development' environment
boostr config
# Displays the configuration of the 'frontend' service for the 'development' environment
boostr frontend config
# Displays the configuration of the 'backend' service for the 'production' environment
boostr backend config --production

boostr [<service>] exec [options] -- <command> ...

Executes any shell command in the root directory of your app (or in the directory of a specified service).

Note: The environment variables specified in your configuration are accessible from the executed shell command.

Options

See the global options.

Examples

# Executes `npx prettier --check .` in the root directory of your app
boostr exec -- npx prettier --check .
# Executes `npm install lodash` in the directory of the 'backend' service
boostr backend exec -- npm install lodash
# Executes `npm version patch --no-git-tag-version` in the directory of
# the 'frontend' service
boostr frontend exec -- npm version patch --no-git-tag-version
# Executes `npm run myscript` in the directory of the 'backend' service
# with the environment variables of the 'production' stage
boostr backend exec --stage=production -- npm run myscript

Web-Frontend Commands

The web-frontend commands are available for all services of type 'web-frontend'.

boostr <web-frontend-service> freeze

Freezes all the files in your web-frontend service's public directory.

Freezing a file means that the file is renamed to match the pattern <name>-<hash>.immutable.<extension> where <name> is the original file name without its extension, <hash> is a hash generated from the contents of the file, and <extension> is the original file extension.

For example, if you have a file named favicon.png in the public directory of your 'frontend' service, running boostr frontend freeze will rename the favicon.png file to something like favicon-3NjLR7w1Mu8UAIqq05vVG3.immutable.png.

When a browser loads a frozen file, it can permanently store it in its cache thanks to a Cache-Control header automatically added when your frontend is deployed.

Note: It is not an issue to run the freeze command several times because the command is clever enough to ignore the files that have already been frozen.

Backend Commands

The backend commands are available for all services of type 'backend'.

boostr <backend-service> eval "<codeToEval>" [options]

Evaluates the specified JavaScript code with your backend service root component exposed globally and outputs the result in the terminal.

Options

See the global options.

Example

If you run the following command with a web app that has just been initialized from the @boostr/web-app-ts template:

boostr backend eval "Application.isHealthy()"

The terminal should output something like this:

[database] MongoDB server started at mongodb://localhost:10744/
[backend] Build succeeded (bundle size: 2.06MB)
[backend] Evaluating code...
[backend] Result:
[backend] true
[database] MongoDB server stopped

boostr <backend-service> repl [options]

Starts a Node.js REPL with your backend root component exposed globally.

Options

See the global options.

Example

If you run the following command with a web app that has just been initialized from the @boostr/web-app-ts template:

boostr backend repl

Then, you should be able to execute the following JavaScript code inside the REPL:

await Application.isHealthy();

And the REPL should output the following result:

true

Global Options

The following options are available for most commands:

  • --stage: Selects a stage. See "Stages" for details.
  • --development: A shorthand for --stage=development.
  • --staging: A shorthand for --stage=staging.
  • --production: A shorthand for --stage=production.
  • --help, -h: Displays inline help. See "Inline Help" for details.
  • --version, -v: Displays the current Boostr version.

Contributing

Contributions are welcome.

Before contributing please read the code of conduct and search the issue tracker to find out if your issue has already been discussed before.

To contribute, fork this repository, commit your changes, and send a pull request.

License

MIT