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 pack
Afterwards, 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 publish
The 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 lt
Change 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 codelyzer
Additional 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-quick
Add 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 husky
Add 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