make medusa-dev-cli compatible with yarn 2/3 (#1765)

This commit is contained in:
Zakaria El Asri
2022-07-03 10:24:41 +01:00
committed by GitHub
parent 3fb74bf512
commit 8fe5fb5503
11 changed files with 464 additions and 378 deletions

View File

@@ -1,5 +1,15 @@
const { getDependantPackages } = require(`../get-dependant-packages`)
function createMockPackageNameToPath(packageNames) {
const packageNameToPath = new Map()
for (const packageName of packageNames) {
packageNameToPath.set(packageName, `/test/${packageName}`)
}
return packageNameToPath
}
describe(`getDependantPackages`, () => {
it(`handles deep dependency chains`, () => {
const packagesToPublish = getDependantPackages({
@@ -9,6 +19,13 @@ describe(`getDependantPackages`, () => {
"package-a-dep1-dep1": new Set([`package-a-dep1`]),
"not-related": new Set([`also-not-related`]),
},
packageNameToPath: createMockPackageNameToPath([
`package-a`,
`package-a-dep1`,
`package-a-dep1-dep1`,
`not-related`,
`also-not-related`,
]),
})
expect(packagesToPublish).toEqual(
@@ -23,6 +40,10 @@ describe(`getDependantPackages`, () => {
"package-a": new Set([`package-b`]),
"package-b": new Set([`package-a`]),
},
packageNameToPath: createMockPackageNameToPath([
`package-a`,
`package-b`,
]),
})
expect(packagesToPublish).toEqual(new Set([`package-a`, `package-b`]))
})

View File

@@ -43,15 +43,25 @@ jest.doMock(
describe(`traversePackageDeps`, () => {
it(`handles deep dependency chains`, () => {
const monoRepoPackages = [
`package-a`,
`package-a-dep1`,
`package-a-dep1-dep1`,
`package-not-used`,
]
const packageNameToPath = new Map()
for (const packageName of monoRepoPackages) {
packageNameToPath.set(
packageName,
path.join(...`<monorepo-path>/packages/${packageName}`.split(`/`))
)
}
const { seenPackages, depTree } = traversePackagesDeps({
root: `<monorepo-path>`,
packages: [`package-a`, `doesnt-exist`],
monoRepoPackages: [
`package-a`,
`package-a-dep1`,
`package-a-dep1-dep1`,
`package-not-used`,
],
monoRepoPackages,
packageNameToPath,
})
expect(seenPackages).toEqual([

View File

@@ -1,9 +1,9 @@
const fs = require(`fs-extra`);
const _ = require(`lodash`);
const fs = require(`fs-extra`)
const _ = require(`lodash`)
const {
getMonorepoPackageJsonPath,
} = require(`./get-monorepo-package-json-path`);
const got = require(`got`);
} = require(`./get-monorepo-package-json-path`)
const got = require(`got`)
function difference(object, base) {
function changes(object, base) {
@@ -12,11 +12,11 @@ function difference(object, base) {
result[key] =
_.isObject(value) && _.isObject(base[key])
? changes(value, base[key])
: value;
: value
}
});
})
}
return changes(object, base);
return changes(object, base)
}
/**
@@ -24,33 +24,33 @@ function difference(object, base) {
* It will skip dependencies that are removed in monorepo package.
*
* If local package is not installed, it will check unpkg.com.
* This allow medusa-dev to skip publishing unnecesairly and
* This allow gatsby-dev to skip publishing unnecesairly and
* let install packages from public npm repository if nothing changed.
*/
exports.checkDepsChanges = async ({
newPath,
packageName,
monoRepoPackages,
root,
isInitialScan,
ignoredPackageJSON,
packageNameToPath,
}) => {
let localPKGjson;
let packageNotInstalled = false;
let localPKGjson
let packageNotInstalled = false
try {
localPKGjson = JSON.parse(fs.readFileSync(newPath, `utf-8`));
localPKGjson = JSON.parse(fs.readFileSync(newPath, `utf-8`))
} catch {
packageNotInstalled = true;
packageNotInstalled = true
// there is no local package - so we still need to install deps
// this is nice because devs won't need to do initial package installation - we can handle this.
if (!isInitialScan) {
console.log(
`'${packageName}' doesn't seem to be installed. Restart medusa-dev to publish it`
);
`'${packageName}' doesn't seem to be installed. Restart gatsby-dev to publish it`
)
return {
didDepsChanged: false,
packageNotInstalled,
};
}
}
// if package is not installed, we will do http GET request to
@@ -60,37 +60,33 @@ exports.checkDepsChanges = async ({
// this allow us to not publish to local repository
// and save some time/work
try {
const response = await got(
`https://unpkg.com/${packageName}/package.json`
);
const version = getPackageVersion(packageName)
const url = `https://unpkg.com/${packageName}@${version}/package.json`
const response = await got(url)
if (response?.statusCode !== 200) {
throw new Error(`No response or non 200 code`);
throw new Error(`No response or non 200 code for ${url}`)
}
localPKGjson = JSON.parse(response.body);
} catch {
localPKGjson = JSON.parse(response.body)
} catch (e) {
console.log(
`'${packageName}' doesn't seem to be installed and is not published on NPM.`
);
`'${packageName}' doesn't seem to be installed and is not published on NPM. Error: ${e.message}`
)
return {
didDepsChanged: true,
packageNotInstalled,
};
}
}
}
const monoDir = packageName.startsWith("@medusajs")
? packageName.split("/")[1]
: packageName;
const monoRepoPackageJsonPath = getMonorepoPackageJsonPath({
packageName: monoDir,
root,
});
packageName,
packageNameToPath,
})
const monorepoPKGjsonString = fs.readFileSync(
monoRepoPackageJsonPath,
`utf-8`
);
const monorepoPKGjson = JSON.parse(monorepoPKGjsonString);
)
const monorepoPKGjson = JSON.parse(monorepoPKGjsonString)
if (ignoredPackageJSON.has(packageName)) {
if (ignoredPackageJSON.get(packageName).includes(monorepoPKGjsonString)) {
// we are in middle of publishing and content of package.json is one set during publish process,
@@ -98,44 +94,44 @@ exports.checkDepsChanges = async ({
return {
didDepsChanged: false,
packageNotInstalled,
};
}
}
}
if (!monorepoPKGjson.dependencies) monorepoPKGjson.dependencies = {};
if (!localPKGjson.dependencies) localPKGjson.dependencies = {};
if (!monorepoPKGjson.dependencies) monorepoPKGjson.dependencies = {}
if (!localPKGjson.dependencies) localPKGjson.dependencies = {}
const areDepsEqual = _.isEqual(
monorepoPKGjson.dependencies,
localPKGjson.dependencies
);
)
if (!areDepsEqual) {
const diff = difference(
monorepoPKGjson.dependencies,
localPKGjson.dependencies
);
)
const diff2 = difference(
localPKGjson.dependencies,
monorepoPKGjson.dependencies
);
)
let needPublishing = false;
let isPublishing = false;
let needPublishing = false
let isPublishing = false
const depChangeLog = _.uniq(Object.keys({ ...diff, ...diff2 }))
.reduce((acc, key) => {
if (monorepoPKGjson.dependencies[key] === `medusa-dev`) {
if (monorepoPKGjson.dependencies[key] === `gatsby-dev`) {
// if we are in middle of publishing to local repository - ignore
isPublishing = true;
return acc;
isPublishing = true
return acc
}
if (localPKGjson.dependencies[key] === `medusa-dev`) {
if (localPKGjson.dependencies[key] === `gatsby-dev`) {
// monorepo packages will restore version, but after installation
// in local site - it will use `medusa-dev` dist tag - we need
// in local site - it will use `gatsby-dev` dist tag - we need
// to ignore changes that
return acc;
return acc
}
if (
@@ -143,48 +139,55 @@ exports.checkDepsChanges = async ({
monorepoPKGjson.dependencies[key]
) {
// Check only for version changes in packages
// that are not from medusa repo.
// Changes in medusa packages will be copied over
// that are not from gatsby repo.
// Changes in gatsby packages will be copied over
// from monorepo - and if those contain other dependency
// changes - they will be covered
if (!monoRepoPackages.includes(key)) {
acc.push(
` - '${key}' changed version from ${localPKGjson.dependencies[key]} to ${monorepoPKGjson.dependencies[key]}`
);
needPublishing = true;
)
needPublishing = true
}
} else if (monorepoPKGjson.dependencies[key]) {
acc.push(
` - '${key}@${monorepoPKGjson.dependencies[key]}' was added`
);
needPublishing = true;
acc.push(` - '${key}@${monorepoPKGjson.dependencies[key]}' was added`)
needPublishing = true
} else {
acc.push(` - '${key}@${localPKGjson.dependencies[key]}' was removed`);
acc.push(` - '${key}@${localPKGjson.dependencies[key]}' was removed`)
// this doesn't need publishing really, so will skip this
}
return acc;
return acc
}, [])
.join(`\n`);
.join(`\n`)
if (!isPublishing && depChangeLog.length > 0) {
console.log(`Dependencies of '${packageName}' changed:\n${depChangeLog}`);
console.log(`Dependencies of '${packageName}' changed:\n${depChangeLog}`)
if (isInitialScan) {
console.log(
`Will ${!needPublishing ? `not ` : ``}publish to local npm registry.`
);
)
} else {
console.warn(
`Installation of dependencies after initial scan is not implemented`
);
)
}
return {
didDepsChanged: needPublishing,
packageNotInstalled,
};
}
}
}
return {
didDepsChanged: false,
packageNotInstalled,
};
};
}
}
function getPackageVersion(packageName) {
const projectPackageJson = JSON.parse(
fs.readFileSync(`./package.json`, `utf-8`)
)
const { dependencies = {}, devDependencies = {} } = projectPackageJson
const version = dependencies[packageName] || devDependencies[packageName]
return version || `latest`
}

View File

@@ -1,11 +1,4 @@
const path = require(`path`);
const path = require(`path`)
exports.getMonorepoPackageJsonPath = ({ packageName, root }) => {
let dirName = packageName;
if (packageName.startsWith("@medusajs")) {
const [, directory] = packageName.split("/");
dirName = directory;
}
return path.join(root, `packages`, dirName, `package.json`);
};
exports.getMonorepoPackageJsonPath = ({ packageName, packageNameToPath }) =>
path.join(packageNameToPath.get(packageName), `package.json`)

View File

@@ -1,10 +1,17 @@
const _ = require(`lodash`);
const path = require(`path`);
const _ = require(`lodash`)
const path = require(`path`)
/**
* @typedef {Object} TraversePackagesDepsReturn
* @property {Object} depTree Lookup table to check dependants for given package.
* Used to determine which packages need to be published.
* @example
* ```
* {
* "medusa-cli": Set(["medusa"]),
* "medusa-telemetry": Set(["medusa", "medusa-cli"]),
* }
* ```
*/
/**
@@ -24,53 +31,58 @@ const path = require(`path`);
* @return {TraversePackagesDepsReturn}
*/
const traversePackagesDeps = ({
root,
packages,
monoRepoPackages,
seenPackages = [...packages],
depTree = {},
packageNameToPath,
}) => {
packages.forEach((p) => {
if (p.startsWith("@medusajs")) {
p = p.split("/")[1];
}
let pkgJson;
let pkgJson
try {
pkgJson = require(path.join(root, `packages`, p, `package.json`));
} catch {
console.error(`"${p}" package doesn't exist in monorepo.`);
const packageRoot = packageNameToPath.get(p)
if (packageRoot) {
pkgJson = require(path.join(packageRoot, `package.json`))
} else {
console.error(`"${p}" package doesn't exist in monorepo.`)
// remove from seenPackages
seenPackages = seenPackages.filter((seenPkg) => seenPkg !== p)
return
}
} catch (e) {
console.error(`"${p}" package doesn't exist in monorepo.`, e)
// remove from seenPackages
seenPackages = seenPackages.filter((seenPkg) => seenPkg !== p);
return;
seenPackages = seenPackages.filter((seenPkg) => seenPkg !== p)
return
}
const fromMonoRepo = _.intersection(
Object.keys({ ...pkgJson.dependencies }),
monoRepoPackages
);
)
fromMonoRepo.forEach((pkgName) => {
depTree[pkgName] = (depTree[pkgName] || new Set()).add(p);
});
depTree[pkgName] = (depTree[pkgName] || new Set()).add(p)
})
// only traverse not yet seen packages to avoid infinite loops
const newPackages = _.difference(fromMonoRepo, seenPackages);
const newPackages = _.difference(fromMonoRepo, seenPackages)
if (newPackages.length) {
newPackages.forEach((depFromMonorepo) => {
seenPackages.push(depFromMonorepo);
});
seenPackages.push(depFromMonorepo)
})
traversePackagesDeps({
root,
packages: fromMonoRepo,
monoRepoPackages,
seenPackages,
depTree,
});
packageNameToPath,
})
}
});
return { seenPackages, depTree };
};
})
return { seenPackages, depTree }
}
exports.traversePackagesDeps = traversePackagesDeps;
exports.traversePackagesDeps = traversePackagesDeps