Skip to content

Commit

Permalink
feat(core): more progress on v2 projects
Browse files Browse the repository at this point in the history
  • Loading branch information
AgentEnder committed Jul 24, 2023
1 parent 619feee commit a71a12c
Show file tree
Hide file tree
Showing 20 changed files with 469 additions and 316 deletions.
9 changes: 5 additions & 4 deletions docs/generated/devkit/nx_devkit.md
Original file line number Diff line number Diff line change
Expand Up @@ -1422,17 +1422,18 @@ but it can also be passed in explicitly.

### getProjects

**getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../devkit/documents/nx_devkit#projectconfiguration)\>
**getProjects**(`tree`, `includeInferredProjects?`): `Map`<`string`, [`ProjectConfiguration`](../../devkit/documents/nx_devkit#projectconfiguration)\>

Get a map of all projects in a workspace.

Use [readProjectConfiguration](../../devkit/documents/nx_devkit#readprojectconfiguration) if only one project is needed.

#### Parameters

| Name | Type |
| :----- | :---------------------------------------------- |
| `tree` | [`Tree`](../../devkit/documents/nx_devkit#tree) |
| Name | Type | Default value |
| :------------------------ | :---------------------------------------------- | :------------ |
| `tree` | [`Tree`](../../devkit/documents/nx_devkit#tree) | `undefined` |
| `includeInferredProjects` | `boolean` | `true` |

#### Returns

Expand Down
9 changes: 5 additions & 4 deletions docs/generated/packages/devkit/documents/nx_devkit.md
Original file line number Diff line number Diff line change
Expand Up @@ -1422,17 +1422,18 @@ but it can also be passed in explicitly.

### getProjects

**getProjects**(`tree`): `Map`<`string`, [`ProjectConfiguration`](../../devkit/documents/nx_devkit#projectconfiguration)\>
**getProjects**(`tree`, `includeInferredProjects?`): `Map`<`string`, [`ProjectConfiguration`](../../devkit/documents/nx_devkit#projectconfiguration)\>

Get a map of all projects in a workspace.

Use [readProjectConfiguration](../../devkit/documents/nx_devkit#readprojectconfiguration) if only one project is needed.

#### Parameters

| Name | Type |
| :----- | :---------------------------------------------- |
| `tree` | [`Tree`](../../devkit/documents/nx_devkit#tree) |
| Name | Type | Default value |
| :------------------------ | :---------------------------------------------- | :------------ |
| `tree` | [`Tree`](../../devkit/documents/nx_devkit#tree) | `undefined` |
| `includeInferredProjects` | `boolean` | `true` |

#### Returns

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ describe('e2e migrator', () => {

await migrator.migrate();

console.log(tree.listChanges().map((c) => `${c.path} ${c.type}`));
expect(tree.exists('protractor.conf.js')).toBe(false);
expect(tree.exists('apps/app1-e2e/protractor.conf.js')).toBe(true);
expect(tree.exists('e2e/tsconfig.json')).toBe(false);
Expand Down
154 changes: 154 additions & 0 deletions packages/nx/plugins/package-json-workspaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { existsSync } from 'node:fs';
import { dirname, join } from 'node:path';

import { NxJsonConfiguration } from '../src/config/nx-json';
import { ProjectConfiguration } from '../src/config/workspace-json-project-json';
import { toProjectName } from '../src/config/workspaces';
import { readJsonFile, readYamlFile } from '../src/utils/fileutils';
import { combineGlobPatterns } from '../src/utils/globs';
import { NX_PREFIX } from '../src/utils/logger';
import { NxPluginV2 } from '../src/utils/nx-plugin';
import { output } from '../src/utils/output';
import { PackageJson } from '../src/utils/package-json';
import { joinPathFragments } from '../src/utils/path';

export function getPackageJsonWorkspacesPlugin(
root: string,
nxJson: NxJsonConfiguration,
readJson: <T extends Object>(string) => T = <T extends Object>(string) =>
readJsonFile<T>(string)
): NxPluginV2 {
const globPatternsFromPackageManagerWorkspaces =
getGlobPatternsFromPackageManagerWorkspaces(root, readJson);
return {
name: 'nx-core-build-package-json-nodes',
processProjectNodes: {
// Load projects from pnpm / npm workspaces
...(globPatternsFromPackageManagerWorkspaces.length
? {
[combineGlobPatterns(globPatternsFromPackageManagerWorkspaces)]: (
pkgJsonPath
) => {
const json = readJson<PackageJson>(pkgJsonPath);
return {
projectNodes: {
[json.name]: buildProjectConfigurationFromPackageJson(
pkgJsonPath,
json,
nxJson
),
},
};
},
}
: {}),
},
};
}

function buildProjectConfigurationFromPackageJson(
path: string,
packageJson: { name: string },
nxJson: NxJsonConfiguration
): ProjectConfiguration & { name: string } {
const normalizedPath = path.split('\\').join('/');
const directory = dirname(normalizedPath);

if (!packageJson.name && directory === '.') {
throw new Error(
'Nx requires the root package.json to specify a name if it is being used as an Nx project.'
);
}

let name = packageJson.name ?? toProjectName(normalizedPath);
if (nxJson?.npmScope) {
const npmPrefix = `@${nxJson.npmScope}/`;
if (name.startsWith(npmPrefix)) {
name = name.replace(npmPrefix, '');
}
}
const projectType =
nxJson?.workspaceLayout?.appsDir != nxJson?.workspaceLayout?.libsDir &&
nxJson?.workspaceLayout?.appsDir &&
directory.startsWith(nxJson.workspaceLayout.appsDir)
? 'application'
: 'library';

return {
root: directory,
sourceRoot: directory,
name,
projectType,
};
}

/**
* Get the package.json globs from package manager workspaces
*/
export function getGlobPatternsFromPackageManagerWorkspaces(
root: string,
readJson: <T extends Object>(path: string) => T = <T extends Object>(path) =>
readJsonFile<T>(join(root, path)) // making this an arg allows us to reuse in devkit
): string[] {
try {
const patterns: string[] = [];
const packageJson = readJson<PackageJson>('package.json');

patterns.push(
...normalizePatterns(
Array.isArray(packageJson.workspaces)
? packageJson.workspaces
: packageJson.workspaces?.packages ?? []
)
);

if (existsSync(join(root, 'pnpm-workspace.yaml'))) {
try {
const { packages } = readYamlFile<{ packages: string[] }>(
join(root, 'pnpm-workspace.yaml')
);
patterns.push(...normalizePatterns(packages || []));
} catch (e: unknown) {
output.warn({
title: `${NX_PREFIX} Unable to parse pnpm-workspace.yaml`,
bodyLines: [e.toString()],
});
}
}

if (existsSync(join(root, 'lerna.json'))) {
try {
const { packages } = readJson<any>('lerna.json');
patterns.push(
...normalizePatterns(packages?.length > 0 ? packages : ['packages/*'])
);
} catch (e: unknown) {
output.warn({
title: `${NX_PREFIX} Unable to parse lerna.json`,
bodyLines: [e.toString()],
});
}
}

// Merge patterns from workspaces definitions
// TODO(@AgentEnder): update logic after better way to determine root project inclusion
// Include the root project
return packageJson.nx ? patterns.concat('package.json') : patterns;
} catch {
return [];
}
}

function normalizePatterns(patterns: string[]): string[] {
return patterns.map((pattern) =>
removeRelativePath(
pattern.endsWith('/package.json')
? pattern
: joinPathFragments(pattern, 'package.json')
)
);
}

function removeRelativePath(pattern: string): string {
return pattern.startsWith('./') ? pattern.substring(2) : pattern;
}
43 changes: 43 additions & 0 deletions packages/nx/plugins/project-json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { dirname } from 'node:path';

import { ProjectConfiguration } from '../src/config/workspace-json-project-json';
import { toProjectName } from '../src/config/workspaces';
import { readJsonFile } from '../src/utils/fileutils';
import { NxPluginV2 } from '../src/utils/nx-plugin';

export function getProjectJsonPlugin(
readJson: <T extends Object>(string) => T = <T extends Object>(string) =>
readJsonFile<T>(string)
): NxPluginV2 {
// making this an arg allows us to reuse in devkit): NxPluginV2 {
return {
name: 'nx-core-build-project-json-nodes',
processProjectNodes: {
// Load projects from project.json files. These will be read second, since
// they are listed last in the plugin, so they will overwrite things from the package.json
// based projects.
'{project.json,**/project.json}': (file) => {
const json = readJson<ProjectConfiguration>(file);
const project = buildProjectFromProjectJson(json, file);
return {
projectNodes: {
[project.name]: project,
},
};
},
},
};
}

export function buildProjectFromProjectJson(
json: Partial<ProjectConfiguration>,
path: string
): ProjectConfiguration {
return {
...{
name: toProjectName(path),
root: dirname(path),
},
...json,
};
}
3 changes: 1 addition & 2 deletions packages/nx/src/config/workspaces.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jest.mock('fs', () => require('memfs').fs);

const libConfig = (root, name?: string) => ({
name: name ?? toProjectName(`${root}/some-file`),
projectType: 'library',
root: `libs/${root}`,
sourceRoot: `libs/${root}/src`,
});
Expand Down Expand Up @@ -68,7 +69,6 @@ describe('Workspaces', () => {

const workspaces = new Workspaces('/root');
const resolved = workspaces.readProjectsConfigurations();
console.log(resolved);
expect(resolved.projects.lib1).toEqual(standaloneConfig);
});

Expand Down Expand Up @@ -100,7 +100,6 @@ describe('Workspaces', () => {

const workspaces = new Workspaces('/root');
const { projects } = workspaces.readProjectsConfigurations();
console.log(projects);

// projects got merged for lib1
expect(projects['lib1']).toEqual({
Expand Down
Loading

0 comments on commit a71a12c

Please sign in to comment.