Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
export const createCompileHook = (originalDir: string) => async (_: any, buildPath: string) => {
await asyncOra('Compiling Application', async () => {
// eslint-disable-next-line import/no-dynamic-require, global-require
const compileCLI = require(path.resolve(originalDir, 'node_modules/electron-compile/lib/cli.js'));
async function compileAndShim(appDir: string) {
for (const entry of await fs.readdir(appDir)) {
if (!entry.match(/^(node_modules|bower_components)$/)) {
const fullPath = path.join(appDir, entry);
if ((await fs.stat(fullPath)).isDirectory()) {
const { log } = console;
console.log = () => {};
await compileCLI.main(appDir, [fullPath]);
console.log = log;
}
}
}
export default async ({
dir = process.cwd(),
interactive = false,
confirmImport,
shouldContinueOnExisting,
shouldRemoveDependency,
shouldUpdateScript,
outDir,
}: ImportOptions) => {
const calculatedOutDir = outDir || 'out';
asyncOra.interactive = interactive;
d(`Attempting to import project in: ${dir}`);
if (!await fs.pathExists(dir) || !await fs.pathExists(path.resolve(dir, 'package.json'))) {
throw new Error(`We couldn't find a project in: ${dir}`);
}
// eslint-disable-next-line max-len
if (typeof confirmImport === 'function') {
if (!await confirmImport()) {
process.exit(0);
}
}
await initGit(dir);
const importDeps = ([] as string[]).concat(deps);
if (!auth.appPassword || !auth.username) {
throw new Error('In order to publish to Bitbucket provide credentials, either through "auth.appPassword" and "auth.username" properties in your Forge config or using BITBUCKET_APP_PASSWORD and BITBUCKET_USERNAME environment variables');
}
for (const [index, makeResult] of makeResults.entries()) {
const data = new FormData();
for (const artifactPath of makeResult.artifacts) {
data.append('files', fs.createReadStream(artifactPath));
}
// If we are not supposed to override an existing version, we'll check check if any of
// the files exist first
if (!replaceExistingFiles) {
await asyncOra('Checking if artifacts have been published previously', async () => {
for (const artifactPath of makeResult.artifacts) {
const fileName = path.basename(artifactPath);
const response = await fetch(`${apiUrl}/${fileName}`, {
headers: {
Authorization: `Basic ${encodedUserAndPass}`,
},
method: 'HEAD',
// We set redirect to 'manual' so that we get the 302 redirects if the file
// already exists
redirect: 'manual',
});
if (response.status === 302) {
throw new Error(`Unable to publish "${fileName}" as it has been published previously. Use the "replaceExistingFiles" property in your Forge config to override this.`);
}
export default async ({
interactive = false,
prerelease = false,
repo,
chooseAsset,
}: InstallOptions) => {
asyncOra.interactive = interactive;
if (typeof chooseAsset !== 'function') {
throw new Error('Expected chooseAsset to be a function in install call');
}
let latestRelease!: Release;
let possibleAssets: Asset[] = [];
await asyncOra('Searching for Application', async (searchSpinner) => {
if (!repo || !repo.includes('/')) {
throw new Error('Invalid repository name, must be in the format owner/name');
}
d('searching for repo:', repo);
let releases!: Release[];
try {
releases = await (await fetch(`${GITHUB_API}/repos/${repo}/releases`)).json();
} catch (err) {
// Ignore error
}
if (!releases || (releases as any).message === 'Not Found' || !Array.isArray(releases)) {
throw new Error(`Failed to find releases for repository "${repo}". Please check the name and try again.`);
}
asyncOra.interactive = interactive;
d(`Initializing in: ${dir}`);
await initDirectory(dir, force);
await initGit(dir);
const templateModule = await findTemplate(dir, template);
if (typeof templateModule.initializeTemplate === 'function') {
await templateModule.initializeTemplate(dir, { copyCIFiles });
const packageJSON = await readRawPackageJson(dir);
setInitialForgeConfig(packageJSON);
await fs.writeJson(path.join(dir, 'package.json'), packageJSON, { spaces: 2 });
}
await asyncOra('Installing Template Dependencies', async () => {
d('installing dependencies');
await installDepList(dir, templateModule.dependencies || []);
d('installing devDependencies');
await installDepList(dir, templateModule.devDependencies || [], DepType.DEV);
});
await initNPM(dir);
};
export default async ({
dir = process.cwd(),
interactive = false,
copyCIFiles = false,
force = false,
template = 'base',
}: InitOptions) => {
asyncOra.interactive = interactive;
d(`Initializing in: ${dir}`);
await initDirectory(dir, force);
await initGit(dir);
const templateModule = await findTemplate(dir, template);
if (typeof templateModule.initializeTemplate === 'function') {
await templateModule.initializeTemplate(dir, { copyCIFiles });
const packageJSON = await readRawPackageJson(dir);
setInitialForgeConfig(packageJSON);
await fs.writeJson(path.join(dir, 'package.json'), packageJSON, { spaces: 2 });
}
await asyncOra('Installing Template Dependencies', async () => {
d('installing dependencies');
await updatePackageScript('start', 'electron-forge start');
await updatePackageScript('package', 'electron-forge package');
await updatePackageScript('make', 'electron-forge make');
d('forgified scripts object:', packageJSON.scripts);
const writeChanges = async () => {
await asyncOra('Writing modified package.json file', async () => {
await fs.writeJson(path.resolve(dir, 'package.json'), packageJSON, { spaces: 2 });
});
};
await writeChanges();
await asyncOra('Installing dependencies', async () => {
d('deleting old dependencies forcefully');
await fs.remove(path.resolve(dir, 'node_modules/.bin/electron'));
await fs.remove(path.resolve(dir, 'node_modules/.bin/electron.cmd'));
d('installing dependencies');
await installDepList(dir, importDeps);
d('installing devDependencies');
await installDepList(dir, importDevDeps, DepType.DEV);
d('installing exactDevDependencies');
await installDepList(dir, importExactDevDeps, DepType.DEV, DepVersionRestriction.EXACT);
});
packageJSON = await readRawPackageJson(dir);
mainConfig: './webpack.main.config.js',
renderer: {
config: './webpack.renderer.config.js',
entryPoints: [{
html: './src/index.html',
js: './src/renderer.js',
name: 'main_window',
}],
},
},
]);
await fs.writeJson(pjPath, currentPJ, {
spaces: 2,
});
});
await asyncOra('Setting up webpack configuration', async () => {
await this.copyTemplateFile(directory, 'webpack.main.config.js');
await this.copyTemplateFile(directory, 'webpack.renderer.config.js');
await this.copyTemplateFile(directory, 'webpack.rules.js');
await this.copyTemplateFile(path.join(directory, 'src'), 'renderer.js');
await this.updateFileByLine(path.resolve(directory, 'src', 'index.js'), (line) => {
if (line.includes('mainWindow.loadFile')) return ' mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);';
return line;
}, path.resolve(directory, 'src', 'main.js'));
await this.updateFileByLine(path.resolve(directory, 'src', 'index.html'), (line) => {
if (line.includes('link rel="stylesheet"')) return '';
return line;
});
});
}
const s3Client = new S3({
accessKeyId: config.accessKeyId || process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: config.secretAccessKey || process.env.AWS_SECRET_ACCESS_KEY,
});
if (!s3Client.config.credentials || !config.bucket) {
throw new Error('In order to publish to s3 you must set the "s3.accessKeyId", "process.env.ELECTRON_FORGE_S3_SECRET_ACCESS_KEY" and "s3.bucket" properties in your Forge config. See the docs for more info');
}
d('creating s3 client with options:', config);
let uploaded = 0;
const spinnerText = () => `Uploading Artifacts ${uploaded}/${artifacts.length}`;
await asyncOra(spinnerText(), async (uploadSpinner) => {
await Promise.all(artifacts.map(async (artifact) => {
const uploader = s3Client.upload({
Body: fs.createReadStream(artifact.path),
Bucket: config.bucket,
Key: this.keyForArtifact(artifact),
ACL: config.public ? 'public-read' : 'private',
} as S3.PutObjectRequest);
d('uploading:', artifact.path);
uploader.on('httpUploadProgress', (progress) => {
const p = `${Math.round((progress.loaded / progress.total) * 100)}%`;
d(`Upload Progress (${path.basename(artifact.path)}) ${p}`);
});
await uploader.promise();
uploaded += 1;
}) as NodeJS.ProcessEnv,
};
if (runAsNode) {
spawnOpts.env.ELECTRON_RUN_AS_NODE = 'true';
} else {
delete spawnOpts.env.ELECTRON_RUN_AS_NODE;
}
if (inspect) {
args = ['--inspect' as (string|number)].concat(args);
}
let spawned!: ElectronProcess;
await asyncOra('Launching Application', async () => {
spawned = spawn(
electronExecPath!,
prefixArgs.concat([appPath]).concat(args as string[]),
spawnOpts as SpawnOptions,
) as ElectronProcess;
});
await runHook(forgeConfig, 'postStart', spawned);
return spawned;
};