nativefier
Version:
Wrap web apps natively
210 lines • 10 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.prepareElectronApp = exports.normalizeAppName = void 0;
const crypto = __importStar(require("crypto"));
const fs = __importStar(require("fs-extra"));
const path = __importStar(require("path"));
const log = __importStar(require("loglevel"));
const helpers_1 = require("../helpers/helpers");
const parseUtils_1 = require("../utils/parseUtils");
const constants_1 = require("../constants");
/**
* Only picks certain app args to pass to nativefier.json
*/
function pickElectronAppArgs(options) {
var _a;
return {
accessibilityPrompt: options.nativefier.accessibilityPrompt,
alwaysOnTop: options.nativefier.alwaysOnTop,
appBundleId: options.packager.appBundleId,
appCategoryType: options.packager.appCategoryType,
appCopyright: options.packager.appCopyright,
appVersion: options.packager.appVersion,
arch: options.packager.arch,
asar: options.packager.asar,
backgroundColor: options.nativefier.backgroundColor,
basicAuthPassword: options.nativefier.basicAuthPassword,
basicAuthUsername: options.nativefier.basicAuthUsername,
blockExternalUrls: options.nativefier.blockExternalUrls,
bounce: options.nativefier.bounce,
browserwindowOptions: options.nativefier.browserwindowOptions,
buildDate: new Date().getTime(),
buildVersion: options.packager.buildVersion,
clearCache: options.nativefier.clearCache,
counter: options.nativefier.counter,
crashReporter: options.nativefier.crashReporter,
darwinDarkModeSupport: options.packager.darwinDarkModeSupport,
derefSymlinks: options.packager.derefSymlinks,
disableContextMenu: options.nativefier.disableContextMenu,
disableDevTools: options.nativefier.disableDevTools,
disableGpu: options.nativefier.disableGpu,
disableOldBuildWarning: options.nativefier.disableOldBuildWarning,
diskCacheSize: options.nativefier.diskCacheSize,
download: options.packager.download,
electronVersionUsed: options.packager.electronVersion,
enableEs3Apis: options.nativefier.enableEs3Apis,
executableName: options.packager.executableName,
fastQuit: options.nativefier.fastQuit,
fileDownloadOptions: options.nativefier.fileDownloadOptions,
flashPluginDir: options.nativefier.flashPluginDir,
fullScreen: options.nativefier.fullScreen,
globalShortcuts: options.nativefier.globalShortcuts,
height: options.nativefier.height,
helperBundleId: options.packager.helperBundleId,
hideWindowFrame: options.nativefier.hideWindowFrame,
ignoreCertificate: options.nativefier.ignoreCertificate,
ignoreGpuBlacklist: options.nativefier.ignoreGpuBlacklist,
insecure: options.nativefier.insecure,
internalUrls: options.nativefier.internalUrls,
isUpgrade: options.packager.upgrade,
junk: options.packager.junk,
lang: options.nativefier.lang,
maximize: options.nativefier.maximize,
maxHeight: options.nativefier.maxHeight,
maxWidth: options.nativefier.maxWidth,
minHeight: options.nativefier.minHeight,
minWidth: options.nativefier.minWidth,
name: (_a = options.packager.name) !== null && _a !== void 0 ? _a : constants_1.DEFAULT_APP_NAME,
nativefierVersion: options.nativefier.nativefierVersion,
osxNotarize: options.packager.osxNotarize,
osxSign: options.packager.osxSign,
portable: options.packager.portable,
processEnvs: options.nativefier.processEnvs,
protocols: options.packager.protocols,
proxyRules: options.nativefier.proxyRules,
prune: options.packager.prune,
quiet: options.packager.quiet,
showMenuBar: options.nativefier.showMenuBar,
singleInstance: options.nativefier.singleInstance,
strictInternalUrls: options.nativefier.strictInternalUrls,
targetUrl: options.packager.targetUrl,
titleBarStyle: options.nativefier.titleBarStyle,
tray: options.nativefier.tray,
usageDescription: options.packager.usageDescription,
userAgent: options.nativefier.userAgent,
userAgentHonest: options.nativefier.userAgentHonest,
versionString: options.nativefier.versionString,
width: options.nativefier.width,
widevine: options.nativefier.widevine,
win32metadata: options.packager.win32metadata,
x: options.nativefier.x,
y: options.nativefier.y,
zoom: options.nativefier.zoom,
// OLD_BUILD_WARNING_TEXT is an undocumented env. var to let *packagers*
// tweak the message shown on warning about an old build, to something
// more tailored to their audience (who might not even know Nativefier).
// See https://github.com/kelyvin/Google-Messages-For-Desktop/issues/34#issuecomment-812731144
// and https://github.com/nativefier/nativefier/issues/1131#issuecomment-812646988
oldBuildWarningText: process.env.OLD_BUILD_WARNING_TEXT || '',
};
}
async function maybeCopyScripts(srcs, dest) {
if (!srcs || srcs.length === 0) {
log.debug('No files to inject, skipping copy.');
return;
}
const supportedInjectionExtensions = ['.css', '.js'];
log.debug(`Copying ${srcs.length} files to inject in app.`);
for (const src of srcs) {
if (!fs.existsSync(src)) {
throw new Error(`File ${src} not found. Note that Nativefier expects *local* files, not URLs.`);
}
if (supportedInjectionExtensions.indexOf(path.extname(src)) < 0) {
log.warn('Skipping unsupported injection file', src);
continue;
}
const postFixHash = (0, helpers_1.generateRandomSuffix)();
const destFileName = `inject-${postFixHash}${path.extname(src)}`;
const destPath = path.join(dest, 'inject', destFileName);
log.debug(`Copying injection file "${src}" to "${destPath}"`);
await fs.copy(src, destPath);
}
}
/**
* Use a basic 6-character hash to prevent collisions. The hash is deterministic url & name,
* so that an upgrade (same URL) of an app keeps using the same appData folder.
* Warning! Changing this normalizing & hashing will change the way appNames are generated,
* changing appData folder, and users will get logged out of their apps after an upgrade.
*/
function normalizeAppName(appName, url) {
const hash = crypto.createHash('md5');
hash.update(url);
const postFixHash = hash.digest('hex').substring(0, 6);
const normalized = appName
.toLowerCase()
.replace(/[,:.]/g, '')
.replace(/[\s_]/g, '-');
return `${normalized}-nativefier-${postFixHash}`;
}
exports.normalizeAppName = normalizeAppName;
function changeAppPackageJsonName(appPath, name, url) {
const packageJsonPath = path.join(appPath, '/package.json');
const packageJson = (0, parseUtils_1.parseJson)(fs.readFileSync(packageJsonPath).toString());
if (!packageJson) {
throw new Error(`Could not load package.json from ${packageJsonPath}`);
}
const normalizedAppName = normalizeAppName(name, url);
packageJson.name = normalizedAppName;
log.debug(`Updating ${packageJsonPath} 'name' field to ${normalizedAppName}`);
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
return normalizedAppName;
}
/**
* Creates a temporary directory, copies the './app folder' inside,
* and adds a text file with the app configuration.
*/
async function prepareElectronApp(src, dest, options) {
log.debug(`Copying electron app from ${src} to ${dest}`);
try {
await fs.copy(src, dest);
}
catch (err) {
throw `Error copying electron app from ${src} to temp dir ${dest}. Error: ${err.message}`;
}
const appJsonPath = path.join(dest, '/nativefier.json');
const pickedOptions = pickElectronAppArgs(options);
log.debug(`Writing app config to ${appJsonPath}`, pickedOptions);
await fs.writeFile(appJsonPath, JSON.stringify(pickedOptions));
if (options.nativefier.bookmarksMenu) {
const bookmarksJsonPath = path.join(dest, '/bookmarks.json');
try {
await fs.copy(options.nativefier.bookmarksMenu, bookmarksJsonPath);
}
catch (err) {
log.error('Error copying bookmarks menu config file.', err);
}
}
try {
await maybeCopyScripts(options.nativefier.inject, dest);
}
catch (err) {
log.error('Error copying injection files.', err);
}
const normalizedAppName = changeAppPackageJsonName(dest, options.packager.name, options.packager.targetUrl);
options.packager.appBundleId = `com.electron.nativefier.${normalizedAppName}`;
}
exports.prepareElectronApp = prepareElectronApp;
//# sourceMappingURL=prepareElectronApp.js.map