feat(generator): create custom generator to create new libs

This commit is contained in:
thomas
2023-06-15 22:59:44 +02:00
parent 3eebb0e498
commit a0560ed906
22 changed files with 3131 additions and 298 deletions

View File

@@ -0,0 +1,10 @@
import { Component } from '@angular/core';
@Component({
standalone: true,
imports: [],
selector: 'app-root',
template: ``,
styles: [''],
})
export class AppComponent {}

View File

@@ -0,0 +1,33 @@
<h1><%= title %></h1>
> Author: Thomas Laforge
<!-- TODO: add Information/Statement/Rules/Constraint/Steps -->
### Information
### Statement
### Step 1
### Step 2
### Constraints:
### Submitting your work
1. Fork the project
2. clone it
3. npm install
4. `npx nx serve <%= projectName %>`
5. _...work on it_
6. Commit your work
7. Submit a PR with a title beginning with **Answer:<%= challengeNumber %>** that I will review and other dev can review.
<a href="https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A<%= challengeNumber %>+label%3Aanswer"><img src="https://img.shields.io/badge/-Solutions-green" alt="<%= projectName %>"/></a>
<a href='https://github.com/tomalaforge/angular-challenges/pulls?q=label%3A<%= challengeNumber %>+label%3A"answer+author"'><img src="https://img.shields.io/badge/-Author solution-important" alt="<%= projectName %> solution author"/></a>
<!-- <a href="{Blog post url}" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/-Blog post explanation-blue" alt="<%= projectName %> blog article"/></a> -->
_You can ask any question on_ <a href="https://twitter.com/laforge_toma" target="_blank" rel="noopener noreferrer"><img src="./../../logo/twitter.svg" height=20px alt="twitter"/></a>

View File

@@ -0,0 +1,8 @@
import { render } from '@testing-library/angular';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
test('...', async () => {
await render(AppComponent);
});
});

View File

@@ -0,0 +1,2 @@
import '@testing-library/jest-dom';
import 'jest-preset-angular/setup-jest';

View File

@@ -0,0 +1,15 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node", "@testing-library/jest-dom"]
},
"files": ["src/test-setup.ts"],
"include": [
"jest.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}

View File

@@ -0,0 +1,51 @@
import {
applicationGenerator,
E2eTestRunner,
UnitTestRunner,
} from '@nx/angular/generators';
import { formatFiles, generateFiles, names, Tree } from '@nx/devkit';
import { Linter } from '@nx/linter';
import { join } from 'path';
import { getProjectDir } from '../../utils/normalize';
import { Schema } from './schema';
export async function appGenerator(tree: Tree, options: Schema) {
const { appDirectory } = getProjectDir(options.name, options.directory);
await applicationGenerator(tree, {
...options,
style: 'scss',
routing: false,
inlineStyle: true,
inlineTemplate: true,
prefix: 'app',
unitTestRunner: options.addTest ? UnitTestRunner.Jest : UnitTestRunner.None,
e2eTestRunner: E2eTestRunner.None,
linter: Linter.EsLint,
addTailwind: true,
standalone: true,
skipTests: true,
});
generateFiles(tree, join(__dirname, 'files', 'app'), appDirectory, {
tmpl: '',
});
tree.delete(join(appDirectory, './src/app/nx-welcome.component.ts'));
generateFiles(tree, join(__dirname, 'files', 'readme'), appDirectory, {
tmpl: '',
projectName: names(options.name).name,
title: options.title,
challengeNumber: options.challengeNumber,
});
if (options.addTest) {
generateFiles(tree, join(__dirname, 'files', 'test'), appDirectory, {
tmpl: '',
});
}
await formatFiles(tree);
}
export default appGenerator;

View File

@@ -0,0 +1,9 @@
export interface Schema {
title: string;
challengeNumber: number;
name: string;
directory?: string;
addTest?: boolean;
skipPackageJson?: boolean;
rootProject?: boolean;
}

View File

@@ -0,0 +1,64 @@
{
"$schema": "http://json-schema.org/schema",
"$id": "GeneratorNxApp",
"title": "Creates an Angular application.",
"description": "Creates an Angular application.",
"type": "object",
"cli": "nx",
"properties": {
"name": {
"description": "The name of the application.",
"type": "string",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "What name would you like to use for the application?",
"pattern": "^[a-zA-Z].*$"
},
"title": {
"description": "Title of your challenge.",
"type": "string",
"$default": {
"$source": "argv",
"index": 1
},
"x-priority": "important"
},
"challengeNumber": {
"description": "The number of your challenge.",
"type": "number",
"$default": {
"$source": "argv",
"index": 2
},
"x-priority": "important"
},
"directory": {
"description": "The directory of the new application.",
"type": "string",
"x-priority": "important"
},
"addTest": {
"description": "add spec files.",
"type": "boolean",
"default": true,
"alias": "S"
},
"skipPackageJson": {
"type": "boolean",
"default": false,
"description": "Do not add dependencies to `package.json`.",
"x-priority": "internal"
},
"rootProject": {
"description": "Create an application at the root of the workspace.",
"type": "boolean",
"default": false,
"hidden": true,
"x-priority": "internal"
}
},
"additionalProperties": false,
"required": ["name", "title", "challengeNumber"]
}

0
libs/cli/src/index.ts Normal file
View File

View File

@@ -0,0 +1,43 @@
import { names } from '@nx/devkit';
export function normalizeDirectory(
appName: string,
directoryName: string
): string {
return directoryName
? `${names(directoryName).fileName}/${names(appName).fileName}`
: names(appName).fileName;
}
export function normalizeProjectName(
appName: string,
directoryName: string
): string {
return normalizeDirectory(appName, directoryName).replace(/\//g, '-');
}
export function extractLayoutDirectory(directory: string): {
layoutDirectory: string;
projectDirectory: string;
} {
if (directory) {
directory = directory.startsWith('/') ? directory.substring(1) : directory;
for (const dir of ['apps', 'libs', 'packages']) {
if (directory.startsWith(dir + '/') || directory === dir) {
return {
layoutDirectory: dir,
projectDirectory: directory.substring(dir.length + 1),
};
}
}
}
return { layoutDirectory: null, projectDirectory: directory };
}
export function getProjectDir(name: string, directory: string) {
const { projectDirectory } = extractLayoutDirectory(directory);
return {
appProjectName: normalizeProjectName(name, projectDirectory),
appDirectory: 'apps/' + normalizeDirectory(name, projectDirectory),
};
}