Skip to content

Instantly share code, notes, and snippets.

@gjtiquia
Forked from robin-hartmann/bundler.js
Last active January 6, 2024 15:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gjtiquia/c8c9981992acf5661ff71ea4f471bdc9 to your computer and use it in GitHub Desktop.
Save gjtiquia/c8c9981992acf5661ff71ea4f471bdc9 to your computer and use it in GitHub Desktop.
npm workspaces support for electron-forge
// from: https://gist.github.com/robin-hartmann/ad6ffc19091c9e661542fbf178647047
// issue: https://github.com/electron/forge/issues/2306
// A bundler for locating local packages from workspaces, because Electron Forge does not support NPM workspaces out of the box
const fs = require('fs/promises');
const path = require('path');
const { findRoot } = require('@manypkg/find-root');
const arborist = require('@npmcli/arborist');
interface Edge {
workspace: boolean,
type: 'prod' | 'dev' | 'peer' | 'optional',
to: Node
}
interface Node {
isLink: boolean,
isWorkspace: boolean,
packageName: string
location: string,
realpath: string,
target: Node,
edgesOut: Map<string, Edge>,
}
const resolveLink = (node: Node): Node => {
return node.isLink ? resolveLink(node.target) : node;
}
const getWorkspaceByPath = (node: Node, realPath: string): Node | undefined => {
return [...node.edgesOut.values()]
.filter((depEdge) => depEdge.workspace)
.map((depEdge) => resolveLink(depEdge.to))
.find((depNode) => depNode.realpath === realPath);
}
const collectProdDeps = (node: Node): Node[] => {
return [...node.edgesOut.values()]
.filter((depEdge) => depEdge.type === 'prod')
.map((depEdge) => resolveLink(depEdge.to))
.flatMap((depNode) => [depNode, ...collectProdDeps(depNode)]);
}
export const bundle = async (source: string, destination: string): Promise<void> => {
const root = await findRoot(source);
const rootNode = await new arborist({ path: root.rootDir }).loadActual();
const sourceNode = getWorkspaceByPath(rootNode, source);
if (!sourceNode) {
throw new Error(`Couldn't find source node. [Debug Info] source: ${source} `);
}
const prodDeps = collectProdDeps(sourceNode);
for (const dep of prodDeps) {
const dest = dep.isWorkspace
? path.join(destination, "node_modules", dep.packageName)
: path.join(destination, dep.location)
await fs.cp(dep.realpath, dest, {
recursive: true,
errorOnExist: false,
dereference: true,
})
}
};
'use strict';
const { bundle } = require('./bundler');
module.exports = {
packagerConfig: {
prune: false, // required for the workaround below to work
},
hooks: {
packageAfterCopy: async (
forgeConfig: any,
buildPath: string,
electronVersion: string,
platform: string,
arch: string,
) => {
// this is a workaround until we find a proper solution
// for running electron-forge in a mono repository
await bundle(__dirname, buildPath);
},
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment