Skip to content

Instantly share code, notes, and snippets.

@iamandrewluca
Last active December 23, 2022 11:47
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iamandrewluca/5cc85b56a595056f0099d04ed6dd8a79 to your computer and use it in GitHub Desktop.
Save iamandrewluca/5cc85b56a595056f0099d04ed6dd8a79 to your computer and use it in GitHub Desktop.
Adjust repository field in package.json for all packages in a monorepo

Update package.json repository field to point to directory in a monorepo setup

Run Gist using npx and zx in repository folder

npx zx https://gist.githubusercontent.com/iamandrewluca/5cc85b56a595056f0099d04ed6dd8a79/raw/run.mjs \
--repository="https://github.com/facebook/react.git" \
--homepage="https://reactjs.org" \
--ignore="fixtures" \
--space="2"

Supported arguments:

  • --repository (required)
  • --homepage (optional)
  • --ignore (optional)
  • --space (optional) defaults to 2 spaces

chore: add repository directory for all packages.json

If the package.json for your package is not in the root directory (for example if it is part of a monorepo), you can specify the directory in which it lives:

"repository": {
  "type" : "git",
  "url" : "https://github.com/facebook/react.git",
  "directory": "packages/react-dom"
}

https://docs.npmjs.com/cli/v6/configuring-npm/package-json#repository

I use a lot https://njt.vercel.app/ to jump to different packages information, and with this PR we can know exactly what package in what folder lives

Made the changes with a script to make it easier 🙂

https://gist.github.com/iamandrewluca/5cc85b56a595056f0099d04ed6dd8a79

const { repository, homepage, space: rawSpace = '2', ignore = '' } = argv
const maybeNumberSpaceArg = Number.parseInt(rawSpace)
const space = Number.isNaN(maybeNumberSpaceArg) ? JSON.parse(`"${rawSpace}"`) : maybeNumberSpaceArg
const ignoreDirectories = ignore.split(',').map(d => d.trim()).filter(Boolean)
if (!repository) {
console.error('--repository argument is required');
process.exit(1);
}
console.log(`Repository: ${repository}`);
console.log(`Homepage: ${homepage}`);
console.log(`Indentation: ${JSON.stringify(space)}`);
console.log(`Ignore: ${JSON.stringify(ignoreDirectories)}`);
console.log();
const cwd = process.cwd()
const possiblePackages = (await $`find . -type f -not -path './node_modules/*' -name "package.json"`).stdout
.split('\n')
.map(packagePath => packagePath.trim())
.filter(packagePath => packagePath.endsWith('/package.json'))
.map(packagePath => ({
packagePath: path.resolve(cwd, packagePath),
directory: packagePath.replace('./', '').replace('/package.json', '').replace('package.json', '')
}))
.map(record => ({ ...record, name: require(record.packagePath).name }))
// root directory
.filter(record => record.directory !== '')
// ignored directories
.filter(record => !ignoreDirectories.some(d => record.directory.includes(d)))
// missing names
.filter(record => record.name)
.map(record => existsInRegistry(record))
const registryPackages = (await Promise.allSettled(possiblePackages))
.filter(isFulfilled)
.filter(fulfilled => fulfilled.value.exists)
.map(fulfilled => fulfilled.value)
for (const record of registryPackages) {
const pkg = require(record.packagePath);
pkg.homepage = homepage || pkg.homepage;
const repoInfo = typeof pkg.repository === 'string' ? { url: pkg.repository } : pkg.repository || {};
pkg.repository = {
...repoInfo,
type: 'git',
url: repository,
directory: record.directory,
};
await fs.writeFile(record.packagePath, JSON.stringify(pkg, null, space) + '\n');
console.log(`UPDATED '${record.directory}/package.json'`);
}
async function existsInRegistry(record) {
const result = await fetch(`https://registry.npmjs.org/${record.name}/latest`)
return {
...record,
exists: result.status !== 404
}
}
function isFulfilled(value) {
return value.status === 'fulfilled'
}
  • ignore if package already has directory matching current
  • maybe no need to check if package exists? it's still a package.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment