@synaptic-simulations/mach
Version:
The last MSFS instrument bundler you'll ever need.
141 lines • 7.69 kB
JavaScript
;
/*
* SPDX-FileCopyrightText: 2022 Synaptic Simulations and its contributors
* SPDX-License-Identifier: MIT
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.writePackageSources = exports.writeMetafile = exports.environment = void 0;
const promises_1 = __importDefault(require("node:fs/promises"));
const node_path_1 = __importDefault(require("node:path"));
const template_file_1 = require("template-file");
const ENV_REGEX = /process\.env\.(?<variable>[A-Za-z0-9_]+)/gm;
/**
* Replace references to `process.env.*` with their value from the current environment.
*/
exports.environment = {
name: "mach-environment",
setup(build) {
const loader = (loader) => async (args) => {
var _a;
let contents = await promises_1.default.readFile(args.path, "utf8");
if (args.path.includes("node_modules")) {
return { contents, loader };
}
let indexOffset = 0;
// The contents are split on newlines for the purposes of warning creation only
// This is done lazily to avoid unnecessary excessive string ops when there are no warnings
let lines = null;
const warnings = [];
for (const match of contents.matchAll(ENV_REGEX)) {
if (match.groups === undefined || match.index === undefined) {
continue;
}
const index = match.index + indexOffset;
const value = (_a = process.env[match.groups.variable]) !== null && _a !== void 0 ? _a : null;
if (value === null) {
if (lines === null) {
lines = contents.split("\n");
}
let line = 0;
let column = match.index;
while (column >= lines[line].length) {
// The extra one accounts for the newline that would be there
column -= lines[line].length + 1;
line += 1;
}
warnings.push({
text: `${match[0]} is not defined`,
location: {
file: args.path,
namespace: args.namespace,
line: line + 1,
column,
length: match[0].length,
lineText: lines[line],
suggestion: "",
},
});
}
const stringified = value === "true" ||
value === "false" ||
// biome-ignore lint/suspicious/noGlobalIsNan: we actually want the type coercion here
(value !== null && value !== "" && !isNaN(value))
? value
: JSON.stringify(value);
contents = contents.slice(0, index) + stringified + contents.slice(index + match[0].length);
indexOffset += stringified.length - match[0].length;
}
return { contents, loader, warnings };
};
build.onLoad({ filter: /\.ts$/ }, loader("ts"));
build.onLoad({ filter: /\.tsx$/ }, loader("tsx"));
build.onLoad({ filter: /\.js$/ }, loader("js"));
build.onLoad({ filter: /\.jsx$/ }, loader("jsx"));
},
};
/**
* Write `build_meta.json` files containing build data into the bundle directory.
*/
exports.writeMetafile = {
name: "mach-write-metafile",
setup(build) {
build.onEnd((result) => {
if (result.errors.length === 0) {
promises_1.default.writeFile(node_path_1.default.join(node_path_1.default.dirname(build.initialOptions.outfile), "build_meta.json"), JSON.stringify(result.metafile));
}
});
},
};
/**
* Export simulator packages to `PackageSources` directory
*/
const writePackageSources = (args, instrument) => ({
name: "mach-write-package-sources",
setup(build) {
build.onEnd(async (result) => {
var _a, _b, _c;
if (instrument.simulatorPackage && result.errors.length === 0) {
const jsBundlePath = node_path_1.default.join(node_path_1.default.dirname(build.initialOptions.outfile), "bundle.js");
const cssBundlePath = node_path_1.default.join(node_path_1.default.dirname(build.initialOptions.outfile), "bundle.css");
const js = await promises_1.default.readFile(jsBundlePath, { encoding: "utf-8" });
const css = await promises_1.default.readFile(cssBundlePath, { encoding: "utf-8" });
const htmlUiPath = node_path_1.default.join(process.cwd(), args.config.packageDir, "html_ui");
const packageTarget = node_path_1.default.join(htmlUiPath, "Pages/VCockpit/Instruments", args.config.packageName, instrument.name);
await promises_1.default.mkdir(packageTarget, { recursive: true });
const fileName = (_a = instrument.simulatorPackage.fileName) !== null && _a !== void 0 ? _a : "instrument";
const templateId = (_b = instrument.simulatorPackage.templateId) !== null && _b !== void 0 ? _b : instrument.name;
const cssPath = node_path_1.default.join(packageTarget, `${fileName}.css`);
const jsPath = node_path_1.default.join(packageTarget, `${fileName}.js`);
const instrumentPath = instrument.simulatorPackage.type === "react"
? node_path_1.default.join(packageTarget, `${fileName}.index.js`)
: jsPath;
const templateParams = {
templateId,
instrumentName: `${args.config.packageName.toLowerCase()}-${templateId.toLowerCase()}`,
mountElementId: instrument.simulatorPackage.type === "react"
? "MSFS_REACT_MOUNT"
: instrument.simulatorPackage.mountElementId,
imports: (_c = instrument.simulatorPackage.imports) !== null && _c !== void 0 ? _c : [],
cssPath: cssPath.replace(htmlUiPath, "").replace(/\\/g, "/"),
jsPath: jsPath.replace(htmlUiPath, "").replace(/\\/g, "/"),
instrumentPath: instrumentPath.replace(htmlUiPath, "").replace(/\\/g, "/"),
};
await promises_1.default.writeFile(cssPath, css);
await promises_1.default.writeFile(jsPath, js);
if (instrument.simulatorPackage.type === "react") {
await promises_1.default.writeFile(instrumentPath, await (0, template_file_1.renderFile)(instrument.simulatorPackage.jsTemplate
? node_path_1.default.resolve(instrument.simulatorPackage.jsTemplate)
: node_path_1.default.join(__dirname, "./templates/instrument.cjs"), templateParams));
}
await promises_1.default.writeFile(node_path_1.default.join(packageTarget, `${fileName}.html`), await (0, template_file_1.renderFile)(instrument.simulatorPackage.htmlTemplate
? node_path_1.default.resolve(instrument.simulatorPackage.htmlTemplate)
: node_path_1.default.join(__dirname, "./templates/index.html"), templateParams));
}
});
},
});
exports.writePackageSources = writePackageSources;
//# sourceMappingURL=plugins.js.map