239 lines
6.6 KiB
TypeScript
239 lines
6.6 KiB
TypeScript
import { execSync } from "child_process";
|
|
import { join as pathJoin, relative as pathRelative } from "path";
|
|
import { getThisCodebaseRootDirPath } from "../src/bin/tools/getThisCodebaseRootDirPath";
|
|
import * as fs from "fs";
|
|
import * as os from "os";
|
|
|
|
const singletonDependencies: string[] = ["react", "@types/react"];
|
|
|
|
// For example [ "@emotion" ] it's more convenient than
|
|
// having to list every sub emotion packages (@emotion/css @emotion/utils ...)
|
|
// in singletonDependencies
|
|
const namespaceSingletonDependencies: string[] = [];
|
|
|
|
const rootDirPath = getThisCodebaseRootDirPath();
|
|
|
|
const commonThirdPartyDeps = [
|
|
...namespaceSingletonDependencies
|
|
.map(namespaceModuleName =>
|
|
fs
|
|
.readdirSync(pathJoin(rootDirPath, "node_modules", namespaceModuleName))
|
|
.map(submoduleName => `${namespaceModuleName}/${submoduleName}`)
|
|
)
|
|
.reduce((prev, curr) => [...prev, ...curr], []),
|
|
...singletonDependencies
|
|
];
|
|
|
|
//NOTE: This is only required because of: https://github.com/garronej/ts-ci/blob/c0e207b9677523d4ec97fe672ddd72ccbb3c1cc4/README.md?plain=1#L54-L58
|
|
{
|
|
let modifiedPackageJsonContent = fs
|
|
.readFileSync(pathJoin(rootDirPath, "package.json"))
|
|
.toString("utf8");
|
|
|
|
modifiedPackageJsonContent = (() => {
|
|
const o = JSON.parse(modifiedPackageJsonContent);
|
|
|
|
delete o.files;
|
|
|
|
return JSON.stringify(o, null, 2);
|
|
})();
|
|
|
|
modifiedPackageJsonContent = modifiedPackageJsonContent
|
|
.replace(/"dist\//g, '"')
|
|
.replace(/"\.\/dist\//g, '"./')
|
|
.replace(/"!dist\//g, '"!')
|
|
.replace(/"!\.\/dist\//g, '"!./');
|
|
|
|
modifiedPackageJsonContent = JSON.stringify(
|
|
{ ...JSON.parse(modifiedPackageJsonContent), version: "0.0.0" },
|
|
null,
|
|
4
|
|
);
|
|
|
|
fs.writeFileSync(
|
|
pathJoin(rootDirPath, "dist", "package.json"),
|
|
Buffer.from(modifiedPackageJsonContent, "utf8")
|
|
);
|
|
}
|
|
const yarnGlobalDirPath = pathJoin(rootDirPath, ".yarn_home");
|
|
|
|
fs.rmSync(yarnGlobalDirPath, { recursive: true, force: true });
|
|
fs.mkdirSync(yarnGlobalDirPath);
|
|
|
|
const execYarnLink = (params: { targetModuleName?: string; cwd: string }) => {
|
|
const { targetModuleName, cwd } = params;
|
|
|
|
if (targetModuleName === undefined) {
|
|
const packageJsonFilePath = pathJoin(cwd, "package.json");
|
|
|
|
const packageJson = JSON.parse(
|
|
fs.readFileSync(packageJsonFilePath).toString("utf8")
|
|
);
|
|
|
|
delete packageJson["packageManager"];
|
|
|
|
fs.writeFileSync(
|
|
packageJsonFilePath,
|
|
Buffer.from(JSON.stringify(packageJson, null, 2))
|
|
);
|
|
}
|
|
|
|
const cmd = [
|
|
"yarn",
|
|
"link",
|
|
...(targetModuleName !== undefined ? [targetModuleName] : ["--no-bin-links"])
|
|
].join(" ");
|
|
|
|
console.log(`$ cd ${pathRelative(rootDirPath, cwd) || "."} && ${cmd}`);
|
|
|
|
execSync(cmd, {
|
|
cwd,
|
|
env: {
|
|
...process.env,
|
|
...(os.platform() === "win32"
|
|
? {
|
|
USERPROFILE: yarnGlobalDirPath,
|
|
LOCALAPPDATA: yarnGlobalDirPath
|
|
}
|
|
: { HOME: yarnGlobalDirPath })
|
|
}
|
|
});
|
|
};
|
|
|
|
const testAppPaths = (() => {
|
|
const [, , ...testAppNames] = process.argv;
|
|
|
|
return testAppNames
|
|
.map(testAppName => {
|
|
const testAppPath = pathJoin(rootDirPath, "..", testAppName);
|
|
|
|
if (fs.existsSync(testAppPath)) {
|
|
return testAppPath;
|
|
}
|
|
|
|
console.warn(
|
|
`Skipping ${testAppName} since it cant be found here: ${testAppPath}`
|
|
);
|
|
|
|
return undefined;
|
|
})
|
|
.filter((path): path is string => path !== undefined);
|
|
})();
|
|
|
|
if (testAppPaths.length === 0) {
|
|
console.error("No test app to link into!");
|
|
process.exit(-1);
|
|
}
|
|
|
|
testAppPaths.forEach(testAppPath => {
|
|
const packageJsonFilePath = pathJoin(testAppPath, "package.json");
|
|
|
|
const packageJsonContent = fs.readFileSync(packageJsonFilePath);
|
|
|
|
const parsedPackageJson = JSON.parse(packageJsonContent.toString("utf8")) as {
|
|
scripts?: Record<string, string>;
|
|
};
|
|
|
|
let hasPostInstallOrPrepareScript = false;
|
|
|
|
if (parsedPackageJson.scripts !== undefined) {
|
|
for (const scriptName of ["postinstall", "prepare"]) {
|
|
if (parsedPackageJson.scripts[scriptName] === undefined) {
|
|
continue;
|
|
}
|
|
|
|
hasPostInstallOrPrepareScript = true;
|
|
|
|
delete parsedPackageJson.scripts[scriptName];
|
|
}
|
|
}
|
|
|
|
if (hasPostInstallOrPrepareScript) {
|
|
fs.writeFileSync(
|
|
packageJsonFilePath,
|
|
Buffer.from(JSON.stringify(parsedPackageJson, null, 2), "utf8")
|
|
);
|
|
}
|
|
|
|
const restorePackageJson = () => {
|
|
if (!hasPostInstallOrPrepareScript) {
|
|
return;
|
|
}
|
|
|
|
fs.writeFileSync(packageJsonFilePath, packageJsonContent);
|
|
};
|
|
|
|
try {
|
|
execSync("yarn install", { cwd: testAppPath });
|
|
} catch (error) {
|
|
restorePackageJson();
|
|
|
|
throw error;
|
|
}
|
|
|
|
restorePackageJson();
|
|
});
|
|
|
|
console.log("=== Linking common dependencies ===");
|
|
|
|
const total = commonThirdPartyDeps.length;
|
|
let current = 0;
|
|
|
|
commonThirdPartyDeps.forEach(commonThirdPartyDep => {
|
|
current++;
|
|
|
|
console.log(`${current}/${total} ${commonThirdPartyDep}`);
|
|
|
|
const localInstallPath = pathJoin(
|
|
...[
|
|
rootDirPath,
|
|
"node_modules",
|
|
...(commonThirdPartyDep.startsWith("@")
|
|
? commonThirdPartyDep.split("/")
|
|
: [commonThirdPartyDep])
|
|
]
|
|
);
|
|
|
|
execYarnLink({ cwd: localInstallPath });
|
|
});
|
|
|
|
commonThirdPartyDeps.forEach(commonThirdPartyDep =>
|
|
testAppPaths.forEach(testAppPath =>
|
|
execYarnLink({
|
|
cwd: testAppPath,
|
|
targetModuleName: commonThirdPartyDep
|
|
})
|
|
)
|
|
);
|
|
|
|
console.log("=== Linking in house dependencies ===");
|
|
|
|
execYarnLink({ cwd: pathJoin(rootDirPath, "dist") });
|
|
|
|
testAppPaths.forEach(testAppPath =>
|
|
execYarnLink({
|
|
cwd: testAppPath,
|
|
targetModuleName: JSON.parse(
|
|
fs.readFileSync(pathJoin(rootDirPath, "package.json")).toString("utf8")
|
|
)["name"]
|
|
})
|
|
);
|
|
|
|
testAppPaths.forEach(testAppPath => {
|
|
const { scripts = {} } = JSON.parse(
|
|
fs.readFileSync(pathJoin(testAppPath, "package.json")).toString("utf8")
|
|
) as {
|
|
scripts?: Record<string, string>;
|
|
};
|
|
|
|
for (const scriptName of ["postinstall", "prepare"]) {
|
|
if (scripts[scriptName] === undefined) {
|
|
continue;
|
|
}
|
|
|
|
execSync(`yarn run ${scriptName}`, { cwd: testAppPath });
|
|
}
|
|
});
|
|
|
|
export {};
|