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

@@ -21,7 +21,9 @@
], ],
"@angular-eslint/no-host-metadata-property": [ "@angular-eslint/no-host-metadata-property": [
"error", "error",
{ "allowStatic": true } {
"allowStatic": true
}
] ]
} }
}, },
@@ -41,6 +43,11 @@
"jest": true "jest": true
}, },
"rules": {} "rules": {}
},
{
"files": "*.json",
"parser": "jsonc-eslint-parser",
"rules": {}
} }
] ]
} }

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"eslint.validate": ["json"]
}

25
libs/cli/.eslintrc.json Normal file
View File

@@ -0,0 +1,25 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
},
{
"files": ["./package.json"],
"parser": "jsonc-eslint-parser",
"rules": {
"@nx/nx-plugin-checks": "error"
}
}
]
}

7
libs/cli/README.md Normal file
View File

@@ -0,0 +1,7 @@
# cli
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build cli` to build the library.

9
libs/cli/generators.json Normal file
View File

@@ -0,0 +1,9 @@
{
"generators": {
"app": {
"factory": "./src/generators/app/generator",
"schema": "./src/generators/app/schema.json",
"description": "app generator"
}
}
}

6
libs/cli/package.json Normal file
View File

@@ -0,0 +1,6 @@
{
"name": "@angular-challenges/cli",
"version": "0.0.1",
"type": "commonjs",
"generators": "./generators.json"
}

48
libs/cli/project.json Normal file
View File

@@ -0,0 +1,48 @@
{
"name": "cli",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/cli/src",
"projectType": "library",
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/cli",
"main": "libs/cli/src/index.ts",
"tsConfig": "libs/cli/tsconfig.lib.json",
"assets": [
"libs/cli/*.md",
{
"input": "./libs/cli/src",
"glob": "**/!(*.ts)",
"output": "./src"
},
{
"input": "./libs/cli/src",
"glob": "**/*.d.ts",
"output": "./src"
},
{
"input": "./libs/cli",
"glob": "generators.json",
"output": "."
},
{
"input": "./libs/cli",
"glob": "executors.json",
"output": "."
}
]
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/cli/**/*.ts", "libs/cli/package.json"]
}
}
},
"tags": []
}

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),
};
}

13
libs/cli/tsconfig.json Normal file
View File

@@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs"
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}

View File

@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"include": ["src/**/*.ts", "../../apps/testing-modal/src/test-setup.ts"],
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
}

3035
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -30,16 +30,17 @@
"@ngrx/entity": "16.0.0", "@ngrx/entity": "16.0.0",
"@ngrx/router-store": "16.0.0", "@ngrx/router-store": "16.0.0",
"@ngrx/store": "16.0.0", "@ngrx/store": "16.0.0",
"@nx/angular": "16.2.1",
"@rx-angular/cdk": "^1.0.0-rc.4", "@rx-angular/cdk": "^1.0.0-rc.4",
"@rx-angular/state": "^1.7.0", "@rx-angular/state": "^1.7.0",
"@rx-angular/template": "^1.0.0-rc.5", "@rx-angular/template": "^1.0.0-rc.5",
"@swc/helpers": "~0.5.0",
"primeicons": "^6.0.1", "primeicons": "^6.0.1",
"primeng": "16.0.0-rc.2", "primeng": "16.0.0-rc.2",
"rxjs": "7.8.1", "rxjs": "7.8.1",
"tailwindcss": "^3.2.1", "tailwindcss": "^3.2.1",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "0.13.0", "zone.js": "0.13.0"
"@nx/angular": "16.2.1"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "16.0.2", "@angular-devkit/build-angular": "16.0.2",
@@ -55,13 +56,24 @@
"@commitlint/config-conventional": "^17.2.0", "@commitlint/config-conventional": "^17.2.0",
"@cypress/webpack-dev-server": "^2.0.0", "@cypress/webpack-dev-server": "^2.0.0",
"@ngrx/schematics": "16.0.0", "@ngrx/schematics": "16.0.0",
"@nx/cypress": "16.2.1",
"@nx/devkit": "16.3.2",
"@nx/eslint-plugin": "16.2.1",
"@nx/jest": "16.3.2",
"@nx/js": "16.3.2",
"@nx/linter": "16.2.1",
"@nx/plugin": "^16.3.2",
"@nx/workspace": "16.2.1",
"@schematics/angular": "16.0.2", "@schematics/angular": "16.0.2",
"@swc-node/register": "~1.4.2",
"@swc/cli": "~0.1.62",
"@swc/core": "~1.3.51",
"@testing-library/angular": "^13.3.0", "@testing-library/angular": "^13.3.0",
"@testing-library/cypress": "^9.0.0", "@testing-library/cypress": "^9.0.0",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/user-event": "^14.4.3", "@testing-library/user-event": "^14.4.3",
"@types/jest": "29.4.0", "@types/jest": "29.4.0",
"@types/node": "16.11.7", "@types/node": "18.7.1",
"@typescript-eslint/eslint-plugin": "5.59.7", "@typescript-eslint/eslint-plugin": "5.59.7",
"@typescript-eslint/parser": "5.59.7", "@typescript-eslint/parser": "5.59.7",
"cypress": "12.12.0", "cypress": "12.12.0",
@@ -73,6 +85,7 @@
"jest": "29.5.0", "jest": "29.5.0",
"jest-environment-jsdom": "29.5.0", "jest-environment-jsdom": "29.5.0",
"jest-preset-angular": "13.1.1", "jest-preset-angular": "13.1.1",
"jsonc-eslint-parser": "^2.1.0",
"lint-staged": "^13.0.3", "lint-staged": "^13.0.3",
"ng-packagr": "16.0.1", "ng-packagr": "16.0.1",
"nx": "16.2.1", "nx": "16.2.1",
@@ -84,14 +97,7 @@
"testing-library-selector": "^0.2.1", "testing-library-selector": "^0.2.1",
"ts-jest": "29.1.0", "ts-jest": "29.1.0",
"ts-node": "10.9.1", "ts-node": "10.9.1",
"typescript": "5.0.4", "typescript": "5.0.4"
"@nx/devkit": "16.2.1",
"@nx/workspace": "16.2.1",
"@nx/cypress": "16.2.1",
"@nx/linter": "16.2.1",
"@nx/js": "16.2.1",
"@nx/eslint-plugin": "16.2.1",
"@nx/jest": "16.2.1"
}, },
"lint-staged": { "lint-staged": {
"*.{ts,json,md}": [ "*.{ts,json,md}": [

View File

@@ -15,6 +15,7 @@
"skipDefaultLibCheck": true, "skipDefaultLibCheck": true,
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@angular-challenges/cli": ["libs/cli/src/index.ts"],
"@angular-challenges/ngrx-notification/backend": [ "@angular-challenges/ngrx-notification/backend": [
"libs/ngrx-notification/backend/src/index.ts" "libs/ngrx-notification/backend/src/index.ts"
], ],