@dflat-core/web 1.0.48 → 1.0.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/README.md +40 -0
  2. package/fesm2022/dflat-core-web-core-data.mjs +19 -18
  3. package/fesm2022/dflat-core-web-core-data.mjs.map +1 -1
  4. package/fesm2022/dflat-core-web-core-model.mjs.map +1 -1
  5. package/fesm2022/dflat-core-web-core-services.mjs +275 -3
  6. package/fesm2022/dflat-core-web-core-services.mjs.map +1 -1
  7. package/fesm2022/dflat-core-web-core-ux-testing.mjs +391 -0
  8. package/fesm2022/dflat-core-web-core-ux-testing.mjs.map +1 -0
  9. package/fesm2022/dflat-core-web-core-ux.mjs +1 -1
  10. package/fesm2022/dflat-core-web-core-ux.mjs.map +1 -1
  11. package/fesm2022/dflat-core-web-system-data.mjs +51 -1
  12. package/fesm2022/dflat-core-web-system-data.mjs.map +1 -1
  13. package/fesm2022/dflat-core-web-system-model.mjs +7 -1
  14. package/fesm2022/dflat-core-web-system-model.mjs.map +1 -1
  15. package/fesm2022/dflat-core-web-system-root.mjs +29 -0
  16. package/fesm2022/dflat-core-web-system-root.mjs.map +1 -1
  17. package/fesm2022/dflat-core-web-system-ux.mjs +246 -10
  18. package/fesm2022/dflat-core-web-system-ux.mjs.map +1 -1
  19. package/fesm2022/dflat-core-web.mjs.map +1 -1
  20. package/package.json +5 -1
  21. package/types/dflat-core-web-core-data.d.ts +9 -0
  22. package/types/dflat-core-web-core-model.d.ts +9 -0
  23. package/types/dflat-core-web-core-services.d.ts +106 -2
  24. package/types/dflat-core-web-core-ux-testing.d.ts +232 -0
  25. package/types/dflat-core-web-core-ux.d.ts +8 -1
  26. package/types/dflat-core-web-system-data.d.ts +11 -1
  27. package/types/dflat-core-web-system-model.d.ts +35 -0
  28. package/types/dflat-core-web-system-root.d.ts +8 -0
  29. package/types/dflat-core-web-system-ux.d.ts +70 -24
@@ -1 +1 @@
1
- {"version":3,"file":"dflat-core-web.mjs","names":[],"sources":["../../src/index.ts"],"sourcesContent":["/*\r\n * Point d'entrée principal de @dflat-core/web.\r\n * Les librairies sont exposées par des points d'entrée secondaires :\r\n * @dflat-core/web/core, @dflat-core/web/core-model, @dflat-core/web/core-services, @dflat-core/web/core-data,\r\n * @dflat-core/web/core-ux, @dflat-core/web/system-model, @dflat-core/web/system-data,\r\n * @dflat-core/web/system-root, @dflat-core/web/system-ux\r\n */\r\nexport const DFLAT_WEB_ENTRY_POINTS = [\r\n 'core', 'core-model', 'core-services', 'core-data', 'core-ux',\r\n 'system-model', 'system-data', 'system-root', 'system-ux'\r\n] as const;\r\n"],"mappings":"AAOA,MAAa,yBAAyB;CAClC;CAAQ;CAAc;CAAiB;CAAa;CACpD;CAAgB;CAAe;CAAe;AACxC"}
1
+ {"version":3,"file":"dflat-core-web.mjs","names":[],"sources":["../../src/index.ts"],"sourcesContent":["/*\r\n * Point d'entrée principal de @dflat-core/web.\r\n * Les librairies sont exposées par des points d'entrée secondaires :\r\n * @dflat-core/web/core, @dflat-core/web/core-model, @dflat-core/web/core-services, @dflat-core/web/core-data,\r\n * @dflat-core/web/core-ux, @dflat-core/web/system-model, @dflat-core/web/system-data,\r\n * @dflat-core/web/system-root, @dflat-core/web/system-ux\r\n * et, pour les fichiers de test seulement, @dflat-core/web/core-ux/testing.\r\n */\r\nexport const DFLAT_WEB_ENTRY_POINTS = [\r\n 'core', 'core-model', 'core-services', 'core-data', 'core-ux',\r\n 'system-model', 'system-data', 'system-root', 'system-ux'\r\n] as const;\r\n"],"mappings":"AAQA,MAAa,yBAAyB;CAClC;CAAQ;CAAc;CAAiB;CAAa;CACpD;CAAgB;CAAe;CAAe;AACxC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dflat-core/web",
3
- "version": "1.0.48",
3
+ "version": "1.0.50",
4
4
  "description": "Librairies Angular Dflat (core, core-*, system-*) et assets partagés, empaquetées en un module npm unique.",
5
5
  "license": "MIT",
6
6
  "peerDependencies": {
@@ -66,6 +66,10 @@
66
66
  "types": "./types/dflat-core-web-core-ux.d.ts",
67
67
  "default": "./fesm2022/dflat-core-web-core-ux.mjs"
68
68
  },
69
+ "./core-ux/testing": {
70
+ "types": "./types/dflat-core-web-core-ux-testing.d.ts",
71
+ "default": "./fesm2022/dflat-core-web-core-ux-testing.mjs"
72
+ },
69
73
  "./system-data": {
70
74
  "types": "./types/dflat-core-web-system-data.d.ts",
71
75
  "default": "./fesm2022/dflat-core-web-system-data.mjs"
@@ -16,10 +16,19 @@ export declare class DataService {
16
16
  baseUrl: string;
17
17
  httpClient: HttpClient;
18
18
  data: any[];
19
+ private initCache;
19
20
  constructor(env: EnvironmentBase, httpClient: HttpClient, headerService: HeadersService);
20
21
  getFormattedParams(params: any): any;
21
22
  private formatValueRecursive;
22
23
  getUrlQueryParams(filter: any): HttpParams;
24
+ /**
25
+ * Appel GET sans paramètre gardé dans le cache d'initialisation (InitCacheService) : données
26
+ * chargées avant la recherche, identiques d'une ouverture de l'écran à l'autre. Le cache est
27
+ * vidé au redémarrage de l'API (horodatage du jeton d'accès) et au changement d'utilisateur.
28
+ */
29
+ getCached<T>(entityKey: string, action: string): Observable<T>;
30
+ /** Vide le cache d'initialisation d'une entité, ou tout le cache. */
31
+ clearCached(entityKey?: string): void;
23
32
  getViewFilterDescriptors(entityKey: string): Observable<FilterDescriptor[]>;
24
33
  getViewColumns(entityKey: string): Observable<ColumnDescriptor[]>;
25
34
  search<TData>(entityKey: string, filter: any): Observable<PagedList<TData>>;
@@ -340,6 +340,15 @@ export interface IUserCredential extends IIdentifiable {
340
340
  ProfileImageUrl: string;
341
341
  AvatarUrl: string;
342
342
  }
343
+ /** Fournisseur d'identité externe proposé à l'écran de connexion (Account/GetLoginProviders). */
344
+ export interface IExternalLoginProvider {
345
+ /** Google, Microsoft ou Apple. */
346
+ Provider: string;
347
+ /** Identifiant de l'application chez le fournisseur. */
348
+ ClientId: string;
349
+ /** Microsoft seulement : locataire du point d'accès (common par défaut). */
350
+ TenantId?: string;
351
+ }
343
352
  export declare class User implements IUserCredential {
344
353
  AccessToken: string;
345
354
  RefreshToken: string;
@@ -1,9 +1,9 @@
1
1
  import { EnsureModuleLoadedOnceGuard, EnvironmentBase } from "@dflat-core/web/core";
2
2
  import * as i0 from "@angular/core";
3
- import { EventEmitter, InjectionToken, Injector } from "@angular/core";
3
+ import { EventEmitter, InjectionToken, Injector, NgZone } from "@angular/core";
4
4
  import * as i1 from "@angular/common";
5
5
  import * as i2 from "@dflat-core/web/core-model";
6
- import { ApiError, DictionnaryWrapper, IUserCredential, Message, Notification, User } from "@dflat-core/web/core-model";
6
+ import { ApiError, DictionnaryWrapper, IExternalLoginProvider, IUserCredential, Message, Notification, User } from "@dflat-core/web/core-model";
7
7
  import { ActivatedRouteSnapshot, Route, Router, RouterStateSnapshot } from "@angular/router";
8
8
  import { Observable, ReplaySubject, Subject, Subscription } from "rxjs";
9
9
  import { HttpClient, HttpErrorResponse, HttpEvent, HttpHandler, HttpHeaders, HttpInterceptor, HttpRequest } from "@angular/common/http";
@@ -189,6 +189,16 @@ export declare class AuthService {
189
189
  private refreshTokenSubscription;
190
190
  constructor(headersService: HeadersService, busMsg: BusMessageService, httpClient: HttpClient, router: Router, localStorage: LocalStoreManager, menuService: MenuService, env: EnvironmentBase);
191
191
  login(username: string, password: string, rememberMe: boolean): Observable<IUserCredential>;
192
+ /**
193
+ * Fournisseurs d'identité externes (Google, Microsoft, Apple) activés et configurés côté
194
+ * serveur (section ExternalLogin de la configuration).
195
+ */
196
+ getLoginProviders(): Observable<IExternalLoginProvider[]>;
197
+ /**
198
+ * Connexion par le jeton d'identité remis par un fournisseur externe. Le serveur vérifie le
199
+ * jeton, retrouve ou crée le compte, puis répond comme la connexion par mot de passe.
200
+ */
201
+ loginExternal(provider: string, idToken: string, rememberMe: boolean, firstName?: string, lastName?: string): Observable<IUserCredential>;
192
202
  register(captchaToken: string, firstName: string, lastName: string, email: string, password: string, rememberMe: boolean): Observable<IUserCredential>;
193
203
  activate(code: string): Observable<Response>;
194
204
  saveUserInfos(user: any, userDetails: string, rememberMe?: boolean): void;
@@ -252,6 +262,69 @@ export declare class AuthInterceptor implements HttpInterceptor {
252
262
  static ɵfac: i0.ɵɵFactoryDeclaration<AuthInterceptor, never>;
253
263
  static ɵprov: i0.ɵɵInjectableDeclaration<any>;
254
264
  }
265
+ /** Jeton d'identité remis par un fournisseur externe, à transmettre à AuthService.loginExternal. */
266
+ export interface IExternalLoginResult {
267
+ /** Google, Microsoft ou Apple. */
268
+ provider: string;
269
+ /** Jeton d'identité (JWT) signé par le fournisseur. */
270
+ idToken: string;
271
+ /** Prénom transmis hors du jeton (Apple, à la première connexion). */
272
+ firstName?: string;
273
+ /** Nom transmis hors du jeton (Apple, à la première connexion). */
274
+ lastName?: string;
275
+ }
276
+ /**
277
+ * Lance, dans le navigateur, la connexion chez un fournisseur d'identité externe et en récupère
278
+ * le jeton d'identité. Aucune dépendance npm : les scripts officiels de Google et d'Apple sont
279
+ * chargés à la demande, Microsoft passe par une fenêtre OpenID Connect.
280
+ *
281
+ * Adresse de retour à déclarer chez Microsoft et Apple : l'origine de l'application
282
+ * (`window.location.origin`, ex. https://mon-application.fr). Chez Google, cette origine est à
283
+ * déclarer comme « origine JavaScript autorisée ».
284
+ */
285
+ export declare class ExternalLoginService {
286
+ private zone;
287
+ static readonly google = "Google";
288
+ static readonly microsoft = "Microsoft";
289
+ static readonly apple = "Apple";
290
+ private static readonly googleScript;
291
+ private static readonly appleScript;
292
+ private scripts;
293
+ constructor(zone: NgZone);
294
+ /**
295
+ * Affiche le bouton officiel « Continuer avec Google » dans un élément de la page. Google
296
+ * n'accepte la connexion que depuis son propre bouton : il ne peut pas être remplacé.
297
+ * @param container Élément qui reçoit le bouton.
298
+ * @param provider Réglages de Google (identifiant client).
299
+ * @param onToken Appelé avec le jeton d'identité quand l'utilisateur s'est connecté.
300
+ */
301
+ renderGoogleButton(container: HTMLElement, provider: IExternalLoginProvider, onToken: (result: IExternalLoginResult) => void): Promise<void>;
302
+ /**
303
+ * Connexion par un compte Microsoft, dans une fenêtre : flux OpenID Connect qui renvoie le
304
+ * jeton d'identité à l'origine de l'application (« jetons d'ID » à cocher dans l'inscription
305
+ * de l'application chez Microsoft).
306
+ */
307
+ signInWithMicrosoft(provider: IExternalLoginProvider): Promise<IExternalLoginResult>;
308
+ /** Connexion par un identifiant Apple, dans la fenêtre du script officiel « Sign in with Apple ». */
309
+ signInWithApple(provider: IExternalLoginProvider): Promise<IExternalLoginResult>;
310
+ /** Vrai si l'erreur vient de l'utilisateur qui a fermé la fenêtre de connexion. */
311
+ isCancellation(error: any): boolean;
312
+ /** Adresse de retour déclarée chez les fournisseurs : l'origine de l'application. */
313
+ private get redirectUri();
314
+ /**
315
+ * Ouvre la fenêtre de connexion et attend son retour sur l'origine de l'application : la
316
+ * réponse du fournisseur est lue dans le fragment de son adresse.
317
+ */
318
+ private openPopup;
319
+ /** Charge une fois le script d'un fournisseur. */
320
+ private loadScript;
321
+ /** Valeur aléatoire (nonce, état) liant la réponse du fournisseur à la demande. */
322
+ private random;
323
+ /** Contenu d'un jeton JWT, sans vérification : la signature est contrôlée par le serveur. */
324
+ private readPayload;
325
+ static ɵfac: i0.ɵɵFactoryDeclaration<ExternalLoginService, never>;
326
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
327
+ }
255
328
  export declare class BreadcrumbService {
256
329
  protected title: Title;
257
330
  current: ReplaySubject<any>;
@@ -349,6 +422,35 @@ export declare class HubService {
349
422
  static ɵfac: i0.ɵɵFactoryDeclaration<HubService, never>;
350
423
  static ɵprov: i0.ɵɵInjectableDeclaration<any>;
351
424
  }
425
+ /**
426
+ * Cache des données d'initialisation des écrans (colonnes, descripteurs de filtre, filtre vide,
427
+ * actions, formulaire) : tout ce qui est chargé avant la recherche et ne change pas d'une
428
+ * ouverture à l'autre.
429
+ *
430
+ * Le cache est vidé quand le jeton d'accès reçu (connexion, rafraîchissement, déconnexion)
431
+ * porte un autre horodatage serveur (claim "cachestamp", régénéré à chaque redémarrage de l'API
432
+ * ou par Config/ResetClientCache) ou un autre utilisateur.
433
+ */
434
+ export declare class InitCacheService {
435
+ static readonly CACHE_STAMP = "cachestamp";
436
+ static readonly USER_ACCOUNT_ID = "id";
437
+ private entries;
438
+ private stamp;
439
+ constructor(busMsg: BusMessageService, localStorage: LocalStoreManager);
440
+ /**
441
+ * Retourne la valeur en cache pour la clé, ou la charge par la fabrique (une seule requête,
442
+ * partagée par les appels simultanés). Chaque abonné reçoit sa propre copie : il peut la
443
+ * modifier sans toucher au cache.
444
+ */
445
+ get<T>(key: string, factory: () => Observable<T>): Observable<T>;
446
+ /** Vide le cache, ou seulement les entrées dont la clé commence par le préfixe. */
447
+ clear(prefix?: string): void;
448
+ private onTokenChanged;
449
+ /** Identité du cache : horodatage serveur et utilisateur du jeton (null sans jeton). */
450
+ private readStamp;
451
+ static ɵfac: i0.ɵɵFactoryDeclaration<InitCacheService, never>;
452
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
453
+ }
352
454
  export declare class MessagesService {
353
455
  private messagesList;
354
456
  newMessages: Subject<Message>;
@@ -367,6 +469,8 @@ export declare class ServerUrl {
367
469
  static hubUrl: string;
368
470
  static loginPath: string;
369
471
  static connectPath: string;
472
+ static connectExternalPath: string;
473
+ static loginProvidersPath: string;
370
474
  static registerPath: string;
371
475
  static activatePath: string;
372
476
  static refreshPath: string;
@@ -0,0 +1,232 @@
1
+ import { Provider, Type } from "@angular/core";
2
+ import { ActivatedRoute, NavigationExtras, Router, Routes, UrlCreationOptions, UrlTree } from "@angular/router";
3
+ import { ActionDescriptor, ColumnDescriptor, EntityViewModel, EntityViewModelWithFields, FilterDescriptor, FilterViewModel, PagedList } from "@dflat-core/web/core-model";
4
+ import { ApplicationService, BaseComponent, EntityFacade, EntityFacadeRegistryService, EntitySelector } from "@dflat-core/web/core-ux";
5
+ import { BreadcrumbService, MenuItem, NotificationMqService } from "@dflat-core/web/core-services";
6
+ import { DataService } from "@dflat-core/web/core-data";
7
+ import { Observable } from "rxjs";
8
+ import { Guid } from "guid-typescript";
9
+ import { Title } from "@angular/platform-browser";
10
+ /** Valeurs attendues d'un composant dérivé de BaseComponent (voir describeBaseComponent). */
11
+ export interface BaseComponentExpectations {
12
+ /** Clé de l'entité (getEntityKey), ex. country. */
13
+ entityKey: string;
14
+ /** Lien du composant (getPath), ex. /sys/country. */
15
+ path: string;
16
+ /** Titre du composant (getTitle). */
17
+ title: string;
18
+ /** Clé de permission du composant (PermissionKey), ex. system.country. */
19
+ permissionKey: string;
20
+ /**
21
+ * Titres des onglets enregistrés par le composant après ngOnInit (facade.sections), dans
22
+ * l'ordre ; non vérifiés si absent.
23
+ */
24
+ sections?: string[];
25
+ /** Fournisseurs ajoutés au module de test (ex. PP_SERVICE). */
26
+ providers?: Provider[];
27
+ }
28
+ /**
29
+ * Fabrique du composant à tester : appelée dans un contexte d'injection, avec les services de
30
+ * test (voir BaseComponentTestContext). Ex. `(app, route) => new TestCountryComponent(app, route)`.
31
+ */
32
+ export type BaseComponentFactory<TFilter extends FilterViewModel, TData extends EntityViewModel> = (app: ApplicationService, route: ActivatedRoute) => BaseComponent<TFilter, TData>;
33
+ /** Fil d'Ariane publié par BreadcrumbService (setCurrent). */
34
+ export interface BreadcrumbData {
35
+ /** Description de la page. */
36
+ description: string;
37
+ /** Le fil d'Ariane est affiché. */
38
+ display: boolean;
39
+ /** En-tête de la page. */
40
+ header: string;
41
+ /** Niveaux du fil d'Ariane : icône, lien et libellé. */
42
+ levels: {
43
+ icon: string;
44
+ link: string[];
45
+ title: string;
46
+ }[];
47
+ }
48
+ /** Compteur des appels d'une méthode (voir countCalls). */
49
+ export interface CallCounter {
50
+ /** Nombre d'appels depuis la pose du compteur. */
51
+ count: number;
52
+ }
53
+ /** Éléments générés d'un module (dflat -g ts) dont describeGeneratedModule vérifie la cohérence. */
54
+ export interface GeneratedModuleExpectations {
55
+ /** Composants des entités ([Module]GeneratedComponents). */
56
+ components: Type<unknown>[];
57
+ /** Routes des composants ([Module]GeneratedRoutes). */
58
+ routes: Routes;
59
+ /** Sélecteurs d'entité ([Module]GeneratedSelectors). */
60
+ selectors: EntitySelector[];
61
+ /** Classe des clés d'entité générées (Base[Module]EntityKeys) : une propriété statique par entité. */
62
+ entityKeys: object;
63
+ /** Lien d'une entité à partir de sa clé (Base[Module]MenuItemProvider.GetLink). */
64
+ getLink: (entityKey: string) => string;
65
+ /** Éléments de menu générés des entités du menu dont la route est générée. */
66
+ menuItems: MenuItem[];
67
+ /** Classe des permissions du module ([Module]Permissions) ; permissions non vérifiées si absente. */
68
+ permissions?: object;
69
+ }
70
+ /**
71
+ * Vérifications communes aux outils de test (Vitest, Jest, Jasmine) utilisées par les suites
72
+ * standard : seul ce sous-ensemble est appelé, pour ne dépendre d'aucun outil.
73
+ */
74
+ export interface TestMatchers {
75
+ /** Égalité stricte (===). */
76
+ toBe(expected: unknown): void;
77
+ /** Égalité de structure (objets et tableaux comparés en profondeur). */
78
+ toEqual(expected: unknown): void;
79
+ /** Valeur considérée comme vraie. */
80
+ toBeTruthy(): void;
81
+ /** Valeur considérée comme fausse. */
82
+ toBeFalsy(): void;
83
+ }
84
+ /**
85
+ * Fonctions globales de l'outil de test (Vitest, Jest, Jasmine) utilisées par les suites
86
+ * standard, lues sur globalThis (voir getTestRunner).
87
+ */
88
+ export interface TestRunner {
89
+ /** Déclare un groupe de tests. */
90
+ describe(name: string, body: () => void): void;
91
+ /** Déclare un test, synchrone ou asynchrone. */
92
+ it(name: string, body: () => void | Promise<void>): void;
93
+ /** Code exécuté avant chaque test du groupe. */
94
+ beforeEach(body: () => void | Promise<void>): void;
95
+ /** Vérifications sur une valeur. */
96
+ expect(actual: unknown): TestMatchers;
97
+ }
98
+ /**
99
+ * Doublure de DataService : aucune requête HTTP. Fournit les données d'initialisation d'une
100
+ * façade (colonnes, filtre vide, formulaire, actions) et enregistre les recherches et lectures
101
+ * de détail demandées par le composant testé.
102
+ */
103
+ export declare class DataServiceDouble {
104
+ /** Recherches demandées (search), dans l'ordre. */
105
+ readonly searchCalls: {
106
+ entityKey: string;
107
+ filter: FilterViewModel;
108
+ }[];
109
+ /** Lectures de détail demandées (getDetails), dans l'ordre. */
110
+ readonly detailsCalls: {
111
+ entityKey: string;
112
+ id: number;
113
+ }[];
114
+ /** Résultat renvoyé par search. */
115
+ searchResult: PagedList<EntityViewModel>;
116
+ /** Entité renvoyée par getDetails. */
117
+ details: EntityViewModel;
118
+ /** Enregistre la recherche et renvoie searchResult. */
119
+ search<TData>(entityKey: string, filter: FilterViewModel): Observable<PagedList<TData>>;
120
+ /** Enregistre la lecture et renvoie details. */
121
+ getDetails<TData>(entityKey: string, id: number): Observable<TData>;
122
+ /** Paramètres d'URL d'un filtre : copie du filtre, sans mise en forme. */
123
+ getFormattedParams(params: object): object;
124
+ /** Colonnes de la grille : aucune. */
125
+ getViewColumns(): Observable<ColumnDescriptor[]>;
126
+ /** Critères du filtre : aucun. */
127
+ getViewFilterDescriptors(): Observable<FilterDescriptor[]>;
128
+ /** Filtre vide : première page de 25 lignes. */
129
+ getEmptyFilter<TFilter>(): Observable<TFilter>;
130
+ /** Formulaire vide, sans champ. */
131
+ getEntityViewModel<TData>(): Observable<EntityViewModelWithFields<TData>>;
132
+ /** Actions étendues : aucune. */
133
+ getExtendedActions(): Observable<ActionDescriptor[]>;
134
+ /** La doublure, vue comme le DataService qu'elle remplace. */
135
+ asDataService(): DataService;
136
+ }
137
+ /** Registre de façades du socle (vraies façades), qui enregistre les façades demandées. */
138
+ export declare class EntityFacadeRegistrySpy extends EntityFacadeRegistryService {
139
+ /** Façades demandées (getFacade), dans l'ordre : clé d'entité, identifiant et façade renvoyée. */
140
+ readonly requests: {
141
+ key: string;
142
+ id: Guid;
143
+ facade: EntityFacade<EntityViewModel>;
144
+ }[];
145
+ /** Enregistre la demande et renvoie la façade du registre. */
146
+ getFacade<TData extends EntityViewModel>(key: string, id: Guid): EntityFacade<TData>;
147
+ }
148
+ /**
149
+ * Doublure de Router : URL courante, construction d'URL (chemin et paramètres) et navigations
150
+ * enregistrées. Une navigation réussit toujours et devient l'URL courante.
151
+ */
152
+ export declare class RouterDouble {
153
+ /** URL courante. */
154
+ url: string;
155
+ /** Navigations demandées (navigate), dans l'ordre. */
156
+ readonly navigations: {
157
+ commands: unknown[];
158
+ extras?: NavigationExtras;
159
+ }[];
160
+ constructor(url: string);
161
+ /** URL formée des segments `commands` et des paramètres `extras.queryParams`. */
162
+ createUrlTree(commands: unknown[], extras?: UrlCreationOptions): UrlTree;
163
+ /** Enregistre la navigation, qui devient l'URL courante. */
164
+ navigate(commands: unknown[], extras?: NavigationExtras): Promise<boolean>;
165
+ /** La doublure, vue comme le Router qu'elle remplace. */
166
+ asRouter(): Router;
167
+ /** URL d'un chemin et de ses paramètres. */
168
+ private static format;
169
+ }
170
+ /**
171
+ * Services donnés à un composant dérivé de BaseComponent pendant un test : vraies classes du
172
+ * socle quand elles s'instancient sans dépendance (ApplicationService, registre de façades et
173
+ * façades, fil d'Ariane, file de messages), doublures pour le service de données, le routeur et
174
+ * la route. Les services que BaseComponent n'utilise pas (authentification, fenêtres modales,
175
+ * alertes, mise en page...) ne sont pas fournis.
176
+ */
177
+ export declare class BaseComponentTestContext {
178
+ /** Doublure du service de données. */
179
+ readonly dataService: DataServiceDouble;
180
+ /** Doublure du routeur. */
181
+ readonly router: RouterDouble;
182
+ /** Route active, sans paramètre. */
183
+ readonly route: ActivatedRoute;
184
+ /** Fil d'Ariane du socle. */
185
+ readonly breadcrumb: BreadcrumbService;
186
+ /** File de messages (notifications d'entité) du socle. */
187
+ readonly notifications: NotificationMqService;
188
+ /** Registre de façades du socle, qui enregistre les façades demandées. */
189
+ readonly registry: EntityFacadeRegistrySpy;
190
+ /** ApplicationService du socle, construit sur les services ci-dessus. */
191
+ readonly app: ApplicationService;
192
+ /**
193
+ * @param url URL courante du routeur.
194
+ * @param title Service du titre de la page (TestBed.inject(Title)), utilisé par le fil d'Ariane.
195
+ */
196
+ constructor(url: string, title: Title);
197
+ /** Fil d'Ariane courant (dernière valeur publiée). */
198
+ get currentBreadcrumb(): BreadcrumbData;
199
+ }
200
+ /**
201
+ * Compte les appels de la méthode `method` de `target`, qui reste exécutée : équivalent, sans
202
+ * outil de test, d'un espion transparent.
203
+ */
204
+ export declare function countCalls<T extends object, K extends keyof T>(target: T, method: K): CallCounter;
205
+ /**
206
+ * Fonctions globales de l'outil de test (describe, it, beforeEach, expect), lues sur globalThis
207
+ * pour ne dépendre d'aucun outil ni de ses types.
208
+ */
209
+ export declare function getTestRunner(): TestRunner;
210
+ /**
211
+ * Suite de test standard d'un composant dérivé de BaseComponent : vérifie, sans rendre son
212
+ * gabarit, le contrat de BaseComponent (création, clé d'entité, lien, titre, permission, façade,
213
+ * ngOnInit, Search / refresh, notifications, ngOnDestroy). À appeler au premier niveau d'un
214
+ * fichier de test :
215
+ * `describeBaseComponent('CountryComponent', (app, route) => new TestCountryComponent(app, route), { ... })`.
216
+ * La suite n'utilise que les fonctions globales de l'outil de test (describe, it, beforeEach,
217
+ * expect) et TestBed.
218
+ *
219
+ * @param name Nom du composant, repris dans le titre de la suite.
220
+ * @param factory Fabrique du composant, appelée dans un contexte d'injection avant chaque test.
221
+ * @param expectations Valeurs attendues du composant.
222
+ */
223
+ export declare function describeBaseComponent<TFilter extends FilterViewModel, TData extends EntityViewModel>(name: string, factory: BaseComponentFactory<TFilter, TData>, expectations: BaseComponentExpectations): void;
224
+ /**
225
+ * Suite de test standard d'un module généré (dflat -g ts) : cohérence de ses composants, routes,
226
+ * sélecteurs, clés d'entité, éléments de menu et permissions. Chaque test compare à une liste
227
+ * vide la liste des éléments en défaut, que l'outil de test affiche en cas d'échec.
228
+ *
229
+ * @param name Nom du module (ex. System), repris dans le titre de la suite.
230
+ * @param module Éléments générés du module.
231
+ */
232
+ export declare function describeGeneratedModule(name: string, module: GeneratedModuleExpectations): void;
@@ -448,6 +448,14 @@ export declare class LayoutService {
448
448
  static ɵfac: i0.ɵɵFactoryDeclaration<LayoutService, never>;
449
449
  static ɵprov: i0.ɵɵInjectableDeclaration<any>;
450
450
  }
451
+ /**
452
+ * Dépendances racines d'ApplicationService et du registre de façades. Le jeton est déclaré dans son
453
+ * propre fichier, sans import d'exécution : ApplicationService et EntityFacadeRegistryService
454
+ * s'importent l'un l'autre, et un jeton déclaré avec ApplicationService serait lu avant son
455
+ * initialisation par le registre quand le package est chargé sans édition de liens Angular
456
+ * (tests unitaires d'une application : "Cannot access 'ROOT_DEPS' before initialization").
457
+ */
458
+ export declare const ROOT_DEPS: InjectionToken<RootDeps>;
451
459
  declare namespace dynamic_form_component_d_exports {
452
460
  export { DynamicFormComponent };
453
461
  }
@@ -2707,7 +2715,6 @@ export interface RootDeps {
2707
2715
  selection: SelectionService<EntityViewModel>;
2708
2716
  readonly test: TestService;
2709
2717
  }
2710
- export declare const ROOT_DEPS: InjectionToken<RootDeps>;
2711
2718
  export declare class ApplicationService {
2712
2719
  deps: RootDeps;
2713
2720
  MQService: NotificationMqService;
@@ -1,7 +1,7 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import * as i1 from "@angular/common";
3
3
  import * as i2 from "@dflat-core/web/system-model";
4
- import { ActivationResults, ActivationViewModel, AddressView, AddressViewFilterViewModel, ChangePasswordViewModel, CheckSireneInfoViewModel, CompanyFilterViewModel, CompanyView, Country, CountryFilterViewModel, CreatePaymentIntentViewModel, Currency, CurrencyFilterViewModel, CustomFieldFilterViewModel, CustomFieldGroup, CustomFieldGroupEntityFilterViewModel, CustomFieldGroupEntityView, CustomFieldGroupFilterViewModel, CustomFieldGroupItemFilterViewModel, CustomFieldGroupItemView, CustomFieldOptionsFilterViewModel, CustomFieldOptionsView, CustomFieldValueFilterViewModel, CustomFieldValueView, CustomFieldView, DayInfo, DayInfoFilterViewModel, EntityFiles, EntityFilesFilterViewModel, ErrorCategory, ErrorCategoryFilterViewModel, ExchangeRateFilterViewModel, ExchangeRateView, ExecOperation, FileDescriptor, FileTypes, FilesFilterViewModel, FilesView, GetFileDescriptorsViewModel, Keyword, KeywordFilterViewModel, LoginViewModel, MetaEntity, MetaEntityField, MetaEntityFieldFilterViewModel, MetaEntityFilterViewModel, MetaEntityFormFieldFilterViewModel, MetaEntityFormFieldView, MetaEntityFormFilterViewModel, MetaEntityFormSectionFilterViewModel, MetaEntityFormSectionView, MetaEntityFormView, MetaEntityKeyword, MetaEntityKeywordFilterViewModel, MetaEntityRelation, MetaEntityRelationDefinition, MetaEntityRelationDefinitionFilterViewModel, MetaEntityRelationFilterViewModel, MetaEntityTranslation, MetaEntityTranslationFilterViewModel, MetaEntityViewField, MetaEntityViewFieldFilterViewModel, News, NewsFilterViewModel, NewsView, ParameterSection, ParameterSectionFilterViewModel, ParameterValueView, ParameterValueViewFilterViewModel, ParameterView, ParameterViewFilterViewModel, PaymentIntentViewModel, Permission, PermissionFilterViewModel, PermissionView, PresentationContext, PresentationProfile, PresentationProfileFilterViewModel, PresentationProfileItem, PresentationProfileItemFilterViewModel, PresentationProfileItemView, Rating, RatingFilterViewModel, RatingSummary, RatingSummaryFilterViewModel, RatingView, RegisterViewModel, RequestEntity, RequestEntityFilterViewModel, RequestFilterViewModel, RequestResultContext, RequestResultFilterViewModel, RequestResultView, RequestType, RequestTypeFilterViewModel, RequestView, ResetPasswordViewModel, ResourceKey, ResourceKeyFilterViewModel, ResourceLanguage, ResourceLanguageFilterViewModel, ResourceTranslationFilterViewModel, ResourceTranslationView, RoleFilterViewModel, RolePermission, RolePermissionFilterViewModel, RoleView, SirenCheckResults, SubcompanyFilterViewModel, SupplierCompany, SupplierCompanyFilterViewModel, SupplierFilterViewModel, SupplierView, SynchronizedCompanyView, SynchronizedCompanyViewFilterViewModel, TvaRateFilterViewModel, TvaRateView, UploadFileResult, UserAccount, UserAccountCompanyFilterViewModel, UserAccountCompanyView, UserAccountFilterViewModel, UserAccountNews, UserAccountNewsFilterViewModel, UserAccountRoleFilterViewModel, UserAccountRoleView, UserAccountToken, UserAccountTokenFilterViewModel, UserCredential, UserFavorite, UserFavoriteFilterViewModel, UserGroup, UserGroupDefinitionFilterViewModel, UserGroupDefinitionView, UserGroupFilterViewModel, UserHistory, UserHistoryFilterViewModel, UserPermissionView, UserPermissionViewFilterViewModel, UserProfileViewModel, UserSession, UserSessionFilterViewModel, Version, VersionFilterViewModel } from "@dflat-core/web/system-model";
4
+ import { ActivationResults, ActivationViewModel, AddressView, AddressViewFilterViewModel, ChangePasswordViewModel, CheckSireneInfoViewModel, CompanyFilterViewModel, CompanyView, Country, CountryFilterViewModel, CreatePaymentIntentViewModel, Currency, CurrencyFilterViewModel, CustomFieldFilterViewModel, CustomFieldGroup, CustomFieldGroupEntityFilterViewModel, CustomFieldGroupEntityView, CustomFieldGroupFilterViewModel, CustomFieldGroupItemFilterViewModel, CustomFieldGroupItemView, CustomFieldOptionsFilterViewModel, CustomFieldOptionsView, CustomFieldValueFilterViewModel, CustomFieldValueView, CustomFieldView, DayInfo, DayInfoFilterViewModel, EntityFiles, EntityFilesFilterViewModel, ErrorCategory, ErrorCategoryFilterViewModel, ExchangeRateFilterViewModel, ExchangeRateView, ExecOperation, ExternalLoginProviderViewModel, ExternalLoginViewModel, FileDescriptor, FileTypes, FilesFilterViewModel, FilesView, GetFileDescriptorsViewModel, Keyword, KeywordFilterViewModel, LoginViewModel, MetaEntity, MetaEntityField, MetaEntityFieldFilterViewModel, MetaEntityFilterViewModel, MetaEntityFormFieldFilterViewModel, MetaEntityFormFieldView, MetaEntityFormFilterViewModel, MetaEntityFormSectionFilterViewModel, MetaEntityFormSectionView, MetaEntityFormView, MetaEntityKeyword, MetaEntityKeywordFilterViewModel, MetaEntityRelation, MetaEntityRelationDefinition, MetaEntityRelationDefinitionFilterViewModel, MetaEntityRelationFilterViewModel, MetaEntityTranslation, MetaEntityTranslationFilterViewModel, MetaEntityViewField, MetaEntityViewFieldFilterViewModel, News, NewsFilterViewModel, NewsView, ParameterSection, ParameterSectionFilterViewModel, ParameterValueView, ParameterValueViewFilterViewModel, ParameterView, ParameterViewFilterViewModel, PaymentIntentViewModel, Permission, PermissionFilterViewModel, PermissionView, PresentationContext, PresentationProfile, PresentationProfileFilterViewModel, PresentationProfileItem, PresentationProfileItemFilterViewModel, PresentationProfileItemView, Rating, RatingFilterViewModel, RatingSummary, RatingSummaryFilterViewModel, RatingView, RegisterViewModel, RequestEntity, RequestEntityFilterViewModel, RequestFilterViewModel, RequestResultContext, RequestResultFilterViewModel, RequestResultView, RequestType, RequestTypeFilterViewModel, RequestView, ResetPasswordViewModel, ResourceKey, ResourceKeyFilterViewModel, ResourceLanguage, ResourceLanguageFilterViewModel, ResourceTranslationFilterViewModel, ResourceTranslationView, RoleFilterViewModel, RolePermission, RolePermissionFilterViewModel, RoleView, SirenCheckResults, SubcompanyFilterViewModel, SupplierCompany, SupplierCompanyFilterViewModel, SupplierFilterViewModel, SupplierView, SynchronizedCompanyView, SynchronizedCompanyViewFilterViewModel, TvaRateFilterViewModel, TvaRateView, UploadFileResult, UserAccount, UserAccountCompanyFilterViewModel, UserAccountCompanyView, UserAccountFilterViewModel, UserAccountLoginFilterViewModel, UserAccountLoginView, UserAccountNews, UserAccountNewsFilterViewModel, UserAccountRoleFilterViewModel, UserAccountRoleView, UserAccountToken, UserAccountTokenFilterViewModel, UserCredential, UserFavorite, UserFavoriteFilterViewModel, UserGroup, UserGroupDefinitionFilterViewModel, UserGroupDefinitionView, UserGroupFilterViewModel, UserHistory, UserHistoryFilterViewModel, UserPermissionView, UserPermissionViewFilterViewModel, UserProfileViewModel, UserSession, UserSessionFilterViewModel, Version, VersionFilterViewModel } from "@dflat-core/web/system-model";
5
5
  import * as i3 from "@dflat-core/web/core-model";
6
6
  import { ColumnDescriptor, EntityViewModelWithFields, EntityWithSpecifics, ExportModel, ExtendedProperty, FilterDescriptor, ImageFormats, PagedList, RunActionContext, SaveResult, SaveResults, TreeItem } from "@dflat-core/web/core-model";
7
7
  import { DataService, EntityDataService } from "@dflat-core/web/core-data";
@@ -19,7 +19,9 @@ export declare class AccountDataService {
19
19
  changePassword(entity: ChangePasswordViewModel): Observable<any>;
20
20
  checkSIRET(checkViewModel: CheckSireneInfoViewModel): Observable<SirenCheckResults>;
21
21
  connect(model: LoginViewModel): Observable<UserCredential>;
22
+ connectExternal(model: ExternalLoginViewModel): Observable<UserCredential>;
22
23
  disconnect(refreshToken: string): Observable<boolean>;
24
+ getLoginProviders(): Observable<ExternalLoginProviderViewModel[]>;
23
25
  refreshToken(refreshToken: string): Observable<UserCredential>;
24
26
  register(registerViewModel: RegisterViewModel): Observable<UserCredential>;
25
27
  resetPassword(activationModel: ResetPasswordViewModel): Observable<ActivationResults>;
@@ -90,6 +92,7 @@ export declare class ConfigDataService {
90
92
  getAgentExecutionHistory(): Observable<ExecOperation[]>;
91
93
  getCachedKeys(): Observable<string[]>;
92
94
  removeExpiredTokens(): Observable<any>;
95
+ resetClientCache(): Observable<number>;
93
96
  runAgentETL(): Observable<SaveResult>;
94
97
  runSSISSP(): Observable<SaveResult>;
95
98
  static ɵfac: i0.ɵɵFactoryDeclaration<ConfigDataService, never>;
@@ -549,4 +552,11 @@ export declare class RequestTypeDataService extends EntityDataService<RequestTyp
549
552
  constructor(dataService: DataService);
550
553
  static ɵfac: i0.ɵɵFactoryDeclaration<RequestTypeDataService, never>;
551
554
  static ɵprov: i0.ɵɵInjectableDeclaration<any>;
555
+ }
556
+ export declare class UserAccountLoginDataService extends EntityDataService<UserAccountLoginView, UserAccountLoginFilterViewModel> {
557
+ protected dataService: DataService;
558
+ getEntityKey(): string;
559
+ constructor(dataService: DataService);
560
+ static ɵfac: i0.ɵɵFactoryDeclaration<UserAccountLoginDataService, never>;
561
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
552
562
  }
@@ -287,6 +287,20 @@ export interface UserAccountNews extends EntityViewModel {
287
287
  RowVersion?: Date;
288
288
  UserAccountId?: number;
289
289
  }
290
+ export interface UserAccountLoginView extends EntityViewModel {
291
+ DisplayName?: string;
292
+ Id?: number;
293
+ IsEmailVerified?: boolean;
294
+ LastLoginDate?: Date;
295
+ LoginProvider?: number;
296
+ LoginProviderLabel?: string;
297
+ ProviderEmail?: string;
298
+ ProviderKey?: string;
299
+ RowVersion?: Date;
300
+ UserAccountEmail?: string;
301
+ UserAccountId?: number;
302
+ UserAccountPseudo?: string;
303
+ }
290
304
  export interface UserAccountCompanyView extends EntityViewModel {
291
305
  CanEditTurnover?: boolean;
292
306
  CompanyCode?: string;
@@ -963,6 +977,11 @@ export interface UserAccountNewsFilterViewModel extends EntityFilterViewModel<Us
963
977
  ReadDate?: Date;
964
978
  UserAccountId?: number;
965
979
  }
980
+ export interface UserAccountLoginFilterViewModel extends EntityFilterViewModel<UserAccountLoginView> {
981
+ LoginProvider?: number;
982
+ ProviderKey?: string;
983
+ UserAccountId?: number;
984
+ }
966
985
  export interface UserAccountFilterViewModel extends EntityFilterViewModel<UserAccount> {
967
986
  CompanyId?: number;
968
987
  Email?: string;
@@ -1246,6 +1265,17 @@ export interface FileDescriptor {
1246
1265
  LengthDescription?: string;
1247
1266
  OwnerUser?: string;
1248
1267
  }
1268
+ export interface ExternalLoginViewModel {
1269
+ FirstName?: string;
1270
+ IdToken?: string;
1271
+ LastName?: string;
1272
+ Provider?: string;
1273
+ }
1274
+ export interface ExternalLoginProviderViewModel {
1275
+ ClientId?: string;
1276
+ Provider?: string;
1277
+ TenantId?: string;
1278
+ }
1249
1279
  export interface ExecOperation {
1250
1280
  CallerName?: string;
1251
1281
  Completed?: boolean;
@@ -1510,6 +1540,11 @@ export declare enum MetaEntityFieldTypes {
1510
1540
  Column = 0,
1511
1541
  CustomField = 1
1512
1542
  }
1543
+ export declare enum LoginProviders {
1544
+ Google = 0,
1545
+ Microsoft = 1,
1546
+ Apple = 2
1547
+ }
1513
1548
  export declare enum LockStatus {
1514
1549
  Unknown = 0,
1515
1550
  Unlocked = 1,
@@ -319,6 +319,12 @@ export declare class SystemPermissions {
319
319
  static readonly SYSTEM_USERACCOUNTCOMPANY_EDIT: string;
320
320
  static readonly SYSTEM_USERACCOUNTCOMPANY_EXPORT: string;
321
321
  static readonly SYSTEM_USERACCOUNTCOMPANY_VIEW: string;
322
+ static readonly SYSTEM_USERACCOUNTLOGIN: string;
323
+ static readonly SYSTEM_USERACCOUNTLOGIN_ADD: string;
324
+ static readonly SYSTEM_USERACCOUNTLOGIN_DELETE: string;
325
+ static readonly SYSTEM_USERACCOUNTLOGIN_EDIT: string;
326
+ static readonly SYSTEM_USERACCOUNTLOGIN_EXPORT: string;
327
+ static readonly SYSTEM_USERACCOUNTLOGIN_VIEW: string;
322
328
  static readonly SYSTEM_USERACCOUNTNEWS: string;
323
329
  static readonly SYSTEM_USERACCOUNTNEWS_ADD: string;
324
330
  static readonly SYSTEM_USERACCOUNTNEWS_DELETE: string;
@@ -436,6 +442,7 @@ export declare class BaseSystemMenuItemProvider {
436
442
  static readonly tvaRateMenuItem: MenuItem;
437
443
  static readonly userAccountMenuItem: MenuItem;
438
444
  static readonly userAccountCompanyMenuItem: MenuItem;
445
+ static readonly userAccountLoginMenuItem: MenuItem;
439
446
  static readonly userAccountNewsMenuItem: MenuItem;
440
447
  static readonly userAccountRoleMenuItem: MenuItem;
441
448
  static readonly userAccountTokenMenuItem: MenuItem;
@@ -542,6 +549,7 @@ export declare class BaseSystemEntityKeys {
542
549
  static readonly TvaRate: string;
543
550
  static readonly UserAccount: string;
544
551
  static readonly UserAccountCompany: string;
552
+ static readonly UserAccountLogin: string;
545
553
  static readonly UserAccountNews: string;
546
554
  static readonly UserAccountRole: string;
547
555
  static readonly UserAccountToken: string;