Skip to content

Commit

Permalink
feat(core): export detectProjects utility function (#3740)
Browse files Browse the repository at this point in the history
  • Loading branch information
fahslaj committed Jun 25, 2023
1 parent 4fb0427 commit 641fecb
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 21 deletions.
1 change: 1 addition & 0 deletions libs/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export {
collectProjects,
} from "./lib/collect-updates";
export { Command, PreInitializedProjectData } from "./lib/command";
export { detectProjects } from "./lib/command/detect-projects";
export { isGitInitialized } from "./lib/command/is-git-initialized";
export { applyBuildMetadata, recommendVersion, updateChangelog } from "./lib/conventional-commits";
export { describeRef, describeRefSync } from "./lib/describe-ref";
Expand Down
34 changes: 34 additions & 0 deletions libs/core/src/lib/command/detect-projects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ProjectFileMap, createProjectFileMapUsingProjectGraph, createProjectGraphAsync } from "@nx/devkit";
import { ProjectGraphWithPackages } from "../project-graph-with-packages";
import { createProjectGraphWithPackages } from "./create-project-graph-with-packages";

export async function detectProjects(packageConfigs: string[]): Promise<{
projectGraph: ProjectGraphWithPackages;
projectFileMap: ProjectFileMap;
}> {
const _projectGraph = await createProjectGraphAsync();

let projectFileMap: ProjectFileMap;

// if we are using Nx >= 16.3.1, we can use the helper function to create the file map
// otherwise, we need to use the old "files" property on the node data
if (createProjectFileMapUsingProjectGraph) {
projectFileMap = await createProjectFileMapUsingProjectGraph(_projectGraph);
} else {
projectFileMap = Object.entries(_projectGraph.nodes).reduce(
(map, [key, node]) => ({
...map,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key]: (node.data as any).files,
}),
{}
);
}

const projectGraph = await createProjectGraphWithPackages(_projectGraph, projectFileMap, packageConfigs);

return {
projectGraph,
projectFileMap,
};
}
23 changes: 5 additions & 18 deletions libs/core/src/lib/command/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ProjectFileMap, createProjectFileMapUsingProjectGraph, createProjectGraphAsync } from "@nx/devkit";
import { ProjectFileMap } from "@nx/devkit";
import cloneDeep from "clone-deep";
import dedent from "dedent";
import { mapValues } from "lodash";
import log from "npmlog";
import { daemonClient } from "nx/src/daemon/client/client";
import os from "os";
Expand All @@ -11,8 +10,8 @@ import { ProjectGraphWithPackages } from "../project-graph-with-packages";
import { ValidationError } from "../validation-error";
import { writeLogFile } from "../write-log-file";
import { cleanStack } from "./clean-stack";
import { createProjectGraphWithPackages } from "./create-project-graph-with-packages";
import { defaultOptions } from "./default-options";
import { detectProjects } from "./detect-projects";
import { isGitInitialized } from "./is-git-initialized";
import { logPackageError } from "./log-package-error";
import { warnIfHanging } from "./warn-if-hanging";
Expand Down Expand Up @@ -205,22 +204,10 @@ export class Command<T extends CommandConfigOptions = CommandConfigOptions> {
}

async detectProjects() {
const projectGraph = await createProjectGraphAsync();
const { projectGraph, projectFileMap } = await detectProjects(this.project.packageConfigs);

// if we are using Nx >= 16.3.1, we can use the helper function to create the file map
// otherwise, we need to use the old "files" property on the node data
if (createProjectFileMapUsingProjectGraph) {
this.projectFileMap = await createProjectFileMapUsingProjectGraph(projectGraph);
} else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.projectFileMap = mapValues(projectGraph.nodes, (node) => (node.data as any).files);
}

this.projectGraph = await createProjectGraphWithPackages(
projectGraph,
this.projectFileMap,
this.project.packageConfigs
);
this.projectGraph = projectGraph;
this.projectFileMap = projectFileMap;
}

configureEnvironment() {
Expand Down
3 changes: 2 additions & 1 deletion packages/lerna/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@
"./commands/diff/lib/*": "./dist/commands/diff/lib/*.js",
"./commands/publish/lib/*": "./dist/commands/publish/lib/*.js",
"./commands/version/lib/*": "./dist/commands/version/lib/*.js",
"./migrations/**/*": "./dist/migrations/**/*"
"./migrations/**/*": "./dist/migrations/**/*",
"./utils": "./dist/utils/index.js"
},
"gitHead": "3900fe95f8bc5a3907156126bcac6989260e1082"
}
3 changes: 2 additions & 1 deletion packages/lerna/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@
"packages/lerna/src/migrations/remove-invalid-lerna-config/remove-invalid-lerna-config.ts",
"packages/lerna/src/migrations/remove-invalid-use-workspaces/remove-invalid-use-workspaces.ts",
"packages/lerna/src/migrations/remove-unnecessary-use-nx/remove-unnecessary-use-nx.ts",
"packages/lerna/src/migrations/update-options-from-legacy-deprecate-config/update-options-from-legacy-deprecate-config.ts"
"packages/lerna/src/migrations/update-options-from-legacy-deprecate-config/update-options-from-legacy-deprecate-config.ts",
"packages/lerna/src/utils/index.ts"
],
"esbuildOptions": {
"external": [
Expand Down
7 changes: 7 additions & 0 deletions packages/lerna/src/utils/detect-projects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Project, detectProjects as _detectProjects } from "@lerna/core";
import { workspaceRoot } from "@nx/devkit";

export async function detectProjects() {
const project = new Project(workspaceRoot);
return _detectProjects(project.packageConfigs);
}
1 change: 1 addition & 0 deletions packages/lerna/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./detect-projects";
29 changes: 29 additions & 0 deletions website/docs/api-reference/utilities.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
id: utilities
title: Utilities
type: reference
---

# Utilities

Lerna ships some utility functions that can be used in creating your own tools within a Lerna monorepo.

```js
const utils = require("lerna/utils");
```

## `detectProjects()`

The `detectProjects()` function creates the same project graph file mapping that Lerna uses under the covers to execute its commands. This is useful for writing your own scripts that need to operate on the same set of packages that Lerna would.

```js
const { detectProjects } = require("lerna/utils");

const { projectGraph, projectFileMap } = await detectProjects();
```

The `projectGraph` that is returned will be a `ProjectGraphWithPackages`, which is an extension of the `ProjectGraph` type from `@nx/devkit`. It contains additional metadata about projects that have `package.json` files. It also has a `localPackageDependencies` property that tracks internal npm dependencies between projects (as opposed to external npm dependencies that are downloaded from the registry).

The `projectFileMap` is a mapping of project names to the files within them. This is used to determine which project needs to be versioned when a file changes.

See [Lerna's TypeScript source code](https://github.com/lerna/lerna/blob/main/libs/core/src/lib/project-graph-with-packages.ts) for specific type details.
2 changes: 1 addition & 1 deletion website/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const sidebars = {
{
type: "category",
label: "API Reference",
items: ["api-reference/commands", "api-reference/configuration"],
items: ["api-reference/commands", "api-reference/configuration", "api-reference/utilities"],
},
"legacy-package-management",
"faq",
Expand Down

0 comments on commit 641fecb

Please sign in to comment.