@mohamedatia/fly-design-system 1.3.7 → 1.3.9
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.
|
@@ -28,6 +28,13 @@ class AuthService {
|
|
|
28
28
|
const s = this._session();
|
|
29
29
|
return s !== null && s.expiresAt > Date.now();
|
|
30
30
|
}, ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : /* istanbul ignore next */ []));
|
|
31
|
+
/**
|
|
32
|
+
* No-op when running as a Module Federation remote — the shell has already
|
|
33
|
+
* initialised the session before the remote bootstraps. Business Apps call
|
|
34
|
+
* this in their APP_INITIALIZER so the same code works in both standalone
|
|
35
|
+
* and embedded modes without branching.
|
|
36
|
+
*/
|
|
37
|
+
async init() { }
|
|
31
38
|
/**
|
|
32
39
|
* Called by the shell after a successful login or silent refresh.
|
|
33
40
|
* Business Apps should not call this directly.
|
|
@@ -314,34 +321,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
314
321
|
* ```typescript
|
|
315
322
|
* // src/app/core/services/auth.service.mock.ts
|
|
316
323
|
* import { Injectable } from '@angular/core';
|
|
317
|
-
* import { MockAuthService } from '@mohamedatia/fly-design-system';
|
|
318
|
-
*
|
|
319
|
-
* const MOCK_USER = { id: 'dev-001', ... };
|
|
324
|
+
* import { MockAuthService, type MockAuthConfig } from '@mohamedatia/fly-design-system';
|
|
320
325
|
*
|
|
321
326
|
* @Injectable({ providedIn: 'root' })
|
|
322
327
|
* export class AuthService extends MockAuthService {
|
|
323
|
-
* protected override getConfig() {
|
|
324
|
-
* return {
|
|
328
|
+
* protected override getConfig(): MockAuthConfig {
|
|
329
|
+
* return {
|
|
330
|
+
* user: { id: 'dev-001', tenantId: 'dev-tenant', email: 'dev@example.com',
|
|
331
|
+
* firstName: 'Dev', lastName: 'User', fullName: 'Dev User',
|
|
332
|
+
* preferredLocale: 'en', roles: ['admin'], apps: ['my-app'] },
|
|
333
|
+
* token: 'my-mock-token',
|
|
334
|
+
* loginRedirect: ['/app'],
|
|
335
|
+
* };
|
|
325
336
|
* }
|
|
326
337
|
* }
|
|
327
338
|
* ```
|
|
328
339
|
*/
|
|
329
340
|
class MockAuthService {
|
|
330
341
|
router = inject(Router);
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
342
|
+
_session;
|
|
343
|
+
_config;
|
|
344
|
+
isAuthenticated;
|
|
345
|
+
currentUser;
|
|
346
|
+
accessToken;
|
|
347
|
+
/** Always false in mock mode — 2FA is handled entirely by the STS. */
|
|
348
|
+
hasPendingTwoFactor;
|
|
349
|
+
/** Always false in mock mode — auth is pre-populated synchronously. */
|
|
350
|
+
initializing;
|
|
351
|
+
constructor() {
|
|
352
|
+
// All signal/computed calls are inside the constructor body so Angular's
|
|
353
|
+
// injection context and ngDevMode are fully set up before they execute.
|
|
354
|
+
this._config = this.getConfig();
|
|
355
|
+
this._session = signal({
|
|
356
|
+
accessToken: this._config.token ?? 'mock-token',
|
|
357
|
+
user: this._config.user,
|
|
358
|
+
expiresAt: Date.now() + 24 * 60 * 60 * 1000,
|
|
359
|
+
}, ...(ngDevMode ? [{ debugName: "_session" }] : /* istanbul ignore next */ []));
|
|
360
|
+
this.isAuthenticated = computed(() => {
|
|
361
|
+
const s = this._session();
|
|
362
|
+
return s !== null && s.expiresAt > Date.now();
|
|
363
|
+
}, ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : /* istanbul ignore next */ []));
|
|
364
|
+
this.currentUser = computed(() => this._session()?.user ?? null, ...(ngDevMode ? [{ debugName: "currentUser" }] : /* istanbul ignore next */ []));
|
|
365
|
+
this.accessToken = computed(() => this._session()?.accessToken ?? null, ...(ngDevMode ? [{ debugName: "accessToken" }] : /* istanbul ignore next */ []));
|
|
366
|
+
this.hasPendingTwoFactor = computed(() => false, ...(ngDevMode ? [{ debugName: "hasPendingTwoFactor" }] : /* istanbul ignore next */ []));
|
|
367
|
+
this.initializing = signal(false).asReadonly();
|
|
368
|
+
}
|
|
345
369
|
/** Override in subclass to supply app-specific mock data. */
|
|
346
370
|
getConfig() {
|
|
347
371
|
return {
|
|
@@ -376,7 +400,8 @@ class MockAuthService {
|
|
|
376
400
|
return;
|
|
377
401
|
this._session.set({ ...session, user: { ...session.user, preferredLocale: locale } });
|
|
378
402
|
}
|
|
379
|
-
|
|
403
|
+
/** Parameter order matches the real AuthService: (user, accessToken, expiresAt). */
|
|
404
|
+
setSession(_user, _accessToken, _expiresAt) {
|
|
380
405
|
// No-op in mock mode — session is hardcoded.
|
|
381
406
|
}
|
|
382
407
|
logout() {
|
|
@@ -388,7 +413,7 @@ class MockAuthService {
|
|
|
388
413
|
}
|
|
389
414
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MockAuthService, decorators: [{
|
|
390
415
|
type: Injectable
|
|
391
|
-
}] });
|
|
416
|
+
}], ctorParameters: () => [] });
|
|
392
417
|
|
|
393
418
|
/*
|
|
394
419
|
* @mohamedatia/fly-design-system — Public API
|
|
@@ -405,6 +430,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
|
|
|
405
430
|
* v1.3.2: loadBundle returns boolean; LoadBundleOptions.silent skips ErrorHandler on failure.
|
|
406
431
|
* v1.3.7: MockAuthService base class + MockAuthConfig for Business App mock auth via fileReplacements.
|
|
407
432
|
* User model extended with optional avatar, source, twoFactorEnabled, createdAt fields.
|
|
433
|
+
* v1.3.8: AuthService.init() no-op added so Business Apps can call init() in APP_INITIALIZER
|
|
434
|
+
* without branching between standalone and embedded modes.
|
|
435
|
+
* v1.3.9: MockAuthService field initializers moved into constructor to fix ngDevMode ReferenceError
|
|
436
|
+
* when the package is loaded in a production-mode bundle (no ngDevMode global defined).
|
|
408
437
|
* See BusinessAppsGuide/03-frontend-app.md.
|
|
409
438
|
*/
|
|
410
439
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mohamedatia-fly-design-system.mjs","sources":["../../../projects/design-system/src/lib/models/window.model.ts","../../../projects/design-system/src/lib/services/auth.service.ts","../../../projects/design-system/src/lib/services/i18n.service.ts","../../../projects/design-system/src/lib/services/fly-theme.service.ts","../../../projects/design-system/src/lib/services/window-manager.service.ts","../../../projects/design-system/src/lib/pipes/translate.pipe.ts","../../../projects/design-system/src/lib/services/auth.service.mock.ts","../../../projects/design-system/src/public-api.ts","../../../projects/design-system/src/mohamedatia-fly-design-system.ts"],"sourcesContent":["import { InjectionToken, Type } from '@angular/core';\r\n\r\nexport type WindowState = 'normal' | 'minimized' | 'maximized';\r\n\r\nexport interface ChildWindowData {\r\n childComponent: Type<unknown>;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface WindowInstance {\r\n id: string;\r\n appId: string;\r\n title: string;\r\n icon: string;\r\n iconBg: string;\r\n state: WindowState;\r\n position: { x: number; y: number };\r\n size: { width: number; height: number };\r\n zIndex: number;\r\n isFocused: boolean;\r\n isClosing?: boolean;\r\n isMinimizing?: boolean;\r\n isRestoring?: boolean;\r\n isMaximizing?: boolean;\r\n isUnmaximizing?: boolean;\r\n parentWindowId?: string;\r\n childData?: ChildWindowData;\r\n /** Populated when remote `loadComponent()` fails (e.g. federation). */\r\n remoteLoadError?: string;\r\n}\r\n\r\nexport const WINDOW_DATA = new InjectionToken<WindowInstance>('WINDOW_DATA');\r\n","import { Injectable, computed, signal } from '@angular/core';\nimport { User } from '../models/user.model';\n\ninterface AuthSession {\n user: User;\n accessToken: string;\n expiresAt: number;\n}\n\n/**\n * Shared AuthService for Business Apps.\n *\n * This is a **read-only signal store** — Business Apps inject it to read the\n * current user and access token. The FlyOS shell populates it after PKCE login\n * and silent refresh. Business Apps must never call setSession() directly.\n *\n * When running as a Module Federation remote, the shell and the Business App\n * share this singleton via the `@mohamedatia/fly-design-system` shared mapping\n * in federation.config.js — so the shell's populated instance is the same\n * object the Business App reads.\n *\n * When running standalone (without the shell), call initFromToken() with a\n * JWT stored in localStorage to hydrate the user.\n */\n@Injectable({ providedIn: 'root' })\nexport class AuthService {\n private _session = signal<AuthSession | null>(null);\n\n readonly currentUser = computed(() => this._session()?.user ?? null);\n readonly accessToken = computed(() => this._session()?.accessToken ?? null);\n readonly isAuthenticated = computed(() => {\n const s = this._session();\n return s !== null && s.expiresAt > Date.now();\n });\n\n /**\n * Called by the shell after a successful login or silent refresh.\n * Business Apps should not call this directly.\n */\n setSession(user: User, accessToken: string, expiresAt: number): void {\n this._session.set({ user, accessToken, expiresAt });\n }\n\n /** Clears the in-memory session (called by the shell on logout). */\n clearSession(): void {\n this._session.set(null);\n }\n\n /**\n * Standalone mode: parse a JWT from localStorage and hydrate the user.\n * Pass the storage key your app uses; embedded remotes typically set this in `APP_INITIALIZER`.\n */\n initFromToken(storageKey = 'circles_token'): void {\n const token = localStorage.getItem(storageKey);\n if (!token) return;\n try {\n const base64 = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/');\n const payload = JSON.parse(decodeURIComponent(\n atob(base64).split('').map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join('')\n )) as Record<string, unknown>;\n\n const rawRole = payload['role'];\n const roles = Array.isArray(rawRole) ? rawRole as string[] : rawRole ? [rawRole as string] : [];\n const rawApps = payload['apps'];\n const apps = Array.isArray(rawApps) ? rawApps as string[] : rawApps ? [rawApps as string] : [];\n const name = (payload['name'] as string) ?? '';\n const nameParts = name.split(' ');\n\n const user: User = {\n id: (payload['sub'] as string) ?? '',\n tenantId: (payload['tenant_id'] as string) ?? (payload['tid'] as string) ?? null,\n email: (payload['email'] as string) ?? '',\n fullName: name,\n firstName: nameParts[0] ?? '',\n lastName: nameParts.slice(1).join(' '),\n preferredLocale: (payload['locale'] as string) ?? 'en',\n roles,\n apps,\n ou: payload['ou'] as string | undefined,\n };\n\n const expiresAt = ((payload['exp'] as number) ?? 0) * 1000;\n this.setSession(user, token, expiresAt);\n } catch {\n // Invalid token — stay unauthenticated\n }\n }\n}\n","import { Injectable, computed, signal, inject, ErrorHandler } from '@angular/core';\n\n/** Locales that use RTL layout for `dir` and DS `isRtl` / `direction`. */\nexport const RTL_LOCALE_SET: ReadonlySet<string> = new Set(['ar', 'ur']);\n\nexport function isRtlLocale(lang: string): boolean {\n return RTL_LOCALE_SET.has(lang);\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** Accepts flat or nested JSON objects; nested keys become dot paths. Rejects arrays and non-string leaves. */\nfunction normalizeLocaleJson(raw: unknown): Record<string, string> {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n throw new Error('Locale bundle must be a JSON object');\n }\n const out: Record<string, string> = {};\n const walk = (obj: Record<string, unknown>, prefix: string): void => {\n for (const [k, v] of Object.entries(obj)) {\n const path = prefix ? `${prefix}.${k}` : k;\n if (typeof v === 'string') {\n out[path] = v;\n } else if (v !== null && typeof v === 'object' && !Array.isArray(v)) {\n walk(v as Record<string, unknown>, path);\n } else {\n throw new Error(`Locale bundle invalid value at \"${path}\" (expected string or nested object)`);\n }\n }\n };\n walk(raw as Record<string, unknown>, '');\n return out;\n}\n\n/** Options for loading a remote or standalone locale JSON bundle. */\nexport interface LoadBundleOptions {\n /** Stable id (e.g. app id from manifest); later loads replace this bundle only. */\n id: string;\n /** Base URL ending with `/`, e.g. `https://app.example.com/locale/` or `/my-remote/locale/` */\n baseUrl: string;\n lang: string;\n /** When aborted, failures are ignored (e.g. superseded language load). */\n signal?: AbortSignal;\n /**\n * When true, fetch/parse failures are not reported via Angular `ErrorHandler`.\n * Use for optional remote locale bundles (e.g. federated apps that may be offline).\n */\n silent?: boolean;\n}\n\n/**\n * Shared I18nService for the shell and Business Apps.\n *\n * **Merge order** (later keys win): shell layer → remote bundles in registration order.\n *\n * - Shell: `setShellTranslations()` after loading `locale/{lang}.json` and API overrides.\n * - Remotes: `loadBundle()` per manifest `localeBaseUrl`.\n */\n@Injectable({ providedIn: 'root' })\nexport class I18nService {\n private readonly errorHandler = inject(ErrorHandler, { optional: true });\n\n private readonly _shell = signal<Record<string, string>>({});\n private readonly _bundles = signal<Record<string, Record<string, string>>>({});\n private readonly _bundleOrder = signal<string[]>([]);\n private readonly _locale = signal<string>('en');\n private readonly _version = signal(0);\n\n private readonly _merged = computed(() => {\n const shell = this._shell();\n const order = this._bundleOrder();\n const bundles = this._bundles();\n let out: Record<string, string> = { ...shell };\n for (const id of order) {\n const b = bundles[id];\n if (b) out = { ...out, ...b };\n }\n return out;\n });\n\n readonly locale = this._locale.asReadonly();\n readonly version = this._version.asReadonly();\n readonly isRtl = computed(() => isRtlLocale(this._locale()));\n readonly direction = computed(() => (isRtlLocale(this._locale()) ? 'rtl' : 'ltr'));\n\n private bump(): void {\n this._version.update((v) => v + 1);\n }\n\n /** Replace shell strings (desktop `locale/*.json` + `/api/i18n/desktop-shell/{lang}` merged by the shell). */\n setShellTranslations(data: Record<string, string>, lang: string): void {\n this._shell.set(data);\n this._locale.set(lang);\n this.bump();\n }\n\n setLanguage(lang: string): void {\n this._locale.set(lang);\n this.bump();\n }\n\n /**\n * Fetch `{baseUrl}{lang}.json` and store under `id`. New ids are appended to the merge order.\n * @returns whether the bundle was loaded successfully.\n */\n async loadBundle(opts: LoadBundleOptions): Promise<boolean> {\n const { id, baseUrl, lang, signal: abortSignal, silent } = opts;\n try {\n const base = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n const url = `${base}${lang}.json`;\n const resp = await fetch(url, { signal: abortSignal });\n if (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n const data = normalizeLocaleJson(await resp.json());\n if (abortSignal?.aborted) return false;\n this._bundles.update((b) => ({ ...b, [id]: data }));\n this._bundleOrder.update((order) => (order.includes(id) ? order : [...order, id]));\n this._locale.set(lang);\n this.bump();\n return true;\n } catch (e) {\n if (abortSignal?.aborted) return false;\n if (!silent) this.errorHandler?.handleError(e);\n return false;\n }\n }\n\n removeBundle(id: string): void {\n this._bundles.update((b) => {\n const next = { ...b };\n delete next[id];\n return next;\n });\n this._bundleOrder.update((order) => order.filter((x) => x !== id));\n this.bump();\n }\n\n clearRemoteBundles(): void {\n this._bundles.set({});\n this._bundleOrder.set([]);\n this.bump();\n }\n\n t(key: string, params?: Record<string, string | number>): string {\n const val = this._merged()[key] ?? key;\n if (!params) return val;\n return Object.entries(params).reduce((result, [k, v]) => {\n const safe = escapeRegExp(k);\n return result.replace(new RegExp(`{{\\\\s*${safe}\\\\s*}}`, 'g'), String(v));\n }, val);\n }\n}\n","import { Injectable, signal } from '@angular/core';\n\nexport type FlyThemeMode = 'light' | 'dark' | 'transparent';\n\n/**\n * Applies `html.light-theme` / `html.dark-theme` / `html.transparent-theme` for DS SCSS.\n * Shell and standalone Business Apps use the same service (federation singleton when shared).\n */\n@Injectable({ providedIn: 'root' })\nexport class FlyThemeService {\n readonly theme = signal<FlyThemeMode>('light');\n\n applyTheme(mode: FlyThemeMode): void {\n this.theme.set(mode);\n const html = document.documentElement;\n html.classList.remove('dark-theme', 'light-theme', 'transparent-theme');\n if (mode === 'dark') {\n html.classList.add('dark-theme');\n } else if (mode === 'transparent') {\n html.classList.add('transparent-theme');\n } else {\n html.classList.add('light-theme');\n }\n }\n}\n","import { Injectable } from '@angular/core';\n\n/** Options for opening a child window. */\nexport interface OpenWindowOptions {\n /** Unique identifier for the window instance. */\n windowId: string;\n /** Display title shown in the window chrome. */\n title: string;\n /** Route path or URL to load inside the window. */\n route: string;\n /** Initial width in pixels. Defaults to 900. */\n width?: number;\n /** Initial height in pixels. Defaults to 600. */\n height?: number;\n /** Whether the window can be resized. Defaults to true. */\n resizable?: boolean;\n /** Whether the window can be maximised. Defaults to true. */\n maximizable?: boolean;\n /** Arbitrary data passed to the child window via WINDOW_DATA. */\n data?: unknown;\n}\n\n/**\n * Abstract interface for the WindowManager.\n * The FlyOS shell provides the concrete implementation; Business Apps\n * inject this token to open, close, and focus windows without depending\n * on the shell's internal implementation.\n */\nexport abstract class WindowManagerService {\n abstract openChildWindow(options: OpenWindowOptions): void;\n abstract closeWindow(windowId: string): void;\n abstract focusWindow(windowId: string): void;\n}\n\n/**\n * No-op fallback implementation used when running a Business App in\n * standalone mode (outside the FlyOS shell). Logs a warning instead of\n * throwing so standalone dev/test flows are not broken.\n */\n@Injectable()\nexport class StandaloneWindowManagerService extends WindowManagerService {\n openChildWindow(options: OpenWindowOptions): void {\n console.warn('[WindowManagerService] openChildWindow called in standalone mode — no shell available.', options);\n }\n\n closeWindow(windowId: string): void {\n console.warn('[WindowManagerService] closeWindow called in standalone mode — no shell available.', windowId);\n }\n\n focusWindow(windowId: string): void {\n console.warn('[WindowManagerService] focusWindow called in standalone mode — no shell available.', windowId);\n }\n}\n\n","import { Pipe, PipeTransform, inject } from '@angular/core';\nimport { I18nService } from '../services/i18n.service';\n\n/**\n * Translates a key using the shared I18nService.\n *\n * @example\n * {{ 'myApp.section.title' | translate }}\n * {{ 'myApp.items_count' | translate:{ n: count() } }}\n */\n@Pipe({\n name: 'translate',\n standalone: true,\n pure: false,\n})\nexport class TranslatePipe implements PipeTransform {\n private readonly i18n = inject(I18nService);\n\n transform(key: string, params?: Record<string, string | number>): string {\n // Read version so template CD re-runs when bundles load (merged translations updated).\n void this.i18n.version();\n return this.i18n.t(key, params);\n }\n}\n","import { Injectable, computed, inject, signal } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { Observable, of } from 'rxjs';\nimport { User } from '../models/user.model';\n\nexport interface MockAuthConfig {\n user: User;\n token?: string;\n loginRedirect?: string[];\n logoutRedirect?: string[];\n}\n\ninterface MockSession {\n accessToken: string;\n user: User;\n expiresAt: number;\n}\n\n/**\n * Shared mock AuthService base class for Business App developers.\n *\n * Extend this class in your app's `auth.service.mock.ts` and override\n * `getConfig()` to supply app-specific mock user data and navigation paths.\n * The subclass must be decorated with `@Injectable({ providedIn: 'root' })`\n * and exported as `AuthService` so Angular's `fileReplacements` swap works.\n *\n * @example\n * ```typescript\n * // src/app/core/services/auth.service.mock.ts\n * import { Injectable } from '@angular/core';\n * import { MockAuthService } from '@mohamedatia/fly-design-system';\n *\n * const MOCK_USER = { id: 'dev-001', ... };\n *\n * @Injectable({ providedIn: 'root' })\n * export class AuthService extends MockAuthService {\n * protected override getConfig() {\n * return { user: MOCK_USER, token: 'my-mock-token', loginRedirect: ['/app'] };\n * }\n * }\n * ```\n */\n@Injectable()\nexport class MockAuthService {\n private readonly router = inject(Router);\n\n private readonly _config = this.getConfig();\n\n private readonly _session = signal<MockSession | null>({\n accessToken: this._config.token ?? 'mock-token',\n user: this._config.user,\n expiresAt: Date.now() + 24 * 60 * 60 * 1000,\n });\n\n private readonly _initializing = signal(false);\n\n readonly isAuthenticated = computed(() => {\n const s = this._session();\n return s !== null && s.expiresAt > Date.now();\n });\n\n readonly currentUser = computed(() => this._session()?.user ?? null);\n\n readonly accessToken = computed(() => this._session()?.accessToken ?? null);\n\n readonly initializing = this._initializing.asReadonly();\n\n /** Override in subclass to supply app-specific mock data. */\n protected getConfig(): MockAuthConfig {\n return {\n user: {\n id: 'mock-user-001',\n tenantId: 'mock-tenant-001',\n email: 'developer@fly.local',\n firstName: 'UI',\n lastName: 'Developer',\n fullName: 'UI Developer',\n preferredLocale: 'en',\n roles: ['admin'],\n apps: [],\n },\n };\n }\n\n async init(): Promise<void> {\n // Mock mode: already authenticated, nothing to initialize.\n }\n\n startLogin(): void {\n this.router.navigate(this._config.loginRedirect ?? ['/']);\n }\n\n handleCallback(_code: string, _state?: string): Observable<User> {\n return of(this._config.user);\n }\n\n async forceRefresh(): Promise<void> {\n // No-op in mock mode — token never expires.\n }\n\n patchSessionPreferredLocale(locale: string): void {\n const session = this._session();\n if (!session?.user) return;\n this._session.set({ ...session, user: { ...session.user, preferredLocale: locale } });\n }\n\n setSession(_token: string, _expiresAt: number, _user: User): void {\n // No-op in mock mode — session is hardcoded.\n }\n\n logout(): void {\n this._session.set(null);\n this.router.navigate(this._config.logoutRedirect ?? ['/']);\n }\n}\n","/*\r\n * @mohamedatia/fly-design-system — Public API\r\n * https://www.npmjs.com/package/@mohamedatia/fly-design-system\r\n *\r\n * This is the single entry point for Business App developers.\r\n * Import everything from '@mohamedatia/fly-design-system' — never from relative shell paths.\r\n *\r\n * NOTE: This package is published under @mohamedatia/fly-design-system until the @fly\r\n * npm org is created. It will be republished as @fly/design-system once available.\r\n *\r\n * v1.3.0: FlyThemeService (html theme classes), hardened I18nService (AbortSignal, ErrorHandler, RTL helpers).\r\n * v1.3.1: loadBundle normalizes locale JSON (flat or nested objects; rejects invalid leaves).\r\n * v1.3.2: loadBundle returns boolean; LoadBundleOptions.silent skips ErrorHandler on failure.\r\n * v1.3.7: MockAuthService base class + MockAuthConfig for Business App mock auth via fileReplacements.\r\n * User model extended with optional avatar, source, twoFactorEnabled, createdAt fields.\r\n * See BusinessAppsGuide/03-frontend-app.md.\r\n */\r\n\r\n// ─── Models ──────────────────────────────────────────────────────────────────\r\nexport type { DesktopApp } from './lib/models/app.model';\r\nexport type {\r\n WindowInstance,\r\n WindowState,\r\n ChildWindowData,\r\n} from './lib/models/window.model';\r\nexport { WINDOW_DATA } from './lib/models/window.model';\r\nexport type { User } from './lib/models/user.model';\r\n\r\n// ─── Remote App Registration ─────────────────────────────────────────────────\r\nexport type { RemoteAppDef } from './lib/models/remote-app.model';\r\n\r\n// ─── Services ────────────────────────────────────────────────────────────────\r\nexport { AuthService } from './lib/services/auth.service';\r\nexport type { LoadBundleOptions } from './lib/services/i18n.service';\r\nexport { I18nService, RTL_LOCALE_SET, isRtlLocale } from './lib/services/i18n.service';\r\nexport { FlyThemeService, type FlyThemeMode } from './lib/services/fly-theme.service';\r\nexport {\r\n WindowManagerService,\r\n StandaloneWindowManagerService,\r\n type OpenWindowOptions,\r\n} from './lib/services/window-manager.service';\r\n\r\n// ─── Pipes ───────────────────────────────────────────────────────────────────\r\nexport { TranslatePipe } from './lib/pipes/translate.pipe';\r\n\r\n// ─── Mock Auth (for fileReplacements in dev/mock builds) ─────────────────────\r\nexport { MockAuthService, type MockAuthConfig } from './lib/services/auth.service.mock';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mohamedatia-fly-design-system.mjs","sources":["../../../projects/design-system/src/lib/models/window.model.ts","../../../projects/design-system/src/lib/services/auth.service.ts","../../../projects/design-system/src/lib/services/i18n.service.ts","../../../projects/design-system/src/lib/services/fly-theme.service.ts","../../../projects/design-system/src/lib/services/window-manager.service.ts","../../../projects/design-system/src/lib/pipes/translate.pipe.ts","../../../projects/design-system/src/lib/services/auth.service.mock.ts","../../../projects/design-system/src/public-api.ts","../../../projects/design-system/src/mohamedatia-fly-design-system.ts"],"sourcesContent":["import { InjectionToken, Type } from '@angular/core';\r\n\r\nexport type WindowState = 'normal' | 'minimized' | 'maximized';\r\n\r\nexport interface ChildWindowData {\r\n childComponent: Type<unknown>;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface WindowInstance {\r\n id: string;\r\n appId: string;\r\n title: string;\r\n icon: string;\r\n iconBg: string;\r\n state: WindowState;\r\n position: { x: number; y: number };\r\n size: { width: number; height: number };\r\n zIndex: number;\r\n isFocused: boolean;\r\n isClosing?: boolean;\r\n isMinimizing?: boolean;\r\n isRestoring?: boolean;\r\n isMaximizing?: boolean;\r\n isUnmaximizing?: boolean;\r\n parentWindowId?: string;\r\n childData?: ChildWindowData;\r\n /** Populated when remote `loadComponent()` fails (e.g. federation). */\r\n remoteLoadError?: string;\r\n}\r\n\r\nexport const WINDOW_DATA = new InjectionToken<WindowInstance>('WINDOW_DATA');\r\n","import { Injectable, computed, signal } from '@angular/core';\nimport { User } from '../models/user.model';\n\ninterface AuthSession {\n user: User;\n accessToken: string;\n expiresAt: number;\n}\n\n/**\n * Shared AuthService for Business Apps.\n *\n * This is a **read-only signal store** — Business Apps inject it to read the\n * current user and access token. The FlyOS shell populates it after PKCE login\n * and silent refresh. Business Apps must never call setSession() directly.\n *\n * When running as a Module Federation remote, the shell and the Business App\n * share this singleton via the `@mohamedatia/fly-design-system` shared mapping\n * in federation.config.js — so the shell's populated instance is the same\n * object the Business App reads.\n *\n * When running standalone (without the shell), call initFromToken() with a\n * JWT stored in localStorage to hydrate the user.\n */\n@Injectable({ providedIn: 'root' })\nexport class AuthService {\n private _session = signal<AuthSession | null>(null);\n\n readonly currentUser = computed(() => this._session()?.user ?? null);\n readonly accessToken = computed(() => this._session()?.accessToken ?? null);\n readonly isAuthenticated = computed(() => {\n const s = this._session();\n return s !== null && s.expiresAt > Date.now();\n });\n\n /**\n * No-op when running as a Module Federation remote — the shell has already\n * initialised the session before the remote bootstraps. Business Apps call\n * this in their APP_INITIALIZER so the same code works in both standalone\n * and embedded modes without branching.\n */\n async init(): Promise<void> {}\n\n /**\n * Called by the shell after a successful login or silent refresh.\n * Business Apps should not call this directly.\n */\n setSession(user: User, accessToken: string, expiresAt: number): void {\n this._session.set({ user, accessToken, expiresAt });\n }\n\n /** Clears the in-memory session (called by the shell on logout). */\n clearSession(): void {\n this._session.set(null);\n }\n\n /**\n * Standalone mode: parse a JWT from localStorage and hydrate the user.\n * Pass the storage key your app uses; embedded remotes typically set this in `APP_INITIALIZER`.\n */\n initFromToken(storageKey = 'circles_token'): void {\n const token = localStorage.getItem(storageKey);\n if (!token) return;\n try {\n const base64 = token.split('.')[1].replace(/-/g, '+').replace(/_/g, '/');\n const payload = JSON.parse(decodeURIComponent(\n atob(base64).split('').map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join('')\n )) as Record<string, unknown>;\n\n const rawRole = payload['role'];\n const roles = Array.isArray(rawRole) ? rawRole as string[] : rawRole ? [rawRole as string] : [];\n const rawApps = payload['apps'];\n const apps = Array.isArray(rawApps) ? rawApps as string[] : rawApps ? [rawApps as string] : [];\n const name = (payload['name'] as string) ?? '';\n const nameParts = name.split(' ');\n\n const user: User = {\n id: (payload['sub'] as string) ?? '',\n tenantId: (payload['tenant_id'] as string) ?? (payload['tid'] as string) ?? null,\n email: (payload['email'] as string) ?? '',\n fullName: name,\n firstName: nameParts[0] ?? '',\n lastName: nameParts.slice(1).join(' '),\n preferredLocale: (payload['locale'] as string) ?? 'en',\n roles,\n apps,\n ou: payload['ou'] as string | undefined,\n };\n\n const expiresAt = ((payload['exp'] as number) ?? 0) * 1000;\n this.setSession(user, token, expiresAt);\n } catch {\n // Invalid token — stay unauthenticated\n }\n }\n}\n","import { Injectable, computed, signal, inject, ErrorHandler } from '@angular/core';\n\n/** Locales that use RTL layout for `dir` and DS `isRtl` / `direction`. */\nexport const RTL_LOCALE_SET: ReadonlySet<string> = new Set(['ar', 'ur']);\n\nexport function isRtlLocale(lang: string): boolean {\n return RTL_LOCALE_SET.has(lang);\n}\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/** Accepts flat or nested JSON objects; nested keys become dot paths. Rejects arrays and non-string leaves. */\nfunction normalizeLocaleJson(raw: unknown): Record<string, string> {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n throw new Error('Locale bundle must be a JSON object');\n }\n const out: Record<string, string> = {};\n const walk = (obj: Record<string, unknown>, prefix: string): void => {\n for (const [k, v] of Object.entries(obj)) {\n const path = prefix ? `${prefix}.${k}` : k;\n if (typeof v === 'string') {\n out[path] = v;\n } else if (v !== null && typeof v === 'object' && !Array.isArray(v)) {\n walk(v as Record<string, unknown>, path);\n } else {\n throw new Error(`Locale bundle invalid value at \"${path}\" (expected string or nested object)`);\n }\n }\n };\n walk(raw as Record<string, unknown>, '');\n return out;\n}\n\n/** Options for loading a remote or standalone locale JSON bundle. */\nexport interface LoadBundleOptions {\n /** Stable id (e.g. app id from manifest); later loads replace this bundle only. */\n id: string;\n /** Base URL ending with `/`, e.g. `https://app.example.com/locale/` or `/my-remote/locale/` */\n baseUrl: string;\n lang: string;\n /** When aborted, failures are ignored (e.g. superseded language load). */\n signal?: AbortSignal;\n /**\n * When true, fetch/parse failures are not reported via Angular `ErrorHandler`.\n * Use for optional remote locale bundles (e.g. federated apps that may be offline).\n */\n silent?: boolean;\n}\n\n/**\n * Shared I18nService for the shell and Business Apps.\n *\n * **Merge order** (later keys win): shell layer → remote bundles in registration order.\n *\n * - Shell: `setShellTranslations()` after loading `locale/{lang}.json` and API overrides.\n * - Remotes: `loadBundle()` per manifest `localeBaseUrl`.\n */\n@Injectable({ providedIn: 'root' })\nexport class I18nService {\n private readonly errorHandler = inject(ErrorHandler, { optional: true });\n\n private readonly _shell = signal<Record<string, string>>({});\n private readonly _bundles = signal<Record<string, Record<string, string>>>({});\n private readonly _bundleOrder = signal<string[]>([]);\n private readonly _locale = signal<string>('en');\n private readonly _version = signal(0);\n\n private readonly _merged = computed(() => {\n const shell = this._shell();\n const order = this._bundleOrder();\n const bundles = this._bundles();\n let out: Record<string, string> = { ...shell };\n for (const id of order) {\n const b = bundles[id];\n if (b) out = { ...out, ...b };\n }\n return out;\n });\n\n readonly locale = this._locale.asReadonly();\n readonly version = this._version.asReadonly();\n readonly isRtl = computed(() => isRtlLocale(this._locale()));\n readonly direction = computed(() => (isRtlLocale(this._locale()) ? 'rtl' : 'ltr'));\n\n private bump(): void {\n this._version.update((v) => v + 1);\n }\n\n /** Replace shell strings (desktop `locale/*.json` + `/api/i18n/desktop-shell/{lang}` merged by the shell). */\n setShellTranslations(data: Record<string, string>, lang: string): void {\n this._shell.set(data);\n this._locale.set(lang);\n this.bump();\n }\n\n setLanguage(lang: string): void {\n this._locale.set(lang);\n this.bump();\n }\n\n /**\n * Fetch `{baseUrl}{lang}.json` and store under `id`. New ids are appended to the merge order.\n * @returns whether the bundle was loaded successfully.\n */\n async loadBundle(opts: LoadBundleOptions): Promise<boolean> {\n const { id, baseUrl, lang, signal: abortSignal, silent } = opts;\n try {\n const base = baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`;\n const url = `${base}${lang}.json`;\n const resp = await fetch(url, { signal: abortSignal });\n if (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n const data = normalizeLocaleJson(await resp.json());\n if (abortSignal?.aborted) return false;\n this._bundles.update((b) => ({ ...b, [id]: data }));\n this._bundleOrder.update((order) => (order.includes(id) ? order : [...order, id]));\n this._locale.set(lang);\n this.bump();\n return true;\n } catch (e) {\n if (abortSignal?.aborted) return false;\n if (!silent) this.errorHandler?.handleError(e);\n return false;\n }\n }\n\n removeBundle(id: string): void {\n this._bundles.update((b) => {\n const next = { ...b };\n delete next[id];\n return next;\n });\n this._bundleOrder.update((order) => order.filter((x) => x !== id));\n this.bump();\n }\n\n clearRemoteBundles(): void {\n this._bundles.set({});\n this._bundleOrder.set([]);\n this.bump();\n }\n\n t(key: string, params?: Record<string, string | number>): string {\n const val = this._merged()[key] ?? key;\n if (!params) return val;\n return Object.entries(params).reduce((result, [k, v]) => {\n const safe = escapeRegExp(k);\n return result.replace(new RegExp(`{{\\\\s*${safe}\\\\s*}}`, 'g'), String(v));\n }, val);\n }\n}\n","import { Injectable, signal } from '@angular/core';\n\nexport type FlyThemeMode = 'light' | 'dark' | 'transparent';\n\n/**\n * Applies `html.light-theme` / `html.dark-theme` / `html.transparent-theme` for DS SCSS.\n * Shell and standalone Business Apps use the same service (federation singleton when shared).\n */\n@Injectable({ providedIn: 'root' })\nexport class FlyThemeService {\n readonly theme = signal<FlyThemeMode>('light');\n\n applyTheme(mode: FlyThemeMode): void {\n this.theme.set(mode);\n const html = document.documentElement;\n html.classList.remove('dark-theme', 'light-theme', 'transparent-theme');\n if (mode === 'dark') {\n html.classList.add('dark-theme');\n } else if (mode === 'transparent') {\n html.classList.add('transparent-theme');\n } else {\n html.classList.add('light-theme');\n }\n }\n}\n","import { Injectable } from '@angular/core';\n\n/** Options for opening a child window. */\nexport interface OpenWindowOptions {\n /** Unique identifier for the window instance. */\n windowId: string;\n /** Display title shown in the window chrome. */\n title: string;\n /** Route path or URL to load inside the window. */\n route: string;\n /** Initial width in pixels. Defaults to 900. */\n width?: number;\n /** Initial height in pixels. Defaults to 600. */\n height?: number;\n /** Whether the window can be resized. Defaults to true. */\n resizable?: boolean;\n /** Whether the window can be maximised. Defaults to true. */\n maximizable?: boolean;\n /** Arbitrary data passed to the child window via WINDOW_DATA. */\n data?: unknown;\n}\n\n/**\n * Abstract interface for the WindowManager.\n * The FlyOS shell provides the concrete implementation; Business Apps\n * inject this token to open, close, and focus windows without depending\n * on the shell's internal implementation.\n */\nexport abstract class WindowManagerService {\n abstract openChildWindow(options: OpenWindowOptions): void;\n abstract closeWindow(windowId: string): void;\n abstract focusWindow(windowId: string): void;\n}\n\n/**\n * No-op fallback implementation used when running a Business App in\n * standalone mode (outside the FlyOS shell). Logs a warning instead of\n * throwing so standalone dev/test flows are not broken.\n */\n@Injectable()\nexport class StandaloneWindowManagerService extends WindowManagerService {\n openChildWindow(options: OpenWindowOptions): void {\n console.warn('[WindowManagerService] openChildWindow called in standalone mode — no shell available.', options);\n }\n\n closeWindow(windowId: string): void {\n console.warn('[WindowManagerService] closeWindow called in standalone mode — no shell available.', windowId);\n }\n\n focusWindow(windowId: string): void {\n console.warn('[WindowManagerService] focusWindow called in standalone mode — no shell available.', windowId);\n }\n}\n\n","import { Pipe, PipeTransform, inject } from '@angular/core';\nimport { I18nService } from '../services/i18n.service';\n\n/**\n * Translates a key using the shared I18nService.\n *\n * @example\n * {{ 'myApp.section.title' | translate }}\n * {{ 'myApp.items_count' | translate:{ n: count() } }}\n */\n@Pipe({\n name: 'translate',\n standalone: true,\n pure: false,\n})\nexport class TranslatePipe implements PipeTransform {\n private readonly i18n = inject(I18nService);\n\n transform(key: string, params?: Record<string, string | number>): string {\n // Read version so template CD re-runs when bundles load (merged translations updated).\n void this.i18n.version();\n return this.i18n.t(key, params);\n }\n}\n","import { Injectable, Signal, computed, inject, signal } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { Observable, of } from 'rxjs';\nimport { User } from '../models/user.model';\n\nexport interface MockAuthConfig {\n user: User;\n token?: string;\n loginRedirect?: string[];\n logoutRedirect?: string[];\n}\n\ninterface MockSession {\n accessToken: string;\n user: User;\n expiresAt: number;\n}\n\n/**\n * Shared mock AuthService base class for Business App developers.\n *\n * Extend this class in your app's `auth.service.mock.ts` and override\n * `getConfig()` to supply app-specific mock user data and navigation paths.\n * The subclass must be decorated with `@Injectable({ providedIn: 'root' })`\n * and exported as `AuthService` so Angular's `fileReplacements` swap works.\n *\n * @example\n * ```typescript\n * // src/app/core/services/auth.service.mock.ts\n * import { Injectable } from '@angular/core';\n * import { MockAuthService, type MockAuthConfig } from '@mohamedatia/fly-design-system';\n *\n * @Injectable({ providedIn: 'root' })\n * export class AuthService extends MockAuthService {\n * protected override getConfig(): MockAuthConfig {\n * return {\n * user: { id: 'dev-001', tenantId: 'dev-tenant', email: 'dev@example.com',\n * firstName: 'Dev', lastName: 'User', fullName: 'Dev User',\n * preferredLocale: 'en', roles: ['admin'], apps: ['my-app'] },\n * token: 'my-mock-token',\n * loginRedirect: ['/app'],\n * };\n * }\n * }\n * ```\n */\n@Injectable()\nexport class MockAuthService {\n private readonly router = inject(Router);\n\n protected readonly _session: ReturnType<typeof signal<MockSession | null>>;\n\n private readonly _config: MockAuthConfig;\n\n readonly isAuthenticated: Signal<boolean>;\n readonly currentUser: Signal<User | null>;\n readonly accessToken: Signal<string | null>;\n /** Always false in mock mode — 2FA is handled entirely by the STS. */\n readonly hasPendingTwoFactor: Signal<boolean>;\n /** Always false in mock mode — auth is pre-populated synchronously. */\n readonly initializing: Signal<boolean>;\n\n constructor() {\n // All signal/computed calls are inside the constructor body so Angular's\n // injection context and ngDevMode are fully set up before they execute.\n this._config = this.getConfig();\n\n this._session = signal<MockSession | null>({\n accessToken: this._config.token ?? 'mock-token',\n user: this._config.user,\n expiresAt: Date.now() + 24 * 60 * 60 * 1000,\n });\n\n this.isAuthenticated = computed(() => {\n const s = this._session();\n return s !== null && s.expiresAt > Date.now();\n });\n\n this.currentUser = computed(() => this._session()?.user ?? null);\n this.accessToken = computed(() => this._session()?.accessToken ?? null);\n this.hasPendingTwoFactor = computed(() => false);\n this.initializing = signal(false).asReadonly();\n }\n\n /** Override in subclass to supply app-specific mock data. */\n protected getConfig(): MockAuthConfig {\n return {\n user: {\n id: 'mock-user-001',\n tenantId: 'mock-tenant-001',\n email: 'developer@fly.local',\n firstName: 'UI',\n lastName: 'Developer',\n fullName: 'UI Developer',\n preferredLocale: 'en',\n roles: ['admin'],\n apps: [],\n },\n };\n }\n\n async init(): Promise<void> {\n // Mock mode: already authenticated, nothing to initialize.\n }\n\n startLogin(): void {\n this.router.navigate(this._config.loginRedirect ?? ['/']);\n }\n\n handleCallback(_code: string, _state?: string): Observable<User> {\n return of(this._config.user);\n }\n\n async forceRefresh(): Promise<void> {\n // No-op in mock mode — token never expires.\n }\n\n patchSessionPreferredLocale(locale: string): void {\n const session = this._session();\n if (!session?.user) return;\n this._session.set({ ...session, user: { ...session.user, preferredLocale: locale } });\n }\n\n /** Parameter order matches the real AuthService: (user, accessToken, expiresAt). */\n setSession(_user: User, _accessToken: string, _expiresAt: number): void {\n // No-op in mock mode — session is hardcoded.\n }\n\n logout(): void {\n this._session.set(null);\n this.router.navigate(this._config.logoutRedirect ?? ['/']);\n }\n}\n","/*\r\n * @mohamedatia/fly-design-system — Public API\r\n * https://www.npmjs.com/package/@mohamedatia/fly-design-system\r\n *\r\n * This is the single entry point for Business App developers.\r\n * Import everything from '@mohamedatia/fly-design-system' — never from relative shell paths.\r\n *\r\n * NOTE: This package is published under @mohamedatia/fly-design-system until the @fly\r\n * npm org is created. It will be republished as @fly/design-system once available.\r\n *\r\n * v1.3.0: FlyThemeService (html theme classes), hardened I18nService (AbortSignal, ErrorHandler, RTL helpers).\r\n * v1.3.1: loadBundle normalizes locale JSON (flat or nested objects; rejects invalid leaves).\r\n * v1.3.2: loadBundle returns boolean; LoadBundleOptions.silent skips ErrorHandler on failure.\r\n * v1.3.7: MockAuthService base class + MockAuthConfig for Business App mock auth via fileReplacements.\r\n * User model extended with optional avatar, source, twoFactorEnabled, createdAt fields.\r\n * v1.3.8: AuthService.init() no-op added so Business Apps can call init() in APP_INITIALIZER\r\n * without branching between standalone and embedded modes.\r\n * v1.3.9: MockAuthService field initializers moved into constructor to fix ngDevMode ReferenceError\r\n * when the package is loaded in a production-mode bundle (no ngDevMode global defined).\r\n * See BusinessAppsGuide/03-frontend-app.md.\r\n */\r\n\r\n// ─── Models ──────────────────────────────────────────────────────────────────\r\nexport type { DesktopApp } from './lib/models/app.model';\r\nexport type {\r\n WindowInstance,\r\n WindowState,\r\n ChildWindowData,\r\n} from './lib/models/window.model';\r\nexport { WINDOW_DATA } from './lib/models/window.model';\r\nexport type { User } from './lib/models/user.model';\r\n\r\n// ─── Remote App Registration ─────────────────────────────────────────────────\r\nexport type { RemoteAppDef } from './lib/models/remote-app.model';\r\n\r\n// ─── Services ────────────────────────────────────────────────────────────────\r\nexport { AuthService } from './lib/services/auth.service';\r\nexport type { LoadBundleOptions } from './lib/services/i18n.service';\r\nexport { I18nService, RTL_LOCALE_SET, isRtlLocale } from './lib/services/i18n.service';\r\nexport { FlyThemeService, type FlyThemeMode } from './lib/services/fly-theme.service';\r\nexport {\r\n WindowManagerService,\r\n StandaloneWindowManagerService,\r\n type OpenWindowOptions,\r\n} from './lib/services/window-manager.service';\r\n\r\n// ─── Pipes ───────────────────────────────────────────────────────────────────\r\nexport { TranslatePipe } from './lib/pipes/translate.pipe';\r\n\r\n// ─── Mock Auth (for fileReplacements in dev/mock builds) ─────────────────────\r\nexport { MockAuthService, type MockAuthConfig } from './lib/services/auth.service.mock';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { Type, InjectionToken, PipeTransform } from '@angular/core';
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Type, InjectionToken, PipeTransform, signal, Signal } from '@angular/core';
|
|
3
3
|
import { Observable } from 'rxjs';
|
|
4
4
|
|
|
5
5
|
interface DesktopApp {
|
|
@@ -122,9 +122,16 @@ interface RemoteAppDef {
|
|
|
122
122
|
*/
|
|
123
123
|
declare class AuthService {
|
|
124
124
|
private _session;
|
|
125
|
-
readonly currentUser:
|
|
126
|
-
readonly accessToken:
|
|
127
|
-
readonly isAuthenticated:
|
|
125
|
+
readonly currentUser: i0.Signal<User | null>;
|
|
126
|
+
readonly accessToken: i0.Signal<string | null>;
|
|
127
|
+
readonly isAuthenticated: i0.Signal<boolean>;
|
|
128
|
+
/**
|
|
129
|
+
* No-op when running as a Module Federation remote — the shell has already
|
|
130
|
+
* initialised the session before the remote bootstraps. Business Apps call
|
|
131
|
+
* this in their APP_INITIALIZER so the same code works in both standalone
|
|
132
|
+
* and embedded modes without branching.
|
|
133
|
+
*/
|
|
134
|
+
init(): Promise<void>;
|
|
128
135
|
/**
|
|
129
136
|
* Called by the shell after a successful login or silent refresh.
|
|
130
137
|
* Business Apps should not call this directly.
|
|
@@ -137,8 +144,8 @@ declare class AuthService {
|
|
|
137
144
|
* Pass the storage key your app uses; embedded remotes typically set this in `APP_INITIALIZER`.
|
|
138
145
|
*/
|
|
139
146
|
initFromToken(storageKey?: string): void;
|
|
140
|
-
static ɵfac:
|
|
141
|
-
static ɵprov:
|
|
147
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AuthService, never>;
|
|
148
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<AuthService>;
|
|
142
149
|
}
|
|
143
150
|
|
|
144
151
|
/** Locales that use RTL layout for `dir` and DS `isRtl` / `direction`. */
|
|
@@ -175,10 +182,10 @@ declare class I18nService {
|
|
|
175
182
|
private readonly _locale;
|
|
176
183
|
private readonly _version;
|
|
177
184
|
private readonly _merged;
|
|
178
|
-
readonly locale:
|
|
179
|
-
readonly version:
|
|
180
|
-
readonly isRtl:
|
|
181
|
-
readonly direction:
|
|
185
|
+
readonly locale: i0.Signal<string>;
|
|
186
|
+
readonly version: i0.Signal<number>;
|
|
187
|
+
readonly isRtl: i0.Signal<boolean>;
|
|
188
|
+
readonly direction: i0.Signal<"rtl" | "ltr">;
|
|
182
189
|
private bump;
|
|
183
190
|
/** Replace shell strings (desktop `locale/*.json` + `/api/i18n/desktop-shell/{lang}` merged by the shell). */
|
|
184
191
|
setShellTranslations(data: Record<string, string>, lang: string): void;
|
|
@@ -191,8 +198,8 @@ declare class I18nService {
|
|
|
191
198
|
removeBundle(id: string): void;
|
|
192
199
|
clearRemoteBundles(): void;
|
|
193
200
|
t(key: string, params?: Record<string, string | number>): string;
|
|
194
|
-
static ɵfac:
|
|
195
|
-
static ɵprov:
|
|
201
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<I18nService, never>;
|
|
202
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<I18nService>;
|
|
196
203
|
}
|
|
197
204
|
|
|
198
205
|
type FlyThemeMode = 'light' | 'dark' | 'transparent';
|
|
@@ -201,10 +208,10 @@ type FlyThemeMode = 'light' | 'dark' | 'transparent';
|
|
|
201
208
|
* Shell and standalone Business Apps use the same service (federation singleton when shared).
|
|
202
209
|
*/
|
|
203
210
|
declare class FlyThemeService {
|
|
204
|
-
readonly theme:
|
|
211
|
+
readonly theme: i0.WritableSignal<FlyThemeMode>;
|
|
205
212
|
applyTheme(mode: FlyThemeMode): void;
|
|
206
|
-
static ɵfac:
|
|
207
|
-
static ɵprov:
|
|
213
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<FlyThemeService, never>;
|
|
214
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<FlyThemeService>;
|
|
208
215
|
}
|
|
209
216
|
|
|
210
217
|
/** Options for opening a child window. */
|
|
@@ -246,8 +253,8 @@ declare class StandaloneWindowManagerService extends WindowManagerService {
|
|
|
246
253
|
openChildWindow(options: OpenWindowOptions): void;
|
|
247
254
|
closeWindow(windowId: string): void;
|
|
248
255
|
focusWindow(windowId: string): void;
|
|
249
|
-
static ɵfac:
|
|
250
|
-
static ɵprov:
|
|
256
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<StandaloneWindowManagerService, never>;
|
|
257
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<StandaloneWindowManagerService>;
|
|
251
258
|
}
|
|
252
259
|
|
|
253
260
|
/**
|
|
@@ -260,8 +267,8 @@ declare class StandaloneWindowManagerService extends WindowManagerService {
|
|
|
260
267
|
declare class TranslatePipe implements PipeTransform {
|
|
261
268
|
private readonly i18n;
|
|
262
269
|
transform(key: string, params?: Record<string, string | number>): string;
|
|
263
|
-
static ɵfac:
|
|
264
|
-
static ɵpipe:
|
|
270
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<TranslatePipe, never>;
|
|
271
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<TranslatePipe, "translate", true>;
|
|
265
272
|
}
|
|
266
273
|
|
|
267
274
|
interface MockAuthConfig {
|
|
@@ -270,6 +277,11 @@ interface MockAuthConfig {
|
|
|
270
277
|
loginRedirect?: string[];
|
|
271
278
|
logoutRedirect?: string[];
|
|
272
279
|
}
|
|
280
|
+
interface MockSession {
|
|
281
|
+
accessToken: string;
|
|
282
|
+
user: User;
|
|
283
|
+
expiresAt: number;
|
|
284
|
+
}
|
|
273
285
|
/**
|
|
274
286
|
* Shared mock AuthService base class for Business App developers.
|
|
275
287
|
*
|
|
@@ -282,27 +294,34 @@ interface MockAuthConfig {
|
|
|
282
294
|
* ```typescript
|
|
283
295
|
* // src/app/core/services/auth.service.mock.ts
|
|
284
296
|
* import { Injectable } from '@angular/core';
|
|
285
|
-
* import { MockAuthService } from '@mohamedatia/fly-design-system';
|
|
286
|
-
*
|
|
287
|
-
* const MOCK_USER = { id: 'dev-001', ... };
|
|
297
|
+
* import { MockAuthService, type MockAuthConfig } from '@mohamedatia/fly-design-system';
|
|
288
298
|
*
|
|
289
299
|
* @Injectable({ providedIn: 'root' })
|
|
290
300
|
* export class AuthService extends MockAuthService {
|
|
291
|
-
* protected override getConfig() {
|
|
292
|
-
* return {
|
|
301
|
+
* protected override getConfig(): MockAuthConfig {
|
|
302
|
+
* return {
|
|
303
|
+
* user: { id: 'dev-001', tenantId: 'dev-tenant', email: 'dev@example.com',
|
|
304
|
+
* firstName: 'Dev', lastName: 'User', fullName: 'Dev User',
|
|
305
|
+
* preferredLocale: 'en', roles: ['admin'], apps: ['my-app'] },
|
|
306
|
+
* token: 'my-mock-token',
|
|
307
|
+
* loginRedirect: ['/app'],
|
|
308
|
+
* };
|
|
293
309
|
* }
|
|
294
310
|
* }
|
|
295
311
|
* ```
|
|
296
312
|
*/
|
|
297
313
|
declare class MockAuthService {
|
|
298
314
|
private readonly router;
|
|
315
|
+
protected readonly _session: ReturnType<typeof signal<MockSession | null>>;
|
|
299
316
|
private readonly _config;
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
readonly
|
|
303
|
-
|
|
304
|
-
readonly
|
|
305
|
-
|
|
317
|
+
readonly isAuthenticated: Signal<boolean>;
|
|
318
|
+
readonly currentUser: Signal<User | null>;
|
|
319
|
+
readonly accessToken: Signal<string | null>;
|
|
320
|
+
/** Always false in mock mode — 2FA is handled entirely by the STS. */
|
|
321
|
+
readonly hasPendingTwoFactor: Signal<boolean>;
|
|
322
|
+
/** Always false in mock mode — auth is pre-populated synchronously. */
|
|
323
|
+
readonly initializing: Signal<boolean>;
|
|
324
|
+
constructor();
|
|
306
325
|
/** Override in subclass to supply app-specific mock data. */
|
|
307
326
|
protected getConfig(): MockAuthConfig;
|
|
308
327
|
init(): Promise<void>;
|
|
@@ -310,10 +329,11 @@ declare class MockAuthService {
|
|
|
310
329
|
handleCallback(_code: string, _state?: string): Observable<User>;
|
|
311
330
|
forceRefresh(): Promise<void>;
|
|
312
331
|
patchSessionPreferredLocale(locale: string): void;
|
|
313
|
-
|
|
332
|
+
/** Parameter order matches the real AuthService: (user, accessToken, expiresAt). */
|
|
333
|
+
setSession(_user: User, _accessToken: string, _expiresAt: number): void;
|
|
314
334
|
logout(): void;
|
|
315
|
-
static ɵfac:
|
|
316
|
-
static ɵprov:
|
|
335
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MockAuthService, never>;
|
|
336
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<MockAuthService>;
|
|
317
337
|
}
|
|
318
338
|
|
|
319
339
|
export { AuthService, FlyThemeService, I18nService, MockAuthService, RTL_LOCALE_SET, StandaloneWindowManagerService, TranslatePipe, WINDOW_DATA, WindowManagerService, isRtlLocale };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mohamedatia-fly-design-system.d.ts","sources":["../../../projects/design-system/src/lib/models/app.model.ts","../../../projects/design-system/src/lib/models/window.model.ts","../../../projects/design-system/src/lib/models/user.model.ts","../../../projects/design-system/src/lib/models/remote-app.model.ts","../../../projects/design-system/src/lib/services/auth.service.ts","../../../projects/design-system/src/lib/services/i18n.service.ts","../../../projects/design-system/src/lib/services/fly-theme.service.ts","../../../projects/design-system/src/lib/services/window-manager.service.ts","../../../projects/design-system/src/lib/pipes/translate.pipe.ts","../../../projects/design-system/src/lib/services/auth.service.mock.ts"],"mappings":";;;;UAEiB,UAAU;;;;;;yBAMJ,OAAO,CAAC,IAAI;AACjC;;;;AACA;;;;;;;AAID;;ACZK,KAAM,WAAW;UAEN,eAAe;AAC9B,oBAAgB,IAAI;AACpB;AACD;UAEgB,cAAc;;;;;;WAMtB,WAAW;AAClB;;;;AACA;;;;;;;;;;;;gBASY,eAAe;;;AAG5B;AAED,cAAa,WAAW,EAAA,cAAA,CAAA,cAAA;;UC/BP,IAAI;;AAEnB;;;;;;;;AAQA;;;;;;gBAMY,IAAI;AACjB;;ACfD;;;;AAIG;UACc,YAAY;;;;;;;;;;;;AAY3B;;;;AACA;;;;;AAEA,cAAU,UAAU;;AAErB;;ACfD;;;;;;;;;;;;;;AAcG;AACH,cACa,WAAW;;
|
|
1
|
+
{"version":3,"file":"mohamedatia-fly-design-system.d.ts","sources":["../../../projects/design-system/src/lib/models/app.model.ts","../../../projects/design-system/src/lib/models/window.model.ts","../../../projects/design-system/src/lib/models/user.model.ts","../../../projects/design-system/src/lib/models/remote-app.model.ts","../../../projects/design-system/src/lib/services/auth.service.ts","../../../projects/design-system/src/lib/services/i18n.service.ts","../../../projects/design-system/src/lib/services/fly-theme.service.ts","../../../projects/design-system/src/lib/services/window-manager.service.ts","../../../projects/design-system/src/lib/pipes/translate.pipe.ts","../../../projects/design-system/src/lib/services/auth.service.mock.ts"],"mappings":";;;;UAEiB,UAAU;;;;;;yBAMJ,OAAO,CAAC,IAAI;AACjC;;;;AACA;;;;;;;AAID;;ACZK,KAAM,WAAW;UAEN,eAAe;AAC9B,oBAAgB,IAAI;AACpB;AACD;UAEgB,cAAc;;;;;;WAMtB,WAAW;AAClB;;;;AACA;;;;;;;;;;;;gBASY,eAAe;;;AAG5B;AAED,cAAa,WAAW,EAAA,cAAA,CAAA,cAAA;;UC/BP,IAAI;;AAEnB;;;;;;;;AAQA;;;;;;gBAMY,IAAI;AACjB;;ACfD;;;;AAIG;UACc,YAAY;;;;;;;;;;;;AAY3B;;;;AACA;;;;;AAEA,cAAU,UAAU;;AAErB;;ACfD;;;;;;;;;;;;;;AAcG;AACH,cACa,WAAW;;0BAGFA,EAAA,CAAA,MAAA,CAAA,IAAA;0BACAA,EAAA,CAAA,MAAA;8BACIA,EAAA,CAAA,MAAA;AAKxB;;;;;AAKG;AACG,YAAQ,OAAO;AAErB;;;AAGG;AACH,qBAAiB,IAAI;;AAKrB;AAIA;;;AAGG;AACH;yCAnCW,WAAW;6CAAX,WAAW;AAsEvB;;AC7FD;AACA,cAAa,cAAc,EAAE,WAAW;AAExC,iBAAgB,WAAW;AA8B3B;UACiB,iBAAiB;;;;;;;aAOvB,WAAW;AACpB;;;AAGG;;AAEJ;AAED;;;;;;;AAOG;AACH,cACa,WAAW;AACtB;AAEA;AACA;AACA;AACA;AACA;AAEA;qBAYeA,EAAA,CAAA,MAAA;sBACCA,EAAA,CAAA,MAAA;oBACFA,EAAA,CAAA,MAAA;wBACIA,EAAA,CAAA,MAAA;AAElB;;AAKA,+BAA2B,MAAM;AAMjC;AAKA;;;AAGG;qBACoB,iBAAiB,GAAG,OAAO;AAqBlD;AAUA;AAMA,4BAAwB,MAAM;yCAnFnB,WAAW;6CAAX,WAAW;AA2FvB;;ACrJK,KAAM,YAAY;AAExB;;;AAGG;AACH,cACa,eAAe;oBACZA,EAAA,CAAA,cAAA,CAAA,YAAA;AAEd,qBAAiB,YAAY;yCAHlB,eAAe;6CAAf,eAAe;AAe3B;;ACtBD;UACiB,iBAAiB;;;;;;;;;;;;;;;;;AAiBjC;AAED;;;;;AAKG;AACH,uBAAsB,oBAAoB;AACxC,sCAAkC,iBAAiB;AACnD;AACA;AACD;AAED;;;;AAIG;AACH,cACa,8BAA+B,SAAQ,oBAAoB;AACtE,6BAAyB,iBAAiB;AAI1C;AAIA;yCATW,8BAA8B;6CAA9B,8BAA8B;AAY1C;;ACjDD;;;;;;AAMG;AACH,cAKa,aAAc,YAAW,aAAa;AACjD;AAEA,oCAAgC,MAAM;yCAH3B,aAAa;uCAAb,aAAa;AAQzB;;UClBgB,cAAc;UACvB,IAAI;;AAEV;AACA;AACD;AAED,UAAU,WAAW;;UAEb,IAAI;;AAEX;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;AACH,cACa,eAAe;AAC1B;AAEA,iCAA6B,UAAU,QAAQ,MAAM,CAAC,WAAW;AAEjE;AAEA,8BAA0B,MAAM;0BACV,MAAM,CAAC,IAAI;0BACX,MAAM;;AAE5B,kCAA8B,MAAM;;AAEpC,2BAAuB,MAAM;;;2BAyBN,cAAc;AAgB/B,YAAQ,OAAO;AAIrB;AAIA,oDAAgD,UAAU,CAAC,IAAI;AAIzD,oBAAgB,OAAO;AAI7B;;AAOA,sBAAkB,IAAI;AAItB;yCAjFW,eAAe;6CAAf,eAAe;AAqF3B;;;;","names":["_angular_core"]}
|