Skip to content

Commit

Permalink
feat(core): expand support for projectRoot token to include project.json
Browse files Browse the repository at this point in the history
  • Loading branch information
AgentEnder committed Aug 3, 2023
1 parent eef0bd5 commit f5e5b46
Show file tree
Hide file tree
Showing 5 changed files with 366 additions and 117 deletions.
67 changes: 67 additions & 0 deletions e2e/nx-run/src/run.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,73 @@ describe('Nx Running Tests', () => {

updateProjectConfig(mylib, (c) => original);
}, 1000000);

describe('tokens support', () => {
let app: string;

beforeAll(() => {
app = uniq('myapp');
runCLI(`generate @nx/web:app ${app}`);
});

it('should support using {projectRoot} in options blocks in project.json', async () => {
updateProjectConfig(app, (c) => {
c.targets['echo'] = {
command: `node -e 'console.log("{projectRoot}")'`,
};
return c;
});

const output = runCLI(`echo ${app}`);
expect(output).toContain(`apps/${app}`);
});

it('should support using {projectName} in options blocks in project.json', async () => {
updateProjectConfig(app, (c) => {
c.targets['echo'] = {
command: `node -e 'console.log("{projectName}")'`,
};
return c;
});

const output = runCLI(`echo ${app}`);
expect(output).toContain(app);
});

it('should support using {projectRoot} in targetDefaults', async () => {
updateJson(`nx.json`, (json) => {
json.targetDefaults = {
echo: {
command: `node -e 'console.log("{projectRoot}")'`,
},
};
return json;
});
updateProjectConfig(app, (c) => {
c.targets['echo'] = {};
return c;
});
const output = runCLI(`echo ${app}`);
expect(output).toContain(`apps/${app}`);
});

it('should support using {projectName} in targetDefaults', async () => {
updateJson(`nx.json`, (json) => {
json.targetDefaults = {
echo: {
command: `node -e 'console.log("{projectName}")'`,
},
};
return json;
});
updateProjectConfig(app, (c) => {
c.targets['echo'] = {};
return c;
});
const output = runCLI(`echo ${app}`);
expect(output).toContain(app);
});
});
});

describe('Nx Bail', () => {
Expand Down
55 changes: 0 additions & 55 deletions packages/nx/src/config/workspaces.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,30 +256,6 @@ describe('Workspaces', () => {
).options
).toEqual({ a: 'project-value' });
});

it('should resolve workspaceRoot and projectRoot tokens', () => {
expect(
mergeTargetConfigurations(
{
root: 'my/project',
targets: {
build: {
options: {
a: '{workspaceRoot}',
},
},
},
},
'build',
{
executor: 'target',
options: {
b: '{workspaceRoot}/dist/{projectRoot}',
},
}
).options
).toEqual({ a: '{workspaceRoot}', b: 'dist/my/project' });
});
});

describe('configurations', () => {
Expand Down Expand Up @@ -392,37 +368,6 @@ describe('Workspaces', () => {
).configurations
).toEqual(projectConfigurations);
});

it('should resolve workspaceRoot and projectRoot tokens', () => {
expect(
mergeTargetConfigurations(
{
root: 'my/project',
targets: {
build: {
configurations: {
dev: {
a: '{workspaceRoot}',
},
},
},
},
},
'build',
{
executor: 'target',
configurations: {
prod: {
a: '{workspaceRoot}/dist/{projectRoot}',
},
},
}
).configurations
).toEqual({
dev: { a: '{workspaceRoot}' },
prod: { a: 'dist/my/project' },
});
});
});

describe('defaultConfiguration', () => {
Expand Down
58 changes: 20 additions & 38 deletions packages/nx/src/config/workspaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export class Workspaces {
) {
for (const proj of Object.values(projects)) {
if (proj.targets) {
for (const targetName of Object.keys(proj.targets)) {
for (const targetName of Object.keys(proj.targets ?? {})) {
const projectTargetDefinition = proj.targets[targetName];
const defaults = readTargetDefaultsForTarget(
targetName,
Expand Down Expand Up @@ -393,62 +393,44 @@ export function mergeTargetConfigurations(
!targetConfiguration.executor ||
targetDefaults.executor === targetConfiguration.executor
) {
result.options = mergeOptions(
defaultOptions,
targetConfiguration.options ?? {},
projectConfiguration,
target
);
result.options = { ...defaultOptions, ...targetConfiguration?.options };
result.configurations = mergeConfigurations(
defaultConfigurations,
targetConfiguration.configurations,
projectConfiguration,
target
targetConfiguration.configurations
);
}
return result as TargetConfiguration;
}

function mergeOptions<T extends Object>(
defaults: T,
options: T,
project: ProjectConfiguration,
key: string
): T {
return {
...resolvePathTokensInOptions(defaults, project, key),
...options,
};
}

function mergeConfigurations<T extends Object>(
defaultConfigurations: Record<string, T>,
projectDefinedConfigurations: Record<string, T>,
project: ProjectConfiguration,
targetName: string
projectDefinedConfigurations: Record<string, T>
): Record<string, T> {
const configurations: Record<string, T> = { ...projectDefinedConfigurations };
for (const configuration in defaultConfigurations) {
configurations[configuration] = mergeOptions(
defaultConfigurations[configuration],
configurations[configuration],
project,
`${targetName}.${configuration}`
);
const result: Record<string, T> = {};
const configurations = new Set([
...Object.keys(defaultConfigurations ?? {}),
...Object.keys(projectDefinedConfigurations ?? {}),
]);
for (const configuration of configurations) {
result[configuration] = {
...(defaultConfigurations?.[configuration] ?? ({} as T)),
...(projectDefinedConfigurations?.[configuration] ?? ({} as T)),
};
}
return configurations;
return result;
}

function resolvePathTokensInOptions<T extends Object | Array<unknown>>(
export function resolveNxTokensInOptions<T extends Object | Array<unknown>>(
object: T,
project: ProjectConfiguration,
key: string
): T {
const result: T = Array.isArray(object) ? ([...object] as T) : { ...object };
for (let [opt, value] of Object.entries(object ?? {})) {
if (typeof value === 'string') {
if (value.startsWith('{workspaceRoot}/')) {
value = value.replace(/^\{workspaceRoot\}\//, '');
const workspaceRootMatch = /^(\{workspaceRoot\}\/?)/.exec(value);
if (workspaceRootMatch?.length) {
value = value.replace(workspaceRootMatch[0], '');
}
if (value.includes('{workspaceRoot}')) {
throw new Error(
Expand All @@ -458,7 +440,7 @@ function resolvePathTokensInOptions<T extends Object | Array<unknown>>(
value = value.replace(/\{projectRoot\}/g, project.root);
result[opt] = value.replace(/\{projectName\}/g, project.name);
} else if (typeof value === 'object' && value) {
result[opt] = resolvePathTokensInOptions(
result[opt] = resolveNxTokensInOptions(
value,
project,
[key, opt].join('.')
Expand Down
Loading

0 comments on commit f5e5b46

Please sign in to comment.