164 lines
4.6 KiB
JavaScript
164 lines
4.6 KiB
JavaScript
const path = require(`path`)
|
|
const fs = require(`fs-extra`)
|
|
|
|
const { promisifiedSpawn } = require(`../utils/promisified-spawn`)
|
|
const { registryUrl } = require(`./verdaccio-config`)
|
|
|
|
const installPackages = async ({
|
|
packagesToInstall,
|
|
yarnWorkspaceRoot,
|
|
newlyPublishedPackageVersions,
|
|
externalRegistry,
|
|
}) => {
|
|
console.log(
|
|
`Installing packages from local registry:\n${packagesToInstall
|
|
.map((packageAndVersion) => ` - ${packageAndVersion}`)
|
|
.join(`\n`)}`
|
|
)
|
|
let installCmd
|
|
if (yarnWorkspaceRoot) {
|
|
// this is very hacky - given root, we run `yarn workspaces info`
|
|
// to get list of all workspaces and their locations, and manually
|
|
// edit package.json file for packages we want to install
|
|
// to make sure there are no mismatched versions of same package
|
|
// in workspaces which should preserve node_modules structure
|
|
// (packages being mostly hoisted to top-level node_modules)
|
|
|
|
const { stdout: yarnVersion } = await promisifiedSpawn([
|
|
`yarn`,
|
|
[`--version`],
|
|
{ stdio: `pipe` },
|
|
])
|
|
const workspaceCommand = !yarnVersion.startsWith("1") ? "list" : "info"
|
|
|
|
const { stdout } = await promisifiedSpawn([
|
|
`yarn`,
|
|
[`workspaces`, workspaceCommand, `--json`],
|
|
{ stdio: `pipe` },
|
|
])
|
|
|
|
let workspacesLayout
|
|
try {
|
|
workspacesLayout = JSON.parse(JSON.parse(stdout).data)
|
|
} catch (e) {
|
|
/*
|
|
Yarn 1.22 doesn't output pure json - it has leading and trailing text:
|
|
```
|
|
$ yarn workspaces info --json
|
|
yarn workspaces v1.22.0
|
|
{
|
|
"z": {
|
|
"location": "z",
|
|
"workspaceDependencies": [],
|
|
"mismatchedWorkspaceDependencies": []
|
|
},
|
|
"y": {
|
|
"location": "y",
|
|
"workspaceDependencies": [],
|
|
"mismatchedWorkspaceDependencies": []
|
|
}
|
|
}
|
|
Done in 0.48s.
|
|
```
|
|
So we need to do some sanitization. We find JSON by matching substring
|
|
that starts with `{` and ends with `}`
|
|
*/
|
|
|
|
const regex = /^[^{]*({.*})[^}]*$/gs
|
|
const sanitizedStdOut = regex.exec(stdout)
|
|
if (sanitizedStdOut?.length >= 2) {
|
|
// pick content of first (and only) capturing group
|
|
const jsonString = sanitizedStdOut[1]
|
|
try {
|
|
workspacesLayout = JSON.parse(jsonString)
|
|
} catch (e) {
|
|
console.error(
|
|
`Failed to parse "sanitized" output of "yarn workspaces info" command.\n\nSanitized string: "${jsonString}`
|
|
)
|
|
// not exitting here, because we have general check for `workspacesLayout` being set below
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!workspacesLayout) {
|
|
console.error(
|
|
`Couldn't parse output of "yarn workspaces info" command`,
|
|
stdout
|
|
)
|
|
process.exit(1)
|
|
}
|
|
|
|
const handleDeps = (deps) => {
|
|
if (!deps) {
|
|
return false
|
|
}
|
|
|
|
let changed = false
|
|
Object.keys(deps).forEach((depName) => {
|
|
if (packagesToInstall.includes(depName)) {
|
|
deps[depName] = `medusa-dev`
|
|
changed = true
|
|
}
|
|
})
|
|
return changed
|
|
}
|
|
|
|
Object.keys(workspacesLayout).forEach((workspaceName) => {
|
|
const { location } = workspacesLayout[workspaceName]
|
|
const pkgJsonPath = path.join(yarnWorkspaceRoot, location, `package.json`)
|
|
if (!fs.existsSync(pkgJsonPath)) {
|
|
return
|
|
}
|
|
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, `utf8`))
|
|
|
|
let changed = false
|
|
changed |= handleDeps(pkg.dependencies)
|
|
changed |= handleDeps(pkg.devDependencies)
|
|
changed |= handleDeps(pkg.peerDependencies)
|
|
|
|
if (changed) {
|
|
console.log(`Changing deps in ${pkgJsonPath} to use @medusa-dev`)
|
|
fs.outputJSONSync(pkgJsonPath, pkg, {
|
|
spaces: 2,
|
|
})
|
|
}
|
|
})
|
|
|
|
// package.json files are changed - so we just want to install
|
|
// using verdaccio registry
|
|
const yarnCommands = [`install`]
|
|
|
|
if (!externalRegistry) {
|
|
yarnCommands.push(`--registry=${registryUrl}`)
|
|
}
|
|
|
|
installCmd = [`yarn`, yarnCommands]
|
|
} else {
|
|
const yarnCommands = [
|
|
`add`,
|
|
...packagesToInstall.map((packageName) => {
|
|
const packageVersion = newlyPublishedPackageVersions[packageName]
|
|
return `${packageName}@${packageVersion}`
|
|
}),
|
|
`--exact`,
|
|
]
|
|
|
|
if (!externalRegistry) {
|
|
yarnCommands.push(`--registry=${registryUrl}`)
|
|
}
|
|
|
|
installCmd = [`yarn`, yarnCommands]
|
|
}
|
|
|
|
try {
|
|
await promisifiedSpawn(installCmd)
|
|
|
|
console.log(`Installation complete`)
|
|
} catch (error) {
|
|
console.error(`Installation failed`, error)
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
exports.installPackages = installPackages
|