-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbundler.js
100 lines (83 loc) · 2.66 KB
/
bundler.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// 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;
* name: string;
* version: string;
* 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 = dep.location.startsWith('packages')
? path.join(destination, 'node_modules', '@microflow', dep.name)
: path.join(destination, 'node_modules', dep.name);
if (dep.name.startsWith('@types')) {
// console.debug(`IGNORE ${dep.name}`);
continue;
}
// console.log(dep.name, `${dep.location} --> ${dest}`);
await fs.cp(dep.realpath, dest, {
recursive: true,
errorOnExist: false,
dereference: true,
filter: source => {
// console.log('>> copying', source);
return true;
},
});
// if (dest.includes('@serialport/bindings-cpp')) {
// // Check if folder exists
// const folder = path.join(dest, 'build', 'node_gyp_bins');
// const exists = await fs.readdir(folder).catch(() => false);
// console.log('!!!! patching serialport', dest, exists);
// }
}
};
module.exports = { bundle };