@atlasauth/angular 0.1.3 → 0.2.1
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.
- package/README.md +8 -8
- package/dist/README.md +11 -11
- package/dist/esm2022/lib/appearance.mjs +36 -1
- package/dist/esm2022/lib/atlas.service.mjs +36 -5
- package/dist/esm2022/lib/directives/atlas-root.directive.mjs +21 -8
- package/dist/fesm2022/atlasauth-angular.mjs +89 -12
- package/dist/fesm2022/atlasauth-angular.mjs.map +1 -1
- package/dist/lib/appearance.d.ts +27 -2
- package/dist/lib/atlas.service.d.ts +16 -3
- package/dist/lib/directives/atlas-root.directive.d.ts +6 -0
- package/package.json +3 -2
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, PLATFORM_ID, computed, Injectable, TemplateRef, ViewContainerRef, Directive, Input, ElementRef, Renderer2,
|
|
3
|
-
import { isPlatformBrowser } from '@angular/common';
|
|
2
|
+
import { InjectionToken, inject, PLATFORM_ID, computed, Injectable, TemplateRef, ViewContainerRef, Directive, Input, ElementRef, Renderer2, EventEmitter, Output, ChangeDetectionStrategy, Component, signal, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, NgModule } from '@angular/core';
|
|
3
|
+
import { isPlatformBrowser, DOCUMENT } from '@angular/common';
|
|
4
4
|
import { toSignal } from '@angular/core/rxjs-interop';
|
|
5
5
|
import { BehaviorSubject, combineLatest, firstValueFrom } from 'rxjs';
|
|
6
6
|
import { map, distinctUntilChanged, filter, take } from 'rxjs/operators';
|
|
7
|
-
import { TokenCache, FapiClient, getProviderToken, readRedirectResult, stripRedirectParams, readExpiry, msUntilRefresh, nextStep, flowFromPending, initialFlow, advance, shouldKeepPolling, pollAttempt } from '@atlasauth/js';
|
|
7
|
+
import { TokenCache, FapiClient, getProviderToken, runFrontChannelLogoutFromResponse, readRedirectResult, stripRedirectParams, readExpiry, msUntilRefresh, nextStep, flowFromPending, initialFlow, advance, shouldKeepPolling, pollAttempt } from '@atlasauth/js';
|
|
8
8
|
export { FapiClient, advance, flowFromPending, getProviderToken, initialFlow, pollAttempt, prepareFactor, requestForStep, shouldKeepPolling } from '@atlasauth/js';
|
|
9
9
|
import { evaluate } from '@atlasauth/authz';
|
|
10
10
|
export { evaluate, hasFromClaims } from '@atlasauth/authz';
|
|
11
|
+
import { renderDesignAppearance, instanceDesignFrom, applyAppearanceToDom } from '@atlasauth/design/runtime';
|
|
12
|
+
export { instanceDesignFrom } from '@atlasauth/design/runtime';
|
|
11
13
|
import { Router } from '@angular/router';
|
|
12
14
|
|
|
13
15
|
/**
|
|
@@ -108,6 +110,39 @@ function classFor(element, appearance, base) {
|
|
|
108
110
|
const override = appearance?.elements?.[element];
|
|
109
111
|
return override ? `${base} ${override}` : base;
|
|
110
112
|
}
|
|
113
|
+
// ---- the design system ---------------------------------------------------------
|
|
114
|
+
/**
|
|
115
|
+
* The legacy tokens the developer chose EXPLICITLY: a non-default `baseTheme`
|
|
116
|
+
* plus `variables`. Only these map onto a design — the token defaults must not
|
|
117
|
+
* overwrite the dashboard design.
|
|
118
|
+
*/
|
|
119
|
+
function explicitTokens(appearance) {
|
|
120
|
+
const out = {};
|
|
121
|
+
if (appearance?.baseTheme && appearance.baseTheme !== 'default') {
|
|
122
|
+
Object.assign(out, THEMES[appearance.baseTheme]);
|
|
123
|
+
}
|
|
124
|
+
for (const [key, value] of Object.entries(appearance?.variables ?? {})) {
|
|
125
|
+
if (value !== undefined)
|
|
126
|
+
out[key] = value;
|
|
127
|
+
}
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Turn an `appearance` (+ the instance's dashboard design from the Frontend
|
|
132
|
+
* API) into root attributes and a stylesheet — the same semantics as
|
|
133
|
+
* `@atlasauth/react`. Precedence, lowest first: dashboard design < `preset` <
|
|
134
|
+
* `variables` (and a non-default `baseTheme`) < `design`. Without a dashboard
|
|
135
|
+
* design and without `preset`/`design`, the output is exactly the
|
|
136
|
+
* pre-design-system one: the token variables, no stylesheet, no attributes.
|
|
137
|
+
*/
|
|
138
|
+
function renderAppearance(appearance, instanceDesign, options = {}) {
|
|
139
|
+
return renderDesignAppearance(appearance, instanceDesign, {
|
|
140
|
+
tokens: explicitTokens(appearance),
|
|
141
|
+
legacyStyle: () => cssVariables(resolveTokens(appearance)),
|
|
142
|
+
frontendApi: options.frontendApi,
|
|
143
|
+
warn: options.warn,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
111
146
|
|
|
112
147
|
/**
|
|
113
148
|
* §10.3: "Every string passes through an i18n catalog; en-US ships, catalog
|
|
@@ -304,6 +339,33 @@ class AtlasService {
|
|
|
304
339
|
appearanceVariables() {
|
|
305
340
|
return cssVariables(resolveTokens(this.options.appearance));
|
|
306
341
|
}
|
|
342
|
+
/**
|
|
343
|
+
* The full appearance render for a root element: inline variables, the
|
|
344
|
+
* `data-atlas-*` attributes and the design stylesheet. Pass the dashboard
|
|
345
|
+
* design (from {@link loadInstanceDesign}) to layer code overrides on it —
|
|
346
|
+
* the same semantics as `@atlasauth/react`.
|
|
347
|
+
*/
|
|
348
|
+
appearanceRender(instanceDesign) {
|
|
349
|
+
return renderAppearance(this.options.appearance, instanceDesign ?? null, {
|
|
350
|
+
frontendApi: this.baseUrl,
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* The design configured in the Atlas dashboard (`GET /v1/appearance`), or null
|
|
355
|
+
* when there is none, it cannot be read, or the app opted out with
|
|
356
|
+
* `appearance.instanceDesign: false`.
|
|
357
|
+
*/
|
|
358
|
+
async loadInstanceDesign() {
|
|
359
|
+
if (this.options.appearance?.instanceDesign === false)
|
|
360
|
+
return null;
|
|
361
|
+
try {
|
|
362
|
+
const response = await this.call('/v1/appearance');
|
|
363
|
+
return response.ok ? instanceDesignFrom(await response.json()) : null;
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
307
369
|
/** A fresh {@link FapiClient} for driving a sign-in/sign-up flow. */
|
|
308
370
|
createFapiClient() {
|
|
309
371
|
return new FapiClient({ publishableKey: this.publishableKey, baseUrl: this.baseUrl });
|
|
@@ -335,12 +397,16 @@ class AtlasService {
|
|
|
335
397
|
return evaluate(this._claims.value, condition).allowed;
|
|
336
398
|
}
|
|
337
399
|
/** Revoke the current session server-side and drop all local auth state. */
|
|
338
|
-
async signOut() {
|
|
400
|
+
async signOut(options) {
|
|
339
401
|
const current = this.cache.peek();
|
|
340
402
|
if (current) {
|
|
341
|
-
await this.call(`/v1/client/sessions/${current.sessionId}/revoke`, {
|
|
403
|
+
const revoked = await this.call(`/v1/client/sessions/${current.sessionId}/revoke`, {
|
|
342
404
|
method: 'POST',
|
|
343
405
|
}).catch(() => undefined);
|
|
406
|
+
// OIDC Front-Channel Logout: let the apps signed in through this session
|
|
407
|
+
// clear theirs in this browser (hidden iframes, capped at 5 s). Best-effort.
|
|
408
|
+
if (options?.frontchannel !== false)
|
|
409
|
+
await runFrontChannelLogoutFromResponse(revoked);
|
|
344
410
|
}
|
|
345
411
|
this.clearRefreshTimer();
|
|
346
412
|
this.cache.clear();
|
|
@@ -722,18 +788,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
722
788
|
* <router-outlet></router-outlet>
|
|
723
789
|
* </div>
|
|
724
790
|
* ```
|
|
791
|
+
*
|
|
792
|
+
* With a design (a code-level `appearance.preset` / `appearance.design`, or
|
|
793
|
+
* the dashboard design, fetched in the browser) the host also gets the stable
|
|
794
|
+
* `data-atlas-*` attributes and the design stylesheet is added to `<head>` once.
|
|
725
795
|
*/
|
|
726
796
|
class AtlasRootDirective {
|
|
727
797
|
atlas = inject(AtlasService);
|
|
728
798
|
el = inject(ElementRef);
|
|
729
799
|
renderer = inject(Renderer2);
|
|
800
|
+
document = inject(DOCUMENT);
|
|
801
|
+
platformId = inject(PLATFORM_ID);
|
|
730
802
|
ngOnInit() {
|
|
731
|
-
this.
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
803
|
+
const host = this.el.nativeElement;
|
|
804
|
+
this.renderer.addClass(host, 'atlas-root');
|
|
805
|
+
// Custom properties via `style.setProperty` (written verbatim, never camelCased).
|
|
806
|
+
let applied = applyAppearanceToDom(this.document, host, this.atlas.appearanceRender());
|
|
807
|
+
if (!isPlatformBrowser(this.platformId))
|
|
808
|
+
return;
|
|
809
|
+
void this.atlas.loadInstanceDesign().then((design) => {
|
|
810
|
+
if (!design)
|
|
811
|
+
return;
|
|
812
|
+
applied = applyAppearanceToDom(this.document, host, this.atlas.appearanceRender(design), applied);
|
|
813
|
+
});
|
|
737
814
|
}
|
|
738
815
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AtlasRootDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
739
816
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: AtlasRootDirective, isStandalone: true, selector: "[atlasRoot]", ngImport: i0 });
|
|
@@ -1553,5 +1630,5 @@ function atlasChildGuard(options = {}) {
|
|
|
1553
1630
|
* Generated bundle index. Do not edit.
|
|
1554
1631
|
*/
|
|
1555
1632
|
|
|
1556
|
-
export { ATLAS_OPTIONS, ATLAS_UI, AtlasFlowController, AtlasLoadedDirective, AtlasLoadingDirective, AtlasModule, AtlasProtectDirective, AtlasRootDirective, AtlasService, AtlasSignedInDirective, AtlasSignedOutDirective, AttemptFlowComponent, DEFAULT_TOKENS, EN_US, OrganizationProfileComponent, OrganizationSwitcherComponent, SignInComponent, SignUpComponent, THEMES, UserButtonComponent, UserProfileComponent, atlasChildGuard, atlasGuard, classFor, cssVariables, provideAtlas, resolveTokens, translate, withFallback };
|
|
1633
|
+
export { ATLAS_OPTIONS, ATLAS_UI, AtlasFlowController, AtlasLoadedDirective, AtlasLoadingDirective, AtlasModule, AtlasProtectDirective, AtlasRootDirective, AtlasService, AtlasSignedInDirective, AtlasSignedOutDirective, AttemptFlowComponent, DEFAULT_TOKENS, EN_US, OrganizationProfileComponent, OrganizationSwitcherComponent, SignInComponent, SignUpComponent, THEMES, UserButtonComponent, UserProfileComponent, atlasChildGuard, atlasGuard, classFor, cssVariables, explicitTokens, provideAtlas, renderAppearance, resolveTokens, translate, withFallback };
|
|
1557
1634
|
//# sourceMappingURL=atlasauth-angular.mjs.map
|