@synaptic-simulations/mach
Version:
The last MSFS instrument bundler you'll ever need.
165 lines (133 loc) • 6.33 kB
Markdown
**Mach** is an ultra-fast transpiler and bundler for use with MSFS (Microsoft Flight Simulator 2020) instruments. Unlike other bundling tools such as *rollup* or *webpack*, Mach has been built from the ground up with the sole purpose of serving the MSFS development community's needs.

## Features
Mach currently supports bundling both JavaScript and TypeScript React instruments, along with any CSS or SCSS stylesheets and images that are included. Instruments built with the [MSFS Avionics Framework](https://microsoft.github.io/msfs-avionics-mirror/docs/intro/) are also supported, but require additional steps to ensure compatibility as described [here](#msfs-avionics-framework-compatibility).
Mach also allows you to create nested instruments, enabling you to bundle MSFS Avionics instruments separately and import them into your React instrument.
## Usage
> [!IMPORTANT]
> Please ensure that you are using Node 22!
### CLI
#### Options
- `-c, --config <filename>` specify path to configuration file (default: `./mach.config.js`)
- `-d, --work-in-config-dir` use config directory as working directory
- `-b, --bundles <dirname>` bundles output directory (default: `./bundles`)
- `-e, --werror` makes all warnings into errors
- `-f, --filter <regex>` regex filter of included instrument names
- `-m, --minify` minify bundle code
- `-s, --skip-simulator-package` skips writing simulator package templates
- `-t, --output-metafile` output `build_meta.json` file to bundles directory
- `-p, --sourcemaps` generate inline sourcemaps
- `-p, --sourcemaps [linked | external | inline | both]` generate sourcemaps (see https://esbuild.github.io/api/#sourcemap for details on options)
- `-v, --verbose` output additional build information
#### `mach build [options]`
The `build` command will simply go through each instrument defined in your [configuration](#configuration), then output the bundles and package source files to the configured directories.
#### `mach watch [options]`
The `watch` command will first build each instrument in the configuration, and then watch the source files for changes in order to re-bundle the instrument. **If there was an error while bundling the instrument in the beginning, the watcher will not run.**
### JavaScript
#### `async function machBuild(conf: MachConfig, filter?: RegExp)`
This function has the same behavior as the [`mach build [options]`](#mach-build-options) CLI command.
#### `async function machWatch(conf: MachConfig, filter?: RegExp)`
This function has the same behavior as the [`mach watch [options]`](#mach-watch-options) CLI command.
## Configuration
Whether you supply the configuration with the `mach.config.js` file to the CLI or with a JavaScript object to the API, the structure is identical.
```ts
interface PackageSettings {
/**
* Specifies type of instrument.
* - `React` instruments will be created with a `BaseInstrument` harness that exposes an `MSFS_REACT_MOUNT` element for mounting.
* - `BaseInstrument` instruments must specify the `instrumentId` and `mountElementId` to match the instrument configuration.
*/
type: string;
/** Final template filename. Defaults to `template` */
fileName?: string;
/** Simulator packages to import in the HTML template. */
imports?: string[];
}
interface ReactInstrumentPackageSettings extends PackageSettings {
type: 'react';
/** Optional parameter to specify template ID. Defaults to `Instrument.name`. */
templateId?: string;
/** Whether the instrument is interactive or not. Defaults to `true`. */
isInteractive?: boolean;
}
interface BaseInstrumentPackageSettings extends PackageSettings {
type: 'baseInstrument';
/**
* Required for `BaseInstrument` instruments.
* This value must match the return value from the `BaseInstrument.templateID()` function.
* */
templateId: string;
/**
* Required for `BaseInstrument` instruments.
* This value must match the ID in your call to `FSComponent.render()`..
*/
mountElementId: string;
}
interface Instrument {
/** Instrument name, used as directory name for bundles and packages. */
name: string;
/** Entrypoint filename for instrument. */
index: string;
/** When passed a configuration object, enables a simulator package export. */
simulatorPackage?: ReactInstrumentPackageSettings | BaseInstrumentPackageSettings;
/** Instruments to import as ESM modules. */
modules?: Instrument[];
/** (Required for instruments included as `modules`) Import name to resolve to the bundled module. */
resolve?: string;
}
interface MachConfig {
/** Name of package, used for bundling simulator packages. */
packageName: string;
/** Path to directory containing `html_ui`. */
packageDir: string;
/**
* esbuild configuration overrides (<https://esbuild.github.io/api/>)
* entryPoints, outfile, format, metafile, bundle are not overridable.
*/
esbuild?: BuildOptions;
/** All instruments to be bundled by Mach. */
instruments: Instrument[];
}
```
```js
const imageInline = require('esbuild-plugin-inline-image');
/** @type { import('@synaptic-simulations/mach').MachConfig } */
module.exports = {
packageName: 'a22x',
packageDir: 'PackageSources',
plugins: [imageInline({ limit: -1 })],
instruments: [
{
name: 'DisplayUnits',
index: 'src/instruments/src/DisplayUnits/index.tsx',
simulatorPackage: {
type: 'react',
imports: ['/JS/dataStorage.js'],
},
modules: [{
name: 'PFD',
resolve: '@instruments/PFD',
index: 'src/instruments/src/PFD/index.tsx',
}],
},
{
name: 'CTP',
index: 'src/instruments/src/CTP/index.tsx',
simulatorPackage: {
type: 'react',
imports: ['/JS/dataStorage.js'],
},
},
{
name: 'ISI',
index: 'src/instruments/src/ISI/index.tsx',
simulatorPackage: {
type: 'react',
imports: ['/JS/dataStorage.js'],
},
},
],
};
```