feat(core): add metadata to targets (#22655)
This commit is contained in:
parent
fc8d5ba828
commit
21f90cae85
@ -8,7 +8,7 @@ Project configuration
|
||||
|
||||
- [generators](../../devkit/documents/ProjectConfiguration#generators): Object
|
||||
- [implicitDependencies](../../devkit/documents/ProjectConfiguration#implicitdependencies): string[]
|
||||
- [metadata](../../devkit/documents/ProjectConfiguration#metadata): Object
|
||||
- [metadata](../../devkit/documents/ProjectConfiguration#metadata): ProjectMetadata
|
||||
- [name](../../devkit/documents/ProjectConfiguration#name): string
|
||||
- [namedInputs](../../devkit/documents/ProjectConfiguration#namedinputs): Object
|
||||
- [projectType](../../devkit/documents/ProjectConfiguration#projecttype): ProjectType
|
||||
@ -56,14 +56,9 @@ List of projects which are added as a dependency
|
||||
|
||||
### metadata
|
||||
|
||||
• `Optional` **metadata**: `Object`
|
||||
• `Optional` **metadata**: `ProjectMetadata`
|
||||
|
||||
#### Type declaration
|
||||
|
||||
| Name | Type |
|
||||
| :-------------- | :------------------------------- |
|
||||
| `targetGroups?` | `Record`\<`string`, `string`[]\> |
|
||||
| `technologies?` | `string`[] |
|
||||
Metadata about the project
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ Target's configuration
|
||||
- [dependsOn](../../devkit/documents/TargetConfiguration#dependson): (string | TargetDependencyConfig)[]
|
||||
- [executor](../../devkit/documents/TargetConfiguration#executor): string
|
||||
- [inputs](../../devkit/documents/TargetConfiguration#inputs): (string | InputDefinition)[]
|
||||
- [metadata](../../devkit/documents/TargetConfiguration#metadata): TargetMetadata
|
||||
- [options](../../devkit/documents/TargetConfiguration#options): T
|
||||
- [outputs](../../devkit/documents/TargetConfiguration#outputs): string[]
|
||||
|
||||
@ -86,6 +87,14 @@ This describes filesets, runtime dependencies and other inputs that a target dep
|
||||
|
||||
---
|
||||
|
||||
### metadata
|
||||
|
||||
• `Optional` **metadata**: `TargetMetadata`
|
||||
|
||||
Metadata about the target
|
||||
|
||||
---
|
||||
|
||||
### options
|
||||
|
||||
• `Optional` **options**: `T`
|
||||
|
||||
@ -3,6 +3,7 @@ import { defineConfig } from 'cypress';
|
||||
|
||||
import { createNodes } from './plugin';
|
||||
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
|
||||
import { resetWorkspaceContext } from 'nx/src/utils/workspace-context';
|
||||
import { join } from 'path';
|
||||
import { nxE2EPreset } from '../../plugins/cypress-preset';
|
||||
|
||||
@ -16,9 +17,9 @@ describe('@nx/cypress/plugin', () => {
|
||||
|
||||
await tempFs.createFiles({
|
||||
'package.json': '{}',
|
||||
'cypress.config.js': '',
|
||||
'src/test.cy.ts': '',
|
||||
});
|
||||
process.chdir(tempFs.tempDir);
|
||||
context = {
|
||||
nxJsonConfiguration: {
|
||||
// These defaults should be overridden by plugin
|
||||
@ -41,6 +42,11 @@ describe('@nx/cypress/plugin', () => {
|
||||
afterEach(() => {
|
||||
jest.resetModules();
|
||||
tempFs.cleanup();
|
||||
tempFs = null;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
resetWorkspaceContext();
|
||||
});
|
||||
|
||||
it('should add a target for e2e', async () => {
|
||||
@ -70,11 +76,7 @@ describe('@nx/cypress/plugin', () => {
|
||||
{
|
||||
"projects": {
|
||||
".": {
|
||||
"metadata": {
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
},
|
||||
"metadata": undefined,
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"e2e": {
|
||||
@ -94,6 +96,12 @@ describe('@nx/cypress/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Cypress Tests",
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
@ -104,6 +112,12 @@ describe('@nx/cypress/plugin', () => {
|
||||
},
|
||||
"open-cypress": {
|
||||
"command": "cypress open",
|
||||
"metadata": {
|
||||
"description": "Opens Cypress",
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
@ -140,11 +154,7 @@ describe('@nx/cypress/plugin', () => {
|
||||
{
|
||||
"projects": {
|
||||
".": {
|
||||
"metadata": {
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
},
|
||||
"metadata": undefined,
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"component-test": {
|
||||
@ -159,6 +169,12 @@ describe('@nx/cypress/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Cypress Component Tests",
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
@ -169,6 +185,12 @@ describe('@nx/cypress/plugin', () => {
|
||||
},
|
||||
"open-cypress": {
|
||||
"command": "cypress open",
|
||||
"metadata": {
|
||||
"description": "Opens Cypress",
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
@ -184,16 +206,16 @@ describe('@nx/cypress/plugin', () => {
|
||||
mockCypressConfig(
|
||||
defineConfig({
|
||||
e2e: {
|
||||
specPattern: '**/*.cy.ts',
|
||||
videosFolder: './dist/videos',
|
||||
screenshotsFolder: './dist/screenshots',
|
||||
...nxE2EPreset('.', {
|
||||
...nxE2EPreset(join(tempFs.tempDir, 'cypress.config.js'), {
|
||||
webServerCommands: {
|
||||
default: 'my-app:serve',
|
||||
production: 'my-app:serve:production',
|
||||
},
|
||||
ciWebServerCommand: 'my-app:serve-static',
|
||||
}),
|
||||
specPattern: '**/*.cy.ts',
|
||||
videosFolder: './dist/videos',
|
||||
screenshotsFolder: './dist/screenshots',
|
||||
},
|
||||
})
|
||||
);
|
||||
@ -216,9 +238,6 @@ describe('@nx/cypress/plugin', () => {
|
||||
"e2e-ci",
|
||||
],
|
||||
},
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
},
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
@ -239,12 +258,18 @@ describe('@nx/cypress/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Cypress Tests",
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
"outputs": [
|
||||
"{projectRoot}/dist/cypress/videos",
|
||||
"{projectRoot}/dist/cypress/screenshots",
|
||||
"{projectRoot}/dist/videos",
|
||||
"{projectRoot}/dist/screenshots",
|
||||
],
|
||||
},
|
||||
"e2e-ci": {
|
||||
@ -266,9 +291,15 @@ describe('@nx/cypress/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Cypress Tests in CI",
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
},
|
||||
"outputs": [
|
||||
"{projectRoot}/dist/cypress/videos",
|
||||
"{projectRoot}/dist/cypress/screenshots",
|
||||
"{projectRoot}/dist/videos",
|
||||
"{projectRoot}/dist/screenshots",
|
||||
],
|
||||
},
|
||||
"e2e-ci--src/test.cy.ts": {
|
||||
@ -283,16 +314,28 @@ describe('@nx/cypress/plugin', () => {
|
||||
],
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"description": "Runs Cypress Tests in src/test.cy.ts in CI",
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
"outputs": [
|
||||
"{projectRoot}/dist/cypress/videos",
|
||||
"{projectRoot}/dist/cypress/screenshots",
|
||||
"{projectRoot}/dist/videos",
|
||||
"{projectRoot}/dist/screenshots",
|
||||
],
|
||||
},
|
||||
"open-cypress": {
|
||||
"command": "cypress open",
|
||||
"metadata": {
|
||||
"description": "Opens Cypress",
|
||||
"technologies": [
|
||||
"cypress",
|
||||
],
|
||||
},
|
||||
"options": {
|
||||
"cwd": ".",
|
||||
},
|
||||
|
||||
@ -67,7 +67,7 @@ export const createNodes: CreateNodes<CypressPluginOptions> = [
|
||||
getLockFileName(detectPackageManager(context.workspaceRoot)),
|
||||
]);
|
||||
|
||||
const { targets, targetGroups } = targetsCache[hash]
|
||||
const { targets, metadata } = targetsCache[hash]
|
||||
? targetsCache[hash]
|
||||
: await buildCypressTargets(
|
||||
configFilePath,
|
||||
@ -76,20 +76,14 @@ export const createNodes: CreateNodes<CypressPluginOptions> = [
|
||||
context
|
||||
);
|
||||
|
||||
calculatedTargets[hash] = { targets, targetGroups };
|
||||
calculatedTargets[hash] = { targets, metadata };
|
||||
|
||||
const project: Omit<ProjectConfiguration, 'root'> = {
|
||||
projectType: 'application',
|
||||
targets,
|
||||
metadata: {
|
||||
technologies: ['cypress'],
|
||||
},
|
||||
metadata,
|
||||
};
|
||||
|
||||
if (targetGroups) {
|
||||
project.metadata.targetGroups = targetGroups;
|
||||
}
|
||||
|
||||
return {
|
||||
projects: {
|
||||
[projectRoot]: project,
|
||||
@ -146,10 +140,7 @@ function getOutputs(
|
||||
return outputs;
|
||||
}
|
||||
|
||||
interface CypressTargets {
|
||||
targets: Record<string, TargetConfiguration>;
|
||||
targetGroups: Record<string, string[]> | null;
|
||||
}
|
||||
type CypressTargets = Pick<ProjectConfiguration, 'targets' | 'metadata'>;
|
||||
|
||||
async function buildCypressTargets(
|
||||
configFilePath: string,
|
||||
@ -173,7 +164,7 @@ async function buildCypressTargets(
|
||||
const namedInputs = getNamedInputs(projectRoot, context);
|
||||
|
||||
const targets: Record<string, TargetConfiguration> = {};
|
||||
let targetGroups: Record<string, string[]>;
|
||||
let metadata: ProjectConfiguration['metadata'];
|
||||
|
||||
if ('e2e' in cypressConfig) {
|
||||
targets[options.targetName] = {
|
||||
@ -182,6 +173,10 @@ async function buildCypressTargets(
|
||||
cache: true,
|
||||
inputs: getInputs(namedInputs),
|
||||
outputs: getOutputs(projectRoot, cypressConfig, 'e2e'),
|
||||
metadata: {
|
||||
technologies: ['cypress'],
|
||||
description: 'Runs Cypress Tests',
|
||||
},
|
||||
};
|
||||
|
||||
if (webServerCommands?.default) {
|
||||
@ -222,8 +217,8 @@ async function buildCypressTargets(
|
||||
const inputs = getInputs(namedInputs);
|
||||
|
||||
const groupName = 'E2E (CI)';
|
||||
targetGroups = { [groupName]: [] };
|
||||
const ciTargetGroup = targetGroups[groupName];
|
||||
metadata = { targetGroups: { [groupName]: [] } };
|
||||
const ciTargetGroup = metadata.targetGroups[groupName];
|
||||
for (const file of specFiles) {
|
||||
const relativeSpecFilePath = normalizePath(relative(projectRoot, file));
|
||||
const targetName = options.ciTargetName + '--' + relativeSpecFilePath;
|
||||
@ -237,6 +232,10 @@ async function buildCypressTargets(
|
||||
options: {
|
||||
cwd: projectRoot,
|
||||
},
|
||||
metadata: {
|
||||
technologies: ['cypress'],
|
||||
description: `Runs Cypress Tests in ${relativeSpecFilePath} in CI`,
|
||||
},
|
||||
};
|
||||
dependsOn.push({
|
||||
target: targetName,
|
||||
@ -251,10 +250,12 @@ async function buildCypressTargets(
|
||||
inputs,
|
||||
outputs,
|
||||
dependsOn,
|
||||
metadata: {
|
||||
technologies: ['cypress'],
|
||||
description: 'Runs Cypress Tests in CI',
|
||||
},
|
||||
};
|
||||
ciTargetGroup.push(options.ciTargetName);
|
||||
} else {
|
||||
targetGroups = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,15 +267,23 @@ async function buildCypressTargets(
|
||||
cache: true,
|
||||
inputs: getInputs(namedInputs),
|
||||
outputs: getOutputs(projectRoot, cypressConfig, 'component'),
|
||||
metadata: {
|
||||
technologies: ['cypress'],
|
||||
description: 'Runs Cypress Component Tests',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
targets[options.openTargetName] = {
|
||||
command: `cypress open`,
|
||||
options: { cwd: projectRoot },
|
||||
metadata: {
|
||||
technologies: ['cypress'],
|
||||
description: 'Opens Cypress',
|
||||
},
|
||||
};
|
||||
|
||||
return { targets, targetGroups };
|
||||
return { targets, metadata };
|
||||
}
|
||||
|
||||
function normalizeOptions(options: CypressPluginOptions): CypressPluginOptions {
|
||||
|
||||
@ -111,10 +111,21 @@ export interface ProjectConfiguration {
|
||||
'generator' | 'generatorOptions'
|
||||
>;
|
||||
};
|
||||
metadata?: {
|
||||
technologies?: string[];
|
||||
targetGroups?: Record<string, string[]>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Metadata about the project
|
||||
*/
|
||||
metadata?: ProjectMetadata;
|
||||
}
|
||||
|
||||
export interface ProjectMetadata {
|
||||
technologies?: string[];
|
||||
targetGroups?: Record<string, string[]>;
|
||||
}
|
||||
|
||||
export interface TargetMetadata {
|
||||
description?: string;
|
||||
technologies?: string[];
|
||||
}
|
||||
|
||||
export interface TargetDependencyConfig {
|
||||
@ -203,4 +214,9 @@ export interface TargetConfiguration<T = any> {
|
||||
* Determines if Nx is able to cache a given target.
|
||||
*/
|
||||
cache?: boolean;
|
||||
|
||||
/**
|
||||
* Metadata about the target
|
||||
*/
|
||||
metadata?: TargetMetadata;
|
||||
}
|
||||
|
||||
@ -444,6 +444,101 @@ describe('project-configuration-utils', () => {
|
||||
expect(result.cache).not.toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('metadata', () => {
|
||||
it('should be added', () => {
|
||||
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',
|
||||
targets: {
|
||||
build: {
|
||||
metadata: {
|
||||
description: 'do stuff',
|
||||
technologies: ['tech'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceMap,
|
||||
['dummy', 'dummy.ts']
|
||||
);
|
||||
|
||||
expect(rootMap.get('libs/lib-a').targets.build.metadata).toEqual({
|
||||
description: 'do stuff',
|
||||
technologies: ['tech'],
|
||||
});
|
||||
expect(sourceMap['libs/lib-a']).toMatchObject({
|
||||
'targets.build.metadata.description': ['dummy', 'dummy.ts'],
|
||||
'targets.build.metadata.technologies': ['dummy', 'dummy.ts'],
|
||||
'targets.build.metadata.technologies.0': ['dummy', 'dummy.ts'],
|
||||
});
|
||||
});
|
||||
|
||||
it('should be merged', () => {
|
||||
const rootMap = new RootMapBuilder()
|
||||
.addProject({
|
||||
root: 'libs/lib-a',
|
||||
name: 'lib-a',
|
||||
targets: {
|
||||
build: {
|
||||
metadata: {
|
||||
description: 'do stuff',
|
||||
technologies: ['tech'],
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
.getRootMap();
|
||||
const sourceMap: ConfigurationSourceMaps = {
|
||||
'libs/lib-a': {
|
||||
'targets.build.metadata.technologies': ['existing', 'existing.ts'],
|
||||
'targets.build.metadata.technologies.0': [
|
||||
'existing',
|
||||
'existing.ts',
|
||||
],
|
||||
},
|
||||
};
|
||||
mergeProjectConfigurationIntoRootMap(
|
||||
rootMap,
|
||||
{
|
||||
root: 'libs/lib-a',
|
||||
name: 'lib-a',
|
||||
targets: {
|
||||
build: {
|
||||
metadata: {
|
||||
description: 'do cool stuff',
|
||||
technologies: ['tech2'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sourceMap,
|
||||
['dummy', 'dummy.ts']
|
||||
);
|
||||
|
||||
expect(rootMap.get('libs/lib-a').targets.build.metadata).toEqual({
|
||||
description: 'do cool stuff',
|
||||
technologies: ['tech', 'tech2'],
|
||||
});
|
||||
expect(sourceMap['libs/lib-a']).toMatchObject({
|
||||
'targets.build.metadata.description': ['dummy', 'dummy.ts'],
|
||||
'targets.build.metadata.technologies': ['existing', 'existing.ts'],
|
||||
'targets.build.metadata.technologies.0': ['existing', 'existing.ts'],
|
||||
'targets.build.metadata.technologies.1': ['dummy', 'dummy.ts'],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('mergeProjectConfigurationIntoRootMap', () => {
|
||||
|
||||
@ -2,7 +2,9 @@ import { NxJsonConfiguration, TargetDefaults } from '../../config/nx-json';
|
||||
import { ProjectGraphExternalNode } from '../../config/project-graph';
|
||||
import {
|
||||
ProjectConfiguration,
|
||||
ProjectMetadata,
|
||||
TargetConfiguration,
|
||||
TargetMetadata,
|
||||
} from '../../config/workspace-json-project-json';
|
||||
import { NX_PREFIX } from '../../utils/logger';
|
||||
import { CreateNodesResult, LoadedNxPlugin } from '../../utils/nx-plugin';
|
||||
@ -149,6 +151,16 @@ export function mergeProjectConfigurationIntoRootMap(
|
||||
}
|
||||
}
|
||||
|
||||
if (project.metadata) {
|
||||
updatedProjectConfiguration.metadata = mergeMetadata(
|
||||
sourceMap,
|
||||
sourceInformation,
|
||||
'metadata',
|
||||
project.metadata,
|
||||
matchingProject.metadata
|
||||
);
|
||||
}
|
||||
|
||||
if (project.targets) {
|
||||
// We merge the targets with special handling, so clear this back to the
|
||||
// targets as defined originally before merging.
|
||||
@ -195,85 +207,85 @@ 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];
|
||||
projectRootMap.set(
|
||||
updatedProjectConfiguration.root,
|
||||
updatedProjectConfiguration
|
||||
);
|
||||
}
|
||||
|
||||
if (Array.isArray(value) && Array.isArray(existingValue)) {
|
||||
for (const item of [...value]) {
|
||||
const newLength =
|
||||
updatedProjectConfiguration.metadata[metadataKey].push(item);
|
||||
function mergeMetadata<T = ProjectMetadata | TargetMetadata>(
|
||||
sourceMap: Record<string, [file: string, plugin: string]>,
|
||||
sourceInformation: [file: string, plugin: string],
|
||||
baseSourceMapPath: string,
|
||||
metadata: T,
|
||||
matchingMetadata?: T
|
||||
): T {
|
||||
const result: T = {
|
||||
...(matchingMetadata ?? ({} as T)),
|
||||
};
|
||||
for (const [metadataKey, value] of Object.entries(metadata)) {
|
||||
const existingValue = matchingMetadata?.[metadataKey];
|
||||
|
||||
if (Array.isArray(value) && Array.isArray(existingValue)) {
|
||||
for (const item of [...value]) {
|
||||
const newLength = result[metadataKey].push(item);
|
||||
if (sourceMap) {
|
||||
sourceMap[`${baseSourceMapPath}.${metadataKey}.${newLength - 1}`] =
|
||||
sourceInformation;
|
||||
}
|
||||
}
|
||||
} else if (Array.isArray(value) && existingValue === undefined) {
|
||||
result[metadataKey] ??= value;
|
||||
if (sourceMap) {
|
||||
sourceMap[`${baseSourceMapPath}.${metadataKey}`] = sourceInformation;
|
||||
}
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if (sourceMap) {
|
||||
sourceMap[`${baseSourceMapPath}.${metadataKey}.${i}`] =
|
||||
sourceInformation;
|
||||
}
|
||||
}
|
||||
} else if (typeof value === 'object' && typeof existingValue === 'object') {
|
||||
for (const key in value) {
|
||||
const existingValue = matchingMetadata?.[metadataKey]?.[key];
|
||||
|
||||
if (Array.isArray(value[key]) && Array.isArray(existingValue)) {
|
||||
for (const item of value[key]) {
|
||||
const i = result[metadataKey][key].push(item);
|
||||
if (sourceMap) {
|
||||
sourceMap[`${baseSourceMapPath}.${metadataKey}.${key}.${i - 1}`] =
|
||||
sourceInformation;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result[metadataKey] = value;
|
||||
if (sourceMap) {
|
||||
sourceMap[`metadata.${metadataKey}.${newLength - 1}`] =
|
||||
sourceMap[`${baseSourceMapPath}.${metadataKey}`] =
|
||||
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];
|
||||
}
|
||||
} else {
|
||||
result[metadataKey] = value;
|
||||
if (sourceMap) {
|
||||
sourceMap[`${baseSourceMapPath}.${metadataKey}`] = sourceInformation;
|
||||
|
||||
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}`] =
|
||||
if (typeof value === 'object') {
|
||||
for (const k in value) {
|
||||
sourceMap[`${baseSourceMapPath}.${metadataKey}.${k}`] =
|
||||
sourceInformation;
|
||||
if (Array.isArray(value[k])) {
|
||||
for (let i = 0; i < value[k].length; i++) {
|
||||
sourceMap[`${baseSourceMapPath}.${metadataKey}.${k}.${i}`] =
|
||||
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(
|
||||
updatedProjectConfiguration.root,
|
||||
updatedProjectConfiguration
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
export type ConfigurationResult = {
|
||||
@ -689,6 +701,17 @@ export function mergeTargetConfigurations(
|
||||
targetIdentifier
|
||||
);
|
||||
}
|
||||
|
||||
if (target.metadata) {
|
||||
result.metadata = mergeMetadata(
|
||||
projectConfigSourceMap,
|
||||
sourceInformation,
|
||||
`${targetIdentifier}.metadata`,
|
||||
target.metadata,
|
||||
baseTarget?.metadata
|
||||
);
|
||||
}
|
||||
|
||||
return result as TargetConfiguration;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user