make medusa-dev-cli compatible with yarn 2/3 (#1765)
This commit is contained in:
@@ -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`]))
|
||||
})
|
||||
|
||||
@@ -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([
|
||||
|
||||
@@ -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`
|
||||
}
|
||||
|
||||
@@ -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`)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user