Last active
January 3, 2024 08:00
-
-
Save robin-hartmann/ad6ffc19091c9e661542fbf178647047 to your computer and use it in GitHub Desktop.
npm workspaces support for electron-forge
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// based on https://github.com/electron-userland/electron-forge/issues/2306#issuecomment-1034882039 | |
'use strict'; | |
/** | |
* @typedef {{ | |
* new (options: { path: string }): { | |
* loadActual(): Promise<Node> | |
* } | |
* }} Arborist | |
*/ | |
const fs = require('fs/promises'); | |
const path = require('path'); | |
/** @type {Arborist} */ | |
// @ts-ignore missing types for @npmcli/arborist | |
const arborist = require('@npmcli/arborist'); | |
const { findRoot } = require('@manypkg/find-root'); | |
/** | |
* @typedef {{ | |
* workspace: boolean; | |
* type: 'prod' | 'dev' | 'peer' | 'optional' | |
* to: Node; | |
* }} Edge | |
*/ | |
/** | |
* @typedef {{ | |
* isLink: boolean; | |
* location: string; | |
* realpath: string; | |
* target: Node; | |
* edgesOut: Map<string, Edge>; | |
* }} Node | |
*/ | |
/** @type {(node: Node) => Node} */ | |
const resolveLink = (node) => (node.isLink ? resolveLink(node.target) : node); | |
/** @type {(node: Node, realPath: string) => Node | undefined} */ | |
const getWorkspaceByPath = (node, realPath) => | |
[...node.edgesOut.values()] | |
.filter((depEdge) => depEdge.workspace) | |
.map((depEdge) => resolveLink(depEdge.to)) | |
.find((depNode) => depNode.realpath === realPath); | |
/** @type {(node: Node) => Node[]} */ | |
const collectProdDeps = (node) => | |
[...node.edgesOut.values()] | |
.filter((depEdge) => depEdge.type === 'prod') | |
.map((depEdge) => resolveLink(depEdge.to)) | |
.flatMap((depNode) => [depNode, ...collectProdDeps(depNode)]); | |
/** @type {(source: string, destination: string) => Promise<void>} */ | |
const bundle = async (source, destination) => { | |
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"); | |
} | |
const prodDeps = collectProdDeps(sourceNode); | |
for (const dep of prodDeps) { | |
const dest = path.join(destination, dep.location); | |
await fs.cp(dep.realpath, dest, { | |
recursive: true, | |
errorOnExist: false, | |
}); | |
} | |
}; | |
module.exports = { bundle }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const { bundle } = require('./bundler'); | |
module.exports = { | |
packagerConfig: { | |
prune: false, // required for the workaround below to work | |
}, | |
hooks: { | |
packageAfterCopy: async ( | |
/** @type {any} */ forgeConfig, | |
/** @type {string} */ buildPath, | |
/** @type {string} */ electronVersion, | |
/** @type {string} */ platform, | |
/** @type {string} */ arch, | |
) => { | |
// this is a workaround until we find a proper solution | |
// for running electron-forge in a mono repository | |
await bundle(__dirname, buildPath); | |
}, | |
}, | |
}; |
Thanks @robin-hartmann and @G-Ray! Was a headache for the past few days and this solution worked!
My project uses Vite and TypeScript, so if anyone is interested I rewrote the above code in TypeScript, combining @G-Ray 's code snippet in this gist.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you @robin-hartmann !
I needed to add
recursive: true
tofs.cp
.Also, in order to copy modules from workspaces I wrote: