Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions scripts/monorepo/src/getDependencies.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@
// - modules(projects) written in TS not having enabled `checkJS:true` wont infer types from .js files, thus the API will have `any` type.
// This errors in strict ts check mode.

/// <reference path="../../../typings/lerna/index.d.ts" />
export declare function getDependencies(packageName: string): Promise<{
dependencies: Dependency[];
devDependencies: Dependency[];
all: Dependency[];
projectGraph: import('lerna/utils').ProjectGraphWithPackages;
projectGraph: import('@nx/devkit').ProjectGraph;
getProjectPackageJsonInfo: (
project: string,
projectGraph: import('@nx/devkit').ProjectGraph,
) => import('./types').PackageJson & { absoluteRootPath: string };
}>;

type Dependency = {
name: string;
isTopLevel: boolean;
dependencyType: import('lerna/utils').ProjectGraphWorkspacePackageDependency['dependencyCollection'];
dependencyType: 'dependencies' | 'devDependencies' | 'optionalDependencies' | null;
};
102 changes: 90 additions & 12 deletions scripts/monorepo/src/getDependencies.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,96 @@
const lernaUtils = require('lerna/utils');
const fs = require('node:fs');

const { createProjectGraphAsync, joinPathFragments, workspaceRoot } = require('@nx/devkit');

/**
* @typedef {{
name: string,
isTopLevel: boolean,
dependencyType: lernaUtils.ProjectGraphWorkspacePackageDependency['dependencyCollection'],
dependencyType: 'dependencies' | 'devDependencies' | 'optionalDependencies' | null,
}} Dependency
*/

/** @typedef {import('./types').PackageJson & {absoluteRootPath:string}} PackageJsonInfoData */

/**
* @type {Record<string,PackageJsonInfoData>}
*/
const packageJsonInfo = {};

/**
*
* @param {string} project
* @param {lernaUtils.ProjectGraphWithPackages} projectGraph
* @param {import('@nx/devkit').ProjectGraph} projectGraph
*/
function getProjectPackageJsonInfo(project, projectGraph) {
const cachedInfo = packageJsonInfo[project];
if (cachedInfo) {
return cachedInfo;
}

const metadata = projectGraph.nodes[project];
const absoluteRootPath = joinPathFragments(workspaceRoot, metadata.data.root);
const pkgJsonContent = fs.readFileSync(joinPathFragments(workspaceRoot, metadata.data.root, 'package.json'), 'utf-8');

/** @type {PackageJsonInfoData} */
const pkgJson = JSON.parse(pkgJsonContent);
pkgJson.absoluteRootPath = absoluteRootPath;

// store in cache
packageJsonInfo[project] = pkgJson;

return pkgJson;
}

/**
* Returns local dependencies of provided project. Local means dependency from within workspace
* @param {string} project
* @param {import('@nx/devkit').ProjectGraph} projectGraph
*/
function getLocalDeps(project, projectGraph) {
const deps = projectGraph.dependencies[project];
const pkgJson = getProjectPackageJsonInfo(project, projectGraph);

/**
* @type {Array<{target:string;dependencyType:ReturnType<typeof getDepType>}>}
*/
const localDeps = [];
for (const dep of deps) {
if (!dep.target.startsWith('npm:')) {
const dependencyType = getDepType(dep.target, pkgJson);
localDeps.push({ target: dep.target, dependencyType });
}
}

if (localDeps.length > 0) {
return localDeps;
}

return null;
}
/**
*
* @param {string} pkgName
* @param {import('./types').PackageJson} json
* @returns
*/
function getDepType(pkgName, json) {
if (json.dependencies?.[pkgName]) {
return 'dependencies';
}
if (json.devDependencies?.[pkgName]) {
return 'devDependencies';
}
if (json.optionalDependencies?.[pkgName]) {
return 'optionalDependencies';
}
return null;
}

/**
*
* @param {string} project
* @param {import('@nx/devkit').ProjectGraph} projectGraph
* @param {*} options
* @param {Dependency[]} _acc
* @param {boolean} _areTopLevelDeps
Expand All @@ -27,28 +106,26 @@ function collectDependencies(
_acc = [],
_areTopLevelDeps = true,
) {
if (!projectGraph.localPackageDependencies[project]) {
const localDeps = getLocalDeps(project, projectGraph);

if (!localDeps) {
return _acc;
}

projectGraph.localPackageDependencies[project].forEach(dependency => {
localDeps.forEach(dependency => {
const isDependencyAlreadyCollected = _acc.some(dep => dep.name === dependency.target);

if (isDependencyAlreadyCollected) {
return;
}

if (
options.dependenciesOnly &&
dependency.dependencyCollection &&
dependency.dependencyCollection !== 'dependencies'
) {
if (options.dependenciesOnly && dependency.dependencyType && dependency.dependencyType !== 'dependencies') {
return;
}

_acc.push({
name: dependency.target,
dependencyType: dependency.dependencyCollection,
dependencyType: dependency.dependencyType,
isTopLevel: _areTopLevelDeps,
});

Expand All @@ -65,7 +142,7 @@ function collectDependencies(
* @param {string} packageName - including `@fluentui/` prefix
*/
async function getDependencies(packageName) {
const { projectGraph } = await lernaUtils.detectProjects();
const projectGraph = await createProjectGraphAsync();

const allDepsGraph = collectDependencies(packageName, projectGraph, { shallow: false, dependenciesOnly: false });
const depsGraph = collectDependencies(packageName, projectGraph, { shallow: false, dependenciesOnly: true });
Expand All @@ -76,6 +153,7 @@ async function getDependencies(packageName) {
devDependencies: devDepsGraph,
all: allDepsGraph,
projectGraph,
getProjectPackageJsonInfo,
};
}

Expand Down
12 changes: 6 additions & 6 deletions scripts/monorepo/src/getDependencies.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,13 @@ describe(`#getDependencies`, () => {
`);
});

it(`should provide similar api like 'new Project(root).getPackages()'`, async () => {
const { projectGraph } = await getDependencies(packageName);
const packageInfo = projectGraph.nodes[packageName].package;
it(`should provide access to package.json`, async () => {
const { projectGraph, getProjectPackageJsonInfo } = await getDependencies(packageName);
const packageInfo = getProjectPackageJsonInfo(packageName, projectGraph);

expect(packageInfo?.location).toEqual(expect.stringContaining('packages/react-components/react-text'));
expect(packageInfo.absoluteRootPath).toEqual(expect.stringContaining('packages/react-components/react-text'));
expect(packageInfo?.dependencies).toEqual(expect.any(Object));
expect(packageInfo?.get('main')).toEqual('lib-commonjs/index.js');
expect(packageInfo?.get('module')).toEqual('lib/index.js');
expect(packageInfo?.main).toEqual('lib-commonjs/index.js');
expect(packageInfo?.module).toEqual('lib/index.js');
});
});
8 changes: 4 additions & 4 deletions scripts/projects-test/src/packPackages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export async function packProjectPackages(logger: Function, project: string): Pr

packedPackages = {};

const { dependencies: projectDependencies, projectGraph } = await getDependencies(project);
const { dependencies: projectDependencies, projectGraph, getProjectPackageJsonInfo } = await getDependencies(project);
// add provided package to be packaged
projectDependencies.unshift({
name: project,
Expand All @@ -51,13 +51,13 @@ export async function packProjectPackages(logger: Function, project: string): Pr
await Promise.all(
projectDependencies.map(async projectConfig => {
const packageName = projectConfig.name;
const packageInfo = projectGraph.nodes[packageName].package;
const packageInfo = getProjectPackageJsonInfo(packageName, projectGraph);
if (!packageInfo) {
throw new Error(`Package ${packageName} doesn't exist`);
}

const packagePath = packageInfo.location;
const packageMain = packageInfo.get('main') as string | undefined;
const packagePath = packageInfo.absoluteRootPath;
const packageMain = packageInfo.main;
const entryPointPath = packageMain ? path.join(packagePath, packageMain) : '';
if (!fs.existsSync(entryPointPath)) {
throw new Error(
Expand Down
75 changes: 0 additions & 75 deletions typings/lerna/index.d.ts

This file was deleted.

5 changes: 0 additions & 5 deletions typings/lerna/tsconfig.json

This file was deleted.

3 changes: 0 additions & 3 deletions typings/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@
},
{
"path": "./find-free-port/tsconfig.json"
},
{
"path": "./lerna/tsconfig.json"
}
]
}