@dflat-core/web
v1.7.2061
Published
Librairies Angular Dflat (core, core-*, system-*) et assets partagés, empaquetées en un module npm unique.
Readme
@dflat-core/web
Librairies Angular de Dflat, empaquetées en un module npm unique (Angular Package Format, construit avec ng-packagr).
Points d'entrée
| Import | Contenu |
| -------------------------- | ------------------------------------------------------------ |
| @dflat-core/web/core | Utilitaires, EnvironmentBase |
| @dflat-core/web/core-model | Modèle de base (interfaces générées depuis Dflat.Kernel.Model) |
| @dflat-core/web/core-services | Authentification, messages, menus, hub SignalR... |
| @dflat-core/web/core-data | DataService, EntityDataService |
| @dflat-core/web/core-ux | Composants, directives et services d'interface |
| @dflat-core/web/core-ux/testing | Suites de test standard (describeBaseComponent, describeGeneratedModule) et doublures, pour les fichiers .spec.ts |
| @dflat-core/web/system-model | Modèle du module System (généré) |
| @dflat-core/web/system-data | Services de données du module System (générés) |
| @dflat-core/web/system-root | Permissions, clés d'entités et menus du module System |
| @dflat-core/web/system-ux | Écrans du module System, et la coquille applicative |
Ressources non TypeScript livrées dans le package :
assets/: styles partagés (site.scss,variables.scss,text.scss...), images et polices ;scss/: styles globaux (dflat-app.scss,core-ux.scss,layout/default/default-layout.scss...).
Coquille applicative
system-ux fournit, en plus des écrans du module System, tout ce qui faisait auparavant
l'ossature de l'application hôte (system-ux/src/lib/app) :
| Symbole | Rôle |
| --------------------------------------------------------- | ----------------------------------------------------------- |
| DflatAppModule | Socle du module racine : modules Angular et tiers, intercepteur HTTP, permissions, menus, langue |
| DFlatLayoutComponent | Mise en page : barre supérieure, menu latéral, contenu |
| HomepageComponent, SearchComponent, SearchResultComponent | Accueil et recherche globale |
| UserMenuComponent, UserProfileComponent | Menu et profil de l'utilisateur |
| AccessDeniedComponent, HistoryComponent, DFlatSpinnerComponent | Écrans et composants utilitaires |
| DflatAppService | Nom, logo et version de l'application (EnvironmentBase) |
| DFlatAuthInterceptor, DFlatPermissionService | Implémentations par défaut, dérivables |
Le module racine d'une application se réduit alors à :
@NgModule({
declarations: [AppComponent],
imports: [DflatAppModule.forRoot(environment), routing],
bootstrap: [AppComponent]
})
export class AppModule {}environment implémente EnvironmentBase : URL de l'API, du hub et des fichiers, et, en
option, appName, appLogoUrl et appVersion, affichés par la mise en page et la page
d'accueil. Pour remplacer un service du socle (menus, permissions, intercepteur), il suffit
de le fournir après DflatAppModule dans les providers du module racine.
La recherche globale n'interroge que les sources déclarées par l'application : une classe
dérivée de DflatSearchProvider par famille d'objets, fournie en multi sous le jeton
DFLAT_SEARCH_PROVIDERS.
Tester
yarn test # tous les *.spec.ts du package (Vitest, jsdom)
yarn vitest run core-ux # un dossier ou un fichier
yarn tsc -p tsconfig.spec.json # contrôle des types des tests@dflat-core/web/core-ux/testing fournit la suite de test standard de BaseComponent :
describeBaseComponent('BaseCountryComponent', (app, route) => new TestCountryComponent(app, route), {
entityKey: 'country', path: '/sys/country', title: 'Pays', permissionKey: 'system.country', requestsSections: true
});Elle vérifie le contrat de BaseComponent sans rendre de gabarit : création dans un contexte
d'injection, clé d'entité, lien, titre et permission, façade demandée au registre avec la clé de
l'entité, ngOnInit (fil d'Ariane, chargement branché sur dataService.search, abonnement aux
notifications, demande des onglets au registre EntitySections), Search / refresh, mise à
jour sur notification, ngOnDestroy.
Elle n'utilise que les fonctions globales de l'outil de test (describe, it, beforeEach,
expect) et TestBed : elle ne dépend pas de l'outil. BaseComponentTestContext fournit les
services du composant (vraies classes du socle, doublures pour DataService et Router).
core-ux/src/lib/v2/components/base-component/base-component.spec.tsapplique la suite à un composant minimal et teste les cas propres à la classe ;dflat -g tsgénère, pour chaque composantBase<X>Componentd'un module,<x>.component.generated.spec.ts(la même suite, avec les valeurs attendues du générateur) et, par module,<module>-components.generated.spec.ts(describeGeneratedModule: chaque composant a sa route, clés d'entité uniques, onglets des entités liées attendus par entité et pointant vers des entités et composants du module, éléments de menu vers une route existante et porteurs d'une permission du module).
Les onglets des entités liées (sections @relations des formulaires) sont déclarés pour tout le
module par le service généré <Module>GeneratedSectionService
(<module>-sections.generated.ts), seul fichier généré qui importe les composants des onglets.
Le module Angular <module>-ux l'enregistre dans son constructeur,
EntitySections.register(injector.get(<Module>GeneratedSectionService)), et Base<X>Component
demande ses onglets par la clé de son entité
(EntitySections.registerSections(this.getEntityKey(), this.facade)), sans importer d'autre
composant : pas de dépendance circulaire entre composants. Le service n'est interrogé qu'une
fois par entité : la définition des onglets est gardée dans le cache d'initialisation des écrans
(InitCacheService, DataService.getCachedValue), comme les descripteurs de filtre et le filtre
vide, et vidée avec eux ; l'enregistrement sur la façade est fait à chaque initialisation.
Dans le package, Vitest est lancé directement (vitest.config.mts, tools/vitest.setup.ts), sans
angular.json : les décorateurs sont compilés en mode JIT et les gabarits remplacés par un
gabarit vide. Une application lance les mêmes tests par sa cible test
(@angular/build:unit-test, Vitest et jsdom), que le modèle dflat-webhost déclare
(yarn test dans webapps). Les .spec.ts ne sont pas publiés ; seul le point d'entrée
testing l'est.
Construire
yarn install
yarn build # <dépôt>/artifacts/nodejs/dflat-web (compilation partielle, publiable)
yarn watch # reconstruction continue pendant le développement
yarn run pack # <dépôt>/artifacts/nodejs/dflat-web-<version>.tgzDepuis la racine du dépôt, scripts/publish-dflat.ps1 enchaîne ces étapes :
.\scripts\publish-dflat.ps1 -bw # yarn install si besoin, build, vidage du cache Angular de webapps
.\scripts\publish-dflat.ps1 -pn # package versionné + archive .tgz (version calculée depuis npmjs.com)
.\scripts\publish-dflat.ps1 -pn -Push # ... puis publication sur npmjs.com, après confirmationyarn install applique tools/patch-ng-packagr.js : correctif d'un bug de ng-packagr 19.2 sur la réécriture
des url() des partials Sass (voir le commentaire du script).
Utiliser dans un espace de travail Angular / Nx
Dépendance, dans
package.json: la version publiée sur npmjs.com ("@dflat-core/web": "1.0.2"), cas de toute application, dont celles créées pardflat -newhost.webapps, dans le dépôt, n'en dépend pas : il compile les librairies depuis leurs sources, pour développer le package et l'application en même temps. Les chemins dewebapps/tsconfig.jsonmènent àwebapps/libs/dflat-web, une jonction par point d'entrée versweb/dflat-web:"@dflat-core/web": ["libs/dflat-web/src/index.ts"], "@dflat-core/web/*": ["libs/dflat-web/*/src/index.ts"]Les jonctions (non versionnées) sont créées par
webapps/tools/check-dflat-web.js, lancé paryarn startet pardflat -r/dflat -rc. Elles sont individuelles : une seule jonction versweb/dflat-webferait résoudre Angular dansweb/dflat-web/node_modules(double instance). Toute modification d'un fichier du package (TypeScript, template, style) est recompilée parnx servedans la foulée (quelques secondes), sans compilerdistni vider le cache. L'application doit aussi installer lespeerDependenciesdu package : les librairies Angular tierces qu'il utilise (ngx-bootstrap,@swimlane/ngx-datatable,ngx-toastr,ng-http-loader...) et les feuilles de style dont dépendent ses assets (bootstrap,bootswatch,font-awesome). Le modèledflat-webhostles liste déjà dans lepackage.jsondu front qu'il génère.Dans les options de build de l'application (
project.json) :"preserveSymlinks": true, "stylePreprocessorOptions": { "includePaths": ["node_modules", "node_modules/@dflat-core/web/assets"] }, "assets": [{ "input": "node_modules/@dflat-core/web/assets", "glob": "*/**", "output": "assets" }]preserveSymlinksévite de résoudre Angular depuisweb/dflat-web/node_modules(double instance).node_modulesdans lesincludePathspermet àdflat-app.scssde résoudre Bootstrap et son thème.Styles globaux (
styles.scss) :@import "../../../node_modules/@dflat-core/web/scss/dflat-app.scss";dflat-app.scssenchaîne les variables, Bootstrap, le thème Bootswatch,core-ux.scss,site.scsset les règles de mise en page plein écran de la coquille. Pour un autre thème, ne l'importez pas : reprenez son contenu dans l'application en changeant la lignebootswatch.Les feuilles de style tierces qui ne passent pas par Sass (toastr, ngx-datatable, bs-datepicker, font-awesome) restent dans le tableau
stylesdes options de build.
Règles propres à une librairie
La compilation partielle d'Angular est plus stricte que celle d'une application :
- pas d'import par le barrel de sa propre librairie (
@dflat-core/web/core-uxdepuis core-ux) : utiliser un chemin relatif. Entre librairies, toujours passer par@dflat-core/web/<librairie>; - toute classe déclarée par un NgModule doit être exportée par le
src/index.tsde sa librairie (NG3001) ; - pas de cycle d'imports entre un composant et ce qu'utilise son template (NG3003). Pour casser un cycle :
import typelorsque le symbole ne sert qu'au typage, ou unInjectionTokenlorsqu'un type de composant est nécessaire à l'exécution (voircore-ux/src/lib/modals/dialog-component.tokens.ts,RowRefHostdansrow-ref.directive.ts) ; - pas de cycle d'imports entre une classe et sa classe parente, même indirect : chaque point d'entrée est
aplati en un seul fichier et la classe fille pourrait y être émise avant la parente
(
Cannot access 'X' before initializationau démarrage de l'application).tools/check-bundles.js, lancé parnpm run build, le détecte.
Code généré
codegenerator -ts -webpkg <dépôt>\web\dflat-web écrit les librairies Dflat (core-model, system-model,
system-data) dans ce dossier et génère les imports en @dflat-core/web/<librairie>. Sans -webpkg (application hôte
hors dépôt), ces librairies ne sont pas générées : elles sont fournies par le package. dbmanager écrit les
permissions TypeScript du module System dans system-root/src/lib.
