forked from clerk/javascript
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpatch-incorrect-lockfile.mjs
144 lines (121 loc) · 3.97 KB
/
patch-incorrect-lockfile.mjs
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//@ts-check
/**
* This file adapted from Next.js' automatic SWC patching script.
* https://github.com/vercel/next.js/blob/f771c6d78783684629c143329273b348990fcbe0/packages/next/src/lib/patch-incorrect-lockfile.ts
*/
import { spawn } from 'child_process';
import { promises } from 'fs';
import path from 'path';
import lockfileParsed from '../package-lock.json' with { type: 'json' };
const registry = 'https://registry.npmjs.org/';
/**
* Run `npm install` a second time to trigger npm's lockfile formatting. This prevents an additional diff to the
* lockfile when the install is run a second time.
*/
async function formatPkgLock() {
return /** @type {Promise<void>} */ (
new Promise((resolve, reject) => {
const npm = spawn('npm', ['install', '--package-lock-only'], {
cwd: process.cwd(),
env: process.env,
stdio: 'inherit',
});
npm.on('close', code => {
if (code === 0) {
resolve();
}
reject(code);
});
})
);
}
/** @typedef {Awaited<ReturnType<typeof fetchPkgInfo>>} PkgInfo */
/**
*
* @param {string} pkg
* @param {string} version
* @returns
*/
async function fetchPkgInfo(pkg, version) {
// https://registry.npmjs.org/@rspack/binding-linux-x64-gnu
const res = await fetch(`${registry}${pkg}/${version}`);
if (!res.ok) {
throw new Error(`Failed to fetch registry info for ${pkg}, got status ${res.status}`);
}
const versionData = await res.json();
return {
version: versionData.version,
os: versionData.os,
cpu: versionData.cpu,
engines: versionData.engines,
tarball: versionData.dist.tarball,
integrity: versionData.dist.integrity,
};
}
/**
* Attempts to patch npm package-lock.json when it
* fails to include optionalDependencies for other platforms
* this can occur when the package-lock is rebuilt from a current
* node_modules install instead of pulling fresh package data
*/
async function patchIncorrectLockfile() {
const expectedRspackPkgs = Object.entries(
lockfileParsed['packages']['node_modules/@rspack/binding']['optionalDependencies'] || {},
).filter(([pkg]) => pkg.startsWith('@rspack/binding-'));
/**
*
* @param {string} pkg
* @param {PkgInfo} pkgData
*/
const patchPackage = (pkg, pkgData) => {
lockfileParsed.packages[pkg] = {
version: pkgData.version,
resolved: pkgData.tarball,
integrity: pkgData.integrity,
cpu: pkgData.cpu,
optional: true,
os: pkgData.os,
engines: pkgData.engines,
};
};
try {
/** @type {[string, string][]} */
const missingRspackPkgs = [];
/** @type {string|undefined} */
let pkgPrefix;
pkgPrefix = '';
for (const pkg of Object.keys(lockfileParsed.packages)) {
if (pkg.endsWith('node_modules/@rspack/core')) {
pkgPrefix = pkg.substring(0, pkg.length - 12);
}
}
if (!pkgPrefix) {
// unable to locate the next package so bail
return;
}
for (const pkg of expectedRspackPkgs) {
if (!lockfileParsed.packages[`${pkgPrefix}${pkg[0]}`]) {
missingRspackPkgs.push(pkg);
}
}
if (missingRspackPkgs.length === 0) {
return;
}
console.warn(`Found lockfile missing swc dependencies,`, 'patching...');
const pkgsData = await Promise.all(missingRspackPkgs.map(([pkg, version]) => fetchPkgInfo(pkg, version)));
for (let i = 0; i < pkgsData.length; i++) {
const pkg = missingRspackPkgs[i][0];
const pkgData = pkgsData[i];
patchPackage(`${pkgPrefix}${pkg}`, pkgData);
}
await promises.writeFile(path.join(process.cwd(), 'package-lock.json'), JSON.stringify(lockfileParsed, null, 2));
console.warn(
'Lockfile was successfully patched, please run "npm install" to ensure Rspack dependencies are downloaded',
);
await formatPkgLock();
} catch (err) {
console.error(`Failed to patch lockfile, please try uninstalling and reinstalling next in this workspace`);
console.error(err);
}
}
await patchIncorrectLockfile();