Skip to content

Commit

Permalink
feat(web): use helper to determine project name and root in applicati…
Browse files Browse the repository at this point in the history
…on generator (#18737)
  • Loading branch information
leosvelperez authored Aug 22, 2023
1 parent bb9f880 commit 6640c32
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 27 deletions.
11 changes: 8 additions & 3 deletions docs/generated/packages/web/generators/application.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "application",
"factory": "./src/generators/application/application#applicationGenerator",
"factory": "./src/generators/application/application#applicationGeneratorInternal",
"schema": {
"$schema": "http://json-schema.org/schema",
"cli": "nx",
Expand All @@ -14,12 +14,17 @@
"type": "string",
"$default": { "$source": "argv", "index": 0 },
"x-prompt": "What name would you like to use for the application?",
"pattern": "^[a-zA-Z].*$"
"pattern": "^[a-zA-Z][^:]*$"
},
"directory": {
"description": "The directory of the new application.",
"type": "string"
},
"projectNameAndRootFormat": {
"description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"style": {
"description": "The file extension to be used for style files.",
"type": "string",
Expand Down Expand Up @@ -107,7 +112,7 @@
"aliases": ["app"],
"x-type": "application",
"description": "Create an web application.",
"implementation": "/packages/web/src/generators/application/application#applicationGenerator.ts",
"implementation": "/packages/web/src/generators/application/application#applicationGeneratorInternal.ts",
"hidden": false,
"path": "/packages/web/src/generators/application/schema.json",
"type": "generator"
Expand Down
21 changes: 21 additions & 0 deletions e2e/web/src/web.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,27 @@ describe('Web Components Applications', () => {
runCLI(`build ${appName} --outputHashing none`);
checkFilesExist(`dist/apps/${appName}/main.js`);
}, 100000);

it('should support generating applications with the new name and root format', () => {
const appName = uniq('app1');

runCLI(
`generate @nx/web:app ${appName} --bundler=webpack --project-name-and-root-format=as-provided --no-interactive`
);

// check files are generated without the layout directory ("apps/") and
// using the project name as the directory when no directory is provided
checkFilesExist(`${appName}/src/main.ts`);
// check build works
expect(runCLI(`build ${appName}`)).toContain(
`Successfully ran target build for project ${appName}`
);
// check tests pass
const appTestResult = runCLI(`test ${appName}`);
expect(appTestResult).toContain(
`Successfully ran target test for project ${appName}`
);
}, 500_000);
});

describe('CLI - Environment Variables', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/web/generators.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"hidden": true
},
"application": {
"factory": "./src/generators/application/application#applicationGenerator",
"factory": "./src/generators/application/application#applicationGeneratorInternal",
"schema": "./src/generators/application/schema.json",
"aliases": ["app"],
"x-type": "application",
Expand Down
55 changes: 33 additions & 22 deletions packages/web/src/generators/application/application.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { join } from 'path';
import {
addDependenciesToPackageJson,
addProjectConfiguration,
convertNxGenerator,
ensurePackage,
extractLayoutDirectory,
formatFiles,
generateFiles,
GeneratorCallback,
Expand All @@ -22,11 +20,11 @@ import {
updateProjectConfiguration,
writeJson,
} from '@nx/devkit';
import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils';
import { getRelativePathToRootTsConfig } from '@nx/js';
import { swcCoreVersion } from '@nx/js/src/utils/versions';
import type { Linter } from '@nx/linter';

import { getRelativePathToRootTsConfig } from '@nx/js';

import { join } from 'path';
import { nxVersion, swcLoaderVersion } from '../../utils/versions';
import { webInitGenerator } from '../init/init';
import { Schema } from './schema';
Expand Down Expand Up @@ -180,7 +178,14 @@ function setDefaults(tree: Tree, options: NormalizedSchema) {
}

export async function applicationGenerator(host: Tree, schema: Schema) {
const options = normalizeOptions(host, schema);
return await applicationGeneratorInternal(host, {
projectNameAndRootFormat: 'derived',
...schema,
});
}

export async function applicationGeneratorInternal(host: Tree, schema: Schema) {
const options = await normalizeOptions(host, schema);

const tasks: GeneratorCallback[] = [];

Expand Down Expand Up @@ -264,8 +269,10 @@ export async function applicationGenerator(host: Tree, schema: Schema) {
>('@nx/cypress', nxVersion);
const cypressTask = await cypressProjectGenerator(host, {
...options,
name: `${options.name}-e2e`,
directory: options.directory,
name: options.e2eProjectName,
directory: options.e2eProjectRoot,
// the name and root are already normalized, instruct the generator to use them as is
projectNameAndRootFormat: 'as-provided',
project: options.projectName,
skipFormat: true,
});
Expand Down Expand Up @@ -341,23 +348,27 @@ export async function applicationGenerator(host: Tree, schema: Schema) {
return runTasksInSerial(...tasks);
}

function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
const { layoutDirectory, projectDirectory } = extractLayoutDirectory(
options.directory
);

const appDirectory = projectDirectory
? `${names(projectDirectory).fileName}/${names(options.name).fileName}`
: names(options.name).fileName;

const { appsDir: defaultAppsDir, npmScope } = getWorkspaceLayout(host);
const appsDir = layoutDirectory ?? defaultAppsDir;
async function normalizeOptions(
host: Tree,
options: Schema
): Promise<NormalizedSchema> {
const {
projectName: appProjectName,
projectRoot: appProjectRoot,
projectNameAndRootFormat,
} = await determineProjectNameAndRootOptions(host, {
name: options.name,
projectType: 'application',
directory: options.directory,
projectNameAndRootFormat: options.projectNameAndRootFormat,
callingGenerator: '@nx/web:application',
});
options.projectNameAndRootFormat = projectNameAndRootFormat;

const appProjectName = appDirectory.replace(new RegExp('/', 'g'), '-');
const e2eProjectName = `${appProjectName}-e2e`;
const e2eProjectRoot = `${appProjectRoot}-e2e`;

const appProjectRoot = joinPathFragments(appsDir, appDirectory);
const e2eProjectRoot = joinPathFragments(appsDir, `${appDirectory}-e2e`);
const { npmScope } = getWorkspaceLayout(host);

const parsedTags = options.tags
? options.tags.split(',').map((s) => s.trim())
Expand Down
2 changes: 2 additions & 0 deletions packages/web/src/generators/application/schema.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { ProjectNameAndRootFormat } from '@nx/devkit/src/generators/project-name-and-root-utils';
import type { Linter } from '@nx/linter';

export interface Schema {
Expand All @@ -8,6 +9,7 @@ export interface Schema {
compiler?: 'babel' | 'swc';
skipFormat?: boolean;
directory?: string;
projectNameAndRootFormat?: ProjectNameAndRootFormat;
tags?: string;
unitTestRunner?: 'jest' | 'vitest' | 'none';
inSourceTests?: boolean;
Expand Down
7 changes: 6 additions & 1 deletion packages/web/src/generators/application/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@
"index": 0
},
"x-prompt": "What name would you like to use for the application?",
"pattern": "^[a-zA-Z].*$"
"pattern": "^[a-zA-Z][^:]*$"
},
"directory": {
"description": "The directory of the new application.",
"type": "string"
},
"projectNameAndRootFormat": {
"description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
"type": "string",
"enum": ["as-provided", "derived"]
},
"style": {
"description": "The file extension to be used for style files.",
"type": "string",
Expand Down

0 comments on commit 6640c32

Please sign in to comment.