This is the base library of lenne.Tech for Angular. It contains the npm package ng-base.
This library contains all the basics to start a new project in combination with the lenne.Tech Nest Server:
- GraphQL service and elements for easy communication with GraphQL API (via Models)
- Standard Model with methods for mapping, cloning and comparing models
- Basic User Model with basic rights handling
- Loading Service for the subscription of loading processes
- Storage Service for comfortable saving of data in local storage
- GraphQL service and elements for easy communication with GraphQL API (via Models)
- Authentication service for user registration
- and much more
The detailed description of the features and instructions on how to use the library can be found in the README.md of the library.
For setting up a new project we recommend our Angular Starter, which already contains this library and also includes a few sample elements as templates.
- Node.js LTS (with npm)
- Angular CLI
npm run packAfterwards, the package can be included in an Angular project as follows in the package.json on a test basis:
{
"dependencies": {
"@lenne.tech/ng-graphql-client": "file:/PATH_TO_PROJECT/ng-base/dist/graphql-client/lenne.tech-ng-base-X.X.X.tgz"
}
}Update version in projects/graphql-client/package.json and projects/graphql-client/package-lock.json.
After that, the new package can be published as follows:
npm run publishThe initialization of this library is inspired by The Best Way To Architect Your Angular Libraries from Thomas Trajan.
Init Angular
ng new ng-base --createApplication false --prefix lt
ng g library ng-base --prefix ltChange package name in projects/ng-base/src
"name": "@lenne.tech/ng-base"
Replace path configuration in tsconfig.json:
{
"paths": {
"@lenne.tech/ng-base/*": ["projects/ng-base/*", "projects/ng-base"],
"@lenne.tech/ng-base": ["dist/ng-base/*", "dist/ng-base"]
}
}Delete the content of the projects/some-lib/src/lib/ folder and remove content of the root public-api.ts file so that it’s empty.
Install ng-samurai to extend the Angular CLI for creating Sub-entries:
npm i -D ng-samurai
Create new Sub-entry (without component --gc false and module --gm false):
ng g ng-samurai:generate-subentry core --gc false --gm false
Migration from TSLint (depracted since 2019) to ESLint (see Migrationsanleitung):
ng add @angular-eslint/schematics
ng g @angular-eslint/schematics:convert-tslint-to-eslint ng-base
rm tslint.json
npm uninstall tslint
npm uninstall codelyzerAdditional rules in .eslintrc.json:
{
"overrides": [
{
"rules": {
"no-underscore-dangle": "off"
}
}
]
}Install Prettier and prettier-quick:
npm install --save-dev --save-exact prettier
npm install --save-dev pretty-quickAdd file .prettierrc:
{
"arrowParens": "always",
"plugins": ["./extras/prettier-imports"],
"printWidth": 120,
"singleQuote": true
}Add file extras/prettier-imports.js:
const { parsers: typescriptParsers } = require('prettier/parser-typescript');
const ts = require('typescript');
// =============================================================================
// Prettier plugin to optimize and sort imports
// see https://github.com/prettier/prettier/issues/6260
// =============================================================================
class SingleLanguageServiceHost {
constructor(name, content) {
this.name = name;
this.content = content;
this.getCompilationSettings = ts.getDefaultCompilerOptions;
this.getDefaultLibFileName = ts.getDefaultLibFilePath;
}
getScriptFileNames() {
return [this.name];
}
getScriptVersion() {
return ts.version;
}
getScriptSnapshot() {
return ts.ScriptSnapshot.fromString(this.content);
}
getCurrentDirectory() {
return '';
}
}
function applyChanges(text, changes) {
return changes.reduceRight((text, change) => {
const head = text.slice(0, change.span.start);
const tail = text.slice(change.span.start + change.span.length);
return `${head}${change.newText}${tail}`;
}, text);
}
function organizeImports(text) {
const fileName = 'file.ts';
const host = new SingleLanguageServiceHost(fileName, text);
const languageService = ts.createLanguageService(host);
const formatOptions = ts.getDefaultFormatCodeSettings();
const fileChanges = languageService.organizeImports({ type: 'file', fileName }, formatOptions, {});
const textChanges = [...fileChanges.map((change) => change.textChanges)];
return applyChanges(text, textChanges);
}
const parsers = {
typescript: {
...typescriptParsers.typescript,
preprocess(text) {
text = organizeImports(text);
return text;
},
},
};
// Uses module.export because of 'Unexpected token export' error
module.exports = parsers;Add scripts in package.json:
"scripts": {
...
"format:check": "prettier --config ./.prettierrc --list-different \"src/{app,environments,assets}/**/*{.ts,.js,.json,.scss}\"",
"format:fix": "pretty-quick --staged",
"format:fixAll": "prettier --write src",
...
}format:check: Check only
format:fix: Optimize stage files
format:fixAll: Optimize all files
Install husky:
npm install --save-dev huskyAdd scripts in package.json:
"scripts": {
"check": "npm run format:fix && npm run lint",
"postinstall": "husky install .husky",
}Add pre-commit hook:
mkdir .husky
npx husky add .husky/pre-commit "cd $(dirname "$0") && npm run check"
Init husky via npm i.
To get a little more leeway in dealing with TypeScript's strict typing, the following rules should be disabled in compilerOptions of tsconfig.json:
{
"compilerOptions": {
"strictNullChecks": false,
"strictPropertyInitialization": false,
"noImplicitAny": false
}
}Many thanks to the developers of Angular, Apollo Angular and all the developers whose packages are used here.
MIT - see LICENSE