Skip to content

Commit

Permalink
feat(core): added pathScheme for project generators (#464)
Browse files Browse the repository at this point in the history
Co-authored-by: Richard Compton <rich.compton@curvedental.com>
  • Loading branch information
rcompton78 and richcomptoncurve authored Jul 18, 2022
1 parent 5d69a5e commit ded5eb8
Show file tree
Hide file tree
Showing 16 changed files with 190 additions and 32 deletions.
4 changes: 4 additions & 0 deletions docs/core/generators/application.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,7 @@ Generate a dotnet project under the application directory.
### skipSwaggerLib

- (): By default, if using webapi template, an additional library is scaffolded for swagger files. This skips that setup.

### pathScheme

- (string): Determines if the project should follow NX or dotnet path naming conventions
4 changes: 4 additions & 0 deletions docs/core/generators/library.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ Generate a dotnet project under the library directory.
### skipSwaggerLib

- (): By default, if using webapi template, an additional library is scaffolded for swagger files. This skips that setup.

### pathScheme

- (string): Determines if the project should follow NX or dotnet path naming conventions
4 changes: 4 additions & 0 deletions docs/core/generators/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,7 @@ Generate a .NET test project for an existing application or library
- (string): The name of the solution file to add the project to

- (boolean): Should the project be added to the default solution file?

### pathScheme

- (string): Determines if the project should follow NX or dotnet path naming conventions
22 changes: 22 additions & 0 deletions e2e/core-e2e/tests/nx-dotnet.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,28 @@ describe('nx-dotnet e2e', () => {
});
});

describe('nx g using dotnet pathSchema', () => {
it('no directory', async () => {
const libName = uniq('CurveDental.Foobar.SomeLib');
await runNxCommandAsync(
`generate @nx-dotnet/core:lib ${libName} --language="C#" --template="classlib" --pathScheme=dotnet`,
);

expect(() => checkFilesExist(`libs/${libName}`)).not.toThrow();
expect(() => checkFilesExist(`libs/${libName}.Test`)).not.toThrow();
});

it('with directory', async () => {
const libName = uniq('CurveDental.Foobar.SomeLib');
await runNxCommandAsync(
`generate @nx-dotnet/core:lib ${libName} --language="C#" --template="classlib" --pathScheme=dotnet --directory foo`,
);

expect(() => checkFilesExist(`libs/foo/${libName}`)).not.toThrow();
expect(() => checkFilesExist(`libs/foo/${libName}.Test`)).not.toThrow();
});
});

describe('nx g import-projects', () => {
it('should import apps, libs, and test', async () => {
const testApp = uniq('app');
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/generators/app/generator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ describe('nx-dotnet app generator', () => {
projectType: 'application',
standalone: false,
skipSwaggerLib: true,
pathScheme: 'nx',
};

beforeEach(() => {
Expand Down
14 changes: 14 additions & 0 deletions packages/core/src/generators/app/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,20 @@
"skipSwaggerLib": {
"description": "By default, if using webapi template, an additional library is scaffolded for swagger files. This skips that setup.",
"default": true
},
"pathScheme": {
"description": "Determines if the project should follow NX or dotnet path naming conventions",
"type": "string",
"default": "nx",
"enum": ["nx", "dotnet"],
"x-prompt": {
"message": "Which path naming conventions should the project use?",
"type": "list",
"items": [
{ "value": "nx", "label": "NX naming conventions" },
{ "value": "dotnet", "label": "Dotnet naming conventions" }
]
}
}
},
"required": ["name", "language"]
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/generators/lib/generator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ describe('nx-dotnet library generator', () => {
standalone: false,
projectType: 'library',
skipSwaggerLib: true,
pathScheme: 'nx',
};

beforeEach(() => {
Expand Down
14 changes: 14 additions & 0 deletions packages/core/src/generators/lib/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@
"skipSwaggerLib": {
"description": "By default, if using webapi template, an additional library is scaffolded for swagger files. This skips that setup.",
"default": false
},
"pathScheme": {
"description": "Determines if the project should follow NX or dotnet path naming conventions",
"type": "string",
"default": "nx",
"enum": ["nx", "dotnet"],
"x-prompt": {
"message": "Which path naming conventions should the project use?",
"type": "list",
"items": [
{ "value": "nx", "label": "NX naming conventions" },
{ "value": "dotnet", "label": "Dotnet naming conventions" }
]
}
}
},
"required": ["name", "language", "testTemplate"]
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/generators/test/generator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ describe('nx-dotnet test generator', () => {
language: 'C#',
skipOutputPathManipulation: true,
standalone: false,
pathScheme: 'nx',
};

beforeEach(() => {
Expand Down
14 changes: 14 additions & 0 deletions packages/core/src/generators/test/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@
}
],
"alias": ["solution", "s"]
},
"pathScheme": {
"description": "Determines if the project should follow NX or dotnet path naming conventions",
"type": "string",
"default": "nx",
"enum": ["nx", "dotnet"],
"x-prompt": {
"message": "Which path naming conventions should the project use?",
"type": "list",
"items": [
{ "value": "nx", "label": "NX naming conventions" },
{ "value": "dotnet", "label": "Dotnet naming conventions" }
]
}
}
},
"required": ["name", "testTemplate"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ describe('nx-dotnet project generator', () => {
standalone: false,
skipSwaggerLib: true,
projectType: 'application',
pathScheme: 'nx',
};

jest.spyOn(dotnetClient, 'listInstalledTemplates').mockReturnValue([
Expand Down
113 changes: 85 additions & 28 deletions packages/core/src/generators/utils/generate-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,38 +55,21 @@ export async function normalizeOptions(
client?: DotNetClient,
projectType?: ProjectType,
): Promise<NormalizedSchema> {
const name = names(options.name).fileName;
const name = getNameFromSchema(options);
const className = names(options.name).className;
const projectDirectory = options.directory
? `${names(options.directory).fileName}/${name}`
: name;
const projectName = projectDirectory.replace(/\//g, '-');
const workspaceLayoutRoot =
(projectType || options.projectType) === 'application'
? getWorkspaceLayout(host).appsDir
: getWorkspaceLayout(host).libsDir;

const projectRoot = workspaceLayoutRoot
? joinPathFragments(workspaceLayoutRoot, projectDirectory)
: projectDirectory;

const parsedTags = options.tags
? options.tags.split(',').map((s) => s.trim())
: [];

const template = client
? await promptForTemplate(client, options.template, options.language)
: options.template;

const npmScope = names(
readWorkspaceConfiguration(host).npmScope || '',
).className;
const featureScope = projectDirectory
// not sure why eslint complains here, testing in devtools shows different results without the escape character.
// eslint-disable-next-line no-useless-escape
.split(/[\/\\]/gm) // Without the unnecessary parentheses, the separator is excluded from the result array.
.map((part: string) => names(part).className);
const namespaceName = [npmScope, ...featureScope].join('.');
const projectName = getProjectNameFromSchema(options, projectDirectory);
const projectRoot = getProjectRootFromSchema(
host,
options,
projectDirectory,
projectType,
);
const parsedTags = getProjectTagsFromSchema(options);
const template = await getTemplate(options, client);
const namespaceName = getNamespaceFromSchema(host, options, projectDirectory);

return {
...options,
Expand All @@ -103,6 +86,80 @@ export async function normalizeOptions(
};
}

function getNameFromSchema(options: NxDotnetProjectGeneratorSchema): string {
return options.pathScheme === 'nx'
? names(options.name).fileName
: options.name;
}

function getNamespaceFromSchema(
host: Tree,
options: NxDotnetProjectGeneratorSchema,
projectDirectory: string,
): string {
const npmScope = names(
readWorkspaceConfiguration(host).npmScope || '',
).className;
const featureScope = projectDirectory
// not sure why eslint complains here, testing in devtools shows different results without the escape character.
// eslint-disable-next-line no-useless-escape
.split(/[\/\\]/gm) // Without the unnecessary parentheses, the separator is excluded from the result array.
.map((part: string) => names(part).className);

return [npmScope, ...featureScope].join('.');
}

async function getTemplate(
options: NxDotnetProjectGeneratorSchema,
client?: DotNetClient,
): Promise<string> {
let template = options.template || '';
if (client) {
template = await promptForTemplate(
client,
options.template,
options.language,
);
}

return template;
}

function getProjectTagsFromSchema(
options: NxDotnetProjectGeneratorSchema,
): string[] {
return options.tags ? options.tags.split(',').map((s) => s.trim()) : [];
}

function getProjectRootFromSchema(
host: Tree,
options: NxDotnetProjectGeneratorSchema,
projectDirectory: string,
projectType?: string,
): string {
const workspaceLayoutRoot =
(projectType || options.projectType) === 'application'
? getWorkspaceLayout(host).appsDir
: getWorkspaceLayout(host).libsDir;

return workspaceLayoutRoot
? joinPathFragments(workspaceLayoutRoot, projectDirectory)
: projectDirectory;
}

function getProjectNameFromSchema(
options: NxDotnetProjectGeneratorSchema,
projectDirectory: string,
): string {
if (options.pathScheme === 'dotnet') {
return options.directory
? `${names(options.directory).className}.${options.name}`
: options.name;
}

return projectDirectory.replace(/\//g, '-');
}

export async function manipulateXmlProjectFile(
host: Tree,
options: Pick<NormalizedSchema, 'projectRoot' | 'projectName'>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ describe('nx-dotnet test project generator', () => {
skipSwaggerLib: true,
className: 'DomainExistingApp',
namespaceName: 'Domain.ExistingApp',
pathScheme: 'nx',
};
testProjectName = options.name + '-test';
});
Expand Down
26 changes: 22 additions & 4 deletions packages/core/src/generators/utils/generate-test-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@ import {
NormalizedSchema,
normalizeOptions,
} from './generate-project';
export interface PathParts {
suffix: string;
separator: '.' | '-';
}

function getPathPartsFromSchema(schema: NormalizedSchema): PathParts {
if (schema.pathScheme === 'nx') {
return {
separator: '-',
suffix: schema.testProjectNameSuffix || 'test',
};
} else {
return {
separator: '.',
suffix: schema.testProjectNameSuffix || 'Test',
};
}
}

export async function GenerateTestProject(
host: Tree,
Expand All @@ -24,9 +42,9 @@ export async function GenerateTestProject(
schema = await normalizeOptions(host, schema);
}

const suffix = schema.testProjectNameSuffix || 'test';
const testRoot = schema.projectRoot + '-' + suffix;
const testProjectName = schema.projectName + '-' + suffix;
const { separator, suffix } = getPathPartsFromSchema(schema);
const testRoot = schema.projectRoot + separator + suffix;
const testProjectName = schema.projectName + separator + suffix;

addProjectConfiguration(
host,
Expand All @@ -48,7 +66,7 @@ export async function GenerateTestProject(
const newParams: dotnetNewOptions = {
language: schema.language,
name: schema.namespaceName + '.' + names(suffix).className,
output: schema.projectRoot + '-' + suffix,
output: testRoot,
};

if (isDryRun()) {
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/models/project-generator-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ export interface NxDotnetProjectGeneratorSchema {
projectType?: ProjectType;
solutionFile?: string | boolean;
skipSwaggerLib: boolean;
pathScheme: 'nx' | 'dotnet';
}
1 change: 1 addition & 0 deletions packages/core/src/models/test-generator-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export interface NxDotnetTestGeneratorSchema {
suffix?: string;
skipOutputPathManipulation: boolean;
standalone: boolean;
pathScheme: 'nx' | 'dotnet';
}

0 comments on commit ded5eb8

Please sign in to comment.