2018-04-04 18:28:03 +08:00
|
|
|
"use strict";
|
|
|
|
|
|
|
|
const fs = require("fs");
|
|
|
|
const path = require("path");
|
2025-07-02 20:10:54 +08:00
|
|
|
|
2018-04-04 18:28:03 +08:00
|
|
|
const root = process.cwd();
|
2024-07-31 09:37:24 +08:00
|
|
|
const nodeModulesFolder = path.resolve(root, "node_modules");
|
2018-04-04 18:28:03 +08:00
|
|
|
const webpackDependencyFolder = path.resolve(root, "node_modules/webpack");
|
|
|
|
|
2025-03-12 09:56:14 +08:00
|
|
|
/**
|
|
|
|
* @returns {Promise<void>} result
|
|
|
|
*/
|
2018-04-04 18:28:03 +08:00
|
|
|
function setup() {
|
2025-07-02 20:10:54 +08:00
|
|
|
return checkSymlinkExistsAsync()
|
2025-07-17 00:13:14 +08:00
|
|
|
.then(async (hasSymlink) => {
|
2018-04-04 18:28:03 +08:00
|
|
|
if (!hasSymlink) {
|
2021-02-22 20:34:42 +08:00
|
|
|
await ensureYarnInstalledAsync();
|
|
|
|
await runSetupSymlinkAsync();
|
|
|
|
if (!(await checkSymlinkExistsAsync())) {
|
|
|
|
throw new Error("windows symlink was not successfully created");
|
|
|
|
}
|
2018-04-04 18:28:03 +08:00
|
|
|
}
|
|
|
|
})
|
2019-11-21 21:29:14 +08:00
|
|
|
.then(() => {
|
2018-04-04 18:28:03 +08:00
|
|
|
process.exitCode = 0;
|
|
|
|
})
|
2025-07-17 00:13:14 +08:00
|
|
|
.catch((err) => {
|
2024-07-31 15:37:05 +08:00
|
|
|
console.error(err);
|
2018-04-04 18:28:03 +08:00
|
|
|
process.exitCode = 1;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2025-03-12 09:56:14 +08:00
|
|
|
/**
|
|
|
|
* @returns {Promise<void>} result
|
|
|
|
*/
|
2021-02-22 20:34:42 +08:00
|
|
|
async function runSetupSymlinkAsync() {
|
|
|
|
await exec("yarn", ["install"], "Install dependencies");
|
|
|
|
await exec("yarn", ["link"], "Create webpack symlink");
|
|
|
|
await exec("yarn", ["link", "webpack"], "Link webpack into itself");
|
|
|
|
}
|
|
|
|
|
2025-03-12 09:56:14 +08:00
|
|
|
/**
|
|
|
|
* @returns {Promise<boolean>} result
|
|
|
|
*/
|
2018-04-04 18:28:03 +08:00
|
|
|
function checkSymlinkExistsAsync() {
|
2025-07-17 00:13:14 +08:00
|
|
|
return new Promise((resolve) => {
|
2018-04-04 18:28:03 +08:00
|
|
|
if (
|
2024-07-31 09:37:24 +08:00
|
|
|
fs.existsSync(nodeModulesFolder) &&
|
2018-04-04 18:28:03 +08:00
|
|
|
fs.existsSync(webpackDependencyFolder) &&
|
|
|
|
fs.lstatSync(webpackDependencyFolder).isSymbolicLink()
|
|
|
|
) {
|
|
|
|
resolve(true);
|
|
|
|
} else {
|
|
|
|
resolve(false);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2025-03-12 09:56:14 +08:00
|
|
|
/**
|
|
|
|
* @returns {Promise<void>} result
|
|
|
|
*/
|
2021-02-22 20:34:42 +08:00
|
|
|
async function ensureYarnInstalledAsync() {
|
2021-05-11 15:31:46 +08:00
|
|
|
const semverPattern =
|
|
|
|
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/;
|
2021-02-22 20:34:42 +08:00
|
|
|
let hasYarn = false;
|
|
|
|
try {
|
|
|
|
const stdout = await execGetOutput("yarn", ["-v"], "Check yarn version");
|
|
|
|
hasYarn = semverPattern.test(stdout);
|
2024-07-31 15:37:05 +08:00
|
|
|
} catch (_err) {
|
2021-02-22 20:34:42 +08:00
|
|
|
hasYarn = false;
|
|
|
|
}
|
|
|
|
if (!hasYarn) await installYarnAsync();
|
2018-04-04 18:28:03 +08:00
|
|
|
}
|
|
|
|
|
2025-03-12 09:56:14 +08:00
|
|
|
/**
|
|
|
|
* @returns {Promise<void>} result
|
|
|
|
*/
|
2018-04-04 18:28:03 +08:00
|
|
|
function installYarnAsync() {
|
|
|
|
return exec("npm", ["install", "-g", "yarn"], "Install yarn");
|
|
|
|
}
|
|
|
|
|
2025-03-12 09:56:14 +08:00
|
|
|
/**
|
|
|
|
* @param {string} command command
|
|
|
|
* @param {string[]} args args
|
|
|
|
* @param {string} description description
|
|
|
|
* @returns {Promise<void>} result
|
|
|
|
*/
|
2018-04-04 18:28:03 +08:00
|
|
|
function exec(command, args, description) {
|
|
|
|
console.log(`Setup: ${description}`);
|
|
|
|
return new Promise((resolve, reject) => {
|
2024-07-31 04:09:42 +08:00
|
|
|
const cp = require("child_process").spawn(command, args, {
|
2018-04-04 18:28:03 +08:00
|
|
|
cwd: root,
|
|
|
|
stdio: "inherit",
|
|
|
|
shell: true
|
|
|
|
});
|
2025-07-02 20:10:54 +08:00
|
|
|
|
2025-07-17 00:13:14 +08:00
|
|
|
cp.on("error", (error) => {
|
2018-04-04 18:28:03 +08:00
|
|
|
reject(new Error(`${description} failed with ${error}`));
|
|
|
|
});
|
2025-07-17 00:13:14 +08:00
|
|
|
cp.on("exit", (exitCode) => {
|
2018-04-04 18:28:03 +08:00
|
|
|
if (exitCode) {
|
2025-07-02 20:10:54 +08:00
|
|
|
reject(new Error(`${description} failed with exit code ${exitCode}`));
|
2018-04-04 18:28:03 +08:00
|
|
|
} else {
|
|
|
|
resolve();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2025-03-12 09:56:14 +08:00
|
|
|
/**
|
|
|
|
* @param {string} command command
|
|
|
|
* @param {string[]} args args
|
|
|
|
* @param {string} description description
|
|
|
|
* @returns {Promise<string>} result
|
|
|
|
*/
|
2018-04-04 18:28:03 +08:00
|
|
|
function execGetOutput(command, args, description) {
|
|
|
|
console.log(`Setup: ${description}`);
|
|
|
|
return new Promise((resolve, reject) => {
|
2024-07-31 04:09:42 +08:00
|
|
|
const cp = require("child_process").spawn(command, args, {
|
2018-04-04 18:28:03 +08:00
|
|
|
cwd: root,
|
|
|
|
stdio: [process.stdin, "pipe", process.stderr],
|
|
|
|
shell: true
|
|
|
|
});
|
2025-07-02 20:10:54 +08:00
|
|
|
|
2025-07-17 00:13:14 +08:00
|
|
|
cp.on("error", (error) => {
|
2018-04-04 18:28:03 +08:00
|
|
|
reject(new Error(`${description} failed with ${error}`));
|
|
|
|
});
|
2025-07-17 00:13:14 +08:00
|
|
|
cp.on("exit", (exitCode) => {
|
2018-04-04 18:28:03 +08:00
|
|
|
if (exitCode) {
|
2025-07-02 20:10:54 +08:00
|
|
|
reject(new Error(`${description} failed with exit code ${exitCode}`));
|
2018-04-04 18:28:03 +08:00
|
|
|
} else {
|
2025-07-02 20:10:54 +08:00
|
|
|
resolve(Buffer.concat(buffers).toString("utf8").trim());
|
2018-04-04 18:28:03 +08:00
|
|
|
}
|
|
|
|
});
|
2025-03-12 09:56:14 +08:00
|
|
|
/** @type {Buffer[]} */
|
2018-04-04 18:28:03 +08:00
|
|
|
const buffers = [];
|
2025-07-17 00:13:14 +08:00
|
|
|
cp.stdout.on("data", (data) => buffers.push(data));
|
2018-04-04 18:28:03 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
setup();
|