From 852c3b0eaed48265354046d068f0cfa565827e7c Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Thu, 27 Jan 2022 16:49:11 +0100 Subject: refactor: Extract resource path management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lets us access absolute paths and URLs without directly calling node APIs. Signed-off-by: Kristóf Marussy --- .../main/src/infrastructure/resources/Resources.ts | 27 +++++ .../impl/__tests__/getDistResources.spec.ts | 112 +++++++++++++++++++++ .../resources/impl/getDistResources.ts | 59 +++++++++++ 3 files changed, 198 insertions(+) create mode 100644 packages/main/src/infrastructure/resources/Resources.ts create mode 100644 packages/main/src/infrastructure/resources/impl/__tests__/getDistResources.spec.ts create mode 100644 packages/main/src/infrastructure/resources/impl/getDistResources.ts (limited to 'packages/main/src/infrastructure/resources') diff --git a/packages/main/src/infrastructure/resources/Resources.ts b/packages/main/src/infrastructure/resources/Resources.ts new file mode 100644 index 0000000..269c838 --- /dev/null +++ b/packages/main/src/infrastructure/resources/Resources.ts @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2022 Kristóf Marussy + * + * This file is part of Sophie. + * + * Sophie is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export default interface Resources { + getPath(packageName: string, relativePathInPackage: string): string; + + getFileURL(packageName: string, relativePathInPackage: string): string; + + getRendererURL(relativePathInRendererPackage: string): string; +} diff --git a/packages/main/src/infrastructure/resources/impl/__tests__/getDistResources.spec.ts b/packages/main/src/infrastructure/resources/impl/__tests__/getDistResources.spec.ts new file mode 100644 index 0000000..d045e54 --- /dev/null +++ b/packages/main/src/infrastructure/resources/impl/__tests__/getDistResources.spec.ts @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2022 Kristóf Marussy + * + * This file is part of Sophie. + * + * Sophie is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import os from 'node:os'; + +import eachModule from 'jest-each'; + +import Resources from '../../Resources'; +import getDistResources from '../getDistResources'; + +// Workaround for jest ESM loader incorrectly wrapping the import in another layer of `default`. +const each = + (eachModule as Partial).default ?? eachModule; + +const defaultDevServerURL = 'http://localhost:3000/'; + +const [ + thisDir, + preloadIndexPath, + preloadIndexFileURL, + rendererIndexFileURL, + rendererRootFileURL, +] = + os.platform() === 'win32' + ? [ + 'C:\\Program Files\\sophie\\resources\\app.asar\\main\\dist', + 'C:\\Program Files\\sophie\\resources\\app.asar\\preload\\dist\\index.cjs', + 'file:///C:/Program Files/sophie/resources/app.asar/preload/dist/index.cjs', + 'file:///C:/Program Files/sophie/resources/app.asar/renderer/dist/index.html', + 'file:///C:/Program Files/sophie/resources/app.asar/renderer/dist/', + ] + : [ + '/opt/sophie/resources/app.asar/main/dist', + '/opt/sophie/resources/app.asar/preload/dist/index.cjs', + 'file:///opt/sophie/resources/app.asar/preload/dist/index.cjs', + 'file:///opt/sophie/resources/app.asar/renderer/dist/index.html', + 'file:///opt/sophie/resources/app.asar/renderer/dist/', + ]; + +const fileURLs: [string, string] = [rendererIndexFileURL, rendererRootFileURL]; + +each([ + ['not in dev mode', false, undefined, ...fileURLs], + [ + 'not in dev mode with VITE_DEV_SERVER_URL set', + false, + defaultDevServerURL, + ...fileURLs, + ], + ['in dev mode with no VITE_DEV_SERVER_URL', true, undefined, ...fileURLs], + [ + 'in dev mode with VITE_DEV_SERVER_URL set', + true, + defaultDevServerURL, + `${defaultDevServerURL}index.html`, + defaultDevServerURL, + ], +]).describe( + 'when %s', + ( + _description: string, + devMode: boolean, + devServerURL: string, + rendererIndexURL: string, + rendererRootURL: string, + ) => { + let resources: Resources; + + beforeEach(() => { + resources = getDistResources(devMode, thisDir, devServerURL); + }); + + it('getPath should return the path to the requested resource', () => { + const path = resources.getPath('preload', 'index.cjs'); + expect(path).toBe(preloadIndexPath); + }); + + it('getFileURL should return the file URL to the requested resource', () => { + const url = resources.getFileURL('preload', 'index.cjs'); + expect(url).toBe(preloadIndexFileURL); + }); + + describe('getRendererURL', () => { + it('should return the URL to the requested resource', () => { + const url = resources.getRendererURL('index.html'); + expect(url).toBe(rendererIndexURL); + }); + + it('should return the root URL', () => { + const url = resources.getRendererURL('/'); + expect(url).toBe(rendererRootURL); + }); + }); + }, +); diff --git a/packages/main/src/infrastructure/resources/impl/getDistResources.ts b/packages/main/src/infrastructure/resources/impl/getDistResources.ts new file mode 100644 index 0000000..f3c3f7b --- /dev/null +++ b/packages/main/src/infrastructure/resources/impl/getDistResources.ts @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2022 Kristóf Marussy + * + * This file is part of Sophie. + * + * Sophie is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import path from 'node:path'; +import { pathToFileURL, URL } from 'node:url'; + +import Resources from '../Resources'; + +export default function getDistResources( + devMode: boolean, + /* + eslint-disable-next-line unicorn/prefer-module -- + Electron apps run in a commonjs environment, so there is no `import.meta.url`. + */ + thisDir = __dirname, + devServerURL = import.meta.env?.VITE_DEV_SERVER_URL, +): Resources { + const packagesRoot = path.join(thisDir, '..', '..'); + + function getPath(packageName: string, relativePathInPackage: string): string { + return path.join(packagesRoot, packageName, 'dist', relativePathInPackage); + } + + function getFileURL( + packageName: string, + relativePathInPackage: string, + ): string { + const absolutePath = getPath(packageName, relativePathInPackage); + return pathToFileURL(absolutePath).toString(); + } + + return { + getPath, + getFileURL, + getRendererURL: + devMode && devServerURL !== undefined + ? (relativePathInRendererPackage) => + new URL(relativePathInRendererPackage, devServerURL).toString() + : (relativePathInRendererPackage) => + getFileURL('renderer', relativePathInRendererPackage), + }; +} -- cgit v1.2.3-70-g09d2