Skip to content

Commit

Permalink
fix: migrate Lerna to NPM Workspaces
Browse files Browse the repository at this point in the history
remove @loopback/monorepo. With the new version of lerna, this package no longer makes sense.

Signed-off-by: Francisco Buceta <[email protected]>
  • Loading branch information
frbuceta committed Jun 28, 2023
1 parent fe72763 commit d5c4994
Show file tree
Hide file tree
Showing 37 changed files with 14,367 additions and 10,633 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,6 @@ jobs:
run: |
node packages/build/bin/run-eslint .
node packages/build/bin/run-prettier --check "**/*.ts" "**/*.js" "**/*.md" "!docs/**/*.md"
- name: Verify package-lock files
run: node packages/monorepo/lib/check-package-locks
- name: Verify package metadata
run: node bin/check-package-metadata.js

Expand Down
1 change: 0 additions & 1 deletion CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,6 @@
# - Standby owner(s): @emonddr
/bin @emonddr @raymondfeng
/packages/build @emonddr @raymondfeng @achrinza
/packages/monorepo @raymondfeng
/packages/eslint-config @emonddr @raymondfeng
/packages/tsdocs @emonddr @raymondfeng
/fixtures/tsdocs-monorepo @emonddr @raymondfeng
Expand Down
62 changes: 38 additions & 24 deletions bin/check-package-metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,25 @@
*/
'use strict';

const path = require('path');
const fs = require('fs-extra');
const {
isTypeScriptPackage,
loadLernaRepo,
runMain,
} = require('../packages/monorepo');
const path = require('node:path');
const fse = require('fs-extra');
const pkgJson = require('@npmcli/package-json');
const mapWorkspaces = require('@npmcli/map-workspaces');
const {runMain} = require('./script-util');

function isTypeScriptPackage(location) {
return fse.existsSync(path.join(location, 'tsconfig.json'));
}

/**
* Check existence of LICENSE file in the monorepo packages
* @param {Package[]} packages A list of @lerna/project packages
* @param {Array} packages A list of @lerna/project packages
*/
async function checkLicenseFiles(packages) {
const errors = [];

for (const p of packages) {
const exists = await fs.pathExists(path.join(p.location, 'LICENSE'));
const exists = await fse.pathExists(path.join(p.location, 'LICENSE'));

if (!exists) {
errors.push(`${p.name} directory doesn't contain LICENSE file`);
Expand All @@ -39,12 +41,12 @@ async function checkLicenseFiles(packages) {

/**
* Check mention of packages in MONOREPO.md file
* @param {Package[]} packages A list of @lerna/project packages
* @param {Array} packages A list of @lerna/project packages
* @param {string} rootPath A project.rootPath
*/
async function checkMonorepoFile(packages, rootPath) {
const errors = [];
const monorepoFile = await fs.readFile('docs/site/MONOREPO.md', 'utf8');
const monorepoFile = await fse.readFile('docs/site/MONOREPO.md', 'utf8');

for (const p of packages) {
const packagePath = path.relative(rootPath, p.location).replace(/\\/g, '/');
Expand All @@ -62,14 +64,14 @@ async function checkMonorepoFile(packages, rootPath) {

/**
* Check mention of packages in CODEOWNERS.md file
* @param {Package[]} packages A list of @lerna/project packages
* @param {Array} packages A list of @lerna/project packages
* @param {string} rootPath A project.rootPath
*/
async function checkCodeOwnersFile(packages, rootPath) {
const errors = [];
const excludes = ['@loopback/sandbox-example'];

const codeOwnersFile = await fs.readFile('CODEOWNERS', 'utf8');
const codeOwnersFile = await fse.readFile('CODEOWNERS', 'utf8');

for (const p of packages) {
if (excludes.includes(p.name)) {
Expand All @@ -88,7 +90,7 @@ async function checkCodeOwnersFile(packages, rootPath) {

/**
* Check all required fields of package.json for each package on the matching with root package.json
* @param {Package[]} packages A list of @lerna/project packages
* @param {Array} packages A list of @lerna/project packages
* @param {Object} rootPkg A root package.json
*/
async function checkPkgsPackageJson(packages, rootPkg) {
Expand All @@ -104,17 +106,17 @@ async function checkPkgsPackageJson(packages, rootPkg) {
}

for (const p of pkgs) {
const pkg = p.toJSON();
const pkg = p.content;

const isCorrectMain = pkg.main && pkg.main === 'dist/index.js';

if (isTypeScriptPackage(p) && !isCorrectMain) {
if (isTypeScriptPackage(p.location) && !isCorrectMain) {
errors.push(getErrorText(p.name, 'main'));
}

const isCorrectTypes = pkg.types && pkg.types === 'dist/index.d.ts';

if (isTypeScriptPackage(p) && !isCorrectTypes) {
if (isTypeScriptPackage(p.location) && !isCorrectTypes) {
errors.push(getErrorText(p.name, 'types'));
}

Expand Down Expand Up @@ -152,7 +154,7 @@ async function checkPkgsPackageJson(packages, rootPkg) {

const isCorrectRepositoryDirectory =
pkg.repository && pkg.repository.directory;
const isRepositoryDirectoryExist = fs.existsSync(p.location);
const isRepositoryDirectoryExist = fse.existsSync(p.location);

if (!isCorrectRepositoryDirectory) {
errors.push(getErrorText(p.name, 'repository.directory'));
Expand Down Expand Up @@ -186,9 +188,21 @@ function formatErrorsText(errors) {
}

async function checkPackagesMetadata() {
const {project, packages} = await loadLernaRepo();
const rootPath = project.rootPath;
const rootPkg = fs.readJsonSync('package.json');
const rootPath = process.cwd();
const {content: pkg} = await pkgJson.load(rootPath);
const workspaces = await mapWorkspaces({cwd: rootPath, pkg});
const packages = await Promise.all(
Array.from(workspaces, async ([name, location]) => {
const {content} = await pkgJson.load(location);
return {
name,
location,
private: content.private ?? false,
content,
};
}),
);
const rootPkg = fse.readJsonSync('package.json');

const errors = (
await Promise.all([
Expand All @@ -204,8 +218,8 @@ async function checkPackagesMetadata() {
}
}

function checkDepsOrder(lernaPkg, pkgJson, errors) {
const actualOrder = Object.keys(pkgJson).filter(k =>
function checkDepsOrder(pkg, json, errors) {
const actualOrder = Object.keys(json).filter(k =>
['dependencies', 'devDependencies', 'peerDependencies'].includes(k),
);

Expand All @@ -219,7 +233,7 @@ function checkDepsOrder(lernaPkg, pkgJson, errors) {
const expectedStr = expectedOrder.join(' ');

if (actualStr !== expectedStr) {
const pkgPath = path.relative(lernaPkg.rootPath, lernaPkg.location);
const pkgPath = path.relative(pkg.rootPath, pkg.location);
errors.push(
`${pkgPath}/package.json has incorrect order of keys.\n` +
` Actual: ${actualStr}\n` +
Expand Down
16 changes: 8 additions & 8 deletions bin/checkout-pr.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@
* 5. Check out <pr-branch> to track <pr-repo>/<pr-branch>
* 6. Rebase the PR branch to the origin/<base-branch>
*/
const path = require('node:path');
const https = require('node:https');
const {parse: parseURL} = require('node:url');
const build = require('../packages/build');
const path = require('path');
const rootDir = path.join(__dirname, '..');
const {runMain} = require('./script-util');

const ROOT_DIR = path.join(__dirname, '..');

async function checkoutPR() {
const prUrlOrNum = process.argv[2];
Expand Down Expand Up @@ -54,17 +58,13 @@ async function checkoutPR() {
console.log(`PR ${prNum} is now checked out.`);
}

const https = require('https');
const url = require('url');
const {runMain} = require('../packages/monorepo');

/**
* Fetch PR information
* @param {string} prUrl - PR url
*/
function getPRInfo(prUrl) {
const options = {
...url.parse(prUrl),
...parseURL(prUrl),
headers: {
'User-Agent': 'Node.js https client',
},
Expand Down Expand Up @@ -118,7 +118,7 @@ function getPRInfo(prUrl) {
async function git(...args) {
console.log('> git', ...args);
const shell = build.runShell('git', args, {
cwd: rootDir,
cwd: ROOT_DIR,
});
await waitForProcessExit(shell);
}
Expand Down
35 changes: 35 additions & 0 deletions bin/config-package-scopes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright IBM Corp. 2020. All Rights Reserved.
// Node module: @loopback/monorepo
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

/**
* This is a script to list workspace packages.
*/
'use strict';

const pkgJson = require('@npmcli/package-json');
const mapWorkspaces = require('@npmcli/map-workspaces');
const debugFactory = require('debug');
const {runMain} = require('./script-util');

const debug = debugFactory('loopback:monorepo');

module.exports = {
rules: {
// eslint-disable-next-line @typescript-eslint/naming-convention
'scope-enum': async ctx => [2, 'always', await getPackageNames(ctx)],
},
};

async function getPackageNames() {
const {content: pkg} = await pkgJson.normalize(process.cwd());
const workspaces = await mapWorkspaces({cwd: process.cwd(), pkg});
const packages = Array.from(workspaces, entry => {
return entry[0].startsWith('@') ? entry[0].split('/')[1] : entry[0];
});
debug('Scope names for the NPM Workspace: %s', packages);
return packages;
}

runMain(module, getPackageNames);
11 changes: 6 additions & 5 deletions bin/create-package.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@
*/
'use strict';

const path = require('node:path');
const fse = require('fs-extra');
const build = require('../packages/build');
const path = require('path');
const {runMain, updateTsProjectRefs} = require('./script-util');

const cwd = process.cwd();
const fs = require('fs-extra');
const {runMain, updateTsProjectRefs} = require('../packages/monorepo');

/**
* Return a promise to be resolved by the child process exit event
Expand Down Expand Up @@ -163,7 +164,7 @@ async function bootstrapProject({repoRoot, name}) {
async function fixupProject({repoRoot, projectDir}) {
process.chdir(path.join(repoRoot, projectDir));
// Update package.json
let pkg = fs.readJsonSync('package.json');
let pkg = fse.readJsonSync('package.json');
pkg = {
...pkg,
version: '0.0.1',
Expand All @@ -184,7 +185,7 @@ async function fixupProject({repoRoot, projectDir}) {
delete pkg.dependencies['@loopback/boot'];
delete pkg.devDependencies['source-map-support'];

fs.writeJsonSync('package.json', pkg, {spaces: 2});
fse.writeJsonSync('package.json', pkg, {spaces: 2});

// Remove unused files
build.clean([
Expand Down
6 changes: 2 additions & 4 deletions bin/fix-monorepo.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@
*/
'use strict';

const path = require('path');

const path = require('node:path');
const syncDevDeps = require('./sync-dev-deps');
const updateMonorepo = require('./update-monorepo-file');

const {
isJsonEqual,
loadLernaRepo,
Expand All @@ -23,7 +21,7 @@ const {
updatePackageJson,
updateTsProjectRefs,
writeJsonSync,
} = require('../packages/monorepo');
} = require('./script-util');

async function fixMonorepo() {
// Ensure all packages use the local version of `@loopback/*`
Expand Down
4 changes: 2 additions & 2 deletions bin/mocha-current-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ Ex:
*/

'use strict';
const path = require('path');
const fs = require('fs');
const path = require('node:path');
const fs = require('node:fs');

function findDistFile(filename) {
const absolutePath = path.resolve(filename);
Expand Down
Loading

0 comments on commit d5c4994

Please sign in to comment.