Skip to content
This repository has been archived by the owner on Aug 5, 2024. It is now read-only.

Commit

Permalink
feat: Schematic for extracting libraries from projects
Browse files Browse the repository at this point in the history
JIRA-Ticket: AV-27910
  • Loading branch information
jeka-gom committed Jan 3, 2024
1 parent 528c54d commit b1e54f1
Show file tree
Hide file tree
Showing 12 changed files with 420 additions and 3 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "avrios-schematics",
"version": "2.5.0",
"version": "2.6.0",
"description": "A blank schematics",
"scripts": {
"build": "tsc -p tsconfig.json"
Expand Down
5 changes: 5 additions & 0 deletions src/collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
"description": "Create an Avrios library",
"factory": "./library",
"schema": "./library/schema.json"
},
"extract-app-libs": {
"description": "Extract app libs from an Avrios project",
"factory": "./extract-app-libs",
"schema": "./extract-app-libs/schema.json"
}
}
}
41 changes: 41 additions & 0 deletions src/extract-app-libs/files/.eslintrc.json.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*", "**/*.stories.ts"],
"overrides": [
{
"files": ["*.ts"],
"extends": ["plugin:@nrwl/nx/angular", "plugin:@angular-eslint/template/process-inline-templates"],
"rules": {
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "avr",
"style": "camelCase"
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "avr",
"style": "kebab-case"
}
],
"@angular-eslint/no-output-on-prefix": "off",
"@typescript-eslint/no-namespace": "off"
},
"plugins": ["@typescript-eslint"],
"parserOptions": {
"project": "libs/<%= dasherize(name) %>/tsconfig-linter.json"
}
}, {
"files": ["*.html"],
"extends": ["plugin:@nrwl/nx/angular-template"],
"rules": {
"@angular-eslint/template/no-negated-async": "off",
"@angular-eslint/template/eqeqeq": "warn"
}
}
]
}
31 changes: 31 additions & 0 deletions src/extract-app-libs/files/jest.config.ts.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const esModules = ['design-system-toolkit', '.*\\.mjs$'].join('|');

module.exports = {
displayName: '<%= dasherize(name) %>',
preset: '../../jest.config.ts',
coverageDirectory: '../../coverage/libs/<%= dasherize(name) %>',
setupFilesAfterEnv: ['<rootDir>../../setupJest.ts'],
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.(html|svg)$',
},
},
transform: {
'^.+\\.(ts|mjs|js|html)$': 'jest-preset-angular',
[`(${esModules}).+\\.js$`]: 'babel-jest',
},
transformIgnorePatterns: [`node_modules/(?!${esModules})`],


moduleNameMapper: {
'^@shared(.*)$': '<rootDir>../shared/src/lib$1',
'^@<%= dasherize(name) %>(.*)$': '<rootDir>/src/lib$1'
},
snapshotSerializers: [
'jest-preset-angular/build/serializers/no-ng-attributes',
'jest-preset-angular/build/serializers/ng-snapshot',
'jest-preset-angular/build/serializers/html-comment',
],
testRunner: 'jest-jasmine2'
};
15 changes: 15 additions & 0 deletions src/extract-app-libs/files/tsconfig-linter.json.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "./tsconfig.json",
"include": [
"./**/*.ts",
"src/**/*.ts"
],
"exclude": [
"../../dist/**/*",
"../../release/**/*",
"../../node_modules/**/*",
"../../tmp/**/*",
"**/*.stories.ts",
"**/*.stories.js"
]
}
19 changes: 19 additions & 0 deletions src/extract-app-libs/files/tsconfig.json.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"extends": "../../tsconfig.json",
"files": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"compilerOptions": {
"paths": {
"@shared/*": ["libs/shared/src/lib/*"],
"@<%= dasherize(namespace) %>/*": ["libs/<%= dasherize(name) %>/src/lib/*"]
},
"target": "es2020"
}
}
19 changes: 19 additions & 0 deletions src/extract-app-libs/files/tsconfig.lib.json.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": [
"angular-loading-bar",
"angular-promise-tracker",
"angular-translate",
"ng-file-upload",
"node"
]
},
"exclude": [
"**/*.spec.ts"
],
"include": [
"**/*.ts"
]
}
17 changes: 17 additions & 0 deletions src/extract-app-libs/files/tsconfig.spec.json.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": [
"angular-ui-bootstrap",
"jest",
"node"
]
},
"include": [
"../../libs/**/*.d.ts",
"**/*.spec.ts",
"**/*.test.ts"
]
}
64 changes: 64 additions & 0 deletions src/extract-app-libs/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

149 changes: 149 additions & 0 deletions src/extract-app-libs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { strings } from '@angular-devkit/core';
import {
Rule,
SchematicsException,
Tree,
apply,
applyTemplates,
chain,
mergeWith,
move,
url
} from '@angular-devkit/schematics';

import { validateName } from '../utilities/validation';
import { parseName } from '../utilities/parse-name';

interface LibraryOptions {
name: string;
prefix: string;
tags?: string;
namespace?: string;
path?: string;
}

export default function (options: LibraryOptions): Rule {
return (host: Tree) => {
const projectJsonFile = '/project.json';
const { prefix, name, tags: tagsString } = options;
const dasherizedName = strings.dasherize(name);

const projectLibsRoot = `libs/${dasherizedName}`;

const parsedPath = parseName(projectLibsRoot, name);
validateName(parsedPath.name);

const appScope = `scope:${dasherizedName}`;
const namespace = options.namespace ? options.namespace : parsedPath.name;
const paths: Record<string, string[]>= {};

const libraryNames = host.getDir(`${projectLibsRoot}/src/lib`).subdirs;
libraryNames.forEach(libraryName => {
validateName(libraryName);
const sourceRoot = `${projectLibsRoot}/src/lib/${libraryName}`;
paths[`@${namespace}/${libraryName}/*`] = [`${projectLibsRoot}/src/lib/${libraryName}/*`];

const projectConfig = {
name: `${dasherizedName}-${libraryName}`,
sourceRoot,
prefix,
tags: [appScope],
projectType: 'library',
generators: {},
targets: {
lint: {
executor: '@nrwl/linter:eslint',
options: {
lintFilePatterns: [
`${sourceRoot}/**/*.ts`,
`${sourceRoot}/**/*.html`
],
eslintConfig: `${projectLibsRoot}/.eslintrc.json`
}
},
test: {
executor: '@nrwl/jest:jest',
options: {
jestConfig: `${projectLibsRoot}/jest.config.ts`,
passWithNoTests: true,
testPathPattern: [`lib/${libraryName}/`]
}
}
}
};

host.exists(`${sourceRoot}/${projectJsonFile}`) || host.create(`${sourceRoot}/${projectJsonFile}`, JSON.stringify(projectConfig));
});

const appTsConfigPath = `apps/${dasherizedName}/tsconfig.json`;
const appEslintrcPath = `apps/${dasherizedName}/.eslintrc.json`;
const eslintrcPath = `/.eslintrc.json`;

const appTsConfig = host.read(appTsConfigPath);
const appEslintrc = host.read(appEslintrcPath);
const eslintrc = host.read(eslintrcPath);

if (!appTsConfig) {
throw new SchematicsException(`Could not find ${dasherizedName}/tsConfig.json file.`);
}

if (!appEslintrc) {
throw new SchematicsException(`Could not find ${dasherizedName}/.eslintrc.json file.`);
}

if (!eslintrc) {
throw new SchematicsException(`Could not find /.eslintrc.json file.`);
}

// Add new libs paths to tsconfig.json
const appTsConfigJson = JSON.parse(appTsConfig.toString());
appTsConfigJson.compilerOptions.paths = {
...paths,
...appTsConfigJson.compilerOptions.paths
};

// Remove deactivated eslint rule @nrwl/nx/enforce-module-boundaries rule from app's .eslintrc.json
const appEslintrcJson = JSON.parse(appEslintrc.toString());
appEslintrcJson.overrides.forEach((elem: any) => {
if (elem.rules && elem.rules['@nrwl/nx/enforce-module-boundaries'] === 'off') {
delete elem.rules['@nrwl/nx/enforce-module-boundaries'];
}
});

const eslintrcJson = JSON.parse(eslintrc.toString());
const tags = tagsString ? tagsString.split(',').map(s => s.trim()) : [];
eslintrcJson.overrides.forEach((elem: any) => {
if (elem.rules && elem.rules['@nrwl/nx/enforce-module-boundaries']) {
const found = elem.rules['@nrwl/nx/enforce-module-boundaries'][1].depConstraints.filter((constraint: any) => constraint.sourceTag === appScope);
if (!found || !found.length) {
elem.rules['@nrwl/nx/enforce-module-boundaries'][1].depConstraints.push(
{
sourceTag: appScope,
onlyDependOnLibsWithTags: [...tags, appScope]
}
);
}
}
});

host.overwrite(appTsConfigPath, JSON.stringify(appTsConfigJson));
host.overwrite(appEslintrcPath, JSON.stringify(appEslintrcJson));
host.overwrite(eslintrcPath, JSON.stringify(eslintrcJson));

options.name = parsedPath.name;
options.path = parsedPath.path;
options.namespace = namespace;

const templateSource = apply(
url('./files'), [
applyTemplates({ ...strings, ...options }),
move(projectLibsRoot),

]);

return chain([
_ => host,
mergeWith(templateSource)
]);
};
}
Loading

0 comments on commit b1e54f1

Please sign in to comment.