Skip to content

Commit

Permalink
fix: put resources in home directory (#121)
Browse files Browse the repository at this point in the history
Fixes #119

Avoid purging of resources on simbridge updates by moving them to an
external location.

Separate PR:

- fix terrain map being downloaded every update, probably a separate PR,
ideas exist

---------

Co-authored-by: Saschl <[email protected]>
  • Loading branch information
Saschl and Saschl authored Oct 2, 2024
1 parent 1946a22 commit ccd1aa0
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 26 deletions.
4 changes: 2 additions & 2 deletions apps/server/src/config/printer.config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { registerAs } from '@nestjs/config';
import { getExecutablePath } from 'apps/server/src/utilities/pathUtil';
import { getSimbridgeDir } from 'apps/server/src/utilities/pathUtil';
import { readFileSync } from 'fs';
import { join } from 'path';

const CONFIG_FILENAME = 'resources/properties.json';

export default registerAs('printer', () => {
const configPath = join(getExecutablePath(), CONFIG_FILENAME);
const configPath = join(getSimbridgeDir(), CONFIG_FILENAME);
const properties = JSON.parse(readFileSync(configPath, 'utf8'));

return {
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/config/server.config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { registerAs } from '@nestjs/config';
import { getExecutablePath } from 'apps/server/src/utilities/pathUtil';
import { getSimbridgeDir } from 'apps/server/src/utilities/pathUtil';
import { readFileSync } from 'fs';
import { join } from 'path';

const CONFIG_FILENAME = 'resources/properties.json';

export default registerAs('server', () => {
const configPath = join(getExecutablePath(), CONFIG_FILENAME);
const configPath = join(getSimbridgeDir(), CONFIG_FILENAME);
const properties = JSON.parse(readFileSync(configPath, 'utf8'));

return {
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/config/winston.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Injectable } from '@nestjs/common';
import { getExecutablePath } from 'apps/server/src/utilities/pathUtil';
import { getSimbridgeDir } from 'apps/server/src/utilities/pathUtil';
import {
WinstonModuleOptions,
WinstonModuleOptionsFactory,
Expand All @@ -23,7 +23,7 @@ const consoleTransport = new winston.transports.Console({
const fileTransport = new winston.transports.DailyRotateFile({
frequency: '24h',
filename: 'fbw-simbridge-%DATE%.log',
dirname: `${join(getExecutablePath(), 'resources/logs')}`,
dirname: `${join(getSimbridgeDir(), 'resources/logs')}`,
datePattern: 'YYYY-MM-DD-HH',
zippedArchive: true,
maxSize: '20m',
Expand Down
37 changes: 31 additions & 6 deletions apps/server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import { NestFactory } from '@nestjs/core';
import { platform } from 'os';
import { hideConsole } from 'node-hide-console-window';
import * as path from 'path';
import { getExecutablePath } from 'apps/server/src/utilities/pathUtil';
import { getSimbridgeDir } from 'apps/server/src/utilities/pathUtil';
import { ShutDownService } from './utilities/shutdown.service';
import { AppModule } from './app.module';
import { NetworkService } from './utilities/network.service';
import { existsSync, writeFileSync } from 'fs';

declare const module: any;

Expand Down Expand Up @@ -40,9 +41,6 @@ async function bootstrap() {
// Validation
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));

// Folder creation
generateResourceFolders();

// Swagger
const swaggerConfig = new DocumentBuilder()
.setTitle('FlyByWire SimBridge')
Expand Down Expand Up @@ -70,12 +68,39 @@ async function bootstrap() {
}
}

generateResourceFolders();
generateDefaultProperties();

bootstrap();

function generateResourceFolders() {
dirs.forEach((dir) => {
access(dir, (error) => {
if (error) mkdirSync(path.join(getExecutablePath(), dir), { recursive: true });
const actualDir = path.join(getSimbridgeDir(), dir);
access(actualDir, (error) => {
if (error) mkdirSync(actualDir, { recursive: true });
});
});
}

function generateDefaultProperties() {
const propertiesFilePath = path.join(getSimbridgeDir(), '/resources', '/properties.json');

const defaultProperties = {
server: {
port: 8380,
hidden: true,
closeWithMSFS: false,
},
printer: {
enabled: false,
printerName: null,
fontSize: 19,
paperSize: 'A4',
margin: 30,
},
};

if (!existsSync(propertiesFilePath)) {
writeFileSync(propertiesFilePath, JSON.stringify(defaultProperties));
}
}
5 changes: 3 additions & 2 deletions apps/server/src/terrain/processing/maphandler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { GPU, IKernelRunShortcut, Texture } from 'gpu.js';
import { readFile } from 'fs/promises';
import { join } from 'path';
import { getExecutablePath } from 'apps/server/src/utilities/pathUtil';
import { getExecutablePath, getSimbridgeDir } from 'apps/server/src/utilities/pathUtil';
import { AircraftStatus, ElevationProfile, NavigationDisplay, PositionData, TerrainRenderingMode } from '../types';
import { TerrainMap } from '../fileformat/terrainmap';
import { Worldmap } from '../mapdata/worldmap';
Expand Down Expand Up @@ -146,7 +146,8 @@ export class MapHandler {

private async readTerrainMap(): Promise<TerrainMap | undefined> {
try {
const buffer = await readFile(join(getExecutablePath(), './terrain/terrain.map'));
// TODO shall we move this as well? Currently the installer downloads the terrain.map file
const buffer = await readFile(join(getExecutablePath(), '/terrain/terrain.map'));
this.logging.info(`Read MB of terrainmap: ${(Buffer.byteLength(buffer) / (1024 * 1024)).toFixed(2)}`);
return new TerrainMap(buffer);
} catch (err) {
Expand Down
16 changes: 8 additions & 8 deletions apps/server/src/utilities/file.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { readFileSync, lstatSync } from 'fs';
import * as xml2js from 'xml2js';
import { getDocument, PDFDocumentProxy } from 'pdfjs-dist/legacy/build/pdf';
import { join } from 'path';
import { getExecutablePath } from './pathUtil';
import { getExecutablePath, getSimbridgeDir } from './pathUtil';
import { pdfToPng } from './pdfConversion';

// eslint-disable-next-line @typescript-eslint/no-var-requires
Expand All @@ -29,7 +29,7 @@ export class FileService {
async getFileCount(directory: string): Promise<number> {
try {
this.logger.debug(`Retrieving number of files in folder: ${directory}`);
const dir = join(getExecutablePath(), directory);
const dir = join(getSimbridgeDir(), directory);
this.checkFilePathSafety(dir);
const retrievedDir = await readdir(dir, { withFileTypes: true });
const fileNames = retrievedDir.filter((dir) => dir.isFile()).map((dir) => dir.name);
Expand All @@ -45,7 +45,7 @@ export class FileService {
try {
this.logger.debug(`Reading all files in directory: ${directory}`);

const dir = join(getExecutablePath(), directory);
const dir = join(getSimbridgeDir(), directory);
this.checkFilePathSafety(dir);
const fileNames = (await readdir(dir, { withFileTypes: true }))
.filter((dir) => dir.isFile())
Expand All @@ -66,7 +66,7 @@ export class FileService {
async getFilenames(directory: string): Promise<string[]> {
try {
this.logger.debug(`Reading all files in directory: ${directory}`);
const dir = join(getExecutablePath(), directory);
const dir = join(getSimbridgeDir(), directory);
this.checkFilePathSafety(dir);
return (await readdir(dir, { withFileTypes: true })).filter((dir) => dir.isFile()).map((dir) => dir.name);
} catch (err) {
Expand All @@ -79,7 +79,7 @@ export class FileService {
async getFoldernames(directory: string): Promise<string[]> {
try {
this.logger.debug(`Reading all Dirs in directory: ${directory}`);
const dir = join(getExecutablePath(), directory);
const dir = join(getSimbridgeDir(), directory);
this.checkFilePathSafety(dir);
return (await readdir(dir, { withFileTypes: true })).filter((dir) => dir.isDirectory()).map((dir) => dir.name);
} catch (err) {
Expand All @@ -93,7 +93,7 @@ export class FileService {
try {
this.logger.debug(`Retrieving file: ${fileName} in folder: ${directory}`);

const path = join(getExecutablePath(), directory, fileName);
const path = join(getSimbridgeDir(), directory, fileName);
this.checkFilePathSafety(path);

if (!lstatSync(path).isFile()) {
Expand Down Expand Up @@ -122,7 +122,7 @@ export class FileService {
throw new HttpException('Unexpected null byte encountered', HttpStatus.UNPROCESSABLE_ENTITY);
}

if (filePath.indexOf(getExecutablePath()) !== 0) {
if (filePath.indexOf(getSimbridgeDir()) !== 0) {
throw new HttpException('Unacceptable file path', HttpStatus.UNPROCESSABLE_ENTITY);
}
}
Expand All @@ -141,7 +141,7 @@ export class FileService {
const STANDARD_FONT_DATA_URL = `${join(getExecutablePath(), 'node_modules', 'pdfjs-dist', 'standard_fonts')}/`;

try {
const conversionFilePath = join(getExecutablePath(), directory, fileName);
const conversionFilePath = join(getSimbridgeDir(), directory, fileName);

this.checkFilePathSafety(conversionFilePath);

Expand Down
5 changes: 4 additions & 1 deletion apps/server/src/utilities/pathUtil.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import getPath from 'platform-folders';
import * as path from 'path';

// @ts-expect-error I don't know why
export const getSimbridgeDir = () => path.join(getPath('documents'), 'FlyByWireSim', 'Simbridge');

//@ts-expect-error pkg only defined when running as exe
export const getExecutablePath = () => (process.pkg ? path.dirname(process.argv[0]) : process.cwd());
2 changes: 1 addition & 1 deletion apps/server/src/utilities/printer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { tmpdir, platform } from 'os';
import * as print from 'pdf-to-printer';
import * as PDFDocument from 'pdfkit';
import { createWriteStream, readFileSync } from 'fs';
import { getExecutablePath } from 'apps/server/src/utilities/pathUtil';
import { getExecutablePath, getSimbridgeDir } from 'apps/server/src/utilities/pathUtil';
import printerConfig from '../config/printer.config';

@Injectable()
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/utilities/systray.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { hideConsole, showConsole } from 'node-hide-console-window';
import open = require('open');
import SysTray, { MenuItem } from 'systray2';
import { join } from 'path';
import { getExecutablePath } from 'apps/server/src/utilities/pathUtil';
import { getExecutablePath, getSimbridgeDir } from 'apps/server/src/utilities/pathUtil';
import { NetworkService } from './network.service';
import serverConfig from '../config/server.config';
import { ShutDownService } from './shutdown.service';
Expand Down Expand Up @@ -67,7 +67,7 @@ export class SysTrayService implements OnApplicationShutdown {
tooltip: 'Open resource folder in your file explorer',
enabled: true,
click: () => {
open.openApp('explorer', { arguments: [`${getExecutablePath()}\\resources`] });
open.openApp('explorer', { arguments: [`${getSimbridgeDir()}\\resources`] });
},
};

Expand Down
21 changes: 21 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"pdf-to-printer": "5.3.0",
"pdfjs-dist": "^2.13.216",
"pdfkit": "^0.13.0",
"platform-folders": "^0.6.0",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-use-websocket": "^2.9.1",
Expand Down Expand Up @@ -203,6 +204,7 @@
"node_modules/bit-twiddle/**/*.*",
"node_modules/@flybywiresim/msfs-nodejs/**/*.*",
"node_modules/es-get-iterator/**/*.*",
"node_modules/platform-folders/build/**/*.*",
"/node_modules/systray2/traybin/*.exe",
"dist/mcdu/**/*",
"dist/assets/**/*",
Expand Down

0 comments on commit ccd1aa0

Please sign in to comment.