-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): more progress on v2 projects
- Loading branch information
1 parent
619feee
commit cda23af
Showing
18 changed files
with
452 additions
and
314 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.