feat(core): add ability to add metadata to projects (#22299)
This commit is contained in:
parent
9f3af7051b
commit
5a9671b3fa
@ -8,6 +8,7 @@ Project configuration
|
|||||||
|
|
||||||
- [generators](../../devkit/documents/ProjectConfiguration#generators): Object
|
- [generators](../../devkit/documents/ProjectConfiguration#generators): Object
|
||||||
- [implicitDependencies](../../devkit/documents/ProjectConfiguration#implicitdependencies): string[]
|
- [implicitDependencies](../../devkit/documents/ProjectConfiguration#implicitdependencies): string[]
|
||||||
|
- [metadata](../../devkit/documents/ProjectConfiguration#metadata): Object
|
||||||
- [name](../../devkit/documents/ProjectConfiguration#name): string
|
- [name](../../devkit/documents/ProjectConfiguration#name): string
|
||||||
- [namedInputs](../../devkit/documents/ProjectConfiguration#namedinputs): Object
|
- [namedInputs](../../devkit/documents/ProjectConfiguration#namedinputs): Object
|
||||||
- [projectType](../../devkit/documents/ProjectConfiguration#projecttype): ProjectType
|
- [projectType](../../devkit/documents/ProjectConfiguration#projecttype): ProjectType
|
||||||
@ -53,6 +54,19 @@ List of projects which are added as a dependency
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### metadata
|
||||||
|
|
||||||
|
• `Optional` **metadata**: `Object`
|
||||||
|
|
||||||
|
#### Type declaration
|
||||||
|
|
||||||
|
| Name | Type |
|
||||||
|
| :-------------- | :------------------------------- |
|
||||||
|
| `targetGroups?` | `Record`\<`string`, `string`[]\> |
|
||||||
|
| `technologies?` | `string`[] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### name
|
### name
|
||||||
|
|
||||||
• `Optional` **name**: `string`
|
• `Optional` **name**: `string`
|
||||||
|
|||||||
@ -70,6 +70,11 @@ describe('@nx/cypress/plugin', () => {
|
|||||||
{
|
{
|
||||||
"projects": {
|
"projects": {
|
||||||
".": {
|
".": {
|
||||||
|
"metadata": {
|
||||||
|
"technologies": [
|
||||||
|
"cypress",
|
||||||
|
],
|
||||||
|
},
|
||||||
"projectType": "application",
|
"projectType": "application",
|
||||||
"targets": {
|
"targets": {
|
||||||
"e2e": {
|
"e2e": {
|
||||||
@ -129,6 +134,11 @@ describe('@nx/cypress/plugin', () => {
|
|||||||
{
|
{
|
||||||
"projects": {
|
"projects": {
|
||||||
".": {
|
".": {
|
||||||
|
"metadata": {
|
||||||
|
"technologies": [
|
||||||
|
"cypress",
|
||||||
|
],
|
||||||
|
},
|
||||||
"projectType": "application",
|
"projectType": "application",
|
||||||
"targets": {
|
"targets": {
|
||||||
"component-test": {
|
"component-test": {
|
||||||
@ -187,6 +197,17 @@ describe('@nx/cypress/plugin', () => {
|
|||||||
{
|
{
|
||||||
"projects": {
|
"projects": {
|
||||||
".": {
|
".": {
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
".:e2e-ci": [
|
||||||
|
"e2e-ci--src/test.cy.ts",
|
||||||
|
"e2e-ci",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"cypress",
|
||||||
|
],
|
||||||
|
},
|
||||||
"projectType": "application",
|
"projectType": "application",
|
||||||
"targets": {
|
"targets": {
|
||||||
"e2e": {
|
"e2e": {
|
||||||
|
|||||||
@ -3,7 +3,10 @@ import {
|
|||||||
CreateNodes,
|
CreateNodes,
|
||||||
CreateNodesContext,
|
CreateNodesContext,
|
||||||
detectPackageManager,
|
detectPackageManager,
|
||||||
|
joinPathFragments,
|
||||||
|
normalizePath,
|
||||||
NxJsonConfiguration,
|
NxJsonConfiguration,
|
||||||
|
ProjectConfiguration,
|
||||||
readJsonFile,
|
readJsonFile,
|
||||||
TargetConfiguration,
|
TargetConfiguration,
|
||||||
writeJsonFile,
|
writeJsonFile,
|
||||||
@ -12,7 +15,6 @@ import { dirname, join, relative } from 'path';
|
|||||||
|
|
||||||
import { getLockFileName } from '@nx/js';
|
import { getLockFileName } from '@nx/js';
|
||||||
|
|
||||||
import { CypressExecutorOptions } from '../executors/cypress/cypress.impl';
|
|
||||||
import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs';
|
import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs';
|
||||||
import { existsSync, readdirSync } from 'fs';
|
import { existsSync, readdirSync } from 'fs';
|
||||||
import { globWithWorkspaceContext } from 'nx/src/utils/workspace-context';
|
import { globWithWorkspaceContext } from 'nx/src/utils/workspace-context';
|
||||||
@ -30,24 +32,13 @@ export interface CypressPluginOptions {
|
|||||||
const cachePath = join(projectGraphCacheDirectory, 'cypress.hash');
|
const cachePath = join(projectGraphCacheDirectory, 'cypress.hash');
|
||||||
const targetsCache = existsSync(cachePath) ? readTargetsCache() : {};
|
const targetsCache = existsSync(cachePath) ? readTargetsCache() : {};
|
||||||
|
|
||||||
const calculatedTargets: Record<
|
const calculatedTargets: Record<string, CypressTargets> = {};
|
||||||
string,
|
|
||||||
Record<string, TargetConfiguration>
|
|
||||||
> = {};
|
|
||||||
|
|
||||||
function readTargetsCache(): Record<
|
function readTargetsCache(): Record<string, CypressTargets> {
|
||||||
string,
|
|
||||||
Record<string, TargetConfiguration<CypressExecutorOptions>>
|
|
||||||
> {
|
|
||||||
return readJsonFile(cachePath);
|
return readJsonFile(cachePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeTargetsToCache(
|
function writeTargetsToCache(targets: Record<string, CypressTargets>) {
|
||||||
targets: Record<
|
|
||||||
string,
|
|
||||||
Record<string, TargetConfiguration<CypressExecutorOptions>>
|
|
||||||
>
|
|
||||||
) {
|
|
||||||
writeJsonFile(cachePath, targets);
|
writeJsonFile(cachePath, targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +66,7 @@ export const createNodes: CreateNodes<CypressPluginOptions> = [
|
|||||||
getLockFileName(detectPackageManager(context.workspaceRoot)),
|
getLockFileName(detectPackageManager(context.workspaceRoot)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const targets = targetsCache[hash]
|
const { targets, ciTestingGroup } = targetsCache[hash]
|
||||||
? targetsCache[hash]
|
? targetsCache[hash]
|
||||||
: await buildCypressTargets(
|
: await buildCypressTargets(
|
||||||
configFilePath,
|
configFilePath,
|
||||||
@ -84,14 +75,25 @@ export const createNodes: CreateNodes<CypressPluginOptions> = [
|
|||||||
context
|
context
|
||||||
);
|
);
|
||||||
|
|
||||||
calculatedTargets[hash] = targets;
|
calculatedTargets[hash] = { targets, ciTestingGroup };
|
||||||
|
|
||||||
|
const project: Omit<ProjectConfiguration, 'root'> = {
|
||||||
|
projectType: 'application',
|
||||||
|
targets,
|
||||||
|
metadata: {
|
||||||
|
technologies: ['cypress'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ciTestingGroup) {
|
||||||
|
project.metadata.targetGroups = {
|
||||||
|
[`${projectRoot}:e2e-ci`]: ciTestingGroup,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
projects: {
|
projects: {
|
||||||
[projectRoot]: {
|
[projectRoot]: project,
|
||||||
projectType: 'application',
|
|
||||||
targets,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -104,9 +106,9 @@ function getOutputs(
|
|||||||
): string[] {
|
): string[] {
|
||||||
function getOutput(path: string): string {
|
function getOutput(path: string): string {
|
||||||
if (path.startsWith('..')) {
|
if (path.startsWith('..')) {
|
||||||
return join('{workspaceRoot}', join(projectRoot, path));
|
return joinPathFragments('{workspaceRoot}', projectRoot, path);
|
||||||
} else {
|
} else {
|
||||||
return join('{projectRoot}', path);
|
return joinPathFragments('{projectRoot}', path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,12 +147,17 @@ function getOutputs(
|
|||||||
return outputs;
|
return outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CypressTargets {
|
||||||
|
targets: Record<string, TargetConfiguration>;
|
||||||
|
ciTestingGroup: string[];
|
||||||
|
}
|
||||||
|
|
||||||
async function buildCypressTargets(
|
async function buildCypressTargets(
|
||||||
configFilePath: string,
|
configFilePath: string,
|
||||||
projectRoot: string,
|
projectRoot: string,
|
||||||
options: CypressPluginOptions,
|
options: CypressPluginOptions,
|
||||||
context: CreateNodesContext
|
context: CreateNodesContext
|
||||||
) {
|
): Promise<CypressTargets> {
|
||||||
const cypressConfig = await loadConfigFile(
|
const cypressConfig = await loadConfigFile(
|
||||||
join(context.workspaceRoot, configFilePath)
|
join(context.workspaceRoot, configFilePath)
|
||||||
);
|
);
|
||||||
@ -167,6 +174,7 @@ async function buildCypressTargets(
|
|||||||
const namedInputs = getNamedInputs(projectRoot, context);
|
const namedInputs = getNamedInputs(projectRoot, context);
|
||||||
|
|
||||||
const targets: Record<string, TargetConfiguration> = {};
|
const targets: Record<string, TargetConfiguration> = {};
|
||||||
|
let ciTestingGroup: string[] = [];
|
||||||
|
|
||||||
if ('e2e' in cypressConfig) {
|
if ('e2e' in cypressConfig) {
|
||||||
targets[options.targetName] = {
|
targets[options.targetName] = {
|
||||||
@ -214,8 +222,10 @@ async function buildCypressTargets(
|
|||||||
const outputs = getOutputs(projectRoot, cypressConfig, 'e2e');
|
const outputs = getOutputs(projectRoot, cypressConfig, 'e2e');
|
||||||
const inputs = getInputs(namedInputs);
|
const inputs = getInputs(namedInputs);
|
||||||
for (const file of specFiles) {
|
for (const file of specFiles) {
|
||||||
const relativeSpecFilePath = relative(projectRoot, file);
|
const relativeSpecFilePath = normalizePath(relative(projectRoot, file));
|
||||||
const targetName = options.ciTargetName + '--' + relativeSpecFilePath;
|
const targetName = options.ciTargetName + '--' + relativeSpecFilePath;
|
||||||
|
|
||||||
|
ciTestingGroup.push(targetName);
|
||||||
targets[targetName] = {
|
targets[targetName] = {
|
||||||
outputs,
|
outputs,
|
||||||
inputs,
|
inputs,
|
||||||
@ -240,6 +250,7 @@ async function buildCypressTargets(
|
|||||||
outputs,
|
outputs,
|
||||||
dependsOn,
|
dependsOn,
|
||||||
};
|
};
|
||||||
|
ciTestingGroup.push(options.ciTargetName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,7 +265,11 @@ async function buildCypressTargets(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return targets;
|
if (ciTestingGroup.length === 0) {
|
||||||
|
ciTestingGroup = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { targets, ciTestingGroup };
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeOptions(options: CypressPluginOptions): CypressPluginOptions {
|
function normalizeOptions(options: CypressPluginOptions): CypressPluginOptions {
|
||||||
|
|||||||
@ -44,6 +44,7 @@ export const allowedProjectExtensions = [
|
|||||||
'projectType',
|
'projectType',
|
||||||
'release',
|
'release',
|
||||||
'includedScripts',
|
'includedScripts',
|
||||||
|
'metadata',
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
// If we pass props on the workspace that angular doesn't know about,
|
// If we pass props on the workspace that angular doesn't know about,
|
||||||
|
|||||||
@ -111,6 +111,10 @@ export interface ProjectConfiguration {
|
|||||||
'generator' | 'generatorOptions'
|
'generator' | 'generatorOptions'
|
||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
|
metadata?: {
|
||||||
|
technologies?: string[];
|
||||||
|
targetGroups?: Record<string, string[]>;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TargetDependencyConfig {
|
export interface TargetDependencyConfig {
|
||||||
|
|||||||
@ -731,6 +731,177 @@ describe('project-configuration-utils', () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should merge release', () => {
|
||||||
|
const rootMap = new RootMapBuilder()
|
||||||
|
.addProject({
|
||||||
|
root: 'libs/lib-a',
|
||||||
|
name: 'lib-a',
|
||||||
|
})
|
||||||
|
.getRootMap();
|
||||||
|
mergeProjectConfigurationIntoRootMap(rootMap, {
|
||||||
|
root: 'libs/lib-a',
|
||||||
|
name: 'lib-a',
|
||||||
|
release: {
|
||||||
|
version: {
|
||||||
|
generatorOptions: {
|
||||||
|
packageRoot: 'dist/libs/lib-a',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(rootMap.get('libs/lib-a').release).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"version": {
|
||||||
|
"generatorOptions": {
|
||||||
|
"packageRoot": "dist/libs/lib-a",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('metadata', () => {
|
||||||
|
it('should be set if not previously defined', () => {
|
||||||
|
const rootMap = new RootMapBuilder()
|
||||||
|
.addProject({
|
||||||
|
root: 'libs/lib-a',
|
||||||
|
name: 'lib-a',
|
||||||
|
})
|
||||||
|
.getRootMap();
|
||||||
|
const sourceMap: ConfigurationSourceMaps = {
|
||||||
|
'libs/lib-a': {},
|
||||||
|
};
|
||||||
|
mergeProjectConfigurationIntoRootMap(
|
||||||
|
rootMap,
|
||||||
|
{
|
||||||
|
root: 'libs/lib-a',
|
||||||
|
name: 'lib-a',
|
||||||
|
metadata: {
|
||||||
|
technologies: ['technology'],
|
||||||
|
targetGroups: {
|
||||||
|
group1: ['target1', 'target2'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sourceMap,
|
||||||
|
['dummy', 'dummy.ts']
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(rootMap.get('libs/lib-a').metadata).toEqual({
|
||||||
|
technologies: ['technology'],
|
||||||
|
targetGroups: {
|
||||||
|
group1: ['target1', 'target2'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(sourceMap['libs/lib-a']).toMatchObject({
|
||||||
|
'metadata.technologies': ['dummy', 'dummy.ts'],
|
||||||
|
'metadata.targetGroups': ['dummy', 'dummy.ts'],
|
||||||
|
'metadata.targetGroups.group1': ['dummy', 'dummy.ts'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should concat arrays', () => {
|
||||||
|
const rootMap = new RootMapBuilder()
|
||||||
|
.addProject({
|
||||||
|
root: 'libs/lib-a',
|
||||||
|
name: 'lib-a',
|
||||||
|
metadata: {
|
||||||
|
technologies: ['technology1'],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.getRootMap();
|
||||||
|
const sourceMap: ConfigurationSourceMaps = {
|
||||||
|
'libs/lib-a': {
|
||||||
|
'metadata.technologies': ['existing', 'existing.ts'],
|
||||||
|
'metadata.technologies.0': ['existing', 'existing.ts'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
mergeProjectConfigurationIntoRootMap(
|
||||||
|
rootMap,
|
||||||
|
{
|
||||||
|
root: 'libs/lib-a',
|
||||||
|
name: 'lib-a',
|
||||||
|
metadata: {
|
||||||
|
technologies: ['technology2'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sourceMap,
|
||||||
|
['dummy', 'dummy.ts']
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(rootMap.get('libs/lib-a').metadata).toEqual({
|
||||||
|
technologies: ['technology1', 'technology2'],
|
||||||
|
});
|
||||||
|
expect(sourceMap['libs/lib-a']).toMatchObject({
|
||||||
|
'metadata.technologies': ['existing', 'existing.ts'],
|
||||||
|
'metadata.technologies.0': ['existing', 'existing.ts'],
|
||||||
|
'metadata.technologies.1': ['dummy', 'dummy.ts'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should concat second level arrays', () => {
|
||||||
|
const rootMap = new RootMapBuilder()
|
||||||
|
.addProject({
|
||||||
|
root: 'libs/lib-a',
|
||||||
|
name: 'lib-a',
|
||||||
|
metadata: {
|
||||||
|
targetGroups: {
|
||||||
|
group1: ['target1'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.getRootMap();
|
||||||
|
const sourceMap: ConfigurationSourceMaps = {
|
||||||
|
'libs/lib-a': {
|
||||||
|
'metadata.targetGroups': ['existing', 'existing.ts'],
|
||||||
|
'metadata.targetGroups.group1': ['existing', 'existing.ts'],
|
||||||
|
'metadata.targetGroups.group1.0': ['existing', 'existing.ts'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
mergeProjectConfigurationIntoRootMap(
|
||||||
|
rootMap,
|
||||||
|
{
|
||||||
|
root: 'libs/lib-a',
|
||||||
|
name: 'lib-a',
|
||||||
|
metadata: {
|
||||||
|
targetGroups: {
|
||||||
|
group1: ['target2'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sourceMap,
|
||||||
|
['dummy', 'dummy.ts']
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(rootMap.get('libs/lib-a').metadata).toEqual({
|
||||||
|
targetGroups: {
|
||||||
|
group1: ['target1', 'target2'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(sourceMap['libs/lib-a']).toMatchObject({
|
||||||
|
'metadata.targetGroups': ['existing', 'existing.ts'],
|
||||||
|
'metadata.targetGroups.group1': ['existing', 'existing.ts'],
|
||||||
|
'metadata.targetGroups.group1.0': ['existing', 'existing.ts'],
|
||||||
|
'metadata.targetGroups.group1.1': ['dummy', 'dummy.ts'],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(sourceMap['libs/lib-a']['metadata.targetGroups']).toEqual([
|
||||||
|
'existing',
|
||||||
|
'existing.ts',
|
||||||
|
]);
|
||||||
|
expect(sourceMap['libs/lib-a']['metadata.targetGroups.group1']).toEqual(
|
||||||
|
['existing', 'existing.ts']
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
sourceMap['libs/lib-a']['metadata.targetGroups.group1.0']
|
||||||
|
).toEqual(['existing', 'existing.ts']);
|
||||||
|
expect(
|
||||||
|
sourceMap['libs/lib-a']['metadata.targetGroups.group1.1']
|
||||||
|
).toEqual(['dummy', 'dummy.ts']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('source map', () => {
|
describe('source map', () => {
|
||||||
it('should add new project info', () => {
|
it('should add new project info', () => {
|
||||||
const rootMap = new RootMapBuilder().getRootMap();
|
const rootMap = new RootMapBuilder().getRootMap();
|
||||||
|
|||||||
@ -60,12 +60,23 @@ export function mergeProjectConfigurationIntoRootMap(
|
|||||||
// a project.json in which case it was already updated above.
|
// a project.json in which case it was already updated above.
|
||||||
const updatedProjectConfiguration = {
|
const updatedProjectConfiguration = {
|
||||||
...matchingProject,
|
...matchingProject,
|
||||||
...project,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (sourceMap) {
|
for (const k in project) {
|
||||||
for (const property in project) {
|
if (
|
||||||
sourceMap[`${property}`] = sourceInformation;
|
![
|
||||||
|
'tags',
|
||||||
|
'implicitDependencies',
|
||||||
|
'generators',
|
||||||
|
'targets',
|
||||||
|
'metadata',
|
||||||
|
'namedInputs',
|
||||||
|
].includes(k)
|
||||||
|
) {
|
||||||
|
updatedProjectConfiguration[k] = project[k];
|
||||||
|
if (sourceMap) {
|
||||||
|
sourceMap[`${k}`] = sourceInformation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +87,7 @@ export function mergeProjectConfigurationIntoRootMap(
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (sourceMap) {
|
if (sourceMap) {
|
||||||
|
sourceMap['tags'] ??= sourceInformation;
|
||||||
project.tags.forEach((tag) => {
|
project.tags.forEach((tag) => {
|
||||||
sourceMap[`tags.${tag}`] = sourceInformation;
|
sourceMap[`tags.${tag}`] = sourceInformation;
|
||||||
});
|
});
|
||||||
@ -88,6 +100,7 @@ export function mergeProjectConfigurationIntoRootMap(
|
|||||||
).concat(project.implicitDependencies);
|
).concat(project.implicitDependencies);
|
||||||
|
|
||||||
if (sourceMap) {
|
if (sourceMap) {
|
||||||
|
sourceMap['implicitDependencies'] ??= sourceInformation;
|
||||||
project.implicitDependencies.forEach((implicitDependency) => {
|
project.implicitDependencies.forEach((implicitDependency) => {
|
||||||
sourceMap[`implicitDependencies.${implicitDependency}`] =
|
sourceMap[`implicitDependencies.${implicitDependency}`] =
|
||||||
sourceInformation;
|
sourceInformation;
|
||||||
@ -100,6 +113,7 @@ export function mergeProjectConfigurationIntoRootMap(
|
|||||||
updatedProjectConfiguration.generators = { ...project.generators };
|
updatedProjectConfiguration.generators = { ...project.generators };
|
||||||
|
|
||||||
if (sourceMap) {
|
if (sourceMap) {
|
||||||
|
sourceMap['generators'] ??= sourceInformation;
|
||||||
for (const generator in project.generators) {
|
for (const generator in project.generators) {
|
||||||
sourceMap[`generators.${generator}`] = sourceInformation;
|
sourceMap[`generators.${generator}`] = sourceInformation;
|
||||||
for (const property in project.generators[generator]) {
|
for (const property in project.generators[generator]) {
|
||||||
@ -127,6 +141,7 @@ export function mergeProjectConfigurationIntoRootMap(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (sourceMap) {
|
if (sourceMap) {
|
||||||
|
sourceMap['namedInputs'] ??= sourceInformation;
|
||||||
for (const namedInput in project.namedInputs) {
|
for (const namedInput in project.namedInputs) {
|
||||||
sourceMap[`namedInputs.${namedInput}`] = sourceInformation;
|
sourceMap[`namedInputs.${namedInput}`] = sourceInformation;
|
||||||
}
|
}
|
||||||
@ -137,6 +152,9 @@ export function mergeProjectConfigurationIntoRootMap(
|
|||||||
// We merge the targets with special handling, so clear this back to the
|
// We merge the targets with special handling, so clear this back to the
|
||||||
// targets as defined originally before merging.
|
// targets as defined originally before merging.
|
||||||
updatedProjectConfiguration.targets = matchingProject?.targets ?? {};
|
updatedProjectConfiguration.targets = matchingProject?.targets ?? {};
|
||||||
|
if (sourceMap) {
|
||||||
|
sourceMap['targets'] ??= sourceInformation;
|
||||||
|
}
|
||||||
|
|
||||||
// For each target defined in the new config
|
// For each target defined in the new config
|
||||||
for (const targetName in project.targets) {
|
for (const targetName in project.targets) {
|
||||||
@ -176,6 +194,81 @@ export function mergeProjectConfigurationIntoRootMap(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (project.metadata) {
|
||||||
|
if (sourceMap) {
|
||||||
|
sourceMap['targets'] ??= sourceInformation;
|
||||||
|
}
|
||||||
|
for (const [metadataKey, value] of Object.entries({
|
||||||
|
...project.metadata,
|
||||||
|
})) {
|
||||||
|
const existingValue = matchingProject.metadata?.[metadataKey];
|
||||||
|
|
||||||
|
if (Array.isArray(value) && Array.isArray(existingValue)) {
|
||||||
|
for (const item of [...value]) {
|
||||||
|
const newLength =
|
||||||
|
updatedProjectConfiguration.metadata[metadataKey].push(item);
|
||||||
|
if (sourceMap) {
|
||||||
|
sourceMap[`metadata.${metadataKey}.${newLength - 1}`] =
|
||||||
|
sourceInformation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (Array.isArray(value) && existingValue === undefined) {
|
||||||
|
updatedProjectConfiguration.metadata ??= {};
|
||||||
|
updatedProjectConfiguration.metadata[metadataKey] ??= value;
|
||||||
|
if (sourceMap) {
|
||||||
|
sourceMap[`metadata.${metadataKey}`] = sourceInformation;
|
||||||
|
}
|
||||||
|
for (let i = 0; i < value.length; i++) {
|
||||||
|
if (sourceMap) {
|
||||||
|
sourceMap[`metadata.${metadataKey}.${i}`] = sourceInformation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
typeof value === 'object' &&
|
||||||
|
typeof existingValue === 'object'
|
||||||
|
) {
|
||||||
|
for (const key in value) {
|
||||||
|
const existingValue = matchingProject.metadata?.[metadataKey]?.[key];
|
||||||
|
|
||||||
|
if (Array.isArray(value[key]) && Array.isArray(existingValue)) {
|
||||||
|
for (const item of value[key]) {
|
||||||
|
const i =
|
||||||
|
updatedProjectConfiguration.metadata[metadataKey][key].push(
|
||||||
|
item
|
||||||
|
);
|
||||||
|
if (sourceMap) {
|
||||||
|
sourceMap[`metadata.${metadataKey}.${key}.${i - 1}`] =
|
||||||
|
sourceInformation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updatedProjectConfiguration.metadata[metadataKey] = value;
|
||||||
|
if (sourceMap) {
|
||||||
|
sourceMap[`metadata.${metadataKey}`] = sourceInformation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
updatedProjectConfiguration.metadata[metadataKey] = value;
|
||||||
|
if (sourceMap) {
|
||||||
|
sourceMap[`metadata.${metadataKey}`] = sourceInformation;
|
||||||
|
|
||||||
|
if (typeof value === 'object') {
|
||||||
|
for (const k in value) {
|
||||||
|
sourceMap[`metadata.${metadataKey}.${k}`] = sourceInformation;
|
||||||
|
if (Array.isArray(value[k])) {
|
||||||
|
for (let i = 0; i < value[k].length; i++) {
|
||||||
|
sourceMap[`metadata.${metadataKey}.${k}.${i}`] =
|
||||||
|
sourceInformation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
projectRootMap.set(
|
projectRootMap.set(
|
||||||
updatedProjectConfiguration.root,
|
updatedProjectConfiguration.root,
|
||||||
updatedProjectConfiguration
|
updatedProjectConfiguration
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user